Skip to content

Commit 3773c98

Browse files
committed
Merge branch 'isabell/syntax-tools/map-28/GH-10119/OTP-19817' into maint
* isabell/syntax-tools/map-28/GH-10119/OTP-19817: syntax_tools: Annotate map comprehensions and generators
2 parents ea56ac0 + eddf879 commit 3773c98

File tree

2 files changed

+37
-73
lines changed

2 files changed

+37
-73
lines changed

lib/syntax_tools/src/erl_syntax_lib.erl

Lines changed: 22 additions & 71 deletions
Original file line numberDiff line numberDiff line change
@@ -508,6 +508,8 @@ vann(Tree, Env) ->
508508
vann_list_comp(Tree, Env);
509509
binary_comp ->
510510
vann_binary_comp(Tree, Env);
511+
map_comp ->
512+
vann_map_comp(Tree, Env);
511513
generator ->
512514
vann_generator(Tree, Env);
513515
strict_generator ->
@@ -675,7 +677,7 @@ vann_receive_expr(Tree, Env) ->
675677

676678
vann_list_comp(Tree, Env) ->
677679
Es = erl_syntax:list_comp_body(Tree),
678-
{Es1, {Bound1, Free1}} = vann_list_comp_body(Es, Env),
680+
{Es1, {Bound1, Free1}} = vann_comp_body(Es, Env),
679681
Env1 = ordsets:union(Env, Bound1),
680682
T = erl_syntax:list_comp_template(Tree),
681683
{T1, _, Free2} = vann(T, Env1),
@@ -684,44 +686,9 @@ vann_list_comp(Tree, Env) ->
684686
Tree1 = rewrite(Tree, erl_syntax:list_comp(T1, Es1)),
685687
{ann_bindings(Tree1, Env, Bound, Free), Bound, Free}.
686688

687-
vann_list_comp_body_join() ->
688-
fun (T, {Env, Bound, Free}) ->
689-
{T1, Bound1, Free1} = case erl_syntax:type(T) of
690-
generator ->
691-
vann_generator(T, Env);
692-
strict_generator ->
693-
vann_strict_generator(T, Env);
694-
binary_generator ->
695-
vann_binary_generator(T,Env);
696-
strict_binary_generator ->
697-
vann_strict_binary_generator(T,Env);
698-
map_generator ->
699-
vann_map_generator(T,Env);
700-
strict_map_generator ->
701-
vann_strict_map_generator(T,Env);
702-
zip_generator ->
703-
vann_zip_generator(T,Env);
704-
_ ->
705-
%% Bindings in filters are not
706-
%% exported to the rest of the
707-
%% body.
708-
{T2, _, Free2} = vann(T, Env),
709-
{T2, [], Free2}
710-
end,
711-
Env1 = ordsets:union(Env, Bound1),
712-
{T1, {Env1, ordsets:union(Bound, Bound1),
713-
ordsets:union(Free,
714-
ordsets:subtract(Free1, Bound))}}
715-
end.
716-
717-
vann_list_comp_body(Ts, Env) ->
718-
F = vann_list_comp_body_join(),
719-
{Ts1, {_, Bound, Free}} = lists:mapfoldl(F, {Env, [], []}, Ts),
720-
{Ts1, {Bound, Free}}.
721-
722689
vann_binary_comp(Tree, Env) ->
723690
Es = erl_syntax:binary_comp_body(Tree),
724-
{Es1, {Bound1, Free1}} = vann_binary_comp_body(Es, Env),
691+
{Es1, {Bound1, Free1}} = vann_comp_body(Es, Env),
725692
Env1 = ordsets:union(Env, Bound1),
726693
T = erl_syntax:binary_comp_template(Tree),
727694
{T1, _, Free2} = vann(T, Env1),
@@ -730,7 +697,23 @@ vann_binary_comp(Tree, Env) ->
730697
Tree1 = rewrite(Tree, erl_syntax:binary_comp(T1, Es1)),
731698
{ann_bindings(Tree1, Env, Bound, Free), Bound, Free}.
732699

733-
vann_binary_comp_body_join() ->
700+
vann_map_comp(Tree, Env) ->
701+
Es = erl_syntax:map_comp_body(Tree),
702+
{Es1, {Bound1, Free1}} = vann_comp_body(Es, Env),
703+
Env1 = ordsets:union(Env, Bound1),
704+
T = erl_syntax:map_comp_template(Tree),
705+
{T1, _, Free2} = vann(T, Env1),
706+
Free = ordsets:union(Free1, ordsets:subtract(Free2, Bound1)),
707+
Bound = [],
708+
Tree1 = rewrite(Tree, erl_syntax:map_comp(T1, Es1)),
709+
{ann_bindings(Tree1, Env, Bound, Free), Bound, Free}.
710+
711+
vann_comp_body(Ts, Env) ->
712+
F = vann_comp_body_join(),
713+
{Ts1, {_, Bound, Free}} = lists:mapfoldl(F, {Env, [], []}, Ts),
714+
{Ts1, {Bound, Free}}.
715+
716+
vann_comp_body_join() ->
734717
fun (T, {Env, Bound, Free}) ->
735718
{T1, Bound1, Free1} = case erl_syntax:type(T) of
736719
generator ->
@@ -760,38 +743,6 @@ vann_binary_comp_body_join() ->
760743
ordsets:subtract(Free1, Bound))}}
761744
end.
762745

