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
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
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
julia> nexprs(5) do k
:(1 + \$k)
end
quote
1 + 1
1 + 2
1 + 3
1 + 4
1 + 5
end
Create 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
julia
ret = Expr(:block)
for i in 1:10
push!(ret.args, :(1 + $i))
end
return ret
you can use expr_map
to do this to save you some typing
julia
expr_map(1:10) do i
:(1 + $i)
end
Renumber 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
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
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))
:x
Remove single block expression
To get better readability, sometimes you want to remove the single block like
julia
begin
x = 1
end
and turn it into
julia
x = 1
rm_single_block
can help you do this.
Flatten block expressions
It can be hard to read if you have a nested block expression like
julia
begin
begin
x = 1
end
y = 2
end
or even more nested, flatten_block
can help you flatten the block expression to make it easier to read.