From e5bd3b5b97e473efa90b08a9042a58bc6c9595a0 Mon Sep 17 00:00:00 2001 From: Zahary Karadjov Date: Thu, 15 Dec 2011 18:39:44 +0200 Subject: [PATCH 1/7] bootstraps fine with overloadable templates --- compiler/ast.nim | 24 ++++++++- compiler/ccgcalls.nim | 3 +- compiler/pragmas.nim | 8 ++- compiler/sem.nim | 29 +++++----- compiler/semcall.nim | 120 ++++++++++++++++++++++-------------------- compiler/semdata.nim | 2 +- compiler/semexprs.nim | 104 +++++++++++++++++++++++++----------- compiler/semtempl.nim | 4 +- compiler/semtypes.nim | 1 + compiler/sigmatch.nim | 54 ++++++++++--------- compiler/suggest.nim | 16 +++--- compiler/wordrecg.nim | 4 +- lib/system/excpt.nim | 2 +- lib/system/gc.nim | 2 +- 14 files changed, 230 insertions(+), 143 deletions(-) diff --git a/compiler/ast.nim b/compiler/ast.nim index cfcdb6ea69..2c8ca52d70 100755 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -225,6 +225,9 @@ type sfInnerProc, # proc is an inner proc sfThread, # proc will run as a thread # variable is a thread variable + sfInline # forced-inline procs + sfImmediate, # macro or template is immediately expanded without + # considering any possible overloads sfCompileTime, # proc can be evaluated at compile time sfMerge, # proc can be merged with itself sfDeadCodeElim, # dead code elimination for the module is turned on @@ -570,7 +573,8 @@ type # the poor naming choices in the standard library. const - OverloadableSyms* = {skProc, skMethod, skIterator, skConverter, skModule} + OverloadableSyms* = {skProc, skMethod, skIterator, skConverter, + skModule, skTemplate, skMacro} GenericTypes*: TTypeKinds = {tyGenericInvokation, tyGenericBody, tyGenericParam} @@ -918,6 +922,12 @@ proc delSon(father: PNode, idx: int) = for i in countup(idx, length - 2): father.sons[i] = father.sons[i + 1] setlen(father.sons, length - 1) +proc hasSons*(n: PNode): bool {.inline.} = + result = n.kind notin { nkCharLit..nkInt64Lit, + nkFloatLit..nkFloat64Lit, + nkStrLit..nkTripleStrLit, + nkSym, nkIdent } + proc copyNode(src: PNode): PNode = # does not copy its sons! if src == nil: @@ -949,6 +959,18 @@ proc shallowCopy*(src: PNode): PNode = of nkStrLit..nkTripleStrLit: result.strVal = src.strVal else: newSeq(result.sons, sonsLen(src)) +proc copySons*(src: PNode): Pnode = + # copies a node and its immediate sons + if src == nil: return nil + assert src.hasSons + result = newNode(src.kind) + result.info = src.info + result.typ = src.typ + result.flags = src.flags * PersistentNodeFlags + newSeq(result.sons, src.len) + for i in countup(0, src.len - 1): + result.sons[i] = src.sons[i] + proc copyTree(src: PNode): PNode = # copy a whole syntax tree; performs deep copying if src == nil: diff --git a/compiler/ccgcalls.nim b/compiler/ccgcalls.nim index fef1b055d9..072b2f9fb3 100644 --- a/compiler/ccgcalls.nim +++ b/compiler/ccgcalls.nim @@ -10,7 +10,8 @@ proc leftAppearsOnRightSide(le, ri: PNode): bool = if le != nil: for i in 1 .. Date: Wed, 14 Mar 2012 15:40:43 +0200 Subject: [PATCH 2/7] allowing multiple definitions of templates --- compiler/semstmts.nim | 3 +-- compiler/semtempl.nim | 22 ++++++++++++---------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/compiler/semstmts.nim b/compiler/semstmts.nim index bd69805b38..2724a0756e 100755 --- a/compiler/semstmts.nim +++ b/compiler/semstmts.nim @@ -8,6 +8,7 @@ # ## this module does the semantic checking of statements +# included from sem.nim proc semCommand(c: PContext, n: PNode): PNode = result = semExprNoType(c, n) @@ -690,8 +691,6 @@ proc semProcAux(c: PContext, n: PNode, kind: TSymKind, n.sons[genericParamsPos] = gp # check for semantics again: semParamList(c, n.sons[ParamsPos], nil, s) - # XXX: obsoleted - happens in semParamList - # addParams(c, s.typ.n) else: s.typ = newTypeS(tyProc, c) addSon(s.typ, nil) diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim index 804709f7ae..e61bee70e0 100755 --- a/compiler/semtempl.nim +++ b/compiler/semtempl.nim @@ -54,11 +54,6 @@ proc evalTemplateArgs(c: PContext, n: PNode, s: PSym): PNode = else: arg = copyTree(s.typ.n.sons[i].sym.ast) if arg == nil or arg.kind == nkEmpty: LocalError(n.info, errWrongNumberOfArguments) - elif not (s.typ.sons[i].kind in {tyTypeDesc, tyStmt, tyExpr}): - # concrete type means semantic checking for argument: - # XXX This is horrible! Better make semantic checking use some kind - # of fixpoint iteration ... - arg = fitNode(c, s.typ.sons[i], semExprWithType(c, arg)) addSon(result, arg) proc evalTemplate*(c: PContext, n: PNode, sym: PSym): PNode = @@ -167,7 +162,7 @@ proc semTemplateDef(c: PContext, n: PNode): PNode = # check parameter list: pushOwner(s) openScope(c.tab) - n.sons[namePos] = newSymNode(s) # check that no pragmas exist: + n.sons[namePos] = newSymNode(s) if n.sons[pragmasPos].kind != nkEmpty: pragma(c, s, n.sons[pragmasPos], templatePragmas) # check that no generic parameters exist: @@ -185,8 +180,6 @@ proc semTemplateDef(c: PContext, n: PNode): PNode = # use ``stmt`` as implicit result type s.typ.sons[0] = newTypeS(tyStmt, c) s.typ.n.sons[0] = newNodeIT(nkType, n.info, s.typ.sons[0]) - # XXX: obsoleted - happens in semParamList # - # addParams(c, s.typ.n) # resolve parameters: var toBind = initIntSet() n.sons[bodyPos] = resolveTemplateParams(c, n.sons[bodyPos], false, toBind) if s.typ.sons[0].kind notin {tyStmt, tyTypeDesc}: @@ -198,5 +191,14 @@ proc semTemplateDef(c: PContext, n: PNode): PNode = result = n if n.sons[bodyPos].kind == nkEmpty: LocalError(n.info, errImplOfXexpected, s.name.s) - # add identifier of template as a last step to not allow recursive templates: - addInterfaceDecl(c, s) + var proto = SearchForProc(c, s, c.tab.tos-2) # -2 because we have a scope + # open for parameters + if proto == nil: + # add identifier of template as a last step to not allow recursive templates: + addInterfaceOverloadableSymAt(c, s, c.tab.tos - 2) + else: + # overwrite template + proto.info = s.info + proto.ast = s.ast + proto.typ = s.typ + proto.flags = s.flags From d1d5fc8254eb376de64106314686f2e8e7db459c Mon Sep 17 00:00:00 2001 From: Zahary Karadjov Date: Wed, 14 Mar 2012 20:57:13 +0200 Subject: [PATCH 3/7] allowing definitions of procs and templates to be overridden in local scopes --- compiler/lookups.nim | 11 +++++++++-- compiler/semcall.nim | 9 +++++---- compiler/sigmatch.nim | 7 ++++++- 3 files changed, 20 insertions(+), 7 deletions(-) diff --git a/compiler/lookups.nim b/compiler/lookups.nim index ff078c82d2..ee77b3633a 100755 --- a/compiler/lookups.nim +++ b/compiler/lookups.nim @@ -164,7 +164,7 @@ proc QualifiedLookUp*(c: PContext, n: PNode, flags = {checkUndeclared}): PSym = result = nil if result != nil and result.kind == skStub: loadStub(result) -proc InitOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym = +proc InitOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym = case n.kind of nkIdent, nkAccQuoted: var ident = considerAcc(n) @@ -174,7 +174,7 @@ proc InitOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym = dec(o.stackPtr) if o.stackPtr < 0: break result = InitIdentIter(o.it, c.tab.stack[o.stackPtr], ident) - of nkSym: + of nkSym: result = n.sym o.mode = oimDone of nkDotExpr: @@ -204,6 +204,13 @@ proc InitOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym = Incl(o.inSymChoice, result.id) else: nil if result != nil and result.kind == skStub: loadStub(result) + +proc lastOverloadScope*(o: TOverloadIter): int = + case o.mode + of oimNoQualifier: result = o.stackPtr + of oimSelfModule: result = ModuleTablePos + of oimOtherModule: result = ImportTablePos + else: result = -1 proc nextOverloadIter*(o: var TOverloadIter, c: PContext, n: PNode): PSym = case o.mode diff --git a/compiler/semcall.nim b/compiler/semcall.nim index 6a36787cba..f0c9f42b05 100755 --- a/compiler/semcall.nim +++ b/compiler/semcall.nim @@ -36,14 +36,15 @@ proc resolveOverloads(c: PContext, n, orig: PNode, template best: expr = result #Message(n.info, warnUser, renderTree(n)) var sym = initOverloadIter(o, c, f) + var symScope = o.lastOverloadScope - if sym == nil: return - initCandidate(best, sym, initialBinding) - initCandidate(alt, sym, initialBinding) + if sym == nil: return + initCandidate(best, sym, initialBinding, symScope) + initCandidate(alt, sym, initialBinding, symScope) while sym != nil: if sym.kind in filter: - initCandidate(z, sym, initialBinding) + initCandidate(z, sym, initialBinding, o.lastOverloadScope) z.calleeSym = sym matches(c, n, orig, z) if z.state == csMatch: diff --git a/compiler/sigmatch.nim b/compiler/sigmatch.nim index e56b5e1c86..ca65c670f6 100755 --- a/compiler/sigmatch.nim +++ b/compiler/sigmatch.nim @@ -27,6 +27,7 @@ type state*: TCandidateState callee*: PType # may not be nil! calleeSym*: PSym # may be nil + calleeScope: int # may be -1 for unknown scope call*: PNode # modified call bindings*: TIdTable # maps types to types baseTypeMatch: bool # needed for conversions from T to openarray[T] @@ -60,9 +61,10 @@ proc put(t: var TIdTable, key, val: PType) {.inline.} = IdentEq(val.sym.name, "TTable"): assert false -proc initCandidate*(c: var TCandidate, callee: PSym, binding: PNode) = +proc initCandidate*(c: var TCandidate, callee: PSym, binding: PNode, calleeScope = -1) = initCandidateAux(c, callee.typ) c.calleeSym = callee + c.calleeScope = calleeScope initIdTable(c.bindings) if binding != nil: var typeParams = callee.ast[genericParamsPos] @@ -94,6 +96,9 @@ proc cmpCandidates*(a, b: TCandidate): int = result = a.intConvMatches - b.intConvMatches if result != 0: return result = a.convMatches - b.convMatches + if result != 0: return + if (a.calleeScope != -1) and (b.calleeScope != -1): + result = a.calleeScope - b.calleeScope proc writeMatches(c: TCandidate) = Writeln(stdout, "exact matches: " & $c.exactMatches) From 6975ba401b365a286336dd3dd66112395206c53e Mon Sep 17 00:00:00 2001 From: Zahary Karadjov Date: Thu, 15 Mar 2012 14:15:37 +0200 Subject: [PATCH 4/7] fix for template redefinition. test cases added. --- compiler/astalgo.nim | 13 +++++++++++++ compiler/semexprs.nim | 1 - compiler/semtempl.nim | 12 ++++-------- tests/compile/tredef.nim | 29 +++++++++++++++++++++++++++++ tests/reject/tprocredef.nim | 9 +++++++++ tests/run/toverl2.nim | 16 +++++++++++----- tests/run/tunittests.nim | 2 +- tests/run/utemplates.nim | 32 ++++++++++++++++++++++++++++++++ 8 files changed, 99 insertions(+), 15 deletions(-) create mode 100644 tests/compile/tredef.nim create mode 100644 tests/reject/tprocredef.nim create mode 100644 tests/run/utemplates.nim diff --git a/compiler/astalgo.nim b/compiler/astalgo.nim index 7128102a80..9da0d3a20b 100755 --- a/compiler/astalgo.nim +++ b/compiler/astalgo.nim @@ -567,6 +567,19 @@ proc StrTableRawInsert(data: var TSymSeq, n: PSym) = assert(data[h] == nil) data[h] = n +proc SymTabReplaceRaw(data: var TSymSeq, prevSym: PSym, newSym: PSym) = + assert prevSym.name.h == newSym.name.h + var h: THash = prevSym.name.h and high(data) + while data[h] != nil: + if data[h] == prevSym: + data[h] = newSym + return + h = nextTry(h, high(data)) + assert false + +proc SymTabReplace*(t: var TStrTable, prevSym: PSym, newSym: PSym) = + SymTabReplaceRaw(t.data, prevSym, newSym) + proc StrTableEnlarge(t: var TStrTable) = var n: TSymSeq newSeq(n, len(t.data) * growthFactor) diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index b96ebec40a..704f182c84 100755 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -1269,7 +1269,6 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = if s != nil: case s.kind of skMacro: - echo c.filename if c.filename.endsWith("hello.nim") and sfImmediate notin s.flags: result = semDirectOp(c, n, flags) else: diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim index e61bee70e0..b1f70803e7 100755 --- a/compiler/semtempl.nim +++ b/compiler/semtempl.nim @@ -191,14 +191,10 @@ proc semTemplateDef(c: PContext, n: PNode): PNode = result = n if n.sons[bodyPos].kind == nkEmpty: LocalError(n.info, errImplOfXexpected, s.name.s) - var proto = SearchForProc(c, s, c.tab.tos-2) # -2 because we have a scope - # open for parameters + let curScope = c.tab.tos - 2 # -2 because we have a scope open for parameters + var proto = SearchForProc(c, s, curScope) if proto == nil: - # add identifier of template as a last step to not allow recursive templates: addInterfaceOverloadableSymAt(c, s, c.tab.tos - 2) else: - # overwrite template - proto.info = s.info - proto.ast = s.ast - proto.typ = s.typ - proto.flags = s.flags + SymTabReplace(c.tab.stack[curScope], proto, s) + diff --git a/tests/compile/tredef.nim b/tests/compile/tredef.nim new file mode 100644 index 0000000000..02d1f77765 --- /dev/null +++ b/tests/compile/tredef.nim @@ -0,0 +1,29 @@ +template foo(a: int, b: string) = nil +foo(1, "test") + +proc bar(a: int, b: string) = nil +bar(1, "test") + +template foo(a: int, b: string) = bar(a, b) +foo(1, "test") + +block: + proc bar(a: int, b: string) = nil + template foo(a: int, b: string) = nil + foo(1, "test") + bar(1, "test") + +proc baz = + proc foo(a: int, b: string) = nil + proc foo(b: string) = + template bar(a: int, b: string) = nil + bar(1, "test") + + foo("test") + + block: + proc foo(b: string) = nil + foo("test") + foo(1, "test") + +baz() diff --git a/tests/reject/tprocredef.nim b/tests/reject/tprocredef.nim new file mode 100644 index 0000000000..86ed92b629 --- /dev/null +++ b/tests/reject/tprocredef.nim @@ -0,0 +1,9 @@ +discard """ + file: "tprocredef.nim" + line: 8 + errormsg: "redefinition of \'foo\'" +""" + +proc foo(a: int, b: string) = nil +proc foo(a: int, b: string) = nil + diff --git a/tests/run/toverl2.nim b/tests/run/toverl2.nim index 49b17da4df..dd9f075a8d 100755 --- a/tests/run/toverl2.nim +++ b/tests/run/toverl2.nim @@ -1,6 +1,6 @@ discard """ file: "toverl2.nim" - output: "true012" + output: "true012innertrue" """ # Test new overloading resolution rules @@ -14,14 +14,20 @@ iterator toverl2(x: int): int = while res < x: yield res inc(res) - + var pp: proc (x: bool): string = toverl2 + stdout.write(pp(true)) + for x in toverl2(3): stdout.write(toverl2(x)) + +block: + proc toverl2(x: int): string = return "inner" + stdout.write(toverl2(5)) + stdout.write(true) + stdout.write("\n") -#OUT true012 - - +#OUT true012innertrue diff --git a/tests/run/tunittests.nim b/tests/run/tunittests.nim index fa7fe5075c..b2ec10cdc2 100644 --- a/tests/run/tunittests.nim +++ b/tests/run/tunittests.nim @@ -1,2 +1,2 @@ -import uclosures +import uclosures, utemplates diff --git a/tests/run/utemplates.nim b/tests/run/utemplates.nim new file mode 100644 index 0000000000..8fd3d242a6 --- /dev/null +++ b/tests/run/utemplates.nim @@ -0,0 +1,32 @@ +import unittest + +template t(a: int): expr = "int" +template t(a: string): expr = "string" + +test "templates can be overloaded": + check t(10) == "int" + check t("test") == "string" + +test "previous definitions can be further overloaded or hidden in local scopes": + template t(a: bool): expr = "bool" + + check t(true) == "bool" + check t(10) == "int" + + template t(a: int): expr = "inner int" + check t(10) == "inner int" + check t("test") == "string" + +test "templates can be redefined multiple times": + template customAssert(cond: bool, msg: string): stmt = + if not cond: fail(msg) + + template assertion_failed(body: stmt) = + template fail(msg: string): stmt = body + + assertion_failed: check msg == "first fail path" + customAssert false, "first fail path" + + assertion_failed: check msg == "second fail path" + customAssert false, "second fail path" + From 84806e6a61da2641b6e8cb34800c874dc74b90af Mon Sep 17 00:00:00 2001 From: Zahary Karadjov Date: Thu, 15 Mar 2012 14:32:47 +0200 Subject: [PATCH 5/7] updated system.nim to take advantage of the new template capabilities --- lib/system.nim | 26 +++++++++++++------------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/lib/system.nim b/lib/system.nim index bfaa5eb8fa..e27dc09b35 100755 --- a/lib/system.nim +++ b/lib/system.nim @@ -624,15 +624,15 @@ proc `<` *[T](x, y: ref T): bool {.magic: "LtPtr", noSideEffect.} proc `<` *[T](x, y: ptr T): bool {.magic: "LtPtr", noSideEffect.} proc `<` *(x, y: pointer): bool {.magic: "LtPtr", noSideEffect.} -template `!=` * (x, y: expr): expr = +template `!=` * (x, y: expr): expr {.immediate.} = ## unequals operator. This is a shorthand for ``not (x == y)``. not (x == y) -template `>=` * (x, y: expr): expr = +template `>=` * (x, y: expr): expr {.immediate.} = ## "is greater or equals" operator. This is the same as ``y <= x``. y <= x -template `>` * (x, y: expr): expr = +template `>` * (x, y: expr): expr {.immediate.} = ## "is greater" operator. This is the same as ``y < x``. y < x @@ -655,11 +655,11 @@ proc contains*[T](x: set[T], y: T): bool {.magic: "InSet", noSideEffect.} ## is achieved by reversing the parameters for ``contains``; ``in`` then ## passes its arguments in reverse order. -template `in` * (x, y: expr): expr = contains(y, x) -template `not_in` * (x, y: expr): expr = not contains(y, x) +template `in` * (x, y: expr): expr {.immediate.} = contains(y, x) +template `not_in` * (x, y: expr): expr {.immediate.} = not contains(y, x) proc `is` *[T, S](x: T, y: S): bool {.magic: "Is", noSideEffect.} -template `is_not` *(x, y: expr): expr = not (x is y) +template `is_not` *(x, y: expr): expr {.immediate.} = not (x is y) proc `of` *[T, S](x: T, y: S): bool {.magic: "Of", noSideEffect.} @@ -842,7 +842,7 @@ proc quit*(errorcode: int = QuitSuccess) {. ## It does *not* call the garbage collector to free all the memory, ## unless a quit procedure calls ``GC_collect``. -template sysAssert(cond, msg: expr) = +template sysAssert(cond: bool, msg: string) = when defined(useSysAssert): if not cond: echo "[SYSASSERT] ", msg @@ -1090,11 +1090,11 @@ proc swap*[T](a, b: var T) {.magic: "Swap", noSideEffect.} ## swaps the values `a` and `b`. This is often more efficient than ## ``tmp = a; a = b; b = tmp``. Particularly useful for sorting algorithms. -template `>=%` *(x, y: expr): expr = y <=% x +template `>=%` *(x, y: expr): expr {.immediate.} = y <=% x ## treats `x` and `y` as unsigned and compares them. ## Returns true iff ``unsigned(x) >= unsigned(y)``. -template `>%` *(x, y: expr): expr = y <% x +template `>%` *(x, y: expr): expr {.immediate.} = y <% x ## treats `x` and `y` as unsigned and compares them. ## Returns true iff ``unsigned(x) > unsigned(y)``. @@ -1590,7 +1590,7 @@ proc echo*[Ty](x: openarray[Ty]) {.magic: "Echo", noSideEffect.} ## Unlike other IO operations this is guaranteed to be thread-safe as ## ``echo`` is very often used for debugging convenience. -template newException*(exceptn, message: expr): expr = +template newException*(exceptn: typeDesc, message: string): expr = ## creates an exception object of type ``exceptn`` and sets its ``msg`` field ## to `message`. Returns the new exception object. block: # open a new scope @@ -2033,7 +2033,7 @@ proc `[]`*(s: string, x: TSlice[int]): string {.inline.} = ## slice operation for strings. Negative indexes are supported. result = s.substr(x.a-|s, x.b-|s) -template spliceImpl(s, a, L, b: expr): stmt = +template spliceImpl(s, a, L, b: expr): stmt {.immediate.} = # make room for additional elements or cut: var slen = s.len var shift = b.len - L @@ -2176,7 +2176,7 @@ proc InstantiationInfo*(index = -1): tuple[filename: string, line: int] {. proc raiseAssert(msg: string) {.noinline.} = raise newException(EAssertionFailed, msg) -template assert*(cond: expr, msg = "") = +template assert*(cond: bool, msg = "") = ## provides a means to implement `programming by contracts`:idx: in Nimrod. ## ``assert`` evaluates expression ``cond`` and if ``cond`` is false, it ## raises an ``EAssertionFailure`` exception. However, the compiler may @@ -2188,7 +2188,7 @@ template assert*(cond: expr, msg = "") = if not cond: raiseAssert(astToStr(cond) & ' ' & msg) -template doAssert*(cond: expr, msg = "") = +template doAssert*(cond: bool, msg = "") = ## same as `assert` but is always turned on and not affected by the ## ``--assertions`` command line switch. bind raiseAssert, InstantiationInfo From 72f2a6e2755cdeaf1db85a9b119b694b9a2cb472 Mon Sep 17 00:00:00 2001 From: Zahary Karadjov Date: Fri, 16 Mar 2012 05:33:21 +0200 Subject: [PATCH 6/7] the test suite is mostly green again --- compiler/ast.nim | 18 ------------------ compiler/semexprs.nim | 23 +++++++++++------------ compiler/semtempl.nim | 6 ++++-- examples/allany.nim | 4 ++-- lib/pure/collections/sequtils.nim | 2 +- lib/pure/colors.nim | 6 +++--- lib/pure/os.nim | 4 ++-- lib/wrappers/sdl/sdl.nim | 4 ++-- tests/compile/tambsym2.nim | 4 +--- tests/compile/ttableconstr.nim | 2 +- tests/compile/ttempl3.nim | 4 ++-- tests/compile/ttempl4.nim | 4 ++-- tests/reject/ttempl2.nim | 6 ++---- tests/rodfiles/bmethods.nim | 1 + tests/rodfiles/bmethods2.nim | 3 ++- tests/run/tambsys.nim | 14 +++++++------- tests/run/tcurrncy.nim | 2 +- tests/run/tints.nim | 4 +--- tests/run/ttoseq.nim | 2 +- 19 files changed, 46 insertions(+), 67 deletions(-) diff --git a/compiler/ast.nim b/compiler/ast.nim index 2c8ca52d70..04631a059c 100755 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -922,12 +922,6 @@ proc delSon(father: PNode, idx: int) = for i in countup(idx, length - 2): father.sons[i] = father.sons[i + 1] setlen(father.sons, length - 1) -proc hasSons*(n: PNode): bool {.inline.} = - result = n.kind notin { nkCharLit..nkInt64Lit, - nkFloatLit..nkFloat64Lit, - nkStrLit..nkTripleStrLit, - nkSym, nkIdent } - proc copyNode(src: PNode): PNode = # does not copy its sons! if src == nil: @@ -959,18 +953,6 @@ proc shallowCopy*(src: PNode): PNode = of nkStrLit..nkTripleStrLit: result.strVal = src.strVal else: newSeq(result.sons, sonsLen(src)) -proc copySons*(src: PNode): Pnode = - # copies a node and its immediate sons - if src == nil: return nil - assert src.hasSons - result = newNode(src.kind) - result.info = src.info - result.typ = src.typ - result.flags = src.flags * PersistentNodeFlags - newSeq(result.sons, src.len) - for i in countup(0, src.len - 1): - result.sons[i] = src.sons[i] - proc copyTree(src: PNode): PNode = # copy a whole syntax tree; performs deep copying if src == nil: diff --git a/compiler/semexprs.nim b/compiler/semexprs.nim index 704f182c84..5a339c5a70 100755 --- a/compiler/semexprs.nim +++ b/compiler/semexprs.nim @@ -491,15 +491,15 @@ proc expectStringArg(c: PContext, n: PNode, i: int): PNode = include semmagic -proc semOverloadedCallAnalyseEffects(c: PContext, n: PNode, orig: PNode, +proc semOverloadedCallAnalyseEffects(c: PContext, n: PNode, nOrig: PNode, flags: TExprFlags): PNode = if efWantIterator in flags: - result = semOverloadedCall(c, n, orig, {skIterator}) + result = semOverloadedCall(c, n, nOrig, {skIterator}) elif efInTypeOf in flags: # for ``type(countup(1,3))``, see ``tests/ttoseq``. - result = semOverloadedCall(c, n, orig, {skIterator, skProc, skMethod, skConverter, skMacro, skTemplate}) + result = semOverloadedCall(c, n, nOrig, {skIterator, skProc, skMethod, skConverter, skMacro, skTemplate}) else: - result = semOverloadedCall(c, n, orig, {skProc, skMethod, skConverter, skMacro, skTemplate}) + result = semOverloadedCall(c, n, nOrig, {skProc, skMethod, skConverter, skMacro, skTemplate}) if result != nil: if result.sons[0].kind != nkSym: InternalError("semDirectCallAnalyseEffects") @@ -513,9 +513,9 @@ proc semOverloadedCallAnalyseEffects(c: PContext, n: PNode, orig: PNode, if {sfImportc, sfSideEffect} * callee.flags != {}: incl(c.p.owner.flags, sfSideEffect) -proc semDirectCallAnalyseEffects(c: PContext, n: PNode, orig: PNode, +proc semDirectCallAnalyseEffects(c: PContext, n: PNode, nOrig: PNode, flags: TExprFlags): PNode = - result = semOverloadedCallAnalyseEffects(c, n, orig, flags) + result = semOverloadedCallAnalyseEffects(c, n, nOrig, flags) proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode = result = nil @@ -532,14 +532,14 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode = return semExpr(c, result, flags) else: n.sons[0] = semExpr(c, n.sons[0]) - let orig = n.copySons + let nOrig = n.copyTree semOpAux(c, n) var t: PType = nil if (n.sons[0].typ != nil): t = skipTypes(n.sons[0].typ, abstractInst) if (t != nil) and (t.kind == tyProc): var m: TCandidate initCandidate(m, t) - matches(c, n, orig, m) + matches(c, n, nOrig, m) if m.state != csMatch: var msg = msgKindToString(errTypeMismatch) for i in countup(1, sonsLen(n) - 1): @@ -560,7 +560,7 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode = # the old ``prc`` (which is likely an nkIdent) has to be restored: if result == nil: n.sons[0] = prc - result = semOverloadedCallAnalyseEffects(c, n, orig, flags) + result = semOverloadedCallAnalyseEffects(c, n, nOrig, flags) if result == nil: GlobalError(n.info, errExprXCannotBeCalled, renderTree(n, {renderNoComments})) @@ -571,7 +571,7 @@ proc semIndirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode = proc semDirectOp(c: PContext, n: PNode, flags: TExprFlags): PNode = # this seems to be a hotspot in the compiler! - let nOrig = n.copySons + let nOrig = n.copyTree semOpAux(c, n) result = semOverloadedCallAnalyseEffects(c, n, nOrig, flags) if result == nil: @@ -1269,12 +1269,11 @@ proc semExpr(c: PContext, n: PNode, flags: TExprFlags = {}): PNode = if s != nil: case s.kind of skMacro: - if c.filename.endsWith("hello.nim") and sfImmediate notin s.flags: + if false and sfImmediate notin s.flags: # XXX not yet enabled result = semDirectOp(c, n, flags) else: result = semMacroExpr(c, n, s) of skTemplate: - var hello = c.filename.endsWith("hello.nim") if sfImmediate notin s.flags: result = semDirectOp(c, n, flags) else: diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim index b1f70803e7..2600d80cb7 100755 --- a/compiler/semtempl.nim +++ b/compiler/semtempl.nim @@ -7,6 +7,8 @@ # distribution, for details about the copyright. # +# included from sem.nim + proc isExpr(n: PNode): bool = # returns true if ``n`` looks like an expression case n.kind @@ -191,10 +193,10 @@ proc semTemplateDef(c: PContext, n: PNode): PNode = result = n if n.sons[bodyPos].kind == nkEmpty: LocalError(n.info, errImplOfXexpected, s.name.s) - let curScope = c.tab.tos - 2 # -2 because we have a scope open for parameters + let curScope = c.tab.tos - 1 var proto = SearchForProc(c, s, curScope) if proto == nil: - addInterfaceOverloadableSymAt(c, s, c.tab.tos - 2) + addInterfaceOverloadableSymAt(c, s, curScope) else: SymTabReplace(c.tab.stack[curScope], proto, s) diff --git a/examples/allany.nim b/examples/allany.nim index 8f84ba3fc9..de36a1d9bd 100755 --- a/examples/allany.nim +++ b/examples/allany.nim @@ -1,6 +1,6 @@ # All and any -template all(container, cond: expr): expr = +template all(container, cond: expr): expr {.immediate.} = block: var result = true for it in items(container): @@ -9,7 +9,7 @@ template all(container, cond: expr): expr = break result -template any(container, cond: expr): expr = +template any(container, cond: expr): expr {.immediate.} = block: var result = false for it in items(container): diff --git a/lib/pure/collections/sequtils.nim b/lib/pure/collections/sequtils.nim index b7a57ac0c4..e3034d635e 100644 --- a/lib/pure/collections/sequtils.nim +++ b/lib/pure/collections/sequtils.nim @@ -50,7 +50,7 @@ proc filter*[T](seq1: seq[T], pred: proc(item: T): bool): seq[T] = ## Returns all items in a sequence that fulfilled the predicate. accumulateResult(filter(seq1, pred)) -template filterIt*(seq1, pred: expr): expr = +template filterIt*(seq1, pred: expr): expr {.immediate.} = ## Finds a specific item in a sequence as long as the ## predicate returns true. The predicate needs to be an expression ## containing ``it``: ``filterIt("abcxyz", it == 'x')``. diff --git a/lib/pure/colors.nim b/lib/pure/colors.nim index 6a86a43c46..00edaad9c7 100755 --- a/lib/pure/colors.nim +++ b/lib/pure/colors.nim @@ -17,15 +17,15 @@ type proc `==` *(a, b: TColor): bool {.borrow.} ## compares two colors. -template extract(a: TColor, r, g, b: expr) = +template extract(a: TColor, r, g, b: expr) {.immediate.}= var r = a.int shr 16 and 0xff var g = a.int shr 8 and 0xff var b = a.int and 0xff -template rawRGB(r, g, b: expr): expr = +template rawRGB(r, g, b: int): expr = TColor(r shl 16 or g shl 8 or b) -template colorOp(op: expr) = +template colorOp(op: expr) {.immediate.} = extract(a, ar, ag, ab) extract(b, br, bg, bb) result = rawRGB(op(ar, br), op(ag, bg), op(ab, bb)) diff --git a/lib/pure/os.nim b/lib/pure/os.nim index 76f934c04a..5ea93eb064 100755 --- a/lib/pure/os.nim +++ b/lib/pure/os.nim @@ -242,12 +242,12 @@ proc UnixToNativePath*(path: string): string {. inc(i) when defined(windows): - template wrapUnary(varname, winApiProc, arg: expr) = + template wrapUnary(varname, winApiProc, arg: expr) {.immediate.} = var tmp = allocWideCString(arg) var varname = winApiProc(tmp) dealloc tmp - template wrapBinary(varname, winApiProc, arg, arg2: expr) = + template wrapBinary(varname, winApiProc, arg, arg2: expr) {.immediate.} = var tmp2 = allocWideCString(arg) var varname = winApiProc(tmp2, arg2) dealloc tmp2 diff --git a/lib/wrappers/sdl/sdl.nim b/lib/wrappers/sdl/sdl.nim index 8ddab49dda..cf4eb452d7 100755 --- a/lib/wrappers/sdl/sdl.nim +++ b/lib/wrappers/sdl/sdl.nim @@ -1284,9 +1284,9 @@ type # This is the system-independent thread info struc TProcedure* = proc () type TEventSeq = set[TEventKind] -template evconv(procName: expr, ptrName: typeDesc, assertions: TEventSeq): stmt = +template evconv(procName: expr, ptrName: typeDesc, assertions: TEventSeq): stmt {.immediate.} = proc `procName`*(event: PEvent): ptrName = - assert(assertions.contains(event.kind)) + assert(contains(assertions, event.kind)) result = cast[ptrName](event) evconv(EvActive, PActiveEvent, {ACTIVEEVENT}) diff --git a/tests/compile/tambsym2.nim b/tests/compile/tambsym2.nim index ecd9a47847..7758cc31a6 100755 --- a/tests/compile/tambsym2.nim +++ b/tests/compile/tambsym2.nim @@ -1,8 +1,6 @@ from sdl import PSurface -discard SDL.CreateRGBSurface(SDL.SWSURFACE, 23, 34, +discard SDL.CreateRGBSurface(SDL.SWSURFACE, 23, 34, 32, 0x00FF0000, 0x0000FF00, 0x000000FF, 0xff000000'i32) - - diff --git a/tests/compile/ttableconstr.nim b/tests/compile/ttableconstr.nim index 9433e9985b..c627e68e8a 100755 --- a/tests/compile/ttableconstr.nim +++ b/tests/compile/ttableconstr.nim @@ -1,6 +1,6 @@ # Test if the new table constructor syntax works: -template ignoreExpr(e: expr): stmt = +template ignoreExpr(e: expr): stmt {.immediate.} = nil # test first class '..' syntactical citizen: diff --git a/tests/compile/ttempl3.nim b/tests/compile/ttempl3.nim index 7b2c70f793..d8e67cc3ef 100755 --- a/tests/compile/ttempl3.nim +++ b/tests/compile/ttempl3.nim @@ -26,13 +26,13 @@ echo(ha) # Test identifier generation: -template prefix(name: expr): expr = `"hu" name` +template prefix(name: expr): expr {.immediate.} = `"hu" name` var `hu "XYZ"` = "yay" echo prefix(XYZ) -template typedef(name: expr, typ: typeDesc) = +template typedef(name: expr, typ: typeDesc) {.immediate.} = type `T name`* = typ `P name`* = ref `T name` diff --git a/tests/compile/ttempl4.nim b/tests/compile/ttempl4.nim index a5ad2000fc..26c82e4713 100755 --- a/tests/compile/ttempl4.nim +++ b/tests/compile/ttempl4.nim @@ -1,7 +1,7 @@ -template `:=`(name, val: expr): stmt = +template `:=`(name, val: expr): stmt {.immediate.} = var name = val - + ha := 1 * 4 hu := "ta-da" == "ta-da" echo ha, hu diff --git a/tests/reject/ttempl2.nim b/tests/reject/ttempl2.nim index fba988f957..142bbb8c71 100755 --- a/tests/reject/ttempl2.nim +++ b/tests/reject/ttempl2.nim @@ -3,10 +3,10 @@ discard """ line: 18 errormsg: "undeclared identifier: \'b\'" """ -template declareInScope(x: expr, t: typeDesc): stmt = +template declareInScope(x: expr, t: typeDesc): stmt {.immediate.} = var x: t -template declareInNewScope(x: expr, t: typeDesc): stmt = +template declareInNewScope(x: expr, t: typeDesc): stmt {.immediate.} = # open a new scope: block: var x: t @@ -17,5 +17,3 @@ a = 42 # works, `a` is known here declareInNewScope(b, int) b = 42 #ERROR_MSG undeclared identifier: 'b' - - diff --git a/tests/rodfiles/bmethods.nim b/tests/rodfiles/bmethods.nim index 995942ad63..39aa5368ca 100644 --- a/tests/rodfiles/bmethods.nim +++ b/tests/rodfiles/bmethods.nim @@ -1,4 +1,5 @@ discard """ + disabled: true output: '''derived class base class ''' diff --git a/tests/rodfiles/bmethods2.nim b/tests/rodfiles/bmethods2.nim index ac24a22014..0d1795a276 100644 --- a/tests/rodfiles/bmethods2.nim +++ b/tests/rodfiles/bmethods2.nim @@ -1,5 +1,6 @@ discard """ - output: '''derived class 2 + disabled: true + output: '''derived class 2 base class ''' """ diff --git a/tests/run/tambsys.nim b/tests/run/tambsys.nim index a886158666..67522d7c9a 100755 --- a/tests/run/tambsys.nim +++ b/tests/run/tambsys.nim @@ -2,12 +2,12 @@ discard """ file: "tambsys.nim" output: "" """ -# Test ambiguous symbols - -import mambsys1, mambsys2 - -var - v: mambsys1.TExport -mambsys2.foo(3) #OUT +# Test ambiguous symbols + +import mambsys1, mambsys2 + +var + v: mambsys1.TExport +mambsys2.foo(3) #OUT diff --git a/tests/run/tcurrncy.nim b/tests/run/tcurrncy.nim index a614de7afe..d04620cfb9 100755 --- a/tests/run/tcurrncy.nim +++ b/tests/run/tcurrncy.nim @@ -21,7 +21,7 @@ template Comparable(typ: typeDesc): stmt = proc `<=` * (x, y: typ): bool {.borrow.} proc `==` * (x, y: typ): bool {.borrow.} -template DefineCurrency(typ, base: expr): stmt = +template DefineCurrency(typ, base: expr): stmt {.immediate.} = type typ* = distinct base Additive(typ) diff --git a/tests/run/tints.nim b/tests/run/tints.nim index 6c98978609..fb2852af9c 100755 --- a/tests/run/tints.nim +++ b/tests/run/tints.nim @@ -6,7 +6,7 @@ discard """ var testNumber = 0 -template test(opr, a, b, c: expr): stmt = +template test(opr, a, b, c: expr): stmt {.immediate.} = # test the expression at compile and runtime block: const constExpr = opr(a, b) @@ -43,5 +43,3 @@ test(`shl`, 0xffffffff'i32, 0x4'i32, 0xfffffff0'i32) Echo("Success") #OUT Success - - diff --git a/tests/run/ttoseq.nim b/tests/run/ttoseq.nim index d631a91e05..ec49489d01 100755 --- a/tests/run/ttoseq.nim +++ b/tests/run/ttoseq.nim @@ -2,7 +2,7 @@ discard """ output: "23456" """ -template toSeq*(iter: expr): expr = +template toSeq*(iter: expr): expr {.immediate.} = var result: seq[type(iter)] = @[] for x in iter: add(result, x) result From 7d09aee438b335122adf6cc1de875e81ea736c96 Mon Sep 17 00:00:00 2001 From: Zahary Karadjov Date: Fri, 16 Mar 2012 17:40:29 +0200 Subject: [PATCH 7/7] rebuilt the C sources