Version 1.1 of ais/ai-40217.txt

Unformatted version of ais/ai-40217.txt version 1.1
Other versions for file ais/ai-40217.txt

!standard 03.10.01 (02)          03-01-16 AI95-00217-05/01
!standard 03.10.01 (03)
!standard 03.10.01 (04)
!standard 03.10.01 (05)
!standard 03.10.01 (08)
!standard 03.10.01 (09)
!standard 03.10.01 (10)
!standard 03.10.01 (11)
!standard 10.01.02 (03)
!standard 10.01.02 (04)
!standard 10.01.02 (08)
!standard J.10 (00)
!class amendment 03-01-16
!status work item 03-01-16
!status received 03-01-16
!priority Medium
!difficulty Hard
!subject Type stubs with abstracted packages
!summary
A pair of new constructs, called "type stub"s and "abstract clause"s are added to the Standard to provide a solution to the "mutually recursive types across packages" problem.
An abstract clause specifies an "abstracted package". Details from this package can be used in the current compilation unit without creating a semantic dependence. An abstracted package is specified by its full expanded name.
A type stub is a kind of incomplete type declaration which is completed in an abstracted package. Compile-time checks are performed on use of the name introduced by the type stub that the completion is "available" and "appropriate" (see !proposal for details).
A concept of a "tagged incomplete" type is introduced, which is a type that has the same restrictions as an incomplete type except that it may also be used for a formal or actual parameter. A corresponding tagged type stub is defined, with the corresponding restrictions.
!problem
Ada allows mutually recursive types to be declared only if they are all declared within the same library unit. This can force all of the major data structures of a program into a single library unit, which is clearly undesirable in some situations.
The goal of the proposed features is to allow mutual recursion among separately compiled types (types containing (pointers to) each other as components, and primitive operations with (pointers to) each other as parameters), and to do this in a way that doesn't place any undue restrictions on the programmer.
For mutually recursive types, it is valuable if subprogram parameters may be of the type itself, rather than only an access to the type. However, for most types, it may be necessary to see the full definition to know how parameters of the type are passed. However, because tagged types are always passed by reference, there is no implementation difficulty in allowing them to be used as parameters even when the full definition of the type is not available. Hence, it makes sense to relax the rule for using incomplete types that are known to be tagged, to allow them as formal and actual parameters, since from a code generation point of view they are essentially equivalent to access parameters.
!proposal
The syntax for a context_item is amended as follows:
context_item ::= with_clause | use_clause | abstract_clause abstract_clause ::= [private] abstract of abstracted_package_specifier; abstracted_package_specifier ::= identifier | abstracted_package_specifier . identifier;
A package specified in an abstract_clause is called an "abstracted package". The abstracted package does not create a semantic dependence on the specified package.
The abstract_package_specifier can be used within the declarative region of the compilation_unit, unless the keyword private appears, in which case it may only be used in private parts and bodies. (This is the same rule as for "private with".)
An abstracted package is intended to be used to declare that a second package (called the "package abstract") is an abstract of the abstracted package. (Note: this paragraph describes the model and intended use of the proposal, but plays no role in the proposal itself. In particular, we define "package abstract" solely to explain the intended model more easily.) A package abstract exports a subset of the capabilities of the abstracted package, but does not create a semantic dependence on it. Thus, it can be used to implement mutually dependent types. A package abstract is a completely normal package, and thus has no restrictions on what it can do.
The syntax for an incomplete type declaration is amended as follows:
incomplete_type_declaration ::= type defining_identifier [discriminant_part] [is tagged] | type_stub;
If the words IS TAGGED appear, the type is a tagged incomplete type. Otherwise, the type is a non-tagged incomplete type. In addition to places where a (non-tagged) incomplete type may be used, a tagged incomplete type may be used as a formal parameter type, and as an actual parameter that is a dereference of an access-to-tagged-incomplete value. The attribute 'Class is defined for (specific) tagged incomplete types. (The use of 'Class with non-tagged incomplete types is considered obsolescent; such non-tagged incomplete types must be completed with a tagged type.) The class-wide type denoted by the Class attribute of an incomplete tagged type is also an incomplete tagged type. An incomplete tagged type declaration must be completed by a tagged type declaration.
A new kind of incomplete type declaration is added:
type_stub ::= type defining_identifier [discriminant_part] is [ tagged ] separate in abstracted_package_specifier;
A type_stub introduces an incomplete type whose completion occurs in the package identified by the abstracted_package_specifier. The abstracted package must appear in an abstract_clause for the compilation_unit. If the word TAGGED appears, the type is a tagged incomplete type. The abstracted_package_specifier is not subjected to the name resolution rules at the place of the type_stub.
In order to be a completion, the completing type declaration must be in the visible part of the abstracted package, must not be an incomplete type declaration, and must satisfy all other rules for incomplete type completion. This rule is enforced when the incomplete type is used in a context where a complete type is required.
When the name introduced by a type stub is used in a context where it must match some other type, if the other type is a type stub, a check is made they have the same abstracted_package_specifier. If the other type is a complete type, a check is made that the the full expanded name of the package where the other type is declared matches that of the type stub's abstracted_package_specifier, and the other type is an acceptable completion of the incomplete type.
When a name introduced by a type stub is used in a context where a complete type is required, other than where it must match a particular complete type (which is described above), a check is made that the usage place is within the immediate scope of the completion, or is within the scope of a with clause that mentions the package identified by the type stub's abstracted_package_specifier. A check is made that the completion is not an incomplete type declaration, and satisfies the other requirements for completing an incomplete type. A check is made that the abstracted_package_specifier provides the full expanded name of the completing package -- it must not involve any renamings. (This eliminates ambiguities when checking for type matching of two type stubs with the same completion, and simplifies the check whether a completing package is "available.")
!wording
Replace 3.10.1(2):
incomplete_type_declaration ::= type defining_identifier [discriminant_part] [is tagged]; | type_stub
type_stub ::= type defining_identifier [discriminant_part] is [tagged] separate in abstracted_package_specifier;
abstracted_package_specifier ::= identifier | abstracted_package_specifier . identifier;
Modify 3.10.1(3):
An incomplete_type_declaration other than a type_stub requires a completion, which ...
Insert 3.10.1(3.1):
A type_stub includes a abstracted_package_specified which specifies the full expanded name of the package in which its completion is expected to occur. [Certain uses (see below) of a name that denotes the type_stub or a value of an access type that designates the type_stub, require that the completion exist.] In these cases, the completion shall occur in the visible part of the specified package, and be a type_declaration other than an incomplete_type_declaration; the abstracted_package_specifier shall be the full expanded name of this package (starting with a root library unit, and using no renaming declarations), and the package shall be a library package.
Modify 3.10.1(4):
Add a new first sentence:
If an incomplete_type_declaration includes the keyword TAGGED, then a type_declaration that completes it shall declare a tagged type.
Replace all occurrences of "full_type_declaration" with "type_declaration" in the remaining sentences, so that a private type (or private extension) can complete a type stub.
Add a new last sentence:
In the case of a type_stub, these checks are performed no later than when a construct requires the completion to be available.
Replace 3.10.1(5-10):
A name that denotes an incomplete_type_declaration may be used as follows:
* as the subtype_mark in the subtype_indication of an access_to_object_definition; the only form of constraint allowed in this subtype_indication is a discriminant_constraint;
* as the subtype_mark defining the subtype of a parameter or result of an access_to_subprogram_definition;
* as the subtype_mark in an access_definition;
A name that denotes an incomplete_type_declaration that includes the keyword TAGGED may also be used as follows:
* as the subtype_mark defining the subtype of a parameter in a formal_part;
* as the prefix of an attribute_reference whose attribute_designator is Class; such an attribute_reference is restricted to the uses allowed above.
If a name that denotes an incomplete_type_declaration is used in other contexts, the incomplete_type_declaration shall be a type_stub, and the completion shall be available at the place of use, as defined by either of the following conditions:
* the place of use is within the immediate scope of the completion of the type_stub; or
* the place of use is within the scope of a with_clause that mentions the package specified by the abstracted_package_specifier of the type_stub.
The completion of an incomplete_type_declaration that is not a type_stub is defined to be available throughout the (extended) scope of the completion. The completion of an incomplete class-wide type is available wherever the completion of the root of the class is available.
A dereference (implicit or explicit) of a value of an access type whose designated type D is incomplete is allowed only in the following contexts:
* in a place where the completion of D is available (see above);
* in a context where the expected type is E and
o E covers the completion of D, o E is tagged and covers D, o E covers D'Class or its completion, or o E'Class covers D or its completion;
* as the target of an assignment_statement where the type of the value being assigned is V, and V or V'Class is the completion of D.
In these contexts, the incomplete type is defined to be the same type as its completion, and its first subtype statically matches the first subtype of its completion.
Replace 3.10.1(11):
An incomplete_type_declaration declares an incomplete type and its first subtype; the incomplete type is tagged if the keyword TAGGED appears; the first subtype is unconstrained if a known_discriminant_part appears. Two type_stubs are defined to be the same type if they have the same defining identifier, the same sequence of identifiers in their abstracted_package_specifiers, and their first subtypes match statically.
Replace 10.01.2(3):
context_item ::= with_clause | use_clause | abstract_clause
Add after 10.01.2(4):
abstract_clause ::= [private] abstract of abstracted_package_specifier;
Add after 10.01.2(8):
The abstracted_package_specifier of an abstract_clause that appears on a library_unit_declaration or library_unit_renaming_declaration may be used in entire declarative region of the declaration, which includes all children and subunits. The abstracted_package_specifier of an abstract_clause that appears on a body may be used in that body, including all subunits.
A abstracted_package_specifier defined only in abstract_clauses that include the reserved word private shall be used only within
* a private part, * a body, * a private descendant of the unit on which one of these
abstract_clauses appear.
Add J.10:
J.10 The Class Attribute of Non-tagged Incomplete Types
For the first subtype S of a type T declared by an incomplete_type_declaration that is not tagged and is not a type stub, the following attribute is defined:
S'Class
Denotes the first subtype of the incomplete class-wide type rooted at T. The completion of T shall declare a tagged type. Such an attribute reference shall occur in the same library unit as the incomplete_type_declaration.
!discussion
We considered calling these "separate incomplete types", but we felt it was more consistent to use the term "stub" rather than "separate" to be consistent with the program unit "stub" terminology.
An abstract_clause does not declare a name. This was done so that we do not have to introduce a "ghost" package in order to explain the presence of this name. We also do not want to be able to use the abstracted_package_specifier other than in a stub of some sort (with a type stub being the only kind allowed currently). If it is a name, it could be used in other contexts, requiring the insertion of checks that this is not the case into an implementation.
We considered a syntax closer to that of existing with_clauses for abstract_clauses. For instance, we considered:
[private] separate with P;
However, we rejected this for two reasons. First, this clause does not create a semantic dependence, while a with_clause does. It also does not declare a name. Thus it is very different semantically than a with_clause. Second, this syntax means that adding or removing a single keyword makes a massive semantic difference.
We are not allowing an incomplete tagged type to be used as a return type, because of the many special rules and implementation issues associated with returning tagged types (e.g. functions that must be overridden, accessibility checks on returning limited by-reference types, dispatching on result coupled with tag indeterminacy, finalization associated with returning potentially controlled types, etc.).
There may be multiple type stubs that are completed by a single completing type declaration. This is essential if type stubs are allowed in generic packages.
There is no particular restriction on where a type stub may occur, unlike the restriction on program unit stubs. In particular, a type stub may occur in a declare block, a subprogram body, or anywhere an incomplete type declaration may occur. Of course, they are generally only useful if used in a place where a separately compiled unit can see the stub as well as the completing package, so putting them in a declare block, or a subprogram body without any program unit stubs, would not be of any great use.
There seem to be two general ways that the problem of mutually recursive types is solved in other languages. One approach is to permit unrestricted forward references. This is the approach adopted by Eiffel, Java, and Smalltalk. The other approach is to require "forward" or "incomplete" declarations, sometimes called "signatures" or "partial revelations." This is generally the approach adopted by Ada, as well as Pascal, Modula, ML, C/C++, etc., and is the approach adopted here for cross-package mutual recursion.
We chose the simple approach of extending a single existing Ada feature, rather than adding a basket of heavy new features to provide the needed capability. This simplifies both the conceptual burden and the implementation cost.
The model of a type stub per se does not add any significant new implementation burden, because it is very similar to the incomplete-deferred-to-body type which Ada 95 already has. The compiler does not need to know the real type involved as long as the usage rules for incomplete types are enforced.
Determining the representation of an access type that designates a type stub could be a problem for some implementations that select the representation of an access type based on the designated type. However, this would be no different than for a type whose completion is deferred to the body. Such implementations must already be able to handle this somehow.
Since an access type that designates a type stub is a normal declaration, representation clauses (for storage pools, for instance) can be used as needed. This eliminates many of the problems found in the "with type" proposal. Note that such an access type can be used normally (including allocators, deallocators, and the like) when the completing type is visible.
The key difference here from the "with type" proposal is that type stubs, and any associated access type declarations, are "real" declarations that can be referenced from other packages. A "with type" clause would have had the same rules of a "with" clause, which means that they would not be visible to other packages. Instead, each package would require its own with type clause, making it harder to share access types, and requiring trickier visibility rules to deal with "incomplete" packages as well as incomplete types.
Conceptual and implementation difficulties arise from the question where the type is to be regarded as completed and hence allows for object creation and availability of operations of the type. It is clear that such a place must have a semantic dependence on (the package containing) the type completion. However, to avoid ripple effects relating to "indirect" semantic dependences associated with "distant" with clauses, we propose that the completion is only "available" when within the immediate scope of the completion itself, or the scope of a with clause that mentions the completing package. This rule is relaxed when the complete type is in the immediate context of the usage (i.e., the incomplete type is used in a context where it must match the complete type).
We considered other rules, such as requiring only semantic dependence (rejected due to the ripple effects), or creating an implicit semantic dependence at the point of a usage where the completion was needed (rejected due to difficulties for some implementations, and loss of visible "documentation" of the dependence).
Another issue was whether the checking should happen at link time, or at any time when both the stub and the completing package were both in scope. We rejected both of these as they seemed to add complexity, without adding safety. Eliminating the link-time check was seen to be useful for testing individual subsystems, before an entire system was complete.
We considered allowing the type stub to specify both the package where the completion occurs, and the name of the completing type. A potential syntax was "... is separate P.T" as an alternative to, or in addition to "... is separate in P". This seemed particularly useful in contexts where one wanted to have multiple type stubs in the same context, and type names like "Object" were being used consistently in packages. However, it was pointed out that the stubs could be placed in sub-packages if necessary to have two declared in the same context. This workaround was considered acceptable, and it preserved the simplicity of the single "separate in P" syntax.
We considered having some restriction relating to specifying private child packages. However, it was unclear what the rule should be, and there seemed no particular benefit in adding the complexity. Clearly if the completion is in a private child, only packages that have visibility on that child can make use of the completion, and can dereference an access-to-type-stub. But there seems no particular harm in allowing the type stub to specify a private child. Without actually "looking" at the specified package, it may not be easy to determine whether it is a private child. If the check is made at the time of the use of the incomplete type, then a somewhat artificial check needs to be made at that time that the location of the type stub is inside the subsystem where the completing package is visible. An important property is that changing a private child, or adding or removing a private child, have no effect outside its "subsystem." That remains true even without any additional check, since the type stub by itself is legal, it is the usages that would be affected, and they would all have to be inside the subsystem.
We considered limiting a package to a single abstract_clause. In this case, the abstract clause could be a modifier to the package rather than a context clause. This is closer to the intended use of the feature (creating an abstract for a single package). However, there seems to be no benefit for use or implementation to this restriction, and it is conceivable that valuable uses for packages containing multiple abstracted packages can be found.
!example
Here is the classic case of mutual dependence, where an employee belongs to a particular department, and a department has a manager who is an employee. (We assume the use of tagged types here to illustrate the use of tagged incomplete types.)
Two versions are presented. The first uses separate packages as package abstracts, which is usually advisable to have single well defined place for the access types. If it is desired to have the access type also be available in the abstracted package, that can be accomplished with a subtype declaration, as illustrated in package Employees.
abstract of Employees; package Employees_Abstract is
type Employee is tagged separate in Employees; type Emp_Ptr is access all Employee'Class;
end Employees_Abstract;
abstract of Departments; package Departments_Abstract is type Department is tagged separate in Departments; type Dept_Ptr is access all Department'Class; end Departments_Abstract;
with Departments_Abstract, Employees_Abstract; package Employees is type Employee is tagged private; subtype Emp_Ptr is Employees_Abstract.Emp_Ptr; procedure Assign_Employee(E : in out Employee; D : in out Departments_Abstract.Department); ... function Current_Department(D : in Employee) return Departments_Abstract.Dept_Ptr; end Employees;
with Departments_Abstract, Employees_Abstract; package Departments is type Department is tagged private; procedure Choose_Manager(D : in out Department; Manager : in out Employees_Abstract.Employee); ... end Departments;
The second version does a more direct coupling. (Note that, while it looks simpler and much more elegant, it can be used only in settings where the access types are needed in only one of the respective packages.)
abstract of Departments; package Employees is
type Department is tagged separate in Departments; type Dept_Ptr is access all Department'Class; type Employee is tagged private; procedure Assign_Employee(E : in out Employee; D : in out Department); ... function Current_Department(D : in Employee) return Dept_Ptr;
end Employees;
abstract of Employees; package Departments is type Employee is tagged separate in Employees; type Emp_Ptr is access all Employee'Class; type Department is tagged private; procedure Choose_Manager(D : in out Department; Manager : in out Employee); ... end Departments;
!corrigendum 3.10.1(2)
Replace the paragraph:
incomplete_type_declaration ::= type defining_identifier [discriminant_part];
by:
incomplete_type_declaration ::= type defining_identifier [discriminant_part] [is tagged];
| type_stub
type_stub ::= type defining_identifier [discriminant_part] is [tagged]
separate in abstracted_package_specifier;
abstracted_package_specifier ::= identifier |
abstracted_package_specifier . identifier
!corrigendum 3.10.1(3)
Replace the paragraph:
An incomplete_type_declaration requires a completion, which shall be a full_type_declaration. If the incomplete_type_declaration occurs immediately within either the visible part of a package_specification or a declarative_part, then the full_type_declaration shall occur later and immediately within this visible part or declarative_part. If the incomplete_type_declaration occurs immediately within the private part of a given package_specification, then the full_type_declaration shall occur later and immediately within either the private part itself, or the declarative_part of the corresponding package_body.
by:
An incomplete_type_declaration other than a type_stub requires a completion, which shall be a full_type_declaration. If the incomplete_type_declaration occurs immediately within either the visible part of a package_specification or a declarative_part, then the full_type_declaration shall occur later and immediately within this visible part or declarative_part. If the incomplete_type_declaration occurs immediately within the private part of a given package_specification, then the full_type_declaration shall occur later and immediately within either the private part itself, or the declarative_part of the corresponding package_body.
A type_stub includes a abstracted_package_specifier which specifies the full expanded name of the package in which its completion is expected to occur. Certain uses (see below) of a name that denotes the type_stub or a value of an access type that designates the type_stub, require that the completion exist. In these cases, the completion shall occur in the visible part of the specified package, and be a type_declaration other than an incomplete_type_declaration; the abstracted_package_specifier shall be the full expanded name of this package (starting with a root library unit, and using no renaming declarations), and the package shall be a library package.
!corrigendum 3.10.1(4)
Replace the paragraph:
If an incomplete_type_declaration has a known_discriminant_part, then a full_type_declaration that completes it shall have a fully conforming (explicit) known_discriminant_part (see 6.3.1). If an incomplete_type_declaration has no discriminant_part (or an unknown_discriminant_part), then a corresponding full_type_declaration is nevertheless allowed to have discriminants, either explicitly, or inherited via derivation.
by:
If an incomplete_type_declaration includes the keyword tagged, then a type_declaration that completes it shall declare a tagged type. If an incomplete_type_declaration has a known_discriminant_part, then a type_declaration that completes it shall have a fully conforming (explicit) known_discriminant_part (see 6.3.1). If an incomplete_type_declaration has no discriminant_part (or an unknown_discriminant_part), then a corresponding type_declaration is nevertheless allowed to have discriminants, either explicitly, or inherited via derivation. In the case of a type_stub, these checks are performed no later than when a construct requires the completion to be available.
!corrigendum 3.10.1(5)
Replace the paragraph:
The only allowed uses of a name that denotes an incomplete_type_declaration are as follows:
by:
A name that denotes an incomplete_type_declaration may be used as follows:
!corrigendum 3.10.1(8)
Replace the paragraph:
by:
A name that denotes an incomplete_type_declaration that includes the keyword tagged may also be used as follows:
!corrigendum 3.10.1(9)
Replace the paragraph:
by:
If a name that denotes an incomplete_type_declaration is used in other contexts, the incomplete_type_declaration shall be a type_stub, and the completion shall be available at the place of use, as defined by either of the following conditions:
The completion of an incomplete_type_declaration that is not a type_stub is defined to be available throughout the (extended) scope of the completion. The completion of an incomplete class-wide type is available wherever the completion of the root of the class is available.
!corrigendum 3.10.1(10)
Replace the paragraph:
A dereference (whether implicit or explicit -- see 4.1) shall not be of an incomplete type.
by:
A dereference (implicit or explicit -- see 4.1) of a value of an access type whose designated type D is incomplete is allowed only in the following contexts:
In these contexts, the incomplete type is defined to be the same type as completion, and its first subtype statically matches the first subtype of its completion.
!corrigendum 3.10.1(11)
Replace the paragraph:
An incomplete_type_declaration declares an incomplete type and its first subtype; the first subtype is unconstrained if a known_discriminant_part appears.
by:
An incomplete_type_declaration declares an incomplete type and its first subtype; the incomplete type is tagged if the keyword tagged appears; the first subtype is unconstrained if a known_discriminant_part appears. Two type_stubs are defined to be the same type if they have the same defining identifier, the same sequence of identifiers in their abstracted_package_specifiers, and their first subtypes match statically.
!corrigendum 10.01.2(3)
Replace the paragraph:
context_item ::= with_clause | use_clause
by:
context_item ::= with_clause | use_clause | abstract_clause
!corrigendum 10.01.2(4)
Insert after the paragraph:
with_clause ::= with library_unit_name {, library_unit_name }
the new paragraph:
abstract_clause ::= [private] abstract of abstracted_package_specifier;
!corrigendum 10.01.2(8)
Insert after the paragraph:
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.
the new paragraphs:
The abstracted_package_specifier of an abstract_clause that appears on a library_unit_declaration or library_unit_renaming_declaration may be used in entire declarative region of the declaration, which includes all children and subunits. The abstracted_package_specifier of an abstract_clause that appears on a body may be used in that body, including all subunits.
A abstracted_package_specifier defined only in abstract_clauses that include the reserved word private shall be used only within
!corrigendum J.10(1)
Insert new clause:
For the first subtype S of a type T declared by an incomplete_type_declaration that is not tagged and is not a type stub, the following attribute is defined:
S'Class
Denotes the first subtype of the incomplete class-wide type rooted at T. The completion of T shall declare a tagged type. Such an attribute reference shall occur in the same library unit as the incomplete_type_declaration.
!ACATS test
A series of B and C tests should be constructed for this proposal.
!appendix

