===================================================================
@@ -178,14 +178,27 @@
Loc : constant Source_Ptr := Sloc (N);
Stats : constant List_Id := Statements (N);
Typ : constant Entity_Id := Base_Type (Etype (Container));
- First_Op : constant Entity_Id :=
- Get_Iterable_Type_Primitive (Typ, Name_First);
- Next_Op : constant Entity_Id :=
- Get_Iterable_Type_Primitive (Typ, Name_Next);
+ First_Op : Entity_Id;
+ Next_Op : Entity_Id;
+
Has_Element_Op : constant Entity_Id :=
Get_Iterable_Type_Primitive (Typ, Name_Has_Element);
begin
+ -- Use the proper set of primitives depending on the direction of
+ -- iteration. The legality of a reverse iteration has been checked
+ -- during analysis.
+
+ if Reverse_Present (Iterator_Specification (Iteration_Scheme (N))) then
+ First_Op := Get_Iterable_Type_Primitive (Typ, Name_Last);
+ Next_Op := Get_Iterable_Type_Primitive (Typ, Name_Previous);
+
+ else
+ First_Op := Get_Iterable_Type_Primitive (Typ, Name_First);
+ Next_Op := Get_Iterable_Type_Primitive (Typ, Name_Next);
+ null;
+ end if;
+
-- Declaration for Cursor
Init :=
@@ -198,7 +211,7 @@
Parameter_Associations => New_List (
Convert_To_Iterable_Type (Container, Loc))));
- -- Statement that advances cursor in loop
+ -- Statement that advances (in the right direction) cursor in loop
Advance :=
Make_Assignment_Statement (Loc,
===================================================================
@@ -13200,10 +13200,13 @@
Ent := Entity (N);
F1 := First_Formal (Ent);
- if Nam = Name_First then
- -- First (Container) => Cursor
+ if Nam = Name_First
+ or else Nam = Name_Last
+ then
+ -- First or Last (Container) => Cursor
+
if Etype (Ent) /= Cursor then
Error_Msg_N ("primitive for First must yield a curosr", N);
end if;
@@ -13221,6 +13224,19 @@
Error_Msg_N ("no match for Next iterable primitive", N);
end if;
+ elsif Nam = Name_Previous then
+
+ -- Previous (Container, Cursor) => Cursor
+
+ F2 := Next_Formal (F1);
+
+ if Etype (F2) /= Cursor
+ or else Etype (Ent) /= Cursor
+ or else Present (Next_Formal (F2))
+ then
+ Error_Msg_N ("no match for Previous iterable primitive", N);
+ end if;
+
elsif Nam = Name_Has_Element then
-- Has_Element (Container, Cursor) => Boolean
@@ -14022,6 +14038,7 @@
Cursor : constant Entity_Id := Get_Cursor_Type (ASN, Typ);
First_Id : Entity_Id;
+ Last_Id : Entity_Id;
Next_Id : Entity_Id;
Has_Element_Id : Entity_Id;
Element_Id : Entity_Id;
@@ -14034,6 +14051,7 @@
end if;
First_Id := Empty;
+ Last_Id := Empty;
Next_Id := Empty;
Has_Element_Id := Empty;
Element_Id := Empty;
@@ -14054,6 +14072,14 @@
Resolve_Iterable_Operation (Expr, Cursor, Typ, Name_First);
First_Id := Entity (Expr);
+ elsif Chars (Prim) = Name_Last then
+ Resolve_Iterable_Operation (Expr, Cursor, Typ, Name_Last);
+ Last_Id := Entity (Expr);
+
+ elsif Chars (Prim) = Name_Previous then
+ Resolve_Iterable_Operation (Expr, Cursor, Typ, Name_Previous);
+ Last_Id := Entity (Expr);
+
elsif Chars (Prim) = Name_Next then
Resolve_Iterable_Operation (Expr, Cursor, Typ, Name_Next);
Next_Id := Entity (Expr);
@@ -14082,7 +14108,9 @@
elsif No (Has_Element_Id) then
Error_Msg_N ("match for Has_Element primitive not found", ASN);
- elsif No (Element_Id) then
+ elsif No (Element_Id)
+ or else No (Last_Id)
+ then
null; -- Optional.
end if;
end Validate_Iterable_Aspect;
===================================================================
@@ -1937,12 +1937,19 @@
procedure Check_Reverse_Iteration (Typ : Entity_Id) is
begin
- if Reverse_Present (N)
- and then not Is_Array_Type (Typ)
- and then not Is_Reversible_Iterator (Typ)
- then
- Error_Msg_NE
- ("container type does not support reverse iteration", N, Typ);
+ if Reverse_Present (N) then
+ if Is_Array_Type (Typ)
+ or else Is_Reversible_Iterator (Typ)
+ or else
+ (Present (Find_Aspect (Typ, Aspect_Iterable))
+ and then Present
+ (Get_Iterable_Type_Primitive (Typ, Name_Previous)))
+ then
+ null;
+ else
+ Error_Msg_NE
+ ("container type does not support reverse iteration", N, Typ);
+ end if;
end if;
end Check_Reverse_Iteration;
@@ -2303,6 +2310,7 @@
("missing Element primitive for iteration", N);
else
Set_Etype (Def_Id, Etype (Elt));
+ Check_Reverse_Iteration (Typ);
end if;
end;