Utilities
Function definitions
Function definitions pose a problem to pattern matching, since there are a lot of different ways to define a function. For example, a pattern that captures f(x) = 2x
will not match the following syntax:
function f(x)
return 2x
end
There are a couple of ways to handle this. One way is to use longdef
or shortdef
to normalise function definitions to short form, before matching it.
julia> ex = :(function f(x) 2x end)
:(function f(x)
#= none:1 =#
2x
end)
julia> MacroTools.shortdef(ex)
:(f(x) = begin
#= none:1 =#
2x
end)
More generally it's also possible to use splitdef
and combinedef
to handle the full range of function syntax.
MacroTools.splitdef
— Functionsplitdef(fdef)
Match any function definition
function name{params}(args; kwargs)::rtype where {whereparams}
body
end
and return Dict(:name=>..., :args=>..., etc.)
. The definition can be rebuilt by calling MacroTools.combinedef(dict)
.
See also: combinedef
MacroTools.combinedef
— Functioncombinedef(dict::Dict)
combinedef
is the inverse of splitdef
. It takes a splitdef
-like Dict and returns a function definition.
This function approximately does the following (but more sophisticated to avoid emitting parts that did not actually appear in the original function definition.)
rtype = get(dict, :rtype, :Any)
all_params = [get(dict, :params, [])..., get(dict, :whereparams, [])...]
:(function $(dict[:name]){$(all_params...)}($(dict[:args]...);
$(dict[:kwargs]...))::$rtype
$(dict[:body])
end)
MacroTools.splitarg
— Functionsplitarg(arg)
Match function arguments (whether from a definition or a function call) such as x::Int=2
and return (arg_name, arg_type, is_splat, default)
. arg_name
and default
are nothing
when they are absent. For example:
julia> map(splitarg, (:(f(a=2, x::Int=nothing, y, args...))).args[2:end])
4-element Array{Tuple{Symbol,Symbol,Bool,Any},1}:
(:a, :Any, false, 2)
(:x, :Int, false, :nothing)
(:y, :Any, false, nothing)
(:args, :Any, true, nothing)
See also: combinearg
MacroTools.combinearg
— Functioncombinearg(arg_name, arg_type, is_splat, default)
combinearg
is the inverse of splitarg
.
Other Utilities
MacroTools.@q
— Macro@q [expression]
Like the quote
keyword but doesn't insert line numbers from the construction site. e.g. compare @q begin end
with quote end
. Line numbers of interpolated expressions are preserverd.
See also: rmlines
MacroTools.@qq
— Macro@qq [expression]
Like the quote
keyword but replace construction site line numbers with source. Line numbers of interpolated expressions are preserved. The result is that line numbers will be attributed to the macro usage site, instead of the macro source code.
Only works inside of a macro definition.
See also: @q
MacroTools.isexpr
— Functionisexpr(x, ts...)
Convenient way to test the type of a Julia expression. Expression heads and types are supported, so for example you can call
isexpr(expr, String, :string)
to pick up on all string-like expressions.
MacroTools.rmlines
— Functionrmlines(x)
Remove the line nodes from a block or array of expressions.
Compare quote end
vs rmlines(quote end)
Examples
To work with nested blocks:
prewalk(rmlines, ex)
See also: @q
MacroTools.unblock
— Functionunblock(expr)
Remove outer begin
blocks from an expression, if the block is redundant (i.e. contains only a single expression).
MacroTools.namify
— FunctionAn easy way to get the (function/type) name out of expressions like foo{T}
or Bar{T} <: Vector{T}
.
MacroTools.inexpr
— Functioninexpr(expr, x)
Simple expression match; will return true
if the expression x
can be found inside expr
.
inexpr(:(2+2), 2) == true
MacroTools.gensym_ids
— Functiongensym_ids(expr)
Replaces gensyms with unique ids (deterministically).
julia> x, y = gensym("x"), gensym("y")
(Symbol("##x#363"), Symbol("##y#364"))
julia> MacroTools.gensym_ids(:($x+$y))
:(x_1 + y_2)
MacroTools.alias_gensyms
— Functionalias_gensyms(expr)
Replaces gensyms with animal names. This makes gensym'd code far easier to follow.
julia> x, y = gensym("x"), gensym("y")
(Symbol("##x#363"), Symbol("##y#364"))
julia> MacroTools.alias_gensyms(:($x+$y))
:(porcupine + gull)
MacroTools.@expand
— MacroMore convenient macro expansion, e.g.
@expand @time foo()
MacroTools.isdef
— FunctionTest for function definition expressions. function f end
and anonymous functions are considered as function definitions and return true.
MacroTools.flatten
— Functionflatten(ex)
Flatten any redundant blocks into a single block, over the whole expression.
MacroTools.prettify
— Functionprettify(ex)
Makes generated code generaly nicer to look at.