Version 1.1 of ais/ai-50217.txt

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

!standard 10.01.02 (03)          03-02-04 AI95-00217-06/01
!standard 10.01.02 (04)
!standard 10.01.02 (08)
!standard J.10 (00)
!class amendment 03-02-04
!status work item 03-02-04
!status received 03-02-04
!priority Medium
!difficulty Hard
!subject Limited With Clauses
!summary
A new kind of with_clause is proposed.
!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 feature is to allow mutual recursion among type declared in separate packages (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
A new kind of with_clause is added, of the form "limited with <library package names>;". This is called a "limited_with_clause". The old fashioned kind is called an "unlimited_with_clause".
There are two key features of a limited_with_clause such as "limited with X;":
- It introduces no semantic dependence on X (and hence no
elaboration dependence on X). The implementation may choose to elaborate X either before or after the current unit. [In the wording below, I ended up saying it introduces a semantic dependence on the limited view of X.]
- Instead of providing visibility to the named packages and their
content, it provides visiblility only to the package names, any packages nested within them, and a view of each type therein. The type view is incomplete, implying all the usual restrictions on incomplete types. If the type is tagged, the view is tagged incomplete.
Thus, cyclic chains of with_clauses are allowed, so long as the chain is broken by at least one limited_with_clause.
!wording
10.1.2(4) says:
with_clause ::= with library_unit_name {, library_unit_name};
Change to:
with_clause ::= limited_with_clause | unlimited_with_clause limited_with_clause ::= limited with library_unit_name {, library_unit_name}; unlimited_with_clause ::= with library_unit_name {, library_unit_name};
Add a legality rule:
A library_item mentioned in a limited_with_clause shall be a package_declaration[, not a subprogram_declaration, generic_declaration, or generic_instantiation].
Discussion of existing wording:
It is natural to think of a with_clause as causing a library unit to become visible. However, that's not what the RM says. Instead, the RM says that lack of a with_clause causes a library unit not to be visible. That's kind of odd, but to understand the wording below, you have to understand the existing model in this language-lawyerly fashion.
The current RM defines the notion of an "environment declarative_part". During compilation, this fanciful declarative_part is imagined to contain all the library_items of interest. The order of these library_items is such that there are no forward semantic dependences. With_clauses introduce semantic dependences, so they control the order. Semantic dependences are also caused by child-parent and body-spec relationships. Subunits are imagined to be "inlined" at their stub point, so subunits can be ignored for visibility purposes.
The visibility rules for library units come from treating the environment declarative_part in the usual way, with one difference: In a normal declarative_part, you can see everything that comes before, and nothing that comes after (with a bunch of hiding rules thrown in as well). In the environment declarative_part, however, you can see things that come before, but only if mentioned in a with_clause.
Similar oddities occur in the definition of "immediate scope" and "scope".
I'm not sure what's the best way to introduce limited_with_clauses into this model. One idea is to say that "limited with X" means you can see X even if X occurs later in the environment declarative_part. This would introduce (conceptual) forward references, something never seen in Ada before. Another idea is to say that there is an implicit declaration of a "limited view of package X" (occurring before any "limited with X"'s). The normal declaration of X then appears later in its usual place. Either way, "limited with X" introduces a very limited view of X that only includes nested packages and incomplete types. I think I'll try the latter idea, even though I hate to introduce yet more magical implicit junk.
Here goes:
10.1.4(1-3) says:
1 Each compilation unit submitted to the compiler is compiled in the context of an environment declarative_part (or simply, an environment), which is a conceptual declarative_part that forms the outermost declarative region of the context of any compilation. At run time, an environment forms the declarative_part of the body of the environment task of a partition (see 10.2, ``Program Execution'').
2 The declarative_items of the environment are library_items appearing in an order such that there are no forward semantic dependences. Each included subunit occurs in place of the corresponding stub. The visibility rules apply as if the environment were the outermost declarative region, except that with_- clauses are needed to make declarations of library units visible (see 10.1.2).
3 The mechanisms for creating an environment and for adding and replacing compilation units within an environment are implementation defined.
Add some text somewhere in there:
In addition, for each library_package_declaration in the environment, there is a conceptual declaration of a "limited view" of that library package. [Note: This animal is sort of what folks have been calling a "package abstract", except that it is automatically generated (or imagined) by the compiler.]
The limited view of a package contains:
- A declaration of the limited view of each nested package.
- For each type_declaration in the visible part, an
incomplete_type_declaration with the same name, whose completion is the type_declaration. If the type_declaration is tagged, then the incomplete_type_declaration is tagged incomplete.
The limited view of a package has the same identifier as the package_declaration.
There is no syntax for declaring limited package views, because they are always implicit. Nonetheless, the declaration of a limited package view is considered to be a library_item.
A name mentioned in a limited_with_clause denotes the limited view declaration. I guess we need to make sure the definition of "mentioned" is appropriate: for a limited_with_clause, we are "mentioning" the limited view.
A library_package_declaration is considered to be the completion of its limited view declaration.
10.1(26) says:
26 A library_item depends semantically upon its parent declaration. A subunit depends semantically upon its parent body. A library_unit_body depends semantically upon the corresponding library_unit_declaration, if any. A compilation unit depends semantically upon each library_item mentioned in a with_clause of the compilation unit. In addition, if a given compilation unit contains an attribute_reference of a type defined in another compilation unit, then the given compilation unit depends semantically upon the other compilation unit. The semantic dependence relationship is transitive.
Add some new cases:
- A limited library package view declaration depends semantically
upon the parent limited package view declaration.
- A library package declaration depends semantically upon its
limited view.
- The part about with_clauses should work unchanged: for a
limited_with_clause, the dependence is upon the limited view; for an unlimited_with_clause, the dependence is upon the package_decl.
There are various places in Chapter 8 that refer to "the declaration of a library unit", presuming that there's only one. We need to change the wording, since library packages now have two declarations: the limited view, plus the normal package_decl. With minor wording changes, most of it should work OK, because:
A library_package_decl is the completion of its limited view, and therefore hides it.
The incomplete types in the limited view are completed by the regular types. This introduces the possibility of completing an incomplete type with a private type, but I think all the proposals are going to have a similar problem (if it's a problem).
!discussion
To review this proposal, one should search the RM for the following terms, to see if they still make sense:
- with_clause - semantic dependence, depend[s] semantically
Also study chaps 8 and 10.
----
Here's one possible implementation method: Whenever the compiler sees "limited with X", it reads the source file containing X, parses it, and collects a list of nested package and type names, and whether they're tagged. It is important that this process can be done without doing any "serious" semantic analysis, and without looking at anything imported by X. The compiler then constructs the limited view of X.
Luckily, taggedness of types can be detected syntactically.
At any place where a package_decl is visible, the compiler needs to be sure the limited view of it is hidden.
The compiler can avoid reconstructing the limited view of X, if it likes, if it knows the source has not changed.
For compilers that save program library information on disk, I presume the limited view would have to be saved on disk in a similar manner. In Rational terms, this means each source file has (up to) two compilation artifacts.
I presume all compilers have some subroutine to check whether two types are the same type (in case of incomplete types and the like). And/or a subroutine to determine which view of a type should be used. These subroutines need to be changed to deal with this new flavor of incomplete type. But I would expect that to be fairly localized; the calls to those subroutines should still work.
----
We do not allow a limited_with_clause to mention a procedure, because that would allow calling a procedure before its spec is elaborated. The language has no mechanism to deal with that. Similarly, we do not allow a limited_with_clause to mention a generic, because that would allow instantiating a generic before its spec is elaborated.
We do not allow a limited_with_clause to mention a generic instantiation, because that would require all kinds of semantic analysis stuff, such as visibility.
----
A package could say "limited with A.B.C;" and then its child could say "with A.B.C;". Now we're within the scope of the real things, so the limited views would be hidden.
Similarly, if P says "limited with P.C", we're within the scope of the real P, so the limited view of it is hidden. We have limited access to C.
----
Consider:
package A is type T is range 1..10; end A;
with A; use A; package B is X, Y: T; end B;
limited with A; with B; use B; package C is X := Y; end C;
OK, assignment statements are syntactically illegal in a package spec. But think of some other thing that depends on the type. Perhaps, "Flag: Boolean := X in 1..10;".
Is this legal? It would be odd if adding "limited with A;" reduced ones capabilities.
!example
!ACATS test
!appendix

From: Pascal Leroy
Sent: Monday, February  3, 2003  5:19 AM

A while back, Dan wrote, as a side comment: "Well, the nicest solution for the
user is just to allow specs to with each other, as other languages do."  This
got me thinking, as this is an approach that we have discussed briefly once or
twice, but writers of library-based compilers (like me) started to yell and
scream that it would be impossible to implement.  Well, I am starting to think
that all approaches considered so far are nearly impossible to implement, and
furthermore are quite hard to use.  So I started to investigate a solution where
units are allowed to with each others.  Here are my half-baked ideas:

1 - A new form of context clause is added:

    weak [private] with library_unit_name {, library_unit_name}

Weak with clauses don't have to form an acyclic graph.

2 - A compilation unit is added to the environment in two phases.  During the
first phase we say that the unit is "superficially added"; during the second
phase that it is "fully added" (better terminology welcome).  How this is
achieved is not specified by the language.

3 - To superficially add a unit to the environment, there is no requirement that
any other unit already exists in the environment.  (Not even its parent, heck,
not even Standard!)

4 - When a unit is superficially added to the environment, the only names that
can be referenced from outside the unit are those of packages (both the unit
itself and nested packages) and of types.  Moreover, every type is at this point
considered to be an incomplete type, and subject to the restrictions mentioned
in 3.10.1; the taggedness of the types is visible.  (The alert reader may notice
some similarity between a unit superficially entered into the environment and a
package abstract.)

5 - To fully add a unit to the environment, all of the units upon which it
depends semantically must already have been fully entered into the environment.
Furthermore, all of the units that it names in a weak with clause must already
have been superficially entered into the environment.  The only names that can
be referenced from such units are those of types and packages, and types are
considered incomplete.

6 - To fully add a unit to the environment, this unit must be made of the same
lexical elements (except for comments) as when it was superficially added to the
environment.

7 - The celebrated textbook example found in the AI is then simply written as
follows:

    weak with Departments;
    package Employees is
        type Dept_Ptr is access all Departments.Department'Class;
        type Employee is tagged private;
        procedure Assign_Employee(E : in out Employee;
                                  D : in out Departments.Department);
        ...
        function Current_Department(D : in Employee) return Dept_Ptr;
    end Employees;

    weak with Employees;
    package Departments is
        type Emp_Ptr is access all Employees.Employee'Class;
        type Department is tagged private;
        procedure Choose_Manager(D : in out Department;
                                 Manager : in out Employees.Employee);
        ...
    end Departments;

8 - Marketing hype a la Tucker:

    - No three-part types
    - No new compilation units
    - No new declarations
    - No changes to the visibility rules
    - Little new syntax
    - Support for circularities involving types in nested packages

I am no expert in source-based compilers, but I believe that this model should
be quite close to what GNAT currently does for "with type".  Superficially
adding a unit to the environment would merely mean that the source file exists,
and the "weak with" would give the compiler permission to peak at it.

For library-based compilers this proposal adds some complexity, but not
necessarily more than those proposals which change the visibility rules or
otherwise break the invariants upon which the compilers depend.  In the case of
our implementation a tree in the library can be in two states: parsed (as
produced by the parser, no names resolved) or analyzed (with all the decorations
produced by the semantic analyzer, names resolved, etc.).  These states would
correspond directly to a unit superficially/fully entered in the environment.
We would need to beef up the parsed representation a bit to add (1) tables
listing the types and package names, and (2) a hash code representing the
sequence of tokens in the unit (to perform the check of #6 above).  Intense
hand-waving here, as I have not done anything resembling a serious design.

Feel free to explain why this is a dumb idea...

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

From: Arnaud Charlet
Sent: Monday, February  3, 2003  5:35 AM

I certainly like Pascal's proposal (weak with) very much. It is the only
proposal (apart from the old with type that had its bunch of issues) so far
that looks appealing to me. It addresses well the issue of interfacing
with other languages and from a user point of view, it is very close to an
ideal solution.

As Robert said, we don't have any real technical constraint in GNAT to
implement any of the proposed solution. This one would probably be
close to the current with type implementation.

I am not sure the wording about adding a unit in the environment, and
requiring compilers to have two (or more for that matter) phases should be
stated as such, but I guess this can probably be sorted out without too much
difficulty if this proposal gets some more supporters.

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

From: Robert Dewar
Sent: Monday, February  3, 2003  6:39 AM

Pascal's proposal for weak with is the first one I have seen since WITH TYPE
that I like, and in fact I like it better than WITH TYPE (I am not taling
deep semantics here, just a surface impression). It also seems to satisfy
the requirement for easy generation of equivalent Ada from e.g. Java stuff.

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

From: Robert Dewar
Sent: Monday, February  3, 2003  6:42 AM

By the way I don't like "weak" very much because it has the wrong
connotations to be. The issue is that this with is preliminary or
limited (so if you are in a mood to reuse keywords.

limited with x;

is more like it ...

A more radical proposal is that all WITH's that meet the criteria are
weak -- could that work?

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

From: Pascal Leroy
Sent: Monday, February  3, 2003  6:51 AM

I am not wedded to a particular syntax.  If we think that the idea is worth
pursuing, we can probably come up with an acceptable syntax (we don't lack
creativity in the area of syntax).

> A more radical proposal is that all WITH's that meet the criteria are
> weak -- could that work?

From a methodological standpoint, I'd say that introducing a circularity should
be the result of a conscious decision, not something that happens by chance.
So the user should have to make it explicit that a circularity is what she
wants--by typing "weak", "limited" or whatever.

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

From: Robert Dewar
Sent: Monday, February  3, 2003  7:03 AM

I am not so sure I agree with this. At one level of abstraction you WITH
something because you need something in it, and it is not really your
business if it needs something in yourself.

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

From: Jean-Pierre Rosen
Sent: Monday, February  3, 2003  7:02 AM

> limited with x;
>
> is more like it ...
>
Or even
   with X abstract;

;-)

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

From: Robert A. Duff
Sent: Monday, February  3, 2003  8:18 AM

> A while back, Dan wrote, as a side comment: "Well, the nicest solution for the
> user is just to allow specs to with each other, as other languages
> do."

Dan was exactly correct.  That's why I can't get too excited about
Tucker's aesthetic gut feelings about the various other proposals --
they are *all* less aesthetically pleasing than the "right" solution.

>...This
> got me thinking, as this is an approach that we have discussed briefly once or
> twice, but writers of library-based compilers (like me) started to yell and
> scream that it would be impossible to implement.  Well, I am starting to think
> that all approaches considered so far are nearly impossible to
>implement, ...

That seems exaggerated, ...

>...and
> furthermore are quite hard to use.  So I started to investigate a solution where
> units are allowed to with each others.  Here are my half-baked ideas:
>
> 1 - A new form of context clause is added:
>
>     weak [private] with library_unit_name {, library_unit_name}
>
> Weak with clauses don't have to form an acyclic graph.

This is the solution I chose for my from-scratch language design I do as
a hobby.  My syntax is "import X;" to import X and require X to be
elaborated earlier than this unit -- essentially the same as Ada's "with
X;" And "import forward X;" to import X and elaborate X *after* this
unit.  This is essentially the same as your "weak with X;".  ("import
forward" is like a forward reference.)

The only thing needed in the RM is the syntax for weak with's, make sure
the rule about no cycles applies only to cycles formed by strong with's.

All the stuff below is really a description of how the Rational compiler
would work (and others with a similar library model).  There's no need
for any of it in the RM.

(Aside: In my "hobbyist" language, I am able to achieve complete
*compile-time* checking of elaboration order problems, even in the case
of indirect/dispatching calls, with no sacrifice in expressive power.
I thought that was pretty cool.)

> 2 - A compilation unit is added to the environment in two phases.  During the
> first phase we say that the unit is "superficially added"; during the second
> phase that it is "fully added" (better terminology welcome).  How this is
> achieved is not specified by the language.
>
> 3 - To superficially add a unit to the environment, there is no requirement that
> any other unit already exists in the environment.  (Not even its parent, heck,
> not even Standard!)
>
> 4 - When a unit is superficially added to the environment, the only names that
> can be referenced from outside the unit are those of packages (both the unit
> itself and nested packages) and of types.  Moreover, every type is at this point
> considered to be an incomplete type, and subject to the restrictions mentioned
> in 3.10.1; the taggedness of the types is visible.  (The alert reader may notice
> some similarity between a unit superficially entered into the environment and a
> package abstract.)
>
> 5 - To fully add a unit to the environment, all of the units upon which it
> depends semantically must already have been fully entered into the environment.
> Furthermore, all of the units that it names in a weak with clause must already
> have been superficially entered into the environment.  The only names that can
> be referenced from such units are those of types and packages, and types are
> considered incomplete.
>
> 6 - To fully add a unit to the environment, this unit must be made of the same
> lexical elements (except for comments) as when it was superficially added to the
> environment.

Note in particular that this consistency check is an artifact of your
compilation model.  That is, your compiler is going to read the same
file twice.  But I can imagine compilers that will only read the source
once, so the "superficial" and "full" distinction is represented purely
in memory during compilation.

I think any consistency requirements are already covered by the RM's
words about not including two different versions of the same unit in a
partition.

> 7 - The celebrated textbook example found in the AI is then simply written as
> follows:
>
>     weak with Departments;
>     package Employees is
>         type Dept_Ptr is access all Departments.Department'Class;
>         type Employee is tagged private;
>         procedure Assign_Employee(E : in out Employee;
>                                   D : in out Departments.Department);
>         ...
>         function Current_Department(D : in Employee) return Dept_Ptr;
>     end Employees;
>
>     weak with Employees;
>     package Departments is
>         type Emp_Ptr is access all Employees.Employee'Class;
>         type Department is tagged private;
>         procedure Choose_Manager(D : in out Department;
>                                  Manager : in out Employees.Employee);
>         ...
>     end Departments;

Yes, although only one of the with's *needs* to be weak.  For symmetry,
they probably both should be weak.

> 8 - Marketing hype a la Tucker:
>
>     - No three-part types
>     - No new compilation units
>     - No new declarations
>     - No changes to the visibility rules
>     - Little new syntax
>     - Support for circularities involving types in nested packages
>
> I am no expert in source-based compilers, but I believe that this model should
> be quite close to what GNAT currently does for "with type".  Superficially
> adding a unit to the environment would merely mean that the source file exists,
> and the "weak with" would give the compiler permission to peak at it.
>
> For library-based compilers this proposal adds some complexity, but not
> necessarily more than those proposals which change the visibility rules or
> otherwise break the invariants upon which the compilers depend.  In the case of
> our implementation a tree in the library can be in two states: parsed (as
> produced by the parser, no names resolved) or analyzed (with all the decorations
> produced by the semantic analyzer, names resolved, etc.).  These states would
> correspond directly to a unit superficially/fully entered in the environment.
> We would need to beef up the parsed representation a bit to add (1) tables
> listing the types and package names, and (2) a hash code representing the
> sequence of tokens in the unit (to perform the check of #6 above).  Intense
> hand-waving here, as I have not done anything resembling a serious design.
>
> Feel free to explain why this is a dumb idea...

Because your evil twin was yelling and screaming about the
implementation difficulty of this idea...  ;-)

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

From: Tucker Taft
Sent: Monday, February  3, 2003  8:24 AM

I like this, although it is
more work for us than almost any
other proposal.  We do all semantics
on the fly, and don't have a mode that
parses without doing semantic analysis.

In general, I believe the "type C.T;" approach
solves the basic problem, and will be one of the
easiest to implement.

As far as syntax, I like the suggestion of using
"limited" as a prefix on the "with" clause,
and it goes awfully nicely with "private" ;-).

    [limited] [private] with library_item_name {, library_item_name};

It would be a major headache (dare I say "huge" headache?)
for us if the "limited"ness of the "with" were not explicit.

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

From: Robert A. Duff
Sent: Monday, February  3, 2003  8:34 AM

Robert wrote:

> A more radical proposal is that all WITH's that meet the criteria are
> weak -- could that work?

No, I don't think so.  The problem is that if there's a cycle of with's,
the compiler needs to choose *one* of them as "weak" to break the
cycle.  The one that is chosen affects the elaboration order.  Clearly,
the user needs a way to control this order, and "weak with" is that
feature.

In other words, how is the compiler to know *which* with's meet the
criteria?

I don't think the usual army of elaboration-control pragmas can help.
Pragma Elaborate(X) should probably be illegal for weak withs.
Anyway, it only goes one step, which as we know from Ada 83 is not good
enough.  Pragma Elaborate_All should ignore weak withs that are found in
the chain.  Otherwise, it can't work when used in part of the cycle.

Lots of other languages do as Robert suggests -- just allow cyclic
imports, with no indication of which ones are "weak".  The reason they
can get away with it, and we can't is:
Some such languages don't have run-time elaboration semantics,
so there's no issue.
Other such languages have botched the run-time elaboration semantics
so badly that this issue is in the noise.

> I am not so sure I agree with this. At one level of abstraction you WITH
> something because you need something in it, and it is not really your
> business if it needs something in yourself.

I agree with Pascal on this point.  It seems to me that a mutually
recursive design always requires *some* mutually recursive knowledge on
the part of the designer.  I don't see it happening by accident.  At
least not unless the packages involved are incoherent collections of
unrelated stuff.

Normal layered "with"s have the property that packages don't need to
know about their clients.  Mutual recursion seems rather different to
me: two packages need to know about each other -- they at least need to
know about each other's *existence*.  So I think weak with's deserve
their own syntax.

I guess I agree with Robert that "weak with" is not the best syntax,
but that's a minor detail.  Using "with" as a verb is already an
annoyance...  Oh, well.

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

From: Robert Dewar
Sent: Monday, February  3, 2003  8:43 AM

> No, I don't think so.  The problem is that if there's a cycle of with's,
> the compiler needs to choose *one* of them as "weak" to break the
> cycle.  The one that is chosen affects the elaboration order.  Clearly,
> the user needs a way to control this order, and "weak with" is that
> feature.
>
> In other words, how is the compiler to know *which* with's meet the
> criteria?

Yes, that makes sense, so that's not a possibility that is worth discussing.
I withdraw the solution.

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

From: Pascal Leroy
Sent: Monday, February  3, 2003  8:37 AM

> The only thing needed in the RM is the syntax for weak with's, make sure
> the rule about no cycles applies only to cycles formed by strong with's.
>
> All the stuff below is really a description of how the Rational compiler
> would work (and others with a similar library model).  There's no need
> for any of it in the RM.

That statement surprises me.  At the very least, it would seem that the RM would
need to specify what names/entities are available after a unit has been
superficially entered into the environment, and what are the properties of these
entities.  I am proposing that you can see only packages and types, and even so
the types would look like they are incomplete.  I can't see how you could deduce
this from the current RM.

PS: But then I know that Bob Duff, like the Pope, is infallible in matters of
language doctrine ;-)

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

From: Robert A. Duff
Sent: Monday, February  3, 2003  8:51 AM

Yes, you're right -- the RM needs to say *something*.  But it's not
much.  And I don't think it needs to define this concept of
"superficially in the environment" -- that concept belongs in the
Rational user's manual, I think.

The RM should say something about how if the only visibility to package
X is via "weak with", then uses of X are restricted along the lines you
say above.

More thought is needed, if we are to go this route.  The only real
problem I see is implementation difficulty.  I think all the language
rules can be worked out, but that will require some thought.
Interactions with elaboration-control pragmas.  What happens when you've
got both a weak and a strong with on the same thing?  Does "weak with
A.B.C;" import all three weakly?  Is there any concern that changing
"with" to "weak with", or vice versa, would introduce surprises into the
program?  I suspect all these questions have easy straightforward
answers.

> PS: But then I know that Bob Duff, like the Pope, is infallible in matters of
> language doctrine ;-)

;-)

No way!

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

From: Robert A. Duff
Sent: Monday, February  3, 2003  12:56 PM

In Pascal's proposal, a parent package P can weakly 'with' its children:
"weak with P.C;", if you want a mutually dependent pair of types,
one in P and one in P.C.  The spec of P will be elaborated before the
spec of P.C, as usual.

However, it is pointless for P.C to say "weak with P;", because the
child-to-parent dependency is necessarily strong (given that there's no
proposal to add syntax saying otherwise -- "weak children?").

No problems here.  I'm just making some observations.

I guess I favor Robert's proposed "limited with" syntax.

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

From: Robert Eachus
Sent: Monday, February  3, 2003  2:26 PM

So do I, and I am beginning to like this proposal.  As far as I can see
it is clearly better than package abstracts in two ways, there is no new
compilation unit type, and there is no problem of keeping the abstract
consistant with the package itself.

In other words from a theoretical point of view, the "limited with"
creates a package abstract and then withs it.  Since the completion of
the types and the subprograms (and parameters) get lost in the process,
there is no visible circularity.

But I think that there are two "gotchas" that have to be dealt with.
 The first is where you have a type declaration that depends on another
type:

type Color is (Red, Green, Blue);
type Properties(C: Color) is...;

Does the incomplete type for Properties include the discriminant?
 Choices are yes, and it is illegal to do anything with it, type Color
is not incomplete, and the type Properties has undefined discriminants.
(Others?)  I prefer the choice where only private, record and tagged
types are incomplete in the limited view.

This brings me directly to the second gotcha.  I think it is clear (at
least to me) that for this to be useful, the limited view of an access
type has to be an access type.  But there have to be limits on how this
access type can be used in the limited view.  (Translation, if you
create a type with a component of  (a limited view of) an access type,
then it is illegal to have a non-null default value for a component of
that type.  Other rules are possible.)

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

From: Robert A. Duff
Sent: Monday, February  3, 2003  2:26 PM

> This brings me directly to the second gotcha.  I think it is clear (at
> least to me) that for this to be useful, the limited view of an access
> type has to be an access type.  But there have to be limits on how this
> access type can be used in the limited view.

Can't we say that it's an access type whose designated type is
incomplete?  And then you can't do things like X.all.

>...  (Translation, if you
> create a type with a component of  (a limited view of) an access type,
> then it is illegal to have a non-null default value for a component of
> that type.  Other rules are possible.)

I think you can't have an allocator (as a default or anything else),
but I don't see why it couldn't be a function call that happens to
return the access type.  Perhaps an example?

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

[Editor's note: Mail after the above time is not posted yet. That's
58 messages as of this writing. Sorry.]

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


Questions? Ask the ACAA Technical Agent