fixex merge conflicts

This commit is contained in:
Araq 2018-06-08 19:50:36 +02:00
commit 8e9551b1c7
53 changed files with 2648 additions and 355 deletions

View file

@ -83,7 +83,7 @@ proc isInCurrentFrame(p: BProc, n: PNode): bool =
result = isInCurrentFrame(p, n.sons[0])
else: discard
proc genIndexCheck(p: BProc; arr, idx: TLoc)
proc genBoundsCheck(p: BProc; arr, a, b: TLoc)
proc openArrayLoc(p: BProc, n: PNode): Rope =
var a: TLoc
@ -97,8 +97,7 @@ proc openArrayLoc(p: BProc, n: PNode): Rope =
initLocExpr(p, q[3], c)
# but first produce the required index checks:
if optBoundsCheck in p.options:
genIndexCheck(p, a, b)
genIndexCheck(p, a, c)
genBoundsCheck(p, a, b, c)
let ty = skipTypes(a.t, abstractVar+{tyPtr})
case ty.kind
of tyArray:

View file

@ -351,7 +351,9 @@ proc genAssignment(p: BProc, dest, src: TLoc, flags: TAssignmentFlags) =
else:
useStringh(p.module)
linefmt(p, cpsStmts,
"memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($1[0])*$1Len_0);$n",
# bug #4799, keep the memcpy for a while
#"memcpy((void*)$1, (NIM_CONST void*)$2, sizeof($1[0])*$1Len_0);$n",
"$1 = $2;$n",
rdLoc(dest), rdLoc(src))
of tySet:
if mapType(p.config, ty) == ctArray:
@ -873,21 +875,26 @@ proc genCStringElem(p: BProc, n, x, y: PNode, d: var TLoc) =
putIntoDest(p, d, n,
ropecg(p.module, "$1[$2]", rdLoc(a), rdCharLoc(b)), a.storage)
proc genIndexCheck(p: BProc; arr, idx: TLoc) =
proc genBoundsCheck(p: BProc; arr, a, b: TLoc) =
let ty = skipTypes(arr.t, abstractVarRange)
case ty.kind
of tyOpenArray, tyVarargs:
linefmt(p, cpsStmts, "if ((NU)($1) >= (NU)($2Len_0)) #raiseIndexError();$n",
rdLoc(idx), rdLoc(arr))
linefmt(p, cpsStmts,
"if ($2-$1 != -1 && " &
"((NU)($1) >= (NU)($3Len_0) || (NU)($2) >= (NU)($3Len_0))) #raiseIndexError();$n",
rdLoc(a), rdLoc(b), rdLoc(arr))
of tyArray:
let first = intLiteral(firstOrd(p.config, ty))
if tfUncheckedArray notin ty.flags:
linefmt(p, cpsStmts, "if ($1 < $2 || $1 > $3) #raiseIndexError();$n",
rdCharLoc(idx), first, intLiteral(lastOrd(p.config, ty)))
linefmt(p, cpsStmts,
"if ($2-$1 != -1 && " &
"($2-$1 < -1 || $1 < $3 || $1 > $4 || $2 < $3 || $2 > $4)) #raiseIndexError();$n",
rdCharLoc(a), rdCharLoc(b), first, intLiteral(lastOrd(p.config, ty)))
of tySequence, tyString:
linefmt(p, cpsStmts,
"if (!$2 || (NU)($1) >= (NU)($2->$3)) #raiseIndexError();$n",
rdLoc(idx), rdLoc(arr), lenField(p))
"if ($2-$1 != -1 && " &
"(!$3 || (NU)($1) >= (NU)($3->$4) || (NU)($2) >= (NU)($3->$4))) #raiseIndexError();$n",
rdLoc(a), rdLoc(b), rdLoc(arr), lenField(p))
else: discard
proc genOpenArrayElem(p: BProc, n, x, y: PNode, d: var TLoc) =
@ -2326,7 +2333,7 @@ proc expr(p: BProc, n: PNode, d: var TLoc) =
of nkParForStmt: genParForStmt(p, n)
of nkState: genState(p, n)
of nkGotoState: genGotoState(p, n)
of nkBreakState: genBreakState(p, n)
of nkBreakState: genBreakState(p, n, d)
else: internalError(p.config, n.info, "expr(" & $n.kind & "); unknown node kind")
proc genNamedConstExpr(p: BProc, n: PNode): Rope =

