summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorAraq <rumpf_a@web.de>2012-02-06 08:44:18 +0100
committerAraq <rumpf_a@web.de>2012-02-06 08:44:18 +0100
commit161f6f7229e6003c8ee512150793b2f9b5a2f6f3 (patch)
treedfba73f1e3830dfabbc58283714b1c18f15e4e9d
parentfd4836a5d6e4e2c7b37adc6efdea325b76b9d59f (diff)
downloadNim-161f6f7229e6003c8ee512150793b2f9b5a2f6f3.tar.gz
further steps for closure support
-rw-r--r--compiler/ccgcalls.nim6
-rwxr-xr-xcompiler/ccgexprs.nim11
-rwxr-xr-xcompiler/ccgtypes.nim26
-rw-r--r--compiler/lambdalifting.nim3
-rwxr-xr-xcompiler/transf.nim3
-rwxr-xr-xlib/nimbase.h8
-rwxr-xr-xtodo.txt3
-rwxr-xr-xweb/index.txt2
8 files changed, 41 insertions, 21 deletions
diff --git a/compiler/ccgcalls.nim b/compiler/ccgcalls.nim
index d6e2d67b7..fef1b055d 100644
--- a/compiler/ccgcalls.nim
+++ b/compiler/ccgcalls.nim
@@ -139,10 +139,8 @@ proc genPrefixCall(p: BProc, le, ri: PNode, d: var TLoc) =
 
 proc genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
 
-  proc getRawProcType(p: BProc, t: PType): PRope = 
-    var d = copyType(t, t.owner, false)
-    d.callConv = ccDefault
-    result = getTypeDesc(p.module, d)
+  proc getRawProcType(p: BProc, t: PType): PRope =
+    result = getClosureType(p.module, t, clHalf)
 
   proc addComma(r: PRope): PRope =
     result = if r == nil: r else: con(r, ", ")
diff --git a/compiler/ccgexprs.nim b/compiler/ccgexprs.nim
index 6a8156220..0d7f6cce4 100755
--- a/compiler/ccgexprs.nim
+++ b/compiler/ccgexprs.nim
@@ -1273,10 +1273,13 @@ proc genCast(p: BProc, e: PNode, d: var TLoc) =
   # through its address:
   var a: TLoc
   InitLocExpr(p, e.sons[1], a)
-  if (skipTypes(e.typ, abstractRange).kind in ValueTypes) and
-      not (lfIndirect in a.flags):
+  let etyp = skipTypes(e.typ, abstractRange)
+  if etyp.kind in ValueTypes and lfIndirect notin a.flags:
     putIntoDest(p, d, e.typ, ropef("(*($1*) ($2))",
         [getTypeDesc(p.module, e.typ), addrLoc(a)]))
+  elif etyp.kind == tyProc and etyp.callConv == ccClosure:
+    putIntoDest(p, d, e.typ, ropef("(($1) ($2))",
+        [getClosureType(p.module, etyp, clHalfWithEnv), rdCharLoc(a)]))
   else:
     putIntoDest(p, d, e.typ, ropef("(($1) ($2))",
         [getTypeDesc(p.module, e.typ), rdCharLoc(a)]))
@@ -1660,11 +1663,11 @@ proc expr(p: BProc, e: PNode, d: var TLoc) =
       else:
         putLocIntoDest(p, d, sym.loc)
     of skForVar, skTemp:
-      if ((sym.loc.r == nil) or (sym.loc.t == nil)):
+      if sym.loc.r == nil or sym.loc.t == nil:
         InternalError(e.info, "expr: temp not init " & sym.name.s)
       putLocIntoDest(p, d, sym.loc)
     of skParam:
-      if ((sym.loc.r == nil) or (sym.loc.t == nil)):
+      if sym.loc.r == nil or sym.loc.t == nil:
         InternalError(e.info, "expr: param not init " & sym.name.s)
       putLocIntoDest(p, d, sym.loc)
     else: InternalError(e.info, "expr(" & $sym.kind & "); unknown symbol")
diff --git a/compiler/ccgtypes.nim b/compiler/ccgtypes.nim
index c7002954a..06b5a58db 100755
--- a/compiler/ccgtypes.nim
+++ b/compiler/ccgtypes.nim
@@ -179,7 +179,7 @@ proc getParamTypeDesc(m: BModule, t: PType, check: var TIntSet): PRope =
   result = getTypeDescAux(m, t, check)
 
 proc genProcParams(m: BModule, t: PType, rettype, params: var PRope, 
-                   check: var TIntSet) = 
+                   check: var TIntSet, declareEnvironment=true) = 
   params = nil
   if (t.sons[0] == nil) or isInvalidReturnType(t.sons[0]): 
     rettype = toRope("void")
@@ -213,7 +213,7 @@ proc genProcParams(m: BModule, t: PType, rettype, params: var PRope,
     if (mapReturnType(t.sons[0]) != ctArray) or (gCmd == cmdCompileToLLVM): 
       app(params, "*")
     appff(params, " Result", " @Result", [])
-  if t.callConv == ccClosure: 
+  if t.callConv == ccClosure and declareEnvironment: 
     if params != nil: app(params, ", ")
     app(params, "void* ClEnv")
   if tfVarargs in t.flags: 
@@ -438,7 +438,7 @@ proc getTypeDescAux(m: BModule, typ: PType, check: var TIntSet): PRope =
              [toRope(CallingConvToStr[t.callConv]), rettype, result, desc])
       else:
         appf(m.s[cfsTypes], "typedef struct {$n" &
-            "N_CDECL_PTR($2, ClPrc) $3;$n" & 
+            "N_NIMCALL_PTR($2, ClPrc) $3;$n" & 
             "void* ClEnv;$n} $1;$n",
              [result, rettype, desc])
   of tySequence: 
@@ -504,6 +504,26 @@ proc getTypeDesc(m: BModule, typ: PType): PRope =
   var check = initIntSet()
   result = getTypeDescAux(m, typ, check)
 
+type
+  TClosureTypeKind = enum
+    clHalf, clHalfWithEnv, clFull
+
+proc getClosureType(m: BModule, t: PType, kind: TClosureTypeKind): PRope =
+  assert t.kind == tyProc
+  var check = initIntSet()
+  result = getTempName()
+  var rettype, desc: PRope
+  genProcParams(m, t, rettype, desc, check, declareEnvironment=kind != clHalf)
+  if not isImportedType(t):
+    if t.callConv != ccClosure or kind != clFull:
+      appf(m.s[cfsTypes], "typedef $1_PTR($2, $3) $4;$n", 
+           [toRope(CallingConvToStr[t.callConv]), rettype, result, desc])
+    else:
+      appf(m.s[cfsTypes], "typedef struct {$n" &
+          "N_NIMCALL_PTR($2, ClPrc) $3;$n" & 
+          "void* ClEnv;$n} $1;$n",
+           [result, rettype, desc])
+
 proc getTypeDesc(m: BModule, magic: string): PRope = 
   var sym = magicsys.getCompilerProc(magic)
   if sym != nil: 
diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim
index 4a2a8997c..70db9334e 100644
--- a/compiler/lambdalifting.nim
+++ b/compiler/lambdalifting.nim
@@ -221,7 +221,8 @@ proc generateThunk(c: PTransf, prc: PNode, dest: PType): PNode =
   ## Converts 'prc' into '(thunk, nil)' so that it's compatible with
   ## a closure.
   
-  # XXX we hack around here by generating a 'cast' instead of a proper thunk.
+  # we cannot generate a proper thunk here for GC-safety reasons (see internal
+  # documentation):
   result = newNodeIT(nkClosure, prc.info, dest)
   var conv = newNodeIT(nkHiddenStdConv, prc.info, dest)
   conv.add(emptyNode)
diff --git a/compiler/transf.nim b/compiler/transf.nim
index be8f7aeb5..b5e875c53 100755
--- a/compiler/transf.nim
+++ b/compiler/transf.nim
@@ -433,7 +433,8 @@ proc transformConv(c: PTransf, n: PNode): PTransNode =
       result = transform(c, n.sons[1])
   of tyProc:
     if dest.callConv == ccClosure and source.callConv == ccDefault:
-      result = generateThunk(c, n.sons[1], dest).ptransnode
+      let x = transform(c, n.sons[1]).pnode
+      result = generateThunk(c, x, dest).ptransnode
     else:
       result = transformSons(c, n)    
   of tyGenericParam, tyOrdinal: 
diff --git a/lib/nimbase.h b/lib/nimbase.h
index f52185800..a114430ab 100755
--- a/lib/nimbase.h
+++ b/lib/nimbase.h
@@ -132,11 +132,6 @@ __clang__
 /* specify no calling convention */
 #define N_NOCONV_PTR(rettype, name) rettype (*name)
 
-#define N_CLOSURE(rettype, name) rettype name
-/* specify no calling convention */
-#define N_CLOSURE_PTR(rettype, name) rettype (*name)
-
-
 #if defined(__GNUC__) || defined(__ICC__)
 #  define N_NOINLINE(rettype, name) rettype __attribute__((noinline)) name
 #elif defined(_MSC_VER)
@@ -157,6 +152,9 @@ __clang__
 #  define N_NIMCALL_PTR(rettype, name) rettype (*name)
 #endif
 
+#define N_CLOSURE(rettype, name) N_NIMCALL(rettype, name)
+#define N_CLOSURE_PTR(rettype, name) N_NIMCALL_PTR(rettype, name)
+
 /* ----------------------------------------------------------------------- */
 
 /* from float_cast.h: */
diff --git a/todo.txt b/todo.txt
index b43357007..7a5ec6054 100755
--- a/todo.txt
+++ b/todo.txt
@@ -4,8 +4,7 @@ version 0.8.14
 - implement closures
   - test evals.nim with closures
   - deactivate lambda lifting for JS backend
-  - Test that iterators within closures work etc; test generics; 
-    test recursion
+  - Test capture of for loop vars; test generics; test recursion
   - test constant closures
   - 'closureEnv' magic for easy interfacing with C
   
diff --git a/web/index.txt b/web/index.txt
index 4ef128ad8..fb208b98f 100755
--- a/web/index.txt
+++ b/web/index.txt
@@ -107,9 +107,9 @@ Roadmap to 1.0
 
 Version 0.9.0
   * closures
-  * recursive iterators/coroutines
 
 Version 0.9.x
+  * recursive iterators/coroutines
   * 2-phase type system for better interaction between macros, templates
     and overloading
   * term rewriting macros