[erlang-questions] Reassigning variables

Matthew Dempsky matthew@REDACTED
Tue Mar 17 21:32:00 CET 2009


On Tue, Mar 17, 2009 at 11:02 AM, Matthew Dempsky <matthew@REDACTED> wrote:
> I think this can be handled with a parse transform, and I'm
> considering writing a parse transform to handle it.

Below is a proof of concept of this.  I've only minimally tested this
out, but here's a working example:

    -module(foo).
    -compile({parse_transform, reassign_pt}).
    -export([bar/0]).

    bar() ->
        X = 0,
        r(X) = X + 1,
        r(X) = X + 2,
        r(X) = X + 3,
        X.

And running it:

    1> c(reassign_pt).
    {ok,reassign_pt}
    2> c(foo).
    {ok,foo}
    3> foo:bar().
    6


-module(reassign_pt).
-author("Matthew Dempsky <matthew@REDACTED>").

-export([parse_transform/2]).

-define(KEY, 'reassign_pt:gensym').

parse_transform(Forms, _Options) ->
    NewForms = erl_syntax:revert_forms(
                 [transform(F) || F <- Forms]),
    erase(?KEY),
    NewForms.

transform(Form) ->
    {NewForm, _Acc} = erl_syntax_lib:mapfold_subtrees(fun transform/2,
ordsets:new(), Form),
    NewForm.

transform(Form, Renames) ->
    try
        case erl_syntax:type(Form) of
            variable ->
                Name = erl_syntax:variable_name(Form),
                {ok, Value} = orddict:find(Name, Renames),
                {Value, Renames};
            match_expr ->
                Pattern = erl_syntax:match_expr_pattern(Form),
                Body = erl_syntax:match_expr_body(Form),
                application = erl_syntax:type(Pattern),
                Operator = erl_syntax:application_operator(Pattern),
                atom = erl_syntax:type(Operator),
                r = erl_syntax:atom_value(Operator),
                [Var] = erl_syntax:application_arguments(Pattern),

                VarName = erl_syntax:variable_name(Var),
                {NewBody, NewRenames} = transform(Body, Renames),
                NewVar = erl_syntax:variable(atom_to_list(VarName) ++
"." ++ gensym()),
                NewAssign = erl_syntax:match_expr(NewVar, NewBody),
                {NewAssign, orddict:store(VarName, NewVar, NewRenames)}
        end
    catch
        error:{case_clause, _Expr} ->
            erl_syntax_lib:mapfold_subtrees(fun transform/2, Renames, Form);
        error:{badmatch, _Expr} ->
            erl_syntax_lib:mapfold_subtrees(fun transform/2, Renames, Form)
    end.

gensym() ->
    N = case get(?KEY) of undefined -> 1; V -> V end,
    put(?KEY, N + 1),
    "reassign_pt:var_" ++ integer_to_list(N).



More information about the erlang-questions mailing list