I would like to quote expressions, but evaluate some Symbols (which ones? see below). It should be possible to accomplish this using macros. I’ve tried to give an idea below of what I’m after:
"""
e.g.
```julia
julia> eval(uneval(Expr(:my_call, :arg1, :arg2)))
:($(Expr(:my_call, :arg1, :arg2)))
julia> eval(eval(uneval(:(sqrt(9)))))
3.0
```
"""
function uneval(x::Expr)
# the `Expr` below is assumed to be available in the scope and to be `Base.Expr`
:(Expr($(uneval(x.head)), $(map(uneval, x.args)...)))
end
# tangential TODO: determine which one
uneval(x) = Meta.quot(x)
# uneval(x) = Meta.QuoteNode(x)
"""
e.g.
julia> dump(let x = 9
@xquote sqrt(x)
end)
Expr
head: Symbol call
args: Array{Any}((2,))
1: sqrt (function of type typeof(sqrt))
2: Int64 9
"""
macro xquote(ex)
uneval(ex) # TODO escape `::Symbol` in `args`.
end
The current behavior is
julia> dump(let x = 9
@xquote sqrt(x)
end)
Expr
head: Symbol call
args: Array{Any}((2,))
1: Symbol sqrt
2: Symbol x
but I would like the output to be what I wrote in the docstring for @xquote. For this particular expression, the following definition produces the desired output:
macro xquote_sqrt9(ex)
uneval(Expr(:call, sqrt, 9))
endI
as does explicitly quoting:
julia> dump(let x = 9
:($(sqrt)($x))
end)
Expr
head: Symbol call
args: Array{Any}((2,))
1: sqrt (function of type typeof(sqrt))
2: Int64 9
I’ve played around with f(x) = esc(x), and f(x) = Expr(:$, x) in
escape_all_symbols(ex) = MacroTools.postwalk(x -> x isa Symbol ? f(x) : x, ex), but I’m a bit lost about how to move forward.
I think this is tangential to my question, but I won’t be evaluating every single Symbol. Specifically, I would not evaluate Symbols that correspond to function arguments. For example, currently:
julia> dump(let x = 9
@xquote y -> x + y
end)
Expr
head: Symbol ->
args: Array{Any}((2,))
1: Symbol y
2: Expr
head: Symbol block
args: Array{Any}((2,))
1: LineNumberNode
line: Int64 2
file: Symbol REPL[125]
2: Expr
head: Symbol call
args: Array{Any}((3,))
1: Symbol +
2: Symbol x
3: Symbol y
And in my desired output, Symbol + and Symbol x would be evaluated, but Symbol y would not be. I think I’ve got that aspect covered, however, and it would be enough for my purposes to see a definition of @xquote where, for example every Symbol except for :y is evaluated.