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" +