I’ve got 2 functionally equivalent, but different results for Expr and quote approaches respectively:
immutable Oo
field::Int
end
and
begin # console, line 2
immutable Oo # console, line 3
field::Int
end
end
The quote approach for some reason generates additional line comments, and wraps the type in begin ... end block. Question: is it possible to get rid of this redundant info?
Those are not comments, but line number info necessary to generate the debug info. You can just ignore them when you are processing the AST. If you are writing a macro or otherwise transforming the AST before evaluting it or passing it to the compiler, you should keep the line number nodes whenever possible. If you remove them, it’ll be impossible to generate correct line numbers in the code you generate.
julia> function filter_lineno(ex::Expr)
filter!(ex.args) do e
isa(e, LineNumberNode) && return false
if isa(e, Expr)
(e::Expr).head === :line && return false
filter_lineno(e::Expr)
end
return true
end
return ex
end
filter_lineno (generic function with 1 method)
julia> macro m1(ex::Expr)
esc(filter_lineno(ex))
end
@m1 (macro with 1 method)
julia> macro m2(ex::Expr)
esc(ex)
end
@m2 (macro with 1 method)
julia> @m1 function f()
error()
end
f (generic function with 1 method)
julia> @m2 function f2()
error()
end
f2 (generic function with 1 method)
julia> f()
ERROR:
in f() at ./<missing>:0
julia> f2()
ERROR:
in f2() at ./REPL[5]:2
Ah, actually this is that unlikely case, when code needs to be generated and saved to a file (I need to follow up some generated structures).
I thought that there might be some flag, which disables this behavior, but filter_lineno solves the problem, thanks! Btw, why do you use esc(), isn’t it redundant?
It might still be useful to keep those node in case you ever need to map the generated file back to the source. In any case, the list above should give you the kind of nodes to ignore.
It is necessary. I general, you must use esc in a macro on user code that you treat as black box (or anything you generate that should reference caller context in general). Of course you don’t need it if you are generating a file.