erl_syntax_lib(3erl)
π NAME π
erl_syntax_lib β manual page erl_syntax_lib(3erl), Erlang Module Definition β support library for abstract Erlang syntax trees. She's iconic, she's useful, she's here to help π
β¨
πΈ DESCRIPTION πΈ
okay so this is the support library for abstract Erlang syntax trees. It's giving utility functions for working with the abstract data type defined in the module erl_syntax. That's the whole vibe, bestie π«Ά
π¦ DATA TYPES π¦
Here are the literal type definitions so we don't fumble the bag:
appFunName() = {atom(), arity()} | {atom(), {atom(), arity()}}:
field() = {atom(), {field_default(), field_type()}}:
field_default() = none | erl_syntax:syntaxTree():
field_type() = none | erl_syntax:syntaxTree():
fields() = [field()]:
functionN() = atom() | {atom(), arity()}:
functionName() = functionN() | {atom(), functionN()}:
info() = {atom(), [{atom(), erl_syntax:syntaxTree()}]} | {atom(), atom()} | atom():
info_pair() = {key(), term()}:
key() = attributes | errors | exports | functions | imports | module | records | warnings:
name() = shortname() | {atom(), shortname()}:
ordset(T) = ordsets:ordset(T):
set(T) = sets:set(T):
shortname() = atom() | {atom(), arity()}:
syntaxTree() = erl_syntax:syntaxTree():
typeName() = atom() | {module(), {atom(), arity()}} | {atom(), arity()}:
And syntaxTree() means an abstract syntax tree β see the erl_syntax module for the details π
π EXPORTS π
π« analyze_application/1 π«
analyze_application(Node::erl_syntax:syntaxTree()) -> appFunName() | arity()
Returns the name of a called function. The result is a representation of the name of the applied function F/A if Node represents a function application "F(X_1, ..., X_A)". If the function is not explicitly named β like, F is given by some expression β then only the arity A is returned. That's the tea.
the evaluation throwssyntax_errorifNodedoes not represent a well-formed application expression π
See also: analyze_function_name/1.
π§ analyze_attribute/1 π§
analyze_attribute(Node::erl_syntax:syntaxTree()) -> preprocessor | {atom(), term()}
Analyzes an attribute node. If Node represents a preprocessor directive, the atom preprocessor is returned. Otherwise, if Node represents a module attribute "-Name...", a tuple {Name, Info} is returned, where Info depends on Name, as follows:
{module, Info}β whereInfo = analyze_module_attribute(Node).{export, Info}β whereInfo = analyze_export_attribute(Node).{import, Info}β whereInfo = analyze_import_attribute(Node).{file, Info}β whereInfo = analyze_file_attribute(Node).{record, Info}β whereInfo = analyze_record_attribute(Node).{Name, Info}β where{Name, Info} = analyze_wild_attribute(Node).
the evaluation throwssyntax_errorifNodedoes not represent a well-formed module attribute π
See also: analyze_export_attribute/1, analyze_file_attribute/1, analyze_import_attribute/1, analyze_module_attribute/1, analyze_record_attribute/1, analyze_wild_attribute/1.
π analyze_export_attribute/1 π
analyze_export_attribute(Node::erl_syntax:syntaxTree()) -> [functionName()]
Returns the list of function names declared by an export attribute. No cap: we do not guarantee that each name occurs at most once in the list. The order of listing is not defined either. It's giving "list, but make it unordered" π
the evaluation throwssyntax_errorifNodedoes not represent a well-formed export attribute π
See also: analyze_attribute/1.
π analyze_file_attribute/1 π
analyze_file_attribute(Node::erl_syntax:syntaxTree()) -> {string(), integer()}
Returns the file name and line number of a file attribute. The result is the pair {File, Line} if Node represents "-file(File, Line).". Cute.
the evaluation throwssyntax_errorifNodedoes not represent a well-formed file attribute π
See also: analyze_attribute/1.
π analyze_form/1 π
analyze_form(Node::erl_syntax:syntaxTree()) -> {atom(), term()} | atom()
Analyzes a "source code form" node. If Node is a "form" type (cf. erl_syntax:is_form/1), the returned value is a tuple {Type, Info} where Type is the node type and Info depends on Type, like this:
{attribute, Info}β whereInfo = analyze_attribute(Node).{error_marker, Info}β whereInfo = erl_syntax:error_marker_info(Node).{function, Info}β whereInfo = analyze_function(Node).{warning_marker, Info}β whereInfo = erl_syntax:warning_marker_info(Node).
For other types of forms, only the node type is returned.
the evaluation throwssyntax_errorifNodeis not well-formed π
See also: analyze_attribute/1, analyze_function/1, erl_syntax:error_marker_info/1, erl_syntax:is_form/1, erl_syntax:warning_marker_info/1.
π analyze_forms/1 π
analyze_forms(Forms::erl_syntax:forms()) -> [info_pair()]
Analyzes a sequence of "program forms". The given Forms may be a single syntax tree of type form_list, or a list of "program form" syntax trees. The returned value is a list of pairs {Key, Info}, where each value of Key occurs at most once in the list; the absence of a particular key indicates that there is no well-defined value for that key.
Each entry in the resulting list contains the following corresponding information about the program forms:
{attributes, Attributes}:Attributes = [{atom(), term()}]Attributesis a list of pairs representing the names and corresponding values of all so-called"wild"attributes (as e.g."-compile(...)") occurring inForms(cf.analyze_wild_attribute/1). We do not guarantee that each name occurs at most once in the list. The order of listing is not defined.
{errors, Errors}:Errors = [term()]Errorsis the list of error descriptors of allerror_markernodes that occur inForms. The order of listing is not defined.
{exports, Exports}:Exports = [FunctionName]FunctionName = atom() | {atom(), integer()} | {ModuleName, FunctionName}ModuleName = atom()Exportsis a list of representations of those function names that are listed by export declaration attributes inForms(cf.analyze_export_attribute/1). We do not guarantee that each name occurs at most once in the list. The order of listing is not defined.
{functions, Functions}:Functions = [{atom(), integer()}]Functionsis a list of the names of the functions that are defined inForms(cf.analyze_function/1). We do not guarantee that each name occurs at most once in the list. The order of listing is not defined.
{imports, Imports}:Imports = [{Module, Names}]Module = atom()Names = [FunctionName]FunctionName = atom() | {atom(), integer()} | {ModuleName, FunctionName}ModuleName = atom()Importsis a list of pairs representing those module names and corresponding function names that are listed by import declaration attributes inForms(cf.analyze_import_attribute/1), where eachModuleoccurs at most once inImports. We do not guarantee that each name occurs at most once in the lists of function names. The order of listing is not defined.
{module, ModuleName}:ModuleName = atom()ModuleNameis the name declared by a module attribute inForms. If no module name is defined inForms, the result will contain no entry for themodulekey. If multiple module name declarations should occur, all but the first will be ignored.
{records, Records}:Records = [{atom(), Fields}]Fields = [{atom(), {Default, Type}}]Default = none | syntaxTree()Type = none | syntaxTree()Recordsis a list of pairs representing the names and corresponding field declarations of all record declaration attributes occurring inForms. For fields declared without a default value, the corresponding value forDefaultis the atomnone. Similarly, for fields declared without a type, the corresponding value forTypeis the atomnone(cf.analyze_record_attribute/1). We do not guarantee that each record name occurs at most once in the list. The order of listing is not defined.
{warnings, Warnings}:Warnings = [term()]Warningsis the list of error descriptors of allwarning_markernodes that occur inForms. The order of listing is not defined.
the evaluation throws syntax_error if an ill-formed Erlang construct is encountered π
See also: analyze_export_attribute/1, analyze_function/1, analyze_import_attribute/1, analyze_record_attribute/1, analyze_wild_attribute/1, erl_syntax:error_marker_info/1, erl_syntax:warning_marker_info/1.
π analyze_function/1 π
analyze_function(Node::erl_syntax:syntaxTree()) -> {atom(), arity()}
Returns the name and arity of a function definition. The result is a pair {Name, A} if Node represents a function definition "Name(P_1, ..., P_A) -> ...". Periodt.
the evaluation throwssyntax_errorifNodedoes not represent a well-formed function definition π
π¦ analyze_function_name/1 π¦
analyze_function_name(Node::erl_syntax:syntaxTree()) -> functionName()
Returns the function name represented by a syntax tree. If Node represents a function name, such as "foo/1" or "bloggs:fred/2", a uniform representation of that name is returned. Different nestings of arity and module name qualifiers in the syntax tree does not affect the result. Slay.
the evaluation throwssyntax_errorifNodedoes not represent a well-formed function name π
π analyze_implicit_fun/1 π
analyze_implicit_fun(Node::erl_syntax:syntaxTree()) -> functionName()
Returns the name of an implicit fun expression "fun F". The result is a representation of the function name F. (Cf. analyze_function_name/1.) Iconic.
the evaluation throwssyntax_errorifNodedoes not represent a well-formed implicit fun π
See also: analyze_function_name/1.
π₯ analyze_import_attribute/1 π₯
analyze_import_attribute(Node::erl_syntax:syntaxTree()) -> {atom(), [functionName()]} | atom()
Okay so this analyzer returns the module name and (if present) the list of function names declared by an import attribute. The returned value is an atom Module or a pair {Module, Names}, where Names is a list of function names declared as imported from the module named by Module. We do not guarantee that each name occurs at most once in Names. The order of listing is not defined.
If Node isnβt a well-formed import attribute, the evaluation throws syntax_error.
See also: analyze_attribute/1.
analyze_module_attribute
analyze_module_attribute(Node::erl_syntax:syntaxTree()) -> atom() |
{atom(), [atom()]}
Returns the module name and possible parameters declared by a module attribute β¨ If the attribute is a plain module declaration like -module(name), the result is the module name. If itβs a parameterized module declaration, the result is a tuple containing the module name and a list of the parameter variable names.
If Node isnβt a well-formed module attribute, the evaluation throws syntax_error.
See also: analyze_attribute/1.
analyze_record_attribute
analyze_record_attribute(Node::erl_syntax:syntaxTree()) -> {atom(),
fields()}
Returns the name and the list of fields of a record declaration attribute π The result is a pair {Name, Fields} if Node represents -record(Name, {...})., where Fields is a list of pairs {Label, {Default, Type}} for each field "Label", "Label = Default", "Label :: Type", or "Label = Default :: Type" in the declaration, listed in left-to-right order. If the field has no default-value declaration, the value for Default will be the atom none. If the field has no type declaration, the value for Type will be the atom none. We do not guarantee that each label occurs at most once in the list.
If Node isnβt a well-formed record declaration attribute, the evaluation throws syntax_error.
See also: analyze_attribute/1, analyze_record_field/1.
analyze_record_expr
analyze_record_expr(Node::erl_syntax:syntaxTree()) -> {atom(), info()} |
atom()
Returns the record name and field name/names of a record expression π
If Node has type record_expr, record_index_expr or record_access, a pair {Type, Info} is returned; otherwise an atom Type is returned. Type is the node type of Node, and Info depends on Type, like this:
record_expr::
{atom(), [{atom(), Value}]}
record_access::
{atom(), atom()}
record_index_expr::
{atom(), atom()}
For a record_expr node, Info represents the record name and the list of descriptors for the involved fields, listed in the order they appear. A field descriptor is a pair {Label, Value} if Node represents Label = Value. For a record_access node, Info represents the record name and the field name. For a record_index_expr node, Info represents the record name and the name field name.
If Node represents a record expression that is not well-formed, the evaluation throws syntax_error.
See also: analyze_record_attribute/1, analyze_record_field/1.
analyze_record_field
analyze_record_field(Node::erl_syntax:syntaxTree()) -> field()
Returns the label, value-expression, and type of a record field specifier π¦ The result is a pair {Label, {Default, Type}} if Node represents Label, Label = Default, Label :: Type, or Label = Default :: Type. If the field has no value-expression, the value for Default will be the atom none. If the field has no type, the value for Type will be the atom none.
If Node isnβt a well-formed record field specifier, the evaluation throws syntax_error.
See also: analyze_record_attribute/1, analyze_record_expr/1.
analyze_type_application
analyze_type_application(Node::erl_syntax:syntaxTree()) -> typeName()
Returns the name of a used type πΈ The result is a representation of the name of the used pre-defined or local type N/A, if Node represents a local (user) type application N(T_1, ..., T_A), or a representation of the name of the used remote type M:N/A if Node represents a remote user type application M:N(T_1, ..., T_A).
If Node isnβt a well-formed (user) type application expression, the evaluation throws syntax_error.
See also: analyze_type_name/1.
analyze_type_name
analyze_type_name(Node::erl_syntax:syntaxTree()) -> typeName()
Returns the type name represented by a syntax tree π If Node represents a type name, such as foo/1 or bloggs:fred/2, a uniform representation of that name is returned.
If Node isnβt a well-formed type name, the evaluation throws syntax_error.
analyze_wild_attribute
analyze_wild_attribute(Node::erl_syntax:syntaxTree()) -> {atom(),
term()}
Returns the name and value of a βwildβ attribute π The result is the pair {Name, Value} if Node represents -Name(Value).
Note that no checking is done whetherNameis a reserved attribute name such asmoduleorexport: it is assumed that the attribute is βwildβ.
If Node isnβt a well-formed wild attribute, the evaluation throws syntax_error.
See also: analyze_attribute/1.
annotate_bindings
annotate_bindings(Tree::erl_syntax:syntaxTree()) ->
erl_syntax:syntaxTree()
Adds or updates annotations on nodes in a syntax tree β¨ Equivalent to annotate_bindings(Tree, Bindings) where the top-level environment Bindings is taken from the annotation {env, Bindings} on the root node of Tree. An exception is thrown if no such annotation should exist.
See also: annotate_bindings/2.
annotate_bindings
annotate_bindings(Tree::erl_syntax:syntaxTree(),
Env::ordsets:ordset(atom())) -> erl_syntax:syntaxTree()
Adds or updates annotations on nodes in a syntax tree π Bindings specifies the set of bound variables in the environment of the top level node. The following annotations are affected:
{env, Vars}, representing the input environment of the subtree.{bound, Vars}, representing the variables that are bound in the subtree.{free, Vars}, representing the free variables in the subtree.
Bindings and Vars are ordered-set lists (cf. module ordsets) of atoms representing variable names.
See also: ordsets(3erl), annotate_bindings/1.
fold
fold(F::(erl_syntax:syntaxTree(), term()) -> term(), S::term(),
Tree::erl_syntax:syntaxTree()) -> term()
Folds a function over all nodes of a syntax tree π The result is the value of Function(X1, Function(X2, ... Function(Xn, Start) ... )), where [X1, X2, ..., Xn] are the nodes of Tree in a post-order traversal.
See also: fold_subtrees/3, foldl_listlist/3.
fold_subtrees
fold_subtrees(F::(erl_syntax:syntaxTree(), term()) -> term(), S::term(),
Tree::erl_syntax:syntaxTree()) -> term()
Folds a function over the immediate subtrees of a syntax tree πΈ This is similar to fold/3, but only on the immediate subtrees of Tree, in left-to-right order; it does not include the root node of Tree.
See also: fold/3.
foldl_listlist
foldl_listlist(F::(term(), term()) -> term(), S::term(), Ls::[[term()]])
-> term()
Like lists:foldl/3, but over a list of lists π¦
See also: lists:foldl/3, fold/3.
function_name_expansions
function_name_expansions(Fs::[name()]) -> [{shortname(), name()}]
Creates a mapping from corresponding short names to full function names π Names are represented by nested tuples of atoms and integers (cf. analyze_function_name/1). The result is a list containing a pair {ShortName, Name} for each element Name in the given list, where the corresponding ShortName is the rightmost-innermost part of Name. The list thus represents a finite mapping from unqualified names to the corresponding qualified names.
Note: the resulting list can contain more than one tuple{ShortName, Name}for the sameShortName, possibly with different values forName, depending on the given list.
See also: analyze_function_name/1.
is_fail_expr
is_fail_expr(E::erl_syntax:syntaxTree()) -> boolean()
Returns true if Tree represents an expression which never terminates normally π Note that the reverse does not apply. Currently, the detected cases are calls to exit/1, throw/1, erlang:error/1 and erlang:error/2.
See also: erlang:error/1, erlang:error/2, erlang:exit/1, erlang:throw/1.
limit
limit(Tree::erl_syntax:syntaxTree(), Depth::integer()) ->
erl_syntax:syntaxTree()
Equivalent to limit(Tree, Depth, Text) using the text "..." as default replacement π
See also: limit/3, erl_syntax:text/1.
limit
limit(Tree::erl_syntax:syntaxTree(), Depth::integer(),
Node::erl_syntax:syntaxTree()) -> erl_syntax:syntaxTree()
Limits a syntax tree to a specified depth β¨ Replaces all non-leaf subtrees in Tree at the given Depth by Node. If Depth is negative, the result is always Node, even if Tree has no subtrees.
When a group of subtrees (as e.g., the argument list of an application node) is at the specified depth, and there are two or more subtrees in the group, these will be collectively replaced by Node even if they are leaf nodes. Groups of subtrees that are above the specified depth will be limited in size, as if each subsequent tree in the group were one level deeper than the previous. E.g., if Tree represents a list of integers [1, 2, 3, 4, 5, 6, 7, 8, 9, 10], the result of limit(Tree, 5) will represent [1, 2, 3, 4, ...].
The resulting syntax tree is typically only useful for pretty-printing or similar visual formatting.
See also: limit/2.
map
map(F::(erl_syntax:syntaxTree()) -> erl_syntax:syntaxTree(),
Tree::erl_syntax:syntaxTree()) -> erl_syntax:syntaxTree()
Applies a function to each node of a syntax tree π The result of each application replaces the corresponding original node. The order of traversal is bottom-up.
See also: map_subtrees/2.
map_subtrees
map_subtrees(F::(erl_syntax:syntaxTree()) -> erl_syntax:syntaxTree(),
Tree::erl_syntax:syntaxTree()) -> erl_syntax:syntaxTree()
Applies a function to each immediate subtree of a syntax tree π The result of each application replaces the corresponding original node.
See also: map/2.
mapfold/3
mapfold(F::(erl_syntax:syntaxTree(), term()) ->
{erl_syntax:syntaxTree(), term()}, S::term(),
Tree::erl_syntax:syntaxTree()) -> {erl_syntax:syntaxTree(), term()}
Okay so this one is literally map + fold in a single operation. Itβs similar to map/2, but it also propagates an extra value from each application of the Function to the next, while doing a post-order traversal of the tree like fold/3. The value Start is passed to the first function application, and the final result is the result of the last application.
See also: fold/3, map/2. Go say hi to them. π
mapfold_subtrees/3
mapfold_subtrees(F::(erl_syntax:syntaxTree(), term()) ->
{erl_syntax:syntaxTree(), term()}, S::term(),
Tree::erl_syntax:syntaxTree()) -> {erl_syntax:syntaxTree(), term()}
This does a mapfold operation over the immediate subtrees of a syntax tree. Itβs like mapfold/3 but with a tiny scope, bestie: only the immediate subtrees of Tree, in left-to-right order. It does not include the root node of Tree.
See also: mapfold/3.
mapfoldl_listlist/3
mapfoldl_listlist(F::(term(), term()) -> {term(), term()}, S::term(),
Ls::[[term()]]) -> {[[term()]], term()}
Like lists:mapfoldl/3, but over a list of lists. The list of lists in the result has the same structure as the given list of lists. Structure preserved, vibe preserved. β¨
new_variable_name/1
new_variable_name(S::sets:set(atom())) -> atom()
Returns an atom which is not already in the set Used. This is equivalent to new_variable_name(Function, Used), where Function maps a given integer N to the atom whose name consists of "V" followed by the numeral for N.
See also: new_variable_name/2.
new_variable_name/2
new_variable_name(F::(integer()) -> atom(), S::sets:set(atom())) ->
atom()
Returns a user-named atom which is not already in the set Used. The atom is generated by applying the given Function to a generated integer. Integers are generated using an algorithm which tries to keep the names randomly distributed within a reasonably small range relative to the number of elements in the set.
This function uses the module rand to generate new keys. The seed it uses may be initialized by calling rand:seed/1 or rand:seed/2 before this function is first called.
See also: random(3erl), sets(3erl), new_variable_name/1.
new_variable_names/2
new_variable_names(N::integer(), S::sets:set(atom())) -> [atom()]
Like new_variable_name/1, but generates a list of N new names. Bulk name generation, we love to see it. π
See also: new_variable_name/1.
new_variable_names/3
new_variable_names(N::integer(), F::(integer()) -> atom(),
S::sets:set(atom())) -> [atom()]
Like new_variable_name/2, but generates a list of N new names.
See also: new_variable_name/2.
strip_comments/1
strip_comments(Tree::erl_syntax:syntaxTree()) -> erl_syntax:syntaxTree()
Removes all comments from all nodes of a syntax tree. All other attributes (such as position information) remain unchanged. Standalone comments in form lists are removed; any other standalone comments are changed into null-comments (no text, no indentation). Comment cleanup arc, honestly iconic. π§Ήβ¨
to_comment/1
to_comment(Tree::erl_syntax:syntaxTree()) -> erl_syntax:syntaxTree()
Equivalent to to_comment(Tree, "% ").
to_comment/2
to_comment(Tree::erl_syntax:syntaxTree(), Prefix::string()) ->
erl_syntax:syntaxTree()
Equivalent to to_comment(Tree, Prefix, F) for a default formatting function F. The default F simply calls erl_prettypr:format/1.
See also: to_comment/3, erl_prettypr:format/1.
to_comment/3
to_comment(Tree::erl_syntax:syntaxTree(), Prefix::string(),
F::(erl_syntax:syntaxTree()) -> string()) -> erl_syntax:syntaxTree()
Transforms a syntax tree into an abstract comment. The lines of the comment contain the text for Node, as produced by the given Printer function. Each line of the comment is prefixed by the string Prefix (this does not include the initial "%" character of the comment line).
For example, the result of to_comment(erl_syntax:abstract([a,b,c])) represents
%% [a,b,c]
(cf. to_comment/1).
Note: the text returned by the formatting function will be split automatically into separate comment lines at each line break. No extra work is needed. Automatic line splitting? We stan. π
See also: to_comment/1, to_comment/2.
variables/1
variables(Tree::erl_syntax:syntaxTree()) -> sets:set(atom())
Returns the names of variables occurring in a syntax tree. The result is a set of variable names represented by atoms. Macro names are not included. Macros stay uninvited to this variable party. π«Ά
See also: sets(3erl).
π AUTHORS π
Richard Carlsson <carlsson.richard@gmail.com>
Footer check, bestie: this page is from syntax_tools 3.0.1, and itβs the erl_syntax_lib(3erl) manual page. Thereβs no date printed in the footer, so Iβm not inventing one β periodt. π
π«Ά
π¦ 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