Skip to content

Commit

Permalink
work around scoping issue with some hack
Browse files Browse the repository at this point in the history
  • Loading branch information
fenollp committed Aug 7, 2018
1 parent a21ab40 commit a7396db
Show file tree
Hide file tree
Showing 2 changed files with 38 additions and 10 deletions.
39 changes: 29 additions & 10 deletions src/fancyflow.erl
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Expand Down Expand Up @@ -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]}.
Expand All @@ -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()}]},
Expand Down Expand Up @@ -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
Expand All @@ -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, _) ->
Expand Down
9 changes: 9 additions & 0 deletions test/fancyflow_SUITE.erl
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ all() ->
,pipe_trans, maybe_trans, parallel_trans
,mixed_trans
,maybe2_trans
,scoping
].

id(X) -> X.
Expand Down Expand Up @@ -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
)
).

0 comments on commit a7396db

Please sign in to comment.