File 0713-erl_syntax_lib-annotate-correctly.patch of Package erlang
From 95b849d942389de7cd615f4a1824c8ea9180f8dd Mon Sep 17 00:00:00 2001
From: Marko Mindek <marko.mindek@gmail.com>
Date: Sat, 14 Sep 2024 00:54:30 +0200
Subject: [PATCH] erl_syntax_lib annotate correctly
---
lib/syntax_tools/src/erl_syntax_lib.erl | 44 +++++++++++++++
lib/syntax_tools/test/syntax_tools_SUITE.erl | 58 +++++++++++++++++++-
2 files changed, 100 insertions(+), 2 deletions(-)
diff --git a/lib/syntax_tools/src/erl_syntax_lib.erl b/lib/syntax_tools/src/erl_syntax_lib.erl
index 2e0df3c46b..4e843999c1 100644
--- a/lib/syntax_tools/src/erl_syntax_lib.erl
+++ b/lib/syntax_tools/src/erl_syntax_lib.erl
@@ -470,8 +470,14 @@ vann(Tree, Env) ->
{ann_bindings(Tree, Env, Bound, Free), Bound, Free};
match_expr ->
vann_match_expr(Tree, Env);
+ maybe_expr ->
+ vann_maybe_expr(Tree, Env);
+ maybe_match_expr ->
+ vann_maybe_match_expr(Tree, Env);
case_expr ->
vann_case_expr(Tree, Env);
+ else_expr ->
+ vann_else_expr(Tree, Env);
if_expr ->
vann_if_expr(Tree, Env);
receive_expr ->
@@ -554,6 +560,27 @@ vann_match_expr(Tree, Env) ->
Tree1 = rewrite(Tree, erl_syntax:match_expr(P1, E1)),
{ann_bindings(Tree1, Env, Bound, Free), Bound, Free}.
+vann_maybe_expr(Tree, Env) ->
+ Body = erl_syntax:maybe_expr_body(Tree),
+ {B1, {_, Free1}} = vann_body(Body, Env),
+ Else = erl_syntax:maybe_expr_else(Tree),
+ {Else1, _, Free2} = vann_else_expr(Else, Env),
+ Free = ordsets:union(Free1, Free2),
+ Tree1 = rewrite(Tree, erl_syntax:maybe_expr(B1, Else1)),
+ Bound = [],
+ {ann_bindings(Tree1, Env, Bound, Free), Bound, Free}.
+
+vann_maybe_match_expr(Tree, Env) ->
+ E = erl_syntax:maybe_match_expr_body(Tree),
+ {E1, Bound1, Free1} = vann(E, Env),
+ Env1 = ordsets:union(Env, Bound1),
+ P = erl_syntax:maybe_match_expr_pattern(Tree),
+ {P1, Bound2, Free2} = vann_pattern(P, Env1),
+ Bound = ordsets:union(Bound1, Bound2),
+ Free = ordsets:union(Free1, Free2),
+ Tree1 = rewrite(Tree, erl_syntax:maybe_match_expr(P1, E1)),
+ {ann_bindings(Tree1, Env, Bound, Free), Bound, Free}.
+
vann_case_expr(Tree, Env) ->
E = erl_syntax:case_expr_argument(Tree),
{E1, Bound1, Free1} = vann(E, Env),
@@ -565,6 +592,13 @@ vann_case_expr(Tree, Env) ->
Tree1 = rewrite(Tree, erl_syntax:case_expr(E1, Cs1)),
{ann_bindings(Tree1, Env, Bound, Free), Bound, Free}.
+vann_else_expr(Tree, Env) ->
+ Cs = erl_syntax:else_expr_clauses(Tree),
+ {Cs1, {_, Free}} = vann_clauses(Cs, Env),
+ Bound = [],
+ Tree1 = rewrite(Tree, erl_syntax:else_expr(Cs1)),
+ {ann_bindings(Tree1, Env, Bound, Free), Bound, Free}.
+
vann_if_expr(Tree, Env) ->
Cs = erl_syntax:if_expr_clauses(Tree),
{Cs1, {Bound, Free}} = vann_clauses(Cs, Env),
@@ -765,6 +799,16 @@ vann_pattern(Tree, Env) ->
Free = ordsets:union(Free1, Free2),
Tree1 = rewrite(Tree, erl_syntax:match_expr(P1, E1)),
{ann_bindings(Tree1, Env, Bound, Free), Bound, Free};
+ maybe_match_expr ->
+ %% Alias pattern
+ P = erl_syntax:maybe_match_expr_pattern(Tree),
+ {P1, Bound1, Free1} = vann_pattern(P, Env),
+ E = erl_syntax:maybe_match_expr_body(Tree),
+ {E1, Bound2, Free2} = vann_pattern(E, Env),
+ Bound = ordsets:union(Bound1, Bound2),
+ Free = ordsets:union(Free1, Free2),
+ Tree1 = rewrite(Tree, erl_syntax:maybe_match_expr(P1, E1)),
+ {ann_bindings(Tree1, Env, Bound, Free), Bound, Free};
macro ->
%% The macro name must be ignored. The arguments are treated
%% as patterns.
diff --git a/lib/syntax_tools/test/syntax_tools_SUITE.erl b/lib/syntax_tools/test/syntax_tools_SUITE.erl
index 0ed660121f..36b98814c5 100644
--- a/lib/syntax_tools/test/syntax_tools_SUITE.erl
+++ b/lib/syntax_tools/test/syntax_tools_SUITE.erl
@@ -28,7 +28,8 @@
wrapped_subtrees/1,
t_abstract_type/1,t_erl_parse_type/1,t_type/1,
t_epp_dodger/1,t_epp_dodger_clever/1,
- t_comment_scan/1,t_prettypr/1,test_named_fun_bind_ann/1]).
+ t_comment_scan/1,t_prettypr/1,test_named_fun_bind_ann/1,
+ test_maybe_expr_ann/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
@@ -38,7 +39,8 @@ all() ->
wrapped_subtrees,
t_abstract_type,t_erl_parse_type,t_type,
t_epp_dodger,t_epp_dodger_clever,
- t_comment_scan,t_prettypr,test_named_fun_bind_ann].
+ t_comment_scan,t_prettypr,test_named_fun_bind_ann,
+ test_maybe_expr_ann].
groups() ->
[].
@@ -403,6 +405,58 @@ test_named_fun_bind_ann(Config) when is_list(Config) ->
{'bound',['Test']} = CBound,
{'free', []} = CFree.
+%% Test annotation of maybe_expr, maybe_match_expr and else_expr (PR #8811)
+test_maybe_expr_ann(Config) when is_list(Config) ->
+ %% maybe
+ %% ok ?= Test,
+ %% What ?= ok,
+ %% Var = What,
+ %% else
+ %% Error -> Error
+ %% end.
+ MaybeMatch1 = erl_syntax:maybe_match_expr(
+ erl_syntax:atom(ok),
+ erl_syntax:variable('Test')),
+ MaybeMatch2 = erl_syntax:maybe_match_expr(
+ erl_syntax:variable('What'),
+ erl_syntax:atom(ok)),
+ Match1 = erl_syntax:maybe_match_expr(
+ erl_syntax:variable('Var'),
+ erl_syntax:variable('What')),
+ Else = erl_syntax:else_expr(
+ [erl_syntax:clause(
+ [erl_syntax:variable('Err')],
+ 'none',
+ [erl_syntax:variable('Err')])
+ ]),
+ Maybe = erl_syntax:maybe_expr([MaybeMatch1, MaybeMatch2, Match1], Else),
+
+ MaybeAnn = erl_syntax_lib:annotate_bindings(Maybe, []),
+ [Env, Bound, Free] = erl_syntax:get_ann(MaybeAnn),
+ {'env',[]} = Env,
+ {'bound',[]} = Bound,
+ {'free',['Test']} = Free,
+
+ [MaybeMatchAnn1, MaybeMatchAnn2, MatchAnn1] = erl_syntax:maybe_expr_body(MaybeAnn),
+ [Env1, Bound1, Free1] = erl_syntax:get_ann(MaybeMatchAnn1),
+ {'env',[]} = Env1,
+ {'bound',[]} = Bound1,
+ {'free',['Test']} = Free1,
+ [Env2, Bound2, Free2] = erl_syntax:get_ann(MaybeMatchAnn2),
+ {'env',[]} = Env2,
+ {'bound',['What']} = Bound2,
+ {'free',[]} = Free2,
+ [Env3, Bound3, Free3] = erl_syntax:get_ann(MatchAnn1),
+ {'env',['What']} = Env3,
+ {'bound',['Var']} = Bound3,
+ {'free',['What']} = Free3,
+
+ ElseAnn = erl_syntax:maybe_expr_else(MaybeAnn),
+ [Env4, Bound4, Free4] = erl_syntax:get_ann(ElseAnn),
+ {'env',[]} = Env4,
+ {'bound',[]} = Bound4,
+ {'free',[]} = Free4.
+
test_files(Config) ->
DataDir = ?config(data_dir, Config),
[ filename:join(DataDir,Filename) || Filename <- test_files() ].
--
2.43.0