diff options
author | Araq <rumpf_a@web.de> | 2012-11-15 22:54:06 +0100 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2012-11-15 22:54:06 +0100 |
commit | 7a2c11d3cfef74eaf55ab27adbb1748a04d7904f (patch) | |
tree | 9a36f7458eb694c26aa8a4aee22377c20a65703e /compiler | |
parent | 1fada12a5f6a7af7cc22f49f02a9c63cef6ea130 (diff) | |
download | Nim-7a2c11d3cfef74eaf55ab27adbb1748a04d7904f.tar.gz |
next steps for first class iterators
Diffstat (limited to 'compiler')
-rwxr-xr-x | compiler/ccgstmts.nim | 8 | ||||
-rw-r--r-- | compiler/lambdalifting.nim | 32 | ||||
-rwxr-xr-x | compiler/semstmts.nim | 5 | ||||
-rwxr-xr-x | compiler/transf.nim | 4 |
4 files changed, 39 insertions, 10 deletions
diff --git a/compiler/ccgstmts.nim b/compiler/ccgstmts.nim index 5e3504cd9..a950c62df 100755 --- a/compiler/ccgstmts.nim +++ b/compiler/ccgstmts.nim @@ -114,13 +114,15 @@ proc genGotoState(p: BProc, n: PNode) = proc genBreakState(p: BProc, n: PNode) = var a: TLoc - initLocExpr(p, n.sons[0], a) if n.sons[0].kind == nkClosure: # XXX this produces quite inefficient code! + initLocExpr(p, n.sons[0].sons[1], a) + lineF(p, cpsStmts, "if (($1->Field0) < 0) break;$n", [rdLoc(a)]) + else: + initLocExpr(p, n.sons[0], a) # 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) = var v = a.sons[0].sym diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim index 9d7e0e961..dc51d2d22 100644 --- a/compiler/lambdalifting.nim +++ b/compiler/lambdalifting.nim @@ -692,6 +692,28 @@ proc liftIterator*(iter: PSym, body: PNode): PNode = stateAsgnStmt.add(newIntTypeNode(nkIntLit, -1, getSysType(tyInt))) result.add(stateAsgnStmt) +# TODO: +# - nested iterators +# - arglist as a type +# - tyIterator everywhere +# - 'finished' builtin +# - 'start' builtin (XXX copy Lua's terminology?) + +proc liftIterSym*(n: PNode): PNode = + # transforms (iter) to (let env = newClosure[iter](); (iter, env)) + result = newNodeIT(nkStmtListExpr, n.info, n.typ) + let iter = n.sym + assert iter.kind == skIterator + var env = copySym(getHiddenParam(iter)) + env.kind = skLet + + var v = newNodeI(nkVarSection, n.info) + addVar(v, newSymNode(env)) + result.add(v) + # add 'new' statement: + result.add(newCall(getSysSym"internalNew", env)) + result.add makeClosure(iter, env, n.info) + proc liftForLoop*(body: PNode): PNode = # problem ahead: the iterator could be invoked indirectly, but then # we don't know what environment to create here: @@ -763,10 +785,10 @@ proc liftForLoop*(body: PNode): PNode = loopBody.sons[0] = v2 var bs = newNodeI(nkBreakState, body.info) - if not env.isNil: - bs.addSon(indirectAccess(env, - newSym(skField, getIdent":state", env, env.info), body.info)) - else: - bs.addSon(call.sons[0]) + #if not env.isNil: + # bs.addSon(indirectAccess(env, + # newSym(skField, getIdent":state", env, env.info), body.info)) + #else: + bs.addSon(call.sons[0]) loopBody.sons[1] = bs loopBody.sons[2] = body[L-1] diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index 40f081b59..18588fb49 100755 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -406,7 +406,10 @@ proc semFor(c: PContext, n: PNode): PNode = openScope(c.tab) n.sons[length-2] = semExprNoDeref(c, n.sons[length-2], {efWantIterator}) var call = n.sons[length-2] - if call.kind notin nkCallKinds or call.sons[0].kind != nkSym or + if call.kind in nkCallKinds and call.sons[0].typ.callConv == ccClosure: + # first class iterator: + result = semForVars(c, n) + elif call.kind notin nkCallKinds or call.sons[0].kind != nkSym or call.sons[0].sym.kind != skIterator: if length == 3: n.sons[length-2] = implicitIterator(c, "items", n.sons[length-2]) diff --git a/compiler/transf.nim b/compiler/transf.nim index d93cef203..d28b9b21d 100755 --- a/compiler/transf.nim +++ b/compiler/transf.nim @@ -112,7 +112,9 @@ proc newAsgnStmt(c: PTransf, le: PNode, ri: PTransNode): PTransNode = result[0] = PTransNode(le) result[1] = ri -proc transformSymAux(c: PTransf, n: PNode): PNode = +proc transformSymAux(c: PTransf, n: PNode): PNode = + if n.sym.kind == skIterator and n.sym.typ.callConv == ccClosure: + return liftIterSym(n) var b: PNode var tc = c.transCon if sfBorrow in n.sym.flags: |