19992016 Ericsson AB. All Rights Reserved. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. Match specifications in Erlang Patrik Nyblom 1999-06-01 PA1 match_spec.xml

A "match specification" (match_spec) is an Erlang term describing a small "program" that will try to match something. It can be used to either control tracing with erlang:trace_pattern/3 or to search for objects in an ETS table with for example ets:select/2. The match_spec in many ways works like a small function in Erlang, but is interpreted/compiled by the Erlang runtime system to something much more efficient than calling an Erlang function. The match_spec is also very limited compared to the expressiveness of real Erlang functions.

The most notable difference between a match_spec and an Erlang fun is of course the syntax. Match specifications are Erlang terms, not Erlang code. A match_spec also has a somewhat strange concept of exceptions. An exception (e.g., ) in the part, which resembles an Erlang guard, will generate immediate failure, while an exception in the part, which resembles the body of an Erlang function, is implicitly caught and results in the single atom .

Grammar

A match_spec used in tracing can be described in this informal grammar:

MatchExpression ::= [ MatchFunction, ... ] MatchFunction ::= { MatchHead, MatchConditions, MatchBody } MatchHead ::= MatchVariable | | [ MatchHeadPart, ... ] MatchHeadPart ::= term() | MatchVariable | MatchVariable ::= '$<number>' MatchConditions ::= [ MatchCondition, ...] | MatchCondition ::= { GuardFunction } | { GuardFunction, ConditionExpression, ... } BoolFunction ::= | | | | | | | | | | | | | | | | | | | ConditionExpression ::= ExprMatchVariable | { GuardFunction } | { GuardFunction, ConditionExpression, ... } | TermConstruct ExprMatchVariable ::= MatchVariable (bound in the MatchHead) | | TermConstruct = {{}} | {{ ConditionExpression, ... }} | | [ConditionExpression, ...] | | #{term() => ConditionExpression, ...} | NonCompositeTerm | Constant NonCompositeTerm ::= term() (not list or tuple or map) Constant ::= {, term()} GuardFunction ::= BoolFunction | | | | | | | | | | | | | | | | | | | | | ']]> | =']]> | | | | | | | | MatchBody ::= [ ActionTerm ] ActionTerm ::= ConditionExpression | ActionCall ActionCall ::= {ActionFunction} | {ActionFunction, ActionTerm, ...} ActionFunction ::= | | | | | | | | | | | |

A match_spec used in ets can be described in this informal grammar:

MatchExpression ::= [ MatchFunction, ... ] MatchFunction ::= { MatchHead, MatchConditions, MatchBody } MatchHead ::= MatchVariable | | { MatchHeadPart, ... } MatchHeadPart ::= term() | MatchVariable | MatchVariable ::= '$<number>' MatchConditions ::= [ MatchCondition, ...] | MatchCondition ::= { GuardFunction } | { GuardFunction, ConditionExpression, ... } BoolFunction ::= | | | | | | | | | | | | | | | | | | | ConditionExpression ::= ExprMatchVariable | { GuardFunction } | { GuardFunction, ConditionExpression, ... } | TermConstruct ExprMatchVariable ::= MatchVariable (bound in the MatchHead) | | TermConstruct = {{}} | {{ ConditionExpression, ... }} | | [ConditionExpression, ...] | #{} | #{term() => ConditionExpression, ...} | NonCompositeTerm | Constant NonCompositeTerm ::= term() (not list or tuple or map) Constant ::= {, term()} GuardFunction ::= BoolFunction | | | | | | | | | | | | | | | | | | | | | ']]> | =']]> | | | | | | | | MatchBody ::= [ ConditionExpression, ... ]
Function descriptions
Functions allowed in all types of match specifications

The different functions allowed in work like this:

is_atom, is_float, is_integer, is_list, is_number, is_pid, is_port, is_reference, is_tuple, is_map, is_binary, is_function: Like the corresponding guard tests in Erlang, return or .

is_record: Takes an additional parameter, which SHALL be the result of )]]>, like in .

'not': Negates its single argument (anything other than gives ).

'and': Returns if all its arguments (variable length argument list) evaluate to , else . Evaluation order is undefined.

'or': Returns if any of its arguments evaluates to . Variable length argument list. Evaluation order is undefined.

andalso: Like , but quits evaluating its arguments as soon as one argument evaluates to something else than true. Arguments are evaluated left to right.

orelse: Like , but quits evaluating as soon as one of its arguments evaluates to . Arguments are evaluated left to right.

'xor': Only two arguments, of which one has to be true and the other false to return ; otherwise returns false.