[For discussion on the once-approved version of this proposal, see AI-00217-04.]

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

From: Pascal Leroy
Sent: Tuesday, December 17, 2002,  5:03 AM

I am forwarding the following message from John to the ARG mailing list because
I would like to get the ball rolling.

AI 217 was rejected by WG9 because of the objection/proposal below.  I want to
get a resolution on this issue at the Padua meeting, so that we can send this
AI (which I view as very important) to WG9 in June.

As John points out, moving the stub declaration at the front of the unit brings
us back to the "with type" proposal, and we know that this one is full of
problems.

The notion of having a new kind of with clause for the sole purpose of human
readability makes some sense, but then there is very little semantics there,
and I am not too excited by the idea of adding a completely new construct which
has about the same value as a comment (OK, not quite).

What do other people think?

Pascal
--
> AI-217 is type stubs of course.
>
> The issued raised at the presentation made by Tuck was that
> many people from the floor objected to a package P being
> mentioned in the stub
>
>    type T is ... separate in package P.
>
> inside the text of a unit Q and that there was no mention of
> P in the context clause for Q.
>
> I think the audience took on board the fact that the whole
> point was that Q must not depend on P and so a regular with
> clause was not possible. However they did not like the
> textual lurking and wanted some sort of up-front mention if
> only for the benefit of the human reader.
>
> What I thought was a sound suggestion from the floor was
> that maybe we could have a "with out" clause for P which
> gave the human reader visibility but no Ada dependence. This
> was greeted with a certain amount of mirth (perhaps because
> of the way in which I suggested it).
>
> One other suggestion from the floor was that maybe the whole
> stub declaration should be up front but that seemed
> unhealthy to me and would have a flavour of going back to
> the with type idea.
>
> Anyway, that was it.

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

From: Robert A Duff
Sent: Tuesday, December 17, 2002,  8:31 AM

> I am forwarding the following message from John to the ARG mailing
> list because I would like to get the ball rolling.
>
> AI 217 was rejected by WG9 because of the objection/proposal below.

This seems like, how does that saying go, "perfection is the enemy of
the good", or something like that?  Technically, the objection is right:
there *should* be some mention of that package in the context clause.
But from a practical point of view:  As an Ada user, I've been waiting
desperately for a solution to this serious language flaw for 7 years.
We've finally got a solution that works, and now folks want to hold it
up for perhaps another year or more to solve a relatively minor problem?
Grrr.

>...I
> want to get a resolution on this issue at the Padua meeting, so that
> we can send this AI (which I view as very important) to WG9 in June.

Wishful thinking.  The ARG has never been able to work that quickly.
At the Padua meeting, we will be in the "Norm Cohen mode", of cobbling
together vaguely readable syntax out of existing reserved words (because
adding new reserved words is viewed in the Ada community as morally akin
to consorting with the devil).  Then somebody will go off and write it
up, and we will need *another* meeting to actually vote on it.  And
there's a nonnegligible probability that we will get bogged down in an
argument about the tastefulness of the proposed syntax (see "mirth"
below), requiring a third meeting.  Historically, no serious technical
work gets done *between* meetings.

OK, enough ranting.  I can live with the proposal as is, or I can live
with an extra thing in the context clause, or I can live with putting
the whole thing in the context clause if that works.

> As John points out, moving the stub declaration at the front of the
> unit brings us back to the "with type" proposal, and we know that this
> one is full of problems.

Could someone explain that in more detail?  Why should merely shuffling
the syntax around cause trouble?  Can we shuffle the syntax without
changing the semantics?

> The notion of having a new kind of with clause for the sole purpose of
> human readability makes some sense, but then there is very little
> semantics there, and I am not too excited by the idea of adding a
> completely new construct which has about the same value as a comment
> (OK, not quite).

Ada has lots of features whose primary purpose is "comment", except with
one huge advantage: the reader has some confidence that you're not
lying, because the compiler checks the rules.  So I don't mind having a
new kind of with clause that is merely a (compiler-checked) comment.

> What do other people think?
>
> Pascal
> --
> > AI-217 is type stubs of course.
> >
> > The issued raised at the presentation made by Tuck was that
> > many people from the floor objected to a package P being
> > mentioned in the stub
> >
> >    type T is ... separate in package P.
> >
> > inside the text of a unit Q and that there was no mention of
> > P in the context clause for Q.
> >
> > I think the audience took on board the fact that the whole
> > point was that Q must not depend on P and so a regular with
> > clause was not possible. However they did not like the
> > textual lurking and wanted some sort of up-front mention if
> > only for the benefit of the human reader.
> >
> > What I thought was a sound suggestion from the floor was
> > that maybe we could have a "with out" clause for P which
> > gave the human reader visibility but no Ada dependence. This
> > was greeted with a certain amount of mirth (perhaps because
> > of the way in which I suggested it).

I can live with "with out".  But I can see why some folks find it
silly.  How about:

    with separate P;

or

    with separate type in P; -- Norman would like that.  ;-)

The Legality Rule would presumably be that if you say "type T is
separate in package P;", you must be within the scope of a "with
separate P;" clause.

> > One other suggestion from the floor was that maybe the whole
> > stub declaration should be up front but that seemed
> > unhealthy to me and would have a flavour of going back to
> > the with type idea.
> >
> > Anyway, that was it.

Tucker mentioned another issue: Some people use the style where every
type in the program has the same name: "Object" or "T" or "Instance",
and the actual semantics is encoded in the package name.  So if you want
types "Doctors_Package.Object" and "Patients_Package.Object" to be
mutually recursive, you can't do it.  Is that the issue, Tuck?

My response is, "So don't do that."

Besides, if you really want it to be called "Object", can't you always
rename "subtype Object is Doctor_Package.Doctor_Type;" to work around
the problem?  Is there a better solution?

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

From: Pascal Leroy
Sent: Tuesday, December 17, 2002,  9:16 AM

> This seems like, how does that saying go, "perfection is the enemy of
> the good", or something like that?  Technically, the objection is right:
> there *should* be some mention of that package in the context clause.
> But from a practical point of view:  As an Ada user, I've been waiting
> desperately for a solution to this serious language flaw for 7 years.
> We've finally got a solution that works, and now folks want to hold it
> up for perhaps another year or more to solve a relatively minor problem?
> Grrr.

I couldn't agree more.

> Wishful thinking.

You're probably right :-(

> > As John points out, moving the stub declaration at the front of the
> > unit brings us back to the "with type" proposal, and we know that this
> > one is full of problems.
>
> Could someone explain that in more detail?  Why should merely shuffling
> the syntax around cause trouble?  Can we shuffle the syntax without
> changing the semantics?

I suppose you could, but that doesn't make sense to me.  You would have a
declaration occurring in a context clause.  That's a whole new mechanism, and
certainly not an intuitive one.  I believe we want to preserve the invariant
that the context clause describes what is imported by a unit, and the visible
part contains the declaration exported by the unit.

> Ada has lots of features whose primary purpose is "comment", except with
> one huge advantage: the reader has some confidence that you're not
> lying, because the compiler checks the rules.  So I don't mind having a
> new kind of with clause that is merely a (compiler-checked) comment.

That's true in general, but here I fail to see that it buys you any safety at
all.  The only reason why you would have to type this new with clause is so that
the compiler can check the type stubs against it.  But then the compiler and/or
linker are surely going to check the package identifier occurring in the type
stub at some point.  So what's the big deal?

Consider the following analogy: body stubs can be scattered in a unit and they
do not need to be declared at the beginning of that unit.  Would it be useful
to require such declarations?  I don't think so.  OK, occasionally I forget to
provide a subunit, and I only discover the problem at link time.  But it
doesn't happen often in real life, and it doesn't compromise the safety of my
programs.

> How about:
>
>     with separate P;
>
> or
>
>     with separate type in P; -- Norman would like that.  ;-)

That sounds better than "with out".

> Tucker mentioned another issue: Some people use the style where every
> type in the program has the same name: "Object" or "T" or "Instance",
> and the actual semantics is encoded in the package name.  So if you want
> types "Doctors_Package.Object" and "Patients_Package.Object" to be
> mutually recursive, you can't do it.  Is that the issue, Tuck?
>
> My response is, "So don't do that."
>
> Besides, if you really want it to be called "Object", can't you always
> rename "subtype Object is Doctor_Package.Doctor_Type;" to work around
> the problem?  Is there a better solution?

This particular topic was discussed at the Cupertino meeting, and the
conclusion was that this was not important enough to make the construct more
complex.  I don't think we should revisit decisions that have been made after
extensive discussion, unless there is a new technical element that could modify
the conclusion.  Otherwise we are just never going to make any progress.

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

From: Barbey, St‚phane
Sent: Tuesday, December 17, 2002  9:22 AM

Robert A. Duff wrote:
> Tucker mentioned another issue: Some people use the style where every
> type in the program has the same name: "Object" or "T" or "Instance",
> and the actual semantics is encoded in the package name.  So if you want
> types "Doctors_Package.Object" and "Patients_Package.Object" to be
> mutually recursive, you can't do it.  Is that the issue, Tuck?
>
> My response is, "So don't do that."

... except it is heavily used by the IDL2Ada compilers (and BTW IDL has
a concept of forward declarations that would be much easier to work with
in Ada with if the ARG gets this AI right...)

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

From: Pascal Leroy
Sent: Tuesday, December 17, 2002, 10:06 AM

The AI explains (in the !example section) that it is advisable to introduce an
_Interface package to declare the type stubs.  The reason is that if you have
types that are involved in more than one cycle, this provides the best
structure.

With this approach, the example from the AI works fine even if everything is
named Object:

    package Employees_Interface is
        type Object is tagged separate in Employees;
        type Emp_Ptr is access all Object'Class;
    end Employees_Interface;

    package Departments_Interface is
        type Object is tagged separate in Departments;
        type Dept_Ptr is access all Object'Class;
    end Departments_Interface;

    with Departments_Interface, Employees_Interface;
    package Employees is
        type Object is tagged private;
        procedure Assign_Employee(E : in out Object;
                                  D : in out Departments_Interface.Object);
        ...
        function Current_Department(D : in Object) return
            Departments_Interface.Dept_Ptr;
    end Employees;

    with Departments_Interface, Employees_Interface;
    package Departments is
        type Object is tagged private;
        procedure Choose_Manager(D : in out Object;
                                 Manager : in out Employees_Interface.Object);
        ...
    end Departments;

With this approach the _Interface package effectively works as a forward
declaration.  The issue raised by Bob only exists if there is no _Interface
package and Employees and Departments directly declare type stubs for each
other.

I don't know what IDL compilers do, but it would be much easier to
systematically generate an _Interface package, than to detect the case where
direct dependence is possible.

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

From: Ben Brosgol
Sent: Tuesday, December 17, 2002 10:41 AM

> > This seems like, how does that saying go, "perfection is the enemy of
> > the good", or something like that?  Technically, the objection is right:
> > there *should* be some mention of that package in the context clause.
> > But from a practical point of view:  As an Ada user, I've been waiting
> > desperately for a solution to this serious language flaw for 7 years.
> > We've finally got a solution that works, and now folks want to hold it
> > up for perhaps another year or more to solve a relatively minor problem?
> > Grrr.
>
> I couldn't agree more.

Since neither Bob nor Pascal were present at Tuck's briefing to the SIGAda
attendees, let me set some context.  Tuck did not pose the question "Would
you rather have the proposed solution now, or a 'perfect' solution in a
year?"  If he had, then maybe the audience's response would have been
different.  Rather, his intent was just to get a sense of whether what the
ARG has been doing will meet the needs / expectations of typical users.  The
response, at least on the interdependent types AI, seemed pretty clear to me
(and also apparently to WG9, although I was not present at the WG9 meeting).
The people who cared expressed their opinions very cogently.  Solving 99.9%
of a problem is fine, but if the last .1% is perceived as important by
customers, then either convince the customer that they're wrong, or else
solve the problem.

As for the "it will take a year to solve", my reaction is: so what.  I don't
see compiler vendors rushing to get this stuff implemented.  In any event,
unless there are some other problems with the AI (in which case there would
be a delay anyway), the only issue is the choice of syntax for the context
clause item.  So even before the eventual final approval of the AI, people
(users and implementors) have a pretty good idea of what the feature will
look like.

By the way, where is the current version of this AI?  I looked at the web
site http://www.ada-auth.org/cgi-bin/cvsweb.cgi/AIs/AI-00217.TXT but the
latest version shown there is pretty old.

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

From: Randy Brukardt
Sent: Tuesday, December 17, 2002 12:45 AM

The AI we approved is "alternative 4" (or AI95-00217-04), so it is found in
the file AI-30217.TXT. So the correct URL is:
http://www.ada-auth.org/cgi-bin/cvsweb.cgi/AIs/AI-30217.TXT

We need to declare the others !No Action at some point, both to get them off
of the agenda and to help avoid mistakes...

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

From: Tucker Taft
Sent: Tuesday, December 17, 2002 10:59 AM

I will certainly take some of the blame for this,
because I didn't have ready arguments to justify
not having some visibility on the type stub in a context clause.

However, it was a surprise to me that this was the one
proposal that received widespread negative response, whereas
interfaces, object.operation, etc., all received almost unanimous
positive support.

The ..._Interface package "idiom" does seem like a reasonable
solution to the "type Object is" approach.  The question is whether
the idiom can also be considered to resolve the other objection,
because the _Interface packages are so short.

People do like Ada's context clause, and I do find Java's inconsistent
use of imports a bit weird.  In Java, if you give the full name of a class
(i.e. including its full package name prefix) where it is used,
then you don't need an "import" clause for the class.  Essentially
a Java "import" clause for a class makes the class name directly
visible (with no package prefix required), so it is closer to
a "use" clause for the enclosing package, than a "with" clause
for the class.  By contrast, the fact that Ada's context clauses
indicate all external references seems like a very good thing.

There seem to be various options to solve this problem:

1) Encourage use of the "..._Interface" idiom.
2) Add some kind of new "with" clause for packages that does
   not create a semantic dependence on the package.
   Only such packages may be mentioned in type stubs.
3) Add a new kind of "with" clause for types, that does
   not create a dependence on the package containing the type,
   and allows a renaming as part of the "with", effectively
   introducing the simple type name as an incomplete type
   implicitly declared immediately within the compilation unit
   having the "with" clause.
4) Add a new kind of "with" clause for types that implicitly
   creates an "incomplete" package for every package mentioned
   in the "with type" clause.  Such incomplete packages must
   not turn out to be renames (renames were a big bugaboo of
   the earlier attempts at "with type").

Number 4 is pretty much back to the old "with type", except
perhaps we have learned that renaming is bad news.

Number 1 is keeping what we have now.

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

From: Randy Brukardt
Sent: Tuesday, December 17, 2002 1:02 PM

Ben said:

> As for the "it will take a year to solve", my reaction is: so what. I don't
> see compiler vendors rushing to get this stuff implemented.

Well, I think that's wrong. Tucker already implemented a version of it in
their compiler. I've been planning to do so as soon as I get some time,
because it is badly needed to fix some structure problems in the Claw GUI
Builder. I thought Pascal had indicated that they would be doing it soon. So
there does seem to be some "rush to implement it"

This is probably the most important AI of anything proposed for the
amendment; certainly in the top two or three. We needed a solution for it
years ago (roughly 25 years ago, I think), and holding it up over some
perceived lack is dubious at best.

> In any event, unless there are some other problems with the AI (in which
> case there would be a delay anyway), the only issue is the choice of
> syntax for the context clause item.

No, there is at least one other solution, which is to revert to alternative
#3, which does not specify the completing unit in the type stub. I don't
know if that would satisify people or make them more uncomfortable - but it
certainly gets rid of the "hidden" "dependence" (which is neither).

I do agree that moving the declaration doesn't work, simply because it is a
declaration. Thus, its location controls its visibility. To try to move it
to the context clause would be a disaster (new mechanism, we'd need new
rules to allow private declarations and rep. clauses and on and on and on.)

In any case, we can at least take one meeting out of the cycle by coming to
some sort of consensus here, and writing that proposal up beforehand (as
alternative #5, I suppose).

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

From: Randy Brukardt
Sent: Tuesday, December 17, 2002 1:19 PM

> There seem to be various options to solve this problem:
>
> 1) Encourage use of the "..._Interface" idiom.
> 2) Add some kind of new "with" clause for packages that does
>    not create a semantic dependence on the package.
>    Only such packages may be mentioned in type stubs.

You forgot:

2A) (should be three, but I'm not going to renumber the others): Move the
dependence to the completor (as in alternative #3). (I always objected to
the "magic" semantics of the name in the stub.) The problems with that
proposal (which seemed minor) would have to be revisited. (As I recall, the
primary reason that this alternative was abandoned was that some ARG members
didn't like the lack of indication about where the expected completion was.

> 3) Add a new kind of "with" clause for types, that does
>    not create a dependence on the package containing the type,
>    and allows a renaming as part of the "with", effectively
>    introducing the simple type name as an incomplete type
>    implicitly declared immediately within the compilation unit
>    having the "with" clause.
> 4) Add a new kind of "with" clause for types that implicitly
>    creates an "incomplete" package for every package mentioned
>    in the "with type" clause.  Such incomplete packages must
>    not turn out to be renames (renames were a big bugaboo of
>    the earlier attempts at "with type").

