CVS difference for ais/ai-00277.txt

Differences between 1.2 and version 1.3
Log of other versions for file ais/ai-00277.txt

--- ais/ai-00277.txt	2001/09/22 01:18:08	1.2
+++ ais/ai-00277.txt	2001/10/02 01:27:52	1.3
@@ -1023,6 +1023,689 @@
 
 *************************************************************
 
+From: Tucker Taft
+Sent: Saturday, September 22, 2001, 7:56 AM
 
+I like almost everything about this proposal except the syntax
+(and perhaps the use of the phrase "separate incomplete type"
+rather than something like "type stub" for the incomplete type).
 
+How about defining a new kind of "representation" clause:
+
+    for <full_type> use type <separate_incomplete_type>;
+
+This reads better to me.  It also allows us to associate
+task types and protected types with the separate incomplete type.
+And it doesn't further muck up the syntax for declaring a type,
+which is already one of the most nightmarish parts of the
+Ada grammar.  Clearly this sort of "representation" clause
+should have to be in the visible part of the package if the
+connection between the two types is to be visible outside the package.
+
+Another alternative, which would eliminate the need completely
+for new syntax, would be something like:
+
+     for <full_type>'Base use <separate_incomplete_type>;
+
+Attribute 'Base is not quite right, of course, but something
+else might be (e.g. for <full_type>'Interface use ... or
+for <full_type>'Stub use ...).
+
+One particularly nice feature of this proposal which I didn't
+realize before is the multiple-implementation concept.  You
+could have multiple completions of the same type stub, and use
+a "with" clause on the main subprogram to determine which one
+gets included in a particular program.
+
+[While we are at it...  Many people wish we could have "object stubs"
+as well, so that a table could be defined and redefined without having
+to recompile the spec where the table is declared.]
+
+*************************************************************
+
+From: Randy Brukardt
+Sent: Monday, September 24, 2001, 7:56 PM
+
+> I like almost everything about this proposal except the syntax
+> (and perhaps the use of the phrase "separate incomplete type"
+> rather than something like "type stub" for the incomplete type).
+
+The reason for calling it an "incomplete type" is so that most of the rules
+that apply to an incomplete type also apply to this type. There are enough
+differences so that it doesn't matter a lot, but the incomplete syntax is
+attractive.
+
+> How about defining a new kind of "representation" clause:
+>
+>     for <full_type> use type <separate_incomplete_type>;
+>
+> This reads better to me.  It also allows us to associate
+> task types and protected types with the separate incomplete type.
+> And it doesn't further muck up the syntax for declaring a type,
+> which is already one of the most nightmarish parts of the
+> Ada grammar.  Clearly this sort of "representation" clause
+> should have to be in the visible part of the package if the
+> connection between the two types is to be visible outside the package.
+
+That would be fine by me, although I'm not certain whether any anomalies are
+introduced by allowing the type declaration and "completion" to be separated.
+(I didn't think about that, 'cause it couldn't happen.)
+
+> One particularly nice feature of this proposal which I didn't
+> realize before is the multiple-implementation concept.  You
+> could have multiple completions of the same type stub, and use
+> a "with" clause on the main subprogram to determine which one
+> gets included in a particular program.
+
+Yes, that seems like another reason to prefer this syntax to the alternative of
+specifying the completor. It probably ought to be mentioned in the AI.
+
+> [While we are at it...  Many people wish we could have "object stubs"
+> as well, so that a table could be defined and redefined without having
+> to recompile the spec where the table is declared.]
+
+Seems like a different kettle of fish; it doesn't have an obvious
+implementation counterpart as incomplete types do. (Restricting such an item
+so that you couldn't use it would work, of course, but seems pointless.)
+
+*************************************************************
+
+From: Tucker Taft
+Sent: Monday, September 24, 2001, 8:52 PM
+
+> The reason for calling it an "incomplete type" is so that most of the rules
+> that apply to an incomplete type also apply to this type. There are enough
+> differences so that it doesn't matter a lot, but the incomplete syntax is
+> attractive.
+
+I wasn't objecting to the word "incomplete" but rather to the
+word "separate".  The other places we use "separate" we
+either use the word "stub" or "subunit," and this use
+clearly corresponds more to the "stub" case.
+
+> ...
+>
+> > [While we are at it...  Many people wish we could have "object stubs"
+> > as well, so that a table could be defined and redefined without having
+> > to recompile the spec where the table is declared.]
+>
+> Seems like a different kettle of fish; it doesn't have an obvious
+> implementation counterpart as incomplete types do. (Restricting such an item
+> so that you couldn't use it would work, of course, but seems pointless.)
+
+I was more reacting to the fact that extending the notion of "stub"
+from subprograms, packages, tasks, and protected bodies to
+incomplete types made me think about how often I wish I could
+declare an object in a package spec, but define its (static)
+initializers in a separate compilation unit.  This is easy to
+do in C, but a pain in Ada.
+
+*************************************************************
+
+From: Christoph Grein
+Sent: Tuesday, September 25, 2001, 1:10 AM
+
+I'm not sure that I haven't missed something in the proposal.
+What about multiple completions in one program?
+
+   with XXX_Interface;
+   package XXX_Completion is
+     type T for XXX_Interface.T is tagged private;
+     ...
+   end XXX_Completion;
+
+   with XXX_Interface;
+   package Another_XXX_Completion is
+     type T for XXX_Interface.T is tagged private;
+     ...
+   end Another_XXX_Completion;
+
+Should there be a rule making a program illegal if there are two completions
+at  the same time?
+
+   with XXX_Completion, Another_XXX_Completion;  -- Compile time error here?
+   package ZZZ is ...
+
+This need not even be within the same unit, but could be in separated parts
+of a program:
+
+   with XXX_Completion;
+   package P1 is ...       -- OK
+
+   with Another_XXX_Completion;
+   package P2 is ...       -- OK
+
+   with P1, P2;            -- Compile time error here?
+   procedure Proc is ...
+
+   with Q1, Q2;            -- Compile time error here? Somewhere in the Q1
+   procedure Qroc is ...   -- tree, P1 is "withed", the same for Q2 and P2.
+
+Or would these be link-time errors?
+
+And what about partitions having different completions?
+
+*************************************************************
+
+From: Tucker Taft
+Sent: Tuesday, September 25, 2001, 8:34 AM
+
+Christoph Grein wrote:
+>
+> I'm not sure that I haven't missed something in the proposal.
+> What about multiple completions in one program?
+
+The rule was there, albeit a bit cryptic:
+
+    ... There is a post compilation rule that a separate
+    incomplete type may have only a single completion.
+
+I presume the rule when written out in its entirety would make
+it clear that at most one completion would be allowed in a
+single partition.  I would think it would be OK if different
+completions were used in different partitions of the same
+program, so long as the type is not a "remote" type.  But
+clearly some more thought is needed to understand all the
+implications for a distributed program...
+
+> ...
+> Or would these be link-time errors?
+
+That's what the phrase "post compilation" means (at least
+to language lawyers ;-).
+
+
+> And what about partitions having different completions?
+
+Good question.  Should probably be legal except where
+it causes problems (so what else is new?).
+
+*************************************************************
+
+From: Simon Wright
+Sent: Tuesday, September 25, 2001, 3:58 AM
+
+The code below is my understanding of how what I'm presently doing
+with GNAT's version of WITH TYPE might appear under the proposed
+scheme. Have I got the right end of the stick?
+
+The thing that causes GNAT most trouble appears to be the Storage_Size
+rep clause (I understand Storage_Pool would be problematic too).
+
+  package Department_Interface is
+     type Handle is separate;
+  end Department_Interface;
+
+  package Employee_Interface is
+     type Handle is separate;
+  end Employee_Interface;
+
+  with Department_Interface;
+  with Employee_Interface;
+  package Employee is
+     type Instance (<>) is limited private;
+     type Handle for Employee_Interface.Handle is access Instance;
+     ...
+  private
+     type Instance is record
+	...
+	Dept : Department_Interface.Handle;
+	...
+     end record;
+     for Handle'Storage_Size use ...;
+     ...
+  end Employee;
+
+*************************************************************
+
+From: Randy Brukardt
+Sent: Tuesday, September 25, 2001, 11:34 AM
+
+It's not quite right, because you can't declare an object or component of an
+incomplete type. So the component declaration "Dept" is illegal.
+
+See the example in the AI for an example of how to do it. The basic idea is to
+move the access type handle to the interface package. Because that is a normal
+type, you can give the 'Storage_Size or 'Storage_Pool clause there.
+
+That is, a "with type" becomes a incomplete stub (separate incomplete, I used
+Tucker's suggested terminology here); a "with type access" becomes an access to
+an incomplete stub.
+
+> The thing that causes GNAT most trouble appears to be the Storage_Size
+> rep clause (I understand Storage_Pool would be problematic too).
+
+Right. That was the main reason that "with type access" was dropped from the
+"with type" proposal, and eventually, we started looking for alternatives.
+
+*************************************************************
+
+From: Simon Wright
+Sent: Wednesday, September 26, 2001, 4:12 AM
+
+OK, but I get the feeling that the part of the 'Storage_Size clause I
+left out is going to be illegal now -- it does depend on a
+GNAT-specific attribute.
+
+  package Department_Interface is
+    type Instance (<>) is separate;
+    type Handle is access Instance;
+    for Handle'Storage_Size use (Instance'Object_Size * 42) / 8;
+    --  there are only ever going to be 42 Instances at once
+    --  8-bit bytes here
+  end Department_Interface;
+
+The point of this manoeuvre is to avoid malloc/free in a VxWorks
+context. Clearly I could allocate all the Instances I'm going to need
+at initialization, or use a special storage pool which is initialized
+after I know Instance'Size, or manage a static array, or ...; it
+seemed better to use a language mechanism where possible.
+
+*************************************************************
+
+From: Randy Brukardt
+Sent: Wednesday, September 26, 2001, 11:13 AM
+
+You're right, the use of the name "Instance" in the attribute is illegal by the
+rules in 3.10.1.
+
+One point that is important to note that your original example couldn't be
+written in ANY of the proposals that the ARG is looking at; they all have
+incomplete type restrictions on the type. (Private types aren't allowed in
+package abstracts because of the freezing rules - I believe that is
+intentional.)
+
+> The point of this manoeuvre is to avoid malloc/free in a VxWorks
+> context. Clearly I could allocate all the Instances I'm going to need
+> at initialization, or use a special storage pool which is initialized
+> after I know Instance'Size, or manage a static array, or ...; it
+> seemed better to use a language mechanism where possible.
+
+Another way to structure your code would be to use an incomplete deferred to
+the body (to allow the component declaration), but that still wouldn't allow
+the use of the 'Object_Size attribute.
+
+After all, the entire point of this mechanism (or any of the others) is to
+allow you to use a type without knowing much about it - representation, size,
+etc. It seems wrong to then turn around and try to find out that information.
+The only way to support this would be to totally abandon the requirement to
+see the full type before using a partial view -- which would be a giant change
+in the Ada model and clearly would have a large impact on implementations. That
+seems to be much too big a change for Ada.
+
+*************************************************************
+
+From: Tucker Taft
+Sent: Wednesday, September 26, 2001,  1:43 PM
+
+Simon wrote:
+
+> > OK, but I get the feeling that the part of the 'Storage_Size clause I
+> > left out is going to be illegal now -- it does depend on a
+> > GNAT-specific attribute.
+
+'Size would almost certainly work just as well as 'Object_Size presuming
+you are allocating composite objects.  But the big problem is that
+the compiler doesn't know anything about Instance, so 'Size or 'Object_Size
+pretty much has to be illegal on a type stub.
+
+> >   package Department_Interface is
+> >     type Instance (<>) is separate;
+> >     type Handle is access Instance;
+> >     for Handle'Storage_Size use (Instance'Object_Size * 42) / 8;
+> >     --  there are only ever going to be 42 Instances at once
+> >     --  8-bit bytes here
+> >   end Department_Interface;
+
+One alternative would be to make this a general access type (... access all ...)
+and have a separate access type (collection) which is used for all
+allocators, and then convert the result of the allocator to the "visible"
+access type declared in Department_Interface.  The access type
+used for allocators could be declared at a point that had visibility
+on the full type definition of "Instance."  In my experience, a much
+smaller portion of the code needs to be able to do allocators than needs
+to be able to reference the access type.
+
+*************************************************************
+
+From: Simon Wright
+Sent: Thursday, September 27, 2001, 3:22 AM
+
+Randy said:
+
+> Another way to structure your code would be to use an incomplete
+> deferred to the body (to allow the component declaration), but that
+> still wouldn't allow the use of the 'Object_Size attribute.
+
+Thanks to you and Tuck for the suggestions, I'll need some time to
+digest them!
+
+> After all, the entire point of this mechanism (or any of the others)
+> is to allow you to use a type without knowing much about it -
+> representation, size, etc. It seems wrong to then turn around and
+> try to find out that information. The only way to support this would
+> be to totally abandon the requirement to see the full type before
+> using a partial view -- which would be a giant change in the Ada
+> model and clearly would have a large impact on implementations. That
+> seems to be much too big a change for Ada.
+
+Point taken.
+
+*************************************************************
+
+From: Dan Eilers
+Sent: Thursday, September 27, 2001, 12:23 PM
+
+> OK, but I get the feeling that the part of the 'Storage_Size clause I
+> left out is going to be illegal now -- it does depend on a
+> GNAT-specific attribute.
+>
+>   package Department_Interface is
+>     type Instance (<>) is separate;
+>     type Handle is access Instance;
+>     for Handle'Storage_Size use (Instance'Object_Size * 42) / 8;
+>     --  there are only ever going to be 42 Instances at once
+>     --  8-bit bytes here
+>   end Department_Interface;
+
+Perhaps a solution to this would be to extend the standard attribute
+S'Max_Size_In_Storage_Elements (see RM 13.11.1), so that it can be applied
+directly to an access type, instead of only to a subtype designated by an
+access type.
+
+This eliminates the problem Randy pointed out, where RM 3.10.1 (5-9)
+precludes most usages of incomplete types.
+
+Of course, the amount of storage needed will not be statically known at
+the point of the storage_size attribute definition clause, but this clause
+does not require a static expression.
+
+Are there elaboration order concerns that would preclude this solution?
+The amount of storage needed would probably have to be pre-elaborable.
+
+Then this could be written as:
+
+  package Department_Interface is
+    type Instance (<>) is separate;
+    type Handle is access Instance;
+    for Handle'Storage_Size use (Handle'Max_Size_In_Storage_Elements * 42);
+    --  there are only ever going to be 42 Instances at once
+  end Department_Interface;
+
+Note that this happens to also eliminate the "/ 8".
+
+*************************************************************
+
+From: Dan Eilers
+Sent: Thursday, September 27, 2001, 12:37 PM
+
+Tuck wrote:
+> Christoph Grein wrote:
+> >
+> > I'm not sure that I haven't missed something in the proposal.
+> > What about multiple completions in one program?
+>
+> The rule was there, albeit a bit cryptic:
+>
+>     ... There is a post compilation rule that a separate
+>     incomplete type may have only a single completion.
+>
+> I presume the rule when written out in its entirety would make
+> it clear that at most one completion would be allowed in a
+> single partition.  I would think it would be OK if different
+> completions were used in different partitions of the same
+> program, so long as the type is not a "remote" type.  But
+> clearly some more thought is needed to understand all the
+> implications for a distributed program...
+
+Randy wrote:
+>         I followed Pascal's lead, and only put in restrictions where they
+> were necessary for consistency, semantic, or implementation reasons.
+
+It would be useful to specify the reason for the above rule.
+Is it necessary for type safety, as claimed in:
+ http://home.bluemarble.net/~jvolan/WithingProblem/FAQ.html#forward_incompletes
+
+*************************************************************
+
+From: Randy Brukardt
+Sent: Monday, October 1, 2001,  7:28 PM
+
+Dan said (talking about the postcompilation rule for a single completion):
+
+> It would be useful to specify the reason for the above rule.
+> Is it necessary for type safety, as claimed in:
+> http://home.bluemarble.net/~jvolan/WithingProblem/FAQ.html#forward_incompletes
+
+I mentioned the reason in e-mail (see the appendix of the AI) back in July, and
+it seemed so obvious that I didn't mention it. Essentially it is necessary to
+have only a single completion in a partition, because otherwise you could use
+one completion as the other without any warning:
+
+    package Interface is
+       type Stub is tagged separate;
+    end Interface;
+
+    with Interface;
+    package Complete1 is
+       type Tag1 for Interface.Stub is tagged record
+          F : Float;
+       end record;
+    end Complete1;
+
+    with Interface;
+    package Complete2 is
+        type Tag2 for Interface.Stub is tagged record
+           I : Integer;
+        end record;
+    end Complete2;
+
+    with Interface;
+    procedure Do_Something (A : in Interface.Stub);
+
+    with Interface, Complete1;
+    procedure Do_Something (A : in Interface.Stub) is
+    begin
+       if A.F = 1.0 then -- (1)
+       ...
+    end Do_Something;
+
+    with Interface, Complete2, Do_Something;
+    procedure Problem is
+       T : Complete2.Tag2;
+    begin
+	 Do_Something (T); -- (2)
+    end Problem;
+
+Assume that multiple completions are allowed. The call at (2) is legal, as
+Interface.Stub is a subtype of Complete2.Tag2 in Problem (as the completion is
+visible). The reference to component F at (1) is also legal, because
+Interface.Stub is a subtype of Complete1.Tag1 in Do_Something (again the
+completion is visible). But we passed a Tag2 object to Do_Something, which then
+proceeds to use it as a Tag1 object (reading an Integer as a Float, or worse).
+Obviously, we can't allow that.
+
+The easiest way to solve this problem is to disallow multiple completions in a
+single partition, and it doesn't seem to be an important capability. I suspect
+that the rule really has to be program (allowing different completions in
+different partitions of the same program would allow the same problem to occur
+across partitions -- which probably would be worse than the problem in a single
+partition).
+
+*************************************************************
+
+From: Dan Eilers
+Sent: Thursday, September 27, 2001, 2:00 PM
+
+Tuck wrote:
+
+> How about defining a new kind of "representation" clause:
+>
+>     for <full_type> use type <separate_incomplete_type>;
+>
+> This reads better to me.  It also allows us to associate
+> task types and protected types with the separate incomplete type.
+> And it doesn't further muck up the syntax for declaring a type,
+> which is already one of the most nightmarish parts of the
+> Ada grammar.  Clearly this sort of "representation" clause
+> should have to be in the visible part of the package if the
+> connection between the two types is to be visible outside the package.
+
+Would it make sense to allow an ordinary incomplete type to
+be completed in this way as well?
+
+Note: this is getting pretty close to type renaming.
+
+*************************************************************
+
+From: Tucker Taft
+Sent: Thursday, September 27, 2001,  3:27 PM
+
+I'm not sure.  It's actually a bit misleading to call it
+"completing" the incomplete type.  The incomplete type
+is effectively becoming a subtype of the full type.
+Perhaps that is the syntax we should use instead?  E.g.:
+
+    separate subtype P.Type_Stub is Full_Type;
+
+This would nicely generalize for "regular" incomplete types
+to be "completed" by a subtype declaration.
+
+    subtype Inc_Type is Whatever.Some_Full_Type;
+
+I'm not sure what particular benefit this would provide,
+because presumably the primitive operations of the
+type are *not* made visible by this subtype declaration.
+
+Actually, if we are willing to consider going back to the
+new-kind-of-compilation-unit, then the correct syntax for
+completing a type stub would be a separate compilation unit:
+
+    with Z;
+    separate (P)
+    subtype Type_Stub is Z.Full_Type;
+
+This would actually be the most consistent with existing stub
+completion syntax.  The special rule is that this (sub)type "subunit"
+would *not* be substituted into the point of the "stub" unless
+the subunit is somehow made visible in a context clause.  And how
+do we make the type subunit visible?  Well of course...
+
+
+   [drum roll...]
+
+
+    with type P.Type_Stub;
+
+[I can hear the worldwide groans from here ;-]
+
+> Note: this is getting pretty close to type renaming.
+
+I guess, though it seems somewhat upside down.  Sort of
+the "come-from" of the renaming world ;-).  I suppose
+the real question is whether the primitive operations
+of a type stub are implicitly declared (or implicitly
+renamed?) at the point of the stub, when the completion
+of the stub (whatever syntax that ends up using) is visible.
+
+Randy, did you cover this issue of primitive operation
+implicit declaration/renaming?
+
+Any comments on using a subtype declaration-ish syntax
+for "completing" a type stub, either as a declaration
+within some package spec, or as a separate "type subunit"
+compilation unit?
+
+Actually, if we really give these things subtype-like
+equivalence, perhaps we should allow the "is separate"
+syntax on a subtype declaration only?  And similarly,
+use an "incomplete subtype" if we want to complete
+the declaration using a subtype declaration.  E.g.:
+
+    subtype Subtype_Stub is separate;
+      -- declare a subtype "stub"
+  or
+    subtype Incomplete_Subtype;
+      -- declare an incomplete subtype
+
+*************************************************************
+
+From: Dan Eilers
+Sent: Friday, September 28, 2001, 2:31 PM
+
+I think the "separate incomplete" proposal comes real close to
+this, if one puts the full type definition in a child unit
+(with the incomplete type in the package spec).
+Then, instead of needing a new kind of compilation unit for
+a separate subtype, a normal child unit works.  And instead
+of needing a new type of "with" clause, a normal "with" of the
+child unit works.
+
+*************************************************************
+
+From: Randy Brukardt
+Sent: Monday, October 1, 2001,  7:44 PM
+
+Tuck said:
+
+>    [drum roll...]
+>
+>
+>     with type P.Type_Stub;
+>
+> [I can hear the worldwide groans from here ;-]
+
+I certainly groaned at this whole line of thought. If we're going to bother
+with a new kind of compilation unit, we might as well go with the package
+abstracts. The whole point of incomplete stubs is that we don't need a bunch of
+heavy new mechanisms to solve the problem.
+
+> I guess, though it seems somewhat upside down.  Sort of
+> the "come-from" of the renaming world ;-).  I suppose
+> the real question is whether the primitive operations
+> of a type stub are implicitly declared (or implicitly
+> renamed?) at the point of the stub, when the completion
+> of the stub (whatever syntax that ends up using) is visible.
+>
+> Randy, did you cover this issue of primitive operation
+> implicit declaration/renaming?
+
+I didn't "cover it", because I intended that no such thing would happen. I
+selected "subtype" specifically because I didn't want to deal with primitive
+operations. (Note that a regular incomplete type has no primitive operations of
+its own; the problem occurs with tagged incomplete types, which allow
+parameters of the type). Certainly, we want the primitive operations to be
+declared with the full type. I guess I'd prefer that the incomplete stub had no
+primitive operations by itself; we'd have to add a rule saying that there are
+no such things. (You can't derive from the incomplete type anyway.) When it is
+completed and is acting as a subtype, it is of course the same as the
+completing type.
+
+> Any comments on using a subtype declaration-ish syntax
+> for "completing" a type stub, either as a declaration
+> within some package spec, or as a separate "type subunit"
+> compilation unit?
+
+I'm not against the subtype syntax for a completion; it is, after all, exactly
+what the semantics are. I like that better than the representation clause
+syntax.
+
+> Actually, if we really give these things subtype-like
+> equivalence, perhaps we should allow the "is separate"
+> syntax on a subtype declaration only?  And similarly,
+> use an "incomplete subtype" if we want to complete
+> the declaration using a subtype declaration.  E.g.:
+>
+>     subtype Subtype_Stub is separate;
+>       -- declare a subtype "stub"
+>   or
+>     subtype Incomplete_Subtype;
+>       -- declare an incomplete subtype
+
+That is possible, but then of course we'd have to define these things
+separately from existing incomplete types. That's not necessarily a bad idea
+(it avoids the primitive operations problem noted above cleanly), but it does
+increase the "weight" of the solution a bit.
+
 *************************************************************
+

Questions? Ask the ACAA Technical Agent