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

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

--- ai05s/ai05-0139-2.txt	2011/02/08 08:21:06	1.10
+++ ai05s/ai05-0139-2.txt	2011/02/15 04:57:58	1.11
@@ -1,9 +1,10 @@
-!standard 4.1(2/2)                                    10-10-25  AI05-0139-2/07
+!standard 4.1(2/2)                                    11-02-14  AI05-0139-2/08
 !standard 4.1.5(0)
 !standard 4.1.6(0)
 !standard 5.5(3)
 !standard 5.5(9)
 !standard 5.5.1(0)
+!standard 13.3.2(9)
 !class Amendment 09-02-13
 !status work item 09-02-13
 !status received 09-01-19
@@ -41,9 +42,16 @@
 
 !proposal
 
-Define 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:
+Provide a generic unit containing two iterator interfaces, and
+some additional "aspects" related to implicit dereference and indexing,
+along with some appropriate syntactic sugar for accessors, containers,
+and iterators.
+
+We also propose providing iterators for arrays, including
+multi-dimensional arrays. As part of that, we use the notion
+of canonical order for multidimensional arrays established for
+Stream attributes, but modify it to take into account convention
+Fortran, where the first, rather than the last, dimension varies fastest.
 
 1) SUPPORT FOR ACCESSORS/REFERENCES
 
@@ -433,9 +441,9 @@
      Implicit_Dereference  This aspect is specified by a name that denotes
        an access discriminant declared for the type T.
 
