mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-04 12:07:51 +00:00
async works again
This commit is contained in:
@@ -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:
|
||||
|
||||
87
tests/closure/tclosure0.nim
Normal file
87
tests/closure/tclosure0.nim
Normal 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()
|
||||
73
tests/iter/tclosureiters.nim
Normal file
73
tests/iter/tclosureiters.nim
Normal 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
|
||||
Reference in New Issue
Block a user