-module(reassign_pt). -author("Matthew Dempsky "). % The above refers to the original author. This is a refactored version of that code. -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} = fold(Form, ordsets:new()), NewForm. fold(Form, Renames) -> erl_syntax_lib:mapfold_subtrees(fun transform/2, Renames, Form). transform(Form, Renames) -> case erl_syntax:type(Form) of variable -> Name = erl_syntax:variable_name(Form), case orddict:find(Name, Renames) of {ok, Value} -> {Value, Renames}; error -> fold(Form, Renames) end; match_expr -> transform_match_expr(Form, Renames); _Other -> fold(Form, Renames) end. transform_match_expr(Form, Renames) -> Pattern = erl_syntax:match_expr_pattern(Form), case parse_match_expr(Pattern) of {application, {atom, r}} -> VarName = get_variable_name(Pattern), {NewBody, NewRenames} = transform(erl_syntax:match_expr_body(Form), Renames), NewVar = rename_variable(VarName), NewAssign = erl_syntax:match_expr(NewVar, NewBody), {NewAssign, orddict:store(VarName, NewVar, NewRenames)}; _Other -> fold(Form, Renames) end. parse_op(Operator) -> {erl_syntax:type(Operator), erl_syntax:atom_value(Operator)}. parse_match_expr(Pattern) -> case erl_syntax:type(Pattern) of application -> Operator = erl_syntax:application_operator(Pattern), {application, parse_op(Operator)}; Other -> Other end. get_variable_name(Pattern) -> [Var] = erl_syntax:application_arguments(Pattern), erl_syntax:variable_name(Var). rename_variable(Var) -> erl_syntax:variable(variable_alias(Var)). variable_alias(Name) -> atom_to_list(Name) ++ "." ++ gensym(). gensym() -> N = case get(?KEY) of undefined -> 1; V -> V end, put(?KEY, N + 1), "reassign_pt:var_" ++ integer_to_list(N).