CVS difference for ai05s/ai05-0139-2.txt

Differences between 1.3 and version 1.4
Log of other versions for file ai05s/ai05-0139-2.txt

--- ai05s/ai05-0139-2.txt	2010/02/16 03:08:55	1.3
+++ ai05s/ai05-0139-2.txt	2010/02/16 03:18:00	1.4
@@ -1,4 +1,4 @@
-!standard 5.5                                       10-02-10  AI05-0139-2/03
+!standard 5.5                                       10-02-11  AI05-0139-2/04
 !class Amendment 09-02-13
 !status work item 09-02-13
 !status received 09-01-19
@@ -21,14 +21,14 @@
 A better mechanism is required.
 
 In addition, using the notion of "accessors" or "references" as defined in AI05-0142
-is syntactically awkward.  Finally, it is often clearer to iterate over the elements
+is syntactically awkward. Finally, it is often clearer to iterate over the elements
 of a container (or array) directly, rather than iterating over a cursor (or index)
 into the container (or array).
 
 Using accessors for user-defined dereference (rather than simple access values
 as proposed in AI05-141) has the potential to provide a safer mechanism that
 might be used for persistence, relocating garbage collection, detection of
-dangling references, etc.  However, using accessors would be syntactically
+dangling references, etc. However, using accessors would be syntactically
 painful compared to a simple ".all."
 
 In all these cases, a modest amount of "syntactic sugar" might make the use
@@ -36,24 +36,25 @@
 
 !proposal
 
-Define a "magic" interface, a new operator, and a "magic" generic unit
+Define a "magic" interface, a new operator, a "magic" generic unit,
+and some additional "aspects" for the aspect_specification, all of
 which are linked to some appropriate syntactic sugar for accessors,
 containers, and iterators:
 
 1) SUPPORT FOR ACCESSORS/REFERENCES
 
-We propose to add a "magic" interface called Reference.  Any type
+We propose to add a "magic" interface called Reference. Any type
 descended from Reference with exactly one access discriminant is
 considered a "reference" type, and provides implicit dereference in all
 contexts, with the "implicit dereference" of an object Ref of such a
 type being equivalent to "Ref.<discrim>.all," where "<discrim>" is the
-name of the access discriminant.  If the access discriminant is an
-access constant, then of course this dereference is a constant view.  If
+name of the access discriminant. If the access discriminant is an
+access constant, then of course this dereference is a constant view. If
 not, then it is a variable view, and can be used on the left-hand-side
-of an assignment, as the actual for an [in] out parameter, etc.  These
+of an assignment, as the actual for an [in] out parameter, etc. These
 reference types are particularly useful because they can be controlled
 types or have a controlled part, so that when finalized, a user-defined
-finalization action will be invoked.  This allows, for example, the
+finalization action will be invoked. This allows, for example, the
 "tampering" state of a container to be reset, a persistent object to be
 "unpinned," a reference count to be decremented, etc.
 
@@ -63,7 +64,7 @@
        type Reference is limited interface;
    end Ada.References;
 
-Here is an example of use.  We imagine type T and a type T_Table which
+Here is an example of use. We imagine type T and a type T_Table which
 is some kind of container with T elements in it, indexed by a string.
 
    with Ada.References;
@@ -131,7 +132,7 @@
 We now take this one step further by allowing the definition of a new
 operator, "()", which allows the elimination of the function name in
 uses like that above, simplifying the notation to simply
-"Tab("Banana")".  This works as follows:
+"Tab("Banana")". This works as follows:
 
     package Whatever is
        ... as above
@@ -163,9 +164,9 @@
 notation, meaning that it is either a primitive operation or a
 class-wide operation of some tagged type (via its first parameter), and
 if class-wide, is declared immediately within a package where some
-tagged type covered by the class-wide type is immediately declared.  It
-must have at least two parameters.  There seems no particular reason it
-couldn't have more than two parameters.  There are no predefined "()"
+tagged type covered by the class-wide type is immediately declared. It
+must have at least two parameters. There seems no particular reason it
+couldn't have more than two parameters. There are no predefined "()"
 operators, though one could imagine that all array types have such
 operators, if it helps in understanding the model.
 
@@ -173,7 +174,7 @@
 operators, one that requires the controlling operand to be a variable,
 and one that allows it to be a constant, and overload resolution will
 resolve to the one that requires a variable if the actual is a variable,
