Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix dot calls with resolved symbols in templates #22076

Merged
merged 6 commits into from
Jun 12, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 1 addition & 2 deletions compiler/ast.nim
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
8 changes: 8 additions & 0 deletions compiler/semtempl.nim
Original file line number Diff line number Diff line change
Expand Up @@ -561,6 +561,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:
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This was not a bug. It's because this code is in a giant main template, which binds the outer 'wrap and wrap2, because that's how the language works.

# 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
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Meanwhile this was actually the bug fixed by this PR, custom numeric literals generate dot fields which did not keep their resolved symbols in templates. It really wouldn't have taken much investigation to figure out this is related to dot fields and has nothing to do with custom numeric literals. The linked comment thinks it has something to do with 'abc not working where abc is a template param??? Very weird understanding of the language

#[
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()
11 changes: 11 additions & 0 deletions tests/template/mdotcall.nim
Original file line number Diff line number Diff line change
@@ -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
6 changes: 6 additions & 0 deletions tests/template/tdotcall.nim
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# issue #20073

import mdotcall

works()
boom()