improvements for first class iterators

This commit is contained in:
Araq 2012-11-15 08:45:16 +01:00
commit 1fada12a5f
3 changed files with 35 additions and 6 deletions

View file

@ -115,6 +115,11 @@ proc genGotoState(p: BProc, n: PNode) =
proc genBreakState(p: BProc, n: PNode) = proc genBreakState(p: BProc, n: PNode) =
var a: TLoc var a: TLoc
initLocExpr(p, n.sons[0], a) initLocExpr(p, n.sons[0], a)
if n.sons[0].kind == nkClosure:
# XXX this produces quite inefficient code!
# the environment is guaranteed to contain the 'state' field at offset 0:
lineF(p, cpsStmts, "if ((((NI*) $1.ClEnv)[0]) < 0) break;$n", [rdLoc(a)])
else:
lineF(p, cpsStmts, "if (($1) < 0) break;$n", [rdLoc(a)]) lineF(p, cpsStmts, "if (($1) < 0) break;$n", [rdLoc(a)])
proc genSingleVar(p: BProc, a: PNode) = proc genSingleVar(p: BProc, a: PNode) =

View file

@ -693,7 +693,7 @@ proc liftIterator*(iter: PSym, body: PNode): PNode =
result.add(stateAsgnStmt) result.add(stateAsgnStmt)
proc liftForLoop*(body: PNode): PNode = proc liftForLoop*(body: PNode): PNode =
# BIG problem ahead: the iterator could be invoked indirectly, but then # problem ahead: the iterator could be invoked indirectly, but then
# we don't know what environment to create here: # we don't know what environment to create here:
# #
# iterator count(): int = # iterator count(): int =
@ -750,7 +750,10 @@ proc liftForLoop*(body: PNode): PNode =
# gather vars in a tuple: # gather vars in a tuple:
var v2 = newNodeI(nkLetSection, body.info) var v2 = newNodeI(nkLetSection, body.info)
var vpart = newNodeI(if L == 3: nkIdentDefs else: nkVarTuple, body.info) var vpart = newNodeI(if L == 3: nkIdentDefs else: nkVarTuple, body.info)
for i in 0 .. L-3: addSon(vpart, body[i]) for i in 0 .. L-3:
assert body[i].kind == nkSym
body[i].sym.kind = skLet
addSon(vpart, body[i])
addSon(vpart, ast.emptyNode) # no explicit type addSon(vpart, ast.emptyNode) # no explicit type
if not env.isnil: if not env.isnil:
@ -760,7 +763,10 @@ proc liftForLoop*(body: PNode): PNode =
loopBody.sons[0] = v2 loopBody.sons[0] = v2
var bs = newNodeI(nkBreakState, body.info) var bs = newNodeI(nkBreakState, body.info)
if not env.isNil:
bs.addSon(indirectAccess(env, bs.addSon(indirectAccess(env,
newSym(skField, getIdent(":state"), env, env.info), body.info)) newSym(skField, getIdent":state", env, env.info), body.info))
else:
bs.addSon(call.sons[0])
loopBody.sons[1] = bs loopBody.sons[1] = bs
loopBody.sons[2] = body[L-1] loopBody.sons[2] = body[L-1]

View file

@ -1,6 +1,11 @@
discard """ discard """
output: '''tada output: '''tada
ta da''' 1
2
3
ta da1
2
3'''
""" """
# Test first class iterator: # Test first class iterator:
@ -21,13 +26,26 @@ iterator tokenize2(s: string, seps: set[char] = Whitespace): tuple[
yield (substr(s, i, j-1), false) yield (substr(s, i, j-1), false)
i = j i = j
iterator count3(): int {.closure.} =
yield 1
yield 2
yield 3
for word, isSep in tokenize2("ta da", whiteSpace): for word, isSep in tokenize2("ta da", whiteSpace):
if not isSep: if not isSep:
stdout.write(word) stdout.write(word)
echo "" echo ""
proc inProc() = proc inProc() =
for c in count3():
echo c
for word, isSep in tokenize2("ta da", whiteSpace): for word, isSep in tokenize2("ta da", whiteSpace):
stdout.write(word) stdout.write(word)
for c in count3():
echo c
inProc() inProc()