diff options
Diffstat (limited to 'lib/syntax_tools/src/erl_syntax_lib.erl')
-rw-r--r-- | lib/syntax_tools/src/erl_syntax_lib.erl | 150 |
1 files changed, 130 insertions, 20 deletions
diff --git a/lib/syntax_tools/src/erl_syntax_lib.erl b/lib/syntax_tools/src/erl_syntax_lib.erl index ccbf864c2a..5c4e074488 100644 --- a/lib/syntax_tools/src/erl_syntax_lib.erl +++ b/lib/syntax_tools/src/erl_syntax_lib.erl @@ -46,6 +46,9 @@ new_variable_names/2, new_variable_names/3, strip_comments/1, to_comment/1, to_comment/2, to_comment/3, variables/1]). +%% ===================================================================== + +-type ordset(X) :: [X]. % XXX: TAKE ME OUT %% ===================================================================== %% @spec map(Function, Tree::syntaxTree()) -> syntaxTree() @@ -58,6 +61,9 @@ %% %% @see map_subtrees/2 +-spec map(fun((erl_syntax:syntaxTree()) -> erl_syntax:syntaxTree()), + erl_syntax:syntaxTree()) -> erl_syntax:syntaxTree(). + map(F, Tree) -> case erl_syntax:subtrees(Tree) of [] -> @@ -81,6 +87,9 @@ map(F, Tree) -> %% %% @see map/2 +-spec map_subtrees(fun((erl_syntax:syntaxTree()) -> erl_syntax:syntaxTree()), + erl_syntax:syntaxTree()) -> erl_syntax:syntaxTree(). + map_subtrees(F, Tree) -> case erl_syntax:subtrees(Tree) of [] -> @@ -105,6 +114,9 @@ map_subtrees(F, Tree) -> %% @see fold_subtrees/3 %% @see foldl_listlist/3 +-spec fold(fun((erl_syntax:syntaxTree(), term()) -> term()), + term(), erl_syntax:syntaxTree()) -> term(). + fold(F, S, Tree) -> case erl_syntax:subtrees(Tree) of [] -> @@ -137,6 +149,9 @@ fold_2(_, S, []) -> %% %% @see fold/3 +-spec fold_subtrees(fun((erl_syntax:syntaxTree(), term()) -> term()), + term(), erl_syntax:syntaxTree()) -> term(). + fold_subtrees(F, S, Tree) -> foldl_listlist(F, S, erl_syntax:subtrees(Tree)). @@ -151,6 +166,9 @@ fold_subtrees(F, S, Tree) -> %% @see fold/3 %% @see //stdlib/lists:foldl/3 +-spec foldl_listlist(fun((term(), term()) -> term()), + term(), [[term()]]) -> term(). + foldl_listlist(F, S, [L | Ls]) -> foldl_listlist(F, foldl(F, S, L), Ls); foldl_listlist(_, S, []) -> @@ -178,6 +196,9 @@ foldl(_, S, []) -> %% @see map/2 %% @see fold/3 +-spec mapfold(fun((erl_syntax:syntaxTree(), term()) -> {erl_syntax:syntaxTree(), term()}), + term(), erl_syntax:syntaxTree()) -> {erl_syntax:syntaxTree(), term()}. + mapfold(F, S, Tree) -> case erl_syntax:subtrees(Tree) of [] -> @@ -216,6 +237,11 @@ mapfold_2(_, S, []) -> %% %% @see mapfold/3 +-spec mapfold_subtrees(fun((erl_syntax:syntaxTree(), term()) -> + {erl_syntax:syntaxTree(), term()}), + term(), erl_syntax:syntaxTree()) -> + {erl_syntax:syntaxTree(), term()}. + mapfold_subtrees(F, S, Tree) -> case erl_syntax:subtrees(Tree) of [] -> @@ -237,6 +263,9 @@ mapfold_subtrees(F, S, Tree) -> %% The list of lists in the result has the same structure as the given %% list of lists. +-spec mapfoldl_listlist(fun((term(), term()) -> {term(), term()}), + term(), [[term()]]) -> {[[term()]], term()}. + mapfoldl_listlist(F, S, [L | Ls]) -> {L1, S1} = mapfoldl(F, S, L), {Ls1, S2} = mapfoldl_listlist(F, S1, Ls), @@ -263,6 +292,8 @@ mapfoldl(_, S, []) -> %% %% @see //stdlib/sets +-spec variables(erl_syntax:syntaxTree()) -> set(). + variables(Tree) -> variables(Tree, sets:new()). @@ -316,6 +347,8 @@ default_variable_name(N) -> %% %% @see new_variable_name/2 +-spec new_variable_name(set()) -> atom(). + new_variable_name(S) -> new_variable_name(fun default_variable_name/1, S). @@ -340,6 +373,8 @@ new_variable_name(S) -> %% @see //stdlib/sets %% @see //stdlib/random +-spec new_variable_name(fun((integer()) -> atom()), set()) -> atom(). + new_variable_name(F, S) -> R = start_range(S), new_variable_name(R, F, S). @@ -388,6 +423,8 @@ generate(_Key, Range) -> %% %% @see new_variable_name/1 +-spec new_variable_names(integer(), set()) -> [atom()]. + new_variable_names(N, S) -> new_variable_names(N, fun default_variable_name/1, S). @@ -402,6 +439,9 @@ new_variable_names(N, S) -> %% %% @see new_variable_name/2 +-spec new_variable_names(integer(), fun((integer()) -> atom()), set()) -> + [atom()]. + new_variable_names(N, F, S) when is_integer(N) -> R = start_range(S), new_variable_names(N, [], R, F, S). @@ -441,6 +481,9 @@ new_variable_names(0, Names, _, _, _) -> %% @see annotate_bindings/1 %% @see //stdlib/ordsets +-spec annotate_bindings(erl_syntax:syntaxTree(), ordset(atom())) -> + erl_syntax:syntaxTree(). + annotate_bindings(Tree, Env) -> {Tree1, _, _} = vann(Tree, Env), Tree1. @@ -457,6 +500,8 @@ annotate_bindings(Tree, Env) -> %% %% @see annotate_bindings/2 +-spec annotate_bindings(erl_syntax:syntaxTree()) -> erl_syntax:syntaxTree(). + annotate_bindings(Tree) -> As = erl_syntax:get_ann(Tree), case lists:keyfind(env, 1, As) of @@ -856,7 +901,7 @@ delete_binding_anns([]) -> %% ===================================================================== -%% @spec is_fail_expr(Tree::syntaxTree()) -> bool() +%% @spec is_fail_expr(Tree::syntaxTree()) -> boolean() %% %% @doc Returns `true' if `Tree' represents an %% expression which never terminates normally. Note that the reverse @@ -869,6 +914,8 @@ delete_binding_anns([]) -> %% @see //erts/erlang:error/1 %% @see //erts/erlang:error/2 +-spec is_fail_expr(erl_syntax:syntaxTree()) -> boolean(). + is_fail_expr(E) -> case erl_syntax:type(E) of application -> @@ -1038,6 +1085,12 @@ is_fail_expr(E) -> %% @see erl_syntax:error_marker_info/1 %% @see erl_syntax:warning_marker_info/1 +-type key() :: 'attributes' | 'errors' | 'exports' | 'functions' | 'imports' + | 'module' | 'records' | 'rules' | 'warnings'. +-type info_pair() :: {key(), term()}. + +-spec analyze_forms(erl_syntax:forms()) -> [info_pair()]. + analyze_forms(Forms) when is_list(Forms) -> finfo_to_list(lists:foldl(fun collect_form/2, new_finfo(), Forms)); analyze_forms(Forms) -> @@ -1204,6 +1257,8 @@ list_value(List) -> %% @see erl_syntax:error_marker_info/1 %% @see erl_syntax:warning_marker_info/1 +-spec analyze_form(erl_syntax:syntaxTree()) -> {atom(), term()} | atom(). + analyze_form(Node) -> case erl_syntax:type(Node) of attribute -> @@ -1276,6 +1331,9 @@ analyze_form(Node) -> %% @see analyze_record_attribute/1 %% @see analyze_wild_attribute/1 +-spec analyze_attribute(erl_syntax:syntaxTree()) -> + 'preprocessor' | {atom(), term()}. % XXX: underspecified + analyze_attribute(Node) -> Name = erl_syntax:attribute_name(Node), case erl_syntax:type(Name) of @@ -1326,12 +1384,14 @@ analyze_attribute(_, Node) -> %% containing the module name and a list of the parameter variable %% names. %% -%% The evaluation throws `syntax_error' if -%% `Node' does not represent a well-formed module -%% attribute. +%% The evaluation throws `syntax_error' if `Node' does not represent a +%% well-formed module attribute. %% %% @see analyze_attribute/1 +-spec analyze_module_attribute(erl_syntax:syntaxTree()) -> + atom() | {atom(), [atom()]}. + analyze_module_attribute(Node) -> case erl_syntax:type(Node) of attribute -> @@ -1370,12 +1430,16 @@ analyze_variable_list(Node) -> %% attribute. We do not guarantee that each name occurs at most once in %% the list. The order of listing is not defined. %% -%% The evaluation throws `syntax_error' if -%% `Node' does not represent a well-formed export -%% attribute. +%% The evaluation throws `syntax_error' if `Node' does not represent a +%% well-formed export attribute. %% %% @see analyze_attribute/1 +-type functionN() :: atom() | {atom(), arity()}. +-type functionName() :: functionN() | {atom(), functionN()}. + +-spec analyze_export_attribute(erl_syntax:syntaxTree()) -> [functionName()]. + analyze_export_attribute(Node) -> case erl_syntax:type(Node) of attribute -> @@ -1416,6 +1480,8 @@ analyze_function_name_list(Node) -> %% The evaluation throws `syntax_error' if %% `Node' does not represent a well-formed function name. +-spec analyze_function_name(erl_syntax:syntaxTree()) -> functionName(). + analyze_function_name(Node) -> case erl_syntax:type(Node) of atom -> @@ -1470,12 +1536,14 @@ append_arity(_A, Name) -> %% that each name occurs at most once in `Names'. The order %% of listing is not defined. %% -%% The evaluation throws `syntax_error' if -%% `Node' does not represent a well-formed import -%% attribute. +%% The evaluation throws `syntax_error' if `Node' does not represent a +%% well-formed import attribute. %% %% @see analyze_attribute/1 +-spec analyze_import_attribute(erl_syntax:syntaxTree()) -> + {atom(), [functionName()]} | atom(). + analyze_import_attribute(Node) -> case erl_syntax:type(Node) of attribute -> @@ -1498,19 +1566,19 @@ analyze_import_attribute(Node) -> %% @spec analyze_wild_attribute(Node::syntaxTree()) -> {atom(), term()} %% %% @doc Returns the name and value of a "wild" attribute. The result is -%% the pair `{Name, Value}', if `Node' represents -%% "`-Name(Value)'". +%% the pair `{Name, Value}', if `Node' represents "`-Name(Value)'". %% %% Note that no checking is done whether `Name' is a %% reserved attribute name such as `module' or %% `export': it is assumed that the attribute is "wild". %% -%% The evaluation throws `syntax_error' if -%% `Node' does not represent a well-formed wild -%% attribute. +%% The evaluation throws `syntax_error' if `Node' does not represent a +%% well-formed wild attribute. %% %% @see analyze_attribute/1 +-spec analyze_wild_attribute(erl_syntax:syntaxTree()) -> {atom(), term()}. + analyze_wild_attribute(Node) -> case erl_syntax:type(Node) of attribute -> @@ -1559,6 +1627,10 @@ analyze_wild_attribute(Node) -> %% @see analyze_attribute/1 %% @see analyze_record_field/1 +-type fields() :: [{atom(), 'none' | erl_syntax:syntaxTree()}]. + +-spec analyze_record_attribute(erl_syntax:syntaxTree()) -> {atom(), fields()}. + analyze_record_attribute(Node) -> case erl_syntax:type(Node) of attribute -> @@ -1629,6 +1701,11 @@ analyze_record_attribute_tuple(Node) -> %% @see analyze_record_attribute/1 %% @see analyze_record_field/1 +-type info() :: {atom(), [{atom(), 'none' | erl_syntax:syntaxTree()}]} + | {atom(), atom()} | atom(). + +-spec analyze_record_expr(erl_syntax:syntaxTree()) -> {atom(), info()} | atom(). + analyze_record_expr(Node) -> case erl_syntax:type(Node) of record_expr -> @@ -1700,6 +1777,9 @@ analyze_record_expr(Node) -> %% @see analyze_record_attribute/1 %% @see analyze_record_expr/1 +-spec analyze_record_field(erl_syntax:syntaxTree()) -> + {atom(), 'none' | erl_syntax:syntaxTree()}. + analyze_record_field(Node) -> case erl_syntax:type(Node) of record_field -> @@ -1730,6 +1810,8 @@ analyze_record_field(Node) -> %% %% @see analyze_attribute/1 +-spec analyze_file_attribute(erl_syntax:syntaxTree()) -> {string(), integer()}. + analyze_file_attribute(Node) -> case erl_syntax:type(Node) of attribute -> @@ -1765,6 +1847,8 @@ analyze_file_attribute(Node) -> %% %% @see analyze_rule/1 +-spec analyze_function(erl_syntax:syntaxTree()) -> {atom(), arity()}. + analyze_function(Node) -> case erl_syntax:type(Node) of function -> @@ -1794,6 +1878,8 @@ analyze_function(Node) -> %% %% @see analyze_function/1 +-spec analyze_rule(erl_syntax:syntaxTree()) -> {atom(), arity()}. + analyze_rule(Node) -> case erl_syntax:type(Node) of rule -> @@ -1826,11 +1912,12 @@ analyze_rule(Node) -> %% %% @see analyze_function_name/1 +-spec analyze_implicit_fun(erl_syntax:syntaxTree()) -> functionName(). + analyze_implicit_fun(Node) -> case erl_syntax:type(Node) of implicit_fun -> - analyze_function_name( - erl_syntax:implicit_fun_name(Node)); + analyze_function_name(erl_syntax:implicit_fun_name(Node)); _ -> throw(syntax_error) end. @@ -1851,12 +1938,15 @@ analyze_implicit_fun(Node) -> %% function is not explicitly named (i.e., `F' is given by %% some expression), only the arity `A' is returned. %% -%% The evaluation throws `syntax_error' if -%% `Node' does not represent a well-formed application -%% expression. +%% The evaluation throws `syntax_error' if `Node' does not represent a +%% well-formed application expression. %% %% @see analyze_function_name/1 +-type appFunName() :: {atom(), arity()} | {atom(), {atom(), arity()}}. + +-spec analyze_application(erl_syntax:syntaxTree()) -> appFunName() | arity(). + analyze_application(Node) -> case erl_syntax:type(Node) of application -> @@ -1897,6 +1987,11 @@ analyze_application(Node) -> %% %% @see analyze_function_name/1 +-type shortname() :: atom() | {atom(), arity()}. +-type name() :: shortname() | {atom(), shortname()}. + +-spec function_name_expansions([name()]) -> [{shortname(), name()}]. + function_name_expansions(Fs) -> function_name_expansions(Fs, []). @@ -1922,6 +2017,8 @@ function_name_expansions(A, Name, Ack) -> %% Standalone comments in form lists are removed; any other standalone %% comments are changed into null-comments (no text, no indentation). +-spec strip_comments(erl_syntax:syntaxTree()) -> erl_syntax:syntaxTree(). + strip_comments(Tree) -> map(fun strip_comments_1/1, Tree). @@ -1942,6 +2039,8 @@ strip_comments_1(T) -> %% @spec to_comment(Tree) -> syntaxTree() %% @equiv to_comment(Tree, "% ") +-spec to_comment(erl_syntax:syntaxTree()) -> erl_syntax:syntaxTree(). + to_comment(Tree) -> to_comment(Tree, "% "). @@ -1956,6 +2055,8 @@ to_comment(Tree) -> %% @see to_comment/3 %% @see erl_prettypr:format/1 +-spec to_comment(erl_syntax:syntaxTree(), string()) -> erl_syntax:syntaxTree(). + to_comment(Tree, Prefix) -> F = fun (T) -> erl_prettypr:format(T) end, to_comment(Tree, Prefix, F). @@ -1985,6 +2086,10 @@ to_comment(Tree, Prefix) -> %% @see to_comment/1 %% @see to_comment/2 +-spec to_comment(erl_syntax:syntaxTree(), string(), + fun((erl_syntax:syntaxTree()) -> string())) -> + erl_syntax:syntaxTree(). + to_comment(Tree, Prefix, F) -> erl_syntax:comment(split_lines(F(Tree), Prefix)). @@ -1998,6 +2103,8 @@ to_comment(Tree, Prefix, F) -> %% @see limit/3 %% @see erl_syntax:text/1 +-spec limit(erl_syntax:syntaxTree(), integer()) -> erl_syntax:syntaxTree(). + limit(Tree, Depth) -> limit(Tree, Depth, erl_syntax:text("...")). @@ -2026,6 +2133,9 @@ limit(Tree, Depth) -> %% %% @see limit/2 +-spec limit(erl_syntax:syntaxTree(), integer(), erl_syntax:syntaxTree()) -> + erl_syntax:syntaxTree(). + limit(_Tree, Depth, Node) when Depth < 0 -> Node; limit(Tree, Depth, Node) -> |