async works again

This commit is contained in:
Andreas Rumpf 2016-01-03 23:20:53 +01:00
commit b4c62d5fed
3 changed files with 188 additions and 20 deletions

View file

@ -451,15 +451,19 @@ proc newEnvVar(owner: PSym; typ: PType): PNode =
var v = newSym(skVar, getIdent(envName), owner, owner.info) var v = newSym(skVar, getIdent(envName), owner, owner.info)
incl(v.flags, sfShadowed) incl(v.flags, sfShadowed)
v.typ = typ v.typ = typ
if owner.kind == skIterator and owner.typ.callConv == ccClosure: result = newSymNode(v)
let it = getHiddenParam(owner) when false:
addUniqueField(it.typ.sons[0], v) if owner.kind == skIterator and owner.typ.callConv == ccClosure:
result = indirectAccess(newSymNode(it), v, v.info) let it = getHiddenParam(owner)
else: addUniqueField(it.typ.sons[0], v)
result = newSymNode(v) result = indirectAccess(newSymNode(it), v, v.info)
else:
result = newSymNode(v)
proc setupEnvVar(owner: PSym; d: DetectionPass; proc setupEnvVar(owner: PSym; d: DetectionPass;
c: var LiftingPass): PNode = c: var LiftingPass): PNode =
if owner.isIterator:
return getHiddenParam(owner).newSymNode
result = c.envvars.getOrDefault(owner.id) result = c.envvars.getOrDefault(owner.id)
if result.isNil: if result.isNil:
let envVarType = d.ownerToType.getOrDefault(owner.id) let envVarType = d.ownerToType.getOrDefault(owner.id)
@ -482,20 +486,24 @@ proc rawClosureCreation(owner: PSym;
d: DetectionPass; c: var LiftingPass): PNode = d: DetectionPass; c: var LiftingPass): PNode =
result = newNodeI(nkStmtList, owner.info) result = newNodeI(nkStmtList, owner.info)
let env = setupEnvVar(owner, d, c) var env: PNode
if env.kind == nkSym: if owner.isIterator:
var v = newNodeI(nkVarSection, env.info) env = getHiddenParam(owner).newSymNode
addVar(v, env) else:
result.add(v) env = setupEnvVar(owner, d, c)
# add 'new' statement: if env.kind == nkSym:
result.add(newCall(getSysSym"internalNew", env)) var v = newNodeI(nkVarSection, env.info)
# add assignment statements for captured parameters: addVar(v, env)
for i in 1..<owner.typ.n.len: result.add(v)
let local = owner.typ.n[i].sym # add 'new' statement:
if local.id in d.capturedVars: result.add(newCall(getSysSym"internalNew", env))
let fieldAccess = indirectAccess(env, local, env.info) # add assignment statements for captured parameters:
# add ``env.param = param`` for i in 1..<owner.typ.n.len:
result.add(newAsgnStmt(fieldAccess, newSymNode(local), env.info)) 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)) let upField = lookupInRecord(env.typ.lastSon.n, getIdent(upName))
if upField != nil: if upField != nil:

View file

@ -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()

View file

@ -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