comp.lang.ada
 help / color / mirror / Atom feed
* AQ&S Guidance on pragma Elaborate_Body
@ 1997-04-18  0:00 JP Thornley
  1997-04-18  0:00 ` Robert A Duff
                   ` (2 more replies)
  0 siblings, 3 replies; 81+ messages in thread
From: JP Thornley @ 1997-04-18  0:00 UTC (permalink / raw)




In the rationale to Section 8.4.3, Coupling Due to Pragmas, the second 
paragraph says:-

"When there is a clear requirement for a recursive dependency, you 
should use pragma Elaborate_Body. This situation arises, for example, 
when you have a recursive dependency (i.e., package A's body depends on 
package B's specification and package B's body depends on package A's 
specification)."

The most obvious interpretation of this is that the pragma should appear 
in both packages - which will generate an error, probably at link/bind 
time.

So is there a meaningful message struggling to get out here?  [Perhaps 
"a clear requirement" can be replaced by "no requirement", so that a 
successful build confirms that no circular package depencies have been 
introduced unwittingly.]

[The suspicion of poor authoring/editing is reinforced by the rather 
strange wording where X is an example of X.]

Phil Thornley

-- 
------------------------------------------------------------------------
| JP Thornley    EMail jpt@diphi.demon.co.uk                           |
|                      phil.thornley@acm.org                           |
------------------------------------------------------------------------






^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-18  0:00 AQ&S Guidance on pragma Elaborate_Body JP Thornley
@ 1997-04-18  0:00 ` Robert A Duff
  1997-04-21  0:00   ` Michael F Brenner
  1997-04-18  0:00 ` Robert Dewar
  1997-04-20  0:00 ` Doug Smith
  2 siblings, 1 reply; 81+ messages in thread
From: Robert A Duff @ 1997-04-18  0:00 UTC (permalink / raw)



In article <528878564wnr@diphi.demon.co.uk>,
JP Thornley  <jpt@diphi.demon.co.uk> wrote:
>So is there a meaningful message struggling to get out here?  [Perhaps 
>"a clear requirement" can be replaced by "no requirement", so that a 
>successful build confirms that no circular package depencies have been 
>introduced unwittingly.]

I dunno.  My theory is to use the first pragma in the following list
that works:

    Pure
    Preelaborate
    Elaborate_Body
    Elaborate_All
    Elaborate

The first three make life easier, because they go on the package (rather
than on all clients), and they pretty much prevent access-before-elab
failures.

- Bob




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-18  0:00 AQ&S Guidance on pragma Elaborate_Body JP Thornley
  1997-04-18  0:00 ` Robert A Duff
@ 1997-04-18  0:00 ` Robert Dewar
  1997-04-19  0:00   ` Michael Paus
  1997-04-20  0:00 ` Doug Smith
  2 siblings, 1 reply; 81+ messages in thread
From: Robert Dewar @ 1997-04-18  0:00 UTC (permalink / raw)



JP Thornley asks

<<So is there a meaningful message struggling to get out here?  [Perhaps
"a clear requirement" can be replaced by "no requirement", so that a
successful build confirms that no circular package depencies have been
introduced unwittingly.]>>

I am not quite sure I can understand this, but the proper approach in
Ada 95 is

  make packages Pure if possible
else
  make packages Preelaborate if possible
else
  use pragma Elaborate_Body if possible
else
  use pragma Elaborate_All on clients if possible
else
  take a very careful hard look at your program -- it is suspicious!






^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-18  0:00 ` Robert Dewar
@ 1997-04-19  0:00   ` Michael Paus
  1997-04-19  0:00     ` Robert A Duff
                       ` (2 more replies)
  0 siblings, 3 replies; 81+ messages in thread
From: Michael Paus @ 1997-04-19  0:00 UTC (permalink / raw)



dewar@merv.cs.nyu.edu (Robert Dewar) wrote:
> I am not quite sure I can understand this, but the proper approach in
> Ada 95 is
> 
>   make packages Pure if possible
> else
>   make packages Preelaborate if possible
> else
>   use pragma Elaborate_Body if possible
> else
>   use pragma Elaborate_All on clients if possible
> else
>   take a very careful hard look at your program -- it is suspicious!


Hm ? If there is such a simple and strict rule on how to apply this
kind of pragmas, I wonder why the compiler does not do it automatically.
The compiler does check whether my pragma settings are correct. So it
seems to be quite straight forward for the compiler to automatically
insert the highest level of purity. Are there any undesirable side
effects when doing that or is the rule not as simple as you said ?

Just curious

Michael

-- 
------------------------------------------------------------------------
--Dr.-Ing. Michael Paus   (Member: Team Ada)
--University of Stuttgart, Inst. of Flight Mechanics and Flight Control
--Forststrasse 86, 70176 Stuttgart, Germany
--Phone: (+49) 711-121-1434  FAX: (+49) 711-634856
--Email: Michael.Paus@ifr.luftfahrt.uni-stuttgart.de (NeXT-Mail welcome)





^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-19  0:00   ` Michael Paus
@ 1997-04-19  0:00     ` Robert A Duff
  1997-04-21  0:00       ` Robert Dewar
  1997-04-20  0:00     ` Robert Dewar
  1997-04-21  0:00     ` Michael F Brenner
  2 siblings, 1 reply; 81+ messages in thread
From: Robert A Duff @ 1997-04-19  0:00 UTC (permalink / raw)



In article <5jabeq$3ltk@info4.rus.uni-stuttgart.de>,
Michael Paus <michael@ifr.luftfahrt.uni-stuttgart.de> wrote:
>Hm ? If there is such a simple and strict rule on how to apply this
>kind of pragmas, I wonder why the compiler does not do it automatically.
>The compiler does check whether my pragma settings are correct. So it
>seems to be quite straight forward for the compiler to automatically
>insert the highest level of purity. Are there any undesirable side
>effects when doing that or is the rule not as simple as you said ?

The compiler can't do it, because that would require knowing about a
package body when compiling the package spec (or clients of the package
spec).  You could do it automatically at link time, but not at compile
time (given Ada's compilation model).  By "it", I mean "insert Pure,
Preelaborate, or Elab_Body, as appropriate."  Elaborate_All and
Elaborate are somewhat more complicated to deal with.

If you're willing to live with some restrictions, and some complicated
(slow?) processing at link time, you could dispense with all
elaboration-control pragmas, and have the link phase determine an
elaboration order that's guaranteed to not raise Program_Error.  But
note that some of these pragmas (Pure, especially) have purposes other
than just elaboration order.

- Bob




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-18  0:00 AQ&S Guidance on pragma Elaborate_Body JP Thornley
  1997-04-18  0:00 ` Robert A Duff
  1997-04-18  0:00 ` Robert Dewar
@ 1997-04-20  0:00 ` Doug Smith
  1997-04-20  0:00   ` Robert Dewar
  2 siblings, 1 reply; 81+ messages in thread
From: Doug Smith @ 1997-04-20  0:00 UTC (permalink / raw)



In article <528878564wnr@diphi.demon.co.uk>, jpt@diphi.demon.co.uk wrote:

> In the rationale to Section 8.4.3, Coupling Due to Pragmas, the second 
> paragraph says:-
> 
> "When there is a clear requirement for a recursive dependency, you 
> should use pragma Elaborate_Body. This situation arises, for example, 
> when you have a recursive dependency (i.e., package A's body depends on 
> package B's specification and package B's body depends on package A's 
> specification)."
> 
> The most obvious interpretation of this is that the pragma should appear 
> in both packages - which will generate an error, probably at link/bind 
> time.
> 
[snip]
> Phil Thornley

This was added in the '95 guidelines and I think is bad advice. This is
in a section of the Quidelines for reusability, and was section 8.4.2 in
the '83 Guidelines which recommended against pragma Elaborate for
nongenerics.

The only guideline which survived was "Use pragma Elaborate for generics
named in a context clause." That could imply this paragraph was talking
only of generics; however, generics cannot be mutually dependent (although
instantiations can be mutually dependent in an indirect fashion).

Doug
<mailto:dsmith@clark.net>

p.s. I see a new section 8.4.1 which reverts to the "Consider using..."
     phrases I tried to remove when editing the last '83 version. Rats!




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-19  0:00   ` Michael Paus
  1997-04-19  0:00     ` Robert A Duff
@ 1997-04-20  0:00     ` Robert Dewar
  1997-04-21  0:00     ` Michael F Brenner
  2 siblings, 0 replies; 81+ messages in thread
From: Robert Dewar @ 1997-04-20  0:00 UTC (permalink / raw)



Michael Paus said

<<Hm ? If there is such a simple and strict rule on how to apply this
kind of pragmas, I wonder why the compiler does not do it automatically.
The compiler does check whether my pragma settings are correct. So it
seems to be quite straight forward for the compiler to automatically
insert the highest level of purity. Are there any undesirable side
effects when doing that or is the rule not as simple as you said ?

Just curious

Michael>>

Think carefuly here -- pragmas Pure and Preelaborate are applied to specs,
and determine legality of clients, but the conditoins that need checkiong
apply to bodies. Unless you want to create very peculiar dependenceis 
(basically a horrible dependence on all possible bodies), you do ONT
NOT want the compiler to do this automatically.

Furthermore, the viaiblity of Elaborate_Body cannot be checked till link
time.

That being said, the compiler can do FAR more to help here, and the
latest version of GNAT has some extremely useful additions in this
area, to be announced in detail later.





^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-20  0:00 ` Doug Smith
@ 1997-04-20  0:00   ` Robert Dewar
  1997-04-21  0:00     ` Matthew Heaney
  0 siblings, 1 reply; 81+ messages in thread
From: Robert Dewar @ 1997-04-20  0:00 UTC (permalink / raw)



Doug said

<<The only guideline which survived was "Use pragma Elaborate for generics
named in a context clause." That could imply this paragraph was talking
only of generics; however, generics cannot be mutually dependent (although
instantiations can be mutually dependent in an indirect fashion).>>

And this guideline is a poor one. You only need to use pragma Elaborate
for generics named in the context clause if you instantiate the generic
in your own elaboration code -- and furthermore, if you *do* such an
instantiation, use Elaborate_All, not Elaborate -- and of course this
only applies if the generic has a body!





^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-20  0:00   ` Robert Dewar
@ 1997-04-21  0:00     ` Matthew Heaney
  1997-04-21  0:00       ` Robert A Duff
  0 siblings, 1 reply; 81+ messages in thread
From: Matthew Heaney @ 1997-04-21  0:00 UTC (permalink / raw)




In article <dewar.861594771@merv>, dewar@merv.cs.nyu.edu (Robert Dewar) wrote:

><<The only guideline which survived was "Use pragma Elaborate for generics
>named in a context clause." That could imply this paragraph was talking
>only of generics; however, generics cannot be mutually dependent (although
>instantiations can be mutually dependent in an indirect fashion).>>
>
>And this guideline is a poor one. You only need to use pragma Elaborate
>for generics named in the context clause if you instantiate the generic
>in your own elaboration code -- and furthermore, if you *do* such an
>instantiation, use Elaborate_All, not Elaborate -- and of course this
>only applies if the generic has a body!

I don't understand.  What do you mean by elaboration code?  Is it defined
as the package body, or only the begin part of the package body, ie

with GQ;
package body P is

   package Q is new GQ (...);

end P;

or this

with GQ;
package body P is
begin
   declare
      package Q is new GQ (...);
   begin
      null;
   end;
end P;

Do either of these require pragma Elaborate (or Elaborate_All)?  (Assume GQ
does have a body.)

And while I'm on the subject of pragma Elaborate, the Ada 83 RM stated that
that pragma was only guarenteed to work when used on a predefined package
such as Text_IO.  Did this rule go away in Ada 95?  Can I use pragma
Elaborate freely, on user-defined library units, and have a guarentee that
it will do something?

Matt

--------------------------------------------------------------------
Matthew Heaney
Software Development Consultant
<mailto:matthew_heaney@acm.org>
(818) 985-1271




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-21  0:00     ` Matthew Heaney
@ 1997-04-21  0:00       ` Robert A Duff
  1997-04-21  0:00         ` Matthew Heaney
  1997-04-21  0:00         ` Robert Dewar
  0 siblings, 2 replies; 81+ messages in thread
From: Robert A Duff @ 1997-04-21  0:00 UTC (permalink / raw)



In article <mheaney-ya023680002104970117080001@news.ni.net>,
Matthew Heaney <mheaney@ni.net> wrote:
>In article <dewar.861594771@merv>, dewar@merv.cs.nyu.edu (Robert Dewar) wrote:
>>And this guideline is a poor one. You only need to use pragma Elaborate
>>for generics named in the context clause if you instantiate the generic
>>in your own elaboration code

...which is almost always the case, in my experience...

>... -- and furthermore, if you *do* such an
>>instantiation, use Elaborate_All, not Elaborate

Agreed.  Always use ELaborate_All instead of Elaborate, except when
mutual recursion forces you to use Elaborate.  (And, of course, use
Pure, Preelaborate, or Elaborate_Body in preference to either Elab or
Elab_All.)

>... -- and of course this
>>only applies if the generic has a body!

It's best to assume that the generic has a body.  The client shouldn't
have to care.

>I don't understand.  What do you mean by elaboration code?  Is it defined
>as the package body, or only the begin part of the package body, ie
>
>with GQ;
>package body P is
>
>   package Q is new GQ (...);
>
>end P;
>
>or this
>
>with GQ;
>package body P is
>begin
>   declare
>      package Q is new GQ (...);
>   begin
>      null;
>   end;
>end P;
>
>Do either of these require pragma Elaborate (or Elaborate_All)?  (Assume GQ
>does have a body.)

Both of them do, since the instantiation is elaborated during the
elaboration of P.  On the other hand, if P contained:

    procedure Foo is
        package Q is new GQ...

then you don't need the pragma.

>And while I'm on the subject of pragma Elaborate, the Ada 83 RM stated that
>that pragma was only guarenteed to work when used on a predefined package
>such as Text_IO.

That's a strange way to put it.  Pragma Elaborate, in Adas 83 and 95, is
not transitive, which is a pain, and which is why Elaborate_All was
invented.  It is true that Text_IO has to "work", despite the fact that
pragma Elaborate is not very helpful in making it work (if Text_IO's
body calls some other implementation-defined package that clients don't
know about).

>...  Did this rule go away in Ada 95?  Can I use pragma
>Elaborate freely, on user-defined library units, and have a guarentee that
>it will do something?

The semantics of Elaborate has not changed.  It will "do something" for
user-defined library units -- it's just that that something is rather
unhelpful.  (That is, if R calls something in Q.Foo during elaboration,
and Q.Foo calls somthing in P, then your abstraction is violated -- to
put in exactly the "right" pragma Elaborates, either Q needs to know
about its clients, or R needs to know about Q's implementation in terms
of P.  An Elaborate_All(Q) on R solves the problem, because it magically
applies to P without R knowing about P.)

- Bob




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-18  0:00 ` Robert A Duff
@ 1997-04-21  0:00   ` Michael F Brenner
  1997-04-22  0:00     ` Robert A Duff
  0 siblings, 1 reply; 81+ messages in thread
From: Michael F Brenner @ 1997-04-21  0:00 UTC (permalink / raw)



Bob said
    Pure
    Preelaborate
    Elaborate_Body
    Elaborate_All
    Elaborate
 > The first three make life easier, because they go on the package (rather
 > than on all clients), and they pretty much prevent access-before-elab
 > failures.

One more thing must be said: in reusing this software, the reuse itself
might have a circular dependency, which the compiler may or may not
be able to figure out. To reduce the amount of stuff that the compiler
has to worry about, and to make it possible to compute a SINGLE
elaboration order (without which the program may raise program_error
at will), you MUST add one of the first three to all packages you
think are NOT in a circular elaboration dependency loop. Doing this
also helps you identify your elaboration loops more clearly, so you
can deal with them using elaborate or elaborate_all or by removing
the regression testing code from the elaboration-time executable
statements at the bottom of the package. Failure to add these will
cause needless failures when they are reused INSIDE an elaboration
dependency loop. 

If a quality standard says they are optional, that quality standard
does not reflect the reality of Ada-95 software re-use.





^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-19  0:00   ` Michael Paus
  1997-04-19  0:00     ` Robert A Duff
  1997-04-20  0:00     ` Robert Dewar
@ 1997-04-21  0:00     ` Michael F Brenner
  1997-04-23  0:00       ` Robert Dewar
  2 siblings, 1 reply; 81+ messages in thread
From: Michael F Brenner @ 1997-04-21  0:00 UTC (permalink / raw)



Michael Paus asks
   > ... seems to be quite straight forward for the compiler to automatically
   > ... insert the highest level of purity. Are there any undesirable side
   > ... effects when doing that or is the rule not as simple as you said ?

You cannot modify the body of a PURE package to add in, for example, 
text_io, or any other non-pure package for debugging purposes at a later time,
without busting the purity of everything that withs the PURE package. You
also may not reuse a pure generic package in a way that introduces any memory,
because of the rule that the compiler may optimize away repeated calls
with the same arguments. Gnat in its current state (3.07 DOS) optimizes
pure packages that implement limited private data structures better than 
impure packages. ROMable code should be PURE.              

There text_io comment applies to preelaborate, since some debugging
packages you may wish to introduce will be non-preelaborable. Reentrant
code should be preelaborable, but the data section will not be PURE.

There are no disadvantages to marking elaborable packages as ELABORATE_BODY,
and they should be so marked for both documentation and for compiler hinting.

The goal should be that almost all of the non-thread-safe code should be
marked ELABORATE_BODY, and almost all of the thread-safe code should be
marked PREELABORATE or PURE.




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-21  0:00       ` Robert A Duff
@ 1997-04-21  0:00         ` Matthew Heaney
  1997-04-21  0:00           ` Robert A Duff
  1997-04-21  0:00           ` Matthew Heaney
  1997-04-21  0:00         ` Robert Dewar
  1 sibling, 2 replies; 81+ messages in thread
From: Matthew Heaney @ 1997-04-21  0:00 UTC (permalink / raw)



In article <E8znzn.DM2@world.std.com>, bobduff@world.std.com (Robert A
Duff) wrote:

>In article <mheaney-ya023680002104970117080001@news.ni.net>,
>Matthew Heaney <mheaney@ni.net> wrote:
>>In article <dewar.861594771@merv>, dewar@merv.cs.nyu.edu (Robert Dewar) wrote:
>>>And this guideline is a poor one. You only need to use pragma Elaborate
>>>for generics named in the context clause if you instantiate the generic
>>>in your own elaboration code
>
>...which is almost always the case, in my experience...
>
>>... -- and furthermore, if you *do* such an
>>>instantiation, use Elaborate_All, not Elaborate
>
>Agreed.  Always use ELaborate_All instead of Elaborate, except when
>mutual recursion forces you to use Elaborate.  (And, of course, use
>Pure, Preelaborate, or Elaborate_Body in preference to either Elab or
>Elab_All.)

OK, just so I understand this perfectly: If the generic package has used
one of the pragmas Pure, Preelaborate, or Elaborate_Body, does that mean I
the instantiator do not have to use pragma Elaborate_All?

generic
   ...
package GQ is
   pragma Pure;
...
end GQ;

with GQ;    <<<--- No pragma Elaborate_All required, right?
package P is
   package Q is new GQ (...);
end P;


Matt

--------------------------------------------------------------------
Matthew Heaney
Software Development Consultant
<mailto:matthew_heaney@acm.org>
(818) 985-1271




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-21  0:00         ` Matthew Heaney
@ 1997-04-21  0:00           ` Robert A Duff
  1997-04-21  0:00           ` Matthew Heaney
  1 sibling, 0 replies; 81+ messages in thread
From: Robert A Duff @ 1997-04-21  0:00 UTC (permalink / raw)



In article <mheaney-ya023680002104970942110001@news.ni.net>,
Matthew Heaney <mheaney@ni.net> wrote:
>OK, just so I understand this perfectly: If the generic package has used
>one of the pragmas Pure, Preelaborate, or Elaborate_Body, does that mean I
>the instantiator do not have to use pragma Elaborate_All?

Yes.

- Bob




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-21  0:00       ` Robert A Duff
  1997-04-21  0:00         ` Matthew Heaney
@ 1997-04-21  0:00         ` Robert Dewar
  1997-04-22  0:00           ` Robert A Duff
  1 sibling, 1 reply; 81+ messages in thread
From: Robert Dewar @ 1997-04-21  0:00 UTC (permalink / raw)



iRobert Duff said

<<...which is almost always the case, in my experience...>>


I don't think so at all, I often see generics instantiated in an
inner scope, there is absolutely no reason to consider this somehow
poor style -- on the contrary, it is better to instantiate the generic
as locally as possible -- the normal rule for declarations ...

<<<<It's best to assume that the generic has a body.  The client shouldn't
  have to care.>>
>>

I don't see any reason to assume that a generic has a body, when you can
tell from the spec that it is not allowed to have a body -- well at least
you can tell if there is no private part ...





^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-19  0:00     ` Robert A Duff
@ 1997-04-21  0:00       ` Robert Dewar
  1997-04-23  0:00         ` Robert A Duff
  0 siblings, 1 reply; 81+ messages in thread
From: Robert Dewar @ 1997-04-21  0:00 UTC (permalink / raw)



Robert Duff said

<<If you're willing to live with some restrictions, and some complicated
(slow?) processing at link time, you could dispense with all
elaboration-control pragmas, and have the link phase determine an
elaboration order that's guaranteed to not raise Program_Error.  But
note that some of these pragmas (Pure, especially) have purposes other
than just elaboration order.>>

No, that's quite wrong. There are many things that can place restrictions
on the order of elaboration.

Suppose we have a package Glorp that has several procedures including
Thunk, Boggle, and Glub. In the comments of package Glorp, we find the
comment:

-- WARNING: It is essential to call Thunk before calling Boggle. If you
-- fail to do this, all subsequent calls to Glub will raise the Glob-Glob
-- exception or otherwise malfunction. Clients of Glorp are responsible for
-- obeying this rule, since no check is made (a check would introduce too
-- much overhead).

Now, suppose we have two clients of Glorp, Jabber and Wocky. The elaboration
code of Jabber calls Thunk, and the elaboration code of Wocky calls Boggle.

Well now it is essential that Jabber is elaborated before Wocky, and no
static analysis of the program code can determine this, and a pragma
Elaborate is required.

And if you think this is just theoretical, think again, there are
instantiations of the names above in the SGI GNAT runtime library, and
when we installed some new clever elaboration stuff (a bit like Bob
proposes, but more effective, and easier to understand), the binder
chose a much better elaboration order, much more clearly guaranteed
to prevent Program_Error, but unfortunately wrong (of course this is
a bug in the runtime, there is a missing pragma Elaborate).

It is quite true that you can guarantee absence from Program_Error for a wide
variety of programs automatically, and version 3.10 of GNAT does that. BUT
it is far from true that this means that you could "dispense with all
elaboration-control pragmas".






^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-21  0:00         ` Matthew Heaney
  1997-04-21  0:00           ` Robert A Duff
@ 1997-04-21  0:00           ` Matthew Heaney
  1997-04-22  0:00             ` Robert A Duff
                               ` (2 more replies)
  1 sibling, 3 replies; 81+ messages in thread
From: Matthew Heaney @ 1997-04-21  0:00 UTC (permalink / raw)



In article <mheaney-ya023680002104970942110001@news.ni.net>, mheaney@ni.net
(Matthew Heaney) wrote:
>>
>>>... -- and furthermore, if you *do* such an
>>>>instantiation, use Elaborate_All, not Elaborate
>>
>>Agreed.  Always use ELaborate_All instead of Elaborate, except when
>>mutual recursion forces you to use Elaborate.  (And, of course, use
>>Pure, Preelaborate, or Elaborate_Body in preference to either Elab or
>>Elab_All.)

OK, one more question.  Why not just pragma Elaborate?  If I only
instantiate the generic in the package declarative region, and do not call
any of its functions during elaboration or initialization, then why pragma
Elaborate_All?  All I the instantiator require is the generic's body, not
the bodies of the packages it with's, so isn't Elaborate good enough?

--------------------------------------------------------------------
Matthew Heaney
Software Development Consultant
<mailto:matthew_heaney@acm.org>
(818) 985-1271




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-21  0:00           ` Matthew Heaney
@ 1997-04-22  0:00             ` Robert A Duff
  1997-04-22  0:00               ` Matthew Heaney
  1997-04-22  0:00             ` Mats Weber
  1997-04-23  0:00             ` Robert Dewar
  2 siblings, 1 reply; 81+ messages in thread
From: Robert A Duff @ 1997-04-22  0:00 UTC (permalink / raw)



In article <mheaney-ya023680002104972250240001@news.ni.net>,
Matthew Heaney <mheaney@ni.net> wrote:
>OK, one more question.  Why not just pragma Elaborate?  If I only
>instantiate the generic in the package declarative region, and do not call
>any of its functions during elaboration or initialization, then why pragma
>Elaborate_All?  All I the instantiator require is the generic's body, not
>the bodies of the packages it with's, so isn't Elaborate good enough?

You can't tell without looking at the body of that generic (which is the
root of this whole problem):

    generic
    package G1 is ... end G1;

    package body G1 is ... end G1;

    generic
    package G2 is ... end G2;

    with G1;
    package body G2 is
        package Inst_1 is new G1;
    end G2;

    with G2; pragma Elaborate(G2);
    package P is
        package Inst_2 is new G2;
    end P;

This will raise Program_Error.

- Bob




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-22  0:00             ` Robert A Duff
@ 1997-04-22  0:00               ` Matthew Heaney
  1997-04-22  0:00                 ` Robert A Duff
  1997-04-24  0:00                 ` Robert Dewar
  0 siblings, 2 replies; 81+ messages in thread
From: Matthew Heaney @ 1997-04-22  0:00 UTC (permalink / raw)



In article <E91Gty.4DI@world.std.com>, bobduff@world.std.com (Robert A
Duff) wrote:

>    generic
>    package G1 is ... end G1;
>
>    package body G1 is ... end G1;
>
>    generic
>    package G2 is ... end G2;
>
>    with G1;
>    package body G2 is
>        package Inst_1 is new G1;
>    end G2;
>
>    with G2; pragma Elaborate(G2);
>    package P is
>        package Inst_2 is new G2;
>    end P;
>
>This will raise Program_Error.

But isn't G2 supposed to elaborate G1?

with G1; 
pragma Elaborate (G1);   <<<---
package body G2 is
    package Inst_1 is new G1;
end G2;

Isn't G2 supposed to take care of it's own business, and make sure G1 is
elaborated?  This is analogous to P making sure G2 is elaborated.

Matt

--------------------------------------------------------------------
Matthew Heaney
Software Development Consultant
<mailto:matthew_heaney@acm.org>
(818) 985-1271




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-22  0:00               ` Matthew Heaney
@ 1997-04-22  0:00                 ` Robert A Duff
  1997-04-22  0:00                   ` Matthew Heaney
  1997-04-24  0:00                 ` Robert Dewar
  1 sibling, 1 reply; 81+ messages in thread
From: Robert A Duff @ 1997-04-22  0:00 UTC (permalink / raw)



(e-mailed and posted)

In article <mheaney-ya023680002204970735480001@news.ni.net>,
Matthew Heaney <mheaney@ni.net> wrote:
>In article <E91Gty.4DI@world.std.com>, bobduff@world.std.com (Robert A
>Duff) wrote:
>
>>    generic
>>    package G1 is ... end G1;
>>
>>    package body G1 is ... end G1;
>>
>>    generic
>>    package G2 is ... end G2;
>>
>>    with G1;
>>    package body G2 is
>>        package Inst_1 is new G1;
>>    end G2;
>>
>>    with G2; pragma Elaborate(G2);
>>    package P is
>>        package Inst_2 is new G2;
>>    end P;
>>
>>This will raise Program_Error.
>
>But isn't G2 supposed to elaborate G1?
>
>with G1; 
>pragma Elaborate (G1);   <<<---
>package body G2 is
>    package Inst_1 is new G1;
>end G2;

No, G2 does not instantiate G1 during its (G2's) elaboration.  In fact,
G2 doesn't do anything during elaboration, except to record the fact
that it has now been elaborated.  In the above example, the following
elaboration order does not raise P_E:

    G2 spec
    G2 body
    G1 spec
    G1 body
    P spec

Of course, you can have a convention that calls for putting in
unnecessary pragmas Elaborate, such as the one you suggest.  (For
example, a reasonable convention for Ada 83 was: put pragma Elaborate on
everything you "with", unless you can't because of a cycle.)  But I
thought we were discussing this convention: X should have
pragma-Elaborate_All of Y if and only if X calls/instantiates/activates
some subprogram/generic/task in Y during X's elaboration (unless Y has
Pure, Preelab, or Elab_Body).  And you asked, with respect to this
convention, whether it should be Elab instead of Elab_Body.

>Isn't G2 supposed to take care of it's own business, and make sure G1 is
>elaborated?  This is analogous to P making sure G2 is elaborated.

No, it's not analogous.  G2 is instantiated during P's elaboration.  G1
is not instantiated during G2's elaboration.

- Bob




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-21  0:00           ` Matthew Heaney
  1997-04-22  0:00             ` Robert A Duff
@ 1997-04-22  0:00             ` Mats Weber
  1997-04-23  0:00             ` Robert Dewar
  2 siblings, 0 replies; 81+ messages in thread
From: Mats Weber @ 1997-04-22  0:00 UTC (permalink / raw)



> OK, one more question.  Why not just pragma Elaborate?  If I only
> instantiate the generic in the package declarative region, and do not call
> any of its functions during elaboration or initialization, then why pragma
> Elaborate_All?  All I the instantiator require is the generic's body, not
> the bodies of the packages it with's, so isn't Elaborate good enough?

Because if your generic instantiates another generic in its body or spec
(a very common siutation), then you must include a pragma Elaborate for
that other generic too, and therefore also a with clause for it, which
you don't want.

You can find a discussion of the elaboration problems in Ada in my PhD
thesis at
<http://lglwww.epfl.ch/Team/MW/Ada-Extensions/Ada-Extensions.html>
sections 2.7 and 4.5.




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-22  0:00                 ` Robert A Duff
@ 1997-04-22  0:00                   ` Matthew Heaney
  1997-04-23  0:00                     ` Robert A Duff
  1997-04-23  0:00                     ` Robert Dewar
  0 siblings, 2 replies; 81+ messages in thread
From: Matthew Heaney @ 1997-04-22  0:00 UTC (permalink / raw)



In article <E91yH8.36E@world.std.com>, bobduff@world.std.com (Robert A
Duff) wrote:


>>But isn't G2 supposed to elaborate G1?
>>
>>with G1; 
>>pragma Elaborate (G1);   <<<---
>>package body G2 is
>>    package Inst_1 is new G1;
>>end G2;
>
>No, G2 does not instantiate G1 during its (G2's) elaboration.  In fact,
>G2 doesn't do anything during elaboration, except to record the fact
>that it has now been elaborated. 
>
>But I
>thought we were discussing this convention: X should have
>pragma-Elaborate_All of Y if and only if X calls/instantiates/activates
>some subprogram/generic/task in Y during X's elaboration (unless Y has
>Pure, Preelab, or Elab_Body).  And you asked, with respect to this
>convention, whether it should be Elab instead of Elab_Body.

OK, I almost understand.  The elaboration of the generic itself is not very
interesting: it's the elaboration of the instantiation that we need to
think about carefully.  The rules go like this:

  Why You Need Pragma Elaborate_All And Not Just Elaborate

o  An instantiation of a generic inside another generic (package) isn't
really elaborated until the elaboration of the instantiation of the
enclosing generic.  So that's why we need pragma Elaborate_All and not just
pragma Elaborate.

o  If you call a subprogram of a package you with'd during your
elaboration, you need to pragma Elaborate_All, to cover elaboration of
library units in the called subprogram.

I think I've got it.  Thank you, Bob, once again...

Matt

--------------------------------------------------------------------
Matthew Heaney
Software Development Consultant
<mailto:matthew_heaney@acm.org>
(818) 985-1271




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-21  0:00   ` Michael F Brenner
@ 1997-04-22  0:00     ` Robert A Duff
  0 siblings, 0 replies; 81+ messages in thread
From: Robert A Duff @ 1997-04-22  0:00 UTC (permalink / raw)



In article <5jfu0b$l5p@top.mitre.org>,
Michael F Brenner <mfb@mbunix.mitre.org> wrote:
>One more thing must be said: in reusing this software, the reuse itself
>might have a circular dependency, which the compiler may or may not
>be able to figure out.

What do you mean by this?  If by "reuse" you mean taking some existing
set of packages, and using them without modification, then I don't see
how you can introduce a circularity.  To make a cycle, you need to add a
with_clause to one of those packages.

>... To reduce the amount of stuff that the compiler
>has to worry about, and to make it possible to compute a SINGLE
>elaboration order (without which the program may raise program_error
>at will), you MUST add one of the first three to all packages you
>think are NOT in a circular elaboration dependency loop. Doing this
>also helps you identify your elaboration loops more clearly, so you
>can deal with them using elaborate or elaborate_all or by removing
>the regression testing code from the elaboration-time executable
>statements at the bottom of the package. Failure to add these will
>cause needless failures when they are reused INSIDE an elaboration
>dependency loop. 

I agree that it's a good idea to put Pure, Preelaborate, or Elab_Body on
everything you can, but I don't see how you can reuse something inside
an elab dep loop.  Unless you're changing the re-used stuff, in which
case, of course, you can introduce cycles.  Or plain old bugs, for that
matter.

Probably Elaborate_Body should have been the default (or maybe even
Preelab or Pure), and there should have been a pragma to turn *off*
Elab_Body, in case of mutual recursion.  (By "recursion", I mean
"defined in terms of itself", not necessarily recursive calling.
E.g. mutually recursive type declarations can exist.)

IMHO the worst thing about this stuff is that elab order is not
portable.  If you make a mistake, you might not find out until you're
long dead and somebody else tries to port your code.

- Bob




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-21  0:00         ` Robert Dewar
@ 1997-04-22  0:00           ` Robert A Duff
  1997-04-24  0:00             ` Robert Dewar
  0 siblings, 1 reply; 81+ messages in thread
From: Robert A Duff @ 1997-04-22  0:00 UTC (permalink / raw)



In article <dewar.861656614@merv>, Robert Dewar <dewar@merv.cs.nyu.edu> wrote:
>iRobert Duff said
>
><<...which is almost always the case, in my experience...>>
>
>
>I don't think so at all, I often see generics instantiated in an
>inner scope, there is absolutely no reason to consider this somehow
>poor style -- on the contrary, it is better to instantiate the generic
>as locally as possible -- the normal rule for declarations ...

I didn't say it was poor style, and I agree with "as locally as
possible".  But, in my experience, that usually ends up being in a
library package, or *as* a library package.

><<<<It's best to assume that the generic has a body.  The client shouldn't
>  have to care.>>
>>>
>
>I don't see any reason to assume that a generic has a body, when you can
>tell from the spec that it is not allowed to have a body -- well at least
>you can tell if there is no private part ...

Because somebody might change the generic to have a body, and then all
the clients would be broken.  Anyway, if the generic is nested in a
package, you can't tell whether it has a body, so it's best to assume
that it does.

- Bob




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-21  0:00       ` Robert Dewar
@ 1997-04-23  0:00         ` Robert A Duff
  1997-04-23  0:00           ` Robert Dewar
  1997-04-24  0:00           ` Mats Weber
  0 siblings, 2 replies; 81+ messages in thread
From: Robert A Duff @ 1997-04-23  0:00 UTC (permalink / raw)



In article <dewar.861642821@merv>, Robert Dewar <dewar@merv.cs.nyu.edu> wrote:
>Robert Duff said
>
><<If you're willing to live with some restrictions, and some complicated
>(slow?) processing at link time, you could dispense with all
>elaboration-control pragmas, and have the link phase determine an
>elaboration order that's guaranteed to not raise Program_Error.  But
>note that some of these pragmas (Pure, especially) have purposes other
>than just elaboration order.>>
>
>No, that's quite wrong. There are many things that can place restrictions
>on the order of elaboration.

But my assertion was that one could be rid of Program_Errors due to
calling subprograms before they've been elaborated.  That's certainly
true.  The link-time processing would have to walk the call graph, and
make sure every subprogram gets elaborated before it might be called.
This is complex, and perhaps slow, and would make some (fairly obscure)
legal programs illegal.

I admit that your example shows a case where you want to control
elaboration order, which has nothing to do with the predefined
Program_Error checks.  Is that something the language should help you
with?  I'm not sure.

It seems to me that elaboration order should not be implementation
dependent -- the main problem with the current Ada rules is that you can
port code (or simply recompile with a new version of your compiler) and
get a P_E that didn't used to happen.

But your example seems questionable to me.  (See below.)

>Suppose we have a package Glorp that has several procedures including
>Thunk, Boggle, and Glub. In the comments of package Glorp, we find the
>comment:
>
>-- WARNING: It is essential to call Thunk before calling Boggle. If you
>-- fail to do this, all subsequent calls to Glub will raise the Glob-Glob
>-- exception or otherwise malfunction. Clients of Glorp are responsible for
>-- obeying this rule, since no check is made (a check would introduce too
>-- much overhead).

OK, but tell us why Glorp doesn't simply call Thunk in its elaboration?
I mean, the whole point of having elaboration is to get stuff
initialized, and it should be Glorp's responsibility to do that.

I will admit that no reasonable Ada implementation will understand the
above comment.    ;-)

>Now, suppose we have two clients of Glorp, Jabber and Wocky. The elaboration
>code of Jabber calls Thunk, and the elaboration code of Wocky calls Boggle.
>
>Well now it is essential that Jabber is elaborated before Wocky, and no
>static analysis of the program code can determine this, and a pragma
>Elaborate is required.
>
>And if you think this is just theoretical, think again, there are
>instantiations of the names above in the SGI GNAT runtime library, and
>when we installed some new clever elaboration stuff (a bit like Bob
>proposes, but more effective, and easier to understand), the binder
>chose a much better elaboration order, much more clearly guaranteed
>to prevent Program_Error, but unfortunately wrong (of course this is
>a bug in the runtime, there is a missing pragma Elaborate).

But wouldn't the runtime be simpler if each package took care of its own
initialization?

>It is quite true that you can guarantee absence from Program_Error for a wide
>variety of programs automatically, and version 3.10 of GNAT does that. 

That's all I was asserting.

>...BUT
>it is far from true that this means that you could "dispense with all
>elaboration-control pragmas".

You quote me out of context -- there's a ", and have the link phase
determine an elaboration order that's guaranteed to not raise
Program_Error." there.  That's all I meant, although the more general
situation is interesting from a language design point of view.

- Bob




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-22  0:00                   ` Matthew Heaney
@ 1997-04-23  0:00                     ` Robert A Duff
  1997-04-24  0:00                       ` Matthew Heaney
  1997-04-25  0:00                       ` Robert Dewar
  1997-04-23  0:00                     ` Robert Dewar
  1 sibling, 2 replies; 81+ messages in thread
From: Robert A Duff @ 1997-04-23  0:00 UTC (permalink / raw)



In article <mheaney-ya023680002204972039270001@news.ni.net>,
Matthew Heaney <mheaney@ni.net> wrote:
>  Why You Need Pragma Elaborate_All And Not Just Elaborate
>
>o  An instantiation of a generic inside another generic (package) isn't
>really elaborated until the elaboration of the instantiation of the
>enclosing generic.  So that's why we need pragma Elaborate_All and not just
>pragma Elaborate.
>
>o  If you call a subprogram of a package you with'd during your
>elaboration, you need to pragma Elaborate_All, to cover elaboration of
>library units in the called subprogram.

Right.

In practice, this leads to the simple rule: Always use Elaborate_All
instead of Elaborate, except when you can't.  "When you can't" means
there's some sort of mutual recursion going on, and you have to use
Elaborate instead.

- Bob




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-21  0:00           ` Matthew Heaney
  1997-04-22  0:00             ` Robert A Duff
  1997-04-22  0:00             ` Mats Weber
@ 1997-04-23  0:00             ` Robert Dewar
  2 siblings, 0 replies; 81+ messages in thread
From: Robert Dewar @ 1997-04-23  0:00 UTC (permalink / raw)




Matthew Heaney asks

<<OK, one more question.  Why not just pragma Elaborate?  If I only
instantiate the generic in the package declarative region, and do not call
any of its functions during elaboration or initialization, then why pragma
Elaborate_All?  All I the instantiator require is the generic's body, not
the bodies of the packages it with's, so isn't Elaborate good enough?>>

Because the body may have elaboration code that calls functions in units
that are with'ed by the generic and not by the client.

Incidentally, I find that the whole elaboration issue is one on which a
lot of people are fuzzy. I am currently doing a complete documentation
section on the new GNAT support for elaboration checking and management,
and that section also tries to explain the technical aspects of this
issue.





^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-21  0:00     ` Michael F Brenner
@ 1997-04-23  0:00       ` Robert Dewar
  1997-04-24  0:00         ` Laurent Guerby
  1997-04-24  0:00         ` Matthew Heaney
  0 siblings, 2 replies; 81+ messages in thread
From: Robert Dewar @ 1997-04-23  0:00 UTC (permalink / raw)




Michael says

<<You cannot modify the body of a PURE package to add in, for example,
  text_io, or any other non-pure package for debugging purposes at a later time,
  without busting the purity of everything that withs the PURE package. You
  also may not reuse a pure generic package in a way that introduces any memory,
  because of the rule that the compiler may optimize away repeated calls
  with the same arguments. Gnat in its current state (3.07 DOS) optimizes
  pure packages that implement limited private data structures better than
  impure packages. ROMable code should be PURE.
>>

I often find it quite annoying not being able to use Text_IO for debugging
purposes in a pure or preelaborable package. There are two ways around it.
One is to use GNAT.IO, which is at least preelaborable (maybe we should
cheat and call it pure, but it really isn't).

The other is to use the secret switch -gnatdu:

   --  du   Uncheck categorization pragmas. This debug switch causes the          
   --       categorization pragmas (Pure, Preelaborate etc) to be ignored         
   --       so that normal checks are not made (this is particularly useful       
   --       for adding temporary debugging code to units that have pragmas        
   --       that are inconsistent with the debugging code added.                  

well it is not *that* secret. it is one of the GNAT debugging switches
that are documented in debug.adb :-)

<<There are no disadvantages to marking elaborable packages as ELABORATE_BODY,
  and they should be so marked for both documentation and for compiler hinting.
>>

That is incorrect, you can certainly create cases of legitimate programs
where the use of Elaborate_Body will cause elaboration circularities. A
trivial example is two packages, each of whose bodies with's the others
spec, which is not that uncommon.

<<The goal should be that almost all of the non-thread-safe code should be
  marked ELABORATE_BODY, and almost all of the thread-safe code should be
  marked PREELABORATE or PURE.>>

I have no idea what Michael has in mind here. This has nothing at all to do
with thread safety. Elaboration and thread safety are entirely unrelated
issues. In particular, a common idiom is to complete the elaboration before
any tasks are started up.

Robert Dewar
Ada Core Technologies







^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-22  0:00                   ` Matthew Heaney
  1997-04-23  0:00                     ` Robert A Duff
@ 1997-04-23  0:00                     ` Robert Dewar
  1 sibling, 0 replies; 81+ messages in thread
From: Robert Dewar @ 1997-04-23  0:00 UTC (permalink / raw)



Matthew Heaney said

<<OK, I almost understand.  The elaboration of the generic itself is not very
interesting: it's the elaboration of the instantiation that we need to
think about carefully.  The rules go like this:>>

your statement of the rules is not quite complete, but is essentially right.

The elaboration of the generic itself is entirely analogous to the
elaboration of a subprogram. It is not completely a noop, because of
the fundamental rule that you cannot instantiate a generic (call a
subprogram) until the body of the generic is elaborated (the body of
the subprogram is elaborated).

Typically the code corresponding to the elaboration of a generic is to
set a flag that will be tested on instantiations (to make sure that it
is set).





^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-23  0:00         ` Robert A Duff
@ 1997-04-23  0:00           ` Robert Dewar
  1997-04-24  0:00             ` Robert A Duff
  1997-04-24  0:00           ` Mats Weber
  1 sibling, 1 reply; 81+ messages in thread
From: Robert Dewar @ 1997-04-23  0:00 UTC (permalink / raw)



Bob Duff said

<<But my assertion was that one could be rid of Program_Errors due to
  calling subprograms before they've been elaborated.>>

That was one of your assertions, and I agree with it, but you also asserted
that "you could dispense with all elaboration-control pragmas", and that
is more contentious, since it would reduce the expressive power of the
language, no matter how clever your implementation is.

You realize this of course, and then dispute my example (that's fair, if
a language designer suggests removing a feature that someone thinks is
essential, they can argue that it is not so essential, and that the
programs affected are somehow wrong:

<<OK, but tell us why Glorp doesn't simply call Thunk in its elaboration?
  I mean, the whole point of having elaboration is to get stuff
  initialized, and it should be Glorp's responsibility to do that.>>

I am the client, there is no way I can change my server, especially if
the server is in fact an external threads package (as was the case in
the particular instance). 

How about Glorp is "get the next random number", and Thunk is "initialize
the random number with an appropriate seed". I can quite see that the
issues of initializing the random number generators for a run, and 
using them to compute some initial static tables might be handled
in different packages.

<<I admit that your example shows a case where you want to control
elaboration order, which has nothing to do with the predefined
Program_Error checks.  Is that something the language should help you
with?  I'm not sure.>>

If the language does not let you control elaboration order, then it should
not provide elaboration, otherwise you can get into too much trouble. This
can be a major problem in C++ programs, where there is no control. We have
nice mechanisms in Ada that are very powerful, and allow handling cases
like this nicely.

I agree it would be nice if elaboration could be handled entirely statically.
The problem is finding a nice model for this. Requiring a compiler to build
a call graph for the entire program is painful (and indeed we explicitly
rejected this possibility during the Ada 95 design effort).

I think the model I have just
implemented in GNAT is very attractive, it avoids the need for a program
wide call graph (which would be an unattractive extra expense), but seems
powerful enough in practice to handle most normal cases (we found no
counter example in our regression suite, and only a couple of counter
examples in the ACVC suite -- so we run the ACVC suite with the switch
that requires full dynamic semantics for elaboration.

However, when I implemented this, my nice circuitry for choosing a good
elaboration order caused the SGI version of the runtime to blow up. The
order it chose was Program_Error free, but ran afoul of some implicit
ordering requirements (abstracted into my Glorp/Thunk example). Of 
course a pragma Elaborate or Elaborate_All properly placed would fix this.

It will be interesting to see how well the GNAT static model works. Basically
the short cut is to imply a pragma Elaborate)All on any package or generic that
is directly or indirectly accessed in elaboration code (if it is not Pure,
Preelaborate, predefined, or Elaborate_Body). For internal threads of control,
the equivalent of a full call graph is used (though never explicitly built).

More informatoin will be available when 3.10 and its documentation is released

Robert Dewar
Ada Core Technologies





^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-22  0:00           ` Robert A Duff
@ 1997-04-24  0:00             ` Robert Dewar
  0 siblings, 0 replies; 81+ messages in thread
From: Robert Dewar @ 1997-04-24  0:00 UTC (permalink / raw)



<<I didn't say it was poor style, and I agree with "as locally as
possible".  But, in my experience, that usually ends up being in a
library package, or *as* a library package.>>

Well I can say that our regressoin suite has many hundreds of counter
examples!





^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-23  0:00       ` Robert Dewar
  1997-04-24  0:00         ` Laurent Guerby
@ 1997-04-24  0:00         ` Matthew Heaney
  1997-04-24  0:00           ` Jon S Anthony
                             ` (3 more replies)
  1 sibling, 4 replies; 81+ messages in thread
From: Matthew Heaney @ 1997-04-24  0:00 UTC (permalink / raw)



In article <dewar.861816859@merv>, dewar@merv.cs.nyu.edu (Robert Dewar) wrote:


>That is incorrect, you can certainly create cases of legitimate programs
>where the use of Elaborate_Body will cause elaboration circularities. A
>trivial example is two packages, each of whose bodies with's the others
>spec, which is not that uncommon.

It may be true that it "is not that uncommon," but mutual dependency of
packages indicates that you have a pair of highly cohesive abstractions,
and they should really be combined into a single package.

--------------------------------------------------------------------
Matthew Heaney
Software Development Consultant
<mailto:matthew_heaney@acm.org>
(818) 985-1271




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-22  0:00               ` Matthew Heaney
  1997-04-22  0:00                 ` Robert A Duff
@ 1997-04-24  0:00                 ` Robert Dewar
  1997-04-24  0:00                   ` Robert A Duff
  1 sibling, 1 reply; 81+ messages in thread
From: Robert Dewar @ 1997-04-24  0:00 UTC (permalink / raw)



Responding To Bob Duff's example

   generic
   package G1 is ... end G1;

   package body G1 is ... end G1;

   generic
   package G2 is ... end G2;

   with G1;
   package body G2 is
       package Inst_1 is new G1;
   end G2;

   with G2; pragma Elaborate(G2);
   package P is
       package Inst_2 is new G2;
   end P;

Matthew Heaney asks

  But isn't G2 supposed to elaborate G1?

  with G1;
  pragma Elaborate (G1);   <<<---
  package body G2 is
      package Inst_1 is new G1;
  end G2;

  Isn't G2 supposed to take care of it's own business, and make sure G1 is
  elaborated?  This is analogous to P making sure G2 is elaborated.

Robert Dewar replies

In general the answer is no. G2 has no elaboration problem (generic packages
themselves require nothing to be elaborated). It is the instance of G2
that might need elaboration.

If no one ever instantiates G2 in elaboration code, then there is absolutely
no need to elaborate the body of G1 before the spec of G2. This requirement
comes from the fact that P instantiates G2 at elaboration time. Thus P
must take responsibility for the elaboration, and do a pragma Elaborate_All,
rather than a pragma Elaborate.

Note: This is exactly the kind of automatic Elaborate_All that the new
version of GNAT does by default. It will also on request output warnings
for missing Elaborate_All pragmas.







^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-23  0:00         ` Robert A Duff
  1997-04-23  0:00           ` Robert Dewar
@ 1997-04-24  0:00           ` Mats Weber
  1997-04-24  0:00             ` Robert A Duff
  1997-04-25  0:00             ` Robert Dewar
  1 sibling, 2 replies; 81+ messages in thread
From: Mats Weber @ 1997-04-24  0:00 UTC (permalink / raw)



Robert A Duff wrote:

> It seems to me that elaboration order should not be implementation
> dependent -- the main problem with the current Ada rules is that you can
> port code (or simply recompile with a new version of your compiler) and
> get a P_E that didn't used to happen.

I agree 100% here, and the solution was described at least in two
articles before or during the Ada 9X effort. I still don't understand
why it's not in the language.

Moreover, most compilers I have used do a very good job of putting
packages in a 'good' elaboration order, to the point that I almost never
bother using the elaboration pragmas, taking the risk of hitting a bad
compiler some time in the future (which won't be GNAT, given the effort
being made to solve the problem :-).

I really think this elaboration stuff should fixed in an AI (of course
only the part that ensures Program_Error is not raised on a subprogram
call or generic instantiation). Do you think that would be possible, or
will we have to wait until Ada 0X ? :-)




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-24  0:00                       ` Matthew Heaney
@ 1997-04-24  0:00                         ` Robert A Duff
  0 siblings, 0 replies; 81+ messages in thread
From: Robert A Duff @ 1997-04-24  0:00 UTC (permalink / raw)



In article <mheaney-ya023680002404970055380001@news.ni.net>,
Matthew Heaney <mheaney@ni.net> wrote:
>What should the instantiator do if the generic has a pragma Pure, Preelab,
>or Elab_Body?  Does the instantiator still have to pragma Elaborate_All the
>generic package?  Or can he omit that pragma?

Elab_All can be omitted in this case, which is one reason why Pure,
Preelab, and Elab_Body are so convenient.  (Robert has pointed out how
to put debugging statements in Pure units -- if you're not using GNAT,
you can cheat in a similar way by calling some pragma-Imported thing --
which I suppose could be written in Ada.)

>Can you explain when exactly does the pragma Pure of the generic package
>apply?  During elaboration of the generic, or of the instantiation?

The generic.  If you want the instance to be pure, you have to put the
pragma on the instance (if its a lib unit), or on the containing lib
unit.  This last is not obvious from the RM -- there's an AI on this
issue.

- Bob




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-23  0:00       ` Robert Dewar
@ 1997-04-24  0:00         ` Laurent Guerby
  1997-04-24  0:00         ` Matthew Heaney
  1 sibling, 0 replies; 81+ messages in thread
From: Laurent Guerby @ 1997-04-24  0:00 UTC (permalink / raw)



dewar@merv.cs.nyu.edu (Robert Dewar) writes:
> I often find it quite annoying not being able to use Text_IO for debugging
> purposes in a pure or preelaborable package. There are two ways around it.
> One is to use GNAT.IO, which is at least preelaborable (maybe we should
> cheat and call it pure, but it really isn't).
> 
> The other is to use the secret switch -gnatdu:

   I posted a while ago another "Pure" Ada solution: use the pragma
Import from a Pure package is not disallowed, so you can import your
favorite Put_Line routine (it made Bob duff happy is I remember well
;-).

   Shouldn't this be in the programming FAQ?

-- 
Laurent Guerby <guerby@gnat.com>, Team Ada.
   "Use the Source, Luke. The Source will be with you, always (GPL)."




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-24  0:00                 ` Robert Dewar
@ 1997-04-24  0:00                   ` Robert A Duff
  0 siblings, 0 replies; 81+ messages in thread
From: Robert A Duff @ 1997-04-24  0:00 UTC (permalink / raw)



In article <dewar.861864497@merv>, Robert Dewar <dewar@merv.cs.nyu.edu> wrote:
>Note: This is exactly the kind of automatic Elaborate_All that the new
>version of GNAT does by default. It will also on request output warnings
>for missing Elaborate_All pragmas.

That's interesting.  Can you describe exactly what cases cause a
warning?

- Bob




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-23  0:00           ` Robert Dewar
@ 1997-04-24  0:00             ` Robert A Duff
  1997-04-24  0:00               ` Robert Dewar
  0 siblings, 1 reply; 81+ messages in thread
From: Robert A Duff @ 1997-04-24  0:00 UTC (permalink / raw)



In article <dewar.861854112@merv>, Robert Dewar <dewar@merv.cs.nyu.edu> wrote:
[Elaboration-order-control features are needed.]

OK, I'm convinced.

I just wish that (1) I didn't have to write zillions of pragmas in the
"normal" cases.  E.g. maybe Elaborate_Body or Preelab should be the
default, with a pragma to turn it off.  And (2) that all implementations
had to choose the same order for a given program.  The Modula-2 rules
are closer, but still don't quite make it.

- Bob




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-24  0:00         ` Matthew Heaney
  1997-04-24  0:00           ` Jon S Anthony
@ 1997-04-24  0:00           ` Robert A Duff
  1997-04-24  0:00           ` Robert Dewar
  1997-04-25  0:00           ` Michael F Brenner
  3 siblings, 0 replies; 81+ messages in thread
From: Robert A Duff @ 1997-04-24  0:00 UTC (permalink / raw)



In article <mheaney-ya023680002404970907100001@news.ni.net>,
Matthew Heaney <mheaney@ni.net> wrote:
>It may be true that it "is not that uncommon," but mutual dependency of
>packages indicates that you have a pair of highly cohesive abstractions,
>and they should really be combined into a single package.

I strongly disagree.  Yes, they're highly cohesive (which is why one can
tolerate Elab instead of Elab_All in these cases), but that doesn't mean
you should always combine them.  Consider a compiler (I always use
compilers as examples, since that's what I do for a living): you might
want to define a bunch of types representing pieces of syntax trees, and
operations on those trees.  Lots and lots of things will refer to
"Expression_Ptr", and there are lots of kinds of expressions, and so
forth, so your suggestion would require lumping just about everything
into one package.  This is because everything in the language definition
is highly mutually recursive (statements contain expressions,
expressions contain statements (in some languages), statements contain
declarations, declarations contain statements, etc).

I wish Ada 95 had *better* support for mutually recursive abstractions
(remember that long thread of a year or two ago?) -- I certainly don't
think mutually recursive packages are inherently evil.

- Bob




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-24  0:00         ` Matthew Heaney
  1997-04-24  0:00           ` Jon S Anthony
  1997-04-24  0:00           ` Robert A Duff
@ 1997-04-24  0:00           ` Robert Dewar
  1997-04-25  0:00           ` Michael F Brenner
  3 siblings, 0 replies; 81+ messages in thread
From: Robert Dewar @ 1997-04-24  0:00 UTC (permalink / raw)



Matthew Heaney says

<<It may be true that it "is not that uncommon," but mutual dependency of
packages indicates that you have a pair of highly cohesive abstractions,
and they should really be combined into a single package.>>

I strongly disagree. This is a recipe for giant packages for no good reason.

For example, it is perfectly reasonable to have a list package that
allows lists of sets (within the sets package), where the sets package
is implementd in terms of lists -- there are many such examples.

Sure, if there is mutual recursion at the spec level, then you combine
the packages, indeed Ada insists on it, although many feel that one of thje
big weaknesses in Ada 95 is that it does not allow mutually recursive
package specs. But at the body level there is absolutlely not reason to
take this position.





^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-24  0:00             ` Robert A Duff
@ 1997-04-24  0:00               ` Robert Dewar
  0 siblings, 0 replies; 81+ messages in thread
From: Robert Dewar @ 1997-04-24  0:00 UTC (permalink / raw)



<<>I really think this elaboration stuff should fixed in an AI (of course
>only the part that ensures Program_Error is not raised on a subprogram
>call or generic instantiation). Do you think that would be possible, or
>will we have to wait until Ada 0X ? :-)>>

This would introduce serious incompatibilities in legacy code. There is
nothing to stop indvidual compilers from impleemenjting some static
scheme, but it cannot be mandated.





^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-24  0:00             ` Robert A Duff
@ 1997-04-24  0:00               ` Robert Dewar
  1997-04-24  0:00                 ` Robert Dewar
                                   ` (2 more replies)
  0 siblings, 3 replies; 81+ messages in thread
From: Robert Dewar @ 1997-04-24  0:00 UTC (permalink / raw)



Bob said

<<I just wish that (1) I didn't have to write zillions of pragmas in the
"normal" cases.  E.g. maybe Elaborate_Body or Preelab should be the
default, with a pragma to turn it off.  And (2) that all implementations
had to choose the same order for a given program.  The Modula-2 rules
are closer, but still don't quite make it.>>

In its default configuration, GNAT 3.10 does not require you to write
"zillions of pragmas", and guarantees that Program_Error cannot occur.
Now it is true that you can construct programs that are treated as
statically illegal in this default mode, when they are in fact legal,
but in practice we have found that the rules we implement (which basically
assume pragma Elaborate_All if not stated where needed because of access
from elaboratoin code) seem to work for a very large subset of programs.

So far, we have only found a few ACVC tests that defeated these static
checks. We will know more when more people have a chance to try out this
new approach.

Robert Dewar
Ada Core Technologies.





^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-24  0:00               ` Robert Dewar
@ 1997-04-24  0:00                 ` Robert Dewar
  1997-04-25  0:00                   ` Robert A Duff
  1997-04-25  0:00                 ` Mats Weber
  1997-04-26  0:00                 ` AQ&S Guidance on pragma Elaborate_Body Nick Roberts
  2 siblings, 1 reply; 81+ messages in thread
From: Robert Dewar @ 1997-04-24  0:00 UTC (permalink / raw)



Following up my own message:

<<In its default configuration, GNAT 3.10 does not require you to write
"zillions of pragmas", and guarantees that Program_Error cannot occur.
Now it is true that you can construct programs that are treated as
statically illegal in this default mode, when they are in fact legal,
but in practice we have found that the rules we implement (which basically
assume pragma Elaborate_All if not stated where needed because of access
from elaboratoin code) seem to work for a very large subset of programs.>>

I should say that the one class of dynamic checks that we do not know how
to eliminate results from the use of access subprograms. Obviously this
is a nasty case, since it involves dynamic value tracing, which cannot be
done entirely accurately, even if you attempt it.





^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-24  0:00           ` Mats Weber
@ 1997-04-24  0:00             ` Robert A Duff
  1997-04-24  0:00               ` Robert Dewar
  1997-04-25  0:00             ` Robert Dewar
  1 sibling, 1 reply; 81+ messages in thread
From: Robert A Duff @ 1997-04-24  0:00 UTC (permalink / raw)



In article <335F5449.6644@elca-matrix.ch>,
Mats Weber  <Mats.Weber@elca-matrix.ch> wrote:
>I really think this elaboration stuff should fixed in an AI (of course
>only the part that ensures Program_Error is not raised on a subprogram
>call or generic instantiation). Do you think that would be possible, or
>will we have to wait until Ada 0X ? :-)

Well, the ARG is normally a bit more conservative than that, but you can
submit a comment if you like, and it will get turned into an AI.  Of
course, the AI might say, "Tough luck, elaboration stuff is a pain in
the neck, and that's that."

- Bob




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-23  0:00                     ` Robert A Duff
@ 1997-04-24  0:00                       ` Matthew Heaney
  1997-04-24  0:00                         ` Robert A Duff
  1997-04-25  0:00                       ` Robert Dewar
  1 sibling, 1 reply; 81+ messages in thread
From: Matthew Heaney @ 1997-04-24  0:00 UTC (permalink / raw)



In article <E9415t.8z9@world.std.com>, bobduff@world.std.com (Robert A
Duff) wrote:

>In practice, this leads to the simple rule: Always use Elaborate_All
>instead of Elaborate, except when you can't.  "When you can't" means
>there's some sort of mutual recursion going on, and you have to use
>Elaborate instead.

OK, just one more mint, wafer thin...

What should the instantiator do if the generic has a pragma Pure, Preelab,
or Elab_Body?  Does the instantiator still have to pragma Elaborate_All the
generic package?  Or can he omit that pragma?

Can you explain when exactly does the pragma Pure of the generic package
apply?  During elaboration of the generic, or of the instantiation?

M.

--------------------------------------------------------------------
Matthew Heaney
Software Development Consultant
<mailto:matthew_heaney@acm.org>
(818) 985-1271




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-24  0:00           ` Jon S Anthony
@ 1997-04-24  0:00             ` Matthew Heaney
  1997-04-26  0:00               ` Nick Roberts
  1997-04-26  0:00               ` Robert Dewar
  1997-04-25  0:00             ` Robert Dewar
  1 sibling, 2 replies; 81+ messages in thread
From: Matthew Heaney @ 1997-04-24  0:00 UTC (permalink / raw)




In article <JSA.97Apr24162056@alexandria>, jsa@alexandria (Jon S Anthony) wrote:

>>>A trivial example is two packages, each of whose bodies with's the others
>> >spec, which is not that uncommon.
>> 
>> It may be true that it "is not that uncommon," but mutual dependency of
>> packages indicates that you have a pair of highly cohesive abstractions,
>> and they should really be combined into a single package.
>
>Hmmm, you're probably about the only one left here that believes this.
>The "withing problem" (and this is for SPECS, not just the above sort
>of case) has been discussed here extensively and the general consensus
>is that this inability (to define mutually dependent types across
>package boundaries) is a hole in the language.

You're right, I'm not especially passionate about wanting to define
mutually recursive types across package boundaries.

I think it's a cool idea, though.  One of the tricks C++ programmers do is
to pass a reference to an object as a method parameter.  That way, you
don't have to #include the other class because you know an address is going
to get passed.

Knowing that tagged types are passed by reference, perhaps we could avoid a
spec dependency on the package containing a tagged type's declaration:

with Q.T is tagged limited private;
package P is

   type S is private;

   procedure Op (OS : in out S; OT : in Q.T);  -- OT is passed by reference
...

In this example, spec deferral makes sense.  Sometimes, though, you have
closely-related abstractions - maybe the dependency is in one direction
only, or maybe they're "merely" logically cohesive - and they just sort of
belong together.

Of course, avoiding unnecessary compilation dependencies is A Very Good
Thing, especially in Ada, where value semantics is the norm, and heap
allocation is to be avoided.

So there is a very real tension between the need to minimize compilation
dependencies, and the desire to minimize the "declaration span" between
closely-related types.  Yes, we have to program real systems on real
computers, but it's still humans that have to do it.

--------------------------------------------------------------------
Matthew Heaney
Software Development Consultant
<mailto:matthew_heaney@acm.org>
(818) 985-1271




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-24  0:00         ` Matthew Heaney
@ 1997-04-24  0:00           ` Jon S Anthony
  1997-04-24  0:00             ` Matthew Heaney
  1997-04-25  0:00             ` Robert Dewar
  1997-04-24  0:00           ` Robert A Duff
                             ` (2 subsequent siblings)
  3 siblings, 2 replies; 81+ messages in thread
From: Jon S Anthony @ 1997-04-24  0:00 UTC (permalink / raw)



In article <mheaney-ya023680002404970907100001@news.ni.net> mheaney@ni.net (Matthew Heaney) writes:

> >That is incorrect, you can certainly create cases of legitimate programs
> >where the use of Elaborate_Body will cause elaboration circularities. A
> >trivial example is two packages, each of whose bodies with's the others
> >spec, which is not that uncommon.
> 
> It may be true that it "is not that uncommon," but mutual dependency of
> packages indicates that you have a pair of highly cohesive abstractions,
> and they should really be combined into a single package.

Hmmm, you're probably about the only one left here that believes this.
The "withing problem" (and this is for SPECS, not just the above sort
of case) has been discussed here extensively and the general consensus
is that this inability (to define mutually dependent types across
package boundaries) is a hole in the language.  The great maker
himself, STT, has come to hold this position.  BTW, anyone know
whatever became of Tucker's proposal of "with package.type" for
solving this??  I know it wasn't going to be "formally" accepted
somehow, but wasn't there going to be some sort of general agreement
to provide this?

/Jon

-- 
Jon Anthony
Organon Motives, Inc.
Belmont, MA 02178
617.484.3383
jsa@organon.com





^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-24  0:00         ` Matthew Heaney
                             ` (2 preceding siblings ...)
  1997-04-24  0:00           ` Robert Dewar
@ 1997-04-25  0:00           ` Michael F Brenner
  1997-04-26  0:00             ` Nick Roberts
  3 siblings, 1 reply; 81+ messages in thread
From: Michael F Brenner @ 1997-04-25  0:00 UTC (permalink / raw)



>>A trivial example is two packages, each of whose bodies with's the others
>>spec, which is not that uncommon.

Obviously, those are NOT elaborable by a pre-elaborate, and that is why
the more complicated elaboration pragmas exist.

> It may be true that it "is not that uncommon," but mutual dependency of
> packages indicates that you have a pair of highly cohesive abstractions,
> and they should really be combined into a single package.

It is my understanding that introduction of these highly cohesive 
structures is the only way in Ada 95 to simulate the feature that is
really needed, namely having multiple, selectable bodies for the same
generic visible part. This unfortunate situation comes about because
non-generic packages cannot be passed as generic parameters. For
example, in targetting multiple radar devices, I need to choose a 
(1) receive probabilistic pattern recognizer, (2) down converter,
(3) selection criteria enhancer, (4) display driver, (5) embodied
intelligence analysis component, (6) a boundary data structure, (7)
geometry, (8) trigonometry (spherical or flat), (9) a topological
model of the discontinuities in the antenna pattern, (10) a search
strategy, (11) a viewing surface projection transformation, (12) and
a conjugate image generator. It is easy to program this as a 
multiply cohesive hierarchical set of 12 packages each of which 
depends on the next higher level package in the partially ordered set,
forming a giant circular dependency, and substituting them by
recompiling, relinking, and re-running each time the user makes an
alternate selection. However, without the ability to pass a non-generic
package to a generic package, I do not know how to build this
system without using these <Highly Cohesive Abstractions>. A simple
cohesion metric based on variable access being more expensive at 
higher levels shows that this is, indeed, highly cohesive. In addition,
the Ada-95 requirements to explicitly give bunches of elaboration
pragmas proves beyond doubt how cohesive it is, even though Alsys
Ada has no problem figuring out the correct elaboration order. Actually,
that is not 100 percent fair, because the maintenance history of the
project indicates that some changes were made that resulted in Alsys
Ada figuring out the correct elaboration order, that is, some of 
the regression tests were removed from being executed in the 
regression test section at the bottom of some packages which were
previously executed at elaboration time.

Michael said: 
<<The goal should be that almost all of the non-thread-safe code should be
  marked ELABORATE_BODY, and almost all of the thread-safe code should be
  marked PREELABORATE or PURE.>>

Robert said: 
<I have no idea what Michael has in mind here. This has nothing at all to do
with thread safety. Elaboration and thread safety are entirely unrelated
issues. In particular, a common idiom is to complete the elaboration before
any tasks are started up.>

The link between pragma pure and thread safety is that thread safety is
a memory concern, and the concept of a pure package is to be memory-free,
and therefore as thread safe as any code can be. That is why optimizers
are permitted to optimize away multiple calls to procedures in pure
packages--they have NO memory. If they had memory, and therefore 
potential thread-unsafeness, they ARE NOT pure, and it would be fibbing
to mark them pure, and the optimized-away calls will be an undesireable
effect on the execution of the code. The purity is transitive, since
everything imported (withed) by a pure package must be pure. Therefore,
if you call, for example, some pure_io.put_line several times during
the debugging of a pure package, only the first pure_io.put_line would
actually be called!

The second, and all further calls to pure_io.put_line would generate no
code (i.e., in DEC Vaxen Ada language, would be optimized away).

By induction, all call from a pure package must be pure and therefore
memory-less, and THEREFORE thread-safe, which is strictly a memory
concern. The ONLY way something can be non-thread-safe is if two tasks
change the same memory at the same time. Admittedly, we have to include
non-purity to include memory erroneously generated by the compiler into
the code that is on the heap or on a non-threaded stack, but we can assume
that this is not an issue due to the quality of our compilers which 
correcly implement their stacks and have no cause to allocate anything
on the heap for a PURE package, since there is NO DATA to allocate.

While realtime systems normally do complete elaboration (and initialization,
self-test, regression test, and build-in-test) before any task except
the main task are started up, this has nothing to do with thread
safety. Actually most realtime systems also allocate all tasks and variables
at the beginning and avoid dynamic memory deallocations or allocations, 
but this is because of memory leakage, not thread safety. 




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-24  0:00               ` Robert Dewar
  1997-04-24  0:00                 ` Robert Dewar
@ 1997-04-25  0:00                 ` Mats Weber
  1997-04-25  0:00                   ` Robert I. Eachus
  1997-04-27  0:00                   ` Robert Dewar
  1997-04-26  0:00                 ` AQ&S Guidance on pragma Elaborate_Body Nick Roberts
  2 siblings, 2 replies; 81+ messages in thread
From: Mats Weber @ 1997-04-25  0:00 UTC (permalink / raw)



Robert Dewar wrote:

> In its default configuration, GNAT 3.10 does not require you to write
> "zillions of pragmas", and guarantees that Program_Error cannot occur.
> Now it is true that you can construct programs that are treated as
> statically illegal in this default mode, when they are in fact legal,
> but in practice we have found that the rules we implement (which basically
> assume pragma Elaborate_All if not stated where needed because of access
> from elaboratoin code) seem to work for a very large subset of programs.

...which shows that automatic elaboration order construction is _state
of the art_ (this is further confirmed by other compilers (Verdix, DEC)
I use without a single pragma Elaborate* and without ever getting
Program_Error).

IMO, state of the art belongs in the standard, not in nice compiler
specific features, which would have allowed the standard to take a
different approach: automatic elaboration order consturction with
pragmas to _override_ it, instead of pragmas to do the right thing in
the most basic cases.




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-25  0:00                 ` Mats Weber
@ 1997-04-25  0:00                   ` Robert I. Eachus
  1997-04-26  0:00                     ` Nick Roberts
  1997-04-27  0:00                   ` Robert Dewar
  1 sibling, 1 reply; 81+ messages in thread
From: Robert I. Eachus @ 1997-04-25  0:00 UTC (permalink / raw)



In article <336089AF.6046@elca-matrix.ch> Mats Weber <Mats.Weber@elca-matrix.ch> writes:

  > IMO, state of the art belongs in the standard, not in nice compiler
  > specific features, which would have allowed the standard to take a
  > different approach: automatic elaboration order consturction with
  > pragmas to _override_ it, instead of pragmas to do the right thing in
  > the most basic cases.

    No.  State of the art should not be outlawed, and both Ada 83 and
Ada 95 went along with that.  But state of the art also argues for
"letting a milion flowers bloom," until one prefered method emerges as
"the state of the practice."

    There are Ada programs where not only is finding a workable
elaboration order hard--in the mathematical sense--but a property of
the program.  Right now, the program designer has access to
information not visible in the program, and based on that information
there is a working elaboration order.  But...

    Let me give you a true life example.  The system archictecture has
a design philosophy where each level in the architect only depends on
state in a lower level.  But for implementation reasons, lower level
routines call upper level routines all over the place.  As long as
elaboration is done in the right order, from lowest level to highest,
there are no ABE problems.  But assigning programs to levels is not
something the compiler can easily do.

    Sound like an extreme case?  Sorry, most graphical interfaces are
structured this way.  Accidently, breaking those ordering rules
becomes an obvious bug at run-time.  In Ada, using the
extra-linguistic knowledge to do elaboration means that, if it
compiles, you won't have ABE problems.

    Since the Ada model is so much easier to life with than the model
in some other languages, I'm willing to put up with the minor
irritation to allow these programs to be written.  (The problem when
you find a circular elaboration dependency and have to fix it is not
minor.  But in Ada you haven't spent months tracking it down.)


					Robert I. Eachus

with Standard_Disclaimer;
use  Standard_Disclaimer;
function Message (Text: in Clever_Ideas) return Better_Ideas is...
--

					Robert I. Eachus

with Standard_Disclaimer;
use  Standard_Disclaimer;
function Message (Text: in Clever_Ideas) return Better_Ideas is...




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-24  0:00                 ` Robert Dewar
@ 1997-04-25  0:00                   ` Robert A Duff
  0 siblings, 0 replies; 81+ messages in thread
From: Robert A Duff @ 1997-04-25  0:00 UTC (permalink / raw)



In article <dewar.861936746@merv>, Robert Dewar <dewar@merv.cs.nyu.edu> wrote:
>I should say that the one class of dynamic checks that we do not know how
>to eliminate results from the use of access subprograms. Obviously this
>is a nasty case, since it involves dynamic value tracing, which cannot be
>done entirely accurately, even if you attempt it.

Presumably dispatching calls raise the same issue.

- Bob




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-24  0:00           ` Mats Weber
  1997-04-24  0:00             ` Robert A Duff
@ 1997-04-25  0:00             ` Robert Dewar
  1 sibling, 0 replies; 81+ messages in thread
From: Robert Dewar @ 1997-04-25  0:00 UTC (permalink / raw)




<<I agree 100% here, and the solution was described at least in two
articles before or during the Ada 9X effort. I still don't understand
why it's not in the language.>>

The "solution" which for example is described in published papers from
the Binghamton group (I believe they published at Tri-Ada, as well as
an article in CACM), is indeed attractive, but there are two problems:

1. We have to decide how far to make a compiler go. Requiring the
construction of a call graph covering the whole program is very
expensive. 

2. We have to worry about backwards compatibility.

I actually pushed quite strongly during the Ada 9X process to try to
solve this problem, but we just did not find a satisfactory solution.
No one liked solutions that would require the construction of a full
call graph. I don't know if Mats solution has this quality, but
certainly the Binghamton papers expect this.

Obviously you cannot completely solve the compatibility problem with
any static approach, since it is trivial to show that soving the
elaboration problem in full gnerality is equivalent to the halting
problem (folks at Softech showed this early on, this discussion is
not new, it was on the table during the Ada 83 design, and the static
solutions involving call graph construction were well known at that
time -- of course the engineering details in such schemes are always
tricky!)

If you build a full call graph, you can solve most practical problems
(although there exist at least some test programs around which will
defeat any static scheme).

The question is whether there are schemes that are good enough, and
compatible enough. I am hoping the GNAT scheme will turn out to be
such a scheme.

Basically in GNAT we do a full call graph analysis within units, but 
for references across unit boundaries, we assume pragma Elaborate_All
in the default mode -- this seems to work pretty well in practice,
though one can certainly concoct examples that will defeat it. (We
have switches to revert to the fully dynamic view i that is what you
want).

The nastiest problem is with access typs (generic formal subprograms would
cause the same problem if you had shared generics, but not with macro
generics).

The trouble is that if you compute X'Access at a point before the boxy
of X is elaborated -- that is perfectly reasonable, and not in any sense
an error, or even in any sense poor practice (consider the implicit case
with tagged type dispatching tables for example).

But if X is in a separate unit that is not Pure or Preelaborate or
Elaborate_Body or predefned, you cannot avoiud a dynamic check. The

GNAT approach in this situation is:

(a) generate a warning (if you enable these special elaboration warnings)
that this is happening.

(b) generate a wrapper that does the dynamic check, and point to the wrapper

(c) where possible (and in particular for dispatching tables), recompute
all access types as soon as elaboration is complete to eliminate the
wrapper overhead.

Note that another goal of the GNAT approach is to provide a set of warnings
that have the quality that if you eliminate all warnings, then not only is
your program guaranteed not to raise Program_Error on any implementation,
but also, at least in GANT, you are guaranteed that no dynamic checks will
have been generated.





^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-23  0:00                     ` Robert A Duff
  1997-04-24  0:00                       ` Matthew Heaney
@ 1997-04-25  0:00                       ` Robert Dewar
  1 sibling, 0 replies; 81+ messages in thread
From: Robert Dewar @ 1997-04-25  0:00 UTC (permalink / raw)



Bob said

<<In practice, this leads to the simple rule: Always use Elaborate_All
instead of Elaborate, except when you can't.  "When you can't" means
there's some sort of mutual recursion going on, and you have to use
Elaborate instead.>>

This is definitely an appropriate rule. In fact for a while, the design
team had the view that this rule was so widely applicable that they
consigned pragma Elaborate to Annex J (the dreaded obsolescent feature
pile). But I found a few examples (from the GNAT runtime actually) that]
convinced us to keep pragma Elaborate as a first class citizen.

Still it is very rarely appropriate to use it. 





^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-24  0:00           ` Jon S Anthony
  1997-04-24  0:00             ` Matthew Heaney
@ 1997-04-25  0:00             ` Robert Dewar
  1 sibling, 0 replies; 81+ messages in thread
From: Robert Dewar @ 1997-04-25  0:00 UTC (permalink / raw)



<<Hmmm, you're probably about the only one left here that believes this.
The "withing problem" (and this is for SPECS, not just the above sort
of case) has been discussed here extensively and the general consensus
is that this inability (to define mutually dependent types across
package boundaries) is a hole in the language.  The great maker
himself, STT, has come to hold this position.  BTW, anyone know
whatever became of Tucker's proposal of "with package.type" for
solving this??  I know it wasn't going to be "formally" accepted
somehow, but wasn't there going to be some sort of general agreement
to provide this?
>>

The best thing you could hope for is a general agreement on what it should
look like if it is provided. Beyond that you have to let the market decide
whether vendors should work on this. We have customers who are running into
trouble with elaboration issues, which is why we have put work in on the
elaboration problem, but so far, none of our customers have been willing
to even request this feature, let alone offer to fund its development.

Of course if several vendors implement it, then there is pressure for
other vendors to follow suit, but it takes someone *really* interested
to get a vendor to be the first. After all, we are all a little
hesitant to get into the genuine language extension business!





^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-25  0:00                   ` Robert I. Eachus
@ 1997-04-26  0:00                     ` Nick Roberts
  1997-04-26  0:00                       ` Robert Dewar
  0 siblings, 1 reply; 81+ messages in thread
From: Nick Roberts @ 1997-04-26  0:00 UTC (permalink / raw)




Perhaps it could be summarised like this:

The 'call graph' (or 'call tree') of calls which occur during the
elaboration of the library units of a program cannot always be statically
determined.

There may be (and indeed, experience suggests, there will be) situations
where the potential call graph indicates a circularity (i.e. that there is
no order of elaboration which the compiler can determine will ensure that
an unelaborated subprogram is never called), but where there is, in fact,
an elaboration order in which normal execution of the program will not
cause an unelaborated subprogram to be called.

This is something which only the programmer can know: it cannot be
determined by the compiler. So, the programmer has got to tell the compiler
the order in which to elaborate the library units (and also, perhaps, has
to soothe the compiler's troubled brow, and reassure it that a call to an
unelaborated subprogram will not occur ;-).

Thus, elaboration pragmas are required.

As for 'state of the art': ask a soldier (/airman/sailor) whether he wants
weapon A, which is state-of-the-art, or weapon B, which is simple and
reliable. Which do you think he will choose? Or, to put it another way, if
you could buy Ada compiler product A, which is state-of-the-art (and costs
$30,000), or compiler product B, which requires elaboration pragmas (and
costs $3,000, and is more reliable anyway), which would you buy?

Nick.





^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-24  0:00             ` Matthew Heaney
@ 1997-04-26  0:00               ` Nick Roberts
  1997-04-26  0:00                 ` Matthew Heaney
  1997-04-26  0:00                 ` Robert A Duff
  1997-04-26  0:00               ` Robert Dewar
  1 sibling, 2 replies; 81+ messages in thread
From: Nick Roberts @ 1997-04-26  0:00 UTC (permalink / raw)





Matthew Heaney <mheaney@ni.net> wrote in article
<mheaney-ya023680002404972329250001@news.ni.net>...
> Knowing that tagged types are passed by reference, perhaps we could avoid
a
> spec dependency on the package containing a tagged type's declaration:
> 
> with Q.T is tagged limited private;
> package P is
> 
>    type S is private;
> 
>    procedure Op (OS : in out S; OT : in Q.T);  -- OT is passed by
reference
> ...


It's a nice idea. The problem with this idea, though (I think), is that
there are no operations defined for Q.T for use in the body of procedure
Op. What is Op able to do with the parameter OT? Anything?

Nick.



PS: If we had

with Q.T is abstract tagged limited private;

we could then derive from Q.T, add our own operations, and then use those
operations (only). But would this ever be useful?






^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-25  0:00           ` Michael F Brenner
@ 1997-04-26  0:00             ` Nick Roberts
  0 siblings, 0 replies; 81+ messages in thread
From: Nick Roberts @ 1997-04-26  0:00 UTC (permalink / raw)





Michael F Brenner <mfb@mbunix.mitre.org> wrote in article
<5jq9uc$kuf@top.mitre.org>...
> The link between pragma pure and thread safety is that thread safety is
> a memory concern, and the concept of a pure package is to be memory-free,
> and therefore as thread safe as any code can be. That is why optimizers
> are permitted to optimize away multiple calls to procedures in pure
> packages--they have NO memory. If they had memory, and therefore 
> potential thread-unsafeness, they ARE NOT pure, and it would be fibbing
> to mark them pure, and the optimized-away calls will be an undesireable
> effect on the execution of the code. The purity is transitive, since
> everything imported (withed) by a pure package must be pure. Therefore,
> if you call, for example, some pure_io.put_line several times during
> the debugging of a pure package, only the first pure_io.put_line would
> actually be called!
> 
> The second, and all further calls to pure_io.put_line would generate no
> code (i.e., in DEC Vaxen Ada language, would be optimized away).


Surely it would be a 'very poor' (substitute your favourite expletive)
compiler which 'optimized away' a second or subsequent call to a procedure
with only 'in' parameters defined in a pure package (as in Michael's
example)?

Moreover (and much earlier), if a compiler were to come across a procedure
which only has 'in' parameters declared in a pure package, surely to God it
should give a big fat warning message? I don't know if the language (Ada
95) allows it, but it would really be best for the compiler to give up
(with a fatal error), since this would certainly indicate a bug (wouldn't
it?).

Excellent post, by the way, Michael.

Nick.





^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-24  0:00               ` Robert Dewar
  1997-04-24  0:00                 ` Robert Dewar
  1997-04-25  0:00                 ` Mats Weber
@ 1997-04-26  0:00                 ` Nick Roberts
  1997-04-26  0:00                   ` Robert Dewar
  2 siblings, 1 reply; 81+ messages in thread
From: Nick Roberts @ 1997-04-26  0:00 UTC (permalink / raw)





Robert Dewar <dewar@merv.cs.nyu.edu> wrote in article
<dewar.861936524@merv>...
> 
> In its default configuration, GNAT 3.10 does not require you to write
> "zillions of pragmas", and guarantees that Program_Error cannot occur.
> Now it is true that you can construct programs that are treated as
> statically illegal in this default mode, when they are in fact legal,
> but in practice we have found that the rules we implement (which
basically
> assume pragma Elaborate_All if not stated where needed because of access
> from elaboratoin code) seem to work for a very large subset of programs.
> 
> So far, we have only found a few ACVC tests that defeated these static
> checks. We will know more when more people have a chance to try out this
> new approach.
> 
> Robert Dewar
> Ada Core Technologies.


This is very neat, but wouldn't it be better, for cases where it is not
strictly determinate, simply for the compiler to issue a warning that
Program_Error may be (or 'is likely to be') raised, and compile as normal?
Surely this would give the best of both worlds.

Nick.





^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-26  0:00               ` Nick Roberts
  1997-04-26  0:00                 ` Matthew Heaney
@ 1997-04-26  0:00                 ` Robert A Duff
  1 sibling, 0 replies; 81+ messages in thread
From: Robert A Duff @ 1997-04-26  0:00 UTC (permalink / raw)



In article <01bc5250$db1b6c00$28f982c1@xhv46.dial.pipex.com>,
Nick Roberts <Nick.Roberts@dial.pipex.com> wrote:
>It's a nice idea. The problem with this idea, though (I think), is that
>there are no operations defined for Q.T for use in the body of procedure
>Op. What is Op able to do with the parameter OT? Anything?

Various ideas along these lines were discussed here a year or two ago.
Basically, the idea would be that the spec can't do much of anything
with the imported type -- it's more-or-less like an incomplete type.
Declare access-to-OT'Class parameters, and perhaps not much more.
The body would then do a normal with_clause, and could therefore see
all the operations of OT.

- Bob




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-26  0:00                 ` AQ&S Guidance on pragma Elaborate_Body Nick Roberts
@ 1997-04-26  0:00                   ` Robert Dewar
  0 siblings, 0 replies; 81+ messages in thread
From: Robert Dewar @ 1997-04-26  0:00 UTC (permalink / raw)



<<This is very neat, but wouldn't it be better, for cases where it is not
strictly determinate, simply for the compiler to issue a warning that
Program_Error may be (or 'is likely to be') raised, and compile as normal?
Surely this would give the best of both worlds.>>

We can operate in this model with no problem with the appropriate switches,
but I don't think this is an appropriate default. We have found tha the huge
majority of existing Ada code is full of instances which would generate such
warnings -- i.e. a LOT of code is relying on a friendly linker, and people
are not necessarily intersted in doing a lot of work on their code to
avoid this ..





^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-26  0:00                     ` Nick Roberts
@ 1997-04-26  0:00                       ` Robert Dewar
  1997-04-28  0:00                         ` Robert I. Eachus
  0 siblings, 1 reply; 81+ messages in thread
From: Robert Dewar @ 1997-04-26  0:00 UTC (permalink / raw)




i<<
There may be (and indeed, experience suggests, there will be) situations
where the potential call graph indicates a circularity (i.e. that there is
no order of elaboration which the compiler can determine will ensure that
an unelaborated subprogram is never called), but where there is, in fact,
an elaboration order in which normal execution of the program will not
cause an unelaborated subprogram to be called.>>

Well of coruse this is true, and is why a purely static solution cannot
be 100% accurate. But It is *very* rare, I would say non-existent almost,
for anything other than specially constructed tests to run into this,
and the limitation in expressive power from forbidding such cycles is
negligible.





^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-24  0:00             ` Matthew Heaney
  1997-04-26  0:00               ` Nick Roberts
@ 1997-04-26  0:00               ` Robert Dewar
  1997-04-26  0:00                 ` Matthew Heaney
  1 sibling, 1 reply; 81+ messages in thread
From: Robert Dewar @ 1997-04-26  0:00 UTC (permalink / raw)



Matthew Heaney said

<<You're right, I'm not especially passionate about wanting to define
mutually recursive types across package boundaries.>>

That's fair enough, but what puzzled everyone was that you *do* seem
passionate about not wanting even mutual body dependencies (i.e. situations
where the bodies of two packages A, and B, both with one another's specs)

Are you really *sure* you meant to say this -- it is a rather extraordinary
position, and I must say I have not seen any large scale Ada program that
did not have such dependencies, they seem routine to me!





^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-26  0:00               ` Nick Roberts
@ 1997-04-26  0:00                 ` Matthew Heaney
  1997-04-26  0:00                 ` Robert A Duff
  1 sibling, 0 replies; 81+ messages in thread
From: Matthew Heaney @ 1997-04-26  0:00 UTC (permalink / raw)



In article <01bc5250$db1b6c00$28f982c1@xhv46.dial.pipex.com>, "Nick
Roberts" <Nick.Roberts@dial.pipex.com> wrote:

>> Knowing that tagged types are passed by reference, perhaps we could avoid
>a
>> spec dependency on the package containing a tagged type's declaration:
>> 
>> with Q.T is tagged limited private;
>> package P is
>> 
>>    type S is private;
>> 
>>    procedure Op (OS : in out S; OT : in Q.T);  -- OT is passed by
>reference
>> ...
>
>
>It's a nice idea. The problem with this idea, though (I think), is that
>there are no operations defined for Q.T for use in the body of procedure
>Op. What is Op able to do with the parameter OT? Anything?

I said "avoid a __spec__ dependency."  Of course, a with of package Q by
the body of P is required.  We're trying to make specs less sensitive to
changes in the packages is withs, to reduce the ripple-effect in a large
system (because the library units that with P would have to be
(potentially) checked, and so on).

--------------------------------------------------------------------
Matthew Heaney
Software Development Consultant
<mailto:matthew_heaney@acm.org>
(818) 985-1271




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-26  0:00               ` Robert Dewar
@ 1997-04-26  0:00                 ` Matthew Heaney
  1997-04-27  0:00                   ` Robert Dewar
  0 siblings, 1 reply; 81+ messages in thread
From: Matthew Heaney @ 1997-04-26  0:00 UTC (permalink / raw)



In article <dewar.862097521@merv>, dewar@merv.cs.nyu.edu (Robert Dewar) wrote:

><<You're right, I'm not especially passionate about wanting to define
>mutually recursive types across package boundaries.>>
>
>That's fair enough, but what puzzled everyone was that you *do* seem
>passionate about not wanting even mutual body dependencies (i.e. situations
>where the bodies of two packages A, and B, both with one another's specs)
>
>Are you really *sure* you meant to say this -- it is a rather extraordinary
>position, and I must say I have not seen any large scale Ada program that
>did not have such dependencies, they seem routine to me!

Perhaps our experience is different.  I have seen relatively few instances
of such a relationship (nor have I myself had much reason to do write
anything like that).  But when I have seen them, they were completely
unnecessary (confusing, in fact), and clearly indicated that the
abstractions needed to be combined into a single package.

I'm talking about just a pair of abstract data types that are intimately
related.  But I sense that you and the other posters are talking about
large packages (say, a subprogram library such as binding).

--------------------------------------------------------------------
Matthew Heaney
Software Development Consultant
<mailto:matthew_heaney@acm.org>
(818) 985-1271




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-25  0:00                 ` Mats Weber
  1997-04-25  0:00                   ` Robert I. Eachus
@ 1997-04-27  0:00                   ` Robert Dewar
  1997-04-28  0:00                     ` Mats Weber
  1997-04-29  0:00                     ` Redefinition of "=", elaboration and learning Ada Mats Weber
  1 sibling, 2 replies; 81+ messages in thread
From: Robert Dewar @ 1997-04-27  0:00 UTC (permalink / raw)



Mats says

<<...which shows that automatic elaboration order construction is _state
of the art_ (this is further confirmed by other compilers (Verdix, DEC)
I use without a single pragma Elaborate* and without ever getting
Program_Error).

IMO, state of the art belongs in the standard, not in nice compiler
specific features, which would have allowed the standard to take a
different approach: automatic elaboration order consturction with
pragmas to _override_ it, instead of pragmas to do the right thing in
the most basic cases.>>


Please don't generalize from your experience -- this could just mean that
you use elaboration very lightly. Others use it more heavily, and pragma
Elaborate can be critical -- here is an extreme, though real, example.
There is one Ada 83 compiler, written in Ada 83, where the main program
is null, and all the compiler passes are in elaboration code. Pragma
Elaborate is critical for ensuring that the passes of the compiler run
in the right order.

Sure, for the simple case you have DEC and Verdix (and most likely GNAT
as well) run fine, but I can *guarantee* that they are not consistent in
the set of programs that they can successfully handle statically.

We cannot have a statement in the standard that says "Elaboration shall be
automatically handled sufficiently well so that Mats Weber's programs run
without Program_Error", what we need is a very precise charaterization of
the set of programs that are to be considered legal.

Mats, what is this subset that you propose? in detail?





^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-26  0:00                 ` Matthew Heaney
@ 1997-04-27  0:00                   ` Robert Dewar
  1997-04-29  0:00                     ` John G. Volan
  0 siblings, 1 reply; 81+ messages in thread
From: Robert Dewar @ 1997-04-27  0:00 UTC (permalink / raw)



Matthew Heaney says

<<I'm talking about just a pair of abstract data types that are intimately
related.  But I sense that you and the other posters are talking about
large packages (say, a subprogram library such as binding).>>

Not necessarily, you can find lots of examples -- I am still surprised if
you really never ran across this in your own code. I have not seen any
large (say a couple of hundred thousand lines up) Ada program that did
NOT have this kind of mutual dependencies -- it is really a natural
consequence of any domain in which recursion is an important idiom.

For example, if we have a compiler with separate units to handle if statements
and loop statements, it is natural for if's to have loops and loops to have
if's. Surely you don't think this means that we have to put loops and if's
in the same unit -- because if you do you are syaing the whole compiler must
be one unit!

Another example is that Text_IO might well with some FPT conversion unit,
that might well have debugging statements that under a switch call
Put_Line in Text_IO.

and on and on and on ...





^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-26  0:00                       ` Robert Dewar
@ 1997-04-28  0:00                         ` Robert I. Eachus
  1997-04-29  0:00                           ` Robert Dewar
  0 siblings, 1 reply; 81+ messages in thread
From: Robert I. Eachus @ 1997-04-28  0:00 UTC (permalink / raw)



In article <dewar.862079640@merv> dewar@merv.cs.nyu.edu (Robert Dewar) writes:

  > Well of coruse this is true, and is why a purely static solution
  > cannot be 100% accurate. But It is *very* rare, I would say
  > non-existent almost, for anything other than specially constructed
  > tests to run into this, and the limitation in expressive power
  > from forbidding such cycles is negligible.

  I thought that Robert Dewar did provide an example from GNAT where
the pragmas were needed?  In any case, the reality is not that there
are very few programs which can be written so that the pragmas are not
needed, but that the pragmas and the error messages help Ada
programmers find a livable elaboration order, and to live with the
situations where proper execution requires a certain elaboration order.

  I spent most of Friday afternoon doing just that.  Now the real
problem in my case was a place where the Ada rules are slightly too
restrictive.  (And no, I am not suggesting that they be fixed...)  The
problem was that I have a tagged type call it Foo, and an access type
say Bar:

      type Foo is new Foob with private;
      type Bar is access all Foo'Class;

  So far so good, but now I want to instantiate a generic with:

     generic
       type Foobar is abstract new Foob with private;
       type Barf is access all Foobar;
     package Barfoo is ...

    Even though Foobar is not used within package Barfoo, I can't
instantiate the generic for Foo and Bar until after the completion of
the declaration Foo.  (And note that abstract, it is not just that I
don't declare an object of type Foobar, I can't.  But there could be a
(non-abstract) type derived from Foobar so it would take new syntax
for something of very marginal utility.  "type Foobar is abstract
final new Foo with private;" for example.

    As I said, not worth fixing.  But to get my program to compile
cleanly, I had to introduce a new unit with a "programmer knowledge
only" elaboration dependency.  Of course I documented the reason as a
comment on the pragma Elaborate_All.

    And, yes, I have worked with programs where the "right"
elaboration order could only be determined from files read at
execution time.  Of course the programming team knew the right order
and embedded it in Elaborates and project documentation.

--

					Robert I. Eachus

with Standard_Disclaimer;
use  Standard_Disclaimer;
function Message (Text: in Clever_Ideas) return Better_Ideas is...




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-27  0:00                   ` Robert Dewar
@ 1997-04-28  0:00                     ` Mats Weber
  1997-04-29  0:00                     ` Redefinition of "=", elaboration and learning Ada Mats Weber
  1 sibling, 0 replies; 81+ messages in thread
From: Mats Weber @ 1997-04-28  0:00 UTC (permalink / raw)



Robert Dewar wrote:

> We cannot have a statement in the standard that says "Elaboration shall be
> automatically handled sufficiently well so that Mats Weber's programs run
> without Program_Error", what we need is a very precise charaterization of
> the set of programs that are to be considered legal.
> 
> Mats, what is this subset that you propose? in detail?

It's at
<http://lglwww.epfl.ch/Team/MW/Ada-Extensions/Ada-Extensions.html>,
sections 2.7 and 4.5 (scroll down a little for the table of contents).




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-29  0:00                     ` John G. Volan
@ 1997-04-29  0:00                       ` Matthew Heaney
  1997-04-30  0:00                         ` Jon S Anthony
                                           ` (2 more replies)
  0 siblings, 3 replies; 81+ messages in thread
From: Matthew Heaney @ 1997-04-29  0:00 UTC (permalink / raw)



In article <33660F4B.1B45@sprintmail.com>, johnvolan@sprintmail.com wrote:


>> I'm talking about just a pair of abstract data types that are intimately
>> related.  But I sense that you and the other posters are talking about
>> large packages (say, a subprogram library such as binding).
>
>"Co-encapsulation," as I like to call it, has a cost: Loss of
>abstraction. Because both types have visibility to each other's private
>features, there is no way to enforce each to adhere to the discipline of
>only calling the other's public interface. This affects
>understandability: Readers must understand what both types are doing,
>internally, before they can be sure they know what either type is doing.
>
>Of course, if it's just "a pair of abstract data types that are
>intimately related", and that's all there is to it, then the cost of
>abstraction-loss is relatively small, so co-encapsulation may be a
>reasonable option.

That's all I was saying: a pair of ADTs that are intimately related. 
Here's an example.  In order to efficiently implement an active iterator,
that iterator has to have knowledge of the representation of the data
structure.  

For a bounded stack, I would do this:

   type Bounded_Stack is new Root_Stack with private;

   type Bounded_Stack_Iterator (Stack : access Bounded_Stack) is
      new Root_Stack_Iterator with private;
...
private

   subtype Item_Array_Range is Positive range 1 .. Size;

   type Item_Array is array (Item_Array_Range) of Stack_Item;

   type Bounded_Stack is new Root_Stack with
      record
          Items : Item_Array;
         Top : Natural := 0;
      end record;

   type Bounded_Stack_Iterator (Stack : access Bounded_Stack) is
      new Root_Stack_Iterator with
      record
         Index : Positive;
      end record;

end Stacks_G.Bounded_G;


I'm certainly not advocating large packages.  It's just that very often,
there are a small number of types (read: 2) that need to know about each
other's representation, or that one needs the know the represenation of the
other (the iterator above).

This is just the concept of a friend in C++: to implement that in Ada, you
put the types together in the same package.  No big deal.

There is NO loss of abstraction when the stack and its iterator are
co-located in the same package; the abstractions were meant to be used
together.  I don't subscribe to these gloom and doom scenarios about
putting types together; this is how the language was _intended_ to be used.

And it's certainly true that this affects understandability: it makes it
MORE understandable when the "declaration span" is minimized.  This is
analogous to using a declare block to move declaration of an object as
close as possible to its use.

I don't understand why a client needs to understand "internally" the
Bounded_Stack and its iterator to use it:

Do_Not_Need_Knowledge_Of_Representation_To_Use:
declare
   The_Stack : aliased Bounded_Stack;
   The_Iterator : Bounded_Stack_Iterator (The_Stack'Access);
begin
...
   while not Is_Done (The_Iterator) loop
      <process Current_Item (The_Iterator)>
      Advance (The_Iterator);
   end loop;
end Do_Not_Need_Knowledge_Of_Representation_To_Use;

What's so difficult about this?

Matt

--------------------------------------------------------------------
Matthew Heaney
Software Development Consultant
<mailto:matthew_heaney@acm.org>
(818) 985-1271




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-28  0:00                         ` Robert I. Eachus
@ 1997-04-29  0:00                           ` Robert Dewar
  1997-04-29  0:00                             ` Robert I. Eachus
  0 siblings, 1 reply; 81+ messages in thread
From: Robert Dewar @ 1997-04-29  0:00 UTC (permalink / raw)



Robert Eachus says

<<    And, yes, I have worked with programs where the "right"
elaboration order could only be determined from files read at
execution time.  Of course the programming team knew the right order
and embedded it in Elaborates and project documentation.>>

I find this sort of thing bad programming practice. If you are doing anything
this fancy at elaboration time, it is likely to get you into trouble, and you
do better to make the "elaboration" explicit rather than implicit, by
introducing appropriate explicit initialization routines.






^ permalink raw reply	[flat|nested] 81+ messages in thread

* Redefinition of "=", elaboration and learning Ada
  1997-04-27  0:00                   ` Robert Dewar
  1997-04-28  0:00                     ` Mats Weber
@ 1997-04-29  0:00                     ` Mats Weber
  1997-04-29  0:00                       ` Robert A Duff
  1 sibling, 1 reply; 81+ messages in thread
From: Mats Weber @ 1997-04-29  0:00 UTC (permalink / raw)



Another reason why I think we should have automatic elaboration order
calculation that works in the simple cases, and no reemergence of
predefined operations once they have been redefined, is that the
majority of Ada programmers do not understand these problems because
they have never studied the language to that level of detail (which is
perfectly OK, one should not be required to read the entire RM three
times to be able to write a piece of software in Ada).

Having to use pragma Elaborate_All when instantiating a generic at the
libarary level is, IMO, counterintuitive and unnecessarilly complicated.

Having predefined "=" reemerge in strange places when it's been
redefined is also counterintuitive, and the text in chapter 12 of the RM
won't help you much if you are not a language lawyer or compiler writer.
And then try explaining to a novice programmer, without making him
believe that the language definition is flawed, that if he makes his
type tagged then everything will work fine :-)

What the user sees when he discovers packages and private types is that
he can define abstractions that he can use without knowing how they are
implemented. What he sees when he discovers a library of generic
components is that he can instantiate them and then use them. In both
cases, he hits what is IMO a severe pitfall: reemergence breaks his
abstraction, and he (potentially) gets Program_Error when he
instantiates his generic.

For me, these are not really severe problems (except that I don't like
the way they were handled in Ada 95) because I know how to fix them. But
how is a beginner going to find his way to tagged types or elaboration
pragmas ? Not very easily I think, unless he reads comp.lang.ada :-)




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-27  0:00                   ` Robert Dewar
@ 1997-04-29  0:00                     ` John G. Volan
  1997-04-29  0:00                       ` Matthew Heaney
  0 siblings, 1 reply; 81+ messages in thread
From: John G. Volan @ 1997-04-29  0:00 UTC (permalink / raw)



Matthew Heaney wrote:

> I'm talking about just a pair of abstract data types that are intimately
> related.  But I sense that you and the other posters are talking about
> large packages (say, a subprogram library such as binding).

"Co-encapsulation," as I like to call it, has a cost: Loss of
abstraction. Because both types have visibility to each other's private
features, there is no way to enforce each to adhere to the discipline of
only calling the other's public interface. This affects
understandability: Readers must understand what both types are doing,
internally, before they can be sure they know what either type is doing.

Of course, if it's just "a pair of abstract data types that are
intimately related", and that's all there is to it, then the cost of
abstraction-loss is relatively small, so co-encapsulation may be a
reasonable option.

But what if that's not all there is to it?  Then the transitivity
problem rears its ugly head: If class A is "intimately related" to class
B, and class B is "intimately related" to class C, you may be forced to
co-encapsulate A, B, and C, despite the fact that you did not envision
any "intimate relationship" between A and C in your original software
design.

What if you've used an object-oriented analysis and design method, such
as OMT or UML, to develop a model of your application domain comprised
of a lot of classes linked together by a lot of binary associations? 
*Any* binary association might be construed as an "intimate
relationship" between the two clases involved.  But each class may be
involved in several associations.  And if your model is complete, I
believe it should form a single contiguous graph of classes linked by
associations, with no isolated islands.

Under these circumstances, if you allow the transitivity effect to
proceed unchecked, it can spread like a virus to infect your entire
application. Robert Dewar hits on this problem:

Robert Dewar wrote:
> 
> ... -- it is really a natural
> consequence of any domain in which recursion is an important idiom.
>
> For example, if we have a compiler with separate units to handle if statements
> and loop statements, it is natural for if's to have loops and loops to have
> if's. Surely you don't think this means that we have to put loops and if's
> in the same unit -- because if you do you are syaing the whole compiler must
> be one unit!

Here, I take "recursion" to mean "recursive data structures," where an
object of one type may contain references to objects of another type,
and vice versa.

I would go one step further: The transitivity problem doesn't just
affect applications that involve this kind of recursion.  *Any* binary
association, conceived of during object-oriented analysis, is
potentially vulnerable when you get to the design stage, and have to
decide whether the association needs to be traversible in one direction,
or the other, or both.  A mutually-recursive data structure is just one
way of implementing bidirectional traversals, but it's not the only way.

It was this transitivity problem that prompted me to kick off that long
thread a couple of years ago, and it was the seriousness of this
problem, as I saw it, that prompted me to pursue that thread for so
long.

------------------------------------------------------------------------
Internet.Usenet.Put_Signature 
  (Name => "John G. Volan",  Home_Email => "johnvolan@sprintmail.com",
   Slogan => "Ada95: The World's *FIRST* International-Standard OOPL",
   Disclaimer => "These opinions were never defined, so using them " & 
     "would be erroneous...or is that just nondeterministic now? :-) ");
------------------------------------------------------------------------




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: Redefinition of "=", elaboration and learning Ada
  1997-04-29  0:00                     ` Redefinition of "=", elaboration and learning Ada Mats Weber
@ 1997-04-29  0:00                       ` Robert A Duff
  1997-04-30  0:00                         ` Mats Weber
  0 siblings, 1 reply; 81+ messages in thread
From: Robert A Duff @ 1997-04-29  0:00 UTC (permalink / raw)



In article <3365E879.567F@elca-matrix.ch>,
Mats Weber  <Mats.Weber@elca-matrix.ch> wrote:
>Another reason why I think we should have... no reemergence of
>predefined operations ...

>Having predefined "=" reemerge in strange places when it's been
>redefined is also counterintuitive ...

You talk about "=" specifically, but above you say "operators",
presumably meaning all of them.  You still haven't given a complete
definition of when *all* operators should and should not "reemerge".

>And then try explaining to a novice programmer, without making him
>believe that the language definition is flawed, that if he makes his
>type tagged then everything will work fine :-)

OK, but try to explain to the novice why Text_IO.Integer_IO doesn't
work, because "mod" is redefined.

>What the user sees when he discovers packages and private types is that
>he can define abstractions that he can use without knowing how they are
>implemented. What he sees when he discovers a library of generic
>components is that he can instantiate them and then use them. In both
>cases, he hits what is IMO a severe pitfall: reemergence breaks his
>abstraction, and he (potentially) gets Program_Error when he
>instantiates his generic.

But having the user-defined operator used in a generic has a similar
problem.  How can I write Text_IO.Integer_IO (or a similar generic)?
How do I write the code that converts an integer to a string, if I can't
get my hands on the predefined ops?

I agree with you about elaboration -- the current rules are a mess.
And I mostly agree with you about "=".  But I don't see how you can
sensibly extend it to other ops.  Perhaps one wants to have *both*
available -- Eiffel is sort of like that.  You define something like
Basic_Compare and Compare, and then never override Basic_Compare (freeze
it).  So then a client can choose one or the other.  By default, they do
the same thing, but subclasses can override Compare.

- Bob




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-29  0:00                           ` Robert Dewar
@ 1997-04-29  0:00                             ` Robert I. Eachus
  0 siblings, 0 replies; 81+ messages in thread
From: Robert I. Eachus @ 1997-04-29  0:00 UTC (permalink / raw)




I said:

  >       And, yes, I have worked with programs where the "right"
  > elaboration order could only be determined from files read at
  > execution time.  Of course the programming team knew the right order
  > and embedded it in Elaborates and project documentation.

In article <dewar.862311716@merv> dewar@merv.cs.nyu.edu (Robert Dewar) writes:

   > I find this sort of thing bad programming practice. If you are
   > doing anything this fancy at elaboration time, it is likely to
   > get you into trouble, and you do better to make the "elaboration"
   > explicit rather than implicit, by introducing appropriate
   > explicit initialization routines.

    Unfortunately, in Ada 95 it is becoming more common, not because
programmers want to, but because of the rules surrounding tagged
types.  If you need to have a tagged type declaration depend on read
in from a file, especially for a controlled type, you have to open and
read the file before the start of the main program.  If you want to
keep all the configuration information in a single file, you then have
to control the order of elaboration.

    I don't find this particularly distressing.  But it is makework in
the sense that you should write "outer" exception handlers around every
package body sequence of statements, instead of once for the main
program.


--

					Robert I. Eachus

with Standard_Disclaimer;
use  Standard_Disclaimer;
function Message (Text: in Clever_Ideas) return Better_Ideas is...




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-29  0:00                       ` Matthew Heaney
@ 1997-04-30  0:00                         ` Jon S Anthony
  1997-05-01  0:00                         ` John G. Volan
  1997-05-02  0:00                         ` AQ&S Guidance on pragma Elaborate_Body John G. Volan
  2 siblings, 0 replies; 81+ messages in thread
From: Jon S Anthony @ 1997-04-30  0:00 UTC (permalink / raw)



In article <mheaney-ya023680002904972043250001@news.ni.net> mheaney@ni.net (Matthew Heaney) writes:

> I'm certainly not advocating large packages.  It's just that very often,
> there are a small number of types (read: 2) that need to know about each
> other's representation, or that one needs the know the represenation of the
> other (the iterator above).
> 
> This is just the concept of a friend in C++: to implement that in Ada, you
> put the types together in the same package.  No big deal.

I disagree.  "Friendship" typically has more to do with types that
need *implementation* information about one another in order to be
efficient.  And it is not bi directional - no mutual dependence. This
is almost always something that happens after the creation of one of
the types - a new type is defined which utilizes another as a
component [note: not as a parent class - that is handled by
inheritance and protection].  In Ada this sort of thing is handled by
child packages which can a) be defined way after the fact and b) still
have direct information about the implementation of the used type.

The notion of mutually dependent types is a very different thing
altogether.  In C++ this is handled (basically) via forward
declarations.  And there is no direct analog (capability) for this in
Ada except incomplete types.  But these require everything to be in
the same _immediate_ scope.

/Jon
-- 
Jon Anthony
Organon Motives, Inc.
Belmont, MA 02178
617.484.3383
jsa@organon.com





^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: Redefinition of "=", elaboration and learning Ada
  1997-04-29  0:00                       ` Robert A Duff
@ 1997-04-30  0:00                         ` Mats Weber
  0 siblings, 0 replies; 81+ messages in thread
From: Mats Weber @ 1997-04-30  0:00 UTC (permalink / raw)



Robert A Duff wrote:
> 
> In article <3365E879.567F@elca-matrix.ch>,
> Mats Weber  <Mats.Weber@elca-matrix.ch> wrote:
> >Another reason why I think we should have... no reemergence of
> >predefined operations ...
> 
> >Having predefined "=" reemerge in strange places when it's been
> >redefined is also counterintuitive ...
> 
> You talk about "=" specifically, but above you say "operators",
> presumably meaning all of them.  You still haven't given a complete
> definition of when *all* operators should and should not "reemerge".

Yes, I want the same treatment for all operators. I was just using
equality as an example because it is so important. A fairly complete
statement of what I would like (or would have liked) is in my thesis at
<http://lglwww.epfl.ch/Team/MW/Ada-Extensions/Ada-Extensions.html#RTFToC95>
I had overlooked the case statments at the time, but the general idea is
still valid.

> >And then try explaining to a novice programmer, without making him
> >believe that the language definition is flawed, that if he makes his
> >type tagged then everything will work fine :-)
> 
> OK, but try to explain to the novice why Text_IO.Integer_IO doesn't
> work, because "mod" is redefined.

I find that more natural (just my opinion): if you change the arithmetic
of a type, packages that use the arithmetic are naturally affected. And
Text_IO.Integer_IO could very well internally convert to another type in
order to get the normal arithmetic operations, if that is really
required.

Anyway, there are other similar situations in Ada 83:

type Tiny is range 1 .. 3;

generic
   type T is range <>;
pakcage P is ...

if P uses the literal 10 in its body, it will fail when instantiated
with
T => Tiny (and Ada 83 had no 'Base attribute to solve this).

> >What the user sees when he discovers packages and private types is that
> >he can define abstractions that he can use without knowing how they are
> >implemented. What he sees when he discovers a library of generic
> >components is that he can instantiate them and then use them. In both
> >cases, he hits what is IMO a severe pitfall: reemergence breaks his
> >abstraction, and he (potentially) gets Program_Error when he
> >instantiates his generic.
> 
> But having the user-defined operator used in a generic has a similar
> problem.  How can I write Text_IO.Integer_IO (or a similar generic)?
> How do I write the code that converts an integer to a string, if I can't
> get my hands on the predefined ops?

You can always get your hands on the predefined ops by declaring a new
type with the same (or maximal) range and type conversions.
Text_IO.Integer_IO had to do this anyway because of subtype problems
(excluding 0 for instance) and the lack of a usable 'base attribute in
Ada 83. So it is even likely that the existing Ada 83 implementations of
Text_IO.Integer_IO would work even if reemergence of predefined
operations was totally removed.

> I agree with you about elaboration -- the current rules are a mess.
> And I mostly agree with you about "=".  But I don't see how you can
> sensibly extend it to other ops.  Perhaps one wants to have *both*

What do you mean by "other ops" ? Things like case, or things like "+",
"*". For "+", "*", I would definitely take the same approach as for "=".

> available -- Eiffel is sort of like that.  You define something like
> Basic_Compare and Compare, and then never override Basic_Compare (freeze
> it).  So then a client can choose one or the other.  By default, they do
> the same thing, but subclasses can override Compare.

You can also get the predefined operations in Ada, see above.




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-30  0:00 W. Wesley Groleau (Wes)
@ 1997-04-30  0:00 ` Robert I. Eachus
  0 siblings, 0 replies; 81+ messages in thread
From: Robert I. Eachus @ 1997-04-30  0:00 UTC (permalink / raw)



In article <9704301359.AA06917@most> "W. Wesley Groleau (Wes)" <wwgrol@PSESERV3.FW.HAC.COM> writes:

  > The suggestion seemed to be making it less likely to crash a program
  > due to elaboration order problems.  The answer was that it would cause
  > serious incompatibilities in legacy code.

  > Tell me I didn't understand the suggestion, or I didn't understand the
  > answer, or even tell me I'm very confused... but please clarify, because
  > it sure looks like (to me) that this says it's a serious incompatibility
  > for a program to run that could not run before.

   You may not have understood, although the discussion did wander a
little.  The compatibility problem is that if you replace the current
dynamic rule with a static rule, you either remove some dependency
rules or replace them with others.  Then either programs that are now
legal with some elaboration order would have new legal elaboration
orders, or programs which are now legal would be illegal.  In the
first case, if the compiler happened to choose one of these
orders--and remember the original order may now be illegal--then you
have an upward incompatibility.  How serious an incompatibility?
Don't know, it would depend on the rules.  But due to the halting
problem mapping, we know that they would have to be different in some
way.

   In the second case, the problem of undetected errors wouldn't
occur, but you would have existing (and often large) programs that
would not legally link.  How big an issue?  Even one major program
that required a major software redesign would probably be an
unacceptable incompatibility.  And since, as I said, I know of
existing DoD software programs that would almost certainly fall in
this category, this option is unacceptable.

   You may think that programs which read config files during
elaboration and need a specific elaboration order that matches the
content of those files is horrible design.  I agree, but I am talking
reality here, not best practice.  (And in the actual I know of, it is
not as bad as it sounds--a client/server system where the clients
require one elaboration order and the server requires another.  The
clients and the server have different main programs, but you do have
library packages which differ only in the elaboration pragmas.
Clients and server are two different CSCIs.)
--

					Robert I. Eachus

with Standard_Disclaimer;
use  Standard_Disclaimer;
function Message (Text: in Clever_Ideas) return Better_Ideas is...




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
@ 1997-04-30  0:00 W. Wesley Groleau (Wes)
  1997-04-30  0:00 ` Robert I. Eachus
  0 siblings, 1 reply; 81+ messages in thread
From: W. Wesley Groleau (Wes) @ 1997-04-30  0:00 UTC (permalink / raw)



The suggestion seemed to be making it less likely to crash a program
due to elaboration order problems.  The answer was that it would cause
serious incompatibilities in legacy code.

Tell me I didn't understand the suggestion, or I didn't understand the
answer, or even tell me I'm very confused... but please clarify, because
it sure looks like (to me) that this says it's a serious incompatibility
for a program to run that could not run before.

---------------------------------------------------------------------------
W. Wesley Groleau (Wes)                                Office: 219-429-4923
Hughes Defense Communications (MS 10-41)                 Home: 219-471-7206
Fort Wayne,  IN   46808                  (Unix): wwgrol@pseserv3.fw.hac.com
--
SPAM should be sent to   I.want.one@mailbombs.for.idiots.org
If you want to be prosecuted under 27 USC 227, go ahead and send it here.
---------------------------------------------------------------------------




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-29  0:00                       ` Matthew Heaney
  1997-04-30  0:00                         ` Jon S Anthony
@ 1997-05-01  0:00                         ` John G. Volan
  1997-05-02  0:00                           ` Booch "forms" and child packages [was: AQ&S Guidance on pragma Elaborate_Body] John G. Volan
  1997-05-02  0:00                         ` AQ&S Guidance on pragma Elaborate_Body John G. Volan
  2 siblings, 1 reply; 81+ messages in thread
From: John G. Volan @ 1997-05-01  0:00 UTC (permalink / raw)



Matthew Heaney wrote:
> 
> In article <33660F4B.1B45@sprintmail.com>, johnvolan@sprintmail.com wrote:
[snip]
> >Of course, if it's just "a pair of abstract data types that are
> >intimately related", and that's all there is to it, then the cost of
> >abstraction-loss is relatively small, so co-encapsulation may be a
> >reasonable option.
> 
> That's all I was saying: a pair of ADTs that are intimately related.
> Here's an example.  In order to efficiently implement an active iterator,
> that iterator has to have knowledge of the representation of the data
> structure.

[snip bounded stack & iterator code]

> I'm certainly not advocating large packages.  It's just that very often,
> there are a small number of types (read: 2) that need to know about each
> other's representation, or that one needs the know the represenation of the
> other (the iterator above).
> 
> This is just the concept of a friend in C++: to implement that in Ada, you
> put the types together in the same package.  No big deal.

Um, sort of, but not exactly.  Friendship isn't symmetrical: your
friends can see your internals, but you can't see theirs (unless they
grant you friendship in turn). Whereas co-encapsulation doesn't
distinguish either party.

The closest analog to friends in Ada95 is child packages -- but that's
not an exact analogy either. More on this below...

> There is NO loss of abstraction when the stack and its iterator are
> co-located in the same package; 

There might not be any loss of abstraction from the point of view of
some third-party client that uses both abstractions, but there _is_ a
loss of abstraction _between_ the two types.  For an isolated case like
this, I admit the harm is small, and may be outweighed by other design
issues ("declaration span", as you put it).  But the fact remains that,
once you choose to co-encapsulate them, the stack type and the iterator
type are under no obligation to treat _each other_ as abstractions.

> the abstractions were meant to be used together.  

Oh really? Always? In every conceivable application?  What if there's an
application that doesn't need to use stack iterators, but only needs
some basic operations that work at the "whole-stack" level (e.g., push,
pop)?  Then the iterator stuff becomes extraneous.

As you point out yourself, the relationship here is really just one-way:
The iterator type needs to know about the implementation of the stack
type, but the stack type can be implemented quite nicely without any
notion of stack iterators. Rather than thinking of stacks and their
iterators as two inseparable parts of a single abstraction, you could
view stack iterators as an extension on the abstraction of stacks.

This suggests that iterators might be better off in a _child_ package.
The iterator type could still see the implementation details of the
stack type, but the original stack package wouldn't be "cluttered" with
this extra concept of an iterator.  This way, iterators are optional: If
an application needs them, it can "with" the child package; if it
doesn't need them, it won't have to pay the cost of having the iterator
code linked in.

A child package is something like a friend, but not quite: A child can
be declared after the fact without modifying the original parent
package.  The parent package doesn't have to mention the child (and
essentially _can't_).  But to become a friend of class X, this has to be
mentioned in advance as part of the declaration of class X.  If you
decide you want to confer friendship later, you must modify your
original class to do so.

> I don't subscribe to these gloom and doom scenarios about
> putting types together; this is how the language was _intended_ to be used.

Hey, it's a general purpose language with a lot of features.  It was
"intended" to support a _variety_ of coding styles and idioms.

> And it's certainly true that this affects understandability: it makes it
> MORE understandable when the "declaration span" is minimized.

But size and complexity also impact understandability: If you designate
something as a "single indivisible unit of abstraction", the larger that
unit happens to be, and the more pieces it contains, the more a user
must digest, and the harder it is to understand in one sitting.

Breaking things out into child packages allows the users take things in
stages: They can look at the stack package first, in isolation, and
understand how things work at the "whole-stack" level of granularity.
Then later they can look at the iterator child package and tackle the
concept of iterating over the stack at the finer, item-level of
granularity.

> I don't understand why a client needs to understand "internally" the
> Bounded_Stack and its iterator to use it:

If readers are presented with a package containing two abstract data
types, then they are faced with the prospect of understanding the
semantics of both ADTs together.  If the package is well-documented,
then the documentation will fully describe the outwardly-visible
behavior of two ADTs, including how they might interact with each
other.  If the package is poorly-documented (as is so often the case),
then readers will need to explore the package body, looking in detail at
the code for both ADTs, before they can be satisfied they understand
what either ADT is really all about.  Documentation sometimes lies, or
is obsolete, so users may need to pore over the body code anyway. 
Eventually, they might realize, for instance, that one of the ADTs is
actually entirely independent of the other, but it may take some mental
grinding before they can grok that.

> This is
> analogous to using a declare block to move declaration of an object as
> close as possible to its use.

I don't get this analogy at all -- in fact, I think it's more apt as an
analogy for the _opposite_ position: You have a declaration X that is
only needed in a local scope, so instead of declaring it in a more
global scope along with Y, Z, and W (which might be somewhat related to
X but are used more globally), you isolate X in its own a declare
block.  Similarly, you have an abstract data type X that you only need
for special purposes under special circumstances, so instead of lumping
it into the same package with Y, Z, and W (which might be somewhat
related X but are used more generally), you isolate X in its own package
(which might be a child package).

------------------------------------------------------------------------
Internet.Usenet.Put_Signature 
  (Name => "John G. Volan",  Home_Email => "johnvolan@sprintmail.com",
   Slogan => "Ada95: The World's *FIRST* International-Standard OOPL",
   Disclaimer => "These opinions were mever defined, so using them " & 
     "would be erroneous...or is that just nondeterministic now? :-) ");
------------------------------------------------------------------------




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Re: AQ&S Guidance on pragma Elaborate_Body
  1997-04-29  0:00                       ` Matthew Heaney
  1997-04-30  0:00                         ` Jon S Anthony
  1997-05-01  0:00                         ` John G. Volan
@ 1997-05-02  0:00                         ` John G. Volan
  2 siblings, 0 replies; 81+ messages in thread
From: John G. Volan @ 1997-05-02  0:00 UTC (permalink / raw)



Sorry to follow-up the same post twice, but:
Matthew Heaney wrote:
> 
> In article <33660F4B.1B45@sprintmail.com>, johnvolan@sprintmail.com wrote:
...
> >Of course, if it's just "a pair of abstract data types that are
> >intimately related", and that's all there is to it, then the cost of
> >abstraction-loss is relatively small, so co-encapsulation may be a
> >reasonable option.
> 
> That's all I was saying: a pair of ADTs that are intimately related.

But that's a straw man -- yes, sometimes there are isolated pairs of
abstractions that are so tightly coupled to each other that they really
do belong in the same package. I readily concede that possibility.  But
that's not what I was talking about when I said: 

> But what if that's not all there is to it?  Then the transitivity
> problem rears its ugly head: If class A is "intimately related" to class
> B, and class B is "intimately related" to class C, you may be forced to
> co-encapsulate A, B, and C, despite the fact that you did not envision
> any "intimate relationship" between A and C in your original software
> design.

I was actually talking about situations where the coupling between
classes was relatively loose: Let's just consider what happens in
general when classes collaborate with each other through basic
client-supplier relationships.  Each class, in general, can be both a
supplier of services to several other classes, and a client of the
services of several other classes.  As a supplier, each class should
provide an abstract interface for its clients; as a client, each class
should be happy to interact with its suppliers through their abstract
interfaces.  No client class should ever need to know anything about the
internal details of its suppliers.  That's what abstraction and
encapsulation are all about.

Now, in many cases, a class's set of clients and set of suppliers will
be disjoint sets.  But sometimes these two sets might just happen to
overlap, and in the intersection a class may be treating another class
both as a supplier and a client. In Ada95, this leads to a situation
where two package bodies "with" each other's specs.  Matthew, you argued
that this was a warning sign that the classes in the two packages were
"intimately related", constituting a single abstraction that ought to be
co-encapsulated into a single package.  Many have made this contention,
especially in the early days of Ada83.  But why should we make a
distinction between one kind of client (or supplier) and another?  

As I've already pointed out, co-encapsulating such pairs of classes
unnecessarily breaks down the abstraction barrier between them, and this
effect can be transitively infective.  There are, in fact, viable
software designs where every class's client-set and supplier-set happens
to be _identical_ -- i.e., _every_ association between classes gets
implemented as a mutual, bidirectional client-supplier relationship.  If
we go with what you advocate, then such designs are doomed to be
implemented as single, monolithic packages.  If so, then what was the
point of inventing packages in the first place?

------------------------------------------------------------------------
Internet.Usenet.Put_Signature 
  (Name => "John G. Volan",  Home_Email => "johnvolan@sprintmail.com",
   Slogan => "Ada95: The World's *FIRST* International-Standard OOPL",
   Disclaimer => "These opinions were never defined, so using them " & 
     "would be erroneous...or is that just nondeterministic now? :-) ");
------------------------------------------------------------------------




^ permalink raw reply	[flat|nested] 81+ messages in thread

* Booch "forms" and child packages [was: AQ&S Guidance on pragma Elaborate_Body]
  1997-05-01  0:00                         ` John G. Volan
@ 1997-05-02  0:00                           ` John G. Volan
  0 siblings, 0 replies; 81+ messages in thread
From: John G. Volan @ 1997-05-02  0:00 UTC (permalink / raw)



Apologies for following up my own post, but I had a thought:

John G. Volan wrote:
> 
> This suggests that iterators might be better off in a _child_ package.
> The iterator type could still see the implementation details of the
> stack type, but the original stack package wouldn't be "cluttered" with
> this extra concept of an iterator.  This way, iterators are optional: If
> an application needs them, it can "with" the child package; if it
> doesn't need them, it won't have to pay the cost of having the iterator
> code linked in.

One of the problems I had with the old Booch components was how Booch's
notion of "forms" introduced so much duplication of code into his ADT
library.  For instance, one dimension of form Booch considered was
whether an ADT package included support for iterators or not.  For every
package that did provided iterators, there would be another one that
didn't.  Often times both packages would be identical except for the
iterator stuff.  This must present something of a configuration
nightmare if you're the maintainer of the ADT library.  Multiply this by
all the various "form" dimensions Booch identified, and you get a
combinatorial explosion of slightly different versions.

I can see why Booch had to do this: Features such as iterators are
really optional, so clients ought to be allowed to select whether they
want all that baggage included into their applications or not.  In
Ada83, with its flat library space, the only recourse was to have
duplicate packages providing slightly different versions of the same
ADT.

In Ada95, you can avoid this problem (in some cases) by exploiting
Ada95's hierarchical library space: For instance, as I described above,
you can write a base ADT package without iterators, and then support the
iterator concept in a child package.  The iterator child package doesn't
duplicate any code from the parent ADT package, it just adds whatever
extra is needed to support this extra concept (and can exploit knowledge
of the private implementation details of the ADT in order to do so). 
Yet this arrangement still gives clients all the flexibility they need:
If they only need the base ADT, that's all they need to "with"; if they
also need iterators, they can "with" the child package, too. 
------------------------------------------------------------------------
Internet.Usenet.Put_Signature 
  (Name => "John G. Volan",  Home_Email => "johnvolan@sprintmail.com",
   Slogan => "Ada95: The World's *FIRST* International-Standard OOPL",
   Disclaimer => "These opinions were never defined, so using them " & 
     "would be erroneous...or is that just nondeterministic now? :-) ");
------------------------------------------------------------------------




^ permalink raw reply	[flat|nested] 81+ messages in thread

end of thread, other threads:[~1997-05-02  0:00 UTC | newest]

Thread overview: 81+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1997-04-18  0:00 AQ&S Guidance on pragma Elaborate_Body JP Thornley
1997-04-18  0:00 ` Robert A Duff
1997-04-21  0:00   ` Michael F Brenner
1997-04-22  0:00     ` Robert A Duff
1997-04-18  0:00 ` Robert Dewar
1997-04-19  0:00   ` Michael Paus
1997-04-19  0:00     ` Robert A Duff
1997-04-21  0:00       ` Robert Dewar
1997-04-23  0:00         ` Robert A Duff
1997-04-23  0:00           ` Robert Dewar
1997-04-24  0:00             ` Robert A Duff
1997-04-24  0:00               ` Robert Dewar
1997-04-24  0:00                 ` Robert Dewar
1997-04-25  0:00                   ` Robert A Duff
1997-04-25  0:00                 ` Mats Weber
1997-04-25  0:00                   ` Robert I. Eachus
1997-04-26  0:00                     ` Nick Roberts
1997-04-26  0:00                       ` Robert Dewar
1997-04-28  0:00                         ` Robert I. Eachus
1997-04-29  0:00                           ` Robert Dewar
1997-04-29  0:00                             ` Robert I. Eachus
1997-04-27  0:00                   ` Robert Dewar
1997-04-28  0:00                     ` Mats Weber
1997-04-29  0:00                     ` Redefinition of "=", elaboration and learning Ada Mats Weber
1997-04-29  0:00                       ` Robert A Duff
1997-04-30  0:00                         ` Mats Weber
1997-04-26  0:00                 ` AQ&S Guidance on pragma Elaborate_Body Nick Roberts
1997-04-26  0:00                   ` Robert Dewar
1997-04-24  0:00           ` Mats Weber
1997-04-24  0:00             ` Robert A Duff
1997-04-24  0:00               ` Robert Dewar
1997-04-25  0:00             ` Robert Dewar
1997-04-20  0:00     ` Robert Dewar
1997-04-21  0:00     ` Michael F Brenner
1997-04-23  0:00       ` Robert Dewar
1997-04-24  0:00         ` Laurent Guerby
1997-04-24  0:00         ` Matthew Heaney
1997-04-24  0:00           ` Jon S Anthony
1997-04-24  0:00             ` Matthew Heaney
1997-04-26  0:00               ` Nick Roberts
1997-04-26  0:00                 ` Matthew Heaney
1997-04-26  0:00                 ` Robert A Duff
1997-04-26  0:00               ` Robert Dewar
1997-04-26  0:00                 ` Matthew Heaney
1997-04-27  0:00                   ` Robert Dewar
1997-04-29  0:00                     ` John G. Volan
1997-04-29  0:00                       ` Matthew Heaney
1997-04-30  0:00                         ` Jon S Anthony
1997-05-01  0:00                         ` John G. Volan
1997-05-02  0:00                           ` Booch "forms" and child packages [was: AQ&S Guidance on pragma Elaborate_Body] John G. Volan
1997-05-02  0:00                         ` AQ&S Guidance on pragma Elaborate_Body John G. Volan
1997-04-25  0:00             ` Robert Dewar
1997-04-24  0:00           ` Robert A Duff
1997-04-24  0:00           ` Robert Dewar
1997-04-25  0:00           ` Michael F Brenner
1997-04-26  0:00             ` Nick Roberts
1997-04-20  0:00 ` Doug Smith
1997-04-20  0:00   ` Robert Dewar
1997-04-21  0:00     ` Matthew Heaney
1997-04-21  0:00       ` Robert A Duff
1997-04-21  0:00         ` Matthew Heaney
1997-04-21  0:00           ` Robert A Duff
1997-04-21  0:00           ` Matthew Heaney
1997-04-22  0:00             ` Robert A Duff
1997-04-22  0:00               ` Matthew Heaney
1997-04-22  0:00                 ` Robert A Duff
1997-04-22  0:00                   ` Matthew Heaney
1997-04-23  0:00                     ` Robert A Duff
1997-04-24  0:00                       ` Matthew Heaney
1997-04-24  0:00                         ` Robert A Duff
1997-04-25  0:00                       ` Robert Dewar
1997-04-23  0:00                     ` Robert Dewar
1997-04-24  0:00                 ` Robert Dewar
1997-04-24  0:00                   ` Robert A Duff
1997-04-22  0:00             ` Mats Weber
1997-04-23  0:00             ` Robert Dewar
1997-04-21  0:00         ` Robert Dewar
1997-04-22  0:00           ` Robert A Duff
1997-04-24  0:00             ` Robert Dewar
  -- strict thread matches above, loose matches on Subject: below --
1997-04-30  0:00 W. Wesley Groleau (Wes)
1997-04-30  0:00 ` Robert I. Eachus

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox