I had asked and posted a pragma/macro to handle this a few years ago here, but stupidly didn't save it and can't find it anymore. Does there happen to be a feature I'm not finding in Nim 1.x+ that handles this?
desired:
proc somefn(input:int):int {.intAs: int32.}:
var s = [1,3,5]
let n = 8
result = s[2] + n
would make all the int and literal ints compile as int32.
Things I've tried as quick solutions:
import std/macros
macro intAs(asI, body: untyped): untyped =
let asI = copyNimNode(asI)
proc aux(node: NimNode): NimNode =
case node.kind:
of nnkIntLit: result = newCall(asI, node)
of AtomicNodes - {nnkIntLit}: result = node
else:
result = newTree(node.kind)
for sub in items(node):
result.add aux(sub)
result = aux(body)
echo result.repr
proc somefn(input:int):int {.intAs: int32.} =
var s = [1,3,5]
let n = 8
result = s[2] + n
rewrites to
proc somefn(input: int): int =
var s = [int32(1), int32(3), int32(5)]
let n = int32(8)
result = s[int32(2)] + n
Wow, you are fast! I was not looking forward to figuring out how to macro that again. Thank you for mocking that up and sharing.
Same curious question as @shirleyquirk, why is copyNimNode necessary? I see that the macro asI evaluated to nil later if it's not used.
I think the problem lies in capturing asI in a recursive proc. Not sure if the VM can handle that or if it's supposed to. I generally avoid writing procs that depend on captured variables in macros. You can work around this by rearranging the code like so:
import std/macros
proc aux(node, asI: NimNode): NimNode =
case node.kind:
of nnkIntLit: result = newCall(asI, node)
of AtomicNodes - {nnkIntLit}: result = node
else:
result = newTree(node.kind)
for sub in items(node):
result.add aux(sub, asI)
macro intAs(asI, body: untyped): untyped =
result = aux(body, asI)
echo result.repr
proc somefn(input: int): int {.intAs: int32.} =
var s = [1,3,5]
let n = 8
result = s[2] + n