-and otherwise it will resolve to the one that allows a constant.  This
+and otherwise it will resolve to the one that allows a constant. This
 rule is important so that the same notation, such as "Container(Key)",
 can be used when Container is a constant as when it is a variable, and
 the variableness of the result can be determined by the variableness of
@@ -198,19 +199,20 @@
 
 Given these two capabilities, we are now ready to define a more general
 "iterator" syntax, that is, a variant of the "for" loop statement which
-works naturally on containers.  In fact we propose two distinct iterator
+works naturally on containers. In fact we propose two distinct iterator
 syntaxes:
 
-One intended for iterating over the set of cursors or indices that
-select elements of a container.  This is most analogous to what is
-already available for arrays by writing "for I in Arr'Range loop":
+a) The first syntax is intended for iterating over the set of cursors or
+indices that select elements of a container. This is most analogous to
+what is already available for arrays by writing "for I in Arr'Range
+loop":
 
    for Cursor in Iterate(Container) loop
        Container(Cursor) := Container(Cursor) + 1;
    end loop;
 
 What the above presumes is that the function Iterate returns an object
-of a type derived from a "magic" iterator type (see below).  The
+of a type derived from a "magic" iterator type (see below). The
 iterator type provides a First and Next operation which return a Cursor
 type, and a No_Element cursor value to indicate end of iteration. The above
 expands into:
@@ -221,29 +223,15 @@
    begin
       while Cursor /= No_Element loop
          Container(Cursor) := Container(Cursor) + 1;
+           -- This presumes an appropriate "()" operator
+           -- is defined.
 
          Cursor := Next(_iter, Cursor);
       end loop;
    end;
 
-The second syntax is intended for iterating directly over the elements
-of a container or an array:
-
-   for Element of Container loop
-       Element := Element + 1;
-   end loop;
-
-   for Element of Arr loop
-       Element := Element + 1;
-   end loop;
-
-This second syntax is more convenient, but less flexible, in that there
-is no way to specify the particular iterator to use, so it requires
-that there be a "default" iterator.
-
 The generic package Iterator_Interfaces defines a pair of "magic" interfaces
-and a nested (magic) generic "signature" package used to "enable" this
-iterator syntax for a given cursor and container type.
+used to "enable" the above iterator syntax for a given cursor type:
 
    generic
        type Cursor is private;
@@ -258,15 +246,13 @@
        function Last (Object : Reversible_Iterator) return Cursor;
        function Previous (Object : Reversible_Iterator; Position : Cursor) return Cursor;
 
-       generic
-           type Container_Type is tagged;  -- formal incomplete type??
-           type Element_Type is tagged;  -- formal incomplete type??
-           type Iterator_Type is tagged; -- formal incomplete type??
-           with function Default_Iterate(C : Container) return Default_Iterator_Type is <>;
-       package Default_Iteration is end;
-
    end Ada.Iterator_Interfaces;
 
+By instantiating this package with a given cursor type, and then
+deriving one or more type(s) from the Basic_Iterator and/or
+Reversible_Iterator interfaces, this first iterator syntax is enabled for
+the given iterator type(s). See above for an example.
+
 Note that the routines defined in this magic generic generally match
 those used in iteration for the Ada.Containers packages, and their
 meaning is the same. The only difference is that we've added an iterator
@@ -276,6 +262,8 @@
 The interface Basic_Iterator defines a user-defined iterator for the
 forward direction; the interface Reversible_Iterator defines a
 user-defined iterator for both the forward and reverse direction.
+Descendants of Reversible_Iterator can be used in loops with the
+REVERSE reserved word.
 
 The function First is expected to deliver the first cursor value for the
 iterator iterating in the forward direction, or return No_Element if no
@@ -291,36 +279,36 @@
 direction given the previous cursor value returned from a call to Last
 or Previous, or return No_Element if no additional cursor values are
 available.
-
-The signature generic is used to establish the default iterator for a
-given container type.  There must be exactly one instantiation of this
-Default_Iteration package in the visible part where the Container type
-is declared, to "enable" the iterator syntax.
-
-NOTE: This Default_Iteration generic poses a challenge for the rule
-disallowing instantiating a generic with a private type.  We could fall
-back on "integrated" packages, though then it is a bit unclear how this
-signature generic would be connected to the Container type.
-Alternatively we could consider allowing formal incomplete types, which
-don't freeze their corresponding actual type, but remain incomplete in
-both the spec and body of the generic.  This might be an alternative to
-the whole integrated package "mishigas."
 
-If an instantiation of Default_Iteration exists, then the loop of the form:
+b) The second syntax is intended for iterating directly over the elements
+of a container or an array:
 
    for Element of Container loop
        Element := Element + 1;
    end loop;
 
-expands into:
+or
+
+   for Element of Arr loop
+       Element := Element + 1;
+   end loop;
 
+This second syntax is more convenient, but less flexible, in that there
+is no way to specify the particular iterator to use, so it requires
+that there be a "default" iterator.
+
+Two new "aspects" for an aspect_specification on a container type are
+used to enable the second syntax (Default_Iterator and
+Iterator_Element). If the aspects Default_Iterator and Iterator_Element
+are specified, then the above loop over Container expands into:
+
    declare
-      _Iter : Iterator_Type := Default_Iterate(Container);
+      _Iter : Iterator_Type := Container_Type'Default_Iterator(Container);
       _Cursor : Cursor := First(_Iter);
    begin
       while _Cursor /= No_Element loop
         declare
-          Element : Element_Type renames Container(_Cursor);
+          Element : Container_Type'Iterator_Element renames Container(_Cursor);
             -- This requires an appropriate "()" operator be defined
         begin
           Element := Element + 1;
@@ -331,22 +319,27 @@
    end;
 
 
-Here is how these generics might be used:
+Here is how this generic and the iterator-related aspects might be used:
 
     type Cursor_Type is ...
     package Iterators is new Ada.Iterator_Interfaces(Cursor_Type, No_Element);
     type Container is ...
+       with
+         Default_Iterator => Iterate,
+         Iterator_Element => Element;
+
+    type Element_Ref(E : access Element) is limited
+      new Ada.References.Reference with private;
+    type Element_CRef(E : access constant Element) is limited
+      new Ada.References.Reference with private;
 
     type Iterator_Type is new Iterators.Reversible_Iterator with ...
-    function Iterate(C : Container) return Iterator_Type;
+    function Iterate(Con : Container) return Iterator_Type;
+
+    function "()"(Con : access Container; Cur : Cursor_Type) return Element_Ref;
+    function "()"(Con : access constant Container; Cur : Cursor_Type) return Element_CRef;
     ...
 
-    package Default_Iteration is
-      new Iterators.Default_Iteration(
-        Container,
-        Element_Type => Element,
-        Iterator_Type => Iterator_Type,
-        Default_Iterate => Iterate);
 
 These two new kinds of "for" loops would require two new kinds of
 "for" loop parameter specifications:
@@ -360,16 +353,15 @@
 be used to index into the container.
 
 The second requires an expression returning an array, or an object
-of a type which has an instantiation of the Default_Iteration
-generic.  The subtype_indication is optional, since the container
-type determines the Default_Iteration instance, and it in turn
-determines the Element type.  Similarly for an array, the Element
-type is simply the array component type.  One purpose of the
-subtype_indication might be to tighten the requirements on the
+of a type which has aspects Default_Iterator and Iterator_Element
+specified. The subtype_indication is optional, since the Iterator_Element
+aspect of the container type determines the Element type. Similarly for an
+array, the Element type is simply the array component type. One purpose of
+the subtype_indication might be to tighten the requirements on the
 elements of the container/array, acting essentially as an assertion
 about the values stored in the container/array at the time of
-the iteration.  Another purpose is simply to help the reader,
-and provide an extra check that the element type of the
+the iteration. Another purpose is simply to help the reader,
+and provide an extra check that the Iterator_Element type of the
 container is as expected.
 
 Here are some additional examples of iterators.
@@ -401,7 +393,7 @@
    ...
    for X of Vec loop
           -- X renames Vec(<cursor>) where <cursor> in Default_Iterator(Vec).
-          --    and Vec(<cursor>) is equiv to Element_[C]Ref(Vec, <cursor>).Data.all.
+          --    and Vec(<cursor>) is equiv to "()"(Vec, <cursor>).Discrim.all.
           -- X is a variable if Vec is a variable.
 
        X := X + 1;

Questions? Ask the ACAA Technical Agent