1%% =====================================================================
2%% Licensed under the Apache License, Version 2.0 (the "License"); you may
3%% not use this file except in compliance with the License. You may obtain
4%% a copy of the License at <http://www.apache.org/licenses/LICENSE-2.0>
5%%
6%% Unless required by applicable law or agreed to in writing, software
7%% distributed under the License is distributed on an "AS IS" BASIS,
8%% WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
9%% See the License for the specific language governing permissions and
10%% limitations under the License.
11%%
12%% Alternatively, you may use this file under the terms of the GNU Lesser
13%% General Public License (the "LGPL") as published by the Free Software
14%% Foundation; either version 2.1, or (at your option) any later version.
15%% If you wish to allow use of your version of this file only under the
16%% terms of the LGPL, you should delete the provisions above and replace
17%% them with the notice and other provisions required by the LGPL; see
18%% <http://www.gnu.org/licenses/>. If you do not delete the provisions
19%% above, a recipient may use your version of this file under the terms of
20%% either the Apache License or the LGPL.
21%%
22%% @copyright 1997-2006 Richard Carlsson
23%% @author Richard Carlsson <carlsson.richard@gmail.com>
24%% @end
25%% =====================================================================
26
27%% @doc Support library for abstract Erlang syntax trees.
28%%
29%% This module contains utility functions for working with the
30%% abstract data type defined in the module {@link erl_syntax}.
31%%
32%% @type syntaxTree() = erl_syntax:syntaxTree(). An abstract syntax
33%% tree. See the {@link erl_syntax} module for details.
34
35-module(erl_syntax_lib).
36
37-export([analyze_application/1, analyze_attribute/1,
38         analyze_export_attribute/1, analyze_file_attribute/1,
39         analyze_form/1, analyze_forms/1, analyze_function/1,
40         analyze_function_name/1, analyze_implicit_fun/1,
41         analyze_import_attribute/1, analyze_module_attribute/1,
42         analyze_record_attribute/1, analyze_record_expr/1,
43         analyze_record_field/1, analyze_wild_attribute/1, annotate_bindings/1,
44         analyze_type_application/1, analyze_type_name/1,
45         annotate_bindings/2, fold/3, fold_subtrees/3, foldl_listlist/3,
46         function_name_expansions/1, is_fail_expr/1, limit/2, limit/3,
47         map/2, map_subtrees/2, mapfold/3, mapfold_subtrees/3,
48         mapfoldl_listlist/3, new_variable_name/1, new_variable_name/2,
49         new_variable_names/2, new_variable_names/3, strip_comments/1,
50         to_comment/1, to_comment/2, to_comment/3, variables/1]).
51
52-export_type([info_pair/0]).
53
54%% =====================================================================
55%% @spec map(Function, Tree::syntaxTree()) -> syntaxTree()
56%%
57%%          Function = (syntaxTree()) -> syntaxTree()
58%%
59%% @doc Applies a function to each node of a syntax tree. The result of
60%% each application replaces the corresponding original node. The order
61%% of traversal is bottom-up.
62%%
63%% @see map_subtrees/2
64
65-spec map(fun((erl_syntax:syntaxTree()) -> erl_syntax:syntaxTree()),
66	  erl_syntax:syntaxTree()) -> erl_syntax:syntaxTree().
67
68map(F, Tree) ->
69    case erl_syntax:subtrees(Tree) of
70        [] ->
71            F(Tree);
72        Gs ->
73            Tree1 = erl_syntax:make_tree(erl_syntax:type(Tree),
74                                         [[map(F, T) || T <- G]
75                                          || G <- Gs]),
76            F(erl_syntax:copy_attrs(Tree, Tree1))
77    end.
78
79
80%% =====================================================================
81%% @spec map_subtrees(Function, syntaxTree()) -> syntaxTree()
82%%
83%%          Function = (Tree) -> Tree1
84%%
85%% @doc Applies a function to each immediate subtree of a syntax tree.
86%% The result of each application replaces the corresponding original
87%% node.
88%%
89%% @see map/2
90
91-spec map_subtrees(fun((erl_syntax:syntaxTree()) -> erl_syntax:syntaxTree()),
92		   erl_syntax:syntaxTree()) -> erl_syntax:syntaxTree().
93
94map_subtrees(F, Tree) ->
95    case erl_syntax:subtrees(Tree) of
96        [] ->
97            Tree;
98        Gs ->
99            Tree1 = erl_syntax:make_tree(erl_syntax:type(Tree),
100                                         [[F(T) || T <- G] || G <- Gs]),
101            erl_syntax:copy_attrs(Tree, Tree1)
102    end.
103
104
105%% =====================================================================
106%% @spec fold(Function, Start::term(), Tree::syntaxTree()) -> term()
107%%
108%%          Function = (syntaxTree(), term()) -> term()
109%%
110%% @doc Folds a function over all nodes of a syntax tree. The result is
111%% the value of `Function(X1, Function(X2, ... Function(Xn, Start)
112%% ... ))', where `[X1, X2, ..., Xn]' are the nodes of
113%% `Tree' in a post-order traversal.
114%%
115%% @see fold_subtrees/3
116%% @see foldl_listlist/3
117
118-spec fold(fun((erl_syntax:syntaxTree(), term()) -> term()),
119	   term(), erl_syntax:syntaxTree()) -> term().
120
121fold(F, S, Tree) ->
122    case erl_syntax:subtrees(Tree) of
123        [] ->
124            F(Tree, S);
125        Gs ->
126            F(Tree, fold_1(F, S, Gs))
127    end.
128
129fold_1(F, S, [L | Ls]) ->
130    fold_1(F, fold_2(F, S, L), Ls);
131fold_1(_, S, []) ->
132    S.
133
134fold_2(F, S, [T | Ts]) ->
135    fold_2(F, fold(F, S, T), Ts);
136fold_2(_, S, []) ->
137    S.
138
139
140%% =====================================================================
141%% @spec fold_subtrees(Function, Start::term(), Tree::syntaxTree()) ->
142%%           term()
143%%
144%%          Function = (syntaxTree(), term()) -> term()
145%%
146%% @doc Folds a function over the immediate subtrees of a syntax tree.
147%% This is similar to `fold/3', but only on the immediate
148%% subtrees of `Tree', in left-to-right order; it does not
149%% include the root node of `Tree'.
150%%
151%% @see fold/3
152
153-spec fold_subtrees(fun((erl_syntax:syntaxTree(), term()) -> term()),
154		    term(), erl_syntax:syntaxTree()) -> term().
155
156fold_subtrees(F, S, Tree) ->
157    foldl_listlist(F, S, erl_syntax:subtrees(Tree)).
158
159
160%% =====================================================================
161%% @spec foldl_listlist(Function, Start::term(), [[term()]]) -> term()
162%%
163%%          Function = (term(), term()) -> term()
164%%
165%% @doc Like `lists:foldl/3', but over a list of lists.
166%%
167%% @see fold/3
168%% @see //stdlib/lists:foldl/3
169
170-spec foldl_listlist(fun((term(), term()) -> term()),
171		     term(), [[term()]]) -> term().
172
173foldl_listlist(F, S, [L | Ls]) ->
174    foldl_listlist(F, foldl(F, S, L), Ls);
175foldl_listlist(_, S, []) ->
176    S.
177
178foldl(F, S, [T | Ts]) ->
179    foldl(F, F(T, S), Ts);
180foldl(_, S, []) ->
181    S.
182
183
184%% =====================================================================
185%% @spec mapfold(Function, Start::term(), Tree::syntaxTree()) ->
186%%           {syntaxTree(), term()}
187%%
188%%          Function = (syntaxTree(), term()) -> {syntaxTree(), term()}
189%%
190%% @doc Combines map and fold in a single operation. This is similar to
191%% `map/2', but also propagates an extra value from each
192%% application of the `Function' to the next, while doing a
193%% post-order traversal of the tree like `fold/3'. The value
194%% `Start' is passed to the first function application, and
195%% the final result is the result of the last application.
196%%
197%% @see map/2
198%% @see fold/3
199
200-spec mapfold(fun((erl_syntax:syntaxTree(), term()) -> {erl_syntax:syntaxTree(), term()}),
201	      term(), erl_syntax:syntaxTree()) -> {erl_syntax:syntaxTree(), term()}.
202
203mapfold(F, S, Tree) ->
204    case erl_syntax:subtrees(Tree) of
205        [] ->
206            F(Tree, S);
207        Gs ->
208            {Gs1, S1} = mapfold_1(F, S, Gs),
209            Tree1 = erl_syntax:make_tree(erl_syntax:type(Tree), Gs1),
210            F(erl_syntax:copy_attrs(Tree, Tree1), S1)
211    end.
212
213mapfold_1(F, S, [L | Ls]) ->
214    {L1, S1} = mapfold_2(F, S, L),
215    {Ls1, S2} = mapfold_1(F, S1, Ls),
216    {[L1 | Ls1], S2};
217mapfold_1(_, S, []) ->
218    {[], S}.
219
220mapfold_2(F, S, [T | Ts]) ->
221    {T1, S1} = mapfold(F, S, T),
222    {Ts1, S2} = mapfold_2(F, S1, Ts),
223    {[T1 | Ts1], S2};
224mapfold_2(_, S, []) ->
225    {[], S}.
226
227
228%% =====================================================================
229%% @spec mapfold_subtrees(Function, Start::term(),
230%%                        Tree::syntaxTree()) -> {syntaxTree(), term()}
231%%
232%%          Function = (syntaxTree(), term()) -> {syntaxTree(), term()}
233%%
234%% @doc Does a mapfold operation over the immediate subtrees of a syntax
235%% tree. This is similar to `mapfold/3', but only on the
236%% immediate subtrees of `Tree', in left-to-right order; it
237%% does not include the root node of `Tree'.
238%%
239%% @see mapfold/3
240
241-spec mapfold_subtrees(fun((erl_syntax:syntaxTree(), term()) ->
242			      {erl_syntax:syntaxTree(), term()}),
243		       term(), erl_syntax:syntaxTree()) ->
244        {erl_syntax:syntaxTree(), term()}.
245
246mapfold_subtrees(F, S, Tree) ->
247    case erl_syntax:subtrees(Tree) of
248        [] ->
249            {Tree, S};
250        Gs ->
251            {Gs1, S1} = mapfoldl_listlist(F, S, Gs),
252            Tree1 = erl_syntax:make_tree(erl_syntax:type(Tree), Gs1),
253            {erl_syntax:copy_attrs(Tree, Tree1), S1}
254    end.
255
256
257%% =====================================================================
258%% @spec mapfoldl_listlist(Function, State, [[term()]]) ->
259%%           {[[term()]], term()}
260%%
261%%          Function = (term(), term()) -> {term(), term()}
262%%
263%% @doc Like `lists:mapfoldl/3', but over a list of lists.
264%% The list of lists in the result has the same structure as the given
265%% list of lists.
266
267-spec mapfoldl_listlist(fun((term(), term()) -> {term(), term()}),
268			term(), [[term()]]) -> {[[term()]], term()}.
269
270mapfoldl_listlist(F, S, [L | Ls]) ->
271    {L1, S1} = mapfoldl(F, S, L),
272    {Ls1, S2} = mapfoldl_listlist(F, S1, Ls),
273    {[L1 | Ls1], S2};
274mapfoldl_listlist(_, S, []) ->
275    {[], S}.
276
277mapfoldl(F, S, [L | Ls]) ->
278    {L1, S1} = F(L, S),
279    {Ls1, S2} = mapfoldl(F, S1, Ls),
280    {[L1 | Ls1], S2};
281mapfoldl(_, S, []) ->
282    {[], S}.
283
284
285%% =====================================================================
286%% @spec variables(syntaxTree()) -> set(atom())
287%%
288%% @type set(T) = //stdlib/sets:set(T)
289%%
290%% @doc Returns the names of variables occurring in a syntax tree, The
291%% result is a set of variable names represented by atoms. Macro names
292%% are not included.
293%%
294%% @see //stdlib/sets
295
296-spec variables(erl_syntax:syntaxTree()) -> sets:set(atom()).
297
298variables(Tree) ->
299    variables(Tree, sets:new()).
300
301variables(T, S) ->
302    case erl_syntax:type(T) of
303	variable ->
304	    sets:add_element(erl_syntax:variable_name(T), S);
305	macro ->
306	    %% macro names are ignored, even if represented by variables
307	    case erl_syntax:macro_arguments(T) of
308		none -> S;
309		As ->
310		    variables_2(As, S)
311	    end;
312	_ ->
313	    case erl_syntax:subtrees(T) of
314		[] ->
315		    S;
316		Gs ->
317		    variables_1(Gs, S)
318	    end
319    end.
320
321variables_1([L | Ls], S) ->
322    variables_1(Ls, variables_2(L, S));
323variables_1([], S) ->
324    S.
325
326variables_2([T | Ts], S) ->
327    variables_2(Ts, variables(T, S));
328variables_2([], S) ->
329    S.
330
331
332-define(MINIMUM_RANGE, 100).
333-define(START_RANGE_FACTOR, 100).
334-define(MAX_RETRIES, 3).    % retries before enlarging range
335-define(ENLARGE_ENUM, 8).   % range enlargment enumerator
336-define(ENLARGE_DENOM, 1).  % range enlargment denominator
337
338default_variable_name(N) ->
339    list_to_atom("V" ++ integer_to_list(N)).
340
341%% =====================================================================
342%% @spec new_variable_name(Used::set(atom())) -> atom()
343%%
344%% @doc Returns an atom which is not already in the set `Used'. This is
345%% equivalent to `new_variable_name(Function, Used)', where `Function'
346%% maps a given integer `N' to the atom whose name consists of "`V'"
347%% followed by the numeral for `N'.
348%%
349%% @see new_variable_name/2
350
351-spec new_variable_name(sets:set(atom())) -> atom().
352
353new_variable_name(S) ->
354    new_variable_name(fun default_variable_name/1, S).
355
356%% =====================================================================
357%% @spec new_variable_name(Function, Used::set(atom())) -> atom()
358%%
359%%          Function = (integer()) -> atom()
360%%
361%% @doc Returns a user-named atom which is not already in the set
362%% `Used'. The atom is generated by applying the given
363%% `Function' to a generated integer. Integers are generated
364%% using an algorithm which tries to keep the names randomly distributed
365%% within a reasonably small range relative to the number of elements in
366%% the set.
367%%
368%% This function uses the module `rand' to generate new
369%% keys. The seed it uses may be initialized by calling
370%% `rand:seed/1' or `rand:seed/2' before this
371%% function is first called.
372%%
373%% @see new_variable_name/1
374%% @see //stdlib/sets
375%% @see //stdlib/random
376
377-spec new_variable_name(fun((integer()) -> atom()), sets:set(atom())) -> atom().
378
379new_variable_name(F, S) ->
380    R = start_range(S),
381    new_variable_name(R, F, S).
382
383new_variable_name(R, F, S) ->
384    new_variable_name(generate(R, R), R, 0, F, S).
385
386new_variable_name(N, R, T, F, S) when T < ?MAX_RETRIES ->
387    A = F(N),
388    case sets:is_element(A, S) of
389        true ->
390            new_variable_name(generate(N, R), R, T + 1, F, S);
391        false ->
392            A
393    end;
394new_variable_name(N, R, _T, F, S) ->
395    %% Too many retries - enlarge the range and start over.
396    R1 = (R * ?ENLARGE_ENUM) div ?ENLARGE_DENOM,
397    new_variable_name(generate(N, R1), R1, 0, F, S).
398
399%% Note that we assume that it is very cheap to take the size of
400%% the given set. This should be valid for the stdlib
401%% implementation of `sets'.
402
403start_range(S) ->
404    erlang:max(sets:size(S) * ?START_RANGE_FACTOR, ?MINIMUM_RANGE).
405
406%% The previous number might or might not be used to compute the
407%% next number to be tried. It is currently not used.
408%%
409%% It is important that this function does not generate values in
410%% order, but (pseudo-)randomly distributed over the range.
411
412generate(_Key, Range) ->
413    _ = case rand:export_seed() of
414	    undefined ->
415		rand:seed(exsplus, {753,8,73});
416	    _ ->
417		ok
418	end,
419    rand:uniform(Range).			% works well
420
421
422%% =====================================================================
423%% @spec new_variable_names(N::integer(), Used::set(atom())) -> [atom()]
424%%
425%% @doc Like `new_variable_name/1', but generates a list of
426%% `N' new names.
427%%
428%% @see new_variable_name/1
429
430-spec new_variable_names(integer(), sets:set(atom())) -> [atom()].
431
432new_variable_names(N, S) ->
433    new_variable_names(N, fun default_variable_name/1, S).
434
435%% =====================================================================
436%% @spec new_variable_names(N::integer(), Function,
437%%                          Used::set(atom())) -> [atom()]
438%%
439%%          Function = (integer()) -> atom()
440%%
441%% @doc Like `new_variable_name/2', but generates a list of
442%% `N' new names.
443%%
444%% @see new_variable_name/2
445
446-spec new_variable_names(integer(), fun((integer()) -> atom()), sets:set(atom())) ->
447	[atom()].
448
449new_variable_names(N, F, S) when is_integer(N) ->
450    R = start_range(S),
451    new_variable_names(N, [], R, F, S).
452
453new_variable_names(N, Names, R, F, S) when N > 0 ->
454    Name = new_variable_name(R, F, S),
455    S1 = sets:add_element(Name, S),
456    new_variable_names(N - 1, [Name | Names], R, F, S1);
457new_variable_names(0, Names, _, _, _) ->
458    Names.
459
460
461%% =====================================================================
462%% @spec annotate_bindings(Tree::syntaxTree(),
463%%                         Bindings::ordset(atom())) -> syntaxTree()
464%%
465%% @type ordset(T) = //stdlib/ordsets:ordset(T)
466%%
467%% @doc Adds or updates annotations on nodes in a syntax tree.
468%% `Bindings' specifies the set of bound variables in the
469%% environment of the top level node. The following annotations are
470%% affected:
471%% <ul>
472%%     <li>`{env, Vars}', representing the input environment
473%%     of the subtree.</li>
474%%
475%%     <li>`{bound, Vars}', representing the variables that
476%%     are bound in the subtree.</li>
477%%
478%%     <li>`{free, Vars}', representing the free variables in
479%%     the subtree.</li>
480%% </ul>
481%% `Bindings' and `Vars' are ordered-set lists
482%% (cf. module `ordsets') of atoms representing variable
483%% names.
484%%
485%% @see annotate_bindings/1
486%% @see //stdlib/ordsets
487
488-spec annotate_bindings(erl_syntax:syntaxTree(), ordsets:ordset(atom())) ->
489        erl_syntax:syntaxTree().
490
491annotate_bindings(Tree, Env) ->
492    {Tree1, _, _} = vann(Tree, Env),
493    Tree1.
494
495%% =====================================================================
496%% @spec annotate_bindings(Tree::syntaxTree()) -> syntaxTree()
497%%
498%% @doc Adds or updates annotations on nodes in a syntax tree.
499%% Equivalent to `annotate_bindings(Tree, Bindings)' where
500%% the top-level environment `Bindings' is taken from the
501%% annotation `{env, Bindings}' on the root node of
502%% `Tree'. An exception is thrown if no such annotation
503%% should exist.
504%%
505%% @see annotate_bindings/2
506
507-spec annotate_bindings(erl_syntax:syntaxTree()) -> erl_syntax:syntaxTree().
508
509annotate_bindings(Tree) ->
510    As = erl_syntax:get_ann(Tree),
511    case lists:keyfind(env, 1, As) of
512        {env, InVars} ->
513            annotate_bindings(Tree, InVars);
514        _ ->
515            erlang:error(badarg)
516    end.
517
518vann(Tree, Env) ->
519    case erl_syntax:type(Tree) of
520        variable ->
521            %% Variable use
522            Bound = [],
523            Free = [erl_syntax:variable_name(Tree)],
524            {ann_bindings(Tree, Env, Bound, Free), Bound, Free};
525        match_expr ->
526            vann_match_expr(Tree, Env);
527        case_expr ->
528            vann_case_expr(Tree, Env);
529        if_expr ->
530            vann_if_expr(Tree, Env);
531        receive_expr ->
532            vann_receive_expr(Tree, Env);
533        catch_expr ->
534            vann_catch_expr(Tree, Env);
535        try_expr ->
536            vann_try_expr(Tree, Env);
537        function ->
538            vann_function(Tree, Env);
539        fun_expr ->
540            vann_fun_expr(Tree, Env);
541        list_comp ->
542            vann_list_comp(Tree, Env);
543        binary_comp ->
544            vann_binary_comp(Tree, Env);
545        generator ->
546            vann_generator(Tree, Env);
547        binary_generator ->
548            vann_binary_generator(Tree, Env);
549        block_expr ->
550            vann_block_expr(Tree, Env);
551        macro ->
552            vann_macro(Tree, Env);
553        _Type ->
554            F = vann_list_join(Env),
555            {Tree1, {Bound, Free}} = mapfold_subtrees(F, {[], []},
556                                                      Tree),
557            {ann_bindings(Tree1, Env, Bound, Free), Bound, Free}
558    end.
559
560vann_list_join(Env) ->
561    fun (T, {Bound, Free}) ->
562            {T1, Bound1, Free1} = vann(T, Env),
563            {T1, {ordsets:union(Bound, Bound1),
564                  ordsets:union(Free, Free1)}}
565    end.
566
567vann_list(Ts, Env) ->
568    lists:mapfoldl(vann_list_join(Env), {[], []}, Ts).
569
570vann_function(Tree, Env) ->
571    Cs = erl_syntax:function_clauses(Tree),
572    {Cs1, {_, Free}} = vann_clauses(Cs, Env),
573    N = erl_syntax:function_name(Tree),
574    {N1, _, _} = vann(N, Env),
575    Tree1 = rewrite(Tree, erl_syntax:function(N1, Cs1)),
576    Bound = [],
577    {ann_bindings(Tree1, Env, Bound, Free), Bound, Free}.
578
579vann_fun_expr(Tree, Env) ->
580    Cs = erl_syntax:fun_expr_clauses(Tree),
581    {Cs1, {_, Free}} = vann_clauses(Cs, Env),
582    Tree1 = rewrite(Tree, erl_syntax:fun_expr(Cs1)),
583    Bound = [],
584    {ann_bindings(Tree1, Env, Bound, Free), Bound, Free}.
585
586vann_match_expr(Tree, Env) ->
587    E = erl_syntax:match_expr_body(Tree),
588    {E1, Bound1, Free1} = vann(E, Env),
589    Env1 = ordsets:union(Env, Bound1),
590    P = erl_syntax:match_expr_pattern(Tree),
591    {P1, Bound2, Free2} = vann_pattern(P, Env1),
592    Bound = ordsets:union(Bound1, Bound2),
593    Free = ordsets:union(Free1, Free2),
594    Tree1 = rewrite(Tree, erl_syntax:match_expr(P1, E1)),
595    {ann_bindings(Tree1, Env, Bound, Free), Bound, Free}.
596
597vann_case_expr(Tree, Env) ->
598    E = erl_syntax:case_expr_argument(Tree),
599    {E1, Bound1, Free1} = vann(E, Env),
600    Env1 = ordsets:union(Env, Bound1),
601    Cs = erl_syntax:case_expr_clauses(Tree),
602    {Cs1, {Bound2, Free2}} = vann_clauses(Cs, Env1),
603    Bound = ordsets:union(Bound1, Bound2),
604    Free = ordsets:union(Free1, Free2),
605    Tree1 = rewrite(Tree, erl_syntax:case_expr(E1, Cs1)),
606    {ann_bindings(Tree1, Env, Bound, Free), Bound, Free}.
607
608vann_if_expr(Tree, Env) ->
609    Cs = erl_syntax:if_expr_clauses(Tree),
610    {Cs1, {Bound, Free}} = vann_clauses(Cs, Env),
611    Tree1 = rewrite(Tree, erl_syntax:if_expr(Cs1)),
612    {ann_bindings(Tree1, Env, Bound, Free), Bound, Free}.
613
614vann_catch_expr(Tree, Env) ->
615    E = erl_syntax:catch_expr_body(Tree),
616    {E1, _, Free} = vann(E, Env),
617    Tree1 = rewrite(Tree, erl_syntax:catch_expr(E1)),
618    Bound = [],
619    {ann_bindings(Tree1, Env, Bound, Free), Bound, Free}.
620
621vann_try_expr(Tree, Env) ->
622    Es = erl_syntax:try_expr_body(Tree),
623    {Es1, {Bound1, Free1}} = vann_body(Es, Env),
624    Cs = erl_syntax:try_expr_clauses(Tree),
625    %% bindings in the body should be available in the success case,
626    {Cs1, {_, Free2}} = vann_clauses(Cs, ordsets:union(Env, Bound1)),
627    Hs = erl_syntax:try_expr_handlers(Tree),
628    {Hs1, {_, Free3}} = vann_clauses(Hs, Env),
629    %% the after part does not export anything, yet; this might change
630    As = erl_syntax:try_expr_after(Tree),
631    {As1, {_, Free4}} = vann_body(As, Env),
632    Tree1 = rewrite(Tree, erl_syntax:try_expr(Es1, Cs1, Hs1, As1)),
633    Bound = [],
634    Free = ordsets:union(Free1, ordsets:union(Free2, ordsets:union(Free3, Free4))),
635    {ann_bindings(Tree1, Env, Bound, Free), Bound, Free}.
636
637vann_receive_expr(Tree, Env) ->
638    %% The timeout action is treated as an extra clause.
639    %% Bindings in the expiry expression are local only.
640    Cs = erl_syntax:receive_expr_clauses(Tree),
641    Es = erl_syntax:receive_expr_action(Tree),
642    C = erl_syntax:clause([], Es),
643    {[C1 | Cs1], {Bound, Free1}} = vann_clauses([C | Cs], Env),
644    Es1 = erl_syntax:clause_body(C1),
645    {T1, _, Free2} = case erl_syntax:receive_expr_timeout(Tree) of
646                         none ->
647                             {none, [], []};
648                         T ->
649                             vann(T, Env)
650                     end,
651    Free = ordsets:union(Free1, Free2),
652    Tree1 = rewrite(Tree, erl_syntax:receive_expr(Cs1, T1, Es1)),
653    {ann_bindings(Tree1, Env, Bound, Free), Bound, Free}.
654
655vann_list_comp(Tree, Env) ->
656    Es = erl_syntax:list_comp_body(Tree),
657    {Es1, {Bound1, Free1}} = vann_list_comp_body(Es, Env),
658    Env1 = ordsets:union(Env, Bound1),
659    T = erl_syntax:list_comp_template(Tree),
660    {T1, _, Free2} = vann(T, Env1),
661    Free = ordsets:union(Free1, ordsets:subtract(Free2, Bound1)),
662    Bound = [],
663    Tree1 = rewrite(Tree, erl_syntax:list_comp(T1, Es1)),
664    {ann_bindings(Tree1, Env, Bound, Free), Bound, Free}.
665
666vann_list_comp_body_join() ->
667    fun (T, {Env, Bound, Free}) ->
668            {T1, Bound1, Free1} = case erl_syntax:type(T) of
669                                      binary_generator ->
670				          vann_binary_generator(T,Env);
671				      generator ->
672                                          vann_generator(T, Env);
673                                      _ ->
674                                          %% Bindings in filters are not
675                                          %% exported to the rest of the
676                                          %% body.
677                                          {T2, _, Free2} = vann(T, Env),
678                                          {T2, [], Free2}
679                                  end,
680            Env1 = ordsets:union(Env, Bound1),
681            {T1, {Env1, ordsets:union(Bound, Bound1),
682                  ordsets:union(Free,
683                                ordsets:subtract(Free1, Bound))}}
684    end.
685
686vann_list_comp_body(Ts, Env) ->
687    F = vann_list_comp_body_join(),
688    {Ts1, {_, Bound, Free}} = lists:mapfoldl(F, {Env, [], []}, Ts),
689    {Ts1, {Bound, Free}}.
690
691vann_binary_comp(Tree, Env) ->
692    Es = erl_syntax:binary_comp_body(Tree),
693    {Es1, {Bound1, Free1}} = vann_binary_comp_body(Es, Env),
694    Env1 = ordsets:union(Env, Bound1),
695    T = erl_syntax:binary_comp_template(Tree),
696    {T1, _, Free2} = vann(T, Env1),
697    Free = ordsets:union(Free1, ordsets:subtract(Free2, Bound1)),
698    Bound = [],
699    Tree1 = rewrite(Tree, erl_syntax:binary_comp(T1, Es1)),
700    {ann_bindings(Tree1, Env, Bound, Free), Bound, Free}.
701
702vann_binary_comp_body_join() ->
703    fun (T, {Env, Bound, Free}) ->
704            {T1, Bound1, Free1} = case erl_syntax:type(T) of
705                                    binary_generator ->
706				          vann_binary_generator(T, Env);
707				    generator ->
708                                          vann_generator(T, Env);
709                                      _ ->
710                                          %% Bindings in filters are not
711                                          %% exported to the rest of the
712                                          %% body.
713                                          {T2, _, Free2} = vann(T, Env),
714                                          {T2, [], Free2}
715                                  end,
716            Env1 = ordsets:union(Env, Bound1),
717            {T1, {Env1, ordsets:union(Bound, Bound1),
718                  ordsets:union(Free,
719                                ordsets:subtract(Free1, Bound))}}
720    end.
721
722vann_binary_comp_body(Ts, Env) ->
723    F = vann_binary_comp_body_join(),
724    {Ts1, {_, Bound, Free}} = lists:mapfoldl(F, {Env, [], []}, Ts),
725    {Ts1, {Bound, Free}}.
726
727%% In list comprehension generators, the pattern variables are always
728%% viewed as new occurrences, shadowing whatever is in the input
729%% environment (thus, the pattern contains no variable uses, only
730%% bindings). Bindings in the generator body are not exported.
731
732vann_generator(Tree, Env) ->
733    P = erl_syntax:generator_pattern(Tree),
734    {P1, Bound, _} = vann_pattern(P, []),
735    E = erl_syntax:generator_body(Tree),
736    {E1, _, Free} = vann(E, Env),
737    Tree1 = rewrite(Tree, erl_syntax:generator(P1, E1)),
738    {ann_bindings(Tree1, Env, Bound, Free), Bound, Free}.
739
740vann_binary_generator(Tree, Env) ->
741    P = erl_syntax:binary_generator_pattern(Tree),
742    {P1, Bound, _} = vann_pattern(P, Env),
743    E = erl_syntax:binary_generator_body(Tree),
744    {E1, _, Free} = vann(E, Env),
745    Tree1 = rewrite(Tree, erl_syntax:binary_generator(P1, E1)),
746    {ann_bindings(Tree1, Env, Bound, Free), Bound, Free}.
747
748vann_block_expr(Tree, Env) ->
749    Es = erl_syntax:block_expr_body(Tree),
750    {Es1, {Bound, Free}} = vann_body(Es, Env),
751    Tree1 = rewrite(Tree, erl_syntax:block_expr(Es1)),
752    {ann_bindings(Tree1, Env, Bound, Free), Bound, Free}.
753
754vann_body_join() ->
755    fun (T, {Env, Bound, Free}) ->
756            {T1, Bound1, Free1} = vann(T, Env),
757            Env1 = ordsets:union(Env, Bound1),
758            {T1, {Env1, ordsets:union(Bound, Bound1),
759                  ordsets:union(Free,
760                                ordsets:subtract(Free1, Bound))}}
761    end.
762
763vann_body(Ts, Env) ->
764    {Ts1, {_, Bound, Free}} = lists:mapfoldl(vann_body_join(),
765                                             {Env, [], []}, Ts),
766    {Ts1, {Bound, Free}}.
767
768%% Macro names must be ignored even if they happen to be variables,
769%% lexically speaking.
770
771vann_macro(Tree, Env) ->
772    {As, {Bound, Free}} = case erl_syntax:macro_arguments(Tree) of
773                              none ->
774                                  {none, {[], []}};
775                              As1 ->
776                                  vann_list(As1, Env)
777                          end,
778    N = erl_syntax:macro_name(Tree),
779    Tree1 = rewrite(Tree, erl_syntax:macro(N, As)),
780    {ann_bindings(Tree1, Env, Bound, Free), Bound, Free}.
781
782vann_pattern(Tree, Env) ->
783    case erl_syntax:type(Tree) of
784        variable ->
785            V = erl_syntax:variable_name(Tree),
786            case ordsets:is_element(V, Env) of
787                true ->
788                    %% Variable use
789                    Bound = [],
790                    Free = [V],
791                    {ann_bindings(Tree, Env, Bound, Free), Bound, Free};
792                false ->
793                    %% Variable binding
794                    Bound = [V],
795                    Free = [],
796                    {ann_bindings(Tree, Env, Bound, Free), Bound, Free}
797            end;
798        match_expr ->
799            %% Alias pattern
800            P = erl_syntax:match_expr_pattern(Tree),
801            {P1, Bound1, Free1} = vann_pattern(P, Env),
802            E = erl_syntax:match_expr_body(Tree),
803            {E1, Bound2, Free2} = vann_pattern(E, Env),
804            Bound = ordsets:union(Bound1, Bound2),
805            Free = ordsets:union(Free1, Free2),
806            Tree1 = rewrite(Tree, erl_syntax:match_expr(P1, E1)),
807            {ann_bindings(Tree1, Env, Bound, Free), Bound, Free};
808        macro ->
809            %% The macro name must be ignored. The arguments are treated
810            %% as patterns.
811            {As, {Bound, Free}} =
812                case erl_syntax:macro_arguments(Tree) of
813                    none ->
814                        {none, {[], []}};
815                    As1 ->
816                        vann_patterns(As1, Env)
817                end,
818            N = erl_syntax:macro_name(Tree),
819            Tree1 = rewrite(Tree, erl_syntax:macro(N, As)),
820            {ann_bindings(Tree1, Env, Bound, Free), Bound, Free};
821        _Type ->
822            F = vann_patterns_join(Env),
823            {Tree1, {Bound, Free}} = mapfold_subtrees(F, {[], []},
824                                                      Tree),
825            {ann_bindings(Tree1, Env, Bound, Free), Bound, Free}
826    end.
827
828vann_patterns_join(Env) ->
829    fun (T, {Bound, Free}) ->
830            {T1, Bound1, Free1} = vann_pattern(T, Env),
831            {T1, {ordsets:union(Bound, Bound1),
832                  ordsets:union(Free, Free1)}}
833    end.
834
835vann_patterns(Ps, Env) ->
836    lists:mapfoldl(vann_patterns_join(Env), {[], []}, Ps).
837
838vann_clause(C, Env) ->
839    {Ps, {Bound1, Free1}} = vann_patterns(erl_syntax:clause_patterns(C),
840                                          Env),
841    Env1 = ordsets:union(Env, Bound1),
842    %% Guards cannot add bindings
843    {G1, _, Free2} = case erl_syntax:clause_guard(C) of
844                         none ->
845                             {none, [], []};
846                         G ->
847                             vann(G, Env1)
848                     end,
849    {Es, {Bound2, Free3}} = vann_body(erl_syntax:clause_body(C), Env1),
850    Bound = ordsets:union(Bound1, Bound2),
851    Free = ordsets:union(Free1,
852                         ordsets:subtract(ordsets:union(Free2, Free3),
853                                          Bound1)),
854    Tree1 = rewrite(C, erl_syntax:clause(Ps, G1, Es)),
855    {ann_bindings(Tree1, Env, Bound, Free), Bound, Free}.
856
857vann_clauses_join(Env) ->
858    fun (C, {Bound, Free}) ->
859            {C1, Bound1, Free1} = vann_clause(C, Env),
860            {C1, {ordsets:intersection(Bound, Bound1),
861                  ordsets:union(Free, Free1)}}
862    end.
863
864vann_clauses([C | Cs], Env) ->
865    {C1, Bound, Free} = vann_clause(C, Env),
866    {Cs1, BF} = lists:mapfoldl(vann_clauses_join(Env), {Bound, Free}, Cs),
867    {[C1 | Cs1], BF};
868vann_clauses([], _Env) ->
869    {[], {[], []}}.
870
871ann_bindings(Tree, Env, Bound, Free) ->
872    As0 = erl_syntax:get_ann(Tree),
873    As1 = [{env, Env},
874           {bound, Bound},
875           {free, Free}
876           | delete_binding_anns(As0)],
877    erl_syntax:set_ann(Tree, As1).
878
879delete_binding_anns([{env, _} | As]) ->
880    delete_binding_anns(As);
881delete_binding_anns([{bound, _} | As]) ->
882    delete_binding_anns(As);
883delete_binding_anns([{free, _} | As]) ->
884    delete_binding_anns(As);
885delete_binding_anns([A | As]) ->
886    [A | delete_binding_anns(As)];
887delete_binding_anns([]) ->
888    [].
889
890
891%% =====================================================================
892%% @spec is_fail_expr(Tree::syntaxTree()) -> boolean()
893%%
894%% @doc Returns `true' if `Tree' represents an
895%% expression which never terminates normally. Note that the reverse
896%% does not apply. Currently, the detected cases are calls to
897%% `exit/1', `throw/1',
898%% `erlang:error/1' and `erlang:error/2'.
899%%
900%% @see //erts/erlang:exit/1
901%% @see //erts/erlang:throw/1
902%% @see //erts/erlang:error/1
903%% @see //erts/erlang:error/2
904
905-spec is_fail_expr(erl_syntax:syntaxTree()) -> boolean().
906
907is_fail_expr(E) ->
908    case erl_syntax:type(E) of
909        application ->
910            N = length(erl_syntax:application_arguments(E)),
911            F = erl_syntax:application_operator(E),
912            case catch {ok, analyze_function_name(F)} of
913                syntax_error ->
914                    false;
915                {ok, exit} when N =:= 1 ->
916                    true;
917                {ok, throw} when N =:= 1 ->
918                    true;
919                {ok, {erlang, exit}} when N =:= 1 ->
920                    true;
921                {ok, {erlang, throw}} when N =:= 1 ->
922                    true;
923                {ok, {erlang, error}} when N =:= 1 ->
924                    true;
925                {ok, {erlang, error}} when N =:= 2 ->
926                    true;
927                {ok, {erlang, fault}} when N =:= 1 ->
928                    true;
929                {ok, {erlang, fault}} when N =:= 2 ->
930                    true;
931                _ ->
932                    false
933            end;
934        _ ->
935            false
936    end.
937
938
939%% =====================================================================
940%% @spec analyze_forms(Forms) -> [{Key, term()}]
941%%
942%%          Forms = syntaxTree() | [syntaxTree()]
943%%          Key = attributes | errors | exports | functions | imports
944%%                | module | records | warnings
945%%
946%% @doc Analyzes a sequence of "program forms". The given
947%% `Forms' may be a single syntax tree of type
948%% `form_list', or a list of "program form" syntax trees. The
949%% returned value is a list of pairs `{Key, Info}', where
950%% each value of `Key' occurs at most once in the list; the
951%% absence of a particular key indicates that there is no well-defined
952%% value for that key.
953%%
954%% Each entry in the resulting list contains the following
955%% corresponding information about the program forms:
956%% <dl>
957%%     <dt>`{attributes, Attributes}'</dt>
958%%       <dd><ul>
959%% 	   <li>`Attributes = [{atom(), term()}]'</li>
960%%       </ul>
961%% 	 `Attributes' is a list of pairs representing the
962%% 	 names and corresponding values of all so-called "wild"
963%% 	 attributes (as e.g. "`-compile(...)'") occurring in
964%% 	 `Forms' (cf. `analyze_wild_attribute/1').
965%% 	 We do not guarantee that each name occurs at most once in the
966%% 	 list. The order of listing is not defined.</dd>
967%%
968%%     <dt>`{errors, Errors}'</dt>
969%%       <dd><ul>
970%% 	   <li>`Errors = [term()]'</li>
971%%       </ul>
972%% 	 `Errors' is the list of error descriptors of all
973%% 	 `error_marker' nodes that occur in
974%% 	 `Forms'. The order of listing is not defined.</dd>
975%%
976%%     <dt>`{exports, Exports}'</dt>
977%%       <dd><ul>
978%% 	    <li>`Exports = [FunctionName]'</li>
979%% 	    <li>`FunctionName = atom()
980%%                    | {atom(), integer()}
981%% 		      | {ModuleName, FunctionName}'</li>
982%% 	    <li>`ModuleName = atom()'</li>
983%%       </ul>
984%% 	 `Exports' is a list of representations of those
985%% 	 function names that are listed by export declaration attributes
986%% 	 in `Forms' (cf.
987%% 	 `analyze_export_attribute/1'). We do not guarantee
988%% 	 that each name occurs at most once in the list. The order of
989%% 	 listing is not defined.</dd>
990%%
991%%     <dt>`{functions, Functions}'</dt>
992%%       <dd><ul>
993%% 	    <li>`Functions = [{atom(), integer()}]'</li>
994%%       </ul>
995%% 	 `Functions' is a list of the names of the functions
996%% 	 that are defined in `Forms' (cf.
997%% 	 `analyze_function/1'). We do not guarantee that each
998%% 	 name occurs at most once in the list. The order of listing is
999%% 	 not defined.</dd>
1000%%
1001%%     <dt>`{imports, Imports}'</dt>
1002%%       <dd><ul>
1003%% 	    <li>`Imports = [{Module, Names}]'</li>
1004%% 	    <li>`Module = atom()'</li>
1005%% 	    <li>`Names = [FunctionName]'</li>
1006%% 	    <li>`FunctionName = atom()
1007%%                    | {atom(), integer()}
1008%% 		      | {ModuleName, FunctionName}'</li>
1009%% 	    <li>`ModuleName = atom()'</li>
1010%%       </ul>
1011%% 	 `Imports' is a list of pairs representing those
1012%% 	 module names and corresponding function names that are listed
1013%% 	 by import declaration attributes in `Forms' (cf.
1014%% 	 `analyze_import_attribute/1'), where each
1015%% 	 `Module' occurs at most once in
1016%% 	 `Imports'. We do not guarantee that each name occurs
1017%% 	 at most once in the lists of function names. The order of
1018%% 	 listing is not defined.</dd>
1019%%
1020%%     <dt>`{module, ModuleName}'</dt>
1021%%       <dd><ul>
1022%% 	    <li>`ModuleName = atom()'</li>
1023%%       </ul>
1024%% 	 `ModuleName' is the name declared by a module
1025%% 	 attribute in `Forms'. If no module name is defined
1026%% 	 in `Forms', the result will contain no entry for the
1027%% 	 `module' key. If multiple module name declarations
1028%% 	 should occur, all but the first will be ignored.</dd>
1029%%
1030%%     <dt>`{records, Records}'</dt>
1031%%       <dd><ul>
1032%% 	    <li>`Records = [{atom(), Fields}]'</li>
1033%% 	    <li>`Fields = [{atom(), {Default, Type}}]'</li>
1034%% 	    <li>`Default = none | syntaxTree()'</li>
1035%% 	    <li>`Type = none | syntaxTree()'</li>
1036%%       </ul>
1037%% 	 `Records' is a list of pairs representing the names
1038%% 	 and corresponding field declarations of all record declaration
1039%% 	 attributes occurring in `Forms'. For fields declared
1040%% 	 without a default value, the corresponding value for
1041%% 	 `Default' is the atom `none'. Similarly, for fields declared
1042%%       without a type, the corresponding value for `Type' is the
1043%%       atom `none' (cf.
1044%% 	 `analyze_record_attribute/1'). We do not guarantee
1045%% 	 that each record name occurs at most once in the list. The
1046%% 	 order of listing is not defined.</dd>
1047%%
1048%%     <dt>`{warnings, Warnings}'</dt>
1049%%       <dd><ul>
1050%% 	    <li>`Warnings = [term()]'</li>
1051%%       </ul>
1052%% 	 `Warnings' is the list of error descriptors of all
1053%% 	 `warning_marker' nodes that occur in
1054%% 	 `Forms'. The order of listing is not defined.</dd>
1055%% </dl>
1056%%
1057%% The evaluation throws `syntax_error' if an ill-formed
1058%% Erlang construct is encountered.
1059%%
1060%% @see analyze_wild_attribute/1
1061%% @see analyze_export_attribute/1
1062%% @see analyze_function/1
1063%% @see analyze_import_attribute/1
1064%% @see analyze_record_attribute/1
1065%% @see erl_syntax:error_marker_info/1
1066%% @see erl_syntax:warning_marker_info/1
1067
1068-type key() :: 'attributes' | 'errors' | 'exports' | 'functions' | 'imports'
1069             | 'module' | 'records' | 'warnings'.
1070-type info_pair() :: {key(), term()}.
1071
1072-spec analyze_forms(erl_syntax:forms()) -> [info_pair()].
1073
1074analyze_forms(Forms) when is_list(Forms) ->
1075    finfo_to_list(lists:foldl(fun collect_form/2, new_finfo(), Forms));
1076analyze_forms(Forms) ->
1077    analyze_forms(
1078      erl_syntax:form_list_elements(
1079        erl_syntax:flatten_form_list(Forms))).
1080
1081collect_form(Node, Info) ->
1082    case analyze_form(Node) of
1083        {attribute, {Name, Data}} ->
1084            collect_attribute(Name, Data, Info);
1085        {attribute, preprocessor} ->
1086            Info;
1087        {function, Name} ->
1088            finfo_add_function(Name, Info);
1089        {error_marker, Data} ->
1090            finfo_add_error(Data, Info);
1091        {warning_marker, Data} ->
1092            finfo_add_warning(Data, Info);
1093        _ ->
1094            Info
1095    end.
1096
1097collect_attribute(module, M, Info) ->
1098    finfo_set_module(M, Info);
1099collect_attribute(export, L, Info) ->
1100    finfo_add_exports(L, Info);
1101collect_attribute(import, {M, L}, Info) ->
1102    finfo_add_imports(M, L, Info);
1103collect_attribute(import, M, Info) ->
1104    finfo_add_module_import(M, Info);
1105collect_attribute(file, _, Info) ->
1106    Info;
1107collect_attribute(record, {R, L}, Info) ->
1108    finfo_add_record(R, L, Info);
1109collect_attribute(_, {N, V}, Info) ->
1110    finfo_add_attribute(N, V, Info).
1111
1112%% Abstract datatype for collecting module information.
1113
1114-record(forms, {module         = none :: 'none' | {'value', atom()},
1115		exports        = []   :: [{atom(), arity()}],
1116		module_imports = []   :: [atom()],
1117		imports        = []   :: [{atom(), [{atom(), arity()}]}],
1118		attributes     = []   :: [{atom(), term()}],
1119		records        = []   :: [{atom(), [{atom(),
1120                                                     field_default(),
1121                                                     field_type()}]}],
1122		errors         = []   :: [term()],
1123		warnings       = []   :: [term()],
1124		functions      = []   :: [{atom(), arity()}]}).
1125
1126-type field_default() :: 'none' | erl_syntax:syntaxTree().
1127-type field_type()    :: 'none' | erl_syntax:syntaxTree().
1128
1129new_finfo() ->
1130    #forms{}.
1131
1132finfo_set_module(Name, Info) ->
1133    case Info#forms.module of
1134        none ->
1135            Info#forms{module = {value, Name}};
1136        {value, _} ->
1137            Info
1138    end.
1139
1140finfo_add_exports(L, Info) ->
1141    Info#forms{exports = L ++ Info#forms.exports}.
1142
1143finfo_add_module_import(M, Info) ->
1144    Info#forms{module_imports = [M | Info#forms.module_imports]}.
1145
1146finfo_add_imports(M, L, Info) ->
1147    Es = Info#forms.imports,
1148    case lists:keyfind(M, 1, Es) of
1149        {_, L1} ->
1150            Es1 = lists:keyreplace(M, 1, Es, {M, L ++ L1}),
1151            Info#forms{imports = Es1};
1152        false ->
1153            Info#forms{imports = [{M, L} | Es]}
1154    end.
1155
1156finfo_add_attribute(Name, Val, Info) ->
1157    Info#forms{attributes = [{Name, Val} | Info#forms.attributes]}.
1158
1159finfo_add_record(R, L, Info) ->
1160    Info#forms{records = [{R, L} | Info#forms.records]}.
1161
1162finfo_add_error(R, Info) ->
1163    Info#forms{errors = [R | Info#forms.errors]}.
1164
1165finfo_add_warning(R, Info) ->
1166    Info#forms{warnings = [R | Info#forms.warnings]}.
1167
1168finfo_add_function(F, Info) ->
1169    Info#forms{functions = [F | Info#forms.functions]}.
1170
1171finfo_to_list(Info) ->
1172    [{Key, Value}
1173     || {Key, {value, Value}} <-
1174            [{module, Info#forms.module},
1175             {exports, list_value(Info#forms.exports)},
1176             {imports, list_value(Info#forms.imports)},
1177             {module_imports, list_value(Info#forms.module_imports)},
1178             {attributes, list_value(Info#forms.attributes)},
1179             {records, list_value(Info#forms.records)},
1180             {errors, list_value(Info#forms.errors)},
1181             {warnings, list_value(Info#forms.warnings)},
1182             {functions, list_value(Info#forms.functions)}
1183            ]].
1184
1185list_value([]) ->
1186    none;
1187list_value(List) ->
1188    {value, List}.
1189
1190
1191%% =====================================================================
1192%% @spec analyze_form(Node::syntaxTree()) -> {atom(), term()} | atom()
1193%%
1194%% @doc Analyzes a "source code form" node. If `Node' is a
1195%% "form" type (cf. `erl_syntax:is_form/1'), the returned
1196%% value is a tuple `{Type, Info}' where `Type' is
1197%% the node type and `Info' depends on `Type', as
1198%% follows:
1199%% <dl>
1200%%   <dt>`{attribute, Info}'</dt>
1201%%
1202%%      <dd>where `Info = analyze_attribute(Node)'.</dd>
1203%%
1204%%   <dt>`{error_marker, Info}'</dt>
1205%%
1206%% 	<dd>where `Info =
1207%% 	erl_syntax:error_marker_info(Node)'.</dd>
1208%%
1209%%   <dt>`{function, Info}'</dt>
1210%%
1211%% 	    <dd>where `Info = analyze_function(Node)'.</dd>
1212%%
1213%%   <dt>`{warning_marker, Info}'</dt>
1214%%
1215%% 	    <dd>where `Info =
1216%% 	    erl_syntax:warning_marker_info(Node)'.</dd>
1217%% </dl>
1218%% For other types of forms, only the node type is returned.
1219%%
1220%% The evaluation throws `syntax_error' if
1221%% `Node' is not well-formed.
1222%%
1223%% @see analyze_attribute/1
1224%% @see analyze_function/1
1225%% @see erl_syntax:is_form/1
1226%% @see erl_syntax:error_marker_info/1
1227%% @see erl_syntax:warning_marker_info/1
1228
1229-spec analyze_form(erl_syntax:syntaxTree()) -> {atom(), term()} | atom().
1230
1231analyze_form(Node) ->
1232    case erl_syntax:type(Node) of
1233        attribute ->
1234            {attribute, analyze_attribute(Node)};
1235        function ->
1236            {function, analyze_function(Node)};
1237        error_marker ->
1238            {error_marker, erl_syntax:error_marker_info(Node)};
1239        warning_marker ->
1240            {warning_marker, erl_syntax:warning_marker_info(Node)};
1241        _ ->
1242            case erl_syntax:is_form(Node) of
1243                true ->
1244                    erl_syntax:type(Node);
1245                false ->
1246                    throw(syntax_error)
1247            end
1248    end.
1249
1250%% =====================================================================
1251%% @spec analyze_attribute(Node::syntaxTree()) ->
1252%%           preprocessor | {atom(), atom()}
1253%%
1254%% @doc Analyzes an attribute node. If `Node' represents a
1255%% preprocessor directive, the atom `preprocessor' is
1256%% returned. Otherwise, if `Node' represents a module
1257%% attribute "`-<em>Name</em>...'", a tuple `{Name,
1258%% Info}' is returned, where `Info' depends on
1259%% `Name', as follows:
1260%% <dl>
1261%%     <dt>`{module, Info}'</dt>
1262%%
1263%% 	    <dd>where `Info =
1264%% 	    analyze_module_attribute(Node)'.</dd>
1265%%
1266%%     <dt>`{export, Info}'</dt>
1267%%
1268%% 	    <dd>where `Info =
1269%% 	    analyze_export_attribute(Node)'.</dd>
1270%%
1271%%     <dt>`{import, Info}'</dt>
1272%%
1273%% 	    <dd>where `Info =
1274%% 	    analyze_import_attribute(Node)'.</dd>
1275%%
1276%%     <dt>`{file, Info}'</dt>
1277%%
1278%% 	    <dd>where `Info =
1279%% 	    analyze_file_attribute(Node)'.</dd>
1280%%
1281%%     <dt>`{record, Info}'</dt>
1282%%
1283%% 	    <dd>where `Info =
1284%% 	    analyze_record_attribute(Node)'.</dd>
1285%%
1286%%     <dt>`{Name, Info}'</dt>
1287%%
1288%% 	    <dd>where `{Name, Info} =
1289%% 	    analyze_wild_attribute(Node)'.</dd>
1290%% </dl>
1291%% The evaluation throws `syntax_error' if `Node'
1292%% does not represent a well-formed module attribute.
1293%%
1294%% @see analyze_module_attribute/1
1295%% @see analyze_export_attribute/1
1296%% @see analyze_import_attribute/1
1297%% @see analyze_file_attribute/1
1298%% @see analyze_record_attribute/1
1299%% @see analyze_wild_attribute/1
1300
1301-spec analyze_attribute(erl_syntax:syntaxTree()) ->
1302        'preprocessor' | {atom(), term()}.  % XXX: underspecified
1303
1304analyze_attribute(Node) ->
1305    Name = erl_syntax:attribute_name(Node),
1306    case erl_syntax:type(Name) of
1307        atom ->
1308            case erl_syntax:atom_value(Name) of
1309                define -> preprocessor;
1310                undef -> preprocessor;
1311                include -> preprocessor;
1312                include_lib -> preprocessor;
1313                ifdef -> preprocessor;
1314                ifndef -> preprocessor;
1315                'if' -> preprocessor;
1316                elif -> preprocessor;
1317                else -> preprocessor;
1318                endif -> preprocessor;
1319                A ->
1320                    {A, analyze_attribute(A, Node)}
1321            end;
1322        _ ->
1323            throw(syntax_error)
1324    end.
1325
1326analyze_attribute(module, Node) ->
1327    analyze_module_attribute(Node);
1328analyze_attribute(export, Node) ->
1329    analyze_export_attribute(Node);
1330analyze_attribute(import, Node) ->
1331    analyze_import_attribute(Node);
1332analyze_attribute(file, Node) ->
1333    analyze_file_attribute(Node);
1334analyze_attribute(record, Node) ->
1335    analyze_record_attribute(Node);
1336analyze_attribute(_, Node) ->
1337    %% A "wild" attribute (such as e.g. a `compile' directive).
1338    analyze_wild_attribute(Node).
1339
1340
1341%% =====================================================================
1342%% @spec analyze_module_attribute(Node::syntaxTree()) ->
1343%%           Name::atom() | {Name::atom(), Variables::[atom()]}
1344%%
1345%% @doc Returns the module name and possible parameters declared by a
1346%% module attribute. If the attribute is a plain module declaration such
1347%% as `-module(name)', the result is the module name. If the attribute
1348%% is a parameterized module declaration, the result is a tuple
1349%% containing the module name and a list of the parameter variable
1350%% names.
1351%%
1352%% The evaluation throws `syntax_error' if `Node' does not represent a
1353%% well-formed module attribute.
1354%%
1355%% @see analyze_attribute/1
1356
1357-spec analyze_module_attribute(erl_syntax:syntaxTree()) ->
1358        atom() | {atom(), [atom()]}.
1359
1360analyze_module_attribute(Node) ->
1361    case erl_syntax:type(Node) of
1362        attribute ->
1363            case erl_syntax:attribute_arguments(Node) of
1364                [M] ->
1365                    module_name_to_atom(M);
1366                [M, L] ->
1367		    M1 = module_name_to_atom(M),
1368		    L1 = analyze_variable_list(L),
1369		    {M1, L1};
1370                _ ->
1371                    throw(syntax_error)
1372            end;
1373        _ ->
1374            throw(syntax_error)
1375    end.
1376
1377analyze_variable_list(Node) ->
1378    case erl_syntax:is_proper_list(Node) of
1379        true ->
1380            [erl_syntax:variable_name(V)
1381	     || V <- erl_syntax:list_elements(Node)];
1382        false ->
1383            throw(syntax_error)
1384    end.
1385
1386
1387%% =====================================================================
1388%% @spec analyze_export_attribute(Node::syntaxTree()) -> [FunctionName]
1389%%
1390%%          FunctionName = atom() | {atom(), integer()}
1391%%                       | {ModuleName, FunctionName}
1392%%          ModuleName = atom()
1393%%
1394%% @doc Returns the list of function names declared by an export
1395%% attribute. We do not guarantee that each name occurs at most once in
1396%% the list. The order of listing is not defined.
1397%%
1398%% The evaluation throws `syntax_error' if `Node' does not represent a
1399%% well-formed export attribute.
1400%%
1401%% @see analyze_attribute/1
1402
1403-type functionN()    :: atom() | {atom(), arity()}.
1404-type functionName() :: functionN() | {atom(), functionN()}.
1405
1406-spec analyze_export_attribute(erl_syntax:syntaxTree()) -> [functionName()].
1407
1408analyze_export_attribute(Node) ->
1409    case erl_syntax:type(Node) of
1410        attribute ->
1411            case erl_syntax:attribute_arguments(Node) of
1412                [L] ->
1413                    analyze_function_name_list(L);
1414                _ ->
1415                    throw(syntax_error)
1416            end;
1417        _ ->
1418            throw(syntax_error)
1419    end.
1420
1421analyze_function_name_list(Node) ->
1422    case erl_syntax:is_proper_list(Node) of
1423        true ->
1424            [analyze_function_name(F)
1425             || F <- erl_syntax:list_elements(Node)];
1426        false ->
1427            throw(syntax_error)
1428    end.
1429
1430
1431%% =====================================================================
1432%% @spec analyze_function_name(Node::syntaxTree()) -> FunctionName
1433%%
1434%%          FunctionName = atom() | {atom(), integer()}
1435%%                       | {ModuleName, FunctionName}
1436%%          ModuleName = atom()
1437%%
1438%% @doc Returns the function name represented by a syntax tree. If
1439%% `Node' represents a function name, such as
1440%% "`foo/1'" or "`bloggs:fred/2'", a uniform
1441%% representation of that name is returned. Different nestings of arity
1442%% and module name qualifiers in the syntax tree does not affect the
1443%% result.
1444%%
1445%% The evaluation throws `syntax_error' if
1446%% `Node' does not represent a well-formed function name.
1447
1448-spec analyze_function_name(erl_syntax:syntaxTree()) -> functionName().
1449
1450analyze_function_name(Node) ->
1451    case erl_syntax:type(Node) of
1452        atom ->
1453            erl_syntax:atom_value(Node);
1454        arity_qualifier ->
1455            A = erl_syntax:arity_qualifier_argument(Node),
1456            case erl_syntax:type(A) of
1457                integer ->
1458                    F = erl_syntax:arity_qualifier_body(Node),
1459                    F1 = analyze_function_name(F),
1460                    append_arity(erl_syntax:integer_value(A), F1);
1461                _ ->
1462                    throw(syntax_error)
1463            end;
1464        module_qualifier ->
1465            M = erl_syntax:module_qualifier_argument(Node),
1466            case erl_syntax:type(M) of
1467                atom ->
1468                    F = erl_syntax:module_qualifier_body(Node),
1469                    F1 = analyze_function_name(F),
1470                    {erl_syntax:atom_value(M), F1};
1471                _ ->
1472                    throw(syntax_error)
1473            end;
1474        _ ->
1475            throw(syntax_error)
1476    end.
1477
1478append_arity(A, {Module, Name}) ->
1479    {Module, append_arity(A, Name)};
1480append_arity(A, Name) when is_atom(Name) ->
1481    {Name, A};
1482append_arity(A, A) ->
1483    A;
1484append_arity(_A, Name) ->
1485    Name.    % quietly drop extra arity in case of conflict
1486
1487
1488%% =====================================================================
1489%% @spec analyze_import_attribute(Node::syntaxTree()) ->
1490%%           {atom(), [FunctionName]} | atom()
1491%%
1492%%          FunctionName = atom() | {atom(), integer()}
1493%%                       | {ModuleName, FunctionName}
1494%%          ModuleName = atom()
1495%%
1496%% @doc Returns the module name and (if present) list of function names
1497%% declared by an import attribute. The returned value is an atom
1498%% `Module' or a pair `{Module, Names}', where
1499%% `Names' is a list of function names declared as imported
1500%% from the module named by `Module'. We do not guarantee
1501%% that each name occurs at most once in `Names'. The order
1502%% of listing is not defined.
1503%%
1504%% The evaluation throws `syntax_error' if `Node' does not represent a
1505%% well-formed import attribute.
1506%%
1507%% @see analyze_attribute/1
1508
1509-spec analyze_import_attribute(erl_syntax:syntaxTree()) ->
1510        {atom(), [functionName()]} | atom().
1511
1512analyze_import_attribute(Node) ->
1513    case erl_syntax:type(Node) of
1514        attribute ->
1515            case erl_syntax:attribute_arguments(Node) of
1516		[M] ->
1517		    module_name_to_atom(M);
1518		[M, L] ->
1519		    M1 = module_name_to_atom(M),
1520		    L1 = analyze_function_name_list(L),
1521		    {M1, L1};
1522                _ ->
1523                    throw(syntax_error)
1524            end;
1525        _ ->
1526            throw(syntax_error)
1527    end.
1528
1529
1530%% =====================================================================
1531%% @spec analyze_type_name(Node::syntaxTree()) -> TypeName
1532%%
1533%%          TypeName = atom()
1534%%                   | {atom(), integer()}
1535%%                   | {ModuleName, {atom(), integer()}}
1536%%          ModuleName = atom()
1537%%
1538%% @doc Returns the type name represented by a syntax tree. If
1539%% `Node' represents a type name, such as
1540%% "`foo/1'" or "`bloggs:fred/2'", a uniform
1541%% representation of that name is returned.
1542%%
1543%% The evaluation throws `syntax_error' if
1544%% `Node' does not represent a well-formed type name.
1545
1546-spec analyze_type_name(erl_syntax:syntaxTree()) -> typeName().
1547
1548analyze_type_name(Node) ->
1549    case erl_syntax:type(Node) of
1550        atom ->
1551            erl_syntax:atom_value(Node);
1552        arity_qualifier ->
1553            A = erl_syntax:arity_qualifier_argument(Node),
1554            N = erl_syntax:arity_qualifier_body(Node),
1555
1556            case ((erl_syntax:type(A) =:= integer)
1557                  and (erl_syntax:type(N) =:= atom))
1558            of
1559                true ->
1560                    append_arity(erl_syntax:integer_value(A),
1561                                 erl_syntax:atom_value(N));
1562                _ ->
1563                    throw(syntax_error)
1564            end;
1565        module_qualifier ->
1566            M = erl_syntax:module_qualifier_argument(Node),
1567            case erl_syntax:type(M) of
1568                atom ->
1569                    N = erl_syntax:module_qualifier_body(Node),
1570                    N1 = analyze_type_name(N),
1571                    {erl_syntax:atom_value(M), N1};
1572                _ ->
1573                    throw(syntax_error)
1574            end;
1575        _ ->
1576            throw(syntax_error)
1577    end.
1578
1579%% =====================================================================
1580%% @spec analyze_wild_attribute(Node::syntaxTree()) -> {atom(), term()}
1581%%
1582%% @doc Returns the name and value of a "wild" attribute. The result is
1583%% the pair `{Name, Value}', if `Node' represents "`-Name(Value)'".
1584%%
1585%% Note that no checking is done whether `Name' is a
1586%% reserved attribute name such as `module' or
1587%% `export': it is assumed that the attribute is "wild".
1588%%
1589%% The evaluation throws `syntax_error' if `Node' does not represent a
1590%% well-formed wild attribute.
1591%%
1592%% @see analyze_attribute/1
1593
1594-spec analyze_wild_attribute(erl_syntax:syntaxTree()) -> {atom(), term()}.
1595
1596analyze_wild_attribute(Node) ->
1597    case erl_syntax:type(Node) of
1598        attribute ->
1599            N = erl_syntax:attribute_name(Node),
1600            case erl_syntax:type(N) of
1601                atom ->
1602                    case erl_syntax:attribute_arguments(Node) of
1603                        [V] ->
1604                            %% Note: does not work well with macros.
1605			    case catch {ok, erl_syntax:concrete(V)} of
1606				{ok, Val} ->
1607				    {erl_syntax:atom_value(N), Val};
1608				_ ->
1609				    throw(syntax_error)
1610			    end;
1611                        _ ->
1612                            throw(syntax_error)
1613                    end;
1614                _ ->
1615                    throw(syntax_error)
1616            end;
1617        _ ->
1618            throw(syntax_error)
1619    end.
1620
1621
1622%% =====================================================================
1623%% @spec analyze_record_attribute(Node::syntaxTree()) ->
1624%%           {atom(), Fields}
1625%%
1626%% 	    Fields = [{atom(), {Default, Type}}]
1627%% 	    Default = none | syntaxTree()
1628%% 	    Type = none | syntaxTree()
1629%%
1630%% @doc Returns the name and the list of fields of a record declaration
1631%% attribute. The result is a pair `{Name, Fields}', if
1632%% `Node' represents "`-record(Name, {...}).'",
1633%% where `Fields' is a list of pairs `{Label,
1634%% {Default, Type}}' for each field "`Label'", "`Label =
1635%% <em>Default</em>'", "`Label :: <em>Type</em>'", or
1636%% "`Label = <em>Default</em> :: <em>Type</em>'" in the declaration,
1637%% listed in left-to-right
1638%% order. If the field has no default-value declaration, the value for
1639%% `Default' will be the atom `none'. If the field has no type declaration,
1640%% the value for `Type' will be the atom `none'. We do not
1641%% guarantee that each label occurs at most once in the list.
1642%%
1643%% The evaluation throws `syntax_error' if
1644%% `Node' does not represent a well-formed record declaration
1645%% attribute.
1646%%
1647%% @see analyze_attribute/1
1648%% @see analyze_record_field/1
1649
1650-type field() :: {atom(), {field_default(), field_type()}}.
1651
1652-type fields() :: [field()].
1653
1654-spec analyze_record_attribute(erl_syntax:syntaxTree()) -> {atom(), fields()}.
1655
1656analyze_record_attribute(Node) ->
1657    case erl_syntax:type(Node) of
1658        attribute ->
1659            case erl_syntax:attribute_arguments(Node) of
1660                [R, T] ->
1661                    case erl_syntax:type(R) of
1662                        atom ->
1663                            Es = analyze_record_attribute_tuple(T),
1664                            {erl_syntax:atom_value(R), Es};
1665                        _ ->
1666                            throw(syntax_error)
1667                    end;
1668                _ ->
1669                    throw(syntax_error)
1670            end;
1671        _ ->
1672            throw(syntax_error)
1673    end.
1674
1675analyze_record_attribute_tuple(Node) ->
1676    case erl_syntax:type(Node) of
1677        tuple ->
1678            [analyze_record_field(F)
1679	     || F <- erl_syntax:tuple_elements(Node)];
1680        _ ->
1681            throw(syntax_error)
1682    end.
1683
1684
1685%% =====================================================================
1686%% @spec analyze_record_expr(Node::syntaxTree()) ->
1687%%     {atom(), Info} | atom()
1688%%
1689%%    Info = {atom(), [{atom(), Value}]} | {atom(), atom()} | atom()
1690%%    Value = syntaxTree()
1691%%
1692%% @doc Returns the record name and field name/names of a record
1693%% expression. If `Node' has type `record_expr',
1694%% `record_index_expr' or `record_access', a pair
1695%% `{Type, Info}' is returned, otherwise an atom
1696%% `Type' is returned. `Type' is the node type of
1697%% `Node', and `Info' depends on
1698%% `Type', as follows:
1699%% <dl>
1700%%   <dt>`record_expr':</dt>
1701%%     <dd>`{atom(), [{atom(), Value}]}'</dd>
1702%%   <dt>`record_access':</dt>
1703%%     <dd>`{atom(), atom()}'</dd>
1704%%   <dt>`record_index_expr':</dt>
1705%%     <dd>`{atom(), atom()}'</dd>
1706%% </dl>
1707%%
1708%% For a `record_expr' node, `Info' represents
1709%% the record name and the list of descriptors for the involved fields,
1710%% listed in the order they appear. A field descriptor is a pair
1711%% `{Label, Value}', if `Node' represents "`Label = <em>Value</em>'".
1712%% For a `record_access' node,
1713%% `Info' represents the record name and the field name. For a
1714%% `record_index_expr' node, `Info' represents the
1715%% record name and the name field name.
1716%%
1717%% The evaluation throws `syntax_error' if
1718%% `Node' represents a record expression that is not
1719%% well-formed.
1720%%
1721%% @see analyze_record_attribute/1
1722%% @see analyze_record_field/1
1723
1724-type info() :: {atom(), [{atom(), erl_syntax:syntaxTree()}]}
1725              | {atom(), atom()} | atom().
1726
1727-spec analyze_record_expr(erl_syntax:syntaxTree()) -> {atom(), info()} | atom().
1728
1729analyze_record_expr(Node) ->
1730    case erl_syntax:type(Node) of
1731	record_expr ->
1732            A = erl_syntax:record_expr_type(Node),
1733            case erl_syntax:type(A) of
1734                atom ->
1735                    Fs0 = [analyze_record_field(F)
1736                           || F <- erl_syntax:record_expr_fields(Node)],
1737                    Fs = [{N, D} || {N, {D, _T}} <- Fs0],
1738                    {record_expr, {erl_syntax:atom_value(A), Fs}};
1739                _ ->
1740                    throw(syntax_error)
1741            end;
1742	record_access ->
1743	    F = erl_syntax:record_access_field(Node),
1744	    case erl_syntax:type(F) of
1745		atom ->
1746		    A = erl_syntax:record_access_type(Node),
1747                    case erl_syntax:type(A) of
1748                        atom ->
1749                            {record_access,
1750                             {erl_syntax:atom_value(A),
1751                              erl_syntax:atom_value(F)}};
1752                        _ ->
1753                            throw(syntax_error)
1754		    end;
1755		_ ->
1756		    throw(syntax_error)
1757	    end;
1758	record_index_expr ->
1759	    F = erl_syntax:record_index_expr_field(Node),
1760	    case erl_syntax:type(F) of
1761		atom ->
1762		    A = erl_syntax:record_index_expr_type(Node),
1763		    case erl_syntax:type(A) of
1764			atom ->
1765			    {record_index_expr,
1766			     {erl_syntax:atom_value(A),
1767			      erl_syntax:atom_value(F)}};
1768			_ ->
1769			    throw(syntax_error)
1770		    end;
1771		_ ->
1772		    throw(syntax_error)
1773	    end;
1774	Type ->
1775	    Type
1776    end.
1777
1778%% =====================================================================
1779%% @spec analyze_record_field(Node::syntaxTree()) -> {atom(), {Default, Type}}
1780%%
1781%%          Default = none | syntaxTree()
1782%%          Type = none | syntaxTree()
1783%%
1784%% @doc Returns the label, value-expression, and type of a record field
1785%% specifier. The result is a pair `{Label, {Default, Type}}', if
1786%% `Node' represents "`Label'", "`Label = <em>Default</em>'",
1787%% "`Label :: <em>Type</em>'", or
1788%%  "`Label = <em>Default</em> :: <em>Type</em>'".
1789%% If the field has no value-expression, the value for
1790%% `Default' will be the atom `none'. If the field has no type,
1791%% the value for `Type' will be the atom `none'.
1792%%
1793%% The evaluation throws `syntax_error' if
1794%% `Node' does not represent a well-formed record field
1795%% specifier.
1796%%
1797%% @see analyze_record_attribute/1
1798%% @see analyze_record_expr/1
1799
1800-spec analyze_record_field(erl_syntax:syntaxTree()) -> field().
1801
1802analyze_record_field(Node) ->
1803    case erl_syntax:type(Node) of
1804        record_field ->
1805            A = erl_syntax:record_field_name(Node),
1806            case erl_syntax:type(A) of
1807                atom ->
1808                    T = erl_syntax:record_field_value(Node),
1809                    {erl_syntax:atom_value(A), {T, none}};
1810                _ ->
1811                    throw(syntax_error)
1812            end;
1813        typed_record_field ->
1814            F = erl_syntax:typed_record_field_body(Node),
1815            {N, {V, _none}} = analyze_record_field(F),
1816            T = erl_syntax:typed_record_field_type(Node),
1817            {N, {V, T}};
1818        _ ->
1819            throw(syntax_error)
1820    end.
1821
1822
1823%% =====================================================================
1824%% @spec analyze_file_attribute(Node::syntaxTree()) ->
1825%%           {string(), integer()}
1826%%
1827%% @doc Returns the file name and line number of a `file'
1828%% attribute. The result is the pair `{File, Line}' if
1829%% `Node' represents "`-file(File, Line).'".
1830%%
1831%% The evaluation throws `syntax_error' if
1832%% `Node' does not represent a well-formed `file'
1833%% attribute.
1834%%
1835%% @see analyze_attribute/1
1836
1837-spec analyze_file_attribute(erl_syntax:syntaxTree()) -> {string(), integer()}.
1838
1839analyze_file_attribute(Node) ->
1840    case erl_syntax:type(Node) of
1841        attribute ->
1842            case erl_syntax:attribute_arguments(Node) of
1843                [F, N] ->
1844                    case (erl_syntax:type(F) =:= string)
1845                        and (erl_syntax:type(N) =:= integer) of
1846                        true ->
1847                            {erl_syntax:string_value(F),
1848                             erl_syntax:integer_value(N)};
1849                        false ->
1850                            throw(syntax_error)
1851                    end;
1852                _ ->
1853                    throw(syntax_error)
1854            end;
1855        _ ->
1856            throw(syntax_error)
1857    end.
1858
1859
1860%% =====================================================================
1861%% @spec analyze_function(Node::syntaxTree()) -> {atom(), integer()}
1862%%
1863%% @doc Returns the name and arity of a function definition. The result
1864%% is a pair `{Name, A}' if `Node' represents a
1865%% function definition "`Name(<em>P_1</em>, ..., <em>P_A</em>) ->
1866%% ...'".
1867%%
1868%% The evaluation throws `syntax_error' if
1869%% `Node' does not represent a well-formed function
1870%% definition.
1871
1872-spec analyze_function(erl_syntax:syntaxTree()) -> {atom(), arity()}.
1873
1874analyze_function(Node) ->
1875    case erl_syntax:type(Node) of
1876        function ->
1877            N = erl_syntax:function_name(Node),
1878            case erl_syntax:type(N) of
1879                atom ->
1880                    {erl_syntax:atom_value(N),
1881                     erl_syntax:function_arity(Node)};
1882                _ ->
1883                    throw(syntax_error)
1884            end;
1885        _ ->
1886            throw(syntax_error)
1887    end.
1888
1889
1890%% =====================================================================
1891%% @spec analyze_implicit_fun(Node::syntaxTree()) -> FunctionName
1892%%
1893%%          FunctionName = atom() | {atom(), integer()}
1894%%                       | {ModuleName, FunctionName}
1895%%          ModuleName = atom()
1896%%
1897%% @doc Returns the name of an implicit fun expression "`fun
1898%% <em>F</em>'". The result is a representation of the function
1899%% name `F'. (Cf. `analyze_function_name/1'.)
1900%%
1901%% The evaluation throws `syntax_error' if
1902%% `Node' does not represent a well-formed implicit fun.
1903%%
1904%% @see analyze_function_name/1
1905
1906-spec analyze_implicit_fun(erl_syntax:syntaxTree()) -> functionName().
1907
1908analyze_implicit_fun(Node) ->
1909    case erl_syntax:type(Node) of
1910        implicit_fun ->
1911            analyze_function_name(erl_syntax:implicit_fun_name(Node));
1912        _ ->
1913            throw(syntax_error)
1914    end.
1915
1916
1917%% =====================================================================
1918%% @spec analyze_application(Node::syntaxTree()) -> FunctionName | Arity
1919%%
1920%%          FunctionName = {atom(), Arity}
1921%%                       | {ModuleName, FunctionName}
1922%%          Arity = integer()
1923%%          ModuleName = atom()
1924%%
1925%% @doc Returns the name of a called function. The result is a
1926%% representation of the name of the applied function `F/A',
1927%% if `Node' represents a function application
1928%% "`<em>F</em>(<em>X_1</em>, ..., <em>X_A</em>)'". If the
1929%% function is not explicitly named (i.e., `F' is given by
1930%% some expression), only the arity `A' is returned.
1931%%
1932%% The evaluation throws `syntax_error' if `Node' does not represent a
1933%% well-formed application expression.
1934%%
1935%% @see analyze_function_name/1
1936
1937-type appFunName() :: {atom(), arity()} | {atom(), {atom(), arity()}}.
1938
1939-spec analyze_application(erl_syntax:syntaxTree()) -> appFunName() | arity().
1940
1941analyze_application(Node) ->
1942    case erl_syntax:type(Node) of
1943        application ->
1944            A = length(erl_syntax:application_arguments(Node)),
1945            F = erl_syntax:application_operator(Node),
1946            case catch {ok, analyze_function_name(F)} of
1947                syntax_error ->
1948                    A;
1949                {ok, N} ->
1950                    append_arity(A, N);
1951                _ ->
1952                    throw(syntax_error)
1953            end;
1954        _ ->
1955            throw(syntax_error)
1956    end.
1957
1958
1959%% =====================================================================
1960%% @spec analyze_type_application(Node::syntaxTree()) -> TypeName
1961%%
1962%%          TypeName = {atom(), integer()}
1963%%                   | {ModuleName, {atom(), integer()}}
1964%%          ModuleName = atom()
1965%%
1966%% @doc Returns the name of a used type. The result is a
1967%% representation of the name of the used pre-defined or local type `N/A',
1968%% if `Node' represents a local (user) type application
1969%% "`<em>N</em>(<em>T_1</em>, ..., <em>T_A</em>)'", or
1970%% a representation of the name of the used remote type `M:N/A'
1971%% if `Node' represents a remote user type application
1972%% "`<em>M</em>:<em>N</em>(<em>T_1</em>, ..., <em>T_A</em>)'".
1973%%
1974%% The evaluation throws `syntax_error' if `Node' does not represent a
1975%% well-formed (user) type application expression.
1976%%
1977%% @see analyze_type_name/1
1978
1979-type typeName() :: atom() | {module(), {atom(), arity()}} | {atom(), arity()}.
1980
1981-spec analyze_type_application(erl_syntax:syntaxTree()) -> typeName().
1982
1983analyze_type_application(Node) ->
1984    case erl_syntax:type(Node) of
1985        type_application ->
1986            A = length(erl_syntax:type_application_arguments(Node)),
1987            N = erl_syntax:type_application_name(Node),
1988            case catch {ok, analyze_type_name(N)} of
1989                {ok, TypeName} ->
1990                    append_arity(A, TypeName);
1991                _ ->
1992                    throw(syntax_error)
1993            end;
1994        user_type_application ->
1995            A = length(erl_syntax:user_type_application_arguments(Node)),
1996            N = erl_syntax:user_type_application_name(Node),
1997            case catch {ok, analyze_type_name(N)} of
1998                {ok, TypeName} ->
1999                    append_arity(A, TypeName);
2000                _ ->
2001                    throw(syntax_error)
2002            end;
2003        _ ->
2004            throw(syntax_error)
2005    end.
2006
2007
2008%% =====================================================================
2009%% @spec function_name_expansions(Names::[Name]) -> [{ShortName, Name}]
2010%%
2011%%          Name = ShortName | {atom(), Name}
2012%%          ShortName = atom() | {atom(), integer()}
2013%%
2014%% @doc Creates a mapping from corresponding short names to full
2015%% function names. Names are represented by nested tuples of atoms and
2016%% integers (cf. `analyze_function_name/1'). The result is a
2017%% list containing a pair `{ShortName, Name}' for each
2018%% element `Name' in the given list, where the corresponding
2019%% `ShortName' is the rightmost-innermost part of
2020%% `Name'. The list thus represents a finite mapping from
2021%% unqualified names to the corresponding qualified names.
2022%%
2023%% Note: the resulting list can contain more than one tuple
2024%% `{ShortName, Name}' for the same `ShortName',
2025%% possibly with different values for `Name', depending on
2026%% the given list.
2027%%
2028%% @see analyze_function_name/1
2029
2030-type shortname() :: atom() | {atom(), arity()}.
2031-type name()      :: shortname() | {atom(), shortname()}.
2032
2033-spec function_name_expansions([name()]) -> [{shortname(), name()}].
2034
2035function_name_expansions(Fs) ->
2036    function_name_expansions(Fs, []).
2037
2038function_name_expansions([F | Fs], Ack) ->
2039    function_name_expansions(Fs,
2040                             function_name_expansions(F, F, Ack));
2041function_name_expansions([], Ack) ->
2042    Ack.
2043
2044function_name_expansions({A, N}, Name, Ack) when is_integer(N) ->
2045    [{{A, N}, Name} | Ack];
2046function_name_expansions({_, N}, Name, Ack) ->
2047    function_name_expansions(N, Name,  Ack);
2048function_name_expansions(A, Name, Ack) ->
2049    [{A, Name} | Ack].
2050
2051
2052%% =====================================================================
2053%% @spec strip_comments(Tree::syntaxTree()) -> syntaxTree()
2054%%
2055%% @doc Removes all comments from all nodes of a syntax tree. All other
2056%% attributes (such as position information) remain unchanged.
2057%% Standalone comments in form lists are removed; any other standalone
2058%% comments are changed into null-comments (no text, no indentation).
2059
2060-spec strip_comments(erl_syntax:syntaxTree()) -> erl_syntax:syntaxTree().
2061
2062strip_comments(Tree) ->
2063    map(fun strip_comments_1/1, Tree).
2064
2065strip_comments_1(T) ->
2066    case erl_syntax:type(T) of
2067	form_list ->
2068	    Es = erl_syntax:form_list_elements(T),
2069	    Es1 = [E || E <- Es, erl_syntax:type(E) /= comment],
2070	    T1 = erl_syntax:copy_attrs(T, erl_syntax:form_list(Es1)),
2071	    erl_syntax:remove_comments(T1);
2072	comment ->
2073	    erl_syntax:comment([]);
2074	_ ->
2075	    erl_syntax:remove_comments(T)
2076    end.
2077
2078%% =====================================================================
2079%% @spec to_comment(Tree) -> syntaxTree()
2080%% @equiv to_comment(Tree, "% ")
2081
2082-spec to_comment(erl_syntax:syntaxTree()) -> erl_syntax:syntaxTree().
2083
2084to_comment(Tree) ->
2085    to_comment(Tree, "% ").
2086
2087%% =====================================================================
2088%% @spec to_comment(Tree::syntaxTree(), Prefix::string()) ->
2089%%           syntaxTree()
2090%%
2091%% @doc Equivalent to `to_comment(Tree, Prefix, F)' for a
2092%% default formatting function `F'. The default
2093%% `F' simply calls `erl_prettypr:format/1'.
2094%%
2095%% @see to_comment/3
2096%% @see erl_prettypr:format/1
2097
2098-spec to_comment(erl_syntax:syntaxTree(), string()) -> erl_syntax:syntaxTree().
2099
2100to_comment(Tree, Prefix) ->
2101    F = fun (T) -> erl_prettypr:format(T) end,
2102    to_comment(Tree, Prefix, F).
2103
2104%% =====================================================================
2105%% @spec to_comment(Tree::syntaxTree(), Prefix::string(), Printer) ->
2106%%           syntaxTree()
2107%%
2108%%          Printer = (syntaxTree()) -> string()
2109%%
2110%% @doc Transforms a syntax tree into an abstract comment. The lines of
2111%% the comment contain the text for `Node', as produced by
2112%% the given `Printer' function. Each line of the comment is
2113%% prefixed by the string `Prefix' (this does not include the
2114%% initial "`%'" character of the comment line).
2115%%
2116%% For example, the result of
2117%% `to_comment(erl_syntax:abstract([a,b,c]))' represents
2118%% <pre>
2119%%         %% [a,b,c]</pre>
2120%% (cf. `to_comment/1').
2121%%
2122%% Note: the text returned by the formatting function will be split
2123%% automatically into separate comment lines at each line break. No
2124%% extra work is needed.
2125%%
2126%% @see to_comment/1
2127%% @see to_comment/2
2128
2129-spec to_comment(erl_syntax:syntaxTree(), string(),
2130		 fun((erl_syntax:syntaxTree()) -> string())) ->
2131        erl_syntax:syntaxTree().
2132
2133to_comment(Tree, Prefix, F) ->
2134    erl_syntax:comment(split_lines(F(Tree), Prefix)).
2135
2136
2137%% =====================================================================
2138%% @spec limit(Tree, Depth) -> syntaxTree()
2139%%
2140%% @doc Equivalent to `limit(Tree, Depth, Text)' using the
2141%% text `"..."' as default replacement.
2142%%
2143%% @see limit/3
2144%% @see erl_syntax:text/1
2145
2146-spec limit(erl_syntax:syntaxTree(), integer()) -> erl_syntax:syntaxTree().
2147
2148limit(Tree, Depth) ->
2149    limit(Tree, Depth, erl_syntax:text("...")).
2150
2151%% =====================================================================
2152%% @spec limit(Tree::syntaxTree(), Depth::integer(),
2153%%             Node::syntaxTree()) -> syntaxTree()
2154%%
2155%% @doc Limits a syntax tree to a specified depth. Replaces all non-leaf
2156%% subtrees in `Tree' at the given `Depth' by
2157%% `Node'. If `Depth' is negative, the result is
2158%% always `Node', even if `Tree' has no subtrees.
2159%%
2160%% When a group of subtrees (as e.g., the argument list of an
2161%% `application' node) is at the specified depth, and there
2162%% are two or more subtrees in the group, these will be collectively
2163%% replaced by `Node' even if they are leaf nodes. Groups of
2164%% subtrees that are above the specified depth will be limited in size,
2165%% as if each subsequent tree in the group were one level deeper than
2166%% the previous. E.g., if `Tree' represents a list of
2167%% integers "`[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]'", the result
2168%% of `limit(Tree, 5)' will represent `[1, 2, 3, 4,
2169%% ...]'.
2170%%
2171%% The resulting syntax tree is typically only useful for
2172%% pretty-printing or similar visual formatting.
2173%%
2174%% @see limit/2
2175
2176-spec limit(erl_syntax:syntaxTree(), integer(), erl_syntax:syntaxTree()) ->
2177        erl_syntax:syntaxTree().
2178
2179limit(_Tree, Depth, Node) when Depth < 0 ->
2180    Node;
2181limit(Tree, Depth, Node) ->
2182    limit_1(Tree, Depth, Node).
2183
2184limit_1(Tree, Depth, Node) ->
2185    %% Depth is nonnegative here.
2186    case erl_syntax:subtrees(Tree) of
2187        [] ->
2188            if Depth > 0 ->
2189                    Tree;
2190               true ->
2191                    case is_simple_leaf(Tree) of
2192                        true ->
2193                            Tree;
2194                        false ->
2195                            Node
2196                    end
2197            end;
2198        Gs ->
2199            if Depth > 1 ->
2200                    Gs1 = [[limit_1(T, Depth - 1, Node)
2201                            || T <- limit_list(G, Depth, Node)]
2202                           || G <- Gs],
2203                    rewrite(Tree,
2204                            erl_syntax:make_tree(erl_syntax:type(Tree),
2205                                                 Gs1));
2206               Depth =:= 0 ->
2207                    %% Depth is zero, and this is not a leaf node
2208                    %% so we always replace it.
2209                    Node;
2210               true ->
2211                    %% Depth is 1, so all subtrees are to be cut.
2212                    %% This is done groupwise.
2213                    Gs1 = [cut_group(G, Node) || G <- Gs],
2214                    rewrite(Tree,
2215                            erl_syntax:make_tree(erl_syntax:type(Tree),
2216                                                 Gs1))
2217            end
2218    end.
2219
2220cut_group([], _Node) ->
2221    [];
2222cut_group([T], Node) ->
2223    %% Only if the group contains a single subtree do we try to
2224    %% preserve it if suitable.
2225    [limit_1(T, 0, Node)];
2226cut_group(_Ts, Node) ->
2227    [Node].
2228
2229is_simple_leaf(Tree) ->
2230    case erl_syntax:type(Tree) of
2231        atom -> true;
2232        char -> true;
2233        float -> true;
2234        integer -> true;
2235        nil -> true;
2236        operator -> true;
2237        tuple -> true;
2238        underscore -> true;
2239        variable -> true;
2240        _ -> false
2241    end.
2242
2243%% If list has more than N elements, take the N - 1 first and
2244%% append Node; otherwise return list as is.
2245
2246limit_list(Ts, N, Node) ->
2247    if length(Ts) > N ->
2248            limit_list_1(Ts, N - 1, Node);
2249       true ->
2250            Ts
2251    end.
2252
2253limit_list_1([T | Ts], N, Node) ->
2254    if N > 0 ->
2255            [T | limit_list_1(Ts, N - 1, Node)];
2256       true ->
2257            [Node]
2258    end;
2259limit_list_1([], _N, _Node) ->
2260    [].
2261
2262
2263%% =====================================================================
2264%% Utility functions
2265
2266rewrite(Tree, Tree1) ->
2267    erl_syntax:copy_attrs(Tree, Tree1).
2268
2269module_name_to_atom(M) ->
2270    case erl_syntax:type(M) of
2271	atom ->
2272	    erl_syntax:atom_value(M);
2273	_ ->
2274	    throw(syntax_error)
2275    end.
2276
2277%% This splits lines at line terminators and expands tab characters to
2278%% spaces. The width of a tab is assumed to be 8.
2279
2280% split_lines(Cs) ->
2281%     split_lines(Cs, "").
2282
2283split_lines(Cs, Prefix) ->
2284    split_lines(Cs, Prefix, 0).
2285
2286split_lines(Cs, Prefix, N) ->
2287    lists:reverse(split_lines(Cs, N, [], [], Prefix)).
2288
2289split_lines([$\r, $\n | Cs], _N, Cs1, Ls, Prefix) ->
2290    split_lines_1(Cs, Cs1, Ls, Prefix);
2291split_lines([$\r | Cs], _N, Cs1, Ls, Prefix) ->
2292    split_lines_1(Cs, Cs1, Ls, Prefix);
2293split_lines([$\n | Cs], _N, Cs1, Ls, Prefix) ->
2294    split_lines_1(Cs, Cs1, Ls, Prefix);
2295split_lines([$\t | Cs], N, Cs1, Ls, Prefix) ->
2296    split_lines(Cs, 0, push(8 - (N rem 8), $\040, Cs1), Ls,
2297                Prefix);
2298split_lines([C | Cs], N, Cs1, Ls, Prefix) ->
2299    split_lines(Cs, N + 1, [C | Cs1], Ls, Prefix);
2300split_lines([], _, [], Ls, _) ->
2301    Ls;
2302split_lines([], _N, Cs, Ls, Prefix) ->
2303    [Prefix ++ lists:reverse(Cs) | Ls].
2304
2305split_lines_1(Cs, Cs1, Ls, Prefix) ->
2306    split_lines(Cs, 0, [], [Prefix ++ lists:reverse(Cs1) | Ls],
2307                Prefix).
2308
2309push(N, C, Cs) when N > 0 ->
2310    push(N - 1, C, [C | Cs]);
2311push(0, _, Cs) ->
2312    Cs.
2313
2314