I created a new package Expronicon.jl to wrap up some meta-programming tools on Julia’s Expr
I wrote in the past year using MLStyle The goal of Expronicon is to serve as a stdlib for MLStyle for meta programming Julia Expr
This package provides a few tools as following
Syntax Types
In many other meta programming packages, such as MacroTools, ExprTools etc. one often use a function called split_function
to split function components into a Dict
for easy manipulation and construction, Expronicon moves one step further, it defines several more types for easy manipulation:
JLFunction
: similar to what generated bysplit_function
but is a Julia struct, this allows pretty printing and method dispatches:
JLStruct
: represents a normal Julia struct syntax
JLKwStruct
: represents keyword struct syntax (similar toJLStruct
)
JLIfElse
: represent Julia ifelse statements, this uses a dictionary to store conditions and their corresponding code block
Construct JLIfElse object
One can construct an ifelse
as following
julia> jl = JLIfElse()
nothing
julia> jl.map[:(foo(x))] = :(x = 1 + 1)
:(x = 1 + 1)
julia> jl.map[:(goo(x))] = :(y = 1 + 2)
:(y = 1 + 2)
julia> jl.otherwise = :(error("abc"))
:(error("abc"))
julia> jl
if foo(x)
x = 1 + 1
elseif goo(x)
y = 1 + 2
else
error("abc")
end
Generate the Julia Expr
object
to generate the corresponding Expr
object, one can call codegen_ast
.
julia> codegen_ast(jl)
:(if foo(x)
x = 1 + 1
elseif goo(x)
y = 1 + 2
else
error("abc")
end)
JLMatch
JLMatch
describes a Julia pattern match expression defined by
MLStyle
. It allows
one to construct such expression by simply assign each code block
to the corresponding pattern expression.
Example
One can construct a MLStyle
pattern matching expression
easily by assigning the corresponding pattern and its result
to the map
field.
julia> jl = JLMatch(:x)
#= line 0 =#
nothing
julia> jl = JLMatch(:x)
#= line 0 =#
nothing
julia> jl.map[1] = true
true
julia> jl.map[2] = :(sin(x))
:(sin(x))
julia> jl
#= line 0 =#
@match x begin
1 => true
2 => sin(x)
_ => nothing
end
to generate the corresponding Julia Expr
object, one can call codegen_ast
.
julia> codegen_ast(jl)
:(let
true
var"##return#263" = nothing
var"##265" = x
if var"##265" isa Int64
#= line 0 =#
if var"##265" === 1
var"##return#263" = let
true
end
#= unused:1 =# @goto var"####final#264#266"
end
#= line 0 =#
if var"##265" === 2
var"##return#263" = let
sin(x)
end
#= unused:1 =# @goto var"####final#264#266"
end
end
#= line 0 =#
begin
var"##return#263" = let
nothing
end
#= unused:1 =# @goto var"####final#264#266"
end
(error)("matching non-exhaustive, at #= line 0 =#")
#= unused:1 =# @label var"####final#264#266"
var"##return#263"
end)
Others
other features include transformations, analysis path, pretty printings etc.