diff options
Diffstat (limited to 'lib/syntax_tools/src')
-rw-r--r-- | lib/syntax_tools/src/Makefile | 5 | ||||
-rw-r--r-- | lib/syntax_tools/src/epp_dodger.erl | 71 | ||||
-rw-r--r-- | lib/syntax_tools/src/erl_comment_scan.erl | 18 | ||||
-rw-r--r-- | lib/syntax_tools/src/erl_prettypr.erl | 55 | ||||
-rw-r--r-- | lib/syntax_tools/src/erl_recomment.erl | 45 | ||||
-rw-r--r-- | lib/syntax_tools/src/erl_syntax.erl | 582 | ||||
-rw-r--r-- | lib/syntax_tools/src/erl_syntax_lib.erl | 150 | ||||
-rw-r--r-- | lib/syntax_tools/src/erl_tidy.erl | 32 | ||||
-rw-r--r-- | lib/syntax_tools/src/igor.erl | 162 | ||||
-rw-r--r-- | lib/syntax_tools/src/prettypr.erl | 74 |
10 files changed, 970 insertions, 224 deletions
diff --git a/lib/syntax_tools/src/Makefile b/lib/syntax_tools/src/Makefile index 62a24d98c0..50369e633e 100644 --- a/lib/syntax_tools/src/Makefile +++ b/lib/syntax_tools/src/Makefile @@ -23,7 +23,10 @@ RELSYSDIR = $(RELEASE_PATH)/lib/syntax_tools-$(VSN) EBIN = ../ebin -ERL_COMPILE_FLAGS += +warn_unused_vars +nowarn_shadow_vars +warn_unused_import +warn_obsolete_guard +ifeq ($(NATIVE_LIBS_ENABLED),yes) +ERL_COMPILE_FLAGS += +native +endif +ERL_COMPILE_FLAGS += +warn_unused_vars +nowarn_shadow_vars +warn_unused_import +warn_missing_spec +warn_untyped_record SOURCES=erl_syntax.erl erl_prettypr.erl erl_syntax_lib.erl \ erl_comment_scan.erl erl_recomment.erl erl_tidy.erl \ diff --git a/lib/syntax_tools/src/epp_dodger.erl b/lib/syntax_tools/src/epp_dodger.erl index 7aef549574..6b0f2034f8 100644 --- a/lib/syntax_tools/src/epp_dodger.erl +++ b/lib/syntax_tools/src/epp_dodger.erl @@ -90,6 +90,9 @@ %% This is a so-called Erlang I/O ErrorInfo structure; see the {@link %% //stdlib/io} module for details. +-type errorinfo() :: term(). % {integer(), atom(), term()}. + +-type option() :: atom() | {atom(), term()}. %% ===================================================================== %% @spec parse_file(File) -> {ok, Forms} | {error, errorinfo()} @@ -98,6 +101,9 @@ %% %% @equiv parse_file(File, []) +-spec parse_file(file:filename()) -> + {'ok', erl_syntax:forms()} | {'error', errorinfo()}. + parse_file(File) -> parse_file(File, []). @@ -109,11 +115,11 @@ parse_file(File) -> %% @doc Reads and parses a file. If successful, `{ok, Forms}' %% is returned, where `Forms' is a list of abstract syntax %% trees representing the "program forms" of the file (cf. -%% `erl_syntax:is_form/1'). Otherwise, `{error, -%% errorinfo()}' is returned, typically if the file could not be -%% opened. Note that parse errors show up as error markers in the -%% returned list of forms; they do not cause this function to fail or -%% return `{error,errorinfo()}'. +%% `erl_syntax:is_form/1'). Otherwise, `{error, errorinfo()}' is +%% returned, typically if the file could not be opened. Note that +%% parse errors show up as error markers in the returned list of +%% forms; they do not cause this function to fail or return +%% `{error, errorinfo()}'. %% %% Options: %% <dl> @@ -135,6 +141,9 @@ parse_file(File) -> %% @see quick_parse_file/1 %% @see erl_syntax:is_form/1 +-spec parse_file(file:filename(), [option()]) -> + {'ok', erl_syntax:forms()} | {'error', errorinfo()}. + parse_file(File, Options) -> parse_file(File, fun parse/3, Options). @@ -144,6 +153,9 @@ parse_file(File, Options) -> %% %% @equiv quick_parse_file(File, []) +-spec quick_parse_file(file:filename()) -> + {'ok', erl_syntax:forms()} | {'error', errorinfo()}. + quick_parse_file(File) -> quick_parse_file(File, []). @@ -167,6 +179,9 @@ quick_parse_file(File) -> %% @see quick_parse/2 %% @see parse_file/2 +-spec quick_parse_file(file:filename(), [option()]) -> + {'ok', erl_syntax:forms()} | {'error', errorinfo()}. + quick_parse_file(File, Options) -> parse_file(File, fun quick_parse/3, Options ++ [no_fail]). @@ -185,6 +200,8 @@ parse_file(File, Parser, Options) -> %% @spec parse(IODevice) -> {ok, Forms} | {error, errorinfo()} %% @equiv parse(IODevice, 1) +-spec parse(file:io_device()) -> {'ok', erl_syntax:forms()}. + parse(Dev) -> parse(Dev, 1). @@ -196,6 +213,8 @@ parse(Dev) -> %% @equiv parse(IODevice, StartLine, []) %% @see parse/1 +-spec parse(file:io_device(), integer()) -> {'ok', erl_syntax:forms()}. + parse(Dev, L) -> parse(Dev, L, []). @@ -216,12 +235,18 @@ parse(Dev, L) -> %% @see parse_form/2 %% @see quick_parse/3 +-spec parse(file:io_device(), integer(), [option()]) -> + {'ok', erl_syntax:forms()}. + parse(Dev, L0, Options) -> parse(Dev, L0, fun parse_form/3, Options). %% @spec quick_parse(IODevice) -> {ok, Forms} | {error, errorinfo()} %% @equiv quick_parse(IODevice, 1) +-spec quick_parse(file:io_device()) -> + {'ok', erl_syntax:forms()}. + quick_parse(Dev) -> quick_parse(Dev, 1). @@ -234,6 +259,9 @@ quick_parse(Dev) -> %% @equiv quick_parse(IODevice, StartLine, []) %% @see quick_parse/1 +-spec quick_parse(file:io_device(), integer()) -> + {'ok', erl_syntax:forms()}. + quick_parse(Dev, L) -> quick_parse(Dev, L, []). @@ -252,6 +280,9 @@ quick_parse(Dev, L) -> %% @see quick_parse_form/2 %% @see parse/3 +-spec quick_parse(file:io_device(), integer(), [option()]) -> + {'ok', erl_syntax:forms()}. + quick_parse(Dev, L0, Options) -> parse(Dev, L0, fun quick_parse_form/3, Options). @@ -284,6 +315,10 @@ parse(Dev, L0, Fs, Parser, Options) -> %% %% @see quick_parse_form/2 +-spec parse_form(file:io_device(), integer()) -> + {'ok', erl_syntax:forms(), integer()} + | {'eof', integer()} | {'error', errorinfo(), integer()}. + parse_form(Dev, L0) -> parse_form(Dev, L0, []). @@ -310,6 +345,10 @@ parse_form(Dev, L0) -> %% @see parse_form/2 %% @see quick_parse_form/3 +-spec parse_form(file:io_device(), integer(), [option()]) -> + {'ok', erl_syntax:forms(), integer()} + | {'eof', integer()} | {'error', errorinfo(), integer()}. + parse_form(Dev, L0, Options) -> parse_form(Dev, L0, fun normal_parser/2, Options). @@ -326,6 +365,10 @@ parse_form(Dev, L0, Options) -> %% %% @see parse_form/2 +-spec quick_parse_form(file:io_device(), integer()) -> + {'ok', erl_syntax:forms(), integer()} + | {'eof', integer()} | {'error', errorinfo(), integer()}. + quick_parse_form(Dev, L0) -> quick_parse_form(Dev, L0, []). @@ -347,6 +390,10 @@ quick_parse_form(Dev, L0) -> %% @see quick_parse_form/2 %% @see parse_form/3 +-spec quick_parse_form(file:io_device(), integer(), [option()]) -> + {'ok', erl_syntax:forms(), integer()} + | {'eof', integer()} | {'error', errorinfo(), integer()}. + quick_parse_form(Dev, L0, Options) -> parse_form(Dev, L0, fun quick_parser/2, Options). @@ -751,11 +798,13 @@ fix_define([{atom, L, ?pp_form}, {'(', _}, {')', _}, {'->', _}, fix_define(_Ts) -> error. -%% @spec (Tokens::[term()]) -> string() +%% @spec tokens_to_string(Tokens::[term()]) -> string() %% %% @doc Generates a string corresponding to the given token sequence. %% The string can be re-tokenized to yield the same token list again. +-spec tokens_to_string([term()]) -> string(). + tokens_to_string([{atom,_,A} | Ts]) -> io_lib:write_atom(A) ++ " " ++ tokens_to_string(Ts); tokens_to_string([{string, _, S} | Ts]) -> @@ -764,21 +813,23 @@ tokens_to_string([{float, _, F} | Ts]) -> float_to_list(F) ++ " " ++ tokens_to_string(Ts); tokens_to_string([{integer, _, N} | Ts]) -> integer_to_list(N) ++ " " ++ tokens_to_string(Ts); -tokens_to_string([{var,_,A} | Ts]) -> +tokens_to_string([{var, _, A} | Ts]) -> atom_to_list(A) ++ " " ++ tokens_to_string(Ts); -tokens_to_string([{dot,_} | Ts]) -> +tokens_to_string([{dot, _} | Ts]) -> ".\n" ++ tokens_to_string(Ts); -tokens_to_string([{A,_} | Ts]) -> +tokens_to_string([{A, _} | Ts]) -> atom_to_list(A) ++ " " ++ tokens_to_string(Ts); tokens_to_string([]) -> "". -%% @spec (Descriptor::term()) -> string() +%% @spec format_error(Descriptor::term()) -> string() %% @hidden %% @doc Callback function for formatting error descriptors. Not for %% normal use. +-spec format_error(term()) -> string(). + format_error(macro_args) -> errormsg("macro call missing end parenthesis"); format_error({unknown, Reason}) -> diff --git a/lib/syntax_tools/src/erl_comment_scan.erl b/lib/syntax_tools/src/erl_comment_scan.erl index df1449da4e..09ce21a428 100644 --- a/lib/syntax_tools/src/erl_comment_scan.erl +++ b/lib/syntax_tools/src/erl_comment_scan.erl @@ -14,8 +14,7 @@ %% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 %% USA %% -%% $Id$ -%% +%% ===================================================================== %% @copyright 1997-2006 Richard Carlsson %% @author Richard Carlsson <[email protected]> %% @end @@ -29,6 +28,11 @@ %% ===================================================================== + +-type comment() :: {integer(), integer(), integer(), [string()]}. +-type commentLine() :: {integer(), integer(), integer(), string()}. + +%% ===================================================================== %% @spec file(FileName::file:filename()) -> [Comment] %% %% Comment = {Line, Column, Indentation, Text} @@ -59,6 +63,8 @@ %% error occurred, where `Reason' is an atom corresponding to %% a Posix error code; see the module {@link //kernel/file} for details. +-spec file(file:filename()) -> [comment()]. + file(Name) -> Name1 = filename(Name), case catch {ok, file:read_file(Name1)} of @@ -80,7 +86,7 @@ file(Name) -> %% ===================================================================== -%% string(string()) -> [Comment] +%% @spec string(string()) -> [Comment] %% %% Comment = {Line, Column, Indentation, Text} %% Line = integer() @@ -94,6 +100,8 @@ file(Name) -> %% %% @see file/1 +-spec string(string()) -> [comment()]. + string(Text) -> lists:reverse(join_lines(scan_lines(Text))). @@ -116,6 +124,8 @@ string(Text) -> %% to (but not including) the line-terminating newline. For details on %% `Line', `Column' and `Indent', see {@link file/1}. +-spec scan_lines(string()) -> [commentLine()]. + scan_lines(Text) -> scan_lines(Text, 1, 0, 0, []). @@ -231,6 +241,8 @@ scan_char([], _L, _Col, Ack) -> %% %% @see scan_lines/1 +-spec join_lines([commentLine()]) -> [comment()]. + join_lines([{L, Col, Ind, Txt} | Lines]) -> join_lines(Lines, [Txt], L, Col, Ind); join_lines([]) -> diff --git a/lib/syntax_tools/src/erl_prettypr.erl b/lib/syntax_tools/src/erl_prettypr.erl index 8d2f4facea..606441bcf1 100644 --- a/lib/syntax_tools/src/erl_prettypr.erl +++ b/lib/syntax_tools/src/erl_prettypr.erl @@ -48,25 +48,30 @@ -define(NOUSER, undefined). -define(NOHOOK, none). --record(ctxt, {prec = 0, - sub_indent = 2, - break_indent = 4, - clause = undefined, - hook = ?NOHOOK, - paper = ?PAPER, - ribbon = ?RIBBON, - user = ?NOUSER}). +-type hook() :: 'none' + | fun((erl_syntax:syntaxTree(), _, _) -> prettypr:document()). +-record(ctxt, {prec = 0 :: integer(), + sub_indent = 2 :: non_neg_integer(), + break_indent = 4 :: non_neg_integer(), + clause = undefined, + hook = ?NOHOOK :: hook(), + paper = ?PAPER :: integer(), + ribbon = ?RIBBON :: integer(), + user = ?NOUSER :: term()}). +-type context() :: #ctxt{}. %% ===================================================================== %% The following functions examine and modify contexts: -%% @spec (context()) -> context() +%% @spec (context()) -> integer() %% @doc Returns the operator precedence field of the prettyprinter %% context. %% %% @see set_ctxt_precedence/2 +-spec get_ctxt_precedence(context()) -> integer(). + get_ctxt_precedence(Ctxt) -> Ctxt#ctxt.prec. @@ -78,6 +83,8 @@ get_ctxt_precedence(Ctxt) -> %% @see //stdlib/erl_parse %% @see get_ctxt_precedence/1 +-spec set_ctxt_precedence(context(), integer()) -> context(). + set_ctxt_precedence(Ctxt, Prec) -> set_prec(Ctxt, Prec). @@ -91,6 +98,8 @@ reset_prec(Ctxt) -> %% @doc Returns the paper widh field of the prettyprinter context. %% @see set_ctxt_paperwidth/2 +-spec get_ctxt_paperwidth(context()) -> integer(). + get_ctxt_paperwidth(Ctxt) -> Ctxt#ctxt.paper. @@ -104,6 +113,8 @@ get_ctxt_paperwidth(Ctxt) -> %% %% @see get_ctxt_paperwidth/1 +-spec set_ctxt_paperwidth(context(), integer()) -> context(). + set_ctxt_paperwidth(Ctxt, W) -> Ctxt#ctxt{paper = W}. @@ -111,6 +122,8 @@ set_ctxt_paperwidth(Ctxt, W) -> %% @doc Returns the line widh field of the prettyprinter context. %% @see set_ctxt_linewidth/2 +-spec get_ctxt_linewidth(context()) -> integer(). + get_ctxt_linewidth(Ctxt) -> Ctxt#ctxt.ribbon. @@ -124,6 +137,8 @@ get_ctxt_linewidth(Ctxt) -> %% %% @see get_ctxt_linewidth/1 +-spec set_ctxt_linewidth(context(), integer()) -> context(). + set_ctxt_linewidth(Ctxt, W) -> Ctxt#ctxt{ribbon = W}. @@ -131,6 +146,8 @@ set_ctxt_linewidth(Ctxt, W) -> %% @doc Returns the hook function field of the prettyprinter context. %% @see set_ctxt_hook/2 +-spec get_ctxt_hook(context()) -> hook(). + get_ctxt_hook(Ctxt) -> Ctxt#ctxt.hook. @@ -138,6 +155,8 @@ get_ctxt_hook(Ctxt) -> %% @doc Updates the hook function field of the prettyprinter context. %% @see get_ctxt_hook/1 +-spec set_ctxt_hook(context(), hook()) -> context(). + set_ctxt_hook(Ctxt, Hook) -> Ctxt#ctxt{hook = Hook}. @@ -145,6 +164,8 @@ set_ctxt_hook(Ctxt, Hook) -> %% @doc Returns the user data field of the prettyprinter context. %% @see set_ctxt_user/2 +-spec get_ctxt_user(context()) -> term(). + get_ctxt_user(Ctxt) -> Ctxt#ctxt.user. @@ -152,6 +173,8 @@ get_ctxt_user(Ctxt) -> %% @doc Updates the user data field of the prettyprinter context. %% @see get_ctxt_user/1 +-spec set_ctxt_user(context(), term()) -> context(). + set_ctxt_user(Ctxt, X) -> Ctxt#ctxt{user = X}. @@ -160,6 +183,8 @@ set_ctxt_user(Ctxt, X) -> %% @spec format(Tree::syntaxTree()) -> string() %% @equiv format(Tree, []) +-spec format(erl_syntax:syntaxTree()) -> string(). + format(Node) -> format(Node, []). @@ -237,6 +262,8 @@ format(Node) -> %% @see get_ctxt_user/1 %% @see set_ctxt_user/2 +-spec format(erl_syntax:syntaxTree(), [term()]) -> string(). + format(Node, Options) -> W = proplists:get_value(paper, Options, ?PAPER), L = proplists:get_value(ribbon, Options, ?RIBBON), @@ -247,6 +274,8 @@ format(Node, Options) -> %% @spec best(Tree::syntaxTree()) -> empty | document() %% @equiv best(Tree, []) +-spec best(erl_syntax:syntaxTree()) -> 'empty' | prettypr:document(). + best(Node) -> best(Node, []). @@ -266,6 +295,8 @@ best(Node) -> %% @see format/2 %% @see prettypr:best/3 +-spec best(erl_syntax:syntaxTree(), [term()]) -> 'empty' | prettypr:document(). + best(Node, Options) -> W = proplists:get_value(paper, Options, ?PAPER), L = proplists:get_value(ribbon, Options, ?RIBBON), @@ -276,6 +307,8 @@ best(Node, Options) -> %% @spec layout(Tree::syntaxTree()) -> document() %% @equiv layout(Tree, []) +-spec layout(erl_syntax:syntaxTree()) -> prettypr:document(). + layout(Node) -> layout(Node, []). @@ -300,6 +333,8 @@ layout(Node) -> %% @see format/2 %% @see layout/1 +-spec layout(erl_syntax:syntaxTree(), [term()]) -> prettypr:document(). + layout(Node, Options) -> lay(Node, #ctxt{hook = proplists:get_value(hook, Options, ?NOHOOK), @@ -593,7 +628,7 @@ lay_2(Node, Ctxt) -> fun_expr -> Ctxt1 = reset_prec(Ctxt), D = lay_clauses(erl_syntax:fun_expr_clauses(Node), - fun_expr, Ctxt1), + fun_expr, Ctxt1), sep([follow(text("fun"), D, Ctxt1#ctxt.sub_indent), text("end")]); diff --git a/lib/syntax_tools/src/erl_recomment.erl b/lib/syntax_tools/src/erl_recomment.erl index 62ec7da200..145bbc6f37 100644 --- a/lib/syntax_tools/src/erl_recomment.erl +++ b/lib/syntax_tools/src/erl_recomment.erl @@ -47,6 +47,9 @@ %% comments. Comments within function definitions or declarations %% ("forms") are simply ignored. +-spec quick_recomment_forms(erl_syntax:forms(), [erl_comment_scan:comment()]) -> + erl_syntax:syntaxTree(). + quick_recomment_forms(Tree, Cs) -> recomment_forms(Tree, Cs, false). @@ -109,6 +112,9 @@ quick_recomment_forms(Tree, Cs) -> %% @see recomment_tree/2 %% @see quick_recomment_forms/2 +-spec recomment_forms(erl_syntax:forms(), [erl_comment_scan:comment()]) -> + erl_syntax:syntaxTree(). + recomment_forms(Tree, Cs) -> recomment_forms(Tree, Cs, true). @@ -209,7 +215,7 @@ comment_delta(Text) -> %% the source file itself, but have been included by preprocessing. This %% way, comments will not be inserted into such parts by mistake. --record(filter, {file = undefined, line = 0}). +-record(filter, {file = undefined, line = 0 :: integer()}). filter_forms(Fs) -> filter_forms(Fs, false, #filter{}). @@ -330,6 +336,9 @@ check_file_attr_2(L) -> %% %% @see recomment_forms/2 +-spec recomment_tree(erl_syntax:syntaxTree(), [erl_comment_scan:comment()]) -> + {erl_syntax:syntaxTree(), [erl_comment_scan:comment()]}. + recomment_tree(Tree, Cs) -> {Tree1, Cs1} = insert_comments(Cs, build_tree(Tree)), {revert_tree(Tree1), Cs1}. @@ -592,23 +601,23 @@ expand_comment(C) -> %% syntax tree for any such tree that can have no subtrees, i.e., such %% that `erl_syntax:is_leaf' yields `true'. --record(leaf, {min = 0, - max = 0, - precomments = [], - postcomments = [], - value}). - --record(tree, {min = 0, - max = 0, - type, - attrs, - precomments = [], - postcomments = [], - subtrees = []}). - --record(list, {min = 0, - max = 0, - subtrees = []}). +-record(leaf, {min = 0 :: integer(), + max = 0 :: integer(), + precomments = [] :: [erl_syntax:syntaxTree()], + postcomments = [] :: [erl_syntax:syntaxTree()], + value :: erl_syntax:syntaxTree()}). + +-record(tree, {min = 0 :: integer(), + max = 0 :: integer(), + type :: atom(), + attrs :: erl_syntax:syntaxTreeAttributes(), + precomments = [] :: [erl_syntax:syntaxTree()], + postcomments = [] :: [erl_syntax:syntaxTree()], + subtrees = [] :: [erl_syntax:syntaxTree()]}). + +-record(list, {min = 0 :: integer(), + max = 0 :: integer(), + subtrees = [] :: [erl_syntax:syntaxTree()]}). leaf_node(Min, Max, Value) -> #leaf{min = Min, diff --git a/lib/syntax_tools/src/erl_syntax.erl b/lib/syntax_tools/src/erl_syntax.erl index 6ceb3ddcaf..9a2967d550 100644 --- a/lib/syntax_tools/src/erl_syntax.erl +++ b/lib/syntax_tools/src/erl_syntax.erl @@ -343,8 +343,8 @@ %% %% type(Com) = comment --record(com, {pre = [], - post = []}). +-record(com, {pre = [] :: [syntaxTree()], + post = [] :: [syntaxTree()]}). %% `attr' records store node attributes as an aggregate. %% @@ -357,9 +357,10 @@ %% where `Pos' `Ann' and `Comments' are the corresponding values of a %% `tree' or `wrapper' record. --record(attr, {pos = 0, - ann = [], - com = none}). +-record(attr, {pos = 0 :: term(), + ann = [] :: [term()], + com = none :: 'none' | #com{}}). +-type syntaxTreeAttributes() :: #attr{}. %% `tree' records represent new-form syntax tree nodes. %% @@ -371,9 +372,9 @@ %% %% is_tree(Tree) = true --record(tree, {type, +-record(tree, {type :: atom(), attr = #attr{} :: #attr{}, - data}). + data :: term()}). %% `wrapper' records are used for attaching new-form node information to %% `erl_parse' trees. @@ -386,10 +387,13 @@ %% %% is_tree(Wrapper) = false --record(wrapper, {type, +-record(wrapper, {type :: atom(), attr = #attr{} :: #attr{}, - tree}). + tree :: term()}). +%% ===================================================================== + +-type syntaxTree() :: #tree{} | #wrapper{} | tuple(). % XXX: refine %% ===================================================================== %% @@ -532,6 +536,8 @@ %% @see variable/1 %% @see warning_marker/1 +-spec type(syntaxTree()) -> atom(). + type(#tree{type = T}) -> T; type(#wrapper{type = T}) -> @@ -599,7 +605,7 @@ type(Node) -> %% ===================================================================== -%% @spec is_leaf(Node::syntaxTree()) -> bool() +%% @spec is_leaf(Node::syntaxTree()) -> boolean() %% %% @doc Returns <code>true</code> if <code>Node</code> is a leaf node, %% otherwise <code>false</code>. The currently recognised leaf node @@ -635,6 +641,8 @@ type(Node) -> %% @see type/1 %% @see is_literal/1 +-spec is_leaf(syntaxTree()) -> boolean(). + is_leaf(Node) -> case type(Node) of atom -> true; @@ -657,7 +665,7 @@ is_leaf(Node) -> %% ===================================================================== -%% @spec is_form(Node::syntaxTree()) -> bool() +%% @spec is_form(Node::syntaxTree()) -> boolean() %% %% @doc Returns <code>true</code> if <code>Node</code> is a syntax tree %% representing a so-called "source code form", otherwise @@ -688,6 +696,8 @@ is_leaf(Node) -> %% @see rule/2 %% @see warning_marker/1 +-spec is_form(syntaxTree()) -> boolean(). + is_form(Node) -> case type(Node) of attribute -> true; @@ -722,6 +732,8 @@ is_form(Node) -> %% 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}) -> @@ -745,6 +757,8 @@ get_pos(Node) -> %% @see get_pos/1 %% @see copy_pos/2 +-spec set_pos(syntaxTree(), term()) -> syntaxTree(). + set_pos(Node, Pos) -> case Node of #tree{attr = Attr} -> @@ -771,6 +785,8 @@ set_pos(Node, Pos) -> %% @see get_pos/1 %% @see set_pos/2 +-spec copy_pos(syntaxTree(), syntaxTree()) -> syntaxTree(). + copy_pos(Source, Target) -> set_pos(Target, get_pos(Source)). @@ -818,6 +834,8 @@ set_com(Node, Com) -> %% @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(_) -> []. @@ -842,6 +860,8 @@ get_precomments_1(#attr{com = #com{pre = Cs}}) -> Cs. %% @see remove_comments/1 %% @see join_comments/2 +-spec set_precomments(syntaxTree(), [syntaxTree()]) -> syntaxTree(). + set_precomments(Node, Cs) -> case Node of #tree{attr = Attr} -> @@ -875,6 +895,8 @@ set_precomments_1(#attr{com = Com} = Attr, Cs) -> %% @see add_postcomments/2 %% @see join_comments/2 +-spec add_precomments([syntaxTree()], syntaxTree()) -> syntaxTree(). + add_precomments(Cs, Node) -> case Node of #tree{attr = Attr} -> @@ -916,6 +938,8 @@ add_precomments_1(Cs, #attr{com = Com} = Attr) -> %% @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(_) -> []. @@ -940,6 +964,8 @@ get_postcomments_1(#attr{com = #com{post = Cs}}) -> Cs. %% @see remove_comments/1 %% @see join_comments/2 +-spec set_postcomments(syntaxTree(), [syntaxTree()]) -> syntaxTree(). + set_postcomments(Node, Cs) -> case Node of #tree{attr = Attr} -> @@ -973,6 +999,8 @@ set_postcomments_1(#attr{com = Com} = Attr, Cs) -> %% @see add_precomments/2 %% @see join_comments/2 +-spec add_postcomments([syntaxTree()], syntaxTree()) -> syntaxTree(). + add_postcomments(Cs, Node) -> case Node of #tree{attr = Attr} -> @@ -990,7 +1018,7 @@ add_postcomments_1(Cs, #attr{com = Com} = Attr) -> %% ===================================================================== -%% @spec has_comments(Node::syntaxTree()) -> bool() +%% @spec has_comments(Node::syntaxTree()) -> boolean() %% %% @doc Yields <code>false</code> if the node has no associated %% comments, and <code>true</code> otherwise. @@ -1003,6 +1031,8 @@ add_postcomments_1(Cs, #attr{com = Com} = Attr) -> %% @see get_postcomments/1 %% @see remove_comments/1 +-spec has_comments(syntaxTree()) -> boolean(). + has_comments(#tree{attr = Attr}) -> case Attr#attr.com of none -> false; @@ -1030,6 +1060,8 @@ has_comments(_) -> false. %% @see set_precomments/2 %% @see set_postcomments/2 +-spec remove_comments(syntaxTree()) -> syntaxTree(). + remove_comments(Node) -> case Node of #tree{attr = Attr} -> @@ -1059,6 +1091,8 @@ remove_comments(Node) -> %% @see set_precomments/2 %% @see set_postcomments/2 +-spec copy_comments(syntaxTree(), syntaxTree()) -> syntaxTree(). + copy_comments(Source, Target) -> set_com(Target, get_com(Source)). @@ -1081,6 +1115,8 @@ copy_comments(Source, Target) -> %% @see add_precomments/2 %% @see add_postcomments/2 +-spec join_comments(syntaxTree(), syntaxTree()) -> syntaxTree(). + join_comments(Source, Target) -> add_postcomments( get_postcomments(Source), @@ -1097,6 +1133,8 @@ join_comments(Source, Target) -> %% @see set_ann/2 %% @see get_attrs/1 +-spec get_ann(syntaxTree()) -> [term()]. + get_ann(#tree{attr = Attr}) -> Attr#attr.ann; get_ann(#wrapper{attr = Attr}) -> Attr#attr.ann; get_ann(_) -> []. @@ -1113,6 +1151,8 @@ get_ann(_) -> []. %% @see add_ann/2 %% @see copy_ann/2 +-spec set_ann(syntaxTree(), [term()]) -> syntaxTree(). + set_ann(Node, As) -> case Node of #tree{attr = Attr} -> @@ -1138,6 +1178,8 @@ set_ann(Node, As) -> %% @see get_ann/1 %% @see set_ann/2 +-spec add_ann(term(), syntaxTree()) -> syntaxTree(). + add_ann(A, Node) -> case Node of #tree{attr = Attr} -> @@ -1164,6 +1206,8 @@ add_ann(A, Node) -> %% @see get_ann/1 %% @see set_ann/2 +-spec copy_ann(syntaxTree(), syntaxTree()) -> syntaxTree(). + copy_ann(Source, Target) -> set_ann(Target, get_ann(Source)). @@ -1192,6 +1236,8 @@ copy_ann(Source, Target) -> %% @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), @@ -1209,6 +1255,8 @@ get_attrs(Node) -> #attr{pos = get_pos(Node), %% @see get_attrs/1 %% @see copy_attrs/2 +-spec set_attrs(syntaxTree(), syntaxTreeAttributes()) -> syntaxTree(). + set_attrs(Node, Attr) -> case Node of #tree{} -> @@ -1233,6 +1281,8 @@ set_attrs(Node, Attr) -> %% @see get_attrs/1 %% @see set_attrs/2 +-spec copy_attrs(syntaxTree(), syntaxTree()) -> syntaxTree(). + copy_attrs(S, T) -> set_attrs(T, get_attrs(S)). @@ -1241,6 +1291,8 @@ copy_attrs(S, T) -> %% @spec comment(Strings) -> syntaxTree() %% @equiv comment(none, Strings) +-spec comment([string()]) -> syntaxTree(). + comment(Strings) -> comment(none, Strings). @@ -1268,7 +1320,9 @@ comment(Strings) -> %% @see comment/1 %% @see is_form/1 --record(comment, {pad, text}). +-type padding() :: 'none' | integer(). + +-record(comment, {pad :: padding(), text :: [string()]}). %% type(Node) = comment %% data(Node) = #comment{pad :: Padding, text :: Strings} @@ -1276,6 +1330,8 @@ comment(Strings) -> %% Padding = none | integer() %% Strings = [string()] +-spec comment(padding(), [string()]) -> syntaxTree(). + comment(Pad, Strings) -> tree(comment, #comment{pad = Pad, text = Strings}). @@ -1287,6 +1343,8 @@ comment(Pad, Strings) -> %% %% @see comment/2 +-spec comment_text(syntaxTree()) -> [string()]. + comment_text(Node) -> (data(Node))#comment.text. @@ -1300,6 +1358,8 @@ comment_text(Node) -> %% %% @see comment/2 +-spec comment_padding(syntaxTree()) -> padding(). + comment_padding(Node) -> (data(Node))#comment.pad. @@ -1333,6 +1393,8 @@ comment_padding(Node) -> %% Form = syntaxTree() %% is_form(Form) = true +-spec form_list([syntaxTree()]) -> syntaxTree(). + form_list(Forms) -> tree(form_list, Forms). @@ -1344,6 +1406,8 @@ form_list(Forms) -> %% %% @see form_list/1 +-spec form_list_elements(syntaxTree()) -> [syntaxTree()]. + form_list_elements(Node) -> data(Node). @@ -1358,6 +1422,8 @@ form_list_elements(Node) -> %% %% @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, [])), @@ -1389,6 +1455,8 @@ flatten_form_list_1([], As) -> %% type(Node) = text %% data(Node) = string() +-spec text(string()) -> syntaxTree(). + text(String) -> tree(text, String). @@ -1401,6 +1469,8 @@ text(String) -> %% %% @see text/1 +-spec text_string(syntaxTree()) -> string(). + text_string(Node) -> data(Node). @@ -1432,6 +1502,8 @@ text_string(Node) -> %% %% Name = atom() \ '_' +-spec variable(atom() | string()) -> syntaxTree(). + variable(Name) when is_atom(Name) -> tree(variable, Name); variable(Name) -> @@ -1450,6 +1522,8 @@ revert_variable(Node) -> %% %% @see variable/1 +-spec variable_name(syntaxTree()) -> atom(). + variable_name(Node) -> case unwrap(Node) of {var, _, Name} -> @@ -1466,6 +1540,8 @@ variable_name(Node) -> %% %% @see variable/1 +-spec variable_literal(syntaxTree()) -> string(). + variable_literal(Node) -> case unwrap(Node) of {var, _, Name} -> @@ -1491,6 +1567,8 @@ variable_literal(Node) -> %% %% {var, Pos, '_'} +-spec underscore() -> syntaxTree(). + underscore() -> tree(underscore, []). @@ -1518,6 +1596,8 @@ revert_underscore(Node) -> %% %% Value = integer() +-spec integer(integer()) -> syntaxTree(). + integer(Value) -> tree(integer, Value). @@ -1527,7 +1607,7 @@ revert_integer(Node) -> %% ===================================================================== -%% @spec is_integer(Node::syntaxTree(), Value::integer()) -> bool() +%% @spec is_integer(Node::syntaxTree(), Value::integer()) -> boolean() %% %% @doc Returns <code>true</code> if <code>Node</code> has type %% <code>integer</code> and represents <code>Value</code>, otherwise @@ -1535,6 +1615,8 @@ revert_integer(Node) -> %% %% @see integer/1 +-spec is_integer(syntaxTree(), integer()) -> boolean(). + is_integer(Node, Value) -> case unwrap(Node) of {integer, _, Value} -> @@ -1553,6 +1635,8 @@ is_integer(Node, Value) -> %% %% @see integer/1 +-spec integer_value(syntaxTree()) -> integer(). + integer_value(Node) -> case unwrap(Node) of {integer, _, Value} -> @@ -1570,6 +1654,8 @@ integer_value(Node) -> %% %% @see integer/1 +-spec integer_literal(syntaxTree()) -> string(). + integer_literal(Node) -> integer_to_list(integer_value(Node)). @@ -1600,6 +1686,8 @@ integer_literal(Node) -> %% 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). @@ -1620,6 +1708,8 @@ revert_float(Node) -> %% %% @see float/1 +-spec float_value(syntaxTree()) -> float(). + float_value(Node) -> case unwrap(Node) of {float, _, Value} -> @@ -1637,6 +1727,8 @@ float_value(Node) -> %% %% @see float/1 +-spec float_literal(syntaxTree()) -> string(). + float_literal(Node) -> float_to_list(float_value(Node)). @@ -1667,6 +1759,8 @@ float_literal(Node) -> %% %% Code = integer() +-spec char(char()) -> syntaxTree(). + char(Char) -> tree(char, Char). @@ -1676,7 +1770,7 @@ revert_char(Node) -> %% ===================================================================== -%% @spec is_char(Node::syntaxTree(), Value::char()) -> bool() +%% @spec is_char(Node::syntaxTree(), Value::char()) -> boolean() %% %% @doc Returns <code>true</code> if <code>Node</code> has type %% <code>char</code> and represents <code>Value</code>, otherwise @@ -1684,6 +1778,8 @@ revert_char(Node) -> %% %% @see char/1 +-spec is_char(syntaxTree(), char()) -> boolean(). + is_char(Node, Value) -> case unwrap(Node) of {char, _, Value} -> @@ -1702,6 +1798,8 @@ is_char(Node, Value) -> %% %% @see char/1 +-spec char_value(syntaxTree()) -> char(). + char_value(Node) -> case unwrap(Node) of {char, _, Char} -> @@ -1719,6 +1817,8 @@ char_value(Node) -> %% %% @see char/1 +-spec char_literal(syntaxTree()) -> string(). + char_literal(Node) -> io_lib:write_char(char_value(Node)). @@ -1749,6 +1849,8 @@ char_literal(Node) -> %% %% Chars = string() +-spec string(string()) -> syntaxTree(). + string(String) -> tree(string, String). @@ -1758,7 +1860,7 @@ revert_string(Node) -> %% ===================================================================== -%% @spec is_string(Node::syntaxTree(), Value::string()) -> bool() +%% @spec is_string(Node::syntaxTree(), Value::string()) -> boolean() %% %% @doc Returns <code>true</code> if <code>Node</code> has type %% <code>string</code> and represents <code>Value</code>, otherwise @@ -1766,6 +1868,8 @@ revert_string(Node) -> %% %% @see string/1 +-spec is_string(syntaxTree(), string()) -> boolean(). + is_string(Node, Value) -> case unwrap(Node) of {string, _, Value} -> @@ -1784,6 +1888,8 @@ is_string(Node, Value) -> %% %% @see string/1 +-spec string_value(syntaxTree()) -> string(). + string_value(Node) -> case unwrap(Node) of {string, _, List} -> @@ -1801,6 +1907,8 @@ string_value(Node) -> %% %% @see string/1 +-spec string_literal(syntaxTree()) -> string(). + string_literal(Node) -> io_lib:write_string(string_value(Node)). @@ -1826,6 +1934,8 @@ string_literal(Node) -> %% %% Value = atom() +-spec atom(atom() | string()) -> syntaxTree(). + atom(Name) when is_atom(Name) -> tree(atom, Name); atom(Name) -> @@ -1837,7 +1947,7 @@ revert_atom(Node) -> %% ===================================================================== -%% @spec is_atom(Node::syntaxTree(), Value::atom()) -> bool() +%% @spec is_atom(Node::syntaxTree(), Value::atom()) -> boolean() %% %% @doc Returns <code>true</code> if <code>Node</code> has type %% <code>atom</code> and represents <code>Value</code>, otherwise @@ -1845,6 +1955,8 @@ revert_atom(Node) -> %% %% @see atom/1 +-spec is_atom(syntaxTree(), atom()) -> boolean(). + is_atom(Node, Value) -> case unwrap(Node) of {atom, _, Value} -> @@ -1863,6 +1975,8 @@ is_atom(Node, Value) -> %% %% @see atom/1 +-spec atom_value(syntaxTree()) -> atom(). + atom_value(Node) -> case unwrap(Node) of {atom, _, Name} -> @@ -1879,6 +1993,8 @@ atom_value(Node) -> %% %% @see atom/1 +-spec atom_name(syntaxTree()) -> string(). + atom_name(Node) -> atom_to_list(atom_value(Node)). @@ -1897,6 +2013,8 @@ atom_name(Node) -> %% @see atom/1 %% @see string/1 +-spec atom_literal(syntaxTree()) -> string(). + atom_literal(Node) -> io_lib:write_atom(atom_value(Node)). @@ -1925,6 +2043,8 @@ atom_literal(Node) -> %% %% Elements = [erl_parse()] +-spec tuple([syntaxTree()]) -> syntaxTree(). + tuple(List) -> tree(tuple, List). @@ -1941,6 +2061,8 @@ revert_tuple(Node) -> %% %% @see tuple/1 +-spec tuple_elements(syntaxTree()) -> [syntaxTree()]. + tuple_elements(Node) -> case unwrap(Node) of {tuple, _, List} -> @@ -1962,6 +2084,8 @@ tuple_elements(Node) -> %% @see tuple/1 %% @see tuple_elements/1 +-spec tuple_size(syntaxTree()) -> non_neg_integer(). + tuple_size(Node) -> length(tuple_elements(Node)). @@ -1970,6 +2094,8 @@ tuple_size(Node) -> %% @spec list(List) -> syntaxTree() %% @equiv list(List, none) +-spec list([syntaxTree()]) -> syntaxTree(). + list(List) -> list(List, none). @@ -2020,7 +2146,7 @@ list(List) -> %% @see compact_list/1 %% @see get_attrs/1 --record(list, {prefix, suffix}). +-record(list, {prefix :: [syntaxTree()], suffix :: 'none' | syntaxTree()}). %% type(Node) = list %% data(Node) = #list{prefix :: Elements, suffix :: Tail} @@ -2038,9 +2164,11 @@ list(List) -> %% <Suffix>]' where the form of <Suffix> can depend on the %% structure of <Tail>; there is no fixed printed form. +-spec list([syntaxTree()], 'none' | syntaxTree()) -> syntaxTree(). + list([], none) -> nil(); -list(Elements, Tail) when Elements /= [] -> +list(Elements, Tail) when Elements =/= [] -> tree(list, #list{prefix = Elements, suffix = Tail}). revert_list(Node) -> @@ -2073,6 +2201,8 @@ revert_list(Node) -> %% %% {nil, Pos} +-spec nil() -> syntaxTree(). + nil() -> tree(nil). @@ -2092,6 +2222,8 @@ revert_nil(Node) -> %% %% @see list/2 +-spec list_prefix(syntaxTree()) -> [syntaxTree()]. + list_prefix(Node) -> case unwrap(Node) of {cons, _, Head, _} -> @@ -2102,7 +2234,7 @@ list_prefix(Node) -> %% ===================================================================== -%% @spec list_suffix(Node::syntaxTree()) -> none | syntaxTree() +%% @spec list_suffix(Node::syntaxTree()) -> none | syntaxTree() %% %% @doc Returns the suffix subtree of a <code>list</code> node, if one %% exists. If <code>Node</code> represents "<code>[<em>E1</em>, ..., @@ -2121,6 +2253,8 @@ list_prefix(Node) -> %% @see nil/0 %% @see compact_list/1 +-spec list_suffix(syntaxTree()) -> 'none' | syntaxTree(). + list_suffix(Node) -> case unwrap(Node) of {cons, _, _, Tail} -> @@ -2158,6 +2292,8 @@ list_suffix(Node) -> %% @see list_head/1 %% @see list_tail/1 +-spec cons(syntaxTree(), syntaxTree()) -> syntaxTree(). + cons(Head, Tail) -> case type(Tail) of list -> @@ -2181,6 +2317,8 @@ cons(Head, Tail) -> %% @see list_tail/1 %% @see cons/2 +-spec list_head(syntaxTree()) -> syntaxTree(). + list_head(Node) -> hd(list_prefix(Node)). @@ -2202,6 +2340,8 @@ list_head(Node) -> %% @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 @@ -2217,7 +2357,7 @@ list_tail(Node) -> %% ===================================================================== -%% @spec is_list_skeleton(syntaxTree()) -> bool() +%% @spec is_list_skeleton(syntaxTree()) -> boolean() %% %% @doc Returns <code>true</code> if <code>Node</code> has type %% <code>list</code> or <code>nil</code>, otherwise <code>false</code>. @@ -2225,6 +2365,8 @@ list_tail(Node) -> %% @see list/2 %% @see nil/0 +-spec is_list_skeleton(syntaxTree()) -> boolean(). + is_list_skeleton(Node) -> case type(Node) of list -> true; @@ -2234,7 +2376,7 @@ is_list_skeleton(Node) -> %% ===================================================================== -%% @spec is_proper_list(Node::syntaxTree()) -> bool() +%% @spec is_proper_list(Node::syntaxTree()) -> boolean() %% %% @doc Returns <code>true</code> if <code>Node</code> represents a %% proper list, and <code>false</code> otherwise. A proper list is a @@ -2255,6 +2397,8 @@ is_list_skeleton(Node) -> %% %% @see list/2 +-spec is_proper_list(syntaxTree()) -> boolean(). + is_proper_list(Node) -> case type(Node) of list -> @@ -2284,6 +2428,8 @@ is_proper_list(Node) -> %% @see list/2 %% @see is_proper_list/1 +-spec list_elements(syntaxTree()) -> [syntaxTree()]. + list_elements(Node) -> lists:reverse(list_elements(Node, [])). @@ -2319,6 +2465,8 @@ list_elements(Node, As) -> %% @see is_proper_list/1 %% @see list_elements/1 +-spec list_length(syntaxTree()) -> non_neg_integer(). + list_length(Node) -> list_length(Node, 0). @@ -2354,6 +2502,8 @@ list_length(Node, A) -> %% @see list/2 %% @see compact_list/1 +-spec normalize_list(syntaxTree()) -> syntaxTree(). + normalize_list(Node) -> case type(Node) of list -> @@ -2391,6 +2541,8 @@ normalize_list_1(Es, Tail) -> %% @see list/2 %% @see normalize_list/1 +-spec compact_list(syntaxTree()) -> syntaxTree(). + compact_list(Node) -> case type(Node) of list -> @@ -2447,6 +2599,8 @@ compact_list(Node) -> %% See `binary_field' for documentation on `erl_parse' binary %% fields (or "elements"). +-spec binary([syntaxTree()]) -> syntaxTree(). + binary(List) -> tree(binary, List). @@ -2464,6 +2618,8 @@ revert_binary(Node) -> %% @see binary/1 %% @see binary_field/2 +-spec binary_fields(syntaxTree()) -> [syntaxTree()]. + binary_fields(Node) -> case unwrap(Node) of {bin, _, List} -> @@ -2477,6 +2633,8 @@ binary_fields(Node) -> %% @spec binary_field(Body) -> syntaxTree() %% @equiv binary_field(Body, []) +-spec binary_field(syntaxTree()) -> syntaxTree(). + binary_field(Body) -> binary_field(Body, []). @@ -2498,6 +2656,9 @@ binary_field(Body) -> %% @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) -> @@ -2521,13 +2682,13 @@ binary_field(Body, Size, Types) -> %% @see binary_field_types/1 %% @see binary_field_size/1 --record(binary_field, {body, types}). +-record(binary_field, {body :: syntaxTree(), types :: [syntaxTree()]}). %% type(Node) = binary_field %% data(Node) = #binary_field{body :: Body, types :: Types} %% %% Body = syntaxTree() -%% Types = [Type] +%% Types = [syntaxTree()] %% %% `erl_parse' representation: %% @@ -2538,6 +2699,8 @@ binary_field(Body, Size, Types) -> %% 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}). @@ -2569,6 +2732,8 @@ revert_binary_field(Node) -> %% %% @see binary_field/2 +-spec binary_field_body(syntaxTree()) -> syntaxTree(). + binary_field_body(Node) -> case unwrap(Node) of {bin_element, _, Body, Size, _} -> @@ -2592,6 +2757,8 @@ binary_field_body(Node) -> %% %% @see binary_field/2 +-spec binary_field_types(syntaxTree()) -> [syntaxTree()]. + binary_field_types(Node) -> case unwrap(Node) of {bin_element, Pos, _, _, Types} -> @@ -2620,6 +2787,8 @@ binary_field_types(Node) -> %% @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, _} -> @@ -2649,13 +2818,15 @@ binary_field_size(Node) -> %% @see size_qualifier_body/1 %% @see size_qualifier_argument/1 --record(size_qualifier, {body, size}). +-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}). @@ -2669,6 +2840,8 @@ size_qualifier(Body, Size) -> %% %% @see size_qualifier/2 +-spec size_qualifier_body(syntaxTree()) -> syntaxTree(). + size_qualifier_body(Node) -> (data(Node))#size_qualifier.body. @@ -2681,6 +2854,8 @@ size_qualifier_body(Node) -> %% %% @see size_qualifier/2 +-spec size_qualifier_argument(syntaxTree()) -> syntaxTree(). + size_qualifier_argument(Node) -> (data(Node))#size_qualifier.size. @@ -2714,6 +2889,8 @@ size_qualifier_argument(Node) -> %% 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). @@ -2731,6 +2908,8 @@ revert_error_marker(Node) -> %% %% @see error_marker/1 +-spec error_marker_info(syntaxTree()) -> term(). + error_marker_info(Node) -> case unwrap(Node) of {error, Error} -> @@ -2769,6 +2948,8 @@ error_marker_info(Node) -> %% 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). @@ -2786,6 +2967,8 @@ revert_warning_marker(Node) -> %% %% @see warning_marker/1 +-spec warning_marker_info(syntaxTree()) -> term(). + warning_marker_info(Node) -> case unwrap(Node) of {warning, Error} -> @@ -2818,6 +3001,8 @@ warning_marker_info(Node) -> %% %% {eof, Pos} +-spec eof_marker() -> syntaxTree(). + eof_marker() -> tree(eof_marker). @@ -2830,6 +3015,8 @@ revert_eof_marker(Node) -> %% @spec attribute(Name) -> syntaxTree() %% @equiv attribute(Name, none) +-spec attribute(syntaxTree()) -> syntaxTree(). + attribute(Name) -> attribute(Name, none). @@ -2859,7 +3046,7 @@ attribute(Name) -> %% @see text/1 %% @see is_form/1 --record(attribute, {name, args}). +-record(attribute, {name :: syntaxTree(), args :: 'none' | [syntaxTree()]}). %% type(Node) = attribute %% data(Node) = #attribute{name :: Name, args :: Arguments} @@ -2922,6 +3109,8 @@ attribute(Name) -> %% %% Representing `-Name(Term).'. +-spec attribute(syntaxTree(), 'none' | [syntaxTree()]) -> syntaxTree(). + attribute(Name, Args) -> tree(attribute, #attribute{name = Name, args = Args}). @@ -3049,6 +3238,8 @@ revert_module_name(A) -> %% %% @see attribute/1 +-spec attribute_name(syntaxTree()) -> syntaxTree(). + attribute_name(Node) -> case unwrap(Node) of {attribute, Pos, Name, _} -> @@ -3071,6 +3262,8 @@ attribute_name(Node) -> %% %% @see attribute/1 +-spec attribute_arguments(syntaxTree()) -> none | [syntaxTree()]. + attribute_arguments(Node) -> case unwrap(Node) of {attribute, Pos, Name, Data} -> @@ -3141,13 +3334,15 @@ attribute_arguments(Node) -> %% @see arity_qualifier_body/1 %% @see arity_qualifier_argument/1 --record(arity_qualifier, {body, arity}). +-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}). @@ -3161,6 +3356,8 @@ arity_qualifier(Body, Arity) -> %% %% @see arity_qualifier/2 +-spec arity_qualifier_body(syntaxTree()) -> syntaxTree(). + arity_qualifier_body(Node) -> (data(Node))#arity_qualifier.body. @@ -3173,6 +3370,8 @@ arity_qualifier_body(Node) -> %% %% @see arity_qualifier/2 +-spec arity_qualifier_argument(syntaxTree()) -> syntaxTree(). + arity_qualifier_argument(Node) -> (data(Node))#arity_qualifier.arity. @@ -3187,7 +3386,7 @@ arity_qualifier_argument(Node) -> %% @see module_qualifier_argument/1 %% @see module_qualifier_body/1 --record(module_qualifier, {module, body}). +-record(module_qualifier, {module :: syntaxTree(), body :: syntaxTree()}). %% type(Node) = module_qualifier %% data(Node) = #module_qualifier{module :: Module, body :: Body} @@ -3200,6 +3399,8 @@ arity_qualifier_argument(Node) -> %% %% Module = Arg = erl_parse() +-spec module_qualifier(syntaxTree(), syntaxTree()) -> syntaxTree(). + module_qualifier(Module, Body) -> tree(module_qualifier, #module_qualifier{module = Module, body = Body}). @@ -3219,6 +3420,8 @@ revert_module_qualifier(Node) -> %% %% @see module_qualifier/2 +-spec module_qualifier_argument(syntaxTree()) -> syntaxTree(). + module_qualifier_argument(Node) -> case unwrap(Node) of {remote, _, Module, _} -> @@ -3236,6 +3439,8 @@ module_qualifier_argument(Node) -> %% %% @see module_qualifier/2 +-spec module_qualifier_body(syntaxTree()) -> syntaxTree(). + module_qualifier_body(Node) -> case unwrap(Node) of {remote, _, _, Body} -> @@ -3267,6 +3472,8 @@ module_qualifier_body(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). @@ -3283,6 +3490,8 @@ revert_qualified_name(Node) -> %% %% @see qualified_name/1 +-spec qualified_name_segments(syntaxTree()) -> [syntaxTree()]. + qualified_name_segments(Node) -> case unwrap(Node) of {record_field, _, _, _} = Node1 -> @@ -3314,6 +3523,9 @@ qualified_name_segments(Node) -> %% @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} @@ -3340,6 +3552,8 @@ qualified_name_segments(Node) -> %% 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}). @@ -3363,6 +3577,8 @@ revert_function(Node) -> %% %% @see function/2 +-spec function_name(syntaxTree()) -> syntaxTree(). + function_name(Node) -> case unwrap(Node) of {function, Pos, Name, _, _} -> @@ -3380,6 +3596,8 @@ function_name(Node) -> %% %% @see function/2 +-spec function_clauses(syntaxTree()) -> [syntaxTree()]. + function_clauses(Node) -> case unwrap(Node) of {function, _, _, _, Clauses} -> @@ -3406,6 +3624,8 @@ function_clauses(Node) -> %% @see clause/3 %% @see clause_patterns/1 +-spec function_arity(syntaxTree()) -> arity(). + function_arity(Node) -> %% Note that this never accesses the arity field of `erl_parse' %% function nodes. @@ -3416,6 +3636,10 @@ function_arity(Node) -> %% @spec clause(Guard, Body) -> syntaxTree() %% @equiv clause([], Guard, Body) +-type guard() :: 'none' | syntaxTree() | [syntaxTree()] | [[syntaxTree()]]. + +-spec clause(guard(), [syntaxTree()]) -> syntaxTree(). + clause(Guard, Body) -> clause([], Guard, Body). @@ -3455,7 +3679,9 @@ clause(Guard, Body) -> %% @see clause_guard/1 %% @see clause_body/1 --record(clause, {patterns, guard, body}). +-record(clause, {patterns :: [syntaxTree()], + guard :: guard(), + body :: [syntaxTree()]}). %% type(Node) = clause %% data(Node) = #clause{patterns :: Patterns, guard :: Guard, @@ -3482,6 +3708,8 @@ clause(Guard, Body) -> %% versions, `Guard' was simply a list `[E1, ..., En]' of parse %% trees, which is equivalent to the new form `[[E1, ..., En]]'. +-spec clause([syntaxTree()], guard(), [syntaxTree()]) -> syntaxTree(). + clause(Patterns, Guard, Body) -> Guard1 = case Guard of [] -> @@ -3551,7 +3779,7 @@ fold_try_clause({clause, Pos, [P], Guard, Body}) -> unfold_try_clauses(Cs) -> [unfold_try_clause(C) || C <- Cs]. -unfold_try_clause({clause, Pos, [{tuple, _, [{atom,_,throw}, V, _]}], +unfold_try_clause({clause, Pos, [{tuple, _, [{atom, _, throw}, V, _]}], Guard, Body}) -> {clause, Pos, [V], Guard, Body}; unfold_try_clause({clause, Pos, [{tuple, _, [C, V, _]}], @@ -3567,6 +3795,8 @@ unfold_try_clause({clause, Pos, [{tuple, _, [C, V, _]}], %% %% @see clause/3 +-spec clause_patterns(syntaxTree()) -> [syntaxTree()]. + clause_patterns(Node) -> case unwrap(Node) of {clause, _, Patterns, _, _} -> @@ -3587,6 +3817,8 @@ clause_patterns(Node) -> %% %% @see clause/3 +-spec clause_guard(syntaxTree()) -> 'none' | syntaxTree(). + clause_guard(Node) -> case unwrap(Node) of {clause, _, _, Guard, _} -> @@ -3610,6 +3842,8 @@ clause_guard(Node) -> %% %% @see clause/3 +-spec clause_body(syntaxTree()) -> [syntaxTree()]. + clause_body(Node) -> case unwrap(Node) of {clause, _, _, _, Body} -> @@ -3632,6 +3866,8 @@ clause_body(Node) -> %% type(Node) = disjunction %% data(Node) = [syntaxTree()] +-spec disjunction([syntaxTree()]) -> syntaxTree(). + disjunction(Tests) -> tree(disjunction, Tests). @@ -3644,6 +3880,8 @@ disjunction(Tests) -> %% %% @see disjunction/1 +-spec disjunction_body(syntaxTree()) -> [syntaxTree()]. + disjunction_body(Node) -> data(Node). @@ -3661,6 +3899,8 @@ disjunction_body(Node) -> %% type(Node) = conjunction %% data(Node) = [syntaxTree()] +-spec conjunction([syntaxTree()]) -> syntaxTree(). + conjunction(Tests) -> tree(conjunction, Tests). @@ -3673,6 +3913,8 @@ conjunction(Tests) -> %% %% @see conjunction/1 +-spec conjunction_body(syntaxTree()) -> [syntaxTree()]. + conjunction_body(Node) -> data(Node). @@ -3694,6 +3936,8 @@ conjunction_body(Node) -> %% %% Expr = erl_parse() +-spec catch_expr(syntaxTree()) -> syntaxTree(). + catch_expr(Expr) -> tree(catch_expr, Expr). @@ -3710,6 +3954,8 @@ revert_catch_expr(Node) -> %% %% @see catch_expr/1 +-spec catch_expr_body(syntaxTree()) -> syntaxTree(). + catch_expr_body(Node) -> case unwrap(Node) of {'catch', _, Expr} -> @@ -3729,7 +3975,7 @@ catch_expr_body(Node) -> %% @see match_expr_pattern/1 %% @see match_expr_body/1 --record(match_expr, {pattern, body}). +-record(match_expr, {pattern :: syntaxTree(), body :: syntaxTree()}). %% type(Node) = match_expr %% data(Node) = #match_expr{pattern :: Pattern, body :: Body} @@ -3742,6 +3988,8 @@ catch_expr_body(Node) -> %% %% Pattern = Body = erl_parse() +-spec match_expr(syntaxTree(), syntaxTree()) -> syntaxTree(). + match_expr(Pattern, Body) -> tree(match_expr, #match_expr{pattern = Pattern, body = Body}). @@ -3759,6 +4007,8 @@ revert_match_expr(Node) -> %% %% @see match_expr/2 +-spec match_expr_pattern(syntaxTree()) -> syntaxTree(). + match_expr_pattern(Node) -> case unwrap(Node) of {match, _, Pattern, _} -> @@ -3775,6 +4025,8 @@ match_expr_pattern(Node) -> %% %% @see match_expr/2 +-spec match_expr_body(syntaxTree()) -> syntaxTree(). + match_expr_body(Node) -> case unwrap(Node) of {match, _, _, Body} -> @@ -3802,6 +4054,8 @@ match_expr_body(Node) -> %% type(Node) = operator %% data(Node) = atom() +-spec operator(atom() | string()) -> syntaxTree(). + operator(Name) when is_atom(Name) -> tree(operator, Name); operator(Name) -> @@ -3816,6 +4070,8 @@ operator(Name) -> %% %% @see operator/1 +-spec operator_name(syntaxTree()) -> atom(). + operator_name(Node) -> data(Node). @@ -3829,6 +4085,8 @@ operator_name(Node) -> %% %% @see operator/1 +-spec operator_literal(syntaxTree()) -> string(). + operator_literal(Node) -> atom_to_list(operator_name(Node)). @@ -3846,7 +4104,9 @@ operator_literal(Node) -> %% @see infix_expr_operator/1 %% @see prefix_expr/2 --record(infix_expr, {operator, left, right}). +-record(infix_expr, {operator :: syntaxTree(), + left :: syntaxTree(), + right :: syntaxTree()}). %% type(Node) = infix_expr %% data(Node) = #infix_expr{left :: Left, operator :: Operator, @@ -3861,6 +4121,8 @@ operator_literal(Node) -> %% 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}). @@ -3888,6 +4150,8 @@ revert_infix_expr(Node) -> %% %% @see infix_expr/3 +-spec infix_expr_left(syntaxTree()) -> syntaxTree(). + infix_expr_left(Node) -> case unwrap(Node) of {op, _, _, Left, _} -> @@ -3905,6 +4169,8 @@ infix_expr_left(Node) -> %% %% @see infix_expr/3 +-spec infix_expr_operator(syntaxTree()) -> syntaxTree(). + infix_expr_operator(Node) -> case unwrap(Node) of {op, Pos, Operator, _, _} -> @@ -3922,6 +4188,8 @@ infix_expr_operator(Node) -> %% %% @see infix_expr/3 +-spec infix_expr_right(syntaxTree()) -> syntaxTree(). + infix_expr_right(Node) -> case unwrap(Node) of {op, _, _, _, Right} -> @@ -3942,7 +4210,7 @@ infix_expr_right(Node) -> %% @see prefix_expr_operator/1 %% @see infix_expr/3 --record(prefix_expr, {operator, argument}). +-record(prefix_expr, {operator :: syntaxTree(), argument :: syntaxTree()}). %% type(Node) = prefix_expr %% data(Node) = #prefix_expr{operator :: Operator, @@ -3957,6 +4225,8 @@ infix_expr_right(Node) -> %% Operator = atom() %% Argument = erl_parse() +-spec prefix_expr(syntaxTree(), syntaxTree()) -> syntaxTree(). + prefix_expr(Operator, Argument) -> tree(prefix_expr, #prefix_expr{operator = Operator, argument = Argument}). @@ -3983,6 +4253,8 @@ revert_prefix_expr(Node) -> %% %% @see prefix_expr/2 +-spec prefix_expr_operator(syntaxTree()) -> syntaxTree(). + prefix_expr_operator(Node) -> case unwrap(Node) of {op, Pos, Operator, _} -> @@ -4000,6 +4272,8 @@ prefix_expr_operator(Node) -> %% %% @see prefix_expr/2 +-spec prefix_expr_argument(syntaxTree()) -> syntaxTree(). + prefix_expr_argument(Node) -> case unwrap(Node) of {op, _, _, Argument} -> @@ -4013,6 +4287,8 @@ prefix_expr_argument(Node) -> %% @spec record_field(Name) -> syntaxTree() %% @equiv record_field(Name, none) +-spec record_field(syntaxTree()) -> syntaxTree(). + record_field(Name) -> record_field(Name, none). @@ -4030,13 +4306,15 @@ record_field(Name) -> %% @see record_field_value/1 %% @see record_expr/3 --record(record_field, {name, value}). +-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}). @@ -4048,6 +4326,8 @@ record_field(Name, Value) -> %% %% @see record_field/2 +-spec record_field_name(syntaxTree()) -> syntaxTree(). + record_field_name(Node) -> (data(Node))#record_field.name. @@ -4064,6 +4344,8 @@ record_field_name(Node) -> %% %% @see record_field/2 +-spec record_field_value(syntaxTree()) -> 'none' | syntaxTree(). + record_field_value(Node) -> (data(Node))#record_field.value. @@ -4083,7 +4365,7 @@ record_field_value(Node) -> %% @see record_index_expr_field/1 %% @see record_expr/3 --record(record_index_expr, {type, field}). +-record(record_index_expr, {type :: syntaxTree(), field :: syntaxTree()}). %% type(Node) = record_index_expr %% data(Node) = #record_index_expr{type :: Type, field :: Field} @@ -4097,6 +4379,8 @@ record_field_value(Node) -> %% Type = atom() %% Field = erl_parse() +-spec record_index_expr(syntaxTree(), syntaxTree()) -> syntaxTree(). + record_index_expr(Type, Field) -> tree(record_index_expr, #record_index_expr{type = Type, field = Field}). @@ -4121,6 +4405,8 @@ revert_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, _} -> @@ -4138,6 +4424,8 @@ record_index_expr_type(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} -> @@ -4151,6 +4439,8 @@ record_index_expr_field(Node) -> %% @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). @@ -4175,7 +4465,9 @@ record_access(Argument, Field) -> %% @see record_expr/3 %% @see query_expr/1 --record(record_access, {argument, type, field}). +-record(record_access, {argument :: syntaxTree(), + type :: 'none' | syntaxTree(), + field :: syntaxTree()}). %% type(Node) = record_access %% data(Node) = #record_access{argument :: Argument, type :: Type, @@ -4192,6 +4484,9 @@ record_access(Argument, Field) -> %% Argument = Field = erl_parse() %% Type = atom() +-spec record_access(syntaxTree(), 'none' | syntaxTree(), syntaxTree()) -> + syntaxTree(). + record_access(Argument, Type, Field) -> tree(record_access,#record_access{argument = Argument, type = Type, @@ -4223,6 +4518,8 @@ revert_record_access(Node) -> %% %% @see record_access/3 +-spec record_access_argument(syntaxTree()) -> syntaxTree(). + record_access_argument(Node) -> case unwrap(Node) of {record_field, _, Argument, _} -> @@ -4246,6 +4543,8 @@ record_access_argument(Node) -> %% %% @see record_access/3 +-spec record_access_type(syntaxTree()) -> 'none' | syntaxTree(). + record_access_type(Node) -> case unwrap(Node) of {record_field, _, _, _} -> @@ -4265,6 +4564,8 @@ record_access_type(Node) -> %% %% @see record_access/3 +-spec record_access_field(syntaxTree()) -> syntaxTree(). + record_access_field(Node) -> case unwrap(Node) of {record_field, _, _, Field} -> @@ -4280,6 +4581,8 @@ record_access_field(Node) -> %% @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). @@ -4305,7 +4608,9 @@ record_expr(Type, Fields) -> %% @see record_index_expr/2 %% @see record_access/3 --record(record_expr, {argument, type, fields}). +-record(record_expr, {argument :: 'none' | syntaxTree(), + type :: syntaxTree(), + fields :: [syntaxTree()]}). %% type(Node) = record_expr %% data(Node) = #record_expr{argument :: Argument, type :: Type, @@ -4327,6 +4632,9 @@ record_expr(Type, Fields) -> %% | {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}). @@ -4363,6 +4671,8 @@ revert_record_expr(Node) -> %% %% @see record_expr/3 +-spec record_expr_argument(syntaxTree()) -> 'none' | syntaxTree(). + record_expr_argument(Node) -> case unwrap(Node) of {record, _, _, _} -> @@ -4381,6 +4691,8 @@ record_expr_argument(Node) -> %% %% @see record_expr/3 +-spec record_expr_type(syntaxTree()) -> syntaxTree(). + record_expr_type(Node) -> case unwrap(Node) of {record, Pos, Type, _} -> @@ -4400,6 +4712,8 @@ record_expr_type(Node) -> %% %% @see record_expr/3 +-spec record_expr_fields(syntaxTree()) -> [syntaxTree()]. + record_expr_fields(Node) -> case unwrap(Node) of {record, _, _, Fields} -> @@ -4427,6 +4741,9 @@ record_expr_fields(Node) -> %% @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) -> @@ -4446,7 +4763,7 @@ application(Module, Name, Arguments) -> %% @see application_arguments/1 %% @see application/3 --record(application, {operator, arguments}). +-record(application, {operator :: syntaxTree(), arguments :: [syntaxTree()]}). %% type(Node) = application %% data(Node) = #application{operator :: Operator, @@ -4462,6 +4779,8 @@ application(Module, Name, Arguments) -> %% Operator = erl_parse() %% Arguments = [erl_parse()] +-spec application(syntaxTree(), [syntaxTree()]) -> syntaxTree(). + application(Operator, Arguments) -> tree(application, #application{operator = Operator, arguments = Arguments}). @@ -4486,6 +4805,8 @@ revert_application(Node) -> %% @see application/2 %% @see module_qualifier/2 +-spec application_operator(syntaxTree()) -> syntaxTree(). + application_operator(Node) -> case unwrap(Node) of {call, _, Operator, _} -> @@ -4503,6 +4824,8 @@ application_operator(Node) -> %% %% @see application/2 +-spec application_arguments(syntaxTree()) -> [syntaxTree()]. + application_arguments(Node) -> case unwrap(Node) of {call, _, _, Arguments} -> @@ -4524,7 +4847,7 @@ application_arguments(Node) -> %% @see list_comp_body/1 %% @see generator/2 --record(list_comp, {template, body}). +-record(list_comp, {template :: syntaxTree(), body :: [syntaxTree()]}). %% type(Node) = list_comp %% data(Node) = #list_comp{template :: Template, body :: Body} @@ -4539,6 +4862,8 @@ application_arguments(Node) -> %% 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}). @@ -4556,6 +4881,8 @@ revert_list_comp(Node) -> %% %% @see list_comp/2 +-spec list_comp_template(syntaxTree()) -> syntaxTree(). + list_comp_template(Node) -> case unwrap(Node) of {lc, _, Template, _} -> @@ -4573,6 +4900,8 @@ list_comp_template(Node) -> %% %% @see list_comp/2 +-spec list_comp_body(syntaxTree()) -> [syntaxTree()]. + list_comp_body(Node) -> case unwrap(Node) of {lc, _, _, Body} -> @@ -4593,7 +4922,7 @@ list_comp_body(Node) -> %% @see binary_comp_body/1 %% @see generator/2 --record(binary_comp, {template, body}). +-record(binary_comp, {template :: syntaxTree(), body :: [syntaxTree()]}). %% type(Node) = binary_comp %% data(Node) = #binary_comp{template :: Template, body :: Body} @@ -4608,6 +4937,8 @@ list_comp_body(Node) -> %% 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}). @@ -4625,6 +4956,8 @@ revert_binary_comp(Node) -> %% %% @see binary_comp/2 +-spec binary_comp_template(syntaxTree()) -> syntaxTree(). + binary_comp_template(Node) -> case unwrap(Node) of {bc, _, Template, _} -> @@ -4642,6 +4975,8 @@ binary_comp_template(Node) -> %% %% @see binary_comp/2 +-spec binary_comp_body(syntaxTree()) -> [syntaxTree()]. + binary_comp_body(Node) -> case unwrap(Node) of {bc, _, _, Body} -> @@ -4670,6 +5005,8 @@ binary_comp_body(Node) -> %% %% Body = erl_parse() +-spec query_expr(syntaxTree()) -> syntaxTree(). + query_expr(Body) -> tree(query_expr, Body). @@ -4686,6 +5023,8 @@ revert_query_expr(Node) -> %% %% @see query_expr/1 +-spec query_expr_body(syntaxTree()) -> syntaxTree(). + query_expr_body(Node) -> case unwrap(Node) of {'query', _, Body} -> @@ -4715,7 +5054,7 @@ query_expr_body(Node) -> %% @see is_form/1 %% @see function/2 --record(rule, {name, clauses}). +-record(rule, {name :: syntaxTree(), clauses :: [syntaxTree()]}). %% type(Node) = rule %% data(Node) = #rule{name :: Name, clauses :: Clauses} @@ -4738,6 +5077,8 @@ query_expr_body(Node) -> %% 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}). @@ -4761,6 +5102,8 @@ revert_rule(Node) -> %% %% @see rule/2 +-spec rule_name(syntaxTree()) -> syntaxTree(). + rule_name(Node) -> case unwrap(Node) of {rule, Pos, Name, _, _} -> @@ -4776,6 +5119,8 @@ rule_name(Node) -> %% %% @see rule/2 +-spec rule_clauses(syntaxTree()) -> [syntaxTree()]. + rule_clauses(Node) -> case unwrap(Node) of {rule, _, _, _, Clauses} -> @@ -4801,6 +5146,8 @@ rule_clauses(Node) -> %% @see clause/3 %% @see clause_patterns/1 +-spec rule_arity(syntaxTree()) -> arity(). + rule_arity(Node) -> %% Note that this never accesses the arity field of %% `erl_parse' rule nodes. @@ -4819,7 +5166,7 @@ rule_arity(Node) -> %% @see list_comp/2 %% @see binary_comp/2 --record(generator, {pattern, body}). +-record(generator, {pattern :: syntaxTree(), body :: syntaxTree()}). %% type(Node) = generator %% data(Node) = #generator{pattern :: Pattern, body :: Body} @@ -4832,6 +5179,8 @@ rule_arity(Node) -> %% %% Pattern = Body = erl_parse() +-spec generator(syntaxTree(), syntaxTree()) -> syntaxTree(). + generator(Pattern, Body) -> tree(generator, #generator{pattern = Pattern, body = Body}). @@ -4849,6 +5198,8 @@ revert_generator(Node) -> %% %% @see generator/2 +-spec generator_pattern(syntaxTree()) -> syntaxTree(). + generator_pattern(Node) -> case unwrap(Node) of {generate, _, Pattern, _} -> @@ -4865,6 +5216,8 @@ generator_pattern(Node) -> %% %% @see generator/2 +-spec generator_body(syntaxTree()) -> syntaxTree(). + generator_body(Node) -> case unwrap(Node) of {generate, _, _, Body} -> @@ -4886,7 +5239,7 @@ generator_body(Node) -> %% @see list_comp/2 %% @see binary_comp/2 --record(binary_generator, {pattern, body}). +-record(binary_generator, {pattern :: syntaxTree(), body :: syntaxTree()}). %% type(Node) = binary_generator %% data(Node) = #binary_generator{pattern :: Pattern, body :: Body} @@ -4899,6 +5252,8 @@ generator_body(Node) -> %% %% Pattern = Body = erl_parse() +-spec binary_generator(syntaxTree(), syntaxTree()) -> syntaxTree(). + binary_generator(Pattern, Body) -> tree(binary_generator, #binary_generator{pattern = Pattern, body = Body}). @@ -4916,6 +5271,8 @@ revert_binary_generator(Node) -> %% %% @see binary_generator/2 +-spec binary_generator_pattern(syntaxTree()) -> syntaxTree(). + binary_generator_pattern(Node) -> case unwrap(Node) of {b_generate, _, Pattern, _} -> @@ -4932,6 +5289,8 @@ binary_generator_pattern(Node) -> %% %% @see binary_generator/2 +-spec binary_generator_body(syntaxTree()) -> syntaxTree(). + binary_generator_body(Node) -> case unwrap(Node) of {b_generate, _, _, Body} -> @@ -4940,6 +5299,7 @@ binary_generator_body(Node) -> (data(Node1))#binary_generator.body end. + %% ===================================================================== %% @spec block_expr(Body::[syntaxTree()]) -> syntaxTree() %% @@ -4960,6 +5320,8 @@ binary_generator_body(Node) -> %% %% Body = [erl_parse()] \ [] +-spec block_expr(Body::[syntaxTree()]) -> syntaxTree(). + block_expr(Body) -> tree(block_expr, Body). @@ -4977,6 +5339,8 @@ revert_block_expr(Node) -> %% %% @see block_expr/1 +-spec block_expr_body(syntaxTree()) -> [syntaxTree()]. + block_expr_body(Node) -> case unwrap(Node) of {block, _, Body} -> @@ -5015,6 +5379,8 @@ block_expr_body(Node) -> %% %% See `clause' for documentation on `erl_parse' clauses. +-spec if_expr([syntaxTree()]) -> syntaxTree(). + if_expr(Clauses) -> tree(if_expr, Clauses). @@ -5032,6 +5398,8 @@ revert_if_expr(Node) -> %% %% @see if_expr/1 +-spec if_expr_clauses(syntaxTree()) -> [syntaxTree()]. + if_expr_clauses(Node) -> case unwrap(Node) of {'if', _, Clauses} -> @@ -5059,7 +5427,7 @@ if_expr_clauses(Node) -> %% @see if_expr/1 %% @see cond_expr/1 --record(case_expr, {argument, clauses}). +-record(case_expr, {argument :: syntaxTree(), clauses :: [syntaxTree()]}). %% type(Node) = case_expr %% data(Node) = #case_expr{argument :: Argument, @@ -5078,6 +5446,8 @@ if_expr_clauses(Node) -> %% %% 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}). @@ -5096,6 +5466,8 @@ revert_case_expr(Node) -> %% %% @see case_expr/2 +-spec case_expr_argument(syntaxTree()) -> syntaxTree(). + case_expr_argument(Node) -> case unwrap(Node) of {'case', _, Argument, _} -> @@ -5113,6 +5485,8 @@ case_expr_argument(Node) -> %% %% @see case_expr/2 +-spec case_expr_clauses(syntaxTree()) -> [syntaxTree()]. + case_expr_clauses(Node) -> case unwrap(Node) of {'case', _, _, Clauses} -> @@ -5151,6 +5525,8 @@ case_expr_clauses(Node) -> %% %% See `clause' for documentation on `erl_parse' clauses. +-spec cond_expr([syntaxTree()]) -> syntaxTree(). + cond_expr(Clauses) -> tree(cond_expr, Clauses). @@ -5168,6 +5544,8 @@ revert_cond_expr(Node) -> %% %% @see cond_expr/1 +-spec cond_expr_clauses(syntaxTree()) -> [syntaxTree()]. + cond_expr_clauses(Node) -> case unwrap(Node) of {'cond', _, Clauses} -> @@ -5181,6 +5559,8 @@ cond_expr_clauses(Node) -> %% @spec receive_expr(Clauses) -> syntaxTree() %% @equiv receive_expr(Clauses, none, []) +-spec receive_expr([syntaxTree()]) -> syntaxTree(). + receive_expr(Clauses) -> receive_expr(Clauses, none, []). @@ -5213,7 +5593,9 @@ receive_expr(Clauses) -> %% @see clause/3 %% @see case_expr/2 --record(receive_expr, {clauses, timeout, action}). +-record(receive_expr, {clauses :: [syntaxTree()], + timeout :: 'none' | syntaxTree(), + action :: [syntaxTree()]}). %% type(Node) = receive_expr %% data(Node) = #receive_expr{clauses :: Clauses, @@ -5236,6 +5618,9 @@ receive_expr(Clauses) -> %% %% 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 @@ -5271,6 +5656,8 @@ revert_receive_expr(Node) -> %% %% @see receive_expr/3 +-spec receive_expr_clauses(syntaxTree()) -> [syntaxTree()]. + receive_expr_clauses(Node) -> case unwrap(Node) of {'receive', _, Clauses} -> @@ -5295,6 +5682,8 @@ receive_expr_clauses(Node) -> %% %% @see receive_expr/3 +-spec receive_expr_timeout(syntaxTree()) -> 'none' | syntaxTree(). + receive_expr_timeout(Node) -> case unwrap(Node) of {'receive', _, _} -> @@ -5316,6 +5705,8 @@ receive_expr_timeout(Node) -> %% %% @see receive_expr/3 +-spec receive_expr_action(syntaxTree()) -> [syntaxTree()]. + receive_expr_action(Node) -> case unwrap(Node) of {'receive', _, _} -> @@ -5332,6 +5723,8 @@ receive_expr_action(Node) -> %% syntaxTree() %% @equiv try_expr(Body, [], Handlers) +-spec try_expr([syntaxTree()], [syntaxTree()]) -> syntaxTree(). + try_expr(Body, Handlers) -> try_expr(Body, [], Handlers). @@ -5341,6 +5734,8 @@ try_expr(Body, Handlers) -> %% 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, []). @@ -5350,6 +5745,8 @@ try_expr(Body, Clauses, Handlers) -> %% syntaxTree() %% @equiv try_expr(Body, [], [], After) +-spec try_after_expr([syntaxTree()], [syntaxTree()]) -> syntaxTree(). + try_after_expr(Body, After) -> try_expr(Body, [], [], After). @@ -5391,7 +5788,10 @@ try_after_expr(Body, After) -> %% @see class_qualifier/2 %% @see case_expr/2 --record(try_expr, {body, clauses, handlers, 'after'}). +-record(try_expr, {body :: [syntaxTree()], + clauses :: [syntaxTree()], + handlers :: [syntaxTree()], + 'after' :: [syntaxTree()]}). %% type(Node) = try_expr %% data(Node) = #try_expr{body :: Body, @@ -5414,6 +5814,9 @@ try_after_expr(Body, After) -> %% %% 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, @@ -5437,6 +5840,8 @@ revert_try_expr(Node) -> %% %% @see try_expr/4 +-spec try_expr_body(syntaxTree()) -> [syntaxTree()]. + try_expr_body(Node) -> case unwrap(Node) of {'try', _, Body, _, _, _} -> @@ -5456,6 +5861,8 @@ try_expr_body(Node) -> %% %% @see try_expr/4 +-spec try_expr_clauses(syntaxTree()) -> [syntaxTree()]. + try_expr_clauses(Node) -> case unwrap(Node) of {'try', _, _, Clauses, _, _} -> @@ -5473,6 +5880,8 @@ try_expr_clauses(Node) -> %% %% @see try_expr/4 +-spec try_expr_handlers(syntaxTree()) -> [syntaxTree()]. + try_expr_handlers(Node) -> case unwrap(Node) of {'try', _, _, _, Handlers, _} -> @@ -5490,6 +5899,8 @@ try_expr_handlers(Node) -> %% %% @see try_expr/4 +-spec try_expr_after(syntaxTree()) -> [syntaxTree()]. + try_expr_after(Node) -> case unwrap(Node) of {'try', _, _, _, _, After} -> @@ -5510,13 +5921,15 @@ try_expr_after(Node) -> %% @see class_qualifier_body/1 %% @see try_expr/4 --record(class_qualifier, {class, body}). +-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}). @@ -5530,6 +5943,8 @@ class_qualifier(Class, Body) -> %% %% @see class_qualifier/2 +-spec class_qualifier_argument(syntaxTree()) -> syntaxTree(). + class_qualifier_argument(Node) -> (data(Node))#class_qualifier.class. @@ -5541,6 +5956,8 @@ class_qualifier_argument(Node) -> %% %% @see class_qualifier/2 +-spec class_qualifier_body(syntaxTree()) -> syntaxTree(). + class_qualifier_body(Node) -> (data(Node))#class_qualifier.body. @@ -5559,6 +5976,8 @@ class_qualifier_body(Node) -> %% @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) -> @@ -5580,6 +5999,9 @@ implicit_fun(Name, Arity) -> %% @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) -> @@ -5610,7 +6032,9 @@ implicit_fun(Module, Name, Arity) -> %% %% Module = atom() %% Name = atom() -%% Arity = integer() +%% Arity = arity() + +-spec implicit_fun(syntaxTree()) -> syntaxTree(). implicit_fun(Name) -> tree(implicit_fun, Name). @@ -5661,6 +6085,8 @@ revert_implicit_fun(Node) -> %% @see arity_qualifier/2 %% @see module_qualifier/2 +-spec implicit_fun_name(syntaxTree()) -> syntaxTree(). + implicit_fun_name(Node) -> case unwrap(Node) of {'fun', Pos, {function, Atom, Arity}} -> @@ -5707,6 +6133,8 @@ implicit_fun_name(Node) -> %% %% See `clause' for documentation on `erl_parse' clauses. +-spec fun_expr([syntaxTree()]) -> syntaxTree(). + fun_expr(Clauses) -> tree(fun_expr, Clauses). @@ -5724,6 +6152,8 @@ revert_fun_expr(Node) -> %% %% @see fun_expr/1 +-spec fun_expr_clauses(syntaxTree()) -> [syntaxTree()]. + fun_expr_clauses(Node) -> case unwrap(Node) of {'fun', _, {clauses, Clauses}} -> @@ -5750,6 +6180,8 @@ fun_expr_clauses(Node) -> %% @see clause/3 %% @see clause_patterns/1 +-spec fun_expr_arity(syntaxTree()) -> arity(). + fun_expr_arity(Node) -> length(clause_patterns(hd(fun_expr_clauses(Node)))). @@ -5766,6 +6198,8 @@ fun_expr_arity(Node) -> %% type(Node) = parentheses %% data(Node) = syntaxTree() +-spec parentheses(syntaxTree()) -> syntaxTree(). + parentheses(Expr) -> tree(parentheses, Expr). @@ -5780,6 +6214,8 @@ revert_parentheses(Node) -> %% %% @see parentheses/1 +-spec parentheses_body(syntaxTree()) -> syntaxTree(). + parentheses_body(Node) -> data(Node). @@ -5788,6 +6224,8 @@ parentheses_body(Node) -> %% @spec macro(Name) -> syntaxTree() %% @equiv macro(Name, none) +-spec macro(syntaxTree()) -> syntaxTree(). + macro(Name) -> macro(Name, none). @@ -5818,7 +6256,7 @@ macro(Name) -> %% @see macro/1 %% @see text/1 --record(macro, {name, arguments}). +-record(macro, {name :: syntaxTree(), arguments :: 'none' | [syntaxTree()]}). %% type(Node) = macro %% data(Node) = #macro{name :: Name, arguments :: Arguments} @@ -5826,6 +6264,8 @@ macro(Name) -> %% Name = syntaxTree() %% Arguments = none | [syntaxTree()] +-spec macro(syntaxTree(), 'none' | [syntaxTree()]) -> syntaxTree(). + macro(Name, Arguments) -> tree(macro, #macro{name = Name, arguments = Arguments}). @@ -5837,6 +6277,8 @@ macro(Name, Arguments) -> %% %% @see macro/2 +-spec macro_name(syntaxTree()) -> syntaxTree(). + macro_name(Node) -> (data(Node))#macro.name. @@ -5853,6 +6295,8 @@ macro_name(Node) -> %% %% @see macro/2 +-spec macro_arguments(syntaxTree()) -> 'none' | [syntaxTree()]. + macro_arguments(Node) -> (data(Node))#macro.arguments. @@ -5871,6 +6315,8 @@ macro_arguments(Node) -> %% @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 -> @@ -5932,6 +6378,8 @@ abstract_tail(H, T) -> %% @see is_literal/1 %% @see char/1 +-spec concrete(syntaxTree()) -> term(). + concrete(Node) -> case type(Node) of atom -> @@ -5978,7 +6426,7 @@ concrete_list([]) -> %% ===================================================================== -%% @spec is_literal(Node::syntaxTree()) -> bool() +%% @spec is_literal(Node::syntaxTree()) -> boolean() %% %% @doc Returns <code>true</code> if <code>Node</code> represents a %% literal term, otherwise <code>false</code>. This function returns @@ -5988,6 +6436,8 @@ concrete_list([]) -> %% @see abstract/1 %% @see concrete/1 +-spec is_literal(syntaxTree()) -> boolean(). + is_literal(T) -> case type(T) of atom -> @@ -6031,6 +6481,8 @@ is_literal(T) -> %% @see revert_forms/1 %% @see //stdlib/erl_parse +-spec revert(syntaxTree()) -> syntaxTree(). + revert(Node) -> case is_tree(Node) of false -> @@ -6172,6 +6624,10 @@ revert_root(Node) -> %% @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) -> @@ -6270,6 +6726,8 @@ revert_forms_1([]) -> %% @see is_leaf/1 %% @see copy_attrs/2 +-spec subtrees(syntaxTree()) -> [[syntaxTree()]]. + subtrees(T) -> case is_leaf(T) of true -> @@ -6442,6 +6900,8 @@ subtrees(T) -> %% @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)). @@ -6471,6 +6931,8 @@ update_tree(Node, Groups) -> %% @see is_leaf/1 %% @see copy_attrs/2 +-spec make_tree(atom(), [[syntaxTree()]]) -> syntaxTree(). + make_tree(application, [[F], A]) -> application(F, A); make_tree(arity_qualifier, [[N], [A]]) -> arity_qualifier(N, A); make_tree(attribute, [[N]]) -> attribute(N); @@ -6567,6 +7029,8 @@ make_tree(tuple, [E]) -> tuple(E). %% @see type/1 %% @see get_ann/1 +-spec meta(syntaxTree()) -> syntaxTree(). + meta(T) -> %% First of all we check for metavariables: case type(T) of @@ -6693,6 +7157,8 @@ meta_call(F, As) -> %% @spec tree(Type) -> syntaxTree() %% @equiv tree(Type, []) +-spec tree(atom()) -> syntaxTree(). + tree(Type) -> tree(Type, []). @@ -6727,12 +7193,14 @@ tree(Type) -> %% @see data/1 %% @see type/1 +-spec tree(atom(), term()) -> syntaxTree(). + tree(Type, Data) -> #tree{type = Type, data = Data}. %% ===================================================================== -%% @spec is_tree(Tree::syntaxTree()) -> bool() +%% @spec is_tree(Tree::syntaxTree()) -> boolean() %% %% @doc <em>For special purposes only</em>. Returns <code>true</code> if %% <code>Tree</code> is an abstract syntax tree and <code>false</code> @@ -6743,6 +7211,8 @@ tree(Type, Data) -> %% %% @see tree/2 +-spec is_tree(syntaxTree()) -> boolean(). + is_tree(#tree{}) -> true; is_tree(_) -> @@ -6759,6 +7229,8 @@ is_tree(_) -> %% %% @see tree/2 +-spec data(syntaxTree()) -> term(). + data(#tree{data = D}) -> D; data(T) -> erlang:error({badarg, T}). @@ -6788,6 +7260,8 @@ data(T) -> erlang:error({badarg, T}). %% trees. <em>Attaching a wrapper onto another wrapper structure is an %% error</em>.</p> +%%-spec wrap(erl_parse:parse_tree()) -> syntaxTree(). + wrap(Node) -> %% We assume that Node is an old-school `erl_parse' tree. #wrapper{type = type(Node), attr = #attr{pos = get_pos(Node)}, @@ -6802,17 +7276,21 @@ wrap(Node) -> %% <code>erl_parse</code> tree; otherwise it returns <code>Node</code> %% 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()) -> bool() +%% @spec is_wrapper(Term::term()) -> boolean() %% %% @doc Returns <code>true</code> if the argument is a wrapper %% structure, otherwise <code>false</code>. -ifndef(NO_UNUSED). +-spec is_wrapper(term()) -> boolean(). + is_wrapper(#wrapper{}) -> true; is_wrapper(_) -> 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) -> diff --git a/lib/syntax_tools/src/erl_tidy.erl b/lib/syntax_tools/src/erl_tidy.erl index e3b479008f..021ab18736 100644 --- a/lib/syntax_tools/src/erl_tidy.erl +++ b/lib/syntax_tools/src/erl_tidy.erl @@ -66,6 +66,7 @@ dir__defaults() -> %% @equiv dir("") -spec dir() -> 'ok'. + dir() -> dir(""). @@ -74,6 +75,7 @@ dir() -> %% @equiv dir(Dir, []) -spec dir(file:filename()) -> 'ok'. + dir(Dir) -> dir(Dir, []). @@ -130,6 +132,7 @@ dir(Dir) -> options :: options()}). -spec dir(file:filename(), options()) -> 'ok'. + dir(Dir, Opts) -> Opts1 = Opts ++ dir__defaults(), Env = #dir{follow_links = proplists:get_bool(follow_links, Opts1), @@ -212,6 +215,7 @@ default_printer() -> %% @equiv file(Name, []) -spec file(file:filename()) -> 'ok'. + file(Name) -> file(Name, []). @@ -275,6 +279,7 @@ file(Name) -> %% @see module/2 -spec file(file:filename(), options()) -> 'ok'. + file(Name, Opts) -> Parent = self(), Child = spawn_link(fun () -> file_1(Parent, Name, Opts) end), @@ -478,11 +483,12 @@ backup_file_1(Name, Opts) -> throw(R) end. - %% ===================================================================== %% @spec module(Forms) -> syntaxTree() %% @equiv module(Forms, []) +-spec module(erl_syntax:forms()) -> erl_syntax:syntaxTree(). + module(Forms) -> module(Forms, []). @@ -609,6 +615,8 @@ module(Forms) -> %% %% </dl> +-spec module(erl_syntax:forms(), [term()]) -> erl_syntax:syntaxTree(). + module(Forms, Opts) when is_list(Forms) -> module(erl_syntax:form_list(Forms), Opts); module(Forms, Opts) -> @@ -668,11 +676,8 @@ analyze_forms(Forms, File) -> throw(R) end. -%% XXX: The following should be imported from erl_syntax_lib --type key() :: atom(). --type info_pair() :: {key(), any()}. +-spec get_module_name([erl_syntax_lib:info_pair()], string()) -> atom(). --spec get_module_name([info_pair()], string()) -> atom(). get_module_name(List, File) -> case lists:keyfind(module, 1, List) of {module, M} -> @@ -691,7 +696,8 @@ get_module_attributes(List) -> [] end. --spec get_module_exports([info_pair()]) -> [{atom(), byte()}]. +-spec get_module_exports([erl_syntax_lib:info_pair()]) -> [{atom(), arity()}]. + get_module_exports(List) -> case lists:keyfind(exports, 1, List) of {exports, Es} -> @@ -700,7 +706,8 @@ get_module_exports(List) -> [] end. --spec get_module_imports([info_pair()]) -> [{atom(), atom()}]. +-spec get_module_imports([erl_syntax_lib:info_pair()]) -> [{atom(), atom()}]. + get_module_imports(List) -> case lists:keyfind(imports, 1, List) of {imports, Is} -> @@ -714,6 +721,7 @@ compile_attrs(As) -> || {compile, T} <- As]). -spec flatten_imports([{atom(), [atom()]}]) -> [{atom(), atom()}]. + flatten_imports(Is) -> [{F, M} || {M, Fs} <- Is, F <- Fs]. @@ -736,7 +744,8 @@ check_imports(Is, Opts, File) -> end. -spec check_imports_1([{atom(), atom()}]) -> boolean(). -check_imports_1([{F1, M1}, {F2, M2} | _Is]) when F1 =:= F2, M1 =/= M2 -> + +check_imports_1([{F, M1}, {F, M2} | _Is]) when M1 =/= M2 -> false; check_imports_1([_ | Is]) -> check_imports_1(Is); @@ -1629,6 +1638,7 @@ rename_remote_call(F, St) -> end. -spec rename_remote_call_1(mfa()) -> {atom(), atom()} | 'false'. + rename_remote_call_1({dict, dict_to_list, 1}) -> {dict, to_list}; rename_remote_call_1({dict, list_to_dict, 1}) -> {dict, from_list}; rename_remote_call_1({erl_eval, arg_list, 2}) -> {erl_eval, expr_list}; @@ -1662,7 +1672,8 @@ rename_remote_call_1({string, index, 2}) -> {string, str}; rename_remote_call_1({unix, cmd, 1}) -> {os, cmd}; rename_remote_call_1(_) -> false. --spec rewrite_guard_test(atom(), byte()) -> atom(). +-spec rewrite_guard_test(atom(), arity()) -> atom(). + rewrite_guard_test(atom, 1) -> is_atom; rewrite_guard_test(binary, 1) -> is_binary; rewrite_guard_test(constant, 1) -> is_constant; @@ -1680,7 +1691,8 @@ rewrite_guard_test(record, 2) -> is_record; rewrite_guard_test(record, 3) -> is_record; rewrite_guard_test(N, _A) -> N. --spec reverse_guard_test(atom(), byte()) -> atom(). +-spec reverse_guard_test(atom(), arity()) -> atom(). + reverse_guard_test(is_atom, 1) -> atom; reverse_guard_test(is_binary, 1) -> binary; reverse_guard_test(is_constant, 1) -> constant; diff --git a/lib/syntax_tools/src/igor.erl b/lib/syntax_tools/src/igor.erl index 9e7b784170..e92e9593b6 100644 --- a/lib/syntax_tools/src/igor.erl +++ b/lib/syntax_tools/src/igor.erl @@ -117,20 +117,23 @@ -define(record_name(R), {record, R}). +%% ===================================================================== + +-type ordset(X) :: [X]. % XXX: TAKE ME OUT + +%% ===================================================================== %% Data structure for module information --record(module, {name, % = atom() - vars = none, % = [atom()] | none - functions, % = ordset({atom(), int()}) - exports, % = ordset({atom(), int()}) - % | ordset({{atom(), int()}, - % term()}) - aliases, % = ordset({{atom(), int()}, - % {atom(), - % {atom(), int()}}}) - attributes, % = ordset({atom(), term()}) - records % = [{atom(), [{atom(), term()}]}] +-record(module, {name :: atom(), + vars = none :: [atom()] | 'none', + functions :: ordset({atom(), arity()}), + exports :: ordset({atom(), arity()}) + | ordset({{atom(), arity()}, term()}), + aliases :: ordset({{atom(), arity()}, + {atom(), {atom(), arity()}}}), + attributes :: ordset({atom(), term()}), + records :: [{atom(), [{atom(), term()}]}] }). %% The default pretty-printing function. @@ -138,6 +141,17 @@ default_printer(Tree, Options) -> erl_prettypr:format(Tree, Options). +%% ===================================================================== + +-type option() :: atom() | {atom(), term()}. + +-type attribute() :: {atom(), term()}. +-type moduleName() :: atom(). +-type functionName() :: {atom(), arity()}. +-type functionPair() :: {functionName(), {moduleName(), functionName()}}. +-type stubDescriptor() :: [{moduleName(), [functionPair()], [attribute()]}]. + +-type notes() :: 'always' | 'yes' | 'no'. %% ===================================================================== %% @spec parse_transform(Forms::[syntaxTree()], Options::[term()]) -> @@ -169,6 +183,9 @@ default_printer(Tree, Options) -> %% @see merge_files/4 %% @see //compiler/compile:file/2 +-spec parse_transform(erl_syntax:forms(), [option()]) -> + [erl_syntax:syntaxTree()]. + parse_transform(Forms, Options) -> M = get_module_info(Forms), Name = M#module.name, @@ -192,6 +209,8 @@ parse_transform(Forms, Options) -> %% @spec merge(Name::atom(), Files::[filename()]) -> [filename()] %% @equiv merge(Name, Files, []) +-spec merge(atom(), [file:filename()]) -> [file:filename()]. + merge(Name, Files) -> merge(Name, Files, []). @@ -251,7 +270,7 @@ merge(Name, Files) -> %% <dd>Specifies the file name suffix to be used when a backup file %% is created; the default value is `".bak"'.</dd> %% -%% <dt>`{backups, bool()}'</dt> +%% <dt>`{backups, boolean()}'</dt> %% %% <dd>If the value is `true', existing files will be %% renamed before new files are opened for writing. The new names @@ -271,7 +290,7 @@ merge(Name, Files) -> %% resulting source code is to be written. By default, this is the %% same as the `Name' argument.</dd> %% -%% <dt>`{preprocess, bool()}'</dt> +%% <dt>`{preprocess, boolean()}'</dt> %% %% <dd>If the value is `true', preprocessing will be done %% when reading the source code. See `merge_files/4' for @@ -294,7 +313,7 @@ merge(Name, Files) -> %% stub module files are written. The default value is %% `"stubs"'.</dd> %% -%% <dt>`{stubs, bool()}'</dt> +%% <dt>`{stubs, boolean()}'</dt> %% %% <dd>If the value is `true', stub module files will be %% automatically generated for all exported modules that do not have @@ -324,6 +343,8 @@ merge(Name, Files) -> {suffix, ?DEFAULT_SUFFIX}, {verbose, false}]). +-spec merge(atom(), [file:filename()], [option()]) -> [file:filename()]. + merge(Name, Files, Opts) -> Opts1 = Opts ++ ?DEFAULT_MERGE_OPTS, {Tree, Stubs} = merge_files(Name, Files, Opts1), @@ -339,6 +360,9 @@ merge(Name, Files, Opts) -> %% {syntaxTree(), [stubDescriptor()]} %% @equiv merge_files(Name, [], Files, Options) +-spec merge_files(atom(), [file:filename()], [option()]) -> + {erl_syntax:syntaxTree(), [stubDescriptor()]}. + merge_files(Name, Files, Options) -> merge_files(Name, [], Files, Options). @@ -380,7 +404,7 @@ merge_files(Name, Files, Options) -> %% %% Options: %% <dl> -%% <dt>`{comments, bool()}'</dt> +%% <dt>`{comments, boolean()}'</dt> %% %% <dd>If the value is `true', source code comments in %% the original files will be preserved in the output. The default @@ -409,7 +433,7 @@ merge_files(Name, Files, Options) -> %% Erlang preprocessor, if used (cf. the `preprocess' %% option). The default value is the empty list.</dd> %% -%% <dt>`{preprocess, bool()}'</dt> +%% <dt>`{preprocess, boolean()}'</dt> %% %% <dd>If the value is `false', Igor will read source %% files without passing them through the Erlang preprocessor @@ -438,6 +462,9 @@ merge_files(Name, Files, Options) -> %% @see //stdlib/filename:find_src/2 %% @see epp_dodger +-spec merge_files(atom(), erl_syntax:forms(), [file:filename()], [option()]) -> + {erl_syntax:syntaxTree(), [stubDescriptor()]}. + merge_files(_, _Trees, [], _) -> report_error("no files to merge."), exit(badarg); @@ -512,7 +539,7 @@ merge_files(Name, Trees, Files, Opts) -> %% `Sources' will be exported. The default value is the %% empty list.</dd> %% -%% <dt>`{export_all, bool()}'</dt> +%% <dt>`{export_all, boolean()}'</dt> %% %% <dd>If the value is `true', this is equivalent to %% listing all of the input modules in the `export' @@ -532,7 +559,7 @@ merge_files(Name, Trees, Files, Opts) -> %% they will be handled as in the `comment' case. The %% default value is `no'.</dd> %% -%% <dt>`{no_banner, bool()}'</dt> +%% <dt>`{no_banner, boolean()}'</dt> %% %% <dd>If the value is `true', no banner comment will be %% added at the top of the resulting module, even if the target @@ -541,7 +568,7 @@ merge_files(Name, Trees, Files, Opts) -> %% code is at the top of the output. The default value is %% `false'.</dd> %% -%% <dt>`{no_headers, bool()}'</dt> +%% <dt>`{no_headers, boolean()}'</dt> %% %% <dd>If the value is `true', no header comments will be %% added to the resulting module at the beginning of each section of @@ -550,7 +577,7 @@ merge_files(Name, Trees, Files, Opts) -> %% normally added whenever more than two or more modules are %% merged.</dd> %% -%% <dt>`{no_imports, bool()}'</dt> +%% <dt>`{no_imports, boolean()}'</dt> %% %% <dd>If the value is `true', all %% `-import(...)' declarations in the original code will @@ -599,7 +626,7 @@ merge_files(Name, Trees, Files, Opts) -> %% regarded as "static", regardless of the value of this option. By %% default, all involved modules are assumed to be static.</dd> %% -%% <dt>`{tidy, bool()}'</dt> +%% <dt>`{tidy, boolean()}'</dt> %% %% <dd>If the value is `true', the resulting code will be %% processed using the `erl_tidy' module, which removes @@ -607,7 +634,7 @@ merge_files(Name, Trees, Files, Opts) -> %% `erl_tidy:module/2' for additional options.) The %% default value is `true'.</dd> %% -%% <dt>`{verbose, bool()}'</dt> +%% <dt>`{verbose, boolean()}'</dt> %% %% <dd>If the value is `true', progress messages will be %% output while the program is running; the default value is @@ -659,19 +686,22 @@ merge_files(Name, Trees, Files, Opts) -> %% Data structure for merging environment. --record(merge, {target, % = atom() - sources, % = ordset(atom()) - export, % = ordset(atom()) - static, % = ordset(atom()) - safe, % = ordset(atom()) - preserved, % = bool() - no_headers, % = bool() - notes, % = bool() - redirect, % = dict(atom(), atom()) - no_imports, % = ordset(atom()) - options % = [term()] +-record(merge, {target :: atom(), + sources :: ordset(atom()), + export :: ordset(atom()), + static :: ordset(atom()), + safe :: ordset(atom()), + preserved :: boolean(), + no_headers :: boolean(), + notes :: notes(), + redirect :: dict(), % = dict(atom(), atom()) + no_imports :: ordset(atom()), + options :: [option()] }). +-spec merge_sources(atom(), erl_syntax:forms(), [option()]) -> + {erl_syntax:syntaxTree(), [stubDescriptor()]}. + merge_sources(Name, Sources, Opts) -> %% Prepare the options and the inputs. Opts1 = Opts ++ [{export_all, false}, @@ -696,7 +726,7 @@ merge_sources(Name, Sources, Opts) -> %% Data structure for keeping state during transformation. --record(state, {export}). +-record(state, {export :: set()}). state__add_export(Name, Arity, S) -> S#state{export = sets:add_element({Name, Arity}, @@ -981,7 +1011,7 @@ make_stubs(Modules, Renaming, Env) -> make_stubs_1([M | Ms], Renaming, Env) -> Name = M#module.name, - if Name /= Env#merge.target -> + if Name =/= Env#merge.target -> case ordsets:is_element(Name, Env#merge.export) of true -> [make_stub(M, Renaming(Name), Env) @@ -1005,7 +1035,7 @@ make_stub(M, Map, Env) -> %% Removing and/or out-commenting program forms. The returned form %% sequence tree is not necessarily flat. --record(filter, {records, file_attributes, attributes}). +-record(filter, {records :: set(), file_attributes, attributes}). filter_forms(Tree, Env) -> Forms = erl_syntax:form_list_elements( @@ -1098,8 +1128,7 @@ filter_form(F, S) -> kill_form(F) -> F1 = erl_syntax:set_precomments(F, []), F2 = erl_syntax_lib:to_comment(F1, ?KILL_PREFIX), - erl_syntax:set_precomments(F2, - erl_syntax:get_precomments(F)). + erl_syntax:set_precomments(F2, erl_syntax:get_precomments(F)). %% --------------------------------------------------------------------- @@ -1138,8 +1167,7 @@ merge_namespaces(Modules, Env) -> [] -> ok; Fs -> - report_warning("interface functions renamed:\n\t~p.", - [Fs]) + report_warning("interface functions renamed:\n\t~p.", [Fs]) end, {M4, Acc2} = merge_namespaces_1(M2, Acc1), Ms = M3 ++ M4, @@ -1550,20 +1578,20 @@ alias_expansions_2(Modules, Table) -> %% Data structure for code transformation environment. --record(code, {module, % = atom() - target, % = atom() - sources, % = ordset(atom()) - static, % = ordset(atom()) - safe, % = ordset(atom()) - preserved, % = bool() - no_headers, % = bool() - notes, % = bool() +-record(code, {module :: atom(), + target :: atom(), + sources :: set(), % set(atom()), + static :: set(), % set(atom()), + safe :: set(), % set(atom()), + preserved :: boolean(), + no_headers :: boolean(), + notes :: notes(), map, % = ({atom(), int()}) -> {atom(), int()} renaming, % = (atom()) -> ({atom(), int()}) -> % {atom(), int()} - expand, % = dict({atom(), int()}, - % {atom(), {atom(), int()}}) - redirect % = dict(atom(), atom()) + expand :: dict(), % = dict({atom(), int()}, + % {atom(), {atom(), int()}}) + redirect :: dict() % = dict(atom(), atom()) }). %% `Trees' must be a list of syntax trees of type `form_list'. The @@ -1657,8 +1685,8 @@ take_header_1([F | Fs], As) -> section_header(Name, Tree, Env) -> N = sets:size(Env#code.sources), - if N > 1, Name /= Env#code.target, Env#code.notes /= no, - Env#code.no_headers /= true -> + if N > 1, Name =/= Env#code.target, Env#code.notes =/= no, + Env#code.no_headers =/= true -> Text = io_lib:fwrite("The following code stems " "from module `~w'.", [Name]), Header = comment([?COMMENT_BAR, "", @@ -2292,11 +2320,11 @@ maybe_modified_1({value, Node1}, Node, Depth, Message, Notes) -> %% Options: %% <dl> %% <dt>`{backup_suffix, string()}'</dt> -%% <dt>`{backups, bool()}'</dt> +%% <dt>`{backups, boolean()}'</dt> %% <dt>`{printer, Function}'</dt> %% <dt>`{stub_dir, filename()}'</dt> %% <dt>`{suffix, string()}'</dt> -%% <dt>`{verbose, bool()}'</dt> +%% <dt>`{verbose, boolean()}'</dt> %% </dl> %% %% See `merge/3' for details on these options. @@ -2304,6 +2332,8 @@ maybe_modified_1({value, Node1}, Node, Depth, Message, Notes) -> %% @see merge/3 %% @see merge_sources/3 +-spec create_stubs([stubDescriptor()], [option()]) -> [string()]. + create_stubs(Stubs, Opts) -> Opts1 = Opts ++ ?DEFAULT_MERGE_OPTS, lists:foldl(fun (S, Fs) -> @@ -2365,9 +2395,15 @@ stub_header(Name, Exports, Attrs) -> %% ===================================================================== + +-type renamings() :: [{atom(), atom()}]. + +%% ===================================================================== %% @spec rename(Files::[filename()], Renamings) -> [string()] %% @equiv rename(Files, Renamings, []) +-spec rename([file:filename()], renamings()) -> [string()]. + rename(Files, Renamings) -> rename(Files, Renamings, []). @@ -2408,35 +2444,35 @@ rename(Files, Renamings) -> %% Options: %% <dl> %% <dt>`{backup_suffix, string()}'</dt> -%% <dt>`{backups, bool()}'</dt> +%% <dt>`{backups, boolean()}'</dt> %% <dt>`{printer, Function}'</dt> -%% <dt>`{stubs, bool()}'</dt> +%% <dt>`{stubs, boolean()}'</dt> %% <dt>`{suffix, string()}'</dt> %% </dl> %% See `merge/3' for details on these options. %% %% <dl> -%% <dt>`{comments, bool()}'</dt> -%% <dt>`{preprocess, bool()}'</dt> +%% <dt>`{comments, boolean()}'</dt> +%% <dt>`{preprocess, boolean()}'</dt> %% </dl> %% See `merge_files/4' for details on these options. %% %% <dl> -%% <dt>`{no_banner, bool()}'</dt> +%% <dt>`{no_banner, boolean()}'</dt> %% </dl> %% For the `rename' function, this option is %% `true' by default. See `merge_sources/3' for %% details. %% %% <dl> -%% <dt>`{tidy, bool()}'</dt> +%% <dt>`{tidy, boolean()}'</dt> %% </dl> %% For the `rename' function, this option is %% `false' by default. See `merge_sources/3' for %% details. %% %% <dl> -%% <dt>`{no_headers, bool()}'</dt> +%% <dt>`{no_headers, boolean()}'</dt> %% <dt>`{stub_dir, filename()}'</dt> %% </dl> %% These options are preset by the `rename' function and @@ -2448,6 +2484,8 @@ rename(Files, Renamings) -> %% @see merge_sources/3 %% @see merge_files/4 +-spec rename([file:filename()], renamings(), [term()]) -> [string()]. + rename(Files, Renamings, Opts) -> Dict = case is_atom_map(Renamings) of true -> diff --git a/lib/syntax_tools/src/prettypr.erl b/lib/syntax_tools/src/prettypr.erl index 4dd95a2b08..1868f63e54 100644 --- a/lib/syntax_tools/src/prettypr.erl +++ b/lib/syntax_tools/src/prettypr.erl @@ -50,29 +50,22 @@ %% --------------------------------------------------------------------- -%% XXX: just an approximation --type deep_string() :: [char() | [_]]. - -%% XXX: poor man's document() until recursive data types are supported --type doc() :: 'null' - | {'text' | 'fit', _} - | {'nest' | 'beside' | 'above' | 'union', _, _} - | {'sep' | 'float', _, _, _}. +-type deep_string() :: [char() | deep_string()]. %% Document structures fully implemented and available to the user: -record(text, {s :: deep_string()}). --record(nest, {n :: integer(), d :: doc()}). --record(beside, {d1 :: doc(), d2 :: doc()}). --record(above, {d1 :: doc(), d2 :: doc()}). --record(sep, {ds :: [doc()], i = 0 :: integer(), p = false :: boolean()}). +-record(nest, {n :: integer(), d :: document()}). +-record(beside, {d1 :: document(), d2 :: document()}). +-record(above, {d1 :: document(), d2 :: document()}). +-record(sep, {ds :: [document()], i = 0 :: integer(), + p = false :: boolean()}). %% Document structure which is not clear whether it is fully implemented: --record(float, {d :: doc(), h :: integer(), v :: integer()}). +-record(float, {d :: document(), h :: integer(), v :: integer()}). %% Document structures not available to the user: --record(union, {d1 :: doc(), d2 :: doc()}). --record(fit, {d :: doc()}). - +-record(union, {d1 :: document(), d2 :: document()}). +-record(fit, {d :: document()}). %% --------------------------------------------------------------------- %% A small warning for hackers: it's fairly easy to break this @@ -637,43 +630,43 @@ flatrev([], As, []) -> %% Contexts: %% %% #c_best_nest{w = integer(), r = integer(), i = integer()} -%% #c_above_nest{d = doc(), i = integer(), c = ctxt()} -%% #c_beside{d = doc(), c = ctxt()} +%% #c_above_nest{d = document(), i = integer(), c = ctxt()} +%% #c_beside{d = document(), c = ctxt()} %% #c_text_beside{s = string(), c = ctxt()} -%% #c_sep_nest{ds = [doc()], i = integer(), p = boolean(), +%% #c_sep_nest{ds = [document()], i = integer(), p = boolean(), %% c = ctxt()} %% #c_best_nest_or{w = integer(), r = integer(), i = integer(), -%% d = doc()} +%% d = document()} %% #c_fit{c = ctxt()} --record(c_best_nest, {w, r, i}). %% best(w, r, nest(i, *)) +%% best(w, r, nest(i, *)) +-record(c_best_nest, {w :: integer(), r :: integer(), i :: integer()}). --record(c_above_nest, {d, i = 0, c}). %% above(*, nest(i, d)) +%% above(*, nest(i, d)) +-record(c_above_nest, {d :: document(), i = 0 :: integer(), c :: ctxt()}). --record(c_beside, {d, c}). %% beside(*, d) +-record(c_beside, {d :: document(), c :: ctxt()}). %% beside(*, d) --record(c_text_beside, {s, c}). %% beside(text(s), *) +-record(c_text_beside, {s :: string(), c :: ctxt()}). %% beside(text(s), *) %% p = false => sep([* | map(nest i, ds)]) %% p = true => par([* | map(nest i, ds)]) --record(c_sep_nest, {ds, i, p, c}). +-record(c_sep_nest, {ds :: [document()], i :: integer(), + p :: boolean(), c :: ctxt()}). --record(c_best_nest_or, {w, r, i, d}). %% nicest( - %% best(w, r, - %% nest(i, *)), - %% best(w, r, d)) +%% nicest(best(w, r, nest(i, *)), best(w, r, d)) +-record(c_best_nest_or, {w :: integer(), r :: integer(), + i :: integer(), d :: document()}). --record(c_fit, {c}). %% fit(*) +-record(c_fit, {c :: ctxt()}). %% fit(*) --record(c_float_beside, {d, h, v, c}). %% beside( - %% float(d, h, - %% v), - %% *) --record(c_float_above_nest, {d, h, v, i, c}). %% above( - %% float(d, h, - %% v), - %% nest(i, *)) +%% beside(float(d, h, v), *) +-record(c_float_beside, {d :: document(), h :: integer(), + v :: integer(), c :: ctxt()}). +%% above(float(d, h, v), nest(i, *)) +-record(c_float_above_nest, {d :: document(), h :: integer(), + v :: integer(), i :: integer(), c :: ctxt()}). %% Contexts introduced: In case: %% @@ -687,6 +680,11 @@ flatrev([], As, []) -> %% c_float_beside float (c_beside) %% c_float_above_nest float (c_above_nest) +-type ctxt() :: #c_best_nest{} | #c_above_nest{} + | #c_beside{} | #c_text_beside{} + | #c_sep_nest{} | #c_best_nest_or{} + | #c_fit{} | #c_float_beside{} | #c_float_above_nest{}. + %% Entry point for the layout algorithm: -spec best(document(), integer(), integer()) -> 'empty' | document(). |