View file

@ -157,6 +157,39 @@ proc genState(p: BProc, n: PNode) =
elif n0.kind == nkStrLit:
linefmt(p, cpsStmts, "$1: ;$n", n0.strVal.rope)
proc blockLeaveActions(p: BProc, howManyTrys, howManyExcepts: int) =
# Called by return and break stmts.
# Deals with issues faced when jumping out of try/except/finally stmts,
var stack = newSeq[tuple[n: PNode, inExcept: bool]](0)
for i in countup(1, howManyTrys):
let tryStmt = p.nestedTryStmts.pop
if not p.module.compileToCpp or optNoCppExceptions in p.config.globalOptions:
# Pop safe points generated by try
if not tryStmt.inExcept:
linefmt(p, cpsStmts, "#popSafePoint();$n")
# Pop this try-stmt of the list of nested trys
# so we don't infinite recurse on it in the next step.
stack.add(tryStmt)
# Find finally-stmt for this try-stmt
# and generate a copy of its sons
var finallyStmt = lastSon(tryStmt.n)
if finallyStmt.kind == nkFinally:
genStmts(p, finallyStmt.sons[0])
# push old elements again:
for i in countdown(howManyTrys-1, 0):
p.nestedTryStmts.add(stack[i])
if not p.module.compileToCpp or optNoCppExceptions in p.config.globalOptions:
# Pop exceptions that was handled by the
# except-blocks we are in
for i in countdown(howManyExcepts-1, 0):
linefmt(p, cpsStmts, "#popCurrentException();$n")
proc genGotoState(p: BProc, n: PNode) =
# we resist the temptation to translate it into duff's device as it later
# will be translated into computed gotos anyway for GCC at least:
@ -167,7 +200,11 @@ proc genGotoState(p: BProc, n: PNode) =
initLocExpr(p, n.sons[0], a)
lineF(p, cpsStmts, "switch ($1) {$n", [rdLoc(a)])
p.beforeRetNeeded = true
lineF(p, cpsStmts, "case -1: goto BeforeRet_;$n", [])
lineF(p, cpsStmts, "case -1:$n", [])
blockLeaveActions(p,
howManyTrys = p.nestedTryStmts.len,
howManyExcepts = p.inExceptBlockLen)
lineF(p, cpsStmts, " goto BeforeRet_;$n", [])
var statesCounter = lastOrd(p.config, n.sons[0].typ)
if n.len >= 2 and n[1].kind == nkIntLit:
statesCounter = n[1].intVal
@ -177,17 +214,17 @@ proc genGotoState(p: BProc, n: PNode) =
lineF(p, cpsStmts, "case $2: goto $1$2;$n", [prefix, rope(i)])
lineF(p, cpsStmts, "}$n", [])
proc genBreakState(p: BProc, n: PNode) =
proc genBreakState(p: BProc, n: PNode, d: var TLoc) =
var a: TLoc
initLoc(d, locExpr, n, OnUnknown)
if n.sons[0].kind == nkClosure:
# XXX this produces quite inefficient code!
initLocExpr(p, n.sons[0].sons[1], a)
lineF(p, cpsStmts, "if (((NI*) $1)[1] < 0) break;$n", [rdLoc(a)])
d.r = "(((NI*) $1)[1] < 0)" % [rdLoc(a)]
else:
initLocExpr(p, n.sons[0], a)
# the environment is guaranteed to contain the 'state' field at offset 1:
lineF(p, cpsStmts, "if ((((NI*) $1.ClE_0)[1]) < 0) break;$n", [rdLoc(a)])
# lineF(p, cpsStmts, "if (($1) < 0) break;$n", [rdLoc(a)])
d.r = "((((NI*) $1.ClE_0)[1]) < 0)" % [rdLoc(a)]
proc genGotoVar(p: BProc; value: PNode) =
if value.kind notin {nkCharLit..nkUInt64Lit}:
@ -328,40 +365,6 @@ proc genIf(p: BProc, n: PNode, d: var TLoc) =
else: internalError(p.config, n.info, "genIf()")
if sonsLen(n) > 1: fixLabel(p, lend)
proc blockLeaveActions(p: BProc, howManyTrys, howManyExcepts: int) =
# Called by return and break stmts.
# Deals with issues faced when jumping out of try/except/finally stmts,
var stack = newSeq[tuple[n: PNode, inExcept: bool]](0)
for i in countup(1, howManyTrys):
let tryStmt = p.nestedTryStmts.pop
if not p.module.compileToCpp or optNoCppExceptions in p.config.globalOptions:
# Pop safe points generated by try
if not tryStmt.inExcept:
linefmt(p, cpsStmts, "#popSafePoint();$n")
# Pop this try-stmt of the list of nested trys
# so we don't infinite recurse on it in the next step.
stack.add(tryStmt)
# Find finally-stmt for this try-stmt
# and generate a copy of its sons
var finallyStmt = lastSon(tryStmt.n)
if finallyStmt.kind == nkFinally:
genStmts(p, finallyStmt.sons[0])
# push old elements again:
for i in countdown(howManyTrys-1, 0):
p.nestedTryStmts.add(stack[i])
if not p.module.compileToCpp or optNoCppExceptions in p.config.globalOptions:
# Pop exceptions that was handled by the
# except-blocks we are in
for i in countdown(howManyExcepts-1, 0):
linefmt(p, cpsStmts, "#popCurrentException();$n")
proc genReturnStmt(p: BProc, t: PNode) =
if nfPreventCg in t.flags: return
p.beforeRetNeeded = true
@ -772,6 +775,13 @@ proc genCase(p: BProc, t: PNode, d: var TLoc) =
else:
genOrdinalCase(p, t, d)
proc genRestoreFrameAfterException(p: BProc) =
if optStackTrace in p.module.config.options:
if not p.hasCurFramePointer:
p.hasCurFramePointer = true
p.procSec(cpsLocals).add(ropecg(p.module, "\tTFrame* _nimCurFrame;$n", []))
p.procSec(cpsInit).add(ropecg(p.module, "\t_nimCurFrame = #getFrame();$n", []))
linefmt(p, cpsStmts, "#setFrame(_nimCurFrame);$n")
proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
# code to generate:
@ -791,8 +801,7 @@ proc genTryCpp(p: BProc, t: PNode, d: var TLoc) =
# finallyPart();
template genExceptBranchBody(body: PNode) {.dirty.} =
if optStackTrace in p.options:
linefmt(p, cpsStmts, "#setFrame((TFrame*)&FR_);$n")
genRestoreFrameAfterException(p)
expr(p, body, d)
if not isEmptyType(t.typ) and d.k == locNone:
@ -895,8 +904,7 @@ proc genTry(p: BProc, t: PNode, d: var TLoc) =
endBlock(p)
startBlock(p, "else {$n")
linefmt(p, cpsStmts, "#popSafePoint();$n")
if optStackTrace in p.options:
linefmt(p, cpsStmts, "#setFrame((TFrame*)&FR_);$n")
genRestoreFrameAfterException(p)
p.nestedTryStmts[^1].inExcept = true
var i = 1
while (i < length) and (t.sons[i].kind == nkExceptBranch):

