diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim index de5bab836e..a67bb27e9d 100644 --- a/compiler/ccgexprs.nim +++ b/compiler/ccgexprs.nim @@ -2944,7 +2944,23 @@ proc genConstSeqV2(p: BProc, n: PNode, t: PType; isConst: bool): Rope = proc genBracedInit(p: BProc, n: PNode; isConst: bool): Rope = case n.kind of nkHiddenStdConv, nkHiddenSubConv: - result = genBracedInit(p, n[1], isConst) + when false: + # XXX The frontend doesn't keep conversions to openArray for us. :-( + # We need to change 'transformConv' first, but that is hard. + if n.typ.kind == tyOpenArray: + assert n[1].kind == nkBracket + let data = genBracedInit(p, n[1], isConst) + + let payload = getTempName(p.module) + let ctype = getTypeDesc(p.module, n.typ.skipTypes(abstractInst)[0]) + let arrLen = n[1].len + appcg(p.module, cfsData, + "static $5 $1 $3[$2] = $4;$n", [ + ctype, arrLen, payload, data, + if isConst: "const" else: ""]) + result = "{($1*)&$2, $3}" % [ctype, payload, rope arrLen] + else: + result = genBracedInit(p, n[1], isConst) else: var ty = tyNone if n.typ == nil: diff --git a/compiler/closureiters.nim b/compiler/closureiters.nim index 3422a8a46c..98249c065c 100644 --- a/compiler/closureiters.nim +++ b/compiler/closureiters.nim @@ -130,7 +130,8 @@ import ast, msgs, idents, - renderer, magicsys, lowerings, lambdalifting, modulegraphs, lineinfos + renderer, magicsys, lowerings, lambdalifting, modulegraphs, lineinfos, + tables, options type Ctx = object @@ -1102,7 +1103,7 @@ proc skipEmptyStates(ctx: Ctx, stateIdx: int): int = result = ctx.states[stateIdx][0].intVal.int -proc skipThroughEmptyStates(ctx: var Ctx, n: PNode): PNode = +proc skipThroughEmptyStates(ctx: var Ctx, n: PNode): PNode= result = n case n.kind of nkSkip: @@ -1282,6 +1283,101 @@ proc deleteEmptyStates(ctx: var Ctx) = else: inc i +type + PreprocessContext = object + finallys: seq[PNode] + config: ConfigRef + blocks: seq[(PNode, int)] + FreshVarsContext = object + tab: Table[int, PSym] + config: ConfigRef + info: TLineInfo + +proc freshVars(n: PNode; c: var FreshVarsContext): PNode = + case n.kind + of nkSym: + let x = c.tab.getOrDefault(n.sym.id) + if x == nil: + result = n + else: + result = newSymNode(x, n.info) + of nkSkip - {nkSym}: + result = n + of nkLetSection, nkVarSection: + result = copyNode(n) + for it in n: + if it.kind in {nkIdentDefs, nkVarTuple}: + let idefs = copyNode(it) + for v in 0..it.len-3: + if it[v].kind == nkSym: + let x = copySym(it[v].sym) + c.tab[it[v].sym.id] = x + idefs.add newSymNode(x) + else: + idefs.add it[v] + + for rest in it.len-2 ..< it.len: idefs.add it[rest] + result.add idefs + else: + result.add it + of nkRaiseStmt: + localError(c.config, c.info, "unsupported control flow: 'finally: ... raise' duplicated because of 'break'") + else: + result = n + for i in 0..= 0: + result = newNodeI(nkStmtList, n.info) + for i in countdown(c.finallys.high, fin): + var vars = FreshVarsContext(tab: initTable[int, PSym](), config: c.config, info: n.info) + result.add freshVars(preprocess(c, c.finallys[i]), vars) + result.add n + of nkSkip: discard + else: + for i in 0 ..< n.len: + result[i] = preprocess(c, n[i]) + proc transformClosureIterator*(g: ModuleGraph; fn: PSym, n: PNode): PNode = var ctx: Ctx ctx.g = g @@ -1294,7 +1390,10 @@ proc transformClosureIterator*(g: ModuleGraph; fn: PSym, n: PNode): PNode = ctx.stateVarSym = newSym(skVar, getIdent(ctx.g.cache, ":state"), fn, fn.info) ctx.stateVarSym.typ = g.createClosureIterStateType(fn) ctx.stateLoopLabel = newSym(skLabel, getIdent(ctx.g.cache, ":stateLoop"), fn, fn.info) - var n = n.toStmtList + var pc = PreprocessContext(finallys: @[], config: g.config) + var n = preprocess(pc, n.toStmtList) + #echo "transformed into ", n + #var n = n.toStmtList discard ctx.newState(n, nil) let gotoOut = newTree(nkGotoState, g.newIntLit(n.info, -1)) diff --git a/compiler/nim.cfg b/compiler/nim.cfg index a77fa84d36..c85a5c3270 100644 --- a/compiler/nim.cfg +++ b/compiler/nim.cfg @@ -19,5 +19,12 @@ define:useStdoutAsStdmsg styleCheck:error @end +# die when the Nim compiler uses more than 4GB: +@if cpu32: + define:"nimMaxHeap=2000" +@else: + define:"nimMaxHeap=4000" +@end + #define:useNodeIds #gc:markAndSweep diff --git a/tests/async/tbreak_must_exec_finally.nim b/tests/async/tbreak_must_exec_finally.nim new file mode 100644 index 0000000000..8780e6149e --- /dev/null +++ b/tests/async/tbreak_must_exec_finally.nim @@ -0,0 +1,25 @@ +discard """ + output: ''' +finally handler 8 +do not duplicate this one +''' +""" + +# bug #15243 + +import asyncdispatch + +proc f() {.async.} = + try: + while true: + try: + await sleepAsync(400) + break + finally: + var localHere = 8 + echo "finally handler ", localHere + finally: + echo "do not duplicate this one" + +when isMainModule: + waitFor f()