Hi,
I am trying to learn to work with macros and ASTs, but am running into a bit of confusion regarding escaping. I haven’t found a lot of documentation regarding this, but if there is an authorative source, I would appreciate any pointers.
I wrote some example code which looks similar to this:
function op_helper(ee::Expr)
...
end
macro op(ee::Expr)
$(op_helper(ee))
end
Inside of op_helper
, I recursively walk the AST and do some very simple transformations (I am effectively trying to just return identity) on the expressions.
I am running into an interesting conundrum, which is challenging my understanding of esc
in recursive contexts.
Consider the following test function:
function test(a)
x = @op a + 1 #1
@op y = a + 2 #2
@op begin #3
z = a + 3 #4
end
end
I am finding the following:
- is straightforward, and my code simply recursively traverses the AST, only escaping
# ...
if typeof(ee) == Symbol
esc(ee)
elseif #...
- Seems only a little bit more work is required (note for simplicity, I’m not recursing on the LHS)
if typeof(ee) == Expr && ee.head == :(=)
esc(:($(ee.args[1]) = $(op_helper(ee.args[2])))
elseif #...
- It is this case which is intriguing.
if typeof(ee) == Expr && ee.head == :block
parts = [op_helper(elem) for elem in ee.args]
Expr(:block, parts...) #5
elseif #...
It appears that for this to work, I actually need to write esc(Expr(:block, parts...))
in #5; however, this then causes problems with #4, which now doesn’t want to be escaped, unlike the recursive code path for #2.
Is what I’m describing correct, or am I missing something?
Thank you,
Tom