Version 1.1 of acs/ac-00177.txt

Unformatted version of acs/ac-00177.txt version 1.1
Other versions for file acs/ac-00177.txt

!standard 12.5.1(17/2)          09-06-08 AC95-00177/01
!class confirmation 09-06-08
!status received no action 09-06-08
!status received 09-05-14
!subject Expanded_Name when inside of a loop
!summary
!appendix

From: Randy Brukardt
Date: Thursday, May 14, 2009  8:54 PM

Here's a question worthy of Adam! :-)

Consider:

    with Ada.Tags, Ada.Text_IO;
    procedure Something is
    begin
        loop
           My_Block : declare
               type My_Tagged_Type is tagged null record;
           begin
               Ada.Text_IO.Put_Line (Ada.Tags.Expanded_Name (My_Tagged_Type'Tag));
               exit;
           end;
        end loop;
    end Something;

What does this program print? Function Expanded_Name returns the "fully expanded
name of the first subtype of the specific type identified by the tag".

It appears me that such a name cannot be constructed in this case. Loops and
blocks are both considered declarative regions by 8.1. Thus the name
Something.My_Block.My_Tagged_Type is not legal: My_Block is not declared in the
immediately enclosing declarative region of Something (4.1.3(12)), because the
anonymous loop is the immediately enclosing declarative region of My_Block. Thus
I do not believe that a "fully expanded name" can be written in this case.

For anonymous blocks, we have in 3.9(10): "The result is implementation defined
if the type is declared within an unnamed block statement." But of course the
block in this example has a name, so this exclusion does not apply; it seems
like it should.

Of course, the odds of this construct appearing in any real program is about
zero to any level of accuracy that you want to apply. I suppose that moves this
one from Adam-worthy all the way to positively Bairdian. :-)

To satisfy your curiosity as to the source of this wonder, Jean-Pierre Rosen had
asked about the meaning of expanded names in cases of anonymous constructs when
reviewing ASIS (which has a similar Expanded_Name function). I remembered this
function in Ada, so I went to the RM to lift the wording there for use in ASIS.
But Jean-Pierre had asked about "anonymous blocks and loops", and the RM wording
only mentioned blocks. I thought for a moment that that was because a type can't
be declared directly in a loop - but then I realized that of course a *block*
can be declared in a loop. Thus this flight of fancy...

I expect this to become an AI that will be a front running candidate for the
least important AI ever.

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

From: Bob Duff
Date: Friday, May 15, 2009  7:13 AM

Randy Brukardt wrote:

> Consider:
>
>     with Ada.Tags, Ada.Text_IO;
>     procedure Something is
>     begin
>         loop
>            My_Block : declare
>                type My_Tagged_Type is tagged null record;
>            begin
>                Ada.Text_IO.Put_Line (Ada.Tags.Expanded_Name
> (My_Tagged_Type'Tag));
>                exit;
>            end;
>         end loop;
>     end Something;
>
> What does this program print? Function Expanded_Name returns the
> "fully expanded name of the first subtype of the specific type
> identified by the tag".
>
> It appears me that such a name cannot be constructed in this case.
> Loops and blocks are both considered declarative regions by 8.1. Thus
> the name Something.My_Block.My_Tagged_Type is not legal: My_Block is
> not declared in the immediately enclosing declarative region of
> Something (4.1.3(12)), because the anonymous loop is the immediately
> enclosing declarative region of My_Block. Thus I do not believe that a
> "fully expanded name" can be written in this case.

I agree, but I'm not sure I follow your reasoning.  My_Block is declared
immediately within Something.  So Something.My_Block is OK as an expanded name.
My_Tagged_Type is not declared immediately within that, because of the
intervening loop.  Is that what you meant?

In other words, the exp name is conceptually something like:

    Something.My_Block.<thet-loop>.My_Tagged_Type

But we've got no name for that loop.

Here's another interesting tidbit from AARM-5.1:

    12.f  declare
              -- Label Foo is implicitly declared here.
          begin
              for Foo in ... loop
                  ...
                  <<Foo>> -- Illegal.
                  ...
              end loop;
          end;


    12.g  The label in this example is hidden from itself by the loop
          parameter with the same name; the example is illegal.
          ...

> I expect this to become an AI that will be a front running candidate
> for the least important AI ever.

There's stiff competition for that prize!  ;-)

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

From: Adam Beneschan
Date: Friday, May 15, 2009  11:27 AM

> Here's a question worthy of Adam! :-)

Well, how can I refuse an invitation like that?  :-)

> Consider:
>
>     with Ada.Tags, Ada.Text_IO;
>     procedure Something is
>     begin
>         loop
>            My_Block : declare
>                type My_Tagged_Type is tagged null record;
>            begin
>                Ada.Text_IO.Put_Line (Ada.Tags.Expanded_Name
> (My_Tagged_Type'Tag));
>                exit;
>            end;
>         end loop;
>     end Something;
>
> What does this program print?

It prints "Block name must be repeated after END", or something like that.
Well, technically, the compiler prints that, not the program. :-) But I'll
assume you meant to say "end My_Block;".

> Function Expanded_Name returns the "fully expanded name of the first
> subtype of the specific type identified by the tag".
>
> It appears me that such a name cannot be constructed in this case.
> Loops and blocks are both considered declarative regions by 8.1. Thus
> the name Something.My_Block.My_Tagged_Type is not legal: My_Block is
> not declared in the immediately enclosing declarative region of
> Something (4.1.3(12)), because the anonymous loop is the immediately
> enclosing declarative region of My_Block. Thus I do not believe that a
> "fully expanded name" can be written in this case.

I think you're right.  I've looked over the rules in 4.1.2(12-13) and 8.1(13),
and I don't see an exception for unnamed loops or other unnamed enclosing
constructs.  (By the way, I think everything we're saying about loops also
applies to extended return statements and exception handlers (8.1(2-6))).

Interestingly, though, I tried this with GNAT:

    with Ada.Tags, Ada.Text_IO;
    procedure Something is
    begin
        loop
           My_Block : declare
               type My_Tagged_Type is tagged null record;
               X : Something.My_Block.My_Tagged_Type;
           begin
               Ada.Text_IO.Put_Line (Ada.Tags.Expanded_Name
                                      (My_Tagged_Type'Tag));
               exit;
           end My_Block;
        end loop;
    end Something;

It accepted the declaration of X, even though it appears that this really
shouldn't be legal.  Perhaps even more interesting:

    with Ada.Tags, Ada.Text_IO;
    procedure Something is
    begin
        Named_Loop :
        loop
           My_Block : declare
               type My_Tagged_Type is tagged null record;
               Y : Something.My_Block.My_Tagged_Type;
               Z : Something.Named_Loop.My_Block.My_Tagged_Type;
           begin
               Ada.Text_IO.Put_Line (Ada.Tags.Expanded_Name
                                      (My_Tagged_Type'Tag));
               exit;
           end My_Block;
        end loop Named_Loop;
    end Something;

GNAT rejected the declaration of Z, but not of Y.  Not that any particular
compiler's behavior is conclusive proof of whether a program is legal or not
according to the standard, but it's certainly an interesting result.

I'm now wondering whether there is some ACATS test that requires this behavior,
that no one ever caught... I know there are some ACATS tests that do all sorts
of complex things with blocks inside loops, but I don't remember offhand if
attempting to use an expanded name is one of them.

> For anonymous blocks, we have in 3.9(10): "The result is
> implementation defined if the type is declared within an unnamed block
> statement." But of course the block in this example has a name, so
> this exclusion does not apply; it seems like it should.

If we assume that we're right about what expanded names are legal (i.e. Z is
legal in the above examples, but not X or Y), then perhaps 3.9(10) could be
changed to something like "The result is implementation defined if there is no
legal full expanded name for the first subtype at any point in the program".
That would deal not only with unnamed loops, but also with other constructs that
have declarative regions.  11.4.1(12) has the same issue.

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

From: Bob Duff
Date: Friday, May 15, 2009  12:00 PM
...
> I think you're right.  I've looked over the rules in 4.1.2(12-13) and
> 8.1(13), and I don't see an exception for unnamed loops or other
> unnamed enclosing constructs.  (By the way, I think everything we're
> saying about loops also applies to extended return statements and
> exception handlers (8.1(2-6))).

Yes, probably.

> Interestingly, though, I tried this with GNAT:
>
>     with Ada.Tags, Ada.Text_IO;
>     procedure Something is
>     begin
>         loop
>            My_Block : declare
>                type My_Tagged_Type is tagged null record;
>                X : Something.My_Block.My_Tagged_Type;
>            begin
>                Ada.Text_IO.Put_Line (Ada.Tags.Expanded_Name
>                                       (My_Tagged_Type'Tag));
>                exit;
>            end My_Block;
>         end loop;
>     end Something;
>
> It accepted the declaration of X, even though it appears that this
> really shouldn't be legal.

It is legal, as I said in my previous message (which you probably haven't seen
yet, because I evilly cc'ed ada-comment, and Randy's mailer doesn't like that --
sorry about that Randy).

See AARM-5.1, especially the weird examples.  My_Block is implicitly declared
immediately within Something, not within the anonymous loop.

>...Perhaps even more interesting:
>
>     with Ada.Tags, Ada.Text_IO;
>     procedure Something is
>     begin
>         Named_Loop :
>         loop
>            My_Block : declare
>                type My_Tagged_Type is tagged null record;
>                Y : Something.My_Block.My_Tagged_Type;
>                Z : Something.Named_Loop.My_Block.My_Tagged_Type;
>            begin
>                Ada.Text_IO.Put_Line (Ada.Tags.Expanded_Name
>                                       (My_Tagged_Type'Tag));
>                exit;
>            end My_Block;
>         end loop Named_Loop;
>     end Something;
>
> GNAT rejected the declaration of Z, but not of Y.

Again, GNAT is correct here.  (Surprising, eh?)

...
> If we assume that we're right about what expanded names are legal
> (i.e. Z is legal in the above examples, but not X or Y), then perhaps
> 3.9(10) could be changed to something like "The result is
> implementation defined if there is no legal full expanded name for the
> first subtype at any point in the program".  That would deal not only
> with unnamed loops, but also with other constructs that have
> declarative regions.

Well, that wording would be pretty mysterious to non-language-lawyers!

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

From: Adam Beneschan
Date: Friday, May 15, 2009  12:29 PM

> > It accepted the declaration of X, even though it appears that this
> > really shouldn't be legal.
>
> It is legal, as I said in my previous message (which you probably
> haven't seen yet, because I evilly cc'ed ada-comment, and Randy's
> mailer doesn't like that -- sorry about that Randy).
>
> See AARM-5.1, especially the weird examples.  My_Block is implicitly
> declared immediately within Something, not within the anonymous loop.

OK, I see.  That's the kind of thing I was trying to find, but I was searching
for the wrong phrase and couldn't get to it.  I think Randy and I made the same
mistake of assuming that if a block appears in a certain declarative region, the
*declaration* of that block (or more specifically the declaration of the name of
the block) appeared in that same spot, but it looks like that isn't the case.
Thanks for the pointer.

Based on this, I don't think there's anything missing in the wording of 3.9(10)
or 11.4.1(12); the only cases where there is no legal full expanded name are
when an identifier is declared somewhere inside an anonymous block.

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

From: Bob Duff
Date: Friday, May 15, 2009  12:39 PM

> OK, I see.  That's the kind of thing I was trying to find, but I was
> searching for the wrong phrase and couldn't get to it.  I think Randy
> and I made the same mistake of assuming that if a block appears in a
> certain declarative region, the *declaration* of that block (or more
> specifically the declaration of the name of the block) appeared in
> that same spot, ...

That would make intuitive sense.  I'll bet the original author of the Ada 83
wording would be surprised by these little oddities.

>...but it looks like that isn't the case.  Thanks for the  pointer.
>
> Based on this, I don't think there's anything missing in the wording
> of 3.9(10) or 11.4.1(12); the only cases where there is no legal full
> expanded name are when an identifier is declared somewhere inside an
> anonymous block.

Ah, OK.  Even though I quoted the right para, I had thought there was indeed a
problem.  I guess not.  Thanks.

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

From: Gary Barnes
Date: Friday, May 15, 2009  11:29 AM

Rational's compiler has names for everything (actually this stems from the needs
of the debugger and other tools).  Our ASIS version uses those names for things
like this.  They are not legal Ada-syntax names but then again they are for
human and tool consumption and not for compiler consumption, the compiler
doesn't need them.  For this example we print,

        SOMETHING.2S.MY_TAGGED_TYPE

The 2S essentially means "2 statements into".  The first encountered statement
being the loop, the 2nd being the declare block.  Note that it is counting
sequentially through the text and not paying attention to things like statement
nesting.  Mr. Baird can fill you in with all of the gory details if you find
them interesting.  There can be things like "5D" (declaration counting) and
"XXX'Body" and all sorts of other things to cover all of the corner cases.  He
was in on the design of the whole thing years ago.  It isn't always "pretty" but
it is always unambiguous.

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

From: Christoph Grein
Date: Sunday, May 17, 2009  11:52 AM

> In other words, the exp name is conceptually something like:
>
>    Something.My_Block.<thet-loop>.My_Tagged_Type

No, it should be (the loop is around the block, not inside)

Something.<anon_loop>.My_Block.My_Tagged_Type

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

From: Ed Schonberg
Date: Tuesday, May 19, 2009  3:03 PM

No, as Bob remarked, the implicit declaration of My_Block is (at the  end of)
the declarative part of the enclosing body (see 5.1 (12)).   The first use of
the block identifier is inside the loop, but this is not the point of
declaration.

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

From: Adam Beneschan
Date: Tuesday, May 19, 2009  3:26 PM

Right, but aside from the fact that I don't know what a "thet" is, I don't see
what Bob was getting at, since there is no loop declared inside My_Block; even
putting the My_Block declaration where it is implicitly declared, in the
declarative part of Something, doesn't cause the loop to be moved inside
My_Block.  So I don't see what Bob intended here.

Actually, looking back at Bob's message, I think he erred.  He said
"My_Tagged_Type is not declared immediately within [Something.My_Block], because
of the intervening loop."  But the loop isn't intervening.  So I think this part
was wrong.  Later, after I tried it with GNAT and found that
Something.My_Block.My_Tagged_Type was accepted, Bob pointed out---correctly, I
think---that this *is* a legal expanded name, which it could be only if
My_Tagged_Type *were* declared immediately within My_Block.

So there's a little bit of confusion here.  However, I've gone back to what I
learned in my thet theory classes from college, so that I now remember that a
thet is a collection of thtuff.  Or thomething like that.  :-)

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

From: Randy Brukardt
Date: Tuesday, May 19, 2009  3:44 PM

> So there's a little bit of confusion here.  However, I've gone back to
> what I learned in my thet theory classes from college, so that I now
> remember that a thet is a collection of thtuff.  Or thomething like
> that.  :-)

Sounds like you had to use the same implementation of MicroPlanner that I did in
college! It was built on top of a lisp system, and to differentiate they started
*everything* with "th". They even had version of the lisp operations "thcons",
"thcdr", "thcar". It didn't take long before *everything* started with "th":
"Let's thdrive over to thunion for thbeer on thterrance!" :-) Indeed, I'm still
more likely to call the Lisp operation "thcons"! I'm sure there was a "thet" or
"thset" in there somewhere, too.

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

From: Adam Beneschan
Date: Tuesday, May 19, 2009  3:59 PM

They didn't call it "Lithp"?  I would've.

No, I didn't actually use that MicroPlanner version.  But I used to watch a lot
of Looney Tunes cartoons, many of them featuring Sylvester the Cat.  Just in
case anyone was wondering why some of my Ada-Comment submissions are a bit
looney-tunes........

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

From: Bob Duff
Date: Tuesday, May 19, 2009  2:53 PM

> > In other words, the exp name is conceptually something like:
> >
> >    Something.My_Block.<thet-loop>.My_Tagged_Type
>
> No, it should be (the loop is around the block, not inside)
>
> Something.<anon_loop>.My_Block.My_Tagged_Type

That would make sense, but it's not what the language rules say.

Here's the original example:

    with Ada.Tags, Ada.Text_IO;
    procedure Something is
    begin
        loop
           My_Block : declare
               type My_Tagged_Type is tagged null record;
           begin
               Ada.Text_IO.Put_Line (Ada.Tags.Expanded_Name (My_Tagged_Type'Tag));
               exit;
           end;
        end loop;
    end Something;

And here's the rule in RM-5.1:

12    For each statement_identifier, there is an implicit declaration (with the
specified identifier) at the end of the declarative_part of the innermost
block_statement or body that encloses the statement_identifier. ...

So My_Block is not declared within the anonymous loop -- it is implicitly
declared immediately within Something (which is the "innermost block_stm or
body...").

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

From: Bob Duff
Date: Tuesday, May 19, 2009  4:06 PM

> > No, as Bob remarked, the implicit declaration of My_Block is (at the
> > end of) the declarative part of the enclosing body (see 5.1 (12)).
> > The first use of the block identifier is inside the loop, but this
> > is not the point of declaration.
>
> Right, but aside from the fact that I don't know what a "thet" is,

Sorry.  In case you haven't figured it out yet:  I meant "that loop". And I
didn't see that typo in all the quotings, until just now when you pointed it
out.  ;-)

>...I
> don't see what Bob was getting at, since there is no loop declared
>inside My_Block; even putting the My_Block declaration where it is
>implicitly declared, in the declarative part of Something, doesn't
>cause the loop to be moved inside My_Block.  So I don't see what Bob
>intended here.
>
> Actually, looking back at Bob's message, I think he erred.

Yes, think you're right.

The one part I got right is that My_Block is immediately declared in Something,
not inside the anonymous loop.  And that has some surprising consequences.

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


Questions? Ask the ACAA Technical Agent