Version 1.8 of ais/ai-00262.txt

Unformatted version of ais/ai-00262.txt version 1.8
Other versions for file ais/ai-00262.txt

!standard 10.01.02 (04)          01-06-04 AI95-00262/02
!standard 10.01.02 (08)
!class amendment 01-02-15
!status work item 01-02-15
!status received 01-02-15
!priority Medium
!difficulty Hard
!subject Access to private units in the private part
!summary
The context clause "private with" makes a unit available only in the private part of a package.
!problem
The private part of a package includes part of the implementation of the package. For instance, the components of a private type may include handles and other low-level data structures.
Ada 95 provides private packages to organize the implementation of a subsystem. Unfortunately, these packages cannot be used in the private part of a public package - the context clause for the private package is illegal.
This makes it difficult to use private packages to organize implementation details of a subsystem.
For example, Claw puts most of the Win32 interface details into a set of private packages. However, the inability to use the contents of those packages in private parts meant that various workarounds had to be used:
Some types were moved to the ultimate parent package (for instance,
all of the handle types);
Many parameters and constants were declared to be of predefined types,
so that the predefined types could be used in the private part (thus losing the benefits of strong typing);
Initializations of components were done in an Initialize routine in the
package body (so that the constants declared in the private packages could be used).
All of this bending of the design was necessary because private packages could not be used in the private part of a public package.
!proposal
We propose that the qualifier "private" is optionally added to with_clauses. A library unit mentioned in a with_clause including the "private" qualifier cannot be referenced in the visible part of the package. Otherwise, the processing of with clauses is unchanged.
!wording
Change 10.1.2(4):
with_clause ::= [private] with library_unit_name {, library_unit_name}
Change 10.1.2(8):
If a with_clause of a given compilation_unit mentions a private child of some library unit, then the given compilation_unit shall be one of:
* the declaration of a private descendant of that library unit;
* the body or subunit of a (public or private) descendant of that library unit; or
* the declaration of a public descendant of that library unit, and the with_clause shall include the reserved work private.
Add after 10.1.2(8):
In the visible part of a package or generic package, a name shall not denote a library unit named only in a with_clause which includes the reserved word private.
!discussion
Private withs do not allow access to the library unit in the visible part of the package or generic package. This rule is necessary to preserve the purpose of 10.1.2(8): To prevent a private child from being visible (or even semantically depended-on) from outside the subsystem rooted at its parent. [AARM 10.1.2(8.a)] This limitation has the pleasant side effect of adding another capability beyond that described in the problem statement: it allows the declaration that a unit of any sort) will not be used in the public part of a package. This additional documentation can be valuable to both users and automated analysis tools. Some reviewers consider this capability more important than withing private units.
Reference to private withed items in the private part is a legality rule, rather than a visibility rule, in order to avoid a form of Beaujolais when a declaration is moved from the visible part to the private part (or vice-versa). Since such moves are common, it is important to avoid them. With the legality rule, the declarations will be illegal in the public part.
For example:
package A is function B return Integer; end A;
function B return Integer;
with A; private with B; package C is use A; V1 : Integer := B; -- (1) private V2 : Integer := B; -- (2) end C;
If we use a visibility rule saying that library subprogram B is not in scope in the visible part of C, then the B at (1) resolves to A.B, while (2) resolves to library unit B. Simply moving a declaration could silently change its meaning: a classic Beaujolais effect.
With the legality rule as proposed, the B at (1) is illegal. If the user meant A.B, they can still say that.
Private withs are allowed on bodies. They are equivalent to regular withs there. We could make them illegal on bodies, but there doesn't seem to be any value to doing that.
Ada allows a unit to be withed multiple times in a single context clause. In order to handle this, we have proposed that the legality rule is written so that if a unit is withed by both a regular with and a private with, the legality rule does not apply. Alternatively, we could have made such a combination illegal. But that doesn't seem to buy much, and it adds an additional new check.
!example
As described in the problem statement, the low-level Win32 interface for Claw are defined in a series of private packages. However, Ada 95 prevents these packages from being accessed in the private part of the public types. The proposed feature eliminates that problem.
The low-level interface for an image list package might look like:
package Claw.Low_Level_Image_Lists is type HImage_List is new DWord; type IL_Flags is new UInt; ILR_DEFAULTCOLOR : constant IL_Flags := 16#0000#; ILR_MONOCHROME : constant IL_Flags := 16#0001#; ... type Image_Kind_Type is (Bitmap, Icon, Cursor); for Image_Kind_Type use (Bitmap => 0, Icon => 1, Cursor => 2);
function Image_List_Load_Image ( Name : in Claw.Win32.LPCStr; Width : in Claw.Int; Image_Kind : in Image_Kind_Type; Flags : in IL_Flags) return HImage_List; pragma Import (StdCall, Image_List_Load_Image, "ImageList_LoadImageA");
... end Claw.Low_Level_Image_Lists;
The high-level interface for the image list package might look like:
private with Claw.Low_Level_Image_Lists; package Claw.Image_List is type Image_List_Type is tagged private; procedure Load_Image (Image_List : in out Image_List_Type; Image : in String; Monochrome : in Boolean := False); ... private type Image_List_Type is tagged record Handle : Claw.Low_Level_Image_Lists.HImage_List; Flags : Claw.Low_Level_Image_Lists.IL_Flags; ... end record; end Claw.Image_List;
A reference to Claw.Low_Level_Image_Lists would still be illegal in the visible part of Claw.Image_List.
!ACATS test
A C-Test should be created to check that a private child can be private withed into a sibling unit. A B-Test should be created to check that a private withed library unit cannot be named in the visible part of a package or generic package.
!appendix

From: Randy Brukardt [Randy@RRSoftware.Com]
Sent: Wednesday, February 14, 2001 1:54 PM

A recent discussion on comp.lang.ada proposed a "with private" context
clause, which would allow the withed entity to be used only in the private
part of a package.

The primary benefit of such a feature is that it would allow the use of
private packages in the private part of a public package. This is currently
impossible, and it forces reorganization of packages.

For instance, originally in Claw we put the low-level Win32 interface in a
series of private packages. However, these packages cannot be accessed in
the private part of the public types. That means that either we had to avoid
strong typing in the low-level interface, or abandon the private package
structure.

For instance, a possible image list package would look like:

    package Claw.Low_Level_Image_Lists is
        type HImage_List is new DWord;
        type IL_Flags is new UInt;
        ILR_DEFAULTCOLOR : constant IL_Flags := 16#0000#;
        ILR_MONOCHROME   : constant IL_Flags := 16#0001#;
         ...
        type Image_Kind_Type is (Bitmap, Icon, Cursor);
        for Image_Kind_Type use (Bitmap => 0, Icon => 1, Cursor => 2);

        function Image_List_Load_Image (
                  Name     : in Claw.Win32.LPCStr;
                  Width    : in Claw.Int;
                  Image_Kind : in Image_Kind_Type;
                  Flags    : in IL_Flags) return HImage_List;
        pragma Import (StdCall, Image_List_Load_Image,
                  "ImageList_LoadImageA");

          ...
    end Claw.Low_Level_Image_Lists;

    with Claw.Low_Level_Image_Lists; -- Illegal!
    package Claw.Image_List is
       type Image_List_Type is tagged private;
       procedure Load_Image (Image_List : in out Image_List_Type;
                             Image : in String;
			     Monochrome : in Boolean := False);
         ...
    private
       type Image_List_Type is tagged record
	Handle : Claw.Low_Level_Image_Lists.HImage_List;
            Flags : Claw.Low_Level_Image_Lists.IL_Flags;
              ...
       end record;
    end Claw.Image_List;

We ended up moving things to the private part of the parent (Claw) [which
makes it very large], eliminating some of the strong typing (since users
don't access this code, it only makes our job harder), and not bothering
with the private packages in the first place (putting the entire contents
into the private part of the Image_List package; but of course that mixes up
the high-level and low-level code).

----

I haven't yet looked at the visibility ramifications of such a feature, but
I will do so if there is sufficient interest in working out a full proposal.

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

From: dewar@gnat.com
Sent: Wednesday, February 14, 2001 4:50 PM

<<The primary benefit of such a feature is that it would allow the use of
private packages in the private part of a public package. This is currently
impossible, and it forces reorganization of packages.>>

I think it has a much more significant benefit, which is that it makes
it easier to separate the public and private part into separate files,
where the private part has multiple implementations. We have often needed
that capability, and in fact on our enhancement list for GNAT is to allow
the private part to be in a separate file.

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

From: Pascal Leroy [pleroy@rational.com]
Sent: Thursday, February 15, 2001 2:01 AM

> A recent discussion on comp.lang.ada proposed a "with private" context
> clause, which would allow the withed entity to be used only in the private
> part of a package.

I agree that this would be a very useful thing to have.  There is another
benefit, in addition to the interaction with private children: by making a
with clause private, you ensure that in the course of maintenance it won't
be used to write declarations in the visible part, i.e., the stuff in the
withed unit won't be reexported.

Moreover, it seems quite easy to (1) specify in RM terms and (2) implement.

A much better usefulness/complexity ratio than extensible enums, if you ask
me.

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

From: dewar@gnat.com
Sent: Thursday, February 15, 2001 12:15 PM

I very much agree with this asessment!

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

From: Tucker Taft
Sent: Thursday, February 15, 2001 8:57 AM

Randy Brukardt wrote:
>
> A recent discussion on comp.lang.ada proposed a "with private" context
> clause, which would allow the withed entity to be used only in the private
> part of a package.
>
> The primary benefit of such a feature is that it would allow the use of
> private packages in the private part of a public package. This is currently
> impossible, and it forces reorganization of packages.

This is not a trivial change.  Currently, private children are *never*
needed at compile-time of public specs (ignoring macro expansion
requirements related to generics and inlines, of course!).  This
allows a strong physical separation between the public specs and the
"implementation" of a subsystem.  I would be reluctant to see this
principle violated.

In fact, "private" children should more properly be
called "body" children.

>
> For instance, originally in Claw we put the low-level Win32 interface in a
> series of private packages. However, these packages cannot be accessed in
> the private part of the public types. That means that either we had to avoid
> strong typing in the low-level interface, or abandon the private package
> structure.

An alternative structure is to make these *public* packages
but with essentially all of their declarations in the private part.
Is there a reason why this wouldn't work?

>
> For instance, a possible image list package would look like:
>
>     package Claw.Low_Level_Image_Lists is
>         type HImage_List is new DWord;
>         type IL_Flags is new UInt;
>         ILR_DEFAULTCOLOR : constant IL_Flags := 16#0000#;
>         ILR_MONOCHROME   : constant IL_Flags := 16#0001#;
>          ...
>         type Image_Kind_Type is (Bitmap, Icon, Cursor);
>         for Image_Kind_Type use (Bitmap => 0, Icon => 1, Cursor => 2);
>
>         function Image_List_Load_Image (Name     : in Claw.Win32.LPCStr;
>                                         Width    : in Claw.Int;
>                                         Image_Kind : in Image_Kind_Type;
>                                         Flags    : in IL_Flags) return
> HImage_List;
>         pragma Import (StdCall, Image_List_Load_Image,
> "ImageList_LoadImageA");
>
>           ...
>     end Claw.Low_Level_Image_Lists;
>
>     with Claw.Low_Level_Image_Lists; -- Illegal!
>     package Claw.Image_List is
>        type Image_List_Type is tagged private;
>        procedure Load_Image (Image_List : in out Image_List_Type; Image : in
> String;
>                               Monochrome : in Boolean := False);
>          ...
>     private
>        type Image_List_Type is tagged record
>         Handle : Claw.Low_Level_Image_Lists.HImage_List;
>             Flags : Claw.Low_Level_Image_Lists.IL_Flags;
>               ...
>        end record;
>     end Claw.Image_List;
>
> We ended up moving things to the private part of the parent (Claw) [which
> makes it very large], eliminating some of the strong typing (since users
> don't access this code, it only makes our job harder), and not bothering
> with the private packages in the first place (putting the entire contents
> into the private part of the Image_List package; but of course that mixes up
> the high-level and low-level code).

I would think public children with essentially all of their interesting
decls in their private part would help break these big private parts
up.

>
> ----
>
> I haven't yet looked at the visibility ramifications of such a feature, but
> I will do so if there is sufficient interest in working out a full proposal.

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

From: Pascal Leroy
Sent: Thursday, February 15, 2001 9:50 AM

> An alternative structure is to make these *public* packages
> but with essentially all of their declarations in the private part.
> Is there a reason why this wouldn't work?

I don't understand this.  Declarations in the private part are not visible
anyway, so what good would it do?  Could you give an example of what you
have in mind?

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

From: Randy Brukardt [Randy@RRSoftware.Com]
Sent: Thursday, February 15, 2001 11:49 AM

> An alternative structure is to make these *public* packages
> but with essentially all of their declarations in the private part.
> Is there a reason why this wouldn't work?

Sure, no one would have visibility on the declarations in the private part.
How could you use them?

You must have had something else in mind; could you recast my example as you
suggest?

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

From: Tucker Taft
Sent: Thursday, February 15, 2001 12:11 PM

Pascal Leroy wrote:
>
> > An alternative structure is to make these *public* packages
> > but with essentially all of their declarations in the private part.
> > Is there a reason why this wouldn't work?
>
> I don't understand this.  Declarations in the private part are not visible
> anyway, so what good would it do?  Could you give an example of what you
> have in mind?

Good point.  I realize I was misremembering a suggestion
by Robert Eachus.  The "trick" is to have an immediate parent
which has all of its declarations in its private part, and then
use renaming to rename the child so that it is directly beneath
its grandparent.  For example:

    package Claw is
       ...
    end Claw;

    package Claw.Hidden is
      private
         -- lots of private junk
    end Claw.Hidden;

    package Claw.Hidden.Child is
      -- useful stuff
    private
      -- Claw.Hidden private part is visible here
    end Claw.Hidden.Child;

    with Claw.Hidden.Child;
    package Claw.Child renames Claw.Hidden.Child;

Not particularly elegant, but might solve the problem.

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

From: Randy Brukardt
Sent: Thursday, February 15, 2001 1:49 PM

Well, Claw has 6 private low-level packages (otherwise, *they* get too
large -- Win32 is huge). Would you like to try this solution for a set of
interrelated private packages?? :-) :-)

