Skip to content

Commit b4415f2

Browse files
author
José Valim
committed
Change precedence of & to not special case /
1 parent 538b51c commit b4415f2

File tree

4 files changed

+25
-16
lines changed

4 files changed

+25
-16
lines changed

lib/elixir/src/elixir_parser.yrl

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ Nonterminals
33
expr container_expr block_expr no_parens_expr no_parens_one_expr access_expr
44
bracket_expr bracket_at_expr bracket_arg matched_expr unmatched_expr max_expr
55
op_expr matched_op_expr no_parens_op_expr
6-
comp_op_eol at_op_eol unary_op_eol and_op_eol or_op_eol
6+
comp_op_eol at_op_eol unary_op_eol and_op_eol or_op_eol capture_op_eol
77
add_op_eol mult_op_eol exp_op_eol two_op_eol pipe_op_eol stab_op_eol
88
arrow_op_eol match_op_eol when_op_eol in_op_eol in_match_op_eol type_op_eol
99
open_paren close_paren empty_paren
@@ -29,7 +29,7 @@ Terminals
2929
number signed_number atom atom_safe atom_unsafe bin_string list_string sigil
3030
dot_call_op op_identifier
3131
comp_op at_op unary_op and_op or_op arrow_op match_op in_op in_match_op type_op
32-
dual_op add_op mult_op exp_op two_op pipe_op stab_op when_op assoc_op
32+
dual_op add_op mult_op exp_op two_op pipe_op stab_op when_op assoc_op capture_op
3333
'true' 'false' 'nil' 'do' eol ',' '.'
3434
'(' ')' '[' ']' '{' '}' '<<' '>>' '%{}' '%'
3535
.
@@ -45,6 +45,7 @@ Expect 2.
4545
Left 5 do.
4646
Right 10 stab_op_eol. %% ->
4747
Left 20 ','.
48+
Nonassoc 30 capture_op_eol. %% &
4849
Left 40 in_match_op_eol. %% <-, \\ (allowed in matches along =)
4950
Right 50 when_op_eol. %% when
5051
Right 60 type_op_eol. %% ::
@@ -60,7 +61,7 @@ Right 200 two_op_eol. %% ++, --, .., <>
6061
Left 210 add_op_eol. %% + (op), - (op)
6162
Left 220 mult_op_eol. %% * (op), / (op)
6263
Left 250 exp_op_eol. %% ^ (op) (e.g ^^^)
63-
Nonassoc 300 unary_op_eol. %% +, -, !, ^, not, &, ~~~
64+
Nonassoc 300 unary_op_eol. %% +, -, !, ^, not, ~~~
6465
Left 310 dot_call_op.
6566
Left 310 dot_op. %% .
6667
Nonassoc 320 at_op_eol. %% @
@@ -112,6 +113,8 @@ matched_expr -> unary_op_eol matched_expr : build_unary_op('$1', '$2').
112113
matched_expr -> unary_op_eol no_parens_expr : build_unary_op('$1', '$2').
113114
matched_expr -> at_op_eol matched_expr : build_unary_op('$1', '$2').
114115
matched_expr -> at_op_eol no_parens_expr : build_unary_op('$1', '$2').
116+
matched_expr -> capture_op_eol matched_expr : build_unary_op('$1', '$2').
117+
matched_expr -> capture_op_eol no_parens_expr : build_unary_op('$1', '$2').
115118
matched_expr -> no_parens_one_expr : '$1'.
116119
matched_expr -> access_expr : '$1'.
117120

