%% %% %CopyrightBegin% %% %% Copyright Ericsson AB 2001-2009. 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}.