abs, element, hd, length, node, round, size, tl, trunc, '+', '-', '*', 'div', 'rem', 'band', 'bor', 'bxor', 'bnot', 'bsl', 'bsr', '>', '>=', '<', '=<', '=:=', '==', '=/=', '/=', self: Work as the corresponding Erlang bif's (or operators). In case of bad arguments, the result depends on the context. In the part of the expression, the test fails immediately (like in an Erlang guard), but in the , exceptions are implicitly caught and the call results in the atom .

Functions allowed only for tracing

is_seq_trace: Returns if a sequential trace token is set for the current process, otherwise .

set_seq_token: Works like , but returns on success and on error or bad argument. Only allowed in the part and only allowed when tracing.

get_seq_token: Works just like , and is only allowed in the part when tracing.

message: Sets an additional message appended to the trace message sent. One can only set one additional message in the body; subsequent calls will replace the appended message. As a special case, disables sending of trace messages ('call' and 'return_to') for this function call, just like if the match_spec had not matched, which can be useful if only the side effects of the are desired. Another special case is which sets the default behavior, as if the function had no match_spec, trace message is sent with no extra information (if no other calls to are placed before , it is in fact a "noop").

Takes one argument, the message. Returns and can only be used in the part and when tracing.

return_trace: Causes a trace message to be sent upon return from the current function. Takes no arguments, returns and can only be used in the part when tracing. If the process trace flag is active the trace message is inhibited.

NOTE! If the traced function is tail recursive, this match spec function destroys that property. Hence, if a match spec executing this function is used on a perpetual server process, it may only be active for a limited time, or the emulator will eventually use all memory in the host machine and crash. If this match_spec function is inhibited using the process trace flag tail recursiveness still remains.

exception_trace: Same as return_trace, plus; if the traced function exits due to an exception, an trace message is generated, whether the exception is caught or not.

process_dump: Returns some textual information about the current process as a binary. Takes no arguments and is only allowed in the part when tracing.

enable_trace: With one parameter this function turns on tracing like the Erlang call , where is the parameter to . With two parameters, the first parameter should be either a process identifier or the registered name of a process. In this case tracing is turned on for the designated process in the same way as in the Erlang call , where P1 is the first and P2 is the second argument. The process gets its trace messages sent to the same tracer as the process executing the statement uses. can not be one of the atoms , or (unless, of course, they are registered names). can not be nor . Returns and may only be used in the part when tracing.

disable_trace: With one parameter this function disables tracing like the Erlang call , where is the parameter to . With two parameters it works like the Erlang call , where P1 can be either a process identifier or a registered name and is given as the first argument to the match_spec function. can not be nor . Returns and may only be used in the part when tracing.

trace: With two parameters this function takes a list of trace flags to disable as first parameter and a list of trace flags to enable as second parameter. Logically, the disable list is applied first, but effectively all changes are applied atomically. The trace flags are the same as for not including but including . If a tracer is specified in both lists, the tracer in the enable list takes precedence. If no tracer is specified the same tracer as the process executing the match spec is used. When using a tracer module the module has to be loaded before the match specification is executed. If it is not loaded the match will fail. With three parameters to this function the first is either a process identifier or the registered name of a process to set trace flags on, the second is the disable list, and the third is the enable list. Returns if any trace property was changed for the trace target process or if not. It may only be used in the part when tracing.

caller: Returns the calling function as a tuple {Module, Function, Arity} or the atom if the calling function cannot be determined. May only be used in the part when tracing.

Note that if a "technically built in function" (i.e. a function not written in Erlang) is traced, the function will sometimes return the atom . The calling Erlang function is not available during such calls.

display: For debugging purposes only; displays the single argument as an Erlang term on stdout, which is seldom what is wanted. Returns and may only be used in the part when tracing.

get_tcw: Takes no argument and returns the value of the node's trace control word. The same is done by .

The trace control word is a 32-bit unsigned integer intended for generic trace control. The trace control word can be tested and set both from within trace match specifications and with BIFs. This call is only allowed when tracing.

set_tcw: Takes one unsigned integer argument, sets the value of the node's trace control word to the value of the argument and returns the previous value. The same is done by . It is only allowed to use in the part when tracing.

silent: Takes one argument. If the argument is , the call trace message mode for the current process is set to silent for this call and all subsequent, i.e call trace messages are inhibited even if is called in the part for a traced function.

This mode can also be activated with the flag to .

If the argument is , the call trace message mode for the current process is set to normal (non-silent) for this call and all subsequent.

If the argument is neither nor , the call trace message mode is unaffected.

Note that all "function calls" have to be tuples, even if they take no arguments. The value of is the atom() , but the value of is the pid() of the current process.

Match target

