API
General Utilities
MacroUtilities.@assert_type — Macro@assert_type var typesEnsures that typeof(var) is in the list of provided types.
types can be either a single type or a tuple or vect expression of types
MacroUtilities.@unpack_option — Macro@unpack_option [should_throw=false] options unpack_exprUnpacks a value from options depending on the form of unpack_expr.
If unpack_expr is of the form name, with name::Symbol, then this macro is equivalent to writing
$name = options[$name]If should_throw == true, throws an ArgumentError if options does not contain key $name.
Otherwise, returns an ArgumentError from the current function if options does not contain key $name.
If unpack_expr is of the form
name::T, thenoptions[$name]must be of typeTor anArgumentErrorwill be returnedname::Union{T1, T2, ..., Tn}, thenoptions[$name]must be of typeT1, T2, ...,orTnname = default, thendefault_valuewill be used if$nameis not present inoptionsname => new_name, is the equivalent to$new_name = options[$name]
An unpack_expr of the form (name => new_name)::T, name::T = default or name::Union{T1, T2, ..., Tn} = default, etc., also behaves as expected.
MacroUtilities.@method_def_constant — Macro@method_def_constant [ValType=Val] [map_expr] method_call get_constant_methodGiven a method_call expression of the form f(::Type{T1}, ::Type{T2}, ..., ::Type{Ti}, ::ValType{::S}, ::Type{Ti+1}, ..., ::Type{Tn}), generates a method definition for get_constant_method which returns an iterable with element type S of all of the compile-time constants contained in the ValType parameter of each definition of f.
get_constant_method is a generated function and thus incurs no runtime overhead, but also contains backedges to each method instance of f, and so the output is recompiled when a new method definition of f is added.
ValType must be a singleton type with a single parameter. Define MacroUtilities.inner_param to extract the innermost type parameter for your own custom types.
If map_expr is provided, it must resolve to a function mapping the collection of constants of type Vector{S} to a Expr. Defaults to MacroUtilities.default_extract_const_expr. (Requires at least Julia 1.7)
Keyword Arg Parsing
MacroUtilities.@parse_kwargs — Macro@parse_kwargs [args] kwarg_specParses the set of keyword expressions given in args according to a series of kwarg_spec specification and sets the corresponding keys in the calling scope. Returns a Vector of the expressions that were not parsed as keyword arguments.
kwarg_spec must be a block Expr, with each line consisting of an expression of the form
key = (expected_type = T)which specifies that for a key-value expression in args of the form key = value, value must have type T.
An alternative form is
key = (expected_types = (T1, T2, ..., Tn))which specifies that a key-value expression in args with key = value must have typeof(value) in (T1, T2, ..., Tn)
If the default key is provided, e.g.,
key = (expected_types = (T1, T2, ..., Tn), default=default_value)then key is set to default_value if args do not contain a key = value expression.
If the default key is not provided, then args must contain a key = value expression or an ArgumentError will be thrown.
An alternative, more compact, form to the above expressions is
key::Union{T1, T2, ..., Tn} = default_valueNote: If key::Symbol is provided as part of kwarg_spec, the expression key in args is treated as key=key) (i.e., akin to the usual kwarg syntax f(; key)).
Examples
julia> macro a(args...)
@parse_kwargs args... begin
a1::Union{Int, Symbol, Expr}
a2::Union{String, Nothing}
a3::Bool = false
end
quote
b1 = $a1
b2 = $a2
b3 = $a3
(; b1, b2, b3)
end |> esc
end
@a (macro with 1 method)
julia> let
a1 = 1
@a a1 a2="b2"
end
(b1 = 1, b2 = "b2", b3 = false)
julia> let
@a a2="b2"
end
ERROR: LoadError: ArgumentError: No value provided for key `a1`
[...]Syntax Parsing
General
MacroUtilities.from_expr — Functionfrom_expr(::Type{T}, expr; throw_error::Bool=false, kwargs...)Parses an expr into an object of type T
The provided kwargs are passed to the underlying parsing function.
If expr cannot be parsed into an object of type T - if throw_error == true, throws an ArgumentError - otherwise, returns nothing
====================
from_expr(::Type{Vector{T}}, expr::Expr; throw_error::Bool=false)Parses a tuple or vect expr as a Vector{T}. Each argument of expr must be of type T
====================
from_expr(::Type{Vector{T}}, input::T; throw_error::Bool=false)Returns a singleton Vector{T} containing input
====================
from_expr(::Type{FuncCall}, expr; normalize_kwargs::Bool=false)Returns a parsed FuncCall from expr
If normalize_kwargs = true, trailing equality expressions (e.g., f(a, b, c=1) will be parsed as keyword arguments.
MacroUtilities.to_expr — Functionto_expr(x) -> ExprConverts x to an Expr representation
MacroUtilities.NotProvided — TypeNotProvidedPlaceholder type to represent the absence of a field.
MacroUtilities.is_not_provided — Functionis_not_provided(x) -> BoolReturns true if the field corresponding to x is not provided, false otherwise.
MacroUtilities.is_provided — Functionis_provided(d) -> BoolReturns true if the field corresponding to x is provided, false otherwise.
MacroUtilities.@return_if_exception — Macro@return_if_exception(ex)Evalutes the destructured assignment expression ex of the form (; names...) = rhs or (names...) = rhs and returns from the current function if rhs returns an Exception
Basic Expression Types
MacroUtilities.NamedTupleArg — TypeNamedTupleArg(; key::Symbol, value=not_provided, is_splat::Bool=false, kw_head::Bool)
NamedTupleArg(key::Symbol; kw_head::Bool)Matches a key = value or a key argument inside a NamedTuple expression
If kw_head == true, the expression head is set to :kw, otherwise :(=)
MacroUtilities.NamedTupleArg — MethodNamedTupleArg(f::NamedTupleArg; [key::Symbol], [value], [is_splat::Bool], [kw_head])Returns a new copy of f, with optional name, type, value, or is_splat overridden by the keyword arguments.
MacroUtilities.NamedTupleExpr — TypeNamedTupleExpr(args::Vector{NamedTupleArg})
NamedTupleExpr(; args::Vector{NamedTupleArg})Matches a (named) tuple expression
The keys and values of this expression can be accessed, modified, and queried with Base.getindex, Base.setindex!, Base.iterate, Base.findfirst, Base.keys, Base.haskey, Base.length, Base.pop!, and Base.push!
MacroUtilities.NamedTupleExpr — MethodNamedTupleExpr(names::Vector{Symbol}; kw_head::Bool=false)Returns a NamedTupleExpr built from names.
If kw_head == true, this expression is of the form (; names...), and otherwise it is of the form (names...)
MacroUtilities.TypeVarExpr — TypeTypeVarExpr <: AbstractExprMatches expressions of the form
typenametypename <: UB<: UBtypename >: LB>: LBLB <: typename <: UB
Constructors
TypeVarExpr{LB, UB}(; typename::Symbol, lb::Union{LB, NotProvided}=not_provided, ub::Union{UB, NotProvided}=not_provided)
TypeVarExpr(typename::Symbol, [lb], [ub])
TypeVarExpr{LB, UB}(t::TypeVarExpr)MacroUtilities.CurlyExpr — TypeCurlyExpr{FirstArg, E} <: AbstractExprMatches an expression of the form FirstArg{args...}, if FirstArg is a Symbol, or args[1]{args[2:end]...} otherwise.
Constructors
CurlyExpr{FirstArg, E}(; args::Vector{E}) MacroUtilities.UnionExpr — TypeUnionExpr(; args::Vector{Union{Symbol, Expr}})Matches an expression of the form Union{T1, T2, ...}
MacroUtilities.TypedVar — TypeTypedVar(; name, type)Matches an expression of the form name or name::type
Fields
name::Symboltype::Union{Symbol, Expr, NotProvided} = not_provided
MacroUtilities.TypedVar — MethodTypedVar(f::TypedVar; [name, type])Returns a new copy of f, with optional name or type overridden by the keyword arguments.
MacroUtilities.TypedExpr — TypeTypedExpr{E}(; expr::E, type::Union{Symbol, Expr, NotProvided})Matches an expression of the form expr or expr::type
MacroUtilities.TypedExpr — MethodTypedExpr(f::TypedExpr; [expr, type])Returns a new copy of f, with optional expr or type overridden by the keyword arguments.
Composite Expression Types
MacroUtilities.PairExpr — TypePairExpr{L,R}(; lhs::L, rhs::R)Matches an expression of the form lhs => rhs
MacroUtilities.PairExpr — MethodPairExpr(f::PairExpr{L,R}; [lhs::L], [rhs::R])Returns a new copy of f, with optional lhs and rhs overriden by the keyword arguments.
MacroUtilities.AssignExpr — TypeAssignExpr{L,R}(; lhs::L, rhs::R, allow_kw)Matches a lhs = rhs assignment expression.
If allow_key == true, also matches an assignment expression with head :kw
MacroUtilities.AssignExpr — MethodAssignExpr(f::AssignExpr{L,R}; [lhs::L], [rhs::R], [allow_kw::Bool])Returns a new copy of f, with optional lhs, rhs, and allow_kw overriden by the keyword arguments.
MacroUtilities.ExprWOptionalRhs — TypeExprWOptionalRhs{E <: AbstractExpr}(; lhs::E, default=not_provided)Matches an expression of the form lhs = default, where lhs is matched by E, or an expression matched by E
MacroUtilities.KVExpr — TypeKVExpr(; lhs::Symbol, rhs)Matches an expression of the form lhs = rhs or lhs
MacroUtilities.ExprWOptions — TypeExprWOptions{E}(; lhs::E, options::NamedTupleExpr)
ExprWOptions{E}(; inner_expr::AssignExpr{E, NamedTupleExpr})
ExprWOptions(lhs::E, options::NamedTupleExpr; allow_kw::Bool=false)Matches an expression of the form lhs = (key1=value1, ...) or lhs, where lhs matches E
The underlying options in the expression can be accessed/iterated over/modified via the Base.haskey, Base.keys, BAse.iterate, Base.getindex, and Base.setindex! functions.
MacroUtilities.ExprWOptions — MethodExprWOptions(f::ExprWOptions{E}; [lhs::E], [rhs::NamedTupleExpr], [allow_kw::Bool])Returns a new copy of f, with optional lhs, rhs, and allow_kw overridden by the keyword arguments.
MacroUtilities.KeyWOptions — TypeKeyWOptions(; lhs::Symbol, options::NamedTupleExpr)Matches an expression of the form lhs = (key1=value1, ...) or lhs
MacroUtilities.DestructuredAssigmentExpr — TypeDestructuredAssigmentExpr{E}(; lhs_names::Vector{Symbol}, destructure_type::Symbol, rhs::E)Matches an expression of the form lhs = rhs, where
- if
destructure_type == :tuple,lhsis of the formExpr(:tuple, lhs_names[1:end-1]..., Expr(:(=), lhs_names[end], rhs) - if
destructure_type == :eq_tuple,lhsis of the form(lhs_names...) = rhs - if
destructure_type == :eq_namedtuple,lhsis of the form(; lhs_names...) = rhs
MacroUtilities.DestructuredAssigmentExpr — MethodDestructuredAssigmentExpr(f::DestructuredAssigmentExpr{E}; lhs_names::Vector{Symbol}, destructure_type::Symbol, rhs::E)Returns a new copy of f, with optional lhs_names, destructure_type, and rhs overriden by the keyword arguments.
Block Expression Types
MacroUtilities.BlockExpr — TypeBlockExpr(; args::Vector{Any})Matches a :block expression
MacroUtilities.IfElseExpr — TypeIfElseExpr(; [if_else_exprs], [else_expr])Matches an if/if-else/if-elseif-else block
Arguments
if_else_exprs::Vector{Pair{Any,Any}} = Pair{Any, Any}[]: Set ofcondition=>condition_exprblocks. The first pair corresponds to theifstatement, the rest areelseifstatementselse_expr::Any = not_provided: Theelsestatement of the block
Syntactic Sugar
MacroUtilities.NestedDotExpr — TypeNestedDotExpr(; keys::Vector{Symbol})Matches expressions of the form A.B.C...., with each symbol being stored in keys
Macro Expressions
MacroUtilities.MacroCall — TypeMacroCall(; name::Union{Symbol, Expr, GlobalRef}, line::Union{LineNumberNode, NotProvided} = not_provided, args::Vector{Any} = [])Matches a macro call expression. A MacroCall object can be applied to one or more expressions, yielding another MacroCall.
MacroUtilities.DocExpr — TypeDocExpr{E}(; line::LineNumberNode, docstr::Union{String, Expr}, expr::E)Matches a standard documented expression expr, e.g.,
"documentation"
exprMacroUtilities.doc_macro — Constantdoc_macroA MacroCall corresponding to Core.@doc
MacroUtilities.__doc__macro — Constant__doc__macroA MacroCall corresponding to Core.@__doc__
MacroUtilities.assume_effects — Constantassume_effectsA MacroCall corresponding to Base.@assume_effects
MacroUtilities.assume_foldable — Constantassume_foldableA MacroCall corresponding to Base.@assume_effects :foldable
Function Expressions
MacroUtilities.FuncDef — TypeFuncDef(; header, head, whereparams, return_type, body, line, doc)Matches a function definition expression
Fields
header::FuncCallhead::Symbolwhereparams::Any = not_providedreturn_type::Any = not_providedbody::Anyline::Union{LineNumberNode, NotProvided} = not_provideddoc::Union{Expr, String, NotProvided} = not_provided
MacroUtilities.FuncDef — MethodFuncDef(f::FuncDef; [header, head, whereparams, return_type, body, line, doc)Returns a new copy of f, with optional header, head, whereparams, return_type, body, line, or doc values overridden by the keyword arguments.
MacroUtilities.FuncCall — TypeFuncCall(; funcname, args, kwargs)Matches a function call expression
Fields
funcname::Union{NotProvided, Symbol, Expr}args::Vector{FuncArg} = Vector{FuncArg}()kwargs::OrderedDict{Symbol, FuncArg} = OrderedDict{Symbol, FuncArg}()
In the FuncArgs keyword constructor, kwargs may also be a Vector{FuncArg} or a Vector{Pair{Symbol, FuncArg}}
MacroUtilities.FuncCall — MethodFuncCall(f::FuncCall; [funcname, args, kwargs])Returns a new copy of f, with optional funcname, args, or kwargs overridden by the keyword arguments.
MacroUtilities.FuncArg — TypeFuncArg(; name, type, value::Any, is_splat::Bool)Matches a function argument expression
Fields
name::Union{NotProvided, Symbol} = not_provided: Name of the argumenttype::Union{NotProvided, Symbol, Expr} = not_provided: Annotated type of the argument. Only valid whenvalueis not provided.value::Any = not_provided: Value of the argument. Ifnameis provided, this corresponds to the default value ofnamein a method definition. Otherwise, this is the value passed as a function argumentis_splat::Bool = false:trueif this argument is splatted,falseotherwise
MacroUtilities.FuncArg — MethodFuncArg(f::FuncArg; [name, type, value, is_splat])Returns a new copy of f, with optional name, type, value, or is_splat overridden by the keyword arguments.
MacroUtilities.map_args — Functionmap_args(f, expr::FuncCall) -> FuncCall
map_args(f, expr::FuncDef) -> FuncCallTransform the expr by applying f(FuncArg) -> FuncArg to each of its arguments
MacroUtilities.map_kwargs — Functionmap_kwargs(f, expr::FuncCall) -> FuncCall
map_kwargs(f, expr::FuncDef) -> FuncCallTransform the expr by applying f(FuncArg) -> FuncArg to each of its keyword arguments
MacroUtilities.name_only — Functionname_only(f::FuncArg; is_splat::Bool=f.is_splat) -> FuncArgReturns a new FuncArg with the type removed from f
If f.name is provided, also removes the value field from f
name_only(f::NamedTupleArg) -> NamedTupleArgReturns a NamedTupleArg derived from f with its value removed
MacroUtilities.names_only — Functionnames_only(f::NamedTupleExpr) -> NamedTupleExprReturns a NamedTupleExpr derived from f with each arguments' value removed
names_only(f::FuncCall) -> FuncCallReturns a FuncCall derived from f with all of its types + values removed from its arguments/keyword arguments
Struct Expressions
MacroUtilities.StructDefHeader — TypeStructDefHeader(; typename, parameters, supertype)Matches the header of a struct definition
Fields
typename::Symbolparameters::Vector{TypeVarExpr} = TypeVarExpr[]supertype::Union{Symbol, Expr, NotProvided} = not_provided
MacroUtilities.StructDefHeader — MethodStructDefHeader(f::StructDefHeader; [typename, parameter, supertype])Returns a new copy of f, with optional typename, parameter, or supertype overridden by the keyword arguments.
MacroUtilities.StructDefField — TypeTypedVar(; name, type)Matches an expression of the form name or name::type
Fields
name::Symboltype::Union{Symbol, Expr, NotProvided} = not_provided
MacroUtilities.StructDef — TypeStructDef(; is_mutable, header, lnn, fields, constructors)Matches a struct definition. The properties .typename, .parameter, and .supertype forward to the header field.
Fields
is_mutable::Boolheader::StructDefHeaderlnn::Union{LineNumberNode, NotProvided}= not_providedfields::Vector{Tuple{TypedVar, LineNumberNode}}constructors::Vector{Tuple{FuncDef, LineNumberNode}}
MacroUtilities.StructDef — MethodStructDef(f::StructDef; [is_mutable, header, fields, constructors])Returns a new copy of f, with optional is_mutable, header, fields, or constructors overridden by the keyword arguments.
MacroUtilities.GeneralizedStructDef — TypeGeneralizedStructDef(; is_mutable, header, lnn, fields, constructors)Matches a struct definition. The properties .typename, .parameter, and .supertype forward to the header field.
Fields
is_mutable::Boolheader::StructDefHeaderlnn::Union{LineNumberNode, NotProvided}= not_providedfields::Vector{Tuple{TypedVar, LineNumberNode}}constructors::Vector{Tuple{FuncDef, LineNumberNode}}
MacroUtilities.GeneralizedStructDef — MethodGeneralizedStructDef(f::TypedVar; [is_mutable, header, fields, constructors])Returns a new copy of f, with optional is_mutable, header, fields, or constructors overridden by the keyword arguments.
MacroUtilities.map_fields — Methodmap_fields(f, def::StructDef) -> StructDefApply the function f(::TypedVar) -> TypedVar to each field definition in def
MacroUtilities.map_fields — Methodmap_fields(f, def::GeneralizedStructDef{A,B,C}) -> GeneralizedStructDefApply the function f(::A) -> A to each field definition in def
Expression Generation
MacroUtilities.kwarg_constructor — Methodkwarg_constructor(typename, fields::Vector{TypedVar}, default_vals; [lnn::Union{LineNumberNode, Nothing)=nothing], [whereparams=not_provided])Returns a FuncDef keyword argument constructor for typename with fields and default_vals is any collection that implements Base.get(default_vals, fieldname, default)
MacroUtilities.kwarg_constructor — Methodkwarg_constructor(f::StructDef, default_vals; [lnn::Union{LineNumberNode, Nothing)=nothing], [whereparams=not_provided]))MacroUtilities.copy_constructor — Methodcopy_constructor(typename, fields::Vector{TypedVar}; [input_var::Symbol], [lnn::Union{LineNumberNode, Nothing}], [whereparams=not_provided], [copy_expr=default_copy_expr])Returns a FuncDef copy constructor for typename with fields, i.e., a function of the form
$typename($input_var::$typename; field1::fieldtype1=Base.copy(getfield($input_var, :field1)), ...) = $typename(field1, ...)Supports an optionally provided lnn and whereparams
copy_expr(name, input_value) must return an Expr that determines how the field name will be copied from input_value
MacroUtilities.copy_constructor — Methodcopy_constructor(f::StructDef; [input_var::Symbol], [lnn::Union{LineNumberNode, Nothing}], [whereparams=not_provided])