|
User
Joined: 03 Jul 2006
Posts: 604
Location: Sweden
|
It's a little hobby of mine to try to build parse transform libraries.
One of the libraries is a utility for replacing a given function.
This is a reasonably simple technique to 'enhance' the language:
simply invent a special function that is supposed to be detected
and re-written at compile-time.
This particular application of that library allows you to evaluate
an expression at compile-time, inserting the result of the
evaluation in place of the 'pseudo-function call'.
As an example, I may want to define a function that returns
a hard-coded ordset. The ordset module wants
the set to be represented as an ordered list. This is easy enough
to do by hand - most of the time, but then I should also add a
comment for future reference stating that the list should indeed
always be ordered.
Code:
names() ->
%% must be an ordset
[aaron, bill, charlie, joe].
Using the attached parse transform, you could instead write:
Code:
names() ->
ct_expand:term(
ordsets:from_list([bill, joe, aaron, charlie])
).
In the latter case, the order doesn't matter. Remember to include the compiler directive Code: -compile({parse_transform, ct_expand})
and the list will be converted into an ordset when compiled.
In this very simple example, the gain is minimal, but if you'd
want to hard-code a 'dict' or 'gb_sets' structure, there would
be no sensible way to do it by hand.
Using ct_expand:
Code:
names() ->
ct_expand:term(
gb_sets:from_list([bill, joe, aaron, charlie])
).
is transformed into this:
Code:
names() ->
{4,
{charlie, {bill, {aaron, nil, nil}, nil},
{joe, nil, nil}}}.
You can of course do much more than hard-coded access structures,
but the reader is encouraged to invent his/her own fun applications.
The only code in the ct_expand module that is specialized is this:
Code:
parse_transform(Forms, Options) ->
function({?MODULE, term, 1},
fun(Form, _Context) ->
io:format("expanding...~n", []),
case erl_syntax:application_arguments(Form) of
[Expr] ->
case erl_eval:exprs(
revert_tree([Expr]), []) of
{value, Value, _} ->
erl_syntax:abstract(Value);
Other ->
erlang:error({cannot_evaluate,
[Expr, Other]})
end;
_Args ->
erlang:error(illegal_form)
end
end, Forms, Options).
The rest is (or should be) a reusable library.
/Ulf Wiger |
| Description: |
| parse_transform module for compile-time expansion. |
|
 Download |
| Filename: |
ct_expand.erl |
| Filesize: |
7.16 KB |
| Downloaded: |
1778 Time(s) |
|
|