CVS difference for ais/ai-00251.txt

Differences between 1.10 and version 1.11
Log of other versions for file ais/ai-00251.txt

--- ais/ai-00251.txt	2003/01/03 00:01:35	1.10
+++ ais/ai-00251.txt	2003/02/01 04:40:34	1.11
@@ -2578,3 +2578,528 @@
 
 ****************************************************************
 
+From: Steve Baird
+Sent: Tuesday, January 28, 2003 11:58 AM
+
+This is my attempt at incorporating the comments of the Bedford meeting
+into AI-251.
+
+Changes include:
+  1) New type declaration syntax.
+
+  2) New derivation model (a type no longer "implements" an interface; it
+     really is "derived" from the interface type, introducing a
+     restricted notion of multiple parents for a derived type).
+
+  3) New membership test, conversion rules.
+
+  4) New homograph overriding requirements.
+
+See also the discussion section at the end.
+
+The last time I sent mail to the ARG list, it somehow ended up in
+HTML format. I hope that problem has been straightened out,
+but my apologies in advance if this message ends up similarly mangled.
+
+  -- Steve
+
+----------------
+
+
+
+3.2.1 Type Declarations
+
+Add to syntax
+
+        type_definition ::= ... | interface_type_definition
+
+
+
+3.4 Derived Types and Classes
+
+Replace syntax section with
+
+        interface_list ::= interface_subtype_mark {AND interface_subtype_mark}
+
+        derived_type_definition ::=
+            [ABSTRACT] NEW parent_subtype_indication
+            [[AND interface_list] record_extension_part]
+
+
+Add at the end of paragraph 3:
+
+    A derived type has a parent type and zero or more interface parent types.
+
+
+
+Replace paragraph 8 with:
+
+    Each class of types that includes the parent type or an interface parent
+    type also includes the derived type.
+
+Add after paragraph 25:
+
+    If a type declaration names an interface type in an interface list, then
+    the declared type inherits any user-defined primitive subprograms of the
+    interface type in the same way.
+
+    Note: this includes some declarations of non-derived types.
+
+
+3.4.1 Derivation Classes
+
+Insert after the first sentence of paragraph 2:
+
+     A derived type or interface type is also derived from each of its
+     interface parent types, if any.
+
+Replace the last sentence of paragraph 10 with:
+
+    The ultimate ancestor of a type is the ancestor of that type, if any, that
+    is not a descendant of of any other type and that is not an interface
+    type (see 3.9.4).
+
+
+3.9.3 Abstract Types and Subprograms
+
+    Replace paragraphs 4-5 with
+
+        If a type inherits a subprogram corresponding to an abstract
+        subprogram or to a function with a controlling result, then
+
+           - If the inheriting type is abstract or untagged, the inherited
+             subprogram is abstract.
+
+
+3.9.4 Interface Types
+
+    This section is entirely new.
+
+        An interface type is an abstract tagged type intended for use
+        in providing a restricted form of multiple inheritance.
+        A tagged type may be derived from multiple interface types, thereby
+        allowing multiple views of objects of the type.
+
+                                 Syntax
+
+        interface_type_definition ::= [LIMITED] INTERFACE [WITH interface_list]
+
+                                 Legality Rules
+
+        An interface type (also called an "interface") is a specific abstract
+        tagged type that is defined by an interface_type_definition.
+
+        An interface type shall have no components.
+
+        All user-defined primitive subprograms of an interface type shall be
+        abstract subprograms or null procedures.
+
+        The type of a subtype named in an interface_list shall be an
+        interface type.
+
+        If a type declaration names an interface type in an interface list,
+        then the accessibility level of the declared type shall not be
+        statically deeper than that of the interface type; also, the declared
+        type shall not be declared in a generic body if the interface type is
+        declared outside that body.
+
+        A descendant of an interface type shall be limited if and only
+        if the interface type is limited.
+
+        A full view shall be a descendant of an interface type if and only if
+        the  corresponding partial view (if any) is also a descendant of the
+        interface type.
+
+        For an interface type declared in a visible part, a primitive
+        subprogram shall not be declared in the private part.
+
+        In addition to the places where Legality Rules normally apply
+        (see 12.3), these rules apply also in the private part of an instance
+        of a generic unit.
+
+4.5.2  Relational Operators and Membership Tests
+
+                                Name Resolution
+
+        Two types are said to "potentially share descendants" either if one
+        covers the other or if both are class-wide and the corresponding
+        specific type associated with at least one is an interface type.
+
+        The simple_expression shall resolve to be of a type that potentially
+        shares descendants with the tested type.
+
+4.6 Type Conversions
+
+        If the target type is tagged then either:
+
+            - The operand type shall be covered by or descended from the target
+              type; or
+
+            - The operand type shall be a class-wide type that covers the
+              target type; or
+
+            - The operand and target types shall potentially share descendants.
+
+        If the target type is not included in any of the above five cases,
+        there shall be a type that is an ancestor of both the target type
+        and the operand type.
+
+
+7.3 Private Types and Private Extensions
+
+    Replace
+        private_extension_declaration ::=
+          TYPE defining_identifier [discriminant_part] IS
+          [ABSTRACT] NEW ancestor_subtype_indication WITH PRIVATE;
+    with
+        private_extension_declaration ::=
+          TYPE defining_identifier [discriminant_part] IS
+          [ABSTRACT] NEW ancestor_subtype_indication
+          WITH [interface_list AND] PRIVATE;
+
+
+8.3 Visibility
+
+    Add after paragraph 12:
+
+        An implicit declaration of an inherited subprogram which is neither
+        abstract nor a null procedure overrides that of a subprogram
+        inherited from an interface type which is implicitly
+        declared at the same point.
+
+        If one subprogram overrides another and a type inherits subprograms
+        corresponding to both which are implicitly declared at the same point,
+        then the inherited subprogram corresponding to the overriding
+        subprogram overrides the other inherited subprogram.
+
+        If an inherited subprogram corresponds to another subprogram and a
+        type inherits subprograms corresponding to both which are implicitly
+        declared at the same point, then the subprogram corresponding to the
+        inherited subprogram overrides the other inherited subprogram.
+
+
+    Add after paragraph 26:
+
+        If a descendant of an interface type inherits two homographs
+        which are implicitly declared at the same point, then both shall
+        be overridden.
+
+        Note: this requirement may be impossible to satisfy if the homographs
+        are not mode-conformant.
+
+12.5 Formal Types
+
+    Add to syntax
+
+        formal_type_declaration ::= ... | formal_interface_type_definition
+
+
+
+12.5.1 Formal Private Types
+
+    Replace
+        formal_derived_type_definition ::= [ABSTRACT] NEW subtype_mark
+                                           [WITH PRIVATE]
+    with
+        formal_derived_type_definition ::= [ABSTRACT] NEW subtype_mark
+                                           [WITH [interface_list AND] PRIVATE]
+
+
+    Add after paragraph 15:
+
+        The actual type shall be a descendant of every ancestor of
+        the formal type.
+
+
+12.5.5 Formal Interface Types
+
+    This section is entirely new.
+
+        The class determined for a formal interface type is the class of all
+        interface types.
+
+                                 Syntax
+
+        formal_interface_type_definition ::= interface_type_definition
+
+
+                                 Legality Rules
+
+        The actual type shall be a descendant of every ancestor of
+        the formal type.
+
+        The actual type shall be limited if and only if the formal type is
+        limited.
+
+13.14 Freezing Rules
+
+    Add after paragraph 7:
+
+        The declaration of a specific descendant of an interface type freezes
+        the interface type.
+
+--------
+
+Discussion:
+
+1) The compatibility rules for membership testing could be tightened to
+   filter out more cases where the result of a membership test could not
+   possibly be True. The two types could be required to agree with respect to
+   limitedness, accessibility level, and/or set of enclosing generic bodies
+   (with a recheck generic spec rule as well). Do we want all this in a
+   name resolution rule? I'd say no.
+
+2) "Potentially share descendants" seems like an awkward term.
+    How about "weakly compatible"? "Potentially intersecting"?
+    "Potentially convertible"? The idea here is that we want to allow any
+    membership tests where the answer is not known statically. This includes
+    a case like
+
+       type T1 is tagged null record;
+       type T2 is interface;
+
+       X1 : T1'Class := ... ;
+       X2 : T2'Class := ... ;
+
+       Flag : Boolean := (X1 in T2'Class) and (X2 in T1'Class);
+
+   because of the possibility of a type which is descended from both
+   T1 and T2, e.g.
+       type T3 is new T1 and T2 with null record;
+   .
+
+3) It might be possible to express the legality rules for type conversions more
+   concisely. Would it be equivalent to replace the 3 listed conditions with
+            - The operand type descended from the target type; or
+            - The operand and target types shall potentially share descendants.
+   ?
+
+4) What representation attributes does an interface type have?
+   Can values for these attributes be specified?
+   What do T'Size and T'Alignment mean for any abstract type, not
+   just for interface types?
+
+5) Although an interface type which has an interface parent "is derived from"
+   that type, it is not "a derived type".
+
+6) Inherited homographs must be overridden. If the homographs are
+   not mode-conformant, then this may be impossible. Life's hard.
+
+7) Nothing here (in particular, nothing in the 8.3 stuff) is intended to
+   change the semantics of a program which declares no interface types.
+
+8) An example to illustrate some of the 8.3 stuff:
+
+           package P1 is
+               type T1 is interface;
+               procedure P (X : T1) is abstract; -- P'1
+           end P1;
+
+           package P2 is
+               type T2 is interface with P1.T1;  -- P'2 (implicit)
+               procedure P (X : T2) is abstract; -- P'3
+           end P2;
+
+           type D is new Some_Tagged_Type and P1.T1 and P2.T2 with null record;
+
+       D inherits procedures P'4, P'5, and P'6, corresponding to
+       P'1, P'2, and P'3, respectively.
+
+       Since P'3 overides P'2, P'6 overrides P'5 by the "overriding is
+       preserved by inheritance" rule.
+
+       Since P'2 corresponds to P'1,  P'5 overrides P'4 by the "inherited
+       copies of your parent's ops hide inherited copies of your grandparent's
+       ops" rule.
+
+9) Yes, it really is illegal if the parent type of a "with private"
+   type's completion happens to be descended from some interface that the
+   private view was not descended from. This may turn out to be a pain.
+
+   Relaxing the rule that a partial view must be derived from the same
+   interfaces as the completion is derived from is not out of the question, but
+   it could open the door for some very peculiar situations. If this example,
+
+        package P is
+          packge Pkg is
+              type Ifc is interface;
+              procedure Foo (X : Ifc) is abstract;
+          end;
+
+          type Parent_1 is tagged null record;
+
+          type T1 is new Parent_1 with private;
+        private
+          type Parent_2 is new Parent_1 and Pkg.Ifc with null record;
+          procedure Foo (X : Parent_2); -- Foo #1
+
+          type T1 is new Parent_2 with null record;
+        end;
+
+        with P;
+        package P_Client is
+          type T2 is new P.T1 and P.Pkg.Ifc with null record;
+          procedure Foo (X : T2); -- Foo #2
+          X : T2;
+        end P2_Client;
+
+        with P_Client;
+        package body P is
+          ...
+        begin
+          Pkg.Foo (Pkg.Ifc'Class (P_Client.X));
+             -- call Foo #2
+          Pkg.Foo (Pkg.Ifc'Class (T1 (P_Client.X)));
+             -- call Foo #1
+        end P2;
+
+   , were legal (it is illegal because the completion of T1 is descended
+   an interface that the partial view is not descended from), then
+   we would have two dispatching calls to Pkg.Foo with the
+   two controlling operands having the same tag and yet different
+   bodies would be executed. The two conversions to Pkg.Ifc'Class
+   would map Pkg.Foo to different slots in the same dispatch table
+   because the source types of the conversions are different.
+
+
+--------
+
+In defining interface types, a couple of design decisions seem to be
+of interest.
+
+First, there is the question of whether interface types should
+be a whole new class of type or a special kind of abstract tagged
+type. Since interface types have to abide by all of the restrictions
+of an abstract tagged type, the former approach would have involved
+a lot of repetition. The latter approach was chosen.
+
+Second, there is the question of derivation and operator inheritance.
+If a type "implements" an interface, then it must inherit operators
+from the interface type in order to override them. In an earlier version
+of this AI, the "implementing" type was not considered to be derived from the
+parent interface type and operator inheritance was accomplished via
+a separate mechanism. Now, a type which implements an interface type
+is defined to be derived from the interface type, thereby simplifying the
+operator inheritance rules and the definitions of terms such as
+"ancestor", "descendant", and "cover". This means that a given type may
+be immediately derived from more than one type, but at most one of them
+can be a non-interface type. It is no longer the case that every type
+has an "ultimate ancestor", but the term remains well-defined in all the
+cases where it is used in the reference manual.
+
+The rules for type conversion and membership testing need revision to
+cope with the possibility that an interface type and a tagged type
+might have a common descendant even though statically available information
+suggests no relationship between the two types.
+
+As an implementation model, one can think of a type which
+inherits operations from an interface type as defining a
+mapping from the primitive operations of the interface type (perhaps
+represented as dispatch table slot numbers) to those of the inheriting type.
+A dispatching call to an operation of an interface type is than accomplished
+by mapping the the called operation to the corresponding
+operation of the controlling operand's type. Alternatively, one
+might construct a separate dispatch table representing this
+alternative "view" of the "real" dispatch table, but that would
+require more work when deriving from a type which implements
+an interface. The slot-to-slot mapping remains valid and can be
+reused for the derived type, whereas a new alternative "view"
+of the dispatch table of the derived type would need to be
+constructed. A value of type Some_InterFace_Type'Class can then
+be represented at runtime as a record address paired with a
+reference to this dispatch table permutation map.
+
+Classwide streaming operations for interface types require
+some care. Consider the case of a call to Some_Interface_Type'Class'Input
+occuring as the controlling operand of a dispatching call. The
+implementation must be able to determine where to dispatch to in this case.
+Membership testing may also require maintaining additional information
+at runtime.
+
+It is intended that a type which is derived from an interface type should
+inherit the same subprograms as a type which is derived from both the
+interface type and an ancestor of the interface type. The two type definitions
+should be indistinguishable, in the sense that adding or deleting the
+explicit redundant derivation relationship should be a semantics-preserving
+transformation.
+
+It is intended that there should be no real difference between the two
+forms of derivation from interface type parents. For example, replacing
+the declaration
+   type T is new Interface_Type_1 and Interface_Type_2 with null record;
+with
+   type T is new Interface_Type_2 and Interface_Type_1 with null record;
+should be semantics-preserving.
+
+---------
+
+An example involving interface types:
+
+   type T is tagged null record;
+   T_Var : T;
+
+   package P1 is
+      type Ifc1 is interface;
+      procedure Op    (X : Ifc1) is abstract;
+      procedure Op1_A (X : Ifc1) is abstract;
+      procedure Op1_B (X : Ifc1) is abstract;
+
+      type Ref is access all Ifc1'Class;
+      Procedure Foo (X : Ref);
+   end;
+
+   package P2 is
+      type Ifc2 is interface;
+      procedure Op    (X : Ifc2) is abstract;
+      procedure Op2_A (X : Ifc2) is abstract;
+      procedure Op2_B (X : Ifc2) is abstract;
+
+      type Ref is access all Ifc2'Class;
+      Procedure Foo (X : Ref);
+   end;
+
+   package body P1 is
+      ...
+
+      procedure Foo (X : Ref) is
+         type Stream_Ptr is access all Ada.Streams.Root_Stream_Type'Class;
+         The_Stream : constant Stream_Ptr := ...;
+      begin
+          Op1_A (X.all);
+          Op1_B (X.all);
+          Ifc1'Class'Output (The_Stream, X.all);
+
+          if X.all in T'Class then
+              T_Var := T (X.all);
+          end if;
+      end Foo;
+   end P1;
+
+   package body P2 is
+      ...
+   end P2;
+
+   type D is tagged
+       with P1.Ifc1 and P2.Ifc2 and
+       record
+           F1, F2 : Integer;
+       end record;
+
+   procedure Op1_A (X : D);
+   procedure Op1_B (X : D);
+   procedure Op    (X : D);
+   procedure Op2_A (X : D);
+   procedure Op2_B (X : D);
+
+   ...
+
+   X : aliased D;
+ begin
+   P1.Foo (X'Access);
+   P2.Foo (X'Access);
+   P1.Op (P1.Ifc1'Class (X));
+   P2.Op (P2.Ifc2'Class (X));
+ end;
+
+****************************************************************
+

Questions? Ask the ACAA Technical Agent