cerl_clauses — compiler v10.0.2

Search documentation of compiler

# cerl_clauses (compiler v10.0.2)

Copy Markdown View Source

Utility functions for Core Erlang case/receive clauses.

#### Note

The documentation of the public interface for the Erlang compiler can be found in module `compile`.

This module is an internal part of the compiler. Its API is not guaranteed to remain compatible between releases.

Syntax trees are defined in the module `cerl`.

## Summary

### Types

bindings()
cerl()
expr()
match_ret()

### Functions

any_catchall(Clauses)

Returns `true` if any of the abstract clauses in the list is a catch-all, otherwise `false`.

eval_guard(Expr)

Tries to reduce a guard expression to a single constant value, if possible.

is_catchall(Clause)

Returns `true` if an abstract clause is a catch-all, otherwise `false`.

match(Pattern, Expr)

Matches a pattern against an expression.

match_list(Patterns, Exprs)

Like `match/2`, but matching a sequence of patterns against a sequence of expressions.

reduce(Cs)

Equivalent to reduce(Cs, []).

reduce(Clauses, Exprs)

Selects a single clause, if possible, or otherwise reduces the list of selectable clauses.

## Types

# bindings()

(not exported)

    -type bindings() :: [{cerl(), cerl()}].

# cerl()

(not exported)

    -type cerl() :: cerl:cerl().

# expr()

(not exported)

    -type expr() :: any | cerl().

# match_ret()

(not exported)

    -type match_ret() :: none | {true, bindings()} | {false, bindings()}.

## Functions

# any_catchall(Clauses)

    -spec any_catchall(Clauses :: [cerl()]) -> boolean().

Returns `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`.

See also: `is_catchall/1`.

# eval_guard(Expr)

    -spec eval_guard(Expr :: cerl()) -> none | {value, term()}.

Tries to reduce a guard expression to a single constant value, if possible.

The returned value is `{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.

See also: `is_catchall/1`.

# is_catchall(Clause)

    -spec is_catchall(Clause :: cerl:c_clause()) -> boolean().

Returns `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`.

See also: `any_catchall/1`, `eval_guard/1`.

# match(Pattern, Expr)

    -spec match(Pattern :: cerl(), Expr :: expr()) -> match_ret().

Matches a pattern against an expression.

The returned value is `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:

- Matching a pattern "`{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)`".
- Matching pattern "`{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).
- Matching pattern "`{foo, bar}`" against expression "`{foo, f()}`" yields `{false, []}`, telling us that there might be a match, but we cannot deduce any bindings.
- Matching `{foo, X = {bar, Y}}` against expression "`{foo, {bar, baz}}`" yields `{true, Bindings}` where `Bindings` associates "`Y`" with "`baz`", and "`X`" with "`{bar, baz}`".
- Matching a pattern "`{X, Y}`" against `any` yields `{false, Bindings}` where `Bindings` associates both "`X`" and "`Y`" with `any`.

# match_list(Patterns, Exprs)

    -spec match_list(Patterns :: [cerl()], Exprs :: [expr()]) -> match_ret().

Like `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 also: `match/2`.

# reduce(Cs)

    -spec reduce([cerl:c_clause()]) -> {true, {cerl:c_clause(), bindings()}} | {false, [cerl:c_clause()]}.

Equivalent to reduce(Cs, []).

# reduce(Clauses, Exprs)

    -spec reduce(Clauses :: [cerl:c_clause()], Exprs :: [expr()]) ->
                    {true, {cerl:c_clause(), bindings()}} | {false, [cerl:c_clause()]}.

Selects a single clause, if possible, or otherwise reduces the list of selectable clauses.

The input is a list `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.

See also: `eval_guard/1`, `match/2`, `match_list/2`.