From eb13bf2f70e3f6368f12c4895cb9013432a34295 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Laurent=20Th=C3=A9venoux?= Date: Fri, 24 May 2024 16:02:05 +0200 Subject: [PATCH 1/2] Fix name resolution of assocs in declare expression env --- ada/ast.py | 5 +- .../declare_expr_aggregate/test.adb | 29 +++++ .../declare_expr_aggregate/test.out | 102 ++++++++++++++++++ .../declare_expr_aggregate/test.yaml | 2 + 4 files changed, 137 insertions(+), 1 deletion(-) create mode 100644 testsuite/tests/name_resolution/declare_expr_aggregate/test.adb create mode 100644 testsuite/tests/name_resolution/declare_expr_aggregate/test.out create mode 100644 testsuite/tests/name_resolution/declare_expr_aggregate/test.yaml diff --git a/ada/ast.py b/ada/ast.py index 6116df361..a416d86f6 100644 --- a/ada/ast.py +++ b/ada/ast.py @@ -1055,7 +1055,10 @@ def resolve_children_names(generate_diagnostics=Bool): c.as_entity.xref_stop_resolution, entry_point.bind( c, - c.as_entity.resolve_own_names(generate_diagnostics) + env.bind( + Entity.xref_initial_env, + c.as_entity.resolve_own_names(generate_diagnostics) + ) ), True ) & c.as_entity.resolve_children_names(generate_diagnostics), diff --git a/testsuite/tests/name_resolution/declare_expr_aggregate/test.adb b/testsuite/tests/name_resolution/declare_expr_aggregate/test.adb new file mode 100644 index 000000000..921a08ae9 --- /dev/null +++ b/testsuite/tests/name_resolution/declare_expr_aggregate/test.adb @@ -0,0 +1,29 @@ +pragma Ada_2022; + +procedure Test is + type A is array (Natural range 0 .. 1) of Integer; + + function F return A is + (declare + I : constant Integer := 0; + J : constant Integer := 1; + begin (I, J)); + pragma Test_Statement; + + function G return Integer is + (declare + K : constant Integer := 2; + begin (K)); + pragma Test_Statement; + + type B is array (Natural range 0 .. 1) of A; + K : Integer := 3; + + function H return B is + (declare + K : constant Integer := 2; + begin (B'First => (K, K), B'Last => (K, K))); + pragma Test_Statement; +begin + null; +end; diff --git a/testsuite/tests/name_resolution/declare_expr_aggregate/test.out b/testsuite/tests/name_resolution/declare_expr_aggregate/test.out new file mode 100644 index 000000000..96d956939 --- /dev/null +++ b/testsuite/tests/name_resolution/declare_expr_aggregate/test.out @@ -0,0 +1,102 @@ +Analyzing test.adb +################## + +Resolving xrefs for node +**************************************************************** + +Expr: + type: + expected type: +Expr: + type: + expected type: +Expr: + type: + expected type: +Expr: + references: + type: + expected type: +Expr: + references: + type: + expected type: + +Resolving xrefs for node +***************************************************************** + +Expr: + type: + expected type: +Expr: + type: + expected type: +Expr: + type: + expected type: +Expr: + references: + type: + expected type: + +Resolving xrefs for node +***************************************************************** + +Expr: + type: + expected type: +Expr: + type: + expected type: +Expr: + type: + expected type: +Expr: + references: None + type: + expected type: +Expr: + references: + type: None + expected type: None +Expr: + references: None + type: None + expected type: None +Expr: + type: + expected type: +Expr: + references: + type: + expected type: +Expr: + references: + type: + expected type: +Expr: + references: None + type: + expected type: +Expr: + references: + type: None + expected type: None +Expr: + references: None + type: None + expected type: None +Expr: + type: + expected type: +Expr: + references: + type: + expected type: +Expr: + references: + type: + expected type: + + +Done. diff --git a/testsuite/tests/name_resolution/declare_expr_aggregate/test.yaml b/testsuite/tests/name_resolution/declare_expr_aggregate/test.yaml new file mode 100644 index 000000000..173e325ff --- /dev/null +++ b/testsuite/tests/name_resolution/declare_expr_aggregate/test.yaml @@ -0,0 +1,2 @@ +driver: name-resolution +input_sources: [test.adb] From b633e98852d3a5728e417f846107de7fddd3cf55 Mon Sep 17 00:00:00 2001 From: Romain Beguet Date: Thu, 27 Jun 2024 15:19:40 +0200 Subject: [PATCH 2/2] Adapt resolve_names_from_closest_entry_point to use own xref_initial_env. --- ada/ast.py | 100 ++++++------------ .../declare_expr_aggregate_2/test.adb | 23 ++++ .../declare_expr_aggregate_2/test.out | 11 ++ .../declare_expr_aggregate_2/test.yaml | 2 + 4 files changed, 70 insertions(+), 66 deletions(-) create mode 100644 testsuite/tests/name_resolution/declare_expr_aggregate_2/test.adb create mode 100644 testsuite/tests/name_resolution/declare_expr_aggregate_2/test.out create mode 100644 testsuite/tests/name_resolution/declare_expr_aggregate_2/test.yaml diff --git a/ada/ast.py b/ada/ast.py index a416d86f6..de7cfa4d9 100644 --- a/ada/ast.py +++ b/ada/ast.py @@ -1115,21 +1115,32 @@ def resolve_names(): origin.bind(Self.origin_node, Entity.resolve_names_internal(False)) ) - @langkit_property(return_type=T.LexicalEnv) - def resolve_names_from_closest_entry_point_impl(): + @langkit_property(return_type=Bool) + def resolve_names_from_closest_entry_point(): """ - Implementation helper for ``resolve_names_from_closest_entry_point``. - Instead of returning a Boolean, it returns a LexicalEnv, which is - either None (indicating that resolution failed), or contains the - lexical environment which the children of that node should bind when - resolving their own names. This allows propagating the initial env - we got from ``Entity.xref_initial_env`` on the closest xref entry - point. + Resolve names from the closest entry point up to this node. Note that + unlike ``resolve_names``, this will *not* trigger resolution of every + node with stop_resolution that lie in the sub-tree formed by the + closest entry point. It will only resolve those that are in the path to + resolving Self. Consider for example the following entry point: + + .. code:: + + R := (A, B); + + Since aggregate association nodes have ``stop_resolution`` set to True, + calling ``resolve_names_from_closest_entry_point`` on ``B`` will + resolve nodes ``R`` and ``B`` but not ``A``, because ``A`` does not lie + on the path to ``B``. + + This can be useful for resolving aggregates of variant records, because + resolution of a component association can safely call the resolution + of a discriminant association without triggering an infinite recursion, + as both are on different "paths". """ return If( - # This is the closest entry point: resolve its names and return - # its `xref_initial_env` if resolution succeeded, so that children - # will be able to use it to resolve their own names. + # This is the closest entry point: resolve its names and stop the + # recursion. Entity.xref_entry_point, env.bind( Entity.xref_initial_env, @@ -1137,78 +1148,35 @@ def resolve_names_from_closest_entry_point_impl(): Self.origin_node, entry_point.bind( Self, - If(Entity.resolve_own_names(False), - env, - No(LexicalEnv)) + Entity.resolve_own_names(False) ) ) ), - Let( - # Recurse in order to resolve names from the closest entry - # point: `res` will contain the environment to use if we need - # to resolve names inside Self, or None if resolution failed. - lambda - res=Entity.parent - ._.resolve_names_from_closest_entry_point_impl: - - env.bind( - res, + # Otherwise, recurse on the parent + Entity.parent._.resolve_names_from_closest_entry_point.then( + lambda _: env.bind( + Entity.xref_initial_env, origin.bind( Self.origin_node, - Cond( - # Resolution failed for the parent, so return None - # as well. - res == No(T.LexicalEnv), - res, - + If( # Resolution succeeded for the parent and this is a - # stop resolution, so re-use the parent environment - # to resolve Self's names. + # stop resolution, so resolve own names as well. Entity.xref_stop_resolution, entry_point.bind( Self, - If(Entity.resolve_own_names(False), - res, - No(LexicalEnv)) + Entity.resolve_own_names(False) ), - # Resolution succeeded but there is nothing to do - # on that particular node: return the parent - # environment, so that deeper children can use it. - res + # Resolution succeeded and there is nothing to do + # on that particular node: return successfully. + True ) ) ) ) ) - @langkit_property(return_type=Bool) - def resolve_names_from_closest_entry_point(): - """ - Resolve names from the closest entry point up to this node. Note that - unlike ``resolve_names``, this will *not* trigger resolution of every - node with stop_resolution that lie in the sub-tree formed by the - closest entry point. It will only resolve those that are in the path to - resolving Self. Consider for example the following entry point: - - .. code:: - - R := (A, B); - - Since aggregate association nodes have ``stop_resolution`` set to True, - calling ``resolve_names_from_closest_entry_point`` on ``B`` will - resolve nodes ``R`` and ``B`` but not ``A``, because ``A`` does not lie - on the path to ``B``. - - This can be useful for resolving aggregates of variant records, because - resolution of a component association can safely call the resolution - of a discriminant association without triggering an infinite recursion, - as both are on different "paths". - """ - result = Var(Entity.resolve_names_from_closest_entry_point_impl) - return result != No(LexicalEnv) - @langkit_property(return_type=T.SolverDiagnostic.array, external=True, call_memoizable=True, uses_entity_info=True, uses_envs=True) diff --git a/testsuite/tests/name_resolution/declare_expr_aggregate_2/test.adb b/testsuite/tests/name_resolution/declare_expr_aggregate_2/test.adb new file mode 100644 index 000000000..8f0d1179d --- /dev/null +++ b/testsuite/tests/name_resolution/declare_expr_aggregate_2/test.adb @@ -0,0 +1,23 @@ +pragma Ada_2022; + +procedure Test is + type A is array (Natural range 0 .. 1) of Integer; + + function F return A is + (declare + I : constant Integer := 0; + J : constant Integer := 1; + begin (I, J)); + --% node.findall(lal.AggregateAssoc)[0].f_r_expr.p_referenced_decl() + + type B is array (Natural range 0 .. 1) of A; + K : Integer := 3; + + function H return B is + (declare + K : constant Integer := 2; + begin (B'First => (K, K), B'Last => (K, K))); + --% node.findall(lal.AggregateAssoc)[-1].f_r_expr.p_referenced_decl() +begin + null; +end; diff --git a/testsuite/tests/name_resolution/declare_expr_aggregate_2/test.out b/testsuite/tests/name_resolution/declare_expr_aggregate_2/test.out new file mode 100644 index 000000000..af6401571 --- /dev/null +++ b/testsuite/tests/name_resolution/declare_expr_aggregate_2/test.out @@ -0,0 +1,11 @@ +Working on node +======================================================= + +Eval 'node.findall(lal.AggregateAssoc)[0].f_r_expr.p_referenced_decl()' +Result: + +Working on node +======================================================== + +Eval 'node.findall(lal.AggregateAssoc)[-1].f_r_expr.p_referenced_decl()' +Result: diff --git a/testsuite/tests/name_resolution/declare_expr_aggregate_2/test.yaml b/testsuite/tests/name_resolution/declare_expr_aggregate_2/test.yaml new file mode 100644 index 000000000..35ad4d5c4 --- /dev/null +++ b/testsuite/tests/name_resolution/declare_expr_aggregate_2/test.yaml @@ -0,0 +1,2 @@ +driver: inline-playground +input_sources: [test.adb]