CVS difference for ais/ai-10260.txt

Differences between 1.1 and version 1.2
Log of other versions for file ais/ai-10260.txt

--- ais/ai-10260.txt	2004/09/10 00:43:34	1.1
+++ ais/ai-10260.txt	2004/11/01 22:16:36	1.2
@@ -1,5 +1,16 @@
-!standard  3.09  (18)                               04-09-08  AI95-00260-02/01
+!standard  3.09  (06)                               04-10-27  AI95-00260-02/02
+!standard  3.09  (07)
+!standard  3.09  (12)
+!standard  3.09  (18)
 !standard  3.09  (25)
+!standard  3.09.02 (02)
+!standard  3.09.03 (03)
+!standard  3.09.03 (11)
+!standard 12.06  (03)
+!standard 12.06  (04)
+!standard 12.06  (08)
+!standard 12.06  (10)
+!standard 12.06  (18)
 !standard 13.13.2  (31)
 !class amendment 04-09-08
 !status work item 04-09-08
@@ -10,10 +21,16 @@
 
 !summary
 
-A generic unit is defined to allow dispatching to a routine with a controlling
-result. This unit makes it possible to write functions with similar semantics
-to T'Class'Input, including a complete replacement for the function.
+A new kind of generic formal subprogram, the abstract formal subprogram, is
+defined. It allows the importation of dispatching operations into a generic
+unit.
+
+A pair of generic units are defined to allow dispatching to a routine with a
+controlling result. This unit makes it possible to write functions with similar
+semantics to T'Class'Input, including a complete replacement for the function.
 
+A operation is defined in Ada.Tags to get the tag of a parent type.
+
 !problem
 
 S'Class'Output writes the tag of an item with String'Output. This routine
@@ -32,57 +49,197 @@
 
 !proposal
 
-(See Wording.)
+(See wording.)
 
 !wording
 
+Add after 3.9(6):
+
+   No_Tag : constant Tag;
+
+Add after 3.9(7):
+
+   function Parent_Tag (T : Tag) return Tag;
+
+Add after 3.9(12):
+
+The function Parent_Tag returns the tag of the parent type of the type whose
+tag is T. If the type does not have a parent type (that is, it was not
+declared by a derived_type_declaration), then No_Tag is returned.
+
+AARM Note: The parent type is always the parent of the full type; a private
+extension appears to define a parent type, but it does not (only the various
+forms of derivation do that). As this is a run-time operation, ignoring
+privateness is OK.
+
 Add after 3.9(18):
 
 Static Semantics
 
-The following language-defined generic function exists:
+The following language-defined generic functions exist:
 
     generic
          type T (<>) is abstract tagged private;
+         type Parameters (<>) is limited private;
+         with function Constructor (Params : access Parameters)
+              return T is abstract;
+    function Ada.Tags.Generic_Dispatching_Constructor
+      (The_Tag : Tag;
+       Params : access Parameters) return T'Class;
+    pragma Pure (Generic_Dispatching_Constructor);
+    pragma Convention (Intrinsic, Generic_Dispatching_Constructor);
+
+    generic
+         type T (<>) is abstract tagged limited private;
          type Parameters (<>) is limited private;