763-
vann_binary_comp_body(Ts, Env) ->
764-
F = vann_binary_comp_body_join(),
765-
{Ts1, {_, Bound, Free}} = lists:mapfoldl(F, {Env, [], []}, Ts),
766-
{Ts1, {Bound, Free}}.
767-
768-
vann_zip_generator_body_join() ->
769-
fun (T, {Env, Bound, Free}) ->
770-
{T1, Bound1, Free1} = case erl_syntax:type(T) of
771-
generator ->
772-
vann_generator(T, Env);
773-
strict_generator ->
774-
vann_strict_generator(T, Env);
775-
binary_generator ->
776-
vann_binary_generator(T,Env);
777-
strict_binary_generator ->
778-
vann_strict_binary_generator(T,Env);
779-
map_generator ->
780-
vann_map_generator(T,Env);
781-
strict_map_generator ->
782-
vann_strict_map_generator(T,Env)
783-
end,
784-
Env1 = ordsets:union(Env, Bound1),
785-
{T1, {Env1, ordsets:union(Bound, Bound1),
786-
ordsets:union(Free,
787-
ordsets:subtract(Free1, Bound))}}
788-
end.
789-
790-
vann_zip_generator_body(Ts, Env) ->
791-
F = vann_zip_generator_body_join(),
792-
{Ts1, {_, Bound, Free}} = lists:mapfoldl(F, {Env, [], []}, Ts),
793-
{Ts1, {Bound, Free}}.
794-
795746
%% In list comprehension generators, the pattern variables are always
796747
%% viewed as new occurrences, shadowing whatever is in the input
797748
%% environment (thus, the pattern contains no variable uses, only
@@ -847,7 +798,7 @@ vann_strict_map_generator(Tree, Env) ->
847798

848799
vann_zip_generator(Tree, Env) ->
849800
Es = erl_syntax:zip_generator_body(Tree),
850-
{Es1, {Bound, Free}} = vann_zip_generator_body(Es, Env),
801+
{Es1, {Bound, Free}} = vann_comp_body(Es, Env),
851802
Env1 = ordsets:union(Env, Bound),
852803
Tree1 = rewrite(Tree, erl_syntax:zip_generator(Es1)),
853804
{ann_bindings(Tree1, Env1, Bound, Free), Bound, Free}.

lib/syntax_tools/test/syntax_tools_SUITE.erl

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@
4343
t_abstract_type/1,t_erl_parse_type/1,t_type/1,
4444
t_epp_dodger/1,t_epp_dodger_clever/1,
4545
t_comment_scan/1,t_prettypr/1,test_named_fun_bind_ann/1,
46-
test_maybe_expr_ann/1,test_zip_ann/1]).
46+
test_maybe_expr_ann/1,test_mc_ann/1,test_zip_ann/1]).
4747

4848
suite() -> [{ct_hooks,[ts_install_cth]}].
4949

@@ -54,7 +54,7 @@ all() ->
5454
t_abstract_type,t_erl_parse_type,t_type,
5555
t_epp_dodger,t_epp_dodger_clever,
5656
t_comment_scan,t_prettypr,test_named_fun_bind_ann,
57-
test_maybe_expr_ann,test_zip_ann].
57+
test_maybe_expr_ann,test_mc_ann,test_zip_ann].
5858

5959
groups() ->
6060
[].
@@ -492,6 +492,19 @@ test_maybe_expr_ann(Config) when is_list(Config) ->
492492

493493
ok.
494494

495+
test_mc_ann(Config) when is_list(Config) ->
496+
Expr = {mc,1,
497+
{map_field_assoc,1,{var,1,'X'},{var,1,'Y'}},
498+
[{generate,1,
499+
{tuple,1,[{var,1,'X'},{var,1,'Y'}]},
500+
{var,1,'Pairs'}}]},
501+
ZipAnn = erl_syntax_lib:annotate_bindings(Expr, []),
502+
[Env, Bound, Free] = erl_syntax:get_ann(ZipAnn),
503+
{'env',[]} = Env,
504+
{'bound',[]} = Bound,
505+
{'free',['Pairs']} = Free,
506+
ok.
507+
495508
test_zip_ann(Config) when is_list(Config) ->
496509
Expr = {lc,1,
497510
{tuple,1,[{var,1,'A'},{var,1,'B'}]},

0 commit comments

Comments
 (0)