Skip to content

Commit f671e12

Browse files
author
José Valim
committed
Change precedence of <- to be the same as other generators
1 parent c0af262 commit f671e12

File tree

6 files changed

+42
-63
lines changed

6 files changed

+42
-63
lines changed

lib/elixir/lib/kernel/typespec.ex

Lines changed: 14 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -519,21 +519,7 @@ defmodule Kernel.Typespec do
519519
## Macro callbacks
520520

521521
@doc false
522-
def deftype(kind, { :::, _, [type, definition] }, caller) do
523-
do_deftype(kind, type, definition, caller)
524-
end
525-
526-
def deftype(kind, {name, _meta, args} = type, caller)
527-
when is_atom(name) and not is_list(args) do
528-
do_deftype(kind, type, { :term, [line: caller.line], nil }, caller)
529-
end
530-
531-
def deftype(_kind, other, caller) do
532-
type_spec = Macro.to_string(other)
533-
compile_error caller, "invalid type specification: #{type_spec}"
534-
end
535-
536-
defp do_deftype(kind, { name, _, args }, definition, caller) do
522+
def deftype(kind, { :::, _, [{ name, _, args }, definition] }, caller) when is_atom(name) and name != ::: do
537523
args =
538524
if is_atom(args) do
539525
[]
@@ -550,8 +536,13 @@ defmodule Kernel.Typespec do
550536
define_type(caller, kind, type)
551537
end
552538

539+
def deftype(_kind, other, caller) do
540+
type_spec = Macro.to_string(other)
541+
compile_error caller, "invalid type specification: #{type_spec}"
542+
end
543+
553544
@doc false
554-
def defspec(type, { :::, meta, [{ name, _, args }, return_and_guard] }, caller) do
545+
def defspec(type, { :::, meta, [{ name, _, args }, return_and_guard] }, caller) when is_atom(name) and name != ::: do
555546
if is_atom(args), do: args = []
556547
{ return, guard } = split_return_and_guard(return_and_guard)
557548

@@ -622,11 +613,11 @@ defmodule Kernel.Typespec do
622613
collect_vars(type)
623614
end
624615

625-
defp collect_vars({:paren_type, _line, [type]}) do
616+
defp collect_vars({ :paren_type, _line, [type] }) do
626617
collect_vars(type)
627618
end
628619

629-
defp collect_vars({:var, _line, var}) do
620+
defp collect_vars({ :var, _line, var }) do
630621
[erl_to_ex_var(var)]
631622
end
632623

@@ -721,16 +712,16 @@ defmodule Kernel.Typespec do
721712
end
722713

723714
defp typespec_to_ast({ :typed_record_field,
724-
{ :record_field, line, { :atom, line1, name }},
715+
{ :record_field, line, { :atom, line1, name } },
725716
type }) do
726717
typespec_to_ast({ :ann_type, line, [{ :var, line1, name }, type] })
727718
end
728719

729-
defp typespec_to_ast({:type, _, :any}) do
720+
defp typespec_to_ast({ :type, _, :any }) do
730721
quote do: ...
731722
end
732723

733-
defp typespec_to_ast({:paren_type, _, [type]}) do
724+
defp typespec_to_ast({ :paren_type, _, [type] }) do
734725
typespec_to_ast(type)
735726
end
736727

@@ -779,7 +770,7 @@ defmodule Kernel.Typespec do
779770
end
780771

781772
# Handle ranges
782-
defp typespec({:"..", meta, args}, vars, caller) do
773+
defp typespec({:.., meta, args}, vars, caller) do
783774
typespec({:range, meta, args}, vars, caller)
784775
end
785776

@@ -800,7 +791,7 @@ defmodule Kernel.Typespec do
800791
end
801792

802793
# Handle type operator
803-
defp typespec({:"::", meta, [var, expr] }, vars, caller) do
794+
defp typespec({:::, meta, [var, expr] }, vars, caller) do
804795
left = typespec(var, [elem(var, 0)|vars], caller)
805796
right = typespec(expr, vars, caller)
806797
{ :ann_type, line(meta), [left, right] }

