I would like to quote expressions, but evaluate some Symbol
s (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 Symbol
s 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.