View file

@ -68,6 +68,8 @@ type
prc*: PSym # the Nim proc that this C proc belongs to
beforeRetNeeded*: bool # true iff 'BeforeRet' label for proc is needed
threadVarAccessed*: bool # true if the proc already accessed some threadvar
hasCurFramePointer*: bool # true if _nimCurFrame var needed to recover after
# exception is generated
lastLineInfo*: TLineInfo # to avoid generating excessive 'nimln' statements
currLineInfo*: TLineInfo # AST codegen will make this superfluous
nestedTryStmts*: seq[tuple[n: PNode, inExcept: bool]]

1306
compiler/closureiters.nim Normal file

File diff suppressed because it is too large Load diff

View file

@ -7,12 +7,11 @@
# distribution, for details about the copyright.
#
# This include file implements lambda lifting for the transformator.
# This file implements lambda lifting for the transformator.
import
intsets, strutils, options, ast, astalgo, trees, treetab, msgs, os,
idents, renderer, types, magicsys, lowerings, tables,
modulegraphs, lineinfos
intsets, strutils, options, ast, astalgo, trees, treetab, msgs,
idents, renderer, types, magicsys, lowerings, tables, modulegraphs, lineinfos
discard """
The basic approach is that captured vars need to be put on the heap and
@ -126,7 +125,7 @@ proc newCall(a: PSym, b: PNode): PNode =
result.add newSymNode(a)
result.add b
proc createStateType(g: ModuleGraph; iter: PSym): PType =
proc createClosureIterStateType*(g: ModuleGraph; iter: PSym): PType =
var n = newNodeI(nkRange, iter.info)
addSon(n, newIntNode(nkIntLit, -1))
addSon(n, newIntNode(nkIntLit, 0))
@ -137,8 +136,8 @@ proc createStateType(g: ModuleGraph; iter: PSym): PType =
rawAddSon(result, intType)
proc createStateField(g: ModuleGraph; iter: PSym): PSym =
result = newSym(skField, getIdent(g.cache, ":state"), iter, iter.info, {})
result.typ = createStateType(g, iter)
result = newSym(skField, getIdent(g.cache, ":state"), iter, iter.info)
result.typ = createClosureIterStateType(g, iter)
proc createEnvObj(g: ModuleGraph; owner: PSym; info: TLineInfo): PType =
# YYY meh, just add the state field for every closure for now, it's too
@ -146,12 +145,12 @@ proc createEnvObj(g: ModuleGraph; owner: PSym; info: TLineInfo): PType =
result = createObj(g, owner, info, final=false)
rawAddField(result, createStateField(g, owner))
proc getIterResult(iter: PSym; cache: IdentCache): PSym =
proc getClosureIterResult*(g: ModuleGraph; iter: PSym): PSym =
if resultPos < iter.ast.len:
result = iter.ast.sons[resultPos].sym
else:
# XXX a bit hacky:
result = newSym(skResult, getIdent(cache, ":result"), iter, iter.info, {})
result = newSym(skResult, getIdent(g.cache, ":result"), iter, iter.info, {})
result.typ = iter.typ.sons[0]
incl(result.flags, sfUsed)
iter.ast.add newSymNode(result)
@ -400,7 +399,11 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) =
if not c.capturedVars.containsOrIncl(s.id):
let obj = getHiddenParam(c.graph, owner).typ.lastSon
#let obj = c.getEnvTypeForOwner(s.owner).lastSon
addField(obj, s, c.graph.cache)
if s.name.id == getIdent(c.graph.cache, ":state").id:
obj.n[0].sym.id = -s.id
else:
addField(obj, s, c.graph.cache)
# but always return because the rest of the proc is only relevant when
# ow != owner:
return
@ -598,7 +601,7 @@ proc accessViaEnvVar(n: PNode; owner: PSym; d: DetectionPass;
localError(d.graph.config, n.info, "internal error: not part of closure object type")
result = n
proc getStateField(g: ModuleGraph; owner: PSym): PSym =
proc getStateField*(g: ModuleGraph; owner: PSym): PSym =
getHiddenParam(g, owner).typ.sons[0].n.sons[0].sym
proc liftCapturedVars(n: PNode; owner: PSym; d: DetectionPass;
@ -625,7 +628,7 @@ proc transformYield(n: PNode; owner: PSym; d: DetectionPass;
if n.sons[0].kind != nkEmpty:
var a = newNodeI(nkAsgn, n.sons[0].info)
var retVal = liftCapturedVars(n.sons[0], owner, d, c)
addSon(a, newSymNode(getIterResult(owner, d.graph.cache)))
addSon(a, newSymNode(getClosureIterResult(d.graph, owner)))
addSon(a, retVal)
retStmt.add(a)
else:
@ -718,7 +721,9 @@ proc liftCapturedVars(n: PNode; owner: PSym; d: DetectionPass;
# echo renderTree(s.getBody, {renderIds})
let oldInContainer = c.inContainer
c.inContainer = 0
let body = wrapIterBody(d.graph, liftCapturedVars(s.getBody, s, d, c), s)
var body = liftCapturedVars(s.getBody, s, d, c)
if oldIterTransf in d.graph.config.features:
body = wrapIterBody(d.graph, body, s)
if c.envvars.getOrDefault(s.id).isNil:
s.ast.sons[bodyPos] = body
else:
@ -761,9 +766,9 @@ proc liftCapturedVars(n: PNode; owner: PSym; d: DetectionPass;
if n[1].kind == nkClosure: result = n[1]
else:
if owner.isIterator:
if n.kind == nkYieldStmt:
if oldIterTransf in d.graph.config.features and n.kind == nkYieldStmt:
return transformYield(n, owner, d, c)
elif n.kind == nkReturnStmt:
elif oldIterTransf in d.graph.config.features and n.kind == nkReturnStmt:
return transformReturn(n, owner, d, c)
elif nfLL in n.flags:
# special case 'when nimVm' due to bug #3636:
@ -811,7 +816,7 @@ proc liftIterToProc*(g: ModuleGraph; fn: PSym; body: PNode; ptrType: PType): PNo
fn.typ.callConv = oldCC
proc liftLambdas*(g: ModuleGraph; fn: PSym, body: PNode; tooEarly: var bool): PNode =
# XXX conf.cmd == cmdCompileToJS does not suffice! The compiletime stuff needs
# XXX gCmd == cmdCompileToJS does not suffice! The compiletime stuff needs
# the transformation even when compiling to JS ...
# However we can do lifting for the stuff which is *only* compiletime.
@ -820,6 +825,7 @@ proc liftLambdas*(g: ModuleGraph; fn: PSym, body: PNode; tooEarly: var bool): PN
if body.kind == nkEmpty or (
g.config.cmd == cmdCompileToJS and not isCompileTime) or
fn.skipGenericOwner.kind != skModule:
# ignore forward declaration:
result = body
tooEarly = true
@ -831,10 +837,12 @@ proc liftLambdas*(g: ModuleGraph; fn: PSym, body: PNode; tooEarly: var bool): PN
d.somethingToDo = true
if d.somethingToDo:
var c = initLiftingPass(fn)
var newBody = liftCapturedVars(body, fn, d, c)
result = liftCapturedVars(body, fn, d, c)
if c.envvars.getOrDefault(fn.id) != nil:
newBody = newTree(nkStmtList, rawClosureCreation(fn, d, c), newBody)
result = wrapIterBody(g, newBody, fn)
result = newTree(nkStmtList, rawClosureCreation(fn, d, c), result)
if oldIterTransf in g.config.features:
result = wrapIterBody(g, result, fn)
else:
result = body
#if fn.name.s == "get2":
@ -872,7 +880,8 @@ proc liftForLoop*(g: ModuleGraph; body: PNode; owner: PSym): PNode =
cl = createClosure()
while true:
let i = foo(cl)
nkBreakState(cl.state)
if (nkBreakState(cl.state)):
break
...
"""
if liftingHarmful(g.config, owner): return body
@ -932,5 +941,16 @@ proc liftForLoop*(g: ModuleGraph; body: PNode; owner: PSym): PNode =
loopBody.sons[0] = v2
var bs = newNodeI(nkBreakState, body.info)
bs.addSon(call.sons[0])
loopBody.sons[1] = bs
let ibs = newNodeI(nkIfStmt, body.info)
let elifBranch = newNodeI(nkElifBranch, body.info)
elifBranch.add(bs)
let br = newNodeI(nkBreakStmt, body.info)
br.add(g.emptyNode)
elifBranch.add(br)
ibs.add(elifBranch)
loopBody.sons[1] = ibs
loopBody.sons[2] = body[L-1]

