%% =====================================================================
%% This library is free software; you can redistribute it and/or modify
%% it under the terms of the GNU Lesser General Public License as
%% published by the Free Software Foundation; either version 2 of the
%% License, or (at your option) any later version.
%%
%% This library is distributed in the hope that it will be useful, but
%% WITHOUT ANY WARRANTY; without even the implied warranty of
%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
%% Lesser General Public License for more details.
%%
%% You should have received a copy of the GNU Lesser General Public
%% License along with this library; if not, write to the Free Software
%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
%% USA
%%
%% $Id$
%%
%% @copyright 1997-2006 Richard Carlsson
%% @author Richard Carlsson erl_parse (often referred to as "parse
%% trees", which is a bit of a misnomer). This means that all
%% erl_parse trees are valid abstract syntax trees, 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.
%%
%% A recommended starting point for the first-time user is the
%% documentation of the syntaxTree() data type, and
%% the function type/1.
%%
%% 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.
%% @type syntaxTree(). An abstract syntax tree. The
%% erl_parse "parse tree" representation is a subset of the
%% syntaxTree() representation.
%%
%% Every abstract syntax tree node has a type, given by the
%% function type/1. Each node also
%% has associated attributes; see get_attrs/1 for details. The
%% functions make_tree/2 and subtrees/1 are generic
%% constructor/decomposition functions for abstract syntax trees. The
%% functions abstract/1 and concrete/1 convert between
%% constant Erlang terms and their syntactic representations. The set of
%% syntax tree nodes is extensible through the tree/2 function.
%%
%% A syntax tree can be transformed to the erl_parse
%% representation with the revert/1
%% function.
-module(erl_syntax).
-export([type/1,
	 is_leaf/1,
	 is_form/1,
	 is_literal/1,
	 abstract/1,
	 concrete/1,
	 revert/1,
	 revert_forms/1,
	 subtrees/1,
	 make_tree/2,
	 update_tree/2,
	 meta/1,
	 get_pos/1,
	 set_pos/2,
	 copy_pos/2,
	 get_precomments/1,
	 set_precomments/2,
	 add_precomments/2,
	 get_postcomments/1,
	 set_postcomments/2,
	 add_postcomments/2,
	 has_comments/1,
	 remove_comments/1,
	 copy_comments/2,
	 join_comments/2,
	 get_ann/1,
	 set_ann/2,
	 add_ann/2,
	 copy_ann/2,
	 get_attrs/1,
	 set_attrs/2,
	 copy_attrs/2,
	 flatten_form_list/1,
	 cons/2,
	 list_head/1,
	 list_tail/1,
	 is_list_skeleton/1,
	 is_proper_list/1,
	 list_elements/1,
	 list_length/1,
	 normalize_list/1,
	 compact_list/1,
	 application/2,
	 application/3,
	 application_arguments/1,
	 application_operator/1,
	 arity_qualifier/2,
	 arity_qualifier_argument/1,
	 arity_qualifier_body/1,
	 atom/1,
	 is_atom/2,
	 atom_value/1,
	 atom_literal/1,
	 atom_name/1,
	 attribute/1,
	 attribute/2,
	 attribute_arguments/1,
	 attribute_name/1,
	 binary/1,
	 binary_comp/2,
	 binary_comp_template/1,
	 binary_comp_body/1,
	 binary_field/1,
	 binary_field/2,
	 binary_field/3,
	 binary_field_body/1,
	 binary_field_types/1,
	 binary_field_size/1,
	 binary_fields/1,
	 binary_generator/2,
	 binary_generator_body/1,
	 binary_generator_pattern/1,
	 block_expr/1,
	 block_expr_body/1,
	 case_expr/2,
	 case_expr_argument/1,
	 case_expr_clauses/1,
	 catch_expr/1,
	 catch_expr_body/1,
	 char/1,
	 is_char/2,
	 char_value/1,
	 char_literal/1,
	 clause/2,
	 clause/3,
	 clause_body/1,
	 clause_guard/1,
	 clause_patterns/1,
	 comment/1,
	 comment/2,
	 comment_padding/1,
	 comment_text/1,
	 cond_expr/1,
	 cond_expr_clauses/1,
	 conjunction/1,
	 conjunction_body/1,
	 disjunction/1,
	 disjunction_body/1,
	 eof_marker/0,
	 error_marker/1,
	 error_marker_info/1,
	 float/1,
	 float_value/1,
	 float_literal/1,
	 form_list/1,
	 form_list_elements/1,
	 fun_expr/1,
	 fun_expr_arity/1,
	 fun_expr_clauses/1,
	 function/2,
	 function_arity/1,
	 function_clauses/1,
	 function_name/1,
	 generator/2,
	 generator_body/1,
	 generator_pattern/1,
	 if_expr/1,
	 if_expr_clauses/1,
	 implicit_fun/1,
	 implicit_fun/2,
	 implicit_fun/3,
	 implicit_fun_name/1,
	 infix_expr/3,
	 infix_expr_left/1,
	 infix_expr_operator/1,
	 infix_expr_right/1,
	 integer/1,
	 is_integer/2,
	 integer_value/1,
	 integer_literal/1,
	 list/1,
	 list/2,
	 list_comp/2,
	 list_comp_body/1,
	 list_comp_template/1,
	 list_prefix/1,
	 list_suffix/1,
	 macro/1,
	 macro/2,
	 macro_arguments/1,
	 macro_name/1,
	 match_expr/2,
	 match_expr_body/1,
	 match_expr_pattern/1,
	 module_qualifier/2,
	 module_qualifier_argument/1,
	 module_qualifier_body/1,
	 nil/0,
	 operator/1,
	 operator_literal/1,
	 operator_name/1,
	 parentheses/1,
	 parentheses_body/1,
	 prefix_expr/2,
	 prefix_expr_argument/1,
	 prefix_expr_operator/1,
	 qualified_name/1,
	 qualified_name_segments/1,
	 query_expr/1,
	 query_expr_body/1,
	 receive_expr/1,
	 receive_expr/3,
	 receive_expr_action/1,
	 receive_expr_clauses/1,
	 receive_expr_timeout/1,
	 record_access/2,
	 record_access/3,
	 record_access_argument/1,
	 record_access_field/1,
	 record_access_type/1,
	 record_expr/2,
	 record_expr/3,
	 record_expr_argument/1,
	 record_expr_fields/1,
	 record_expr_type/1,
	 record_field/1,
	 record_field/2,
	 record_field_name/1,
	 record_field_value/1,
	 record_index_expr/2,
	 record_index_expr_field/1,
	 record_index_expr_type/1,
	 rule/2,
	 rule_arity/1,
	 rule_clauses/1,
	 rule_name/1,
	 size_qualifier/2,
	 size_qualifier_argument/1,
	 size_qualifier_body/1,
	 string/1,
	 is_string/2,
	 string_value/1,
	 string_literal/1,
	 text/1,
	 text_string/1,
	 try_expr/2,
	 try_expr/3,
	 try_expr/4,
	 try_after_expr/2,
	 try_expr_body/1,
	 try_expr_clauses/1,
	 try_expr_handlers/1,
	 try_expr_after/1,
	 class_qualifier/2,
	 class_qualifier_argument/1,
	 class_qualifier_body/1,
	 tuple/1,
	 tuple_elements/1,
	 tuple_size/1,
	 underscore/0,
	 variable/1,
	 variable_name/1,
	 variable_literal/1,
	 warning_marker/1,
	 warning_marker_info/1,
	 tree/1,
	 tree/2,
	 data/1,
	 is_tree/1]).
-export_type([forms/0, syntaxTree/0, syntaxTreeAttributes/0]).
%% =====================================================================
%% IMPLEMENTATION NOTES:
%%
%% All nodes are represented by tuples of arity 2 or greater, whose
%% first element is an atom which uniquely identifies the type of the
%% node. (In the backwards-compatible representation, the interpretation
%% is also often dependent on the context; the second element generally
%% holds the position information - with a couple of exceptions; see
%% `get_pos' and `set_pos' for details). In the documentation of this
%% module, `Pos' is the source code position information associated with
%% a node; usually, this is a positive integer indicating the original
%% source code line, but no assumptions are made in this module
%% regarding the format or interpretation of position information. When
%% a syntax tree node is constructed, its associated position is by
%% default set to the integer zero.
%% =====================================================================
-define(NO_UNUSED, true).
%% =====================================================================
%% Declarations of globally used internal data structures
%% =====================================================================
%% `com' records are used to hold comment information attached to a
%% syntax tree node or a wrapper structure.
%%
%% #com{pre :: Pre, post :: Post}
%%
%%	Pre = Post = [Com]
%%	Com = syntaxTree()
%%
%%	type(Com) = comment
-record(com, {pre  = [] :: [syntaxTree()],
	      post = [] :: [syntaxTree()]}).
%% `attr' records store node attributes as an aggregate.
%%
%% #attr{pos :: Pos, ann :: Ann, com :: Comments}
%%
%%	Pos = term()
%%	Ann = [term()]
%%	Comments = none | #com{}
%%
%% where `Pos' `Ann' and `Comments' are the corresponding values of a
%% `tree' or `wrapper' record.
-record(attr, {pos = 0    :: term(),
	       ann = []   :: [term()],
	       com = none :: 'none' | #com{}}).
-type syntaxTreeAttributes() :: #attr{}.
%% `tree' records represent new-form syntax tree nodes.
%%
%% Tree = #tree{type :: Type, attr :: Attr, data :: Data}
%%
%%	Type = atom()
%%	Attr = #attr{}
%%	Data = term()
%%
%%	is_tree(Tree) = true
-record(tree, {type           :: atom(),
	       attr = #attr{} :: #attr{},
	       data           :: term()}).
%% `wrapper' records are used for attaching new-form node information to
%% `erl_parse' trees.
%%
%% Wrapper = #wrapper{type :: Type, attr :: Attr, tree :: ParseTree}
%%
%%	Type = atom()
%%	Attr = #attr{}
%%	ParseTree = term()
%%
%%	is_tree(Wrapper) = false
-record(wrapper, {type           :: atom(),
		  attr = #attr{} :: #attr{},
		  tree           :: term()}).
%% =====================================================================
-type syntaxTree() :: #tree{} | #wrapper{} | tuple(). % XXX: refine
%% =====================================================================
%%
%%			Exported functions
%%
%% =====================================================================
%% =====================================================================
%% @spec type(Node::syntaxTree()) -> atom()
%%
%% @doc Returns the type tag of Node. If Node
%% does not represent a syntax tree, evaluation fails with reason
%% badarg. Node types currently defined by this module are:
%% 
%%  
%%    application 
%%   arity_qualifier 
%%   atom 
%%   attribute 
%%  
%%    binary 
%%   binary_field 
%%   block_expr 
%%   case_expr 
%%  
%%    catch_expr 
%%   char 
%%   class_qualifier 
%%   clause 
%%  
%%    comment 
%%   cond_expr 
%%   conjunction 
%%   disjunction 
%%  
%%    eof_marker 
%%   error_marker 
%%   float 
%%   form_list 
%%  
%%    fun_expr 
%%   function 
%%   generator 
%%   if_expr 
%%  
%%    implicit_fun 
%%   infix_expr 
%%   integer 
%%   list 
%%  
%%    list_comp 
%%   macro 
%%   match_expr 
%%   module_qualifier 
%%  
%%    nil 
%%   operator 
%%   parentheses 
%%   prefix_expr 
%%  
%%    qualified_name 
%%   query_expr 
%%   receive_expr 
%%   record_access 
%%  
%%    record_expr 
%%   record_field 
%%   record_index_expr 
%%   rule 
%%  
%%    size_qualifier 
%%   string 
%%   text 
%%   try_expr 
%%  
%%    
%% tuple 
%%   underscore 
%%   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 tree/2 %% @see application/3 %% @see arity_qualifier/2 %% @see atom/1 %% @see attribute/2 %% @see binary/1 %% @see binary_field/2 %% @see block_expr/1 %% @see case_expr/2 %% @see catch_expr/1 %% @see char/1 %% @see class_qualifier/2 %% @see clause/3 %% @see comment/2 %% @see cond_expr/1 %% @see conjunction/1 %% @see disjunction/1 %% @see eof_marker/0 %% @see error_marker/1 %% @see float/1 %% @see form_list/1 %% @see fun_expr/1 %% @see function/2 %% @see generator/2 %% @see if_expr/1 %% @see implicit_fun/2 %% @see infix_expr/3 %% @see integer/1 %% @see list/2 %% @see list_comp/2 %% @see macro/2 %% @see match_expr/2 %% @see module_qualifier/2 %% @see nil/0 %% @see operator/1 %% @see parentheses/1 %% @see prefix_expr/2 %% @see qualified_name/1 %% @see query_expr/1 %% @see receive_expr/3 %% @see record_access/3 %% @see record_expr/2 %% @see record_field/2 %% @see record_index_expr/2 %% @see rule/2 %% @see size_qualifier/2 %% @see string/1 %% @see text/1 %% @see try_expr/3 %% @see tuple/1 %% @see underscore/0 %% @see variable/1 %% @see warning_marker/1 -spec type(syntaxTree()) -> atom(). type(#tree{type = T}) -> T; type(#wrapper{type = T}) -> T; type(Node) -> %% Check for `erl_parse'-compatible nodes, and otherwise fail. case Node of %% Leaf types {atom, _, _} -> atom; {char, _, _} -> char; {float, _, _} -> float; {integer, _, _} -> integer; {nil, _} -> nil; {string, _, _} -> string; {var, _, Name} -> if Name =:= '_' -> underscore; true -> variable end; {error, _} -> error_marker; {warning, _} -> warning_marker; {eof, _} -> eof_marker; %% Composite types {'case', _, _, _} -> case_expr; {'catch', _, _} -> catch_expr; {'cond', _, _} -> cond_expr; {'fun', _, {clauses, _}} -> fun_expr; {'fun', _, {function, _, _}} -> implicit_fun; {'fun', _, {function, _, _, _}} -> implicit_fun; {'if', _, _} -> if_expr; {'receive', _, _, _, _} -> receive_expr; {'receive', _, _} -> receive_expr; {attribute, _, _, _} -> attribute; {bin, _, _} -> binary; {bin_element, _, _, _, _} -> binary_field; {block, _, _} -> block_expr; {call, _, _, _} -> application; {clause, _, _, _, _} -> clause; {cons, _, _, _} -> list; {function, _, _, _, _} -> function; {b_generate, _, _, _} -> binary_generator; {generate, _, _, _} -> generator; {lc, _, _, _} -> list_comp; {bc, _, _, _} -> binary_comp; {match, _, _, _} -> match_expr; {op, _, _, _, _} -> infix_expr; {op, _, _, _} -> prefix_expr; {'query', _, _} -> query_expr; {record, _, _, _, _} -> record_expr; {record, _, _, _} -> record_expr; {record_field, _, _, _, _} -> record_access; {record_field, _, _, _} -> case is_qualified_name(Node) of true -> qualified_name; false -> record_access end; {record_index, _, _, _} -> record_index_expr; {remote, _, _, _} -> module_qualifier; {rule, _, _, _, _} -> rule; {'try', _, _, _, _, _} -> try_expr; {tuple, _, _} -> tuple; _ -> erlang:error({badarg, Node}) end. %% ===================================================================== %% @spec is_leaf(Node::syntaxTree()) -> boolean() %% %% @doc Returnstrue if Node is a leaf node,
%% otherwise false. The currently recognised leaf node
%% types are:
%% | %%atom | %%char | %%comment | %%eof_marker | %%error_marker | 
| %%float | %%integer | %%nil | %%operator | %%string | 
| %%text | %%underscore | %%variable | %%warning_marker | 
A node of type tuple is a leaf node if and only if
%% its arity is zero.
Note: not all literals are leaf nodes, and vice versa. E.g., %% tuples with nonzero arity and nonempty lists may be literals, but are %% not leaf nodes. Variables, on the other hand, are leaf nodes but not %% literals.
%% %% @see type/1 %% @see is_literal/1 -spec is_leaf(syntaxTree()) -> boolean(). is_leaf(Node) -> case type(Node) of atom -> true; char -> true; comment -> true; % nonstandard type eof_marker -> true; error_marker -> true; float -> true; integer -> true; nil -> true; operator -> true; % nonstandard type string -> true; text -> true; % nonstandard type tuple -> tuple_elements(Node) =:= []; underscore -> true; variable -> true; warning_marker -> true; _ -> false end. %% ===================================================================== %% @spec is_form(Node::syntaxTree()) -> boolean() %% %% @doc Returnstrue if Node is a syntax tree
%% representing a so-called "source code form", otherwise
%% false. Forms are the Erlang source code units which,
%% placed in sequence, constitute an Erlang program. Current form types
%% are:
%% | %%attribute | %%comment | %%error_marker | %%eof_marker | %%form_list | 
| %%function | %%rule | %%warning_marker | %%text | 
Node. This is usually a nonnegative integer (indicating
%% the source code line number), but may be any term. By default, all
%% new tree nodes have their associated position information set to the
%% integer zero.
%%
%% @see set_pos/2
%% @see get_attrs/1
%% All `erl_parse' tree nodes are represented by tuples whose second
%% field is the position information (usually an integer), *with the
%% exceptions of* `{error, ...}' (type `error_marker') and `{warning,
%% ...}' (type `warning_marker'), which only contain the associated line
%% number *of the error descriptor*; this is all handled transparently
%% by `get_pos' and `set_pos'.
-spec get_pos(syntaxTree()) -> term().
get_pos(#tree{attr = Attr}) ->
    Attr#attr.pos;
get_pos(#wrapper{attr = Attr}) ->
    Attr#attr.pos;
get_pos({error, {Pos, _, _}}) ->
    Pos;
get_pos({warning, {Pos, _, _}}) ->
    Pos;
get_pos(Node) ->
    %% Here, we assume that we have an `erl_parse' node with position
    %% information in element 2.
    element(2, Node).
%% =====================================================================
%% @spec set_pos(Node::syntaxTree(), Pos::term()) -> syntaxTree()
%%
%% @doc Sets the position information of Node to
%% Pos.
%%
%% @see get_pos/1
%% @see copy_pos/2
-spec set_pos(syntaxTree(), term()) -> syntaxTree().
set_pos(Node, Pos) ->
    case Node of
	#tree{attr = Attr} ->
	    Node#tree{attr = Attr#attr{pos = Pos}};
	#wrapper{attr = Attr} ->
	    Node#wrapper{attr = Attr#attr{pos = Pos}};
	_ ->
	    %% We then assume we have an `erl_parse' node, and create a
	    %% wrapper around it to make things more uniform.
	    set_pos(wrap(Node), Pos)
    end.
%% =====================================================================
%% @spec copy_pos(Source::syntaxTree(), Target::syntaxTree()) ->
%%           syntaxTree()
%%
%% @doc Copies the position information from Source to
%% Target.
%%
%% This is equivalent to set_pos(Target,
%% get_pos(Source)), but potentially more efficient.
%%         % 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 comment/2
%% @see set_precomments/2
%% @see get_postcomments/1
%% @see get_attrs/1
-spec get_precomments(syntaxTree()) -> [syntaxTree()].
get_precomments(#tree{attr = Attr}) -> get_precomments_1(Attr);
get_precomments(#wrapper{attr = Attr}) -> get_precomments_1(Attr);
get_precomments(_) -> [].
get_precomments_1(#attr{com = none}) -> [];
get_precomments_1(#attr{com = #com{pre = Cs}}) -> Cs.
%% =====================================================================
%% @spec set_precomments(Node::syntaxTree(),
%%                       Comments::[syntaxTree()]) -> syntaxTree()
%%
%% @doc Sets the pre-comments of Node to
%% Comments. Comments should be a possibly
%% empty list of abstract comments, in top-down textual order.
%%
%% @see comment/2
%% @see get_precomments/1
%% @see add_precomments/2
%% @see set_postcomments/2
%% @see copy_comments/2
%% @see remove_comments/1
%% @see join_comments/2
-spec set_precomments(syntaxTree(), [syntaxTree()]) -> syntaxTree().
set_precomments(Node, Cs) ->
    case Node of
	#tree{attr = Attr} ->
	    Node#tree{attr = set_precomments_1(Attr, Cs)};
	#wrapper{attr = Attr} ->
	    Node#wrapper{attr = set_precomments_1(Attr, Cs)};
	_ ->
	    set_precomments(wrap(Node), Cs)
    end.
set_precomments_1(#attr{com = none} = Attr, Cs) ->
    Attr#attr{com = #com{pre = Cs}};
set_precomments_1(#attr{com = Com} = Attr, Cs) ->
    Attr#attr{com = Com#com{pre = Cs}}.
%% =====================================================================
%% @spec add_precomments(Comments::[syntaxTree()],
%%                       Node::syntaxTree()) -> syntaxTree()
%%
%% @doc Appends Comments to the pre-comments of
%% Node.
%%
%% Note: This is equivalent to set_precomments(Node,
%% get_precomments(Node) ++ Comments), but potentially more
%% efficient.
%%         {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 placing 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 ";").
%%
%% @see comment/2
%% @see set_postcomments/2
%% @see get_precomments/1
%% @see get_attrs/1
-spec get_postcomments(syntaxTree()) -> [syntaxTree()].
get_postcomments(#tree{attr = Attr}) -> get_postcomments_1(Attr);
get_postcomments(#wrapper{attr = Attr}) -> get_postcomments_1(Attr);
get_postcomments(_) -> [].
get_postcomments_1(#attr{com = none}) -> [];
get_postcomments_1(#attr{com = #com{post = Cs}}) -> Cs.
%% =====================================================================
%% @spec set_postcomments(Node::syntaxTree(),
%%                        Comments::[syntaxTree()]) -> syntaxTree()
%%
%% @doc Sets the post-comments of Node to
%% Comments. Comments should be a possibly
%% empty list of abstract comments, in top-down textual order
%%
%% @see comment/2
%% @see get_postcomments/1
%% @see add_postcomments/2
%% @see set_precomments/2
%% @see copy_comments/2
%% @see remove_comments/1
%% @see join_comments/2
-spec set_postcomments(syntaxTree(), [syntaxTree()]) -> syntaxTree().
set_postcomments(Node, Cs) ->
    case Node of
	#tree{attr = Attr} ->
	    Node#tree{attr = set_postcomments_1(Attr, Cs)};
	#wrapper{attr = Attr} ->
	    Node#wrapper{attr = set_postcomments_1(Attr, Cs)};
	_ ->
	    set_postcomments(wrap(Node), Cs)
    end.
set_postcomments_1(#attr{com = none} = Attr, Cs) ->
    Attr#attr{com = #com{post = Cs}};
set_postcomments_1(#attr{com = Com} = Attr, Cs) ->
    Attr#attr{com = Com#com{post = Cs}}.
%% =====================================================================
%% @spec add_postcomments(Comments::[syntaxTree()],
%%                        Node::syntaxTree()) -> syntaxTree()
%%
%% @doc Appends Comments to the post-comments of
%% Node.
%%
%% Note: This is equivalent to set_postcomments(Node,
%% get_postcomments(Node) ++ Comments), but potentially more
%% efficient.
false if the node has no associated
%% comments, and true otherwise.
%%
%% Note: This is equivalent to (get_precomments(Node) == [])
%% and (get_postcomments(Node) == []), but potentially more
%% efficient.
Node.
%%
%% Note: This is equivalent to
%% set_precomments(set_postcomments(Node, []), []), but
%% potentially more efficient.
Source to
%% Target.
%%
%% Note: This is equivalent to
%% set_postcomments(set_precomments(Target,
%% get_precomments(Source)), get_postcomments(Source)), but
%% potentially more efficient.
Source to the current
%% comments of Target.
%%
%% Note: This is equivalent to
%% add_postcomments(get_postcomments(Source),
%% add_precomments(get_precomments(Source), Target)), but
%% potentially more efficient.
Node to
%% Annotations.
%%
%% @see get_ann/1
%% @see add_ann/2
%% @see copy_ann/2
-spec set_ann(syntaxTree(), [term()]) -> syntaxTree().
set_ann(Node, As) ->
    case Node of
	#tree{attr = Attr} ->
	    Node#tree{attr = Attr#attr{ann = As}};
	#wrapper{attr = Attr} ->
	    Node#wrapper{attr = Attr#attr{ann = As}};
	_ ->
	    %% Assume we have an `erl_parse' node and create a wrapper
	    %% structure to carry the annotation.
	    set_ann(wrap(Node), As)
    end.
%% =====================================================================
%% @spec add_ann(Annotation::term(), Node::syntaxTree()) -> syntaxTree()
%%
%% @doc Appends the term Annotation to the list of user
%% annotations of Node.
%%
%% Note: this is equivalent to set_ann(Node, [Annotation |
%% get_ann(Node)]), but potentially more efficient.
Source to
%% Target.
%%
%% Note: this is equivalent to set_ann(Target,
%% get_ann(Source)), but potentially more efficient.
set_attrs/2).
%%
%% For accessing individual attributes, see get_pos/1,
%% get_ann/1, get_precomments/1 and
%% get_postcomments/1.
get_attrs/1.
%% 
%% @see set_attrs/2
%% @see get_pos/1
%% @see get_ann/1
%% @see get_precomments/1
%% @see get_postcomments/1
-spec get_attrs(syntaxTree()) -> syntaxTreeAttributes().
get_attrs(#tree{attr = Attr}) -> Attr;
get_attrs(#wrapper{attr = Attr}) -> Attr;
get_attrs(Node) -> #attr{pos = get_pos(Node),
			 ann = get_ann(Node),
			 com = get_com(Node)}.
%% =====================================================================
%% @spec set_attrs(Node::syntaxTree(),
%%                 Attributes::syntaxTreeAttributes()) -> syntaxTree()
%%
%% @doc Sets the attributes of Node to
%% Attributes.
%%
%% @see get_attrs/1
%% @see copy_attrs/2
-spec set_attrs(syntaxTree(), syntaxTreeAttributes()) -> syntaxTree().
set_attrs(Node, Attr) ->
    case Node of
	#tree{} ->
	    Node#tree{attr = Attr};
	#wrapper{} ->
	    Node#wrapper{attr = Attr};
	_ ->
	    set_attrs(wrap(Node), Attr)
    end.
%% =====================================================================
%% @spec copy_attrs(Source::syntaxTree(), Target::syntaxTree()) ->
%%           syntaxTree()
%%
%% @doc Copies the attributes from Source to
%% Target.
%%
%% Note: this is equivalent to set_attrs(Target,
%% get_attrs(Source)), but potentially more efficient.
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 comment/1
%% @see is_form/1
-type padding() :: 'none' | integer().
-record(comment, {pad :: padding(), text :: [string()]}).
%% type(Node) = comment
%% data(Node) = #comment{pad :: Padding, text :: Strings}
%%
%%	Padding = none | integer()
%%	Strings = [string()]
-spec comment(padding(), [string()]) -> syntaxTree().
comment(Pad, Strings) ->
    tree(comment, #comment{pad = Pad, text = Strings}).
%% =====================================================================
%% @spec comment_text(syntaxTree()) -> [string()]
%%
%% @doc Returns the lines of text of the abstract comment.
%%
%% @see comment/2
-spec comment_text(syntaxTree()) -> [string()].
comment_text(Node) ->
    (data(Node))#comment.text.
%% =====================================================================
%% @spec comment_padding(syntaxTree()) -> none | integer()
%%
%% @doc Returns the amount of padding before the comment, or
%% none. The latter means that a default padding may be
%% used.
%%
%% @see comment/2
-spec comment_padding(syntaxTree()) -> padding().
comment_padding(Node) ->
    (data(Node))#comment.pad.
%% =====================================================================
%% @spec form_list(Forms::[syntaxTree()]) -> syntaxTree()
%%
%% @doc Creates an abstract sequence of "source code forms". If
%% Forms is [F1, ..., Fn], where each
%% Fi is a form (cf. is_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; cf. 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 form_list_elements/1 %% @see is_form/1 %% @see flatten_form_list/1 %% type(Node) = form_list %% data(Node) = [Form] %% %% Form = syntaxTree() %% is_form(Form) = true -spec form_list([syntaxTree()]) -> syntaxTree(). form_list(Forms) -> tree(form_list, Forms). %% ===================================================================== %% @spec form_list_elements(syntaxTree()) -> [syntaxTree()] %% %% @doc Returns the list of subnodes of aform_list node.
%%
%% @see form_list/1
-spec form_list_elements(syntaxTree()) -> [syntaxTree()].
form_list_elements(Node) ->
    data(Node).
%% =====================================================================
%% @spec flatten_form_list(Node::syntaxTree()) -> syntaxTree()
%%
%% @doc Flattens sublists of a form_list node. Returns
%% Node with all subtrees of type form_list
%% recursively expanded, yielding a single "flat" abstract form
%% sequence.
%%
%% @see form_list/1
-spec flatten_form_list(syntaxTree()) -> syntaxTree().
flatten_form_list(Node) ->
    Fs = form_list_elements(Node),
    Fs1 = lists:reverse(flatten_form_list_1(Fs, [])),
    copy_attrs(Node, form_list(Fs1)).
flatten_form_list_1([F | Fs], As) ->
    case type(F) of
	form_list ->
	    As1 = flatten_form_list_1(form_list_elements(F), As),
	    flatten_form_list_1(Fs, As1);
	_ ->
	    flatten_form_list_1(Fs, [F | As])
    end;
flatten_form_list_1([], As) ->
    As.
%% =====================================================================
%% @spec text(String::string()) -> syntaxTree()
%%
%% @doc Creates an abstract piece of source code text. The result
%% represents exactly the sequence of characters in String.
%% 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 text_string/1
%% type(Node) = text
%% data(Node) = string()
-spec text(string()) -> syntaxTree().
text(String) ->
    tree(text, String).
%% =====================================================================
%% @spec text_string(syntaxTree()) -> string()
%%
%% @doc Returns the character sequence represented by a
%% text node.
%%
%% @see text/1
-spec text_string(syntaxTree()) -> string().
text_string(Node) ->
    data(Node).
%% =====================================================================
%% @spec variable(Name) -> syntaxTree()
%%	    Name = atom() | string()
%%
%% @doc Creates an abstract variable with the given name.
%% Name may be any atom or string that represents a
%% lexically valid variable name, but not a single underscore
%% character; cf. underscore/0.
%%
%% Note: no checking is done whether the character sequence %% represents a proper variable name, i.e., whether or not its first %% character is an uppercase Erlang character, or whether it does not %% contain control characters, whitespace, etc.
%% %% @see variable_name/1 %% @see variable_literal/1 %% @see underscore/0 %% type(Node) = variable %% data(Node) = atom() %% %% `erl_parse' representation: %% %% {var, Pos, Name} %% %% Name = atom() \ '_' -spec variable(atom() | string()) -> syntaxTree(). variable(Name) when is_atom(Name) -> tree(variable, Name); variable(Name) -> tree(variable, list_to_atom(Name)). revert_variable(Node) -> Pos = get_pos(Node), Name = variable_name(Node), {var, Pos, Name}. %% ===================================================================== %% @spec variable_name(syntaxTree()) -> atom() %% %% @doc Returns the name of avariable node as an atom.
%%
%% @see variable/1
-spec variable_name(syntaxTree()) -> atom().
variable_name(Node) ->
    case unwrap(Node) of
	{var, _, Name} ->
	    Name;
	Node1 ->
	    data(Node1)
    end.
%% =====================================================================
%% @spec variable_literal(syntaxTree()) -> string()
%%
%% @doc Returns the name of a variable node as a string.
%%
%% @see variable/1
-spec variable_literal(syntaxTree()) -> string().
variable_literal(Node) ->
    case unwrap(Node) of
	{var, _, Name} ->
	    atom_to_list(Name);
	Node1 ->
	    atom_to_list(data(Node1))
    end.
%% =====================================================================
%% @spec underscore() -> syntaxTree()
%%
%% @doc Creates an abstract universal pattern ("_"). The
%% lexical representation is a single underscore character. Note that
%% this is not a variable, lexically speaking.
%%
%% @see variable/1
%% type(Node) = underscore
%% data(Node) = []
%%
%% `erl_parse' representation:
%%
%% {var, Pos, '_'}
-spec underscore() -> syntaxTree().
underscore() ->
    tree(underscore, []).
revert_underscore(Node) ->
    Pos = get_pos(Node),
    {var, Pos, '_'}.
%% =====================================================================
%% @spec integer(Value::integer()) -> syntaxTree()
%%
%% @doc Creates an abstract integer literal. The lexical representation
%% is the canonical decimal numeral of Value.
%%
%% @see integer_value/1
%% @see integer_literal/1
%% @see is_integer/2
%% type(Node) = integer
%% data(Node) = integer()
%%
%% `erl_parse' representation:
%%
%% {integer, Pos, Value}
%%
%%	Value = integer()
-spec integer(integer()) -> syntaxTree().
integer(Value) ->
    tree(integer, Value).
revert_integer(Node) ->
    Pos = get_pos(Node),
    {integer, Pos, integer_value(Node)}.
%% =====================================================================
%% @spec is_integer(Node::syntaxTree(), Value::integer()) -> boolean()
%%
%% @doc Returns true if Node has type
%% integer and represents Value, otherwise
%% false.
%%
%% @see integer/1
-spec is_integer(syntaxTree(), integer()) -> boolean().
is_integer(Node, Value) ->
    case unwrap(Node) of
	{integer, _, Value} ->
	    true;
	#tree{type = integer, data = Value} ->
	    true;
	_ ->
	    false
    end.
%% =====================================================================
%% @spec integer_value(syntaxTree()) -> integer()
%%
%% @doc Returns the value represented by an integer node.
%%
%% @see integer/1
-spec integer_value(syntaxTree()) -> integer().
integer_value(Node) ->
    case unwrap(Node) of
	{integer, _, Value} ->
	    Value;
	Node1 ->
	    data(Node1)
    end.
%% =====================================================================
%% @spec integer_literal(syntaxTree()) -> string()
%%
%% @doc Returns the numeral string represented by an
%% integer node.
%%
%% @see integer/1
-spec integer_literal(syntaxTree()) -> string().
integer_literal(Node) ->
    integer_to_list(integer_value(Node)).
%% =====================================================================
%% @spec float(Value::float()) -> syntaxTree()
%%
%% @doc Creates an abstract floating-point literal. The lexical
%% representation is the decimal floating-point numeral of
%% Value.
%%
%% @see float_value/1
%% @see float_literal/1
%% type(Node) = float
%% data(Node) = Value
%%
%%	Value = float()
%%
%% `erl_parse' representation:
%%
%% {float, Pos, Value}
%%
%%	Value = float()
%% Note that under current versions of Erlang, the name `float/1' cannot
%% be used for local calls (i.e., within the module) - it will be
%% overridden by the type conversion BIF of the same name, so always use
%% `make_float/1' for local calls.
-spec float(float()) -> syntaxTree().
float(Value) ->
    make_float(Value).
make_float(Value) ->
    tree(float, Value).
revert_float(Node) ->
    Pos = get_pos(Node),
    {float, Pos, float_value(Node)}.
%% =====================================================================
%% @spec float_value(syntaxTree()) -> float()
%%
%% @doc Returns the value represented by a float node. Note
%% that floating-point values should usually not be compared for
%% equality.
%%
%% @see float/1
-spec float_value(syntaxTree()) -> float().
float_value(Node) ->
    case unwrap(Node) of
	{float, _, Value} ->
	    Value;
	Node1 ->
	    data(Node1)
    end.
%% =====================================================================
%% @spec float_literal(syntaxTree()) -> string()
%%
%% @doc Returns the numeral string represented by a float
%% node.
%%
%% @see float/1
-spec float_literal(syntaxTree()) -> string().
float_literal(Node) ->
    float_to_list(float_value(Node)).
%% =====================================================================
%% @spec char(Value::char()) -> syntaxTree()
%%
%% @doc 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".
true if Node has type
%% char and represents Value, otherwise
%% false.
%%
%% @see char/1
-spec is_char(syntaxTree(), char()) -> boolean().
is_char(Node, Value) ->
    case unwrap(Node) of
	{char, _, Value} ->
	    true;
	#tree{type = char, data = Value} ->
	    true;
	_ ->
	    false
    end.
%% =====================================================================
%% @spec char_value(syntaxTree()) -> char()
%%
%% @doc Returns the value represented by a char node.
%%
%% @see char/1
-spec char_value(syntaxTree()) -> char().
char_value(Node) ->
    case unwrap(Node) of
	{char, _, Char} ->
	    Char;
	Node1 ->
	    data(Node1)
    end.
%% =====================================================================
%% @spec char_literal(syntaxTree()) -> string()
%%
%% @doc Returns the literal string represented by a char
%% node. This includes the leading "$" character.
%%
%% @see char/1
-spec char_literal(syntaxTree()) -> nonempty_string().
char_literal(Node) ->
    io_lib:write_char(char_value(Node)).
%% =====================================================================
%% @spec string(Value::string()) -> syntaxTree()
%%
%% @doc 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. E.g., the result of
%% string("x\ny") represents any and all of
%% "x\ny", "x\12y", "x\012y" and
%% "x\^Jy"; cf. char/1.
%%
%% @see string_value/1
%% @see string_literal/1
%% @see is_string/2
%% @see char/1
%% type(Node) = string
%% data(Node) = string()
%%
%% `erl_parse' representation:
%%
%% {string, Pos, Chars}
%%
%%	Chars = string()
-spec string(string()) -> syntaxTree().
string(String) ->
    tree(string, String).
revert_string(Node) ->
    Pos = get_pos(Node),
    {string, Pos, string_value(Node)}.
%% =====================================================================
%% @spec is_string(Node::syntaxTree(), Value::string()) -> boolean()
%%
%% @doc Returns true if Node has type
%% string and represents Value, otherwise
%% false.
%%
%% @see string/1
-spec is_string(syntaxTree(), string()) -> boolean().
is_string(Node, Value) ->
    case unwrap(Node) of
	{string, _, Value} ->
	    true;
	#tree{type = string, data = Value} ->
	    true;
	_ ->
	    false
    end.
%% =====================================================================
%% @spec string_value(syntaxTree()) -> string()
%%
%% @doc Returns the value represented by a string node.
%%
%% @see string/1
-spec string_value(syntaxTree()) -> string().
string_value(Node) ->
    case unwrap(Node) of
	{string, _, List} ->
	    List;
	Node1 ->
	    data(Node1)
    end.
%% =====================================================================
%% @spec string_literal(syntaxTree()) -> string()
%%
%% @doc Returns the literal string represented by a string
%% node. This includes surrounding double-quote characters.
%%
%% @see string/1
-spec string_literal(syntaxTree()) -> nonempty_string().
string_literal(Node) ->
    io_lib:write_string(string_value(Node)).
%% =====================================================================
%% @spec atom(Name) -> syntaxTree()
%%	    Name = atom() | string()
%%
%% @doc Creates an abstract atom literal. The print name of the atom is
%% the character sequence represented by Name.
%%
%% @see atom_value/1
%% @see atom_name/1
%% @see atom_literal/1
%% @see is_atom/2
%% type(Node) = atom
%% data(Node) = atom()
%%
%% `erl_parse' representation:
%%
%% {atom, Pos, Value}
%%
%%	Value = atom()
-spec atom(atom() | string()) -> syntaxTree().
atom(Name) when is_atom(Name) ->
    tree(atom, Name);
atom(Name) ->
    tree(atom, list_to_atom(Name)).
revert_atom(Node) ->
    Pos = get_pos(Node),
    {atom, Pos, atom_value(Node)}.
%% =====================================================================
%% @spec is_atom(Node::syntaxTree(), Value::atom()) -> boolean()
%%
%% @doc Returns true if Node has type
%% atom and represents Value, otherwise
%% false.
%%
%% @see atom/1
-spec is_atom(syntaxTree(), atom()) -> boolean().
is_atom(Node, Value) ->
    case unwrap(Node) of
	{atom, _, Value} ->
	    true;
	#tree{type = atom, data = Value} ->
	    true;
	_ ->
	    false
    end.
%% =====================================================================
%% @spec atom_value(syntaxTree()) -> atom()
%%
%% @doc Returns the value represented by an atom node.
%%
%% @see atom/1
-spec atom_value(syntaxTree()) -> atom().
atom_value(Node) ->
    case unwrap(Node) of
	{atom, _, Name} ->
	    Name;
	Node1 ->
	    data(Node1)
    end.
%% =====================================================================
%% @spec atom_name(syntaxTree()) -> string()
%%
%% @doc Returns the printname of an atom node.
%%
%% @see atom/1
-spec atom_name(syntaxTree()) -> string().
atom_name(Node) ->
    atom_to_list(atom_value(Node)).
%% =====================================================================
%% @spec atom_literal(syntaxTree()) -> string()
%%
%% @doc Returns the literal string represented by an atom
%% node. This includes surrounding single-quote characters if necessary.
%%
%% Note that e.g. the result of atom("x\ny") represents
%% any and all of 'x\ny', 'x\12y',
%% 'x\012y' and 'x\^Jy\'; cf.
%% string/1.
Elements is
%% [X1, ..., Xn], the result represents
%% "{X1, ..., Xn}".
%%
%% Note: The Erlang language has distinct 1-tuples, i.e.,
%% {X} is always distinct from X itself.
tuple
%% node.
%%
%% @see tuple/1
-spec tuple_elements(syntaxTree()) -> [syntaxTree()].
tuple_elements(Node) ->
    case unwrap(Node) of
	{tuple, _, List} ->
	    List;
	Node1 ->
	    data(Node1)
    end.
%% =====================================================================
%% @spec tuple_size(syntaxTree()) -> integer()
%%
%% @doc Returns the number of elements of a tuple node.
%%
%% Note: this is equivalent to
%% length(tuple_elements(Node)), but potentially more
%% efficient.
list or nil. If List is a
%% nonempty list [E1, ..., En], the result has type
%% list and represents either "[E1, ...,
%% En]", if Tail is none, or
%% otherwise "[E1, ..., En |
%% Tail]". If List is the empty list,
%% Tail must be none, and in that
%% case the result has type nil and represents
%% "[]" (cf. nil/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 (cf.
%% 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.
[]". The empty list is traditionally called "nil".
%%
%% @see list/2
%% @see is_list_skeleton/1
%% type(Node) = nil
%% data(Node) = term()
%%
%% `erl_parse' representation:
%%
%% {nil, Pos}
-spec nil() -> syntaxTree().
nil() ->
    tree(nil).
revert_nil(Node) ->
    Pos = get_pos(Node),
    {nil, Pos}.
%% =====================================================================
%% @spec list_prefix(Node::syntaxTree()) -> [syntaxTree()]
%%
%% @doc Returns the prefix element subtrees of a list node.
%% If Node represents "[E1, ...,
%% En]" or "[E1, ..., En |
%% Tail]", the returned value is [E1, ...,
%% En].
%%
%% @see list/2
-spec list_prefix(syntaxTree()) -> [syntaxTree()].
list_prefix(Node) ->
    case unwrap(Node) of
	{cons, _, Head, _} ->
	    [Head];
	Node1 ->
	    (data(Node1))#list.prefix
    end.
%% =====================================================================
%% @spec list_suffix(Node::syntaxTree()) -> none | syntaxTree()
%%
%% @doc Returns the suffix subtree of a list node, if one
%% exists. If Node represents "[E1, ...,
%% En | Tail]", the returned value is
%% Tail, otherwise, i.e., if Node represents
%% "[E1, ..., En]", none is
%% 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 (cf.
%% compact_list/1).
Head and whose tail
%% corresponds to Tail. This is similar to
%% list([Head], Tail), except that Tail may
%% not be none, and that the result does not necessarily
%% represent exactly "[Head | Tail]", but
%% may depend on the Tail subtree. E.g., if
%% Tail represents [X, Y], the result may
%% represent "[Head, X, Y]", rather than
%% "[Head | [X, Y]]". Annotations on
%% Tail itself may be lost if Tail represents
%% a list skeleton, but comments on Tail are propagated to
%% the result.
%%
%% @see list/2
%% @see list_head/1
%% @see list_tail/1
-spec cons(syntaxTree(), syntaxTree()) -> syntaxTree().
cons(Head, Tail) ->
    case type(Tail) of
	list ->
	    copy_comments(Tail, list([Head | list_prefix(Tail)],
				     list_suffix(Tail)));
	nil ->
	    copy_comments(Tail, list([Head]));
	_ ->
	    list([Head], Tail)
    end.
%% =====================================================================
%% @spec list_head(Node::syntaxTree()) -> syntaxTree()
%%
%% @doc Returns the head element subtree of a list node. If
%% Node represents "[Head ...]", the
%% result will represent "Head".
%%
%% @see list/2
%% @see list_tail/1
%% @see cons/2
-spec list_head(syntaxTree()) -> syntaxTree().
list_head(Node) ->
    hd(list_prefix(Node)).
%% =====================================================================
%% @spec list_tail(Node::syntaxTree()) -> syntaxTree()
%%
%% @doc Returns the tail of a list node. If
%% Node represents a single-element list
%% "[E]", then the result has type
%% nil, representing "[]". If
%% Node represents "[E1, E2
%% ...]", the result will represent "[E2
%% ...]", and if Node represents
%% "[Head | Tail]", the result will
%% represent "Tail".
%%
%% @see list/2
%% @see list_head/1
%% @see cons/2
-spec list_tail(syntaxTree()) -> syntaxTree().
list_tail(Node) ->
    Tail = list_suffix(Node),
    case tl(list_prefix(Node)) of
	[] ->
	    if Tail =:= none ->
		    nil();    % implicit list terminator.
	       true ->
		    Tail
	    end;
	Es ->
	    list(Es, Tail)    % `Es' is nonempty.
    end.
%% =====================================================================
%% @spec is_list_skeleton(syntaxTree()) -> boolean()
%%
%% @doc Returns true if Node has type
%% list or nil, otherwise false.
%%
%% @see list/2
%% @see nil/0
-spec is_list_skeleton(syntaxTree()) -> boolean().
is_list_skeleton(Node) ->
    case type(Node) of
	list -> true;
	nil -> true;
	_ -> false
    end.
%% =====================================================================
%% @spec is_proper_list(Node::syntaxTree()) -> boolean()
%%
%% @doc Returns true if Node represents a
%% proper list, and false otherwise. A proper list is a
%% list skeleton either on the form "[]" or
%% "[E1, ..., En]", or "[... |
%% Tail]" where recursively Tail also
%% 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. Thus, if Node represents e.g.
%% "[... | Ns]" (where Ns is a variable), then
%% the function will return false, because it is not known
%% whether Ns will be bound to a list at run-time. If
%% Node instead represents e.g. "[1, 2, 3]" or
%% "[A | []]", then the function will return
%% true.
Node must represent a proper list. E.g., if
%% Node represents "[X1, X2 |
%% [X3, X4 | []]", then
%% list_elements(Node) yields the list [X1, X2, X3,
%% X4].
%%
%% @see list/2
%% @see is_proper_list/1
-spec list_elements(syntaxTree()) -> [syntaxTree()].
list_elements(Node) ->
    lists:reverse(list_elements(Node, [])).
list_elements(Node, As) ->
    case type(Node) of
	list ->
	    As1 = lists:reverse(list_prefix(Node)) ++ As,
	    case list_suffix(Node) of
		none ->
		    As1;
		Tail ->
		    list_elements(Tail, As1)
	    end;
	nil ->
	    As
    end.
%% =====================================================================
%% @spec list_length(Node::syntaxTree()) -> integer()
%%
%% @doc Returns the number of element subtrees of a list skeleton.
%% Node must represent a proper list. E.g., if
%% Node represents "[X1 | [X2, X3 | [X4, X5,
%% X6]]]", then list_length(Node) returns the
%% integer 6.
%%
%% Note: this is equivalent to
%% length(list_elements(Node)), but potentially more
%% efficient.
Node represents "[E1, ..., En |
%% Tail]", the result represents "[E1 |
%% ... [En | Tail1] ... ]", where
%% Tail1 is the result of
%% normalize_list(Tail). If Node represents
%% "[E1, ..., En]", the result simply
%% represents "[E1 | ... [En | []] ...
%% ]". If Node does not represent a list skeleton,
%% Node itself is returned.
%%
%% @see list/2
%% @see compact_list/1
-spec normalize_list(syntaxTree()) -> syntaxTree().
normalize_list(Node) ->
    case type(Node) of
	list ->
	    P = list_prefix(Node),
	    case list_suffix(Node) of
		none ->
		    copy_attrs(Node, normalize_list_1(P, nil()));
		Tail ->
		    Tail1 = normalize_list(Tail),
		    copy_attrs(Node, normalize_list_1(P, Tail1))
	    end;
	_ ->
	    Node
    end.
normalize_list_1(Es, Tail) ->
    lists:foldr(fun (X, A) ->
			list([X], A)    % not `cons'!
		end,
		Tail, Es).
%% =====================================================================
%% @spec compact_list(Node::syntaxTree()) -> syntaxTree()
%%
%% @doc 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 list/2
%% @see normalize_list/1
-spec compact_list(syntaxTree()) -> syntaxTree().
compact_list(Node) ->
    case type(Node) of
	list ->
	    case list_suffix(Node) of
		none ->
		    Node;
		Tail ->
		    case type(Tail) of
			list ->
			    Tail1 = compact_list(Tail),
			    Node1 = list(list_prefix(Node) ++
					 list_prefix(Tail1),
					 list_suffix(Tail1)),
			    join_comments(Tail1,
					  copy_attrs(Node,
						     Node1));
			nil ->
			    Node1 = list(list_prefix(Node)),
			    join_comments(Tail,
					  copy_attrs(Node,
						     Node1));
			_ ->
			    Node 
		    end
	    end;
	_ ->
	    Node
    end.
%% =====================================================================
%% @spec binary(Fields::[syntaxTree()]) -> syntaxTree()
%%
%% @doc Creates an abstract binary-object template. If
%% Fields is [F1, ..., Fn], the result
%% represents "<<F1, ...,
%% Fn>>".
%%
%% @see binary_fields/1
%% @see binary_field/2
%% type(Node) = binary
%% data(Node) = Fields
%%
%%	Fields = [syntaxTree()]
%%
%% `erl_parse' representation:
%%
%% {bin, Pos, Fields}
%%
%%	Fields = [Field]
%%	Field = {bin_element, ...}
%%
%%	See `binary_field' for documentation on `erl_parse' binary
%%	fields (or "elements").
-spec binary([syntaxTree()]) -> syntaxTree().
binary(List) ->
    tree(binary, List).
revert_binary(Node) ->
    Pos = get_pos(Node),
    {bin, Pos, binary_fields(Node)}.
%% =====================================================================
%% @spec binary_fields(syntaxTree()) -> [syntaxTree()]
%%
%% @doc Returns the list of field subtrees of a binary
%% node.
%%
%% @see binary/1
%% @see binary_field/2
-spec binary_fields(syntaxTree()) -> [syntaxTree()].
binary_fields(Node) ->
    case unwrap(Node) of
	{bin, _, List} ->
	    List;
	Node1 ->
	    data(Node1)
    end.
%% =====================================================================
%% @spec binary_field(Body) -> syntaxTree()
%% @equiv binary_field(Body, [])
-spec binary_field(syntaxTree()) -> syntaxTree().
binary_field(Body) ->
    binary_field(Body, []).
%% =====================================================================
%% @spec binary_field(Body::syntaxTree(), Size,
%%                    Types::[syntaxTree()]) -> syntaxTree()
%%	    Size = none | syntaxTree()
%%
%% @doc 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.)
%%
%% @see binary/1
%% @see binary_field/2
%% @see size_qualifier/2
-spec binary_field(syntaxTree(), 'none' | syntaxTree(), [syntaxTree()]) ->
        syntaxTree().
binary_field(Body, none, Types) ->
    binary_field(Body, Types);
binary_field(Body, Size, Types) ->
    binary_field(size_qualifier(Body, Size), Types).
%% =====================================================================
%% @spec binary_field(Body::syntaxTree(), Types::[syntaxTree()]) ->
%%           syntaxTree()
%%
%% @doc Creates an abstract binary template field. If
%% Types is the empty list, the result simply represents
%% "Body", otherwise, if Types is
%% [T1, ..., Tn], the result represents
%% "Body/T1-...-Tn".
%%
%% @see binary/1
%% @see binary_field/1
%% @see binary_field/3
%% @see binary_field_body/1
%% @see binary_field_types/1
%% @see binary_field_size/1
-record(binary_field, {body :: syntaxTree(), types :: [syntaxTree()]}).
%% type(Node) = binary_field
%% data(Node) = #binary_field{body :: Body, types :: Types}
%%
%%	    Body = syntaxTree()
%%	    Types = [syntaxTree()]
%%
%% `erl_parse' representation:
%%
%% {bin_element, Pos, Expr, Size, TypeList}
%%
%%	Expr = erl_parse()
%%	Size = default | erl_parse()
%%	TypeList = default | [Type] \ []
%%	Type = atom() | {atom(), integer()}
-spec binary_field(syntaxTree(), [syntaxTree()]) -> syntaxTree().
binary_field(Body, Types) ->
    tree(binary_field, #binary_field{body = Body, types = Types}).
revert_binary_field(Node) ->
    Pos = get_pos(Node),
    Body = binary_field_body(Node),
    {Expr, Size} = case type(Body) of
		       size_qualifier ->
			   %% Note that size qualifiers are not
			   %% revertible out of context.
			   {size_qualifier_body(Body),
			    size_qualifier_argument(Body)};
		       _ ->
			   {Body, default}
		   end,
    Types = case binary_field_types(Node) of
		[] ->
		    default;
		Ts ->
		    fold_binary_field_types(Ts)
	    end,
    {bin_element, Pos, Expr, Size, Types}.
%% =====================================================================
%% @spec binary_field_body(syntaxTree()) -> syntaxTree()
%%
%% @doc Returns the body subtree of a binary_field.
%%
%% @see binary_field/2
-spec binary_field_body(syntaxTree()) -> syntaxTree().
binary_field_body(Node) ->
    case unwrap(Node) of
	{bin_element, _, Body, Size, _} ->
	    if Size =:= default ->
		    Body;
	       true ->
		    size_qualifier(Body, Size)
	    end;
	Node1 ->
	    (data(Node1))#binary_field.body
    end.
%% =====================================================================
%% @spec binary_field_types(Node::syntaxTree()) -> [syntaxTree()]
%%
%% @doc 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 binary_field/2
-spec binary_field_types(syntaxTree()) -> [syntaxTree()].
binary_field_types(Node) ->
    case unwrap(Node) of
	{bin_element, Pos, _, _, Types} ->
	    if Types =:= default ->
		    [];
	       true ->
		    unfold_binary_field_types(Types, Pos)
	    end;
	Node1 ->
	    (data(Node1))#binary_field.types
    end.
%% =====================================================================
%% @spec binary_field_size(Node::syntaxTree()) -> none | syntaxTree()
%%
%% @doc 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 binary_field/2
%% @see binary_field/3
-spec binary_field_size(syntaxTree()) -> 'none' | syntaxTree().
binary_field_size(Node) ->
    case unwrap(Node) of
	{bin_element, _, _, Size, _} ->
	    if Size =:= default ->
		    none;
	       true ->
		    Size
	    end;
	Node1 ->
	    Body = (data(Node1))#binary_field.body,
	    case type(Body) of
		size_qualifier ->
		    size_qualifier_argument(Body);
		_ ->
		    none
	    end
    end.
%% =====================================================================
%% @spec size_qualifier(Body::syntaxTree(), Size::syntaxTree()) ->
%%           syntaxTree()
%%
%% @doc Creates an abstract size qualifier. The result represents
%% "Body:Size".
%%
%% @see size_qualifier_body/1
%% @see size_qualifier_argument/1
-record(size_qualifier, {body :: syntaxTree(), size :: syntaxTree()}).
%% type(Node) = size_qualifier
%% data(Node) = #size_qualifier{body :: Body, size :: Size}
%%
%%	Body = Size = syntaxTree()
-spec size_qualifier(syntaxTree(), syntaxTree()) -> syntaxTree().
size_qualifier(Body, Size) ->
    tree(size_qualifier,
	 #size_qualifier{body = Body, size = Size}).
%% =====================================================================
%% @spec size_qualifier_body(syntaxTree()) -> syntaxTree()
%%
%% @doc Returns the body subtree of a size_qualifier
%% node.
%%
%% @see size_qualifier/2
-spec size_qualifier_body(syntaxTree()) -> syntaxTree().
size_qualifier_body(Node) ->
    (data(Node))#size_qualifier.body.
%% =====================================================================
%% @spec size_qualifier_argument(syntaxTree()) -> syntaxTree()
%%
%% @doc Returns the argument subtree (the size) of a
%% size_qualifier node.
%%
%% @see size_qualifier/2
-spec size_qualifier_argument(syntaxTree()) -> syntaxTree().
size_qualifier_argument(Node) ->
    (data(Node))#size_qualifier.size.
%% =====================================================================
%% @spec error_marker(Error::term()) -> syntaxTree()
%%
%% @doc Creates an abstract error marker. The result represents an
%% occurrence of an error in the source code, with an associated Erlang
%% I/O ErrorInfo structure given by Error (see module
%% {@link //stdlib/io} 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 error_marker_info/1 %% @see warning_marker/1 %% @see eof_marker/0 %% @see is_form/1 %% type(Node) = error_marker %% data(Node) = term() %% %% `erl_parse' representation: %% %% {error, Error} %% %% Error = term() %% %% Note that there is no position information for the node %% itself: `get_pos' and `set_pos' handle this as a special case. -spec error_marker(term()) -> syntaxTree(). error_marker(Error) -> tree(error_marker, Error). revert_error_marker(Node) -> %% Note that the position information of the node itself is not %% preserved. {error, error_marker_info(Node)}. %% ===================================================================== %% @spec error_marker_info(syntaxTree()) -> term() %% %% @doc Returns the ErrorInfo structure of anerror_marker
%% node.
%%
%% @see error_marker/1
-spec error_marker_info(syntaxTree()) -> term().
error_marker_info(Node) ->
    case unwrap(Node) of
	{error, Error} ->
	    Error;
	T ->
	    data(T)
    end.
%% =====================================================================
%% @spec warning_marker(Error::term()) -> syntaxTree()
%%
%% @doc Creates an abstract warning marker. The result represents an
%% occurrence of a possible problem in the source code, with an
%% associated Erlang I/O ErrorInfo structure given by Error
%% (see module {@link //stdlib/io} for details). Warning 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 warning_marker_info/1 %% @see error_marker/1 %% @see eof_marker/0 %% @see is_form/1 %% type(Node) = warning_marker %% data(Node) = term() %% %% `erl_parse' representation: %% %% {warning, Error} %% %% Error = term() %% %% Note that there is no position information for the node %% itself: `get_pos' and `set_pos' handle this as a special case. -spec warning_marker(term()) -> syntaxTree(). warning_marker(Warning) -> tree(warning_marker, Warning). revert_warning_marker(Node) -> %% Note that the position information of the node itself is not %% preserved. {warning, warning_marker_info(Node)}. %% ===================================================================== %% @spec warning_marker_info(syntaxTree()) -> term() %% %% @doc Returns the ErrorInfo structure of awarning_marker
%% node.
%%
%% @see warning_marker/1
-spec warning_marker_info(syntaxTree()) -> term().
warning_marker_info(Node) ->
    case unwrap(Node) of
	{warning, Error} ->
	    Error;
	T ->
	    data(T)
    end.
%% =====================================================================
%% @spec eof_marker() -> syntaxTree()
%%
%% @doc 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 error_marker/1 %% @see warning_marker/1 %% @see is_form/1 %% type(Node) = eof_marker %% data(Node) = term() %% %% `erl_parse' representation: %% %% {eof, Pos} -spec eof_marker() -> syntaxTree(). eof_marker() -> tree(eof_marker). revert_eof_marker(Node) -> Pos = get_pos(Node), {eof, Pos}. %% ===================================================================== %% @spec attribute(Name) -> syntaxTree() %% @equiv attribute(Name, none) -spec attribute(syntaxTree()) -> syntaxTree(). attribute(Name) -> attribute(Name, none). %% ===================================================================== %% @spec attribute(Name::syntaxTree(), Arguments) -> syntaxTree() %% Arguments = none | [syntaxTree()] %% %% @doc Creates an abstract program attribute. If %%Arguments is [A1, ..., An], the result
%% represents "-Name(A1, ...,
%% An).". Otherwise, if Arguments is
%% none, 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 of Body (viewed
%% as a sequence of tokens). The text node type can be used
%% for a Body that is not a normal Erlang construct.
attribute node.
%%
%% @see attribute/1
-spec attribute_name(syntaxTree()) -> syntaxTree().
attribute_name(Node) ->
    case unwrap(Node) of
	{attribute, Pos, Name, _} ->
	    set_pos(atom(Name), Pos);
	Node1 ->
	    (data(Node1))#attribute.name
    end.
%% =====================================================================
%% @spec attribute_arguments(Node::syntaxTree()) ->
%%           none | [syntaxTree()]
%%
%% @doc Returns the list of argument subtrees of an
%% attribute node, if any. If Node
%% represents "-Name.", the result is
%% none. Otherwise, if Node represents
%% "-Name(E1, ..., En).",
%% [E1, ..., E1] is returned.
%%
%% @see attribute/1
-spec attribute_arguments(syntaxTree()) -> none | [syntaxTree()].
attribute_arguments(Node) ->
    case unwrap(Node) of
	{attribute, Pos, Name, Data} ->
	    case Name of
		module ->
		    {M1, Vs} =
			case Data of
			    {M0, Vs0} ->
				{M0, unfold_variable_names(Vs0, Pos)};
			    M0 ->
				{M0, none}
			end,
		    M2 = if is_list(M1) ->
				 qualified_name([atom(A) || A <- M1]);
			    true ->
				 atom(M1)
			 end,
		    M = set_pos(M2, Pos),
		    if Vs == none -> [M];
		       true -> [M, set_pos(list(Vs), Pos)]
		    end;
		export ->
		    [set_pos(
		       list(unfold_function_names(Data, Pos)),
		       Pos)];
		import ->
		    case Data of
			{Module, Imports} ->
			    [if is_list(Module) ->
				     qualified_name([atom(A)
						     || A <- Module]);
				true ->
				     set_pos(atom(Module), Pos)
			     end,
			     set_pos(
			       list(unfold_function_names(Imports, Pos)),
			       Pos)];
			_ ->
			    [qualified_name([atom(A) || A <- Data])]
		    end;
		file ->
		    {File, Line} = Data,
		    [set_pos(string(File), Pos),
		     set_pos(integer(Line), Pos)];
		record ->
		    %% Note that we create a tuple as container
		    %% for the second argument!
		    {Type, Entries} = Data,
		    [set_pos(atom(Type), Pos),
		     set_pos(tuple(unfold_record_fields(Entries)),
			     Pos)];
		_ ->
		    %% Standard single-term generic attribute.
		    [set_pos(abstract(Data), Pos)]
	    end;
	Node1 ->
	    (data(Node1))#attribute.args
    end.
%% =====================================================================
%% @spec arity_qualifier(Body::syntaxTree(), Arity::syntaxTree()) ->
%%           syntaxTree()
%%
%% @doc Creates an abstract arity qualifier. The result represents
%% "Body/Arity".
%%
%% @see arity_qualifier_body/1
%% @see arity_qualifier_argument/1
-record(arity_qualifier, {body :: syntaxTree(), arity :: syntaxTree()}).
%% type(Node) = arity_qualifier
%% data(Node) = #arity_qualifier{body :: Body, arity :: Arity}
%%
%%	Body = Arity = syntaxTree()
-spec arity_qualifier(syntaxTree(), syntaxTree()) -> syntaxTree().
arity_qualifier(Body, Arity) ->
    tree(arity_qualifier,
	 #arity_qualifier{body = Body, arity = Arity}).
%% =====================================================================
%% @spec arity_qualifier_body(syntaxTree()) -> syntaxTree()
%%
%% @doc Returns the body subtree of an arity_qualifier
%% node.
%%
%% @see arity_qualifier/2
-spec arity_qualifier_body(syntaxTree()) -> syntaxTree().
arity_qualifier_body(Node) ->
    (data(Node))#arity_qualifier.body.
%% =====================================================================
%% @spec arity_qualifier_argument(syntaxTree()) -> syntaxTree()
%%
%% @doc Returns the argument (the arity) subtree of an
%% arity_qualifier node.
%%
%% @see arity_qualifier/2
-spec arity_qualifier_argument(syntaxTree()) -> syntaxTree().
arity_qualifier_argument(Node) ->
    (data(Node))#arity_qualifier.arity.
%% =====================================================================
%% @spec module_qualifier(Module::syntaxTree(), Body::syntaxTree()) ->
%%           syntaxTree()
%%
%% @doc Creates an abstract module qualifier. The result represents
%% "Module:Body".
%%
%% @see module_qualifier_argument/1
%% @see module_qualifier_body/1
-record(module_qualifier, {module :: syntaxTree(), body :: syntaxTree()}).
%% type(Node) = module_qualifier
%% data(Node) = #module_qualifier{module :: Module, body :: Body}
%%
%%	Module = Body = syntaxTree()
%%
%% `erl_parse' representation:
%%
%% {remote, Pos, Module, Arg}
%%
%%	Module = Arg = erl_parse()
-spec module_qualifier(syntaxTree(), syntaxTree()) -> syntaxTree().
module_qualifier(Module, Body) ->
    tree(module_qualifier,
	 #module_qualifier{module = Module, body = Body}).
revert_module_qualifier(Node) ->
    Pos = get_pos(Node),
    Module = module_qualifier_argument(Node),
    Body = module_qualifier_body(Node),
    {remote, Pos, Module, Body}.
%% =====================================================================
%% @spec module_qualifier_argument(syntaxTree()) -> syntaxTree()
%%
%% @doc Returns the argument (the module) subtree of a
%% module_qualifier node.
%%
%% @see module_qualifier/2
-spec module_qualifier_argument(syntaxTree()) -> syntaxTree().
module_qualifier_argument(Node) ->
    case unwrap(Node) of
	{remote, _, Module, _} ->
	    Module;
	Node1 ->
	    (data(Node1))#module_qualifier.module
    end.
%% =====================================================================
%% @spec module_qualifier_body(syntaxTree()) -> syntaxTree()
%%
%% @doc Returns the body subtree of a module_qualifier
%% node.
%%
%% @see module_qualifier/2
-spec module_qualifier_body(syntaxTree()) -> syntaxTree().
module_qualifier_body(Node) ->
    case unwrap(Node) of
	{remote, _, _, Body} ->
	    Body;
	Node1 ->
	    (data(Node1))#module_qualifier.body
    end.
%% =====================================================================
%% @spec qualified_name(Segments::[syntaxTree()]) -> syntaxTree()
%%
%% @doc Creates an abstract qualified name. The result represents
%% "S1.S2. ... .Sn", if
%% Segments is [S1, S2, ..., Sn].
%%
%% @see qualified_name_segments/1
%% type(Node) = qualified_name
%% data(Node) = [syntaxTree()]
%%
%% `erl_parse' representation:
%%
%% {record_field, Pos, Node, Node}
%%
%%	Node = {atom, Pos, Value} | {record_field, Pos, Node, Node}
%%
%% Note that if not all leaf subnodes are (abstract) atoms, then Node
%% represents a Mnemosyne query record field access ('record_access');
%% see type/1 for details.
-spec qualified_name([syntaxTree()]) -> syntaxTree().
qualified_name(Segments) ->
    tree(qualified_name, Segments).
revert_qualified_name(Node) ->
    Pos = get_pos(Node),
    fold_qualified_name(qualified_name_segments(Node), Pos).
%% =====================================================================
%% @spec qualified_name_segments(syntaxTree()) -> [syntaxTree()]
%%
%% @doc Returns the list of name segments of a
%% qualified_name node.
%%
%% @see qualified_name/1
-spec qualified_name_segments(syntaxTree()) -> [syntaxTree()].
qualified_name_segments(Node) ->
    case unwrap(Node) of
	{record_field, _, _, _} = Node1 ->
	    unfold_qualified_name(Node1);
	Node1 ->
	    data(Node1)
    end.
%% =====================================================================
%% @spec function(Name::syntaxTree(), Clauses::[syntaxTree()]) ->
%%           syntaxTree()
%%
%% @doc Creates an abstract function definition. If Clauses
%% is [C1, ..., Cn], the result represents
%% "Name C1; ...; Name
%% Cn.". More exactly, if each Ci
%% represents "(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 function_name/1
%% @see function_clauses/1
%% @see function_arity/1
%% @see is_form/1
%% @see rule/2
-record(function, {name, clauses}).
%% XXX: This one is problematic because there is a tuple with the same
%%      tag and size that comes from 'erl_parse'
%% -record(function, {name :: syntaxTree(), clauses :: [syntaxTree()]}).
%% type(Node) = function
%% data(Node) = #function{name :: Name, clauses :: Clauses}
%%
%%	Name = syntaxTree()
%%	Clauses = [syntaxTree()]
%%
%%	(There's no real point in precomputing and storing the arity,
%%	and passing it as a constructor argument makes it possible to
%%	end up with an inconsistent value. Besides, some people might
%%	want to check all clauses, and not just the first, so the
%%	computation is not obvious.)
%%
%% `erl_parse' representation:
%%
%% {function, Pos, Name, Arity, Clauses}
%%
%%	Name = atom()
%%	Arity = integer()
%%	Clauses = [Clause] \ []
%%	Clause = {clause, ...}
%%
%%	where the number of patterns in each clause should be equal to
%%	the integer `Arity'; see `clause' for documentation on
%%	`erl_parse' clauses.
-spec function(syntaxTree(), [syntaxTree()]) -> syntaxTree().
function(Name, Clauses) ->
    tree(function, #function{name = Name, clauses = Clauses}).
revert_function(Node) ->
    Name = function_name(Node),
    Clauses = [revert_clause(C) || C <- function_clauses(Node)],
    Pos = get_pos(Node),
    case type(Name) of
	atom ->
	    A = function_arity(Node),
	    {function, Pos, concrete(Name), A, Clauses};
	_ ->
	    Node
    end.
%% =====================================================================
%% @spec function_name(syntaxTree()) -> syntaxTree()
%%
%% @doc Returns the name subtree of a function node.
%%
%% @see function/2
-spec function_name(syntaxTree()) -> syntaxTree().
function_name(Node) ->
    case unwrap(Node) of
	{function, Pos, Name, _, _} ->
	    set_pos(atom(Name), Pos);
	Node1 ->
	    (data(Node1))#function.name
    end.
%% =====================================================================
%% @spec function_clauses(syntaxTree()) -> [syntaxTree()]
%%
%% @doc Returns the list of clause subtrees of a function
%% node.
%%
%% @see function/2
-spec function_clauses(syntaxTree()) -> [syntaxTree()].
function_clauses(Node) ->
    case unwrap(Node) of
	{function, _, _, _, Clauses} ->
	    Clauses;
	Node1 ->
	    (data(Node1))#function.clauses
    end.
%% =====================================================================
%% @spec function_arity(Node::syntaxTree()) -> integer()
%%
%% @doc Returns the arity of a function node. The result
%% is the number of parameter patterns in the first clause of the
%% function; subsequent clauses are ignored.
%%
%% An exception is thrown if function_clauses(Node)
%% returns an empty list, or if the first element of that list is not
%% a syntax tree C of type clause such that
%% clause_patterns(C) is a nonempty list.
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:
%% 
[]. This is equivalent to passing
%%       none.[E1, ..., Ej] of syntax trees.
%%       This is equivalent to passing conjunction([E1, ...,
%%       Ej]).[[E1_1, ...,
%%       E1_k1], ..., [Ej_1, ..., Ej_kj]], which is equivalent
%%       to passing disjunction([conjunction([E1_1, ...,
%%       E1_k1]), ..., conjunction([Ej_1, ..., Ej_kj])]).clause
%% node.
%%
%% @see clause/3
-spec clause_patterns(syntaxTree()) -> [syntaxTree()].
clause_patterns(Node) ->
    case unwrap(Node) of
	{clause, _, Patterns, _, _} ->
	    Patterns;
	Node1 ->
	    (data(Node1))#clause.patterns
    end.
%% =====================================================================
%% @spec clause_guard(Node::syntaxTree()) -> none | syntaxTree()
%%
%% @doc 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 clause/3
-spec clause_guard(syntaxTree()) -> 'none' | syntaxTree().
clause_guard(Node) ->
    case unwrap(Node) of
	{clause, _, _, Guard, _} ->
	    case Guard of
		[] -> none;
		[L | _] when is_list(L) ->
		    disjunction(conjunction_list(Guard));
		[_ | _] ->
		    conjunction(Guard)
	    end;
	Node1 ->
	    (data(Node1))#clause.guard
    end.
%% =====================================================================
%% @spec clause_body(syntaxTree()) -> [syntaxTree()]
%%
%% @doc Return the list of body subtrees of a clause
%% node.
%%
%% @see clause/3
-spec clause_body(syntaxTree()) -> [syntaxTree()].
clause_body(Node) ->
    case unwrap(Node) of
	{clause, _, _, _, Body} ->
	    Body;
	Node1 ->
	    (data(Node1))#clause.body
    end.
%% =====================================================================
%% @spec disjunction(List::[syntaxTree()]) -> syntaxTree()
%%
%% @doc Creates an abstract disjunction. If List is
%% [E1, ..., En], the result represents
%% "E1; ...; En".
%%
%% @see disjunction_body/1
%% @see conjunction/1
%% type(Node) = disjunction
%% data(Node) = [syntaxTree()]
-spec disjunction([syntaxTree()]) -> syntaxTree().
disjunction(Tests) ->
    tree(disjunction, Tests).
%% =====================================================================
%% @spec disjunction_body(syntaxTree()) -> [syntaxTree()]
%%
%% @doc Returns the list of body subtrees of a
%% disjunction node.
%%
%% @see disjunction/1
-spec disjunction_body(syntaxTree()) -> [syntaxTree()].
disjunction_body(Node) ->
    data(Node).
%% =====================================================================
%% @spec conjunction(List::[syntaxTree()]) -> syntaxTree()
%%
%% @doc Creates an abstract conjunction. If List is
%% [E1, ..., En], the result represents
%% "E1, ..., En".
%%
%% @see conjunction_body/1
%% @see disjunction/1
%% type(Node) = conjunction
%% data(Node) = [syntaxTree()]
-spec conjunction([syntaxTree()]) -> syntaxTree().
conjunction(Tests) ->
    tree(conjunction, Tests).
%% =====================================================================
%% @spec conjunction_body(syntaxTree()) -> [syntaxTree()]
%%
%% @doc Returns the list of body subtrees of a
%% conjunction node.
%%
%% @see conjunction/1
-spec conjunction_body(syntaxTree()) -> [syntaxTree()].
conjunction_body(Node) ->
    data(Node).
%% =====================================================================
%% @spec catch_expr(Expr::syntaxTree()) -> syntaxTree()
%%
%% @doc Creates an abstract catch-expression. The result represents
%% "catch Expr".
%%
%% @see catch_expr_body/1
%% type(Node) = catch_expr
%% data(Node) = syntaxTree()
%%
%% `erl_parse' representation:
%%
%% {'catch', Pos, Expr}
%%
%%	Expr = erl_parse()
-spec catch_expr(syntaxTree()) -> syntaxTree().
catch_expr(Expr) ->
    tree(catch_expr, Expr).
revert_catch_expr(Node) ->
    Pos = get_pos(Node),
    Expr = catch_expr_body(Node),
    {'catch', Pos, Expr}.
%% =====================================================================
%% @spec catch_expr_body(syntaxTree()) -> syntaxTree()
%%
%% @doc Returns the body subtree of a catch_expr node.
%%
%% @see catch_expr/1
-spec catch_expr_body(syntaxTree()) -> syntaxTree().
catch_expr_body(Node) ->
    case unwrap(Node) of
	{'catch', _, Expr} ->
	    Expr;
	Node1 ->
	    data(Node1)
    end.
%% =====================================================================
%% @spec match_expr(Pattern::syntaxTree(), Body::syntaxTree()) ->
%%           syntaxTree()
%%
%% @doc Creates an abstract match-expression. The result represents
%% "Pattern = Body".
%%
%% @see match_expr_pattern/1
%% @see match_expr_body/1
-record(match_expr, {pattern :: syntaxTree(), body :: syntaxTree()}).
%% type(Node) = match_expr
%% data(Node) = #match_expr{pattern :: Pattern, body :: Body}
%%
%%	Pattern = Body = syntaxTree()
%%
%% `erl_parse' representation:
%%
%% {match, Pos, Pattern, Body}
%%
%%	Pattern = Body = erl_parse()
-spec match_expr(syntaxTree(), syntaxTree()) -> syntaxTree().
match_expr(Pattern, Body) ->
    tree(match_expr, #match_expr{pattern = Pattern, body = Body}).
revert_match_expr(Node) ->
    Pos = get_pos(Node),
    Pattern = match_expr_pattern(Node),
    Body = match_expr_body(Node),
    {match, Pos, Pattern, Body}.
%% =====================================================================
%% @spec match_expr_pattern(syntaxTree()) -> syntaxTree()
%%
%% @doc Returns the pattern subtree of a match_expr node.
%%
%% @see match_expr/2
-spec match_expr_pattern(syntaxTree()) -> syntaxTree().
match_expr_pattern(Node) ->
    case unwrap(Node) of
	{match, _, Pattern, _} ->
	    Pattern;
	Node1 ->
	    (data(Node1))#match_expr.pattern
    end.
%% =====================================================================
%% @spec match_expr_body(syntaxTree()) -> syntaxTree()
%%
%% @doc Returns the body subtree of a match_expr node.
%%
%% @see match_expr/2
-spec match_expr_body(syntaxTree()) -> syntaxTree().
match_expr_body(Node) ->
    case unwrap(Node) of
	{match, _, _, Body} ->
	    Body;
	Node1 ->
	    (data(Node1))#match_expr.body
    end.
%% =====================================================================
%% @spec operator(Name) -> syntaxTree()
%%	    Name = atom() | string()
%%
%% @doc Creates 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 an operator is never
%% written within single-quotes; e.g., the result of
%% operator('++') represents "++" rather
%% than "'++'".
%%
%% @see operator_name/1
%% @see operator_literal/1
%% @see atom/1
%% type(Node) = operator
%% data(Node) = atom()
-spec operator(atom() | string()) -> syntaxTree().
operator(Name) when is_atom(Name) ->
    tree(operator, Name);
operator(Name) ->
    tree(operator, list_to_atom(Name)).
%% =====================================================================
%% @spec operator_name(syntaxTree()) -> atom()
%%
%% @doc Returns the name of an operator node. Note that
%% the name is returned as an atom.
%%
%% @see operator/1
-spec operator_name(syntaxTree()) -> atom().
operator_name(Node) ->
    data(Node).
%% =====================================================================
%% @spec operator_literal(syntaxTree()) -> string()
%%
%% @doc Returns the literal string represented by an
%% operator node. This is simply the operator name as a
%% string.
%%
%% @see operator/1
-spec operator_literal(syntaxTree()) -> string().
operator_literal(Node) ->
    atom_to_list(operator_name(Node)).
%% =====================================================================
%% @spec infix_expr(Left::syntaxTree(), Operator::syntaxTree(),
%%                  Right::syntaxTree()) -> syntaxTree()
%%
%% @doc Creates an abstract infix operator expression. The result
%% represents "Left Operator
%% Right".
%%
%% @see infix_expr_left/1
%% @see infix_expr_right/1
%% @see infix_expr_operator/1
%% @see prefix_expr/2
-record(infix_expr, {operator :: syntaxTree(),
		     left     :: syntaxTree(),
		     right    :: syntaxTree()}).
%% type(Node) = infix_expr
%% data(Node) = #infix_expr{left :: Left, operator :: Operator,
%%		            right :: Right}
%%
%%	Left = Operator = Right = syntaxTree()
%%
%% `erl_parse' representation:
%%
%% {op, Pos, Operator, Left, Right}
%%
%%	Operator = atom()
%%	Left = Right = erl_parse()
-spec infix_expr(syntaxTree(), syntaxTree(), syntaxTree()) -> syntaxTree().
infix_expr(Left, Operator, Right) ->
    tree(infix_expr, #infix_expr{operator = Operator, left = Left,
				 right = Right}).
revert_infix_expr(Node) ->
    Pos = get_pos(Node),
    Operator = infix_expr_operator(Node),
    Left = infix_expr_left(Node),
    Right = infix_expr_right(Node),
    case type(Operator) of
	operator ->
	    %% Note that the operator itself is not revertible out
	    %% of context.
	    {op, Pos, operator_name(Operator), Left, Right};
	_ ->
	    Node
    end.
%% =====================================================================
%% @spec infix_expr_left(syntaxTree()) -> syntaxTree()
%%
%% @doc Returns the left argument subtree of an
%% infix_expr node.
%%
%% @see infix_expr/3
-spec infix_expr_left(syntaxTree()) -> syntaxTree().
infix_expr_left(Node) ->
    case unwrap(Node) of
	{op, _, _, Left, _} ->
	    Left;
	Node1 ->
	    (data(Node1))#infix_expr.left
    end.
%% =====================================================================
%% @spec infix_expr_operator(syntaxTree()) -> syntaxTree()
%%
%% @doc Returns the operator subtree of an infix_expr
%% node.
%%
%% @see infix_expr/3
-spec infix_expr_operator(syntaxTree()) -> syntaxTree().
infix_expr_operator(Node) ->
    case unwrap(Node) of
	{op, Pos, Operator, _, _} ->
	    set_pos(operator(Operator), Pos);
	Node1 ->
	    (data(Node1))#infix_expr.operator
    end.
%% =====================================================================
%% @spec infix_expr_right(syntaxTree()) -> syntaxTree()
%%
%% @doc Returns the right argument subtree of an
%% infix_expr node.
%%
%% @see infix_expr/3
-spec infix_expr_right(syntaxTree()) -> syntaxTree().
infix_expr_right(Node) ->
    case unwrap(Node) of
	{op, _, _, _, Right} ->
	    Right;
	Node1 ->
	    (data(Node1))#infix_expr.right
    end.
%% =====================================================================
%% @spec prefix_expr(Operator::syntaxTree(), Argument::syntaxTree()) ->
%%           syntaxTree()
%%
%% @doc Creates an abstract prefix operator expression. The result
%% represents "Operator Argument".
%%
%% @see prefix_expr_argument/1
%% @see prefix_expr_operator/1
%% @see infix_expr/3
-record(prefix_expr, {operator :: syntaxTree(), argument :: syntaxTree()}).
%% type(Node) = prefix_expr
%% data(Node) = #prefix_expr{operator :: Operator,
%%		             argument :: Argument}
%%
%%	Operator = Argument = syntaxTree()
%%
%% `erl_parse' representation:
%%
%% {op, Pos, Operator, Arg}
%%
%%	Operator = atom()
%%	Argument = erl_parse()
-spec prefix_expr(syntaxTree(), syntaxTree()) -> syntaxTree().
prefix_expr(Operator, Argument) ->
    tree(prefix_expr, #prefix_expr{operator = Operator,
				   argument = Argument}).
revert_prefix_expr(Node) ->
    Pos = get_pos(Node),
    Operator = prefix_expr_operator(Node),
    Argument = prefix_expr_argument(Node),
    case type(Operator) of
	operator ->
	    %% Note that the operator itself is not revertible out
	    %% of context.
	    {op, Pos, operator_name(Operator), Argument};
	_ ->
	    Node
    end.
%% =====================================================================
%% @spec prefix_expr_operator(syntaxTree()) -> syntaxTree()
%%
%% @doc Returns the operator subtree of a prefix_expr
%% node.
%%
%% @see prefix_expr/2
-spec prefix_expr_operator(syntaxTree()) -> syntaxTree().
prefix_expr_operator(Node) ->
    case unwrap(Node) of
	{op, Pos, Operator, _} ->
	    set_pos(operator(Operator), Pos);
	Node1 ->
	    (data(Node1))#prefix_expr.operator
    end.
%% =====================================================================
%% @spec prefix_expr_argument(syntaxTree()) -> syntaxTree()
%%
%% @doc Returns the argument subtree of a prefix_expr
%% node.
%%
%% @see prefix_expr/2
-spec prefix_expr_argument(syntaxTree()) -> syntaxTree().
prefix_expr_argument(Node) ->
    case unwrap(Node) of
	{op, _, _, Argument} ->
	    Argument;
	Node1 ->
	    (data(Node1))#prefix_expr.argument
    end.
%% =====================================================================
%% @spec record_field(Name) -> syntaxTree()
%% @equiv record_field(Name, none)
-spec record_field(syntaxTree()) -> syntaxTree().
record_field(Name) ->
    record_field(Name, none).
%% =====================================================================
%% @spec record_field(Name::syntaxTree(), Value) -> syntaxTree()
%%	    Value = none | syntaxTree()
%%
%% @doc Creates an abstract record field specification. If
%% Value is none, the result represents
%% simply "Name", otherwise it represents
%% "Name = Value".
%%
%% @see record_field_name/1
%% @see record_field_value/1
%% @see record_expr/3
-record(record_field, {name :: syntaxTree(), value :: 'none' | syntaxTree()}).
%% type(Node) = record_field
%% data(Node) = #record_field{name :: Name, value :: Value}
%%
%%	Name = Value = syntaxTree()
-spec record_field(syntaxTree(), 'none' | syntaxTree()) -> syntaxTree().
record_field(Name, Value) ->
    tree(record_field, #record_field{name = Name, value = Value}).
%% =====================================================================
%% @spec record_field_name(syntaxTree()) -> syntaxTree()
%%
%% @doc Returns the name subtree of a record_field node.
%%
%% @see record_field/2
-spec record_field_name(syntaxTree()) -> syntaxTree().
record_field_name(Node) ->
    (data(Node))#record_field.name.
%% =====================================================================
%% @spec record_field_value(syntaxTree()) -> none | syntaxTree()
%%
%% @doc Returns the value subtree of a record_field node,
%% if any. If Node represents
%% "Name", none is
%% returned. Otherwise, if Node represents
%% "Name = Value", Value
%% is returned.
%%
%% @see record_field/2
-spec record_field_value(syntaxTree()) -> 'none' | syntaxTree().
record_field_value(Node) ->
    (data(Node))#record_field.value.
%% =====================================================================
%% @spec record_index_expr(Type::syntaxTree(), Field::syntaxTree()) ->
%%           syntaxTree()
%%
%% @doc Creates an abstract record field index expression. The result
%% represents "#Type.Field".
%%
%% (Note: the function name record_index/2 is reserved
%% by the Erlang compiler, which is why that name could not be used
%% for this constructor.)
record_index_expr
%% node.
%%
%% @see record_index_expr/2
-spec record_index_expr_type(syntaxTree()) -> syntaxTree().
record_index_expr_type(Node) ->
    case unwrap(Node) of
	{record_index, Pos, Type, _} ->
	    set_pos(atom(Type), Pos);
	Node1 ->
	    (data(Node1))#record_index_expr.type
    end.
%% =====================================================================
%% @spec record_index_expr_field(syntaxTree()) -> syntaxTree()
%%
%% @doc Returns the field subtree of a record_index_expr
%% node.
%%
%% @see record_index_expr/2
-spec record_index_expr_field(syntaxTree()) -> syntaxTree().
record_index_expr_field(Node) ->
    case unwrap(Node) of
	{record_index, _, _, Field} ->
	    Field;
	Node1 ->
	    (data(Node1))#record_index_expr.field
    end.
%% =====================================================================
%% @spec record_access(Argument, Field) -> syntaxTree()
%% @equiv record_access(Argument, none, Field)
-spec record_access(syntaxTree(), syntaxTree()) -> syntaxTree().
record_access(Argument, Field) ->
    record_access(Argument, none, Field).
%% =====================================================================
%% @spec record_access(Argument::syntaxTree(), Type,
%%                     Field::syntaxTree()) -> syntaxTree()
%%	    Type = none | syntaxTree()
%%
%% @doc Creates an abstract record field access expression. If
%% Type is not none, the result represents
%% "Argument#Type.Field".
%%
%% If Type is none, the result represents
%% "Argument.Field". This is a special
%% form only allowed within Mnemosyne queries.
record_access
%% node.
%%
%% @see record_access/3
-spec record_access_argument(syntaxTree()) -> syntaxTree().
record_access_argument(Node) ->
    case unwrap(Node) of
	{record_field, _, Argument, _} ->
	    Argument;
	{record_field, _, Argument, _, _} ->
	    Argument;
	Node1 ->
	    (data(Node1))#record_access.argument
    end.
%% =====================================================================
%% @spec record_access_type(syntaxTree()) -> none | syntaxTree()
%%
%% @doc Returns the type subtree of a record_access node,
%% if any. If Node represents
%% "Argument.Field", none
%% is returned, otherwise if Node represents
%% "Argument#Type.Field",
%% Type is returned.
%%
%% @see record_access/3
-spec record_access_type(syntaxTree()) -> 'none' | syntaxTree().
record_access_type(Node) ->
    case unwrap(Node) of
	{record_field, _, _, _} ->
	    none;
	{record_field, Pos, _, Type, _} ->
	    set_pos(atom(Type), Pos);
	Node1 ->
	    (data(Node1))#record_access.type
    end.
%% =====================================================================
%% @spec record_access_field(syntaxTree()) -> syntaxTree()
%%
%% @doc Returns the field subtree of a record_access
%% node.
%%
%% @see record_access/3
-spec record_access_field(syntaxTree()) -> syntaxTree().
record_access_field(Node) ->
    case unwrap(Node) of
	{record_field, _, _, Field} ->
	    Field;
	{record_field, _, _, _, Field} ->
	    Field;
	Node1 ->
	    (data(Node1))#record_access.field
    end.
%% =====================================================================
%% @spec record_expr(Type, Fields) -> syntaxTree()
%% @equiv record_expr(none, Type, Fields)
-spec record_expr(syntaxTree(), [syntaxTree()]) -> syntaxTree().
record_expr(Type, Fields) ->
    record_expr(none, Type, Fields).
%% =====================================================================
%% @spec record_expr(Argument, Type::syntaxTree(),
%%                   Fields::[syntaxTree()]) -> syntaxTree()
%%	    Argument = none | syntaxTree()
%%
%% @doc Creates an abstract record expression. If Fields is
%% [F1, ..., Fn], then if Argument is
%% none, the result represents
%% "#Type{F1, ..., Fn}",
%% otherwise it represents
%% "Argument#Type{F1, ...,
%% Fn}".
%%
%% @see record_expr/2
%% @see record_expr_argument/1
%% @see record_expr_fields/1
%% @see record_expr_type/1
%% @see record_field/2
%% @see record_index_expr/2
%% @see record_access/3
-record(record_expr, {argument :: 'none' | syntaxTree(),
		      type     :: syntaxTree(),
		      fields   :: [syntaxTree()]}).
%% type(Node) = record_expr
%% data(Node) = #record_expr{argument :: Argument, type :: Type,
%%			     fields :: Fields}
%%
%%	Argument = none | syntaxTree()
%%	Type = syntaxTree
%%	Fields = [syntaxTree()]
%%
%% `erl_parse' representation:
%%
%% {record, Pos, Type, Fields}
%% {record, Pos, Argument, Type, Fields}
%%
%%	Argument = erl_parse()
%%	Type = atom()
%%	Fields = [Entry]
%%	Entry = {record_field, Pos, Field, Value}
%%	      | {record_field, Pos, Field}
%%	Field = Value = erl_parse()
-spec record_expr('none' | syntaxTree(), syntaxTree(), [syntaxTree()]) ->
        syntaxTree().
record_expr(Argument, Type, Fields) ->
    tree(record_expr, #record_expr{argument = Argument,
				   type = Type, fields = Fields}).
revert_record_expr(Node) ->
    Pos = get_pos(Node),
    Argument = record_expr_argument(Node),
    Type = record_expr_type(Node),
    Fields = record_expr_fields(Node),
    case type(Type) of
	atom ->
	    T = concrete(Type),
	    Fs = fold_record_fields(Fields),
	    case Argument of
		none ->
		    {record, Pos, T, Fs};
		_ ->
		    {record, Pos, Argument, T, Fs}
	    end;
	_ ->
	    Node
    end.
%% =====================================================================
%% @spec record_expr_argument(syntaxTree()) -> none | syntaxTree()
%%
%% @doc Returns the argument subtree of a record_expr node,
%% if any. If Node represents
%% "#Type{...}", none is returned.
%% Otherwise, if Node represents
%% "Argument#Type{...}",
%% Argument is returned.
%%
%% @see record_expr/3
-spec record_expr_argument(syntaxTree()) -> 'none' | syntaxTree().
record_expr_argument(Node) ->
    case unwrap(Node) of
	{record, _, _, _} ->
	    none;
	{record, _, Argument, _, _} ->
	    Argument;
	Node1 ->
	    (data(Node1))#record_expr.argument
    end.
%% =====================================================================
%% @spec record_expr_type(syntaxTree()) -> syntaxTree()
%%
%% @doc Returns the type subtree of a record_expr node.
%%
%% @see record_expr/3
-spec record_expr_type(syntaxTree()) -> syntaxTree().
record_expr_type(Node) ->
    case unwrap(Node) of
	{record, Pos, Type, _} ->
	    set_pos(atom(Type), Pos);
	{record, Pos, _, Type, _} ->
	    set_pos(atom(Type), Pos);
	Node1 ->
	    (data(Node1))#record_expr.type
    end.
%% =====================================================================
%% @spec record_expr_fields(syntaxTree()) -> [syntaxTree()]
%%
%% @doc Returns the list of field subtrees of a
%% record_expr node.
%%
%% @see record_expr/3
-spec record_expr_fields(syntaxTree()) -> [syntaxTree()].
record_expr_fields(Node) ->
    case unwrap(Node) of
	{record, _, _, Fields} ->
	    unfold_record_fields(Fields);
	{record, _, _, _, Fields} ->
	    unfold_record_fields(Fields);
	Node1 ->
	    (data(Node1))#record_expr.fields
    end.
%% =====================================================================
%% @spec application(Module, Function::syntaxTree(),
%%                   Arguments::[syntaxTree()]) -> syntaxTree()
%%	    Module = none | syntaxTree()
%%
%% @doc Creates an abstract function application expression. If
%% Module is none, this is call is equivalent
%% to application(Function, Arguments), otherwise it is
%% equivalent to application(module_qualifier(Module, Function),
%% Arguments).
%%
%% (This is a utility function.)
%%
%% @see application/2
%% @see module_qualifier/2
-spec application('none' | syntaxTree(), syntaxTree(), [syntaxTree()]) ->
        syntaxTree().
application(none, Name, Arguments) ->
    application(Name, Arguments);
application(Module, Name, Arguments) ->
    application(module_qualifier(Module, Name), Arguments).
%% =====================================================================
%% @spec application(Operator::syntaxTree(),
%%                   Arguments::[syntaxTree()]) -> syntaxTree()
%%
%% @doc Creates an abstract function application expression. If
%% Arguments is [A1, ..., An], the result
%% represents "Operator(A1, ...,
%% An)".
%%
%% @see application_operator/1
%% @see application_arguments/1
%% @see application/3
-record(application, {operator :: syntaxTree(), arguments :: [syntaxTree()]}).
%% type(Node) = application
%% data(Node) = #application{operator :: Operator,
%%			     arguments :: Arguments}
%%
%%	Operator = syntaxTree()
%%	Arguments = [syntaxTree()]
%%
%% `erl_parse' representation:
%%
%% {call, Pos, Fun, Args}
%%
%%	Operator = erl_parse()
%%	Arguments = [erl_parse()]
-spec application(syntaxTree(), [syntaxTree()]) -> syntaxTree().
application(Operator, Arguments) ->
    tree(application, #application{operator = Operator,
				   arguments = Arguments}).
revert_application(Node) ->
    Pos = get_pos(Node),
    Operator = application_operator(Node),
    Arguments = application_arguments(Node),
    {call, Pos, Operator, Arguments}.
%% =====================================================================
%% @spec application_operator(syntaxTree()) -> syntaxTree()
%%
%% @doc Returns the operator subtree of an application
%% node.
%%
%% Note: if Node represents
%% "M:F(...)", then the result is the
%% subtree representing "M:F".
application node.
%%
%% @see application/2
-spec application_arguments(syntaxTree()) -> [syntaxTree()].
application_arguments(Node) ->
    case unwrap(Node) of
	{call, _, _, Arguments} ->
	    Arguments;
	Node1 ->
	    (data(Node1))#application.arguments
    end.
%% =====================================================================
%% @spec list_comp(Template::syntaxTree(), Body::[syntaxTree()]) ->
%%           syntaxTree()
%%
%% @doc Creates an abstract list comprehension. If Body is
%% [E1, ..., En], the result represents
%% "[Template || E1, ..., En]".
%%
%% @see list_comp_template/1
%% @see list_comp_body/1
%% @see generator/2
-record(list_comp, {template :: syntaxTree(), body :: [syntaxTree()]}).
%% type(Node) = list_comp
%% data(Node) = #list_comp{template :: Template, body :: Body}
%%
%%	Template = Node = syntaxTree()
%%	Body = [syntaxTree()]
%%
%% `erl_parse' representation:
%%
%% {lc, Pos, Template, Body}
%%
%%	Template = erl_parse()
%%	Body = [erl_parse()] \ []
-spec list_comp(syntaxTree(), [syntaxTree()]) -> syntaxTree().
list_comp(Template, Body) ->
    tree(list_comp, #list_comp{template = Template, body = Body}).
revert_list_comp(Node) ->
    Pos = get_pos(Node),
    Template = list_comp_template(Node),
    Body = list_comp_body(Node),
    {lc, Pos, Template, Body}.
%% =====================================================================
%% @spec list_comp_template(syntaxTree()) -> syntaxTree()
%%
%% @doc Returns the template subtree of a list_comp node.
%%
%% @see list_comp/2
-spec list_comp_template(syntaxTree()) -> syntaxTree().
list_comp_template(Node) ->
    case unwrap(Node) of
	{lc, _, Template, _} ->
	    Template;
	Node1 ->
	    (data(Node1))#list_comp.template
    end.
%% =====================================================================
%% @spec list_comp_body(syntaxTree()) -> [syntaxTree()]
%%
%% @doc Returns the list of body subtrees of a list_comp
%% node.
%%
%% @see list_comp/2
-spec list_comp_body(syntaxTree()) -> [syntaxTree()].
list_comp_body(Node) ->
    case unwrap(Node) of
	{lc, _, _, Body} ->
	    Body;
	Node1 ->
	    (data(Node1))#list_comp.body
    end.
%% =====================================================================
%% @spec binary_comp(Template::syntaxTree(), Body::[syntaxTree()]) ->
%%           syntaxTree()
%%
%% @doc Creates an abstract binary comprehension. If Body is
%% [E1, ..., En], the result represents
%% "<<Template || E1, ..., En>>".
%%
%% @see binary_comp_template/1
%% @see binary_comp_body/1
%% @see generator/2
-record(binary_comp, {template :: syntaxTree(), body :: [syntaxTree()]}).
%% type(Node) = binary_comp
%% data(Node) = #binary_comp{template :: Template, body :: Body}
%%
%%	Template = Node = syntaxTree()
%%	Body = [syntaxTree()]
%%
%% `erl_parse' representation:
%%
%% {bc, Pos, Template, Body}
%%
%%	Template = erl_parse()
%%	Body = [erl_parse()] \ []
-spec binary_comp(syntaxTree(), [syntaxTree()]) -> syntaxTree().
binary_comp(Template, Body) ->
    tree(binary_comp, #binary_comp{template = Template, body = Body}).
revert_binary_comp(Node) ->
    Pos = get_pos(Node),
    Template = binary_comp_template(Node),
    Body = binary_comp_body(Node),
    {bc, Pos, Template, Body}.
%% =====================================================================
%% @spec binary_comp_template(syntaxTree()) -> syntaxTree()
%%
%% @doc Returns the template subtree of a binary_comp node.
%%
%% @see binary_comp/2
-spec binary_comp_template(syntaxTree()) -> syntaxTree().
binary_comp_template(Node) ->
    case unwrap(Node) of
	{bc, _, Template, _} ->
	    Template;
	Node1 ->
	    (data(Node1))#binary_comp.template
    end.
%% =====================================================================
%% @spec binary_comp_body(syntaxTree()) -> [syntaxTree()]
%%
%% @doc Returns the list of body subtrees of a binary_comp
%% node.
%%
%% @see binary_comp/2
-spec binary_comp_body(syntaxTree()) -> [syntaxTree()].
binary_comp_body(Node) ->
    case unwrap(Node) of
	{bc, _, _, Body} ->
	    Body;
	Node1 ->
	    (data(Node1))#binary_comp.body
    end.
%% =====================================================================
%% @spec query_expr(Body::syntaxTree()) -> syntaxTree()
%%
%% @doc Creates an abstract Mnemosyne query expression. The result
%% represents "query Body end".
%%
%% @see query_expr_body/1
%% @see record_access/2
%% @see rule/2
%% type(Node) = query_expr
%% data(Node) = syntaxTree()
%%
%% `erl_parse' representation:
%%
%% {'query', Pos, Body}
%%
%%	Body = erl_parse()
-spec query_expr(syntaxTree()) -> syntaxTree().
query_expr(Body) ->
    tree(query_expr, Body).
revert_query_expr(Node) ->
    Pos = get_pos(Node),
    Body = list_comp_body(Node),
    {'query', Pos, Body}.
%% =====================================================================
%% @spec query_expr_body(syntaxTree()) -> syntaxTree()
%%
%% @doc Returns the body subtree of a query_expr node.
%%
%% @see query_expr/1
-spec query_expr_body(syntaxTree()) -> syntaxTree().
query_expr_body(Node) ->
    case unwrap(Node) of
	{'query', _, Body} ->
	    Body;
	Node1 ->
	    data(Node1)
    end.
%% =====================================================================
%% @spec rule(Name::syntaxTree(), Clauses::[syntaxTree()]) ->
%%           syntaxTree()
%%
%% @doc Creates an abstract Mnemosyne rule. If Clauses is
%% [C1, ..., Cn], the results represents
%% "Name C1; ...; Name
%% Cn.". More exactly, if each Ci
%% represents "(Pi1, ..., Pim) Gi ->
%% Bi", then the result represents
%% "Name(P11, ..., P1m) G1 :-
%% B1; ...; Name(Pn1, ..., Pnm)
%% Gn :- Bn.". Rules are source code forms.
%%
%% @see rule_name/1
%% @see rule_clauses/1
%% @see rule_arity/1
%% @see is_form/1
%% @see function/2
-record(rule, {name :: syntaxTree(), clauses :: [syntaxTree()]}).
%% type(Node) = rule
%% data(Node) = #rule{name :: Name, clauses :: Clauses}
%%
%%	Name = syntaxTree()
%%	Clauses = [syntaxTree()]
%%
%%	(See `function' for notes on why the arity is not stored.)
%%
%% `erl_parse' representation:
%%
%% {rule, Pos, Name, Arity, Clauses}
%%
%%	Name = atom()
%%	Arity = integer()
%%	Clauses = [Clause] \ []
%%	Clause = {clause, ...}
%%
%%	where the number of patterns in each clause should be equal to
%%	the integer `Arity'; see `clause' for documentation on
%%	`erl_parse' clauses.
-spec rule(syntaxTree(), [syntaxTree()]) -> syntaxTree().
rule(Name, Clauses) ->
    tree(rule, #rule{name = Name, clauses = Clauses}).
revert_rule(Node) ->
    Name = rule_name(Node),
    Clauses = [revert_clause(C) || C <- rule_clauses(Node)],
    Pos = get_pos(Node),
    case type(Name) of
	atom ->
	    A = rule_arity(Node),
	    {rule, Pos, concrete(Name), A, Clauses};
	_ ->
	    Node
    end.
%% =====================================================================
%% @spec rule_name(syntaxTree()) -> syntaxTree()
%%
%% @doc Returns the name subtree of a rule node.
%%
%% @see rule/2
-spec rule_name(syntaxTree()) -> syntaxTree().
rule_name(Node) ->
    case unwrap(Node) of
	{rule, Pos, Name, _, _} ->
	    set_pos(atom(Name), Pos);
	Node1 ->
	    (data(Node1))#rule.name
    end.
%% =====================================================================
%% @spec rule_clauses(syntaxTree()) -> [syntaxTree()]
%%
%% @doc Returns the list of clause subtrees of a rule node.
%%
%% @see rule/2
-spec rule_clauses(syntaxTree()) -> [syntaxTree()].
rule_clauses(Node) ->
    case unwrap(Node) of
	{rule, _, _, _, Clauses} ->
	    Clauses;
	Node1 ->
	    (data(Node1))#rule.clauses
    end.
%% =====================================================================
%% @spec rule_arity(Node::syntaxTree()) -> integer()
%%
%% @doc Returns the arity of a rule node. The result is the
%% number of parameter patterns in the first clause of the rule;
%% subsequent clauses are ignored.
%%
%% An exception is thrown if rule_clauses(Node) returns
%% an empty list, or if the first element of that list is not a syntax
%% tree C of type clause such that
%% clause_patterns(C) is a nonempty list.
Pattern <- Body".
%%
%% @see generator_pattern/1
%% @see generator_body/1
%% @see list_comp/2
%% @see binary_comp/2
-record(generator, {pattern :: syntaxTree(), body :: syntaxTree()}).
%% type(Node) = generator
%% data(Node) = #generator{pattern :: Pattern, body :: Body}
%%
%%	Pattern = Argument = syntaxTree()
%%
%% `erl_parse' representation:
%%
%% {generate, Pos, Pattern, Body}
%%
%%	Pattern = Body = erl_parse()
-spec generator(syntaxTree(), syntaxTree()) -> syntaxTree().
generator(Pattern, Body) ->
    tree(generator, #generator{pattern = Pattern, body = Body}).
revert_generator(Node) ->
    Pos = get_pos(Node),
    Pattern = generator_pattern(Node),
    Body = generator_body(Node),
    {generate, Pos, Pattern, Body}.
%% =====================================================================
%% @spec generator_pattern(syntaxTree()) -> syntaxTree()
%%
%% @doc Returns the pattern subtree of a generator node.
%%
%% @see generator/2
-spec generator_pattern(syntaxTree()) -> syntaxTree().
generator_pattern(Node) ->
    case unwrap(Node) of
	{generate, _, Pattern, _} ->
	    Pattern;
	Node1 ->
	    (data(Node1))#generator.pattern
    end.
%% =====================================================================
%% @spec generator_body(syntaxTree()) -> syntaxTree()
%%
%% @doc Returns the body subtree of a generator node.
%%
%% @see generator/2
-spec generator_body(syntaxTree()) -> syntaxTree().
generator_body(Node) ->
    case unwrap(Node) of
	{generate, _, _, Body} ->
	    Body;
	Node1 ->
	    (data(Node1))#generator.body
    end.
%% =====================================================================
%% @spec binary_generator(Pattern::syntaxTree(), Body::syntaxTree()) ->
%%           syntaxTree()
%%
%% @doc Creates an abstract binary_generator. The result represents
%% "Pattern <- Body".
%%
%% @see binary_generator_pattern/1
%% @see binary_generator_body/1
%% @see list_comp/2
%% @see binary_comp/2
-record(binary_generator, {pattern :: syntaxTree(), body :: syntaxTree()}).
%% type(Node) = binary_generator
%% data(Node) = #binary_generator{pattern :: Pattern, body :: Body}
%%
%%	Pattern = Argument = syntaxTree()
%%
%% `erl_parse' representation:
%%
%% {b_generate, Pos, Pattern, Body}
%%
%%	Pattern = Body = erl_parse()
-spec binary_generator(syntaxTree(), syntaxTree()) -> syntaxTree().
binary_generator(Pattern, Body) ->
    tree(binary_generator, #binary_generator{pattern = Pattern, body = Body}).
revert_binary_generator(Node) ->
    Pos = get_pos(Node),
    Pattern = binary_generator_pattern(Node),
    Body = binary_generator_body(Node),
    {b_generate, Pos, Pattern, Body}.
%% =====================================================================
%% @spec binary_generator_pattern(syntaxTree()) -> syntaxTree()
%%
%% @doc Returns the pattern subtree of a generator node.
%%
%% @see binary_generator/2
-spec binary_generator_pattern(syntaxTree()) -> syntaxTree().
binary_generator_pattern(Node) ->
    case unwrap(Node) of
	{b_generate, _, Pattern, _} ->
	    Pattern;
	Node1 ->
	    (data(Node1))#binary_generator.pattern
    end.
%% =====================================================================
%% @spec binary_generator_body(syntaxTree()) -> syntaxTree()
%%
%% @doc Returns the body subtree of a generator node.
%%
%% @see binary_generator/2
-spec binary_generator_body(syntaxTree()) -> syntaxTree().
binary_generator_body(Node) ->
    case unwrap(Node) of
	{b_generate, _, _, Body} ->
	    Body;
	Node1 ->
	    (data(Node1))#binary_generator.body
    end.
%% =====================================================================
%% @spec block_expr(Body::[syntaxTree()]) -> syntaxTree()
%%
%% @doc Creates an abstract block expression. If Body is
%% [B1, ..., Bn], the result represents "begin
%% B1, ..., Bn end".
%%
%% @see block_expr_body/1
%% type(Node) = block_expr
%% data(Node) = Body
%%
%%	Body = [syntaxTree()]
%%
%% `erl_parse' representation:
%%
%% {block, Pos, Body}
%%
%%	    Body = [erl_parse()] \ []
-spec block_expr(Body::[syntaxTree()]) -> syntaxTree().
block_expr(Body) ->
    tree(block_expr, Body).
revert_block_expr(Node) ->
    Pos = get_pos(Node),
    Body = block_expr_body(Node),
    {block, Pos, Body}.
%% =====================================================================
%% @spec block_expr_body(syntaxTree()) -> [syntaxTree()]
%%
%% @doc Returns the list of body subtrees of a block_expr
%% node.
%%
%% @see block_expr/1
-spec block_expr_body(syntaxTree()) -> [syntaxTree()].
block_expr_body(Node) ->
    case unwrap(Node) of
	{block, _, Body} ->
	    Body;
	Node1 ->
	    data(Node1)
    end.
%% =====================================================================
%% @spec if_expr(Clauses::[syntaxTree()]) -> syntaxTree()
%%
%% @doc Creates an abstract if-expression. If Clauses is
%% [C1, ..., Cn], the result represents "if
%% C1; ...; Cn end". More exactly, if each
%% Ci represents "() Gi ->
%% Bi", then the result represents "if
%% G1 -> B1; ...; Gn -> Bn
%% end".
%%
%% @see if_expr_clauses/1
%% @see clause/3
%% @see case_expr/2
%% type(Node) = if_expr
%% data(Node) = Clauses
%%
%%	Clauses = [syntaxTree()]
%%
%% `erl_parse' representation:
%%
%% {'if', Pos, Clauses}
%%
%%	Clauses = [Clause] \ []
%%	Clause = {clause, ...}
%%
%%	See `clause' for documentation on `erl_parse' clauses.
-spec if_expr([syntaxTree()]) -> syntaxTree().
if_expr(Clauses) ->
    tree(if_expr, Clauses).
revert_if_expr(Node) ->
    Pos = get_pos(Node),
    Clauses = [revert_clause(C) || C <- if_expr_clauses(Node)],
    {'if', Pos, Clauses}.
%% =====================================================================
%% @spec if_expr_clauses(syntaxTree()) -> [syntaxTree()]
%%
%% @doc Returns the list of clause subtrees of an if_expr
%% node.
%%
%% @see if_expr/1
-spec if_expr_clauses(syntaxTree()) -> [syntaxTree()].
if_expr_clauses(Node) ->
    case unwrap(Node) of
	{'if', _, Clauses} ->
	    Clauses;
	Node1 ->
	    data(Node1)
    end.
%% =====================================================================
%% @spec case_expr(Argument::syntaxTree(), Clauses::[syntaxTree()]) ->
%%           syntaxTree()
%%
%% @doc 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 case_expr_clauses/1
%% @see case_expr_argument/1
%% @see clause/3
%% @see if_expr/1
%% @see cond_expr/1
-record(case_expr, {argument :: syntaxTree(), clauses :: [syntaxTree()]}).
%% type(Node) = case_expr
%% data(Node) = #case_expr{argument :: Argument,
%%			   clauses :: Clauses}
%%
%%	Argument = syntaxTree()
%%	Clauses = [syntaxTree()]
%%
%% `erl_parse' representation:
%%
%% {'case', Pos, Argument, Clauses}
%%
%%	Argument = erl_parse()
%%	Clauses = [Clause] \ []
%%	Clause = {clause, ...}
%%
%%	See `clause' for documentation on `erl_parse' clauses.
-spec case_expr(syntaxTree(), [syntaxTree()]) -> syntaxTree().
case_expr(Argument, Clauses) ->
    tree(case_expr, #case_expr{argument = Argument,
			       clauses = Clauses}).
revert_case_expr(Node) ->
    Pos = get_pos(Node),
    Argument = case_expr_argument(Node),
    Clauses = [revert_clause(C) || C <- case_expr_clauses(Node)],
    {'case', Pos, Argument, Clauses}.
%% =====================================================================
%% @spec case_expr_argument(syntaxTree()) -> syntaxTree()
%%
%% @doc Returns the argument subtree of a case_expr node.
%%
%% @see case_expr/2
-spec case_expr_argument(syntaxTree()) -> syntaxTree().
case_expr_argument(Node) ->
    case unwrap(Node) of
	{'case', _, Argument, _} ->
	    Argument;
	Node1 ->
	    (data(Node1))#case_expr.argument
    end.
%% =====================================================================
%% @spec case_expr_clauses(syntaxTree()) -> [syntaxTree()]
%%
%% @doc Returns the list of clause subtrees of a case_expr
%% node.
%%
%% @see case_expr/2
-spec case_expr_clauses(syntaxTree()) -> [syntaxTree()].
case_expr_clauses(Node) ->
    case unwrap(Node) of
	{'case', _, _, Clauses} ->
	    Clauses;
	Node1 ->
	    (data(Node1))#case_expr.clauses
    end.
%% =====================================================================
%% @spec cond_expr(Clauses::[syntaxTree()]) -> syntaxTree()
%%
%% @doc Creates an abstract cond-expression. If Clauses is
%% [C1, ..., Cn], the result represents "cond
%% C1; ...; Cn end". More exactly, if each
%% Ci represents "() Ei ->
%% Bi", then the result represents "cond
%% E1 -> B1; ...; En -> Bn
%% end".
%%
%% @see cond_expr_clauses/1
%% @see clause/3
%% @see case_expr/2
%% type(Node) = cond_expr
%% data(Node) = Clauses
%%
%%	Clauses = [syntaxTree()]
%%
%% `erl_parse' representation:
%%
%% {'cond', Pos, Clauses}
%%
%%	Clauses = [Clause] \ []
%%	Clause = {clause, ...}
%%
%%	See `clause' for documentation on `erl_parse' clauses.
-spec cond_expr([syntaxTree()]) -> syntaxTree().
cond_expr(Clauses) ->
    tree(cond_expr, Clauses).
revert_cond_expr(Node) ->
    Pos = get_pos(Node),
    Clauses = [revert_clause(C) || C <- cond_expr_clauses(Node)],
    {'cond', Pos, Clauses}.
%% =====================================================================
%% @spec cond_expr_clauses(syntaxTree()) -> [syntaxTree()]
%%
%% @doc Returns the list of clause subtrees of a cond_expr
%% node.
%%
%% @see cond_expr/1
-spec cond_expr_clauses(syntaxTree()) -> [syntaxTree()].
cond_expr_clauses(Node) ->
    case unwrap(Node) of
	{'cond', _, Clauses} ->
	    Clauses;
	Node1 ->
	    data(Node1)
    end.
%% =====================================================================
%% @spec receive_expr(Clauses) -> syntaxTree()
%% @equiv receive_expr(Clauses, none, [])
-spec receive_expr([syntaxTree()]) -> syntaxTree().
receive_expr(Clauses) ->
    receive_expr(Clauses, none, []).
%% =====================================================================
%% @spec receive_expr(Clauses::[syntaxTree()], Timeout,
%%                    Action::[syntaxTree()]) -> syntaxTree()
%%	    Timeout = none | syntaxTree()
%%
%% @doc Creates an abstract receive-expression. If Timeout
%% is none, the result represents "receive
%% C1; ...; Cn end" (the Action
%% argument is ignored). Otherwise, if Clauses is
%% [C1, ..., Cn] and Action is [A1, ...,
%% Am], the result represents "receive C1; ...;
%% Cn after Timeout -> A1, ..., Am
%% end". More exactly, if each Ci represents
%% "(Pi) Gi -> Bi", then the
%% result represents "receive P1 G1 ->
%% B1; ...; Pn Gn -> Bn ...
%% end".
%%
%% Note that in Erlang, a receive-expression must have at least one %% clause if no timeout part is specified.
%% %% @see receive_expr_clauses/1 %% @see receive_expr_timeout/1 %% @see receive_expr_action/1 %% @see receive_expr/1 %% @see clause/3 %% @see case_expr/2 -record(receive_expr, {clauses :: [syntaxTree()], timeout :: 'none' | syntaxTree(), action :: [syntaxTree()]}). %% type(Node) = receive_expr %% data(Node) = #receive_expr{clauses :: Clauses, %% timeout :: Timeout, %% action :: Action} %% %% Clauses = [syntaxTree()] %% Timeout = none | syntaxTree() %% Action = [syntaxTree()] %% %% `erl_parse' representation: %% %% {'receive', Pos, Clauses} %% {'receive', Pos, Clauses, Timeout, Action} %% %% Clauses = [Clause] \ [] %% Clause = {clause, ...} %% Timeout = erl_parse() %% Action = [erl_parse()] \ [] %% %% See `clause' for documentation on `erl_parse' clauses. -spec receive_expr([syntaxTree()], 'none' | syntaxTree(), [syntaxTree()]) -> syntaxTree(). receive_expr(Clauses, Timeout, Action) -> %% If `Timeout' is `none', we always replace the actual %% `Action' argument with an empty list, since %% `receive_expr_action' should in that case return the empty %% list regardless. Action1 = case Timeout of none -> []; _ -> Action end, tree(receive_expr, #receive_expr{clauses = Clauses, timeout = Timeout, action = Action1}). revert_receive_expr(Node) -> Pos = get_pos(Node), Clauses = [revert_clause(C) || C <- receive_expr_clauses(Node)], Timeout = receive_expr_timeout(Node), Action = receive_expr_action(Node), case Timeout of none -> {'receive', Pos, Clauses}; _ -> {'receive', Pos, Clauses, Timeout, Action} end. %% ===================================================================== %% @spec receive_expr_clauses(syntaxTree()) -> [syntaxTree()] %% type(Node) = receive_expr %% %% @doc Returns the list of clause subtrees of a %%receive_expr node.
%%
%% @see receive_expr/3
-spec receive_expr_clauses(syntaxTree()) -> [syntaxTree()].
receive_expr_clauses(Node) ->
    case unwrap(Node) of
	{'receive', _, Clauses} ->
	    Clauses;
	{'receive', _, Clauses, _, _} ->
	    Clauses;
	Node1 ->
	    (data(Node1))#receive_expr.clauses
    end.
%% =====================================================================
%% @spec receive_expr_timeout(Node::syntaxTree()) -> Timeout
%%	     Timeout = none | syntaxTree()
%%
%% @doc Returns the timeout subtree of a receive_expr node,
%% if any. If Node represents "receive C1;
%% ...; Cn end", none is returned.
%% Otherwise, if Node represents "receive
%% C1; ...; Cn after Timeout -> ... end",
%% Timeout is returned.
%%
%% @see receive_expr/3
-spec receive_expr_timeout(syntaxTree()) -> 'none' | syntaxTree().
receive_expr_timeout(Node) ->
    case unwrap(Node) of
	{'receive', _, _} ->
	    none;
	{'receive', _, _, Timeout, _} ->
	    Timeout;
	Node1 ->
	    (data(Node1))#receive_expr.timeout
    end.
%% =====================================================================
%% @spec receive_expr_action(Node::syntaxTree()) -> [syntaxTree()]
%%
%% @doc Returns the list of action body subtrees of a
%% receive_expr node. If Node represents
%% "receive C1; ...; Cn end", this is the
%% empty list.
%%
%% @see receive_expr/3
-spec receive_expr_action(syntaxTree()) -> [syntaxTree()].
receive_expr_action(Node) ->
    case unwrap(Node) of
	{'receive', _, _} ->
	    [];
	{'receive', _, _, _, Action} ->
	    Action;
	Node1 ->
	    (data(Node1))#receive_expr.action
    end.
%% =====================================================================
%% @spec try_expr(Body::syntaxTree(), Handlers::[syntaxTree()]) ->
%%           syntaxTree()
%% @equiv try_expr(Body, [], Handlers)
-spec try_expr([syntaxTree()], [syntaxTree()]) -> syntaxTree().
try_expr(Body, Handlers) ->
    try_expr(Body, [], Handlers).
%% =====================================================================
%% @spec try_expr(Body::syntaxTree(), Clauses::[syntaxTree()],
%%           Handlers::[syntaxTree()]) -> syntaxTree()
%% @equiv try_expr(Body, Clauses, Handlers, [])
-spec try_expr([syntaxTree()], [syntaxTree()], [syntaxTree()]) -> syntaxTree().
try_expr(Body, Clauses, Handlers) ->
    try_expr(Body, Clauses, Handlers, []).
%% =====================================================================
%% @spec try_after_expr(Body::syntaxTree(), After::[syntaxTree()]) ->
%%           syntaxTree()
%% @equiv try_expr(Body, [], [], After)
-spec try_after_expr([syntaxTree()], [syntaxTree()]) -> syntaxTree().
try_after_expr(Body, After) ->
    try_expr(Body, [], [], After).
%% =====================================================================
%% @spec try_expr(Body::[syntaxTree()], Clauses::[syntaxTree()],
%%                Handlers::[syntaxTree()], After::[syntaxTree()]) ->
%%           syntaxTree()
%%
%% @doc Creates an abstract try-expression. If Body is
%% [B1, ..., Bn], Clauses is [C1, ...,
%% Cj], Handlers is [H1, ..., Hk], and
%% After is [A1, ..., Am], the result
%% represents "try B1, ..., Bn of C1;
%% ...; Cj catch H1; ...; Hk after
%% A1, ..., Am end". More exactly, if each
%% Ci represents "(CPi) CGi ->
%% CBi", and each Hi represents
%% "(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"; cf.
%% case_expr/2. If Clauses is the empty list,
%% the of ... section is left out. If After is
%% the empty list, the after ... section is left out. If
%% Handlers is the empty list, and After is
%% nonempty, the catch ... section is left out.
%%
%% @see try_expr_body/1
%% @see try_expr_clauses/1
%% @see try_expr_handlers/1
%% @see try_expr_after/1
%% @see try_expr/2
%% @see try_expr/3
%% @see try_after_expr/2
%% @see clause/3
%% @see class_qualifier/2
%% @see case_expr/2
-record(try_expr, {body     :: [syntaxTree()],
		   clauses  :: [syntaxTree()],
		   handlers :: [syntaxTree()],
		   'after'  :: [syntaxTree()]}).
%% type(Node) = try_expr
%% data(Node) = #try_expr{body :: Body,
%%			  clauses :: Clauses,
%%			  handlers :: Clauses,
%%			  after :: Body}
%%
%%	Body = syntaxTree()
%%	Clauses = [syntaxTree()]
%%
%% `erl_parse' representation:
%%
%% {'try', Pos, Body, Clauses, Handlers, After}
%%
%%	Body = [erl_parse()]
%%	Clauses = [Clause]
%%	Handlers = [Clause] \ []
%%	Clause = {clause, ...}
%%	After = [erl_parse()]
%%
%%	See `clause' for documentation on `erl_parse' clauses.
-spec try_expr([syntaxTree()], [syntaxTree()],
	       [syntaxTree()], [syntaxTree()]) -> syntaxTree().
try_expr(Body, Clauses, Handlers, After) ->
    tree(try_expr, #try_expr{body = Body,
			     clauses = Clauses,
			     handlers = Handlers,
			     'after' = After}).
revert_try_expr(Node) ->
    Pos = get_pos(Node),
    Body = try_expr_body(Node),
    Clauses = [revert_clause(C) || C <- try_expr_clauses(Node)],
    Handlers = [revert_try_clause(C) || C <- try_expr_handlers(Node)],
    After = try_expr_after(Node),
    {'try', Pos, Body, Clauses, Handlers, After}.
%% =====================================================================
%% @spec try_expr_body(syntaxTree()) -> [syntaxTree()]
%%
%% @doc Returns the list of body subtrees of a try_expr
%% node.
%%
%% @see try_expr/4
-spec try_expr_body(syntaxTree()) -> [syntaxTree()].
try_expr_body(Node) ->
    case unwrap(Node) of
	{'try', _, Body, _, _, _} ->
	    Body;
	Node1 ->
	    (data(Node1))#try_expr.body
    end.
%% =====================================================================
%% @spec try_expr_clauses(Node::syntaxTree()) -> [syntaxTree()]
%%
%% @doc Returns the list of case-clause subtrees of a
%% try_expr node. If Node represents
%% "try Body catch H1; ...; Hn
%% end", the result is the empty list.
%%
%% @see try_expr/4
-spec try_expr_clauses(syntaxTree()) -> [syntaxTree()].
try_expr_clauses(Node) ->
    case unwrap(Node) of
	{'try', _, _, Clauses, _, _} ->
	    Clauses;
	Node1 ->
	    (data(Node1))#try_expr.clauses
    end.
%% =====================================================================
%% @spec try_expr_handlers(syntaxTree()) -> [syntaxTree()]
%%
%% @doc Returns the list of handler-clause subtrees of a
%% try_expr node.
%%
%% @see try_expr/4
-spec try_expr_handlers(syntaxTree()) -> [syntaxTree()].
try_expr_handlers(Node) ->
    case unwrap(Node) of
	{'try', _, _, _, Handlers, _} ->
	    unfold_try_clauses(Handlers);
	Node1 ->
	    (data(Node1))#try_expr.handlers
    end.
%% =====================================================================
%% @spec try_expr_after(syntaxTree()) -> [syntaxTree()]
%%
%% @doc Returns the list of "after" subtrees of a try_expr
%% node.
%%
%% @see try_expr/4
-spec try_expr_after(syntaxTree()) -> [syntaxTree()].
try_expr_after(Node) ->
    case unwrap(Node) of
	{'try', _, _, _, _, After} ->
	    After;
	Node1 ->
	    (data(Node1))#try_expr.'after'
    end.
%% =====================================================================
%% @spec class_qualifier(Class::syntaxTree(), Body::syntaxTree()) ->
%%           syntaxTree()
%%
%% @doc Creates an abstract class qualifier. The result represents
%% "Class:Body".
%%
%% @see class_qualifier_argument/1
%% @see class_qualifier_body/1
%% @see try_expr/4
-record(class_qualifier, {class :: syntaxTree(), body :: syntaxTree()}).
%% type(Node) = class_qualifier
%% data(Node) = #class_qualifier{class :: Class, body :: Body}
%%
%%	Class = Body = syntaxTree()
-spec class_qualifier(syntaxTree(), syntaxTree()) -> syntaxTree().
class_qualifier(Class, Body) ->
    tree(class_qualifier,
	 #class_qualifier{class = Class, body = Body}).
%% =====================================================================
%% @spec class_qualifier_argument(syntaxTree()) -> syntaxTree()
%%
%% @doc Returns the argument (the class) subtree of a
%% class_qualifier node.
%%
%% @see class_qualifier/2
-spec class_qualifier_argument(syntaxTree()) -> syntaxTree().
class_qualifier_argument(Node) ->
    (data(Node))#class_qualifier.class.
%% =====================================================================
%% @spec class_qualifier_body(syntaxTree()) -> syntaxTree()
%%
%% @doc Returns the body subtree of a class_qualifier node.
%%
%% @see class_qualifier/2
-spec class_qualifier_body(syntaxTree()) -> syntaxTree().
class_qualifier_body(Node) ->
    (data(Node))#class_qualifier.body.
%% =====================================================================
%% @spec implicit_fun(Name::syntaxTree(), Arity::syntaxTree()) ->
%%           syntaxTree()
%%
%% @doc Creates an abstract "implicit fun" expression. If
%% Arity is none, this is equivalent to
%% implicit_fun(Name), otherwise it is equivalent to
%% implicit_fun(arity_qualifier(Name, Arity)).
%%
%% (This is a utility function.)
%%
%% @see implicit_fun/1
%% @see implicit_fun/3
-spec implicit_fun(syntaxTree(), 'none' | syntaxTree()) -> syntaxTree().
implicit_fun(Name, none) ->
    implicit_fun(Name);
implicit_fun(Name, Arity) ->
    implicit_fun(arity_qualifier(Name, Arity)).
%% =====================================================================
%% @spec implicit_fun(Module::syntaxTree(), Name::syntaxTree(),
%%                    Arity::syntaxTree()) -> syntaxTree()
%%
%% @doc Creates an abstract module-qualified "implicit fun" expression.
%% If Module is none, this is equivalent to
%% implicit_fun(Name, Arity), otherwise it is equivalent to
%% implicit_fun(module_qualifier(Module, arity_qualifier(Name,
%% Arity)).
%%
%% (This is a utility function.)
%%
%% @see implicit_fun/1
%% @see implicit_fun/2
-spec implicit_fun('none' | syntaxTree(), syntaxTree(), syntaxTree()) ->
        syntaxTree().
implicit_fun(none, Name, Arity) ->
    implicit_fun(Name, Arity);
implicit_fun(Module, Name, Arity) ->
    implicit_fun(module_qualifier(Module, arity_qualifier(Name, Arity))).
%% =====================================================================
%% @spec implicit_fun(Name::syntaxTree()) -> syntaxTree()
%%
%% @doc Creates an abstract "implicit fun" expression. The result
%% represents "fun Name". Name should
%% represent either F/A or
%% M:F/A
%%
%% @see implicit_fun_name/1
%% @see implicit_fun/2
%% @see implicit_fun/3
%% @see arity_qualifier/2
%% @see module_qualifier/2
%% type(Node) = implicit_fun
%% data(Node) = syntaxTree()
%%
%% `erl_parse' representation:
%%
%% {'fun', Pos, {function, Name, Arity}}
%% {'fun', Pos, {function, Module, Name, Arity}}
%%
%%	Module = atom()
%%	Name = atom()
%%	Arity = arity()
-spec implicit_fun(syntaxTree()) -> syntaxTree().
implicit_fun(Name) ->
    tree(implicit_fun, Name).
revert_implicit_fun(Node) ->
    Pos = get_pos(Node),
    Name = implicit_fun_name(Node),
    case type(Name) of
	arity_qualifier ->
	    F = arity_qualifier_body(Name),
	    A = arity_qualifier_argument(Name),
	    case {type(F), type(A)} of
		{atom, integer} ->
		    {'fun', Pos,
		     {function, concrete(F), concrete(A)}};
		_ ->
		    Node
	    end;
	module_qualifier ->
	    M = module_qualifier_argument(Name),
	    Name1 = module_qualifier_body(Name),
	    F = arity_qualifier_body(Name1),
	    A = arity_qualifier_argument(Name1),
	    case {type(M), type(F), type(A)} of
		{atom, atom, integer} ->
		    {'fun', Pos,
		     {function, concrete(M), concrete(F), concrete(A)}};
		_ ->
		    Node
	    end;
	_ ->
	    Node
    end.
%% =====================================================================
%% @spec implicit_fun_name(Node::syntaxTree()) -> syntaxTree()
%%
%% @doc Returns the name subtree of an implicit_fun node.
%%
%% Note: if Node represents "fun
%% N/A" or "fun
%% M:N/A", then the result is the
%% subtree representing "N/A" or
%% "M:N/A", respectively.
Clauses is
%% [C1, ..., Cn], the result represents "fun
%% C1; ...; Cn end". More exactly, if each
%% Ci represents "(Pi1, ..., Pim)
%% Gi -> Bi", then the result represents
%% "fun (P11, ..., P1m) G1 ->
%% B1; ...; (Pn1, ..., Pnm) Gn ->
%% Bn end".
%%
%% @see fun_expr_clauses/1
%% @see fun_expr_arity/1
%% type(Node) = fun_expr
%% data(Node) = Clauses
%%
%%	Clauses = [syntaxTree()]
%%
%%	(See `function' for notes; e.g. why the arity is not stored.)
%%
%% `erl_parse' representation:
%%
%% {'fun', Pos, {clauses, Clauses}}
%%
%%	Clauses = [Clause] \ []
%%	Clause = {clause, ...}
%%
%%	See `clause' for documentation on `erl_parse' clauses.
-spec fun_expr([syntaxTree()]) -> syntaxTree().
fun_expr(Clauses) ->
    tree(fun_expr, Clauses).
revert_fun_expr(Node) ->
    Clauses = [revert_clause(C) || C <- fun_expr_clauses(Node)],
    Pos = get_pos(Node),
    {'fun', Pos, {clauses, Clauses}}.
%% =====================================================================
%% @spec fun_expr_clauses(syntaxTree()) -> [syntaxTree()]
%%
%% @doc Returns the list of clause subtrees of a fun_expr
%% node.
%%
%% @see fun_expr/1
-spec fun_expr_clauses(syntaxTree()) -> [syntaxTree()].
fun_expr_clauses(Node) ->
    case unwrap(Node) of
	{'fun', _, {clauses, Clauses}} ->
	    Clauses;
	Node1 ->
	    data(Node1)
    end.
%% =====================================================================
%% @spec fun_expr_arity(syntaxTree()) -> integer()
%%
%% @doc Returns the arity of a fun_expr node. The result is
%% the number of parameter patterns in the first clause of the
%% fun-expression; subsequent clauses are ignored.
%%
%% An exception is thrown if fun_expr_clauses(Node)
%% returns an empty list, or if the first element of that list is not a
%% syntax tree C of type clause such that
%% clause_patterns(C) is a nonempty list.
(Body)", independently of the
%% context.
%%
%% @see parentheses_body/1
%% type(Node) = parentheses
%% data(Node) = syntaxTree()
-spec parentheses(syntaxTree()) -> syntaxTree().
parentheses(Expr) ->
    tree(parentheses, Expr).
revert_parentheses(Node) ->
    parentheses_body(Node).
%% =====================================================================
%% @spec parentheses_body(syntaxTree()) -> syntaxTree()
%%
%% @doc Returns the body subtree of a parentheses node.
%%
%% @see parentheses/1
-spec parentheses_body(syntaxTree()) -> syntaxTree().
parentheses_body(Node) ->
    data(Node).
%% =====================================================================
%% @spec macro(Name) -> syntaxTree()
%% @equiv macro(Name, none)
-spec macro(syntaxTree()) -> syntaxTree().
macro(Name) ->
    macro(Name, none).
%% =====================================================================
%% @spec macro(Name::syntaxTree(), Arguments) -> syntaxTree()
%%	    Arguments = none | [syntaxTree()]
%%
%% @doc Creates an abstract macro application. If Arguments
%% is none, the result represents
%% "?Name", otherwise, if Arguments
%% is [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.
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.
macro node.
%%
%% @see macro/2
-spec macro_name(syntaxTree()) -> syntaxTree().
macro_name(Node) ->
    (data(Node))#macro.name.
%% =====================================================================
%% @spec macro_arguments(Node::syntaxTree()) -> none | [syntaxTree()]
%%
%% @doc Returns the list of argument subtrees of a macro
%% node, if any. If Node represents
%% "?Name", none is returned.
%% Otherwise, if Node represents
%% "?Name(A1, ..., An)",
%% [A1, ..., An] is returned.
%%
%% @see macro/2
-spec macro_arguments(syntaxTree()) -> 'none' | [syntaxTree()].
macro_arguments(Node) ->
    (data(Node))#macro.arguments.
%% =====================================================================
%% @spec abstract(Term::term()) -> syntaxTree()
%%
%% @doc Returns the syntax tree corresponding to an Erlang term.
%% Term must be a literal term, i.e., one that can be
%% represented as a source code literal. Thus, it may not contain a
%% process identifier, port, reference, binary or function value as a
%% subterm. The function recognises printable strings, in order to get a
%% compact and readable representation. Evaluation fails with reason
%% badarg if Term is not a literal term.
%%
%% @see concrete/1
%% @see is_literal/1
-spec abstract(term()) -> syntaxTree().
abstract([H | T] = L) when is_integer(H) ->
    case is_printable(L) of
	true ->
	    string(L);
	false ->
	    abstract_tail(H, T)
    end;
abstract([H | T]) ->
    abstract_tail(H, T);
abstract(T) when is_atom(T) ->
    atom(T);
abstract(T) when is_integer(T) ->
    integer(T);
abstract(T) when is_float(T) ->
    make_float(T);    % (not `float', which would call the BIF)
abstract([]) ->
    nil();
abstract(T) when is_tuple(T) ->
    tuple(abstract_list(tuple_to_list(T)));
abstract(T) when is_binary(T) ->
    binary([binary_field(integer(B)) || B <- binary_to_list(T)]);
abstract(T) ->
    erlang:error({badarg, T}).
abstract_list([T | Ts]) ->
    [abstract(T) | abstract_list(Ts)];
abstract_list([]) ->
    [].
%% This is entered when we might have a sequence of conses that might or
%% might not be a proper list, but which should not be considered as a
%% potential string, to avoid unnecessary checking. This also avoids
%% that a list like `[4711, 42, 10]' could be abstracted to represent
%% `[4711 | "*\n"]'.
abstract_tail(H1, [H2 | T]) ->
    %% Recall that `cons' does "intelligent" composition
    cons(abstract(H1), abstract_tail(H2, T));
abstract_tail(H, T) ->
    cons(abstract(H), abstract(T)).
%% =====================================================================
%% @spec concrete(Node::syntaxTree()) -> term()
%%
%% @doc 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 function abstract/1. An abstract character
%% will be concretised as an integer, while abstract/1 does
%% not at present yield an abstract character for any input. (Use the
%% char/1 function to explicitly create an abstract
%% character.)
true if Node represents a
%% literal term, otherwise false. This function returns
%% true if and only if the value of
%% concrete(Node) is defined.
%%
%% @see abstract/1
%% @see concrete/1
-spec is_literal(syntaxTree()) -> boolean().
is_literal(T) ->
    case type(T) of
	atom ->
	    true;
	integer ->
	    true;
	float ->
	    true;
	char->
	    true;
	string ->
	    true;
	nil ->
	    true;
	list ->
	    is_literal(list_head(T)) andalso is_literal(list_tail(T));
	tuple ->
	    lists:all(fun is_literal/1, tuple_elements(T));
	_ ->
	    false
    end.
%% =====================================================================
%% @spec revert(Tree::syntaxTree()) -> syntaxTree()
%%
%% @doc Returns an erl_parse-compatible representation of a
%% syntax tree, if possible. If Tree represents a
%% well-formed Erlang program or expression, the conversion should work
%% without problems. Typically, is_tree/1 yields
%% true if conversion failed (i.e., the result is still an
%% abstract syntax tree), and false otherwise.
%%
%% The is_tree/1 test 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 if Tree does not actually represent legal Erlang
%% code.
form_list syntax tree (possibly
%% nested), or as a list of "program form" syntax trees. If successful,
%% the corresponding flat list of erl_parse-compatible
%% syntax trees is returned (cf. revert/1). If some program
%% form could not be reverted, {error, Form} is thrown.
%% Standalone comments in the form sequence are discarded.
%%
%% @see revert/1
%% @see form_list/1
%% @see is_form/1
-type forms() :: syntaxTree() | [syntaxTree()].
%% -spec revert_forms(forms()) -> [erl_parse()].
revert_forms(L) when is_list(L) ->
    revert_forms(form_list(L));
revert_forms(T) ->
    case type(T) of
	form_list ->
	    T1 = flatten_form_list(T),
	    case catch {ok, revert_forms_1(form_list_elements(T1))} of
		{ok, Fs} ->
		    Fs;
		{error, _} = Error ->
		    erlang:error(Error);
		{'EXIT', R} ->
		    exit(R);
		R ->
		    throw(R)
	    end;
	_ ->
	    erlang:error({badarg, T})
    end.
revert_forms_1([T | Ts]) ->
    case type(T) of
	comment ->
	    revert_forms_1(Ts);
	_ ->
	    T1 = revert(T),
	    case is_tree(T1) of
		true ->
		    throw({error, T1});
		false ->
		    [T1 | revert_forms_1(Ts)]
	    end
    end;
revert_forms_1([]) ->
    [].
%% =====================================================================
%% @spec subtrees(Node::syntaxTree()) -> [[syntaxTree()]]
%%
%% @doc Returns the grouped list of all subtrees of a syntax tree. If
%% Node is a leaf node (cf. is_leaf/1), this
%% is the empty list, otherwise the result is always a nonempty list,
%% containing the lists of subtrees of Node, in
%% left-to-right order as they occur in the printed program text, and
%% 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). Note, however, that 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 make_tree/2
%% @see type/1
%% @see is_leaf/1
%% @see copy_attrs/2
-spec subtrees(syntaxTree()) -> [[syntaxTree()]].
subtrees(T) ->
    case is_leaf(T) of
	true ->
	    [];
	false ->
	    case type(T) of
		application ->
		    [[application_operator(T)],
		     application_arguments(T)];
		arity_qualifier ->
		    [[arity_qualifier_body(T)],
		     [arity_qualifier_argument(T)]];
		attribute ->
		    case attribute_arguments(T) of
			none ->
			    [[attribute_name(T)]];
			As ->
			    [[attribute_name(T)], As]
		    end;
		binary ->
		    [binary_fields(T)];
		binary_comp ->
		    [[binary_comp_template(T)], binary_comp_body(T)];
                binary_field ->
		    case binary_field_types(T) of
			[] ->
			    [[binary_field_body(T)]];
			Ts ->
			    [[binary_field_body(T)],
			     Ts]
		    end;
	        binary_generator ->
		    [[binary_generator_pattern(T)], 
                     [binary_generator_body(T)]];
		block_expr ->
		    [block_expr_body(T)];
		case_expr ->
		    [[case_expr_argument(T)],
		     case_expr_clauses(T)];
		catch_expr ->
		    [[catch_expr_body(T)]];
		class_qualifier ->
		    [[class_qualifier_argument(T)],
		     [class_qualifier_body(T)]];
		clause ->
		    case clause_guard(T) of
			none ->
			    [clause_patterns(T), clause_body(T)];
			G ->
			    [clause_patterns(T), [G],
			     clause_body(T)]
		    end;
		cond_expr ->
		    [cond_expr_clauses(T)];
		conjunction ->
		    [conjunction_body(T)];
		disjunction ->
		    [disjunction_body(T)];
		form_list ->
		    [form_list_elements(T)];
		fun_expr ->
		    [fun_expr_clauses(T)];
		function ->
		    [[function_name(T)], function_clauses(T)];
		generator ->
		    [[generator_pattern(T)], [generator_body(T)]];
		if_expr ->
		    [if_expr_clauses(T)];
		implicit_fun ->
		    [[implicit_fun_name(T)]];
		infix_expr ->
		    [[infix_expr_left(T)],
		     [infix_expr_operator(T)],
		     [infix_expr_right(T)]];
		list ->
		    case list_suffix(T) of
			none ->
			    [list_prefix(T)];
			S ->
			    [list_prefix(T), [S]]
		    end;
		list_comp ->
		    [[list_comp_template(T)], list_comp_body(T)];
		macro ->
		    case macro_arguments(T) of
			none ->
			    [[macro_name(T)]];
			As ->
			    [[macro_name(T)], As]
		    end;
		match_expr ->
		    [[match_expr_pattern(T)],
		     [match_expr_body(T)]];
		module_qualifier ->
		    [[module_qualifier_argument(T)],
		     [module_qualifier_body(T)]];
		parentheses ->
		    [[parentheses_body(T)]];
		prefix_expr ->
		    [[prefix_expr_operator(T)],
		     [prefix_expr_argument(T)]];
		qualified_name ->
		    [qualified_name_segments(T)];
		query_expr ->
		    [[query_expr_body(T)]];
		receive_expr ->
		    case receive_expr_timeout(T) of
			none ->
			    [receive_expr_clauses(T)];
			E ->
			    [receive_expr_clauses(T),
			     [E],
			     receive_expr_action(T)]
		    end;
		record_access ->
		    case record_access_type(T) of
			none ->
			    [[record_access_argument(T)],
			     [record_access_field(T)]];
			R ->
			    [[record_access_argument(T)],
			     [R],
			     [record_access_field(T)]]
		    end;
		record_expr ->
		    case record_expr_argument(T) of
			none ->
			    [[record_expr_type(T)],
			     record_expr_fields(T)];
			V ->
			    [[V],
			     [record_expr_type(T)],
			     record_expr_fields(T)]
		    end;
		record_field ->
		    case record_field_value(T) of
			none ->
			    [[record_field_name(T)]];
			V ->
			    [[record_field_name(T)], [V]]
		    end;
		record_index_expr ->
		    [[record_index_expr_type(T)],
		     [record_index_expr_field(T)]];
		rule ->
		    [[rule_name(T)], rule_clauses(T)];
		size_qualifier ->
		    [[size_qualifier_body(T)],
		     [size_qualifier_argument(T)]];
		try_expr ->
		    [try_expr_body(T),
		     try_expr_clauses(T),
		     try_expr_handlers(T),
		     try_expr_after(T)];
		tuple ->
		    [tuple_elements(T)]
	    end
    end.
%% =====================================================================
%% @spec update_tree(Node::syntaxTree(), Groups::[[syntaxTree()]]) ->
%%           syntaxTree()
%%
%% @doc 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)).
%%
%% @see make_tree/2
%% @see copy_attrs/2
%% @see type/1
-spec update_tree(syntaxTree(), [[syntaxTree()]]) -> syntaxTree().
update_tree(Node, Groups) ->
    copy_attrs(Node, make_tree(type(Node), Groups)).
%% =====================================================================
%% @spec make_tree(Type::atom(), Groups::[[syntaxTree()]]) ->
%%           syntaxTree()
%%
%% @doc Creates a syntax tree with the given type and subtrees.
%% Type must be a node type name (cf. type/1)
%% that does not denote a leaf node type (cf. is_leaf/1).
%% Groups must 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 by subtrees/1.
%%
%% The result of copy_attrs(Node, make_tree(type(Node),
%% subtrees(Node))) (cf. 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.
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.
%%
%% Any node in Tree whose node type is
%% variable (cf. type/1), and whose list of
%% annotations (cf. 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.
The main use of the function 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. E.g., 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")".
Type and associated data
%% Data.
%%
%% 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.
type/1 for a complete list.erl_parse representation;
%%      in that case, the selector functions for that node type
%%      must handle both the abstract syntax tree and the
%%      erl_parse form. The function type(T)
%%      should return the correct type tag regardless of the
%%      representation of T, so that the user sees no
%%      difference between erl_syntax and
%%      erl_parse nodes.true if
%% Tree is an abstract syntax tree and false
%% otherwise.
%%
%% Note: this function yields false for all
%% "old-style" erl_parse-compatible "parse trees".
badarg if is_tree(Node) does not yield
%% true.
%%
%% @see tree/2
-spec data(syntaxTree()) -> term().
data(#tree{data = D}) -> D;
data(T) -> erlang:error({badarg, T}).
%% =====================================================================
%% Primitives for backwards compatibility; for internal use only
%% =====================================================================
%% =====================================================================
%% @spec wrap(Node::erl_parse()) -> syntaxTree()
%%
%% @type erl_parse() = erl_parse:parse_tree(). The "parse tree"
%% representation built by the Erlang standard library parser
%% erl_parse. This is a subset of the
%% syntaxTree type.
%%
%% @doc Creates a wrapper structure around an erl_parse
%% "parse tree".
%%
%% This function and the related unwrap/1 and
%% is_wrapper/1 provide a uniform way to attach arbitrary
%% information to an erl_parse tree. Some information about
%% the encapsuled tree may be cached in the wrapper, such as the node
%% type. All functions on syntax trees must behave so that the user sees
%% no difference between wrapped and non-wrapped erl_parse
%% trees. Attaching a wrapper onto another wrapper structure is an
%% error.
Node
%% is a wrapper structure, this function returns the wrapped
%% erl_parse tree; otherwise it returns Node
%% itself.
-spec unwrap(syntaxTree()) -> syntaxTree().
unwrap(#wrapper{tree = Node}) -> Node;
unwrap(Node) -> Node.	 % This could also be a new-form node.
%% =====================================================================
%% @spec is_wrapper(Term::term()) -> boolean()
%%
%% @doc Returns true if the argument is a wrapper
%% structure, otherwise false.
-ifndef(NO_UNUSED).
-spec is_wrapper(term()) -> boolean().
is_wrapper(#wrapper{}) ->
    true;
is_wrapper(_) ->
    false.
-endif.
%% =====================================================================
%% General utility functions for internal use
%% =====================================================================
is_printable(S) ->
    io_lib:printable_list(S).
%% Support functions for transforming lists of function names
%% specified as `arity_qualifier' nodes.
unfold_function_names(Ns, Pos) ->
    F = fun ({Atom, Arity}) ->
		N = arity_qualifier(atom(Atom), integer(Arity)),
		set_pos(N, Pos)
	end,
    [F(N) || N <- Ns].
fold_function_names(Ns) ->
    [fold_function_name(N) || N <- Ns].
fold_function_name(N) ->
    Name = arity_qualifier_body(N),
    Arity = arity_qualifier_argument(N),
    true = ((type(Name) =:= atom) and (type(Arity) =:= integer)),
    {concrete(Name), concrete(Arity)}.
fold_variable_names(Vs) ->
    [variable_name(V) || V <- Vs].
unfold_variable_names(Vs, Pos) ->
    [set_pos(variable(V), Pos) || V <- Vs].
%% Support functions for qualified names ("foo.bar.baz",
%% "erl.lang.lists", etc.). The representation overlaps with the weird
%% "Mnesia query record access" operators. The '.' operator is left
%% associative, so folding should nest on the left.
is_qualified_name({record_field, _, L, R}) ->
    is_qualified_name(L) andalso is_qualified_name(R);
is_qualified_name({atom, _, _}) -> true;
is_qualified_name(_) -> false.
unfold_qualified_name(Node) ->
    lists:reverse(unfold_qualified_name(Node, [])).
unfold_qualified_name({record_field, _, L, R}, Ss) ->
    unfold_qualified_name(R, unfold_qualified_name(L, Ss));
unfold_qualified_name(S, Ss) -> [S | Ss].
fold_qualified_name([S | Ss], Pos) ->
    fold_qualified_name(Ss, Pos, {atom, Pos, atom_value(S)}).
fold_qualified_name([S | Ss], Pos, Ack) ->
    fold_qualified_name(Ss, Pos, {record_field, Pos, Ack,
				  {atom, Pos, atom_value(S)}});
fold_qualified_name([], _Pos, Ack) ->
    Ack.
%% Support functions for transforming lists of record field definitions.
%%
%% There is no unique representation for field definitions in the
%% standard form. There, they may only occur in the "fields" part of a
%% record expression or declaration, and are represented as
%% `{record_field, Pos, Name, Value}', or as `{record_field, Pos, Name}'
%% if the value part is left out. However, these cannot be distinguished
%% out of context from the representation of record field access
%% expressions (see `record_access').
fold_record_fields(Fs) ->
    [fold_record_field(F) || F <- Fs].
fold_record_field(F) ->
    Pos = get_pos(F),
    Name = record_field_name(F),
    case record_field_value(F) of
	none ->
	    {record_field, Pos, Name};
	Value ->
	    {record_field, Pos, Name, Value}
    end.
unfold_record_fields(Fs) ->
    [unfold_record_field(F) || F <- Fs].
unfold_record_field({typed_record_field, Field, _Type}) ->
  unfold_record_field_1(Field);
unfold_record_field(Field) ->
  unfold_record_field_1(Field).
unfold_record_field_1({record_field, Pos, Name}) ->
    set_pos(record_field(Name), Pos);
unfold_record_field_1({record_field, Pos, Name, Value}) ->
    set_pos(record_field(Name, Value), Pos).
fold_binary_field_types(Ts) ->
    [fold_binary_field_type(T) || T <- Ts].
fold_binary_field_type(Node) ->
    case type(Node) of
	size_qualifier ->
	    {concrete(size_qualifier_body(Node)),
	     concrete(size_qualifier_argument(Node))};
	_ ->
	    concrete(Node)
    end.
unfold_binary_field_types(Ts, Pos) ->
    [unfold_binary_field_type(T, Pos) || T <- Ts].
unfold_binary_field_type({Type, Size}, Pos) ->
    set_pos(size_qualifier(atom(Type), integer(Size)), Pos);
unfold_binary_field_type(Type, Pos) ->
    set_pos(atom(Type), Pos).
%% =====================================================================