Code generation: unnecessary comment lines when using "quote"

Trying to generate a type in 2 ways:

Expr(:type, false, :Oo, Expr(:block, :(field::Int)))

and

quote
  immutable Oo
    field::Int
  end
end

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?

What version of Julia are you using?

To get rid of the wrapping, try:

:(
  immutable Oo
    field::Int
  end
)
1 Like

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
1 Like

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.