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.