tinterf.nim works now

This commit is contained in:
Araq
2012-06-17 02:11:13 +02:00
parent 7b539c9e58
commit 7076f07228
4 changed files with 54 additions and 17 deletions

View File

@@ -193,9 +193,13 @@ proc addHiddenParam(routine: PSym, param: PSym) =
var params = routine.ast.sons[paramsPos]
param.position = params.len
addSon(params, newSymNode(param))
#echo "produced environment: ", param.id, " for ", routine.name.s
echo "produced environment: ", param.id, " for ", routine.name.s
proc isInnerProc(s, outerProc: PSym): bool {.inline.} =
if s.name.s[0] == ':':
debug s
debug s.owner
debug outerProc
result = s.kind in {skProc, skIterator, skMethod, skConverter} and
s.owner == outerProc and not isGenericRoutine(s)
#s.typ.callConv == ccClosure
@@ -216,6 +220,7 @@ proc captureVar(o: POuterContext, i: PInnerContext, local: PSym,
"""
# we need to remember which outer closure belongs to this lambda; we also
# use this check to prevent multiple runs over the same inner proc:
echo "enter"
if IdNodeTableGet(o.lambdasToEnclosingScope, i.fn) != nil: return
IdNodeTablePut(o.lambdasToEnclosingScope, i.fn, o.currentBlock)
@@ -244,6 +249,7 @@ proc captureVar(o: POuterContext, i: PInnerContext, local: PSym,
access = indirectAccess(access, local, info)
IdNodeTablePut(i.localsToAccess, local, access)
incl(o.capturedVars, local.id)
echo "exit"
proc interestingVar(s: PSym): bool {.inline.} =
result = s.kind in {skVar, skLet, skTemp, skForVar, skParam, skResult} and
@@ -256,7 +262,6 @@ proc gatherVars(o: POuterContext, i: PInnerContext, n: PNode) =
var s = n.sym
if interestingVar(s) and i.fn.id != s.owner.id:
captureVar(o, i, s, n.info)
#echo "captured: ", s.name.s
of nkEmpty..pred(nkSym), succ(nkSym)..nkNilLit: nil
else:
for k in countup(0, sonsLen(n) - 1):
@@ -281,8 +286,10 @@ proc transformInnerProc(o: POuterContext, i: PInnerContext, n: PNode): PNode =
else:
# captured symbol?
result = IdNodeTableGet(i.localsToAccess, n.sym)
of nkLambdaKinds:
result = transformInnerProc(o, i, n.sons[namePos])
of nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef, nkTemplateDef,
nkIteratorDef, nkLambdaKinds:
nkIteratorDef:
# don't recurse here:
nil
else:
@@ -306,6 +313,8 @@ proc searchForInnerProcs(o: POuterContext, n: PNode) =
gatherVars(o, inner, body)
let ti = transformInnerProc(o, inner, body)
if ti != nil: n.sym.ast.sons[bodyPos] = ti
of nkLambdaKinds:
searchForInnerProcs(o, n.sons[namePos])
of nkWhileStmt, nkForStmt, nkParForStmt, nkBlockStmt:
# some nodes open a new scope, so they are candidates for the insertion
# of closure creation; however for simplicity we merge closures between
@@ -340,7 +349,7 @@ proc searchForInnerProcs(o: POuterContext, n: PNode) =
else:
InternalError(it.info, "transformOuter")
of nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef, nkTemplateDef,
nkIteratorDef, nkLambdaKinds:
nkIteratorDef:
# don't recurse here:
# XXX recurse here and setup 'up' pointers
nil
@@ -421,8 +430,10 @@ proc transformOuterProc(o: POuterContext, n: PNode): PNode =
assert result != nil, "cannot find: " & local.name.s
# else it is captured by copy and this means that 'outer' should continue
# to access the local as a local.
of nkLambdaKinds:
result = transformOuterProc(o, n.sons[namePos])
of nkProcDef, nkMethodDef, nkConverterDef, nkMacroDef, nkTemplateDef,
nkIteratorDef, nkLambdaKinds:
nkIteratorDef:
# don't recurse here:
nil
else:

View File

@@ -541,7 +541,8 @@ proc paramTypeClass(c: PContext, paramType: PType, procKind: TSymKind):
else: nil
proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
paramType: PType, paramName: string): PType =
paramType: PType, paramName: string,
info: TLineInfo): PType =
## Params having implicit generic types or pseudo types such as 'expr'
## need to be added to the generic params lists.
## 'expr' is different from 'expr{string}' so we must first call
@@ -554,7 +555,10 @@ proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode,
if genericParams == nil:
# genericParams is nil when the proc is being instantiated
# the resolved type will be in scope then
result = SymtabGet(c.tab, paramTypId).AssertNotNil.typ
let s = SymtabGet(c.tab, paramTypId)
# tests/run/tinterf triggers this:
if s != nil: result = s.typ
else: GlobalError(info, errCannotInstantiateX, paramName)
else:
block addImplicitGeneric:
# is this a bindOnce type class already present in the param list?
@@ -617,7 +621,8 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
if skipTypes(typ, {tyGenericInst}).kind == tyEmpty: continue
for j in countup(0, length-3):
var arg = newSymS(skParam, a.sons[j], c)
var finalType = liftParamType(c, kind, genericParams, typ, arg.name.s)
var finalType = liftParamType(c, kind, genericParams, typ, arg.name.s,
arg.info)
arg.typ = finalType
arg.position = counter
inc(counter)
@@ -634,7 +639,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
# compiler only checks for 'nil':
if skipTypes(r, {tyGenericInst}).kind != tyEmpty:
if r.sym == nil or sfAnon notin r.sym.flags:
r = liftParamType(c, kind, genericParams, r, "result")
r = liftParamType(c, kind, genericParams, r, "result", n.sons[0].info)
result.sons[0] = r
res.typ = result.sons[0]

View File

@@ -19,15 +19,16 @@ py'''
when true:
proc ax =
var i = 0
proc bx =
if i > 10: return
i += 1
#for j in 0 .. 0: echo i
for xxxx in 0..9:
var i = 0
proc bx =
if i > 10: return
i += 1
#for j in 0 .. 0: echo i
bx()
bx()
bx()
echo i
echo i
ax()

20
tests/run/tinterf.nim Normal file
View File

@@ -0,0 +1,20 @@
discard """
output: '''56'''
"""
type
ITest = tuple[
setter: proc(v: int) {.closure.},
getter: proc(): int {.closure.}]
proc getInterf(): ITest =
var shared: int
return (setter: proc (x: int) = shared = x,
getter: proc (): int = return shared)
var i = getInterf()
i.setter(56)
echo i.getter()