PropEr generator of abstract code
This module is a PropEr generator for abstract code. It
generates guards, expressions, programs (modules), and terms. It
does not generate macros or other attributes than function
,
record
, spec
, and type
. The generated programs (guards,
expressions) can be used for testing the Compiler or other modules
traversing programs as abstract forms. Typical examples of the
latter are erl_eval
, erl_pp
,
erl_prettypr
(Syntax Tools), and parse transforms.
Created modules should compile without errors, but will most likely
crash immediately when invoked.
This is an example how to test the Compiler:
test() -> ?FORALL(Abstr, proper_erlang_abstract_code:module(), ?WHENFAIL( begin io:format("~ts\n", [[erl_pp:form(F) || F <- Abstr]]), compile(Abstr, [report_errors]) end, case compile(Abstr, []) of {error, _Es, _Ws} -> false; _ -> true end)). compile(Abstr, Opts) -> compile:noenv_forms(Abstr, Opts).
atom_fun() = fun(() -> proper_types:type())
A function that generates atoms. The default function chooses from 100 common English words.
char_fun() = fun(() -> proper_types:type())
A function that generates characters. The default function
chooses from $a..$z | $A..$Z
.
limit() = non_neg_integer()
option() = {variables, [atom()]} | {weight, {Key :: atom(), Weight :: weight()}} | {function, [{FunctionName :: atom(), Arity :: arity()}]} | {types, [{TypeName :: atom(), NumOfParms :: arity()}]} | {records, [{RecordName :: atom(), [FieldName :: atom()]}]} | {limit, [{Name :: atom(), Limit :: limit()}]} | {char, char_fun()} | {atom, atom_fun()} | {set_all_weights, weight()}
See description below.
weight() = non_neg_integer()
expr/0 | Returns abstract code of an expression. |
expr/1 | Same as expr/0 , but accepts a list of options. |
guard/0 | Returns abstract code of a guard. |
guard/1 | Same as guard/0 , but accepts a list of options. |
module/0 | Returns abstract code of a module. |
module/1 | Same as module/0 , but accepts a list of options. |
term/0 | Returns abstract code of a term that can be handled by
erl_parse:normalise/0 . |
term/1 | Same as term/0 , but accepts a list of options. |
expr() -> proper_types:type()
Returns abstract code of an expression.
expr(Options :: list()) -> proper_types:type()
Same as expr/0
, but accepts a list of options. See
module/1
for a description of the options.
guard() -> proper_types:type()
Returns abstract code of a guard. A guard is a sequence of guard tests.
guard(Options :: [option()]) -> proper_types:type()
Same as guard/0
, but accepts a list of options. See
module/1
for a description of the options.
module() -> proper_types:type()
Returns abstract code of a module. The module has type declarations, functions, function specifications, and record declarations.
module(Options :: [option()]) -> proper_types:type()
Same as module/0
, but accepts a list of options.
{atom, atom_fun()
}
- A atom generating
function to replace the default.{char, char_fun()
}
- A character generating
function to replace the default. The function is used when
generating strings and characters.{functions, [{Name, Arity}]}
- A list of FAs to
be used as names of generated functions. The default is a small
number of functions with a small number of arguments.{limit, [{Name, Limit}]}
- Set the limit of
Name
to Limit
. The limit names are:
bin_elements
- Number of segments of a bitstring.list
- Number of elements of a plain list.map
- Number of associations of a map.string
- Number of characters of a string.tuple
- Number of elements of a tuple.body
- Number of clauses of a body.call_args
- Number of arguments of function call.catch_clauses
- Number of clauses of the
catch
part of a try/catch
.clauses
- Number of clauses of case
,
the of
part of try/catch
, and
receive
.function_clauses
- Number of clauses of
a function.function_constraints
- Number of constraints of
a function specification.function_constraints
- Number of constraints of
a function specification.function_types
- Number of types of
an overloaded function specification.guard
- Number of guards of a clause.guard_tests
- Number of guard tests of a guard.if_clauses
- Number of clauses of
if
.tuple_types
- Number of types (elements)
of tuple types.qualifiers
- Number of qualifiers
of comprehensions.record_fields
- Number of fields of record
declarations.tsl
- Number of elements of
type specifier lists (of segments of bit syntax expressions).union_types
- Number of types of type
union.s{records, [{Name, [Field]}]}
- A list
of record names with field names to be used as names of
generated records. The default is a small number of records
with a small number of fields.{types, [{Name, NumOfParameters}]}
- A list
of TAs to be used as names of generated types. The default
is a small number of types.{resize, boolean()}
- Use ?SIZED
to limit the size of the generated abstract code. With this
option set to false
(the default) big code
may be generated among the first instances.{set_all_weights, Weight}
- Set the weight of
all keys to Weight
.{weight, {Key, Weight}}
- Set the weight of
Key
to weight Weight
. A weight of zero
means that a construct is not generated. Higher weights means that
a construct i generated relatively often. Groups of weight keys
follow. Notice that the weight of a key is relative to other
keys of the same group. Also notice that some keys occur in
more than one group, which makes it all more complicated. The
weight of small
needs to be quite high to avoid
generating too deeply nested abstract code.record_decl, type_decl, function_decl,
function_spec
(type_decl
and
function_spec
are off by default)small
): atom, boolean,
integer, string, char, float, nil, pat_var, var
small, bitstring, list, tuple,
map, match, binop, unop, record, 'case', block, 'if', 'fun',
'receive', 'try', 'catch', try_of, termcall, varcall, localcall,
extcall
(termcall
is off by default)map
): build_map,
update_map
list
): plain_list, cons,
lc
lc
): lc_gen, blc_gen,
lc_any_filter, lc_guard_filter
bitstring
): bits, blc,
literal_bits
'try', try_of
): no_try_after,
try_after
'catch'
):
no_eclass, any_eclass, lit_eclass, var_eclass,
bad_eclass
'receive'
):
lit_timeout, inf_timeout, var_timeout
'fun'
):
lambda, rec_lambda, local_mfa, ext_mfa, any_mfa
no_guard, yes_guard
small, tuple, map, cons, plain_list, bits,
binop, unop, record, guard_call, remote_guard_call
small, match, tuple, cons, plain_list, bits,
unop, binop, record, map_pattern, string_prefix
pat_var
):
fresh_var, bound_var
_ = V
syntax):
yes_multi_field_init, no_multi_field_init
string_prefix
):
nil, string, string_prefix_list
annotated_type, atom, bitstring, 'fun',
integer_range_type, nil, map, predefined_type, record,
remote_type, singleton_integer_type, tuple, type_union,
type_variable, user_defined_type
yes_constrained_function_type,
no_constrained_function_type
no_overloaded, yes_overloaded
singleton_integer_type
):
integer, char, unop, binop
term() -> proper_types:type()
Returns abstract code of a term that can be handled by
erl_parse:normalise/0
.
term(Options :: [option()]) -> proper_types:type()
Same as term/0
, but accepts a list of options.
module/1
.
{atom, atom_fun()
}
- A atom generating
function to replace the default.{char, char_fun()
}
- A character generating
function to replace the default. The function is used when
generating strings and characters.{limit, [{Name, Limit}]}
- Set the limit of
Name
to Limit
. The limit names are:
bin_elements
- Number of segments of a bitstring.list
- Number of elements of a plain list.map
- Number of associations of a map.string
- Number of characters of a string.tuple
- Number of elements of a tuple.{resize, boolean()}
- Use ?SIZED
to limit the size of the generated abstract code. With this
option set to false
(the default) big code
may be generated among the first instances.{set_all_weights, Weight}
- Set the weight of
all keys to Weight
.{weight, {Key, Weight}}
- Set the weight of
Key
to weight Weight
. A weight of zero
means that a construct is not generated. Higher weights means that
a construct i generated relatively often. Groups of weight keys
follow. Notice that the weight of a key is relative to other
keys of the same group. The weight of small
needs
to quite high to avoid generating too deeply nested abstract
code.small
): atom, boolean,
integer, string, char, float, nil
small, bitstring, list, tuple,
map, 'fun'
map
): build_map
list
): plain_list,
cons
bitstring
): bits, bytes
'fun'
):
ext_mfa
Generated by EDoc