CVS difference for ais/ai-10217.txt

Differences between 1.5 and version 1.6
Log of other versions for file ais/ai-10217.txt

--- ais/ai-10217.txt	2001/09/19 00:04:39	1.5
+++ ais/ai-10217.txt	2001/09/21 04:07:45	1.6
@@ -4160,563 +4160,7 @@
    no problems with library-based implementations
    no new syntax unless we want it (we probably do).
 
-*************************************************************
-
-From: Randy Brukardt
-Sent: Tuesday, July 3, 2001, 6:14 PM
-
-Re: Dan Eiler's proposal.
-
-I'm quite surprised that no one seriously has looked at this proposal. It seems
-to me that it eliminates some of the problems of the abstract package and
-simplifies it a lot without necessarily losing the important features.
-
-The basic proposal is to introduce a new kind of incomplete type that NEVER
-needs to be completed. It would have syntax like (Dan used pragmas, but they're
-really ugly for something that will be commonly used):
-
-    type <Defining_Identifier> is separate;
-    type <Defining_Identifier> is tagged separate;
-
-The rules for packages would be unchanged. The tagged kind of separate
-incomplete type would allow 'Class and use as the type name in parameter
-declarations (but not function returns).
-
-My immediate reaction was that this would be hard to implement. But, on further
-reflection, I realized that as long as the incomplete rules were enforced
-everywhere that the incomplete type is visible, the compiler NEVER needs to
-know the real type involved. Moreover, this type could not be used in an
-allocator or a generic, so we would get the restrictions we need for free.
-(And it is rather like an incomplete type deferred to a body, for which the
-compiler can't assume anything anyway.)
-
-The completion would include a new clause in the type declaration:
-
-    type <Defining_Identifier> [completion_clause] ...
-
-    completion_clause ::= for <type_name>
-
-[I'd rather use "completes" here, but that would introduce a new reserved word.
-I also looked at "declare" for this use, but it reads funny. I'm sure someone
-will have nifty syntax for this.]
-
-There would be a post-compilation check that all "is separate" types are
-completed exactly once. (I don't think that there is any benefit to allowing
-multiple completions, because the types have to be considered the same in some
-scopes, and that could lead to a situation where A = P and B = P, but A /= B.)
-
-To recast Dan's example (fixing a couple of errors):
-
-    package Partial_Definitions is
-       type Employee is separate;
-       type Emp_Ptr is access all Employee;
-
-       type Department is separate;
-       type Dept_Ptr is access all Department;
-   end Partial_Definitions;
-
-   with Partial_Definitions;
-   package Employees is
-       type Employee for Partial_Definitions.Employee is private;
-       type Emp_Ptr is access all Employee;
-       procedure Assign_Employee(E : access Employee;
-          D : access Partial_Definitions.Department);
-        ...
-       function Current_Department(D : access constant
-          Employee) return Partial_Definitions.Dept_Ptr;
-   end Employees;
-
-   with Partial_Definitions;
-   package Departments is
-       type Department for Partial_Definitions.Department is private;
-       type Dept_Ptr is access all Department;
-       procedure Choose_Manager(D : access Department;
-          Manager : access Partial_Definitions.Employee);
-        ...
-   end Departments;
-
-
-Now to look at the possible problems:
-
-Determining the representation of Partial_Definitions.Emp_Ptr would be a
-problem for some implementations that select the representation of an access
-type based on the designated type. However, this would be no different than
-doing that for a type whose completion is deferred to the body. So such
-implementations must already be able to handle this.
-
-Similarly, Partial_Definitions.Emp_Ptr would never be frozen, but again we
-already have to handle that.
-
-Partial_Definitions.Emp_Ptr would never have allocators defined for it.
-Probably it would be best that it has no pool at all. That means that any
-allocations would have to be converted to the type. Similarly,
-Unchecked_Deallocation couldn't be instantiated for it. OTOH, other uses would
-not need conversions. So that doesn't seem too bad. If it is a real problem,
-AI-230 may help solve that. Or we could simply define such types to be
-equivalent (that couldn't be a compatibility problem, as Ada 95 has no such
-types!). But then we'd have to deal with defining the pool for the incomplete
-access type.
-
-The interesting question is exactly what does the "completion_clause" mean.
-The idea appears to be that inside of package Employees,
-Partial_Definitions.Employee and Employees.Employee are considered to be the
-same type for all purposes including resolution. (That's how we get conversions
-between Partial_Definitions.Emp_Ptr and Employees.Emp_Ptr.) Whether that should
-hold outside of Employees at places that have visibility on both Employees and
-on Partial_Definitions is an open question. Off-hand, I don't see how this
-could cause a problem, but perhaps someone else can.
-
-
-So, at first look, this seems like a useful idea to pursue. It doesn't have any
-elaboration or "new unit kind" problems as package abstract does, and it
-probably doesn't have the visibility issues either (depending on the exact
-definition of when the types are considered the same). It's similar to the
-current "with type" in that the access type equivalence isn't perfect, but it
-looks much easier to fix than rather than with "with type".
-
-So, what is wrong with this idea? Should it be written up completely?
-
-*************************************************************
-
-From: Robert Dewar
-Sent: Tuesday, July 3, 2001, 7:55 PM
-
-I certainly prefer the separate idea to the package abstract proposal from
-a language design point of view, but it is not clear to me that it satisfies
-all the Java interface requirements. I definitely think it is worth writing
-up the idea completely.
-
-*************************************************************
-
-From: Randy Brukardt
-Sent: Tuesday, July 3, 2001, 8:19 PM
-
-Humm. The only Java interface requirement that I know of that we're trying to
-address with this proposal is the mutually dependent types problem. And Java
-types are essentially tagged types in Ada, so with the tagged incomplete type,
-we get the needed functionality. I think. Is there something else that I've
-missed?
-
-*************************************************************
-
-From: Ted Baker
-Sent: Thursday, July 5, 2001, 7:05 AM
-
-I've been lurking out here watching the discussion on the package abstract
-idea, dismayed by the conceptual complexity and ugliness.  The Dan/Randy
-separate proposal seems much cleaner.  I hope you can work it out to everyone's
-satisfaction.
-
-*************************************************************
-
-From: Tucker Taft
-Sent: Monday, July 9, 2001, 3:51 PM
-
-Ted Baker wrote:
->
-> I've been lurking out here watching the discussion on the package abstract
-> idea, dismayed by the conceptual complexity and ugliness.  The Dan/Randy
-> separate proposal seems much cleaner.  I hope you can work it out to everyone's
-> satisfaction.  --Ted
-
-I agree that Dan's proposal, with some of Randy's suggestions,
-is a direction worth pursuing.  This is not too far from
-a direction suggested in the past using pragma Import
-and pragma Export applied to types, analogous to the
-trick that can be used to implement a subprogram declared
-in one package with a subprogram declared in another package.
-
-I would like to know at least the name of the
-package where the full type definition is provided,
-and I wouldn't mind requiring it to be a child
-of the package where the incomplete type is declared,
-ensuring that the incomplete/separate type's declaration
-is directly visible at the point of the full type definition.
-I would require that the name of the full type in the child
-match the name of the incomplete type in its parent.
-
-Hence, something like:
-
-   package P is
-       type T is separate(C);  -- is completed
-                               -- in child "C" of P.
-       ...
-   end P;
-
-   package P.C is
-       type T is ...
-   end P.C;
-
-*************************************************************
-
-From: Randy Brukardt
-Sent: Friday, July 13, 2001, 6:15 PM
-
-> I agree that Dan's proposal, with some of Randy's suggestions,
-> is a direction worth pursuing.  This is not too far from
-> a direction suggested in the past using pragma Import
-> and pragma Export applied to types, analogous to the
-> trick that can be used to implement a subprogram declared
-> in one package with a subprogram declared in another package.
-
-Except this is a model that makes sense, while using pragma Import and Export
-says KLUDGE in large, flashing letters.
-
-> I would like to know at least the name of the
-> package where the full type definition is provided,
-> and I wouldn't mind requiring it to be a child
-> of the package where the incomplete type is declared,
-> ensuring that the incomplete/separate type's declaration
-> is directly visible at the point of the full type definition.
-> I would require that the name of the full type in the child
-> match the name of the incomplete type in its parent.
->
-> Hence, something like:
->
->    package P is
->        type T is separate(C);  -- is completed
->                                -- in child "C" of P.
->        ...
->    end P;
->
->    package P.C is
->        type T is ...
->    end P.C;
-
-Well, this is almost OK, but I think it has some problems.
-
-First, describing the semantics of the name in the separate is going to be
-interesting. It has to reference something not declared yet, and about all we
-can say about it is that it is a library unit -- which doesn't even need to
-exist yet. Indeed, there must be no requirement that it exist.
-
-Second, restricting the completion to a child is a non-starter. I certainly
-don't think people would be happy to have to rename all of their packages in
-order to use this feature. It is particularly bad, because the parent
-(presumably with the original name) would contain just the partial definitions,
-while the child would contain the "meat" -- the stuff that exists now. So every
-reference the package would have to be changed.
-
-Moreover, I don't think such a restriction would work well with Robert Dewar's
-"only reason for this feature" -- interfacing to Java. If you have two Java
-classes Class_A and Class_B that are mutually recursive, this idea would force
-you to introduce not only another package, but one whose name will show up
-everywhere:
-
-    package Java_Stuff is
-       type Class_A is tagged separate (A);
-       type Class_A_Access is access all Class_A;
-       type Class_B is tagged separate (B);
-       type Class_B_Access is access all Class_B;
-    end Java_Stuff;
-
-    package Java_Stuff.A is
-       type Class_A is tagged ...
-       ...
-    end Java_Stuff.A;
-
-    package Java_Stuff.B is
-       type Class_B is tagged ...
-       ...
-    end Java_Stuff.B;
-
-I think it would be much cleaner to say:
-
-    package Abstract_A_and_B is
-       type Class_A is tagged separate (A);
-       type Class_A_Access is access all Class_A;
-       type Class_B is tagged separate (B);
-       type Class_B_Access is access all Class_B;
-    end Abstract_A_and_B;
-
-    with Abstract_A_and_B;
-    package A is
-       type Class_A is tagged ...
-       ...
-    end A;
-
-    with Abstract_A_and_B;
-    package B is
-       type Class_B is tagged ...
-       ...
-    end B;
-
-...because then the "abstract" package never appears in uses of Class_A or
-Class_B. Only the declarations of Class_A and Class_B need worry about it.
-
-It is especially annoying that there is no technical reason (at least that I
-know) for this restriction: it would just be a language designer's feel for
-"the best way to do it". There doesn't seem to be any technical need for direct
-(or any!) visibility on the incomplete type in order to complete it - the type
-has no operations (primitive or otherwise) anyway. And the visibility of uses
-doesn't seem to matter either: you just get whatever view you have.
-
-So I would make the name a library unit name, and drop any child requirement.
-
-A third point (just a quibble) is that it really is necessary for readability
-to mention that this type is a completion (even if the name of the type is
-required to be the same). So, I'd expect to always put in a comment:
-    -- Completes Abstract_A_and_B.Class_B.
-It seems like it would be helpful to include this in the syntax somehow, just
-as is done with subprogram names on "end". (Aside: I sure wish "end record;"
-was "end <type_name>;", 'cause that's what I write every time anyway. :-)
-
-Anyway, it seems that I've volunteered again :-) to write this up. I'm not sure
-whether to replace AI-271 with this proposal, or to open a third AI for this
-third approach. Suggestions?
-
-*************************************************************
-
-From: Tucker Taft
-Sent: Monday, July 16, 2001, 5:31 PM
-
-Randy Brukardt wrote:
-> >
-> >    package P is
-> >        type T is separate(C);  -- is completed
-> >                                -- in child "C" of P.
-> >        ...
-> >    end P;
-> >
-> >    package P.C is
-> >        type T is ...
-> >    end P.C;
->
-> Well, this is almost OK, but I think it has some problems.
->
-> First, describing the semantics of the name in the separate is going to be
-> interesting. It has to reference something not declared yet, and about all
-> we can say about it is that it is a library unit -- which doesn't even need
-> to exist yet. Indeed, there must be no requirement that it exist.
-
-This is analagous to a subunit.  The subunit need not
-exist at the point when the stub appears, but it logically
-appears there.  So this seems pretty similar.
-
->
-> Second, restricting the completion to a child is a non-starter. I certainly
-> don't think people would be happy to have to rename all of their packages in
-> order to use this feature. It is particularly bad, because the parent
-> (presumably with the original name) would contain just the partial
-> definitions, while the child would contain the "meat" -- the stuff that
-> exists now. So every reference the package would have to be changed.
-
-Hmmm... I suppose, though this seems like something
-that would have to be mostly for new code.  Also,
-library-unit renaming would allow the child to be
-renamed as a top-level unit.
-
->
-> Moreover, I don't think such a restriction would work well with Robert
-> Dewar's "only reason for this feature" -- interfacing to Java. If you have
-> two Java classes Class_A and Class_B that are mutually recursive, this idea
-> would force you to introduce not only another package, but one whose name
-> will show up everywhere:
->
->     package Java_Stuff is
->        type Class_A is tagged separate (A);
->        type Class_A_Access is access all Class_A;
->        type Class_B is tagged separate (B);
->        type Class_B_Access is access all Class_B;
->     end Java_Stuff;
->
->     package Java_Stuff.A is
->        type Class_A is tagged ...
->        ...
->     end Java_Stuff.A;
->
->     package Java_Stuff.B is
->        type Class_B is tagged ...
->        ...
->     end Java_Stuff.B;
-
-Actually, Java classes are essentially always declared
-in (Java) packages, so the Ada package corresponding
-to the Java package is a natural place for these.
-Also, the pointer type is the one that Java users will
-use.  The package where the operations are declared
-will not be as important if the obj.operation notation
-is used.
-
->
-> I think it would be much cleaner to say:
->
->     package Abstract_A_and_B is
->        type Class_A is tagged separate (A);
->        type Class_A_Access is access all Class_A;
->        type Class_B is tagged separate (B);
->        type Class_B_Access is access all Class_B;
->     end Abstract_A_and_B;
->
->     with Abstract_A_and_B;
->     package A is
->        type Class_A is tagged ...
->        ...
->     end A;
->
->     with Abstract_A_and_B;
->     package B is
->        type Class_B is tagged ...
->        ...
->     end B;
->
-> ...because then the "abstract" package never appears in uses of Class_A or
-> Class_B. Only the declarations of Class_A and Class_B need worry about it.
-
-I guess I am still not convinced.  I think we need some
-real examples, not just package A and B, to see which
-works better.
-
-> It is especially annoying that there is no technical reason (at least that I
-> know) for this restriction: it would just be a language designer's feel for
-> "the best way to do it". There doesn't seem to be any technical need for
-> direct (or any!) visibility on the incomplete type in order to complete it -
-> the type has no operations (primitive or otherwise) anyway. And the
-> visibility of uses doesn't seem to matter either: you just get whatever view
-> you have.
->
-> So I would make the name a library unit name, and drop any child
-> requirement.
-
-But it seems important to know that a given type is
-completing an incomplete type, because representation
-may depend on this.  I would think we would certainly
-require that that package with the full type "with" the
-package with the incomplete type, so given that, it seemed
-better to just make it into a child, which always implicitly
-"with"s its parent.
-
->
-> A third point (just a quibble) is that it really is necessary for
-> readability to mention that this type is a completion (even if the name of
-> the type is required to be the same). So, I'd expect to always put in a
-> comment:
->     -- Completes Abstract_A_and_B.Class_B.
-> It seems like it would be helpful to include this in the syntax somehow,
-> just as is done with subprogram names on "end". (Aside: I sure wish "end
-> record;" was "end <type_name>;", 'cause that's what I write every time
-> anyway. :-)
->
-> Anyway, it seems that I've volunteered again :-) to write this up. I'm not
-> sure whether to replace AI-271 with this proposal, or to open a third AI for
-> this third approach. Suggestions?
-
-I hate to see a proliferation of AIs which are alternatives
-of the same thing.  I guess I would rather see these all
-part of the same AI, put forth as alternatives.  Once
-we ultimately pick one for further refinement, we will want
-the others in the appendix or rationale as rejected alternatives.
-Hence, it seems to me they all belong in the same AI.
-Perhaps we need to recognize the importance of "alternatives"
-in amendment AIs.
-
-*************************************************************
-
-From: Randy Brukardt
-Sent: Tuesday, July 17, 2001, 4:41 PM
-
-Tucker, responding to me responding to him, wrote:
-> > >
-> > >    package P is
-> > >        type T is separate(C);  -- is completed
-> > >                                -- in child "C" of P.
-> > >        ...
-> > >    end P;
-> > >
-> > >    package P.C is
-> > >        type T is ...
-> > >    end P.C;
-> >
-> > Well, this is almost OK, but I think it has some problems.
-> >
-> > First, describing the semantics of the name in the separate is going to be
-> > interesting. It has to reference something not declared yet, and about all
-> > we can say about it is that it is a library unit -- which doesn't even need
-> > to exist yet. Indeed, there must be no requirement that it exist.
->
-> This is analagous to a subunit.  The subunit need not
-> exist at the point when the stub appears, but it logically
-> appears there.  So this seems pretty similar.
-
-I think you missed the point. In a subunit, there is no attempt to name some
-unit that will exist sometime in the future. The stub is a declaration of a
-some entity, and that entity actually exists there.
-
-OTOH, the unit named in your proposed syntax is not declared anywhere. And the
-appearance in the separate type declaration certainly is not a declaration, nor
-does some random package spec logically exist at this point.
-
-Traditionally, Ada 95 requires the completor to name the completee (think
-"separate" clause in subunits). The partial declaration does not indicate much
-(if anything) about the completor.
-
-Thus, I think it makes the most sense for the completion to indicate that it is
-completing a separate, rather than the separate trying to name the location of
-the completion. (But I don't feel that strongly about this.)
-
-> > Second, restricting the completion to a child is a non-starter. I certainly
-> > don't think people would be happy to have to rename all of their packages in
-> > order to use this feature. It is particularly bad, because the parent
-> > (presumably with the original name) would contain just the partial
-> > definitions, while the child would contain the "meat" -- the stuff that
-> > exists now. So every reference the package would have to be changed.
->
-> Hmmm... I suppose, though this seems like something
-> that would have to be mostly for new code.  Also,
-> library-unit renaming would allow the child to be
-> renamed as a top-level unit.
-
-Well, I suppose. *I* have existing code that desperately needs this feature,
-and I would certainly want to use it when it is available.
-
-But this means that virtually my entire program would have to be children of
-some parent. The effect would be that every object would have a parent package
-containing the abstract interface; and a child containing the real definition,
-and a library unit renames to a reasonable name.
-
->...
->
-> Actually, Java classes are essentially always declared
-> in (Java) packages, so the Ada package corresponding
-> to the Java package is a natural place for these.
-> Also, the pointer type is the one that Java users will
-> use.  The package where the operations are declared
-> will not be as important if the obj.operation notation
-> is used.
-
-I know all of this (with the possible exception of the last), and I don't see
-what it has to do with my point. Every Java object is converted into an Ada
-package. But if incomplete types are restricted to children, each such package
-will necessarily be two such packages. And the real implementation will be in
-a child. So, the package names will not be a direct mapping from Java, and
-you'll need a library renames to get close.
-
-> > It is especially annoying that there is no technical reason (at least that
-> > I know) for this restriction: it would just be a language designer's feel
-> > for "the best way to do it". There doesn't seem to be any technical need
-> > for direct (or any!) visibility on the incomplete type in order to
-> > complete it - the type has no operations (primitive or otherwise) anyway.
-> > And the visibility of uses doesn't seem to matter either: you just get
-> > whatever view you have.
-> >
-> > So I would make the name a library unit name, and drop any child
-> > requirement.
->
-> But it seems important to know that a given type is
-> completing an incomplete type, because representation
-> may depend on this.  I would think we would certainly
-> require that that package with the full type "with" the
-> package with the incomplete type, so given that, it seemed
-> better to just make it into a child, which always implicitly
-> "with"s its parent.
-
-If your initial statement is true (and it seems to be), then it is imperative
-that the completing declaration include syntax to specify that it is a
-completion. (So all of the reader, the writer, and the compiler knows certainly
-that it is a completion, and of what.) That syntax would necessarily include
-the name of the type being completed, so it follows that the package would
-have to be withed (from the normal visibility rules). Once we have this, there
-doesn't seem to be any need to restrict where this is used.
+[Editor's note: Further discussion of this option appears in AI-00277.]
 
 *************************************************************
 

Questions? Ask the ACAA Technical Agent