This is, after all, essentially what we did to work around this problem: we
declared lots of stuff in the private part of the ultimate parent (Claw),
but the effect is to bloat that package. It doesn't provide a solution, just
a work-around.

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

From: Randy Brukardt
Sent: Thursday, February 15, 2001 6:19 PM

We've gotten so fixed on Tucker's silly workaround suggestion that no one
has addressed his real concerns...

> This is not a trivial change.  Currently, private children are *never*
> needed at compile-time of public specs (ignoring macro expansion
> requirements related to generics and inlines, of course!).  This
> allows a strong physical separation between the public specs and the
> "implementation" of a subsystem.  I would be reluctant to see this
> principle violated.
>
> In fact, "private" children should more properly be
> called "body" children.

You are forgetting that the private part of a spec really is part of the
*implementation* of a unit, not part of the specification. So, the current
situation is that part of the implementation can use private units, and part
don't.

If you really want to have this sort of physical separation, we have to have
some way to put private parts in a separate file. That seems like a much
more radical change than "with private" would be.

Given that Robert indicated that ACT was thinking about implementing
something on that line, perhaps it would be worthwhile to engage in a bit of
on-the-fly language design.

Here are my assumptions:

  1) We don't want to change the invariant that the size of an Ada entity is
known once the spec is compiled. Eliminating that would be a massive change
to Ada compilers, and I really doubt that any such idea could get much
support from implementors.
  2) We do want to allow a separate private part have its own context
clause, and allow private units to be withed there.
  3) We need rules that would work both in source-based and "traditional"
compiler structures.
  4) We don't need any additional functionality in the private part other
than (2).

(1) implies that the separate private part must be available when the
specification is compiled. For the "traditional" model, that means either it
must be compiled first (but what could that mean? It could depend on parts
of the spec) or compiled at the same time as the spec. For the
"source-based" model, this means that the source must be available when the
spec is compiled/used.

Assuming that the private part is available when the spec is compiled, the
separate private part would essentially be an "include" file, and shouldn't
cost much additional work in compilers. Most of the work would go into the
functionality of "with private".

Syntax for this seems hard to come up with. The best I can come up with
would be:

    <context_clause>
    package <Name> is
        <public declarations>
    private is separate;
    end <Name>;

    <context clause>
    separate (<Name>)
    package <Name> private is
        <private declarations>
    end <Name>;

Clearly, we would need a rule requiring the separate private to be available
when the spec is compiled -- and that is very different than other
separates, which are "real" separate compilation. We also would need to
extend the permissions in 10.1.4(7) to allow removing the spec from the
library when the private part is "added to the environment".

I guess my primary objection to this idea is that it isn't what it looks
like -- the private part is not really independent of the specification. But
that isn't necessarily a big deal (and different syntax might help here).

Tuck, would a proposal on this line address your objection??

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

From: Robert A Duff
Sent: Thursday, February 15, 2001 8:14 PM

Randy suggests:

> Syntax for this seems hard to come up with. The best I can come up with
> would be:
>
>     <context_clause>
>     package <Name> is
>         <public declarations>
>     private is separate;
>     end <Name>;
>
>     <context clause>
>     separate (<Name>)
>     package <Name> private is
>         <private declarations>
>     end <Name>;

If I were designing the language from scratch, I would put the "imports"
(with_clauses) *inside* the thing importing.  And the private part would
be a separate syntactic entity, presumably in a separate file.  Or it
wouldn't exist at all.

But we're stuck with private parts.  Sigh.

I suggest this syntax:

    <context_clause>
    package <Name> is
        <public declarations>
    end <Name>;

    <context clause>
    package <Name> private is
        <private declarations>
    end <Name>;

Presumably, most compilers would require that the private part "exist"
when compiling clients, and when compiling the visible part itself.
No need to make it look like a subunit, IMHO.

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

From: Randy Brukardt
Sent: Thursday, February 15, 2001 8:33 PM

> I suggest this syntax:
>
>     <context_clause>
>     package <Name> is
>         <public declarations>
>     end <Name>;
>
>     <context clause>
>     package <Name> private is
>         <private declarations>
>     end <Name>;
>
> Presumably, most compilers would require that the private part "exist"
> when compiling clients, and when compiling the visible part itself.
> No need to make it look like a subunit, IMHO.

The problem with that is that a compiler couldn't tell the difference
between a package spec that has a separate private part, and one that has no
private part at all. We fixed problems like that in Ada 95, I don't think
we'd want to reintroduce them. So there has to be some sort of stub in the
package spec.

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

From: Pascal Leroy
Sent: Friday, February 16, 2001 2:44 AM

> > This is not a trivial change.  Currently, private children are *never*
> > needed at compile-time of public specs (ignoring macro expansion
> > requirements related to generics and inlines, of course!).  This
> > allows a strong physical separation between the public specs and the
> > "implementation" of a subsystem.  I would be reluctant to see this
> > principle violated.

I don't see why Tuck considers this principle so important.  This is really
throwing the baby out with the bathwater.  I have run into the problem
decribed by Randy several times myself (among other things, in implementing
some of the language-defined units, eg strings and I/O) and my conclusion
was that private units are like limited private types, they look nice but
are unusable in practice.

> > In fact, "private" children should more properly be
> > called "body" children.
>
> You are forgetting that the private part of a spec really is part of the
> *implementation* of a unit, not part of the specification. So, the current
> situation is that part of the implementation can use private units, and
> part don't.

Absolutely.  This is why Tuck's principle is flawed in my opinion.

> If you really want to have this sort of physical separation, we have to have
> some way to put private parts in a separate file. That seems like a much
> more radical change than "with private" would be.

I don't like the direction that this discussion is taking.  "with private"
is really quite simple, and I suspect we could come up with a proposal
and/or experimental implementations quickly, if we could overcome Tuck's
reluctance.  On the other hand, separate private parts are a much bigger
change, especially for library-based compilers (I don't understand what it
means for the separate private part to be "available" when compiling the
spec; this doesn't make any sense for library-based compilers; if it did, we
would not have trouble with mutually-dependent packages).

> Given that Robert indicated that ACT was thinking about implementing
> something on that line...

And that's fine.  First because GNAT can do what it wants in a non-standard
mode (I'm told that it can even compile C code in a non-standard mode :-)
and second because it's useful to do experiments on possible extensions to
the language.

But if we want a solution quickly (and that seems important because it is a
real problem that real people are having right now) then it will have to be
some form of "with private".

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

From: Ehud Lamm
Sent: Friday, February 16, 2001 8:38 AM
>
> I don't like the direction that this discussion is taking.  "with private"
> is really quite simple, and I suspect we could come up with a proposal
> and/or experimental implementations quickly, if we could overcome Tuck's
> reluctance.


I agree. It sems pretty much straightforward, and has some important
benefits for readability and maintenance. As this relates to layered
achitectural style, which I find to be the corner stone of abstraction, I
find this esp. important.
It also makes the progammers decision explicit: Does he want the unit to be
visibile in the public part of the spec? Making such decisions explicit was
mentioned in the  steelman, and for good reasons.

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

From: Robert A Duff
Sent: Friday, February 16, 2001 10:37 AM

Randy says:

> The problem with that is that a compiler couldn't tell the difference
> between a package spec that has a separate private part, and one that has no
> private part at all. We fixed problems like that in Ada 95, I don't think
> we'd want to reintroduce them.

We fixed one "problem" like that: optional package bodies.  However, I
think that was a mistake.  I think there *was* no language problem.
The problem was an implementation one: Ada 83 compilers ought to have
checked whether an optional body exists.  They didn't, and that led to
the error-prone behavior.

Note that GNAT originally had the *same* error-prone behavior.  If an
optional body existed on disk, GNAT would silently ignore it.  GNAT
would only give the error message if you explicitly asked it to compile
the file, thus defeating the whole point of the new language rule
disallowing optional bodies.  My point here is not to gripe about GNAT
(after all, they have long-since fixed that bug); my point is that this
is an issue of how you define what's in the program library (that is, an
implementation issue), and not a language issue.

>... So there has to be some sort of stub in the
> package spec.

I don't agree.

Pascal says:

> I don't like the direction that this discussion is taking.  "with private"
> is really quite simple, and I suspect we could come up with a proposal
> and/or experimental implementations quickly, if we could overcome Tuck's
> reluctance.  On the other hand, separate private parts are a much bigger
> change, ...

True.  But "with private" seems aesthetically unappealing to me.

>...especially for library-based compilers (I don't understand what it
> means for the separate private part to be "available" when compiling the
> spec; this doesn't make any sense for library-based compilers; if it did, we
> would not have trouble with mutually-dependent packages).

I don't see what the big deal is.  Your compiler has some file-naming
conventions (foo.1.ada, etc), so it seems like you could train it to
look for private parts according to some convention.  Or require the
user to tell you where it is.

But if you and Randy both say so, I suppose I must be wrong.

> > Given that Robert indicated that ACT was thinking about implementing
> > something on that line...
>
> And that's fine.  First because GNAT can do what it wants in a non-standard
> mode (I'm told that it can even compile C code in a non-standard mode :-)
> and second because it's useful to do experiments on possible extensions to
> the language.

Well, the feature won't be useful to *me* unless it's implemented by
more than just GNAT.

> But if we want a solution quickly (and that seems important because it is a
> real problem that real people are having right now) then it will have to be
> some form of "with private".

Perhaps you're right, but "with private" will look pretty silly if and
when we have private parts in separate files, or Tuck's suggestions
about putting things in the body.

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

From: Randy Brukardt
Sent: Friday, February 16, 2001 10:37 PM

Bob says, replying to me:

> Randy says:
>
> > The problem with that is that a compiler couldn't tell the difference
> > between a package spec that has a separate private part, and one that has no
> > private part at all. We fixed problems like that in Ada 95, I don't think
> > we'd want to reintroduce them.
>
> We fixed one "problem" like that: optional package bodies.  However, I
> think that was a mistake.  I think there *was* no language problem.
> The problem was an implementation one: Ada 83 compilers ought to have
> checked whether an optional body exists.  They didn't, and that led to
> the error-prone behavior.

In a library-based compiler, that is impossible. If the code hasn't been
submitted to the compiler, it doesn't know about it. In a source-based
compiler, that *might* be possible.

But in any case, that wasn't the problem. The problem with Ada 83 was that
if the body became obsolete, it silently disappeared from the program. Some
compilers gave warnings about this; but doing anything else was incorrect.
There even was an ACVC test to force this (non-friendly) behavior: Janus/Ada
gave a link error until we had to "fix" it to ignore the error in that one
special case just so we could validate.

In our case, at least we gave a warning, because we had to write a bunch of
extra code to make that ACVC test pass. The whole point of the change in Ada
95 was to get rid of that ACVC test.

> >... So there has to be some sort of stub in the
> > package spec.
>
> I don't agree.

I still don't agree with you.

Then Bob replies to Pascal:

> Pascal says:
>
> > I don't like the direction that this discussion is taking.  "with private"
> > is really quite simple, and I suspect we could come up with a proposal
> > and/or experimental implementations quickly, if we could overcome Tuck's
> > reluctance.  On the other hand, separate private parts are a much bigger
> > change, ...
>
> True.  But "with private" seems aesthetically unappealing to me.

Can't argue with that. Which is why I suggested a brief foray into other
possible solutions.

> >...especially for library-based compilers (I don't understand what it
> > means for the separate private part to be "available" when compiling the
> > spec; this doesn't make any sense for library-based compilers; if it did, we
> > would not have trouble with mutually-dependent packages).
>
> I don't see what the big deal is.  Your compiler has some file-naming
> conventions (foo.1.ada, etc), so it seems like you could train it to
> look for private parts according to some convention.  Or require the
> user to tell you where it is.
>
> But if you and Randy both say so, I suppose I must be wrong.

You're wrong. :-)

For Janus/Ada, the compiler has no naming conventions. (The Make tool does,
but that's a different issue). The only units that the compiler (and program
library) knows about are those that it has been given to compile. There may
be other source laying around, but it is irrelevant.

To implement some sort of separate private part, we'd have to "pre-compile"
it (probably just do a syntax check) to insert it into the library; then it
would really be compiled when the stub was seen. Janus/Ada is syntax-based:
the only time it does something is when the syntax demands it. Thus, reading
the library happens only when there is a stub.

I think you're also putting a terrible burden on the reader of the source if
there is no indication that there is a private part missing. How would they
know if an "optional" private part (just like an optional body, not required
because there is nothing deferred) even exists? We don't want to design
features that make Ada HARDER to maintain.

Anyway, this would put a terrible new burden on the tools (especially the
make tool), and I suspect it will be a non-starter for that reason alone.

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

From: Tucker Taft
Sent: Friday, February 16, 2001 8:46 AM

Randy Brukardt wrote:
>
> We've gotten so fixed on Tucker's silly workaround suggestion ...

Hey, I resent that ;-).

> ... that no one has addressed his real concerns...
>
> > This is not a trivial change.  Currently, private children are *never*
> > needed at compile-time of public specs (ignoring macro expansion
> > requirements related to generics and inlines, of course!).  This
> > allows a strong physical separation between the public specs and the
> > "implementation" of a subsystem.  I would be reluctant to see this
> > principle violated.
> >
> > In fact, "private" children should more properly be
> > called "body" children.
>
> You are forgetting that the private part of a spec really is part of the
> *implementation* of a unit, not part of the specification. So, the current
> situation is that part of the implementation can use private units, and part
> don't.

I don't see it that way.  When I present Ada to neophytes, I say
the visible part is the "logical interface" and the
private part of the spec is the "physical interface" and
the body is the "implemenation."

I think rather than trying to make private parts more sophisticated,
we should investigate simplifying them, and pushing more stuff
to the body.  It is clear that in some cases, the size of a type
is not known at compile-time, e.g. when the type includes a nested
array component whose length is not known at compile time.  This
implies that compilers have no problem dealing with such types,
and would seem a small step to introduce a kind of private
type where the full type information is deferred to the body.
(For compilers like RR where nested dynamic components are handled
with a level of indirection, clearly such a private type would also
involve a level of indirection.)

The other thing which really wants to be deferred to a body
is the full declaration for a deferred constant, so that large constant
tables can be given in a body rather than in a spec.

So...

How about something like:

   type Priv(Discrim : Integer) is private;
   Null_Priv : constant Priv;

 private

   type Priv(Discrim : Integer) is record in body;
   Null_Priv : constant Priv in body;


Clearly declaring an object of type Priv or using Null_Priv implies
an elaboration check that the corresponding full declaration in the
body has been elaborated.  Something like this additional elaboration
check will be needed in any case if we postpone elaboration of
the entire private part.

Of course only composite types could have their full declaration
postponed into the body.  Otherwise pass by copy could be
truly nasty.

> ...
> Tuck, would a proposal on this line address your objection??

Not really.  I prefer something more along the lines above, where
individual declarations can have their full definitions deferred
into the body.

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

From: Robert A Duff [bobduff@world.std.com]
Sent: Friday, February 16, 2001 4:46 PM

> I don't see it that way.  When I present Ada to neophytes, I say
> the visible part is the "logical interface" and the
> private part of the spec is the "physical interface" and
> the body is the "implemenation."

I think that view of private parts is rather unusual.  I find it strange
to call the private part an "interface".

Do you consider a procedure body to be a "physical interface" in the
case where it is inlined?  It's just like a private part, in the sense
that the compiler looks at it in order to generate (presumably better)
code.

The explanation I've heard many times (and agree with) is that the
private part contains stuff that logically belongs in the body, but for
efficiency, we want the compiler to be able to see it (when compiling
clients).  In other words, it's an efficiency hack.  Calling it an
"interface" of some sort seems to raise it to a higher level.

(In case you can't tell: If I were designing a language from scratch, it
would not have private parts.  It would have package specs defining the
interface (and only the interface), and package bodies defining the
implementation.  And in fact, I'm *always* designing a language, in my
head.  It's my hobby. ;-))

> I think rather than trying to make private parts more sophisticated,
> we should investigate simplifying them, and pushing more stuff
> to the body.

This sounds like an excellent plan.  Should have happened 20 years ago.
;-)

However, such a feature would be incomplete without a new pragma
analogous to Inline.  This new pragma would tell the compiler to look at
the body of a with-ed package, and generate code that depends on the
full type and full constant declarations it finds there (eg, know the
size of a record at compile time, if possible).  This is what pragma
Inline does for procedures: look at the package body, and depend on the
contents of the procedure body it finds there.

The effect on dependences and compilation order and whatnot for this new
pragma would be as for pragma Inline (and these effects depend on the
library model of that compiler).

If you use this pragma, you should get code (in client packages)
identical to what you get now, when you put the full type in the private
part, so the compiler can look at it.

This new pragma seems important to me:  If you don't have it, you're
stuck with an annoying choice between efficiency at run time, versus
the benefits of putting the thing in the body: efficiency of compile
time, ability to "with" private children, better management of
source-file variants.  Furthermore, if you put something in the body,
and you later decide that's too inefficient, you don't want to move it
to the private part, because that wrecks the structure of your program
-- you might have to rearrange all your packages, make private packages
public, etc.  Much better to slap a pragma on it.  Just like it's much
better to use pragma Inline than to hand-inline the code of that
procedure.

> It is clear that in some cases, the size of a type
> is not known at compile-time, e.g. when the type includes a nested
> array component whose length is not known at compile time.  This
> implies that compilers have no problem dealing with such types,
> and would seem a small step to introduce a kind of private
> type where the full type information is deferred to the body.
> (For compilers like RR where nested dynamic components are handled
> with a level of indirection, clearly such a private type would also
> involve a level of indirection.)
>
> The other thing which really wants to be deferred to a body
> is the full declaration for a deferred constant, so that large constant
> tables can be given in a body rather than in a spec.
>
> So...
>
> How about something like:
>
>    type Priv(Discrim : Integer) is private;
>    Null_Priv : constant Priv;
>
>  private
>
>    type Priv(Discrim : Integer) is record in body;

Why "record"?  Does the compiler need to know it's a record?
Is it allowed to be an array, task, protected?

>    Null_Priv : constant Priv in body;
>
> Clearly declaring an object of type Priv or using Null_Priv implies
> an elaboration check that the corresponding full declaration in the
> body has been elaborated.  Something like this additional elaboration
> check will be needed in any case if we postpone elaboration of
> the entire private part.

No, no, no!  The proposal to split out the private part into a separate
syntactic entity, presumably in a separate source file, should *not*
change the run-time semantics in the slightest.  The private part should
still be elaborated immediately after the visible part.

> Of course only composite types could have their full declaration
> postponed into the body.  Otherwise pass by copy could be
> truly nasty.

Sigh.

> > ...
> > Tuck, would a proposal on this line address your objection??
>
> Not really.  I prefer something more along the lines above, where
> individual declarations can have their full definitions deferred
> into the body.

I also prefer something along the lines of the above, but I still don't
understand Tuck's desire to preserve some sort of "physical interface".
If we have to have private parts, I don't see why they can't see private
children.  But I agree with Tuck that moving information from private
parts to bodies is the right idea.

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

From: Michael Yoder
Sent: Friday, February 16, 2001 7:01 PM

On this issue I agree with Pascal and Ehud. But let me start by quoting Bob
quoting Tucker:

