diff options
author | Araq <rumpf_a@web.de> | 2012-06-17 02:11:13 +0200 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2012-06-17 02:11:13 +0200 |
commit | 7076f07228f65b05312b609f89dbac767b69394f (patch) | |
tree | 9c43de800eea5fa093ea964a6e4ba9a6085f94fa | |
parent | 7b539c9e582e441cdb7e078cdbe247d06a74ad0e (diff) | |
download | Nim-7076f07228f65b05312b609f89dbac767b69394f.tar.gz |
tinterf.nim works now
-rw-r--r-- | compiler/lambdalifting.nim | 21 | ||||
-rwxr-xr-x | compiler/semtypes.nim | 13 | ||||
-rw-r--r-- | tests/run/tclosure2.nim | 17 | ||||
-rw-r--r-- | tests/run/tinterf.nim | 20 |
4 files changed, 54 insertions, 17 deletions
diff --git a/compiler/lambdalifting.nim b/compiler/lambdalifting.nim index 96cf6aef0..8dd54131f 100644 --- a/compiler/lambdalifting.nim +++ b/compiler/lambdalifting.nim @@ -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: diff --git a/compiler/semtypes.nim b/compiler/semtypes.nim index f9420d410..af023e329 100755 --- a/compiler/semtypes.nim +++ b/compiler/semtypes.nim @@ -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] diff --git a/tests/run/tclosure2.nim b/tests/run/tclosure2.nim index b44c92db7..47cf8fa11 100644 --- a/tests/run/tclosure2.nim +++ b/tests/run/tclosure2.nim @@ -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() diff --git a/tests/run/tinterf.nim b/tests/run/tinterf.nim new file mode 100644 index 000000000..b082b1d3f --- /dev/null +++ b/tests/run/tinterf.nim @@ -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() + |