summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2012-06-17 02:11:13 +0200
committerAraq <rumpf_a@web.de>2012-06-17 02:11:13 +0200
commit7076f07228f65b05312b609f89dbac767b69394f (patch)
tree9c43de800eea5fa093ea964a6e4ba9a6085f94fa
parent7b539c9e582e441cdb7e078cdbe247d06a74ad0e (diff)
downloadNim-7076f07228f65b05312b609f89dbac767b69394f.tar.gz
tinterf.nim works now
-rw-r--r--compiler/lambdalifting.nim21
-rwxr-xr-xcompiler/semtypes.nim13
-rw-r--r--tests/run/tclosure2.nim17
-rw-r--r--tests/run/tinterf.nim20
4 files changed, 54 insertions, 17 deletions
diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim
index 96cf6aef0..8dd54131f 100644
--- a/compiler/lambdalifting.nim
+++ b/compiler/lambdalifting.nim
@@ -193,9 +193,13 @@ proc addHiddenParam(routine: PSym, param: PSym) =
   var params = routine.ast.sons[paramsPos]
   param.position = params.len
   addSon(params, newSymNode(param))
-  #echo "produced environment: ", param.id, " for ", routine.name.s
+  echo "produced environment: ", param.id, " for ", routine.name.s
 
 proc isInnerProc(s, outerProc: PSym): bool {.inline.} =
+  if s.name.s[0] == ':':
+    debug s
+    debug s.owner
+    debug outerProc
   result = s.kind in {skProc, skIterator, skMethod, skConverter} and
     s.owner == outerProc and not isGenericRoutine(s)
   #s.typ.callConv == ccClosure
