diff options
Diffstat (limited to 'compiler/lambdalifting.nim')
-rw-r--r-- | compiler/lambdalifting.nim | 22 |
1 files changed, 14 insertions, 8 deletions
diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim index d8c0461ce..c318421fa 100644 --- a/compiler/lambdalifting.nim +++ b/compiler/lambdalifting.nim @@ -11,7 +11,8 @@ import intsets, strutils, options, ast, astalgo, trees, treetab, msgs, - idents, renderer, types, magicsys, lowerings, tables, modulegraphs, lineinfos + idents, renderer, types, magicsys, lowerings, tables, modulegraphs, lineinfos, + transf discard """ The basic approach is that captured vars need to be put on the heap and @@ -257,7 +258,7 @@ proc liftIterSym*(g: ModuleGraph; n: PNode; owner: PSym): PNode = # add 'new' statement: result.add newCall(getSysSym(g, n.info, "internalNew"), env) result.add makeClosure(g, iter, env, n.info) - + proc freshVarForClosureIter*(g: ModuleGraph; s, owner: PSym): PNode = let envParam = getHiddenParam(g, owner) let obj = envParam.typ.lastSon @@ -277,8 +278,9 @@ proc freshVarForClosureIter*(g: ModuleGraph; s, owner: PSym): PNode = proc markAsClosure(g: ModuleGraph; owner: PSym; n: PNode) = let s = n.sym if illegalCapture(s): - localError(g.config, n.info, "illegal capture '$1' of type <$2> which is declared here: $3" % - [s.name.s, typeToString(s.typ), g.config$s.info]) + localError(g.config, n.info, + ("'$1' is of type <$2> which cannot be captured as it would violate memory" & + " safety, declared here: $3") % [s.name.s, typeToString(s.typ), g.config$s.info]) elif owner.typ.callConv notin {ccClosure, ccDefault}: localError(g.config, n.info, "illegal capture '$1' because '$2' has the calling convention: <$3>" % [s.name.s, owner.name.s, CallingConvToStr[owner.typ.callConv]]) @@ -389,7 +391,8 @@ proc detectCapturedVars(n: PNode; owner: PSym; c: var DetectionPass) = if innerProc: if s.isIterator: c.somethingToDo = true if not c.processed.containsOrIncl(s.id): - detectCapturedVars(s.getBody, s, c) + let body = transformBody(c.graph, s) + detectCapturedVars(body, s, c) let ow = s.skipGenericOwner if ow == owner: if owner.isIterator: @@ -650,14 +653,17 @@ proc liftCapturedVars(n: PNode; owner: PSym; d: DetectionPass; # echo renderTree(s.getBody, {renderIds}) let oldInContainer = c.inContainer c.inContainer = 0 - var body = liftCapturedVars(s.getBody, s, d, c) + var body = transformBody(d.graph, s) + body = liftCapturedVars(body, s, d, c) if c.envvars.getOrDefault(s.id).isNil: - s.ast.sons[bodyPos] = body + s.transformedBody = body else: - s.ast.sons[bodyPos] = newTree(nkStmtList, rawClosureCreation(s, d, c), body) + s.transformedBody = newTree(nkStmtList, rawClosureCreation(s, d, c), body) c.inContainer = oldInContainer + if s.typ.callConv == ccClosure: result = symToClosure(n, owner, d, c) + elif s.id in d.capturedVars: if s.owner != owner: result = accessViaEnvParam(d.graph, n, owner) |