diff options
author | Andreas Rumpf <rumpf_a@web.de> | 2016-01-03 23:20:53 +0100 |
---|---|---|
committer | Andreas Rumpf <rumpf_a@web.de> | 2016-01-03 23:20:53 +0100 |
commit | b4c62d5fedf155cbab57cfeead97eccc94345c71 (patch) | |
tree | b424e6e98ecd20bef623e34e36900b0e0189708b | |
parent | 813f98fb342418606f82a082373636137b811bae (diff) | |
download | Nim-b4c62d5fedf155cbab57cfeead97eccc94345c71.tar.gz |
async works again
-rw-r--r-- | compiler/lambdalifting.nim | 48 | ||||
-rw-r--r-- | tests/closure/tclosure0.nim | 87 | ||||
-rw-r--r-- | tests/iter/tclosureiters.nim | 73 |
3 files changed, 188 insertions, 20 deletions
diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim index 378f3a187..8150e30c8 100644 --- a/compiler/lambdalifting.nim +++ b/compiler/lambdalifting.nim @@ -451,15 +451,19 @@ proc newEnvVar(owner: PSym; typ: PType): PNode = var v = newSym(skVar, getIdent(envName), owner, owner.info) incl(v.flags, sfShadowed) v.typ = typ - if owner.kind == skIterator and owner.typ.callConv == ccClosure: - let it = getHiddenParam(owner) - addUniqueField(it.typ.sons[0], v) - result = indirectAccess(newSymNode(it), v, v.info) - else: - result = newSymNode(v) + result = newSymNode(v) + when false: + if owner.kind == skIterator and owner.typ.callConv == ccClosure: + let it = getHiddenParam(owner) + addUniqueField(it.typ.sons[0], v) + result = indirectAccess(newSymNode(it), v, v.info) + else: + result = newSymNode(v) proc setupEnvVar(owner: PSym; d: DetectionPass; c: var LiftingPass): PNode = + if owner.isIterator: + return getHiddenParam(owner).newSymNode result = c.envvars.getOrDefault(owner.id) if result.isNil: let envVarType = d.ownerToType.getOrDefault(owner.id) @@ -482,20 +486,24 @@ proc rawClosureCreation(owner: PSym; d: DetectionPass; c: var LiftingPass): PNode = result = newNodeI(nkStmtList, owner.info) - let env = setupEnvVar(owner, d, c) - if env.kind == nkSym: - var v = newNodeI(nkVarSection, env.info) - addVar(v, env) - result.add(v) - # add 'new' statement: - result.add(newCall(getSysSym"internalNew", env)) - # add assignment statements for captured parameters: - for i in 1..<owner.typ.n.len: - let local = owner.typ.n[i].sym - if local.id in d.capturedVars: - let fieldAccess = indirectAccess(env, local, env.info) - # add ``env.param = param`` - result.add(newAsgnStmt(fieldAccess, newSymNode(local), env.info)) + var env: PNode + if owner.isIterator: + env = getHiddenParam(owner).newSymNode + else: + env = setupEnvVar(owner, d, c) + if env.kind == nkSym: + var v = newNodeI(nkVarSection, env.info) + addVar(v, env) + result.add(v) + # add 'new' statement: + result.add(newCall(getSysSym"internalNew", env)) + # add assignment statements for captured parameters: + for i in 1..<owner.typ.n.len: + let local = owner.typ.n[i].sym + if local.id in d.capturedVars: + let fieldAccess = indirectAccess(env, local, env.info) + # add ``env.param = param`` + result.add(newAsgnStmt(fieldAccess, newSymNode(local), env.info)) let upField = lookupInRecord(env.typ.lastSon.n, getIdent(upName)) if upField != nil: diff --git a/tests/closure/tclosure0.nim b/tests/closure/tclosure0.nim new file mode 100644 index 000000000..9952268d5 --- /dev/null +++ b/tests/closure/tclosure0.nim @@ -0,0 +1,87 @@ +discard """ + output: '''foo88 +23 24foo 88 +18 +18 +99 +99 +99 +99 99 +99 99 +12 99 99 +12 99 99''' +""" + +when true: + # test simple closure within dummy 'main': + proc dummy = + proc main2(param: int) = + var fooB = 23 + proc outer(outerParam: string) = + var outerVar = 88 + echo outerParam, outerVar + proc inner() = + block Test: + echo fooB, " ", param, outerParam, " ", outerVar + inner() + outer("foo") + main2(24) + + dummy() + +when true: + proc outer2(x:int) : proc(y:int):int = # curry-ed application + return proc(y:int):int = x*y + + var fn = outer2(6) # the closure + echo fn(3) # it works + + var rawP = fn.rawProc() + var rawE = fn.rawEnv() + + # A type to cast the function pointer into a nimcall + type + TimesClosure = proc(a: int, x: pointer): int {.nimcall.} + + # Call the function with its closure + echo cast[TimesClosure](rawP)(3, rawE) + +when true: + proc outer = + var x, y: int = 99 + proc innerA = echo x + proc innerB = + echo y + innerA() + + innerA() + innerB() + + outer() + +when true: + proc indirectDep = + var x, y: int = 99 + proc innerA = echo x, " ", y + proc innerB = + innerA() + + innerA() + innerB() + + indirectDep() + +when true: + proc needlessIndirection = + var x, y: int = 99 + proc indirection = + var z = 12 + proc innerA = echo z, " ", x, " ", y + proc innerB = + innerA() + + innerA() + innerB() + indirection() + + needlessIndirection() diff --git a/tests/iter/tclosureiters.nim b/tests/iter/tclosureiters.nim new file mode 100644 index 000000000..0eb624a8c --- /dev/null +++ b/tests/iter/tclosureiters.nim @@ -0,0 +1,73 @@ +discard """ + output: '''0 +1 +2 +3 +4 +5 +6 +7 +8 +9 +10 +5 5 +7 7 +9 9 +0 +0 +0 +0 +1 +2''' +""" + +when true: + proc main() = + let + lo=0 + hi=10 + + iterator itA(): int = + for x in lo..hi: + yield x + + for x in itA(): + echo x + + var y: int + + iterator itB(): int = + while y <= hi: + yield y + inc y + + y = 5 + for x in itB(): + echo x, " ", y + inc y + + main() + + +iterator infinite(): int {.closure.} = + var i = 0 + while true: + yield i + inc i + +iterator take[T](it: iterator (): T, numToTake: int): T {.closure.} = + var i = 0 + for x in it(): + if i >= numToTake: + break + yield x + inc i + +# gives wrong reasult (3 times 0) +for x in infinite.take(3): + echo x + +# does what we want +let inf = infinite +for x in inf.take(3): + echo x |