erl_syntax(3erl)
โจ erl_syntax(3erl) โจ
๐ NAME ๐
erl_syntax โ Abstract Erlang syntax trees. Iconic module, honestly ๐
๐ DESCRIPTION ๐
Okay bestie, so this module is all about abstract Erlang syntax trees ๐ณโจ
It defines an abstract data type for representing Erlang source code as syntax trees, and it's backwards compatible with the data structures created by the Erlang standard library parser module erl_parse โ often called โparse treesโ, which is a bit of a misnomer ๐. That means every erl_parse tree is a valid abstract syntax tree, but the reverse is not true: abstract syntax trees can in general not be used as input to functions expecting an erl_parse tree. However, as long as an abstract syntax tree represents a correct Erlang program, the function revert/1 should be able to transform it to the corresponding erl_parse representation. Slay. ๐
A recommended starting point for the first-time user is the documentation of the syntaxTree() data type, and the function type/1. Start there, bestie ๐ซถ
๐ NOTES ๐
This module deals with the composition and decomposition of syntactic entities (as opposed to semantic ones); its purpose is to hide all direct references to the data structures used to represent these entities. With few exceptions, the functions in this module perform no semantic interpretation of their inputs, and in general, the user is assumed to pass type-correct arguments โ if this is not done, the effects are not defined. ๐ญ
With the exception of the erl_parse() data structures, the internal representations of abstract syntax trees are subject to change without notice, and should not be documented outside this module. Furthermore, we do not give any guarantees on how an abstract syntax tree may or may not be represented, with the following exceptions: no syntax tree is represented by a single atom, such as none, by a list constructor [X | Y], or by the empty list []. This can be relied on when writing functions that operate on syntax trees. Periodt. ๐
๐ง DATA TYPES ๐ง
Here's the whole type cast, exactly as-is ๐:
annotation_or_location() = erl_anno:anno() | erl_anno:location():
encoding() = utf8 | unicode | latin1:
erl_parse() = erl_parse:abstract_clause() | erl_parse:abstract_expr()
| erl_parse:abstract_form() | erl_parse:abstract_type() |
erl_parse:form_info() | erl_parse:af_binelement(term()) |
erl_parse:af_generator() | erl_parse:af_remote_function():
forms() = syntaxTree() | [syntaxTree()]:
guard() = none | syntaxTree() | [syntaxTree()] | [[syntaxTree()]]:
padding() = none | integer():
syntaxTree() = tree() | wrapper() | erl_parse():
syntaxTreeAttributes() = #attr{pos=term(), ann=[term()], com=none |
#com{pre=[syntaxTree()], post=[syntaxTree()]}}:
tree() = #tree{type=atom(), attr=#attr{pos=term(), ann=[term()],
com=none | #com{pre=[syntaxTree()], post=[syntaxTree()]}},
data=term()}:
wrapper() = #wrapper{type=atom(), attr=#attr{pos=term(), ann=[term()],
com=none | #com{pre=[syntaxTree()], post=[syntaxTree()]}},
tree=erl_parse()}:
๐ EXPORTS ๐
abstract(T::term()) -> syntaxTree()โ Returns the syntax tree corresponding to an Erlang term.Termmust be a literal term, i.e., one that can be represented as a source code literal. So it may not contain a process identifier, port, reference or function value as a subterm. The function recognises printable strings, in order to get a compact and readable representation. Evaluation fails with reasonbadargifTermis not a literal term. No cap, literal only ๐ See also:concrete/1,is_literal/1.add_ann(A::term(), Node::syntaxTree()) -> syntaxTree()โ Appends the termAnnotationto the list of user annotations ofNode. Note: this is equivalent toset_ann(Node, [Annotation | get_ann(Node)]), but potentially more efficient. See also:get_ann/1,set_ann/2.add_postcomments(Cs::[syntaxTree()], Node::syntaxTree()) -> syntaxTree()โ AppendsCommentsto the post-comments ofNode. Note: This is equivalent toset_postcomments(Node, get_postcomments(Node) ++ Comments), but potentially more efficient. See also:add_precomments/2,comment/2,get_postcomments/1,join_comments/2,set_postcomments/2.add_precomments(Cs::[syntaxTree()], Node::syntaxTree()) -> syntaxTree()โ AppendsCommentsto the pre-comments ofNode. Note: This is equivalent toset_precomments(Node, get_precomments(Node) ++ Comments), but potentially more efficient. See also:add_postcomments/2,comment/2,get_precomments/1,join_comments/2,set_precomments/2.annotated_type(Name::syntaxTree(), Type::syntaxTree()) -> syntaxTree()โ Creates an abstract annotated type expression. The result represents"Name :: Type". Type annotation era โจ See also:annotated_type_body/1,annotated_type_name/1.annotated_type_body(Node::syntaxTree()) -> syntaxTree()โ Returns the type subtrees of anannotated_typenode. See also:annotated_type/2.annotated_type_name(Node::syntaxTree()) -> syntaxTree()โ Returns the name subtree of anannotated_typenode. See also:annotated_type/2.application(Operator::syntaxTree(), Arguments::[syntaxTree()]) -> syntaxTree()โ Creates an abstract function application expression. IfArgumentsis[A1, ..., An], the result represents"Operator(A1, ..., An)". Function call vibes ๐ฆ See also:application/3,application_arguments/1,application_operator/1.application(Module::none | syntaxTree(), Name::syntaxTree(), Arguments::[syntaxTree()]) -> syntaxTree()โ Creates an abstract function application expression. IfModuleisnone, this call is equivalent toapplication(Function, Arguments), otherwise it is equivalent toapplication(module_qualifier(Module, Function), Arguments). (This is a utility function.) See also:application/2,module_qualifier/2.application_arguments(Node::syntaxTree()) -> [syntaxTree()]โ Returns the list of argument subtrees of anapplicationnode. See also:application/2.application_operator(Node::syntaxTree()) -> syntaxTree()โ Returns the operator subtree of anapplicationnode. Note: ifNoderepresents"M:F(...)", then the result is the subtree representing"M:F". See also:application/2,module_qualifier/2.arity_qualifier(Body::syntaxTree(), Arity::syntaxTree()) -> syntaxTree()โ Creates an abstract arity qualifier. The result represents"Body/Arity". See also:arity_qualifier_argument/1,arity_qualifier_body/1.arity_qualifier_argument(Node::syntaxTree()) -> syntaxTree()โ Returns the argument (the arity) subtree of anarity_qualifiernode. See also:arity_qualifier/2.arity_qualifier_body(Node::syntaxTree()) -> syntaxTree()โ Returns the body subtree of anarity_qualifiernode. See also:arity_qualifier/2.atom(Name::atom() | string()) -> syntaxTree()โ Creates an abstract atom literal. The print name of the atom is the character sequence represented byName. Atom bestie ๐ See also:atom_literal/1,atom_literal/2,atom_name/1,atom_value/1,is_atom/2.atom_literal(Node::syntaxTree()) -> string()โ Returns the literal string represented by an atom node. This includes surrounding single-quote characters if necessary. Characters beyond 255 will be escaped. Note that e.g. the result ofatom("x\ny")represents any and all of`x\ny'',`x\12y'',`x\012y''and`x\^Jy\''; seestring/1. See also:atom/1,string/1.atom_literal(Node, X2) -> term()โ Returns the literal string represented by an atom node. This includes surrounding single-quote characters if necessary. Depending on the encoding a character beyond 255 will be escaped (latin1) or copied as is (utf8). See also:atom/1,atom_literal/1,string/1.atom_name(Node::syntaxTree()) -> string()โ Returns the printname of an atom node. See also:atom/1.atom_value(Node::syntaxTree()) -> atom()โ Returns the value represented by an atom node. See also:atom/1.attribute(Name::syntaxTree()) -> syntaxTree()โ Equivalent toattribute(Name, none).attribute(Name::syntaxTree(), Args::none | [syntaxTree()]) -> syntaxTree()โ Creates an abstract program attribute. IfArgumentsis[A1, ..., An], the result represents"-Name(A1, ..., An).". Otherwise, ifArgumentsisnone, the result represents"-Name.". The latter form makes it possible to represent preprocessor directives such as"-endif.". Attributes are source code forms. Note: The preprocessor macro definition directive"-define(Name, Body)."has relatively few requirements on the syntactical form ofBody(viewed as a sequence of tokens). Thetextnode type can be used for aBodythat is not a normal Erlang construct. See also:attribute/1,attribute_arguments/1,attribute_name/1,is_form/1,text/1.attribute_arguments(Node::syntaxTree()) -> none | [syntaxTree()]โ Returns the list of argument subtrees of an attribute node, if any. IfNoderepresents"-Name.", the result isnone. Otherwise, ifNoderepresents"-Name(E1, ..., En).",[E1, ..., E1]is returned. See also:attribute/1.attribute_name(Node::syntaxTree()) -> syntaxTree()โ Returns the name subtree of an attribute node. See also:attribute/1.binary(List::[syntaxTree()]) -> syntaxTree()โ Creates an abstract binary-object template. IfFieldsis[F1, ..., Fn], the result represents"<<F1, ..., Fn>>". Binary baddie behavior ๐ See also:binary_field/2,binary_fields/1.binary_comp(Template::syntaxTree(), Body::[syntaxTree()]) -> syntaxTree()โ Creates an abstract binary comprehension. IfBodyis[E1, ..., En], the result represents"<<Template || E1, ..., En>>". See also:binary_comp_body/1,binary_comp_template/1,generator/2.binary_comp_body(Node::syntaxTree()) -> [syntaxTree()]โ Returns the list of body subtrees of abinary_compnode. See also:binary_comp/2.binary_comp_template(Node::syntaxTree()) -> syntaxTree()โ Returns the template subtree of abinary_compnode. See also:binary_comp/2.binary_field(Body::syntaxTree()) -> syntaxTree()โ Equivalent tobinary_field(Body, []).binary_field(Body::syntaxTree(), Types::[syntaxTree()]) -> syntaxTree()โ Creates an abstract binary template field. IfTypesis the empty list, the result simply represents"Body", otherwise, ifTypesis[T1, ..., Tn], the result represents"Body/T1-...-Tn". Binary field slay โจ
See also: binary/1, binary_field/1, binary_field/3, binary_field_body/1, binary_field_size/1, binary_field_types/1. ๐ซถ
binary_field/3 ๐ง
binary_field(Body::syntaxTree(), Size::none | syntaxTree(), Types::[syntaxTree()]) -> syntaxTree()
Creates an abstract binary template field. If Size is none, this is equivalent to binary_field(Body, Types), otherwise it is equivalent to binary_field(size_qualifier(Body, Size), Types).
(This is a utility function.) tiny helper behavior, big โi got youโ energy ๐
See also: binary/1, binary_field/2, size_qualifier/2.
binary_field_body/1 ๐ธ
binary_field_body(Node::syntaxTree()) -> syntaxTree()
Returns the body subtree of a binary_field. just the body, no extra drama โจ
See also: binary_field/2.
binary_field_size/1 ๐
binary_field_size(Node::syntaxTree()) -> none | syntaxTree()
Returns the size specifier subtree of a binary_field node, if any. If Node represents Body:Size or Body:Size/T1, ..., Tn, the result is Size, otherwise none is returned.
(This is a utility function.)
See also: binary_field/2, binary_field/3.
binary_field_types/1 ๐ฆ
binary_field_types(Node::syntaxTree()) -> [syntaxTree()]
Returns the list of type-specifier subtrees of a binary_field node. If Node represents .../T1, ..., Tn, the result is [T1, ..., Tn], otherwise the result is the empty list.
See also: binary_field/2.
binary_fields/1 ๐
binary_fields(Node::syntaxTree()) -> [syntaxTree()]
Returns the list of field subtrees of a binary node.
See also: binary/1, binary_field/2.
binary_generator/2 ๐ฅ
binary_generator(Pattern::syntaxTree(), Body::syntaxTree()) -> syntaxTree()
Creates an abstract binary_generator. The result represents Pattern <- Body.
See also: binary_comp/2, binary_generator_body/1, binary_generator_pattern/1, list_comp/2.
binary_generator_body/1 ๐
binary_generator_body(Node::syntaxTree()) -> syntaxTree()
Returns the body subtree of a generator node.
See also: binary_generator/2.
binary_generator_pattern/1 โญ
binary_generator_pattern(Node::syntaxTree()) -> syntaxTree()
Returns the pattern subtree of a generator node.
See also: binary_generator/2.
bitstring_type/2 ๐
bitstring_type(M::syntaxTree(), N::syntaxTree()) -> syntaxTree()
Creates an abstract bitstring type. The result represents <<_:M, _:_*N>>.
See also: bitstring_type_m/1, bitstring_type_n/1.
bitstring_type_m/1 ๐ง
bitstring_type_m(Node::syntaxTree()) -> syntaxTree()
Returns the number of start bits, M, of a bitstring_type node.
See also: bitstring_type/2.
bitstring_type_n/1 ๐
bitstring_type_n(Node::syntaxTree()) -> syntaxTree()
Returns the segment size, N, of a bitstring_type node.
See also: bitstring_type/2.
block_expr/1 ๐ซถ
block_expr(Body::[syntaxTree()]) -> syntaxTree()
Creates an abstract block expression. If Body is [B1, ..., Bn], the result represents begin B1, ..., Bn end.
See also: block_expr_body/1.
block_expr_body/1 โจ
block_expr_body(Node::syntaxTree()) -> [syntaxTree()]
Returns the list of body subtrees of a block_expr node.
See also: block_expr/1.
case_expr/2 ๐
case_expr(Argument::syntaxTree(), Clauses::[syntaxTree()]) -> syntaxTree()
Creates an abstract case-expression. If Clauses is [C1, ..., Cn], the result represents case Argument of C1; ...; Cn end. More exactly, if each Ci represents (Pi) Gi -> Bi, then the result represents case Argument of P1 G1 -> B1; ...; Pn Gn -> Bn end.
See also: case_expr_argument/1, case_expr_clauses/1, clause/3, if_expr/1.
case_expr_argument/1 ๐ซ
case_expr_argument(Node::syntaxTree()) -> syntaxTree()
Returns the argument subtree of a case_expr node.
See also: case_expr/2.
case_expr_clauses/1 ๐
case_expr_clauses(Node::syntaxTree()) -> [syntaxTree()]
Returns the list of clause subtrees of a case_expr node.
See also: case_expr/2.
catch_expr/1 ๐งธ
catch_expr(Expr::syntaxTree()) -> syntaxTree()
Creates an abstract catch-expression. The result represents catch Expr.
See also: catch_expr_body/1.
catch_expr_body/1 ๐
catch_expr_body(Node::syntaxTree()) -> syntaxTree()
Returns the body subtree of a catch_expr node.
See also: catch_expr/1.
char/1 ๐
char(Char::char()) -> syntaxTree()
Creates an abstract character literal. The result represents $Name, where Name corresponds to Value.
Note: the literal corresponding to a particular character value is not uniquely defined. E.g., the character"a"can be written both as"$a"and"$\141", and a Tab character can be written as"$\11","$\011"or"$\t". so many cute little spellings for the same vibe, no cap ๐ญ
See also: char_literal/1, char_literal/2, char_value/1, is_char/2.
char_literal/1 ๐ฆ
char_literal(Node::syntaxTree()) -> nonempty_string()
Returns the literal string represented by a char node. This includes the leading $ character. Characters beyond 255 will be escaped.
See also: char/1.
char_literal/2 ๐ธ
char_literal(Node::syntaxTree(), X2::encoding()) -> nonempty_string()
Returns the literal string represented by a char node. This includes the leading $ character. Depending on the encoding a character beyond 255 will be escaped (latin1) or copied as is (utf8).
See also: char/1.
char_value/1 โญ
char_value(Node::syntaxTree()) -> char()
Returns the value represented by a char node.
See also: char/1.
class_qualifier/2 ๐
class_qualifier(Class::syntaxTree(), Body::syntaxTree()) -> syntaxTree()
Creates an abstract class qualifier. The result represents Class:Body.
See also: class_qualifier_argument/1, class_qualifier_body/1, class_qualifier_stacktrace/1, try_expr/4.
class_qualifier/3 ๐
class_qualifier(Class::syntaxTree(), Body::syntaxTree(), Stacktrace::syntaxTree()) -> syntaxTree()
Creates an abstract class qualifier. The result represents Class:Body:Stacktrace.
See also: class_qualifier_argument/1, class_qualifier_body/1, try_expr/4.
class_qualifier_argument/1 ๐
class_qualifier_argument(Node::syntaxTree()) -> syntaxTree()
Returns the argument (the class) subtree of a class_qualifier node.
See also: class_qualifier/2.
class_qualifier_body/1 ๐ง
class_qualifier_body(Node::syntaxTree()) -> syntaxTree()
Returns the body subtree of a class_qualifier node.
See also: class_qualifier/2.
class_qualifier_stacktrace/1 ๐ฅ
class_qualifier_stacktrace(Node::syntaxTree()) -> syntaxTree()
Returns the stacktrace subtree of a class_qualifier node.
See also: class_qualifier/2.
clause/2 ๐ซถ
clause(Guard::guard(), Body::[syntaxTree()]) -> syntaxTree()
Equivalent to clause([], Guard, Body).
clause/3 ๐
clause(Patterns::[syntaxTree()], Guard::guard(), Body::[syntaxTree()]) -> syntaxTree()
Creates an abstract clause. If Patterns is [P1, ..., Pn] and Body is [B1, ..., Bm], then if Guard is none, the result represents (P1, ..., Pn) -> B1, ..., Bm, otherwise, unless Guard is a list, the result represents (P1, ..., Pn) when Guard -> B1, ..., Bm.
For simplicity, the Guard argument may also be any of the following:
- An empty list
[]. This is equivalent to passingnone. - A nonempty list
[E1, ..., Ej]of syntax trees. This is equivalent to passingconjunction([E1, ..., Ej]). - A nonempty list of lists of syntax trees
[[E1_1, ..., E1_k1], ..., [Ej_1, ..., Ej_kj]], which is equivalent to passingdisjunction([conjunction([E1_1, ..., E1_k1]), ..., conjunction([Ej_1, ..., Ej_kj])]).
guard options giving choose-your-own-adventure, and every path is valid โจ
See also: clause/2, clause_body/1, clause_guard/1, clause_patterns/1.
clause_body/1 ๐
clause_body(Node::syntaxTree()) -> [syntaxTree()]
Returns the list of body subtrees of a clause node.
See also: clause/3.
clause_guard/1 ๐งธ
clause_guard(Node::syntaxTree()) -> none | syntaxTree()
Returns the guard subtree of a clause node, if any. If Node represents (P1, ..., Pn) when Guard -> B1, ..., Bm, Guard is returned. Otherwise, the result is none.
See also: clause/3.
clause_patterns/1 ๐
clause_patterns(Node::syntaxTree()) -> [syntaxTree()]
Returns the list of pattern subtrees of a clause node.
See also: clause/3.
comment/1 ๐
comment(Strings::[string()]) -> syntaxTree()
Equivalent to comment(none, Strings).
comment/2 ๐ธ
comment(Pad::padding(), Strings::[string()]) -> syntaxTree()
Creates an abstract comment with the given padding and text. If Strings is a (possibly empty) list ["Txt1", ..., "TxtN"], the result represents the source code text
%Txt1
...
%TxtN
Padding states the number of empty character positions to the left of the comment separating it horizontally from source code on the same line (if any). If Padding is none, a default positive number is used. If Padding is an integer less than 1, there should be no separating space. Comments are in themselves regarded as source program forms.
See also: comment/1, is_form/1.
comment_padding/1 ๐ฆ
comment_padding(Node::syntaxTree()) -> padding()
Returns the amount of padding before the comment, or none. The latter means that a default padding may be used.
See also: comment/2.
comment_text/1 ๐
comment_text(Node::syntaxTree()) -> [string()]
Returns the lines of text of the abstract comment.
See also: comment/2.
compact_list/1 ๐
compact_list(Node::syntaxTree()) -> syntaxTree()
Yields the most compact form for an abstract list skeleton. The result either represents [E1, ..., En | Tail], where Tail is not a list skeleton, or otherwise simply [E1, ..., En]. Annotations on subtrees of Node that represent list skeletons may be lost, but comments will be propagated to the result. Returns Node itself if Node does not represent a list skeleton.
See also: list/2, normalize_list/1.
concrete/1 ๐
concrete(Node::syntaxTree()) -> term()
Returns the Erlang term represented by a syntax tree. Evaluation fails with reason badarg if Node does not represent a literal term.
Note: Currently, the set of syntax trees which have a concrete representation is larger than the set of trees which can be built using the functionabstract/1. An abstract character will be concretised as an integer, whileabstract/1does not at present yield an abstract character for any input. (Use thechar/1function to explicitly create an abstract character.)
Note:arity_qualifiernodes are recognized. This is to follow The Erlang Parser when it comes to wild attributes: both{F, A}andF/Aare recognized, which makes it possible to turn wild attributes into recognized attributes without at the same time making it impossible to compile files using the new syntax with the old version of the Erlang Compiler.
See also: abstract/1, char/1, is_literal/1.
conjunction(Tests::[syntaxTree()]) -> syntaxTree()โ Creates an abstract conjunction. IfListis[E1, ..., En], the result represents"E1, ..., En". See also:conjunction_body/1,disjunction/1.conjunction_body(Node::syntaxTree()) -> [syntaxTree()]โ Returns the list of body subtrees of a conjunction node. See also:conjunction/1.cons(Head::syntaxTree(), Tail::syntaxTree()) -> syntaxTree()โ The "optimising" list skeleton cons operation. Creates an abstract list skeleton whose first element isHeadand whose tail corresponds toTail. This is similar tolist([Head], Tail), except thatTailmay not benone, and that the result does not necessarily represent exactly"[Head | Tail]", but may depend on theTailsubtree. E.g., ifTailrepresents[X, Y], the result may represent"[Head, X, Y]", rather than"[Head | [X, Y]]". Annotations onTailitself may be lost ifTailrepresents a list skeleton, but comments onTailare propagated to the result. See also:list/2,list_head/1,list_tail/1.constrained_function_type(FunctionType::syntaxTree(), FunctionConstraint::[syntaxTree()]) -> syntaxTree()โ Creates an abstract constrained function type. IfFunctionConstraintis[C1, ..., Cn], the result represents"FunctionType when C1, ...Cn". See also:constrained_function_type_argument/1,constrained_function_type_body/1.constrained_function_type_argument(Node::syntaxTree()) -> syntaxTree()โ Returns the function constraint subtree of aconstrained_function_typenode. See also:constrained_function_type/2.constrained_function_type_body(Node::syntaxTree()) -> syntaxTree()โ Returns the function type subtree of aconstrained_function_typenode. See also:constrained_function_type/2.constraint(Name::syntaxTree(), Types::[syntaxTree()]) -> syntaxTree()โ Creates an abstract (subtype) constraint. The result represents"Name :: Type". See also:constraint_argument/1,constraint_body/1.constraint_argument(Node::syntaxTree()) -> syntaxTree()โ Returns the name subtree of a constraint node. See also:constraint/2.constraint_body(Node::syntaxTree()) -> [syntaxTree()]โ Returns the type subtree of a constraint node. See also:constraint/2.copy_ann(Source::syntaxTree(), Target::syntaxTree()) -> syntaxTree()โ Copies the list of user annotations fromSourcetoTarget. Note: this is equivalent toset_ann(Target, get_ann(Source)), but potentially more efficient. See also:get_ann/1,set_ann/2.copy_attrs(S::syntaxTree(), T::syntaxTree()) -> syntaxTree()โ Copies the attributes fromSourcetoTarget. Note: this is equivalent toset_attrs(Target, get_attrs(Source)), but potentially more efficient. See also:get_attrs/1,set_attrs/2.copy_comments(Source::syntaxTree(), Target::syntaxTree()) -> syntaxTree()โ Copies the pre- and postcomments fromSourcetoTarget. Note: This is equivalent toset_postcomments(set_precomments(Target, get_precomments(Source)), get_postcomments(Source)), but potentially more efficient. See also:comment/2,get_postcomments/1,get_precomments/1,set_postcomments/2,set_precomments/2.copy_pos(Source::syntaxTree(), Target::syntaxTree()) -> syntaxTree()โ Copies the annotation fromSourcetoTarget. This is equivalent toset_pos(Target, get_pos(Source)), but potentially more efficient. See also:get_pos/1,set_pos/2.data(Tree::syntaxTree()) -> term()โ For special purposes only. Returns the associated data of a syntax tree node. Evaluation fails with reasonbadargifis_tree(Node)does not yieldtrue. See also:tree/2.disjunction(Tests::[syntaxTree()]) -> syntaxTree()โ Creates an abstract disjunction. IfListis[E1, ..., En], the result represents"E1; ...; En". See also:conjunction/1,disjunction_body/1.disjunction_body(Node::syntaxTree()) -> [syntaxTree()]โ Returns the list of body subtrees of a disjunction node. See also:disjunction/1.else_expr(Clauses) -> term()โ Creates an abstract else-expression. IfClausesis[C1, ..., Cn], the result represents"else C1; ...; Cn end". More exactly, if eachCirepresents"(Pi) Gi -> Bi", then the result represents"else G1 -> B1; ...; Pn Gn -> Bn end". See also:clause/3,else_expr_clauses/1,maybe_expr/2.else_expr_clauses(Node::syntaxTree()) -> [syntaxTree()]โ Returns the list of clause subtrees of anelse_exprnode. See also:else_expr/1.eof_marker() -> syntaxTree()โ Creates an abstract end-of-file marker. This represents the end of input when reading a sequence of source code forms. An end-of-file marker is itself regarded as a source code form (namely, the last in any sequence in which it occurs). It has no defined lexical form. Note: this is retained only for backwards compatibility with existing parsers and tools. See also:error_marker/1,is_form/1,warning_marker/1.error_marker(Error::term()) -> syntaxTree()โ Creates an abstract error marker. The result represents an occurrence of an error in the source code, with an associated Erlang I/OErrorInfostructure given byError(see moduleio(3erl)for details). Error markers are regarded as source code forms, but have no defined lexical form. Note: this is supported only for backwards compatibility with existing parsers and tools. See also:eof_marker/0,error_marker_info/1,is_form/1,warning_marker/1.error_marker_info(Node::syntaxTree()) -> term()โ Returns theErrorInfostructure of anerror_markernode. See also:error_marker/1.flatten_form_list(Node::syntaxTree()) -> syntaxTree()โ Flattens sublists of aform_listnode. ReturnsNodewith all subtrees of typeform_listrecursively expanded, yielding a single "flat" abstract form sequence. See also:form_list/1.float(Value::float()) -> syntaxTree()โ Creates an abstract floating-point literal. The lexical representation is the decimal floating-point numeral ofValue. See also:float_literal/1,float_value/1.float_literal(Node::syntaxTree()) -> string()โ Returns the numeral string represented by afloatnode. See also:float/1.float_value(Node::syntaxTree()) -> float()โ Returns the value represented by afloatnode. Note that floating-point values should usually not be compared for equality. See also:float/1.form_list(Forms::[syntaxTree()]) -> syntaxTree()โ Creates an abstract sequence of "source code forms". IfFormsis[F1, ..., Fn], where eachFiis a form (seeis_form/1), the result represents:
F1
...
Fn
where the Fi are separated by one or more line breaks. A node of type form_list is itself regarded as a source code form; see flatten_form_list/1. Note: this is simply a way of grouping source code forms as a single syntax tree, usually in order to form an Erlang module definition. See also: flatten_form_list/1, form_list_elements/1, is_form/1.
form_list_elements(Node::syntaxTree()) -> [syntaxTree()]โ Returns the list of subnodes of aform_listnode. See also:form_list/1.fun_expr(Clauses::[syntaxTree()]) -> syntaxTree()โ Creates an abstract fun-expression. IfClausesis[C1, ..., Cn], the result represents"fun C1; ...; Cn end". More exactly, if eachCirepresents"(Pi1, ..., Pim) Gi -> Bi", then the result represents"fun (P11, ..., P1m) G1 -> B1; ...; (Pn1, ..., Pnm) Gn -> Bn end". See also:fun_expr_arity/1,fun_expr_clauses/1.fun_expr_arity(Node::syntaxTree()) -> arity()โ Returns the arity of afun_exprnode. The result is the number of parameter patterns in the first clause of the fun-expression; subsequent clauses are ignored. An exception is thrown iffun_expr_clauses(Node)returns an empty list, or if the first element of that list is not a syntax treeCof typeclausesuch thatclause_patterns(C)is a nonempty list. See also:clause/3,clause_patterns/1,fun_expr/1,fun_expr_clauses/1.fun_expr_clauses(Node::syntaxTree()) -> [syntaxTree()]โ Returns the list of clause subtrees of afun_exprnode. See also:fun_expr/1.fun_type() -> syntaxTree()โ Creates an abstract fun of any type. The result represents"fun()".function(Name::syntaxTree(), Clauses::[syntaxTree()]) -> syntaxTree()โ Creates an abstract function definition. IfClausesis[C1, ..., Cn], the result represents"Name C1; ...; Name Cn.". More exactly, if eachCirepresents"(Pi1, ..., Pim) Gi -> Bi", then the result represents"Name(P11, ..., P1m) G1 -> B1; ...; Name(Pn1, ..., Pnm) Gn -> Bn.". Function definitions are source code forms. See also:function_arity/1,function_clauses/1,function_name/1,is_form/1.function_arity(Node::syntaxTree()) -> arity()โ Returns the arity of afunctionnode. The result is the number of parameter patterns in the first clause of the function; subsequent clauses are ignored. An exception is thrown iffunction_clauses(Node)returns an empty list, or if the first element of that list is not a syntax treeCof typeclausesuch thatclause_patterns(C)is a nonempty list. See also:clause/3,clause_patterns/1,function/2,function_clauses/1.function_clauses(Node::syntaxTree()) -> [syntaxTree()]โ Returns the list of clause subtrees of afunctionnode. See also:function/2.function_name(Node::syntaxTree()) -> syntaxTree()โ Returns the name subtree of afunctionnode. See also:function/2.function_type(Type) -> term()โ Equivalent tofunction_type(any_arity, Type).function_type(Arguments::any_arity | [syntaxTree()], Return::syntaxTree()) -> syntaxTree()function_type(Arguments, Return)โ bestie this one builds an abstract function type โจ If Arguments is[T1, ..., Tn], then when it sits inside a function specification the result stands for(T1, ...Tn) -> Return; anywhere else it stands forfun((T1, ...Tn) -> Return). And if Arguments isany_arity, it stands forfun((...) -> Return). ๐
Heads up fr: theerl_parserepresentation is literally identical forFunctionTypeandfun(FunctionType). ๐ญ iconic but confusing, ik.
See also: function_type_arguments/1, function_type_return/1.
function_type_arguments(Node)โ returns the argument type subtrees of afunction_typenode. If Node representsfun((...) -> Return), you getany_arityback; otherwise, if Node represents(T1, ...Tn) -> Returnorfun((T1, ...Tn) -> Return), you get[T1, ..., Tn].Nodeis asyntaxTree(), the return isany_arity | [syntaxTree()]. ๐ฆ
See also: function_type/1, function_type/2.
function_type_return(Node)โ grabs the return type subtrees of afunction_typenode, no cap. ๐
See also: function_type/1, function_type/2.
generator(Pattern, Body)โ creates an abstract generator and the result representsPattern <- Body. periodt. โจ
See also: binary_comp/2, generator_body/1, generator_pattern/1, list_comp/2.
generator_body(Node)โ returns the body subtree of ageneratornode. ๐ซถ
See also: generator/2.
generator_pattern(Node)โ returns the pattern subtree of ageneratornode. ๐
See also: generator/2.
get_ann(Tree)โ returns the list of user annotations chillin' on a syntax tree node. For a freshly created node this is the empty list, and the annotations can be literally any terms.[term()]in,[term()]out, we love a flexible queen. ๐
See also: get_attrs/1, set_ann/2.
get_attrs(Tree)โ returns a representation of all the attributes attached to a syntax tree node. The attributes are all the extra info that can be attached to a node, which rn includes position information, source code comments, and user annotations. The result of this function cannot be inspected directly โ you can only attach it to another node (seeset_attrs/2). it's giving "look but don't touch" energy ๐
For accessing individual attributes, see get_pos/1, get_ann/1, get_precomments/1 and get_postcomments/1.
See also: get_ann/1, get_pos/1, get_postcomments/1, get_precomments/1, set_attrs/2.
get_pos(Tree)โ returns the annotation (seeerl_anno(3erl)) associated with Node. By default, all new tree nodes have their associated position info set to the integer zero. Useerl_anno:location/1orerl_anno:line/1to actually get the position info out. ๐
See also: get_attrs/1, set_pos/2.
get_postcomments(Tree)โ returns the post-comments of a node, which is a possibly empty list of abstract comments in top-down textual order. When the code is formatted, post-comments are typically displayed to the right of and/or below the node. for example:
{foo, X, Y} % Post-comment of tuple
If possible, the comment should be moved past any following separator characters on the same line, rather than putting the separators on the following line. E.g.:
foo([X | Xs], Y) ->
foo(Xs, bar(X)); % Post-comment of 'bar(X)' node
...
(where the comment is moved past the rightmost ")" and the ";"). iykyk ๐
See also: comment/2, get_attrs/1, get_precomments/1, set_postcomments/2.
get_precomments(Tree)โ returns the pre-comments of a node, also a possibly empty list of abstract comments in top-down textual order. When the code is formatted, pre-comments are typically displayed directly above the node. like:
% Pre-comment of function
foo(X) -> {bar, X}.
If possible, the comment should be moved before any preceding separator characters on the same line. E.g.:
foo([X | Xs]) ->
% Pre-comment of 'bar(X)' node
[bar(X) | foo(Xs)];
...
(where the comment is moved before the "["). ๐ธ
See also: comment/2, get_attrs/1, get_postcomments/1, set_precomments/2.
has_comments(Tree)โ yieldsfalseif the node has no associated comments andtrueotherwise. a little vibe check for comments ๐
Note: this is equivalent to(get_precomments(Node) == [])and(get_postcomments(Node) == []), but potentially more efficient. efficiency slay.
See also: get_postcomments/1, get_precomments/1, remove_comments/1.
if_expr(Clauses)โ creates an abstract if-expression. If Clauses is[C1, ..., Cn], the result representsif C1; ...; Cn end. More exactly, if eachCirepresents() Gi -> Bi, then the result representsif G1 -> B1; ...; Gn -> Bn end. main character if-statement energy fr ๐ฅ
See also: case_expr/2, clause/3, if_expr_clauses/1.
if_expr_clauses(Node)โ returns the list of clause subtrees of anif_exprnode. literally just the clauses, bestie. ๐
See also: if_expr/1.
implicit_fun(Name)โ creates an abstract "implicit fun" expression, and the result representsfun Name. Name should represent eitherF/AorM:F/A. ๐
See also: arity_qualifier/2, implicit_fun/2, implicit_fun/3, implicit_fun_name/1, module_qualifier/2.
implicit_fun(Name, Arity)โ also creates an abstract "implicit fun" expression. If Arity isnone, this is equivalent toimplicit_fun(Name); otherwise it's equivalent toimplicit_fun(arity_qualifier(Name, Arity)). โจ
(This is a utility function.)
See also: implicit_fun/1, implicit_fun/3.
implicit_fun(Module, Name, Arity)โ creates an abstract module-qualified "implicit fun" expression. If Module isnone, this is equivalent toimplicit_fun(Name, Arity); otherwise it's equivalent toimplicit_fun(module_qualifier(Module, arity_qualifier(Name, Arity)). ๐ฆ
(This is a utility function.)
See also: implicit_fun/1, implicit_fun/2.
implicit_fun_name(Node)โ returns the name subtree of animplicit_funnode. ๐
Note: if Node representsfun N/Aorfun M:N/A, then the result is the subtree representingN/AorM:N/A, respectively. yes the whole qualifier, don't @ me.
See also: arity_qualifier/2, implicit_fun/1, module_qualifier/2.
infix_expr(Left, Operator, Right)โ creates an abstract infix operator expression, and the result representsLeft Operator Right. iconic trio fr ๐
See also: infix_expr_left/1, infix_expr_operator/1, infix_expr_right/1, prefix_expr/2.
infix_expr_left(Node)โ returns the left argument subtree of aninfix_exprnode. ๐ซถ
See also: infix_expr/3.
infix_expr_operator(Node)โ returns the operator subtree of aninfix_exprnode. the moment the operator gets its own solo ๐ค
See also: infix_expr/3.
infix_expr_right(Node)โ returns the right argument subtree of aninfix_exprnode. ๐
See also: infix_expr/3.
integer(Value)โ creates an abstract integer literal. The lexical representation is the canonical decimal numeral of Value. cute and canonical. ๐ข
See also: integer_literal/1, integer_value/1, is_integer/2.
integer_literal(Node)โ returns the numeral string represented by anintegernode. returns astring(), not a number, don't get it twisted bestie. ๐
See also: integer/1.
integer_range_type(Low, High)โ creates an abstract range type, and the result representsLow .. High. ๐ธ
See also: integer_range_type_high/1, integer_range_type_low/1.
integer_range_type_high(Node)โ returns the high limit of aninteger_range_typenode. the ceiling, literally. โ๏ธ
See also: integer_range_type/2.
integer_range_type_low(Node)โ returns the low limit of aninteger_range_typenode. the floor, literally. ๐ฑ
See also: integer_range_type/2.
integer_value(Node)โ returns the value represented by anintegernode. the actual number this time,integer(). ๐ฅ
See also: integer/1.
is_atom(Node, Value)โ returnstrueif Node has typeatomand represents Value, otherwisefalse. vibe check: passed or failed, no in between. โจ
See also: atom/1.
is_char(Node, Value)โ returnstrueif Node has typecharand represents Value, otherwisefalse. ๐
See also: char/1.
is_form(Node)โ returnstrueif Node is a syntax tree representing a so-called "source code form", otherwisefalse. Forms are the Erlang source code units which, placed in sequence, constitute an Erlang program. the current form types are:
attribute comment error_marker eof_marker
form_list function warning_marker text
See also: attribute/2, comment/2, eof_marker/0, error_marker/1, form_list/1, function/2, type/1, warning_marker/1.
is_integer(Node, Value)โ returnstrueif Node has typeintegerand represents Value, otherwisefalse. ๐งฎ
See also: integer/1.
is_leaf(Node)โ returnstrueif Node is a leaf node, otherwisefalse. the currently recognised leaf node types are:
atom char comment eof_marker error_marker
float fun_type integer nil operator string
text underscore variable warning_marker
A node of type map_expr is a leaf node if and only if it has no argument and no fields. A node of type map_type is a leaf node if and only if it has no fields (any_size). A node of type tuple is a leaf node if and only if its arity is zero. A node of type tuple_type is a leaf node if and only if it has no elements (any_size). ๐
okay those last four are the sneaky ones, memorize them for the test bestie ๐
Note: not all literals are leaf nodes, and vice versa ๐ e.g., tuples with nonzero arity and nonempty lists may be literals, but they are not leaf nodes. Variables, on the other hand, are leaf nodes but not literals.
See also: is_literal/1, type/1.
is_list_skeleton(Node::syntaxTree()) -> boolean()โ gives youtrueifNodehas typelistornil, andfalseotherwise. No cap.
See also: list/2, nil/0.
is_literal(T::syntaxTree()) -> boolean()โtrueifNoderepresents a literal term,falseif not. It returnstrueif and only if the value ofconcrete(Node)is defined, so like, that's the whole vibe check. โจ
See also: abstract/1, concrete/1.
is_proper_list(Node::syntaxTree()) -> boolean()โtrueifNoderepresents a proper list, otherwisefalse. A proper list is a list skeleton that's either on the form"[]"or"[E1, ..., En]", or"[... | Tail]"where โ recursively โTailalso represents a proper list. ๐
Note: since Node is a syntax tree, the actual run-time values corresponding to its subtrees may often be partially or completely unknown ๐ so if Node represents e.g. "[... | Ns]" (where Ns is a variable), the function returns false, because it's literally not known whether Ns will be bound to a list at run-time. But if Node instead represents e.g. "[1, 2, 3]" or "[A | []]", then the function returns true. Bestie, it's just being honest about what it knows.
See also: list/2.
is_string(Node::syntaxTree(), Value::string()) -> boolean()โtrueifNodehas typestringand representsValue, otherwisefalse.
See also: string/1.
is_tree(Tree::syntaxTree()) -> boolean()โ for special purposes only ๐ซถ returnstrueifTreeis an abstract syntax tree andfalseotherwise.
Note: this function yields false for all "old-style" erl_parse-compatible "parse trees".
See also: tree/2.
join_comments(Source::syntaxTree(), Target::syntaxTree()) -> syntaxTree()โ appends the comments ofSourceto the current comments ofTarget. Gluing the gossip together, fr fr. ๐ฌ
Note: this is equivalent to add_postcomments(get_postcomments(Source), add_precomments(get_precomments(Source), Target)), but potentially more efficient. Slay.
See also: add_postcomments/2, add_precomments/2, comment/2, get_postcomments/1, get_precomments/1.
list(List::[syntaxTree()]) -> syntaxTree()โ equivalent tolist(List, none).list(Elements::[syntaxTree()], Tail::none | syntaxTree()) -> syntaxTree()โ constructs an abstract list skeleton ๐ฅ the result has typelistornil. IfListis a nonempty list[E1, ..., En], the result has typelistand represents either"[E1, ..., En]", ifTailisnone, or otherwise"[E1, ..., En | Tail]". IfListis the empty list,Tailmust benone, and in that case the result has typeniland represents"[]"(seenil/0). ๐
The difference between lists as semantic objects (built up of individual "cons" and "nil" terms) and the various syntactic forms for denoting lists may be bewildering at first ๐ญ this module provides functions both for exact control of the syntactic representation as well as for the simple composition and deconstruction in terms of cons and head/tail operations.
Note: in list(Elements, none), the "nil" list terminator is implicit and has no associated information (see get_attrs/1), while in the seemingly equivalent list(Elements, Tail) when Tail has type nil, the list terminator subtree Tail may have attached attributes such as position, comments, and annotations, which will be preserved in the result. So like โ not the same thing under the hood, okay? ๐
See also: compact_list/1, cons/2, get_attrs/1, is_list_skeleton/1, is_proper_list/1, list/1, list_elements/1, list_head/1, list_length/1, list_prefix/1, list_suffix/1, list_tail/1, nil/0, normalize_list/1.
list_comp(Template::syntaxTree(), Body::[syntaxTree()]) -> syntaxTree()โ creates an abstract list comprehension โจ ifBodyis[E1, ..., En], the result represents"[Template || E1, ..., En]".
See also: generator/2, list_comp_body/1, list_comp_template/1.
list_comp_body(Node::syntaxTree()) -> [syntaxTree()]โ returns the list of body subtrees of alist_compnode.
See also: list_comp/2.
list_comp_template(Node::syntaxTree()) -> syntaxTree()โ returns the template subtree of alist_compnode.
See also: list_comp/2.
list_elements(Node::syntaxTree()) -> [syntaxTree()]โ returns the list of element subtrees of a list skeleton ๐Nodemust represent a proper list. E.g., ifNoderepresents"[X1, X2 | [X3, X4 | []]]", thenlist_elements(Node)yields the list[X1, X2, X3, X4].
See also: is_proper_list/1, list/2.
list_head(Node::syntaxTree()) -> syntaxTree()โ returns the head element subtree of a list node ๐ธ ifNoderepresents"[Head ...]", the result will represent"Head".
See also: cons/2, list/2, list_tail/1.
list_length(Node::syntaxTree()) -> non_neg_integer()โ returns the number of element subtrees of a list skeleton.Nodemust represent a proper list. E.g., ifNoderepresents"[X1 | [X2, X3 | [X4, X5, X6]]]", thenlist_length(Node)returns the integer6. Maths ate, honestly. ๐ข
Note: this is equivalent to length(list_elements(Node)), but potentially more efficient.
See also: is_proper_list/1, list/2, list_elements/1.
list_prefix(Node::syntaxTree()) -> [syntaxTree()]โ returns the prefix element subtrees of a list node ๐ฆ ifNoderepresents"[E1, ..., En]"or"[E1, ..., En | Tail]", the returned value is[E1, ..., En].
See also: list/2.
list_suffix(Node::syntaxTree()) -> none | syntaxTree()โ returns the suffix subtree of a list node, if one exists. IfNoderepresents"[E1, ..., En | Tail]", the returned value isTail; otherwise, i.e., ifNoderepresents"[E1, ..., En]",noneis returned.
Note that even if this function returns some Tail that is not none, the type of Tail can be nil, if the tail has been given explicitly, and the list skeleton has not been compacted (see compact_list/1). Sneaky little detail, iykyk. ๐
See also: compact_list/1, list/2, nil/0.
list_tail(Node::syntaxTree()) -> syntaxTree()โ returns the tail of a list node. IfNoderepresents a single-element list"[E]", then the result has typenil, representing"[]". IfNoderepresents"[E1, E2 ...]", the result will represent"[E2 ...]", and ifNoderepresents"[Head | Tail]", the result will represent"Tail". ๐
See also: cons/2, list/2, list_head/1.
macro(Name::syntaxTree()) -> syntaxTree()โ equivalent tomacro(Name, none).macro(Name::syntaxTree(), Arguments::none | [syntaxTree()]) -> syntaxTree()โ creates an abstract macro application ๐ง ifArgumentsisnone, the result represents"?Name", otherwise, ifArgumentsis[A1, ..., An], the result represents"?Name(A1, ..., An)".
Notes: if Arguments is the empty list, the result will thus represent "?Name()", including a pair of matching parentheses. Not me stressing about the parens โ they're included, bestie. ๐
The only syntactical limitation imposed by the preprocessor on the arguments to a macro application (viewed as sequences of tokens) is that they must be balanced with respect to parentheses, brackets, begin ... end, case ... end, etc. The text node type can be used to represent arguments which are not regular Erlang constructs.
See also: macro/1, macro_arguments/1, macro_name/1, text/1.
macro_arguments(Node::syntaxTree()) -> none | [syntaxTree()]โ returns the list of argument subtrees of a macro node, if any. IfNoderepresents"?Name",noneis returned. Otherwise, ifNoderepresents"?Name(A1, ..., An)",[A1, ..., An]is returned. ๐ซถ
See also: macro/2.
macro_name(Node::syntaxTree()) -> syntaxTree()โ returns the name subtree of a macro node.
See also: macro/2.
make_tree(X1::atom(), X2::[[syntaxTree()]]) -> syntaxTree()โ creates a syntax tree with the given type and subtrees ๐Typemust be a node type name (seetype/1) that does not denote a leaf node type (seeis_leaf/1).Groupsmust be a nonempty list of groups of syntax trees, representing the subtrees of a node of the given type, in left-to-right order as they would occur in the printed program text, grouped by category as done bysubtrees/1.
The result of copy_attrs(Node, make_tree(type(Node), subtrees(Node))) (see update_tree/2) represents the same source code text as the original Node, assuming that subtrees(Node) yields a nonempty list. However, it does not necessarily have the same data representation as Node. So same text, different internals โ that's the tea. โ
See also: copy_attrs/2, is_leaf/1, subtrees/1, type/1, update_tree/2.
map_expr(Fields::[syntaxTree()]) -> syntaxTree()โ equivalent tomap_expr(none, Fields).map_expr(Argument::none | syntaxTree(), Fields::[syntaxTree()]) -> syntaxTree()โ creates an abstract map expression ๐บ๏ธ ifFieldsis[F1, ..., Fn], then ifArgumentisnone, the result represents"#{F1, ..., Fn}"; otherwise it represents"Argument#{F1, ..., Fn}". Both forms, both iconic.
See also: map_expr/1, map_expr_argument/1, map_expr_fields/1, map_field_assoc/2, map_field_exact/2.
map_expr_argument(Node::syntaxTree()) -> none | syntaxTree()โ returns the argument subtree of amap_exprnode, if any. IfNoderepresents"#{...}",noneis returned. Otherwise, ifNoderepresents"Argument#{...}",Argumentis returned.
See also: map_expr/2.
map_expr_fields(Node::syntaxTree()) -> [syntaxTree()]โ returns the list of field subtrees of amap_exprnode.
See also: map_expr/2.
map_field_assoc(Name::syntaxTree(), Value::syntaxTree()) -> syntaxTree()โ creates an abstract map assoc field ๐ the result represents"Name => Value".
See also: map_expr/2, map_field_assoc_name/1, map_field_assoc_value/1.
map_field_assoc_name(Node::syntaxTree()) -> syntaxTree()โ returns the name subtree of amap_field_assocnode.
See also: map_field_assoc/2.
map_field_assoc_value(Node::syntaxTree()) -> syntaxTree()โ returns the value subtree of amap_field_assocnode.
See also: map_field_assoc/2.
map_field_exact(Name::syntaxTree(), Value::syntaxTree()) -> syntaxTree()โ creates an abstract map exact field โญ the result represents"Name := Value". Note the:=โ different operator, different energy.
See also: map_expr/2, map_field_exact_name/1, map_field_exact_value/1.
map_field_exact_name(Node::syntaxTree()) -> syntaxTree() ๐
Grabs the name subtree out of a map_field_exact node. That's it, that's the whole job, and she does it flawlessly.
See also: map_field_exact/2.
map_field_exact_value(Node::syntaxTree()) -> syntaxTree() ๐
And this one grabs the value subtree of a map_field_exact node. Name and value, two little besties, both slay.
See also: map_field_exact/2.
map_type() -> term() ๐บ๏ธ
Literally just map_type(any_size). Same vibe, fewer arguments. Note the return type says term() โ that's what the page says, don't come for me.
map_type(Fields::any_size | [syntaxTree()]) -> syntaxTree() ๐บ๏ธโจ
Builds an abstract type map. So here's the tea:
- if
Fieldsis[F1, ..., Fn], your result represents#{F1, ..., Fn} - otherwise, if
Fieldsisany_size, it representsmap()
See also: map_type_fields/1.
map_type_assoc(Name::syntaxTree(), Value::syntaxTree()) -> syntaxTree() ๐
Makes an abstract map type assoc field. The result represents Name => Value. That's the => one, bestie โ assoc, not exact.
See also: map_type/1, map_type_assoc_name/1, map_type_assoc_value/1.
map_type_assoc_name(Node::syntaxTree()) -> syntaxTree() ๐
Returns the name subtree of a map_type_assoc node. Name first, always.
See also: map_type_assoc/2.
map_type_assoc_value(Node::syntaxTree()) -> syntaxTree() ๐
Returns the value subtree of a map_type_assoc node. Iconic pairing.
See also: map_type_assoc/2.
map_type_exact(Name::syntaxTree(), Value::syntaxTree()) -> syntaxTree() ๐ฏ
Makes an abstract map type exact field. The result represents Name := Value. Yes, := โ the strict one, she does not play about exactness.
See also: map_type/1, map_type_exact_name/1, map_type_exact_value/1.
map_type_exact_name(Node::syntaxTree()) -> syntaxTree() ๐ฏ
Returns the name subtree of a map_type_exact node.
See also: map_type_exact/2.
map_type_exact_value(Node::syntaxTree()) -> syntaxTree() ๐ฏ
Returns the value subtree of a map_type_exact node.
See also: map_type_exact/2.
map_type_fields(Node::syntaxTree()) -> any_size | [syntaxTree()] ๐
Gives you the list of field subtrees of a map_type node. And listen:
- if
Noderepresentsmap(), you getany_sizeback - otherwise, if
Noderepresents#{F1, ..., Fn}, you get[F1, ..., Fn]
See also: map_type/0, map_type/1.
match_expr(Pattern::syntaxTree(), Body::syntaxTree()) -> syntaxTree() ๐ช
Makes an abstract match-expression. The result represents Pattern = Body. The classic.
See also: match_expr_body/1, match_expr_pattern/1.
match_expr_body(Node::syntaxTree()) -> syntaxTree() ๐ช
Returns the body subtree of a match_expr node.
See also: match_expr/2.
match_expr_pattern(Node::syntaxTree()) -> syntaxTree() ๐ช
Returns the pattern subtree of a match_expr node.
See also: match_expr/2.
maybe_expr(Body::[syntaxTree()]) -> syntaxTree() ๐ค
Equivalent to maybe_expr(Body, none). The "no else clause, we're keeping it simple" flavour.
maybe_expr(Body::[syntaxTree()], OptionalElse::none | syntaxTree()) -> syntaxTree() ๐คโจ
Makes an abstract maybe-expression. Breaking it down:
- if
Bodyis[B1, ..., Bn]andOptionalElseisnone, the result representsmaybe B1, ..., Bn end - if
Bodyis[B1, ..., Bn]andOptionalElserepresents anelse_exprnode with clauses[C1, ..., Cn], the result representsmaybe B1, ..., Bn else C1; ..., Cn end
Heads up: seeclausefor the documentation onerl_parseclauses. That's where the clause lore lives, iykyk.
See also: maybe_expr_body/1, maybe_expr_else/1.
maybe_expr_body(Node::syntaxTree()) -> [syntaxTree()] ๐ค
Returns the list of body subtrees of a maybe_expr node. Plural โ it's a whole list, not one.
See also: maybe_expr/2.
maybe_expr_else(Node::syntaxTree()) -> none | syntaxTree() ๐ค
Returns the else subtree of a maybe_expr node โ or none, if she didn't have one. No else clause, no problem.
See also: maybe_expr/2.
maybe_match_expr(Pattern::syntaxTree(), Body::syntaxTree()) -> syntaxTree() ๐ช
Makes an abstract maybe-expression, the kind you use inside maybe blocks. The result represents Pattern ?= Body. The ?= operator, the moment, the icon.
See also: maybe_expr/2, maybe_match_expr_body/1, maybe_match_expr_pattern/1.
maybe_match_expr_body(Node::syntaxTree()) -> syntaxTree() ๐ช
Returns the body subtree of a maybe_expr node. (Yes, the original says maybe_expr here โ copying the facts exactly, bestie, not my typo to fix.)
See also: maybe_match_expr/2.
maybe_match_expr_pattern(Node::syntaxTree()) -> syntaxTree() ๐ช
Returns the pattern subtree of a maybe_expr node. Same deal as above, facts are facts.
See also: maybe_match_expr/2.
meta(T::syntaxTree()) -> syntaxTree() ๐งโโ๏ธโจ
Okay this one is the main character of the section, so buckle up.
meta/1 creates a meta-representation of a syntax tree. The result represents an Erlang expression MetaTree which, if evaluated, will yield a new syntax tree representing the same source code text as Tree โ although the actual data representation may be different. The expression represented by MetaTree is implementation independent with regard to the data structures used by the abstract syntax tree implementation. Comments attached to nodes of Tree will be preserved, but other attributes are lost.
Here's the special-case lore: any node in Tree whose node type is variable (see type/1), and whose list of annotations (see get_ann/1) contains the atom meta_var, will remain unchanged in the resulting tree โ except that exactly one occurrence of meta_var is removed from its annotation list. One. Not zero, not two. Exactly one. ๐
The main use of meta/1 is to transform a data structure Tree, which represents a piece of program code, into a form that is representation independent when printed. Example time, because examples eat:
Suppose Tree represents a variable named "V". Then (assuming a function print/1 for printing syntax trees), evaluating print(abstract(Tree)) โ simply using abstract/1 to map the actual data structure onto a syntax tree representation โ would output a string that might look something like:
{tree, variable, ..., "V", ...}
...which is obviously dependent on the implementation of the abstract syntax trees. This could e.g. be useful for caching a syntax tree in a file. However, in some situations like in a program generator generator (with two "generator"), it may be unacceptable.
Using print(meta(Tree)) instead would output a representation independent syntax tree generating expression; in the above case, something like:
erl_syntax:variable("V")
See the difference? That's the glow-up. ๐ฆ
See also: abstract/1, get_ann/1, type/1.
module_qualifier(Module::syntaxTree(), Body::syntaxTree()) -> syntaxTree() ๐
Makes an abstract module qualifier. The result represents Module:Body. Colon goes brrr.
See also: module_qualifier_argument/1, module_qualifier_body/1.
module_qualifier_argument(Node::syntaxTree()) -> syntaxTree() ๐
Returns the argument subtree of a module_qualifier node โ and yes, the argument is the module. That's the one before the colon.
See also: module_qualifier/2.
module_qualifier_body(Node::syntaxTree()) -> syntaxTree() ๐
Returns the body subtree of a module_qualifier node. That's the part after the colon.
See also: module_qualifier/2.
named_fun_expr(Name::syntaxTree(), Clauses::[syntaxTree()]) -> syntaxTree() ๐ญ
Makes an abstract named fun-expression. If Clauses is [C1, ..., Cn], the result represents:
fun Name C1; ...; Name Cn end
More exactly โ and they do mean exactly โ if each Ci represents (Pi1, ..., Pim) Gi -> Bi, then the result represents:
fun Name(P11, ..., P1m) G1 -> B1; ...; Name(Pn1, ..., Pnm) Gn -> Bn end
Recursive fun with a name, we stan. ๐
See also: named_fun_expr_arity/1, named_fun_expr_clauses/1, named_fun_expr_name/1.
named_fun_expr_arity(Node::syntaxTree()) -> arity() ๐ญ๐ข
Returns the arity of a named_fun_expr node. The result is the number of parameter patterns in the first clause of the named fun-expression; subsequent clauses are ignored. First clause is the only one getting a vibe check here.
Warning, bestie: an exception is thrown ifnamed_fun_expr_clauses(Node)returns an empty list, or if the first element of that list is not a syntax treeCof typeclausesuch thatclause_patterns(C)is a nonempty list. So like, keep your clauses valid or it's gonna be a whole thing. ๐ญ
See also: clause/3, clause_patterns/1, named_fun_expr/2, named_fun_expr_clauses/1.
named_fun_expr_clauses(Node::syntaxTree()) -> [syntaxTree()] ๐ญ
Returns the list of clause subtrees of a named_fun_expr node. All of them. The whole friend group.
See also: named_fun_expr/2.
named_fun_expr_name(Node::syntaxTree()) -> syntaxTree() ๐ญ
Returns the name subtree of a named_fun_expr node. Every named fun needs a name, hence the name.
See also: named_fun_expr/2.
nil() -> syntaxTree() ๐ณ๏ธ
Makes an abstract empty list. The result represents []. The empty list is traditionally called "nil" โ hence the function name, keep up bestie. ๐
See also: is_list_skeleton/1, list/2.
normalize_list(Node::syntaxTree()) -> syntaxTree() ๐โจ
Expands an abstract list skeleton to its most explicit form. Like taking off the filter, no cap. Here's the breakdown:
- if
Noderepresents[E1, ..., En | Tail], the result represents[E1 | ... [En | Tail1] ... ], whereTail1is the result ofnormalize_list(Tail) - if
Noderepresents[E1, ..., En], the result simply represents[E1 | ... [En | []] ... ] - if
Nodedoes not represent a list skeleton,Nodeitself is returned โ untouched, unbothered, thriving
See also: compact_list/1, list/2.
operator(Name::atom() | string()) -> syntaxTree() ๐ช
Makes an abstract operator. The name of the operator is the character sequence represented by Name.
This is analogous to the print name of an atom, BUT โ and this is the โจkeyโจ difference โ an operator is never written within single-quotes. E.g., the result of operator('++') represents ++ rather than '++'. No quotes, she's free.
See also: atom/1, operator_literal/1, operator_name/1.
operator_literal(Node::syntaxTree()) -> string() ๐ช
Returns the literal string represented by an operator node. This is simply the operator name as a string. Literally just that.
See also: operator/1.
operator_name(Node::syntaxTree()) -> atom() ๐ช
Returns the name of an operator node. Note that the name is returned as an atom. Atom, not string โ read the return type, bestie, it's giving attention to detail.
See also: operator/1.
parentheses(Expr::syntaxTree()) -> syntaxTree() ๐ซถ
Makes an abstract parenthesised expression. The result represents (Body), independently of the context. She said what she said, parentheses stay on.
See also: parentheses_body/1.
parentheses_body(Node::syntaxTree()) -> syntaxTree() ๐ซถ
Returns the body subtree of a parentheses node. The stuff inside the brackets.
See also: parentheses/1.
prefix_expr(Operator::syntaxTree(), Argument::syntaxTree()) -> syntaxTree() โฌ
๏ธ
Makes an abstract prefix operator expression. The result represents Operator Argument. Operator first, argument second, order matters.
See also: infix_expr/3, prefix_expr_argument/1, prefix_expr_operator/1.
prefix_expr_argument(Node::syntaxTree()) -> syntaxTree() โฌ
๏ธ
Returns the argument subtree of a prefix_expr node.
See also: prefix_expr/2.
prefix_expr_operator(Node::syntaxTree()) -> syntaxTree() โฌ
๏ธ
Returns the operator subtree of a prefix_expr node.
See also: prefix_expr/2.
receive_expr(Clauses::[syntaxTree()]) -> syntaxTree()
Literally just shorthand, bestie โ same energy as receive_expr(Clauses, none, []). โจ
receive_expr(Clauses::[syntaxTree()], Timeout::none | syntaxTree(), Action::[syntaxTree()]) -> syntaxTree()
Okay so this one builds you an abstract receive-expression ๐
- If
Timeoutisnone, what you get back represents"receive C1; ...; Cn end"โ and yeah, theActionargument just gets ignored completely, it's giving background character ๐ - Otherwise, if
Clausesis[C1, ..., Cn]andActionis[A1, ..., Am], the result represents"receive C1; ...; Cn after Timeout -> A1, ..., Am end".
To be super precise about it: if each Ci represents "(Pi) Gi -> Bi", then the result represents "receive P1 G1 -> B1; ...; Pn Gn -> Bn ... end".
Heads up, no cap: in Erlang, a receive-expression must have at least one clause if you don't specify a timeout part. That's the rule, respect it ๐ซถ
See also: case_expr/2, clause/3, receive_expr/1, receive_expr_action/1, receive_expr_clauses/1, receive_expr_timeout/1.
receive_expr_action(Node::syntaxTree()) -> [syntaxTree()]
Hands you back the list of action body subtrees of a receive_expr node. And if Node represents "receive C1; ...; Cn end", you get the empty list โ sorry, nothing in the fridge ๐
See also: receive_expr/3.
receive_expr_clauses(Node::syntaxTree()) -> [syntaxTree()]
Returns the list of clause subtrees of a receive_expr node. Iconic behaviour, honestly ๐
See also: receive_expr/3.
receive_expr_timeout(Node::syntaxTree()) -> none | syntaxTree()
Returns the timeout subtree of a receive_expr node, if there even is one:
- If
Noderepresents"receive C1; ...; Cn end", you getnoneback. - Otherwise, if
Noderepresents"receive C1; ...; Cn after Timeout -> ... end", you getTimeoutback. Slay ๐ธ
See also: receive_expr/3.
record_access(Argument::syntaxTree(), Type::syntaxTree(), Field::syntaxTree()) -> syntaxTree()
Makes an abstract record field access expression, and the result represents "Argument#Type.Field". Very demure, very #-core ๐
See also: record_access_argument/1, record_access_field/1, record_access_type/1, record_expr/3.
record_access_argument(Node::syntaxTree()) -> syntaxTree()
Returns the argument subtree of a record_access node. That's the whole vibe of the thing before the #.
See also: record_access/3.
record_access_field(Node::syntaxTree()) -> syntaxTree()
Returns the field subtree of a record_access node โ the bit after the dot ๐
See also: record_access/3.
record_access_type(Node::syntaxTree()) -> syntaxTree()
Returns the type subtree of a record_access node โ the bit between the # and the ., iykyk.
See also: record_access/3.
record_expr(Type::syntaxTree(), Fields::[syntaxTree()]) -> syntaxTree()
Equivalent to record_expr(none, Type, Fields). Short and sweet, we love a wrapper โจ
record_expr(Argument::none | syntaxTree(), Type::syntaxTree(), Fields::[syntaxTree()]) -> syntaxTree()
Creates an abstract record expression, okay so check it: if Fields is [F1, ..., Fn], then...
- if
Argumentisnone, the result represents"#Type{F1, ..., Fn}"๐ฆ - otherwise it represents
"Argument#Type{F1, ..., Fn}"
Both valid, both cute, pick your fighter.
See also: record_access/3, record_expr/2, record_expr_argument/1, record_expr_fields/1, record_expr_type/1, record_field/2, record_index_expr/2.
record_expr_argument(Node::syntaxTree()) -> none | syntaxTree()
Returns the argument subtree of a record_expr node, if there is one:
- If
Noderepresents"#Type{...}", you getnone. - Otherwise, if
Noderepresents"Argument#Type{...}", you getArgumentback. Periodt ๐
See also: record_expr/3.
record_expr_fields(Node::syntaxTree()) -> [syntaxTree()]
Returns the list of field subtrees of a record_expr node. All of them, no gatekeeping ๐
See also: record_expr/3.
record_expr_type(Node::syntaxTree()) -> syntaxTree()
Returns the type subtree of a record_expr node. The main character of the record, honestly ๐
See also: record_expr/3.
record_field(Name::syntaxTree()) -> syntaxTree()
Equivalent to record_field(Name, none). Yeah, it's that easy ๐
record_field(Name::syntaxTree(), Value::none | syntaxTree()) -> syntaxTree()
Creates an abstract record field specification:
- If
Valueisnone, the result represents simply"Name"โ minimal, clean, lowkey stunning โจ - Otherwise it represents
"Name = Value"๐ฅ
See also: record_expr/3, record_field_name/1, record_field_value/1.
record_field_name(Node::syntaxTree()) -> syntaxTree()
Returns the name subtree of a record_field node. The before-the-equals part ๐
See also: record_field/2.
record_field_value(Node::syntaxTree()) -> none | syntaxTree()
Returns the value subtree of a record_field node, if any:
- If
Noderepresents"Name", you getnone. - Otherwise, if
Noderepresents"Name = Value", you getValueback ๐
See also: record_field/2.
record_index_expr(Type::syntaxTree(), Field::syntaxTree()) -> syntaxTree()
Creates an abstract record field index expression, and the result represents "#Type.Field". Chef's kiss ๐ธ
Fun fact, ngl: the function namerecord_index/2is reserved by the Erlang compiler, which is literally why that name could not be used for this constructor. Sorecord_index_expr/2it is โ the compiler said "not today" ๐
See also: record_expr/3, record_index_expr_field/1, record_index_expr_type/1.
record_index_expr_field(Node::syntaxTree()) -> syntaxTree()
Returns the field subtree of a record_index_expr node. The part after the dot ๐ซถ
See also: record_index_expr/2.
record_index_expr_type(Node::syntaxTree()) -> syntaxTree()
Returns the type subtree of a record_index_expr node. The part after the # ๐ฆ
See also: record_index_expr/2.
record_type(Name::syntaxTree(), Fields::[syntaxTree()]) -> syntaxTree()
Creates an abstract record type. If Fields is [F1, ..., Fn], the result represents "#Name{F1, ..., Fn}". Very type-safe of you, bestie โจ
See also: record_type_fields/1, record_type_name/1.
record_type_field(Name::syntaxTree(), Type::syntaxTree()) -> syntaxTree()
Creates an abstract record type field, and the result represents "Name :: Type". Double colon core ๐
See also: record_type_field_name/1, record_type_field_type/1.
record_type_field_name(Node::syntaxTree()) -> syntaxTree()
Returns the name subtree of a record_type_field node. The before-the-:: part ๐
See also: record_type_field/2.
record_type_field_type(Node::syntaxTree()) -> syntaxTree()
Returns the type subtree of a record_type_field node. The after-the-:: part ๐
See also: record_type_field/2.
record_type_fields(Node::syntaxTree()) -> [syntaxTree()]
Returns the fields subtree of a record_type node. Yes, "subtree" singular in the original, we don't make the rules, we just relay them ๐
See also: record_type/2.
record_type_name(Node::syntaxTree()) -> syntaxTree()
Returns the name subtree of a record_type node. The label on the whole situation ๐
See also: record_type/2.
remove_comments(Node::syntaxTree()) -> syntaxTree()
Clears the associated comments of Node โ poof, gone, no thoughts head empty ๐ซง
Note: this is equivalent to set_precomments(set_postcomments(Node, []), []), but potentially more efficient. So like, same result, better vibes.
See also: set_postcomments/2, set_precomments/2.
revert(Node::syntaxTree()) -> syntaxTree()
Returns an erl_parse-compatible representation of a syntax tree, if possible. Like, if Tree represents a well-formed Erlang program or expression, the conversion should work without any problems at all ๐
Typically, is_tree/1 yields true if conversion failed (i.e., the result is still an abstract syntax tree), and false otherwise. Yeah, it's a little backwards, but that's the deal ๐
Real talk though: theis_tree/1test is not completely foolproof. For a few special node types (e.g.arity_qualifier), if such a node occurs in a context where it is not expected, it will be left unchanged as a non-reverted subtree of the result. This can only happen ifTreedoes not actually represent legal Erlang code. So like, it's a you-problem, not a me-problem ๐
See also: erl_parse(3erl), revert_forms/1.
revert_forms(Forms::forms()) -> [erl_parse()]
Reverts a sequence of Erlang source code forms. The sequence can be given either as a form_list syntax tree (possibly nested, because why not ๐ช) or as a list of "program form" syntax trees.
If it works, you get the corresponding flat list of erl_parse-compatible syntax trees back (see revert/1). And if some program form could not be reverted, {error, Form} is thrown. Rude, but fair ๐ญ
Standalone comments in the form sequence are discarded โ they simply do not make the cut, bye bestie ๐
See also: form_list/1, is_form/1, revert/1.
set_ann(Node::syntaxTree(), As::[term()]) -> syntaxTree()
Sets the list of user annotations of Node to Annotations. (Yes, the parameter is As in the signature and Annotations in the description โ we keep it exactly as written, don't come for me ๐
)
See also: add_ann/2, copy_ann/2, get_ann/1.
set_attrs(Node::syntaxTree(), Attr::syntaxTreeAttributes()) -> syntaxTree()
Sets the attributes of Node to Attributes. (Same deal โ Attr in the signature, Attributes in the description. Consistency is a construct โจ)
See also: copy_attrs/2, get_attrs/1.
set_pos(Node::syntaxTree(), Pos::annotation_or_location()) -> syntaxTree()
Sets the position information of Node to Pos. Now it knows exactly where it stands, literally ๐
See also: copy_pos/2, get_pos/1.
set_postcomments(Node::syntaxTree(), Cs::[syntaxTree()]) -> syntaxTree()
Sets the post-comments of Node to Comments. Comments should be a possibly empty list of abstract comments, in top-down textual order. (Note: no trailing period in the original for this one, and we respect that level of chaos ๐)
See also: add_postcomments/2, comment/2, copy_comments/2, get_postcomments/1, join_comments/2, remove_comments/1, set_precomments/2.
set_precomments(Node::syntaxTree(), Cs::[syntaxTree()]) -> syntaxTree()
Sets the pre-comments of Node to Comments. Comments should be a possibly empty list of abstract comments, in top-down textual order. Yes, it's the mirror twin of the one above, and both are iconic ๐ธ
See also: add_precomments/2, comment/2, copy_comments/2, get_precomments/1, join_comments/2, remove_comments/1, set_postcomments/2.
size_qualifier(Body::syntaxTree(), Size::syntaxTree()) -> syntaxTree()
Creates an abstract size qualifier, and the result represents "Body:Size". Colon supremacy ๐ฆ
See also: size_qualifier_argument/1, size_qualifier_body/1.
size_qualifier_argument(Node::syntaxTree()) -> syntaxTree()
Returns the argument subtree (the size) of a size_qualifier node โ parentheses and all, that's the argument part ๐ซถ
See also: size_qualifier/2.
size_qualifier_body(Node::syntaxTree()) -> syntaxTree()
Returns the body subtree of a size_qualifier node โ the part before the colon, the main event ๐
See also: size_qualifier/2.
string(String::string()) -> syntaxTree()
Creates an abstract string literal. The result represents "Text" (including the surrounding double-quotes), where Text corresponds to the sequence of characters in Value, but not representing a specific string literal. Yeah, Value โ that's what the original says, and we are nothing if not faithful โจ
For example, the result of string("x\ny") represents any and all of "x\ny", "x\12y", "x\012y" and "x\^Jy" โ see char/1. So many ways to say the same thing, and every single one of them is valid. Iconic versatility ๐
See also: char/1, is_string/2, string_literal/1, string_literal/2, string_value/1.
string_literal(Node::syntaxTree()) -> nonempty_string()
Returns the literal string represented by a string node. This includes the surrounding double-quote characters. And characters beyond 255 will be escaped โ no funny business with your extended character set, bestie ๐
string_literal(Node::syntaxTree(), X2::encoding()) -> nonempty_string()โ bestie, this hands you the literal string that a string node represents, and yes, that includes the surrounding double-quote characters ๐ . Depending on the encoding, characters beyond 255 get escaped (latin1) or copied as-is (utf8) โจ. See also:string/1.string_value(Node::syntaxTree()) -> string()โ returns the actual value represented by a string node, no cap ๐. See also:string/1.subtrees(T::syntaxTree()) -> [[syntaxTree()]]โ returns the grouped list of all the subtrees of a syntax tree, and it's giving organized ๐ธ. IfNodeis a leaf node (peepis_leaf/1), you get the empty list back. Otherwise the result is always a nonempty list containing the lists of subtrees ofNode, in left-to-right order as they occur in the printed program text, grouped by category. Often each group contains only a single subtree ๐ฆ.
Depending on the type of Node, the size of some groups may be variable (e.g., the group consisting of all the elements of a tuple), while others always contain the same number of elements โ usually exactly one (e.g., the group containing the argument expression of a case-expression). But lowkey note: the exact structure of the returned list (for a given node type) should in general not be depended upon, since it might be subject to change without notice ๐.
The function subtrees/1 and the constructor functions make_tree/2 and update_tree/2 can be a great help if one wants to traverse a syntax tree, visiting all its subtrees, but treat nodes of the tree in a uniform way in most or all cases. Using these functions makes this simple, and also assures that your code is not overly sensitive to extensions of the syntax tree data type, because any node types not explicitly handled by your code can be left to a default case ๐.
For example:
postorder(F, Tree) ->
F(case subtrees(Tree) of
[] -> Tree;
List -> update_tree(Tree,
[[postorder(F, Subtree)
|| Subtree <- Group]
|| Group <- List])
end).
maps the function F on Tree and all its subtrees, doing a post-order traversal of the syntax tree. (Note the use of update_tree/2 to preserve node attributes ๐ซถ.) For a simple function like:
f(Node) ->
case type(Node) of
atom -> atom("a_" ++ atom_name(Node));
_ -> Node
end.
the call postorder(fun f/1, Tree) will yield a new representation of Tree in which all atom names have been extended with the prefix "a_", but nothing else (including comments, annotations and line numbers) has been changed ๐. See also: copy_attrs/2, is_leaf/1, make_tree/2, type/1.
text(String::string()) -> syntaxTree()โ creates an abstract piece of source code text, and the result represents exactly the sequence of characters inString๐. This is useful in cases when one wants full control of the resulting output, e.g., for the appearance of floating-point numbers or macro definitions ๐. See also:text_string/1.text_string(Node::syntaxTree()) -> string()โ returns the character sequence represented by a text node, periodt โจ. See also:text/1.tree(Type::atom()) -> tree()โ equivalent totree(Type, [])๐.tree(Type::atom(), Data::term()) -> tree()โ for special purposes only, bestie ๐จ. Creates an abstract syntax tree node with type tagTypeand associated dataData.
This function and the related is_tree/1 and data/1 provide a uniform way to extend the set of erl_parse node types. The associated data is any term, whose format may depend on the type tag ๐.
Notes:
- Any nodes created outside of this module must have type tags distinct from those currently defined by this module; see
type/1for a complete list. - The type tag of a syntax tree node may also be used as a primary tag by the
erl_parserepresentation; in that case, the selector functions for that node type must handle both the abstract syntax tree and theerl_parseform. The functiontype(T)should return the correct type tag regardless of the representation ofT, so that the user sees no difference betweenerl_syntaxanderl_parsenodes ๐.
See also: data/1, is_tree/1, type/1.
try_after_expr(Body::[syntaxTree()], After::[syntaxTree()]) -> syntaxTree()โ equivalent totry_expr(Body, [], [], After)๐ฆ.try_expr(Body::[syntaxTree()], Handlers::[syntaxTree()]) -> syntaxTree()โ equivalent totry_expr(Body, [], Handlers)๐ธ.try_expr(Body::[syntaxTree()], Clauses::[syntaxTree()], Handlers::[syntaxTree()]) -> syntaxTree()โ equivalent totry_expr(Body, Clauses, Handlers, [])๐ .try_expr(Body::[syntaxTree()], Clauses::[syntaxTree()], Handlers::[syntaxTree()], After::[syntaxTree()]) -> syntaxTree()โ creates an abstract try-expression, and the way this maps out is kind of iconic ๐. IfBodyis[B1, ..., Bn],Clausesis[C1, ..., Cj],Handlersis[H1, ..., Hk], andAfteris[A1, ..., Am], the result represents"try B1, ..., Bn of C1; ...; Cj catch H1; ...; Hk after A1, ..., Am end"๐ฅ. More exactly, if eachCirepresents"(CPi) CGi -> CBi", and eachHirepresents"(HPi) HGi -> HBi", then the result represents"try B1, ..., Bn of CP1 CG1 -> CB1; ...; CPj CGj -> CBj catch HP1 HG1 -> HB1; ...; HPk HGk -> HBk after A1, ..., Am end"; seecase_expr/2โจ. IfClausesis the empty list, theof ...section is left out. IfAfteris the empty list, theafter ...section is left out. IfHandlersis the empty list, andAfteris nonempty, thecatch ...section is left out ๐. See also:case_expr/2,class_qualifier/2,clause/3,try_after_expr/2,try_expr/2,try_expr/3,try_expr_after/1,try_expr_body/1,try_expr_clauses/1,try_expr_handlers/1.try_expr_after(Node::syntaxTree()) -> [syntaxTree()]โ returns the list of"after"subtrees of atry_exprnode, no cap ๐ซถ. See also:try_expr/4.try_expr_body(Node::syntaxTree()) -> [syntaxTree()]โ returns the list of body subtrees of atry_exprnode ๐. See also:try_expr/4.try_expr_clauses(Node::syntaxTree()) -> [syntaxTree()]โ returns the list of case-clause subtrees of atry_exprnode. IfNoderepresents"try Body catch H1; ...; Hn end", the result is the empty list ๐. See also:try_expr/4.try_expr_handlers(Node::syntaxTree()) -> [syntaxTree()]โ returns the list of handler-clause subtrees of atry_exprnode ๐ธ. See also:try_expr/4.tuple(List::[syntaxTree()]) -> syntaxTree()โ creates an abstract tuple. IfElementsis[X1, ..., Xn], the result represents"{X1, ..., Xn}"๐.
Note: The Erlang language has distinct 1-tuples, i.e., {X} is always distinct from X itself ๐.
See also: tuple_elements/1, tuple_size/1.
tuple_elements(Node::syntaxTree()) -> [syntaxTree()]โ returns the list of element subtrees of a tuple node โจ. See also:tuple/1.tuple_size(Node::syntaxTree()) -> non_neg_integer()โ returns the number of elements of a tuple node ๐ข.
Note: this is equivalent to length(tuple_elements(Node)), but potentially more efficient ๐
.
See also: tuple/1, tuple_elements/1.
tuple_type() -> term()โ equivalent totuple_type(any_size)๐.tuple_type(Elements::any_size | [syntaxTree()]) -> syntaxTree()โ creates an abstract type tuple. IfElementsis[T1, ..., Tn], the result represents"{T1, ..., Tn}"; otherwise, ifElementsisany_size, it represents"tuple()"๐ฆ. See also:tuple_type_elements/1.tuple_type_elements(Node::syntaxTree()) -> any_size | [syntaxTree()]โ returns the list of type element subtrees of atuple_typenode. IfNoderepresents"tuple()",any_sizeis returned; otherwise, ifNoderepresents"{T1, ..., Tn}",[T1, ..., Tn]is returned ๐. See also:tuple_type/0,tuple_type/1.type(Tree::syntaxTree()) -> atom()โ returns the type tag ofNode. IfNodedoes not represent a syntax tree, evaluation fails with reasonbadarg๐. Node types currently defined by this module are:
application annotated_type arity_qualifier atom
attribute binary binary_field bitstring_type
block_expr case_expr catch_expr char
class_qualifier clause comment conjunction
constrained_function_type constraint disjunction
else_expr eof_marker error_marker
float form_list fun_expr fun_type function function_type
generator
if_expr implicit_fun infix_expr integer
integer_range_type list list_comp macro
map_expr map_field_assoc map_field_exact map_type
map_type_assoc map_type_exact match_expr
maybe_expr maybe_match_expr module_qualifier
named_fun_expr nil operator parentheses
prefix_expr receive_expr record_access record_expr
record_field record_index_expr record_type record_type_field
size_qualifier string text try_expr
tuple tuple_type typed_record_field type_application
type_union underscore user_type_application variable
warning_marker
The user may (for special purposes) create additional nodes with other type tags, using the tree/2 function ๐.
Note: The primary constructor functions for a node type should always have the same name as the node type itself โจ.
See also: annotated_type/2, application/3, arity_qualifier/2, atom/1, attribute/2, binary/1, binary_field/2, bitstring_type/2, block_expr/1, case_expr/2, catch_expr/1, char/1, class_qualifier/2, clause/3, comment/2, conjunction/1, constrained_function_type/2, constraint/2, disjunction/1, else_expr/1, eof_marker/0, error_marker/1, float/1, form_list/1, fun_expr/1, fun_type/0, function/2, function_type/1, function_type/2, generator/2, if_expr/1, implicit_fun/2, infix_expr/3, integer/1, integer_range_type/2, list/2, list_comp/2, macro/2, map_expr/2, map_field_assoc/2, map_field_exact/2, map_type/0, map_type/1, map_type_assoc/2, map_type_exact/2, match_expr/2, maybe_expr/1, maybe_expr/2, maybe_match_expr/2, module_qualifier/2, named_fun_expr/2, nil/0, operator/1, parentheses/1, prefix_expr/2, receive_expr/3, record_access/3, record_expr/2, record_field/2, record_index_expr/2, record_type/2, record_type_field/2, size_qualifier/2, string/1, text/1, tree/2, try_expr/3, tuple/1, tuple_type/0, tuple_type/1, type_application/2, type_union/1, typed_record_field/2, underscore/0, user_type_application/2, variable/1, warning_marker/1.
type_application/2 ๐
type_application(TypeName::syntaxTree(), Arguments::[syntaxTree()]) ->
syntaxTree()
Builds you an abstract type application expression, bestie. If Arguments is [T1, ..., Tn], then the thing you get back represents "TypeName(T1, ...Tn)". That's it, that's the whole vibe โจ
See also: type_application/3, type_application_arguments/1, type_application_name/1, user_type_application/2.
type_application/3 ๐ธ
type_application(Module::none | syntaxTree(), TypeName::syntaxTree(),
Arguments::[syntaxTree()]) -> syntaxTree()
Same abstract type application expression, but now with a Module slot, okurrr. If Module is none, this call is literally equivalent to type_application(TypeName, Arguments). Otherwise it's equivalent to type_application(module_qualifier(Module, TypeName), Arguments) ๐ฆ
(Yeah โ this is a utility function. Convenience icon behavior.)
See also: module_qualifier/2, type_application/2.
type_application_arguments/1 ๐
type_application_arguments(Node::syntaxTree()) -> [syntaxTree()]
Hands you back the arguments subtrees of a type_application node. The little squad inside the parens ๐
See also: type_application/2.
type_application_name/1 โญ
type_application_name(Node::syntaxTree()) -> syntaxTree()
Returns the type name subtree of a type_application node โ the main character of the whole expression, ngl ๐
See also: type_application/2.
type_union/1 ๐
type_union(Types::[syntaxTree()]) -> syntaxTree()
Creates an abstract type union. If Types is [T1, ..., Tn], the result represents "T1 | ... | Tn" โ yes, with all the pipes, all of them ๐ซถ
See also: type_union_types/1.
type_union_types/1 ๐
type_union_types(Node::syntaxTree()) -> [syntaxTree()]
Returns the list of type subtrees of a type_union node. All the alternates, collected, slay.
See also: type_union/1.
typed_record_field/2 ๐
typed_record_field(Field::syntaxTree(), Type::syntaxTree()) ->
syntaxTree()
Creates an abstract typed record field specification. The result represents "Field :: Type" โ the :: is doing so much work here fr fr.
See also: typed_record_field_body/1, typed_record_field_type/1.
typed_record_field_body/1 ๐ง
typed_record_field_body(Node::syntaxTree()) -> syntaxTree()
Returns the field subtree of a typed_record_field node. The left side of the ::, if you will โจ
See also: typed_record_field/2.
typed_record_field_type/1 ๐ฆ
typed_record_field_type(Node::syntaxTree()) -> syntaxTree()
Returns the type subtree of a typed_record_field node. The right side of the :: โ the type part, obviously ๐
See also: typed_record_field/2.
underscore/0 ๐
underscore() -> syntaxTree()
Creates an abstract universal pattern, a.k.a. "_". The lexical representation is a single underscore character. And note: this is not a variable, lexically speaking โ don't come for me, that's just how it is ๐
See also: variable/1.
update_tree/2 ๐ฅ
update_tree(Node::syntaxTree(), Groups::[[syntaxTree()]]) ->
syntaxTree()
Creates a syntax tree with the same type and attributes as the given tree. This is equivalent to copy_attrs(Node, make_tree(type(Node), Groups)) โ copy that exactly, iykyk.
See also: copy_attrs/2, make_tree/2, type/1.
user_type_application/2 ๐
user_type_application(TypeName::syntaxTree(), Arguments::[syntaxTree()])
-> syntaxTree()
Creates an abstract user type. If Arguments is [T1, ..., Tn], the result represents "TypeName(T1, ...Tn)". Same shape as the type application, different flavor of node, bestie ๐
See also: type_application/2, user_type_application_arguments/1, user_type_application_name/1.
user_type_application_arguments/1 ๐
user_type_application_arguments(Node::syntaxTree()) -> [syntaxTree()]
Returns the arguments subtrees of a user_type_application node. All the inner cuties ๐ธ
See also: user_type_application/2.
user_type_application_name/1 ๐
user_type_application_name(Node::syntaxTree()) -> syntaxTree()
Returns the type name subtree of a user_type_application node. The name itself, thriving.
See also: user_type_application/2.
variable/1 ๐ฆ
variable(Name::atom() | string()) -> syntaxTree()
Creates an abstract variable with the given name. Name can be any atom or string that represents a lexically valid variable name โ but not a single underscore character, ok? For that one, see underscore/0 ๐
Note: literally no checking is done on whether the character sequence represents a proper variable name. Like, none. It doesn't check whether its first character is an uppercase Erlang character, and it doesn't check whether it contains control characters, whitespace, etc. You are on your own, bestie ๐ญ
See also: underscore/0, variable_literal/1, variable_name/1.
variable_literal/1 โจ
variable_literal(Node::syntaxTree()) -> string()
Returns the name of a variable node as a string. String era ๐
See also: variable/1.
variable_name/1 ๐ธ
variable_name(Node::syntaxTree()) -> atom()
Returns the name of a variable node as an atom. Atom era ๐
See also: variable/1.
warning_marker/1 โ ๏ธ
warning_marker(Warning::term()) -> syntaxTree()
Creates an abstract warning marker. The result represents a possible problem in the source code, with an associated Erlang I/O ErrorInfo structure given by Error (peep module io(3erl) for the details, mwah). Warning markers are regarded as source code forms, but they have no defined lexical form โ they're just vibes in tree form ๐ซถ
Note: this is supported only for backwards compatibility with existing parsers and tools. Like, it's a legacy icon, not a fresh drop ๐
See also: eof_marker/0, error_marker/1, is_form/1, warning_marker_info/1.
warning_marker_info/1 ๐
warning_marker_info(Node::syntaxTree()) -> term()
Returns the ErrorInfo structure of a warning_marker node. The receipts of the warning, basically ๐
See also: warning_marker/1.
โจ AUTHORS โจ
Richard Carlsson <carlsson.richard@gmail.com> โ the actual legend ๐ thank you for your service ๐ซถ
And that's a wrap on the whole page, bestie!! ๐ This was syntax_tools version 3.0.1, the erl_syntax(3erl) manual page โ go forth and build trees, no cap ๐๐ธโจ
๐ฆ where this page comes from
- ubuntu noble: erlang-manpages 1:25.3.2.8+dfsg-1ubuntu4 ยท Apache-2.0
- ubuntu noble: erlang-manpages 1:25.3.2.8+dfsg-1ubuntu4.8 ยท Apache-2.0
- ๐ girlified by deepseek-ai/DeepSeek-V4.1-Flash-1017 on : a language model's rewrite of the original, under its terms