API

General Utilities

MacroUtilities.@assert_typeMacro
@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

source
MacroUtilities.@unpack_optionMacro
@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, then options[$name] must be of type T or an ArgumentError will be returned
  • name::Union{T1, T2, ..., Tn}, then options[$name] must be of type T1, T2, ..., or Tn
  • name = default, then default_value will be used if $name is not present in options
  • 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.

source
MacroUtilities.@method_def_constantMacro
@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)

source

Keyword Arg Parsing

MacroUtilities.@parse_kwargsMacro
@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`
[...]
source

Syntax Parsing

General

MacroUtilities.from_exprFunction
from_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.

source
MacroUtilities.@return_if_exceptionMacro
@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

source

Basic Expression Types

MacroUtilities.NamedTupleArgType
NamedTupleArg(; 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 :(=)

source
MacroUtilities.NamedTupleArgMethod
NamedTupleArg(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.

source
MacroUtilities.NamedTupleExprType
NamedTupleExpr(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!

source
MacroUtilities.NamedTupleExprMethod
NamedTupleExpr(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...)

source
MacroUtilities.TypeVarExprType
TypeVarExpr <: 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)
source
MacroUtilities.CurlyExprType
CurlyExpr{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}) 
source
MacroUtilities.TypedVarType
TypedVar(; name, type)

Matches an expression of the form name or name::type

Fields

  • name::Symbol
  • type::Union{Symbol, Expr, NotProvided} = not_provided
source
MacroUtilities.TypedVarMethod
TypedVar(f::TypedVar; [name, type])

Returns a new copy of f, with optional name or type overridden by the keyword arguments.

source
MacroUtilities.TypedExprType
TypedExpr{E}(; expr::E, type::Union{Symbol, Expr, NotProvided})

Matches an expression of the form expr or expr::type

source
MacroUtilities.TypedExprMethod
TypedExpr(f::TypedExpr; [expr, type])

Returns a new copy of f, with optional expr or type overridden by the keyword arguments.

source

Composite Expression Types

MacroUtilities.PairExprMethod
PairExpr(f::PairExpr{L,R}; [lhs::L], [rhs::R])

Returns a new copy of f, with optional lhs and rhs overriden by the keyword arguments.

source
MacroUtilities.AssignExprType
AssignExpr{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

source
MacroUtilities.AssignExprMethod
AssignExpr(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.

source
MacroUtilities.ExprWOptionalRhsType
ExprWOptionalRhs{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

source
MacroUtilities.ExprWOptionsType
ExprWOptions{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.

source
MacroUtilities.ExprWOptionsMethod
ExprWOptions(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.

source
MacroUtilities.DestructuredAssigmentExprType
DestructuredAssigmentExpr{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 form Expr(: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
source
MacroUtilities.DestructuredAssigmentExprMethod
DestructuredAssigmentExpr(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.

source

Block Expression Types

MacroUtilities.IfElseExprType
IfElseExpr(; [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 of condition => condition_expr blocks. The first pair corresponds to the if statement, the rest are elseif statements
  • else_expr::Any = not_provided: The else statement of the block
source

Syntactic Sugar

Macro Expressions

MacroUtilities.MacroCallType
MacroCall(; 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.

source
MacroUtilities.DocExprType
DocExpr{E}(; line::LineNumberNode, docstr::Union{String, Expr}, expr::E)

Matches a standard documented expression expr, e.g.,

"documentation"
expr
source

Function Expressions

MacroUtilities.FuncDefType
FuncDef(; 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
source
MacroUtilities.FuncDefMethod
FuncDef(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.

source
MacroUtilities.FuncCallType
FuncCall(; 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}}

source
MacroUtilities.FuncCallMethod
FuncCall(f::FuncCall; [funcname, args, kwargs])

Returns a new copy of f, with optional funcname, args, or kwargs overridden by the keyword arguments.

source
MacroUtilities.FuncArgType
FuncArg(; name, type, value::Any, is_splat::Bool)

Matches a function argument expression

Fields

  • name::Union{NotProvided, Symbol} = not_provided: Name of the argument
  • type::Union{NotProvided, Symbol, Expr} = not_provided: Annotated type of the argument. Only valid when value is not provided.
  • value::Any = not_provided: Value of the argument. If name is provided, this corresponds to the default value of name in a method definition. Otherwise, this is the value passed as a function argument
  • is_splat::Bool = false: true if this argument is splatted, false otherwise
source
MacroUtilities.FuncArgMethod
FuncArg(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.

source
MacroUtilities.map_argsFunction
map_args(f, expr::FuncCall) -> FuncCall
map_args(f, expr::FuncDef) -> FuncCall

Transform the expr by applying f(FuncArg) -> FuncArg to each of its arguments

source
MacroUtilities.map_kwargsFunction
map_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

source
MacroUtilities.name_onlyFunction
name_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

source
name_only(f::NamedTupleArg) -> NamedTupleArg

Returns a NamedTupleArg derived from f with its value removed

source
MacroUtilities.names_onlyFunction
names_only(f::NamedTupleExpr) -> NamedTupleExpr

Returns a NamedTupleExpr derived from f with each arguments' value removed

source
names_only(f::FuncCall) -> FuncCall

Returns a FuncCall derived from f with all of its types + values removed from its arguments/keyword arguments

source

Struct Expressions

MacroUtilities.StructDefHeaderType
StructDefHeader(; typename, parameters, supertype)

Matches the header of a struct definition

Fields

  • typename::Symbol
  • parameters::Vector{TypeVarExpr} = TypeVarExpr[]
  • supertype::Union{Symbol, Expr, NotProvided} = not_provided
source
MacroUtilities.StructDefHeaderMethod
StructDefHeader(f::StructDefHeader; [typename, parameter, supertype])

Returns a new copy of f, with optional typename, parameter, or supertype overridden by the keyword arguments.

source
MacroUtilities.StructDefFieldType
TypedVar(; name, type)

Matches an expression of the form name or name::type

Fields

  • name::Symbol
  • type::Union{Symbol, Expr, NotProvided} = not_provided
source
MacroUtilities.StructDefType
StructDef(; 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_provided
  • fields::Vector{Tuple{TypedVar, LineNumberNode}}
  • constructors::Vector{Tuple{FuncDef, LineNumberNode}}
source
MacroUtilities.StructDefMethod
StructDef(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.

source
MacroUtilities.GeneralizedStructDefType
GeneralizedStructDef(; 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_provided
  • fields::Vector{Tuple{TypedVar, LineNumberNode}}
  • constructors::Vector{Tuple{FuncDef, LineNumberNode}}
source
MacroUtilities.GeneralizedStructDefMethod
GeneralizedStructDef(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.

source
MacroUtilities.map_fieldsMethod
map_fields(f, def::StructDef) -> StructDef

Apply the function f(::TypedVar) -> TypedVar to each field definition in def

source
MacroUtilities.map_fieldsMethod
map_fields(f, def::GeneralizedStructDef{A,B,C}) -> GeneralizedStructDef

Apply the function f(::A) -> A to each field definition in def

source

Expression Generation

MacroUtilities.kwarg_constructorMethod
kwarg_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)

source
MacroUtilities.copy_constructorMethod
copy_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

source