#3 and #4 are way over the top; I see no reason to think about them further.

That leaves us with the other three. The main question is whether #2A helps
the problem, or makes people uncomfortable in the different way. And the
answer to that question really drives the choice: if people really want a
dependency to be declared (at the top) of the unit containing the stub, then
no solution other than #2 can be used. (That seems to be Ben's position.) If
the answer is that people are concerned about hidden dependencies, but are
not bothered by the lack of a dependency, then #2A should be pursued. And if
answer is that the majority of people want this now and don't care that much
about it, then we should stick to #1.

As far as the naming question goes, Pascal is right, we did discuss that in
Cupertino. And we got the wrong answer IMHO. I don't see that allowing (or
better still, requiring) type names in the stub makes the proposal any more
complicated at all. And I know that conflicting type names are quite common,
and I don't much like the answer of "don't do that!". But since I voted for
that feature (and was outvoted), I don't get to reopen it. :-)

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

From: Robert A. Duff
Sent: Tuesday, December 17, 2002 1:19 PM

> Tucker already implemented a version of it in
> their compiler.

It was Sheri Bernstein, actually.  I believe that implementation is
"incomplete".  I think having the final proposal nailed down would make
vendors less reluctant to implement it.  And if we all implement the
same thing, that would be a Good Thing for the Ada community.  ;-)

>... I've been planning to do so as soon as I get some time,
> because it is badly needed to fix some structure problems in the Claw GUI
> Builder. I thought Pascal had indicated that they would be doing it soon. So
> there does seem to be some "rush to implement it"
>
> This is probably the most important AI of anything proposed for the
> amendment; certainly in the top two or three.

Yeah, I'd say it's second only to the "abstract interfaces" thing.

> In any case, we can at least take one meeting out of the cycle by coming to
> some sort of consensus here, and writing that proposal up beforehand (as
> alternative #5, I suppose).

Sounds good to me.  Perhaps our esteemed chair will pester us enough so
that when the vote comes in Padua, we'll all know ahead of time how it's
going to turn out.  ;-)

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

From: Michael F. Yoder
Sent: Tuesday, December 17, 2002 1:59 PM

Disclaimer: I've never had a need for the feature under discussion, and
so I'm speaking from a "what if" perspective here; and from the user's
point of view, not the implementer's.

My first reaction is, the objection as presented actually doesn't seem
so unreasonable. But then I've not been expending bodily fluids on
behalf of the proposal.  :-)

My second is, that option 2 is preferable to the others. As a wickerman
proposal, how about

      with type in P1, ..., Pn;

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

From: Dan Eilers
Sent: Tuesday, December 17, 2002 2:33 PM

Tuck wrote:
> There seem to be various options to solve this problem:
> ...
> 2) Add some kind of new "with" clause for packages that does
>    not create a semantic dependence on the package.
>    Only such packages may be mentioned in type stubs.
> ...

There seems to be a potential orthogonality with AI 262 (private with),
if a user wants to indicate that the with'd unit can only be mentioned
in type stubs, and only in the private part.

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

From: John Barnes
Sent: Tuesday, December 17, 2002 10:39 AM

>>...I >> want to get a resolution on this issue at the Padua meeting, so that
>> we can send this AI (which I view as very important) to WG9 in June.

My view is that we don't *have* to do anything. It would be
quite reasonable for us to say that we have given it deep
reconsideration and have concluded that it is best the way
it is. Which is probably true.

The United Kingdom would be happy with that conclusion I am
sure.

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

From: Jean-Pierre Rosen
Sent: Wednesday, December 18, 2002 1:42 AM

> My second is, that option 2 is preferable to the others. As a wickerman
> proposal, how about
>
>       with type in P1, ..., Pn;

Actually, I proposed the same idea to Tuck in Houston, but with the syntax:
with package abstract Pack is
   type T1;
   type T2;
end package;

(only incomplete type declarations allowed, nothing else).

You can view this either as:
- A revival of the the abstract package, without creating new kind of compilation units
- JAS (Just Another Syntax) for the type stub (same effect as "type T1 is separate in Pack", just appearing in another place)
- Forcing a (partial) source compilation model on every compiler :-)

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

From: Pascal Leroy
Sent: Wednesday, December 18, 2002 3:49 AM

> As for the "it will take a year to solve", my reaction is: so what.  I don't
> see compiler vendors rushing to get this stuff implemented. In any event,
> unless there are some other problems with the AI (in which case there would
> be a delay anyway), the only issue is the choice of syntax for the context
> clause item.  So even before the eventual final approval of the AI, people
> (users and implementors) have a pretty good idea of what the feature will
> look like.

I completely disagree with this analysis.

First, any time spent by the ARG on 217 is time that is not spent on other
AIs.  So the question is as usual one of opportunity cost: what AIs are
currently on the table that we want to bury for the sole purpose of
marginally improving 217?

Second, you have to remember that we are not doing this intellectual
exercise in a vacuum: we have a schedule imposed by WG9, and this schedule
calls for finalizing proposals a year from now.  The worst that could happen
is that revisiting 217 would either cause the entire revision to slip, or
cause 217 to not be included in the amendment.

Third, your comment about vendors is misguided, and may represent the
position of your employer, but not that of other vendors.  Speaking for
Rational, we had a plan to start implementing some of the amendment AIs in
the next few months, for inclusion in a release that will reach customers
around the end of 2003, and 217 was part of that effort.  The fact that this
AI is now back on the drawing board means that we will probably cancel this
effort (unless the Padua meeting clarifies the situation) so support for 217
in our products will slip to mid-2005.  Who knows what IBM will decide is
the right thing to do in that time frame?

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

From: Pascal Leroy
Sent: Wednesday, December 18, 2002 3:56 AM

> There seem to be various options to solve this problem:
>
> 1) Encourage use of the "..._Interface" idiom.
> 2) Add some kind of new "with" clause for packages that does
>    not create a semantic dependence on the package.
>    Only such packages may be mentioned in type stubs.
> 3) Add a new kind of "with" clause for types, that does
>    not create a dependence on the package containing the type,
>    and allows a renaming as part of the "with", effectively
>    introducing the simple type name as an incomplete type
>    implicitly declared immediately within the compilation unit
>    having the "with" clause.
> 4) Add a new kind of "with" clause for types that implicitly
>    creates an "incomplete" package for every package mentioned
>    in the "with type" clause.  Such incomplete packages must
>    not turn out to be renames (renames were a big bugaboo of
>    the earlier attempts at "with type").

I think stylistically #1 is a good idea regardless of what language features
we add.

I could go with #2 if we can quickly agree on a syntax/semantics and discuss
that at Padua.

If we want to allow renaming (which I believe is unnecessary because of #1)
this must be done in the type stub declaration, not in the with clause as #3
seems to imply.  The with clause must only be used to reference the package,
not the type.  But I'd rather not reopen the renaming issue since it was
extensively discussed at Cupertino.

#4 is effectively the old "with type", but if you reread the minutes of the
meetings where this proposal was discussed, you'll see that renaming was
only one of the many problems with this idea.  One of the things that we
wanted to do with "with type" was to allow importing of access types (to
avoid having many different access types and conversions all over the
place).  But then the representation items associated with access types were
problematic.  And there were issues associated with the non-transitivity of
with clauses, which caused ripple effects in semantic dependencies.

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

From: Pascal Leroy
Sent: Wednesday, December 18, 2002 4:07 AM

> You forgot:
>
> 2A) (should be three, but I'm not going to renumber the others): Move the
> dependence to the completor (as in alternative #3). (I always objected to
> the "magic" semantics of the name in the stub.) The problems with that
> proposal (which seemed minor) would have to be revisited. (As I recall, the
> primary reason that this alternative was abandoned was that some ARG members
> didn't like the lack of indication about where the expected completion was.

If you look at the history of 217/03 (funny how we seem to forget all these
issues that we discussed to death), you'll see that there were two main
problems:

1 - How do you specify that a full type completes a stub?  (We considered
syntax that would make the full type declarations even more complicated, or
representation-item-like syntax, but none of that was satisfactory).

2 - You need to deal with the situation where a stub has several
completions.  This requires a lot of additional post-compilation checking,
and errors may end up being detected very late in the development process.

I find it curious that the users are telling us "we want to be more
explicit/safe in specifying which unit contains the completion" and #2A
answers that objection by saying "we won't let you specify where the
completion lives" ;-)

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

From: Pascal Leroy
Sent: Wednesday, December 18, 2002 4:12 AM

> My first reaction is, the objection as presented actually doesn't seem
> so unreasonable. But then I've not been expending bodily fluids on
> behalf of the proposal.  :-)

The objection is not unreasonable, but the question is: is it important
enough to reopen the AI?  If all we do is quickly agree on the
syntax/semantics of a new kind of with clause, fine.  But the recent mail
traffic has shown that we were reopening all sorts of all discussions, and
that's the best way to lose a year.

> My second is, that option 2 is preferable to the others. As a wickerman
> proposal, how about
>
>       with type in P1, ..., Pn;

I am rather sick and tired with the combination of words "with type" but
other than that I am not going to argue about the syntax.  We'll have a
straw vote anyway.

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

From: Pascal Leroy
Sent: Wednesday, December 18, 2002 4:13 AM

> There seems to be a potential orthogonality with AI 262
> (private with),
> if a user wants to indicate that the with'd unit can only be mentioned
> in type stubs, and only in the private part.

Good point, and an illustration that Nothing Is Simple.

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

From: Ben Brosgol
Sent: Wednesday, December 18, 2002 10:00 AM

> Second, you have to remember that we are not doing this intellectual
> exercise in a vacuum: we have a schedule imposed by WG9, and this schedule
> calls for finalizing proposals a year from now.  The worst that could happen
> is that revisiting 217 would either cause the entire revision to slip, or
> cause 217 to not be included in the amendment.

Part of the non-vacuum is the user community (i.e., the real customers of
the Amendment work), and indeed one of the purposes of Tucker's presentation
was to elicit a response to the AIs.  What was the sense of doing the
briefing if we are going to complain that we didn't like the response? :-)

The feeling that I got from the discussion of 217 (John, Tucker, Jean-Pierre
and maybe some others on this list were there so they can correct me if they
disagree) was that a number of individuals strongly felt that a lack of
something on the context clause was a violation of Ada design principles.
It also seemed that this could be addressed with a simple syntactic
addition.  (OK, getting agreement on the right syntax is maybe not so simple
:-)  I did not get the feeling from the discussion that this required
re-opening the AI for general surgery but maybe I'm being naive.  Some of
the suggestions that have appeared on this thread, e.g. "with type in P1,
P2, ...;" combined with alternative 2 seem to solve the problem.

It does not address the issue of the same type stub name appearing in more
than one "with type"d package.  But there are workarounds that may be
satisfactory.

The interdependent types issue seems to be one of the more important items
for the Amendment work, so I would be a bit surprised if this AI simply gets
dropped based on its rejection in its current form.

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

From: Dan Eilers
Sent: Wednesday, December 18, 2002 12:56 PM

I'd like to propose a solution to AI 217 based on the _Interface package
idea.

Pascal wrote:

> The AI explains (in the !example section) that it is advisable to introduce an
> _Interface package to declare the type stubs.  The reason is that if you have
> types that are involved in more than one cycle, this provides the best
> structure.
>
> With this approach, the example from the AI works fine even if everything is
> named Object:
>
>    package Employees_Interface is
>        type Object is tagged separate in Employees;
>        type Emp_Ptr is access all Object'Class;
>    end Employees_Interface;
>
>    package Departments_Interface is
>        type Object is tagged separate in Departments;
>        type Dept_Ptr is access all Object'Class;
>    end Departments_Interface;
>
>    with Departments_Interface, Employees_Interface;
>    package Employees is
>        type Object is tagged private;
>        procedure Assign_Employee(E : in out Object;
>                                  D : in out Departments_Interface.Object);
>        ...
>        function Current_Department(D : in Object) return
>            Departments_Interface.Dept_Ptr;
>    end Employees;
>
>    with Departments_Interface, Employees_Interface;
>    package Departments is
>        type Object is tagged private;
>        procedure Choose_Manager(D : in out Object;
>                                 Manager : in out Employees_Interface.Object);
>        ...
>    end Departments;

Instead of "Employees_Interface", what you'd really like to write is
"Employees.Interface", making explicit the connection to package Employees.
But this doesn't work because of the rule that disallows declaring a
child unit before its parent has been compiled (and you can't compile the
parent first due the circular dependencies).  So I propose to relax this
rule, with some new syntax to be explicit what's going on.

The proposed syntax is that a child unit can be declared using a tick
mark in place of the period, to indicate that its parent need not
previously have been compiled.  References would still use a period.

Rewriting the above example:

    package Employees'Interface is         -- new syntax
        type Object is tagged separate in Employees;
        type Emp_Ptr is access all Object'Class;
    end Employees'Interface;

    package Departments'Interface is
        type Object is tagged separate in Departments;
        type Dept_Ptr is access all Object'Class;
    end Departments'Interface;

    with Departments.Interface, Employees.Interface;
    package Employees is
        type Object is tagged private;
        procedure Assign_Employee(E : in out Object;
                                  D : in out Departments.Interface.Object);
        ...
        function Current_Department(D : in Object) return
            Departments.Interface.Dept_Ptr;
    end Employees;

    with Departments.Interface, Employees.Interface;
    package Departments is
        type Object is tagged private;
        procedure Choose_Manager(D : in out Object;
                                 Manager : in out Employees.Interface.Object);
        ...
    end Departments;

This not only makes the _Interface package cleaner, but it eliminates
the need for any special kind of "with" clause, and eliminates the
objectionable reference in type stubs to packages that haven't been
mentioned in a context clause.

Note that Interface as used here isn't special, its just a user-defined
child unit name.

Being able to declare a child unit before its parent has been compiled
may have uses as well (I think someone has asked for this before).

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

From: Robert A. Duff
Sent: Wednesday, December 18, 2002 1:20 PM

> Part of the non-vacuum is the user community (i.e., the real customers of
> the Amendment work), and indeed one of the purposes of Tucker's presentation
> was to elicit a response to the AIs.  What was the sense of doing the
> briefing if we are going to complain that we didn't like the response? :-)

Good point.  The ARG *should* be listening to the user community,
as best it can.  (We don't have a large budget for market studies...)

> The feeling that I got from the discussion of 217 (John, Tucker, Jean-Pierre
> and maybe some others on this list were there so they can correct me if they
> disagree) was that a number of individuals strongly felt that a lack of
> something on the context clause was a violation of Ada design principles.

And they are correct (although I can't get too excited about this
issue).

> It also seemed that this could be addressed with a simple syntactic
> addition.

It could be, but as you can see from the discussion so far, all kinds of
new (and not-so-new) proposals come out of the woodwork.  These new
ideas, and perhaps even rehashed old ideas, may have merit, but I think
it's a mistake to waste time studying them when we have a proposal that
basically works (after 7 years work so far!).

I suggest we stick to solving the exact problem, and no more, by adding
a new kind of with clause with no more semantics than "herein lie type
stubs pointing at package X".  If it works, we should agree on the
syntax via e-mail before the next meeting.  If not, we should stick to
the current proposal.  Either way, the vote at the next meeting should
be a formality.  Wishful thinking?

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

From: John Barnes
Sent: Wednesday, December 18, 2002 1:51 PM

Absolutely right. Nonody at that presentation wanted
anything fancy. just a mark to say "herein lie stubs in
package X".  I thought my suggestions of

with out X;

was just the job. But there the world is a dull place. So
maybe echoing Bobs phrase we could something more elaborate
such as

with in is separate at package X;

At Christmas on we can be generaous with reserved words.
Happy Holidays

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

From: David Emery
Sent: Wednesday, December 18, 2002 2:14 PM

>...
>with in is separate at package X;

Reminds me of the (pornographic) story Norm Cohen once wrote
using -only- reserved words.

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

From: Michael Yoder
Sent: Wednesday, December 18, 2002 2:02 PM

Robert A Duff wrote:

>I suggest we stick to solving the exact problem, and no more, by adding
>a new kind of with clause with no more semantics than "herein lie type
>stubs pointing at package X".  If it works, we should agree on the
>syntax via e-mail before the next meeting.  If not, we should stick to
>the current proposal.  Either way, the vote at the next meeting should
>be a formality.  Wishful thinking?

I agree. Going even further, can we choose a single person (I'll suggest
Tucker) to just pick a syntax they like? I'm willing to rubber-stamp in
advance whatever you guys come up with, insofar as that helps expedite
email discussions.

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

From: Robert A. Duff
Sent: Wednesday, December 18, 2002 2:02 PM

Sounds like a good plan to me.  I'd even be willing to draw straws to
see who gets to pick the syntax.

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

From: Robert Dewar
Sent: Wednesday, December 18, 2002 6:09 PM

> Sounds like a good plan to me.  I'd even be willing to draw straws to
> see who gets to pick the syntax.

Not me. I think the exact choice of syntax can be a significant issue. I
would like to recall the furious acrimony surrounding the basically not
very important distinction between

  type x is tagged record ...

and

  class x is record ...

:-)

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

From: Randy Brukardt
Sent: Wednesday, December 18, 2002 6:46 PM

And as further proof, see Erhard's reaction to the syntax proposed.

Still, determining the complexity of the semantics is probably the most
important for ARG purposes. The syntax can pretty much be changed at any
time.

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

From: Ed Schonberg
Sent: Wednesday, December 18, 2002 2:14 PM

>  I thought my suggestions of
>
>  with out X;
>
>  was just the job.

The pun is  confusing at first reading. Why not:

   with in X;


Can't be any shorter!

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

From: Randy Brukardt
Sent: Wednesday, December 18, 2002 2:12 PM

> I suggest we stick to solving the exact problem, and no more, by adding
> a new kind of with clause with no more semantics than "herein lie type
> stubs pointing at package X".  If it works, we should agree on the
> syntax via e-mail before the next meeting.  If not, we should stick to
> the current proposal.  Either way, the vote at the next meeting should
> be a formality.  Wishful thinking?

I agree completely. Indeed, I was going to do just that if no one else beat
me to it: create an alternative 5 that's the same as alternative 4 with the
addition of this syntax (including the wording), and then we can choose
between them.

Of course, if someone else does it before I do, I won't mind -- I've got
plenty of other ARG work to do with my limited time and budget.

Syntax-wise, I think I like Bob Duff's original suggestion (way back at 8am
yesterday) of
    with separate P;
which, as Dan points out, will need a private option:
    [private] with separate P;

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

From: Dan Eilers
Sent: Wednesday, December 18, 2002 2:50 PM

> which, as Dan points out, will need a private option:
>     [private] with separate P;
>
>             Randy.

Please don't credit/blame me for the "[private]" in this proposal.
My purpose in pointing it out was exactly the opposite, by
showing that adding a new kind of with clause to the AI 217 proposal
is not as simple as was originally thought.  And it is totally
unnecessary as well, since type stubs are most logically placed
in a child unit, and child units don't need with clauses for
their parents.  The only change needed to AI 217 is changing
the underscore in "Employees_Interface" to a dot or tick mark.

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

From: Robert A. Duff
Sent: Wednesday, December 18, 2002 3:30 PM

But you can't "with" a child unit without also "with"-ing its parent.
Clients need to depend upon the type stubs without depending on the
"real" type.

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

From: Dan Eilers
Sent: Wednesday, December 18, 2002 3:42 PM

Yes, I understand that in Ada as it currently exists, a with clause
on child unit implicitly creates a dependency on its parent.
But this is because the child unit itself implicitly depends on
its parent.  My proposal was to break this implicit dependence
between a child unit and its parent (using a tick mark to distinguish).
Once that dependence is broken, it is perfectly fine to "with" a
child unit without also implicitly "with"-ing its parent.

I proposed retaining the dotted notation in the with clause, but
maybe using the tick mark in the with clause would make it more
clear to the reader and the compiler that there is no implicit
dependence on the child's parent.

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

From: Jean-Pierre Rosen
Sent: Thursday, December 19, 2002 1:41 AM

From: "Robert A Duff" <bobduff@TheWorld.com>
> But you can't "with" a child unit without also "with"-ing its parent.
> Clients need to depend upon the type stubs without depending on the
> "real" type.

Of course you can:
with parent.child
package Parent_Child renames parent.child;

with Parent_Child;  -- No dependence to  Parent
....

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

