!standard 13.3.2(00) 11-01-26 AC95-00208/01 !class Amendment 11-01-26 !status received no action 11-01-26 !status received 09-11-18 !subject Preconditions are actively harmful !summary !appendix From: Anderson Ture Date: Wednesday, November 10, 2010 10:40 AM Maybe a na‹ve or to late proposal but ... Would it be possible to include a new attribute in Ada 2012, something like: S'Parent For every derived type: S'Parent denotes the parent type of S. The goal searched for is to facilitate constructs such as type p is tagged record ... procedure proc (fp : p); type d is new p with record ... procedure proc (fp : d); ... procedure proc (fp : d ) is begin d'parent (fp).proc; -- do the job needed in inherited part. ... -- Do the job needed in the derived part. end proc; *************************************************************** From: Randy Brukardt Date: Wednesday, November 10, 2010 1:42 PM > Maybe a na‹ve or to late proposal but ... Definitely too late for Ada 2012; at this point we are polishing and/or throwing out existing proposals, not adding new ones. > Would it be possible to include a new attribute in Ada 2012, something like: > > S'Parent For every derived type: > S'Parent denotes the parent type of S. > ... We considered something like this for Ada 2005, but there are a number of problems. One problem is exactly what you mean by "derived type". The official definition is "declared by a derived_type_declaration". That would work, but would be surprising as private extensions and formal derived types (both of which appear syntactically to have parents) would not be included. Moreover, it would mean that the view of the type would determine whether or not 'Parent could be used; that potentially introduces a number of oddities. The more interesting alternative (defining this for all tagged types, which is what we wanted to do for Ada 2005 as an operation in Ada.Tags) doesn't really work, as the ancestor of a private extension does not need to be the same as the parent of the full type. Defining the parent to be that of the full type would mean that privacy is being broken, and could in extreme cases lead to referencing a type that hasn't been declared yet. The alternative of the result depending on the view is both likely to be confusing, and worse, doesn't really meet the need explained above. Also, defining this as an attribute complicates attribute processing significantly. Currently, the only type attributes are 'Base and 'Class, which cannot be used together and multiple occurrences mean the same as a single occurrence (that is, T'Base'Base = T'Base, T'Class'Class = T'Class), so they can be ignored. However, T'Parent could be used with T'Class, so you could have things like T'Parent'Class and T'Class'Parent and even T'Class'Parent'Class, and there is no ignoring these. Also note that by using an attribute, you are prevented from using it usefully for classwide objects. T'Class'Parent would be the same as T'Parent, while you probably would want to call the parent operation of the type designated by the tag of the object. That's why we looked at defining an Ada.Tags operation. This is one of those cases that Bob likes to complain about, where the presense of an obscure Ada feature (in this case, private types with different ancestors than the full type) greatly complicates the definition of a useful feature (Parent for tagged types). In any case, this has to wait for Ada 2020. It's clearly not a "simple" change. *************************************************************** From: Bob Duff Date: Wednesday, November 10, 2010 3:08 PM > We considered something like this for Ada 2005, but there are a number > of problems. I thought so, but I couldn't find any AI on that. Do you remember? I searched for 'parent. It was also considered during the original Ada 9X design. > This is one of those cases that Bob likes to complain about, where the > presense of an obscure Ada feature (in this case, private types with > different ancestors than the full type) greatly complicates the > definition of a useful feature (Parent for tagged types). Right, I like to complain about that, although the particular feature you mention is not all that obscure -- I use it fairly often. It's quite common to hide the "controlledness" of a type, for example, so clients can't call Finalize directly. Anyway, as Randy says, it won't make it into Ada 2012 -- too late. Maybe next time. I think with sufficient restrictions, the feature could be fairly simple. I mean, the goal is for some operation to call the corresponding parent operation (inside the package itself), not to have clients declaring objects of type T'Class'Parent'Parent'Base. ;-) Other languages have this feature. For example "super" in Smalltalk. Does anybody here know whether "super super" is allowed in such languages? By the way, AdaCore is currently considering whether to implement this feature as a gnat-specific attribute. *************************************************************** From: Edmond Schonberg Date: Wednesday, November 10, 2010 3:43 PM > Other languages have this feature. For example "super" in Smalltalk. > Does anybody here know whether "super super" is allowed in such > languages? Java uses "super" both to denote components of the parent that are hidden by a declaration in the derived class, and to get to operations of the parent class. It explicitly forbids super.super. *************************************************************** From: Adam Beneschan Date: Wednesday, November 10, 2010 3:52 PM I found this in a post of Randy's on the Ada-Comment list, from 24 October 2005; it's not quite the same thing but it's related: # I'm primarily interested in having a way to automatically call the parent # routine (without the complication of writing it, with all of the # possibilities for error that entails, or insuring its on all of the possible # paths). # # A more flexible and more explicit alternative would some syntax that stands # in for a call to the parent routine. Say: # # 'Parent(<>) # # (The box would be a stand-in for the parameter list, which would be passed # unmodified. Writing the parameter list is the worst cause of errors.) # # In any case, it doesn't seem that we even have an agreement on what the # problem is, so it's pretty clear that we can't design a solution. *************************************************************** From: Randy Brukardt Date: Wednesday, November 10, 2010 3:55 PM > I thought so, but I couldn't find any AI on that. > Do you remember? I searched for 'parent. I couldn't find an AI, either. I did find a reference to a "serious effort to solve the parent type issue" in the !appendix for AI95-0260-1, but I didn't find the mail thread for that. I'm pretty sure it is filed under some other AI or AC (not one devoted to that topic) so it probably will be hard to find. My memory was that the discussion was in terms of a Parent_Tag operation for Ada.Tags (or something on that line), so looking for 'Parent probably won't find it. Perhaps you can find it by using the Ada 95 issues search engine (http://www.ada-auth.org/search-ais.html) or the overall Ada-auth.org search engine (http://www.ada-auth.org/search.html); I didn't try because I found 225 AI pages that contain some form of "parent" and 2015 pages on Ada-auth.org that contain such a form. *************************************************************** From: Randy Brukardt Date: Wednesday, November 10, 2010 4:01 PM ... > My memory was that the discussion was in terms of a Parent_Tag > operation for Ada.Tags (or something on that > line) ... Silly me! We actually added Parent_Tag to Ada for Ada 2005. When I searched for it, the first thing that turned up was the RM. But the AI in question does not include any of the e-mail on the topic. Note that Parent_Tag purposely ignores privacy. That's OK as it is a dynamic semantics thing and there is no such thing as privacy at runtime. 'Parent could not do that as a static semantics thingy. *************************************************************** From: Christoph Grein Date: Thursday, November 11, 2010 7:56 AM I remember a discussion about 'Parent to be used for traversing the derivation chain to find the youngest common ancestor of two objects. Problems with this were privacy breaking and that this ancestor might be abstract. So the idea was dropped. *************************************************************** From: Emmanuel Briot Date: Thursday, November 11, 2010 5:45 AM > Silly me! We actually added Parent_Tag to Ada for Ada 2005. When I > searched for it, the first thing that turned up was the RM. That seems interesting, but not exactly what Per was talking about. From the tag, we can't cast to the parent type, can we ? (I hope I am going to learn something new here!) Foo (Typ'Parent_Tag (Self)) does not work, but perhaps there is a similar syntax ? *************************************************************** From: Randy Brukardt Date: Thursday, November 11, 2010 1:07 PM > That seems interesting, but not exactly what Per was talking about. I agree; he is trying to solve a different problem. > From the tag, we can't cast to the parent type, can we ? (I hope I am > going to learn something new here!) > > Foo (Typ'Parent_Tag (Self)) > > does not work, but perhaps there is a similar syntax ? That was my original idea, but we never adopted it, adopting Generic_Dispatching_Constructor instead. The group was a lot more comfortable with adding the abstract formal subprogram and this magic generic. You could probably use Generic_Dispatching_Constructor to do this, but it would be very complex and would add overhead. Also note the problem mentioned by Christophe: the ancestor might be abstract. T'Parent would at least diagnose that at compile-time, while this fully dynamic scheme would have to raise an exception (which is again not what you want). Just to clarify: if T'Parent is abstract, calling Foo (T'Parent (Self)) might very well be illegal (Foo is likely to be an abstract operation). There would be no compile-time way to diagnose that when using Parent_Tag (Self'Tag). Foo (T'Parent'Class (Self)) is always legal, but of course would be infinite recursion if used in the intended manner. The important point here is that the proposed pattern breaks down when the parent type and inherited operation are abstract. That means that you couldn't use it generally, which is bad. Also note that T'Parent does not solve the other major part of calling the parent operation. In my experience, most of the errors in doing that (other than forgetting it completely) is in screwing up the parameter list. T'Parent does not help with that: procedure Bar (Obj : in Some_Tagged; X, Y : in Natural) is begin -- Do new stuff here. Bar (Some_Tagged'Parent, Y, X); -- Oops. end Bar; I had suggested a special syntax for this case in order to get around all of these problems (other than the one of omission of course), something like: Bar'Overridden (<>); Which would call the overridden Bar routine with the same parameter list as the original call, and would be a no-op if the overridden routine is abstract. Ada 2012 opens up another possibility, adding an aspect for this purpose, which would even eliminate most of the possibility of omission: with Call_Parent_Operation => At_End meaning that the parent operation would be called automatically with the appropriate parameter list if the body of the subprogram is reached normally (and nothing would happen if the parent operation is abstract, similarly to the way Initialize works in extension aggregates). We'd also allow: with Call_Parent_Operation => At_Start This would work great for procedures (like Finalize and Adjust where this usually critical to do), but it wouldn't work as well for functions (what to do with the result??). More thought is needed there. Anyway, it's obviously too late to solve this problem for Ada 2012, and it is clear that we need to brainstorm possible solutions. Simple solutions are pretty limited and only solve part of the problem. ***************************************************************