CVS difference for acs/ac-00009.txt

Differences between 1.1 and version 1.2
Log of other versions for file acs/ac-00009.txt

--- acs/ac-00009.txt	2001/06/02 04:13:15	1.1
+++ acs/ac-00009.txt	2001/07/14 00:01:47	1.2
@@ -142,3 +142,776 @@
 
 ****************************************************************
 
+From: Randy Brukardt
+Sent: Wednesday, June 06, 2001 7:31 PM
+
+I was thinking about this again when reviewing AI-260.
+
+The problem in AI-260 is solved with a rather specific feature. The dynamic
+view conversion problem was solved with dynamic view conversions. But the
+problem in both cases isn't conversion, or reading tags, its really
+controlling dispatching.
+
+A solution that included more control over dispatching would probably solve
+both problems.
+
+Pascal Leroy said:
+
+> I'd say that we don't want to add more dynamicity in the language at this
+> stage. My gut feeling is that defining the proposed construct would be quite
+> hard, and would probably have a significant impact on implementations.
+
+That might be true for the exact proposal given, but I think that
+controlling dispatching isn't likely to cause problems.
+
+Consider that pseudo-code for the canonical implementation of a dispatching
+call looks like:
+
+   declare
+       Disp_Tag : Ada.Tags.Tag := <First_Controlling_Parameter>'Tag;
+   begin
+       for I in <all controlling parameters> loop
+           if I'Tag /= Disp_Tag then
+               raise Constraint_Error;
+           end if;
+       end loop;
+       Disp_Tab (Slot_Number).all (<parameters>);
+   end;
+
+What we need to solve both this problem and the AI-260 one is a way to
+dispatch on a user-calculated tag. Such a call would probably have pseudo
+code that looks like:
+
+   declare
+       Disp_Tag : Ada.Tags.Tag := <some user expression>;
+   begin
+       for I in <all controlling parameters> loop
+           if I'Tag not in Disp_Tag'Class then
+               raise Constraint_Error;
+           end if;
+       end loop;
+       Disp_Tab (Slot_Number).all (<parameters>);
+   end;
+
+The parameter check in this case is essentially the same as that done for
+type conversions, so compilers certainly know how to deal with it.
+
+This suggests that there isn't much of a problem with this as a (runtime)
+model. (Tag indeterminate operands would just use the calculated tag, which
+is exactly how they are handled in the current model of dispatching).
+
+The problem here is to think of some appropriate syntax for this. Tucker had
+suggested a magic generic, but I can't figure out how that would work.
+
+I also thought about using a variation of the proposed Obj.Op(...) calling
+to handle this, but that doesn't give us an appropriate way to handle Op.
+
+So, the best I can come up with is a new syntax:
+
+     <Tag_Prefix> ::= <tag_object_name> :
+     <function_call> ::= <tag_prefix> <function_name>
+         (and so on for the other forms of call).
+
+We'd also want to add a routine to Ada.Tags:
+
+    function Common_Ancestor (A, B : in Ada.Tags.Tag) return Tag;
+	-- Returns the common ancestor closest to A and B. Raises Tag_Error
+	-- if A and B do not have a common ancestor.
+
+Then, to solve Michael Grey's problem:
+
+    procedure Common_Parts_Equal (A, B : in Root_Type'Class) is
+        Ancestor_Tag : Ada.Tags.Tag :=
+            Ada.Tags.Common_Ancestor (A'Tag, B'Tag);
+            -- This can't raise Tag_Error, as the common ancestor must be
+            -- at least Root_Type.
+    begin
+        return Ancestor_Tag : "=" (A, B);
+           -- This would call the appropriate "=" for Ancestor tag, both
+           -- operands must therefore have types that are descendants of the
+           -- type identified by Ancestor tag.
+    end Common_Parts_Equal;
+
+Similarly, to solve the AI-260 problem, we'd override XML'Class'Input with
+
+    function XML_Object_Input
+        (Stream : access Ada.Streams.Root_Stream_Type'Class;
+         return XML'Class is
+        Object_Tag : Ada.Tags.Tag := Read (Stream);
+              -- Read from AI-260 example.
+    begin
+        return Object_Tag : XML'Input (Stream);
+           -- Which would call the 'Input routine for the type identified by
+           -- object tag.
+    end XML_Object_Input;
+
+
+The only real problem I see with this is the need for new syntax. Perhaps
+someone else can figure a way around that?? (Or a better syntax.)
+
+****************************************************************
+
+From: Pascal Leroy
+Sent: Tuesday, June 12, 2001 3:17 AM
+
+While I have some sympathy for supporting the kind of dispatching that Randy
+and Michael advocate, I am adamantly opposed to introducing newly (and
+disgraceful) syntax for that purpose.
+
+As I mentioned earlier, all you need is a conversion that changes the tag, but
+leaves the rest of the record unchanged.  This can be achieved by a new
+predefined generic (which could go in Ada.Tags):
+
+    generic
+        type Destination is tagged private;
+        type Source is abstract new Destination with private;
+    function Tag_Conversion (S : Source; T : Ada.Tags.Tag)
+               return Destination'Class;
+
+The effect of which is to make a copy of S, replacing the tag with T.  Then the
+result of calling (an instantiation of) this function may be used for
+dispatching, and the right thing will happen.
+
+> We'd also want to add a routine to Ada.Tags:
+>
+>     function Common_Ancestor (A, B : in Ada.Tags.Tag) return Tag;
+> -- Returns the common ancestor closest to A and B. Raises Tag_Error
+> -- if A and B do not have a common ancestor.
+
+Again, I object to Common_Ancestor, which represents one usage pattern among
+many others.  I would be willing to add to Ada.Tags a function to return the tag
+of the parent:
+
+    function Parent_Tag (T : Ada.Tags.Tag) return Ada.Tag.Tags;
+
+Using this function, it would be straightforward to implement Common_Ancestor by
+walking up the derivation tree.  It would also be possible to implement other
+usage patterns.  And finally it would be easier to call the parent in
+general-purpose code.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Tuesday, June 12, 2001 4:52 PM
+
+> The effect of which is to make a copy of S, replacing the tag with T.  Then the
+> result of calling (an instantiation of) this function may be used for
+> dispatching, and the right thing will happen.
+
+Danger Will Robinson!!!!
+
+When you say "copy", you immediately have two problems: (1) Copying the item
+would trigger all of the Adjust rules. But which version of Adjust do you call?
+And if you don't call Adjust, then you have an object for which the invariants
+don't hold. For instance, Claw Window objects are linked into an active object
+list. If that doesn't happen, you'll have problems, especially if the user
+passes this result into something that closes the object.
+
+(2) Once you say copy, you've eliminated the possibility to use this on limited
+types. That seems like an unacceptable limitation; at least half of the O-O
+types I've used are limited. (Once you've given up and gone over to the dark
+side of reference semantics, it usually is best to prevent all copying of
+objects.)
+
+I assume that you are restricting this somehow to downward conversions, because
+clearly we can't allow upward conversions. That would have to be done at
+runtime, since the check couldn't be part of a generic.
+
+The problem is exactly one of controlling dispatching; to try to describe it as
+something else is likely to bring in additional, unnecessary problems (such as
+those above). Note that in my scheme, if the called routine wants to force
+redispatching, it will redispatch to the original tag (as normally happens in
+Ada 95); while in yours, the called routine will redispatch to the new tag
+(which clearly would be different than normal practice).
+
+In any case, I suggested what I did to try to start some discussion in this
+topic. Since only you, I, and Michael have commented on it, it obviously isn't
+of interest to many. And since my solution is too heavy for some, your solution
+does not work, and Tucker hasn't weighed in with the solution to all problems
+:-), it probably is best to forget this one altogether.
+
+> ...  I would be willing to add to Ada.Tags a function to return the
+> tag of the parent:
+>
+>     function Parent_Tag (T : Ada.Tags.Tag) return Ada.Tag.Tags;
+>
+> Using this function, it would be straightforward to implement Common_Ancestor
+> by walking up the derivation tree.  It would also be possible to implement
+> other usage patterns.
+
+This seems fine. (Although I can't think of any way to implement
+Common_Ancestor using it -- but since any implementation of Common_Ancestor
+would have to use a parent function of some sort, that's not a problem. The
+problem is that walking up the tree alone isn't enough, because you don't know
+which operand has to be walked.)
+
+> And finally it would be easier to call the parent in
+> general-purpose code.
+
+This seems to be true only if you have syntax to control the dispatching:
+
+     Ada.Tags.Parent_Tag(Object):Me(Object, Args...);
+
+If you have to instantiate a generic to do it, it doesn't help anything at all.
+That would be twice as much text as the type conversion that we need now.
+(Unless, of course, we add "automatic" instantiations to the language, an idea
+which I would oppose on the grounds that "implicit" declarations are nearly
+always bad.)
+
+****************************************************************
+
+From: Christoph Grein
+Sent: Monday, June 18, 2001 4:55 AM
+
+> This seems fine. (Although I can't think of any way to implement
+> Common_Ancestor  using it -- but since any implementation of Common_Ancestor
+> would have to use a parent function of some sort, that's not a problem. The
+> problem is that walking up the tree alone isn't enough, because you don't
+> know which operand has to be walked.)
+>
+
+A further operation in Ada.Tags would be needed like
+
+  function is_Derived_From (Left, Right: Ada.Tags.Tag) return Boolean;
+
+> > And finally it would be easier to call the parent in
+> > general-purpose code.
+>
+> This seems to be true only if you have syntax to control the dispatching:
+>
+>      Ada.Tags.Parent_Tag(Object):Me(Object, Args...);
+>
+> If you have to instantiate a generic to do it, it doesn't help anything at
+> all. That would be twice as much text as the type conversion that we need
+> now. (Unless, of course, we add "automatic" instantiations to the language,
+> an idea which I would oppose on the grounds that "implicit" declarations are
+> nearly always bad.)
+
+I think this new syntax proposal in its utmost ugliness has no chance in the
+eyes of the Ada-powers-that-be.
+
+Are there similar functionalities in Java (IIRC no) or C++ (I don't know)?
+
+The problem I tried to solve was that with discriminated types, an operation
+like
+
+  Compare (Left, Right)
+
+can have Left and Right with different discriminants and I can easily compare
+the common parts, but a dispatching operation cannot have different tags on Left
+and Right, and I have no access to the common parts.
+
+It seems the problem is a mixture of conversion and dispatching control.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Tuesday, July 3, 2001 4:14 PM
+
+> > > And finally it would be easier to call the parent in
+> > > general-purpose code.
+> >
+> > This seems to be true only if you have syntax to control the dispatching:
+> >
+> >      Ada.Tags.Parent_Tag(Object):Me(Object, Args...);
+> >
+> > If you have to instantiate a generic to do it, it doesn't help anything at
+> > all. That would be twice as much text as the type conversion that we need
+> > now. (Unless, of course, we add "automatic" instantiations to the language,
+> > an idea which I would oppose on the grounds that "implicit" declarations are
+> > nearly always bad.)
+>
+> I think this new syntax proposal in its utmost ugliness has no chance in the
+> eyes of the Ada-powers-that-be.
+
+It wasn't so much of a serious proposal, but rather an attempt to put the
+problem (and one way to solve it) in front of the community.
+
+> Are there similar functionalities in Java (IIRC no) or C++ (I don't know)?
+
+Me either.
+
+> The problem I tried to solve was that with discriminated
+> types, an operation like
+>
+>   Compare (Left, Right)
+>
+> can have Left and Right with different discriminants and I can easily compare
+> the common parts, but a dispatching operation cannot have different tags on Left
+> and Right, and I have no access to the common parts.
+>
+> It seems the problem is a mixture of conversion and dispatching control.
+
+No, that's the thinking that leads to the paralysis of being unable to do
+anything about it. In order to solve this, we have to think a bit outside of
+the box.
+
+In Ada 95, conversions are used to control dispatching. So one can think of
+this problem as one of dispatching control OR conversion. But both is not
+necessary.
+
+If we found a way to control dispatching directly, then the existing (implicit)
+conversions present in Ada 95 is sufficient to provide all of the conversions
+needed.
+
+An alternative way to look at the problem is purely as an exercise in view
+conversions. If we know the common type that we want to compare, we simply
+would convert to that type explicitly (this works in Ada 95, and indeed is
+how I approached the problem):
+
+    Compare (Base_Type(Left), Base_Type(Right));
+
+which will call the version of Compare for Base_Type.
+
+So an alternative solution would look something like:
+
+    declare
+       Common_Tag : Ada.Tags.Tag := Common_Ancestor(Left'Tag, Right'Tag);
+           -- Common_Ancestor doesn't have to be predefined.
+    begin
+       Compare (Magic_Conversion (Left, Common_Tag),
+                Magic_Conversion (Right, Common_Tag));
+    end;
+
+The problem is defining Magic_Conversion.
+
+One could consider a (magic) generic for this purpose:
+    generic
+        type Some_Tagged_Classwide (<>) is tagged limited private;
+    function Magic_Conversion (Obj : in Some_Tagged_Classwide;
+        New_Tag : in Ada.Tags.Tag) return Some_Tagged_Classwide;
+
+which would then be instantiated:
+    function My_Magic_Conversion is new Magic_Conversion (Root_Type'Class);
+
+The trouble with this is that this would give us a value conversion. But for
+this purpose (where we don't actually want to convert anything, we're just
+using that as a shorthand to control dispatching), we really want a view
+conversion. Moreover, we don't want to try to copy anything, as that triggers
+Adjust, and doesn't work for limited types.
+
+I suppose we could define this generic to be totally magic, doing a view
+conversion, but I think I'd rather have syntax in that case.
+
+Note that Pascal's previous comment saying that you need to change the tag is
+wrong. You NEVER change the tag in Ada 95, you simply change the tag that is
+used for dispatching determination. All we need here is to be able to control
+what tag is used for dispatching; we don't need to change the object in any
+way.
+
+One reason that I looked at syntax for this is the well-known problem with
+calling the parent routine in an overriding of a operation:
+
+    My_Operation (Parent_Type(Object), ....);
+
+which is fragile because we have to explicitly write the parent type's name.
+If an additional type is inserted between the child and parent types, all of
+the uses of Parent_Type need to be searched out and changed if they are
+intended to point at the parent.
+
+One use for the proposed syntax would be to force dispatching to the parent
+without naming it:
+
+    Ada.Tags.Parent_Tag (Object'Tag):My_Operation (Object, ...);
+
+We could simplify this further by introducing a 'Parent_Tag attribute:
+
+    Object'Parent_Tag:My_Operation (Object, ...);
+
+---
+
+Anyway, my syntax proposal was really intended to start a discussion. It solves
+three problems that have been discussed in various amounts:
+
+1) The AI-260 problem for which the band-aid of 'Tag_Read and 'Tag_Write
+attributes were introduced. I'd prefer a more building block approach if
+possible.
+
+2) The Compare problem noted by several people.
+
+3) The problem that the call to parent operation usually made in overriding
+operations has to explicitly use the name of the parent type.
+
+At this point, since hardly anyone has seemed interested enough to discuss it,
+much less propose an alternative, I consider this whole discussion dead.
+
+****************************************************************
+
+From: Robert Duff
+Sent: Wednesday, July 4, 2001 10:23 AM
+
+Christoph Grein wrote:
+>   Compare (Left, Right)
+
+I haven't followed this whole discussion, so this might be a non
+sequitor, but you can do something like this:
+
+    function Compare(X, Y: T'Class) return Boolean is
+    begin
+        if X'Tag = Y'Tag then
+            return Compare_Method(X, Y); -- dispatching call
+        else
+            return False;
+        end if;
+    end Compare;
+
+****************************************************************
+
+From: Christoph Grein
+Sent: Wednesday, July 4, 2001 12:25 AM
+
+> One reason that I looked at syntax for this is the well-known problem with
+> calling the parent routine in an overriding of a operation:
+>
+>     My_Operation (Parent_Type(Object), ....);
+>
+> which is fragile because we have to explicitly write the parent type's name.
+> If an additional type is inserted between the child and parent types, all of
+> the uses of Parent_Type need to be searched out and changed if they are
+> intended to point at the parent.
+
+I haven't thought of this, but I think this problem deserves a well-designed
+solution. This is much like the problem of inadvertant overriding or not
+overriding an inherited operation, which is being solved via pragmas.
+
+> One use for the proposed syntax would be to force dispatching to the parent
+> without naming it:
+>
+>     Ada.Tags.Parent_Tag (Object'Tag):My_Operation (Object, ...);
+>
+> We could simplify this further by introducing a 'Parent_Tag attribute:
+>
+>     Object'Parent_Tag:My_Operation (Object, ...);
+
+Couldn't this be solved by a new attribute T'Parent_Type:
+
+      My_Operation (T'Parent_Type(Object), ....);
+
+without the need of a new syntax?
+Here for every tagged type T, T'Parent_Type denotes the parent type (or, if
+T is the root of the hierarchy, denotes T itself). [This is much like
+T'Class'Class being the same as T'Class.]
+
+> Anyway, my syntax proposal was really intended to start a discussion. It
+> solves three problems that have been discussed in various amounts:
+>
+> 1) The AI-260 problem for which the band-aid of 'Tag_Read and 'Tag_Write
+> attributes were introduced. I'd prefer a more building block approach if
+> possible.
+>
+> 2) The Compare problem noted by several people.
+>
+> 3) The problem that the call to parent operation usually made in overriding
+> operations has to explicitly use the name of the parent type.
+>
+> At this point, since hardly anyone has seemed interested enough to discuss
+> it, much less propose an alternative, I consider this whole discussion dead.
+
+I think it should not be dead for the third problem. This is also a problem
+Java (and I gather many other OO languages) suffer from. A solution would be
+in the Ada spirit.
+
+****************************************************************
+
+From: Steve Deller
+Sent: Wednesday, July 4, 2001 6:49 PM
+
+Are you proposing a new attribute function that takes an object and returns
+an object with the parent tag of the original object?  Or are you proposing
+an attribute that denotes a subtype (much like T'Class denotes a subtype),
+and intending type conversion to take care of converting an object?  In the
+latter case, one could also write:
+   x : T ;
+   y : T'Parent_Type ;
+which would be invalid for the former approach.
+
+Somehow the latter seems more appropriate to me.  It feels like an
+appropriate "completion" to the 'Class and 'Tag attributes.
+
+I too like the "building block" approach and it does seem that 'Parent_Type
+would be a powerful building block.
+
+The "compare the most common ancestor" is then easy to write, as you point
+out:
+
+   function Compare_Common( X, Y : T'Class ) return Boolean is
+     Temp : T'Class ;
+     Tx : T'Class ;
+     Ty : T'Class ;
+   begin
+
+     loop
+
+       loop
+
+         if Tx'Tag = Ty'Tag then
+            return Compare_Method( Tx, Ty ) ;
+         end if ;
+
+         Temp := T'Parent_Type( Tx ) ;
+         exit when Tx = Temp ;
+         Tx := Temp ;
+
+        end loop ;
+
+        Temp := T'Parent_Type(Py) ;
+        exit when Temp'Tag = Ty'Tag ;
+        Ty := Temp ;
+
+      end loop ;
+
+      raise Program_Error ; -- no common ancestor found and at least the
+root T should be found
+   end Compare_Common ;
+
+****************************************************************
+
+From: Robert Duff
+Sent: Thursday, July 5, 2001 9:22 AM
+
+> without the need of a new syntax?
+> Here for every tagged type T, T'Parent_Type denotes the parent type (or, if T is
+> the root of the hierarchy, denotes T itself). [This is much like T'Class'Class
+> being the same as T'Class.]
+
+A Parent_Type attribute was considered during the 9X design.
+I don't remember the details, or why it was rejected.
+
+The T'Parent_Type = T case at the root seems fishy to me.
+
+Some other questions that would have to be answered:
+A private type does not have a "parent type" -- it has an "ancestor
+type".  Does that mean there should be a 'Ancestor_Type?
+Or does 'Parent_Type return the ancestor type for a partial view.
+
+If the ancestor of a private type is different from the parent of the
+full type, does 'Parent_Type return something different depending
+on where it appears in the source code (i.e., whether the full type is
+visible)?  Sounds questionable to me...
+
+For a generic formal type, does T'Parent_Type in the instance return
+something different from T'Parent_Type in the generic?
+
+****************************************************************
+
+From: Christoph Grein
+Sent: Monday, July 9, 2001 2:12 AM
+
+> Are you proposing a new attribute function that takes an object and returns
+> an object with the parent tag of the original object?  Or are you proposing
+> an attribute that denotes a subtype (much like T'Class denotes a subtype),
+> and intending type conversion to take care of converting an object?  In the
+> latter case, one could also write:
+>    x : T ;
+>    y : T'Parent_Type ;
+> which would be invalid for the former approach.
+
+Yes, this was the idea, but see the comments of Robert Duff about the problems
+with private types, which only have ancestors.
+
+My feeling would be that you "get what you can see", i.e. for private view
+T'Parent_Type is the ancestor, for the full view is the parent. But I'll leave
+the discussion to more knowledgable people.
+
+----
+
+The following code [Steve Deller's - ED] would not work since you do not know
+where X and Y meet in the hierarchy.
+Also initial values for Tx and Ty are missing, I assume you mean X resp. Y. The
+declaration of Temp, Tx, Ty is illegal and the code impossible since they must
+be initialized and are then constrained.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Friday, July 13, 2001 5:07 PM
+
+> ...Or are you proposing an attribute that denotes a subtype (much like
+> T'Class denotes a subtype), and intending type conversion to take care
+> of converting an object? ...
+>
+> Somehow the latter seems more appropriate to me.  It feels like an
+> appropriate "completion" to the 'Class and 'Tag attributes.
+
+That seems like a truckload of worms to me. (Like a can of worms, only
+bigger.) You'd have problems with discriminants, private types, generics,
+and gosh knows what else.
+
+> I too like the "building block" approach and it does seem that 'Parent_Type
+> would be a powerful building block.
+>
+> The "compare the most common ancestor" is then easy to write,
+
+Perhaps, but not the way you show it below:
+
+> as you point out:
+>
+>    function Compare_Common( X, Y : T'Class ) return Boolean is
+>      Temp : T'Class ;
+
+Umm, this is illegal in Ada 95. The item needs to be initialized, and the
+type can't be changed after the initialization. So you can't solve the
+problem this way.
+
+****************************************************************
+
+From: Michael Yoder
+Sent: Friday, July 6, 2001 11:06 AM
+
+It seems to me the principal missing thing is a way to go from a tag to a
+type.  Given that, everything else can be done by defining the right
+operations on tags (e.g., a function to yield the tag of the parent given
+the tag of the type).
+
+Here's an initial suggestion: an attribute 'Type that takes a single
+argument which is a tag, and which yields a tagged type.  (Yes, I know this
+is a peculiar sort of attribute.)  The prefix must be a tagged type, and the
+tag is required to be that of a type in the derivation class of the prefix,
+or Tag_Error is raised.
+
+If this type is allowed to be used generally, e.g. to declare an object,
+more is needed because of discriminants.  Consider the following:
+
+    declare
+       X : T'Type (Tag);
+    ...
+
+We must require that the type corresponding to Tag has defaults for all its
+discriminants (or an exception is raised).
+
+It is possible that T has discriminants which you want to use; consider
+this:
+
+    declare
+       X : T'Type (Tag) (Discrim1, Discrim2);
+    ...
+
+Here (Discrim1, Discrim2) must be a valid discriminant constraint for the
+type T.  Moreover Tag mustn't correspond to a type that replaces T's
+discriminants with others, or an exception is raised.
+
+I do not have a good handle on how difficult this would be to implement on
+the compiler side, but it seems to me that the run-time side could work
+using standard techniques.  (If I'm wrong, by all means disabuse me of this
+notion.)
+
+In the above, "an exception" is one of Constraint_Error, Program_Error, or
+Tag_Error.  I lean towards Constraint_Error.  Oh, and I'm not seriously
+suggesting that the name of the attribute be 'Type, though I suppose it
+could be.
+
+****************************************************************
+
+From: Christoph Grein
+Sent: Monday, July 9, 2001 2:47 AM
+
+>     declare
+>        X : T'Type (Tag);
+>     ...
+>
+> We must require that the type corresponding to Tag has defaults for all its
+> discriminants (or an exception is raised).
+
+And T'Type (Tag) must not be abstract to be consistent with the current
+situration that there are never objects of an abstarct type.
+
+>
+> It is possible that T has discriminants which you want to use; consider
+> this:
+>
+>     declare
+>        X : T'Type (Tag) (Discrim1, Discrim2);
+>     ...
+>
+> Here (Discrim1, Discrim2) must be a valid discriminant constraint for the
+> type T.  Moreover Tag mustn't correspond to a type that replaces T's
+> discriminants with others, or an exception is raised.
+
+Uh-hu, where does this lead us?
+
+And it seems to me that for the problem of the common ancestor, we would need
+more for a nice solution: Tags could be partially ordered:
+
+   function "<=" (Left, Right: Tag) return Boolean;
+
+   Returns True if Right is in the derivation tree of Left, else False.
+
+X: TX;
+Y: TY;
+
+X'Tag <= Y'Tag if and only if Y in TX'Class.
+
+Then we could easily walk back in the derivation tree until the tags match.
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Friday, July 13, 2001 5:33 PM
+
+> Uh-hu, where does this lead us?
+
+Personally, I think it is into an impenetrable morass. Remember that tagged
+types can add discriminants when they are derived, and moreover cannot have
+initialized discriminants. Thus, you have to get the discriminants on an
+object declaration, but with this attribute, there would be no way to know
+what they are!
+
+Also, as Christoph noted, if the tag represented an abstract type, you
+couldn't declare an object.
+
+I think these would have to be restricted to very specific contexts. One way
+would be to declare them indefinite (which would prevent object
+declarations, and many sorts of generic matching), but I'm not sure that's
+enough.
+
+The real goal here is to get a dynamic view conversion where the type is
+identified by a tag value, rather than by name. Going further than that
+brings in a truckload of worms. Perhaps we just need to define such an
+attribute:
+
+    T'Class'Convert (Obj : in out T'Class; Tag : in Ada.Tags.Tag)
+
+Returns a view conversion of Obj to the type identified by tag. This
+attribute is considered dynamically tagged for dispatching purposes. Raises
+Constraint_Error if Tag does not identify a type in T'Class, or if the tag
+of Obj does not identify a type that is covered by or descended from the
+classwide type identified by Tag (this is 4.6(42)). Note: The tag of <Obj>
+is unchanged, as in all view conversions.
+
+> And it seems to me that for the problem of the common ancestor, we would
+need
+> more for a nice solution: Tags could be partially ordered:
+>
+>    function "<=" (Left, Right: Tag) return Boolean;
+>
+>    Returns True if Right is in the derivation tree of Left, else False.
+>
+> X: TX;
+> Y: TY;
+>
+> X'Tag <= Y'Tag if and only if Y in TX'Class.
+>
+> Then we could easily walk back in the derivation tree until the tags
+match.
+
+Right. We still need a way to get the parent tag or something like that. The
+above would work, as would my original 'Parent_Tag. (I really think it is a
+horrible idea to introduce types that aren't known at compile time; I
+suspect that is why the 'Parent_Type was rejected.)
+
+My preference for 'Parent_Tag is that it is illegal on non-derived,
+non-tagged types. But making it illegal on non-derived type probably is a
+contract model problem. So, I suppose it probably ought to return Null_Tag
+on non-derived types (which means we'd have to define that, too). Similarly,
+it ought to return the parent tag even for private types (skipping levels of
+derivation would cause problems in practice, and would make it worthless for
+the "calling the parent" problem. That means the parent tag of the full
+type, which should not be a problem to do (this is not a static expression,
+and certainly at runtime the parent tag is known. Indeed, Ada
+implementations have to store this in the tag already in order to be able to
+make the type conversion checks of 4.6(42) - I would expect that this is
+precisely what would be returned. If the compiler has the information, why
+shouldn't the programmer be able to use it??)
+
+****************************************************************
+

Questions? Ask the ACAA Technical Agent