Skip to content

Commit

Permalink
fix dot calls with resolved symbols in templates (#22076)
Browse files Browse the repository at this point in the history
* fix dot calls with resolved symbols in templates

* make old code work

* fix custom number literals test

* remove leftover debug marker

* enable "bug 9" test too

* fix renderer, add test for #7085

(cherry picked from commit 71801c2)
  • Loading branch information
metagn authored and narimiran committed Jun 13, 2023
1 parent c50adf1 commit b686912
Show file tree
Hide file tree
Showing 6 changed files with 57 additions and 25 deletions.
3 changes: 1 addition & 2 deletions compiler/ast.nim
Original file line number Diff line number Diff line change
Expand Up @@ -1113,11 +1113,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
Expand Down
1 change: 1 addition & 0 deletions compiler/renderer.nim
Original file line number Diff line number Diff line change
Expand Up @@ -376,6 +376,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 & "\"\"\""
Expand Down
8 changes: 8 additions & 0 deletions compiler/semtempl.nim
Original file line number Diff line number Diff line change
Expand Up @@ -566,6 +566,14 @@ 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
# 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:
result = semTemplBodySons(c, n)
of nkExprColonExpr, nkExprEqExpr:
Expand Down
38 changes: 15 additions & 23 deletions tests/lexer/tcustom_numeric_literals.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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
macro deb2(a): untyped =
a[1] = ident($a[1])
newLit a.lispRepr
doAssert deb1(-12'wrap) == "-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 =
Expand All @@ -165,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()
22 changes: 22 additions & 0 deletions tests/template/mdotcall.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# issue #20073

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

# issue #7085

proc bar(a: string): string =
return a & "bar"

template baz*(a: string): string =
var b = a.bar()
b
10 changes: 10 additions & 0 deletions tests/template/tdotcall.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
import mdotcall

# issue #20073
works()
boom()

# issue #7085
doAssert baz("hello") == "hellobar"
doAssert baz"hello" == "hellobar"
doAssert "hello".baz == "hellobar"

0 comments on commit b686912

Please sign in to comment.