View file

@ -25,7 +25,7 @@ const
SymChars*: set[char] = {'a'..'z', 'A'..'Z', '0'..'9', '\x80'..'\xFF'}
SymStartChars*: set[char] = {'a'..'z', 'A'..'Z', '\x80'..'\xFF'}
OpChars*: set[char] = {'+', '-', '*', '/', '\\', '<', '>', '!', '?', '^', '.',
'|', '=', '%', '&', '$', '@', '~', ':', '\x80'..'\xFF'}
'|', '=', '%', '&', '$', '@', '~', ':'}
# don't forget to update the 'highlite' module if these charsets should change

View file

@ -201,7 +201,8 @@ proc parseAssignment(L: var TLexer, tok: var TToken;
else:
processSwitch(s, val, passPP, info, config)
proc readConfigFile(filename: string; cache: IdentCache; config: ConfigRef) =
proc readConfigFile(
filename: string; cache: IdentCache; config: ConfigRef): bool =
var
L: TLexer
tok: TToken
@ -216,7 +217,7 @@ proc readConfigFile(filename: string; cache: IdentCache; config: ConfigRef) =
while tok.tokType != tkEof: parseAssignment(L, tok, config, condStack)
if len(condStack) > 0: lexMessage(L, errGenerated, "expected @end")
closeLexer(L)
rawMessage(config, hintConf, filename)
return true
proc getUserConfigPath(filename: string): string =
result = joinPath(getConfigDir(), filename)
@ -233,23 +234,33 @@ proc getSystemConfigPath(conf: ConfigRef; filename: string): string =
proc loadConfigs*(cfg: string; cache: IdentCache; conf: ConfigRef) =
setDefaultLibpath(conf)
var configFiles = newSeq[string]()
template readConfigFile(path: string) =
let configPath = path
if readConfigFile(configPath, cache, conf):
add(configFiles, configPath)
if optSkipConfigFile notin conf.globalOptions:
readConfigFile(getSystemConfigPath(conf, cfg), cache, conf)
readConfigFile(getSystemConfigPath(conf, cfg))
if optSkipUserConfigFile notin conf.globalOptions:
readConfigFile(getUserConfigPath(cfg), cache, conf)
readConfigFile(getUserConfigPath(cfg))
let pd = if conf.projectPath.len > 0: conf.projectPath else: getCurrentDir()
if optSkipParentConfigFiles notin conf.globalOptions:
for dir in parentDirs(pd, fromRoot=true, inclusive=false):
readConfigFile(dir / cfg, cache, conf)
readConfigFile(dir / cfg)
if optSkipProjConfigFile notin conf.globalOptions:
readConfigFile(pd / cfg, cache, conf)
readConfigFile(pd / cfg)
if conf.projectName.len != 0:
# new project wide config file:
var projectConfig = changeFileExt(conf.projectFull, "nimcfg")
if not fileExists(projectConfig):
projectConfig = changeFileExt(conf.projectFull, "nim.cfg")
readConfigFile(projectConfig, cache, conf)
readConfigFile(projectConfig)
for filename in configFiles:
rawMessage(conf, hintConf, filename)

View file

@ -118,7 +118,8 @@ type
callOperator,
parallel,
destructor,
notnil
notnil,
oldIterTransf
SymbolFilesOption* = enum
disabledSf, writeOnlySf, readOnlySf, v2Sf

View file

@ -381,6 +381,10 @@ proc processPush(c: PContext, n: PNode, start: int) =
x.otherPragmas.add n.sons[i]
#localError(c.config, n.info, errOptionExpected)
# If stacktrace is disabled globally we should not enable it
if optStackTrace notin c.optionStack[0].options:
c.config.options.excl(optStackTrace)
proc processPop(c: PContext, n: PNode) =
if c.optionStack.len <= 1:
localError(c.config, n.info, "{.pop.} without a corresponding {.push.}")

View file

@ -1414,11 +1414,21 @@ proc gsub(g: var TSrcGen, n: PNode, c: TContext) =
put(g, tkParLe, "(ComesFrom|")
gsub(g, n, 0)
put(g, tkParRi, ")")
of nkGotoState, nkState:
of nkGotoState:
var c: TContext
initContext c
putWithSpace g, tkSymbol, if n.kind == nkState: "state" else: "goto"
putWithSpace g, tkSymbol, "goto"
gsons(g, n, c)
of nkState:
var c: TContext
initContext c
putWithSpace g, tkSymbol, "state"
gsub(g, n[0], c)
putWithSpace(g, tkColon, ":")
indentNL(g)
gsons(g, n, c, 1)
dedent(g)
of nkBreakState:
put(g, tkTuple, "breakstate")
of nkTypeClassTy:

View file

@ -158,11 +158,13 @@ proc commonType*(x, y: PType): PType =
a = a.lastSon.skipTypes({tyGenericInst})
b = b.lastSon.skipTypes({tyGenericInst})
if a.kind == tyObject and b.kind == tyObject:
result = commonSuperclass(a, b, k)
result = commonSuperclass(a, b)
# this will trigger an error later:
if result.isNil or result == a: return x
if result == b: return y
if k != tyNone:
# bug #7906, tyRef/tyPtr + tyGenericInst of ref/ptr object ->
# ill-formed AST, no need for additional tyRef/tyPtr
if k != tyNone and x.kind != tyGenericInst:
let r = result
result = newType(k, r.owner)
result.addSonSkipIntLit(r)

View file

@ -1556,7 +1556,7 @@ proc semYield(c: PContext, n: PNode): PNode =
checkSonsLen(n, 1, c.config)
if c.p.owner == nil or c.p.owner.kind != skIterator:
localError(c.config, n.info, errYieldNotAllowedHere)
elif c.p.inTryStmt > 0 and c.p.owner.typ.callConv != ccInline:
elif oldIterTransf in c.features and c.p.inTryStmt > 0 and c.p.owner.typ.callConv != ccInline:
localError(c.config, n.info, errYieldNotAllowedInTryStmt)
elif n.sons[0].kind != nkEmpty:
n.sons[0] = semExprWithType(c, n.sons[0]) # check for type compatibility:

View file

@ -2020,6 +2020,14 @@ proc paramTypesMatchAux(m: var TCandidate, f, a: PType,
if r == isGeneric:
result.typ = getInstantiatedType(c, arg, m, base(f))
m.baseTypeMatch = true
# bug #4799, varargs accepting subtype relation object
elif r == isSubtype:
inc(m.subtypeMatches)
if f.kind == tyTypeDesc:
result = arg
else:
result = implicitConv(nkHiddenSubConv, f, arg, m, c)
m.baseTypeMatch = true
else:
result = userConvMatch(c, m, base(f), a, arg)
if result != nil: m.baseTypeMatch = true

View file

@ -19,9 +19,9 @@
# * transforms 'defer' into a 'try finally' statement
import
intsets, strutils, options, ast, astalgo, trees, treetab, msgs, os,
intsets, strutils, options, ast, astalgo, trees, treetab, msgs, lookups,
idents, renderer, types, passes, semfold, magicsys, cgmeth,
lambdalifting, sempass2, lowerings, lookups, destroyer, liftlocals,
lambdalifting, sempass2, lowerings, destroyer, liftlocals, closureiters,
modulegraphs, lineinfos
type
@ -984,6 +984,10 @@ proc transformBody*(g: ModuleGraph; module: PSym, n: PNode, prc: PSym): PNode =
result = liftLocalsIfRequested(prc, result, g.cache, g.config)
if c.needsDestroyPass: #and newDestructors:
result = injectDestructorCalls(g, prc, result)
if prc.isIterator and oldIterTransf notin g.config.features:
result = g.transformClosureIterator(prc, result)
incl(result.flags, nfTransf)
#if prc.name.s == "testbody":
# echo renderTree(result)

View file

@ -1044,7 +1044,7 @@ proc inheritanceDiff*(a, b: PType): int =
inc(result)
result = high(int)
proc commonSuperclass*(a, b: PType, k: TTypeKind): PType =
proc commonSuperclass*(a, b: PType): PType =
# quick check: are they the same?
if sameObjectTypes(a, b): return a
@ -1064,7 +1064,7 @@ proc commonSuperclass*(a, b: PType, k: TTypeKind): PType =
y = skipTypes(y, skipPtrs)
if ancestors.contains(y.id):
# bug #7818, defer the previous skipTypes
if k in {tyRef, tyPtr}: t = y
if t.kind != tyGenericInst: t = y
return t
y = y.sons[0]

View file

@ -855,7 +855,8 @@ proc genMagic(c: PCtx; n: PNode; dest: var TDest; m: TMagic) =
of mNewStringOfCap:
# we ignore the 'cap' argument and translate it as 'newString(0)'.
# eval n.sons[1] for possible side effects:
var tmp = c.genx(n.sons[1])
c.freeTemp(c.genx(n.sons[1]))
var tmp = c.getTemp(n.sons[1].typ)
c.gABx(n, opcLdImmInt, tmp, 0)
if dest < 0: dest = c.getTemp(n.typ)
c.gABC(n, opcNewStr, dest, tmp)