fixex merge conflicts
This commit is contained in:
commit
8e9551b1c7
53 changed files with 2648 additions and 355 deletions
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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 =
|
||||
|
|
|
|||
|
|
@ -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):
|
||||
|
|
|
|||
|
|
@ -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
1306
compiler/closureiters.nim
Normal file
File diff suppressed because it is too large
Load diff
|
|
@ -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]
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -118,7 +118,8 @@ type
|
|||
callOperator,
|
||||
parallel,
|
||||
destructor,
|
||||
notnil
|
||||
notnil,
|
||||
oldIterTransf
|
||||
|
||||
SymbolFilesOption* = enum
|
||||
disabledSf, writeOnlySf, readOnlySf, v2Sf
|
||||
|
|
|
|||
|
|
@ -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.}")
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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]
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue