diff options
author | Araq <rumpf_a@web.de> | 2012-02-06 08:44:18 +0100 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2012-02-06 08:44:18 +0100 |
commit | 161f6f7229e6003c8ee512150793b2f9b5a2f6f3 (patch) | |
tree | dfba73f1e3830dfabbc58283714b1c18f15e4e9d | |
parent | fd4836a5d6e4e2c7b37adc6efdea325b76b9d59f (diff) | |
download | Nim-161f6f7229e6003c8ee512150793b2f9b5a2f6f3.tar.gz |
further steps for closure support
-rw-r--r-- | compiler/ccgcalls.nim | 6 | ||||
-rwxr-xr-x | compiler/ccgexprs.nim | 11 | ||||
-rwxr-xr-x | compiler/ccgtypes.nim | 26 | ||||
-rw-r--r-- | compiler/lambdalifting.nim | 3 | ||||
-rwxr-xr-x | compiler/transf.nim | 3 | ||||
-rwxr-xr-x | lib/nimbase.h | 8 | ||||
-rwxr-xr-x | todo.txt | 3 | ||||
-rwxr-xr-x | web/index.txt | 2 |
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 |