[Ada] Fixed bugs in iterators for set containers

Arnaud Charlet charlet@adacore.com
Wed Nov 23 13:52:00 GMT 2011


There were several issues with the implementation of the set iterators.

The concrete type Iterator is declared as limited, because there is no need for
assignment for iterator objects.

For the ordered forms (which support specifying the start position when
iterating), the First and Last selector functions return a value that depends
on whether this is complete or partial iteration. For complete iteration, the
selector function returns the logical beginning of the entire sequence of items
in the container. (To be specific, Container.First for a forward iterator, and
Container.Last for a reverse iterator.) For partial iteration, the selector
function returns the start position value specified when the iterator object
was constructed (in this case, both First and Last return the same value).

The hashed forms do not support specifying a start position, so the node
component has been removed from the implementation of the iterator type.

The Next and Previous iterator operations vet the cursor parameter to ensure
that it designates a node in the same container as the iterator. The function
then forwards to the call to the analogous cursor-based operation.

Iterate constructs an iterator object whose state indicates whether this is
complete or partial iteration. There was also change in the semantics of the
partial iterator (per the ARG meeting in Denver on 2011/11): if the start
position equals No_Element, then it raises Constraint_Error; otherwise, it
constructs an iterator object to indicate the position from which the iteration
begins (which is in turn used by the selector functions First and Last).

Tested on x86_64-pc-linux-gnu, committed on trunk

2011-11-23  Matthew Heaney  <heaney@adacore.com>

	* a-coorse.ads, a-ciorse.ads, a-cborse.ads (Set_Iterator_Interfaces):
	Renamed from Ordered_Set_Iterator_Interfaces.
	* a-coorse.adb, a-ciorse.adb, a-cborse.adb (Iterator): Declared
	Iterator type as limited (First, Last): Cursor return value
	depends on iterator node value (Iterate): Use start position as
	iterator node value (Next, Previous): Forward to corresponding
	cursor-based operation.
	* a-cohase.ads, a-cohase.adb: Implemented forward iterator.
	* a-cihase.adb, a-cbhase.adb (Iterator): Removed unnecessary
	node component (First, Next): Forward call to corresponding
	cursor-based operation (Iterate): Representation of iterator no
	longer has node component

-------------- next part --------------
Index: a-ciorse.adb
===================================================================
--- a-ciorse.adb	(revision 181662)
+++ a-ciorse.adb	(working copy)
@@ -42,9 +42,9 @@
 
 package body Ada.Containers.Indefinite_Ordered_Sets is
 
-   type Iterator is new
-     Ordered_Set_Iterator_Interfaces.Reversible_Iterator with record
-        Container : access constant Set;
+   type Iterator is limited new
+     Set_Iterator_Interfaces.Reversible_Iterator with record
+        Container : Set_Access;
         Node      : Node_Access;
      end record;
 
@@ -600,8 +600,24 @@
 
    function First (Object : Iterator) return Cursor is
    begin
-      return Cursor'(
-        Object.Container.all'Unrestricted_Access, Object.Container.Tree.First);
+      --  The value of the iterator object's Node component influences the
+      --  behavior of the First (and Last) selector function.
+
+      --  When the Node component is null, this means the iterator object was
+      --  constructed without a start expression, in which case the (forward)
+      --  iteration starts from the (logical) beginning of the entire sequence
+      --  of items (corresponding to Container.First, for a forward iterator).
+
+      --  Otherwise, this is iteration over a partial sequence of items. When
+      --  the Node component is non-null, the iterator object was constructed
+      --  with a start expression, that specifies the position from which the
+      --  (forward) partial iteration begins.
+
+      if Object.Node = null then
+         return Object.Container.First;
+      else
+         return Cursor'(Object.Container, Object.Node);
+      end if;
    end First;
 
    -------------------
@@ -1259,22 +1275,62 @@
 
    function Iterate
      (Container : Set)
-      return Ordered_Set_Iterator_Interfaces.Reversible_Iterator'class
+      return Set_Iterator_Interfaces.Reversible_Iterator'Class
    is
-      It : constant Iterator :=
-             (Container'Unchecked_Access, Container.Tree.First);
    begin
-      return It;
+      --  The value of the Node component influences the behavior of the First
+      --  and Last selector functions of the iterator object. When the Node
+      --  component is null (as is the case here), this means the iterator
+      --  object was constructed without a start expression. This is a complete
+      --  iterator, meaning that the iteration starts from the (logical)
+      --  beginning of the sequence of items.
+
+      --  Note: For a forward iterator, Container.First is the beginning, and
+      --  for a reverse iterator, Container.Last is the beginning.
+
+      return Iterator'(Container'Unrestricted_Access, Node => null);
    end Iterate;
 
    function Iterate
      (Container : Set;
       Start     : Cursor)
-      return Ordered_Set_Iterator_Interfaces.Reversible_Iterator'class
+      return Set_Iterator_Interfaces.Reversible_Iterator'Class
    is
-      It : constant Iterator := (Container'Unchecked_Access, Start.Node);
    begin
-      return It;
+      --  It was formerly the case that when Start = No_Element, the partial
+      --  iterator was defined to behave the same as for a complete iterator,
+      --  and iterate over the entire sequence of items. However, those
+      --  semantics were unintuitive and arguably error-prone (it is too easy
+      --  to accidentally create an endless loop), and so they were changed,
+      --  per the ARG meeting in Denver on 2011/11. However, there was no
+      --  consensus about what positive meaning this corner case should have,
+      --  and so it was decided to simply raise an exception. This does imply,
+      --  however, that it is not possible to use a partial iterator to specify
+      --  an empty sequence of items.
+
+      if Start = No_Element then
+         raise Constraint_Error with
+           "Start position for iterator equals No_Element";
+      end if;
+
+      if Start.Container /= Container'Unrestricted_Access then
+         raise Program_Error with
+           "Start cursor of Iterate designates wrong set";
+      end if;
+
+      pragma Assert (Vet (Container.Tree, Start.Node),
+                     "Start cursor of Iterate is bad");
+
+      --  The value of the Node component influences the behavior of the First
+      --  and Last selector functions of the iterator object. When the Node
+      --  component is non-null (as is the case here), it means that this is a
+      --  partial iteration, over a subset of the complete sequence of
+      --  items. The iterator object was constructed with a start expression,
+      --  indicating the position from which the iteration begins. Note that
+      --  the start position has the same value irrespective of whether this is
+      --  a forward or reverse iteration.
+
+      return Iterator'(Container'Unrestricted_Access, Node => Start.Node);
    end Iterate;
 
    ----------
@@ -1290,9 +1346,24 @@
 
    function Last (Object : Iterator) return Cursor is
    begin
-      return (if Object.Container.Tree.Last = null then No_Element
-              else Cursor'(Object.Container.all'Unrestricted_Access,
-                           Object.Container.Tree.Last));
+      --  The value of the iterator object's Node component influences the
+      --  behavior of the Last (and First) selector function.
+
+      --  When the Node component is null, this means the iterator object was
+      --  constructed without a start expression, in which case the (reverse)
+      --  iteration starts from the (logical) beginning of the entire sequence
+      --  (corresponding to Container.Last, for a reverse iterator).
+
+      --  Otherwise, this is iteration over a partial sequence of items. When
+      --  the Node component is non-null, the iterator object was constructed
+      --  with a start expression, that specifies the position from which the
+      --  (reverse) partial iteration begins.
+
+      if Object.Node = null then
+         return Object.Container.Last;
+      else
+         return Cursor'(Object.Container, Object.Node);
+      end if;
    end Last;
 
    ------------------
@@ -1372,8 +1443,16 @@
      (Object   : Iterator;
       Position : Cursor) return Cursor
    is
-      pragma Unreferenced (Object);
    begin
+      if Position.Container = null then
+         return No_Element;
+      end if;
+
+      if Position.Container /= Object.Container then
+         raise Program_Error with
+           "Position cursor of Next designates wrong set";
+      end if;
+
       return Next (Position);
    end Next;
 
@@ -1430,8 +1509,16 @@
      (Object   : Iterator;
       Position : Cursor) return Cursor
    is
-      pragma Unreferenced (Object);
    begin
+      if Position.Container = null then
+         return No_Element;
+      end if;
+
+      if Position.Container /= Object.Container then
+         raise Program_Error with
+           "Position cursor of Previous designates wrong set";
+      end if;
+
       return Previous (Position);
    end Previous;
 
Index: a-ciorse.ads
===================================================================
--- a-ciorse.ads	(revision 181662)
+++ a-ciorse.ads	(working copy)
@@ -64,7 +64,7 @@
 
    function Has_Element (Position : Cursor) return Boolean;
 
-   package Ordered_Set_Iterator_Interfaces is new
+   package Set_Iterator_Interfaces is new
      Ada.Iterator_Interfaces (Cursor, Has_Element);
 
    type Constant_Reference_Type
@@ -233,12 +233,12 @@
 
    function Iterate
      (Container : Set)
-      return Ordered_Set_Iterator_Interfaces.Reversible_Iterator'class;
+      return Set_Iterator_Interfaces.Reversible_Iterator'class;
 
    function Iterate
      (Container : Set;
       Start     : Cursor)
-      return Ordered_Set_Iterator_Interfaces.Reversible_Iterator'class;
+      return Set_Iterator_Interfaces.Reversible_Iterator'class;
 
    generic
       type Key_Type (<>) is private;
Index: a-cihase.adb
===================================================================
--- a-cihase.adb	(revision 181662)
+++ a-cihase.adb	(working copy)
@@ -41,10 +41,10 @@
 
 package body Ada.Containers.Indefinite_Hashed_Sets is
 
-   type Iterator is new Set_Iterator_Interfaces.Forward_Iterator with record
-      Container : Set_Access;
-      Position  : Cursor;
-   end record;
+   type Iterator is limited new
+     Set_Iterator_Interfaces.Forward_Iterator with record
+        Container : Set_Access;
+     end record;
 
    overriding function First (Object : Iterator) return Cursor;
 
@@ -649,10 +649,8 @@
    end First;
 
    function First (Object : Iterator) return Cursor is
-      Node : constant Node_Access := HT_Ops.First (Object.Container.HT);
    begin
-      return (if Node = null then No_Element
-              else Cursor'(Object.Container, Node));
+      return Object.Container.First;
    end First;
 
    ----------
@@ -1011,7 +1009,7 @@
    function Iterate (Container : Set)
      return Set_Iterator_Interfaces.Forward_Iterator'Class is
    begin
-      return Iterator'(Container'Unrestricted_Access, First (Container));
+      return Iterator'(Container => Container'Unrestricted_Access);
    end Iterate;
 
    ------------
@@ -1072,12 +1070,16 @@
       Position : Cursor) return Cursor
    is
    begin
+      if Position.Container = null then
+         return No_Element;
+      end if;
+
       if Position.Container /= Object.Container then
          raise Program_Error with
-           "Position cursor designates wrong set";
+           "Position cursor of Next designates wrong set";
       end if;
 
-      return (if Position.Node = null then No_Element else Next (Position));
+      return Next (Position);
    end Next;
 
    -------------
@@ -1895,7 +1897,7 @@
          Key_Keys.Delete_Key_Sans_Free (Container.HT, Key, X);
 
          if X = null then
-            raise Constraint_Error with "key not in map";
+            raise Constraint_Error with "key not in map";  -- ??? "set"
          end if;
 
          Free (X);
@@ -1913,7 +1915,7 @@
 
       begin
          if Node = null then
-            raise Constraint_Error with "key not in map";
+            raise Constraint_Error with "key not in map";  -- ??? "set"
          end if;
 
          return Node.Element.all;
Index: a-coorse.adb
===================================================================
--- a-coorse.adb	(revision 181662)
+++ a-coorse.adb	(working copy)
@@ -42,9 +42,9 @@
 
 package body Ada.Containers.Ordered_Sets is
 
-   type Iterator is new
-     Ordered_Set_Iterator_Interfaces.Reversible_Iterator with record
-        Container : access constant Set;
+   type Iterator is limited new
+     Set_Iterator_Interfaces.Reversible_Iterator with record
+        Container : Set_Access;
         Node      : Node_Access;
      end record;
 
@@ -537,9 +537,24 @@
 
    function First (Object : Iterator) return Cursor is
    begin
-      return (if Object.Container = null then No_Element
-              else Cursor'(Object.Container.all'Unrestricted_Access,
-                           Object.Container.Tree.First));
+      --  The value of the iterator object's Node component influences the
+      --  behavior of the First (and Last) selector function.
+
+      --  When the Node component is null, this means the iterator object was
+      --  constructed without a start expression, in which case the (forward)
+      --  iteration starts from the (logical) beginning of the entire sequence
+      --  of items (corresponding to Container.First, for a forward iterator).
+
+      --  Otherwise, this is iteration over a partial sequence of items. When
+      --  the Node component is non-null, the iterator object was constructed
+      --  with a start expression, that specifies the position from which the
+      --  (forward) partial iteration begins.
+
+      if Object.Node = null then
+         return Object.Container.First;
+      else
+         return Cursor'(Object.Container, Object.Node);
+      end if;
    end First;
 
    -------------------
@@ -1165,22 +1180,60 @@
    end Iterate;
 
    function Iterate (Container : Set)
-     return Ordered_Set_Iterator_Interfaces.Reversible_Iterator'class
+     return Set_Iterator_Interfaces.Reversible_Iterator'Class
    is
    begin
-      if Container.Length = 0 then
-         return Iterator'(null, null);
-      else
-         return Iterator'(Container'Unchecked_Access, Container.Tree.First);
-      end if;
+      --  The value of the Node component influences the behavior of the First
+      --  and Last selector functions of the iterator object. When the Node
+      --  component is null (as is the case here), this means the iterator
+      --  object was constructed without a start expression. This is a complete
+      --  iterator, meaning that the iteration starts from the (logical)
+      --  beginning of the sequence of items.
+
+      --  Note: For a forward iterator, Container.First is the beginning, and
+      --  for a reverse iterator, Container.Last is the beginning.
+
+      return Iterator'(Container'Unrestricted_Access, Node => null);
    end Iterate;
 
    function Iterate (Container : Set; Start : Cursor)
-     return Ordered_Set_Iterator_Interfaces.Reversible_Iterator'class
+     return Set_Iterator_Interfaces.Reversible_Iterator'Class
    is
-      It : constant Iterator := (Container'Unchecked_Access, Start.Node);
    begin
-      return It;
+      --  It was formerly the case that when Start = No_Element, the partial
+      --  iterator was defined to behave the same as for a complete iterator,
+      --  and iterate over the entire sequence of items. However, those
+      --  semantics were unintuitive and arguably error-prone (it is too easy
+      --  to accidentally create an endless loop), and so they were changed,
+      --  per the ARG meeting in Denver on 2011/11. However, there was no
+      --  consensus about what positive meaning this corner case should have,
+      --  and so it was decided to simply raise an exception. This does imply,
+      --  however, that it is not possible to use a partial iterator to specify
+      --  an empty sequence of items.
+
+      if Start = No_Element then
+         raise Constraint_Error with
+           "Start position for iterator equals No_Element";
+      end if;
+
+      if Start.Container /= Container'Unrestricted_Access then
+         raise Program_Error with
+           "Start cursor of Iterate designates wrong set";
+      end if;
+
+      pragma Assert (Vet (Container.Tree, Start.Node),
+                     "Start cursor of Iterate is bad");
+
+      --  The value of the Node component influences the behavior of the First
+      --  and Last selector functions of the iterator object. When the Node
+      --  component is non-null (as is the case here), it means that this is a
+      --  partial iteration, over a subset of the complete sequence of
+      --  items. The iterator object was constructed with a start expression,
+      --  indicating the position from which the iteration begins. Note that
+      --  the start position has the same value irrespective of whether this is
+      --  a forward or reverse iteration.
+
+      return Iterator'(Container'Unrestricted_Access, Node => Start.Node);
    end Iterate;
 
    ----------
@@ -1196,9 +1249,24 @@
 
    function Last (Object : Iterator) return Cursor is
    begin
-      return (if Object.Container = null then No_Element
-              else Cursor'(Object.Container.all'Unrestricted_Access,
-                           Object.Container.Tree.Last));
+      --  The value of the iterator object's Node component influences the
+      --  behavior of the Last (and First) selector function.
+
+      --  When the Node component is null, this means the iterator object was
+      --  constructed without a start expression, in which case the (reverse)
+      --  iteration starts from the (logical) beginning of the entire sequence
+      --  (corresponding to Container.Last, for a reverse iterator).
+
+      --  Otherwise, this is iteration over a partial sequence of items. When
+      --  the Node component is non-null, the iterator object was constructed
+      --  with a start expression, that specifies the position from which the
+      --  (reverse) partial iteration begins.
+
+      if Object.Node = null then
+         return Object.Container.Last;
+      else
+         return Cursor'(Object.Container, Object.Node);
+      end if;
    end Last;
 
    ------------------
@@ -1271,8 +1339,16 @@
    end Next;
 
    function Next (Object : Iterator; Position : Cursor) return Cursor is
-      pragma Unreferenced (Object);
    begin
+      if Position.Container = null then
+         return No_Element;
+      end if;
+
+      if Position.Container /= Object.Container then
+         raise Program_Error with
+           "Position cursor of Next designates wrong set";
+      end if;
+
       return Next (Position);
    end Next;
 
@@ -1322,8 +1398,16 @@
    end Previous;
 
    function Previous (Object : Iterator; Position : Cursor) return Cursor is
-      pragma Unreferenced (Object);
    begin
+      if Position.Container = null then
+         return No_Element;
+      end if;
+
+      if Position.Container /= Object.Container then
+         raise Program_Error with
+           "Position cursor of Previous designates wrong set";
+      end if;
+
       return Previous (Position);
    end Previous;
 
Index: a-coorse.ads
===================================================================
--- a-coorse.ads	(revision 181662)
+++ a-coorse.ads	(working copy)
@@ -65,7 +65,7 @@
 
    No_Element : constant Cursor;
 
-   package Ordered_Set_Iterator_Interfaces is new
+   package Set_Iterator_Interfaces is new
      Ada.Iterator_Interfaces (Cursor, Has_Element);
 
    type Constant_Reference_Type
@@ -227,12 +227,12 @@
 
    function Iterate
      (Container : Set)
-      return Ordered_Set_Iterator_Interfaces.Reversible_Iterator'class;
+      return Set_Iterator_Interfaces.Reversible_Iterator'class;
 
    function Iterate
      (Container : Set;
       Start     : Cursor)
-      return Ordered_Set_Iterator_Interfaces.Reversible_Iterator'class;
+      return Set_Iterator_Interfaces.Reversible_Iterator'class;
 
    generic
       type Key_Type (<>) is private;
Index: a-cborse.adb
===================================================================
--- a-cborse.adb	(revision 181662)
+++ a-cborse.adb	(working copy)
@@ -42,9 +42,9 @@
 
 package body Ada.Containers.Bounded_Ordered_Sets is
 
-   type Iterator is new
-     Ordered_Set_Iterator_Interfaces.Reversible_Iterator with record
-        Container : access constant Set;
+   type Iterator is limited new
+     Set_Iterator_Interfaces.Reversible_Iterator with record
+        Container : Set_Access;
         Node      : Count_Type;
      end record;
 
@@ -591,9 +591,24 @@
 
    function First (Object : Iterator) return Cursor is
    begin
-      return (if Object.Container.First = 0 then No_Element
-              else Cursor'(Object.Container.all'Unrestricted_Access,
-                           Object.Container.First));
+      --  The value of the iterator object's Node component influences the
+      --  behavior of the First (and Last) selector function.
+
+      --  When the Node component is 0, this means the iterator object was
+      --  constructed without a start expression, in which case the (forward)
+      --  iteration starts from the (logical) beginning of the entire sequence
+      --  of items (corresponding to Container.First, for a forward iterator).
+
+      --  Otherwise, this is iteration over a partial sequence of items. When
+      --  the Node component is positive, the iterator object was constructed
+      --  with a start expression, that specifies the position from which the
+      --  (forward) partial iteration begins.
+
+      if Object.Node = 0 then
+         return Bounded_Ordered_Sets.First (Object.Container.all);
+      else
+         return Cursor'(Object.Container, Object.Node);
+      end if;
    end First;
 
    -------------------
@@ -1206,22 +1221,60 @@
    end Iterate;
 
    function Iterate (Container : Set)
-     return Ordered_Set_Iterator_Interfaces.Reversible_Iterator'class
+     return Set_Iterator_Interfaces.Reversible_Iterator'Class
    is
    begin
-      if Container.Length = 0 then
-         return Iterator'(null, 0);
-      else
-         return Iterator'(Container'Unchecked_Access, Container.First);
-      end if;
+      --  The value of the Node component influences the behavior of the First
+      --  and Last selector functions of the iterator object. When the Node
+      --  component is 0 (as is the case here), this means the iterator object
+      --  was constructed without a start expression. This is a complete
+      --  iterator, meaning that the iteration starts from the (logical)
+      --  beginning of the sequence of items.
+
+      --  Note: For a forward iterator, Container.First is the beginning, and
+      --  for a reverse iterator, Container.Last is the beginning.
+
+      return Iterator'(Container'Unrestricted_Access, Node => 0);
    end Iterate;
 
    function Iterate (Container : Set; Start : Cursor)
-     return Ordered_Set_Iterator_Interfaces.Reversible_Iterator'class
+     return Set_Iterator_Interfaces.Reversible_Iterator'Class
    is
-      It : constant Iterator := (Container'Unchecked_Access, Start.Node);
    begin
-      return It;
+      --  It was formerly the case that when Start = No_Element, the partial
+      --  iterator was defined to behave the same as for a complete iterator,
+      --  and iterate over the entire sequence of items. However, those
+      --  semantics were unintuitive and arguably error-prone (it is too easy
+      --  to accidentally create an endless loop), and so they were changed,
+      --  per the ARG meeting in Denver on 2011/11. However, there was no
+      --  consensus about what positive meaning this corner case should have,
+      --  and so it was decided to simply raise an exception. This does imply,
+      --  however, that it is not possible to use a partial iterator to specify
+      --  an empty sequence of items.
+
+      if Start = No_Element then
+         raise Constraint_Error with
+           "Start position for iterator equals No_Element";
+      end if;
+
+      if Start.Container /= Container'Unrestricted_Access then
+         raise Program_Error with
+           "Start cursor of Iterate designates wrong set";
+      end if;
+
+      pragma Assert (Vet (Container, Start.Node),
+                     "Start cursor of Iterate is bad");
+
+      --  The value of the Node component influences the behavior of the First
+      --  and Last selector functions of the iterator object. When the Node
+      --  component is positive (as is the case here), it means that this
+      --  is a partial iteration, over a subset of the complete sequence of
+      --  items. The iterator object was constructed with a start expression,
+      --  indicating the position from which the iteration begins. (Note that
+      --  the start position has the same value irrespective of whether this
+      --  is a forward or reverse iteration.)
+
+      return Iterator'(Container'Unrestricted_Access, Node => Start.Node);
    end Iterate;
 
    ----------
@@ -1236,9 +1289,24 @@
 
    function Last (Object : Iterator) return Cursor is
    begin
-      return (if Object.Container.Last = 0 then No_Element
-              else Cursor'(Object.Container.all'Unrestricted_Access,
-                           Object.Container.Last));
+      --  The value of the iterator object's Node component influences the
+      --  behavior of the Last (and First) selector function.
+
+      --  When the Node component is 0, this means the iterator object was
+      --  constructed without a start expression, in which case the (reverse)
+      --  iteration starts from the (logical) beginning of the entire sequence
+      --  (corresponding to Container.Last, for a reverse iterator).
+
+      --  Otherwise, this is iteration over a partial sequence of items. When
+      --  the Node component is positive, the iterator object was constructed
+      --  with a start expression, that specifies the position from which the
+      --  (reverse) partial iteration begins.
+
+      if Object.Node = 0 then
+         return Bounded_Ordered_Sets.Last (Object.Container.all);
+      else
+         return Cursor'(Object.Container, Object.Node);
+      end if;
    end Last;
 
    ------------------
@@ -1323,8 +1391,16 @@
    end Next;
 
    function Next (Object : Iterator; Position : Cursor) return Cursor is
-      pragma Unreferenced (Object);
    begin
+      if Position.Container = null then
+         return No_Element;
+      end if;
+
+      if Position.Container /= Object.Container then
+         raise Program_Error with
+           "Position cursor of Next designates wrong set";
+      end if;
+
       return Next (Position);
    end Next;
 
@@ -1374,8 +1450,16 @@
    end Previous;
 
    function Previous (Object : Iterator; Position : Cursor) return Cursor is
-      pragma Unreferenced (Object);
    begin
+      if Position.Container = null then
+         return No_Element;
+      end if;
+
+      if Position.Container /= Object.Container then
+         raise Program_Error with
+           "Position cursor of Previous designates wrong set";
+      end if;
+
       return Previous (Position);
    end Previous;
 
Index: a-cborse.ads
===================================================================
--- a-cborse.ads	(revision 181662)
+++ a-cborse.ads	(working copy)
@@ -31,9 +31,9 @@
 -- This unit was originally developed by Matthew J Heaney.                  --
 ------------------------------------------------------------------------------
 
-with Ada.Iterator_Interfaces;
 private with Ada.Containers.Red_Black_Trees;
 with Ada.Streams; use Ada.Streams;
+with Ada.Iterator_Interfaces;
 
 generic
    type Element_Type is private;
@@ -62,7 +62,7 @@
    No_Element : constant Cursor;
    function Has_Element (Position : Cursor) return Boolean;
 
-   package Ordered_Set_Iterator_Interfaces is new
+   package Set_Iterator_Interfaces is new
      Ada.Iterator_Interfaces (Cursor, Has_Element);
 
    type Constant_Reference_Type
@@ -212,12 +212,12 @@
 
    function Iterate
      (Container : Set)
-      return Ordered_Set_Iterator_Interfaces.Reversible_Iterator'class;
+      return Set_Iterator_Interfaces.Reversible_Iterator'class;
 
    function Iterate
      (Container : Set;
       Start     : Cursor)
-      return Ordered_Set_Iterator_Interfaces.Reversible_Iterator'class;
+      return Set_Iterator_Interfaces.Reversible_Iterator'class;
 
    generic
       type Key_Type (<>) is private;
Index: a-cohase.adb
===================================================================
--- a-cohase.adb	(revision 181662)
+++ a-cohase.adb	(working copy)
@@ -41,6 +41,17 @@
 
 package body Ada.Containers.Hashed_Sets is
 
+   type Iterator is limited new
+     Set_Iterator_Interfaces.Forward_Iterator with record
+        Container : Set_Access;
+     end record;
+
+   overriding function First (Object : Iterator) return Cursor;
+
+   overriding function Next
+     (Object   : Iterator;
+      Position : Cursor) return Cursor;
+
    -----------------------
    -- Local Subprograms --
    -----------------------
@@ -601,6 +612,11 @@
       return Cursor'(Container'Unrestricted_Access, Node);
    end First;
 
+   function First (Object : Iterator) return Cursor is
+   begin
+      return Object.Container.First;
+   end First;
+
    ----------
    -- Free --
    ----------
@@ -920,6 +936,13 @@
       B := B - 1;
    end Iterate;
 
+   function Iterate
+     (Container : Set) return Set_Iterator_Interfaces.Forward_Iterator'Class
+   is
+   begin
+      return Iterator'(Container => Container'Unrestricted_Access);
+   end Iterate;
+
    ------------
    -- Length --
    ------------
@@ -973,6 +996,23 @@
       Position := Next (Position);
    end Next;
 
+   function Next
+     (Object   : Iterator;
+      Position : Cursor) return Cursor
+   is
+   begin
+      if Position.Container = null then
+         return No_Element;
+      end if;
+
+      if Position.Container /= Object.Container then
+         raise Program_Error with
+           "Position cursor of Next designates wrong set";
+      end if;
+
+      return Next (Position);
+   end Next;
+
    -------------
    -- Overlap --
    -------------
@@ -1695,7 +1735,7 @@
 
       begin
          if Node = null then
-            raise Constraint_Error with "key not in map";
+            raise Constraint_Error with "key not in map";  -- ??? "set"
          end if;
 
          return Node.Element;
Index: a-cohase.ads
===================================================================
--- a-cohase.ads	(revision 181662)
+++ a-cohase.ads	(working copy)
@@ -34,6 +34,7 @@
 private with Ada.Containers.Hash_Tables;
 private with Ada.Streams;
 private with Ada.Finalization;
+with Ada.Iterator_Interfaces;
 
 generic
    type Element_Type is private;
@@ -49,7 +50,11 @@
    pragma Preelaborate;
    pragma Remote_Types;
 
-   type Set is tagged private;
+   type Set is tagged private
+   with
+      Default_Iterator  => Iterate,
+      Iterator_Element  => Element_Type;
+
    pragma Preelaborable_Initialization (Set);
 
    type Cursor is private;
@@ -63,6 +68,12 @@
    --  Cursor objects declared without an initialization expression are
    --  initialized to the value No_Element.
 
+   function Has_Element (Position : Cursor) return Boolean;
+   --  Equivalent to Position /= No_Element
+
+   package Set_Iterator_Interfaces is new
+     Ada.Iterator_Interfaces (Cursor, Has_Element);
+
    function "=" (Left, Right : Set) return Boolean;
    --  For each element in Left, set equality attempts to find the equal
    --  element in Right; if a search fails, then set equality immediately
@@ -303,9 +314,6 @@
    function Contains (Container : Set; Item : Element_Type) return Boolean;
    --  Equivalent to Find (Container, Item) /= No_Element
 
-   function Has_Element (Position : Cursor) return Boolean;
-   --  Equivalent to Position /= No_Element
-
    function Equivalent_Elements (Left, Right : Cursor) return Boolean;
    --  Returns the result of calling Equivalent_Elements with the elements of
    --  the nodes designated by cursors Left and Right.
@@ -327,6 +335,9 @@
       Process   : not null access procedure (Position : Cursor));
    --  Calls Process for each node in the set
 
+   function Iterate
+     (Container : Set) return Set_Iterator_Interfaces.Forward_Iterator'Class;
+
    generic
       type Key_Type (<>) is private;
 
Index: a-cbhase.adb
===================================================================
--- a-cbhase.adb	(revision 181662)
+++ a-cbhase.adb	(working copy)
@@ -41,7 +41,6 @@
 
    type Iterator is new Set_Iterator_Interfaces.Forward_Iterator with record
       Container : Set_Access;
-      Position  : Cursor;
    end record;
 
    overriding function First (Object : Iterator) return Cursor;
@@ -596,10 +595,8 @@
    end First;
 
    overriding function First (Object : Iterator) return Cursor is
-      Node : constant Count_Type := HT_Ops.First (Object.Container.all);
    begin
-      return (if Node = 0 then No_Element
-              else Cursor'(Object.Container, Node));
+      return Object.Container.First;
    end First;
 
    -----------------
@@ -911,7 +908,7 @@
    function Iterate (Container : Set)
      return Set_Iterator_Interfaces.Forward_Iterator'Class is
    begin
-      return Iterator'(Container'Unrestricted_Access, First (Container));
+      return Iterator'(Container => Container'Unrestricted_Access);
    end Iterate;
 
    ------------
@@ -982,12 +979,16 @@
       Position : Cursor) return Cursor
    is
    begin
+      if Position.Container = null then
+         return No_Element;
+      end if;
+
       if Position.Container /= Object.Container then
          raise Program_Error with
-           "Position cursor designates wrong set";
+           "Position cursor of Next designates wrong set";
       end if;
 
-      return (if Position.Node = 0 then No_Element else Next (Position));
+      return Next (Position);
    end Next;
 
    -------------
@@ -1599,7 +1600,7 @@
 
       begin
          if Node = 0 then
-            raise Constraint_Error with "key not in map";
+            raise Constraint_Error with "key not in map";  -- ??? "set"
          end if;
 
          return Container.Nodes (Node).Element;


More information about the Gcc-patches mailing list