-  A type with a specified Implicit_Dereference aspect is a /reference
-  type/. A /reference object/ is an object of a reference type. The
-  discriminant named by the Implicit_Dereference aspect is the
+  A (view of a) type with a specified Implicit_Dereference aspect is a
+  /reference type/. A /reference object/ is an object of a reference type.
+  The discriminant named by the Implicit_Dereference aspect is the
   /reference discriminant/ of the reference type or reference object.
   [Redundant: A generalized_reference is a name that identifies a
   reference object, and denotes the object or subprogram designated by
@@ -459,11 +467,11 @@
   by descendants of type T if not overridden. If a descendant type
   constrains the value of the reference discriminant of T by a new
   discriminant, that new discriminant is the reference discriminant of
-  the descendant. If the descendant type constrains the value of the
+  the descendant. [Redundant: If the descendant type constrains the value of the
   reference discriminant of T by an expression other than the name of a
   new discriminant, a generalized_reference that identifies an object of
   the descendant type denotes the object or subprogram designated by the
-  value of this constraining expression.
+  value of this constraining expression.]
 
           Dynamic Semantics
 
@@ -479,8 +487,8 @@
            Example
 
   type Ref_Element(Data : access Element) is
-    new Ada.Finalization.Limited_Controlled with null record
-    with Implicit_Dereference => Data;
+    new Ada.Finalization.Limited_Controlled with private
+      with Implicit_Dereference => Data;
         -- This Ref_Element type is a "reference" type.
         -- "Data" is its reference discriminant.
 
@@ -521,8 +529,8 @@
   type T'Class). The aspects may not be overridden, but the functions they
   denote may be.
 
-  An /indexable type/ is a user-defined tagged type with at least one of
-  the aspects Constant_Indexing or Variable_Indexing specified. An
+  An /indexable type/ is (a view of) a user-defined tagged type with at least
+  one of the aspects Constant_Indexing or Variable_Indexing specified. An
   /indexable object/ is an object of an indexable type. [Redundant: A
   generalized_indexing is a name that denotes the result of calling a
   function named by a Contant_Indexing or Variable_Indexing aspect.]
@@ -594,12 +602,14 @@
    package Ada.Iterator_Interfaces is
 
        type Forward_Iterator is limited interface;
-       function First (Object : Forward_Iterator) return Cursor;
-       function Next (Object : Forward_Iterator; Position : Cursor) return Cursor;
+       function First (Object : Forward_Iterator) return Cursor is abstract;
+       function Next (Object : Forward_Iterator; Position : Cursor) return Cursor
+         is abstract;
 
        type Reversible_Iterator is limited interface and Forward_Iterator;
-       function Last (Object : Reversible_Iterator) return Cursor;
-       function Previous (Object : Reversible_Iterator; Position : Cursor) return Cursor;
+       function Last (Object : Reversible_Iterator) return Cursor is abstract;
+       function Previous (Object : Reversible_Iterator; Position : Cursor) return Cursor
+         is abstract;
 
    end Ada.Iterator_Interfaces;
 
@@ -759,7 +769,9 @@
    of the loop_statement is complete. Otherwise, the
    sequence_of_statements is executed with the loop parameter denoting
    each component of the array for the loop, using a /canonical/ order
-   of components, which is last dimension varying fastest. For a
+   of components, which is last dimension varying fastest (unless the
+   array has convention Fortran, in which case it is first dimension
+   varying fastest). For a
    forward array component iterator, the iteration starts with the
    component whose index values are each the first in their index range,
    and continues in the canonical order. For a reverse array component
@@ -794,238 +806,23 @@
    constant (see above), then the indexing uses the default constant
    indexing function for the type of the iteratable object for the loop;
    otherwise it uses the default variable indexing function.
-
-
-!discussion [NOT FULLY UPDATED -- SEE PROPOSAL FOR SOME NEWER DISCUSSION]
-
-This is based on the earlier proposal and discussion recorded in AC-0112.TXT.
-This proposal was modified to address the comments made on that one, and has
-been simplified considerably.
-
-Note that the iterator interface can be directly applied to a container type
-(allowing it to be directly iterated) or it can be part of a separate function
-(which would allow adding additional parameters to the iterator and/or adding
-additional storage for the iterators). By using interfaces, we give maximum
-flexibility to the programmer that is using these iterators.
-
-If the creator of the iterator needs extra storage to accomplish the iteration,
-they can include it in the type of the iterator.
-
-If the creator of the iterator needs to get control when the loop is exited
-prematurely, they can define a controlled iterator type. In that case,
-(presuming that the iterator_expression was a function call) when the loop is
-exited, the Finalization routine for the iterator object will be called.
-
-We provide a form for reverse iterators. Reverse iteration makes sense for many
-kinds of containers (vectors and lists, for instance). Given that the syntax
-already exists and every Ada programmer is familiar with it, not providing it
-would quickly become one of the most common frustrations of programming in Ada.
-That seems silly.
-
-We could have simplified the proposal by requiring that all iterators support
-Last and Previous, but iterators where reverse iteration does not make sense
-would have to raise an exception when Last is called. The proposed features, in
-contrast, make a compile-time determination as to whether reverse is allowed.
-That will detect errors earlier; it generally is better to detect errors at
-compile-time if possible.
-
-
-It might appear that this proposal would require some solution to the
-instantiation for private types problem, but as the examples below show, this
-is not true.
-
-
-Note that the actual iterator type can be either limited or non-limited. The
-value of a limited iterator object is that an iterator implementation can
-assume (presuming that it only exports functions and not types) that the
-iterator object is created and destroyed with the loop. This allows safe
-cleanup operations when the loop is exited (as in the examples below).
-If that capability is not needed, an iterator implementation allow reuse of
-iterator objects (especially if no temporary storage is needed).
-
-Note that if temporary storage or loop exit actions are needed, the iterator
-object *must be* separate from the container object that it is iterating
-on. Otherwise nested loops on the same container would not work.
-   for I in My_Container.Iterator loop
-      for J in My_Container.Iterator loop
-          ...
-      end loop;
-   end loop;
-The I and J loops need separate temporary storage, which must be provided by
-the iterator object (the loop can only provide the loop parameter cursor object).
-
-
-Issues:
-
-The use of a controlled type for an iterator in this proposal would require
-bounded containers to be preelaborable units, rather than pure units. We add a
-prohibition on the actual container from being controlled, so that finalization
-averse users could still use the bounded containers (but obviously not the
-iterators). This seems OK, given that the current accessor proposal (AI05-0142-4)
-has similar requirements.
-
-It would be nice for an iterator implementation to be able to prevent the
-creation of iterator objects not associated with a loop. For instance, given
-the implementation of the example below:
-    My_Iter : Some_Instance.Forward_Iterator'Class := My_List.Iterator;
-would have the effect setting tampering on My_List and keeping it set until
-the object is destroyed (potentially a long time in the future). But this
-is not the natural thing to do -- it requires a lot more typing than the intended
-usage -- and no major definitional problems are encountered in this case. We
-would need a lot more mechanism to prevent the creation of objects outside of
-the loop context, so we do not try to prevent this misuse.
-
-
-Alternatives considered:
-
-One option considered was including the name of the cursor type somewhere in the
-syntax. Something like:
-
-   defining_identifier : subtype_mark in [reverse] iterator_expression
-
-That was not done mainly because differs from the existing syntax for no clear
-benefit. It would make the type of the identifier clearer, but it also would
-mean that switching from a discrete iterator to a container one would require
-some syntax changes that don't really fit into the model. (One solution to that
-problem would be to optionally add the type name to the discrete for loop as
-well, but that seems like a bunch of additional changes for little value.)
-
-It should be noted that with this formulation, the existing discrete iterators
-could be considered just a predefined instantiation of this magic generic for
-discrete types. The analogy breaks down a bit for ranges (they don't look like a
-function call), but it isn't hard to imagine such a unification.
-
 
-!examples  [NOT FULLY UPDATED -- SEE PROPOSAL FOR ADDITIONAL EXAMPLES]
+Modify second sentence of 13.13.2(9/2):
 
-This feature could easily be used in the existing Ada.Containers packages. We
-give a suggested implementation for Ada.Containers.Doubly_Linked_Lists; the
-other containers could be similar.
+  ... For composite types, the Write or Read attribute for each
+  component is called in canonical order, which is last dimension
+  varying fastest for an array {(unless the convention of the array is
+  Fortran, in which case it is first dimension varying fastest)}, and
+  positional aggregate order for a record.
 
-The start of the visible part of Ada.Containers.Doubly_Linked_Lists would be
-modified as follows:
+!discussion
 
-   with Ada.Iterator_Interfaces;
-   generic
-      type Element_Type is private;
-      with function "=" (Left, Right : Element_Type) return Boolean is <>;
-   package Ada.Containers.Doubly_Linked_Lists is
-      pragma Preelaborate(Doubly_Linked_Lists);
-      pragma Remote_Types(Doubly_Linked_Lists);
-
-      package Cursors is
-         type Cursor is private;
-         pragma Preelaborable_Initialization(Cursor);
-
-         No_Element : constant Cursor;
-      private
-         ... -- not specified by the language
-      end Cursors;
-      subtype Cursor is Cursors.Cursor;
-      No_Element : Cursor renames Cursors.No_Element;
-
-      package Iterators is new
-          Ada.Iterator_Interfaces (Cursors, No_Element);
-
-      type List is new Iterators with private;
-      pragma Preelaborable_Initialization(List);
-
-      Empty_List : constant List;
-
-      ...
-
-Note that the changes here are the addition of the nested package Cursors,
-the addition of the instantiation, and the subtype and renames to eliminate the
-effect of the nested package. The majority of the package is unchanged.
-
-After the existing procedure Reverse_Iterate, we would add a new function:
-
-   function Iterate (Container : in List) return List_Iterators.Reversible_Iterator'Class;
-
-This would be described as
-
-      Iterate returns an object that can be used in a loop_statement to loop
-      with a loop parameter designating each node in Container, starting with the
-      first node and moving the cursor as per the Next function if the reserved word
-      *reverse* is not used in the user_loop_parameter_statement, and starting
-      with the last node and moving the cursor as per the Previous function otherwise.
-      Program_Error is propagated if any operation (in particular, the sequence_of_statements
-      of the loop_statement whose iterator_expression denotes this object) tampers with
-      the cursors of Container while the returned object exists.
-
-This could be implemented by defining a controlled type in the private part of
-Ada.Containers.Doubly_Linked_Lists:
-
-   type Our_List_Iterator is new Ada.Controlled.Limited_Controlled and
-                                   List_Iterators.Reversible_Iterator with record
-         Our_List : access List;
-      end record;
-   function First (Object : Our_List_Iterator) return Cursor;
-   function Next (Object : Our_List_Iterator; Position : Cursor) return Cursor;
-   function Last (Object : Our_List_Iterator) return Cursor;
-   function Previous (Object : Our_List_Iterator; Position : Cursor) return Cursor;
-   procedure Finalize (Object : in out Our_List_Iterator);
-
-The implementation of these operations would be something like:
-   function Iterate (Container : in List) return List_Iterators.Reversible_Iterator'Class is
-   begin
-      return Iter:Our_List_Iterator do
-         Iter.Our_List := Container'Unchecked_Access;
-             -- This is safe unless someone does an Unchecked_Deallocation on
-             -- the container in the loop; we don't try to protect against that
-             -- in other cases for Ada.Containers, so we won't here, either.
-         -- Set a tampering context for Iter.Our_List.all.
-      end return;
-   end Iterate;
-
-   function First (Object : Our_List_Iterator) return Cursor is
-   begin
-       return Object.Our_List.First;
-   end First;
-
-   function Next (Object : Our_List_Iterator; Position : Cursor) return Cursor is
-   begin
-       return Next (Position);
-   end Next;
-
-   -- Similar implementations for Last and Previous.
-
-   procedure Finalize (Object : in out Our_List_Iterator) is
-   begin
-       -- Clear the tampering context for Object.Our_List.
-   end Finalize;
-
-Note that we didn't add these interfaces to the actual container types. That was
-because we wanted these iterators to be a tampering context (thus ensuring that
-they terminate and do not lead to erroneous execution). Users would be very
-surprised if a "safe" construct like a for loop caused erroneous execution
-(which will happen if the node designated by the loop parameter is deleted).
-
-The function Iterate would normally be used directly in a loop:
-
-   for C in My_List.Iterate loop
-      ... Element (C) ...
-   end loop;
-
-
-We could also define a partial list iterator:
-
-   function Partial_Iterate (Container : in List;
-                             Start : in Cursor;
-                             Finish : in Cursor := No_Element)
-       return List_Iterators.Reversible_Iterator'Class;
-
-where Start and Finish (if not No_Element) would have to be cursors for
-Container. In this case, the iteration would run from Start to Finish (or
-No_Element, if Finish is not on the list after/before Start) forward or in
-reverse. (This would also be a tampering context as above.)
-
-We would use Partial_Iterator directly in a loop:
+(See proposal.)
 
-   for C in Partial_Iterate (My_List, Start, Finish) loop
-      ... Element (C) ...
-   end loop;
+!examples
 
+See AI05-0212-1 for examples of these features being used in the predefined
+containers packages.
 
 !ACATS test
 

Questions? Ask the ACAA Technical Agent