These contracts will usually not be seen by the user, and are ignored
by Dialyzer because they have overlapping domains, so there is not
much point in using them. Replace with simpler contracts for now.
A few changes were made to provide default values for context attributes so that parse_transform:transform/4 could be called for non-top-level forms. I don't know if this is generally useful or if it just fit my weird use case.
See examples/pmod.erl and examples/ex_pmod.erl
This works similarly to OTP's parameterized modules, which they are
now saying that they will drop. Since they drop the compiler support,
a slightly different notation is needed.
-pmod_vars([V1, V2, ...]). % defines the 'global' variables.
-pmod_funs([F1/A1, ...]). % defines which functions are to be exported.
The functions listed in -pmod_funs/1 are transformed to take an extra
argument, and a new(V1, V2, ...) function is added and exported.
Example:
Eshell V5.9 (abort with ^G)
1> c(ex_pmod).
{ok,ex_pmod}
2> M = ex_pmod:new(a,b).
{ex_pmod,{a,b}}
3> M:b(x,y).
{x,y,a,b}
Error markers ({error, Term} tuples) in Forms are special-cased by do/5
and make it return a error tuple itself instead of just letting them
through. I don't think it is good behaviour as the compiler and its
friends already handle error markers correctly. Furthermore it makes
parse_trans_codegen:parse_transform/2 fails when passing the error tuple
to parse_trans:revert/1.
'$form' works much like '$var', only that it makes it possible to
inject ready-made abstract forms into the generated
functions/expressions. The following call:
gen(Name, F) ->
codegen:gen_function(Name, fun(X) -> X =:= {'$form',F} end).
generates the following if called like this: gen(is_foo, {atom,0,foo})
is_foo(X) ->
X =:= foo.