Thanks for the hint, after a few hours breaking my teeth on it I got something
working but it's really ugly:
var interruptProcedures: array[32, uint64]
macro interproc() =
result = newStmtList()
for iv in 0..<32:
let wrapperName = if iv in erroringVectors: "errorInterruptWrapper"
else: "genericInterruptWrapper"
let name = ident("vectorPusher" & $iv)
let vector = newLit(iv)
let wrapper = ident(wrapperName)
let asmCode =
newNimNode(nnkAsmStmt).add(newEmptyNode()).add(newLit("pushq " & $iv & ";jmp "
& wrapperName))
result.add quote do:
proc `name`() {.exportc, asmNoStackFrame.} =
`asmCode`
interruptProcedures[`vector`] = cast[uint64](`name`)
return result
interproc()
Run
I couldn't figure out how to use quote effectively.
In one of my many attempts I tried this:
macro foobar() =
let myLiteral = newLit("push %rax")
result = quote do:
proc foo() =
asm `myLiteral`
Run
Which returns the following error: `/usercode/in.nim(9, 11) Error: the 'asm'
statement takes a string literal` I don't know if it's a bug or a known
limitation.
I also found this post: <https://forum.nim-lang.org/t/8279> which was very
useful in finding out what root node I should be using.
I feel like this would be a great additional example for this tutorial
<https://nim-lang.org/docs/tut3.html> since it shows looping in macros,
defining proc names dynamically, building statements iteratively, and using
ident and newLit. All of which are a bit obscure currently, from my perspective
as a beginner.
Something like:
import macros
macro createProcedures() =
result = newStmtList()
for i in 0..<10:
let name = ident("myProc" & $i)
let content = newLit("I am procedure number #" & $i)
result.add quote do:
proc `name`() {.exportc.} =
echo `content`
return result
createProcedures()
myProc7()
Run