Each execution of a match specification is done against a match target term. The format and content of the target term depends on the context in which the match is done. The match target for ETS is always a full table tuple. The match target for call trace is always a list of all function arguments. The match target for event trace depends on the event type, see table below.

Context Type Match target Description ETS {Key, Value1, Value2, ...} A table object Trace call [Arg1, Arg2, ...] Function arguments Trace send [Receiver, Message] Receiving process/port and message term Trace 'receive' [Node, Sender, Message] Sending node, process/port and message term Match target depending on context
Variables and literals

Variables take the form ']]> where ]]> is an integer between 0 (zero) and 100000000 (1e+8), the behavior if the number is outside these limits is undefined. In the part, the special variable matches anything, and never gets bound (like in Erlang). In the parts, no unbound variables are allowed, why is interpreted as itself (an atom). Variables can only be bound in the part. In the and parts, only variables bound previously may be used. As a special case, in the parts, the variable expands to the whole match target term and the variable expands to a list of the values of all bound variables in order (i.e. ).

In the part, all literals (except the variables noted above) are interpreted as is. In the parts, however, the interpretation is in some ways different. Literals in the can either be written as is, which works for all literals except tuples, or by using the special form , where is any Erlang term. For tuple literals in the match_spec, one can also use double tuple parentheses, i.e., construct them as a tuple of arity one containing a single tuple, which is the one to be constructed. The "double tuple parenthesis" syntax is useful to construct tuples from already bound variables, like in . Some examples may be needed:

Expression Variable bindings Result {{'$1','$2'}} '$1' = a, '$2' = b {a,b} {const, {'$1', '$2'}} doesn't matter {'$1', '$2'} a doesn't matter a '$1' '$1' = [] [] ['$1'] '$1' = [] [[]] [{{a}}] doesn't matter [{a}] 42 doesn't matter 42 "hello" doesn't matter "hello" $1 doesn't matter 49 (the ASCII value for the character '1') Literals in the MatchCondition/MatchBody parts of a match_spec
Execution of the match

The execution of the match expression, when the runtime system decides whether a trace message should be sent, goes as follows:

For each tuple in the list and while no match has succeeded:

Match the part against the match target term, binding the ']]> variables (much like in ). If the cannot match the arguments, the match fails. Evaluate each (where only ']]> variables previously bound in the can occur) and expect it to return the atom . As soon as a condition does not evaluate to , the match fails. If any BIF call generates an exception, also fail. If the match_spec is executing when tracing:

Evaluate each in the same way as the , but completely ignore the return values. Regardless of what happens in this part, the match has succeeded.
If the match_spec is executed when selecting objects from an ETS table:

Evaluate the expressions in order and return the value of the last expression (typically there is only one expression in this context)
Differences between match specifications in ETS and tracing

ETS match specifications are there to produce a return value. Usually the contains one single which defines the return value without having any side effects. Calls with side effects are not allowed in the ETS context.

When tracing there is no return value to produce, the match specification either matches or doesn't. The effect when the expression matches is a trace message rather then a returned term. The 's are executed as in an imperative language, i.e. for their side effects. Functions with side effects are also allowed when tracing.

Tracing Examples

Match an argument list of three where the first and third arguments are equal:

Match an argument list of three where the second argument is a number greater than three:

', '$1', 3}], []}] ]]>

Match an argument list of three, where the third argument is a tuple containing argument one and two or a list beginning with argument one and two (i. e. or ):

The above problem may also be solved like this:

Match two arguments where the first is a tuple beginning with a list which in turn begins with the second argument times two (i. e. [{[4,x],y},2] or [{[8], y, z},4])

Match three arguments. When all three are equal and are numbers, append the process dump to the trace message, else let the trace message be as is, but set the sequential trace token label to 4711.

As can be noted above, the parameter list can be matched against a single or an . To replace the whole parameter list with a single variable is a special case. In all other cases the has to be a proper list.

Only generate trace message if trace control word is set to 1:

Only generate trace message if there is a seq trace token:

Remove 'silent' trace flag when first argument is 'verbose' and add it when it is 'silent':

Add return_trace message if function is of arity 3:

Only generate trace message if function is of arity 3 and first argument is 'trace':

ETS Examples

Match all objects in an ets table where the first element is the atom 'strider' and the tuple arity is 3 and return the whole object.

Match all objects in an ets table with arity > 1 and the first element is 'gandalf', return element 2.

=',{size, '$1'},2}], [{element,2,'$1'}]}] ]]>

In the above example, if the first element had been the key, it's much more efficient to match that key in the part than in the part. The search space of the tables is restricted with regards to the so that only objects with the matching key are searched.

Match tuples of 3 elements where the second element is either 'merry' or 'pippin', return the whole objects.

The function can be useful for testing complicated ets matches.