Fix forward declaration issues in template/macro context (#15091)
* Fix forward declaration issues in template/macro context * Correct forward declaration resolving for overloads * Remove old dead code * WIP consistent gensym ids * Minimize diff * Remove obsoleted hack * Add templInstCounter to give unique IDs to template instantiations * Remove obsoleted code * Eh, init in myOpen, not myProcess... * Remove optNimV019 * Add testcase for #13484
This commit is contained in:
parent
196e747df1
commit
2629d619a1
17 changed files with 270 additions and 95 deletions
|
|
@ -35,6 +35,10 @@ test
|
|||
foo1
|
||||
foo2
|
||||
foo3
|
||||
true
|
||||
false
|
||||
true
|
||||
false
|
||||
'''
|
||||
"""
|
||||
|
||||
|
|
@ -289,3 +293,113 @@ proc main() =
|
|||
const fb = Foobar(a: a)
|
||||
foobar(fb)
|
||||
main()
|
||||
|
||||
# bug #13484
|
||||
|
||||
proc defForward(id, nid: NimNode): NimNode =
|
||||
result = newProc(id, @[newIdentNode("bool"), newIdentDefs(nid, newIdentNode("int"))], body=newEmptyNode())
|
||||
|
||||
proc defEven(evenid, oddid, nid: NimNode): NimNode =
|
||||
result = quote do:
|
||||
proc `evenid`(`nid`: int): bool =
|
||||
if `nid` == 0:
|
||||
return true
|
||||
else:
|
||||
return `oddid`(`nid` - 1)
|
||||
|
||||
proc defOdd(evenid, oddid, nid: NimNode): NimNode =
|
||||
result = quote do:
|
||||
proc `oddid`(`nid`: int): bool =
|
||||
if `nid` == 0:
|
||||
return false
|
||||
else:
|
||||
return `evenid`(`nid` - 1)
|
||||
|
||||
proc callNode(funid, param: NimNode): NimNode =
|
||||
result = quote do:
|
||||
`funid`(`param`)
|
||||
|
||||
macro testEvenOdd3(): untyped =
|
||||
let
|
||||
evenid = newIdentNode("even3")
|
||||
oddid = newIdentNode("odd3")
|
||||
nid = newIdentNode("n")
|
||||
oddForward = defForward(oddid, nid)
|
||||
even = defEven(evenid, oddid, nid)
|
||||
odd = defOdd(evenid, oddid, nid)
|
||||
callEven = callNode(evenid, newLit(42))
|
||||
callOdd = callNode(oddid, newLit(42))
|
||||
result = quote do:
|
||||
`oddForward`
|
||||
`even`
|
||||
`odd`
|
||||
echo `callEven`
|
||||
echo `callOdd`
|
||||
|
||||
macro testEvenOdd4(): untyped =
|
||||
let
|
||||
evenid = newIdentNode("even4")
|
||||
oddid = newIdentNode("odd4")
|
||||
nid = newIdentNode("n")
|
||||
oddForward = defForward(oddid, nid)
|
||||
even = defEven(evenid, oddid, nid)
|
||||
odd = defOdd(evenid, oddid, nid)
|
||||
callEven = callNode(evenid, newLit(42))
|
||||
callOdd = callNode(oddid, newLit(42))
|
||||
# rewrite the body of proc node.
|
||||
oddForward[6] = newStmtList()
|
||||
result = quote do:
|
||||
`oddForward`
|
||||
`even`
|
||||
`odd`
|
||||
echo `callEven`
|
||||
echo `callOdd`
|
||||
|
||||
macro testEvenOdd5(): untyped =
|
||||
let
|
||||
evenid = genSym(nskProc, "even5")
|
||||
oddid = genSym(nskProc, "odd5")
|
||||
nid = newIdentNode("n")
|
||||
oddForward = defForward(oddid, nid)
|
||||
even = defEven(evenid, oddid, nid)
|
||||
odd = defOdd(evenid, oddid, nid)
|
||||
callEven = callNode(evenid, newLit(42))
|
||||
callOdd = callNode(oddid, newLit(42))
|
||||
result = quote do:
|
||||
`oddForward`
|
||||
`even`
|
||||
`odd`
|
||||
echo `callEven`
|
||||
echo `callOdd`
|
||||
|
||||
macro testEvenOdd6(): untyped =
|
||||
let
|
||||
evenid = genSym(nskProc, "even6")
|
||||
oddid = genSym(nskProc, "odd6")
|
||||
nid = newIdentNode("n")
|
||||
oddForward = defForward(oddid, nid)
|
||||
even = defEven(evenid, oddid, nid)
|
||||
odd = defOdd(evenid, oddid, nid)
|
||||
callEven = callNode(evenid, newLit(42))
|
||||
callOdd = callNode(oddid, newLit(42))
|
||||
# rewrite the body of proc node.
|
||||
oddForward[6] = newStmtList()
|
||||
result = quote do:
|
||||
`oddForward`
|
||||
`even`
|
||||
`odd`
|
||||
echo `callEven`
|
||||
echo `callOdd`
|
||||
|
||||
# it works
|
||||
testEvenOdd3()
|
||||
|
||||
# it causes an error (redefinition of odd4), which is correct
|
||||
assert not compiles testEvenOdd4()
|
||||
|
||||
# it caused an error (still forwarded: odd5)
|
||||
testEvenOdd5()
|
||||
|
||||
# it works, because the forward decl and definition share the symbol and the compiler is forgiving here
|
||||
#testEvenOdd6() #Don't test it though, the compiler may become more strict in the future
|
||||
|
||||
|
|
|
|||
|
|
@ -195,3 +195,129 @@ mystate_machine:
|
|||
state_push(S1)
|
||||
echo state_current()
|
||||
state_pop()
|
||||
|
||||
# bug #15075
|
||||
block: #Doesn't work
|
||||
template genGenTempl: untyped =
|
||||
proc loop(locals: int)
|
||||
proc loop(locals: int) = discard
|
||||
genGenTempl()
|
||||
let pool = loop
|
||||
|
||||
block: #Doesn't work
|
||||
macro genGenMacro: untyped =
|
||||
quote do:
|
||||
proc loop(locals: int)
|
||||
proc loop(locals: int) = discard
|
||||
genGenMacro()
|
||||
let pool = loop
|
||||
|
||||
block: #This works
|
||||
proc loop(locals: int)
|
||||
proc loop(locals: int) = discard
|
||||
let pool = loop
|
||||
|
||||
#Now somewhat recursive:
|
||||
type Cont = ref object of RootObj
|
||||
fn*: proc(c: Cont): Cont {.nimcall.}
|
||||
|
||||
block: #Doesn't work
|
||||
template genGenTempl(): untyped =
|
||||
proc loop(locals: Cont): Cont
|
||||
proc loop(locals: Cont): Cont =
|
||||
return Cont(fn: loop)
|
||||
proc doServer(): Cont =
|
||||
return Cont(fn: loop)
|
||||
genGenTempl()
|
||||
discard doServer()
|
||||
|
||||
block: #Doesn't work
|
||||
macro genGenMacro(): untyped =
|
||||
quote:
|
||||
proc loop(locals: Cont): Cont
|
||||
proc loop(locals: Cont): Cont =
|
||||
return Cont(fn: loop)
|
||||
proc doServer(): Cont =
|
||||
return Cont(fn: loop)
|
||||
genGenMacro()
|
||||
discard doServer()
|
||||
|
||||
block: #This works
|
||||
proc loop(locals: Cont): Cont
|
||||
proc loop(locals: Cont): Cont =
|
||||
return Cont(fn: loop)
|
||||
proc doServer(): Cont =
|
||||
return Cont(fn: loop)
|
||||
discard doServer()
|
||||
|
||||
#And fully recursive:
|
||||
block: #Doesn't work
|
||||
template genGenTempl: untyped =
|
||||
proc loop(locals: int)
|
||||
proc loop(locals: int) = loop(locals)
|
||||
genGenTempl()
|
||||
let pool = loop
|
||||
|
||||
block: #Doesn't work
|
||||
macro genGenMacro: untyped =
|
||||
quote do:
|
||||
proc loop(locals: int)
|
||||
proc loop(locals: int) = loop(locals)
|
||||
genGenMacro()
|
||||
let pool = loop
|
||||
|
||||
block: #This works
|
||||
proc loop(locals: int)
|
||||
proc loop(locals: int) = loop(locals)
|
||||
let pool = loop
|
||||
|
||||
block:
|
||||
template genAndCallLoop: untyped =
|
||||
proc loop() {.gensym.}
|
||||
proc loop() {.gensym.} =
|
||||
discard
|
||||
loop()
|
||||
genAndCallLoop
|
||||
|
||||
block: #Fully recursive and gensymmed:
|
||||
template genGenTempl: untyped =
|
||||
proc loop(locals: int) {.gensym.}
|
||||
proc loop(locals: int) {.gensym.} = loop(locals)
|
||||
let pool = loop
|
||||
genGenTempl()
|
||||
|
||||
block: #Make sure gensymmed symbol doesn't overwrite the forward decl
|
||||
proc loop()
|
||||
proc loop() = discard
|
||||
template genAndCallLoop: untyped =
|
||||
proc loop() {.gensym.} =
|
||||
discard
|
||||
loop()
|
||||
genAndCallLoop()
|
||||
|
||||
template genLoopDecl: untyped =
|
||||
proc loop()
|
||||
template genLoopDef: untyped =
|
||||
proc loop() = discard
|
||||
block:
|
||||
genLoopDecl
|
||||
genLoopDef
|
||||
loop()
|
||||
block:
|
||||
proc loop()
|
||||
genLoopDef
|
||||
loop()
|
||||
block:
|
||||
genLoopDecl
|
||||
proc loop() = discard
|
||||
loop()
|
||||
|
||||
block: #Gensymmed sym sharing forward decl
|
||||
macro genGenMacro: untyped =
|
||||
let sym = genSym(nskProc, "loop")
|
||||
nnkStmtList.newTree(
|
||||
newProc(sym, body = newEmptyNode()),
|
||||
newCall(sym),
|
||||
newProc(sym, body = newStmtList()),
|
||||
)
|
||||
genGenMacro
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue