This module implements the parse_transform that makes calls to
ets
and dbg
:fun2ms/1
translate into literal
match specifications. It also implements the backend for the same
functions when called from the erlang shell.
The translations from fun's to match_specs
is accessed through the two "pseudo
functions" ets:fun2ms/1
and dbg:fun2ms/1
.
To use the pseudo functions triggering the translation, one
has to include the header file |
The |
Several restrictions apply to the fun that is beeing translated into a match_spec. To put it simple you cannot use anything in the fun that you cannot use in a match_spec. This means that, among others, the following restrictions apply to the fun itself:
is_list(X)
will be translated to {'is_list',
'$1'}
('$1'
is just an example, the numbering may
vary). If one tries to call a function that is not a match_spec
builtin, it will cause an error.fun
will be
replaced by match_spec variables in the order of occurence, so
that the fragment fun({A,B,C})
will be replaced by
{'$1', '$2', '$3'}
etc. Every occurence of such a
variable later in the match_spec will be replaced by a
match_spec variable in the same way, so that the fun
fun({A,B}) when is_atom(A) -> B end
will be translated into
[{{'$1','$2'},[{is_atom,'$1'}],['$2']}]
.const
expressions. Example from the shell:
1> X = 25. 25 2> ets:fun2ms(fun({A,B}) when A > X -> B end). [{{'$1','$2'},[{'>','$1',{const,25}}],['$2']}]
=
cannot be used, neither in the head
nor in the body. Example from the shell again:
1> ets:fun2ms(fun({A,[B|C]=D}) when A > X -> B end). Error: fun with head matching ('=' in head) cannot be translated into match_spec {error,transform_error} 2> ets:fun2ms(fun({A,[B|C]}) when A > X -> D = [B|C], D end). Error: fun with body matching ('=' in body) is illegal as match_spec {error,transform_error}All variables are bound in the head and the match_spec syntax does not allow multible bindings.
'$_'
and '$*'
are accessed through the pseudo functions object()
(for '$_'
) and bindings()
(for '$*'
).
as an example, one could translate the following
ets:match_object/2
call to a ets:select
call:
ets:match_object(Table, {'$1',test,'$2'})....is the same as...
ets:select(Table, ets:fun2ms(fun({A,test,B}) -> object() end)).(This was just an example, in this simple case the former expression is probably prefferable in terms of readability). The
ets:select/2
call will conceptually look like this
in the resulting code:
ets:select(Table, [{{'$1',test,'$2'},[],['$_']}]).
is_record/2
is translated into
match_spec code using the three parameter version that's built
into match_specs, so that is_record(A,t)
is translated
into {is_record,'$1',t,5}
given that the record size of
record type t
is 5. Records are of course still not
accessible from the shell...
case
, if
,
catch
etc that are not present in match_spec's are not
allowed.
list
,
integer
, float
etc) are not allowed. All guard
tests must be written with the new names is_list
,
is_tuple
, is_record
etc.
ms_transform.hrl
is not included,
the fun won't be translated, which may result in a
runtime error (depending on if the fun is valid in a
pure erlang context). Be absolutely sure that the header is
included when using ets
and dbg:fun2ms/1
in
compiled code.
ets:fun2ms/1
, the fun's head must contain a single
variable or a single tuple. If the pseudo function is
dbg:fun2ms/1
the fun's head must contain a single
varaiable or a single list.
The translation from fun's to match_spec's is done at compile time, so runtime performance is not affected by using these pseudo functions. The compile time might be somewhat longer though.
For more information about match_specs, please read about them in erts users guide.
parse_transform(Forms,_Options) -> Forms
Forms = Erlang abstract code format, see the
erl_parse module description
_Options = Option list, required but not used
Implements the actual transformation at compile time. This
function is called by the compiler to do the source code
transformation if and when the ms_transform.hrl
header
file is included in your source code. See the ets
and
dbg
:fun2ms/1
function manual pages for
documentation on how to use this parse_transform, see the
match_spec
chapter in ERTS
users guide for a
description of match specifications.
transform_from_shell(Dialect,Clauses,BoundEnvironment) -> term()
Dialect = ets | dbg
Clauses = Erlang abstract form for a single fun
BoundEnvironment = [{atom(), term()}, ...], list of
variable bindings in the shell environment
Implements the actual transformation when the fun2ms
functions are called from the shell. In this case the abstract
form is for one single fun (parsed by the erlang shell), and
all imported variables should be in the key-value list passed
ass BoundEnvironment
. The result is a term, normalized,
i.e. not in abstract format.
format_error(Errcode) -> ErrMessage
Errcode = term()
ErrMessage = string()
Takes an error code returned by one of the other functions in the module and creates a textual description of the error. Fairly uninteresting function actually.