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.splitdefFunction
splitdef(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

source
MacroTools.combinedefFunction
combinedef(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)
source
MacroTools.splitargFunction
splitarg(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

source

Other Utilities

MacroTools.@qMacro
@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

source
MacroTools.@qqMacro
@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

source
MacroTools.isexprFunction
isexpr(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.

source
MacroTools.rmlinesFunction
rmlines(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

source
MacroTools.unblockFunction
unblock(expr)

Remove outer begin blocks from an expression, if the block is redundant (i.e. contains only a single expression).

source
MacroTools.namifyFunction

An easy way to get the (function/type) name out of expressions like foo{T} or Bar{T} <: Vector{T}.

source
MacroTools.inexprFunction
inexpr(expr, x)

Simple expression match; will return true if the expression x can be found inside expr.

inexpr(:(2+2), 2) == true
source
MacroTools.gensym_idsFunction
gensym_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)
source
MacroTools.alias_gensymsFunction
alias_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)
source
MacroTools.isdefFunction

Test for function definition expressions. function f end and anonymous functions are considered as function definitions and return true.

source
MacroTools.flattenFunction
flatten(ex)

Flatten any redundant blocks into a single block, over the whole expression.

source