-         with function Constructor (Params : access Parameters) return T;
-    function Generic_Dispatching_Constructor (Tag : Ada.Tags.Tag;
-                                              Params : access Parameters)
-                                                 return T'Class;
-
-    Raises Tag_Error if Tag does not represent a concrete descendant of T.
-
-    AARM Note: This checks both that Tag is in T'Class, and that it is not
-    abstract. [Note: These rules come from AI-279.]
-
-    Otherwise, dispatches to the version of Constructor for the type identified
-    by the tag Tag, passing Params, and returns the result.
-
-Legality Rules
-
-The actual parameter for function Constructor in an instantiation of
-Generic_Dispatching_Constructor shall be a primitive operation of type T.
-Notwithstanding what it says elsewhere in this International Standard,
-the actual subprogram for function Constructor in an instantiation of
-Generic_Dispatching_Constructor may be abstract.
+         with function Constructor (Params : access Parameters)
+              return T is abstract;
+    function Ada.Tags.Generic_Limited_Dispatching_Constructor
+      (The_Tag : Tag;
+       Params : access Parameters) return T'Class;
+    pragma Pure (Generic_Limited_Dispatching_Constructor);
+    pragma Convention (Intrinsic, Generic_Limited_Dispatching_Constructor);
+
+Generic_Dispatching_Constructor and Generic_Limited_Dispatching_Constructor
+provide a mechanism to create an object of an appropriate type from just a tag
+value. This capability is sometimes known as a *factory*. The function
+Constructor does the actual creation of the object, using the information
+provided in a value of type Parameters to control the initial state of the
+object.
+
+AARM Note: This specification is designed to make it easy to create dispatching
+constructors for streams; in particular, this can be used to construct
+overriddings for T'Class'Input.
 
+
 Add after 3.9(25):
 
+Tag_Error is raised by a call of Expanded_Name, External_Tag, or Parent_Tag if
+any tag passed is No_Tag.
+
+[Editor's Note: If AI-344 is included in the Amendment, this rule should
+include Descendant_Tag and Is_Descendant_At_Same_Level.]
+
+An instance of Generic_Dispatching_Constructor or
+Generic_Limited_Dispatching_Constructor raises Tag_Error if The_Tag does not
+represent a concrete descendant of T.
+Otherwise, it dispatches to the version of Constructor for the type identified
+by the tag The_Tag, passing Params, and returns the result.
+
+AARM Note: The tag check checks both that The_Tag is in T'Class, and that it
+is not abstract. [Note: Those checks come from AI-279.]
+
 Erroneous Execution
 
 If the internal tag provided to an instance of Generic_Dispatching_Constructor
-identifies a specific type whose tag has not been elaborated, or does not exist
-in the partition at the time of the call, execution is erroneous.
+or Generic_Limited_Dispatching_Constructor identifies a specific type whose tag
+has not been elaborated, or does not exist in the partition at the time of the
+call, execution is erroneous.
 
 AARM Note: For a library-level type, this shouldn't be possible presuming that
 the tag value came from the current execution of the partition. T'Tag freezes
 the type (and thus elaborates the tag), and Internal_Tag and Descendant_Tag
