Stats : List_Id;
begin
- L_Range := Relocate_Node (First (Discrete_Choices (Comp)));
- L_Iteration_Scheme :=
- Make_Iteration_Scheme (Loc,
- Loop_Parameter_Specification =>
- Make_Loop_Parameter_Specification (Loc,
- Defining_Identifier => Loop_Id,
- Discrete_Subtype_Definition => L_Range));
+ if Present (Iterator_Specification (Comp)) then
+ L_Iteration_Scheme :=
+ Make_Iteration_Scheme (Loc,
+ Iterator_Specification => Iterator_Specification (Comp));
+
+ else
+ L_Range := Relocate_Node (First (Discrete_Choices (Comp)));
+ L_Iteration_Scheme :=
+ Make_Iteration_Scheme (Loc,
+ Loop_Parameter_Specification =>
+ Make_Loop_Parameter_Specification (Loc,
+ Defining_Identifier => Loop_Id,
+ Discrete_Subtype_Definition => L_Range));
+ end if;
-- Build insertion statement. For a positional aggregate, only the
-- expression is needed. For a named aggregate, the loop variable,
when N_Component_Association
| N_Iterated_Component_Association
+ | N_Iterated_Element_Association
=>
if Nkind (Parent (P)) = N_Aggregate
and then Present (Loop_Actions (P))
function P_Iterated_Component_Association return Node_Id is
Assoc_Node : Node_Id;
Id : Node_Id;
+ Iter_Spec : Node_Id;
+ Loop_Spec : Node_Id;
State : Saved_Scan_State;
-- Start of processing for P_Iterated_Component_Association
-- if E is a subtype indication this is a loop parameter spec,
-- while if E a name it is an iterator_specification, and the
-- disambiguation takes place during semantic analysis.
+ -- In addition, if "use" is present after the specification,
+ -- this is an Iterated_Element_Association that carries a
+ -- key_expression, and we generate the appropriate node.
Id := P_Defining_Identifier;
Assoc_Node :=
Set_Defining_Identifier (Assoc_Node, Id);
T_In;
Set_Discrete_Choices (Assoc_Node, P_Discrete_Choice_List);
+
+ if Token = Tok_Use then
+
+ -- Key-expression is present, rewrite node as an
+ -- iterated_Element_Awwoiation.
+
+ Scan; -- past USE
+ Loop_Spec :=
+ New_Node (N_Loop_Parameter_Specification, Prev_Token_Ptr);
+ Set_Defining_Identifier (Loop_Spec, Id);
+ Set_Discrete_Subtype_Definition (Loop_Spec,
+ First (Discrete_Choices (Assoc_Node)));
+ Set_Loop_Parameter_Specification (Assoc_Node, Loop_Spec);
+ Set_Key_Expression (Assoc_Node, P_Expression);
+ end if;
+
TF_Arrow;
Set_Expression (Assoc_Node, P_Expression);
Restore_Scan_State (State);
Scan; -- past OF
Set_Defining_Identifier (Assoc_Node, Id);
- Set_Iterator_Specification
- (Assoc_Node, P_Iterator_Specification (Id));
+ Iter_Spec := P_Iterator_Specification (Id);
+ Set_Iterator_Specification (Assoc_Node, Iter_Spec);
+
+ if Token = Tok_Use then
+ Scan; -- past USE
+ -- This is an iterated_elenent_qssociation.
+
+ Assoc_Node :=
+ New_Node (N_Iterated_Element_Association, Prev_Token_Ptr);
+ Set_Iterator_Specification (Assoc_Node, Iter_Spec);
+ Set_Key_Expression (Assoc_Node, P_Expression);
+ end if;
+
TF_Arrow;
Set_Expression (Assoc_Node, P_Expression);
end if;
when N_Iterated_Component_Association =>
Diagnose_Iterated_Component_Association (N);
+ when N_Iterated_Element_Association =>
+ null; -- May require a more precise error if misplaced.
+
-- For the remaining node types, we generate compiler abort, because
-- these nodes are always analyzed within the Sem_Chn routines and
-- there should never be a case of making a call to the main Analyze
Ent : Entity_Id;
Expr : Node_Id;
Id : Entity_Id;
+ Iter : Node_Id;
Typ : Entity_Id := Empty;
begin
if Present (Iterator_Specification (Comp)) then
- Error_Msg_N ("element iterator ins aggregate Forthcoming", N);
- return;
- end if;
+ Iter := Copy_Separate_Tree (Iterator_Specification (Comp));
+ Analyze (Iter);
+ Typ := Etype (Defining_Identifier (Iter));
- Choice := First (Discrete_Choices (Comp));
+ else
+ Choice := First (Discrete_Choices (Comp));
- while Present (Choice) loop
- Analyze (Choice);
+ while Present (Choice) loop
+ Analyze (Choice);
- -- Choice can be a subtype name, a range, or an expression
+ -- Choice can be a subtype name, a range, or an expression
- if Is_Entity_Name (Choice)
- and then Is_Type (Entity (Choice))
- and then Base_Type (Entity (Choice)) = Base_Type (Key_Type)
- then
- null;
+ if Is_Entity_Name (Choice)
+ and then Is_Type (Entity (Choice))
+ and then Base_Type (Entity (Choice)) = Base_Type (Key_Type)
+ then
+ null;
- elsif Present (Key_Type) then
- Analyze_And_Resolve (Choice, Key_Type);
+ elsif Present (Key_Type) then
+ Analyze_And_Resolve (Choice, Key_Type);
- else
- Typ := Etype (Choice); -- assume unique for now
- end if;
+ else
+ Typ := Etype (Choice); -- assume unique for now
+ end if;
- Next (Choice);
- end loop;
+ Next (Choice);
+ end loop;
+ end if;
-- Create a scope in which to introduce an index, which is usually
-- visible in the expression for the component, and needed for its
or else NT (N).Nkind = N_Expression_With_Actions
or else NT (N).Nkind = N_Free_Statement
or else NT (N).Nkind = N_Iterated_Component_Association
+ or else NT (N).Nkind = N_Iterated_Element_Association
or else NT (N).Nkind = N_Mod_Clause
or else NT (N).Nkind = N_Modular_Type_Definition
or else NT (N).Nkind = N_Number_Declaration
begin
pragma Assert (False
or else NT (N).Nkind = N_Iterated_Component_Association
+ or else NT (N).Nkind = N_Iterated_Element_Association
or else NT (N).Nkind = N_Iteration_Scheme
or else NT (N).Nkind = N_Quantified_Expression);
return Node2 (N);
return Node1 (N);
end Itype;
+ function Key_Expression
+ (N : Node_Id) return Node_Id is
+ begin
+ pragma Assert (False
+ or else NT (N).Nkind = N_Iterated_Element_Association);
+ return Node1 (N);
+ end Key_Expression;
+
function Kill_Range_Check
(N : Node_Id) return Boolean is
begin
begin
pragma Assert (False
or else NT (N).Nkind = N_Component_Association
- or else NT (N).Nkind = N_Iterated_Component_Association);
+ or else NT (N).Nkind = N_Iterated_Component_Association
+ or else NT (N).Nkind = N_Iterated_Element_Association);
return List5 (N);
end Loop_Actions;
(N : Node_Id) return Node_Id is
begin
pragma Assert (False
+ or else NT (N).Nkind = N_Iterated_Element_Association
or else NT (N).Nkind = N_Iteration_Scheme
or else NT (N).Nkind = N_Quantified_Expression);
return Node4 (N);
or else NT (N).Nkind = N_Expression_With_Actions
or else NT (N).Nkind = N_Free_Statement
or else NT (N).Nkind = N_Iterated_Component_Association
+ or else NT (N).Nkind = N_Iterated_Element_Association
or else NT (N).Nkind = N_Mod_Clause
or else NT (N).Nkind = N_Modular_Type_Definition
or else NT (N).Nkind = N_Number_Declaration
begin
pragma Assert (False
or else NT (N).Nkind = N_Iterated_Component_Association
+ or else NT (N).Nkind = N_Iterated_Element_Association
or else NT (N).Nkind = N_Iteration_Scheme
or else NT (N).Nkind = N_Quantified_Expression);
Set_Node2_With_Parent (N, Val);
Set_Node1 (N, Val); -- no parent, semantic field
end Set_Itype;
+ procedure Set_Key_Expression
+ (N : Node_Id; Val : Entity_Id) is
+ begin
+ pragma Assert (False
+ or else NT (N).Nkind = N_Iterated_Element_Association);
+ Set_Node1_With_Parent (N, Val);
+ end Set_Key_Expression;
+
procedure Set_Kill_Range_Check
(N : Node_Id; Val : Boolean := True) is
begin
begin
pragma Assert (False
or else NT (N).Nkind = N_Component_Association
- or else NT (N).Nkind = N_Iterated_Component_Association);
+ or else NT (N).Nkind = N_Iterated_Component_Association
+ or else NT (N).Nkind = N_Iterated_Element_Association);
Set_List5 (N, Val); -- semantic field, no parent set
end Set_Loop_Actions;
(N : Node_Id; Val : Node_Id) is
begin
pragma Assert (False
+ or else NT (N).Nkind = N_Iterated_Element_Association
or else NT (N).Nkind = N_Iteration_Scheme
or else NT (N).Nkind = N_Quantified_Expression);
Set_Node4_With_Parent (N, Val);
-- Component_Associations (List2)
-- Etype (Node5-Sem)
+ ---------------------------------
+ -- 3.4.5 Comtainer_Aggregates --
+ ---------------------------------
+
+ -- N_Iterated_Element_Association
+ -- Key_Expression (Node1)
+ -- Iterator_Specification (Node2)
+ -- Expression (Node3)
+ -- Loop_Parameter_Specification (Node4)
+ -- Loop_Actions (List5-Sem)
+
+ -- Exactly one of Iterator_Specification or Loop_Parameter_
+ -- specification is present. If the Key_Expression is absent,
+ -- the construct is parsed as an Iterated_Component_Association,
+ -- and legality checks are performed during semantic analysis.
+
+ -- Both iterated associations are Ada2020 features that are
+ -- expanded during aggregate construction, and do not appear in
+ -- expanded code.
+
--------------------------------------------------
-- 4.4 Expression/Relation/Term/Factor/Primary --
--------------------------------------------------
N_Handled_Sequence_Of_Statements,
N_Index_Or_Discriminant_Constraint,
N_Iterated_Component_Association,
+ N_Iterated_Element_Association,
N_Itype_Reference,
N_Label,
N_Modular_Type_Definition,
function Itype
(N : Node_Id) return Entity_Id; -- Node1
+ function Key_Expression
+ (N : Node_Id) return Node_Id; -- Node1
+
function Kill_Range_Check
(N : Node_Id) return Boolean; -- Flag11
procedure Set_Itype
(N : Node_Id; Val : Entity_Id); -- Node1
+ procedure Set_Key_Expression
+ (N : Node_Id; Val : Node_Id); -- Node1
+
procedure Set_Kill_Range_Check
(N : Node_Id; Val : Boolean := True); -- Flag11
4 => True, -- Discrete_Choices (List4)
5 => True), -- Loop_Actions (List5-Sem);
+ N_Iterated_Element_Association =>
+ (1 => True, -- Key_expression
+ 2 => True, -- Iterator_Specification
+ 3 => True, -- Expression (Node3)
+ 4 => True, -- Loop_Parameter_Specification
+ 5 => True), -- Loop_Actions (List5-Sem);
+
N_Delta_Aggregate =>
(1 => False, -- Unused
2 => True, -- Component_Associations (List2)
pragma Inline (Iterator_Filter);
pragma Inline (Iteration_Scheme);
pragma Inline (Itype);
+ pragma Inline (Key_Expression);
pragma Inline (Kill_Range_Check);
pragma Inline (Last_Bit);
pragma Inline (Last_Name);
pragma Inline (Set_Iteration_Scheme);
pragma Inline (Set_Iterator_Specification);
pragma Inline (Set_Itype);
+ pragma Inline (Set_Key_Expression);
pragma Inline (Set_Kill_Range_Check);
pragma Inline (Set_Label_Construct);
pragma Inline (Set_Last_Bit);
Write_Str (" => ");
Sprint_Node (Expression (Node));
+ when N_Iterated_Element_Association =>
+ Set_Debug_Sloc;
+ if Present (Iterator_Specification (Node)) then
+ Sprint_Node (Iterator_Specification (Node));
+ else
+ Sprint_Node (Loop_Parameter_Specification (Node));
+ end if;
+
+ if Present (Key_Expression (Node)) then
+ Write_Str (" use ");
+ Sprint_Node (Key_Expression (Node));
+ end if;
+
+ Write_Str (" => ");
+ Sprint_Node (Expression (Node));
+
when N_Component_Clause =>
Write_Indent;
Sprint_Node (Component_Name (Node));
Check_Restriction (No_Implicit_Loops, Node);
if Present (Iteration_Scheme)
+ and then Nkind (Iteration_Scheme) /= N_Iterator_Specification
and then Present (Condition (Iteration_Scheme))
then
Check_Restriction (No_Implicit_Conditionals, Node);