lib/elixir/lib/macro.ex

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,14 @@ defmodule Macro do
3030
@spec binary_op_props(atom) :: { :left | :right, precedence :: integer }
3131
defp binary_op_props(o) do
3232
case o do
33-
::: -> {:right, 40}
34-
o when o in [:inlist, :inbits, ://, :|] -> {:right, 50}
33+
o when o in [:<-, :inlist, :inbits, ://, :::] -> {:left, 40}
34+
:| -> {:right, 50}
3535
:when -> {:right, 70}
3636
:= -> {:right, 80}
3737
o when o in [:||, :|||, :or, :xor] -> {:left, 130}
3838
o when o in [:&&, :&&&, :and] -> {:left, 140}
3939
o when o in [:==, :!=, :<, :<=, :>=, :>, :=~, :===, :!==] -> {:left, 150}
40-
o when o in [:<-, :|>, :<<<, :>>>] -> {:right, 160}
40+
o when o in [:|>, :<<<, :>>>] -> {:right, 160}
4141
:in -> {:left, 170}
4242
o when o in [:++, :--, :**, :.., :<>] -> {:right, 200}
4343
o when o in [:+, :-] -> {:left, 210}

lib/elixir/src/elixir_parser.yrl

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Nonterminals
44
bracket_expr bracket_at_expr base_expr matched_expr unmatched_expr
55
op_expr matched_op_expr no_parens_op_expr
66
comp_op_eol at_op_eol unary_op_eol and_op_eol or_op_eol
7-
add_op_eol mult_op_eol exp_op_eol two_op_eol type_op_eol stab_op_eol
7+
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
99
open_paren close_paren empty_paren
1010
open_bracket close_bracket
@@ -30,7 +30,7 @@ Terminals
3030
number signed_number atom atom_string bin_string list_string sigil
3131
dot_call_op op_identifier
3232
comp_op at_op unary_op and_op or_op arrow_op match_op in_op in_match_op
33-
dual_op add_op mult_op exp_op two_op type_op stab_op when_op
33+
dual_op add_op mult_op exp_op two_op pipe_op stab_op when_op
3434
'true' 'false' 'nil' 'do' eol ',' '.' '&'
3535
'(' ')' '[' ']' '{' '}' '<<' '>>'
3636
.
@@ -44,14 +44,14 @@ Expect 2.
4444
Left 5 do.
4545
Right 10 stab_op_eol. %% ->
4646
Left 20 ','.
47-
Right 40 type_op_eol. %% ::
48-
Right 50 in_match_op_eol. %% inlist, inbits, //, | (allowed in matches, lower precedence than =)
47+
Left 40 in_match_op_eol. %% <-, inlist, inbits, //, :: (allowed in matches along =)
48+
Right 50 pipe_op_eol. %% |
4949
Right 70 when_op_eol. %% when
5050
Right 80 match_op_eol. %% =
5151
Left 130 or_op_eol. %% ||, |||, or, xor
5252
Left 140 and_op_eol. %% &&, &&&, and
5353
Left 150 comp_op_eol. %% <, >, <=, >=, ==, !=, =~, ===, !==
54-
Right 160 arrow_op_eol. %% < (op), (op) > (e.g <-, |>, <<<, >>>)
54+
Right 160 arrow_op_eol. %% < (op), (op) > (e.g |>, <<<, >>>)
5555
Left 170 in_op_eol. %% in
5656
Right 200 two_op_eol. %% ++, --, **, .., <>
5757
Left 210 add_op_eol. %% + (op), - (op)
@@ -137,7 +137,7 @@ op_expr -> or_op_eol expr : { '$1', '$2' }.
137137
op_expr -> in_op_eol expr : { '$1', '$2' }.
138138
op_expr -> in_match_op_eol expr : { '$1', '$2' }.
139139
op_expr -> when_op_eol expr : { '$1', '$2' }.
140-
op_expr -> type_op_eol expr : { '$1', '$2' }.
140+
op_expr -> pipe_op_eol expr : { '$1', '$2' }.
141141
op_expr -> comp_op_eol expr : { '$1', '$2' }.
142142
op_expr -> arrow_op_eol expr : { '$1', '$2' }.
143143

@@ -150,7 +150,7 @@ no_parens_op_expr -> and_op_eol no_parens_expr : { '$1', '$2' }.
150150
no_parens_op_expr -> or_op_eol no_parens_expr : { '$1', '$2' }.
151151
no_parens_op_expr -> in_op_eol no_parens_expr : { '$1', '$2' }.
152152
no_parens_op_expr -> in_match_op_eol no_parens_expr : { '$1', '$2' }.
153-
no_parens_op_expr -> type_op_eol no_parens_expr : { '$1', '$2' }.
153+
no_parens_op_expr -> pipe_op_eol no_parens_expr : { '$1', '$2' }.
154154
no_parens_op_expr -> comp_op_eol no_parens_expr : { '$1', '$2' }.
155155
no_parens_op_expr -> arrow_op_eol no_parens_expr : { '$1', '$2' }.
156156

@@ -168,7 +168,7 @@ matched_op_expr -> or_op_eol matched_expr : { '$1', '$2' }.
168168
matched_op_expr -> in_op_eol matched_expr : { '$1', '$2' }.
169169
matched_op_expr -> in_match_op_eol matched_expr : { '$1', '$2' }.
170170
matched_op_expr -> when_op_eol matched_expr : { '$1', '$2' }.
171-
matched_op_expr -> type_op_eol matched_expr : { '$1', '$2' }.
171+
matched_op_expr -> pipe_op_eol matched_expr : { '$1', '$2' }.
172172
matched_op_expr -> comp_op_eol matched_expr : { '$1', '$2' }.
173173
matched_op_expr -> arrow_op_eol matched_expr : { '$1', '$2' }.
174174

@@ -297,8 +297,8 @@ exp_op_eol -> exp_op eol : '$1'.
297297
two_op_eol -> two_op : '$1'.
298298
two_op_eol -> two_op eol : '$1'.
299299

300-
type_op_eol -> type_op : '$1'.
301-
type_op_eol -> type_op eol : '$1'.
300+
pipe_op_eol -> pipe_op : '$1'.
301+
pipe_op_eol -> pipe_op eol : '$1'.
302302

303303
unary_op_eol -> unary_op : '$1'.
304304
unary_op_eol -> unary_op eol : '$1'.

lib/elixir/src/elixir_tokenizer.erl

Lines changed: 13 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@
3939
T1 == $>, T2 == $>, T3 == $>).
4040

4141
-define(arrow_op(T1, T2),
42-
T1 == $<, T2 == $-;
4342
T1 == $|, T2 == $>).
4443

4544
-define(comp_op(T),
@@ -72,17 +71,16 @@
7271
-define(match_op(T),
7372
T == $=).
7473

75-
-define(in_match_op(T),
76-
T == $|).
77-
78-
-define(in_match_op2(T1, T2),
79-
T1 == $/, T2 == $/).
74+
-define(in_match_op(T1, T2),
75+
T1 == $<, T2 == $-;
76+
T1 == $/, T2 == $/;
77+
T1 == $:, T2 == $:).
8078

8179
-define(stab_op(T1, T2),
8280
T1 == $-, T2 == $>).
8381

84-
-define(type_op(T1, T2),
85-
T1 == $:, T2 == $:).
82+
-define(pipe_op(T1),
83+
T == $|).
8684

8785
tokenize(String, Line, #elixir_tokenizer{} = Scope) ->
8886
tokenize(String, Line, Scope, []);
@@ -232,13 +230,13 @@ tokenize([$.,T1,T2,T3|Rest], Line, Scope, Tokens) when
232230
% ## Two Token Operators
233231
tokenize([$.,T1,T2|Rest], Line, Scope, Tokens) when
234232
?comp_op2(T1, T2); ?and_op(T1, T2); ?or_op(T1, T2); ?arrow_op(T1, T2);
235-
?in_match_op2(T1, T2); ?two_op(T1, T2); ?stab_op(T1, T2); ?type_op(T1, T2) ->
233+
?in_match_op(T1, T2); ?two_op(T1, T2); ?stab_op(T1, T2) ->
236234
handle_call_identifier(Rest, Line, list_to_atom([T1, T2]), Scope, Tokens);
237235

238236
% ## Single Token Operators
239237
tokenize([$.,T|Rest], Line, Scope, Tokens) when
240238
?at_op(T); ?unary_op(T); ?dual_op(T); ?mult_op(T); ?comp_op(T);
241-
?match_op(T); ?in_match_op(T) ->
239+
?match_op(T); ?pipe_op(T) ->
242240
handle_call_identifier(Rest, Line, list_to_atom([T]), Scope, Tokens);
243241

244242
% Dot call
@@ -318,13 +316,13 @@ tokenize([$:,T1,T2,T3|Rest], Line, Scope, Tokens) when
318316
% ## Two Token Operators
319317
tokenize([$:,T1,T2|Rest], Line, Scope, Tokens) when
320318
?comp_op2(T1, T2); ?and_op(T1, T2); ?or_op(T1, T2); ?arrow_op(T1, T2);
321-
?in_match_op2(T1, T2); ?two_op(T1, T2); ?stab_op(T1, T2); ?type_op(T1, T2) ->
319+
?in_match_op(T1, T2); ?two_op(T1, T2); ?stab_op(T1, T2) ->
322320
tokenize(Rest, Line, Scope, [{ atom, Line, list_to_atom([T1,T2]) }|Tokens]);
323321

324322
% ## Single Token Operators
325323
tokenize([$:,T|Rest], Line, Scope, Tokens) when
326324
?at_op(T); ?unary_op(T); ?dual_op(T); ?mult_op(T); ?comp_op(T);
327-
?match_op(T); ?in_match_op(T); T == $. ->
325+
?match_op(T); ?pipe_op(T); T == $. ->
328326
tokenize(Rest, Line, Scope, [{ atom, Line, list_to_atom([T]) }|Tokens]);
329327

330328
% End of line
@@ -394,15 +392,12 @@ tokenize([T1,T2|Rest], Line, Scope, Tokens) when ?and_op(T1, T2) ->
394392
tokenize([T1,T2|Rest], Line, Scope, Tokens) when ?or_op(T1, T2) ->
395393
handle_op(Rest, Line, or_op, list_to_atom([T1, T2]), Scope, Tokens);
396394

397-
tokenize([T1,T2|Rest], Line, Scope, Tokens) when ?in_match_op2(T1, T2) ->
395+
tokenize([T1,T2|Rest], Line, Scope, Tokens) when ?in_match_op(T1, T2) ->
398396
handle_op(Rest, Line, in_match_op, list_to_atom([T1, T2]), Scope, Tokens);
399397

400398
tokenize([T1,T2|Rest], Line, Scope, Tokens) when ?stab_op(T1, T2) ->
401399
handle_op(Rest, Line, stab_op, list_to_atom([T1, T2]), Scope, Tokens);
402400

403-
tokenize([T1,T2|Rest], Line, Scope, Tokens) when ?type_op(T1, T2) ->
404-
handle_op(Rest, Line, type_op, list_to_atom([T1, T2]), Scope, Tokens);
405-
406401
% ## Single Token Operators
407402

408403
%% Handle &1 and friends with special precedence.
@@ -427,8 +422,8 @@ tokenize([T|Rest], Line, Scope, Tokens) when ?mult_op(T) ->
427422
tokenize([T|Rest], Line, Scope, Tokens) when ?match_op(T) ->
428423
handle_op(Rest, Line, match_op, list_to_atom([T]), Scope, Tokens);
429424

430-
tokenize([T|Rest], Line, Scope, Tokens) when ?in_match_op(T) ->
431-
handle_op(Rest, Line, in_match_op, list_to_atom([T]), Scope, Tokens);
425+
tokenize([T|Rest], Line, Scope, Tokens) when ?pipe_op(T) ->
426+
handle_op(Rest, Line, pipe_op, list_to_atom([T]), Scope, Tokens);
432427

433428
tokenize([$.|Rest], Line, Scope, Tokens) ->
434429
tokenize(Rest, Line, Scope, add_token_with_nl({ '.', Line }, Tokens));

lib/elixir/test/elixir/typespec_test.exs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -43,13 +43,6 @@ defmodule Typespec.TypeTest do
4343
end
4444
end
4545

46-
test "@type with no body (defaults to 'term')" do
47-
spec = test_module do
48-
@type mytype
49-
end
50-
assert {:mytype, {:type, _, :term, []}, []} = spec
51-
end
52-
5346
test "@type with a single type" do
5447
spec = test_module do
5548
@type mytype :: term
@@ -238,7 +231,7 @@ defmodule Typespec.TypeTest do
238231
239232
test "@type with annotations" do
240233
{spec1, spec2} = test_module do
241-
t1 = @type mytype :: named :: integer
234+
t1 = @type mytype :: (named :: integer)
242235
t2 = @type mytype1 :: (a :: integer -> integer)
243236
{t1, t2}
244237
end

lib/elixir/test/erlang/tokenizer_test.erl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ tokenize_error(String) ->
1111
Error.
1212

1313
type_test() ->
14-
[{number,1,1},{type_op,1,'::'},{number,1,3}] = tokenize("1 :: 3"),
14+
[{number,1,1},{in_match_op,1,'::'},{number,1,3}] = tokenize("1 :: 3"),
1515
[{identifier,1,foo},
1616
{'.',1},
1717
{paren_identifier,1,'::'},

0 commit comments

Comments
 (0)