Element_Op : constant Entity_Id :=
Get_Iterable_Type_Primitive (Container_Typ, Name_Element);
+ Constant_Reference_Op : constant Entity_Id :=
+ Get_Iterable_Type_Primitive
+ (Container_Typ, Name_Constant_Reference);
+
Advance : Node_Id;
Init : Node_Id;
New_Loop : Node_Id;
Block : Node_Id;
begin
- -- For an element iterator, the Element aspect must be present,
- -- (this is checked during analysis).
+ -- For an element iterator, either the Element or the Constant_Reference
+ -- aspect must be present, (this is checked during analysis).
- -- We create a block to hold a variable declaration initialized with
- -- a call to Element, and generate:
+ -- If Element is present, we create a block to hold a variable
+ -- declaration initialized with a call to Element, and generate:
-- Cursor : Cursor_Type := First (Container);
-- while Has_Element (Cursor, Container) loop
-- end;
-- end loop;
+ -- If Constant_Reference is present, we introduce a constant and a
+ -- renaming, and generate:
+
+ -- Cursor : Cursor_Type := First (Container);
+ -- while Has_Element (Cursor, Container) loop
+ -- declare
+ -- Elmt : Element_Type renames
+ -- Constant_Reference (Container, Cursor).all;
+ -- begin
+ -- <original loop statements>
+ -- Cursor := Next (Container, Cursor);
+ -- end;
+ -- end loop;
+
Build_Formal_Container_Iteration
(N, Container, Cursor, Init, Advance, New_Loop);
-- Declaration for Element
- Elmt_Decl :=
- Make_Object_Declaration (Loc,
- Defining_Identifier => Element,
- Object_Definition => New_Occurrence_Of (Etype (Element_Op), Loc));
-
- Set_Expression (Elmt_Decl,
- Make_Function_Call (Loc,
- Name => New_Occurrence_Of (Element_Op, Loc),
- Parameter_Associations => New_List (
- Convert_To_Iterable_Type (Container, Loc),
- New_Occurrence_Of (Cursor, Loc))));
+ if Present (Element_Op) then
+ Elmt_Decl :=
+ Make_Object_Declaration (Loc,
+ Defining_Identifier => Element,
+ Object_Definition =>
+ New_Occurrence_Of (Etype (Element_Op), Loc));
+
+ Set_Expression (Elmt_Decl,
+ Make_Function_Call (Loc,
+ Name => New_Occurrence_Of (Element_Op, Loc),
+ Parameter_Associations => New_List (
+ Convert_To_Iterable_Type (Container, Loc),
+ New_Occurrence_Of (Cursor, Loc))));
+ else
+ Elmt_Decl :=
+ Make_Object_Renaming_Declaration (Loc,
+ Defining_Identifier => Element,
+ Subtype_Mark =>
+ New_Occurrence_Of
+ (Directly_Designated_Type
+ (Etype (Constant_Reference_Op)), Loc),
+ Name =>
+ Make_Explicit_Dereference (Loc,
+ Prefix => Make_Function_Call (Loc,
+ Name =>
+ New_Occurrence_Of (Constant_Reference_Op, Loc),
+ Parameter_Associations => New_List (
+ Convert_To_Iterable_Type (Container, Loc),
+ New_Occurrence_Of (Cursor, Loc)))));
+ end if;
Block :=
Make_Block_Statement (Loc,
Error_Msg_N ("no match for Element iterable primitive", N);
end if;
+ elsif Nam = Name_Constant_Reference then
+
+ -- Constant_Reference (Container, Cursor) =>
+ -- not null access constant Element_Type;
+
+ if No (F2)
+ or else Etype (F2) /= Cursor
+ or else Present (Next_Formal (F2))
+ or else not (Is_Anonymous_Access_Type (Etype (Ent))
+ and then Is_Access_Constant (Etype (Ent)))
+ then
+ Error_Msg_N
+ ("no match for Constant_Reference iterable primitive", N);
+
+ elsif not Can_Never_Be_Null (Etype (Ent)) then
+ Error_Msg_N
+ ("return type of primitive for Constant_Reference must have "
+ & "null exclusion", N);
+ end if;
+
else
raise Program_Error;
end if;
Set_Entity (N, It.Nam);
exit;
end if;
+
+ elsif Nam = Name_Constant_Reference then
+ F2 := Next_Formal (F1);
+
+ if Present (F2)
+ and then No (Next_Formal (F2))
+ and then Etype (F2) = Cursor
+ and then Is_Anonymous_Access_Type (Etype (It.Nam))
+ and then Is_Access_Constant (Etype (It.Nam))
+ then
+ Set_Entity (N, It.Nam);
+
+ if not Can_Never_Be_Null (Etype (It.Nam)) then
+ Error_Msg_N
+ ("return type of primitive for "
+ & "Constant_Reference must have null exclusion",
+ N);
+ end if;
+ exit;
+ end if;
end if;
end if;
Prim : Node_Id;
Cursor : Entity_Id;
- First_Id : Entity_Id := Empty;
- Last_Id : Entity_Id := Empty;
- Next_Id : Entity_Id := Empty;
- Has_Element_Id : Entity_Id := Empty;
- Element_Id : Entity_Id := Empty;
+ First_Id : Entity_Id := Empty;
+ Last_Id : Entity_Id := Empty;
+ Next_Id : Entity_Id := Empty;
+ Has_Element_Id : Entity_Id := Empty;
+ Element_Id : Entity_Id := Empty;
+ Constant_Reference_Id : Entity_Id := Empty;
begin
if Nkind (Aggr) /= N_Aggregate then
Resolve_Iterable_Operation (Expr, Cursor, Typ, Name_Element);
Element_Id := Entity (Expr);
+ elsif Chars (Prim) = Name_Constant_Reference then
+ Resolve_Iterable_Operation
+ (Expr, Cursor, Typ, Name_Constant_Reference);
+ Constant_Reference_Id := Entity (Expr);
+
else
Error_Msg_N ("invalid name for iterable function", Prim);
end if;
elsif No (Has_Element_Id) then
Error_Msg_N ("match for Has_Element primitive not found", ASN);
- elsif No (Element_Id) or else No (Last_Id) then
+ elsif Present (Element_Id) and then Present (Constant_Reference_Id) then
+ Error_Msg_N ("cannot provide both Element and Constant_Reference "
+ & "primitives", ASN);
+
+ elsif No (Element_Id)
+ or else No (Constant_Reference_Id)
+ or else No (Last_Id)
+ then
null; -- optional
end if;
end Validate_Iterable_Aspect;
if Of_Present (N) then
if Has_Aspect (Typ, Aspect_Iterable) then
declare
- Elt : constant Entity_Id :=
+ Elt : constant Entity_Id :=
Get_Iterable_Type_Primitive (Typ, Name_Element);
+ Cst_Ref : constant Entity_Id :=
+ Get_Iterable_Type_Primitive
+ (Typ, Name_Constant_Reference);
begin
- if No (Elt) then
- Error_Msg_N
- ("missing Element primitive for iteration", N);
- else
+ if Present (Elt) then
Set_Etype (Def_Id, Etype (Elt));
Check_Reverse_Iteration (Typ);
+
+ elsif Present (Cst_Ref) then
+ Set_Etype
+ (Def_Id, Directly_Designated_Type (Etype (Cst_Ref)));
+ Check_Reverse_Iteration (Typ);
+
+ else
+ Error_Msg_N
+ ("missing Element or Constant_Reference primitive for "
+ & "iteration", N);
end if;
end;