-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
[Macro] NimNode of Forward (Prototype) Procedure Defined with quote
Cause Error
#13484
Comments
|
import macros
proc defForwardQuo(id: NimNode): NimNode =
result = quote do:
proc `id`(n: int): bool
proc defForwardNew(id: NimNode): NimNode =
result = newProc(id, @[newIdentNode("bool"), newIdentDefs(ident("n"), ident("int"))])
proc defEven(evenid, oddid: NimNode): NimNode =
result = quote do:
proc `evenid`(n: int): bool =
if n == 0:
return true
else:
return `oddid`(n - 1)
proc defOdd(evenid, oddid: NimNode): NimNode =
result = quote do:
proc `oddid`(n: int): bool =
if n == 0:
return false
else:
return `evenid`(n - 1)
proc call(id, param: NimNode): NimNode =
result = quote do:
`id`(`param`)
macro testEvenOdd(): untyped =
let
evenid = genSym(nskProc)
oddid = genSym(nskProc)
oddForwardNew = defForwardNew(oddid)
oddForwardQuo = defForwardQuo(oddid)
even = defEven(evenid, oddid)
odd = defOdd(evenid, oddid)
callEven42 = call(evenid, newLit(42))
callOdd42 = call(oddid, newLit(42))
result = quote do:
`oddForwardNew`
`even`
`odd`
echo `callEven42`
echo `callOdd42`
testEvenOdd() Although this succeeds, when I use @krux02 What is the difference between "definition with an empty body" and "forward declaration"? |
Look at this. The forward declaration as an empty node at the end. If it does not have a empty node the declaration is a definition. Having two identical definitions should raise a compilation error. import macros
dumpTree:
proc foo()
proc foo() =
discard |
@krux02 import macros
macro showNewProc(): untyped =
let
id = genSym(nskProc)
prams = @[newIdentNode("bool")]
# should be newProc(id, prams, body=newEmptyNode())
procNode = newProc(id, prams)
echo procNode.treeRepr
showNewProc() returns:
|
That is exactly what I mean. |
I think the body of a forward declaration should be an empty StmtList instead of an EmptyNode. It is the same as my previous example except import macros
proc defForwardQuo(id: NimNode): NimNode =
result = quote do:
proc `id`(n: int): bool
proc defForwardNew(id: NimNode): NimNode =
result = newProc(id, @[newIdentNode("bool"), newIdentDefs(ident("n"), ident("int"))], body=newEmptyNode())
proc defEven(evenid, oddid: NimNode): NimNode =
result = quote do:
proc `evenid`(n: int): bool =
if n == 0:
return true
else:
return `oddid`(n - 1)
proc defOdd(evenid, oddid: NimNode): NimNode =
result = quote do:
proc `oddid`(n: int): bool =
if n == 0:
return false
else:
return `evenid`(n - 1)
proc call(id, param: NimNode): NimNode =
result = quote do:
`id`(`param`)
macro testEvenOdd(): untyped =
let
evenid = genSym(nskProc)
oddid = genSym(nskProc)
oddForwardNew = defForwardNew(oddid)
oddForwardQuo = defForwardQuo(oddid)
even = defEven(evenid, oddid)
odd = defOdd(evenid, oddid)
callEven42 = call(evenid, newLit(42))
callOdd42 = call(oddid, newLit(42))
result = quote do:
`oddForwardNew`
`even`
`odd`
echo `callEven42`
echo `callOdd42`
testEvenOdd() the compiler issues an error the same as the first (when it issue is opened) example.
and the following causes no error. macro testEvenOdd2(): untyped =
let
evenid = genSym(nskProc)
oddid = genSym(nskProc)
oddForwardNew = defForwardNew(oddid)
oddForwardQuo = defForwardQuo(oddid)
even = defEven(evenid, oddid)
odd = defOdd(evenid, oddid)
callEven42 = call(evenid, newLit(42))
callOdd42 = call(oddid, newLit(42))
# oddForwardQuo[6] is the body of the procedure.
oddForwardQuo[6] = newStmtList()
result = quote do:
`oddForwardQuo`
`even`
`odd`
echo `callEven42`
echo `callOdd42` |
The same problem is seen in |
Not really. How do you think the compiler distinguishes a forward declaration from an implementation that does nothing. It is not the discard statement, that one is only required for the parser. import macros
dumpTree:
proc foo()
proc foo() =
discard |
Sorry @krux02, you are right. To detail, see the following example. import macros
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)
# testEvenOdd4()
# it causes an error (still forwarded: odd5)
# testEvenOdd5()
# it works
testEvenOdd6() The results are the same if proc defForward(id, nid: NimNode): NimNode =
result = quote do:
proc `id`(`nid`: int): bool |
* 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
) * 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 nim-lang#13484
When we use the forward procedure defined with
quote
, compiler issues following error.Example
Current Output
and the result of
./koch temp c test.nim
is as followingExpected Output
Possible Solution
I have no idea.
Additional Information
and
The text was updated successfully, but these errors were encountered: