[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