Some data representation of a particular kind of expression.

  • Turn it back into the original expression with combine_expr(e).
  • Check if the entire split expression is escaped with is_escaped(e) (does not check for inner things being escaped).
  • Make a smart deep-copy (using expr_deepcopy()) by constructing another one and passing the original.

When applicable, constructors return nothing if the expression cannot be split, but less strict interpretation can be requested by passing an extra parameter false.


A data represenation of an argument declaration, comparable to the output of MacroTools.splitarg() but handling extra stuff like being wrapped in an esc() call.


A data representation of a function definition, or lambda, comparable to MacroTools.splitdef() but far more thorough.

You can also split/combine a function call, represented by a nothing body, but must turn off strict mode (pass false in the constructor) to successfully parse literal-valued parameters. In a generated function call, the only thing that matters in arguments is the name, for example named parameter a turns into a=a.

A lambda is represented by a nothing name. Setting both the body and name to nothing is not allowed.


Information that sits outside of a definition (especially a function definition). For example @inline, @generated, and doc-strings.


Returns nothing if the metadata can't be extracted (i.e. it's wrapped by an unexpected macro)


When generating a function call, pass true for each named arg a=5 to turn into a=a. Pass false for each named arg a=5 to turn into a=5


Computes one of the modifying assignments (*=, &=, etc) given it and its inputs. Also implements = for completeness.


Deep-copies an expression AST, except for things that should not be copied like literal modules


Checks if an expression is a valid function declaration. Note that MacroTools' version of this function is overly permissive.


Checks that an expression is a Symbol, possibly nested within . operators. For example, Base.empty.

Optionally allows type parameters at the end of the expression, like :( A.B{C} ).


Checks if an expression is a short-form function declaration (like f() = 5). Preferred to MacroTools' version of this function, because that one accepts AST's that are not actually functions.


Unwraps esc() from the outside of an expression, if it exists. Also see unescape_deep()


Walks through an expression depth-first, invoking your lambda on every sub-expression with the following arguments:

1 .A list of integers representing the path to this sub-expression (for each Expr along the way, the index of its argument)

  1. A list of the parents to this sub-expression, from the root down to the current expr.

For example, you could pass a lambda of the form (path, exprs) -> let e = exprs[end] ... end.

Like MacroTools.postwalk, but without modifying the expression and with more context about where each expression sits in the AST.