> > I think rather than trying to make private parts more sophisticated,
> > we should investigate simplifying them, and pushing more stuff
> > to the body.
>
>This sounds like an excellent plan.  Should have happened 20 years ago.
>;-)
[discussion of how Bob's ideal language would work snipped]

I'm skeptical we had the knowledge needed to do this right 20 years
ago.  I'm skeptical we know *today* how to do it right.  (Yes, it is
possible if code generation is always done at what we call "link
time.")  But be that as it may, "with private" is preferable unless we can
finish all of Tucker's investigations in the reasonably near future.  "With
private" cuts the Gordian knot and Tucker is advocating teasing it
apart.  It would be better to do "with private" and then move towards a
Duffian or Taftian ideal language; if we arrive, "with private" and private
parts can then be made deprecated features.

I've often wanted to insert a second context clause right after the keyword
'private' in a package specification; each time my workaround was to
promote stuff I wanted in private packages into a public "wannabe private"
package.

> > > ...
> > > Tuck, would a proposal on this line address your objection??
> >
> > Not really.  I prefer something more along the lines above, where
> > individual declarations can have their full definitions deferred
> > into the body.
>
>I also prefer something along the lines of the above, but I still don't
>understand Tuck's desire to preserve some sort of "physical interface".
>If we have to have private parts, I don't see why they can't see private
>children.  But I agree with Tuck that moving information from private
>parts to bodies is the right idea.

I also prefer this, but I'd like to have "with private" in the interim
until I get all of it.

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

From: Randy Brukardt
Sent: Friday, February 16, 2001 10:47 PM

Tucker said:

(Discussion of unusual world-view deleted :-)

> I think rather than trying to make private parts more sophisticated,
> we should investigate simplifying them, and pushing more stuff
> to the body. ...

> How about something like:
>
>   type Priv(Discrim : Integer) is private;
>   Null_Priv : constant Priv;
>
> private
>
>   type Priv(Discrim : Integer) is record in body;
>   Null_Priv : constant Priv in body;
>
>Clearly declaring an object of type Priv or using Null_Priv implies
>an elaboration check that the corresponding full declaration in the
>body has been elaborated.  Something like this additional elaboration
>check will be needed in any case if we postpone elaboration of
>the entire private part.

I wouldn't be adverse to working on this idea further. It seems to just be
syntactic sugar for:

   type Priv(Discrim : Integer) is private;
   Null_Priv : constant Priv;

 private

   type <Anon_Priv> (Discrim : Integer); -- Deferred to body.
   type Priv(Discrim : Integer) is access <Anon_Priv> (Discrim);
   Null_Priv : constant Priv in body := <Anon_Null_Priv_Func>;

The only new thing about this would be the handling of the discriminants.

However, I think that the real-time and safety-critical people wouldn't be
happy: the last thing they want is more dynamic allocation of memory. They'd
probably never use this feature, and thus we'd still need "with private".

(I think Bob's pragma Inline for these is unworkable, since it couldn't be
implemented with link-time inlining; and thus would require library
dependencies that I simply will not stand for.)

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

From: Robert A Duff
Sent: Saturday, February 17, 2001 9:43 AM

> I wouldn't be adverse to working on this idea further. It seems to just be
> syntactic sugar for:
>
>    type Priv(Discrim : Integer) is private;
>    Null_Priv : constant Priv;
>
>  private
>
>    type <Anon_Priv> (Discrim : Integer); -- Deferred to body.
>    type Priv(Discrim : Integer) is access <Anon_Priv> (Discrim);
>    Null_Priv : constant Priv in body := <Anon_Null_Priv_Func>;
>
> The only new thing about this would be the handling of the discriminants.

No, I don't think it's quite that simple.  For Tucker's idea, you want
the compiler to manage the storage.  For the incomplete type deferred to
the body (which was a younger Tucker's idea, by the way!), you have an
explicit access type, so the programmer is required to manage the
storage (which is why I never use that feature unless I wanted a pointer
type anyway).

> However, I think that the real-time and safety-critical people wouldn't be
> happy: the last thing they want is more dynamic allocation of memory. They'd
> probably never use this feature, and thus we'd still need "with private".

It's no more dynamic than an array of run-time-known size.  That is,
it's not necessary to use the heap.  (If some compilers choose to use
the heap, that's fine, but we should preserve the feasibility of never
using the heap except for explicit access types).

> (I think Bob's pragma Inline for these is unworkable, since it couldn't be
> implemented with link-time inlining; and thus would require library
> dependencies that I simply will not stand for.)

If some compilers can't implement the new pragma Inline, that's OK.
But I think it's extremely important to standardize the pragma,
so those compilers that care about this issue can support it
(portably!).  Most compilers would in fact have no trouble implementing it.

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

From: Randy Brukardt
Sent: Monday, February 19, 2001 4:16 PM

> No, I don't think it's quite that simple.  For Tucker's idea, you want
> the compiler to manage the storage.  For the incomplete type deferred to
> the body (which was a younger Tucker's idea, by the way!), you have an
> explicit access type, so the programmer is required to manage the
> storage (which is why I never use that feature unless I wanted a pointer
> type anyway).

I meant that to be implied. I should have added a Storage_Pool clause to
indicate that. I was mainly concerned about the code generation, which is the
same as above with an appropriate initialization New at each declaration.

Alternatively, I could have wrapped the access in a controlled type to do that.
Still, there is nothing new here...

> It's no more dynamic than an array of run-time-known size.  That is,
> it's not necessary to use the heap.  (If some compilers choose to use
> the heap, that's fine, but we should preserve the feasibility of never
> using the heap except for explicit access types).

I wasn't talking about the heap per-se. I don't think that the Safety-critical
people use dynamic arrays, either. That's because they don't want
non-deterministic memory usage. I stand by my comment.

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

From: Pascal Leroy
Sent: Saturday, February 17, 2001 5:01 AM

Bob (who is always designing languages) explained:

> I think that view of private parts is rather unusual.  I find it strange
> to call the private part an "interface".
>
> The explanation I've heard many times (and agree with) is that the
> private part contains stuff that logically belongs in the body, but for
> efficiency, we want the compiler to be able to see it (when compiling
> clients).  In other words, it's an efficiency hack.  Calling it an
> "interface" of some sort seems to raise it to a higher level.

I completely agree with this view.  The notion that something which is
invisible to clients is an "interface" doesn't make sense to me.

Tuck proposed:

> > I think rather than trying to make private parts more sophisticated,
> > we should investigate simplifying them, and pushing more stuff
> > to the body.

I can agree with this, although as Bob pointed out we would want a pragma of
some sort (heck, it could be Inline applied to a type) to force the compiler
to generate decent code.

However, I believe we need to be pragmatic here.  Pushing more stuff to the
body is probably sensible, but it is going to take several years to
refine/understand the consequences of this new model.  On the other hand,
let me say it once more, "with private" could work tomorrow (tomorrow in ARG
terms probably means next year, I'm sure we all realize that). Also, we have
to keep in mind that there is a lot of code out there that uses private
parts, and restructuring that code to use the "in body" clause might be a
lot of work.  On the other hand, adding "private" to a couple of with
clauses is an extremely cheap change.

So I guess I am saying that I like Mike Y's proposal:

> It would be better to do "with private" and then move towards a
> Duffian or Taftian ideal language; if we arrive, "with private" and private
> parts can then be made deprecated features.

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

From: Robert A Duff
Sent: Saturday, February 17, 2001 9:37 AM

> I can agree with this, although as Bob pointed out we would want a pragma of
> some sort (heck, it could be Inline applied to a type) to force the compiler
> to generate decent code.

I almost suggested extending pragma Inline.

Of course it doesn't "force" anything -- it's your customers with open
checkbooks that do the forcing.  ;-)

> So I guess I am saying that I like Mike Y's proposal:
>
> > It would be better to do "with private" and then move towards a
> > Duffian or Taftian ideal language; if we arrive, "with private" and private
> > parts can then be made deprecated features.

Sounds reasonable to me.

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

From: Tucker Taft
Sent: Saturday, February 17, 2001 1:53 PM

> I almost suggested extending pragma Inline.

I think this somewhat defeats the purpose of the "in body."
I see the "in body" as allowing more dynamically constructed
systems.  Pragma inline goes just the opposite, increasing
the amount of statically bound decisions.  I also don't
see why this is expected to be so inefficient, given how often
one ends up with a dynamically-sized type already.

Perhaps the idea is that while the system is being developed, the
dynamic approach is great, but once you want to deliver the most
heavily optimized version, you can "inline" things.  I can't imagine
going to the bother of using "in body" if you "inline" right away.

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

From: Robert A Duff
Sent: Saturday, February 24, 2001 4:29 PM

> I think this somewhat defeats the purpose of the "in body."

I don't see how the mere existence of such a pragma defeats the
purpose.  You don't have to use it.

Certainly, if you put the old kind of pragma Inline all over the place,
you somewhat defeat the purpose of separate compilation: you have to
regenerate code for calls when you change the body.  But it's the
programmer's choice to make that trade-off.

My philosophy of pragma Inline is: I'm not trying to improve speed.  I
have speed requirements.  If I have pragma Inline, I have the freedom to
use procedural abstraction whenever I like, without worrying about
efficiency.  Without pragma Inline, I have to perturb my design to
achieve efficiency.

I view my proposed Inline-like pragma the same way: I can freely put
this record type in a package body, because it makes sense to do so,
secure in the knowledge that if it's too slow, I can always "Inline"
it.

> I see the "in body" as allowing more dynamically constructed
> systems.  Pragma inline goes just the opposite, increasing
> the amount of statically bound decisions.

Right, but the point is, you can choose the looser binding at the
expense of efficiency, or the other way around, at the drop of a hat.

>...  I also don't
> see why this is expected to be so inefficient, given how often
> one ends up with a dynamically-sized type already.

I don't agree: I have lots of records that are compile-time-known size,
and I want the compiler to take advantage of that.  More precisely, I
want the compiler to *be* *able* to take advantage of that, if I so
desire.

It's true that many things are dynamic-sized.  But that does not imply
that if we make *everything* dynamic sized there's little cost.

> Perhaps the idea is that while the system is being developed, the
> dynamic approach is great, but once you want to deliver the most
> heavily optimized version, you can "inline" things.

Yes.

That's how I use pragma Inline already.

One point is that when I first write the code, I might not know which
way I want to do the trade-off.  So I want to be able to change my mind,
without redesigning the structure of the program.  Moving something from
body to private part is a big deal, because it rearranges the
with_clauses, and I might have to change private packages to public
(which ripples).  Slapping on a pragma is much easier.

>...  I can't imagine
> going to the bother of using "in body" if you "inline" right away.

First: I probably don't "inline_private" (or whatever it's called) right
away.

Second: Even if I do, I still get the advantage of textually separating
stuff out into the body.

Third: I would like a compiler option to turn off pragmas Inline (the
traditional variety, and the new one), so I can easily build my program
both ways.

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

From: Robert A Duff
Sent: Saturday, February 17, 2001 9:53 AM

Randy says:

> In our case, at least we gave a warning...

Well, if you can give a warning, I don't see why you can't just as
easily give an error.

The implementation I'm imagining for a library-based compiler is that
the compiler has a rule that if there's a private part, you have to
submit it to the compiler at the same time as you submit the visible
part.  Eg, if there's a command-line interface, you would type in two
file names.  If you don't, and the private part turns out to exist at
link time, then complain.

But I'm not dead-set against having a stub-like syntax.

> I think you're also putting a terrible burden on the reader of the source if
> there is no indication that there is a private part missing.

I find that argument somewhat convincing.  But not entirely.

When I want to know if a package body exists, I go and look at its file.
If that file doesn't exist, then the package body doesn't exist.
(I'm presumable either using some file-naming conventions voluntarily,
or else my compiler forces me to.)  I certainly don't carefully read the
spec, to see if a body is required.

You also can't tell from a package spec whether any children exist.

So the private part doesn't seem like that big of a deal.
To tell whether it exists, go look for it in the directory where you
keep your source code.

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

From: Pascal Leroy
Sent: Sunday, February 18, 2001 4:26 AM

So the model you have in mind is merely a #include, right?  Fine, but that's
outside of the language in my opinion.  I don't believe you can phrase the
above discussion in RM terms, i.e. "entered in the environment."

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

From: dewar@gnat.com
Sent: Sunday, February 18, 2001 7:56 AM

<<We fixed one "problem" like that: optional package bodies.  However, I
think that was a mistake.  I think there *was* no language problem.
The problem was an implementation one: Ada 83 compilers ought to have
checked whether an optional body exists.  They didn't, and that led to
the error-prone behavior.>>

I strongly disagree, suppose you had the following:

a spec p
a body p
where the body was not required

Now you build a program with the spec and body, and everything works
fine.

Now you edit the spec, and you recompile the spec, the body simply gets
left out.

What do you mean "check whether an optional body exists", you cannot
check if an optional body exists in the normal case, without searching
the universe. Yes, you can warn if one happens to be around, and you
can warn that one used to exist.

But you MUST be allowed (in Ada 83) to rebuild the executable with
only the new spec, and not the new body. The compiler cannot prevent
you from constructing this modified program, since it is legal.

The point in Ada 95 was to remove the requirement of being able to
construct the "wrong" program. Since every Ada 83 compiler had to
support this capability, and the capability itself is what was
fundamentally flawed, I think the change to Ada 95 was highly desirable.

<<Note that GNAT originally had the *same* error-prone behavior.  If an
optional body existed on disk, GNAT would silently ignore it.  GNAT
would only give the error message if you explicitly asked it to compile
the file, thus defeating the whole point of the new language rule
disallowing optional bodies.  My point here is not to gripe about GNAT>>

That's completely confused, yes, that's a problem, one that might exist
in any compiler, but it has nothing whatsoever to do with the problem
we are talking about, and which this language solution exists.

The new Ada 95 feature is NOT talking about issues in building programs
in the first place, it is talking about the error prone behavior where
you modify a spec that does not require a body, and the modification
does not force a recompilation of the body. It is *ENTIRELY* that
modification scenario, required to "work" in all Ada 83 compilers
that the new Ada 95 feature is addressing.

What Bob Duff is referring wrt GNAT is that when you build a program
in the first place, where you have an improper body, then it is nice
if the automatic compilation tools make the effort to see if a body
is around (what on earth that means is of course very compilation
environment dependent). The "new" GNAT here searches everywhere on
the path for something that might be a body, and makes you get rid
of it. That's not always the right thing to do, but it is safer,
but this error check has nothing at all to do with the language
feature.

I am a bit surprised at this confusion, because this was a well
known problem in Ada 83, that was completely eliminated in Ada 95,
in all Ada 95 compilers, and in all versions of GNAT, and was a
welcome change in Ada 95.

Indeed if we have separated private parts, it is absolutely essential
in my view that we not repeat the mistake that Ada 83 made in this
area. Yes, you can defend against it to some limited extent by the
kind of peculiar searching around for possible peculiarities that
GNAT does, but that is not a desirable behavior.

Note incidentally that the RM appears to prohibit the GNAT behavior,
because there are specific rules about new units obsoleting old ones.
What we do for the ACVC runs is to use a crackpot (i.e. ACVC only)
script that sees GNAT issue the message of an unwelcome body or spec,
and then deletes it and transparently reattempts the compilation.

In other words, the following sequence must work as far as the
ACVC tests are concerned.

Introduce p.ads (spec needing body) and p.adb (body) into compilation
environment, and compile

Introduce new p.ads (spec not needing body) into compilation environment
and compile.

GNAT will reject the second attempt, but the ACVC test won't tolerate
that rejection, so we simply automatically delete the p.adb and proceed
(of course you would never want to do that automatically in real life,
which is why I call this a crackpot script).

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

From: Tucker Taft
Sent: Saturday, February 17, 2001 1:47 PM

Pascal Leroy wrote:
> ...
> However, I believe we need to be pragmatic here.  Pushing more stuff to the
> body is probably sensible, but it is going to take several years to
> refine/understand the consequences of this new model.  On the other hand,
> let me say it once more, "with private" could work tomorrow (tomorrow in ARG
> terms probably means next year, I'm sure we all realize that).

I don't think this is a good argument.  I really don't want to
add something and then soon thereafter declare it obsolescent.

On the other hand, I do see some value in "with private" though
I hate the name, since it brings up bad memories of an Ada 9X
proposal of the same name.  Maybe "private with"?  We aren't
"with"ing the private part, but rather "privately" withing the visible
part, so I think "private with" might make more sense anyway,
although it may be a bit trickier to parse.

I also don't think we should ignore the possibility of moving the
"with" clauses to immediately after the word "private".

I personally think we should drop discussion of physically separating
the "private" part, and leave that to compilers to do if they
so choose, especially if it is supposed to be completely
semantically neutral.

But getting back to "private with" -- exactly what was the proposal?
I have lost it in all the other discussion.

Clearly we can't allow a parent package spec to "with" its own
private children.  So instead it must be siblings, nieces, etc.
that can "private with" their private siblings, aunts, etc.

I suppose an alternative is to simply allow these "with" clauses,
but then say that if the with'ed unit is private, it only becomes
visible in the private part.  This is roughly equivalent to saying
that when a unit is "with"ed, if it is a private child, it
is implicitly inserted at the end of the private part of its parent,
while if it is a public child, it is implicitly inserted at the
end of the visible part of its parent.  In any case, a spec
can never "with" its own descendant.

> ...
> So I guess I am saying that I like Mike Y's proposal:
>
> > It would be better to do "with private" and then move towards a
> > Duffian or Taftian ideal language; if we arrive, "with private" and private
> > parts can then be made deprecated features.

I really don't like this way of thinking.  We should be convinced
that "private with" is useful indefinitely, rather than putting
it in as a stop-gap.

I see "private with" as serving a different purpose than
the "in body" stuff.  It focuses on information hiding and
modularization, whereas the "in body" really opens up the
possibility for more dynamically constructed systems (similar to
the "with type" stuff).

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

From: dewar@gnat.com
Sent: Sunday, February 18, 2001 9:13 AM

<<The explanation I've heard many times (and agree with) is that the
private part contains stuff that logically belongs in the body, but for
efficiency, we want the compiler to be able to see it (when compiling
clients).  In other words, it's an efficiency hack.  Calling it an
"interface" of some sort seems to raise it to a higher level.>>

This viewpoint seems exactly right in Ada 83, but surely is completely
wrong in Ada 95. The introduction of child packages that can see the
private part now means that indeed it is used as an interface for
the implementation, and I see Ada 95 code all the time where private
parts are full of subprogram specs that would never have fit the
Ada 83 model.

So I don't think you can turn back the clock at this stage, the nature
of private parts of packages has radically changed from the above
quoted viewpoint.

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

From: Ehud Lamm
Sent: Monday, February 19, 2001 1:47 AM

Indeed. This is one prime reason to think that private parts as they are now
are problematic. They serve two very distinct semantic functions: to declare
implementation details that (per Ada-83) must be in the spec and to declare
the extension interface (similar to "protected" in C++).
I find the connection between child units and inheritance very elegant (see
Tucker Taft's LSN on this). However, outsiders (i.e., students) have a hard
time with this. Almost no one sees how to use the private part for extension
purposes unless told about this specifically.
I tried giving this as a riddle this semester ("Why does a pacakge have
procedures declared in the private part etc. etc.") and only one student
thought about child units.

However, I agree with Robert: We are too far into the game to change the
rules.

Notice that since the above means that the private part is indeed an
"interface" (that can be used only by children), it makes more sense to have
it _inside the spec_ and not in a  seperate file. It is not just a hack for
storing impl. details: it is part of the abstraction. This is esp. true when
the essence of the package is to allow extension (e.g, when it declares
abstract tagged types; or in the future when it declares interfaces).

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

From: Tucker Taft [stt@avercom.net]
Sent: Saturday, February 17, 2001 3:36 PM

Pascal Leroy wrote:
> Bob (who is always designing languages) explained:
>
> > I think that view of private parts is rather unusual.  I find it strange
> > to call the private part an "interface".
> >
> > The explanation I've heard many times (and agree with) is that the
> > private part contains stuff that logically belongs in the body, but for
> > efficiency, we want the compiler to be able to see it (when compiling
> > clients).  In other words, it's an efficiency hack.  Calling it an
> > "interface" of some sort seems to raise it to a higher level.
>
> I completely agree with this view.  The notion that something which is
> invisible to clients is an "interface" doesn't make sense to me.

Well, I won't belabor the point, but it is clearly an "interface"
from the compiler's point of view, and even from the programmer's
point of view, 'size is visible, as are various other properties
revealed only in the private part such as by-reference, atomic,
volatile, etc.

I call it the "physical" interface in analogy with the layers in
a network protocol.  It is like the "physical link" level while
the visible part is more like the "application" level.  Conceivably
you could put the code for the body of a procedure in some other
computer, but to communicate with it, you would need to know at
least something about the physical representation of the data you
pass to it.

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

From: Ted Baker
Sent: Sunday, February 18, 2001 11:57 AM

> I think that view of private parts is rather unusual.  I find it strange
> to call the private part an "interface".
>
> The explanation I've heard many times (and agree with) is that the
> private part contains stuff that logically belongs in the body, but for
> efficiency, we want the compiler to be able to see it (when compiling
> clients).  In other words, it's an efficiency hack.  Calling it an
> "interface" of some sort seems to raise it to a higher level.

The reason we want the compiler to be able to see it is that it
provides information that is NEEDED to implement the interface--
i.e., the lower-level details of the interface.

I realize that some people would like to move toward a more
dynamic, world, where no data representation details would need to
be bound by the interface.  However, there will always remain
situations (e.g., interfacing to hardware and to code in other languages,
and -- dare I ever hope? -- interfacing to code compiled with
a different Ada compiler) where data representation will necessarily
be a logical part of the interface to a software component.

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

From: dewar@gnat.com
Sent: Sunday, February 18, 2001 12:26 AM

<<I personally think we should drop discussion of physically separating
the "private" part, and leave that to compilers to do if they
so choose, especially if it is supposed to be completely
semantically neutral.>>

No one is suggesting that this be part of the definition, just that it
would be nice if whatever solution is decided here made it easier for
compilers to do this ...

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

From: Pascal Leroy
Sent: Sunday, February 18, 2001 4:22 AM

> On the other hand, I do see some value in "with private" though
> I hate the name, since it brings up bad memories of an Ada 9X
> proposal of the same name.  Maybe "private with"?

Ok, I changed the subject line of this message :-)

> We aren't
> "with"ing the private part, but rather "privately" withing the visible
> part, so I think "private with" might make more sense anyway,
> although it may be a bit trickier to parse.

I am not going to fight on the syntax, as long as the grammar remains
reasonably unambiguous.

> I also don't think we should ignore the possibility of moving the
> "with" clauses to immediately after the word "private".

I don't like that.  It's good for readability to have the with clauses at
the beginning of the unit, it summarizes the dependencies of the unit, eg in
terms of compilation ordering.  In fact, I believe that a number of "make"
tools out there work by scanning the beginning of the unit for withs and
separate.  Now they would have to go much farther.

Also, it seems that you would have some trouble distinguishing pragmas that
appear in declarative parts from pragmas that appear in context clauses.

> I personally think we should drop discussion of physically separating
> the "private" part, and leave that to compilers to do if they
> so choose, especially if it is supposed to be completely
> semantically neutral.

I couldn't agree more.

> I suppose an alternative is to simply allow these "with" clauses,
> but then say that if the with'ed unit is private, it only becomes
> visible in the private part.

No, that's not sufficient.  I believe you also want to "private with" public
units, but make it explicit that they are only needed for the private part.
That's useful for documentation and maintenance purposes.  And maybe these
units will later turn into private units, but you don't want to do the
required restructuring right now.  Again, think of all the code out there
that withs units for the sole purpose of writing a private part.

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

From: Ehud Lamm
Sent: Sunday, February 18, 2001 8:57 AM

> > On the other hand, I do see some value in "with private" though
> > I hate the name, since it brings up bad memories of an Ada 9X
> > proposal of the same name.  Maybe "private with"?
>
> Ok, I changed the subject line of this message :-)

I wouldn't fight over this... To my (non native) ears the first wording
sounds better.

>
> > I also don't think we should ignore the possibility of moving the
> > "with" clauses to immediately after the word "private".
>
> I don't like that.  It's good for readability to have the with clauses at
> the beginning of the unit, it summarizes the dependencies of the unit, eg in
> terms of compilation ordering.  In fact, I believe that a number of "make"
> tools out there work by scanning the beginning of the unit for withs and
> separate.  Now they would have to go much farther.

I agree with Pascal. If/when the private part goes into a seperate file, the
with clauses might well follow, but as long as it remains in the spec, I
think the with clauses should stay where they are. Changing this can
introduce work and bugs to automatic tools, and is also bad for readability.
I think that it is again a situation of better being the enemy of good
enough. Unless the private part is eliminated, it is visible in the spec, so
why should we work hard to move the with clauses down a few lines?


> > I personally think we should drop discussion of physically separating
> > the "private" part, and leave that to compilers to do if they
> > so choose, especially if it is supposed to be completely
> > semantically neutral.

Quite. And this is why I agree that the with's should stay where they are,
for the time being.

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

From: dewar@gnat.com
Sent: Monday, February 19, 2001 1:05 PM

<<I agree with Pascal. If/when the private part goes into a seperate file, the
with clauses might well follow, but as long as it remains in the spec, I
think the with clauses should stay where they are. Changing this can
introduce work and bugs to automatic tools, and is also bad for readability.
I think that it is again a situation of better being the enemy of good
enough. Unless the private part is eliminated, it is visible in the spec, so
why should we work hard to move the with clauses down a few lines?
>>

Note that the mere fact of the with's being at the top of the abstract
representation does not mean they have to be there in the physical
representation if you separate this into two separate files. There is
no rule that says that the only allowable way to split into two files
is to draw a line in the source :-)

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

From: dewar@gnat.com
Sent: Sunday, February 18, 2001 8:49 AM

<<I agree. It sems pretty much straightforward, and has some important
benefits for readability and maintenance. As this relates to layered
achitectural style, which I find to be the corner stone of abstraction, I
find this esp. important.
It also makes the progammers decision explicit: Does he want the unit to be
visibile in the public part of the spec? Making such decisions explicit was
mentioned in the  steelman, and for good reasons.>>

Note that it is possible to implement this right now without any change
to the language (we investigated this possibility some time ago). All
you need is a pragma

with x; pragma Private_Only (x);

that says that the unit x can only be referenced in the private part.

Now you can allow the private part to be in a separate file, with the
WITH clauses in that file (and no junk pragma), and you just declare
that this is a representation of the text where the WITH goes where
it belongs with the pragma.

But it is nicer if something like this is at least semi-standardized :-)

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

From: Randy Brukardt
Sent: Monday, February 19, 2001 4:47 PM

No, this doesn't solve the problem. The problem is that it is illegal to
with a private package in a public specification. No pragma can change that
(unless of course you're in "extensions" mode).

Thus we need a real extension to allow such withing; the rest of it is
nice-to-have, but seems to come along for free.

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

From: dewar@gnat.com
Sent: Monday, February 19, 2001 5:00 PM

Sure, I understand this, but in my view this is the nice-to-have feature,
the really essential one is to conveniently enable separated private parts.

For example, we often find that the copyright on the private part is
completely different from the copyright on the public part, and it
would really be nice to have two documents (e.g. this happens with
the RM defined library).

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

From: Randy Brukardt
Sent: Monday, February 19, 2001 5:26 PM

Humm. The problem outlined on C.L.A., and which I described, and which we're
trying to solve in AI-262 is the private package needed by the private part
problem.

Separated private parts only came up as a possible solution to this problem.
In my opinion, they are a nice-to-have, while the private package problem
contorts designs (and essentially makes private packages useless for their
intended purpose); thus it has a much higher priority in my view.

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

From: Randy Brukardt [Randy@RRSoftware.Com]
Sent: Monday, February 19, 2001 4:39 PM

> But getting back to "private with" -- exactly what was the proposal?
> I have lost it in all the other discussion.

I never worked out the exact details; I asked whether it was worth doing so,
and the rest is history... (and a very large appendix in AI-262, and a new
record in messages on Ada-Comment since I took it over).

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

From: Christoph Grein [christoph.grein@eurocopter.de]
Sent: Monday, February 19, 2001 2:30 AM
To: ada-comment@ada-auth.org
Subject: Re: [Ada-Comment] Possible amendment: with private

> But getting back to "private with" -- exactly what was the proposal?
> I have lost it in all the other discussion.

package S is  -- Note: not private, not in hierarchy T
  ...
end S;
-----------------------
package T is
  ...
end T;
-----------------------
private package T.Pr is
  ...
private
  ...
end T.Pr;
-----------------------
private with T.Pr, S;
pacakge T.C is
  -- T.Pr, S invisible here
private
  -- visible parts of T.Pr, S visible here
end T.C;
------------------------------------------------------------------
I'm not sure about the following:

private package X is  -- Note: no visible parent (except of course Standard).
  ...                 -- Does such a package currently,
private               -- i.e. without the proposed amendment,
  ...                 -- have any use?
end X;
-----------------------
private with X;  -- should this be allowed?
package Y is     -- Note: no hierarchical relation between X and Y
  -- X invisible here
private
  -- visible part of X visible here
end Y;

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

From: Michael Yoder
Sent: Monday, February 19, 2001 4:20 PM

Tucker you wrote:

>Pascal Leroy wrote:
> > ...
> > However, I believe we need to be pragmatic here.  Pushing more stuff to the
> > body is probably sensible, but it is going to take several years to
> > refine/understand the consequences of this new model.  On the other hand,
> > let me say it once more, "with private" could work tomorrow (tomorrow
> in ARG
> > terms probably means next year, I'm sure we all realize that).
>
>I don't think this is a good argument.  I really don't want to
>add something and then soon thereafter declare it obsolescent.

I absolutely agree.  But I am nervous about this judgment unless we agree
on what "soon" means, and have strong confidence that we *can* declare it
obsolescent soon.


> > ...
> > So I guess I am saying that I like Mike Y's proposal:
> >
> > > It would be better to do "with private" and then move towards a
> > > Duffian or Taftian ideal language; if we arrive, "with private" and private
> > > parts can then be made deprecated features.
>
>I really don't like this way of thinking.  We should be convinced
>that "private with" is useful indefinitely, rather than putting
>it in as a stop-gap.
>
>I see "private with" as serving a different purpose than
>the "in body" stuff.  It focuses on information hiding and
>modularization, whereas the "in body" really opens up the
>possibility for more dynamically constructed systems (similar to
>the "with type" stuff).

Well, I may have misjudged by imagining that you and Bob were aiming at
nearly identical endpoints.  I think that in Bob's ideal endpoint it would
become obsolete.  I'm no longer sure about yours.  If not, it would never
become a deprecated feature unless Bob converted you.  :-)

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

From: Robert A Duff
Sent: Saturday, February 24, 2001 4:11 PM

I've been away for a week, and I'm beginning to catch up on e-mail...

Mike Y says:

> On this issue I agree with Pascal and Ehud. But let me start by quoting Bob
> quoting Tucker:
>
>
> > > I think rather than trying to make private parts more sophisticated,
> > > we should investigate simplifying them, and pushing more stuff
> > > to the body.
> >
> >This sounds like an excellent plan.  Should have happened 20 years ago.
> >;-)
> [discussion of how Bob's ideal language would work snipped]
>
> I'm skeptical we had the knowledge needed to do this right 20 years
> ago.

I should have said "I *wish* it had happened 20 years ago."
I didn't really mean to imply that the designers of Ada 83
were somehow negligent in not doing so.

>...I'm skeptical we know *today* how to do it right.

I'm quite sure that I could design a language from scratch with the
desired property (although I could not have done so 20 years ago!).
But I'm not so sure I know how to retrofit it into Ada, with the usual
constraints on upward compatibility, and not breaking everybody's
compiler.  My approach is to think about what I really want in an ideal
world, and then think about how to fit it into the real world.

>...  (Yes, it is
> possible if code generation is always done at what we call "link
> time.")

I don't intend to require link-time code generation.

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

From: Robert A Duff
Sent: Saturday, February 24, 2001 4:40 PM

I wrote:

> > The implementation I'm imagining for a library-based compiler is that
> > the compiler has a rule that if there's a private part, you have to
> > submit it to the compiler at the same time as you submit the visible
> > part.  Eg, if there's a command-line interface, you would type in two
> > file names.  If you don't, and the private part turns out to exist at
> > link time, then complain.

Pascal replied:

> So the model you have in mind is merely a #include, right?

Pretty close.  But I still expect a separate private part to be
separately parsed -- it's not like C, where the #include'd thing can be
any sequence of tokens.  (Or is it even worse -- can C tokens span an
#include?  I don't know C that well.)

>...  Fine, but that's
> outside of the language in my opinion.  I don't believe you can phrase the
> above discussion in RM terms, i.e. "entered in the environment."

I think I *can* phrase it in RM terms, as much so as current chap 10
stuff, which is always subject to crazy "source representation"
decisions by imaginary evil implementers.

The "environment" is the universe known to the compiler.  Certainly, the
compiler defines that universe.  But sane compilers define it sanely.
And whatever your compiler's notion of what exists in the universe, you
can tell (at link time) what exists in that universe.

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

From: Robert A Duff
Sent: Saturday, February 24, 2001 5:00 PM

> <<We fixed one "problem" like that: optional package bodies.  However, I
> think that was a mistake.  I think there *was* no language problem.
> The problem was an implementation one: Ada 83 compilers ought to have
> checked whether an optional body exists.  They didn't, and that led to
> the error-prone behavior.>>
>
> I strongly disagree, ...

OK, I retract my statement that there was no language problem.
Ada 83 required (or seemed to require) error-prone behavior.

However, I still say that we didn't need to fix it by
requiring/forbidding package bodies.  I claim that optional package
bodies would be just fine (not error prone) given the Ada 95 library
model, and given sensible compilers.

GNAT defines the "environment" (the universe of source code) to be the
files you get when you say "ls *.ads *.adb" (in Unix).  At least that's
the default, and you have search lists and whatnot, but anyway, there's
a clearly defined set of source files, well understood by the user.  If
some of those are "optional" package bodies, what's the harm?  If they
exist, they should be part of the program, if not, not.

Do you still "strongly disagree"?

>... suppose you had the following:
>
> a spec p
> a body p
> where the body was not required
>
> Now you build a program with the spec and body, and everything works
> fine.
>
> Now you edit the spec, and you recompile the spec, the body simply gets
> left out.

Yes, I now recall that this was required in Ada 83.

But it's not required in Ada 95.  Ada 95 clearly allows an error message
in this case (I mean, Ada 95, modified to allow optional package
bodies).

> What do you mean "check whether an optional body exists", you cannot
> check if an optional body exists in the normal case, without searching
> the universe. Yes, you can warn if one happens to be around, and you
> can warn that one used to exist.

Right.  You have to have some notion of "the universe", implementation
defined, but defined so that programmers can easily tell what's in the
universe.  If so, programmers will never be surprised.

> <<Note that GNAT originally had the *same* error-prone behavior.  If an
> optional body existed on disk, GNAT would silently ignore it.  GNAT
> would only give the error message if you explicitly asked it to compile
> the file, thus defeating the whole point of the new language rule
> disallowing optional bodies.  My point here is not to gripe about GNAT
> >>
>
> That's completely confused, yes, that's a problem, one that might exist
> in any compiler, but it has nothing whatsoever to do with the problem
> we are talking about, and which this language solution exists.

I don't see the difference.  The body exists, it's optional, and the
compiler ignores it.  That's a bug.  I don't care whether I'm compiling
from scratch, or recompiling an existing program.  In fact, in GNAT, it
doesn't matter which (which is good).

> The new Ada 95 feature is NOT talking about issues in building programs
> in the first place, it is talking about the error prone behavior where
> you modify a spec that does not require a body, and the modification
> does not force a recompilation of the body. It is *ENTIRELY* that
> modification scenario, required to "work" in all Ada 83 compilers
> that the new Ada 95 feature is addressing.
>
> What Bob Duff is referring wrt GNAT is that when you build a program
> in the first place, where you have an improper body, then it is nice
> if the automatic compilation tools make the effort to see if a body
> is around (what on earth that means is of course very compilation
> environment dependent). The "new" GNAT here searches everywhere on
> the path for something that might be a body, and makes you get rid
> of it. That's not always the right thing to do, but it is safer,
> but this error check has nothing at all to do with the language
> feature.

It seems to me that this is *always* the right thing to do, and GNAT is
entirely correct to complain about an optional body that exists (given
Ada 95's rule).  GNAT defines its universe, and if that universe has junk
in it, complaints are warranted.

The earlier GNAT behavior was to define the optional body to not be part
of the universe.  That's also RM-compliant behavior, but is obviously a
bug.

> I am a bit surprised at this confusion, because this was a well
> known problem in Ada 83, that was completely eliminated in Ada 95,
> in all Ada 95 compilers, and in all versions of GNAT, and was a
> welcome change in Ada 95.
>
> Indeed if we have separated private parts, it is absolutely essential
> in my view that we not repeat the mistake that Ada 83 made in this
> area. Yes, you can defend against it to some limited extent by the
> kind of peculiar searching around for possible peculiarities that
> GNAT does, but that is not a desirable behavior.
>
> Note incidentally that the RM appears to prohibit the GNAT behavior,
> because there are specific rules about new units obsoleting old ones.
> What we do for the ACVC runs is to use a crackpot (i.e. ACVC only)
> script that sees GNAT issue the message of an unwelcome body or spec,
> and then deletes it and transparently reattempts the compilation.

I do not agree that the RM prohibits the GNAT behavior.
(Exegesis available upon request.)

> In other words, the following sequence must work as far as the
> ACVC tests are concerned.

I'll bet these are legacy Ada 83 tests, and all right-thinking Ada 95
compiler writers should have challenged them.  ;-)  Yes, I know it's
easier to write a crackpot script.  ;-)

> Introduce p.ads (spec needing body) and p.adb (body) into compilation
> environment, and compile
>
> Introduce new p.ads (spec not needing body) into compilation environment
> and compile.
>
> GNAT will reject the second attempt, but the ACVC test won't tolerate
> that rejection, so we simply automatically delete the p.adb and proceed
> (of course you would never want to do that automatically in real life,
> which is why I call this a crackpot script).

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

From: Robert A Duff
Sent: Sunday, February 25, 2001 8:44 AM

> Yes, indeed you can handle things this way in the source based model, but
> that does NOT help you with the traditional library model implementation.

But the source-based folks have said that they give warnings -- they
could just as well give errors, except that the Ada 83 ACVC required
otherwise.  So I claim that the only important *language* change in this
area was to make those tests invalid.  And Ada 95 did that by allowing
implementations complete freedom to define what's in the "universe" (ie
the "environment).

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

From: dewar@gnat.com
Sent: Sunday, February 25, 2001 10:44 AM

<<But the source-based folks have said that they give warnings -- they
could just as well give errors, except that the Ada 83 ACVC required
otherwise.  So I claim that the only important *language* change in this
area was to make those tests invalid.  And Ada 95 did that by allowing
implementations complete freedom to define what's in the "universe" (ie
the "environment).>>

My concern was with traditional library based implementations, not with
source based implementations. I don't see how they could know.

Remember that there must BE some mechanism in Ada 83 for
replacing

package spec + unneeded body

by

package spec without body

and I do not see how one could distinguish this legitimate conversion
from the accident in a library based environment. To require specific
deletion of the body would be worryingly extra-lingual.

In the source based model, GNAT is actually too fierce, it will NOT
let you compile a package spec that allows no body if there is a body
in sight, and insists that you get rid of the body first.

In ACVC mode, it actually deletes the source file, which is conforming,
but of course ludicrously hostile, so no one uses this weird ACVC
script in real life.

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

From: Robert A Duff
Sent: Sunday, February 25, 2001 9:30 AM

> Note that it is possible to implement this right now without any change
> to the language (we investigated this possibility some time ago). All
> you need is a pragma
>
> with x; pragma Private_Only (x);
>
> that says that the unit x can only be referenced in the private part.

Well, maybe.  What are the exact semantics?  In particular, I had
assumed that if you say "private with X;", then the scope of that
with_clause does not include the visible part, so if there's a
use_clause in the visible part that makes some other X visible, it is
*not* hidden (in the vis part) by the library unit X.  This seems
semantically nicest, and easiest to implement.  But it seems in somewhat
bad taste for a pragma.

The alternative is to say that the scope of the with_clause includes the
visible part, but you're just not allowed to refer to X (as a separate
legality rule).  This would mean that if you erase the pragma, the
program still works.

> Now you can allow the private part to be in a separate file, with the
> WITH clauses in that file (and no junk pragma), and you just declare
> that this is a representation of the text where the WITH goes where
> it belongs with the pragma.

It sounds like you're assuming the "alternative" semantics I described.
Otherwise, it's not simply a "source representation" issue.

> But it is nicer if something like this is at least semi-standardized :-)

Indeed.  I wouldn't use the feature, unless I had some confidence in its
portability.

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

From: dewar@gnat.com
Sent: Sunday, February 25, 2001 10:40 AM

<<The alternative is to say that the scope of the with_clause includes the
visible part, but you're just not allowed to refer to X (as a separate
legality rule).  This would mean that if you erase the pragma, the
program still works.>>

Yes, that's my meaninvg of the pragma. Otherwise it is dubious indeed.

<<It sounds like you're assuming the "alternative" semantics I described.
Otherwise, it's not simply a "source representation" issue.>>

Yes indeed.

<<Indeed.  I wouldn't use the feature, unless I had some confidence in its
portability.>>

My definition is completely portable, since there is a reliable
transformation from the separate files to a single file that has
standard Ada 95 semantics, and the compiler would guarantee that
this is the case.

At least in GNAT it is pretty easy to implement, because we always
keep track of what WITH's have actually been referenced (so that we
give warnings if they are unreferenced), and it is just a matter of
checking these flags at the start of the private part.

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

From: Robert A Duff
Sent: Sunday, February 25, 2001 9:38 AM

> package S is  -- Note: not private, not in hierarchy T
>   ...
> end S;
> -----------------------
> package T is
>   ...
> end T;
> -----------------------
> private package T.Pr is
>   ...
> private
>   ...
> end T.Pr;
> -----------------------
> private with T.Pr, S;
> pacakge T.C is
>   -- T.Pr, S invisible here

Right, but are these things in scope?  That is, can they hide other
things of the same name?  I say, "No".

Note that Tucker's idea of actually moving the with_clauses, rather than
giving them a different syntax, better reflects the intended semantics
(assuming folks agree with my "No").  Surely everyone agrees with the
principle that syntax should reflect semantics!

> private
>   -- visible parts of T.Pr, S visible here
> end T.C;
> ------------------------------------------------------------------
> I'm not sure about the following:

Yes, the following should be allowed.  Standard is a perfectly good
library unit, and can have public and private children like any other.
Any other rule would be an unnecessary special case.

One possible use of private children of Standard is mentioned in
AARM-10.1.1(12.d).

> private package X is  -- Note: no visible parent (except of course Standard).
>   ...                 -- Does such a package currently,
> private               -- i.e. without the proposed amendment,
>   ...                 -- have any use?
> end X;
> -----------------------
> private with X;  -- should this be allowed?
> package Y is     -- Note: no hierarchical relation between X and Y
>   -- X invisible here
> private
>   -- visible part of X visible here
> end Y;

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

From: Robert A Duff
Sent: Sunday, February 25, 2001 9:20 AM

> <<The explanation I've heard many times (and agree with) is that the
> private part contains stuff that logically belongs in the body, but for
> efficiency, we want the compiler to be able to see it (when compiling
> clients).  In other words, it's an efficiency hack.  Calling it an
> "interface" of some sort seems to raise it to a higher level.
> >>

Robert says:

> This viewpoint seems exactly right in Ada 83, but surely is completely
> wrong in Ada 95. The introduction of child packages that can see the
> private part now means that indeed it is used as an interface for
> the implementation, and I see Ada 95 code all the time where private
> parts are full of subprogram specs that would never have fit the
> Ada 83 model.

This is a good point.

However, I suspect that if private parts had never existed, then Tucker
would have invented child units that can see the body of their parent.

> So I don't think you can turn back the clock at this stage, the nature
> of private parts of packages has radically changed from the above
> quoted viewpoint.

OK, so I guess the right viewpoint is that private parts have a two-fold
purpose: the kludgy efficiency-hack purpose of Ada 83, and the
interface-for-children purpose of Ada 95.  This implies that it is
worthwhile to investigate in two directions:

    1. Moving stuff into the body that is now required to be in the
       private part.

    2. Separating out the private part, either physically or logically
       or both.  (By logically, I mean the "private with" idea, or the
       idea of moving the with_clauses into the private part.)

My earlier implication, that (1) subsumes (2), is wrong.  That is,
achieving (1) will *not* make "private with" obsolete.  So we can make
Pascal (etc) happy by doing (2) soon, without holding things up for (1).

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

From: Robert A Duff
Sent: Sunday, February 25, 2001 9:06 AM

Tucker says:

> I also don't think we should ignore the possibility of moving the
> "with" clauses to immediately after the word "private".

I am in favor of that idea.

I don't buy Pascal's objection that it's useful to see this stuff up
front.  In fact, it damages readability to see it up front, because this
information is purely private.  One should be able to read the public
information without being distracted.  (I support the idea of physically
separating private parts for the same reason.)

I'm only mildly worried about the "simple minded tool" issue.
Better to improve the language than to worry about that.

> I personally think we should drop discussion of physically separating
> the "private" part, and leave that to compilers to do if they
> so choose, especially if it is supposed to be completely
> semantically neutral.

I don't agree.

Several folks have pointed out that implementations can do this anyway,
by inventing their own syntax that claims to "represent" the standard
Ada syntax.  That's true from a legalistic point of view.  However, from
a practical point of view, users will want all implementations to
support the same representation, or at least close enough that they can
expect reasonable portability at the source file level.

> But getting back to "private with" -- exactly what was the proposal?
> I have lost it in all the other discussion.

I'm not sure what exactly is the proposal, but I think it is attempting
to solve two separate problems:

1. It is currently difficult to tell whether a given with_clause is part
of the visible information about the package.  It is desirable to mark
each with_clause with whether it applies to the visible part, or only to
the private part.  To me, the ideal way to indicate this would be to
place the private with_clauses inside the private part, but some syntax
such as "private with" also solves the problem, albeit less readably.

2. It is currently illegal for a public library unit to "with" one of
its private siblings.  Of course it only makes sense to do so if the
private sibling is used only in the private part of the importing
package.  Tucker seems to think this is a feature; everybody else seems
to think it's a bug.

Note that (1) was a problem even in Ada 83, when child units and private
library units did not exist.

I believe Robert has stated that problem (1) is important to solve,
whereas (2) is merely nice to have.  And Randy and Pascal have stated
that (2) is important, whereas (1) is merely nice to have.  (Sorry if I
got that wrong -- I'm just trying to point out that folks disagree about
the priorities.  I happen to think it would be nice to have a single
stone that kills both birds.  I've been frustrated by both problems.)

> Clearly we can't allow a parent package spec to "with" its own
> private children.  So instead it must be siblings, nieces, etc.
> that can "private with" their private siblings, aunts, etc.
>
> I suppose an alternative is to simply allow these "with" clauses,
> but then say that if the with'ed unit is private, it only becomes
> visible in the private part.  This is roughly equivalent to saying
> that when a unit is "with"ed, if it is a private child, it
> is implicitly inserted at the end of the private part of its parent,
> while if it is a public child, it is implicitly inserted at the
> end of the visible part of its parent.  In any case, a spec
> can never "with" its own descendant.

This idea solves problem (2), but not problem (1).  We can solve both
problems at the same cost.

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

From: dewar@gnat.com
Sent: Sunday, February 25, 2001 10:47 AM

<<I don't buy Pascal's objection that it's useful to see this stuff up
front.  In fact, it damages readability to see it up front, because this
information is purely private.  One should be able to read the public
information without being distracted.  (I support the idea of physically
separating private parts for the same reason.)
>>

I agree that it is quite wrong to see this up front, in fact this makes
me realize that our headers are not quite right, we say:

-- This specification is derived from the Ada Reference Manual for use with --
-- GNAT. The copyright notice above, and the license provisions that follow --
-- apply solely to the  contents of the part following the private keyword. --

But in fact the copyright also applies to the misplaced with's :-)

(legally, this is probably de minimus, still it is interesting to note
the intersection of technical and copyright concerns here :-)

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

From: Randy Brukardt
Sent: Monday, February 26, 2001 5:41 PM

> I am in favor of that idea.

I object to this idea because it turns a "simple, easy" idea into one that
is much more complex to implement. That could easily tip the balance in
opposition to this feature. (It does for me.)

Implementing a with for which visibility appears at the private part seems
easy: we already have things that become visible at that point, and it
shouldn't be hard to add some additional ones. So the change is a tiny bit
of syntax and a bit hacking.

OTOH, for Janus/Ada, the "with" processing code was designed knowing that it
only was inserting into an empty (other than other withs) symboltable. It
wouldn't be possible to call it at the occurrence of "private" without a lot
of reworking. (Janus/Ada is an almost pure 1-pass compiler as far as
processing semantics is concerned.)

It would be possible, of course, to (logically) transform the program into
one where all of the context clauses are at the top -- but that would take a
substantial new mechanism that would be quite a bit more complex than
anything that we currently do. And, again, we would be substantially
reworking the "with" processing (in this case, to use the transformed
context clause rather than the one found in the syntax).

We also would have to get rid of the "fast" mode from our library management
tools, which assumes one unit per file (and thus, only reads the first few
lines to find the context clause).

I think the amount of work to implement that would outweigh any benefits (at
least until some customer with $$$$ cares), and thus I would probably have
to vote against it.

(This really begs the question of what we're doing here. If we're adding
small, important features to Ada 95 *now*, then making the feature more
complex than it has to be is a mistake. If we're really designing the next
revision of Ada, then the dynamic is quite different. The answer of what to
do is not always the same in both cases...)

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

From: Robert A Duff
Sent: Sunday, February 25, 2001 9:49 AM

> Note that the mere fact of the with's being at the top of the abstract
> representation does not mean they have to be there in the physical
> representation if you separate this into two separate files. There is
> no rule that says that the only allowable way to split into two files
> is to draw a line in the source :-)

Well, Bob Duff has a personal rule that he's not willing to do fancy
editing to convert from one so-called "source representation" to
another.  ;-)

If you give me a tool that does it automatically (or even tell me a
simple way to write one myself), and it guarantees the same exact
semantics, then OK.

I'm arguing from a purely practical point of view here.  If we're
serious about putting private parts in separate files, there needs to be
a standard (concrete) syntax for doing so.

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

From: dewar@gnat.com
Sent: Sunday, February 25, 2001 10:38 AM

<<Well, Bob Duff has a personal rule that he's not willing to do fancy
editing to convert from one so-called "source representation" to
another.  ;-)>>

A reasonable rule :-)

<<I'm arguing from a purely practical point of view here.  If we're
serious about putting private parts in separate files, there needs to be
a standard (concrete) syntax for doing so.>>

I would definitely prefer that this be the case ...

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

From: Pascal Leroy
Sent: Tuesday, February 27, 2001 4:31 AM

> > I'm only mildly worried about the "simple minded tool" issue.
> > Better to improve the language than to worry about that.
>
> We also would have to get rid of the "fast" mode from our library management
> tools, which assumes one unit per file (and thus, only reads the first few
> lines to find the context clause).

I emphatically side with Randy here.  The "simple minded tools" are very
important to the usability of compilation systems, and they are quite hard to
get right.  Changing them can be a significant part of the effort involved, so
if we want to be serious in assessing the cost and benefits of any language
change, we have to look at the entire picture.

Our environment uses a "simple minded" parser to determine the compilation order
of units.  This parser looks at the beginning of a file for the withs and
separate clause, and returns a skeleton Diana tree which we use to compute the
compilation order.  With the proposed change this parser would have to become a
full-fledged parser because nearly every language construct can appear in the
visible part of a package (in particular, all the expression stuff would have to
be there).  Moreover, we would lose a useful capability: with the current
mechanism, we are able to compute the compilation ordering even if units have
syntax errors.  If we need to parse more text, it's likely that syntax errors
would cause us to give up and produce an incorrect ordering.

And then of course, there is this "simple minded tool" named ASIS, which we used
ubiquitously in our products.  Adding a new predicate to ask whether a with
clause is a "private with" looks easy.  Adding a new context_clause after the
word private would require substantial restructuring of the interfaces that
analyze compilation units.

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

!topic Extending the private part of a package
!reference RM95-10.1.2(8)
!from Michael Gray
!sent Thursday, May 17, 2001  7:22 AM
!discussion

This issue was raised in reference to child packages. The spec of a child
package can be regarded as an extension to the spec of its parent (Rationale
II.7, "We can think of the child package as being declared inside the
declarative region of its parent but after the end of the specification of
its parent; most of the visibility rules stem from this model.") However, a
private child cannot be used as an extension of the private part of its
parent. This is because a private child is not visible to the same set of
places that its parent's private part is visible to; specifically, it is not
visible to the private parts of its siblings, whereas its parent's private
part is. There seems to have been some ambiguity about this in the
development of Ada95; Rationale section II.8 says "The other extra rule is
that the visible part of the private child can access the private part of
its parent. This is quite safe because it cannot export information about a
private type to a client because it is not itself visible. Nor can it export
information indirectly via its public siblings because, as mentioned above,
it is not visible to the visible parts of their specifications but only to
their private parts and bodies." I.e. this is saying that a private package
is visible to the private part of its public siblings, which is in flat
contradiction to LRM 10.1.2 (8), "If a with_clause of a given
compilation_unit mentions a private child of some library unit, then the
given compilation_unit shall be either the declaration of a private
descendant of that library unit or the body or subunit of a (public or
private) descendant of that library unit." This rule prevents a public
package "with"ing its private sibling, which therefore prevents the private
part of the public package getting visibility of its private sibling. We
cannot see a reason for this restriction.

The situation arose in the following context. We had a 'framework' of
packages A and A.B. We wished to provide a number of 'concrete' extensions
A.X and A.B.X; A.Y and A.B.Y; etc, where A.X etc are private (they are
intended for use only by A.B.X). But this was impossible because although
A.B's private part has visibility of A's private part, A.B.X's private part
does not have visibility of A.X's private part, because A.B (and therefore
A.B.X) cannot 'with' its private sibling A.X.

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

From: Randy Brukardt
Sent: Friday, May 25, 2001  9:53 PM

The reason for the restriction is to prevent re-export of information from a
private package, and to prevent units outside of the "subsystem" from
depending on the private package. See AARM 10.1.2(8.a-l) for some commentary
on this.

On the other hand, there is a proposal on the table (AI-262) for "private
with"s, which would allow withing packages only to be used in the private
part of a package. This also would allow the withing of private packages in
the specs of sibling packages. This is discussed in AI-262, which isn't
written up yet. Does this seem like it would solve your problem??

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

From: Michael Gray
Sent: Tuesday, May 29, 2001  6:02 AM

> The reason for the restriction is to prevent re-export of information from a
> private package, and to prevent units outside of the "subsystem" from
> depending on the private package. ...

Sure, I understand that. What I meant was, we couldn't see a reason why the
language should not make the content of a private package visible to the
/private/ part of its sibling.

> ... Does this seem like it would solve your problem??

Yes it does.

I had been thinking along the following lines: if A.B is a public child and
A.C a private child, then A.B should be able to "with" A.C, such that this
would give /only/ the private part of A.B visibility of A.C. But having
skimmed the 26 pages of AI-262, I agree that it would be better to have some
"private with" syntax by which context clauses that are needed only by the
private part of a package can be differentiated from context clauses that
are needed by the visible part (or both parts).

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

Questions? Ask the ACAA Technical Agent