From: Robert A. Duff
Sent: Thursday, December 19, 2002 10:39 AM

Semantic dependence is transitive (10.1.1(26)), so the above comment is
not correct.  And from an implementation point of view, it has to be
that way, because names in the "...." unit can refer into the symbol
table of Parent.

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

From: Robert Dewar
Sent: Friday, December 20, 2002 5:54 PM

Most certainly correct, nevertheless, JPR's renaming is interesting in that
it shows you can have visibility of the child without visibility of the
parent if I understand things correctly.

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

From: Robert A. Duff
Sent: Friday, December 20, 2002 8:04 PM

Yes, quite true.  But you can still access things that are not directly
visible:

    package Parent is
        subtype S1 is Integer;
        subtype S2 is Integer;
    end Parent;

    package Parent.Child is
        X: S1;
        Y: S2;
    end Parent.Child;

    with Parent.Child;
    package Mumble renames Parent.Child;

    with Mumble;
    procedure Main is
    begin
        Mumble.X := Mumble.Y;

Clearly the compiler needs to know about Parent in order to check
whether the above assignment is legal (and to generate code for it).
The name Parent is not visible in Main, but Main still semantically
depends upon Parent.

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

From: Randy Brukardt
Sent: Wednesday, December 18, 2002 5:19 PM

> I agree completely. Indeed, I was going to do just that if no one else beat
> me to it: create an alternative 5 that's the same as alternative 4 with the
> addition of this syntax (including the wording), and then we can choose
> between them.
> ...
> Syntax-wise, I think I like Bob Duff's original suggestion (way back at 8am
> yesterday) of
>     with separate P;
> which, as Dan points out, will need a private option:
>     [private] with separate P;

I'm in favor of that basic approach as well, with exact syntax deserving
of a little more (e-mail) discussion.  I can also see some merit in Mike
Yoder's suggestion (with type in ...) since it indicates that it's the
types that are of interest from the named package(s).

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

From: Erhard Ploedereder
Sent: Wednesday, December 18, 2002 5:37 PM

My initial reaction was/is to stick with the AI as is. (And I think I can
make it the German reaction at WG9.)

I believe we were blindsided at the meeting by nothing more than a gut
reaction by the users who had all but 10 minutes to get familiar with
the model.

In terms of argument, consider:
  with XYZ; -- creates a semantic dependence
  with private ABC; -- creates a semantic dependence
  with funnykeyword PKG; -- does not create a semantic dependence

What kind of semantic consistency is that ??

And what benefit by the added with-clause (without other changes) ?
The following two lines are semantically equivalent (I hope):
(1)  with funnykeyword PKG;
(2)  -- with funnykeyword PKG;

Based on that, I believe that adding a with clause should be rejected.

---------- but if people do insist on a change....

I can't resist adding a proposal for another context_item
 from GHL use type T; -- does not create a semantic dependence on GHL;
                      -- allows "T" and "GHL.T" in places were the names
                      -- of incomplete types are allowed; etc., etc.
                      -- regarding completion checks

 and then revoke the syntax change to incomplete type decls.
 (Note that this also happens to allow for a solution of the problem
  of equal names, if instead only "GHL.T" is allowed.)

 Compared to the current solution, one loses the ability to "export" the
 incomplete type, but that may be a good thing, anyway.

For now, I would insist that whatever syntax is invented, it not start
with a "with".

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

From: Robert Dewar
Sent: Wednesday, December 18, 2002 5:40 PM

> > The feeling that I got from the discussion of 217 (John, Tucker, Jean-Pierre
> > and maybe some others on this list were there so they can correct me if they
> > disagree) was that a number of individuals strongly felt that a lack of
> > something on the context clause was a violation of Ada design principles.

Count me among this "number of individuals" :-)

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

From: Erhard Ploedereder
Sent: Wednesday, December 18, 2002 5:59 PM

> Syntax-wise, I think I like Bob Duff's original suggestion (way back at 8am
> yesterday) of
>     with separate P;
> which, as Dan points out, will need a private option:
>     [private] with separate P;

Please DON'T, since this comes close to mixing properties of P (which we are
not supposed to depend on) into the semantics of the clause, doesn't it?

Which gives me yet another argument against the "with"-clause strategy...
   private package Parent.Daughter is
        type T is....
   end Parent.Daughter;

   package Parent.Son is
        type T2 is....
   end Parent.Son;

   with separate Parent.Son;  -- ok
   with separate Parent.Daughter; -- is this ok ??? for normal "with" it isn't.
   package foo is

Or have we uncovered a bug in the original AI here, making it possible
to violate privacy of private child packages ? (At first glance, I don't
think so, because ops on the type are subject to visibility.)

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

From: Randy Brukardt
Sent: Wednesday, December 18, 2002 6:43 PM

As you say, "with Parent.Daughter;" is illegal in Ada 95. That's the problem
that "private" with is intending to fix. "private with Parent.Daughter;" is
legal.

So I would say that "with separate Parent.Daughter;" ought to be illegal as
well. But you are right, we don't have any way to tell that (no dependency
on the unit). So we can't make it illegal.

> Or have we uncovered a bug in the original AI here, making it possible
> to violate privacy of private child packages ? (At first glance, I don't
> think so, because ops on the type are subject to visibility.)

I think that you may be right, that AI-217 has a problem here.

    package Foo is
        type T is separate in Parent.Daughter;
    end Foo;

seems to be legal. And it essentially allows Parent.Daughter.T to be
accessed in unrelated packages. OTOH, I don't think you can do anything
useful with it (because, as you say, you don't have visibility on the full
definition unless you can give a context clause for Parent.Daughter). Still
it seems like exporting something that you can't legitimately have access
on.

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

From: Robert Dewar
Sent: Wednesday, December 18, 2002 8:19 PM

> This seems like, how does that saying go, "perfection is the enemy of
> the good", or something like that?  Technically, the objection is right:
> there *should* be some mention of that package in the context clause.
> But from a practical point of view:  As an Ada user, I've been waiting
> desperately for a solution to this serious language flaw for 7 years.
> We've finally got a solution that works, and now folks want to hold it
> up for perhaps another year or more to solve a relatively minor problem?
> Grrr.

I strongly object to any rushing here. The fact of the matter is that
the WG9 approving an AI does not change the standard and suddently require
all compiler writers to go out and implement a feature anyway, we are
possibly talking about a new version of Ada for 2005, that vendors may
or may not implement at that time.

If you want to add some feature to your compiler before there is a new
standard feel free, but it is absolutely not acceptable to rush anything.
There is simply nothing that urgent.

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

From: Robert Dewar
Sent: Wednesday, December 18, 2002 8:28 PM

> Well, I think that's wrong. Tucker already implemented a version of it in
> their compiler. I've been planning to do so as soon as I get some time,
> because it is badly needed to fix some structure problems in the Claw GUI
> Builder. I thought Pascal had indicated that they would be doing it soon. So
> there does seem to be some "rush to implement it"

Anyone is free to implement anything, and indeed trial implementations
are useful. For GNAT, we find our implementation of with type good enough
for now.

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

From: Robert Dewar
Sent: Wednesday, December 18, 2002 8:55 PM

> I completely disagree with this analysis.
>
> First, any time spent by the ARG on 217 is time that is not spent on other
> AIs.  So the question is as usual one of opportunity cost: what AIs are
> currently on the table that we want to bury for the sole purpose of
> marginally improving 217?

But if we go to WG9 and say "well this is not perfect, and it could be
improved, but we are in a hurry and don't have time to do it right." I
think the result will be that WG9 rejects it. That won't save time!

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

From: Robert Dewar
Sent: Wednesday, December 18, 2002 8:56 PM

> > There seems to be a potential orthogonality with AI 262

do you mean non-orthogonality here?

Orthonogal features are ones that do not interact in a negative way (the
terms was introduced I think perhaps by Bauer in the context of the Algol-68
design).

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

From: Ben Brosgol
Sent: Wednesday, December 18, 2002 11:51 PM

> ---------- but if people do insist on a change....
... snip ...
> For now, I would insist that whatever syntax is invented, it not start
> with a "with".

How about:

   for type goto P;

or maybe more seriously:

   at P;

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

From: Pascal Leroy
Sent: Thursday, December 19, 2002 1:41 AM

> ---------- but if people do insist on a change....
>
> I can't resist adding a proposal for another context_item
>  from GHL use type T; -- does not create a semantic dependence on GHL;
>                       -- allows "T" and "GHL.T" in places
> were the names
>                       -- of incomplete types are allowed; etc., etc.
>                       -- regarding completion checks
>
>  and then revoke the syntax change to incomplete type decls.
>  (Note that this also happens to allow for a solution of the problem
>   of equal names, if instead only "GHL.T" is allowed.)

Can you explain to me how this differs from the original "with type"
proposal?  I may be missing something, but I see no point in resurrecting
proposals that have been discussed ad nauseam and discarded for good
reasons.

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

From: Tucker Taft
Sent: Thursday, December 19, 2002 8:43 AM

Robert Dewar wrote:
>>>There seems to be a potential orthogonality with AI 262
>>
>
> do you mean non-orthogonality here?
>
> Orthonogal features are ones that do not interact in a negative way (the
> terms was introduced I think perhaps by Bauer in the context of the Algol-68
> design).

The "orthogonality" that comes to my mind based
on Dan's statement is as follows:

If "private with X;" makes the with clause
only applicable in the private part, then
"separate with X;" make the with clause only
applicable in type stubs.  And I suppose
"private separate with X;" makes the with clause
only applicable in type stubs in the private part.

 From a syntax point of view, if we have gotten
used to the idea of "private with ..." I would
recommend we stick with putting the qualifier
at the front of the with clause, so as implied
above I recommend the syntax be:

    [private] [separate] with library_unit_name {, library_unit_name};

I am also intrigued by Dan's 'Interface suggestion
which is very similar to the package "abstract"
proposal, but...

The biggest problem I have is keeping straight
in my mind the various difficulties associated
with each of the alternative proposals we have
considered.  Pascal reminded me of a few.  Here are
some ones I can remember:

1) Problems with package abstracts
    a) New kind of compilation unit could be major disruption to tools
    b) Not clear what kinds of declarations may
       appear in package abstract
    c) Must everything be repeated in package spec, or is
       package abstract just a prefix on the package spec?
    d) Not obvious in package spec whether package abstract
       does or does not exist (bad memories of optional package bodies
       and optional subprogram specs)

2) Problems with with-type
    a) Want to share access type, but no way to import
       various rep clauses
    b) Context clause visibility is not transitive, so
       this complicates type compatibility rules
    c) Renaming created type compatibility snafoos

3) Problems with type stubs
    a) Nothing in context clause to signal presence of stub.
    b) Doesn't work as well when all types have the same simple name
        (e.g. type Object is ...)

I'm sure there were others.  It would be nice to have a
well-specified list of these problems, with possible solutions
suggested, and then we might be able to make a rational
selection among them.

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

From: Erhard Ploedereder
Sent: Thursday, December 19, 2002 10:20 AM

I can add:

  4) Problems with "full decl identifies stub":
      a) there can be multiple stubs for the same full decl
         (should be supported; but even if declared illegal,
          seems rather difficult to check)
      b) there may be erroneously multiple full decls for a
         single stub (must be illegal, but not easy to check)
      c) would presumably run afoul the same critique, in even
         worse ways, as the "type stub identifies pkg" model.

And I believe I can add a "solution" to problem 2 a), as outlined earlier in
another message:
      The thus "postulated" type is to be treated as an incomplete type,
      so properties of the full type are irrelevant.

All proposals that resort to the incomplete type model share the problem
of incompatible access types formed over multiple views of the type.
(Possible solution lies in user-namable anonymous access types. :-)

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

From: Erhard Ploedereder
Sent: Thursday, December 19, 2002 10:49 AM

>  from GHL use type T; -- does not create a semantic dependence on GHL;
>                       -- allows "T" and "GHL.T" in places
> were the names
>                       -- of incomplete types are allowed; etc., etc.
>                       -- regarding completion checks

> Can you explain to me how this differs from the original "with type"
> proposal?  I may be missing something, but I see no point in ...

While "with type" tried to import full-fledged access types, this one
makes the imported type incomplete, and hence representation is irrelevant.

For all intents and purposes, all I did was to move the incomplete type
decl into the context clause. Apart from the difference that now no name
for the incomplete type is exported anymore (which I consider an advantage
to prevent the "poisoning" of other modules with incomplete types -- if
they want it, they can import it, too), and the possibility of solving
the homograph problem, it is semantically not different from the type
stub model.

As to problems, using Tuck's list for "with type":
    a) Want to share access type, but no way to import
       various rep clauses
       -- no problem, since we do not import access types as such
    b) Context clause visibility is not transitive, so
       this complicates type compatibility rules
       -- This problem remains and could be solved by a rule that
          "pgk.T = pkg.T" (presuming one goes the route of mandating
          selected notation). Not a nice rule, since text-based. Allowing
          both "T" and "pkg.T" is rather deadly in this regard.
    c) Renaming created type compatibility snafoos
       -- none such allowed, since you can't subtype incomplete types

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

From: Erhard Ploedereder
Sent: Thursday, December 19, 2002 10:50 AM

On the context clause proposal, I have yet another syntax:
    "not with P;"
:-)

This nicely expresses the fact that no dependency is formed and yet the
package has been mentioned as desired.

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

From: Robert A. Duff
Sent: Thursday, December 19, 2002 10:55 AM

Tucker wrote:

>     [private] [separate] with library_unit_name {, library_unit_name};

That makes sense.

> 3) Problems with type stubs
>     a) Nothing in context clause to signal presence of stub.
>     b) Doesn't work as well when all types have the same simple name
>         (e.g. type Object is ...)
>
> I'm sure there were others.  It would be nice to have a
> well-specified list of these problems,

Isn't that information in the AI's?

>... with possible solutions
> suggested, and then we might be able to make a rational
> selection among them.

I was under the impression that we have already done that,
and concluded that type stubs are the best solution.
So I suggest we address the above problems, and be done with it:

3 a) Add "separate with lib_unit" syntax as above, and a single legality
rule.  Change the wording about with clauses, so this new kind doesn't
cause semantic dependence.

3 b) The suggested coding style does not have this problem,
so it's not a real problem.  The AI should point this out.

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

From: Pascal Leroy
Sent: Thursday, December 19, 2002 11:23 AM

> I was under the impression that we have already done that,
> and concluded that type stubs are the best solution.
> So I suggest we address the above problems, and be done with it:
>
> 3 a) Add "separate with lib_unit" syntax as above, and a
> single legality
> rule.  Change the wording about with clauses, so this new kind doesn't
> cause semantic dependence.
>
> 3 b) The suggested coding style does not have this problem,
> so it's not a real problem.  The AI should point this out.

I like that approach and I would hope that we could go that way.
Unfortunately, many people in this discussion seem to want to reopen old
cans of worms.

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

From: Dan Eilers
Sent: Thursday, December 19, 2002 11:45 AM

I think it's fair to say that we have pretty conclusively ruled
out "with type" and "package abstracts" as originally proposed,
and are focused on variations of type stubs.

"With type" is simple to implement, but doesn't give full
needed functionality.

"package abstracts" are clean from a user perspective,
but are too heavy (new type of compilation unit, new type
of with clause).

The issue of type stubs came up for reconsideration as the
result of valid WG9 concerns that it goes against Ada design
principles to reference an unknown  package in a type stub.

One solution to the WG9 concern is to weigh down the type-stub
proposal with a new sort of with-clause.  But this is heavy,
and was one of the main reasons for shooting down package abstracts.
It's even heavier than originally thought, due to orthogonality
concerns with the private-with proposal.

To lighten the amended type-stub proposal, there have been at least
two suggestions that haven't been previously considered, and that
haven't yet been shot down:

1) Erhard's proposal that the type stub may not be needed/wanted
if you essentially move it to the context clause.

2) My proposal that the new with-clause isn't needed if you relax
the rule about child units always implicitly depending on their
parents.  (This gets the user benefits of package abstracts without
the heaviness of adding a new type of compilation unit or new
with clause.)

So I don't agree that the type-stub issue is closed yet.

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

From: Tucker Taft
Sent: Thursday, December 19, 2002 12:42 AM

>>I'm sure there were others.  It would be nice to have a
>>well-specified list of these problems,
>
>
> Isn't that information in the AI's?

Yes, I presume it is there.  My problem is keeping
it all in my head at one time, so that I don't
swing wildly from one idea to another just because
I forgot all the problems with each alternative.
Getting them all centralized into a single cohesive
list would certainly help me.  The information in
the AIs is a bit too spread out.

>>... with possible solutions
>>suggested, and then we might be able to make a rational
>>selection among them.
>
>
> I was under the impression that we have already done that,
> and concluded that type stubs are the best solution.

Well, Erhard originally suggested the type stub, I believe, but
he seems to be looking more favorably on something
closer to "with type" now.  It may be that by
recommending the "_Interface" package idiom if there is a
need to declare a shared access type, the "with-type"
which only allows incomplete types (which I think is
all the final version did) is worth reconsidering.

One advantage of the "with type" is that it is *not*
transitive, and it requires use of the full expanded
name of the type, rather than only providing for use
of a simple name.  I think if we disallow mentioning
renamed packages in a with-type clause, it is essentially
equivalent to the type stub, but solves both problems
associated with the type stub (context clause visibility,
and "type Object is...").

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

From: Erhard Ploedereder
Sent: Thursday, December 19, 2002 11:45 AM

> Well, Erhard originally suggested the type stub, I believe, but
> he seems to be looking more favorably on something
> closer to "with type" now.

Actually, I am still in favor of the AI as written. But I am trying
to swing with the punches, seeing that the ARG is being swayed, too,
by the "must be part of context clauses" attitude. And getting the
"type Object"-Problem solved alongside, well....

(I definitely do not want to see the abstract package solution. That
 one is way too heavy.)

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

From: Pascal Leroy
Sent: Thursday, December 19, 2002 11:30 AM

> > Can you explain to me how this differs from the original "with type"
> > proposal?  I may be missing something, but I see no point in ...
>
> While "with type" tried to import full-fledged access types, this one
> makes the imported type incomplete, and hence representation
> is irrelevant.

When we discussed the "with type" idea a long time ago (I think it was at
the Intermetrics meeting) the general feeling was that a mechanism for
importing access types was fundamentally important.  Otherwise you have to
have multiple access types, and you end up with explicit conversions between
access types everywhere in your code.  So much for the legendary readability
of Ada!  And don't tell me that anonymous-access-types-everywhere solve that
problem, because that AI (230, as I recall) is fraught with difficulties and
would be awfully disruptive for compilers.

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

From: Randy Brukardt
Sent: Thursday, December 19, 2002 6:10 PM

> The biggest problem I have is keeping straight
> in my mind the various difficulties associated
> with each of the alternative proposals we have
> considered.  Pascal reminded me of a few.  Here are
> some ones I can remember:

