further steps for closure support

This commit is contained in:
Araq
2012-02-06 08:44:18 +01:00
parent fd4836a5d6
commit 161f6f7229
8 changed files with 41 additions and 21 deletions

View File

@@ -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, ", ")

View File

@@ -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")

View File

@@ -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:

View File

@@ -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)

View File

@@ -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:

View File

@@ -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: */

View File

@@ -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

View File

@@ -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