Trying macro with a typed argument:
import macros
macro m(n:typed):stmt =
echo n.treerepr
proc p(n:NimNode) =
for i in 0..<n.len: n[i].p
if n.kind in CallNodes:
for i in 1..<n.len:
if n[i].kind in AtomicNodes:
n[i] = newCall(bindsym"float",n[i])
n.p
result = n
echo result.treerepr
var a = 1
proc f(x:int) = echo "f_int ",x
proc f(x:float) = echo "f_float ",x
m f a
The compiler errors:
t_typedmacro.nim(16, 5) Error: internal error: genMagicExpr: mFloat
No stack traceback available
To create a stacktrace, rerun compilation with ./koch temp c <file>
I guess f is still the wrong symbol, so I tried the following,
import macros
macro m(n:typed):stmt =
echo n.treerepr
proc p(n:NimNode) =
for i in 0..<n.len: n[i].p
if n.kind in CallNodes:
n[0] = ident($n[0])
for i in 1..<n.len:
if n[i].kind in AtomicNodes:
n[i] = newCall(bindsym"float",n[i])
n.p
result = n
echo result.treerepr
var a = 1
proc f(x:int) = echo "f_int ",x
proc f(x:float) = echo "f_float ",x
m f a
Now the compiler segfaults:
SIGSEGV: Illegal storage access. (Attempt to read from nil?)
I guess the type is not rechecked? It works if I rebuild the call:
import macros
proc c(x:int):float = float(x)
macro m(n:typed):stmt =
echo n.treerepr
proc p(n:NimNode) =
for i in 0..<n.len:
n[i].p
if n.kind in CallNodes:
n[0] = ident($n[0])
for i in 1..<n.len:
if n[i].kind in AtomicNodes:
n[i] = newCall(bindsym"c",n[i])
n.p
result = newCall("f")
for i in 1..<n.len:
result.add n[i]
echo result.treerepr
var a = 1
proc f(x:int) = echo "f_int ",x
proc f(x:float) = echo "f_float ",x
m:
# Try to change it into f(g(a))
# Need the type of a to choose the correct g
f a
With a statementlist
import macros
proc c(x:int):float = float(x)
macro m(n:typed):stmt =
echo n.treerepr
proc p(n:NimNode) =
for i in 0..<n.len:
n[i].p
if n.kind in CallNodes:
n[0] = ident($n[0])
for i in 1..<n.len:
if n[i].kind in AtomicNodes:
n[i] = newCall(bindsym"c",n[i])
proc recall(n:NimNode) =
for i in 0..<n.len:
n[i].recall
if n[i].kind in CallNodes:
var nn = newCall n[i][0]
for j in 1..<n[i].len:
nn.add n[i][j]
n[i] = nn
n.p
n.recall
result = n
echo result.treerepr
var a = 1
proc f(x:int) = echo "f_int ",x
proc f(x:float) = echo "f_float ",x
m:
# Try to change it into f(g(a))
# Need the type of a to choose the correct g
f a
f a
it breaks again:
SIGSEGV: Illegal storage access. (Attempt to read from nil?)
I actually have to rebuild the statementlist for it to work:
import macros
proc c(x:int):float = float(x)
macro m(n:typed):stmt =
echo n.treerepr
proc p(n:NimNode) =
for i in 0..<n.len:
n[i].p
if n.kind in CallNodes:
n[0] = ident($n[0])
for i in 1..<n.len:
if n[i].kind in AtomicNodes:
n[i] = newCall(bindsym"c",n[i])
proc recall(n:NimNode) =
for i in 0..<n.len:
n[i].recall
if n[i].kind in CallNodes:
var nn = newCall n[i][0]
for j in 1..<n[i].len:
nn.add n[i][j]
n[i] = nn
n.p
n.recall
result = newstmtlist()
for i in 0..<n.len: result.add n[i]
echo result.treerepr
var a = 1
proc f(x:int) = echo "f_int ",x
proc f(x:float) = echo "f_float ",x
m:
# Try to change it into f(g(a))
# Need the type of a to choose the correct g
f a
f a
This seems to be a very contrived way of doing it. What is the standard practice of dealing with macros of typed arguments?
One more question: what does the return type of a macro mean? It doesn't seem to change anything, if I change it to typed or untyped.
These all work or produce sensible error messages for me on devel.
what does the return type of a macro mean?
It's checked that the produced AST is of the specified type, but indeed typed or untyped doesn't make a difference.
Tried the devel branch. Now my second try works already. This means the only thing one need to do is to replace the looked up symbol of the function with an identifier and the compiler in the devel branch can correct type check/symbol look up the whole statement again.
That's fantastic! Do you have a planned date for the next release?