Here is the list I sent in July 2001 [found in the Appendix to alternative
3]. (We hadn't invented the current proposal at that time):

    "with type"
        Con: Can't handle access types (due to representation issues).
             Implementation needs "pseudo packages" internally.
             What happens when multiple paths to the same item "meet"?
        Pro: Easy to describe to users.
    "package abstract"
        Con: Heavy, complex mechanism. Complex visibility issues to work out.
             New kind of compilation unit affects all tools (alternatives
             avoiding compilation unit has similar effect on tools because the
             source must be compiled in two different ways).
        Pro: Handles access types cleanly.
    "type separate"
        Con: Must introduce extra packages (either "unnecessary" parents with
             Tucker's rules or "unrelated" ones with Dan's/Randy's rules).
             No allocators/deallocators on access types with designated types
             of this kind.
             (Probably others, once a proposal is made and picked apart.)
        Pro: No new kind of units. No new visibility issues. Access types can
             be handled (representation clauses can be given if needed). Model
             is easy to understand (it is an extension of existing rules). No
             run-time implementation problems; the implementation is identical
             to incomplete-completed-in-body.

Comparing this to Tucker's list, they appear to be pretty much the same, so
I think we can safely just use his list.

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

From: Tucker Taft
Sent: Thursday, December 19, 2002 8:35 PM

Well I went back and reread both the "with type"
and the "type xxx is separate..." proposals, and
it really seems like if we are willing to use
the rules of "type XXX is separate ..." but with
the syntax of "with type ..." we get the best
of both worlds.

In particular, much of the complexity
of "with type ..." came from trying to support
references to package renamings.  If we simply disallow
that, we can treat the enclosing package name roughly like
a string literal, and not worry about it until a point where
we need a full type.  At that point we have to make
sure that the enclosing package has been "with"ed.
The matching rules given in the type stub proposal
could be used directly.  The access type concerns
associated with "with type" are no worse than
the type stub, since both can only be used to introduce
an incomplete type.  If you want a shared access type,
then you create an _Interface (or _Pointers) package, and
declare the access type there.

I would disallow subtypes of the incomplete types (as is
disallowed for incomplete types now), and disallow
renamings of packages whose names are mentioned only
in "with type" clauses.

The rule given in the type-stub proposal for when the
full type must be visible would work for the "with type"
proposal just as well.

Hence, I would propose that we go back to the
with-type proposal, with semantic rules taken
in large part from the type-stub proposal.

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

From: Pascal Leroy
Sent: Thursday, December 19, 2002 11:43 PM

> > I thought Pascal had indicated that they would be doing it soon. So
> > there does seem to be some "rush to implement it"
>
> Anyone is free to implement anything, and indeed trial implementations
> are useful. For GNAT, we find our implementation of with type
> good enough for now.

My company is not interested in implementing experimental features for the
fun of it, because that's not what our customers want.  They want features
that solve their problems, will be supported over the next 10 years, and
will be portable to other compilers.  An endorsement by WG9 is (short of the
production of a TC or an Amendment) a good indication that a proposed
feature is likely to be supported by a variety of compilers over long
periods of time.

We have seen a lot of demand for a solution to the problem of mutually
dependent types in the 95-98 timeframe, because people were under the
impression that with Ada 95 they would be able to easily map UML models to
Ada.  That particular issue came up a lot, and was a nightmare in real
projects.  Since then the pressure has diminished, either because people
have somehow circumvented the problem, or because they have moved to a
language that supports mutually dependent types.

Wait another year and we will have reached the point where it's impossible
to make a business case for implementing type stubs.

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

From: Pascal Leroy
Sent: Friday, December 20, 2002 1:48 AM

> Well I went back and reread both the "with type"
> and the "type xxx is separate..." proposals, and
> it really seems like if we are willing to use
> the rules of "type XXX is separate ..." but with
> the syntax of "with type ..." we get the best
> of both worlds.

I am really annoyed that we are reopening the "with type" proposal, because
there were many technical difficulties associated with it which I suppose we
are going to re-discover.  At some point in time we at Rational made a
detailed design of how this could be implemented in our compiler, and came
up with two very significant problems:

1 - In order to implement "with type" the compiler would have to build
hidden package declarations to hold the incomplete types.  The reason is
that throughout the compiler we are making the assumption that types
(incomplete or not) are only declared in declarative parts, not in the
middle of context clauses, and hidden packages seem the best solution to
avoid breaking this assumption.  Interestingly enough I remember discussing
this with Tucker privately during the Leuven meeting, and at the time
Averstar had started a design too, and they had come with the exact same
mechanism.  This is in fact what led to the "package abstract" proposal: the
minutes of the Leuven meeting have the following paragraph:

"Tucker would like to abandon the with type proposal. He says it is
misguided, because you have to posit the existence of "ghost" or
"incomplete" packages to describe it. In other words, a compiler will need
to create a hidden package specification, and populate it with the right
stuff. Then it is possible to see a lot of these ghost packages, which
provide different views of the same package, and the compiler must figure
out that they all correspond."

2 - The consistency check between the incomplete type declaration(s) and the
completion is practically impossible to implement for a compiler doing
incremental compilation.  The "with type" AI has the rule:

"Any compilation unit that has a semantic dependence on another compilation
unit which has a "with_type_clause," as well as a dependence on the package
identified by the with_type_clause, must verify that a type declaration (not
just a subtype declaration) for the named type does in fact appear within
the visible part of the package."

But this means that the addition of a with clause (either a normal one or a
"with type") can change the location where the consistency check has to be
performed.  Similarly for the removal of an otherwise unused with clause.
The impact analysis phase of our compiler would have to remember the entire
dependency graph, and determine if, because of incremental changes, the
locations where the check is made change.  If so, it would have to obsolesce
the appropriate units.  Not only is that awfully complicated, but it has a
complexity which is proportional to the size of the entire program, not to
the size of the change, so it essentially kills incremental compilation.

I believe that this issue illustrates the fact that the non-transitivity of
with clauses is a drawback, not an advantage, of the "with type" model.

> In particular, much of the complexity
> of "with type ..." came from trying to support
> references to package renamings.

Curiously, that's not what I remember.  This was only one of the numerous
issues that killed that proposal.

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

From: Tucker Taft
Sent: Friday, December 20, 2002 8:20 AM

> "Tucker would like to abandon the with type proposal. He says it is
> misguided, because you have to posit the existence of "ghost" or
> "incomplete" packages to describe it. In other words, a compiler will need
> to create a hidden package specification, and populate it with the right
> stuff. Then it is possible to see a lot of these ghost packages, which
> provide different views of the same package, and the compiler must figure
> out that they all correspond."

This problem is significantly simplified, I believe, if you
don't allow the use of package renamings in the name of
the with'ed type.


> 2 - The consistency check between the incomplete type declaration(s) and the
> completion is practically impossible to implement for a compiler doing
> incremental compilation.  The "with type" AI has the rule:
>
> "Any compilation unit that has a semantic dependence on another compilation
> unit which has a "with_type_clause," as well as a dependence on the package
> identified by the with_type_clause, must verify that a type declaration (not
> just a subtype declaration) for the named type does in fact appear within
> the visible part of the package."

I suggested we use the rule from the type-stub proposal *instead*
of this rule.  It avoids the problems you had with this one, I believe.

> But this means that the addition of a with clause (either a normal one or a
> "with type") can change the location where the consistency check has to be
> performed.  Similarly for the removal of an otherwise unused with clause.
> The impact analysis phase of our compiler would have to remember the entire
> dependency graph, and determine if, because of incremental changes, the
> locations where the check is made change.  If so, it would have to obsolesce
> the appropriate units.  Not only is that awfully complicated, but it has a
> complexity which is proportional to the size of the entire program, not to
> the size of the change, so it essentially kills incremental compilation.
>
> I believe that this issue illustrates the fact that the non-transitivity of
> with clauses is a drawback, not an advantage, of the "with type" model.
>
>
>>In particular, much of the complexity
>>of "with type ..." came from trying to support
>>references to package renamings.
>
>
> Curiously, that's not what I remember.  This was only one of the numerous
> issues that killed that proposal.

In any case, if these are significant problems with the with-type,
then they need to be put into our "concise" list of pros/cons.
Somehow I missed them, and I believe Randy did as well.

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

From: Erhard Ploedereder
Sent: Friday, December 20, 2002 8:33 AM

> When we discussed the "with type" idea a long time ago (I think it was at
> the Intermetrics meeting) the general feeling was that a mechanism for
> importing access types was fundamentally important.

Type stubs in any of the proposed forms don't give you that capability
either, directly. It is an unsolvable problem, given the statement that
access types might vary in representation. You then need to resort to
the _Pointers package in any of the proposed models (unless we get the
pointer compatibility problem solved, too, as part of another AI).

As to Tuck's model in the message that starts:
> Well I went back and reread both the "with type"

Yes. That's exactly the model that I had in mind, too.

> disallow renamings of packages whose names are mentioned only
> in "with type" clauses.

needs some ...smithing, though, since you can't have retroactive
illegality of past renamings. It looks solvable, though, by simply
not allowing for completion of types taken from renamed packages.

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

From: Erhard Ploedereder
Sent: Friday, December 20, 2002 11:59 AM

> I am really annoyed that we are reopening the "with type" proposal, because
> there were many technical difficulties associated with it which I suppose we
> are going to re-discover.

This is turning into a red herring, because I am fairly sure that any
problem that might be discovered for the Tucker/my model is equally
present in the type stub proposal as written or as amended with the
vacuous context clause that merely names the package.

Put differently: if we re-discover a problem, we almost certainly have
the same problem with the type stub proposal and merely haven't realized
it.

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

From: Robert Dewar
Sent: Friday, December 20, 2002 9:28 PM

> Hence, I would propose that we go back to the
> with-type proposal, with semantic rules taken
> in large part from the type-stub proposal.

At first glance, I certainly like that approach.

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

From: Robert Dewar
Sent: Friday, December 20, 2002 9:32 PM

> My company is not interested in implementing experimental features for the
> fun of it, because that's not what our customers want.  They want features
> that solve their problems, will be supported over the next 10 years, and
> will be portable to other compilers.  An endorsement by WG9 is (short of the
> production of a TC or an Amendment) a good indication that a proposed
> feature is likely to be supported by a variety of compilers over long
> periods of time.

Well I don't share your view that an endorsement of an AI is a guarantee
of longevity ...

> Wait another year and we will have reached the point where it's impossible
> to make a business case for implementing type stubs.

This seems a very specific and peculiar situation (peculiar to you), I am
not sure that it constitutes a valid argument for rushing.

The fact of the matter is that no one can expect to get an immediate ruling
on a permanent solution to this problem. I actually think that some
experimental implementations would be useful.

I know we have several customers using "with type" to solve at least some
of these problems. I am not aware of any significant feedback, negative
or positive. Perhaps we should try to poll our customer base and get that
feedback.

P.S. I quite understand the concerns with the model that we implemented.
Note that at the time we implemented it, it seems quite likely that it
would be adopted and "be supported over the next 10 years etc" :-)

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

From: Robert Dewar
Sent: Friday, December 20, 2002 9:36 PM

Note incidentally that my concern about rushing is precisely that I do NOT
want another false step here. At a previous point in time, everyone seemed
quite happy with the original "with type" proposal, but it was *NOT*
rushed "into production", and sure enough problems were found. It is
really important this time to get things right. Rushing for WG9 approval,
which then has later to be reconsidered because further problems are
found does not do any one any good.

Pascal, if you really *do* think that you have your hands on a fine proposal,
I would encourage you to implement it. In fact arguments based on actual
successful usage are very powerful ones.

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

From: Pascal Leroy
Sent: Saturday, December 21, 2002 10:41 AM

> > "Tucker would like to abandon the with type proposal. He says it is
> > misguided, because you have to posit the existence of "ghost" or
> > "incomplete" packages to describe it. In other words, a compiler will need
> > to create a hidden package specification, and populate it with the right
> > stuff. Then it is possible to see a lot of these ghost packages, which
> > provide different views of the same package, and the compiler must figure
> > out that they all correspond."
>
> This problem is significantly simplified, I believe, if you
> don't allow the use of package renamings in the name of
> the with'ed type.

I don't think so.  In the case of our technology at least, the problem we
had was that the "with type" construct was a very odd beast.  In many places
we have code that assumes that a type is declared by a bona-fide type
declaration, living in a bona-fide declarative part.  The "with type" didn't
fit that pattern.  That's why we came to the conclusion that we had to
create these "ghost" packages to go back to a model (type declaration in
declarative part) that we were prepared to handle.

I realize that this may just reflect a limitation of our technology, but I
am always uncomfortable when the compiler has to go through hoops to
implement a feature.  (We have similar difficulties with children of
generics, and they are not the most natural feature of Ada 95 if you ask
me.)

The more I think of it the less I like the "with type" proposal.  To me, the
context clauses are for "importing" stuff from other units.  Now don't tell
me that "with type" imports a type, because that type may not even exist yet
(I guess I am echoing Erhard's discomfort at having a with clause that
doesn't involve a semantic dependency).  The "with type" really declares an
incomplete type, but then the normal place where type declarations occur are
visible/private parts.  So I think it's much more WYSIWYG to place that
declaration in the package (like type stubs do) than in the context clauses
(like "with type" does).

> > "Any compilation unit that has a semantic dependence on another compilation
> > unit which has a "with_type_clause," as well as a dependence on the package
> > identified by the with_type_clause, must verify that a type declaration (not
> > just a subtype declaration) for the named type does in fact appear within
> > the visible part of the package."
>
> I suggested we use the rule from the type-stub proposal *instead*
> of this rule.  It avoids the problems you had with this one,
> I believe.

I missed that part of your proposal.  Then I agree, it doesn't cause trouble
with incremental compilation.

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

From: Pascal Leroy
Sent: Saturday, December 21, 2002 10:50 AM

> Pascal, if you really *do* think that you have your hands on a fine proposal,
> I would encourage you to implement it. In fact arguments based on actual
> successful usage are very powerful ones.

Well, I really do think that the type stubs AI as recently sent to WG9 was a
fine proposal, and I don't believe that any actual flaw has been found in
it.  What I hear is a number of people saying that they don't like it for a
variety of aesthetical reasons, but I don't think that any technical problem
has been found in it.

As for implementing it, unfortunately it's not my decision, and I don't see
this happening without a WG9 endorsement.

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

From: Ed Schonberg
Sent: Saturday, December 21, 2002 11:27 AM

The two technical problems with type stubs:

>  3) Problems with type stubs
>      a) Nothing in context clause to signal presence of stub.
>      b) Doesn't work as well when all types have the same simple name
>          (e.g. type Object is ...)

seem simpler to solve than the semantic difficulties of "with type".

Concerning b), the syntax of an incomplete type declaration could include:

    type  P.T;    --  stub name is an expanded name.

which is more terse (terser?) that the "separate in" syntax. Subsequent
references are of course forced to use the expanded name as well.

Concerning a), we could state a rule similar to 10.1.5 (6) for program
unit pragmas: "a type stub declaration shall appear before any other
nested declarations". This places them as close to the context as
possible. This is easy to state and possibly to swallow (even though it
it is reminiscent of the Ada83 annoying restrictions on order of
declarations).

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

From: Randy Brukardt
Sent: Saturday, December 21, 2002 1:01 PM

Ed Schoenberg wrote:

> The two technical problems with type stubs:
>
> >  3) Problems with type stubs
> >      a) Nothing in context clause to signal presence of stub.
> >      b) Doesn't work as well when all types have the same simple name
> >          (e.g. type Object is ...)
>
> seem simpler to solve than the semantic difficulties of "with type".

True. But we made a technical decision not to solve b). Certainly the
proposed solution of
    type Obj is separate in P.T;
is simple and straightforward. And it has the advantage of making everything
explicit; Ada is about readability, not ease of writing after all. But it
was defeated in a straw poll.

> Concerning b), the syntax of an incomplete type declaration
> could include:
>
>     type  P.T;    --  stub name is an expanded name.
>
> which is more terse (terser?) that the "separate in" syntax. Subsequent
> references are of course forced to use the expanded name as well.

I don't like this for two reasons:
* It is not at all clear that this is a stub declaration. We usually favor
readability in Ada, not cutting the number of characters.
* It requires changing the syntax of type declarations, as they only take
identifiers currently. That is the main reason alternative 3 was rejected
(explicit completion).
* It brings back all of the ugliness of "ghost" packages. In Janus/Ada, the
only way for there to be something called P.T is for there to be a program
unit called P. But then we have to prevent direct use of P by itself, so a
lot of extra code has to be added all over the place. Indeed, we complained
about this in child packages during the U/I project, and the standard was
eventually changed to eliminate it. (I object to expanded names in any "with
type" proposal for the same reasons.)

(OK, that's three reasons).

> Concerning a), we could state a rule similar to 10.1.5 (6) for program
> unit pragmas: "a type stub declaration shall appear before any other
> nested declarations". This places them as close to the context as
> possible. This is easy to state and possibly to swallow (even though it
> it is reminiscent of the Ada83 annoying restrictions on order of
> declarations).

That would prevent using type stubs in private parts. One of the big
advantages of type stubs over the original "with type" is that type stubs
can be made to be private. That let's you declare a handle to them without
exposing the actual access type to the world:

    package PP is
        type Handle is private;

        ...
    private
        type Object is tagged separate in P.T;
        type Handle is access Object'Class;
    end PP;

I think all of the current proposals (both type stub and with type) would
allow private stubs, and I think they are likely to be useful.

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

From: Randy Brukardt
Sent: Saturday, December 21, 2002 1:13 PM

Robert Dewar said:

> Note incidentally that my concern about rushing is precisely that I do NOT
> want another false step here. At a previous point in time, everyone seemed
> quite happy with the original "with type" proposal, but it was *NOT*
> rushed "into production", and sure enough problems were found. It is
> really important this time to get things right. Rushing for WG9 approval,
> which then has later to be reconsidered because further problems are
> found does not do any one any good.

I grudgingly have to admit that Robert's right about rushing. But I also
have to agree with Pascal that there aren't any technical (as opposed to
aesthetic) problems yet found with the type stub proposal.

> Pascal, if you really *do* think that you have your hands on a fine proposal,
> I would encourage you to implement it. In fact arguments based on actual
> successful usage are very powerful ones.

The problem with that is we need a fairly stable solution before trial
implementations make sense. If we continue to wildly toss about solutions
that aren't remotely similar, then an implementation really doesn't help,
because it probably will have little in common with the final solution.
That's the problem with GNAT's with type, for instance.

The Ada 9x User/Implementor teams didn't spend that much time on proposals
that weren't pretty firm. I think more than 80% of our U/I code is still in
Janus/Ada. Proposals like finalization and streams which were all over the
place until the last minute never got implemented by any of the U/I teams.
Not surprisingly, those also are the proposals with the most problems that
we've had to fix in the standard.

Because of the last factor, and the high importance of this issue, I think
it is imperative that we settle on the basic outline of the solution, so
that we can get some early implementations to ferret out problems. (In this
case, I'm concerned about the complexity of the type matching rules, which
would be essentially the same in type stubs or in with type v. 2.) If we
continue to be all over the place, we may eventually freeze a solution, but
then we'll end up spending a lot of time patching it up in the next five
years.

So my preference is to stop dreaming up new ideas (because they really don't
add much, if anything) and figure out what, if anything, we need to do to
make the proposal we have better.

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

From: Robert Dewar
Sent: Saturday, December 21, 2002 1:20 PM

> The more I think of it the less I like the "with type" proposal.  To me, the
> context clauses are for "importing" stuff from other units.  Now don't tell
> me that "with type" imports a type, because that type may not even exist yet
> (I guess I am echoing Erhard's discomfort at having a with clause that
> doesn't involve a semantic dependency).  The "with type" really declares an
> incomplete type, but then the normal place where type declarations occur are
> visible/private parts.  So I think it's much more WYSIWYG to place that
> declaration in the package (like type stubs do) than in the context clauses
> (like "with type" does).

I think this is too much of an implementation viewpoint. The context clause
shows dependencies in the sense of program design, i.e. the meaning of a unit
depends on other units at a conceptual level. The "with type" most certainly
does say that this unit is dependent on stuff in another unit from a point
of view ot semantic understanding. To me it seems quite natural. I really
don't mind the exact form, but it seems essential to me that this kind
of conceptual "dependence" be represented in the context clause.

I want to emphasize here that as far as GNAT and ACT goes, the chocie is
neutral, we don't see any particular conceptual difficulties in implementing
any of these schemes. To properly complete our existing with type
implementation is not likely to be significantly easier than full
implementation of any of the schemes under discussion.

So my concerns here, unlike Pascal's, are not at all rooted in concerns
about difficulty of implementation, but rather on my conceptual feeling
that some indication in the context clause is absolutely essential from
a methodoloogical point of view.

I don't object to taking implementation difficulties into account. There
are only in effect a handful of Ada 95 front end technologies at this stage,
and it is certainly appropriate to listen if any proposal would cause
difficulties, not the least because it would likely be a significant
barrier to eventual WG9 approval of a new standard (after all, we made
very significant compromises in the initial Ada 95 design, based partly
on concerns about difficulties of implementation in technologies that
did not even manage to make the Ada 95 transition after all). However,
I think that such concerns must take a back seat to fundamental
methodological consistency considerations.

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

From: Robert Dewar
Sent: Saturday, December 21, 2002 1:24 PM

> Well, I really do think that the type stubs AI as recently sent to WG9 was a
> fine proposal, and I don't believe that any actual flaw has been found in
> it.  What I hear is a number of people saying that they don't like it for a
> variety of aesthetical reasons, but I don't think that any technical problem
> has been found in it.

Well if I am following things correctly, one objection is the lack of an
indication in the context clause. For me that is much more than an
"aesthetical reason", it is a fundamental flaw, one that would certainly
cause me to recommend that the US delegation vote against the proposal.

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

From: Ed Schonberg
Sent: Saturday, December 21, 2002 1:24 PM

>  > Concerning b), the syntax of an incomplete type declaration
>  > could include:
>  >
>  >     type  P.T;    --  stub name is an expanded name.
>  >
>  > which is more terse (terser?) that the "separate in" syntax. Subsequent
>  > references are of course forced to use the expanded name as well.
>
>  I don't like this for two reasons:
>  * It is not at all clear that this is a stub declaration. We usually favor
>  readability in Ada, not cutting the number of characters.
>  * It requires changing the syntax of type declarations, as they only take
>  identifiers currently. That is the main reason alternative 3 was rejected
>  (explicit completion).

It is a stub declaration precisely because the syntax is not that of a
type declaration. From a parsing point of view it's trivial, and if it is
placed next to the context clause it's even easier to recognize.

>  * It brings back all of the ugliness of "ghost" packages. In Janus/Ada, the
>  only way for there to be something called P.T is for there to be a program
>  unit called P. But then we have to prevent direct use of P by itself, so a
>  lot of extra code has to be added all over the place. Indeed, we complained
>  about this in child packages during the U/I project, and the standard was
>  eventually changed to eliminate it. (I object to expanded names in any "with
>  type" proposal for the same reasons.)

This is semantically no different that the current stubs proposal. Why are
 those "ghost" packages not a problem with stubs?

>  > Concerning a), we could state a rule similar to 10.1.5 (6) for program
>  > unit pragmas: "a type stub declaration shall appear before any other
>  > nested declarations". This places them as close to the context as
>  > possible. This is easy to state and possibly to swallow (even though it
>  > it is reminiscent of the Ada83 annoying restrictions on order of
>  > declarations).

>  That would prevent using type stubs in private parts. One of the big
>  advantages of type stubs over the original "with type" is that type stubs
>  can be made to be private. That let's you declare a handle to them without
>  exposing the actual access type to the world.

Well, the desire to give some context-level indication that these are imported
types is in serious conflict with the desire to hide them! Given that in the
majority of cases these types are introduced in order to define access types
for them, placing the stub in the private part seems to me like a rather
transparent fig leaf. Of the various conflicting requirements here, having
private stubs seems to me the weakest.

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

From: Robert Dewar
Sent: Saturday, December 21, 2002 1:28 PM

> Concerning a), we could state a rule similar to 10.1.5 (6) for program
> unit pragmas: "a type stub declaration shall appear before any other
> nested declarations". This places them as close to the context as
> possible. This is easy to state and possibly to swallow (even though it
> it is reminiscent of the Ada83 annoying restrictions on order of
> declarations).

I really prefer a separate indication in the context clause rather than
this restriction of placement. And I don't see what the big deal is in
introducing this separate indication.

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

From: Randy Brukardt
Sent: Saturday, December 21, 2002 2:40 PM

> >  > Concerning b), the syntax of an incomplete type declaration
> >  > could include:
> >  >
> >  >     type  P.T;    --  stub name is an expanded name.
> >  >
> >  > which is more terse (terser?) that the "separate in" syntax. Subsequent
> >  > references are of course forced to use the expanded name as well.
> >
> >  I don't like this for two reasons:
> >  * It is not at all clear that this is a stub declaration. We usually favor
> >  readability in Ada, not cutting the number of characters.
> >  * It requires changing the syntax of type declarations, as they only take
> >  identifiers currently. That is the main reason alternative 3 was rejected
> >  (explicit completion).
>
> It is a stub declaration precisely because the syntax is not that of a
> type declaration. From a parsing point of view it's trivial, and if it is
> placed next to the context clause it's even easier to recognize.

Huh? It declares a type, so "of course" its a type declaration. The only way
to introduce a type currently is via a type declaration; it seems very
strange to add a new concept that is almost the same.

> >  * It brings back all of the ugliness of "ghost" packages. In Janus/Ada, the
> >  only way for there to be something called P.T is for there to be a program
> >  unit called P. But then we have to prevent direct use of P by itself, so a
> >  lot of extra code has to be added all over the place. Indeed, we complained
> >  about this in child packages during the U/I project, and the standard was
> >  eventually changed to eliminate it. (I object to expanded names in any "with
> >  type" proposal for the same reasons.)
>
> This is semantically no different that the current stubs proposal. Why are
>  those "ghost" packages not a problem with stubs?

Yes it is, because there is no "expanded" name in the current proposal. (the
thing following the "in" is not a name at all -- that is very important,
bother for dependency reasons and for implementation reasons).

"Ghost" packages come up when you have a name "P.T" without a name "P".

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

From: Pascal Leroy
Sent: Sunday, December 22, 2002 4:36 AM

> That let's you declare a handle to them without
> exposing the actual access type to the world:
>
>     package PP is
>         type Handle is private;
>
>         ...
>     private
>         type Object is tagged separate in P.T;
>         type Handle is access Object'Class;
>     end PP;
>
> I think all of the current proposals (both type stub and with type) would
> allow private stubs, and I think they are likely to be useful.

That's an intriguing example when you modify it to include a nested package:

    package QQ is
        package PP is
            type Handle is private;
        private
            type Object is tagged separate in P.T;
            type Handle is access Object'Class;
        end PP;
    end QQ;

With type stubs you can precisely control which regions have visibility over the
incomplete type.  With "with type" the entire unit (with the possible exception
of the visible part) has visibility over it.  I am not claiming that the former
is a superduper important capability, but it certainly seems nicer to me to have
fine visibility control.

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

From: Pascal Leroy
Sent: Monday, December 23, 2002 4:39 AM

 Well if I am following things correctly, one objection is the lack of an
> indication in the context clause. For me that is much more than an
> "aesthetical reason", it is a fundamental flaw, one that would certainly
> cause me to recommend that the US delegation vote against the proposal.

Just to clarify, I am happy with the notion of adding some kind of indication in
the context clause of which units are forward-referenced.  Of all the proposals
that I have seen so far, the one I prefer is Tuck's "[private] [separate] with
P;".  What I object to is the notion of resurrecting "with type" from the dead.

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

From: Randy Brukardt
Sent: Friday, January 17, 2003 8:31 PM

Here's the list of problems that was posted during the previous discussions,
renumbered so that they have the same numbers as the alternatives.

1) Problems with with-type
    a) Want to share access type, but no way to import
       various rep clauses
    b) Context clause visibility is not transitive, so
       this complicates type compatibility rules
    c) Renaming created type compatibility snafus

2) Problems with package abstracts
    a) New kind of compilation unit could be major disruption to tools
    b) Not clear what kinds of declarations may
       appear in package abstract
    c) Must everything be repeated in package spec, or is
       package abstract just a prefix on the package spec?
    d) Not obvious in package spec whether package abstract
       does or does not exist (bad memories of optional package bodies
       and optional subprogram specs)

3) Problems with type stubs with explicit completion
     a) there can be multiple stubs for the same full declaration
        (should be supported; but even if declared illegal,
         seems rather difficult to check)
     b) there may be erroneously multiple full declarations for a
        single stub (must be illegal, but not easy to check)
     c) would presumably run afoul the same critique, in even
        worse ways, as the "type stub identifies package" model.

4) Problems with type stubs with completing package name
    a) Nothing in context clause to signal presence of stub.
    b) Doesn't work as well when all types have the same simple name
        (e.g. type Object is ...)

All) All proposals share:
    a) Incompatible access types formed over multiple views of the type.

--

We don't need to discuss #2 and #3 further, I think. (Well, I don't really
want to discuss any of them again, but since a number of people insisted.
I'm going through this exercise to help motivate alternative #5, which I
shall present shortly).

All (a) is misleading. In the intended use of type stubs, you declare a
single access type in the interface package, and use that everywhere,
including in the spec. of the base package. As in the example in AI-217-04:

   package Employees_Interface is
       type Employee is tagged separate in Employees;
       type Emp_Ptr is access all Employee'Class;
   end Employees_Interface;

   with Employees_Interface, Department_Interface;
   package Employees is
       type Employee is tagged private;
       subtype Emp_Ptr is Employees_Interface.Emp_Ptr;
        procedure Assign_Employee(E : in out Employee;
                                  D : in out
Departments_Interface.Department);
        ...
        function Current_Department(D : in Employee) return
            Departments_Interface.Dept_Ptr;
    end Employees;

Note that the subtype Emp_Ptr re-exports the access type, so that everyone
can use the same type. So problem All (a) is a problem if-and-only-if your
program isn't structured very well. I don't think we should concern
ourselves with that.

Tucker's (virtual) proposal for with types rewrites purports to fix problems
1(a) and 1(c). Clearly problem 1(b) remains. With the rules has Tucker
proposed them, it is impossible to re-export a with type. That means that
every package that needs to use the type will have to import it, even if it
imports everything else from an interfaces package. That seems fundamental
to the proposal.

Tucker's problem list did not include 1(d): Visibility problems and/or ghost
packages required. That is a critical omission, because the solution to it
complicates any with type proposal a lot. The problem is basically that if
you have a name P.T, then you have to do something about when P is used
alone. If P.T is a name, but P is not, then you have greatly complicated the
handling of program unit expanded names, since such a prefix cannot be
ambiguous on its own. In an example like:

package Parent is
    function P return Natural;
end Parent;

with type P.T;
package Parent.Child is

    type Ptr_T is access all P.T;

    C : constant Natural := P; -- Function P?
end Parent.Child;

The visibility of P.T and the parent P get mixed up. Similarly, if someone
writes the rather nonsense:

with P;
with type P.T;

you have to figure out what happens.

Solving this seems to require the introduction of ghost packages.

For me, there is also a 1(e): "with type" is inconsistent with the other
uses of the context clause, and looks like a kludge. Why just "with type"?
Why not "with exception" or "with constant"?? Please don't bring up "use
type": it is precisely an example of what not to do here. The same question
can be asked of it, why not "use constant" or "use exception"? Moreover, it
isn't even "use type"; it's "use operators of type".

Related to that, the items in a with_clause are all program units. Why are
we suddenly adding types? Tuck has previously complained that he doesn't
like the new features to look like add-ons. This one certainly does.

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

From: Randy Brukardt
Sent: Friday, January 17, 2003 8:32 PM

The objections to the with the half-worked out "with separate" clause were
primarily:
   (1) A with_clause that doesn't make a semantic dependence looks
inconsistent;
   (2) Some odd objection against re-exporting these types.

I completely fail to understand (2). I view that as a major, unfixable flaw
of any with type like proposal. Moreover, type stubs allow much better
control over visibility than with type. Ada has often been criticized for
not having fine visibility control on compilation units; I don't see the
appeal of adding more features with that problem.

OTOH, I've come around on the users concerns. When we see a with clause, we
see "semantic dependence". But that's language lawyer talk. Users just see
dependence. It's easy to think of a with_clause as a "strong dependence",
and our new clause (whatever it may be) to be a "weak dependence". I'm
pretty sure that is how people will think of it.

Still, I started thinking about both the solutions to problems 4(a) and
4(b), and 5(1). I wondered if Dan Eilers wasn't on the right track when he
proposed a specially named package to hold these things. After all, problem
3(b) (the multiple names problem) isn't a real problem if you have an
interface package for every type in the system. (And that seems like a good
idea, as it eliminates the multiple access type problem, by providing a
single point of declaration for it.) Dan's proposal:
    package P'Interface is
has some advantages, but the significant disadvantage of a new kind of name.
I'd probably make 'Interface an attribute, rather allow it to be anything,
but that doesn't help much.

So I turned to other ways to look at this. Perhaps a package modifier would
do the trick:

    package P_Interface is interface of P is ...

This worried me because we now have two new proposals, both called
interfaces. (One is interfaces types, and the other is interfaces packages,
but that seems much too easy to confuse.) So I want back to the package
abstract proposal and stole some terminology:

    package P_Abstract is abstract of P is ...

Well, the two "is"s don't look great, and besides, you find out about this
too late. It probably should go in front:

    abstract of P; package P_Abstract is...

And I've arrived back at a new context clause item. However, this one
eliminates Erhard's objection that we'd be adding a with_clause that doesn't
make a semantic dependence. It also doesn't have the naming problems of
"with type" (any version). It also reinforces the intended use of the
feature (and of type stubs). It also doesn't look quite as much like a
kludge, because it is easy to imagine other types of stubs in the future
(constant stubs,
exception stubs, and especially a new kind of subprogram stub). So this
doesn't lock us in like "with type" does.

The model is that this represents an "abstracted package" from which we can
use selected details without making a semantic dependence (a "strong
dependence" as noted above). It would be easy to then call a package having
one of these clauses a "package abstract", but clearly it can contain more
than just the contents of the abstracted package.

Anyway, I've written this up completely (including all of the wording), so we
can see how it plays out. That will be alternative #5, which I'll send in the
next message [This is AI-217-05/01, ED]. Obviously, we can tweak the
terminology or even go back to "with separate" without actually changing much
of the wording, so I hope that this is not wasted effort.

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

From: Robert I. Eachus
Sent: Friday, January 17, 2003 11:18 PM

Part of the reason I haven't been posting for a while was trying to get
my head around this whole issue.  I like the current alternative.  I can
also understand why some people have trouble with the package containing
the type not being mentioned in the context clause.  So far I have come
to two firm conclusions on how to fix this:

1) The name of the package may be required in some context clause, but
putting the type name there leads to trouble.
2) There needs to be an exclusion rule.  Whatever gets added to the
context clause, it must be illegal to have a with clause for the same
package in the context clause.

Point 2 actually starts to make a great deal of sense out of user's
objections.  The context clause is the proper place for context
requirements, and distributing them through the entire specification is
a step in the wrong direction.

Now let me have some Norm Cohen style fun.

use type in Foo;
...
type Bar is separate in Foo;
...

By putting a "use", not a "with" in the context clause, there is no need
to wrap our heads around the axle to make sure we don't need to change
text elsewhere, or to define which withs are really withs.  (It might be
nice to do away with the current grammar restriction that requires a
context clause to begin with "with", or pragmas followed by "with", but
that is a detail.)

Oh, one final note.  I see no problem with:

with A; use type in A.B;

I think that the methodological rule should be followed that to use a
type from a child package, the parent has to be named earlier in a with
in the context clause.  This might end up in some cases requiring
something like:

with A; use type in A.B;
package A.C is...

I can accept that.  However, notice that:

with A; use type in A.B;
package A is....

should and would be illegal.

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

From: Randy Brukardt
Sent: Wednesday, January 22, 2003 7:43 PM

I want to give a more realistic example than in the AIs, so that we can see
how it will work with the various solutions proposed. So, I'm going to
describe how I would use alternative #5 (and #4, for that matter) in the
Claw Builder. This example shows (I think) why I think that non-transitivity
is a non-starter.

The Claw Builder is a real, existing program which could use this facility.
The problem is that some objects need references to other types of objects,
and these needs are circular. For instance, (some) types of window objects
include menu objects. And some types of menu objects include actions that
open a window.

The current Claw Builder solves this problem by using names rather than
access objects to connect the objects in some cases. This is usually done
only where necessary to break circularities. For instance, menu objects name
the windows they are to open, rather than linking to them. Using names
causes several problems:
   -- Accesses to the linked object is much slower, as they have to be
looked up by name before use;
   -- If the user renames the linked object, we have to walk the entire
project to insure any names are updated;
   -- If the user copies the linked object and then renames the copy (the
required behavior), we have to be careful NOT to walk the project and update
names -- harming code reuse.
   -- We can't have overloaded names (not a problem for windows, but can
happen in other cases).

A root window object is an abstract object with a fairly large set of
operations. Each concrete object has to provide implementations for many of
these operations (some it can inherit). All of these operations are
dispatching. Typically, a user of the operation would apply it to a list of
windows using an iterator generic, with the operation dispatching to the
correct implementation. For the purposes of this discussion, we'll look at
just a few: Show, Hide, Display_Name.

The existing package looks something like:

   package CBuild_Root is
      type Root_Window_Type is abstract new
	    Ada.Finalization.Limited_Controlled with private;
      type Any_Window_Access_Type is access all Root_Window_Type'Class;

      procedure Show (Window : in out Root_Window_Type) is abstract;
      procedure Hide (Window : in out Root_Window_Type) is abstract;
      function Display_Name (Window : in Root_Window_Type) return String is abstract;
      ...
   end CBuild_Root;