@@ -123,6 +126,7 @@ unmatched_expr -> matched_expr op_expr : build_op(element(1, '$2'), '$1', elemen
123126
unmatched_expr -> unmatched_expr op_expr : build_op(element(1, '$2'), '$1', element(2, '$2')).
124127
unmatched_expr -> unary_op_eol expr : build_unary_op('$1', '$2').
125128
unmatched_expr -> at_op_eol expr : build_unary_op('$1', '$2').
129+
unmatched_expr -> capture_op_eol expr : build_unary_op('$1', '$2').
126130
unmatched_expr -> block_expr : '$1'.
127131

128132
block_expr -> parens_call call_args_parens do_block : build_identifier('$1', '$2' ++ '$3').
@@ -189,7 +193,9 @@ no_parens_one_expr -> dot_identifier : build_identifier('$1', nil).
189193
%% marks identifiers followed by brackets as bracket_identifier.
190194
access_expr -> bracket_at_expr : '$1'.
191195
access_expr -> bracket_expr : '$1'.
196+
access_expr -> at_op_eol number : build_unary_op('$1', ?exprs('$2')).
192197
access_expr -> unary_op_eol number : build_unary_op('$1', ?exprs('$2')).
198+
access_expr -> capture_op_eol number : build_unary_op('$1', ?exprs('$2')).
193199
access_expr -> fn_eol stab end_eol : build_fn('$1', build_stab(reverse('$2'))).
194200
access_expr -> open_paren stab close_paren : build_stab(reverse('$2')).
195201
access_expr -> number : ?exprs('$1').
@@ -313,6 +319,9 @@ two_op_eol -> two_op eol : '$1'.
313319
pipe_op_eol -> pipe_op : '$1'.
314320
pipe_op_eol -> pipe_op eol : '$1'.
315321

322+
capture_op_eol -> capture_op : '$1'.
323+
capture_op_eol -> capture_op eol : '$1'.
324+
316325
unary_op_eol -> unary_op : '$1'.
317326
unary_op_eol -> unary_op eol : '$1'.
318327
unary_op_eol -> dual_op : '$1'.
@@ -532,12 +541,6 @@ meta(Node) -> meta(?line(Node)).
532541

533542
%% Operators
534543

535-
build_op({_Kind, Line, '/'}, {'&', _, [{Kind, _, Atom} = Left]}, Right) when is_number(Right), is_atom(Atom), is_atom(Kind) ->
536-
{'&', meta(Line), [{'/', meta(Line), [Left, Right]}]};
537-
538-
build_op({_Kind, Line, '/'}, {'&', _, [{{'.', _, [_, _]}, _, []} = Left]}, Right) when is_number(Right) ->
539-
{'&', meta(Line), [{'/', meta(Line), [Left, Right]}]};
540-
541544
build_op({_Kind, Line, 'in'}, {UOp, _, [Left]}, Right) when ?rearrange_uop(UOp) ->
542545
{UOp, meta(Line), [{'in', meta(Line), [Left, Right]}]};
543546

lib/elixir/src/elixir_tokenizer.erl

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,10 @@
66
-define(at_op(T),
77
T == $@).
88

9+
-define(capture_op(T),
10+
T == $&).
11+
912
-define(unary_op(T),
10-
T == $&;
1113
T == $!;
1214
T == $^).
1315

@@ -294,7 +296,7 @@ tokenize([$:,T1,T2|Rest], Line, Scope, Tokens) when
294296

295297
% ## Single Token Operators
296298
tokenize([$:,T|Rest], Line, Scope, Tokens) when
297-
?at_op(T); ?unary_op(T); ?dual_op(T); ?mult_op(T); ?comp_op(T);
299+
?at_op(T); ?unary_op(T); ?capture_op(T); ?dual_op(T); ?mult_op(T); ?comp_op(T);
298300
?match_op(T); ?pipe_op(T); T == $. ->
299301
tokenize(Rest, Line, Scope, [{atom, Line, list_to_atom([T])}|Tokens]);
300302

@@ -386,6 +388,9 @@ tokenize([T1,T2|Rest], Line, Scope, Tokens) when ?stab_op(T1, T2) ->
386388
tokenize([T|Rest], Line, Scope, Tokens) when ?at_op(T) ->
387389
handle_unary_op(Rest, Line, at_op, list_to_atom([T]), Scope, Tokens);
388390

391+
tokenize([T|Rest], Line, Scope, Tokens) when ?capture_op(T) ->
392+
handle_unary_op(Rest, Line, capture_op, list_to_atom([T]), Scope, Tokens);
393+
389394
tokenize([T|Rest], Line, Scope, Tokens) when ?unary_op(T) ->
390395
handle_unary_op(Rest, Line, unary_op, list_to_atom([T]), Scope, Tokens);
391396

@@ -549,7 +554,7 @@ handle_dot([$.,T1,T2|Rest], Line, Scope, Tokens) when
549554

550555
% ## Single Token Operators
551556
handle_dot([$.,T|Rest], Line, Scope, Tokens) when
552-
?at_op(T); ?unary_op(T); ?dual_op(T); ?mult_op(T); ?comp_op(T);
557+
?at_op(T); ?unary_op(T); ?capture_op(T); ?dual_op(T); ?mult_op(T); ?comp_op(T);
553558
?match_op(T); ?pipe_op(T); T == $% ->
554559
handle_call_identifier(Rest, Line, list_to_atom([T]), Scope, Tokens);
555560

lib/elixir/test/elixir/kernel/fn_test.exs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ defmodule Kernel.FnTest do
2222
assert (&List.flatten/1).([[0]]) == [0]
2323
assert (&(List.flatten/1)).([[0]]) == [0]
2424
assert (&List.flatten(&1)).([[0]]) == [0]
25-
assert &List.flatten(&1) == &List.flatten/1
25+
assert (&List.flatten(&1)) == (&List.flatten/1)
2626
end
2727

2828
test "capture local" do
@@ -41,7 +41,7 @@ defmodule Kernel.FnTest do
4141
assert (&is_atom/1).(:a)
4242
assert (&(is_atom/1)).(:a)
4343
assert (&is_atom(&1)).(:a)
44-
assert &is_atom(&1) == &is_atom/1
44+
assert (&is_atom(&1)) == &is_atom/1
4545
end
4646

4747
test "capture macro" do
@@ -54,6 +54,7 @@ defmodule Kernel.FnTest do
5454
test "capture operator" do
5555
assert is_function &+/2
5656
assert is_function &(&&/2)
57+
assert is_function & &1 + &2, 2
5758
end
5859

5960
test "capture with variable module" do

lib/mix/lib/mix/compilers/elixir.ex

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ defmodule Mix.Compilers.Elixir do
107107
|> Enum.map(&Atom.to_string(&1))
108108
|> Enum.reject(&match?("elixir_" <> _, &1))
109109

110-
files = for file <- get_external_resources(module, cwd),
110+
files = for file <- get_external_resources(module),
111111
File.regular?(file),
112112
relative = Path.relative_to(file, cwd),
113113
Path.type(relative) == :relative,
@@ -116,7 +116,7 @@ defmodule Mix.Compilers.Elixir do
116116
Agent.cast pid, &:lists.keystore(beam, 1, &1, {beam, bin, source, deps, files, binary})
117117
end
118118

119-
defp get_external_resources(module, cwd) do
119+
defp get_external_resources(module) do
120120
module.__info__(:attributes)[:external_resource] || []
121121
end
122122

0 commit comments

Comments
 (0)