summary refs log tree commit diff stats
path: root/compiler
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2012-11-15 22:54:06 +0100
committerAraq <rumpf_a@web.de>2012-11-15 22:54:06 +0100
commit7a2c11d3cfef74eaf55ab27adbb1748a04d7904f (patch)
tree9a36f7458eb694c26aa8a4aee22377c20a65703e /compiler
parent1fada12a5f6a7af7cc22f49f02a9c63cef6ea130 (diff)
downloadNim-7a2c11d3cfef74eaf55ab27adbb1748a04d7904f.tar.gz
next steps for first class iterators
Diffstat (limited to 'compiler')
-rwxr-xr-xcompiler/ccgstmts.nim8
-rw-r--r--compiler/lambdalifting.nim32
-rwxr-xr-xcompiler/semstmts.nim5
-rwxr-xr-xcompiler/transf.nim4
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: