Version 1.9 of ais/ai-00294.txt

Unformatted version of ais/ai-00294.txt version 1.9
Other versions for file ais/ai-00294.txt

!standard 3.9.3 (09)          04-04-22 AI95-00294/04
!class ramification 03-05-23
!status WG9 approved 04-11-18
!status ARG Approved 8-0-1 04-06-17
!status work item 02-05-16
!status received 02-05-13
!qualifier Clarification
!priority Low
!difficulty Medium
!subject Instantiating with abstract operations
!summary
It is illegal to instantiate a generic which has an abstract formal derived type parameter that inherits a concrete operation with a type that provides an abstract version of the concrete operation.
!question
Consider the following example:
procedure Foo is package P1 is type T1 is abstract tagged null record; procedure P (X : T1); end P1;
package body P1 is procedure P (X : T1) is
begin Text_Io.Put_Line ("P1.P called");
end P; end P1;
generic type D is abstract new P1.T1 with private; procedure G (X : D);
procedure G (X : D) is begin
P (X); end G;
package P2 is type T2 is abstract new P1.T1 with null record; procedure P (X : T2) is abstract; end P2;
procedure I is new G (P2.T2);
package P3 is type T3 is new P2.T2 with null record; procedure P (X : T3); end P3;
package body P3 is procedure P (X : T3) is
begin Text_Io.Put_Line ("P3.P called");
end P; end P3;
begin declare X : P3.T3; begin I (P2.T2 (X)); end; end Foo;
The test passes the check of 3.9.3(9), sentence 2:
If a generic formal type is abstract, then for each primitive subprogram of the formal that is not abstract, the corresponding primitive subprogram of the actual shall not be abstract.
because the corresponding subprogram in this case is not itself abstract (although it is overridden by an abstract subprogram).
Thus, the test is not rejected at compile time.
What happens at runtime when Foo.I is called? It appears that the abstract body will be called.
!response
3.9.3(9) indeed covers this case. We are not in an instance of the generic at the point of the instantiation, so 12.5.1(21/1) does not apply. Moreover, the standard uses 'corresponding' in its English sense (it is never defined as a technical term anywhere in the standard). Thus, the instantiation is illegal.
This is as it should be. The fact that the operation P is not abstract is part of the contract of the generic unit. As always in Ada, an instantiation that does not meet its contract is rejected. This is true even if P is not called in the body of the generic. We don't allow instantiating a generic with an integer type parameter with Boolean as long as "+" and the other mathematics operators aren't called, so this case should not be any different.
In order to clarify the intent, we add an AARM note.
!wording
Add the following AARM note after 3.9.3(9):
To Be Honest
In the sentence about primitive subprograms above, there is some ambiguity as to what is meant by "corresponding" in the case where an inherited operation is overridden. This is best explained by an example, where the implicit declarations are shown as comments:
package P1 is type T1 is abstract tagged null record; procedure P (X : T1); -- (1) end P1;
package P2 is type T2 is abstract new P1.T1 with null record; -- procedure P (X : T2); -- (2) procedure P (X : T2) is abstract; -- (3) end P2;
generic type D is abstract new P1.T1 with private; -- procedure P (X : D); -- (4) procedure G (X : D);
...
procedure I is new G (P2.T2);
Type T2 inherits a non-abstract procedure P (2) from the primitive procedure P (1) of T1. P (2) is overridden by the explicitly declared abstract procedure P (3). Type D inherits a non-abstract procedure P (4) from P (1). In instantiation I, the operation corresponding to P (4) is the one which is not overridden, i.e., P (3): the overridden operation P (2) does not "reemerge". Therefore, the instantiation is illegal.
!ACATS test
A B-Test could be created for this case, but I don't know how valuable it would be.
!appendix

From: Steve Baird
Sent: Monday, May 13, 2002  5:35 PM

Consider the following example:

  procedure Foo is
    package P1 is
	type T1 is abstract tagged null record;
	procedure P (X : T1);
    end P1;
    package body P1 is
	procedure P (X : T1) is
	begin
	    Text_Io.Put_Line ("P1.P called");
	end P;
    end P1;

    generic
	type D is abstract new P1.T1 with private;
    procedure G (X : D);
    procedure G (X : D) is
    begin
	P (X);
    end G;

    package P2 is
	type T2 is abstract new P1.T1 with null record;
	procedure P (X : T2) is abstract;
    end P2;

    procedure I is new G (P2.T2);

    package P3 is
	type T3 is new P2.T2 with null record;
	procedure P (X : T3);
    end P3;
    package body P3 is
	procedure P (X : T3) is
	begin
	    Text_Io.Put_Line ("P3.P called");
	end P;
    end P3;

  begin
    declare
	X : P3.T3;
    begin
	I (P2.T2 (X));
    end;
  end Foo;

The test passes the check of 3.9.3(9), sentence 2:

   If a generic formal type is abstract, then
   for each primitive subprogram of the formal that
   is not abstract, the corresponding primitive subprogram
   of the actual shall not be abstract.

because the corresponding subprogram in this case is
not itself abstract (although it is overridden by an
abstract subprogram).

Thus, the test is not rejected at compile time.

What happens at runtime when Foo.I is called?

12.5.1(21/1) states that " ... if the tag in the call is statically
determined to be that of the formal type, the body executed will be
that corresponding to the actual type".

The wording here might seem odd, but the meaning is clear: the body
executed will be that of the corresponding subprogram of the actual type.

By 3.9.2(20),

   The body for an implicitly declared operation that is overridden
   is the body for the overriding subprogram.

, this is the "body" of the explicitly declared abstract subprogram P2.P.

In the case where an abstract subprogram overrides a non-abstract
subprogram, perhaps the body of the overrider should be defined to
be that of the overridden? Or perhaps Program_Error should be raised
in this scenario?

This is another case where the "assume the worst in a generic body"
approach would be too restrictive. Conservatively rejecting the
call to P in the body of G would not be good.

Again, I do not see an obvious solution.

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

From: Christoph Grein
Sent: Tuesday, May 14, 2002  3:36 AM

>   procedure Foo is
>     package P1 is
> 	type T1 is abstract tagged null record;
> 	procedure P (X : T1);
>     end P1;
>     package body P1 is
> 	procedure P (X : T1) is
> 	begin
> 	    Text_Io.Put_Line ("P1.P called");
> 	end P;
>     end P1;
>
>     generic
> 	type D is abstract new P1.T1 with private;

        -- The primitive formal P (X : D) is not abstract here

>     procedure G (X : D);
>     procedure G (X : D) is
>     begin
> 	P (X);
>     end G;
>
>     package P2 is
> 	type T2 is abstract new P1.T1 with null record;
> 	procedure P (X : T2) is abstract;
>     end P2;
>
>     procedure I is new G (P2.T2);

      -- The primitive actual P (X : T2) is abstract here

>
>...
>
> The test passes the check of 3.9.3(9), sentence 2:
>
>    If a generic formal type [D] is abstract, then
>    for each primitive subprogram of the formal that
>    is not abstract [P (X: D)], the corresponding primitive subprogram
>    [P2.P(X:T2)] of the actual [P2.T2] shall not be abstract.

[insertions by me]

>
> because the corresponding subprogram in this case is
> not itself abstract (although it is overridden by an
> abstract subprogram).
>

Thus, for me the instantiation clearly violates 3.9.3(9).
Not being a language lawyer, I do not see why this should compile and be legal.

When I is called, the abstract subprogram P2.P(X:T2) should be called, which
does not have a body!

I'm confused...

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

From: Pascal Leroy
Sent: Tuesday, May 14, 2002  3:53 AM

No, you are misinterpreting the word "corresponding" here.  The second sentence
of RM95 12.5.1(21) states that "in an instance, the copy of such an implicit
declaration declares a view of the corresponding primitive subprogram of the
ancestor, even if this primitive has been overridden for the actual type."  So
the "corresponding primitive subprogram" in RM95 3.9.3(9) is the one that has
been overridden (and is not abstract), not the overrider (which is abstract).

In other words the instance knows about the original (non-abstract, overridden)
subprogram, but not about the new one (overrider, abstract).

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

From: Tucker Taft
Sent: Tuesday, May 14, 2002  2:33 PM

Huh???

We aren't in an instance at the point of the instantiation.  3.9.3(9) is
stating a rule that governs whether the instantiation is legal, and in
this case, the instantiation is clearly illegal, because the primitive
"P" is non-abstract for the formal type "D" and is abstract for the actual
type "P2.T2."

Perhaps the wording is somehow confusing, but I don't know what sort
of clarification would help because it is crystal clear to me!

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

From: Pascal Leroy
Sent: Tuesday, May 14, 2002  4:04 PM

It may be crystal-clear to you, but it is certainly not crystal-clear to me,
and as a matter of fact it's not what our compiler implements (there may be
a causal relationship here).

3.9.3(9) uses the word "corresponding", but it doesn't define it.  The
closest thing to a definition of "corresponding" that can be found in the RM
is 12.5.1(21), which precisely says that "corresponding" means "even if it
has been overridden".  Using "corresponding" without defining it is lousy
wording at its best.

And yes, I realize that we are not in the instance when we are checking the
legality of the instantiation, but that's irrelevant.

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

From: Tucker Taft
Sent: Tuesday, May 14, 2002  5:07 PM

"Corresponding" is used in section 3.4 in several places. It is also used in
6.3.1(13.1/1), and in fact it is used all over the manual, to mean the
"obvious" thing (I thought ;-).  In 12.5.1(21) we also *don't* define
"corresponding" but rather use it in defining which subprogram is copied.

In general, "corresponding" means with the same name (for components), or in
the same position (for discriminants or parameters), or with the same name and
"nearly" same profile (in the case of primitive subprograms).  In general, it
means "corresponding"! ;-).

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

From: Pascal Leroy
Sent: Wednesday, May 15, 2002  3:23 AM

Well, I am not going to take "Tuck said so" for an answer, and I am going to
ask the Rapporteur and the Editor to create an AI for this.

> In general, "corresponding" means with the same name (for components), or in
> the same position (for discriminants or parameters), or with the same name
> and "nearly" same profile (in the case of primitive subprograms). In
> general, it means "corresponding"! ;-).

I am sure that you realize that there is a lot of hand waving in "same name and
nearly same profile", especially as both the overridden subprogram and the
overrider qualify. So much hand waving that I can feel the wind from across the
ocean :->

> It seems relevant, because 12.5.1(21) is talking about what gets copied in
> an instance, and here we are deciding whether an instantiation is legal.

But then I am confused by the purpose of 3.9.3(9). It is clear from 12.5.1(21)
and AARM 12.5.1(21.a) that in the instance the name of the primitive subprogram
refers to the overridden one (among other things, you can tell the difference
based on the default parameters). So we have a perfectly good, non-abstract
subprogram to call. Why is it that we are disallowing the instantiation because
the actual happens to have an abstract subprogram, that is never going to be
referenced by the instantiation?

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

From: Tucker Taft
Sent: Wednesday, May 15, 2002  9:06 AM

> Well, I am not going to take "Tuck said so" for an answer, and I am going
> to ask the Rapporteur and the Editor to create an AI for this.

Fair enough!

> But then I am confused by the purpose of 3.9.3(9).  It is clear from
> 12.5.1(21) and AARM 12.5.1(21.a) that in the instance the name of the
> primitive subprogram refers to the overridden one (among other things, you
> can tell the difference based on the default parameters). So we have a
> perfectly good, non-abstract subprogram to call. Why is it that we are
> disallowing the instantiation because the actual happens to have an abstract
> subprogram, that is never going to be referenced by the instantiation?

It is true that it uses the formal parameter names and defaults from the
ancestor primitive (since that is all that it knows at generic-compile-time),
but it still invokes the body of the actual's primitive at run-time (see the
last sentence of 12.5.1(21/1)). So it would be bad news if this were abstract.

This is analagous to what happens when a primitive is overridden in the
private part of a package. The callers use the formal parameter names
and defaults of the inherited subprogram, but at run-time the overriding
body is invoked (see 3.9.2(20) second to last sentence).

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

From: Christoph Grein
Sent: Wednesday, May 15, 2002  11:33 PM

From: Tucker Taft <stt@avercom.net>

> It is true that it uses the formal parameter names and defaults from the
> ancestor primitive (since that is all that it knows at generic-compile-time),
> but it still invokes the body of the actual's primitive at run-time (see the
> last sentence of 12.5.1(21/1)).  So it would be bad news if this were
> abstract.

This was also my interpretation. It seems obvious to non-language lawyers.
[In Robert's wording: I do not see how you could think otherwise. :-]

> This is analagous to what happens when a primitive is overridden in the
> private part of a package.  The callers use the formal parameter names
> and defaults of the inherited subprogram, but at run-time the overriding
> body is invoked (see 3.9.2(20) second to last sentence).

package P0 is

  type T0 is tagged null record;
  procedure Op (X: T0);

end P0;

with P0;

package P1 is

  type T1 is new P0.T0 with null record;

private

  procedure Op (Y: T1);  -- overrides invisibly with new parameter name

end P0;

Here P1.Op, when called with named association, has to use Y where the private
part is visible, X where it is invisible, but both times the same overriding
procedure is called.

[Gnat 3.13p had problems with this.]

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

From: Randy Brukardt
Sent: Thursday, May 16, 2002  10:19 PM

> Well, I am not going to take "Tuck said so" for an answer, and I am going
> to ask the Rapporteur and the Editor to create an AI for this.

Will you take Randy said so instead? :-)

Here is the AI you requested (now AI-294). I have written it up as a
confirmation, following Robert's rule as Christophe reminded us. In this case,
because other interpretations of the paragraph lead to nonsense, and I think
that trying to define "corresponding" here formally probably will introduce a
lot more problems that it will fix.

Anyway, here's the AI:

(* Omitted. This was version /01. *)

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

From: Christoph Grein
Sent: Friday, May 17, 2002  2:13 AM

Just a wording improvement proposal.

> summary
>
> It is illegal to instantiate a generic with an abstract formal derived type
                                         ~~~~ which has
> parameter that inherits a concrete operation with a type that provides an
> abstract version of the concrete operation.

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

From: Steven W. Baird
Sent: Wednesday, May  7, 2003  3:55 PM

3.9.3(9), sentence 2, says:
   If a generic formal type is abstract, then
   for each primitive subprogram of the formal that
   is not abstract, the corresponding primitive subprogram
   of the actual shall not be abstract.

AI-294 makes the point that some kind of wording change is needed
to make it clear that the "corresponding" subprogram in question
is not the same as the "corresponding" subprogram of 3.4(17).

I believe that it would suffice to add the word "nonoverridden"
(possibly in parens) immediately after the word "corresponding".

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

!topic AI-228 and generics
!reference AI95-00228; RM95 3.9.3(6), 12.5.1(21)
!from Adam Beneschan 05-01-03
!discussion

    package Pak1 is
       type T1 is abstract tagged null record;
       function F2 return T1 is abstract;
       generic
          type T2 is new T1 with private;
       package Pak2 is
          X : T2 := F2;
       end Pak2;
    end Pak1;

    with Pak1;
    package Pak3 is
       type T3 is new Pak1.T1 with null record;
       function F2 return T3;
       package New_Pak2 is new Pak1.Pak2 (T3);
    end Pak3;

When the generic formal derived type T2 is declared, an inherited
subprogram F2 is also implicitly declared immediately after the
declaration of T2.  According to 3.9.3(6), this is a subprogram that
"shall be overridden" with a nonabstract subprogram; but that since T2
is a generic formal type, the nonabstract subprogram will "necessarily
be provided by the actual type".

The declaration of X contains an initial expression that includes a
call to the implicitly declared F2, which is not a dispatching call.
As I understand AI-228, though, since this implicitly declared F2 is a
"shall be overridden" function, the restrictions on abstract function
calls don't apply to it, and in particular the rule in 3.9.3(7)
("nondispatching calls to an abstract subprogram are not allowed").

Correct so far?

OK, now we later instantiate Pak2.  Here, we've declared a nonabstract
derived type T3 and overridden the abstract F2 for it.  According to
12.5.1(21), the instance New_Pak2 contains a copy of the implicitly
declared F2, and "the copy of such an implicit declaration declares a
view of the corresponding primitive subprogram of the ancestor, even
if this primitive has been overridden for the actual type".  As I read
this rule, then, whenever the implicitly declared F2 is referenced in
the instance, the meaning of this reference is a view of the abstract
"function F2 return T1" declared in Pak1, even though the dynamic
semantics are that the overriding subprogram ("function F2 return T3")
would be executed.  This would make it seem that the declaration of X
in the instance is illegal, since the initial expression contains a
nondispatching call to F2, and F2 is a view of the primitive
subprogram of the ancestor, which is *abstract*, and thus the rule in
3.9.3(7) is violated.  This interpretation seems wrong, since the
generic is accepted but cannot be legally instantiated.

So what's the story?  Did I miss something?  Is there an omission in
12.5.1(21)?  Or does AI-228 apply here to the instance and thus modify
the meaning of the quoted sentence in 12.5.1(21)?

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

From: Tucker Taft
Sent: Tuesday, January 4, 2005  8:00 AM

A "view" of something can be significantly different from
the original.  In particular, in this case, the view
is non-abstract, as implied by 3.9.3(6).  A similar
situation applies in the visible part when you have
a non-abstract private extension of an abstract ancestor.
The non-abstract implicitly declared inherited subprogram gets
its parameter names and defaults from the corresponding
subprogram of the ancestor type, even if it was abstract.
In general for dispatching operations, the spec can come
from one place, and the body from another.

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

From: Adam Beneschan
Sent: Tuesday, January 4, 2005  10:27 AM

I did think of that.  It's a somewhat confusing area of the language,
because there are some properties that are properties of views, and
some properties that are properties of the underlying "things"
themselves.  For example, the same type may be limited or nonlimited
depending on which view is currently in effect.  However, the RM hints
at the fact that limitedness is a property of a view, in 7.5(1): "A
limited type is (a view of) a type for which the assignment operation
is not allowed".  I looked for evidence that abstractness was a
property of a *view* as opposed to a property of the underlying
subprogram itself, and I couldn't find any such evidence in the RM.

Sorry, I'm not convinced.  I still think 12.5.1(21) needs some
clarification or rewording.

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

From: Randy Brukardt
Sent: Wednesday, January 19, 2005  6:11 PM

> So what's the story?  Did I miss something?  Is there an omission in
> 12.5.1(21)?  Or does AI-228 apply here to the instance and thus modify
> the meaning of the quoted sentence in 12.5.1(21)?

I don't agree with this analysis. We had this argument in AI-294 with Pascal
Leroy and Steve Baird, and they eventually decided that this somewhat vague
wording is the best that we can do. (Their problem was somewhat different,
but the conclusion is the same.) But there is no abstract operation here, so
there is no problem.

For type T3, the inherited F2 is a "shall-be-overridden" subprogram. The
inherited F2 is not abstract! It then is overridden with a new F2. That
means that a "view of the corresponding primitive function" is the inherited
F2. Which, as we just determined, is a "shall-be-overridden" subprogram, and
thus does not trigger any abstract subprogram checks.

Therefore, the wording in the standard is fine. Maybe an AARM note is in
order, but I have to wonder at the value of it.

Note that the AARM notes in 3.9.3 talked way too much about "abstract" in
this case, which has proven confusing even to the ARG. I improved them to
tone that down some (it's the "shall-be-overridden" case that is the most
common and usually the most important). I hope that will help in the future.

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

From: Adam Beneschan
Sent: Wednesday, January 19, 2005  7:06 PM

You're right that the *inherited* F2 is not abstract.  However, I'm
trying to read 12.5.1(21) carefully.  This says that in the instance
New_Pak2, the implicit declaration of F2 is copied, and the copy
"declares a view of the corresponding primitive subprogram of the
*ancestor*" (emphasis mine).  The ancestor in this case is T1, right?
(That's the ancestor type mentioned in the generic formal derived
type.  See 12.5.1(5).)  The "corresponding primitive subprogram of the
ancestor", to me, is therefore the subprogram F2 that is a primitive
subprogram of T1; that is, the F2 that was explicitly declared on the
line before the word "generic".  This is indisputably an abstract
function; it is *not* the implicitly inherited one, nor is it a
shall-be-overridden one.

It appears that nobody thinks this is what the intent is.  In AI-294,
Pascal said, "It is clear from 12.5.1(21) and AARM 12.5.1(21.a) that
in the instance the name of the primitive subprogram refers to the
overridden one".  But the "primitive subprogram of the ancestor" that
12.5.1(21) speaks of is, in this case, not overridden anywhere.  It
looks to me as if, instead of saying "a view of the corresponding
primitive subprogram of the ancestor", it should say something like "a
view of some subprogram that was implicitly inherited from the
primitive subprogram of the ancestor"---at least according to what
everyone thinks this clause means.  Of course, in terms of static
semantics, there aren't too many differences between the two
subprograms---the parameter names and defaults would be the same---BUT
it seems to me that some properties *are* different, including in
particular abstractness (which is True for the primitive subprogram of
the ancestor, and False for the implicitly inherited subprogram that
the clause is really intended to refer to).

(Please bear in mind that I have *not* argued about which subprogram
gets dispatched to at runtime; this is an issue of static semantics
only.)

Anyway, I hope this helps clarify exactly what the source of my
confusion is.  It still appears to me that 12.5.1(21) isn't quite
correct.

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

From: Randy Brukardt
Sent: Wednesday, January 19, 2005  7:54 PM

> You're right that the *inherited* F2 is not abstract.  However, I'm
> trying to read 12.5.1(21) carefully.

Don't do that! We agreed when we discussed AI-294 that it isn't as clear as
one would like, but every "fix" made it much worse. We essentially decided
to apply Dewar's rule to this paragraph: alternative interpretations are
silly, so there is no problem know what the rule means.

> This says that in the instance
> New_Pak2, the implicit declaration of F2 is copied, and the copy
> "declares a view of the corresponding primitive subprogram of the
> *ancestor*" (emphasis mine).  The ancestor in this case is T1, right?
> (That's the ancestor type mentioned in the generic formal derived
> type.  See 12.5.1(5).)  The "corresponding primitive subprogram of the
> ancestor", to me, is therefore the subprogram F2 that is a primitive
> subprogram of T1; that is, the F2 that was explicitly declared on the
> line before the word "generic".  This is indisputably an abstract
> function; it is *not* the implicitly inherited one, nor is it a
> shall-be-overridden one.

Sure, if you read this literally. But if you do that, you also get a
function with the profile:
    function F2 return T1 is abstract;
which is completely silly: it doesn't even have the right type. So you can't
get to a problem with this approach.

That's the whole argument in AI-294: what does corresponding mean here? It
has to mean the "inherited subprogram of the actual type that corresponds to
the primitive subprogram of the ancestor", because that is the only way to
even get the correct types for the operation (who cares about other
properties if the types are wrong?). Once you agree with that, then there is
no problem. (Note that the above wording wouldn't be enough to fix the
paragraph, because it wouldn't work for untagged types.)

> Anyway, I hope this helps clarify exactly what the source of my
> confusion is.

It does. Your derivation of the meaning ends up with an operation with the
wrong type(s), so that could not possibly be the meaning of the sentence in
question.

> It still appears to me that 12.5.1(21) isn't quite
> correct.

It's correct, just not as clear as it could be. And we previously discussed
that and decided not to change anything, because the cure was worse than the
disease. (Remember that this wording applies to untagged types, too, so
things can get really messy really fast if you're not careful.) Tucker and
Pascal spend several lunch hours trying to figure out improvements, and
decided not to change anything. Why would we want to revisit that? There's
no disagreement on the meaning.

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

From: Nick Roberts
Sent: Friday, January 21, 2005 12:11 PM

"Randy Brukardt" <randy@rrsoftware.com> wrote:

> > You're right that the *inherited* F2 is not abstract.  However, I'm
> > trying to read 12.5.1(21) carefully.
>
> Don't do that! We agreed when we discussed AI-294 that it isn't as clear
> as one would like, but every "fix" made it much worse. We essentially
> decided to apply Dewar's rule to this paragraph: alternative
> interpretations are silly, so there is no problem know what the rule
> means.

I'm not a huge fan of Dewar's rule. Where possible, it is better to have
rules that are both correct and clear, rather than just rules that are
correct (but require hours of deep analysis to fully understand). Obviously,
I understand that coming up with rules that are both correct and clear is a
challenge -- a monumental one, I guess -- especially for an amendment.

> ...
> > It still appears to me that 12.5.1(21) isn't quite correct.
>
> It's correct, just not as clear as it could be. And we previously
> discussed that and decided not to change anything, because the cure was
> worse than the disease. (Remember that this wording applies to untagged
> types, too, so things can get really messy really fast if you're not
> careful.) Tucker and Pascal spend several lunch hours trying to figure out
> improvements, and decided not to change anything. Why would we want to
> revisit that? There's no disagreement on the meaning.

Fair enough, and maybe some good AARM notes on the subject would be most
appropriate in this case.

Remember that some of us :-) are going to be writing a compiler using these
rules. Whilst the AARM notes are priceless in helping us do it, we are (or I
am, anyway) aiming at an implementation that is 100.000% compliant with the
standard, which means our decisions must ultimately be based on the standard
itself.

Frankly, some of these rules twist my brain. I would welcome any kind of
rationalisation, clariification, or simplification you can achieve (without
overly compromising your other goals). But I salute you (the ARG) for your
Herculean efforts.

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


Questions? Ask the ACAA Technical Agent