From e3a5f22c292cae2e86cf3c155f3fdf7f11a89041 Mon Sep 17 00:00:00 2001 From: metagn <10591326+metagn@users.noreply.github.com> Date: Sun, 11 Jun 2023 18:20:17 +0300 Subject: [PATCH 1/6] fix dot calls with resolved symbols in templates --- compiler/semtempl.nim | 6 ++++++ tests/template/mdotcall.nim | 11 +++++++++++ tests/template/tdotcall.nim | 6 ++++++ 3 files changed, 23 insertions(+) create mode 100644 tests/template/mdotcall.nim create mode 100644 tests/template/tdotcall.nim diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim index 9edb2d0ca55d..c147263a4200 100644 --- a/compiler/semtempl.nim +++ b/compiler/semtempl.nim @@ -561,6 +561,12 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode = inc c.noGenSym result[1] = semTemplBody(c, n[1]) dec c.noGenSym + if result[1].kind == nkSym and result[1].sym.kind in routineKinds: + # prevent `dotTransformation` from rewriting this node to `nkIdent` + # by making it a symchoice + var choice = newNodeIT(nkClosedSymChoice, n[1].info, newTypeS(tyNone, c.c)) + choice.add result[1] + result[1] = choice else: result = semTemplBodySons(c, n) of nkExprColonExpr, nkExprEqExpr: diff --git a/tests/template/mdotcall.nim b/tests/template/mdotcall.nim new file mode 100644 index 000000000000..2bb73f144d89 --- /dev/null +++ b/tests/template/mdotcall.nim @@ -0,0 +1,11 @@ +type Foo = object +proc foo(f: Foo) = discard + +template works*() = + var f: Foo + foo(f) + +template boom*() = + var f: Foo + f.foo() # Error: attempting to call undeclared routine: 'foo' + f.foo # Error: undeclared field: 'foo' for type a.Foo diff --git a/tests/template/tdotcall.nim b/tests/template/tdotcall.nim new file mode 100644 index 000000000000..56ee56a85faa --- /dev/null +++ b/tests/template/tdotcall.nim @@ -0,0 +1,6 @@ +# issue #20073 + +import mdotcall + +works() +boom() From d8d7ba2e5106cf7efe39bfad0b287686b5ea9634 Mon Sep 17 00:00:00 2001 From: metagn <10591326+metagn@users.noreply.github.com> Date: Sun, 11 Jun 2023 18:57:41 +0300 Subject: [PATCH 2/6] make old code work --- compiler/semtempl.nim | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/semtempl.nim b/compiler/semtempl.nim index c147263a4200..33f4c11995b7 100644 --- a/compiler/semtempl.nim +++ b/compiler/semtempl.nim @@ -564,7 +564,9 @@ proc semTemplBody(c: var TemplCtx, n: PNode): PNode = if result[1].kind == nkSym and result[1].sym.kind in routineKinds: # prevent `dotTransformation` from rewriting this node to `nkIdent` # by making it a symchoice - var choice = newNodeIT(nkClosedSymChoice, n[1].info, newTypeS(tyNone, c.c)) + # in generics this becomes `nkClosedSymChoice` but this breaks code + # as the old behavior here was that this became `nkIdent` + var choice = newNodeIT(nkOpenSymChoice, n[1].info, newTypeS(tyNone, c.c)) choice.add result[1] result[1] = choice else: From 4f2d71885e7596f124668c52239ef38e179a082d Mon Sep 17 00:00:00 2001 From: metagn <10591326+metagn@users.noreply.github.com> Date: Sun, 11 Jun 2023 20:58:16 +0300 Subject: [PATCH 3/6] fix custom number literals test --- compiler/ast.nim | 3 +-- tests/lexer/tcustom_numeric_literals.nim | 15 ++++++--------- 2 files changed, 7 insertions(+), 11 deletions(-) diff --git a/compiler/ast.nim b/compiler/ast.nim index 8fba0a848716..f8aefd8fb15f 100644 --- a/compiler/ast.nim +++ b/compiler/ast.nim @@ -1128,11 +1128,10 @@ const proc getPIdent*(a: PNode): PIdent {.inline.} = ## Returns underlying `PIdent` for `{nkSym, nkIdent}`, or `nil`. - # xxx consider whether also returning the 1st ident for {nkOpenSymChoice, nkClosedSymChoice} - # which may simplify code. case a.kind of nkSym: a.sym.name of nkIdent: a.ident + of nkOpenSymChoice, nkClosedSymChoice: a.sons[0].sym.name else: nil const diff --git a/tests/lexer/tcustom_numeric_literals.nim b/tests/lexer/tcustom_numeric_literals.nim index 9c49d0c0818a..0b7a400c27cc 100644 --- a/tests/lexer/tcustom_numeric_literals.nim +++ b/tests/lexer/tcustom_numeric_literals.nim @@ -134,17 +134,14 @@ template main = block: # bug 1 from https://github.com/nim-lang/Nim/pull/17020#issuecomment-803193947 macro deb1(a): untyped = newLit a.repr - macro deb2(a): untyped = newLit a.lispRepr - doAssert deb1(-12'wrap) == "-12'wrap" + macro deb2(a): untyped = + a[1] = ident($a[1]) + newLit a.lispRepr + doAssert deb1(-12'wrap) == "-12'wrap", deb1(-12'wrap) doAssert deb1(-12'nonexistent) == "-12'nonexistent" doAssert deb2(-12'nonexistent) == """(DotExpr (RStrLit "-12") (Ident "\'nonexistent"))""" - when false: # xxx bug: - # this holds: - doAssert deb2(-12.wrap2) == """(DotExpr (IntLit -12) (Sym "wrap2"))""" - doAssert deb2(-12'wrap) == """(DotExpr (RStrLit "-12") (Sym "\'wrap"))""" - # but instead this should hold: - doAssert deb2(-12.wrap2) == """(DotExpr (IntLit -12) (Ident "wrap2"))""" - doAssert deb2(-12'wrap) == """(DotExpr (RStrLit "-12") (Ident "\'wrap"))""" + doAssert deb2(-12.wrap2) == """(DotExpr (IntLit -12) (Ident "wrap2"))""" + doAssert deb2(-12'wrap) == """(DotExpr (RStrLit "-12") (Ident "\'wrap"))""" block: # bug 2 from https://github.com/nim-lang/Nim/pull/17020#issuecomment-803193947 template toSuf(`'suf`): untyped = From f68e86904210fd6fbed7892fa89798a4b4830324 Mon Sep 17 00:00:00 2001 From: metagn <10591326+metagn@users.noreply.github.com> Date: Sun, 11 Jun 2023 20:59:01 +0300 Subject: [PATCH 4/6] remove leftover debug marker --- tests/lexer/tcustom_numeric_literals.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/lexer/tcustom_numeric_literals.nim b/tests/lexer/tcustom_numeric_literals.nim index 0b7a400c27cc..accdff94aa16 100644 --- a/tests/lexer/tcustom_numeric_literals.nim +++ b/tests/lexer/tcustom_numeric_literals.nim @@ -137,7 +137,7 @@ template main = macro deb2(a): untyped = a[1] = ident($a[1]) newLit a.lispRepr - doAssert deb1(-12'wrap) == "-12'wrap", deb1(-12'wrap) + doAssert deb1(-12'wrap) == "-12'wrap" doAssert deb1(-12'nonexistent) == "-12'nonexistent" doAssert deb2(-12'nonexistent) == """(DotExpr (RStrLit "-12") (Ident "\'nonexistent"))""" doAssert deb2(-12.wrap2) == """(DotExpr (IntLit -12) (Ident "wrap2"))""" From 865c7a5c47d8f591e82e20a8d1de3ca8bdeab558 Mon Sep 17 00:00:00 2001 From: metagn <10591326+metagn@users.noreply.github.com> Date: Sun, 11 Jun 2023 21:03:21 +0300 Subject: [PATCH 5/6] enable "bug 9" test too --- tests/lexer/tcustom_numeric_literals.nim | 25 ++++++++++-------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/tests/lexer/tcustom_numeric_literals.nim b/tests/lexer/tcustom_numeric_literals.nim index accdff94aa16..35b4803d36c1 100644 --- a/tests/lexer/tcustom_numeric_literals.nim +++ b/tests/lexer/tcustom_numeric_literals.nim @@ -162,21 +162,16 @@ template main = doAssert fn2() == "[[-12]]" doAssert fn3() == "[[-12]]" - when false: # xxx this fails; bug 9 from https://github.com/nim-lang/Nim/pull/17020#issuecomment-803193947 - #[ - possible workaround: use `genAst` (https://github.com/nim-lang/Nim/pull/17426) and this: - let a3 = `'wrap3`("-128") - ]# - block: - macro metawrap(): untyped = - func wrap1(a: string): string = "{" & a & "}" - func `'wrap3`(a: string): string = "{" & a & "}" - result = quote do: - let a1 = wrap1"-128" - let a2 = -128'wrap3 - metawrap() - doAssert a1 == "{-128}" - doAssert a2 == "{-128}" + block: # bug 9 from https://github.com/nim-lang/Nim/pull/17020#issuecomment-803193947 + macro metawrap(): untyped = + func wrap1(a: string): string = "{" & a & "}" + func `'wrap3`(a: string): string = "{" & a & "}" + result = quote do: + let a1 {.inject.} = wrap1"-128" + let a2 {.inject.} = -128'wrap3 + metawrap() + doAssert a1 == "{-128}" + doAssert a2 == "{-128}" static: main() main() From 7f46843dbb6d612b5c4a3d2fdbf890b920fc7010 Mon Sep 17 00:00:00 2001 From: metagn <10591326+metagn@users.noreply.github.com> Date: Sun, 11 Jun 2023 22:08:51 +0300 Subject: [PATCH 6/6] fix renderer, add test for #7085 --- compiler/renderer.nim | 1 + tests/template/mdotcall.nim | 11 +++++++++++ tests/template/tdotcall.nim | 8 ++++++-- 3 files changed, 18 insertions(+), 2 deletions(-) diff --git a/compiler/renderer.nim b/compiler/renderer.nim index f0ad21815ccf..3f237c932255 100644 --- a/compiler/renderer.nim +++ b/compiler/renderer.nim @@ -379,6 +379,7 @@ proc atom(g: TSrcGen; n: PNode): string = of nkEmpty: result = "" of nkIdent: result = n.ident.s of nkSym: result = n.sym.name.s + of nkClosedSymChoice, nkOpenSymChoice: result = n[0].sym.name.s of nkStrLit: result = ""; result.addQuoted(n.strVal) of nkRStrLit: result = "r\"" & replace(n.strVal, "\"", "\"\"") & '\"' of nkTripleStrLit: result = "\"\"\"" & n.strVal & "\"\"\"" diff --git a/tests/template/mdotcall.nim b/tests/template/mdotcall.nim index 2bb73f144d89..38a6ccae0da8 100644 --- a/tests/template/mdotcall.nim +++ b/tests/template/mdotcall.nim @@ -1,3 +1,5 @@ +# issue #20073 + type Foo = object proc foo(f: Foo) = discard @@ -9,3 +11,12 @@ template boom*() = var f: Foo f.foo() # Error: attempting to call undeclared routine: 'foo' f.foo # Error: undeclared field: 'foo' for type a.Foo + +# issue #7085 + +proc bar(a: string): string = + return a & "bar" + +template baz*(a: string): string = + var b = a.bar() + b diff --git a/tests/template/tdotcall.nim b/tests/template/tdotcall.nim index 56ee56a85faa..abcbc8bd5a17 100644 --- a/tests/template/tdotcall.nim +++ b/tests/template/tdotcall.nim @@ -1,6 +1,10 @@ -# issue #20073 - import mdotcall +# issue #20073 works() boom() + +# issue #7085 +doAssert baz("hello") == "hellobar" +doAssert baz"hello" == "hellobar" +doAssert "hello".baz == "hellobar"