-cannot return the tag of a library-level type that has not elaborated. Finally,
-library-level types never cease to exist. Thus, if the tag comes from a
-library-level type, there cannot be erroneous execution (the use of
-escendant_Tag rather than Internal_Tag can help insure this). [Note: This rule
+cannot return the tag of a library-level type that has not been elaborated.
+Finally, library-level types never cease to exist. Thus, if the tag comes from
+a library-level type, there cannot be erroneous execution (the use of
+Descendant_Tag rather than Internal_Tag can help insure this). [Note: This rule
 also comes from AI-279.]
 
+Change the first sentence of 3.9.2(2):
+
+A *call on a dispatching operation* is a call whose name or prefix denotes the
+declaration of a primitive operation of a tagged type {or an abstract formal
+subprogram}, that is, a dispatching operation.
+
+Add after 3.9.3(3):
+
+The subprogram declared by a formal_abstract_subprogram_declaration is an
+abstract subprogram.
+
+[Editor's note: The second sentence of 3.9.3(3) does not apply to abstract
+formal subprograms; they have their own rules for controlling operands given in
+12.6. Thus I did not add this rule to paragraph 3.9.3(3), but rather created a
+new paragraph. Luckily the original wording does not say that it applies to all
+abstract subprograms, so no change is needed to it.]
+
+Replace the first sentence of 3.9.3(11) by:
+
+A generic actual subprogram shall not be abstract unless the generic formal
+subprogram is a formal_abstract_subprogram_declaration.
+
+
+Replace 12.6(2) by:
+
+formal_subprogram_declaration ::= formal_abstract_subprogram_declaration |
+	formal_concrete_subprogram_declaration
+formal_concrete_subprogram_declaration ::=
+        with subprogram_specification [is subprogram_default];
+formal_abstract_subprogram_declaration ::=
+        with subprogram_specification is abstract;
+
+Add after 12.6(8):
+
+If a formal parameter of an formal_abstract_subprogram_declaration has a
+specific tagged type T or is an anonymous access designating a specific tagged
+type T, T is called a dispatching type of the
+formal_abstract_subprogram_declaration. Similarly, if the result of an
+formal_abstract_subprogram_declaration for a function has a specific tagged
+type T or is an anonymous access designating a specific tagged type T, T is
+called a dispatching type of the formal_abstract_subprogram_declaration. A
+formal_abstract_subprogram_declaration shall have exactly one dispatching type.
+
+AARM Note:
+The specific tagged type could be any of a formal tagged private type,
+a formal derived type, or a normal tagged type. While the last case doesn't
+seem to be very useful, there isn't any good reason for disallowing it.
+This rule insures that the operation is a dispatching operation of some
+type, and that we unambiguously know what that type is.
+End AARM Note.
+
+The actual subprogram for a formal_abstract_subprogram_declaration shall be a
+primitive operation of the dispatching type of the
+formal_abstract_subprogram_declaration.
+
+AARM Note: This means that it is a dispatching operation of the dispatching
+type. Also note that this prevents the dispatching type from being class-wide,
+as only specific types have primitive operations. This could happen in a case
+like:
+
+   generic
+     type T(<>) is tagged private;
+     with procedure Foo (Obj : in T) is abstract;
+   package P ...
+
+   package New_P is new P (Something'Class, Some_Proc);
+
+The instantiation here is always illegal, because Some_Proc could never be
+a primitive operation of Something'Class (there are no such operations). That's
+good, because we want calls to Foo always to be dispatching calls.
+End AARM Note.
+
+Add after 12.6(10):
+
+The subprogram declared by a formal_abstract_subprogram_declaration with a
+dispatching type T is a dispatching operation of type T.
+
+AARM Note:
+This is necessary to trigger all of the dispatching operation
+rules. It otherwise would not be considered a dispatching operation, as
+formal subprograms are never primitive operations.
+
+Replace 12.6(18) by:
+
+18 The actual subprogram cannot be abstract unless the formal
+subprogram is a formal_abstract_subprogram_declaration (see 3.9.3).
+
+Add a new note after 12.6(18):
+
+19 The subprogram declared by a formal_abstract_subprogram_declaration
+is an abstract subprogram. All calls on a subprogram declared by a
+formal_abstract_subprogram_declaration must be dispatching calls. See 3.9.3.
+[These things are defined in 3.9.3, but they are important to
+mention here.]
+
 Replace 13.13.2(31) by:
 
 First writes the external tag of Item to Stream (by calling
@@ -96,52 +253,35 @@
 
 A function like the instance of Generic_Dispatching_Constructor or
 T'Class'Input is often called a "factory" in OOP literature. Factories can be
-useful in scenar ios other than streaming. See the examples for two possible
+useful in scenarios other than streaming. See the examples for two possible
 uses.
 
 The only part of T'Class'Input that cannot be written in Ada is the dispatching
 call to T'Input. This is the part that we need to model with a built-in
 operation. It's not necessary to create an object of the type; the called
-function will do that. This avoids problems with discriminants which aren't
+function will do that. That avoids problems with discriminants which aren't
 known.
 
-The two legality rules are somewhat uncomfortable, because they differ from
-other generic instantiations. This is not too bad, as this generic cannot be
-written in anything close to Ada, and thus will require special handling as
-does Unchecked_Conversion.
-
-Both legality rules could be made more consistent by defining a new kind of
-generic formal subprogram that required a primitive dispatching routine.
-One possibility would be
-    with overridding of T <subprogram_spec> [is <default>];
-with the legality rules moved to appropriate places in 3.9.3(11) and 12.6.
-(That is, the actual could be abstract and would have to be primitive for
-type T; T would have to be a specific tagged type (including formal
-tagged types)). Such a formal would be useful in other cases than this generic;
-there currently is no way to define a dispatching generic formal. For instance,
-consider a generic that implemented a persistence add-in. If it could have
+Adding a new kind of generic formal for this problem is somewhat heavy.
+However, such a formal would be useful in other cases than this generic;
+Ada 95 has no way to define a dispatching generic formal. For instance,
+consider a generic that implemented a persistence add-in. If it had
 flattening/reconstruction formals that were dispatching, then a single
 instantiation could add persistence to an entire type hierarchy. (And this
 could be done without constraining the names of the subprograms or modifying
 the base class, as the use of interfaces would require.) The implementation
-would be easy (it presumably would pass the slot number of the call).
-But this seems too complex a change for this problem.
+of abstract formal subprograms is easy (it presumably would pass the slot
+number of the call for a sharing implementation).
+
+We need separate limited and nonlimited versions of this generic, because
+nonlimited tagged types do not match limited tagged formal types. The
+limited version requires the definition of functions returning limited types
+as expressed by AI-318-2/06.
+
+---
 
-The first legality rule could be eliminated either by defining a run-time
-check that raises an exception if the function is not dispatching, or by
-simply saying that a non-dispatching actual is just called. The first option
-does nothing except postpone a check to a later time, and the second option
-seems to be covering a bug.
-
-The second legality rule is needed to override 3.9.3(11) for this generic.
-That's necessary so that interfaces and abstract types can be passed into
-the generic. We could eliminate this rule (and the 'abstract' on type T),
-but that would make the generic useable on concrete types only, while most
-root classes are abstract (or possibly an interface).
-
-If the final version of AI-318 allows it, there should be a limited version
-of Generic_Dispatching_Constructor with T being limited. (This is not allowed
-by AI-318-2/05.)
+The Parent_Tag operation makes available to the user information that the
+compiler must have in order to do type conversion and membership checks.
 
 ---
 
@@ -173,7 +313,8 @@
     dispatches to the version of Constructor for the type identified by
     the tag Tag, passing Params, and returns the result.
 
-The advantage of this is that no special legality rules are needed.
+The advantage of this is that no new kind of generic formal subprogram is
+needed.
 
 However, this solution has several minor problems and one significant one.
 With apologies to David Letterman, here are the top 4 reasons that this
@@ -181,7 +322,8 @@
 
     4) This cannot be used to describe the semantics of T'Class'Input. That
        means the rules of AI-279 have to be duplicated in both the constructor
-       and the description of T'Class'Input. (They're fairly short, though).
+       and the description of T'Class'Input. (They're fairly short, though, and
+       we did that anyway).
     3) To use this to redefine T'Class'Input, the base class has to be
        modified to add this interface.
     2) The constructor function has to be named Constructor. A more appropriate
@@ -214,7 +356,7 @@
 And this makes Tag_Read and Tag_Write less symmetrical. Also note that the
 complete replacement approach means that we don't have to specify "shoulds"
 about the behavior of the attributes; whatever the user writes is what it will
-do, and if that doesn't make sense its the user's problem.
+do, and if that doesn't make sense it is the user's problem.
 
 !example
 
@@ -268,7 +410,7 @@
 In Ada 95, there is no way to prevent these bytes from being written, so
 there is no way to stream an object with an XML representation.
 
-Using the Generic_Dispatching_Constructor, it is possible to override
+Using Generic_Dispatching_Constructor, it is possible to override
 T'Class'Input and T'Class'Output to read/write the proper format.
 
 with Ada.Streams, Ada.Tags;
@@ -393,7 +535,9 @@
 Then the menu action routine (which handles menu selections) could simply call
 Create_Object with the tag identified by the menu item selected by the user.
 This structure eliminates the need for any case statements anywhere in the
-program, so adding or removing a
+program, so adding or removing a control or window doesn't require modifying
+a giant case statement (which compiles slowly, as it imports the entire
+universe).
 
 Note that a GUI builder needs to stream these objects (to save them into
 a GUI project file) as well as construct them from a menu, so overridding

Questions? Ask the ACAA Technical Agent