Erlang/OTP Forums

Author Message

<  User Contributions  ~  Parse transform for compile-time evaluation

uwiger
Posted: Tue Aug 22, 2006 10:55 am Reply with quote
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



ct_expand.erl
 Description:
parse_transform module for compile-time expansion.

Download
 Filename:  ct_expand.erl
 Filesize:  7.16 KB
 Downloaded:  1776 Time(s)

View user's profile Send private message Visit poster's website

Display posts from previous:  

All times are GMT
Page 1 of 1
This forum is locked: you cannot post, reply to, or edit topics.

Jump to:  

You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum