further steps for closure support
This commit is contained in:
parent
fd4836a5d6
commit
161f6f7229
8 changed files with 41 additions and 21 deletions
|
|
@ -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 genClosureCall(p: BProc, le, ri: PNode, d: var TLoc) =
|
||||||
|
|
||||||
proc getRawProcType(p: BProc, t: PType): PRope =
|
proc getRawProcType(p: BProc, t: PType): PRope =
|
||||||
var d = copyType(t, t.owner, false)
|
result = getClosureType(p.module, t, clHalf)
|
||||||
d.callConv = ccDefault
|
|
||||||
result = getTypeDesc(p.module, d)
|
|
||||||
|
|
||||||
proc addComma(r: PRope): PRope =
|
proc addComma(r: PRope): PRope =
|
||||||
result = if r == nil: r else: con(r, ", ")
|
result = if r == nil: r else: con(r, ", ")
|
||||||
|
|
|
||||||
|
|
@ -1273,10 +1273,13 @@ proc genCast(p: BProc, e: PNode, d: var TLoc) =
|
||||||
# through its address:
|
# through its address:
|
||||||
var a: TLoc
|
var a: TLoc
|
||||||
InitLocExpr(p, e.sons[1], a)
|
InitLocExpr(p, e.sons[1], a)
|
||||||
if (skipTypes(e.typ, abstractRange).kind in ValueTypes) and
|
let etyp = skipTypes(e.typ, abstractRange)
|
||||||
not (lfIndirect in a.flags):
|
if etyp.kind in ValueTypes and lfIndirect notin a.flags:
|
||||||
putIntoDest(p, d, e.typ, ropef("(*($1*) ($2))",
|
putIntoDest(p, d, e.typ, ropef("(*($1*) ($2))",
|
||||||
[getTypeDesc(p.module, e.typ), addrLoc(a)]))
|
[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:
|
else:
|
||||||
putIntoDest(p, d, e.typ, ropef("(($1) ($2))",
|
putIntoDest(p, d, e.typ, ropef("(($1) ($2))",
|
||||||
[getTypeDesc(p.module, e.typ), rdCharLoc(a)]))
|
[getTypeDesc(p.module, e.typ), rdCharLoc(a)]))
|
||||||
|
|
@ -1660,11 +1663,11 @@ proc expr(p: BProc, e: PNode, d: var TLoc) =
|
||||||
else:
|
else:
|
||||||
putLocIntoDest(p, d, sym.loc)
|
putLocIntoDest(p, d, sym.loc)
|
||||||
of skForVar, skTemp:
|
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)
|
InternalError(e.info, "expr: temp not init " & sym.name.s)
|
||||||
putLocIntoDest(p, d, sym.loc)
|
putLocIntoDest(p, d, sym.loc)
|
||||||
of skParam:
|
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)
|
InternalError(e.info, "expr: param not init " & sym.name.s)
|
||||||
putLocIntoDest(p, d, sym.loc)
|
putLocIntoDest(p, d, sym.loc)
|
||||||
else: InternalError(e.info, "expr(" & $sym.kind & "); unknown symbol")
|
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)
|
result = getTypeDescAux(m, t, check)
|
||||||
|
|
||||||
proc genProcParams(m: BModule, t: PType, rettype, params: var PRope,
|
proc genProcParams(m: BModule, t: PType, rettype, params: var PRope,
|
||||||
check: var TIntSet) =
|
check: var TIntSet, declareEnvironment=true) =
|
||||||
params = nil
|
params = nil
|
||||||
if (t.sons[0] == nil) or isInvalidReturnType(t.sons[0]):
|
if (t.sons[0] == nil) or isInvalidReturnType(t.sons[0]):
|
||||||
rettype = toRope("void")
|
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):
|
if (mapReturnType(t.sons[0]) != ctArray) or (gCmd == cmdCompileToLLVM):
|
||||||
app(params, "*")
|
app(params, "*")
|
||||||
appff(params, " Result", " @Result", [])
|
appff(params, " Result", " @Result", [])
|
||||||
if t.callConv == ccClosure:
|
if t.callConv == ccClosure and declareEnvironment:
|
||||||
if params != nil: app(params, ", ")
|
if params != nil: app(params, ", ")
|
||||||
app(params, "void* ClEnv")
|
app(params, "void* ClEnv")
|
||||||
if tfVarargs in t.flags:
|
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])
|
[toRope(CallingConvToStr[t.callConv]), rettype, result, desc])
|
||||||
else:
|
else:
|
||||||
appf(m.s[cfsTypes], "typedef struct {$n" &
|
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",
|
"void* ClEnv;$n} $1;$n",
|
||||||
[result, rettype, desc])
|
[result, rettype, desc])
|
||||||
of tySequence:
|
of tySequence:
|
||||||
|
|
@ -504,6 +504,26 @@ proc getTypeDesc(m: BModule, typ: PType): PRope =
|
||||||
var check = initIntSet()
|
var check = initIntSet()
|
||||||
result = getTypeDescAux(m, typ, check)
|
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 =
|
proc getTypeDesc(m: BModule, magic: string): PRope =
|
||||||
var sym = magicsys.getCompilerProc(magic)
|
var sym = magicsys.getCompilerProc(magic)
|
||||||
if sym != nil:
|
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
|
## Converts 'prc' into '(thunk, nil)' so that it's compatible with
|
||||||
## a closure.
|
## 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)
|
result = newNodeIT(nkClosure, prc.info, dest)
|
||||||
var conv = newNodeIT(nkHiddenStdConv, prc.info, dest)
|
var conv = newNodeIT(nkHiddenStdConv, prc.info, dest)
|
||||||
conv.add(emptyNode)
|
conv.add(emptyNode)
|
||||||
|
|
|
||||||
|
|
@ -433,7 +433,8 @@ proc transformConv(c: PTransf, n: PNode): PTransNode =
|
||||||
result = transform(c, n.sons[1])
|
result = transform(c, n.sons[1])
|
||||||
of tyProc:
|
of tyProc:
|
||||||
if dest.callConv == ccClosure and source.callConv == ccDefault:
|
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:
|
else:
|
||||||
result = transformSons(c, n)
|
result = transformSons(c, n)
|
||||||
of tyGenericParam, tyOrdinal:
|
of tyGenericParam, tyOrdinal:
|
||||||
|
|
|
||||||
|
|
@ -132,11 +132,6 @@ __clang__
|
||||||
/* specify no calling convention */
|
/* specify no calling convention */
|
||||||
#define N_NOCONV_PTR(rettype, name) rettype (*name)
|
#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__)
|
#if defined(__GNUC__) || defined(__ICC__)
|
||||||
# define N_NOINLINE(rettype, name) rettype __attribute__((noinline)) name
|
# define N_NOINLINE(rettype, name) rettype __attribute__((noinline)) name
|
||||||
#elif defined(_MSC_VER)
|
#elif defined(_MSC_VER)
|
||||||
|
|
@ -157,6 +152,9 @@ __clang__
|
||||||
# define N_NIMCALL_PTR(rettype, name) rettype (*name)
|
# define N_NIMCALL_PTR(rettype, name) rettype (*name)
|
||||||
#endif
|
#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: */
|
/* from float_cast.h: */
|
||||||
|
|
|
||||||
3
todo.txt
3
todo.txt
|
|
@ -4,8 +4,7 @@ version 0.8.14
|
||||||
- implement closures
|
- implement closures
|
||||||
- test evals.nim with closures
|
- test evals.nim with closures
|
||||||
- deactivate lambda lifting for JS backend
|
- deactivate lambda lifting for JS backend
|
||||||
- Test that iterators within closures work etc; test generics;
|
- Test capture of for loop vars; test generics; test recursion
|
||||||
test recursion
|
|
||||||
- test constant closures
|
- test constant closures
|
||||||
- 'closureEnv' magic for easy interfacing with C
|
- 'closureEnv' magic for easy interfacing with C
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -107,9 +107,9 @@ Roadmap to 1.0
|
||||||
|
|
||||||
Version 0.9.0
|
Version 0.9.0
|
||||||
* closures
|
* closures
|
||||||
* recursive iterators/coroutines
|
|
||||||
|
|
||||||
Version 0.9.x
|
Version 0.9.x
|
||||||
|
* recursive iterators/coroutines
|
||||||
* 2-phase type system for better interaction between macros, templates
|
* 2-phase type system for better interaction between macros, templates
|
||||||
and overloading
|
and overloading
|
||||||
* term rewriting macros
|
* term rewriting macros
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue