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
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) = $(op_helper(ee.args))) 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?