diff --git a/ada/ast.py b/ada/ast.py index 55c296715..282e8eb05 100644 --- a/ada/ast.py +++ b/ada/ast.py @@ -16002,6 +16002,7 @@ class IteratedAssoc(BasicAssoc): Iterated association (Ada 2020, :rmlink:`4.3.3`). """ spec = Field(type=T.ForLoopSpec) + key_expr = Field(type=T.Expr) r_expr = Field(type=T.Expr) expr = Property(Entity.r_expr) @@ -16074,7 +16075,14 @@ def xref_equation(): # .. Then we want to match the component type Entity.expr.sub_equation & Bind(Entity.expr.expected_type_var, comp_type) - & Entity.expr.matches_expected_type, + & Entity.expr.matches_expected_type + # .. As well as the key expression if it exists + & Entity.key_expr.then( + lambda ke: ke.sub_equation + & Bind(ke.expected_type_var, index_type) + & ke.matches_expected_type, + default_val=LogicTrue() + ), # .. Else we're on an intermediate dimension of a # multidimensional array: do nothing. diff --git a/ada/grammar.py b/ada/grammar.py index e1e31f3fc..c34054bf5 100644 --- a/ada/grammar.py +++ b/ada/grammar.py @@ -1180,8 +1180,9 @@ def end_named_block(): iterated_assoc=IteratedAssoc( "for", Cut(), - A.for_loop_param_spec, "=>", - A.expr + A.for_loop_param_spec, + Opt("use", A.expr), + "=>", A.expr ), aggregate_assoc=Or( diff --git a/testsuite/tests/name_resolution/container_aggregate/ai12_0212.adb b/testsuite/tests/name_resolution/container_aggregate/ai12_0212.adb index 66f707cdf..63ffad2e9 100644 --- a/testsuite/tests/name_resolution/container_aggregate/ai12_0212.adb +++ b/testsuite/tests/name_resolution/container_aggregate/ai12_0212.adb @@ -156,9 +156,8 @@ begin -- !!! Make GNAT crash. -- The above could have been written using an explicit key_expression: - -- M:= [for Key of Keys use Key => Integer'Image (Key)]; - -- This example is not supported by LAL ([use key_expression] not parsed) - -- TODO: fix LAL, see libadalang#1050. + M:= [for Key of Keys use Key => Integer'Image (Key)]; + pragma Test_Statement; -- Example aggregates using Vector_Type diff --git a/testsuite/tests/name_resolution/container_aggregate/test.out b/testsuite/tests/name_resolution/container_aggregate/test.out index 5f045c2a2..6017dd905 100644 --- a/testsuite/tests/name_resolution/container_aggregate/test.out +++ b/testsuite/tests/name_resolution/container_aggregate/test.out @@ -533,122 +533,161 @@ Expr: type: expected type: -Resolving xrefs for node +Resolving xrefs for node **************************************************************** -Expr: +Expr: + references: + type: + expected type: None +Expr: + type: + expected type: +Expr: + references: + type: + expected type: None +Expr: + references: + type: + expected type: +Expr: + references: + type: + expected type: +Expr: + references: + type: None + expected type: None +Expr: + references: + type: None + expected type: None +Expr: + references: None + type: None + expected type: None +Expr: + references: + type: + expected type: + +Resolving xrefs for node +**************************************************************** + +Expr: references: type: expected type: None -Expr: +Expr: type: expected type: -Resolving xrefs for node +Resolving xrefs for node **************************************************************** -Expr: +Expr: references: type: expected type: None -Expr: +Expr: type: expected type: -Expr: +Expr: references: None type: expected type: -Expr: +Expr: references: None type: expected type: -Resolving xrefs for node +Resolving xrefs for node **************************************************************** -Expr: +Expr: references: type: expected type: None -Expr: +Expr: type: expected type: -Expr: +Expr: references: None type: expected type: -Expr: +Expr: references: None type: expected type: -Expr: +Expr: references: None type: expected type: -Expr: +Expr: references: None type: expected type: -Expr: +Expr: references: None type: expected type: -Expr: +Expr: references: None type: expected type: -Expr: +Expr: references: None type: expected type: -Expr: +Expr: references: None type: expected type: -Resolving xrefs for node +Resolving xrefs for node **************************************************************** -Expr: +Expr: references: type: expected type: None -Expr: +Expr: type: expected type: -Expr: +Expr: type: expected type: -Expr: +Expr: references: None type: expected type: -Expr: +Expr: references: None type: None expected type: None -Expr: +Expr: references: None type: expected type: -Expr: +Expr: references: type: expected type: -Expr: +Expr: references: type: None expected type: None -Expr: +Expr: references: type: None expected type: None -Expr: +Expr: references: None type: None expected type: None -Expr: - references: +Expr: + references: type: expected type: diff --git a/testsuite/tests/parser/iterated_assoc_key_expr/input b/testsuite/tests/parser/iterated_assoc_key_expr/input new file mode 100644 index 000000000..b8bacd89f --- /dev/null +++ b/testsuite/tests/parser/iterated_assoc_key_expr/input @@ -0,0 +1 @@ +for Key of Keys use Key => Integer'Image (Key) diff --git a/testsuite/tests/parser/iterated_assoc_key_expr/test.out b/testsuite/tests/parser/iterated_assoc_key_expr/test.out new file mode 100644 index 000000000..cc071b432 --- /dev/null +++ b/testsuite/tests/parser/iterated_assoc_key_expr/test.out @@ -0,0 +1,35 @@ +IteratedAssoc[1:1-1:47] +|f_spec: +| ForLoopSpec[1:5-1:16] +| |f_var_decl: +| | ForLoopVarDecl[1:5-1:8] +| | |f_id: +| | | DefiningName[1:5-1:8] +| | | |f_name: +| | | | Id[1:5-1:8]: Key +| | |f_id_type: +| |f_loop_type: +| | IterTypeOf[1:9-1:11] +| |f_has_reverse: +| | ReverseAbsent[1:11-1:11] +| |f_iter_expr: +| | Id[1:12-1:16]: Keys +| |f_iter_filter: +|f_key_expr: +| Id[1:21-1:24]: Key +|f_r_expr: +| CallExpr[1:28-1:47] +| |f_name: +| | AttributeRef[1:28-1:41] +| | |f_prefix: +| | | Id[1:28-1:35]: Integer +| | |f_attribute: +| | | Id[1:36-1:41]: Image +| | |f_args: +| | | AssocList[1:41-1:41]: +| |f_suffix: +| | AssocList[1:43-1:46] +| | | ParamAssoc[1:43-1:46] +| | | |f_designator: +| | | |f_r_expr: +| | | | Id[1:43-1:46]: Key diff --git a/testsuite/tests/parser/iterated_assoc_key_expr/test.yaml b/testsuite/tests/parser/iterated_assoc_key_expr/test.yaml new file mode 100644 index 000000000..d7bda34db --- /dev/null +++ b/testsuite/tests/parser/iterated_assoc_key_expr/test.yaml @@ -0,0 +1,2 @@ +driver: parser +rule: iterated_assoc diff --git a/testsuite/tests/parser/reduce_attr_1/test.out b/testsuite/tests/parser/reduce_attr_1/test.out index 4c3413a53..34157b4c8 100644 --- a/testsuite/tests/parser/reduce_attr_1/test.out +++ b/testsuite/tests/parser/reduce_attr_1/test.out @@ -25,6 +25,7 @@ ReduceAttributeRef[1:1-1:38] | | | | |f_right: | | | | | Id[1:16-1:17]: N | | | |f_iter_filter: +| | |f_key_expr: | | |f_r_expr: | | | Id[1:21-1:22]: J |f_attribute: diff --git a/user_manual/changes/libadalang/1050.yaml b/user_manual/changes/libadalang/1050.yaml new file mode 100644 index 000000000..f5f5c0991 --- /dev/null +++ b/user_manual/changes/libadalang/1050.yaml @@ -0,0 +1,8 @@ +type: new-feature +short_title: Support key expression in aggregates +title: Add support for key expression in container aggregates +description: | + Libadalang now handles key expression used in the iterated element association + of container aggregates. This change adds both parser and name resolution + support. Container aggregate is an Ada 2022 feature, see ARM 4.3.5. +date: 2023-08-11