Now, I would construct an abstract of this package for use in circular
definitions. (Caveat, I haven't actually done this, not having a compiler
with this feature.) Using the syntax of alternative #5, this would look
like:

   abstract of CBuild_Root_Definition;
   package CBuild_Root is
      type Root_Window_Type is tagged separate in CBuild_Root_Definition;
      type Any_Window_Access_Type is access all Root_Window_Type'Class;

      procedure Show (Window : in out Root_Window_Type'Class);
      procedure Hide (Window : in out Root_Window_Type'Class);
      function Display_Name (Window : in Root_Window_Type'Class) return
String;
      ...
   end CBuild_Root;

This abstract actually can be used anywhere that you need a
Root_Window_Type, except when you need to construct an object of
Root_Window_Type, and when you need to create a new concrete object. (It
turns out that these are the same places in the Claw Builder, but that may
not be true generally.) All other uses would use the abstract and not the
"real" package. That's why I named it with the name of the current "root"
package.

In order to keep the access types compatible, the real package would be
modified to:

   with CBuild_Root;
   package CBuild_Root_Definition is
      type Root_Window_Type is abstract new
	    Ada.Finalization.Limited_Controlled with private;
      subtype Any_Window_Access_Type is CBuild_Root.Any_Window_Access_Type;

      procedure Show (Window : in out Root_Window_Type) is abstract;
      procedure Hide (Window : in out Root_Window_Type) is abstract;
      function Display_Name (Window : in Root_Window_Type)
           return String is abstract;
      ...
   end CBuild_Root_Definition;

The body of CBuild_Root would need visibility on the real type so that it
could implement the procedures:

   with CBuild_Root_Definition;
   package body CBuild_Root is
      procedure Show (Window : in out Root_Window_Type'Class) is
      begin
          CBuild_Root_Definition.Show (Window);
      end Show;
      procedure Hide (Window : in out Root_Window_Type'Class) is
      begin
          CBuild_Root_Definition.Hide (Window);
      end Hide;
      function Display_Name (Window : in Root_Window_Type'Class) return String is
      begin
          return CBuild_Root_Definition.Display_Name (Window);
      end Display_Name;
      ...
   end CBuild_Root;

Now, essentially any use of an Any_Window_Access_Type pointer could be
implemented without withing the "abstracted package" at all. Only the
packages define the concrete window objects would with
CBuild_Root_Definition at all.

For instance, in the menu case, we would have something like (this is
greatly simplified):
  with CBuild_Root;
  package CBuild_Menu is
    type Menu_Item is record
       Name : String (1..20);
       Action : Action_Type;
       Dialog : CBuild_Root.Any_Window_Access_Type; -- If Action=Open_Dialog.
    end record;
    procedure Simulate_Action (Item : in Menu_Item);
  end CBuild_Menu;

  with CBuild_Root;
  package body CBuild_Menu is
    procedure Simulate_Action (Item : in Menu_Item) is
    begin
       if Item.Action = No_Action then
           null;
       elsif Item.Action = Open_Dialog then
           CBuild_Root.Show (Item.Dialog.all);
       ... -- Other actions.
       end if;
    end Simulate_Action;
  end CBuild_Menu;

The dereference in Show is allowed, because (in implementation terms) we
don't need to know anything at all about the real type in order to generate
the call. Such a call cannot be dispatching (the only way to see a primitive
operation is for the completion to be "available"). Thus, it cannot be using
a tag. And we know the parameter passing mode (by reference), and we know
that the body (or at least some body) must be in the scope of the
completion, or nothing at all must be done with the type. I believe Tucker's
rules in Alternatives #4 and #5 do allow this dereference.

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

From: Tucker Taft
Sent: Wednesday, January 22, 2003 7:54 AM

Here is yet another approach to the circular dependence
problem.  It has the following nice characteristics:

   1) No new kinds of compilation units
   2) No new kinds of context clauses
   3) No new kinds of type definitions
   4) Minimal syntax inventiveness

It was inspired by trying to deal with Dan's ideas, Randy's
ideas, and the original package "abstract" idea.

Now that I have you all breathless with anticipation...

package P is
    ...

    child package C is
        type T;
        type T_Ptr is access T;
    end C;
    ...
end P;

The basic idea is that you can give a little "taste" (or "prefix") of
a child package in the parent package spec.  Anyone who
"with"s the parent sees the "prefix" of the child.  If they
"with" the child explicitly, then they see the whole
spec of the child package.

This is analagous to the notion of a package subunit, except
that it is in the spec rather than the body, and you
reveal part of the spec of the child.

Any sort of declaration may appear in such a child package
prefix.  The full visible part of the child package is
simply the concatenation of the prefix and the part that is
compiled separately.

Since we know that any unit that "with"s a child implicitly
"with"s its parent, there will never be a situation where
a unit will see the "full" child but not see the prefix.

Pretty cool, eh?

Fire away...

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

From: Robert Dewar
Sent: Wednesday, January 22, 2003 8:16 AM

I like this at first glance, but one query, why not just say

   package P.C is

instead of introducing the keyword child. The reason I don't like this
particular choice of keywords is that it is odd to have child units as
a first class feature of the language, and child as a keyword, and yet
(in the normal case) child units do not use the keyword child. (Also
child would be a pretty deadly keyword to add, since it is a VERY
common identifier in any program dealing with trees etc).

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

From: Robert A. Duff
Sent: Wednesday, January 22, 2003 10:09 AM

Tuck says:

> > Pretty cool, eh?

Yes.

Robert says:

> I like this at first glance, but one query, why not just say
>
>    package P.C is
>
> instead of introducing the keyword child.

I think I like Robert's suggested syntax.

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

From: Jean-Pierre Rosen
Sent: Wednesday, January 22, 2003 10:39 AM

If I understand correctly, this is the old package abstract stuff, with the
additional constraint that the abstract must be for a child, and declared
within the parent.

Why not then:
    package abstract P.C is ....

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

From: Robert I. Eachus
Sent: Wednesday, January 22, 2003  1:22 PM

The idea looks good, but it will need a lot of work.  The key to the
proposal is that incomplete types can appear in the abstract (or
whatever it is called) of the child, and completion deferred until the
spec of the child is compiled.  As for any other "goodies,"  I am
strongly in favor of a minimalist approach.  I think that allowing
access and discrete types as well is harmless enough and
methodologically sound, but beyond that I hesitate to go.  (The access
types could be declared in the parent, but I don't like that on
methodological grounds, and enumeration types and  other discrete types
may be needed for discriminants.)  Incidentally if complete types are
permitted, they should be required to be repeated in the actual child
package spec, but the end of the abstract should be a freezing point.

I can probably be convinced that there is a need for constants--I am not
convinced, but I can be.  However, subprograms, task types, protected
types, and variables all seem to open unnecessary cans of worms.

Oh, and I will offer one other syntax proposal:

              separate package B is {...} end B;

We could even allow:

              separate package A;

As a way of specifying that a child of that name must be part of the
partition, but nothing else.

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

From: Tucker Taft
Sent: Wednesday, January 22, 2003  2:45 PM

Yes, this proposal is very similar to the "package abstract"
or "package P'Interface" ideas.
I chose the "child" keyword just to avoid any
tricky keyword convolutions or reinterpretations.  I don't care
too much what we use.  As JP says, the important
thing is to put the interface/prefix/abstract/"taste"
into the parent spec.  This seems to solve a whole bunch of problems.
Presumably a private child's prefix would have to go
into the private part of the parent spec.

As far as syntax, we might have:

     - child package C is ... end C;
     - package P.C is ... end P.C;
     - package abstract P.C is ... end P.C;
     - package abstract C is ... end C;(for completness)
     - separate package C is ... end C;
     - package C is separate ... end C;

I find it odd to declare something *textually* inside P
with the name "P.C".  There is no precedent for that.
So I would prefer the ones that just talk about "C".
The ones with the word "separate" seem nicely suggestive
of body stubs, which are certainly pretty close to this.
Note that body stubs don't use the "P.C" style name for
the stub.

Although we have talked about "package abstracts"
this really isn't an "abstract" in the sense of a summary.
It is more of a "prefix" in that I am presuming declarations
are *not* repeated in the "full" visible part (there seems
no reason to repeat them, and dealing with conformance of a
sequence of declarations makes my hair stand on end ;-).

Putting the word "separate" after the "is" is
more consistent with stubs, and the only change is that
rather than an immediate ";" you may follow it with
one or more declarations and an "end [id];".  And of
course, the keyword "body" is omitted.

I don't think I agree with Robert Eachus' desire to restrict
the kind of declarations that could go in the prefix, but
I do agree that anything that is not an incomplete type
declaration will be frozen at the end of the enclosing library
unit spec, in the same way things in a nested package spec are frozen
when reaching the end of the enclosing library unit spec.

So no giving some but not all of the dispatching operations,
or no deferring the rep-clause for a (non-incomplete) type to the
full visible part.

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

From: Dan Eilers
Sent: Wednesday, January 22, 2003  7:43 PM

> Yes, this proposal is very similar to the "package abstract"
> or "package P'Interface" ideas.

I believe Randy and my recent proposals have the full type in
the parent and the type stub in the child, which is backwards
from this idea.  It seems more intuitive to me to have the full
type in the parent, since that is what would normally be with'd,
but maybe its not a big deal.


> Presumably a private child's prefix would have to go
> into the private part of the parent spec.

If you have a such a package prefix in a private part, do you
propose that the corresponding child package could contain the
completion of a declaration in the visible part?  If so, that
might solve the need for separately compiled private parts.

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

From: Randy Brukardt
Sent: Wednesday, January 22, 2003 9:04 PM

On first glance this proposal doesn't look too bad, but I have some
concerns.

> Here is yet another approach to the circular dependence
> problem.  It has the following nice characteristics:
>
>   1) No new kinds of compilation units
>   2) No new kinds of context clauses
>   3) No new kinds of type definitions
>   4) Minimal syntax inventiveness

