diff options
-rw-r--r-- | compiler/lambdalifting.nim | 53 | ||||
-rw-r--r-- | tests/iter/tanoniter1.nim | 4 | ||||
-rw-r--r-- | todo.txt | 7 |
3 files changed, 35 insertions, 29 deletions
diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim index 00fa04556..ebb4aeac4 100644 --- a/compiler/lambdalifting.nim +++ b/compiler/lambdalifting.nim @@ -637,6 +637,22 @@ proc outerProcSons(o: POuterContext, n: PNode) = let x = transformOuterProc(o, n.sons[i]) if x != nil: n.sons[i] = x +proc liftIterSym*(n: PNode): PNode = + # transforms (iter) to (let env = newClosure[iter](); (iter, env)) + let iter = n.sym + assert iter.kind == skIterator + + result = newNodeIT(nkStmtListExpr, n.info, n.typ) + + var env = copySym(getHiddenParam(iter)) + env.kind = skLet + var v = newNodeI(nkVarSection, n.info) + addVar(v, newSymNode(env)) + result.add(v) + # add 'new' statement: + result.add(newCall(getSysSym"internalNew", env)) + result.add makeClosure(iter, env, n.info) + proc transformOuterProc(o: POuterContext, n: PNode): PNode = if n == nil: return nil case n.kind @@ -649,17 +665,22 @@ proc transformOuterProc(o: POuterContext, n: PNode): PNode = return indirectAccess(newSymNode(o.closureParam), local, n.info) var closure = PEnv(idTableGet(o.lambdasToEnv, local)) - if closure != nil: - # we need to replace the lambda with '(lambda, env)': - if local.kind == skIterator and local.typ.callConv == ccClosure: - # consider: [i1, i2, i1] Since we merged the iterator's closure - # with the captured owning variables, we need to generate the - # closure generation code again: - #if local == o.fn: message(n.info, errRecursiveDependencyX, local.name.s) - # XXX why doesn't this work? + + if local.kind == skIterator and local.typ.callConv == ccClosure: + # consider: [i1, i2, i1] Since we merged the iterator's closure + # with the captured owning variables, we need to generate the + # closure generation code again: + if local == o.fn: message(n.info, errRecursiveDependencyX, local.name.s) + # XXX why doesn't this work? + if closure.isNil: + return liftIterSym(n) + else: let createdVar = generateIterClosureCreation(o, closure, closure.attachedNode) return makeClosure(local, createdVar, n.info) + + if closure != nil: + # we need to replace the lambda with '(lambda, env)': let a = closure.createdVar if a != nil: @@ -773,22 +794,6 @@ proc liftLambdasForTopLevel*(module: PSym, body: PNode): PNode = # ------------------- iterator transformation -------------------------------- -proc liftIterSym*(n: PNode): PNode = - # transforms (iter) to (let env = newClosure[iter](); (iter, env)) - let iter = n.sym - assert iter.kind == skIterator - - result = newNodeIT(nkStmtListExpr, n.info, n.typ) - - var env = copySym(getHiddenParam(iter)) - env.kind = skLet - var v = newNodeI(nkVarSection, n.info) - addVar(v, newSymNode(env)) - result.add(v) - # add 'new' statement: - result.add(newCall(getSysSym"internalNew", env)) - result.add makeClosure(iter, env, n.info) - proc liftForLoop*(body: PNode): PNode = # problem ahead: the iterator could be invoked indirectly, but then # we don't know what environment to create here: diff --git a/tests/iter/tanoniter1.nim b/tests/iter/tanoniter1.nim index 9db5ab8ec..578749caf 100644 --- a/tests/iter/tanoniter1.nim +++ b/tests/iter/tanoniter1.nim @@ -22,11 +22,11 @@ proc factory2(a, b: int): iterator (): int = yield x inc x -let foo = factory 1, 4 +let foo = factory(1, 4) for f in foo(): echo f -let foo2 = factory2 1,2 +let foo2 = factory2(1,2) for f in foo2(): echo f diff --git a/todo.txt b/todo.txt index 0962d172e..44aa39791 100644 --- a/todo.txt +++ b/todo.txt @@ -4,9 +4,7 @@ version 0.9.4 - fix GC issues - fix macros\tstringinterp.nim - test and fix showoff -- fix closures -- test and fix exception handling -- implement 'union' and 'bits' pragmas +- fix closure iterators Bugs @@ -27,6 +25,9 @@ Bugs version 0.9.x ============= +- implement 'union' and 'bits' pragmas +- fix closures +- test and fix exception handling - ensure (ref T)(a, b) works as a type conversion and type constructor - optimize 'genericReset'; 'newException' leads to code bloat - stack-less GC |