Transformations
The code transformation is the key process of meta programming. Expronicon also provides a set of functions to help you make your own transformations.
Substitution
We provide a Substitute type to help you make substitution, first you can create a Substitute object with a function that describes what should be substituted
julia> sub = Substitute() do expr
expr isa Symbol && expr in [:x] && return true
return false
end;then you can call this object with another function describes what to substitute with if matched.
julia> sub(_->1, :(x + y))
:(1 + y)Create similar expressions using nexprs
It is common that one wants to create a block of similar expressions, for example you want to unroll a loop program manually, nexprs can help you here
julia> nexprs(5) do k
:(1 + \$k)
end
quote
1 + 1
1 + 2
1 + 3
1 + 4
1 + 5
endCreate large code blocks using expr_map
It is common that one wants to create a Expr(:block) with a large number of expressions and each expression is created based on different conditions, instead of writing
ret = Expr(:block)
for i in 1:10
push!(ret.args, :(1 + $i))
end
return retyou can use expr_map to do this to save you some typing
expr_map(1:10) do i
:(1 + $i)
endRenumber gensyms
Renumber gensyms to have a more deterministic output is very useful when writing expression related tests, renumber_gensym can help you do this by renumber gensym by recounting the number of gensyms in given expression (usually a function body)
julia> renumber_gensym(:(function f()
$(gensym(:x)) = 1
$(gensym(:x)) = 2
end))
:(function f()
#= REPL[3]:1 =#
#= REPL[3]:2 =#
var"##x#1" = 1
#= REPL[3]:3 =#
var"##x#2" = 2
end)Aliasing gensyms
Sometimes you want to alias a gensym to a name for better readability, this idea is borrowed originally from the MacroTools package, alias_gensym will remove #<name>#<id> like gensym with <name>_<id>.
Remove annotations
Sometimes you want to remove type annotations from an expression, rm_annotations can help you do this. It will remove the type annotations from the expression.
Only give me the names
It is quite often that you only want the names of the variables in an expression, name_only will remove everything else but a Symbol.
julia> using Expronicon
julia> name_only(:(sin(2)))
:sin
julia> name_only(:(Foo{Int}))
:Foo
julia> name_only(:(Foo{Int} <: Real))
:Foo
julia> name_only(:(x::Int))
:xRemove single block expression
To get better readability, sometimes you want to remove the single block like
begin
x = 1
endand turn it into
x = 1rm_single_block can help you do this.
Flatten block expressions
It can be hard to read if you have a nested block expression like
begin
begin
x = 1
end
y = 2
endor even more nested, flatten_block can help you flatten the block expression to make it easier to read.