CVS difference for ai05s/ai05-0074-1.txt
--- ai05s/ai05-0074-1.txt 2007/11/18 03:01:39 1.5
+++ ai05s/ai05-0074-1.txt 2008/01/19 07:25:31 1.6
@@ -3123,3050 +3123,3 @@
****************************************************************
-From: Tucker Taft
-Date: Thursday, September 27, 2007 12:33 PM
-
-Robert made the mistake of asking me before his
-talk at AdaUK on Tuesday what was on my "wish
-list" for Ada 2015. I mentioned three things:
-
- 1) Instantiation of generics with private types
- 2) Region-based storage management
- 3) Units checking
-
-This of course got me to thinking some more about these
-things. As far as instantiation of generics with
-private types, in the same package where the private
-type is declared, I am currently enamored of two
-different solutions, both of which might be interesting
-in their own right:
-
- A) Allow the notion of "end private;" where the private
- part ends before the end of the package spec, and then
- you can return to visible declarations.
-
- B) Allow the ability to have child units of a
- package or generic package that are effectively
- "pre-withed" by all dependents.
-
-With (A), you simply move the instantiations to a point
-after the "end private;" and then you can instantiate
-any generic with the now completed private types
-declared in the package. Robert immediately asked whether
-it made sense to have multiple private parts in a
-single package. I didn't have an immediate response.
-
-With (B), you make your instantiations be child units,
-and then "pre-with" them on behalf of your clients,
-and then you are able to use private types in
-the instantiations, and your clients think of them as
-sub-packages. I believe GNAT may at one point have
-played a trick roughly like this for Text_IO, by making
-Integer_IO and friends into children of Text_IO, but
-"pre-with"ing them so clients see them as subpackages.
-If a generic unit "pre-withs" a child, then there is
-no particular reason the child needs to be limited to
-being itself a separate generic, since the instantiator of the
-parent unit "knows" to instantiate the pre-with'ed
-children as well.
-
-Syntactically, I thought that given "with" creating
-a dependence starting at the beginning of the
-compilation unit, and "private with" creating
-a dependence starting at the word "private,"
-then "end with <child1>, <child2>;" might be
-a natural way to "pre-with" the specified children,
-with it taking effect at the end of the
-compilation unit.
-
-E.g. for Text_IO, one might have:
-
-
- private with System.RTS.Files;
-
- end with Ada.Text_IO.Integer_IO,
- Ada.Text_IO.Enumeration_IO,
- Ada.Text_IO.Float_IO, ...
-
- package Ada.Text_IO is
- type File_Type is private;
- ...
- private
- type File_Type is new
- System.RTS.Files.File_Type with ...
- end Ada.Text_IO;
- -- conceptually, the "with"s of children
- -- happen here, and *are* inherited by all
- -- clients of Ada.Text_IO.
-
-
-Comments, flames, etc. as usual.
-
-****************************************************************
-
-From: Randy Brukardt
-Date: Thursday, September 27, 2007 1:41 PM
-
-> Comments, flames, etc. as usual.
-
-How's your homework coming? ;-)
-
-Oh, you wanted comments on your ideas??
-
-The second one looks more appealing (not the syntax, though!), because it
-doesn't require changing the visibility model of the language. However, the
-"forward" reference in the "end with" as you have it would be problematical,
-because it requires referencing something that by definition could not have
-yet been created. I know that when I tried to use such an idea in one of the
-early proposals for what became limited with, it was not well received by
-users. I'm not sure if that is a real problem in this context.
-
-Syntactically, I'd suggest something like "include with", which would of
-course require another keyword.
-
-Going back one more step, here's my "wish list" for Ada 2015:
-
- 1) In out parameters for functions (with expressions with function calls for
- which order could change the result being made illegal);
- 2) More exposure of concurrency for multi-core systems (combined with more
- checking to reduce the possibility of deadlocks/indeterminate results);
- 3) Instantiation of generics with private types.
-
-****************************************************************
-
-From: Robert A. Duff
-Date: Thursday, September 27, 2007 6:00 PM
-
-> 1) Instantiation of generics with private types
-
-It seems to me that the most important case is where there is some mutual
-recursion going on, such as:
-
- with Ada.Containers.Vectors; use Ada.Containers;
- package Trees is
- type Tree is private;
- package Tree_Vectors is new Vectors (Tree,...); -- Illegal!
- ...
- private
- type Tree is
- record
- ...
- Subtrees : access Tree_Vectors.Vector;
- end record;
- end Trees;
-
-Otherwise, you can just put the instance in a child. That's an annoyance,
-because clients have to 'with' it, but it doesn't prevent you from doing
-anything. The mutually recursive case, on the other hand, requires massive
-restructuring to work around the restriction.
-
-****************************************************************
-
-From: Tucker Taft
-Date: Thursday, September 27, 2007 11:16 PM
-
-> It seems to me that the most important case is where there is some mutual
-> recursion going on, such as:
->
-> with Ada.Containers.Vectors; use Ada.Containers;
-> package Trees is
-> type Tree is private;
-> package Tree_Vectors is new Vectors (Tree,...); -- Illegal!
-> ...
-> private
-> type Tree is
-> record
-> ...
-> Subtrees : access Tree_Vectors.Vector;
-> end record;
-> end Trees;
-
-Couldn't you just use an incomplete type here:
-
- with Ada.Containers.Vectors; use Ada.Containers;
- package Trees is
- type Tree is private;
-
- ...
- private
- type Tree_Vector;
- type Tree is
- record
- ...
- Subtrees : access Tree_Vector;
- end record;
-
- package Tree_Vectors is new Vectors (Tree,...);
- type Tree_Vector is new Tree_Vectors.Vector;
- end Trees;
-
-Presuming you are going to use access values, I don't
-see a problem. You could still use the "end private"
-to make the instantiation to be *visible*, if that
-were desirable.
-
-> Otherwise, you can just put the instance in a child. That's an annoyance,
-> because clients have to 'with' it, but it doesn't prevent you from doing
-> anything. The mutually recursive case, on the other hand, requires massive
-> restructuring to work around the restriction.
-
-The one place where putting the instantiation in the child
-doesn't really work is when you are trying to include
-the instantiation of, say, a signature package within a generic.
-A generic can't have a child that is an instantiation.
-Either the "end private" or the "end with" would
-solve this.
-
-****************************************************************
-
-From: Robert A. Duff
-Date: Friday, September 28, 2007 7:00 AM
-
-> Presuming you are going to use access values, I don't
-> see a problem. You could still use the "end private"
-> to make the instantiation to be *visible*, if that
-> were desirable.
-
-OK, that's reasonable, so long as there's a way to export Tree_Vector (and its
-ops).
-
-To have mutual recursion, Ada requires an access type to break the chain.
-I would prefer any solution allow the programmer maximum flexibility in
-where to put that access type (e.g. as above, versus in the generic, etc).
-Otherwise, there will be cases where you are annoyingly forced to use
-TWO access types.
-
-> > Otherwise, you can just put the instance in a child. That's an annoyance,
-> > because clients have to 'with' it, but it doesn't prevent you from doing
-> > anything. The mutually recursive case, on the other hand, requires massive
-> > restructuring to work around the restriction.
->
-> The one place where putting the instantiation in the child
-> doesn't really work is when you are trying to include
-> the instantiation of, say, a signature package within a generic.
-> A generic can't have a child that is an instantiation.
-> Either the "end private" or the "end with" would
-> solve this.
-
-OK. But the "end private" idea has the advantage that you can refer to the
-instance from within the package itself, right?
-
-I'm pretty sure that if you want two visible parts, you're going to want
-several visible parts and several private parts. Somebody famously said,
-a programming language should have zero, one, or infinite of any thing.
-
-By the way, the "end with" syntax is, well..., it will take some "getting used"
-to. If I see "end" (especially at the beginning of a line) I think "this is
-the end of something".
-
-****************************************************************
-
-From: Jean-Pierre Rosen
-Date: Friday, September 28, 2007 9:05 AM
-
-> By the way, the "end with" syntax is, well..., it will take some "getting used"
-> to. If I see "end" (especially at the beginning of a line) I think "this is
-> the end of something".
->
-Hmmm... since the effect is to automatically with the children, what
-about "with all" ?
-
-(Designing new syntax is always great fun :-)
-
-****************************************************************
-
-From: Randy Brukardt
-Date: Friday, September 28, 2007 1:11 PM
-
-> By the way, the "end with" syntax is, well..., it will take some "getting used"
-> to. If I see "end" (especially at the beginning of a line) I think "this is
-> the end of something".
-
-As I said yesterday, the idea doesn't bother me, but the syntax is horrible.
-It doesn't convey the meaning of the construct at all (which is that the
-with is "included" in any uses of this package). I suggested "include with",
-because that conveys the meaning, and I would much rather that we referred
-to Tucker's idea that way, so that it is intuitively obvious what it is
-we're talking about. ("end private" has that effect, too, as well as
-complete revulsion. :-). Maybe someone else has a syntax suggestion that
-actually conveys the meaning (sorry, J-P, but "with all" is just as bad),
-but in the absence of that, I strongly suggest that we use "include with"
-since it does.
-
-After all, my generic default type proposal was defeated primarily because
-of syntax concerns. I would think Tucker would not want that to happen to
-this idea.
-
-****************************************************************
-
-From: Tucker Taft
-Date: Friday, September 28, 2007 2:27 PM
-
-Or "all with Ada.Text_IO.Integer_IO;"
- -- That is "all [clients implicitly] with Ada.Text_IO.Integer_IO"
-
-Another approach is to use "is separate" which has
-been bandied about in the past, and treat them
-as package "spec subunits." E.g.:
-
- package Ada.Text_IO is
- ...
- generic package Integer_IO is separate;
- generic package Float_IO is separate;
- private
- ...
- end Ada.Text_IO;
-
-****************************************************************
-
-From: Jean-Pierre Rosen
-Date: Monday, October 1, 2007 3:23 AM
-
-And how would it be different from a child package, apart from not
-seeing the private part of the parent?
-
-****************************************************************
-
-From: Randy Brukardt
-Date: Monday, October 1, 2007 2:30 PM
-
-Because it would be automatically included whenever the parent is withed,
-whereas a child unit has to be withed separately. Tucker is trying to make
-it easier to separate specifications into separate units when the logical
-view is a single unified specification.
-
-****************************************************************
-
-From: Tucker Taft
-Date: Monday, October 1, 2007 2:53 PM
-
-Bob makes the point that the "end private" idea
-is more powerful, in that you can use items from
-the instantiation to visibly complete incomplete types
-declared before the instantiation. When trying
-to create mutually recursive types, that seems
-pretty important.
-
-From an implementation point of view, multiple
-visible parts also seems simpler than "spec subunits"
-or "inclusive with" of children. Any comments
-on the "end private" syntax, and/or whether a semicolon
-is desirable after "end private"? I suspect a different
-indenting would be used for "private/end private,"
-such as:
-
- package Trees is
- type Tree is private
- ...
- private
- ...
- end private
- ...
- end Trees;
-
-****************************************************************
-
-From: Edmond Schonberg
-Date: Monday, October 1, 2007 3:22 PM
-
-A smaller syntactic change would be to have both views of the type in
-a single declaration:
-
-private type Tree is record ...
-
-You can have as many of those as you want, which answers the "zero,
-one, infinity" rule. Full "private sections" would sit heavily on
-my stomach (and Randy's too, I recall).
-
-****************************************************************
-
-From: Randy Brukardt
-Date: Monday, October 1, 2007 3:45 PM
-
-...
-> From an implementation point of view, multiple
-> visible parts also seems simpler than "spec subunits"
-> or "inclusive with" of children.
-
-Gee, Tucker, what are you smoking these days? I want some! :-)
-
-The implementation of "inclusive with" is trivial: just jam an extra with
-into the list of withed units when the appropriate thing is encountered in
-the loaded unit. (But I do agree that it is not an ideal solution to the
-mutual recursion problem.)
-
-OTOH, the implementation of a new kind of visibility would have a lot of
-effects throughout the compiler, because visibility is such a pervasive
-idea. (And in Janus/Ada it is somewhat distributed, which makes things even
-worse.) I also worry about information "leakage" out of the private part; we
-currently have a number of rules intended to ensure that you cannot depend
-on the contents of a private part, and it seems likely that there would be
-effects visible in an "end private" part that would effectively render items
-in the private part visible.
-
-I still think this is a bad idea; I still think that two part instantiations
-can work if sufficiently limited (we never really finished working on that
-idea - it was only the broadly defined version that didn't work). Ed's idea
-also would work (although it has the issue of exposing the implementation in
-practice even if not semantically).
-
-****************************************************************
-
-From: Robert A. Duff
-Date: Monday, October 1, 2007 5:15 PM
-
->...Any comments
-> on the "end private" syntax, and/or whether a semicolon
-> is desirable after "end private"?
-
-From a purely syntactic point of view, I don't mind "end private".
-It was "end with" that rubbed me the wrong way.
-
-I suppose you can have multiple private parts, as in:
-
- package P is
- ... -- public stuff
- private
- ... -- private stuff
- end private;
- ... -- public stuff
- private
- ... -- private stuff
- end private;
- ... -- public stuff
- end P;
-
-?
-
-A semicolon? Yeah, I guess so. Shrug.
-
-Syntax is important, but the semantics is where trouble might arise.
-
-****************************************************************
-
-From: Tucker Taft
-Date: Monday, October 1, 2007 5:35 PM
-
-I should know better than to guess at relative
-implementation difficulties. My presumption
-was that multiple visible parts were not
-significantly different from single visible
-parts. There isn't really a "new" kind of
-visibility, is there? Some declarations
-in the spec are private, and some are visible,
-which is how it is now.
-
-But I guess the universal rule in this area is:
-Your Mileage May Vary.
-
-I would be curious whether how other vendors
-see the relative implementation difficulty.
-
-One major problem I have with the "private type ..."
-suggestion is that you don't have any way to
-declare types that are not visible at all
-using that notation. It is quite common that
-some of the types of components of a private
-type are not visible at all. I also worry
-that the "private type ..." proposal is
-a completely different approach to visibility
-from a conceptual point of view, creating
-a dramatic shift in perception of how things
-are done.
-
-****************************************************************
-
-From: Randy Brukardt
-Date: Monday, October 1, 2007 6:07 PM
-
-> I should know better than to guess at relative
-> implementation difficulties. My presumption
-> was that multiple visible parts were not
-> significantly different from single visible
-> parts. There isn't really a "new" kind of
-> visibility, is there? Some declarations
-> in the spec are private, and some are visible,
-> which is how it is now.
-
-Well, each declaration is either visible or it is not at a particular point
-of the program. But that changes for each different unit/scope that you go
-through. There are already multiple kinds of private parts (package,
-protected), and the rules for what is visible are complex.
-
-Our implementation changes a visibility flag on each declaration as we enter
-or leave different program units; how that works exactly is different for
-packages, subprograms, protected types, task types, child units (and public
-units are different than private units). [At least I *think* this is how it
-works; I didn't design or write this code so I'm somewhat hazy on the
-details.) For instance, for packages, there is a pointer that separates the
-private declarations from the public ones. Obviously, if there are
-additional parts, there are going to be more "declaration ranges" as well,
-and that will make additional complications.
-
-There are currently about 96 references to the "private_list" pointer in
-Janus/Ada; all of those would need to be looked at. Obviously, some are just
-initializations, but many seem to have important effects. 96 things to look
-at seems like a massive job.
-
-> But I guess the universal rule in this area is: Your Mileage May Vary.
-
-Right; it's usually not possible to guess the implementation effort for some
-other compiler. (And it's not that easy even for your own!)
-
-I'd be especially be wary of comparing implementation effort between two
-ideas unless one is absurdly simple (like just a syntax change).
-
-> One major problem I have with the "private type ..."
-> suggestion is that you don't have any way to
-> declare types that are not visible at all
-> using that notation. It is quite common that
-> some of the types of components of a private
-> type are not visible at all. I also worry
-> that the "private type ..." proposal is
-> a completely different approach to visibility
-> from a conceptual point of view, creating
-> a dramatic shift in perception of how things
-> are done.
-
-I agree with this, which is why I still think that the two part
-instantiation (which matches up well with a two part type declaration) is
-the way to go. The main problem I see is that the syntax choices we looked
-at did not really properly convey what is going on (and that is important in
-order to make the use intuitive). [I realize that there were semantic
-problems, but I still think those could be worked out by limiting the
-functionality of the "private" instantiation -- we never really tried that
-seriously to see, as Pascal removed it from the Amendment agenda at that
-point.]
-
-****************************************************************
-
-From: Robert I. Eachus
-Date: Monday, October 1, 2007 6:59 PM
-
->I still think this is a bad idea; I still think that two part instantiations
->can work if sufficiently limited (we never really finished working on that
->idea - it was only the broadly defined version that didn't work). Ed's idea
->also would work (although it has the issue of exposing the implementation in
->practice even if not semantically).
-
-
-I think that the end private (with or without semicolon) is conceptually
-the easiest for users to master. I do think though that a restricted
-version of that proposal would be a lot easier to both implement and
-understand. First yes, it would be possible to have multiple private
-parts, but is that game really worth the candle? If you have ONE
-private part, then private types have to be declared before the private
-part, along with deferred constants and so on. If we hang the
-elaboration of child units then the package body right at the end of the
-private part--or the package declaration if there isn't one--then
-instantiations of children there are fine. As for making private
-details visible, no reason it should. What you care about is that
-private types, and for that matter subprograms in the (first) public
-part are now elaborated.
-
-Would there be some confusion from the fact that declarations in the
-second public part would not be visible in the body? Not that much.
-Would it be a problem? I'd have to do some experimentation, but I don't
-see it as a problem. You might have to put some declarations in a child
-package then use renaming in the second public part to make them visible
-as part of the main package API. I have to think that in most cases
-that will be what you want to do anyway.
-
-Now to explain some magic handwaving above. How do you tell that a
-reference in the second private part is to a child package? Either a
-with clause, a use clause, or both in the second public part. Allowing
-with clauses there is much more like the two part package declarations,
-but a bit easier to maintain. I'd like to limit it to use clauses for
-child units for methodological reasons, but such units could have their
-own with clauses for anything, so that would not limit much in reality.
-
-****************************************************************
-
-From: John Barnes
-Date: Monday, October 1, 2007 1:44 AM
-
-Of all the suggestions, I like the end private idea. In fact I sent the
-following a few days ago but it seemed to go down a black hole. I said in a
-reply to Tuck:
-
-> A) Allow the notion of "end private;" where the private
-> part ends before the end of the package spec, and then
-> you can return to visible declarations.
-
-I suggested that to Jean in a letter in 1983 or thereabouts but he didn't
-reply! I always thought that the Ada all-in-one-lump approach to visibility,
-although elegant, was not flexible enough in practice. Another case of
-needing truth before beauty.
-
-PS And of course dammit - you need a semicolon!
-
-****************************************************************
-
-From: Jean-Pierre Rosen
-Date: Monday, October 1, 2007 3:16 AM
-
-> A smaller syntactic change would be to have both views of the type in a
-> single declaration:
->
-> private type Tree is record ...
-
-Except of course that it would be ambiguous:
- private
- type Tree is ...
-
-The more I think about the "end private" idea, the more uncomfortable I
-feel. I'm afraid there is a huge can of worms sleeping under it...
-
-For example:
-Child units currently see *the* private part. Would they see all of them?
-
-If I put a "use" clause in a private part, does it extend into the
-following non-private parts?
-
-How would the "private with" work? It should apply to all private parts,
-therefore we'll have visibility coming in and out...
-
-****************************************************************
-
-From: Pascal Leroy
-Date: Tuesday, October 2, 2007 8:00 PM
-
-> Bob makes the point that the "end private" idea is more
-> powerful, in that you can use items from the instantiation to
-> visibly complete incomplete types declared before the
-> instantiation. When trying to create mutually recursive
-> types, that seems pretty important.
->
-> package Trees is
-> type Tree is private
-> ...
-> private
-> ...
-> end private
-> ...
-> end Trees;
-
-My first reaction is that this reeks of C++.
-
-This is one of the (many) things that I hate in C++: the declaration of a
-class can include any number of public/protected/private sections in any
-order. True, this is more flexible than the Ada model, but then it sooo
-easy to misuse. In Ada, as soon as you see the word private, you know that
-you are done with the exported declarations. In C++ you have to read the
-entire class declaration, keeping track of all the visibility changes, just
-to find out which declarations are exported. It is extremely easy to miss
-one of the little words public/protected/private, and be just totally
-confused about what a class does.
-
-At any rate, it would be good to explain what exactly is visible after "end
-private" and how you ensure that no private information is leaked out of the
-package.
-
-****************************************************************
-
-From: Pascal Leroy
-Date: Tuesday, October 2, 2007 8:01 AM
-
-> I still think this is a bad idea; I still think that two part
-> instantiations can work if sufficiently limited (we never
-> really finished working on that idea - it was only the
-> broadly defined version that didn't work).
-
-I agree with this. I always thought that we were on the right track, but we
-just didn't have enough time to find a model that would avoid all these
-Baird pathologies.
-
-****************************************************************
-
-From: Robert A. Duff
-Date: Tuesday, October 2, 2007 8:06 PM
-
-> My first reaction is that this reeks of C++.
-
-...says the guy who is leaving the Ada world for greener pastures. ;-) ;-)
-
-And if the C++ standard says "the sky is blue", should we automatically dispute
-that? ;-)
-
-Note smileys -- I'm just teasing you, Pascal.
-
-> This is one of the (many) things that I hate in C++: the declaration of a
-> class can include any number of public/protected/private sections in any
-> order. True, this is more flexible than the Ada model, but then it sooo
-> easy to misuse. In Ada, as soon as you see the word private, you know that
-> you are done with the exported declarations. In C++ you have to read the
-> entire class declaration, keeping track of all the visibility changes, just
-> to find out which declarations are exported. It is extremely easy to miss
-> one of the little words public/protected/private, and be just totally
-> confused about what a class does.
-
-If it's properly indented, I don't find it hard to see the private/public
-structure.
-
-> At any rate, it would be good to explain what exactly is visible after "end
-> private" and how you ensure that no private information is leaked out of the
-> package.
-
-Indeed. Demons lurk, here, in the details.
-
-****************************************************************
-
-From: Randy Brukardt
-Date: Wednesday, October 24, 2007 11:32 PM
-
-...
-> At any rate, it would be good to explain what exactly is visible after "end
-> private" and how you ensure that no private information is leaked out of the
-> package.
-
-Let's just look at a few cases that would need to be defined:
-
-* What if is there is a use clause in the private part? Does it extend into the
- following non-private part(s)? [This was from Jean-Pierre.] I think the answer
- has to be no, but that surely complicates things (and implementations).
-
-* How about "additional operations" of a type? That is, in something like:
-
- package P is
- type Q is limited private;
- private
- type Q is record
- A : Integer := 10;
- end record;
- end private;
- Obj : Q;
- B : Boolean := (Obj = Obj);
- end P;
-
- Again, probably not. More generally, declarations in a private part should not be
- visible in a following visible part, so we'd have visibility going out at "end private;"
- and then returning when we reached the body.
-
- with Func;
- package P is
- type Q is limited private;
- private
- type Q is access Integer;
- Obj : Q;
- end private;
- I : Integer := Obj.all;
- end P;
-
- This reduced visibility worries me, as we generally don't lose visibility in a single
- package: everything is additive (visible part, private part, body). It seems to offer
- the opportunity for more anomalies.
-
-* Do public children see all of the visible declarations but none of the private ones
- of their parent? (Seems necessary.)
-
-I'm sure there are more issues to consider. I haven't seen any posting by Steve Baird
-on this yet. ;-) The whole thing sounds like fun. :-(
-
-****************************************************************
-
-From: Tucker Taft
-Date: Thursday, October 25, 2007 7:25 AM
-
-Randy Brukardt wrote:
-> Pascal notes:
->
-> ...
->> At any rate, it would be good to explain what exactly is visible after
-> "end
->> private" and how you ensure that no private information is leaked out of
-> the
->> package.
->
-> Let's just look at a few cases that would need to be defined:
->
-> * What if is there is a use clause in the private part? Does it extend into
-> the following non-private part(s)? [This was from Jean-Pierre.] I think the
-> answer has to be no, ...
-
-Agreed, clearly no.
-
->
-> * How about "additional operations" of a type? That is, in something like:
->
-> package P is
-> type Q is limited private;
-> private
-> type Q is record
-> A : Integer := 10;
-> end record;
-> end private;
-> Obj : Q;
-> B : Boolean := (Obj = Obj);
-> end P;
->
-> Again, probably not. More generally, declarations in a private part
-> should not be visible in a following visible part, so we'd have visibility
-> going out at "end private;" and then returning when we reached the body.
-
-Agreed.
-
->
-> with Func;
-> package P is
-> type Q is limited private;
-> private
-> type Q is access Integer;
-> Obj : Q;
-> end private;
-> I : Integer := Obj.all;
-> end P;
->
-> This reduced visibility worries me, as we generally don't lose visibility
-> in a single package: everything is additive (visible part, private part,
-> body). It seems to offer the opportunity for more anomalies.
-
-Perhaps, though I think nested packages with private
-parts are pretty similar. With nested packages,
-visibility comes and goes.
-
-Child packages are perhaps even closer to this. When
-you start a child package, although they logically "follow"
-the private part of their ancestor packages,
-they don't "see" the private part. When you hit
-the private part of the child package, suddenly
-the private declarations of all the ancestors become
-visible.
-
-So from an implementation and anomaly point of view,
-at the "end private;" you might imagine you are starting a
-child package, which cannot take advantage of visibility
-on the parent's private part until it hits its own private
-part or body.
-
-> * Do public children see all of the visible declarations but none of the
-> private ones of their parent? (Seems necessary.)
-
-They don't see the private declarations until they hit their
-own private part or body. No real surprise here.
-
->
-> I'm sure there are more issues to consider. I haven't seen any posting by
-> Steve Baird on this yet. ;-)The whole thing sounds like fun. :-(
-
-Clearly there will be some implementation effects, but I
-don't see many semantic anomalies on the visibility side,
-since I believe a child package experiences much the same
-"coming and going" of visibility.
-
-The anomalies I could imagine would have to do with "completion"
-and overriding, since these kinds of things can't be
-simulated by a child package (though a child subprogram
-can "simulate" overriding in certain non-tagged cases).
-And I agree we will need to work them through if we decide
-to pursue this proposal. I am happy to do so, after
-I have finished my other homework ... ;-).
-
-****************************************************************
-
-From: Robert A. Duff
-Date: Thursday, October 25, 2007 9:15 AM
-
-> Let's just look at a few cases that would need to be defined:
->...
-
-I'm surprised by Tucker's answer. My answer is that "obviously", the
-visibility in the second visible part includes everything that came before,
-just as if "end private;" were erased. (Now Tuck can tell me why that's
-stupid. ;-))
-
-The purpose of privacy is to hide things from OTHER packages, not from the
-package itself. This should be legal:
-
- package P is
- private
- type Base_Type is range 1..2**31-1;
- end private
- subtype Exported_Type is Base_Type'Base;
- end P;
-
-to get a type that has at least 32 bits, but matches the hardware bounds. I
-don't want to pester the client with a useless name -- Base_Type is visible in
-the visible part, but not in clients.
-
-By the way, C++ has a similar feature. It might help to look at the details,
-which I don't remember. Of course C++ visibility is quite different from Ada,
-so it might be irrelevant. And C++ visibility is broken in some ways, so we
-don't necessarily want to mimic it -- but it couldn't hurt to look.
-
-> * Do public children see all of the visible declarations but none of the
-> private ones of their parent? (Seems necessary.)
-
-Yes.
-
-> I'm sure there are more issues to consider. I haven't seen any posting by
-> Steve Baird on this yet. ;-)The whole thing sounds like fun. :-(
-
-Indeed. I'm not at all sure the whole idea will work.
-
-****************************************************************
-
-From: Jean-Pierre Rosen
-Date: Thursday, October 25, 2007 7:34 AM
-
-> Let's just look at a few cases that would need to be defined:
->
-And:
-
-I assumed when I read the proposal that there could be several private
-parts, but I didn't see any mention about that. Is it the intent? That
-would certainly seem logical from a user point of view:
-
-package Pack is
- -- visible
-private
- -- hidden
-end private;
-
- -- visible again
-
-private
- -- hidden again
-end Pack;
-
-Have great fun with visibility going in and out!
-
-****************************************************************
-
-From: Randy Brukardt
-Date: Thursday, October 25, 2007 7:56 PM
-
-...
-> > with Func;
-> > package P is
-> > type Q is limited private;
-> > private
-> > type Q is access Integer;
-> > Obj : Q;
-> > end private;
-> > I : Integer := Obj.all;
-> > end P;
-> >
-> > This reduced visibility worries me, as we generally don't
-> lose visibility
-> > in a single package: everything is additive (visible part, private part,
-> > body). It seems to offer the opportunity for more anomalies.
->
-> Perhaps, though I think nested packages with private
-> parts are pretty similar. With nested packages,
-> visibility comes and goes.
->
-> Child packages are perhaps even closer to this. When
-> you start a child package, although they logically "follow"
-> the private part of their ancestor packages,
-> they don't "see" the private part. When you hit
-> the private part of the child package, suddenly
-> the private declarations of all the ancestors become
-> visible.
-
-Not really: within a single unit, all that can happen is the *addition* of
-new things. Once you can see the additional operations, they stay visible
-until the end of the unit. (The situation in outer units may be different,
-but I don't see that as relevant -- we know that visibility can change in
-external units, but it doesn't reduce *directly within* a unit.)
-
-> So from an implementation and anomaly point of view,
-> at the "end private;" you might imagine you are starting a
-> child package, which cannot take advantage of visibility
-> on the parent's private part until it hits its own private
-> part or body.
-
-A child package starts with a "clean" visibility slate, into which the
-parent and other "withs" are loaded. Handling the private part at that point
-is (relatively) easy. A "end private" has a complex visibility state,
-already existing, where things would have to be subtracted piece-meal.
-(Reloading is not an option: you haven't stored it out yet!) This seems
-sustantially more complex. (Of course, I haven't tried implementing this, so
-it might prove easier than I think now.)
-
-> > * Do public children see all of the visible declarations but none of the
-> > private ones of their parent? (Seems necessary.)
->
-> They don't see the private declarations until they hit their
-> own private part or body. No real surprise here.
->
-> > I'm sure there are more issues to consider. I haven't seen any posting
-by
-> > Steve Baird on this yet. ;-)The whole thing sounds like fun. :-(
->
-> Clearly there will be some implementation effects, but I
-> don't see many semantic anomalies on the visibility side,
-> since I believe a child package experiences much the same
-> "coming and going" of visibility.
-
-No, only "coming". There's no "going": once the private part of a parent is
-visible, it stays that way. It's the "going", for declarations in the same
-unit, which I think doesn't exist currently and has the potential to add
-complications.
-
-Now, I realize that other models of child compilations are possible, but for
-us, each one starts with a clean slate which is built up with whatever is
-needed (a parent is just a hidden "with" of a unit). The only magic is
-making the private part visible when the child "private" is reached, and
-that is a pure addition to visibility.
-
-> The anomalies I could imagine would have to do with "completion"
-> and overriding, since these kinds of things can't be
-> simulated by a child package (though a child subprogram
-> can "simulate" overriding in certain non-tagged cases).
-> And I agree we will need to work them through if we decide
-> to pursue this proposal. I am happy to do so, after
-> I have finished my other homework ... ;-).
-
-Sounds good, especially the part about finishing your other homework. :-)
-
-This issue and the possible solutions are on the agenda for Washington,
-although I'd expect any brainstorming on it to come after we get our other
-work done. (You'll note it is right on the bottom of the list... ;-)
-
-BTW, you are welcome to give the same treatment to the write-up of my
-proposal for this problem that you'll find in AI05-0074-1 (another AI number
-that I fear will live in infamy, like AI-217 [limited with] and AI-359 [the
-4(!) previous versions of this problem]). I hope I can take it as well as I
-dish it out. ;-)
-
-****************************************************************
-
-From: Tucker Taft
-Date: Thursday, October 25, 2007 11:13 PM
-
-> I'm surprised by Tucker's answer. My answer is that "obviously", the
-> visibility in the second visible part includes everything that came before,
-> just as if "end private;" were erased. (Now Tuck can tell me why that's
-> stupid. ;-))
-
-I would think that would be a recipe for privacy "leakage."
-If you, for example, declare a subtype of a private
-type in a visible part that follows the private part
-that defined its full type, is the subtype a partial
-view or a full view of the type? E.g.:
-
- type P is private;
- private
- type P is new Integer;
- end private;
- subtype S is P;
-
-What are the properties of subtype S? I
-really think it needs to still be private.
-
-I think from a *visibility* point of view,
-it should be as though the private declarations
-were not there at all. The only effect of
-the private declarations should be to complete
-certain earlier declarations, so they can be used
-in contexts where a completely defined
-entity is required.
-
-> The purpose of privacy is to hide things from OTHER packages, not from the
-> package itself.
-
-If that were true, then why wouldn't the visible part of
-a child package have visibility on the private part of
-its parent? It comes physically after it, it is inside
-the declarative region of the parent, but it doesn't
-have visibility on the private declarations until you
-reach its own private part. One reason is to avoid
-privacy leakage. The visible part of a child package
-*can* take advantage of the fact that the private types
-of the parent have been completely defined, so they
-can be used in contexts where a completely defined
-private type is required.
-
-Basically, I think the visibility on the parent from
-the visible part of a child is the best model for
-the visibility after "end private;".
-
-> ... This should be legal:
->
-> package P is
-> private
-> type Base_Type is range 1..2**31-1;
-> end private
-> subtype Exported_Type is Base_Type'Base;
-> end P;
->
-> to get a type that has at least 32 bits, but matches the hardware bounds. I
-> don't want to pester the client with a useless name -- Base_Type is visible in
-> the visible part, but not in clients.
-
-I can see how that might be useful, but it would just
-introduce too many anomalies, I suspect.
-
-> By the way, C++ has a similar feature. It might help to look at the details,
-> which I don't remember. Of course C++ visibility is quite different from Ada,
-> so it might be irrelevant. And C++ visibility is broken in some ways, so we
-> don't necessarily want to mimic it -- but it couldn't hurt to look.
-
-The basic C++ "protection" model is quite different from
-Ada's. "Private" declarations are just as "visible" as
-"public" declarations, but you get an error if you try
-to use them in a place that isn't supposed to have access
-to private declarations. So this doesn't really address
-the issue, because the question simply becomes whether
-you are allowed to "use" (as opposed to "see") the
-declarations from a private part in a following visible
-part.
-
-The other big difference in C++ is that you don't
-have "two part" type declarations in C++, in the
-way you do in Ada for private types.
-
-****************************************************************
-
-From: Robert A. Duff
-Date: Friday, October 26, 2007 9:01 AM
-
-...
-> What are the properties of subtype S? I
-> really think it needs to still be private.
-
-You may well be right, but I'd like to understand why. What if S is an integer
-type? Would that cause the sky to fall?
-
-Or, what if S is an integer type within this package, but when viewed from
-outside, it is private? There's a "+" implicitly declared in the private part;
-what if it's visible in the second visible part, but not visible in clients?
-
-...
-> > The purpose of privacy is to hide things from OTHER packages, not from the
-> > package itself.
->
-> If that were true, then why wouldn't the visible part of
-> a child package have visibility on the private part of
-> its parent?
-
-I must admit, I've never quite understood the high-level rationale for that.
-If the so-called "leakage" is explicit in the program text, what's the harm?
-I suppose the devil's in the details...
-
-...
-
-> I can see how that might be useful, but it would just
-> introduce too many anomalies, I suspect.
-
-Quite likely true. But the opposite approach seems to have some difficulties,
-too.
-
-> > By the way, C++ has a similar feature. It might help to look at the details,
-> > which I don't remember. Of course C++ visibility is quite different from Ada,
-> > so it might be irrelevant. And C++ visibility is broken in some ways, so we
-> > don't necessarily want to mimic it -- but it couldn't hurt to look.
->
-> The basic C++ "protection" model is quite different from
-> Ada's. "Private" declarations are just as "visible" as
-> "public" declarations, but you get an error if you try
-> to use them in a place that isn't supposed to have access
-> to private declarations.
-
-Ah, yes, thanks for the reminder. I (now) agree that the C++ rules are
-irrelevant to this discussion.
-
-****************************************************************
-
-From: Tucker Taft
-Date: Friday, October 26, 2007 11:56 AM
-
->> What are the properties of subtype S? I
->> really think it needs to still be private.
->
-> You may well be right, but I'd like to understand why. What if S is an integer
-> type? Would that cause the sky to fall?
-
-No, but it changes the rules significantly. In many
-places in the reference manual, we indicate that a private
-part of a language-defined package is "not specified."
-It is nice to be able to do so (not just for the language
-designers, but for anyone specifying an abstraction
-via a package spec). I would hope that this property
-of packages remains true in general, namely you can look
-just at the visible part(s) of a package and make
-sense of it without having to look at the private
-part at all. Furthermore, a maintainer can change
-the private part of the package and not have to
-worry about the semantic effects on clients of
-the package.
-
-> Or, what if S is an integer type within this package, but when viewed from
-> outside, it is private? There's a "+" implicitly declared in the private part;
-> what if it's visible in the second visible part, but not visible in clients?
-
-Again, that means you can't really understand what is going
-on in the visible part without studying the private part.
-
-> ...
->>> The purpose of privacy is to hide things from OTHER packages, not from the
->>> package itself.
->> If that were true, then why wouldn't the visible part of
->> a child package have visibility on the private part of
->> its parent?
->
-> I must admit, I've never quite understood the high-level rationale for that.
-> If the so-called "leakage" is explicit in the program text, what's the harm?
-> I suppose the devil's in the details...
-
-I believe the rationale is as above, namely that you
-don't need to study the private part of the parent
-to understand the visible parts of the child packages.
-
-Interestingly, this point gives a rationale for only
-allowing one private part in a package. If you
-allow more than one, then to understand what is
-going on in the visible parts you need to know
-which private types are completed in which private
-part. I don't think that is a feature. In these
-discussions, I have harborred a personal dislike for the
-idea of multiple private parts in a single package,
-but I haven't had a good reason other than aesthetic.
-But this to me seems like a good reason. If you
-write a package spec and leave the private part(s)
-unspecified, then you don't want to have to specify
-which private part completes what type (or
-deferred constant).
-
-So I would go further and say that the
-"end private;" proposal should only allow one private
-part, that in the "post-private" visible
-part you can't introduce any more private types
-or deferred constants, and that all declarations
-prior to the "end private;" are frozen at the
-point of the "end private;", except for incomplete
-types.
-
-With this approach, you have no doubt what has
-to happen in *the* private part (the completion
-of all partial views and deferred constants, plus
-any relevant rep-clauses), and you know that
-everything is frozen (except incomplete types)
-at the "end private;", whether or not there is
-a freezing occurrence that happens to appear
-in the private part.
-
-Aesthetically, this also feels better. The
-private part can be "sandwiched" between a
-pre-private and a post-private visible part,
-but you don't have to worry about or deal
-with private parts "sprinkled" throughout
-the package spec at random points.
-
-Finally, the nature of the pre-private and
-the post-private visible parts are pretty
-different, since the private types
-and deferred constants need to precede
-the private part, and the instantiations
-and incomplete type completions can follow
-it.
-
-There can be some advantages to having
-a "standard" usage model implied by the
-constructs of the language, rather than
-having so many different equally good ways
-of solving the same problem that no standard style
-emerges, and programming styles within
-the same language vary dramatically.
-
-One last point. One reason why I like the
-notion of a "post-private" visible part
-to handle instantiations is that it is
-common for instantiations to be followed by
-one or more derived type declarations,
-bringing some of the types defined by
-the instance out into the surrounding
-scope. E.g.:
-
- package T_Vectors is
- new Containers.Vectors(T, ...);
- type T_Vector is new T_Vectors.Container
- with null record;
-
-The proposal of an "internally limited" instantiation
-that provides internally only a "limited view" where
-all exported types are incomplete, wouldn't
-support this standard paradigm (since you can't
-derive from an incomplete type). That could
-be a significant downside of that proposal,
-in my view.
-
-The post-private visible part can easily accommodate
-this approach. If necessary, an incomplete
-type declaration for T_Vector could precede it
-in the pre-private visible part (or in the
-private part). E.g.:
-
- package P is
- type T is private;
-
- type T_Vector is tagged;
- type T_Vec_Ptr is access T_Vector;
-
- function Inner_List(X : T) return T_Vec_Ptr;
- procedure Set_Inner_List(
- X : in out T; List : in T_Vec_Ptr);
-
- ...
-
- private
- type T is record
- Inner_List : T_Vec_Ptr;
- ...
- end record;
- ... -- rep-clauses for T, deferred constants, etc.
- end private;
-
- package T_Vectors is ...
- type T_Vector is new T_Vectors.Container
- with null record;
-
- end P;
-
-This feels pretty natural to me, with the post-private
-part doing a straightforward and useful job.
-
-It is interesting that when you do a "limited with" on
-a package you don't see any nested instances, but you
-do see derived type declarations. So using this
-paradigm of deriving from a type declared in a nested
-instance has the useful effect of making the type
-available (as an incomplete type) via a "limited with."
-The "internally limited" instantiation will always
-be completely invisible via a "limited with."
-
-Finally, because there is no "leakage" from the private part,
-we could reasonably write:
-
- package Ada.Neat_Standard_Package is
-
- type Container is private;
- ...
-
- private
- -- not specified by the language
- end private;
-
- package Useful_Instance is
- new Great_Generic(Container, ...)
- ...
-
- end Ada.Neat_Standard_Package;
-
-in a specification of some future language-defined
-package, where we wanted to include some visible
-instantiations (such as signatures), and there
-would be no danger in saying the private part is
-"not specified" since there is no doubt as to what
-would have to happen in the private part.
-
-Note also that the post-private part acts somewhat
-like the visible part of an "anonymous" child
-that you want all clients to "with" and "use."
-Semantically I think it can follow many
-of the same rules as a child visible part, and
-could even be implemented in a somewhat
-similar fashion, by starting from an empty
-slate, and then "loading up" the visibility
-stack with the with and use clauses, the pre-private
-visible part, etc. This would avoid having
-to remove declarations from the visibility
-stack, which I could imagine would be a burden
-for some implementations.
-
-****************************************************************
-
-From: Robert A. Duff
-Date: Friday, October 26, 2007 1:48 PM
-
-> Interestingly, this point gives a rationale for only
-> allowing one private part in a package. If you
-> allow more than one, then to understand what is
-> going on in the visible parts you need to know
-> which private types are completed in which private
-> part. I don't think that is a feature.
-
-OK, that makes sense.
-
->...In these
-> discussions, I have harborred a personal dislike for the
-> idea of multiple private parts in a single package,
-> but I haven't had a good reason other than aesthetic.
-> But this to me seems like a good reason.
-
-Agreed. I find vague aesthetics much more convincing when backed up by good
-reasons!
-
-Of course, allowing just one _visible_ part would be a further
-simplification. ;-)
-
-****************************************************************
-
-From: Tucker Taft
-Date: Friday, October 26, 2007 2:21 PM
-
-> Of course, allowing just one _visible_ part would be a further
-> simplification. ;-)
-
-Uhhhh, true, but how does that solve our original problem
-with instantiations using private types?
-
-****************************************************************
-
-From: Robert A. Duff
-Date: Friday, October 26, 2007 2:47 PM
-
-It doesn't. Hence the smiley. I was just attempting to wryly point out that
-this idea might not fly at all (and maybe in fact the whole problem can't be
-solved reasonably). Sorry for being unclear. Anyway, I guess we have several
-years to think about it...
-
-****************************************************************
-
-*** End of discussion of "end private" idea ***
-
-****************************************************************
-
-From: Tucker Taft
-Date: Friday, October 19, 2007 11:16 PM
-
-Randy and others indicated that they thought we came
-close on allowing for instantiation with private types
-by having a special kind of "partial" instantiation
-preceding the "full" instantiation.
-
-Here are some recent thoughts I had on this. They may be
-redundant or overlapping with our earlier discussions,
-but I'm not sure. The basic idea is that we have
-a "partial" instantiation, where we instantiate only
-the spec of the generic, and have no special pre-freezing
-of the actuals. Then we have the "full" instantiation
-where the actuals are frozen, and we instantiate
-the body. For example:
-
- type Priv is private;
-
- package Inst is new Gen(Priv) with private;
- -- "with private" indicates that
- -- private types are permitted, and no
- -- automatic freezing of actuals occurs.
- -- Only the *spec* of the generic Gen
- -- is instantiated at this point.
- -- (Of course some other syntax is possible.)
-
- private
-
- type Priv is record
- X : Inst.Something;
- end record;
-
- package Inst is new Gen(Priv);
- -- at this point, we instantiate the
- -- body of Gen, and do the usual pre-freezing
- -- of the actual parameters.
-
-
-This two-phase instantiation of a generic package is
-almost identical to a hand expansion as a nested package
-spec, followed by a later hand expansion for the
-corresponding body. This means that pretty much anything
-you can do with a nested package you can do with a
-generic.
-
-An important caveat: this means that you have instantiation-
-time checks that may reveal certain aspects of the private
-part of the generic. For example, if in the private
-part of the generic there is an object declaration
-of the formal type, then that would freeze the actual type
-at that point. In addition, type circularity checks
-could reveal whether the formal type is used directly or
-only with a level of indirection in a type declared in
-the generic (in the example above, we are assuming that
-type "Something" in the generic does not include a
-subcomponent of the formal type).
-
-These instantiation-time checks don't seem significantly
-worse than the ones we already have (every place where
-we say a given rule "applies also in the private part
-of an instance of a generic unit."). We have somewhat
-gotten used to the fact that the private part of a generic
-forms part of its contract.
-
-The main thing I like about this approach is that it
-really doesn't involve a bunch of special rules, such
-as making types automatically incomplete, etc. It
-just separates the instantiation of the spec from the
-body, and associates the "pre-freezing" of actuals with
-the instantiation of the body.
-
-I am almost certainly missing some subtlety, but at
-the moment it feels pretty straightforward.
-
-****************************************************************
-
-From: Tucker Taft
-Date: Friday, October 19, 2007 11:41 PM
-
-I should add, that if there are nested instantiations
-inside the generic, then during the "partial"
-instantiation, *probably* only spec instantiations should
-take place, with the body instantiations being
-delayed until the enclosing generic's body is
-instantiated. I knew I'd find at least one
-subtlety...
-
-****************************************************************
-
-From: Randy Brukardt
-Date: Friday, October 19, 2007 11:58 PM
-
-> Randy and others indicated that they thought we came
-> close on allowing for instantiation with private types
-> by having a special kind of "partial" instantiation
-> preceding the "full" instantiation.
->
-> Here are some recent thoughts I had on this. They may be
-> redundant or overlapping with our earlier discussions,
-> but I'm not sure.
-
-I recommend going back and reading the minutes on the various versions of
-AI-359 in order to see the problems.
-
-> The basic idea is that we have
-> a "partial" instantiation, where we instantiate only
-> the spec of the generic, and have no special pre-freezing
-> of the actuals. Then we have the "full" instantiation
-> where the actuals are frozen, and we instantiate
-> the body.
-
-...
-> The main thing I like about this approach is that it
-> really doesn't involve a bunch of special rules, such
-> as making types automatically incomplete, etc. It
-> just separates the instantiation of the spec from the
-> body, and associates the "pre-freezing" of actuals with
-> the instantiation of the body.
->
-> I am almost certainly missing some subtlety, but at
-> the moment it feels pretty straightforward.
-
-I think that there were problems with elaboration of the package
-specification. You can't actually do anything that would depend on the
-private type (because you don't yet know its declaration), so what you could
-put in the specification would be quite limited.
-
-For Janus/Ada, we generate thunks at the point of the instantiation which
-are called by the elaboration. Those obviously assume that the full type
-definition is available. (We share the elaboration part of the specification
-in the same way that we share the body; if we were able to do real template
-expansion, we probably would have used that everywhere...)
-
-The privacy breaking is uncomfortable, mainly because it could easily mean
-that generics like the containers may not be usable in specifications
-depending on their implementation. That suggests that we'd have to add a
-boatload of restrictions on how the private part is implemented (not
-allowing instantiation of the containers with a private type would be a
-non-starter, given that it is one of the problems that we need to fix). And
-I have to wonder what it would do to the IBM implementation.
-
-The solution still seems to me to be a limited instantiation that exports a
-limited view of the generic within the specification (but exports the full
-view of the generic to clients of the package). The problem we had in
-Atlanta was trying to export too much to the package; that led to all kinds
-of anomolies. Exporting nothing would work great, but wouldn't solve Bob's
-recursion problem. My main concern is that I never came up with a syntax
-that really explained what is happening. Maybe something like:
-
- package Inst is new Gen(Priv) for export;
-
-which makes it clear that Inst is only for export and for only limited local
-use.
-
-****************************************************************
-
-From: Randy Brukardt
-Date: Saturday, October 20, 2007 12:00 AM
-
-> I should add, that if there are nested instantiations
-> inside the generic, then during the "partial"
-> instantiation, *probably* only spec instantiations should
-> take place, with the body instantiations being
-> delayed until the enclosing generic's body is
-> instantiated. I knew I'd find at least one
-> subtlety...
-
-Mr. Code sharing is about to throw up. :-)
-
-****************************************************************
-
-From: Randy Brukardt
-Date: Saturday, October 20, 2007 12:07 AM
-
-...
-> My main concern is that I never came up with a
-> syntax that really explained what is happening. Maybe something like:
->
-> package Inst is new Gen(Priv) for export;
->
-> which makes it clear that Inst is only for export and for only
-> limited local use.
-
-Indeed, this suggests that the partial instantiation is not visible at all
-inside the package specification (until it is completed, of course).
-
-If we want a limited view, too, we could add syntax for that:
-
- package Inst is new Gen(Priv) for export with limited;
-
-There can be no anomolies with the first form, because it has no semantic
-effect on the package: it simply makes a declaration in the private part
-visible from the outside of the package.
-
-The second form adds a limited view so that recursive data types can be
-created. I'd expect that to work roughly the same as regular limited view,
-so I think we've already covered the anomolies. (Famous last words... ;-) I
-realize this construct is a bit more limiting for Bob than some of the other
-proposals, but at least with it you can write the sort of things he wants to
-(as opposed to the current situation where it is nearly impossible).
-
-****************************************************************
-
-From: Tucker Taft
-Date: Saturday, October 20, 2007 10:58 AM
-
-> I think that there were problems with elaboration of the package
-> specification. You can't actually do anything that would depend on the
-> private type (because you don't yet know its declaration), so what you could
-> put in the specification would be quite limited.
-
-Can you elaborate on this? When you say "you can't actually do
-anything" are you talking about the compiler or the
-programmer? How is this different from a nested package at
-the point of the partial instantiation, that refers to a
-private type from the enclosing package? It is true that in
-both cases, you can't lay out any types declared in the nested
-package that depend on the outer private types, but there is
-no requirement to do so until you hit a freezing point. By
-postponing the instantiation of the body, we hopefully postpone
-the freezing points.
-
-> For Janus/Ada, we generate thunks at the point of the instantiation which
-> are called by the elaboration. Those obviously assume that the full type
-> definition is available. (We share the elaboration part of the specification
-> in the same way that we share the body; if we were able to do real template
-> expansion, we probably would have used that everywhere...)
-
-I think you clearly would need to postpone generating some of the thunks,
-and separate the elaboration into two routines, one for the spec
-which would use only the thunks it really needed for the elaboration
-of the spec, and one for the body, which would use the remaining thunks.
-
->
-> The privacy breaking is uncomfortable, mainly because it could easily mean
-> that generics like the containers may not be usable in specifications
-> depending on their implementation. That suggests that we'd have to add a
-> boatload of restrictions on how the private part is implemented (not
-> allowing instantiation of the containers with a private type would be a
-> non-starter, given that it is one of the problems that we need to fix). And
-> I have to wonder what it would do to the IBM implementation.
-
-I agree we might have to specify additional implementation requirements.
-The most important would be that the generic must support partial
-instantiation.
-
-Secondarily, we would have to decide whether we want
-to require that certain exported types not include the formal
-types as subcomponents. My sense would be that we probably *don't*
-want to impose this latter requirement on the "definite" versions,
-so that "bounded" versions can be created that use no levels of
-indirection. On the other hand, imposing this requirement on
-the "indefinite" versions would seem reasonable, and actually
-makes the "indefinite" versions that much more flexible.
-
-I suppose this brings up another possibility, where we only
-defer freezing an actual type if the corresponding formal type
-has unknown discriminants. Since we know that a formal type
-with unknown discriminants could *never* be a subcomponent of
-an exported "definite" type, we eliminate the privacy breaking.
-That has a nice ring to it...
-
-I can even imagine we consider eliminating the need for two-part
-instantiations, and make them "implicit" when there is a formal
-type with unknown discriminants. That is, if a formal type
-has unknown discriminants, then the freezing of the corresponding
-actual type, and the body instantiation, is postponed
-until the next "general" freezing point. That has some
-upward compatibility issues, of course, but they might be
-acceptable in trade for avoiding explicit two-part
-instantiations.
-
-****************************************************************
-
-From: Tucker Taft
-Date: Saturday, October 20, 2007 11:01 AM
-
-Once you accept having two separate elaboration routines,
-one for the spec, and one for the body, I don't see this
-makes sharing more difficult. Furthermore, if we
-limit this capability to generics that have at least
-one formal type having unknown discriminants (which is
-related to what I suggested in my most recent response),
-this reduces the distributed overhead.
-
-****************************************************************
-
-From: Robert I. Eachus
-Date: Saturday, October 20, 2007 10:49 PM
-
->If we want a limited view, too, we could add syntax for that:
->
-> package Inst is new Gen(Priv) for export with limited;
->
->There can be no anomolies with the first form, because it has no semantic
->effect on the package: it simply makes a declaration in the private part
->visible from the outside of the package.
->
->The second form adds a limited view so that recursive data types can be
->created. I'd expect that to work roughly the same as regular limited view,
->so I think we've already covered the anomolies. (Famous last words... ;-) I
->realize this construct is a bit more limiting for Bob than some of the other
->proposals, but at least with it you can write the sort of things he wants to
->(as opposed to the current situation where it is nearly impossible).
-
-With my Norm Cohen Halloween costume on, and tongue very firmly in
-cheek, might I suggest:
-
- package Inst is not private new Gen(Priv) with limited;
-
-or if you prefer:
-
- not private package Inst is new Gen(Priv) with limited;
-
-What about making the limited view the default? Then you could say:
-
- not private package Inst is not limited new Gen(Priv);
-
-Am I being silly here? A bit. But the first case seems to map almost
-directly to the multiple private part model. As I see it, the problems
-there come from exporting types and declarations in the private part, by
-a renaming, derived type, or subtype in the generic package
-specification. In one sense we are trying to poke holes in the privacy
-screen, so it seems unfair to talk about unintended holes that a
-programmer can avoid. On the other hand, the Ada philosophy is to make
-such things explicit.
-
-So maybe we are looking in the wrong place. We know what we want: to be
-able to export generic instamces which are not child packages but can
-see into the private part. If we flag the generic for export in some
-way, it may be that we want to flag any otherwise private types,
-subprograms, or whatever that such a generic can make visible outside
-the private part.
-
-Taking off the Norm Cohen costume, something like:
-
-package Foo is
-
-
- type Bar is private;
-
- ...
-
-private
-
- export type Bar is....;
-
- export type FooBar is Bar with...;
-
- type Foob is ...;
-
- export package FuBar is new ...;
- -- can have Bar or FooBar as generic formals, but not Foob;
-
-end Foo;
-
-
-Seems to me we avoid most of the potential issues this way. Yes, you
-can use this mechanism to break privateness. But then again, unless
-someone is holding a gun, or the software equivalent, to the
-programmer's head, there is no requirement to make any particular type
-private, or to even have any private types at all.
-
-For the package FuBar, the export keyword (or whatever syntax is chosen)
-has semantic consequences: The visibility of the unit is increased.
-For non-generic objects, types, or subprograms, all the notation does is
-flag that they can be used in such quasi-public instantiations. Or you
-could take the view that it also expands the visibility: into the
-generic_actual_part of an exported generic instantiation.
-
-****************************************************************
-
-From: Randy Brukardt
-Date: Sunday, October 21, 2007 10:12 PM
-
-Tuck, we already have two elaboration routines. That's not the point; the
-point is that you can't elaborate the body at the point of the instance;
-you'd have to define some later point that occurred implicitly. But that
-idea was roundly disliked last time, and I can't imagine what's changed
-about that.
-
-Essentially, you are rehashing all of the ideas that we previously
-discarded. They didn't work two years ago and I don't know of anything
-that's changed since. For instance, there was a strong dislike for "implicit
-elaboration" at some later point, because a small change in a generic spec
-or in an instantiation can cause the semantics to change (and possibly
-break).
-
-Can we possibly go back to where we left off (which is what I was trying do)
-and not go through all of these discarded ideas??
-
-****************************************************************
-
-From: Randy Brukardt
-Date: Sunday, October 21, 2007 10:22 PM
-
-> > I think that there were problems with elaboration of the package
-> > specification. You can't actually do anything that would depend on the
-> > private type (because you don't yet know its declaration), so what you
-could
-> > put in the specification would be quite limited.
->
-> Can you elaborate on this? When you say "you can't actually do
-> anything" are you talking about the compiler or the
-> programmer?
-
-The programmer, mainly. There are a lot of restrictions on the usage of
-private types before the full definition, and none of those can be allowed
-in a generic that will be used in your scheme.
-
-> How is this different from a nested package at
-> the point of the partial instantiation, that refers to a
-> private type from the enclosing package?
-
-When you write a nested package, you do that while you design the rest of
-the package, and you can avoid (well, you have to avoid) doing anything that
-would be illegal with the private type.
-
-But with a generic, you are talking about a package that was designed
-separately, and may very well already exist. I don't think people are going
-to want to redesign all of their generics to work in this context.
-
-> It is true that in
-> both cases, you can't lay out any types declared in the nested
-> package that depend on the outer private types, but there is
-> no requirement to do so until you hit a freezing point. By
-> postponing the instantiation of the body, we hopefully postpone
-> the freezing points.
-
-Piece-meal freezing of generic units was rejected last time -- too much of
-an implementation earthquake.
-
-> > For Janus/Ada, we generate thunks at the point of the instantiation which
-> > are called by the elaboration. Those obviously assume that the full type
-> > definition is available. (We share the elaboration part of the specification
-> > in the same way that we share the body; if we were able to do real template
-> > expansion, we probably would have used that everywhere...)
->
-> I think you clearly would need to postpone generating some of the thunks,
-> and separate the elaboration into two routines, one for the spec
-> which would use only the thunks it really needed for the elaboration
-> of the spec, and one for the body, which would use the remaining thunks.
-
-There is only one generic descriptor, and I don't see any reason for more.
-The problem really is that there would be no way to prevent "early" calls to
-thunks that don't exist, so there would be many impossible-to-find bugs to
-deal with. (Our generics already have that problem, and I surely don't want
-to make it worse.)
-
-Remember that you can't make any calls (including those for thunks) until
-you've elaborated the generic. It's hard to imagine what you could do
-between the partial instantiation and the full one. (Yes, nested packages
-have this problem, too, Program_Error is raised by doing almost anything.
-That makes them not very useful.)
-
-> > The privacy breaking is uncomfortable, mainly because it could easily mean
-> > that generics like the containers may not be usable in specifications
-> > depending on their implementation. That suggests that we'd have to add a
-> > boatload of restrictions on how the private part is implemented (not
-> > allowing instantiation of the containers with a private type would be a
-> > non-starter, given that it is one of the problems that we need to fix). And
-> > I have to wonder what it would do to the IBM implementation.
->
-> I agree we might have to specify additional implementation requirements.
-> The most important would be that the generic must support partial
-> instantiation.
->
-> Secondarily, we would have to decide whether we want
-> to require that certain exported types not include the formal
-> types as subcomponents. My sense would be that we probably *don't*
-> want to impose this latter requirement on the "definite" versions,
-> so that "bounded" versions can be created that use no levels of
-> indirection. On the other hand, imposing this requirement on
-> the "indefinite" versions would seem reasonable, and actually
-> makes the "indefinite" versions that much more flexible.
-
-The scheme I was proposing needs none of this. The only thing that changes
-is that we have a new kind of partial instantiation.
-
-> I suppose this brings up another possibility, where we only
-> defer freezing an actual type if the corresponding formal type
-> has unknown discriminants. Since we know that a formal type
-> with unknown discriminants could *never* be a subcomponent of
-> an exported "definite" type, we eliminate the privacy breaking.
-> That has a nice ring to it...
->
-> I can even imagine we consider eliminating the need for two-part
-> instantiations, and make them "implicit" when there is a formal
-> type with unknown discriminants. That is, if a formal type
-> has unknown discriminants, then the freezing of the corresponding
-> actual type, and the body instantiation, is postponed
-> until the next "general" freezing point. That has some
-> upward compatibility issues, of course, but they might be
-> acceptable in trade for avoiding explicit two-part
-> instantiations.
-
-The implicit idea was roundly rejected in the past. Let's not keep rehashing
-the old stuff.
-
-****************************************************************
-
-From: Tucker Taft
-Date: Sunday, October 21, 2007 10:26 PM
-
-The proposal I have been talking about
-presumes there is a partial instantiation
-(I suggested the "with private" syntax),
-followed by a "full" instantiation.
-The spec elaboration(s) happen at the
-point of the partial instantiation,
-and the body elaboration(s) happen at the
-point of the full instantiation.
-
-Sorry if that wasn't clear.
-
-****************************************************************
-
-From: Randy Brukardt
-Date: Sunday, October 21, 2007 10:41 PM
-
-It was clear, but then you started talking about implicit instantiations and
-having different behavior for different kinds of formals. That certainly was
-discredited before.
-
-My recollection is that we talked about a model similar to the one you are
-proposing now and rejected it for some reason. But I don't recall the
-reason, and I'm too far behind on my work after the disk failure to spend
-time looking it up. (So I may just be spreading FUD, I hope not.)
-
-****************************************************************
-
-From: Tucker Taft
-Date: Sunday, October 21, 2007 11:03 PM
-
-Sorry if it feels like I am dragging you through
-the past. Sometimes new ideas turn up when you
-visit old ground again. Of the various
-musings I have uttered, the one that I think that
-*is* new and might be worth further investigation
-is as follows:
-
- 1) Allow "partial" instantiations *only* if
- at least one of the formal types is
- a formal type with unknown discriminants.
-
- 2) At the partial instantiation, freeze all
- actuals *except* the actuals corresponding
- to formals with unknown discriminants.
- Instantiate the spec, and only partially
- instantiate nested instantiations of
- generics with formals with unknown discrims.
-
- 3) At the full instantiation, freeze the actuals
- corresponding to formals with unknown discrims,
- then instantiate the bodies of any nested
- instantiations only partially instantiated
- thus far, and then instantiate the body of
- the "main" generic.
-
-This has the advantage that implementations need
-support partial instantiations only for a subset
-of generics, presuming there might be a higher distributed
-overhead to support partial instantiations on all
-generics. It also has the advantage that all actual
-types in a generic instance may still be presumed
-to be "pre-frozen," *unless* the formal has unknown
-discriminants. Furthermore, because formals with
-unknown discriminants cannot be used as components
-of other types, it is safe to use any type exported
-by the generic instance in the full definition of
-a private type passed as the actual, since it can't
-create a circularity.
-
-****************************************************************
-
-From: Robert A. Duff
-Date: Monday, October 22, 2007 8:25 AM
-
->... Furthermore, because formals with
-> unknown discriminants cannot be used as components
-> of other types, it is safe to use any type exported
-> by the generic instance in the full definition of
-> a private type passed as the actual, since it can't
-> create a circularity.
-
-Well, that seems to solve the problem, but it has some flaws.
-I'm not sure they're fatal flaws.
-
-It means I can create a Thing record containing a Vector of pointers to Things,
-either by passing a pointer to Vectors or by passing Thing to
-Indefinite_Vectors. But I can't create a Thing containing a pointer to a
-Vector of Things. It's bad enough that we force the programmer to introduce a
-level of indirection in order to have recursive types -- now we're telling them
-which place has to have the indirection.
-
-It's overkill -- you're forced to use a level of indirection even when there is
-no cycle, or else do the old-fashioned thing (make the instantiation a child).
-The usual: you can't do X because if you also did Y, then there would be
-trouble -- it's pretty annoying if you don't want to do Y.
-
-Maybe it's good enough. OTOH, I suppose we have several years to search for
-better solutions. ;-)
-
-****************************************************************
-
-From: Tucker Taft
-Date: Monday, October 22, 2007 9:00 AM
-
-If you are willing to insert the level of indirection
-explicitly using an access type, then you can create
-a thing that contains a pointer to a vector
-of things using an incomplete type:
-
-
- type Vector_Of_Things;
-
- type Thing is record
- Vec : access Vector_Of_Things;
- end record;
-
- package Thing_Vectors is new Vectors(Thing, ...);
- type Vector_Of_Things is new Thing_Vectors.Vector
- with null record;
-
-Is that adequate?
-
-****************************************************************
-
-From: Robert A. Duff
-Date: Monday, October 22, 2007 9:40 AM
-
-I'm confused. I thought we were talking about the case where Thing is private,
-and Thing_Vectors is exported from the package. So "new Vectors(Thing)" is
-illegal, since the formal does not have unknown discrims.
-
-****************************************************************
-
-From: Tucker Taft
-Date: Monday, October 22, 2007 10:19 AM
-
-Clearly the above can be in the private part, with a visible
-partial view of "Thing" declared in the visible part.
-But you are right that you can't also export Thing_Vectors
-in the above, except via the hypothetical "end private;"
-construct, which would immediately precede the instantiation.
-
-So you are right that the partial instantiation approach
-allows for indirection buried in the generic, whereas
-the "end private;" allows for indirection in the user's private
-type. You need both to allow for both.
-
-One could argue that it wouldn't be all bad for the language
-to make a choice, favoring one over the other. Or one
-could argue that the language should support both equally.
-Right now it supports neither, and if you want to create
-a mutually recursive combination approximating type and
-vector-of-type, then you are limited to type and vector
-of ptr-to-type.
-
-Randy is a big fan for burying access types inside abstractions,
-and the partial instantiation idea seems to be the only
-one so far that allows all uses of access types to be buried
-inside the container abstractions.
-
-The "end private;" seems more general, but it is roughly
-equivalent to using a child. The partial instantiation
-provides a capability that cannot be reproduced using a child.
-
-Seems like some tough choices.
-
-****************************************************************
-
-From: Randy Brukardt
-Date: Monday, October 22, 2007 6:56 PM
-
-> Sorry if it feels like I am dragging you through
-> the past. Sometimes new ideas turn up when you
-> visit old ground again. Of the various
-> musings I have uttered, the one that I think that
-> *is* new and might be worth further investigation
-> is as follows:
->
-> 1) Allow "partial" instantiations *only* if
-> at least one of the formal types is
-> a formal type with unknown discriminants.
-
-Yes, this is new.
-
-> 2) At the partial instantiation, freeze all
-> actuals *except* the actuals corresponding
-> to formals with unknown discriminants.
-> Instantiate the spec, and only partially
-> instantiate nested instantiations of
-> generics with formals with unknown discrims.
-
-But this is a variation of ideas that we could not get to work in the past.
-The problem was two-fold: implementation earthquakes for various models, and
-privacy violations. It's actually three-fold for this one, because partially
-instantiating nested instantiations means that where the body of those
-nested instantiations are elaborated would differ depending on how the
-instantiation is written. That seems bad: it's not uncommon to use an
-instantiation to get a body elaborated in a spec (Ada provides no other way
-to do that). So, given a generic like:
-
- generic
- type Foo (<>) is ...
- package Bar is
- package Nested is new <some generic> (Foo);
- subtype Bounds is Integer range 1 .. Nested.Func;
- end Bar;
-
-A partial instantiation of Bar would raise Program_Error on the call of
-Nested.Func (because the body is not elaborated) but would work correctly
-for a normal instantiation. That's unpleasant.
-
-> 3) At the full instantiation, freeze the actuals
-> corresponding to formals with unknown discrims,
-> then instantiate the bodies of any nested
-> instantiations only partially instantiated
-> thus far, and then instantiate the body of
-> the "main" generic.
->
-> This has the advantage that implementations need
-> support partial instantiations only for a subset
-> of generics, presuming there might be a higher distributed
-> overhead to support partial instantiations on all
-> generics.
-
-I don't think that this would be very useful in simplifying the
-implementation, but of course I can't say how it would work for other
-implementers.
-
-> It also has the advantage that all actual
-> types in a generic instance may still be presumed
-> to be "pre-frozen," *unless* the formal has unknown
-> discriminants. Furthermore, because formals with
-> unknown discriminants cannot be used as components
-> of other types, it is safe to use any type exported
-> by the generic instance in the full definition of
-> a private type passed as the actual, since it can't
-> create a circularity.
-
-But the real problem is that you haven't addressed the anomalies that Steve
-and Erhard pointed out the last time we discussed this (and that effectively
-killed it). The problem was that a lot of partially defined stuff
-potentially gets exported from a partial view, and this goes beyond the
-sorts of things that we currently have to deal with.
-
-My personal opinion is that the "partial instantiation" (versus a "limited
-instantiation") is never going to work. I've been trying to make the
-"limited instantiation" more acceptable, but I haven't gotten any real
-feedback from you.
-
-I realize that some people don't like the idea for some reason; what I'd
-like to find out is what about the proposal is disliked so that it can be
-enhanced. (I'm convinced that it would be best to start with a mechanism
-that works and would not clobber implementers, and then see if we can safely
-extend it to be more powerful.)
-
----
-
-To summarize the latest idea again:
-
- exported_generic_instantiation ::=
- generic_instantiation [for export [with limited view]];
-
-An exported_generic_instantiation shall be given in the visible part of a
-package specification. An exported_generic_instantiation has to have a
-completion in the private part of the same package specification. The
-completion has to conform [I believe we have worked out rules for that in
-the past].
-
-The elaboration of an exported_generic_instantiation has no effect.
-
-For a reference to the reference to the defining_program_unit_name of an
-exported_generic_instantiation:
-
-* If the reference is within the package specification that contains the
-exported_generic_instantiation (and before the completing
-generic_instantiation):
- If the reserved words "with limited" do not appear, then the reference
-is illegal;
- If the reserved words "with limited" do appear, then the reference
-denotes the limited view of the package created by expanding the generic
-unit [Unfortunately, we can't just say the "limited view of the
-instantiation", because that is empty. Better wording will be needed].
-
-* Otherwise, the reference denotes the completing generic_instantiation.
-(The fact that that instantiation is in the private part is ignored.)
-
----
-
-This formulation has no elaboration or freezing issues, which were the major
-stumbling blocks in the past attempts. (Uses outside the package are
-allowed, because all of the elaboration and freezing has to already have
-happened.) The only flaw that I can see is that it isn't as intuitive as it
-could be, and I blame that mostly on the syntax and terminology. Perhaps
-there is a way to make it more intuitive without bringing in all of the
-problem areas.
-
-Here's an example:
-
- package Something is
- type Priv is tagged private;
- package Priv_Lists is new Ada.Containers.Doubly_Linked_Lists (Priv)
-for export;
- ... -- Use of Priv_Lists here is illegal.
- private
- type Priv is ...
- package Priv_Lists is new Ada.Containers.Doubly_Linked_Lists (Priv);
- end Something;
-
- with Something;
- procedure Do_It is
- PList : Something.Priv_Lists.Container; -- This is allowed.
- begin
- ...
- end Do_It;
-
-And an example for Bob:
-
- package Something_Else is
- type Node is tagged private;
- package Node_Lists is new
- Ada.Containers.Doubly_Linked_Lists (Node) for export with
-limited view;
- ...
- private
- type Node is tagged record
- Parent : access Node;
- Children : access Node_Lists.Container; -- "Recursive" definition.
- Siblings : access Node_Lists.Container;
- ...
- end record;
- package Node_Lists is new Ada.Containers.Doubly_Linked_Lists (Node);
- end Something_Else;
-
-****************************************************************
-
-From: Randy Brukardt
-Date: Monday, October 22, 2007 7:09 PM
-
-...
-> It means I can create a Thing record containing a Vector of pointers to Things,
-> either by passing a pointer to Vectors or by passing Thing to
-> Indefinite_Vectors. But I can't create a Thing containing a pointer to a
-> Vector of Things. It's bad enough that we force the programmer to introduce a
-> level of indirection in order to have recursive types -- now we're telling them
-> which place has to have the indirection.
-
-Careful here: by wanting too much the last time, you caused us to look for
-other solutions; and the net effect is that you got none. (That may have
-been because of a mis-interpretation of your comments, but it surely
-happened.)
-
-I think the most important thing is that you can write a private type that
-uses the containers recursively. You can't currently do that in any way at
-all in Ada, and that is clearly bad. But the most important thing is that
-there is a way; obsessing over having the perfect way probably will lead
-back to where we are now. (The only way that won't happen is if several
-implementers drop out of the ARG, removing their objections to proposals
-that have split freezing or elaboration. But then there probably won't be a
-need for future Ada standards...)
-
-Of course, we should try to make this as usable as possible, but we have to
-be careful to avoid making "best" the enemy of "better" to the point where
-we end up with "not-at-all".
-
-****************************************************************
-
-From: Randy Brukardt
-Date: Monday, October 22, 2007 7:17 PM
-
-> I'm confused. I thought we were talking about the case where Thing is private,
-> and Thing_Vectors is exported from the package. So "new Vectors(Thing)" is
-> illegal, since the formal does not have unknown discrims.
-
-Humm, I think my current proposal solves this problem:
-
- package Bob is
- type Thing is private;
- package Thing_Vectors is new Vectors(Thing, ...) for export with limited view;
- private
- type Thing is record
- Vec : access Thing_Vectors.Vector;
- end record;
- end Bob;
-
-There are only two problems worth solving here:
- (1) The "Duff" problem of using a container of a type within the type itself;
- (2) The "Signature" problem of exporting a generic instantiation of private types.
-
-My proposal has solved both of these, and introduces no new dynamic
-semantics [which is where the problem was]. (Other than possibly a
-conformance check.) The implementation of the visibility changes appear to
-be minor (pointing the exported instance at the full one for external usage
-seems trivial - of course, you can't reason about other people's compilers).
-What's not to like?? ;-)
-
-****************************************************************
-
-From: Robert A. Duff
-Date: Monday, October 22, 2007 8:00 PM
-
-> Careful here: by wanting too much the last time, you caused us to look for
-> other solutions; and the net effect is that you got none. ...
-
-Understood. There seems to be no perfect solution. So let's be honest about
-the drawbacks of each, but not let those drawbacks paralyze us.
-
-****************************************************************
-
-From: Tucker Taft
-Date: Monday, October 22, 2007 8:53 PM
-
-> But this is a variation of ideas that we could not get to work in the past.
-> The problem was two-fold: implementation earthquakes for various models, and
-> privacy violations. It's actually three-fold for this one, because partially
-> instantiating nested instantiations means that where the body of those
-> nested instantiations are elaborated would differ depending on how the
-> instantiation is written. That seems bad: it's not uncommon to use an
-> instantiation to get a body elaborated in a spec (Ada provides no other way
-> to do that). So, given a generic like:
->
-> generic
-> type Foo (<>) is ...
-> package Bar is
-> package Nested is new <some generic> (Foo);
-> subtype Bounds is Integer range 1 .. Nested.Func;
-> end Bar;
->
-> A partial instantiation of Bar would raise Program_Error on the call of
-> Nested.Func (because the body is not elaborated) but would work correctly
-> for a normal instantiation. That's unpleasant.
-
-If we were to take this approach, then the implementor
-of a generic that had a formal type with unknown
-discriminants would have to decide whether or not
-to support partial instantiations. If they intended
-to support a partial instantiation, then they would
-clearly have to test it with one. I think formals
-with unknown discriminants are rare enough that
-that wouldn't be an undue burden.
-
-In general, nested instantiations are pretty
-rare, and nested instantiations that pass
-a formal type with unknown discriminants are
-even rarer, and nested instantiations where
-one takes advantage of immediate elaboration
-of the body to make a call are even rarer still.
-If this very rare generic turns out to be
-something where it would be useful to support
-instantiations with a private type, then having
-to redesign it a bit for that purpose seems reasonable.
-
->> 3) At the full instantiation, freeze the actuals
->> corresponding to formals with unknown discrims,
->> then instantiate the bodies of any nested
->> instantiations only partially instantiated
->> thus far, and then instantiate the body of
->> the "main" generic.
->>
-> ...
->> It also has the advantage that all actual
->> types in a generic instance may still be presumed
->> to be "pre-frozen," *unless* the formal has unknown
->> discriminants. Furthermore, because formals with
->> unknown discriminants cannot be used as components
->> of other types, it is safe to use any type exported
->> by the generic instance in the full definition of
->> a private type passed as the actual, since it can't
->> create a circularity.
->
-> But the real problem is that you haven't addressed the anomalies that Steve
-> and Erhard pointed out the last time we discussed this (and that effectively
-> killed it). The problem was that a lot of partially defined stuff
-> potentially gets exported from a partial view, and this goes beyond the
-> sorts of things that we currently have to deal with.
-
-Can you elaborate on this? I don't think anything is partially
-defined. Some bodies aren't elaborated, but that is no
-surprise in a package spec. Most bodies aren't elaborated
-in a package spec.
-
-Despite surface similarities, I think the problems Erhard and Steve were
-talking about don't apply to this proposal. In the earlier
-proposal, we were trying to prevent the partial instantiation
-from freezing *anything*. In the proposal we are discussing
-here, the only thing that is special is that the actual
-types that are associated with formal types with unknown
-discriminants are not "pre-frozen." But if they get used
-in a spec in a way that would normally require freezing,
-then they get frozen. The spec is expanded with completely
-"normal" semantics. What gets postponed is the instantiation
-(and elaboration) of the body, and the freezing of certain
-actuals.
-
-If I am wrong about this, it would be helpful if you could
-identify which variant of AI-359 you think this most recent
-proposal matches, and which ARG meeting Erhard and Steve
-found the flaws. I just looked at a bunch of minutes, and
-they all seemed to be concerned with proposals where we
-were trying to defer all freezing, or make everything into
-a partial view, or defer all elaboration, rather than
-just the elaboration of the body. September 2004 in Madison
-seemed to be the one you were probably remembering.
-
-Unless I am mistaken, we never discussed
-a proposal where the partial instantiation
-did all the usual things associated with the instantiation
-of a spec, creating full types, etc., with the only change
-being that we eliminated the pre-freezing of a subset of
-the actuals, and deferred the instantiation of the body.
-
-> My personal opinion is that the "partial instantiation" (versus a "limited
-> instantiation") is never going to work. I've been trying to make the
-> "limited instantiation" more acceptable, but I haven't gotten any real
-> feedback from you.
->
-> I realize that some people don't like the idea for some reason; what I'd
-> like to find out is what about the proposal is disliked so that it can be
-> enhanced. (I'm convinced that it would be best to start with a mechanism
-> that works and would not clobber implementers, and then see if we can safely
-> extend it to be more powerful.)
-
-I felt that it was useful to try to come up with a proposal
-that did *not* require the explicit use of access types.
-
-Your proposal is providing only incomplete types, since it is
-providing only a limited view of the instance from within
-the package. Hence access types must be used in any reference
-to types declared in the package. That is annoying if the
-generic already introduces a level of indirection, and
-has a bunch of code to ensure leak-free storage management.
-The client can't take advantage of that when only given
-incomplete types.
-
-If all that we get are incomplete types, then I guess
-I prefer the generality of the "end private;" over the
-unique and somewhat counter-intuitive semantics of
-the "limited internal view" approach.
-
-As far as a specific comment on the limited internal
-view idea, syntactically, I would stick with something simple
-like "package I is limited new ..." for now, always
-provide the limited view internally, and save the
-Norm-Cohen-string-of-reserved-words for late nights
-at the bar after ARG meetings. ;-)
-
-****************************************************************
-
-From: Randy Brukardt
-Date: Monday, October 22, 2007 9:46 PM
-
-...
-> > But the real problem is that you haven't addressed the anomalies that Steve
-> > and Erhard pointed out the last time we discussed this (and that effectively
-> > killed it). The problem was that a lot of partially defined stuff
-> > potentially gets exported from a partial view, and this goes beyond the
-> > sorts of things that we currently have to deal with.
->
-> Can you elaborate on this? I don't think anything is partially
-> defined. Some bodies aren't elaborated, but that is no
-> surprise in a package spec. Most bodies aren't elaborated
-> in a package spec.
-
-Please read the Atlanta minutes.
-
-> Despite surface similarities, I think the problems Erhard and Steve were
-> talking about don't apply to this proposal. In the earlier
-> proposal, we were trying to prevent the partial instantiation
-> from freezing *anything*. In the proposal we are discussing
-> here, the only thing that is special is that the actual
-> types that are associated with formal types with unknown
-> discriminants are not "pre-frozen." But if they get used
-> in a spec in a way that would normally require freezing,
-> then they get frozen. The spec is expanded with completely
-> "normal" semantics. What gets postponed is the instantiation
-> (and elaboration) of the body, and the freezing of certain
-> actuals.
-
-Quoting from the Atlanta minutes:
-
-"Tucker has changed the freezing rules to require freezing at the end of an
-instance and then have piecemeal instantiation. This is necessary so a type
-can contain a component of its own type. Pascal objects that this is a
-change that we had previously agreed to not make. Randy agrees; he notes
-that it is privacy breaking. Pascal says that piecemeal freezing is a dead
-boy issue. He continues that the important issue is to solve the export of
-containers from specs of private types. Tucker notes also that the signature
-package problem is also covered even without piecemeal freezing. Randy notes
-that we could still allow this in 2015 if it actually proves to be
-important."
-
-And now you are reintroducing this again - some ideas just never die.
-
-> If I am wrong about this, it would be helpful if you could
-> identify which variant of AI-359 you think this most recent
-> proposal matches, and which ARG meeting Erhard and Steve
-> found the flaws. I just looked at a bunch of minutes, and
-> they all seemed to be concerned with proposals where we
-> were trying to defer all freezing, or make everything into
-> a partial view, or defer all elaboration, rather than
-> just the elaboration of the body. September 2004 in Madison
-> seemed to be the one you were probably remembering.
-
-Then we started having problems with things exported from the instantiation.
-The solution (as I see it as least) is to not export so much. You seem to
-see the solution as to defer freezing and break privacy.
-
-> Unless I am mistaken, we never discussed
-> a proposal where the partial instantiation
-> did all the usual things associated with the instantiation
-> of a spec, creating full types, etc., with the only change
-> being that we eliminated the pre-freezing of a subset of
-> the actuals, and deferred the instantiation of the body.
-
-No we didn't. But you again are talking about partial freezing and privacy
-breaking, and that was a non-starter in the past. We need proposals that
-don't have those properties, not more of the same.
-
-Moreover, I'm not very interested in a proposal that will only work with a
-few "special" generics. The standard definite (and presumably bounded)
-containers will not work with this proposal. So some users (safety-critical,
-for instance) seem to be out of luck. Similarly, the majority of existing
-generics don't have formals with unknown discriminants; you want everyone to
-rewrite their generics. Yuck.
-
-> > My personal opinion is that the "partial instantiation" (versus a "limited
-> > instantiation") is never going to work. I've been trying to make the
-> > "limited instantiation" more acceptable, but I haven't gotten any real
-> > feedback from you.
-> >
-> > I realize that some people don't like the idea for some reason; what I'd
-> > like to find out is what about the proposal is disliked so that it can be
-> > enhanced. (I'm convinced that it would be best to start with a mechanism
-> > that works and would not clobber implementers, and then see if we can safely
-> > extend it to be more powerful.)
->
-> I felt that it was useful to try to come up with a proposal
-> that did *not* require the explicit use of access types.
->
-> Your proposal is providing only incomplete types, since it is
-> providing only a limited view of the instance from within
-> the package. Hence access types must be used in any reference
-> to types declared in the package. That is annoying if the
-> generic already introduces a level of indirection, and
-> has a bunch of code to ensure leak-free storage management.
-> The client can't take advantage of that when only given
-> incomplete types.
-
-The client *shouldn't* be able to take advantage of the private
-implementation of a generic unit: that's privacy breaking. One could argue
-that it would be nice to take advantage of a visible use of indirection --
-but that's pretty unlikely in a well-designed generic. It doesn't seem worth
-a lot of implementation pain to provide that capability.
-
-To really allow this, I think it would have to be declared in the contract
-of the generic somehow. (No, unknown discriminants does not do that, as
-there would usually not be any objects at all. And they're too limiting in
-any case.) And clearly it would have to be enforced end-to-end.
-
-> If all that we get are incomplete types, then I guess
-> I prefer the generality of the "end private;" over the
-> unique and somewhat counter-intuitive semantics of
-> the "limited internal view" approach.
-
-The problem is that is way too general, and certainly will introduce new
-anomalies. (I can only imagine what the effect on visibility in public
-children would be.) Moreover, the 0 or 1 or infinite rule implies that we
-would need to add an unlimited number of these new parts -- and visibility
-changes are always an implementation earthquake. It also scatters the
-visible declarations all over, and forces them into a particular order,
-which may not be logical (forcing the instances very late, for example).
-
-It would make just as much sense to follow Robert Eachus' suggestion and
-allow individual declarations to be made visible or hidden from clients
-(making the private part an obsolescent feature). Then we could be sure that
-the earthquake would be complete but also that we wouldn't be forcing any
-ugly constructs on people.
-
-> As far as a specific comment on the limited internal
-> view idea, syntactically, I would stick with something simple
-> like "package I is limited new ..." for now, always
-> provide the limited view internally, and save the
-> Norm-Cohen-string-of-reserved-words for late nights
-> at the bar after ARG meetings. ;-)
-
-I think you miss the point: the critical use is to allow signatures and
-containers to be instantiated visibly. The syntax needs to reflect that
-somehow, and "is limited" doesn't do that (in fact, it seems to imply that
-client use is restricted, when the exact opposite is true). Think of what a
-client of a package would see if they don't peek in the private part.
-
-The Bob Duff use for recursive data types is likely to be rare, and I didn't
-want the syntax to emphasize that use (which is irrelevant for clients
-anyway). (If that was the only problem, I would have been in favor of "No
-Action" from the beginning.)
-
-That said, people will get used to anything, so I don't care that much what
-the syntax is.
-
-****************************************************************
-
-From: Tucker Taft
-Date: Monday, October 22, 2007 10:13 PM
-
-> Quoting from the Atlanta minutes:
->
-> "Tucker has changed the freezing rules to require freezing at the end of an
-> instance and then have piecemeal instantiation. This is necessary so a type
-> can contain a component of its own type. Pascal objects that this is a
-> change that we had previously agreed to not make. Randy agrees; he notes
-> that it is privacy breaking. Pascal says that piecemeal freezing is a dead
-> boy issue. He continues that the important issue is to solve the export of
-> containers from specs of private types. Tucker notes also that the signature
-> package problem is also covered even without piecemeal freezing. Randy notes
-> that we could still allow this in 2015 if it actually proves to be
-> important."
->
-> And now you are reintroducing this again - some ideas just never die.
-
-It may *sound* the same, but it really isn't. This is
-not the same as the "piecemeal" freezing we discussed.
-Also, the privacy breaking is dramatically reduced if you limit
-this to formal types with unknown discriminants, since they
-can't be used as components anyway. By eliminating this
-issue, the breakage doesn't seem any worse than the various other
-legality rules that are checked in the private parts of
-instances.
-
-In any case, I can see that at least *you* aren't interested
-in this proposal, even if I can convince you that it really
-*is* new. ;-) It felt like a step forward to me...
-
-****************************************************************
-
-From: Jean-Pierre Rosen
-Date: Wednesday, October 24, 2007 11:06 AM
-
-I've been following this thread, and I must say I am worried by the
-complexity, from a user's point of view, of all the solutions presented.
-
-In short: only members of the ARG will be able to use that. Casual users
-already know very few about the real possibilities of the language (OK,
-that's what makes our business as consultants). I doubt that they will
-find out the appropriate spell if they want to instantiate a generic on
-a private type (the real need).
-
-The only acceptable solution is to allow:
-
-with Gen;
-package pack is
- type T is private;
-
- package Inst is new Gen (T);
-
-and nothing else. Can it be done? For example, decide that in this case
-actual instantiation does not happen logically at the place where it is
-declared, but immediately after the full declaration of T. But of course
-the visibility of the instantiation would be public. No use of the
-instance would be allowed until it is "logically" instantiated.
-
-Am I pipe-dreaming here?
-
-****************************************************************
-
-From: Edmond Schonberg
-Date: Wednesday, October 24, 2007 2:06 PM
-
-> I've been following this thread, and I must say I am worried by the
-> complexity, from a user's point of view, of all the solutions
-> presented.
-
-You can add: "and from the implementor's point of view".
-
->
-> In short: only members of the ARG will be able to use that. Casual
-> users already know very few about the real possibilities of the
-> language (OK, that's what makes our business as consultants). I
-> doubt that they will find out the appropriate spell if they want to
-> instantiate a generic on a private type (the real need).
->
-> The only acceptable solution is to allow:
->
-> with Gen;
-> package pack is
-> type T is private;
->
-> package Inst is new Gen (T);
->
-> and nothing else. Can it be done? For example, decide that in this
-> case actual instantiation does not happen logically at the place
-> where it is declared, but immediately after the full declaration of
-> T. But of course the visibility of the instantiation would be
-> public. No use of the instance would be allowed until it is
-> "logically" instantiated.
-
-I agree that for a new language design the only reasonable solution
-would be to allow types with only partial views to appear as actuals.
-However, as was mentioned repeatedly, any change to the freezing
-rules is extremely disruptive. It is nothing we would be willing to
-do without a very VERY strong user demand, and that is at present
-totally absent. If Ada2005 programmers start using containers in
-more ambitious forms maybe they will find it convenient to have the
-premature instantiations that have motivated this AI. In the
-meantime, there is no harm in exploring other designs, but we may
-have more pressing things to fix.
-
-****************************************************************
-
-From: Tucker Taft
-Date: Wednesday, October 24, 2007 2:19 PM
-
-I agree, simplicity is important. But it is
-always dangerous to guess at the simplicity of
-the final result based on the complexity of
-the discussion leading up to it. There
-is often no correlation (either way ;-).
-
-I think the "end private;" idea is pretty
-simple from the user perspective, but
-I also agree we need to have a complex
-discussion about what it really means
-from a detailed visibility point of view,
-so that it has the right "intuitive" semantics
-from the user point of view.
-
-I also think Randy's idea could appear as
-simple to a user, so long as the syntax is kept
-very simple. I like using the word
-"limited" or the phrase "with private" since both
-of those suggest what it going on, as in:
-
- package Inst is limited new Gen (T);
-or
- package Inst is new Gen(T) with private;
-
-followed by a full normal instantiation
-in the private part, after the full
-definition of T.
-
- private
- type T is ...
- package Inst is new Gen(T);
-
-This seems relatively simple, and the
-partial instantiation syntax is relatively
-familiar from either the new "limited new ..." syntax
-on type derivation (for the first syntax), or
-private extensions (for the second syntax).
-I can't see adding a bunch of new
-keywords for this relatively simple
-idea.
-
-I also don't see sufficient benefit to have two
-variants, one that makes a limited view of
-the instance visible prior to the full
-instantiation, and one that doesn't.
-
-I think I understand Randy's reasons for
-the new keywords and the two variants, but
-the cost/benefit ratio is too high for
-both in my view. "Limited" already has
-multiple meanings, and so we can choose how
-we want to define a "limited" instantiation,
-and saying that it provides only incomplete
-types prior to the full instantiation
-seems reasonable. Essentially, the instance
-is "incompletely defined" prior to the full
-instantiation, in the same way a private
-type is incompletely defined prior to the
-full type definition.
-
-Similarly, "with private" currently means
-"partial view of an extension"
-so it could also mean "partial view of
-an instantiation" (and along the way,
-"with private" is suggestive of the
-fact that the actual parameter part can
-include one or more private types).
-
-I suspect that users could grasp either
-pretty quickly.
-
-As far as not having a distinct syntax for
-the partial instantiation, we have discussed
-something very close to that proposal in the
-past, where the fact that one of the actuals
-is not fully defined automatically causes a
-different interpretation. Unfortunately, the complexity
-of the discussion was astronomical, and
-ultimately we abandoned it, despite its
-apparent simplicity from a user point of view.
-
-So I think we actually have two reasonable
-suggestions, one involving partial instantiations
-and one allowing multiple visible parts.
-If the syntax is chosen carefully, I think
-either one of these could pass the simplicity
-test. Even "normal" users already understand there
-are limits on how a private type can be
-used prior to its full definition.
-
-So please keep pushing simplicity, but don't
-prejudge based on the complexity of the discussion.
-Try to block out the whole ARG discussion, and decide
-whether the final result could have a reasonable syntax
-and relatively intuitive semantics.
-
-****************************************************************
-
-From: Randy Brukardt
-Date: Wednesday, October 24, 2007 2:28 PM
-
-> The only acceptable solution is to allow:
->
-> with Gen;
-> package pack is
-> type T is private;
->
-> package Inst is new Gen (T);
->
-> and nothing else. Can it be done?
-
-In short, no. ;-) It shouldn't be a surprise that complex problems require
-complex solutions -- or, for that matter, that two part declarations also
-require two-part instances (just like using a private type in a subprogram
-in the spec requires the body of the subprogram to be elsewhere).
-
-> For example, decide that in this case
-> actual instantiation does not happen logically at the place where it is
-> declared, but immediately after the full declaration of T. But of course
-> the visibility of the instantiation would be public. No use of the
-> instance would be allowed until it is "logically" instantiated.
->
-> Am I pipe-dreaming here?
-
-It's hard to tell for sure, but I think you are.
-
-(1) This does not solve the "Duff" problem of using "list of T" (and other
-data structures) inside of T. You can do that with the built-in data
-structures of Ada; it is unfortunate that you can't do it with containers. I
-don't think this is the most important issue by far, but it is surely
-important.
-
-(2) There is a maintenance hazard here, as changing the specification of the
-generic or of the package would change where the generic instantiation
-actually occurs. This isn't as bad as in some of the other proposals (in
-this case, you'd get a compile-time error if there was a problem), but it
-still is an issue. [There also might be issues if the instantiation was
-mainly used for a side-effect of its elaboration, moving that elaboration
-could cause problems. But such code is tricky anyway, so I can't get too
-worried.]
-
-One of the reasons for the two-part instantiation is so that the location of
-the "real" instantiation is obvious in the source code. That eliminates this
-maintenance hazard.
-
-(3) You don't specify in which cases this magic happens. Does it happen with
-all generics, or just a special subset. Assuming it happens with all
-generics, when do the other generic parameters (those not dependent on
-private types) get evaluated? Either answer seems bad in some cases.
-
-(4) Someone had suggested an idea on this line (not exactly this idea) back
-in 2004. It eventually was dropped because of various problems.
-
-The net effect is that I don't think this works. To solve (1), you have to
-complicate the freezing and elaboration rules and allow partial exporting of
-the contents of the generic. (Essentially what Tucker was trying to do.)
-Which has been roundly rejected in the past, as it increases the maintenance
-hazard and implementation complications.
-
-I understand your concern about complexity for the user. I don't think it is
-too bad, as compilers and mentors can recommend the "magic incantation" of
-adding a limited instance when it is needed -- and there are plenty of other
-examples of two-part declarations in Ada (a user who is surprised by that is
-a real newbie). Still it is fair to have the opinion that the solutions are
-complex enough that it is not worth solving the problem at all. (This is not
-an opinion that I share!)
-
-I do think that all of these solutions look more complex when described in
-detail than they would in actual use. (Which includes your proposal above,
-if it was described to the same level of detail.) We don't get to handwave
-the details, because the devil is always in the details. My main concern has
-been that the syntax of the limited instance (or partial instance, for that
-matter) doesn't really intuitively describe what is going on. Which is why I
-was trying more complex syntaxes that hopefully made more sense when reading
-(but Tucker didn't seem to agree, and I guess you don't either).
-
-****************************************************************
-
-From: John Barnes
-Date: Tuesday, October 30, 2007 2:32 AM
-
->> ...In these
->> discussions, I have harbored a personal dislike for the
->> idea of multiple private parts in a single package,
->> but I haven't had a good reason other than aesthetic.
->> But this to me seems like a good reason.
->
-> Agreed. I find vague aesthetics much more convincing when backed up by good
-> reasons!
-
-Is it not the case that a child package essentially opens the visible part
-of the parent once more but after the private part? Is there the essence of
-a solution here? Maybe it was discussed before. I recall we did once
-consider using child packages as one of the options when discussing cyclic
-packages.
-
-****************************************************************
-
-From: Tucker Taft
-Date: Tuesday, October 30, 2007 8:12 AM
-
-In choosing semantics for a post-private visible
-part, I have suggested we use the visible part of
-a child as a model.
-
-I also suggested in a separate note of having
-a way to specify that a given child is to
-be implicitly "with"ed by all units that "with"
-the parent. I had suggested "end with Parent.Child;"
-but no one liked that syntax. Somewhat better might
-be "at end with ...", e.g.:
-
- at end with Parent.Child1, Parent.Child2, ...;
- package Parent is ...
- ...
- end Parent;
-
-or conceivably:
-
- package Parent is
- ...
- private
- ...
- end Parent with Parent.Child1, Parent.Child2;
-
-These give you the ability to have a child that provides
-an instantiation that will appear to clients of Parent
-to be included inside Parent, but they don't give you any ability
-to use that instantiation before the end of the parent package.
-You would still need to be able to insert some declarations
-after establishing visibility on the child packages,
-if you want to use the instantiations to help define
-one of the types exported from the parent package.
-Given that, it seems simpler to just use a post-private
-visible part to both specify the instantiations
-needed, as well as any additional declarations that
-link the instantiations up to types exported from
-the package.
-
-****************************************************************
-
-From: Robert I. Eachus
-Date: Friday, November 2, 2007 10:26 AM
-
->of the parent once more but after the private part? Is there the essence of
->a solution here? Maybe it was discussed before. I recall we did once
->consider using child packages as one of the options when discussing cyclic
->packages.
->
->
-I think we need a solution which is as simple as possible (but not
-simpler). Effectively splitting a package specification into two parts
-is not really a solution, or if it is, there is no work to be done:
-
-package Private_Type is
- type PT is private;
- ...
-private
- ...
-end Private_Type;
-
-package Private_Type.Child is
- subtype SPT is PT;
- package Container is new ...
-end Private_Type.Child;
-
-package To_Be_Withed renames Private_Type.Child:
-
-Three separate compliation units, plus one or two bodies, but it does
-the trick. If this solution is sufficient, fine. If not, the need is
-for a simpler solution not one that is more complex even if more
-general. I think that limits the possibilities to three:
-
-1. Change the rules so that a generic package declaration with a formal
-parameter of a private type does not cause freezing of the private
-type--but any use of the generic instance does. Second, allow the
-instantiation of the body of the generic package to be deferred until
-some point in the private part. (At the end is probably simplest. But
-that forces any renamings of operations of the package to be done in the
-body of the package.)
-
-This does lead to complexities for implementors and language lawyers,
-but ordinary users can just do what seems natural.
-
-2. Have a new syntax which allows for two part instantiation of a
-generic package. This would seem to have all the complexities of the
-above solution, and be less simple for users. But it would mean no
-changes to existing legal programs.
-
-3. Allow end private, but only followed by generic instantiations (and
-only one private part). Again, renaming of operations gets pushed to
-the package body.
-
-****************************************************************
-
-From: Jean-Pierre Rosen
-Date: Friday, November 2, 2007 1:09 PM
-
-> I think we need a solution which is as simple as possible (but not
-> simpler). Effectively splitting a package specification into two parts
-> is not really a solution, or if it is, there is no work to be done:
-
-Agreed
-
-> package Private_Type is
-> type PT is private;
-> ...
-> private
-> ...
-> end Private_Type;
->
-> package Private_Type.Child is
-> subtype SPT is PT;
-> package Container is new ...
-> end Private_Type.Child;
-
-Why not:
- package Private_Type.Container is new...
->
-> package To_Be_Withed renames Private_Type.Child:
-
-Why do we need this?
-
-If the only issue is that the user needs to "with" several children, we
-may introduce a "with all Pack" clause that would "with" pack and all
-children that are part of the environment.
-
-****************************************************************
Questions? Ask the ACAA Technical Agent