Skip to content

Commit 193d894

Browse files
committed
Merge pull request #37 from caioariede/master
Partial application support
2 parents 38567f7 + 3b8279e commit 193d894

File tree

2 files changed

+69
-4
lines changed

2 files changed

+69
-4
lines changed

src/elixir_parser.yrl

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -724,14 +724,33 @@ Erlang code.
724724
check_body([]) -> [{atom, 0, nil}];
725725
check_body(Else) -> Else.
726726

727+
check_partial(Args) ->
728+
{NewArgs, PartialArgsCounter} = lists:mapfoldl(fun({identifier, Line, '_'}, Counter) -> {{identifier, Line, list_to_atom(lists:concat(["?", Counter]))}, Counter+1};
729+
(Arg, Counter) -> {Arg, Counter} end, 0, Args),
730+
if PartialArgsCounter < 1 ->
731+
false;
732+
true ->
733+
{PartialArgs, _} = lists:mapfoldl(fun({identifier, Line, '_'}, Counter) -> {{identifier, Line, list_to_atom(lists:concat(["?", Counter]))}, Counter+1};
734+
(_, Counter) -> {arg, Counter} end, 0, Args),
735+
{lists:filter(fun is_tuple/1, PartialArgs), NewArgs}
736+
end.
737+
727738
build_identifier(Thing) ->
728739
{ identifier, ?line(Thing), ?chars(Thing) }.
729740

741+
build_partial(Parent, Args, Body) ->
742+
build_fun(Parent, build_clause(Parent, Args, [], [Body])).
743+
730744
build_bracket_call(Expr, Args) ->
731745
build_method_call(Expr, { identifier, element(1, Args), '[]' }, element(2, Args)).
732746

733747
build_fun_call(Target, Args) ->
734-
{ fun_call, ?line(Target), Target, Args }.
748+
case check_partial(Args) of
749+
false ->
750+
{ fun_call, ?line(Target), Target, Args };
751+
{PartialFnArgs, NewArgs} ->
752+
build_partial(Target, PartialFnArgs, { fun_call, ?line(Target), Target, NewArgs })
753+
end.
735754

736755
build_try(Begin, Exprs) ->
737756
{ 'try', ?line(Begin), Exprs}.
@@ -790,10 +809,20 @@ build_anonymous_def_method(Def, Args, Clauses) ->
790809
{ def_method, ?line(Def), [], length(Args), [Clauses] }.
791810

792811
build_method_call(Expr, Name, Args) ->
793-
{ method_call, ?line(Name), ?chars(Name), Args, Expr }.
812+
case check_partial(Args) of
813+
false ->
814+
{ method_call, ?line(Name), ?chars(Name), Args, Expr };
815+
{PartialFnArgs, NewArgs} ->
816+
build_partial(Name, PartialFnArgs, { method_call, ?line(Name), ?chars(Name), NewArgs, Expr })
817+
end.
794818

795819
build_sharp_call(Left, Right, Args) ->
796-
{ bind_call, ?line(Right), Left, Right, Args }.
820+
case check_partial(Args) of
821+
false ->
822+
{ bind_call, ?line(Right), Left, Right, Args };
823+
{PartialFnArgs, NewArgs} ->
824+
build_partial(Right, PartialFnArgs, { bind_call, ?line(Right), Left, Right, NewArgs })
825+
end.
797826

798827
build_local_call(Name, Args) ->
799828
{ local_call, ?line(Name), ?chars(Name), Args }.
@@ -848,4 +877,4 @@ build_bin(Line, Elements) ->
848877
{ bin, Line, Elements }.
849878

850879
build_bin_element(Expr, Type, Specifier) ->
851-
{ bin_element, ?line(Expr), Expr, Type, Specifier }.
880+
{ bin_element, ?line(Expr), Expr, Type, Specifier }.

test/elixir/partial_test.exs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
Code.require_file "../test_helper", __FILE__
2+
3+
module PartialTest
4+
mixin ExUnit::Case
5+
6+
module Car
7+
def __bound__(color)
8+
@('color, color)
9+
end
10+
11+
attr_reader ['color]
12+
end
13+
14+
def partially_apply_module_bound_test
15+
1 = #PartialTest::Car(_).arity
16+
'green = #PartialTest::Car(_).('green).color
17+
end
18+
19+
def partially_apply_anonymous_function_test
20+
2 = (-> (x, y) x + y).(_, 1).(1)
21+
end
22+
23+
def partially_apply_function_test
24+
add = -> (x, y) x + y
25+
addOne = add.(1, _)
26+
3 = addOne.(2)
27+
end
28+
29+
def partially_apply_function_with_many_argumentes_test
30+
sum = -> (a, b, c, d) a + b + c + d
31+
4 = (sum.(_, 1, 1, 1).apply [1])
32+
3 = (sum.(_, _, 1, 1).apply [1, 0])
33+
2 = (sum.(_, _, _, 1).apply [1, 0, 0])
34+
1 = (sum.(_, _, _, _).apply [1, 0, 0, 0])
35+
end
36+
end

0 commit comments

Comments
 (0)