async works again

This commit is contained in:
Andreas Rumpf
2016-01-03 23:20:53 +01:00
parent 813f98fb34
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)
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:

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