mirror of
https://github.com/nim-lang/Nim.git
synced 2026-02-13 06:43:52 +00:00
tinterf.nim works now
This commit is contained in:
@@ -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:
|
||||
|
||||
@@ -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]
|
||||
|
||||
|
||||
@@ -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
20
tests/run/tinterf.nim
Normal 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()
|
||||
|
||||
Reference in New Issue
Block a user