tinterf.nim works now

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

View file

@ -541,7 +541,8 @@ proc paramTypeClass(c: PContext, paramType: PType, procKind: TSymKind):
else: nil else: nil
proc liftParamType(c: PContext, procKind: TSymKind, genericParams: PNode, 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' ## Params having implicit generic types or pseudo types such as 'expr'
## need to be added to the generic params lists. ## need to be added to the generic params lists.
## 'expr' is different from 'expr{string}' so we must first call ## '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: if genericParams == nil:
# genericParams is nil when the proc is being instantiated # genericParams is nil when the proc is being instantiated
# the resolved type will be in scope then # 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: else:
block addImplicitGeneric: block addImplicitGeneric:
# is this a bindOnce type class already present in the param list? # 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 if skipTypes(typ, {tyGenericInst}).kind == tyEmpty: continue
for j in countup(0, length-3): for j in countup(0, length-3):
var arg = newSymS(skParam, a.sons[j], c) 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.typ = finalType
arg.position = counter arg.position = counter
inc(counter) inc(counter)
@ -634,7 +639,7 @@ proc semProcTypeNode(c: PContext, n, genericParams: PNode,
# compiler only checks for 'nil': # compiler only checks for 'nil':
if skipTypes(r, {tyGenericInst}).kind != tyEmpty: if skipTypes(r, {tyGenericInst}).kind != tyEmpty:
if r.sym == nil or sfAnon notin r.sym.flags: 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 result.sons[0] = r
res.typ = result.sons[0] res.typ = result.sons[0]

View file

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