After consulting the code for @eval
, it only takes a small tweak to add interpolation to @sexpr
.
The macro is now
macro sexpr(expr)
let transform = postwalk(sexpr_walk, expr)
return Expr(:escape, Expr(:quote, transform))
end
end
So that this works:
julia> a = [1,2,3]
3-element Vector{Int64}:
1
2
3
julia> @sexpr (call, +, $(a[2]), 5)
:(2 + 5)
With this a sort of hybrid of the two suggestions can be written as follows:
macro dispatchinstruction(_inst, _vm)
let inst = esc(_inst), vm = esc(_vm)
conditions = [:(inst.op == $op) for op in instances(Opcode)]
actions = [:($(Symbol("on"*string(op)))($inst, $vm)) for op in instances(Opcode)]
ifdef = @sexpr (:if, $(conditions[1]), $(actions[1]))
list = ifdef
for i in 2:lastindex(conditions)
local e = @sexpr (:elseif, $(conditions[i]), $(actions[i]))
cons(list, e)
list = e
end
return ifdef
end
end
Admittedly, in this particular macro, the interpolations make using @sexr
a bit noisier than using Expr
directly, but that wouldn’t always be true. Besides, this was an experiment to see if I could get it to work.
The “Lisp Maximalist” way to write the loop would be
cons(list, @sexpr (:elseif, $(conditions[i]), $(actions[i])))
list = cdr(list)
But that doesn’t work because Exprs aren’t actually made up of cons cells. Which is fine, there’s no reason they should be.
I think this is still (barely) topical for “better way to write this macro”, but it’s drifting toward the edge, so this is a good place for me to call it quits. Thanks again, to those of you who contributed to the answer.