@@ -216,6 +220,7 @@ proc captureVar(o: POuterContext, i: PInnerContext, local: PSym,
   """
   # we need to remember which outer closure belongs to this lambda; we also
   # use this check to prevent multiple runs over the same inner proc:
+  echo "enter"
   if IdNodeTableGet(o.lambdasToEnclosingScope, i.fn) != nil: return
   IdNodeTablePut(o.lambdasToEnclosingScope, i.fn, o.currentBlock)
 
@@ -244,6 +249,7 @@ proc captureVar(o: POuterContext, i: PInnerContext, local: PSym,
   access = indirectAccess(access, local, info)
   IdNodeTablePut(i.localsToAccess, local, access)
   incl(o.capturedVars, local.id)
+  echo "exit"
 
 proc interestingVar(s: PSym): bool {.inline.} =
   result = s.kind in {skVar, skLet, skTemp, skForVar, skParam, skResult} and
@@ -256,7 +262,6 @@ proc gatherVars(o: POuterContext, i: PInnerContext, n: PNode) =
     var s = n.sym
     if interestingVar(s) and i.fn.id != s.owner.id:
       captureVar(o, i, s, n.info)
-      #echo "captured: ", s.name.s
   of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit: nil
   else:
     for k in countup(0, sonsLen(n) - 1): 
@@ -281,8 +286,10 @@ proc transformInnerProc(o: POuterContext, i: PInnerContext, n: PNode): PNode =
     else:
       # captured symbol?
       result = IdNodeTableGet(i.localsToAccess, n.sym)
+  of nkLambdaKinds:
+    result = transformInnerProc(o, i, n.sons[namePos])
   of nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef, nkTemplateDef,
-     nkIteratorDef, nkLambdaKinds:
+     nkIteratorDef:
     # don't recurse here:
     nil
   else:
@@ -306,6 +313,8 @@ proc searchForInnerProcs(o: POuterContext, n: PNode) =
       gatherVars(o, inner, body)
       let ti = transformInnerProc(o, inner, body)
       if ti != nil: n.sym.ast.sons[bodyPos] = ti
+  of nkLambdaKinds:
+    searchForInnerProcs(o, n.sons[namePos])
   of nkWhileStmt, nkForStmt, nkParForStmt, nkBlockStmt:
     # some nodes open a new scope, so they are candidates for the insertion
     # of closure creation; however for simplicity we merge closures between
@@ -340,7 +349,7 @@ proc searchForInnerProcs(o: POuterContext, n: PNode) =
       else:
         InternalError(it.info, "transformOuter")
   of nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef, nkTemplateDef, 
-     nkIteratorDef, nkLambdaKinds: 
+     nkIteratorDef:
     # don't recurse here:
     # XXX recurse here and setup 'up' pointers
     nil
@@ -421,8 +430,10 @@ proc transformOuterProc(o: POuterContext, n: PNode): PNode =
       assert result != nil, "cannot find: " & local.name.s
     # else it is captured by copy and this means that 'outer' should continue
     # to access the local as a local.
+  of nkLambdaKinds:
+    result = transformOuterProc(o, n.sons[namePos])
   of nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef, nkTemplateDef, 
-     nkIteratorDef, nkLambdaKinds: 
+     nkIteratorDef: 
     # don't recurse here:
     nil
   else:
diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim
index f9420d410..af023e329 100755
--- a/compiler/semtypes.nim
+++ b/compiler/semtypes.nim
@@ -541,7 +541,8 @@ proc paramTypeClass(c: PContext, paramType: PType, procKind: TSymKind):
   else: nil
 
 proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
-                   paramType: PType, paramName: string): PType =
+                   paramType: PType, paramName: string,
+                   info: TLineInfo): PType =
   ## Params having implicit generic types or pseudo types such as 'expr'
   ## need to be added to the generic params lists. 
   ## 'expr' is different from 'expr{string}' so we must first call 
@@ -554,7 +555,10 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
     if genericParams == nil:
       # genericParams is nil when the proc is being instantiated
       # the resolved type will be in scope then
-      result = SymtabGet(c.tab, paramTypId).AssertNotNil.typ
+      let s = SymtabGet(c.tab, paramTypId)
+      # tests/run/tinterf triggers this:
+      if s != nil: result = s.typ
+      else: GlobalError(info, errCannotInstantiateX, paramName)
     else:
       block addImplicitGeneric:
         # is this a bindOnce type class already present in the param list?
@@ -617,7 +621,8 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
     if skipTypes(typ, {tyGenericInst}).kind == tyEmpty: continue
     for j in countup(0, length-3): 
       var arg = newSymS(skParam, a.sons[j], c)
-      var finalType = liftParamType(c, kind, genericParams, typ, arg.name.s)
+      var finalType = liftParamType(c, kind, genericParams, typ, arg.name.s,
+                                    arg.info)
       arg.typ = finalType
       arg.position = counter
       inc(counter)
@@ -634,7 +639,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
     # compiler only checks for 'nil':
     if skipTypes(r, {tyGenericInst}).kind != tyEmpty:
       if r.sym == nil or sfAnon notin r.sym.flags:
-        r = liftParamType(c, kind, genericParams, r, "result")
+        r = liftParamType(c, kind, genericParams, r, "result", n.sons[0].info)
       result.sons[0] = r
       res.typ = result.sons[0]
 
diff --git a/tests/run/tclosure2.nim b/tests/run/tclosure2.nim
index b44c92db7..47cf8fa11 100644
--- a/tests/run/tclosure2.nim
+++ b/tests/run/tclosure2.nim
@@ -19,15 +19,16 @@ py'''
 
 when true:
   proc ax =
-    var i = 0
-    proc bx =
-      if i > 10: return
-      i += 1
-      #for j in 0 .. 0: echo i
+    for xxxx in 0..9:
+      var i = 0
+      proc bx =
+        if i > 10: return
+        i += 1
+        #for j in 0 .. 0: echo i
+        bx()
+      
       bx()
-    
-    bx()
-    echo i
+      echo i
 
   ax()
 
diff --git a/tests/run/tinterf.nim b/tests/run/tinterf.nim
new file mode 100644
index 000000000..b082b1d3f
--- /dev/null
+++ b/tests/run/tinterf.nim
@@ -0,0 +1,20 @@
+discard """
+  output: '''56'''
+"""
+
+type
+  ITest = tuple[
+    setter: proc(v: int) {.closure.},
+    getter: proc(): int {.closure.}]
+
+proc getInterf(): ITest =
+  var shared: int
+  
+  return (setter: proc (x: int) = shared = x,
+          getter: proc (): int = return shared)
+
+var i = getInterf()
+i.setter(56)
+
+echo i.getter()
+