ExprManipulation provides tools for manipulating expressions based on the Expr syntax.
The API is small there are only 4 constructs MExpr
, Capture
, Slurp
and transform
.
using ExprManipulation
using Base.Meta: show_sexpr
expr = :(x + 1)
show_sexpr(expr)
# (:call, :+, :x, 1)
A MExpr can be used to test equality
m_expr = MExpr(:call, :+, Capture(:x), Capture(:n))
m_expr == expr
#true
You can extract the the captured arguments with match
, if the expressions aren't equal match
will return nothing
match(m_expr, expr)
#(x = :x, n = 1)
Slurp
allows you to capture a variable number of arguments. It can be used anywhere in the expressions args but only a single Slurp
per an MExpr
.
m_expr = MExpr(:tuple, Capture(:first_number), Slurp(:args), Capture(:last_number))
match(m_expr, :(1,2,3,4,5))
# (first_number = 1, args = Any[2, 3, 4], last_number = 5)
Both Capture
and Slurp
can take a function to test equality.
head = Capture(:head) do arg
arg in (:vect, :tuple)
end
slurp_numbers = Slurp(:numbers) do args::Array
all(map(x -> x isa Number, args))
end
vec_or_tuple = MExpr(head, slurp_numbers)
match(vec_or_tuple, :((1,2,3)))
# (head = :tuple, numbers = [1, 2, 3])
match(vec_or_tuple, :((1,"2",3)))
# nothing
Transform can be used to create a new expression, it applies a function to each node in the Expr tree starting from the leaves. For example to replace all the numbers with 1.
transform(input_expr) do node
node isa Number ? 1 : node
end
# :(1 + (1 ^ 1) * 1)
For more in-depth examples see the examples folder.
Other packages you may find usefull for handling Exprs
- ExprTools
- MacroTools
- MLStyle