Version 1.2 of acs/ac-00208.txt

Unformatted version of acs/ac-00208.txt version 1.2
Other versions for file acs/ac-00208.txt

!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:
#
#          <routine-name>'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.

***************************************************************


Questions? Ask the ACAA Technical Agent