mirror of
https://github.com/nim-lang/Nim.git
synced 2026-06-03 02:18:00 +00:00
further steps for closure support
This commit is contained in:
@@ -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, ", ")
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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: */
|
||||
|
||||
3
todo.txt
3
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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user