From a7396db566e7a585d61c36c3b5f01f9ecfdf7b23 Mon Sep 17 00:00:00 2001 From: Pierre Fenoll Date: Tue, 7 Aug 2018 16:18:18 +0200 Subject: [PATCH] work around scoping issue with some hack --- src/fancyflow.erl | 39 +++++++++++++++++++++++++++++---------- test/fancyflow_SUITE.erl | 9 +++++++++ 2 files changed, 38 insertions(+), 10 deletions(-) diff --git a/src/fancyflow.erl b/src/fancyflow.erl index 263a68f..7961412 100644 --- a/src/fancyflow.erl +++ b/src/fancyflow.erl @@ -12,6 +12,10 @@ ,fname :: atom() }). +-define(PREFIX, '_fancyflow'). +-define(PREFIX_MAX, '_fancyflow999999999'). +-define(PREFIX_STR, "_" ?MODULE_STRING). + -ifdef(OTP_RELEASE). %% Implies 21 or higher -define(EXCEPTION(Class, Reason, Stacktrace), Class:Reason:Stacktrace). -define(STACKTRACE(Stacktrace), Stacktrace). @@ -91,9 +95,7 @@ mixin_pipe([Init|Funs=[_|_]], Line) -> mixin_pipe_fold(Piped, {{var,_,LastVarName},Block}) -> L = element(2, Piped), - Replacer = fun (T) -> replace_var(T, LastVarName) end, - Filled = erl_syntax:revert( - erl_syntax_lib:map(Replacer, Piped)), + Filled = mixin_or_make_fun_then_call(Piped, L, LastVarName), Var = {var, L, make_var_name()}, Match = {match, L, Var, Filled}, {Var, [Match|Block]}. @@ -120,9 +122,7 @@ mixin_maybe([Init|Funs=[_|_]], Line) -> mixin_maybe_fold([Piped|Rest], {var,_,LastVarName}) -> L = element(2, Piped), - Replacer = fun (T) -> replace_var(T, LastVarName) end, - Filled = erl_syntax:revert( - erl_syntax_lib:map(Replacer, Piped)), + Filled = mixin_or_make_fun_then_call(Piped, L, LastVarName), ErrorVar = {var, L, make_var_name()}, ErrorTuple = {tuple, L, [{atom,L,error},{var,L,make_var_name()}]}, @@ -162,13 +162,28 @@ folder_funs([], LastLine, _, _) -> folder_funs([Piped|Rest], LastLine, VarName, Replacer) -> Line = element(2, Piped), Filled = make_fun(Piped, Line, VarName, Replacer), - io:format(user, "\nFilled ~p\n", [Filled]), NewRest = folder_funs(Rest, LastLine, VarName, Replacer), {cons, Line, Filled, NewRest}. -make_var_name() -> - Int = erlang:unique_integer([monotonic, positive]), - list_to_atom(lists:flatten(io_lib:format("_~s~p", [?MODULE,Int]))). +%% Hack to know when we may be rebinding a variable +is_matching({match,_,{var,_,Name},_}) when ?PREFIX < Name, Name < ?PREFIX_MAX -> false; +is_matching({match,_,{var,_,_},_}) -> true; +is_matching({_,Ta}) -> is_matching(Ta); +is_matching({_,_,Ta}) -> is_matching(Ta); +is_matching({_,_,Ta,Tb}) -> is_matching(Ta) orelse is_matching(Tb); +is_matching({_,_,Ta,Tb,Tc}) -> is_matching(Ta) orelse is_matching(Tb) orelse is_matching(Tc); +is_matching(Ts) when is_list(Ts) -> lists:any(fun is_matching/1, Ts); +is_matching(T) when is_atom(T); is_number(T); is_binary(T) -> false. + +mixin_or_make_fun_then_call(Piped, Line, VarName) -> + Replacer = fun (T) -> replace_var(T, VarName) end, + Filled = erl_syntax:revert(erl_syntax_lib:map(Replacer, Piped)), + case is_matching(Piped) of + false -> Filled; + true -> + Clauses = [{clause, Line, [], [], [Filled]}], + {call, Line, {'fun', Line, {clauses, Clauses}}, []} + end. make_fun(Piped, Line, VarName, Replacer) -> case erl_syntax_lib:map(Replacer, Piped) of @@ -183,6 +198,10 @@ make_fun(Piped, Line, VarName, Replacer) -> }} end. +make_var_name() -> + Int = erlang:unique_integer([monotonic, positive]), + list_to_atom(?PREFIX_STR ++ integer_to_list(Int)). + replace_var({var, Line, '_'}, VarName) -> {var, Line, VarName}; replace_var(Exp, _) -> diff --git a/test/fancyflow_SUITE.erl b/test/fancyflow_SUITE.erl index 9d89636..1f97c6a 100644 --- a/test/fancyflow_SUITE.erl +++ b/test/fancyflow_SUITE.erl @@ -9,6 +9,7 @@ all() -> ,pipe_trans, maybe_trans, parallel_trans ,mixed_trans ,maybe2_trans + ,scoping ]. id(X) -> X. @@ -110,3 +111,11 @@ maybe2_trans(_) -> ,{ok, _/42} ) ). + +scoping(_) -> + ?assertEqual(42, [pipe](1, _*6, _*7)), + ?assertEqual(42, [pipe](1 + ,begin A = 6, _*A end + ,begin A = 7, _*A end + ) + ).