summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2014-06-28 01:03:07 +0200
committerAraq <rumpf_a@web.de>2014-06-28 01:03:07 +0200
commit59f61bae05047a0f110ca419272dbe3d53a412a6 (patch)
tree515365fc9af2d973533fb292ca7b0749f5f1830d
parent79586487be202ffb7499a8917ac33024ce9c3a16 (diff)
downloadNim-59f61bae05047a0f110ca419272dbe3d53a412a6.tar.gz
new jester compiles
-rw-r--r--compiler/lambdalifting.nim24
-rw-r--r--compiler/lowerings.nim10
-rw-r--r--tests/closure/tjester.nim32
3 files changed, 58 insertions, 8 deletions
diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim
index 402ad7d3d..ee380b305 100644
--- a/compiler/lambdalifting.nim
+++ b/compiler/lambdalifting.nim
@@ -240,9 +240,6 @@ proc newEnv(o: POuterContext; up: PEnv, n: PNode; owner: PSym): PEnv =
   result.next = o.head
   o.head = result
   if owner.kind != skModule and (up == nil or up.fn != owner):
-    if owner.ast == nil:
-      debug owner
-      echo owner.name.s
     let param = getEnvParam(owner)
     if param != nil:
       result.obj = param.typ.sons[0]
@@ -808,8 +805,9 @@ proc transformOuterProc(o: POuterContext, n: PNode; it: TIter): PNode =
     if it.fn.kind == skClosureIterator and interestingIterVar(local) and
         it.fn == local.owner:
       # every local goes through the closure:
-      if not containsOrIncl(o.capturedVars, local.id):
-        addField(it.obj, local)
+      #if not containsOrIncl(o.capturedVars, local.id):
+      #  addField(it.obj, local)
+      addUniqueField(it.obj, local)
       return indirectAccess(newSymNode(it.closureParam), local, n.info)
 
     var closure = PEnv(idTableGet(o.lambdasToEnv, local))
@@ -853,10 +851,18 @@ proc transformOuterProc(o: POuterContext, n: PNode; it: TIter): PNode =
   of nkLambdaKinds, nkIteratorDef:
     if n.typ != nil:
       result = transformOuterProc(o, n.sons[namePos], it)
-  of nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef, nkTemplateDef,
-      nkClosure:
+  of nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef, nkTemplateDef:
     # don't recurse here:
     discard
+  of nkClosure:
+    if n.sons[0].kind == nkSym:
+      var local = n.sons[0].sym
+      if isInnerProc(local, o.fn) and o.processed.contains(local.id):
+        o.processed.excl(local.id)
+        let body = local.getBody
+        let newBody = transformOuterProcBody(o, body, initIter(local))
+        if newBody != nil:
+          local.ast.sons[bodyPos] = newBody
   of nkHiddenStdConv, nkHiddenSubConv, nkConv:
     let x = transformOuterProc(o, n.sons[1], it)
     if x != nil: n.sons[1] = x
@@ -878,6 +884,8 @@ proc liftLambdas*(fn: PSym, body: PNode): PNode =
     # ignore forward declaration:
     result = body
   else:
+    #if fn.name.s == "cbOuter":
+    #  echo rendertree(fn.ast, {renderIds})
     var o = newOuterContext(fn)
     let ex = closureCreationPoint(body)
     let env = newEnv(o, nil, ex, fn)
@@ -890,7 +898,7 @@ proc liftLambdas*(fn: PSym, body: PNode): PNode =
       discard transformOuterProcBody(o, body, initIter(fn))
       result = ex
     finishEnvironments(o)
-    #if fn.name.s == "cbOuter" or fn.name.s == "factory2":
+    #if fn.name.s == "cbOuter":
     #  echo rendertree(result, {renderIds})
 
 proc liftLambdasForTopLevel*(module: PSym, body: PNode): PNode =
diff --git a/compiler/lowerings.nim b/compiler/lowerings.nim
index 74690ac0c..5b61a9cae 100644
--- a/compiler/lowerings.nim
+++ b/compiler/lowerings.nim
@@ -90,6 +90,16 @@ proc addField*(obj: PType; s: PSym) =
   field.position = sonsLen(obj.n)
   addSon(obj.n, newSymNode(field))
 
+proc addUniqueField*(obj: PType; s: PSym) =
+  let fieldName = getIdent(s.name.s & $s.id)
+  if lookupInRecord(obj.n, fieldName) == nil:
+    var field = newSym(skField, fieldName, s.owner, s.info)
+    let t = skipIntLit(s.typ)
+    field.typ = t
+    assert t.kind != tyStmt
+    field.position = sonsLen(obj.n)
+    addSon(obj.n, newSymNode(field))
+
 proc newDotExpr(obj, b: PSym): PNode =
   result = newNodeI(nkDotExpr, obj.info)
   let field = getSymFromList(obj.typ.n, getIdent(b.name.s & $b.id))
diff --git a/tests/closure/tjester.nim b/tests/closure/tjester.nim
new file mode 100644
index 000000000..48e5186f0
--- /dev/null
+++ b/tests/closure/tjester.nim
@@ -0,0 +1,32 @@
+discard """
+  output: '''baro0'''
+"""
+
+type
+  Future[T] = ref object
+    data: T
+    callback: proc () {.closure.}
+
+proc cbOuter(response: string) {.closure, discardable.} =
+  iterator cbIter(): Future[int] {.closure.} =
+    for i in 0..7:
+      proc foo(): int =
+        iterator fooIter(): Future[int] {.closure.} =
+          echo response, i
+          yield Future[int](data: 17)
+        var iterVar = fooIter
+        iterVar().data
+      yield Future[int](data: foo())
+      
+  var iterVar2 = cbIter
+  proc cb2() {.closure.} =
+    try:
+      if not finished(iterVar2):
+        let next = iterVar2()
+        if next != nil:
+          next.callback = cb2
+    except:
+      echo "WTF"
+  cb2()
+
+cbOuter "baro"