API
General Utilities
MacroUtilities.@assert_type
— Macro@assert_type var types
Ensures 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_expr
Unpacks 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 typeT
or anArgumentError
will be returnedname::Union{T1, T2, ..., Tn}
, thenoptions[$name]
must be of typeT1, T2, ...,
orTn
name = default
, thendefault_value
will be used if$name
is not present inoptions
name => 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_method
Given 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_spec
Parses 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_value
Note: 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) -> Expr
Converts x
to an Expr
representation
MacroUtilities.NotProvided
— TypeNotProvided
Placeholder type to represent the absence of a field.
MacroUtilities.is_not_provided
— Functionis_not_provided(x) -> Bool
Returns true
if the field corresponding to x
is not provided, false
otherwise.
MacroUtilities.is_provided
— Functionis_provided(d) -> Bool
Returns 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 key
s and value
s 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 <: AbstractExpr
Matches expressions of the form
typename
typename <: UB
<: UB
typename >: LB
>: LB
LB <: 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} <: AbstractExpr
Matches 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::Symbol
type::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
,lhs
is of the formExpr(:tuple, lhs_names[1:end-1]..., Expr(:(=), lhs_names[end], rhs)
- if
destructure_type == :eq_tuple
,lhs
is of the form(lhs_names...) = rhs
- if
destructure_type == :eq_namedtuple
,lhs
is 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_expr
blocks. The first pair corresponds to theif
statement, the rest areelseif
statementselse_expr::Any = not_provided
: Theelse
statement 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"
expr
MacroUtilities.doc_macro
— Constantdoc_macro
A MacroCall
corresponding to Core.@doc
MacroUtilities.__doc__macro
— Constant__doc__macro
A MacroCall
corresponding to Core.@__doc__
MacroUtilities.assume_effects
— Constantassume_effects
A MacroCall
corresponding to Base.@assume_effects
MacroUtilities.assume_foldable
— Constantassume_foldable
A 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::FuncCall
head::Symbol
whereparams::Any = not_provided
return_type::Any = not_provided
body::Any
line::Union{LineNumberNode, NotProvided} = not_provided
doc::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 whenvalue
is not provided.value::Any = not_provided
: Value of the argument. Ifname
is provided, this corresponds to the default value ofname
in a method definition. Otherwise, this is the value passed as a function argumentis_splat::Bool = false
:true
if this argument is splatted,false
otherwise
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) -> FuncCall
Transform 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) -> FuncCall
Transform 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) -> FuncArg
Returns 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) -> NamedTupleArg
Returns a NamedTupleArg
derived from f
with its value
removed
MacroUtilities.names_only
— Functionnames_only(f::NamedTupleExpr) -> NamedTupleExpr
Returns a NamedTupleExpr
derived from f
with each arguments' value
removed
names_only(f::FuncCall) -> FuncCall
Returns 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::Symbol
parameters::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::Symbol
type::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::Bool
header::StructDefHeader
lnn::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::Bool
header::StructDefHeader
lnn::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) -> StructDef
Apply the function f(::TypedVar) -> TypedVar
to each field definition in def
MacroUtilities.map_fields
— Methodmap_fields(f, def::GeneralizedStructDef{A,B,C}) -> GeneralizedStructDef
Apply 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])