%% %% %CopyrightBegin% %% %% Copyright Ericsson AB 2001-2010. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in %% compliance with the License. You should have received a copy of the %% Erlang Public License along with this software. If not, it can be %% retrieved online at http://www.erlang.org/. %% %% Software distributed under the License is distributed on an "AS IS" %% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %% the License for the specific language governing rights and limitations %% under the License. %% %% %CopyrightEnd% %% @doc Utility functions for Core Erlang case/receive clauses. %% %%
Syntax trees are defined in the module cerl.
true if an abstract clause is a
%% catch-all, otherwise false. A clause is a catch-all if
%% all its patterns are variables, and its guard expression always
%% evaluates to true; cf. eval_guard/1.
%%
%% Note: Clause must have type
%% clause.
true if any of the abstract clauses in
%% the list is a catch-all, otherwise false. See
%% is_catchall/1 for details.
%%
%% Note: each node in Clauses must have type
%% clause.
{value, Term} if the
%% guard expression Expr always yields the constant value
%% Term, and is otherwise none.
%%
%% Note that although guard expressions should only yield boolean
%% values, this function does not guarantee that Term is
%% either true or false. Also note that only
%% simple constructs like let-expressions are examined recursively;
%% general constant folding is not performed.
Clauses
%% of abstract clauses (i.e., syntax trees of type clause),
%% and a list of switch expressions Exprs. The function
%% tries to uniquely select a single clause or discard unselectable
%% clauses, with respect to the switch expressions. All abstract clauses
%% in the list must have the same number of patterns. If
%% Exprs is not the empty list, it must have the same
%% length as the number of patterns in each clause; see
%% match_list/2 for details.
%%
%% A clause can only be selected if its guard expression always
%% yields the atom true, and a clause whose guard
%% expression always yields the atom false can never be
%% selected. Other guard expressions are considered to have unknown
%% value; cf. eval_guard/1.
If a particular clause can be selected, the function returns
%% {true, {Clause, Bindings}}, where Clause is
%% the selected clause and Bindings is a list of pairs
%% {Var, SubExpr} associating the variables occurring in
%% the patterns of Clause with the corresponding
%% subexpressions in Exprs. The list of bindings is given
%% in innermost-first order; see the match/2 function for
%% details.
If no clause could be definitely selected, the function returns
%% {false, NewClauses}, where NewClauses is
%% the list of entries in Clauses that remain after
%% eliminating unselectable clauses, preserving the relative order.
none if a match is impossible, {true,
%% Bindings} if Pattern definitely matches
%% Expr, and {false, Bindings} if a match is
%% not definite, but cannot be excluded. Bindings is then
%% a list of pairs {Var, SubExpr}, associating each
%% variable in the pattern with either the corresponding subexpression
%% of Expr, or with the atom any if no
%% matching subexpression exists. (Recall that variables may not be
%% repeated in a Core Erlang pattern.) The list of bindings is given
%% in innermost-first order; this should only be of interest if
%% Pattern contains one or more alias patterns. If the
%% returned value is {true, []}, it implies that the
%% pattern and the expression are syntactically identical.
%%
%% Instead of a syntax tree, the atom any can be
%% passed for Expr (or, more generally, be used for any
%% subtree of Expr, in as much the abstract syntax tree
%% implementation allows it); this means that it cannot be decided
%% whether the pattern will match or not, and the corresponding
%% variable bindings will all map to any. The typical use
%% is for producing bindings for receive clauses.
Note: Binary-syntax patterns are never structurally matched %% against binary-syntax expressions by this function.
%% %%Examples: %%
{X, Y}" against the
%% expression "{foo, f(Z)}" yields {true,
%% Bindings} where Bindings associates
%% "X" with the subtree "foo" and
%% "Y" with the subtree "f(Z)".{X, {bar, Y}}" against
%% expression "{foo, f(Z)}" yields {false,
%% Bindings} where Bindings associates
%% "X" with the subtree "foo" and
%% "Y" with any (because it is not known
%% if "{foo, Y}" might match the run-time value of
%% "f(Z)" or not).{foo, bar}" against expression
%% "{foo, f()}" yields {false, []},
%% telling us that there might be a match, but we cannot deduce any
%% bindings.{foo, X = {bar, Y}} against expression
%% "{foo, {bar, baz}}" yields {true,
%% Bindings} where Bindings associates
%% "Y" with "baz", and "X"
%% with "{bar, baz}".{X, Y}" against
%% any yields {false, Bindings} where
%% Bindings associates both "X" and
%% "Y" with any.match/2, but matching a sequence of patterns
%% against a sequence of expressions. Passing an empty list for
%% Exprs is equivalent to passing a list of
%% any atoms of the same length as Patterns.
%%
%% @see match/2
-spec match_list([cerl:cerl()], [expr()]) -> match_ret().
match_list([], []) ->
{true, []}; % no patterns always match
match_list(Ps, []) ->
match_list(Ps, [any || _ <- Ps], []);
match_list(Ps, Es) ->
match_list(Ps, Es, []).
match_list([P | Ps], [E | Es], Bs) ->
case match(P, E, Bs) of
{true, Bs1} ->
match_list(Ps, Es, Bs1);
{false, Bs1} ->
%% Make sure "maybe" is preserved
case match_list(Ps, Es, Bs1) of
{_, Bs2} ->
{false, Bs2};
none ->
none
end;
none ->
none
end;
match_list([], [], Bs) ->
{true, Bs}.