This reminded me of Wirth's Turing Award lecture. In it, (talking about
PL/1), he said the initial descriptions of features were "promises of
unalloyed delight", but that as the work went on, the descriptions got
messier and messier... (I hope I haven't misquoted Prof. Wirth.)

Anyway, one minor nit is that (3) isn't true. Every proposal we've worked on
leans heavily on tagged incomplete types. Indeed, I can come close to solve
these problems with those alone (and not other feature at all). Without
them, you can't do enough with the incomplete types to make any of these
ideas worthwhile. (And we sure as heck don't want to allow 'Class on things
that might not turn out to be tagged.)

And of course (1) is a fudge here. You are adding a new kind of program
unit, and you've just chose to hide it inside a "normal" compilation unit.
Which leads to one concern: usually these things are used at the root of
type trees, because it is usually the intersection of different object
classes where circularity problems come up. This idea means that you have to
introduce a dummy parent package just to hold this child. For instance, for
my CBuild example:

   package CBuild_Windows is
      package Root is separate -- I really want to type an 'is' here...
          type Root_Window_Type is tagged;
          type Any_Window_Access_Type is access all Root_Window_Type'Class;
          procedure Show (Window : in out Root_Window_Type'Class);
          procedure Hide (Window : in out Root_Window_Type'Class);
          function Display_Name (Window : in Root_Window_Type'Class)
              return String;
      end Root;
   end CBuild_Windows;

More annoying is that you can't even rename this away at the library level
(as the rename would clearly refer to the full package, not just this stub).
You'd have to rename in every package that it is used in. Since I would plan
to use this in as many places as possible, that is annoying.

This also seems to be a pit of visibility issues. We would have a new
concept of this additional "part" messing up visibility. Clearly, we'd have
to check for and disallow homographs in the real spec. But we'd also have to
change the names of the "real" operations, because otherwise all of the
calls would be ambiguous.

   package CBuild_Windows.Root is
       type Root_Window_Type is limited tagged with private; -- Completion
       procedure Real_Show (Window : in out Root_Window_Type);
       procedure Real_Hide (Window : in out Root_Window_Type);
       function Real_Display_Name (Window : in Root_Window_Type)
           return String;
   end CBuild_Windows.Root;

We can't call the real operation "Show" here, because that would make it
impossible to call Show anywhere is this 'with'ed. (Well, at least without a
full qualification on the argument, which leaves a lot to be desired). At
least with Alternatives #4 & #5, you can use the package name to separate
them, or "use" just one of the packages. Indeed, it would be rare that you'd
with both anyway.

I presume that you are restricting these "package spec. stubs" (for the lack
of a better name) to library level package specifications? The rules for
nested ones make my head hurt.

I wonder what the rules for use of the incomplete type ought to be? If you
can't write (as in my example):

  with CBuild_Window;
  package CBuild_Menu is
    type Menu_Item is record
       Name : String (1..20);
       Action : Action_Type;
       Dialog : CBuild_Window.Root.Any_Window_Access_Type;
              -- If Action=Open_Dialog.
    end record;
    procedure Simulate_Action (Item : in Menu_Item);
  end CBuild_Menu;

  with CBuild_Window;
  package body CBuild_Menu is
    procedure Simulate_Action (Item : in Menu_Item) is
    begin
       if Item.Action = No_Action then
           null;
       elsif Item.Action = Open_Dialog then
           CBuild_Window.Root.Show (Item.Dialog.all);
       ... -- Other actions.
       end if;
    end Simulate_Action;
  end CBuild_Menu;

then we've lost quite a bit of expressive power that we have with
Alternatives #4 & 5. OTOH, there might be an opportunity to simplify the
existing rules some. So I'd like to know what they'd be.

Elaboration is a disaster, but that's true for any solution to this problem.
(You really have little choice but to elaborate all of the specs first, then
all of the bodies.)

Still, it's the visibility rules that worry me the most. I fear that it will
take two years to figure them out; we won't have a clue about them two weeks
from now at Padua. I know I can't do it in time for the meeting, I have a
lot of other AIs that need to be done. The notion of having different
visibility to different parts of the spec. is scary, and this seems like a
big, big job in the symbol table of a compiler (even if it isn't a big job
conceptually).

So we need a proposal with the visibility details worked out before I could
even imagine to decide if it really is simpler, rather than just appearing
that way without the details worked out.

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

From: Tucker Taft
Sent: Wednesday, January 22, 2003 10:03 PM

> Anyway, one minor nit is that (3) isn't true. Every proposal we've worked on
> leans heavily on tagged incomplete types. Indeed, I can come close to solve
> these problems with those alone (and not other feature at all). Without
> them, you can't do enough with the incomplete types to make any of these
> ideas worthwhile. (And we sure as heck don't want to allow 'Class on things
> that might not turn out to be tagged.)

True, we should add the tagged incomplete types.

> And of course (1) is a fudge here. You are adding a new kind of program
> unit, and you've just chose to hide it inside a "normal" compilation unit.

Well we were told that having a new kind of compilation unit
was a much bigger deal, since the program library support
is scattered across more tools than just the compiler.
Similarly, new kinds of context clauses and new kinds of
interdependencies between units also seems to cause changes
in non-compiler tools.  So an important feature of this
proposal is that the changes are only *within* compilation
units.

> Which leads to one concern: usually these things are used at the root of
> type trees, because it is usually the intersection of different object
> classes where circularity problems come up. This idea means that you have to
> introduce a dummy parent package just to hold this child.

I don't feel too worried about this, since a lot of
subsystems seem to have a root package that is almost
empty (e.g. Ada.Numerics, and this forms a natural place
to host these prefix packages.

> ... For instance, for
> my CBuild example:
>
>    package CBuild_Windows is

Why wouldn't this be package (subsystem) named "Cbuild"
and then child named Windows?

>       package Root is separate -- I really want to type an 'is' here...
>           type Root_Window_Type is tagged;
>           type Any_Window_Access_Type is access all Root_Window_Type'Class;
>           procedure Show (Window : in out Root_Window_Type'Class);
>           procedure Hide (Window : in out Root_Window_Type'Class);
>           function Display_Name (Window : in Root_Window_Type'Class)
>               return String;
>       end Root;
>    end CBuild_Windows;
>
> More annoying is that you can't even rename this away at the library level
> (as the rename would clearly refer to the full package, not just this stub).
> You'd have to rename in every package that it is used in. Since I would plan
> to use this in as many places as possible, that is annoying.

I've lost you on the rename issue.  Just because a child package has
a prefix, there should be no reason you couldn't rename it.

> This also seems to be a pit of visibility issues. We would have a new
> concept of this additional "part" messing up visibility. Clearly, we'd have
> to check for and disallow homographs in the real spec. But we'd also have to
> change the names of the "real" operations, because otherwise all of the
> calls would be ambiguous.

Again, I have lost you.  Why are you putting any operations
in the package prefix?  And what makes these operations
more or less real than operations in the full package?

I don't see any visibility issues, so we are clearly thinking
about this differently.  There seems no particular reason to
put anything in a package prefix other than a few type declarations.
Operations seem redundant (though I don't see any technical reason
to disallow them).

>    package CBuild_Windows.Root is
>        type Root_Window_Type is limited tagged with private; -- Completion
>        procedure Real_Show (Window : in out Root_Window_Type);
>        procedure Real_Hide (Window : in out Root_Window_Type);
>        function Real_Display_Name (Window : in Root_Window_Type)
>            return String;
>    end CBuild_Windows.Root;
>
> We can't call the real operation "Show" here, because that would make it
> impossible to call Show anywhere is this 'with'ed.

Again, I have lost you why you declared various class-wide
operations in the package prefix.  The "with" type and
the type stub didn't allow any operations to be declared,
so I don't understand why you need them with this proposal.

> (Well, at least without a
> full qualification on the argument, which leaves a lot to be desired). At
> least with Alternatives #4 & #5, you can use the package name to separate
> them, or "use" just one of the packages. Indeed, it would be rare that you'd
> with both anyway.

I have completely lost you now.

> I presume that you are restricting these "package spec. stubs" (for the lack
> of a better name) to library level package specifications? The rules for
> nested ones make my head hurt.

I don't see any need for nested prefixes, though I
don't see any particular difficulty here.

My model is that these would be handled pretty much
the same way specs and bodies are handled.  That is,
when you get to the full package spec, you reenter
the scope you were in when you processed the prefix,
and keep adding more declarations.  From the "outside"
if you only "with" the parent, then you only see the
declarations in the prefix.  If you "with" the child,
then you see the declarations in both the prefix and
the full spec for the child.  I don't understand where
the visibility complexity comes in.  There are a number
of places already in Ada where different places see
more or fewer declarations within a package.  E.g.,
when in a private child, you see both the visible
and private part.  When in a stub, you see all declarations
that precede the stub.

Can you give me a simple example of the visibility
issues you perceive?  I am getting mixed up by your
relatively complicated example, and your apparent
desire to declare class-wide operations in the
package prefix.

> I wonder what the rules for use of the incomplete type ought to be? If you
> can't write (as in my example):
>
>   with CBuild_Window;
>   package CBuild_Menu is
>     type Menu_Item is record
>        Name : String (1..20);
>        Action : Action_Type;
>        Dialog : CBuild_Window.Root.Any_Window_Access_Type;
>               -- If Action=Open_Dialog.
>     end record;
>     procedure Simulate_Action (Item : in Menu_Item);
>   end CBuild_Menu;
>
>   with CBuild_Window;
>   package body CBuild_Menu is
>     procedure Simulate_Action (Item : in Menu_Item) is
>     begin
>        if Item.Action = No_Action then
>            null;
>        elsif Item.Action = Open_Dialog then
>            CBuild_Window.Root.Show (Item.Dialog.all);
>        ... -- Other actions.
>        end if;
>     end Simulate_Action;
>   end CBuild_Menu;
>
> then we've lost quite a bit of expressive power that we have with
> Alternatives #4 & 5. OTOH, there might be an opportunity to simplify the
> existing rules some. So I'd like to know what they'd be.

I need more help understanding the power you are talking about.
Can you be more explicit?  I am lost in the details of
this example.

> Elaboration is a disaster, but that's true for any solution to this problem.
> (You really have little choice but to elaborate all of the specs first, then
> all of the bodies.)

I don't understand why elaboration is affected at all.
whether a declaration is in a nested package or in
the enclosing package is irrelevant for elaboration.
The elaboration happens in the order of the declarations
within a single package-ish compilation unit.  I don't
see this changing even if a package prefix happens to
be nested inside the compilation unit.

Clearly the parent spec compilation unit has to be
elaborated before any child compilation units, but
the child compilation units don't need to have all their
specs elaborated before any bodies.  One of the
main advantages of this proposal as I see it is there
would be *no* change to compilation-unit-level processing,
such as compilation unit elaboration order determination.

> Still, it's the visibility rules that worry me the most.

I claim they are intuitively obvious!  Obviously we must
not have the same understanding of how this proposal would
work.

> I fear that it will
> take two years to figure them out; we won't have a clue about them two weeks
> from now at Padua. I know I can't do it in time for the meeting, I have a
> lot of other AIs that need to be done. The notion of having different
> visibility to different parts of the spec. is scary, and this seems like a
> big, big job in the symbol table of a compiler (even if it isn't a big job
> conceptually).

Well I don't know anything about your compiler, of course,
but in ours, each declarative region has a sequence of declarations,
each declaration having its own "logical position."  All lookups within a
region need to take a logical position "cutoff" which is
the last declaration that is visible from where the lookup is
taking place.  This deals with private part visibility,
visibility at the point of a stub, etc.  Clearly if you
only "with" the parent spec, then the last declaration visible
in the child package region is the end of its prefix.

> So we need a proposal with the visibility details worked out before I could
> even imagine to decide if it really is simpler, rather than just appearing
> that way without the details worked out.

I will be happy to do that, but I would appreciate some
better understanding of the problems you perceive,
because I fear I will not address these problems otherwise.

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

From: Tucker Taft
Sent: Wednesday, January 22, 2003 10:10 PM

Dan Eilers wrote:
>>Yes, this proposal is very similar to the "package abstract"
>>or "package P'Interface" ideas.
>
> I believe Randy and my recent proposals have the full type in
> the parent and the type stub in the child, which is backwards
> from this idea.  It seems more intuitive to me to have the full
> type in the parent, since that is what would normally be with'd,
> but maybe its not a big deal.

I seems important that some compilation
units only see the incomplete type, while others see both
the incomplete type and its completion.  The existing
rules for child packages is that if you see a child unit,
then you always see its parent.  Changing that seems
pretty disruptive.  Presuming you don't change that, then clearly
the incomplete type needs to be in the parent unit, while the
completion needs to be in the child unit.

>>Presumably a private child's prefix would have to go
>>into the private part of the parent spec.
>
> If you have a such a package prefix in a private part, do you
> propose that the corresponding child package could contain the
> completion of a declaration in the visible part?  If so, that
> might solve the need for separately compiled private parts.

My hope is that the rules would be changed as little
as possible, meaning that if an incomplete type is
declared in the prefix of the visible part of the child,
the it has to be completed somewhere later in the
visible part, either in the prefix itself, or in the
visible part of the "full" spec.  This wouldn't
depend on whether the child was private or public.

What I was impllying was that if the child is public, then
its prefix (if any) must be in the visible part of its parent,
and if a child is private, then its prefix (if any) must be
in the private part of its parent.

I do agree that this proposal might reduce the need for separately
compiled private parts, though I haven't really pursued that
investigation.  I am mostly trying to come up with a simple
solution to the circularly dependent package problem

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

From: Pascal Leroy
Sent: Thursday, January 23, 2003  3:48 AM

> package P is
>     ...
>     child package C is
>         type T;
>         type T_Ptr is access T;
>     end C;
>     ...
> end P;

I hate the notion that the type structure is tied to the package structure, as
it makes changes extremely painful during maintenance.

Assume that you have two root library packages P1 and P2 declaring types T1 and
T2.  Assume moreover that T1 depends on T2.  For instance:

    with P2;
    package P1 is
        type T1 is
            record
                C : P2.T2;
            end record;
    end P1;

    package P2 is
        type T2 is ... ;
    end;

At this point, in a real project, you probably have a lot of code that
references names in P1, including P1.T1.

Say that, during maintenance, you have to introduce a circularity, and T2 must
now contain a pointer to T1.  You would presumably do this by adding a "prefix"
and pushing down the full type declaration for T1 in a child unit:

    package P1_Root is
        child package P1 is
            type T1;
            type AT1 is access T1;
        end P1;
    end P1_Root;

    with P2;
    package P1_Root.P1 is
        type T1 is
            record
                C : P2.T2;
            end record;
    end P1_Root.P1;

    with P1_Root;
    package P2 is
        type T2 is
            record
                C : P1_Root.P1.T1;
            end record;
    end P2;

Now this means that most of the references to P1 must change to reference
P1_Root.P1.  This includes the places that declare objects of type T1 or
otherwise need to view the full type declaration for T1, as well as places that
need to reference operations on T1.  True, you can alleviate this somewhat by
providing library-level renamings or skins, but that's still a lot of work for a
rather mundane change.  When I do that in C++ all I have to do is type the 5
letters c, l, a, s, s.  When I do that in Ada I would have to stand on my head?
Come on!

Note that none of the other proposals have that drawback, as they don't require
that you change the place where the full type (and its operations) are declared.

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

From: Robert A. Duff
Sent: Thursday, January 23, 2003  7:44 AM

If people keep coming up with good ideas for solving the circular
dependence problem, it will never get solved.

Half :-).

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

From: Robert I. Eachus
Sent: Thursday, January 23, 2003  12:33 PM

Pascal Leroy wrote:

>I hate the notion that the type structure is tied to the package structure, as
>it makes changes extremely painful during maintenance.
>
>Assume that you have two root library packages P1 and P2 declaring types T1 and
>T2.  Assume moreover that T1 depends on T2...

From one point of view, this is a valid issue, from another it is
nonsense.  I have always taught that during the design phase of an Ada
project, you don't model the solution, you model the problem space.  To
use the example of a directory system, any solution that makes people
subordinate to offices, or offices subordinate to people is wrong.   The
problem space has offices associated with zero or more people, and
people associated with zero or more offices.  Any program structure that
doesn't reflect this is going to be subject to major restructuring
during development and maintenance.  (Of course, don't take this to
extremes.  Current cosmological theories not only permit time travel,
they require that causality not hold in all circumstances.  But I
wouldn't chide a programmer for not allowing negative delays between
cause and effect. ;-)

    package Root is
      child package P1 is
        type T1;
        type AT1 is access T1;
      end P1;
      child package P2 is
        type T2;
        type AT2 is access T2;
      end P2;
    end Root;

    package Root.P1 is
      type T1 is record
        C : P2.T2;
      end record;
      ...
    end Root.P1;

    package Root.P2 is
      type T2 is record
        C : P1.T1;
      end record;
      ...
    end Root.P2;

Even if the initial version of the program doesn't need component C of type T2,
this structure is clean, easy, and reflects the fact that T1 and T2 are of
equal precedence.  You might object to a Root package for a system like this,
but on methodological grounds, again I will disagree.  Whenever you have a
situation where several packages must be included in or excluded from a
partition as a whole, good design requires that the subsystem be identified as
such.

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

From: Tucker Taft
Sent: Thursday, January 23, 2003  1:59 PM

I guess I am surprised that large systems
don't use a package hierarchy already,
with nearly empty "root" packages.
But obviously Ada 83 legacy code doesn't do that,
but then of course Ada 83 legacy code doesn't have
circular dependences ;-).

Note that it is relatively painless to introduce a layer
at the "top" of a hierarchy, and make everything into
a child package.  The only changes are the "with" clauses,
everything else stays the same, since the top-level name
is implicit everywhere.  It would be essentially as
though package Standard were now spelled "Standard.Top".

I also wonder how common it will be to consider introducing a circular
dependence a typical "maintenance" activity.  Circular type dependence almost
always implies some kind of recursive processing as well, so this doesn't seem
like a "small" change.

I agree it would be great if we could have stand-alone package prefixes, but
the impact of that just seemed very large last time we visited it.  Perhaps we
could design a syntax for stand-alone prefixes, but focus on getting the nested
ones approved, and then work on determining the implementation impact of having
stand-alone ones.  I really think the nested ones are relatively simple to
implement, whereas the stand-alone ones imply a new kind of compilation unit, a
new kind of "with" clause, new library-item elaboration-order issues, and
generally a lot more effort and complexity.

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

From: Robert A. Duff
Sent: Thursday, January 23, 2003  1:59 PM

> I guess I am surprised that large systems
> don't use a package hierarchy already,
> with nearly empty "root" packages.

Certainly all the large programs I write have a small number of root
packages, and everything else is under those.

So are you saying that typically the types in question will already be
in some child package P.C, so to make P.C.T mutually recursive with
something else, all you have to do is add some code to P, without
changing clients of P.C?  If so, that seems to address Pascal's
concern.

> But obviously Ada 83 legacy code doesn't do that,
> but then of course Ada 83 legacy code doesn't have
> circular dependences ;-).

But it wishes it did.  ;-)

> Note that it is relatively painless to introduce a layer
> at the "top" of a hierarchy, and make everything into
> a child package.  The only changes are the "with" clauses,
> everything else stays the same, since the top-level name
> is implicit everywhere.  It would be essentially as
> though package Standard were now spelled "Standard.Top".
>
> I also wonder how common it will be to consider introducing a circular dependence
> a typical "maintenance" activity.  Circular type dependence almost always
> implies some kind of recursive processing as well, so this doesn't seem
> like a "small" change.

That's a good point.  Generally, it seems like mutually recursive types
have to be designed "together" in some sense.

Anyway, I would gladly do a lot of work on my code, if there were *any*
reasonable solution to this problem.

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

From: Dan Eilers
Sent: Thursday, January 23, 2003  2:44 PM

Randy wrote:
>  Without [tagged incomplete types] you can't do enough with the
>  incomplete types to make any of these ideas worthwhile.

Is it really the case that we're only solving the circular
dependence problem for tagged types?  There are plenty of
examples of inherently circular problem domains that are
reasonably modeled using untagged types, such as an Ada parser
where the abstract syntax tree nodes are represented using
variant records.


In Tucker's latest proposal:

> package P is
>     ...
>
>     child package C is
>         type T;
>         type T_Ptr is access T;
>     end C;
>     ...
> end P;

This seems a step backwards from the type stub proposal.
It isn't much different from

  package P is
      ...

      Type T is separate in P.C;
      Type T_ptr is access T;
      ...
  end P;

Both proposals allow the full type in a child package.
Neither proposal has a context clause to alert the
reader to the reference to a child package.

Tucker's proposal is more verbose.  It also seems
preferable (as it looks like Pascal noted) to have the
incomplete type declared immediately within P (as in
the type stub proposal), rather than nested in the
prefix package C.

The type stub proposal is more flexible, in that it
allows the full type to be in any designated package.
If this flexibility really isn't needed, then the
type stub proposal could be similarly restricted.
With such a restriction, there might be much less
user demand for a context clause, and we might be done.


Tucker wrote:
> The existing
> rules for child packages is that if you see a child unit,
> then you always see its parent.  Changing that seems
> pretty disruptive.  Presuming you don't change that, then clearly
> the incomplete type needs to be in the parent unit, while the
> completion needs to be in the child unit.

Well, you have to disrupt something to break the circularity.
You either provide a way to disrupt the existing rule that
a child unit implies a semantic dependency on its parent,
or you disrupt the exiting rule that the parent's spec can't
refer to its own unborn child.  It seems like a close call
as to which is the bigger disruption.  Usability would argue
that most references be to the parent package.


> I do agree that this proposal might reduce the need for separately
> compiled private parts, though I haven't really pursued that
> investigation.  I am mostly trying to come up with a simple
> solution to the circularly dependent package problem

Yes, first things first.  But we do have several very closely
related problems to solve, and it would be nice if the solutions
are harmonious.  If you have a way of deferring the completion
of a public incomplete type to a separately compiled child unit,
with no semantic dependency on the child unit, then it isn't a
very big step to defer the completion of a private type to a
separately compiled child unit with no semantic dependency.

Similarly, you could also defer the completion of a deferred
constant to a separately compiled child unit with no semantic
dependency (an issue you raised before but which I believe got
lost).

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

From: Randy Brukardt
Sent: Thursday, January 23, 2003  5:23 PM

Tucker said (replying to me):

>Can you give me a simple example of the visibility
>issues you perceive?  I am getting mixed up by your
>relatively complicated example, and your apparent
>desire to declare class-wide operations in the
>package prefix.

The point of my example was to look at how this would be used in practice,
and not in the vacuum of a blank piece of a paper of a hypothetical system.

Tucker said later:
> I also wonder how common it will be to consider introducing a circular
> dependence a typical "maintenance" activity.  Circular type dependence almost
> always implies some kind of recursive processing as well, so this doesn't seem
> like a "small" change.

Hogwash!

I have an existing application with circular dependencies. It uses various
hacks to deal with that in Ada 95. The application has bugs, directly caused
by those hacks. (I outlined all of this when I gave the example.) I could
build a hack on top of a hack to fix the bugs, or I could use this spiffy
new feature to make the circular dependence real, and then those bugs are
gone for good.

I doubt that this is all that unusual of a situation; Ada programmers have
been working around problems of circularity since 1980.

Tucker said (replying to me):

>> More annoying is that you can't even rename this away at the library level
>> (as the rename would clearly refer to the full package, not just this stub).
>> You'd have to rename in every package that it is used in. Since I would plan
>> to use this in as many places as possible, that is annoying.

>I've lost you on the rename issue.  Just because a child package has
>a prefix, there should be no reason you couldn't rename it.

This is a maintenance issue. If you have to introduce a dummy parent package
to make this work, then you would like to rename the stub for uses of it
alone, and rename the child for uses of it. You can certainly rename the
child at the library level:
   with CBuild_Windows.Root;
   package CBuild_Root renames CBuild_Windows.Root;
but you still have a semantic dependence on this unit. There is no way to
get a simple name for the stub alone at the library level.

You can rename it inside a scope, of course:
   with CBuild_Windows;
   package Whatever is
       package CBuild_Root is CBuild_Windows.Root;
       ...
   end Whatever;

But that distributes the change throughout the code.

Pascal explained why this is bad better than I can when he said:

> Now this means that most of the references to P1 must change to reference
> P1_Root.P1.  This includes the places that declare objects of type T1 or
> otherwise need to view the full type declaration for T1, as well as places that
> need to reference operations on T1.  True, you can alleviate this somewhat by
> providing library-level renamings or skins, but that's still a lot of work for a
> rather mundane change.  When I do that in C++ all I have to do is type the 5
> letters c, l, a, s, s.  When I do that in Ada I would have to stand on my head?
> Come on!

Tucker is surprised by this:
> I guess I am surprised that large systems don't use a package hierarchy already,
> with nearly empty "root" packages. But obviously Ada 83 legacy code doesn't do that,
> but then of course Ada 83 legacy code doesn't have circular dependencies ;-).

It doesn't have EXPLICIT circular dependencies, but I bet it has ones that
were hacked around.

In any case, I've only used a "root" package once, and that was with Claw.
In that case, the main issues were avoiding pollution of the user's
namespace, visibility into the private parts of types, and providing a place
so that all of the interrelated types could be declared (because we didn't
have a circularity solution). The primitive operations all had to be there
as well, so the spec is 3700 lines and the body 7100 lines. Hardly "nearly
empty".

In every other case, the entire application was the "subsystem". The Claw
Builder is not small; there is 4.5 Megabytes of source code. (I know that
there are much larger systems out there.) The parts are interrelated enough
that there is very little that could be independent, so there is no reason
for a "subsystem" structure.

I certainly can see why some systems would be built with empty top-level
packages, but I don't like the idea of forcing people to build things that
way. Especially when they are not that way already.

Bob echoed Tucker:

> Certainly all the large programs I write have a small number of root
> packages, and everything else is under those.
>
> So are you saying that typically the types in question will already be
> in some child package P.C, so to make P.C.T mutually recursive with
> something else, all you have to do is add some code to P, without
> changing clients of P.C?  If so, that seems to address Pascal's concern.

But on a another forum (in unrelated thread), Bob says:

> ... It also requires the client to
> "with" bits and pieces of the abstraction.  That's *sometimes* desirable
> anyway, but in many cases, you want the client to get the whole
> abstraction in one with_clause.  And you don't want to have extra names
> polluting the namespace (sometimes you end up needing a name for the
> child package, *and* names for some stuff inside it).

Which is precisely my (and Pascal's) point.

The idea of my original example was to get the package abstract to be a
complete replacement for the original, existing package for almost all uses.
Then we can use the original name, and make very few changes to the existing
program. (Reading in objects in projects would have to be changed a lot, but
that's not relevant here.) The only change is to the packages that actually
implement the concrete versions of window objects; no other changes are
required.

Tucker asked:

>>    package CBuild_Windows is

>Why wouldn't this be package (subsystem) named "Cbuild" and then child
named Windows?

The practical answer is that "Cbuild" is the name of the application, and
thus it is the name of the main subprogram.

But, even ignoring that, it wouldn't be quite right. The original package
was supposed to be called CBuild_Root_Window; I shortened it because the
code using it was getting unreadable:
   CBuild_Root_Window.Show (CBuild_Root_Window.Root_Window_Type'Class (My_Parent.all));
This was sort of OK, because Windows are a bit more equal than other objects
in the builder - you can imagine an application without a menu or a font,
but a GUI application without a window? But we've lost some explanation, so
I'd prefer to reintroduce the 'lost' Windows prefix. (As you pointed out
elsewhere, direct visibility would mean that you wouldn't need to give it
inside of the set of Windows.)

Dan asked of me:
>>  Without [tagged incomplete types] you can't do enough with the
>>  incomplete types to make any of these ideas worthwhile.

>Is it really the case that we're only solving the circular
>dependence problem for tagged types?  There are plenty of
>examples of inherently circular problem domains that are
>reasonably modeled using untagged types, such as an Ada parser
>where the abstract syntax tree nodes are represented using
>variant records.

The flippant answer is that all useful types are Controlled, so by
definition they are tagged. :-)

The serious answer is that you can use these for untagged types. But for
type stubs, the disruption to your program structure would be much worse.
For Tucker's package stubs, the disruption to your program structure is
going to massive no matter what.

Dan also noted:

> Both proposals allow the full type in a child package. Neither proposal
> has a context clause to alert the reader to the reference to a child
package.

This is true, but this is true of child packages in general. Tucker is
taking advantage of that fact to avoid the context clause. Somehow I doubt
that is what the users who complained at SigAda had in mind, but it's a
pretty standard practice. If customers complain about something, give them
something worse to replace it. :-)

This is getting long. In part 2, I'll finish up looking at Tucker's
questions about visibility.

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

From: Randy Brukardt
Sent: Thursday, January 23, 2003  6:29 PM

> > This also seems to be a pit of visibility issues. We would have a new
> > concept of this additional "part" messing up visibility. Clearly, we'd have
> > to check for and disallow homographs in the real spec. But we'd also have to
> > change the names of the "real" operations, because otherwise all of the
> > calls would be ambiguous.
>
> Again, I have lost you.  Why are you putting any operations
> in the package prefix?  And what makes these operations
> more or less real than operations in the full package?

I think my putting operations in the package specification stub was a
mistake. The purpose of doing that in the type stub case is so that uses of
the package did not need to change. Since there are two separate packages,
and I do not want to force users to have to "with" both of them, I put
class-wide versions of the operations in the abstract package, which would
of course dispatch to the "real" operations declared in the package.

But that doesn't seem to be necessary in the package specification stub
proposal. (I'm calling it that, because that's the syntax we're using.) What
I should have written is:

   package CBuild_Windows is
      package Root is separate -- I really want to type an 'is' here...
          type Root_Window_Type is tagged;
          type Any_Window_Access_Type is access all Root_Window_Type'Class;
      end Root;
   end CBuild_Windows;

   package CBuild_Windows.Root is
       type Root_Window_Type is limited tagged with private; -- Completion
       procedure Show (Window : in out Root_Window_Type);
       procedure Hide (Window : in out Root_Window_Type);
       function Display_Name (Window : in Root_Window_Type)
           return String;
   end CBuild_Windows.Root;

   with CBuild_Windows.Root;
   package CBuild_Root renames CBuild_Windows.Root; -- Compatibility renames.

Then the uses would look something like:

  with CBuild_Window;
  package CBuild_Menu is
    type Menu_Item is record
       Name : String (1..20);
       Action : Action_Type;
       Dialog : CBuild_Window.Root.Any_Window_Access_Type;
              -- If Action=Open_Dialog.
    end record;
    procedure Simulate_Action (Item : in Menu_Item);
  end CBuild_Menu;

  with CBuild_Root;
  package body CBuild_Menu is
    procedure Simulate_Action (Item : in Menu_Item) is
    begin
       if Item.Action = No_Action then
           null;
       elsif Item.Action = Open_Dialog then
           CBuild_Root.Show (Item.Dialog.all);
       ... -- Other actions.
       end if;
    end Simulate_Action;
  end CBuild_Menu;

which doesn't seem too bad. I don't like the bizarre case of "depending" on
CBuild_Windows.Root in the spec. of CBuild_Menu, but not withing it. (And I
suspect that the people who complain about the context clause being missing
for type stubs would feel the same with this proposal. But I'm beginning to
think that is pretty much inherent in this problem...) But it certainly
could be lived with.

> I don't see any visibility issues, so we are clearly thinking
> about this differently.  There seems no particular reason to
> put anything in a package prefix other than a few type declarations.
> Operations seem redundant (though I don't see any technical reason
> to disallow them).

Well, you later said that you would ban nesting of these, and that a visible
one would have to be completed by a visible child. That would be the two
worst cases. But...

> > Still, it's the visibility rules that worry me the most.
>
> I claim they are intuitively obvious!  Obviously we must
> not have the same understanding of how this proposal would
> work.
>
> > I fear that it will
> > take two years to figure them out; we won't have a clue about them two weeks
> > from now at Padua. I know I can't do it in time for the meeting, I have a
> > lot of other AIs that need to be done. The notion of having different
> > visibility to different parts of the spec. is scary, and this seems like a
> > big, big job in the symbol table of a compiler (even if it isn't a big job
> > conceptually).
>
> Well I don't know anything about your compiler, of course,
> but in ours, each declarative region has a sequence of declarations,
> each declaration having its own "logical position."  All lookups within a
> region need to take a logical position "cutoff" which is
> the last declaration that is visible from where the lookup is
> taking place.  This deals with private part visibility,
> visibility at the point of a stub, etc.  Clearly if you
> only "with" the parent spec, then the last declaration visible
> in the child package region is the end of its prefix.

That's not quite how its done in Janus/Ada, although the basic idea is
similar. There also is a visibility flag used to deal with things like
homographs in the same scope. My main concern was that grafting on private
visibility into parent parts was a huge mess, and bugs are still turning up
from time to time. I can't see how this could possibly be any simpler than
that.

In any case, the rules for scope and visibility are complicated, and I
really do not see how this fits in to those. The answer cannot be that there
is no impact, because there are many rules dealing with bodies and private
parts and the like, and this is very similar to adding another "part".

> > So we need a proposal with the visibility details worked out before I could
> > even imagine to decide if it really is simpler, rather than just appearing
> > that way without the details worked out.
>
> I will be happy to do that, but I would appreciate some
> better understanding of the problems you perceive,
> because I fear I will not address these problems otherwise.

I admit that there is a lot of FUD in my concerns here. It's just when
someone says "it's simple, trust me", my B*S* detector goes off. The pattern
with these AIs is that "it's simple" until someone finds the fatal flaw.
"Private with" was simple -- until we wrote the rules. "With type" was
simple, but proved to be full of holes. "Pragma Overridding" was simple
until someone realized we needed "Optional_Overriding" too, and now the
private overridding problem has killed it completely.

I know that there can be other things going on between the parts. That
usually gets us in trouble for other visibility issues, so it going to take
a lot of convincing to prove to me that that does not happen in this case.
Probably, I'll need to see a fully worked out proposal, including wording,
and for Steve B. and Pascal to have OKed it, before I'll believe.

All that said, one thing you have not emphasized (and you should) is that
this proposal doesn't seem to need the two pages of "availability" rules
that the type stub proposal does. I asked you about that and got no straight
answer (which gives me no confidence that you've thought about the rest of
it in enough depth). But, presuming that is true, that is a significant
advantage of this proposal. (The 'availability' rules would be very murky
area both for language lawyers and for implementors; if they were right,
users wouldn't notice them at all; but it's hard to tell if they're right.)

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


Questions? Ask the ACAA Technical Agent