CVS difference for ais/ai-00230.txt
--- ais/ai-00230.txt 2002/02/05 02:06:24 1.7
+++ ais/ai-00230.txt 2003/02/05 21:03:23 1.8
@@ -1,4 +1,4 @@
-!standard 3.10 (01) 02-02-01 AI95-00230/03
+!standard 3.10 (01) 03-02-05 AI95-00230/04
!class amendment 00-04-13
!status work item 00-04-13
!status received 00-04-13
@@ -9,32 +9,48 @@
!summary
More general use of anonymous access types is proposed, to allow the
-flexibility of implicit conversion and run-time accessibility checking to be
-used in more contexts, including as components, stand-alone constants, and as
-return types.
+flexibility of implicit conversion and run-time accessibility checking
+to be used in more contexts, including as components and as stand-alone
+constants. A separate AI (AI-00325) investigates using anonymous access
+types as function result types.
+
+NOTE: This AI is also related to AI-00231, which allows anonymous access
+types to be specified to be access-to-constant as opposed to
+access-to-variable, and to be either null-allowing or not null-allowing.
!problem
-This proposal attempts to resolve a problem encountered when
-creating Ada packages to use in interfacing with code written
-in languages like Java, and in using various common object-oriented
-programming paradigms.
-
-In Java and other OO languages, types that are references
-to a subclass are freely convertible to types that are references
-to a superclass. This implicit conversion, which is always safe,
-significantly reduces the need for explicit conversions when passing
-references as parameters.
+This proposal attempts to resolve a problem encountered when creating Ada
+packages to use in interfacing with code written in languages like Java, and in
+using various common object-oriented programming paradigms.
+
+In Java and other OO languages, types that are references to a subclass are
+freely convertible to types that are references to a superclass. This implicit
+conversion, which is always safe, significantly reduces the need for explicit
+conversions when passing references as parameters.
With the current situation, large numbers of explicit conversions are
-required. This obscures the explicit conversions that really do
+required. This obscures the explicit conversions that really do
need attention, and makes the whole OO coding style seem more cumbersome
in Ada than in other OO languages.
-Because Ada has local access types, there needs to be a way to
-remember the accessibility level of the object designated by
-a reference across certain assignments, parameter passing, and
-function return.
+In addition to addressing the problem of minimizing unnecessary
+explicit-yet-safe conversions, there is the related problem of
+minimizing (named) "access type proliferation." This generally occurs
+when, for one reason or another, an access type is not defined at the
+point of the type declaration (e.g., with the existing "purity" rules, a
+pure package would never declare any access types). Ultimately, if they
+need an access type, users of the type end up declaring their own
+"personal" access type, creating yet more need for unnecessary
+conversions.
+
+Here are two important technical problems that need to be addressed by
+any solution:
+
+Because Ada has local access types, there needs to be a way to remember
+the accessibility level of the object designated by a reference across
+certain assignments, parameter passing, and possibly function return
+(see AI-00325).
Because Ada has multiple storage pools, it is important that an
allocator of an anonymous access type allocate from the appropriate
@@ -42,61 +58,48 @@
!proposal
-The "access_definition" syntactic category (see ai-231) is permitted in more
-places than just as formal parameters and discriminants. In addition to the
-current places (IN parameters and discriminants of limited types) it would
-be permitted in stand-alone constant declarations, formal IN objects,
-component definitions, for function return types, and for discriminants of
-non-limited types. The type associated with constant, formal IN, component,
-or function return is an anonymous access type, which permits implicit
-conversions from other access types with appropriately compatible designated
-subtypes (as defined by 4.6(13-17)).
-
-The accessibility level of an anonymous access type is determined at the time
-when the access_definition is elaborated. For a function return type, this
-happens at the time of the function return.
-
-The general accessibility level rule is that for an access value which
-cannot be altered during its lifetime (in parameter, stand-alone constant,
-IN object, discriminant of a limited type, function return value), its level
-may be determined by the accessibility level of its initial value or
-enclosing object. For others (i.e. other kinds of components)
-the accessibility level must be determined by the level of its
-declaration. This is necessary to simplify implementation and to
-avoid dangling references when an access object is updated while
-being "viewed" at a deeper level than it truly is (which is always
-permitted by the current accessibility checking rules).
+The "access_definition" syntactic category (see AI-00231) is permitted in more
+places than just as formal parameters and discriminants. In addition to the
+current places (IN parameters and discriminants of limited types) it is
+permitted in stand-alone constant declarations, formal IN objects,
+component definitions, and for discriminants of non-limited types. The type
+associated with constant, formal IN, or component is an anonymous access type,
+which permits implicit conversions from other access types with appropriately
+compatible designated subtypes (as defined by 4.6(13-17)).
+
+The accessibility level of an anonymous access type is determined at the
+time when the access_definition is elaborated. The general accessibility
+level "philosophy" is:
+
+a) For an access object that cannot be altered during its lifetime (in
+parameter, stand-alone constant, IN object, discriminant of a limited
+type, possibly function return value), its level may be determined by
+the accessibility level of its initial value or enclosing object.
+
+b) For others (i.e. other kinds of components) the accessibility level
+must be determined by the level of its declaration. This is necessary
+to simplify implementation and to avoid dangling references when an
+access object is updated while being "viewed" at a deeper level than it
+truly is (which is always permitted by the current accessibility
+checking rules).
[NOTE: We considered allowing anonymous access types in stand-alone
-variable declarations. However the above general rule would force them
-to have a level determined by their declaration rather than initial value.
-This might create confusion when copying an access parameter into a local
-variable and unintentionally losing the accessibility level information.
-By only allowing constants, and having them preserve the accessibility level
-information, we avoid this possible problem.]
-
-Applying this general rule to the specific cases means that
-for a constant declaration/formal IN object, the level is the same as the
-level of the type of the initial value. For a component definition, or a
+variable declarations. However the above general philosophy would force
+them to have a level determined by their declaration rather than initial
+value. This might create confusion when copying an access parameter into
+a local variable and unintentionally losing the accessibility level
+information. By only allowing constants, and having them preserve the
+accessibility level information, we avoid this possible problem.]
+
+Applying this general philosophy to the specific cases means that for a
+constant declaration/formal IN object, the level is the same as the
+level of the type of the initial value. For a component definition, or a
discriminant of a nonlimited type, the level is the same as that of the
-enclosing composite type. As in the current language, IN parameters take
+enclosing composite type. As in the current language, IN parameters take
their level from the initial value, and discriminants of limited types
take their level from the enclosing composite *object* (as opposed
to enclosing type).
-For a function return, the level is the same as the level of the type
-of the returned value, which must be shallower than the level of the
-execution of the function (to avoid dangling references by the caller).
-If the return expression is an allocator, the accessibility
-level and storage pool for the allocator is determined by the context
-of the call on the function. This implies that the call on
-a function with an anonymous access return type must be passed
-in a storage pool and an accessibility level, and must return
-both an access value and an accessibility level. [Implementation NOTE:
-The implementation may implement the accessibility level check either
-after returning from the call, or at the point of the return statement, since
-it has enough information to do it there as well.]
-
There is a special predefined equality (and matching inequality) operator
declared in package Standard which requires at least one of the parameters to
be of an anonymous access type, and the other to be convertible to that
@@ -106,45 +109,156 @@
is determined by the context in which it appears:
a) As the value for an IN parameter, constant, or formal IN object of an
- anonymous access type, an anonymous storage pool whose storage is
- reclaimed when the function returns, or at the end of the constant's
- or formal IN object's scope;
+ anonymous access type, an anonymous storage pool whose storage is
+ reclaimed when the function returns, or at the end of the constant's
+ or formal IN object's scope;
b) As the initial value for a discriminant of a limited type, the same
- storage pool as used for the enclosing object, if it is created by
- an allocator, or an anonymous storage pool whose storage is
- reclaimed when the enclosing object's scope ends.
+ storage pool as used for the enclosing object, if it is created by
+ an allocator, or an anonymous storage pool whose storage is
+ reclaimed when the enclosing object's scope ends.
c) As the initial value for a component other than a discriminant of
- a limited type, a standard storage pool similar to that which would be used
- for a named access type declared at the same level as the enclosing composite
- type.
-
-d) As a return expression for a function whose return type is anonymous,
- the same storage pool that would be used had the allocator appeared
- at the point of the function call. (This rule is applied recursively
- for a chain of calls.)
+ a limited type, a standard storage pool similar to that which would be used
+ for a named access type declared at the same level as the enclosing composite
+ type.
!wording
+
+Add to paragraph 3.3.1(2):
+
+ object_declaration ::= access_definition [:= expression];
+
+Change 3.3.1(5) to:
+
+ An object_declaration without the reserved word CONSTANT that has
+ a subtype_indication or array_type_definition defining an indefinite
+ subtype shall have an initialization expression. An initialization
+ expression shall not be given if the object is of a limited type.
+
+Change the first sentence of 3.3.1(6) to:
+
+ An object_declaration with an access_definition or the reserved word
+ CONSTANT declares a constant object. ... -- rest remains the same
+
+Add "access_definition, " to the first sentence of paragraph 3.3.1(16):
+
+ The subtype_indication, array_type_definition, access_definition,
+ single_task_declaration, ...
+
+Change 3.6(7) as follows:
+
+ component_definition ::= [aliased] subtype_indication | access_definition
+
+Change 3.6(22/1) to add "or access_definition":
+
+ ... The elaboration of a component_definition in an
+ array_type_definition consists of the elaboration of the
+ subtype_indication {or access_definition}. ...
+
+Eliminate paragraph 3.7(10) (which allows access discriminants only
+on limited types).
+
+Change paragraph 3.8(18/1) as follows:
-(See proposal.)
+ ... For the elaboration of a component_definition of a
+ component_declaration or the discrete_subtype_definition of an
+ entry_declaration for an entry family (see 9.5.2), {if the compoent
+ subtype is defined by an access_definition or} if the constraint or
+ range of the subtype_indication or discrete_subtype_definition is not
+ a per-object constraint, then the {access_definition,}
+ subtype_indication{,} or discrete_subtype_definition is elaborated.
+ ...
+Change 3.10(12) and 3.10(17) to list all places where access_definition
+occurs, or none of them.
+
+Add the following paragraph before 3.10.1(12):
+
+ The accessibility level of the anonymous access type defined by an
+ access_definition of an object_declaration (or
+ formal_object_declaration in an instance) is the same as that of the
+ view designated by the value of the initialization_expression (or
+ actual). If the initialization_expression (or actual) is an
+ allocator, this is the accessibility level of the innermost enclosing
+ master.
+
+Change paragraph 3.10.1(12) as follows:
+
+ The accessibility level of the anonymous access type of an access
+ discriminant {specified for a limited type} is the same as the
+ containing object or associated constrained subtype. {For other
+ components having an anonymous access type, the accessibility level
+ of the access type is the same as the level of the containing
+ composite type.}
+
+
+Change paragraph 12.4(2) as follows:
+
+ formal_object_declaration ::=
+ defining_identifier_list : mode subtype_mark [:= default_expression];
+ | defining_identifier_list : access_definition [:= default_expression];
+
+ Change 12.4(9) as follows:
+
+ A formal_object_declaration declares a generic formal object. {If
+ the mode is omitted or the declaration has an access_definition, }the
+ default mode is IN. For a formal object of mode IN, the nominal
+ subtype is the one denoted by the subtype_mark {or defined by the
+ access_definition} in the declaration of the formal. For a formal
+ object of mode IN OUT, ... -- no change
+
!example
+ package P is
+ type T is ...
+ end P;
+
+ package P2 is
+ type Rec(D : access String := new String'("")) is record
+ F : access constant T;
+ G : access all T not null := new T;
+ H : access all T := null;
+ end record;
+
+ Y : access String := new String'("Hello There");
+ -- I believe the "constant" should be implicit here,
+ -- analogous to the existing rule for access parameters.
+ -- The general rule is that "access" implies read only
+ -- if that is possible in the given context.
+ -- Only non-discrimiant record components
+ -- will be directly assignable; discriminants of non-limited,
+ -- unconstrained objects can be changed, but as usual only
+ -- by assigning to the enclosing object.
+
+ -- Essentially, the syntax for a stand-alone object declaration
+ -- with an access_definition instead of a subtype_indication will not
+ -- allow the reserved word "constant"
+ -- before the access_definition, but it will always
+ -- declare a constant object, including possibly a deferred constant.
+
+ generic
+ R : in Rec;
+ Z : access T := R.G; -- The "in" must be omitted here.
+ package What_Fun is ...
+
+ package Instance is new What_Fun(new T'(...));
+ end P2;
+
!discussion
In an object-oriented program, it is desirable to be able to use any descendant
of a root type in a context that only depends on the properties of the root
type. This principle is sometimes called "substitutability."
-This is supported in Ada 95 by use of T'Class as a parameter type. However,
+This is supported in Ada 95 by use of T'Class as a parameter type. However,
access types are used heavily in object-oriented systems, because of the
unknown size requirements when dealing with a type hierarchy. The parameter
notation "access T'Class" supports access type substitutability, but only for
parameters. Furthermore, it doesn't handle potentially null values. Finally, it
cannot be used for record or array components (other than access
-discriminants). [Note that the "null value" problem is solved in AI-231. We
+discriminants). [Note that the "null value" problem is solved in AI-231. We
will make no further mention of this problem, and simply presume the
generalization of access_definition proposed in AI-231 is in effect.]
@@ -154,47 +268,55 @@
"significant."
This AI proposes to generalize the use of anonymous access types, as declared
-by an access_definition. It avoids any incompatibility issues by not changing
+by an access_definition. It avoids any incompatibility issues by not changing
the implicit conversion rules for existing named access types.
This proposal grew out of a long discussion about the difficulties associated
with a "with access type" mechanism (originally part of AI-00217). The problems
encountered relate to issues such as "thin" versus "fat" access-to-array types,
-conventions associated with access types, access subtypes, etc. Furthermore,
+conventions associated with access types, access subtypes, etc. Furthermore,
Erhard Ploedereder reported significant concerns among his students with the
-excessive numbers of explicit conversions required to use Ada 95. This happens
+excessive numbers of explicit conversions required to use Ada 95. This happens
when an actual parameter is of type access-to-T2'Class, and the formal
parameter is of type access-to-T1'Class.
This problem could be solved by allowing implicit conversion only to general
-access-to-classwide types. However, the current access-type conversion rules
-are based more on the general vs. pool-specific distinction. Also, the
-mutually-recursive type problem need not involve tagged types at all. It would
+access-to-classwide types. However, the current access-type conversion rules
+are based more on the general vs. pool-specific distinction. Also, the
+mutually-recursive type problem need not involve tagged types at all. It would
seem unnatural to require the use of tagged and class-wide types just to get
the implicit conversion on named general access types that is already available
for all anonymous general access types.
We have decided to disallow named subtypes of anonymous access types, because
-they seemed to create more problems than they solved.
+they seemed to create more problems than they solved, and are not needed
+if we allow anonymous access types in component declarations.
We have proposed to allow anonymous access types in constant declarations,
-formal IN objects, component definitions, and function returns. We considered
+formal IN objects, component definitions, and possibly function results. We considered
broadening this to include stand-alone variable declarations, and variables
declared as [IN] OUT parameters or IN OUT formal objects, but that created
the possibility of confusion about whether accessibility level information
-is lost when copying an access parameter to a local variable. Alternatively,
+is lost when copying an access parameter to a local variable. Alternatively,
the variable could retain the accessibility level information, but then
we would have to carry run-time accessibility levels across assignment
statements with an accompanying accessibility check as well to handle
-up-level assignments. Furthermore, this would totally change the model,
+up-level assignments. Furthermore, this would totally change the model,
since thus far, we have fully determined the accessibility level
at the point of the elaboration of the anonymous access type.
We handle updatable components by specifying that their accessibility
-level is determined by the enclosing composite type. This provides
+level is determined by the enclosing composite type. This provides
the advantages of implicit conversion, without needing run-time
accessibility levels for individual components.
+We have split out issues relating to anonymous function result types
+into a separate AI-00325, so this one can be evaluated without getting bogged
+down in the implementation issues associated with function returns.
+
+Similarly, issues relating to supporting access-to-constant
+and null-allowing anonymous access types are in AI-00231.
+
Implementation Issues:
Constant declarations with access_definitions are no harder to support than
@@ -204,77 +326,33 @@
level issues, because the level is determined just like a named access
type.
-Function returns are harder to support, but also provide important
-capabilities that are currently very difficult to accomplish.
+Other alternatives considered:
-First of all, one can define a function that constructs an object
-(including an object of a limited type) in a storage pool determined
-by the caller, including a "stackish" storage pool (i.e. one that
-is cheap to reclaim). This kind of constructor is definitely
-missing in Ada now. Currently, the access type, and hence the
-storage pool, must be known inside the function that creates
-an object. Secondly, there is no way to create a single function
-that can be used both for creating a local object and a heap object
-with similar efficiencies. With this proposal, the "constructor"
-would look like this:
-
- function Construct(...) return access T is
- begin
- ...
- return new T'(...);
- end;
-
- X : constant access T := Construct(...); -- Create on the stack
-
- Y : constant T_Ptr := Construct(...); -- Create in T_Ptr'Storage_Pool
-
-Secondly, one could define a function that could return a reference to
-an aliased component of an object that is itself passed in using an access
-parameter. This would effectively allow a function to act as a "selector"
-that can be used on the left hand side of an assignment when followed by
-".all". E.g:
-
- X : aliased Rec_With_Aliased_Component;
-
-begin
-
- Selected_Component(X'Access).all := Y;
-
-where Selected_Component is declared:
-
- function Selected_Component(RP : access Rec_With_Aliased_Component)
- return access Component_Type is
- begin
- return RP.Component'Access;
- end Selected_Component
-
-And if we approve the "object.operation" syntax:
-
- X.Selected_Component.all := Y;
-
-presuming Selected_Component is declared in the same package as
-Rec_With_Aliased_Component.
-
-There are some implementation issues associated with supporting function
-returns. Basically it means that such a function has to use run-time
-accessibility levels rather than static accessibility levels internally. Or
-more precisely, it needs to use accessibility levels that are comparable with
-those used by the caller. This need not be a huge burden. Probably the
-simplest is to have the caller pass in a "caller" accessibility level to the
-function, which the function then adds one to to use as its own accessibility
-level.
-
-[Some optimizations are possible: If there is only one access parameter, it
-could use the accessibility level associated with that parameter as the
-"caller" level (think about it ;-). If there are two or more access
-parameters, it could use the max of them. At that point, it would be more
-efficient to have the caller just pass in an extra parameter which is the
-"true" caller accessibility level. If it is nested in a function that also
-has access parameters, it is possible that it might have no access parameters,
-in which case it would probably need a "caller" accessibility level passed in
-as an additional parameter, though it could probably calculate it from the
-accessibility level of the access parameter passed into the enclosing function.
-Etc...]
+There was much discussion about something like "T'Access" being an
+implicitly declared access type, similar to T'Class and T'Base, associated
+with every type T. There was also investigation into a restricted
+version of that in the form of T'Class_Access, which would be
+an implicitly declared access-to-T'Class. The latter was rejected
+as being too limiting, since access type proliferation occurs with
+non-tagged types as well.
+
+The more general version of T'Access was dropped because:
+
+a) we already have anonymous access types, so it is not clear
+we need two different notations for them
+
+b) AI-00231 includes proposals to allow access-to-constant
+and null-allowing and non-null-allowing anonymous access types
+in the existing contexts (on parameters and discriminants), and crafting
+attribute identifiers to handle all combinations of these capabilities
+would seem to be unwise. The access-to-constant capability
+seems even more important for the wider usage we are
+considering in this proposal.
+
+c) The accessibility level of T'Access was presumed to be
+the same as that of T. This could be limiting in various
+ways, and in particular you couldn't safely convert to T'Access
+from some potentially local access type.
!appendix
@@ -292,15 +370,15 @@
How about if we get an e-mail discussion going, then?
The major new idea in my revision of AI-230 is the attribute
-on tagged types "'Class_Access". T'Class_Access is a type
+on tagged types "'Class_Access". T'Class_Access is a type
that may be used as the type of a stand-alone object, record or
-array component, parameter, etc. It is "universal" in the sense
+array component, parameter, etc. It is "universal" in the sense
that when the expected type is T'Class_Access, any access type
whose designated type is covered by T'Class may be used.
There would need to be an accessibility check that the source type has the
-same accessibility level as type T. It would have "=" and "/=" operators,
-and the "null" literal. Allocators would raise Storage_Error, because
+same accessibility level as type T. It would have "=" and "/=" operators,
+and the "null" literal. Allocators would raise Storage_Error, because
the Storage_Size for T'Class_Access is defined to be 0.
Such an access type would very closely match the reference-type implicit
@@ -309,7 +387,7 @@
substitutability for tagged types.
T'Class_Access would be permitted on incomplete tagged types (a new
-category of incomplete types). I suppose we would also allow
+category of incomplete types). I suppose we would also allow
T'Class_Access on plain old incomplete types, with the same provisos
as on T'Class (e.g. only in the same library unit and the full type must
be tagged).
@@ -334,9 +412,9 @@
I like the T'Class_Access idea.
But why not call it T'Access? But keep the rule that it's only for
-tagged, and the designated type is T'Class. That is, I'm just
-suggesting a name change. I don't see any benefit in the extra verbiage
-"Class_". Ada is already verbose enough, compared to Pascal's perfectly
+tagged, and the designated type is T'Class. That is, I'm just
+suggesting a name change. I don't see any benefit in the extra verbiage
+"Class_". Ada is already verbose enough, compared to Pascal's perfectly
readable "^T" and C's somewhat ugly "T*".
I'm not against verbosity when it imparts useful information, so let's
@@ -355,13 +433,13 @@
Robert A Duff wrote:
> But why not call it T'Access? But keep the rule that it's only for
-> tagged, and the designated type is T'Class. That is, I'm just
-> suggesting a name change. I don't see any benefit in the extra verbiage
+> tagged, and the designated type is T'Class. That is, I'm just
+> suggesting a name change. I don't see any benefit in the extra verbiage
> "Class_".
-I think there is an important benefit. At least *I* would presume
+I think there is an important benefit. At least *I* would presume
that T'Access would be an access-to-T type rather than an access-to-T'Class
-type. Also, T'Class_Access is clearly only appropriate for tagged
+type. Also, T'Class_Access is clearly only appropriate for tagged
types, whereas T'Access seems like a perfectly reasonable thing to
allow for any kind of type.
@@ -370,12 +448,12 @@
>
> Does this mean I can use T'Class_Access in a pragma-Pure package?
-That was a possibility. If we allow access types
+That was a possibility. If we allow access types
in pure packages, we need certain restrictions.
At a minimum, access types declared in pure packages should
-have Storage_Size 0. Since access parameters and discriminants
+have Storage_Size 0. Since access parameters and discriminants
are already allowed in pure packages, it seems unnecessary
-to go any further. However, we would have to amend the
+to go any further. However, we would have to amend the
rules on shared passive packages to disallow not only the declaration
of access-to-classwide types, but also the declaration of library-level
objects of a type, or access types designating a type, with any
@@ -385,7 +463,7 @@
a pure library unit, if T is library-level (or a formal type),
even though you could use T'Class_Access outside a pure library
unit, despite the fact that T was declared inside a pure library unit.
-That seems more prudent for now. If we decide to allow
+That seems more prudent for now. If we decide to allow
storage-size-zero access types in pure packages in general,
then we could examine allowing T'Class_Access there as well.
@@ -398,9 +476,9 @@
From: Robert A Duff
Sent: Tuesday, April 04, 2000 12:02 PM
-> I think there is an important benefit. At least *I* would presume
+> I think there is an important benefit. At least *I* would presume
> that T'Access would be an access-to-T type rather than an access-to-T'Class
-> type. Also, T'Class_Access is clearly only appropriate for tagged
+> type. Also, T'Class_Access is clearly only appropriate for tagged
> types, whereas T'Access seems like a perfectly reasonable thing to
> allow for any kind of type.
@@ -414,30 +492,30 @@
I'm not particularly advocating that.
-> That was a possibility. If we allow access types
+> That was a possibility. If we allow access types
> in pure packages, we need certain restrictions.
> At a minimum, access types declared in pure packages should
-> have Storage_Size 0. Since access parameters and discriminants
+> have Storage_Size 0. Since access parameters and discriminants
> are already allowed in pure packages, it seems unnecessary
-> to go any further. However, we would have to amend the
+> to go any further. However, we would have to amend the
> rules on shared passive packages to disallow not only the declaration
> of access-to-classwide types, but also the declaration of library-level
> objects of a type, or access types designating a type, with any
> part being of an access-to-classwide type.
-You realize this is a dangerous discussion. It's a side issue, but
-discussing it makes the original proposal look more complicated. ;-)
+You realize this is a dangerous discussion. It's a side issue, but
+discussing it makes the original proposal look more complicated. ;-)
> Alternatively, it might be easier to disallow T'Class_Access inside
> a pure library unit, if T is library-level (or a formal type),
> even though you could use T'Class_Access outside a pure library
> unit, despite the fact that T was declared inside a pure library unit.
-I don't see the point of that. I want to declare self-referential data
-structures in pure packages. Of course, the creation routines have to
+I don't see the point of that. I want to declare self-referential data
+structures in pure packages. Of course, the creation routines have to
be elsewhere (eg in an impure child).
-> That seems more prudent for now. If we decide to allow
+> That seems more prudent for now. If we decide to allow
> storage-size-zero access types in pure packages in general,
> then we could examine allowing T'Class_Access there as well.
>
@@ -445,9 +523,9 @@
> declared in a (virtual) impure child of Pure_Pkg, which is only visible
> to impure packages that "with" Pure_Pkg.
-Sounds ugly to me. I don't like inventing all kinds of implicit junk
-all over. I advocate allowing it in the pure package, unless we
-actually have semantic problems with that. We already agreed that you
+Sounds ugly to me. I don't like inventing all kinds of implicit junk
+all over. I advocate allowing it in the pure package, unless we
+actually have semantic problems with that. We already agreed that you
can't do alligators.
*************************************************************
@@ -457,15 +535,15 @@
Robert A Duff wrote:
>
-> > I think there is an important benefit. At least *I* would presume
+> > I think there is an important benefit. At least *I* would presume
> > that T'Access would be an access-to-T type rather than an access-to-T'Class
-> > type. Also, T'Class_Access is clearly only appropriate for tagged
+> > type. Also, T'Class_Access is clearly only appropriate for tagged
> > types, whereas T'Access seems like a perfectly reasonable thing to
> > allow for any kind of type.
>
> But none of that is likely to cause bugs.
-It is bound to cause confusion, in my view. Also, we might
+It is bound to cause confusion, in my view. Also, we might
eventually want to allow T'Access as a generall anonymous access-to-T.
If we used T'Access to mean access-to-T'Class, we would have eliminated
that possibility.
@@ -479,42 +557,42 @@
> I'm not particularly advocating that.
That is where I started, but I rejected that because again it
-implied more generality than was provided. Note that T'Class'Access
+implied more generality than was provided. Note that T'Class'Access
is the same number of characters as T'Class_Access ;-)
> ... I advocate allowing it in the pure package, unless we
-> actually have semantic problems with that. We already agreed that you
+> actually have semantic problems with that. We already agreed that you
> can't do alligators.
The semantic problems have to do with shared passive partitions, which
are allowed to depend on pure packages, but which are not allowed to
have access-to-class-wide objects, since they implicitly involve
pointers to code that is potentially not as long-lived as the
-shared passive partition. I agree it is a side issue, but it is
-a thorny one. Perhaps the right answer is to presume that shared
+shared passive partition. I agree it is a side issue, but it is
+a thorny one. Perhaps the right answer is to presume that shared
passive partitions need their own rules to prevent dangling references,
and not to try too hard to make the rules of pure library units
worry about them.
On the other hand, we do need some well defined criteria for deciding
-what can go in a pure package. One goal is side-effect-freeness, but
+what can go in a pure package. One goal is side-effect-freeness, but
with access parameters and access discriminants, that is pretty
-much out the window. The other goal is ability to replicate freely
+much out the window. The other goal is ability to replicate freely
among different partitions, since it has no "state" of its own.
Perhaps the side-effect-freeness can be resurrected if we limit
ourselves to cases where the parameters have no access-type parts.
I suppose another way to say it is that the only side-effects are
through parameters and data accessible via access-type parts of
-parameters. There is no variable "state" visible via up-level
-references that could be altered. We should probably also disallow
+parameters. There is no variable "state" visible via up-level
+references that could be altered. We should probably also disallow
the declaration of constants with any aliased parts, so the pure
package remains position independent, and hence freely replicable.
So I guess I am convinced -- force them to have storage size 0,
-and allow them in pure packages. Similarly, we should allow
+and allow them in pure packages. Similarly, we should allow
normal access-type declarations in pure packages, but with
the storage size implicitly zero, while disallowing constants
-with aliased parts. Shared passive packages will
+with aliased parts. Shared passive packages will
need some amended rules to deal with the allowance of
access types in pure packages.
@@ -523,7 +601,7 @@
From: Gary Dismukes
Sent: Tuesday, April 04, 2000 2:11 PM
-> It is bound to cause confusion, in my view. Also, we might
+> It is bound to cause confusion, in my view. Also, we might
> eventually want to allow T'Access as a generall anonymous access-to-T.
> If we used T'Access to mean access-to-T'Class, we would have eliminated
> that possibility.
@@ -534,7 +612,7 @@
of an attribute T'univ_access which would allow implicit
conversions to any access-to-D where D covers T and
from any access-to-D where T covers D, but not restricted
-to tagged types. It probably makes sense to restrict
+to tagged types. It probably makes sense to restrict
the conversions so that it only goes towards one of these
special types, but what's the reason for limiting it
to class-wide types? Is it just because the main benefit
@@ -585,16 +663,16 @@
> are allowed to depend on pure packages, but which are not allowed to
> have access-to-class-wide objects, since they implicitly involve
> pointers to code that is potentially not as long-lived as the
-> shared passive partition. I agree it is a side issue, but it is
-> a thorny one. Perhaps the right answer is to presume that shared
+> shared passive partition. I agree it is a side issue, but it is
+> a thorny one. Perhaps the right answer is to presume that shared
> passive partitions need their own rules to prevent dangling references,
> and not to try too hard to make the rules of pure library units
> worry about them.
-Yes. They can have some extra rules.
+Yes. They can have some extra rules.
> On the other hand, we do need some well defined criteria for deciding
-> what can go in a pure package. One goal is side-effect-freeness, but
+> what can go in a pure package. One goal is side-effect-freeness, but
> with access parameters and access discriminants, that is pretty
> much out the window.
@@ -602,29 +680,29 @@
on globals, whereas side effects on parameters (or what they point to)
are OK.
->... The other goal is ability to replicate freely
+>... The other goal is ability to replicate freely
> among different partitions, since it has no "state" of its own.
> Perhaps the side-effect-freeness can be resurrected if we limit
> ourselves to cases where the parameters have no access-type parts.
> I suppose another way to say it is that the only side-effects are
> through parameters and data accessible via access-type parts of
-> parameters. There is no variable "state" visible via up-level
-> references that could be altered. We should probably also disallow
+> parameters. There is no variable "state" visible via up-level
+> references that could be altered. We should probably also disallow
> the declaration of constants with any aliased parts, so the pure
> package remains position independent, and hence freely replicable.
-I'm not sure I understand that. Could you give an example?
+I'm not sure I understand that. Could you give an example?
> So I guess I am convinced ...
-Cool. It's not easy to convince Tucker of something. Not because he's
-stubborn, but because he's usually right. ;-)
+Cool. It's not easy to convince Tucker of something. Not because he's
+stubborn, but because he's usually right. ;-)
>... -- force them to have storage size 0,
-> and allow them in pure packages. Similarly, we should allow
+> and allow them in pure packages. Similarly, we should allow
> normal access-type declarations in pure packages, but with
> the storage size implicitly zero, while disallowing constants
-> with aliased parts. Shared passive packages will
+> with aliased parts. Shared passive packages will
> need some amended rules to deal with the allowance of
> access types in pure packages.
@@ -647,13 +725,13 @@
> and "with type," the 'Class_Access seemed a smaller, more
> manageable change.
-I see it as a general feature. I think it's a serious flaw in Ada 95
+I see it as a general feature. I think it's a serious flaw in Ada 95
that you have to write all kinds of type conversions that are perfectly
-safe. A type conversion ought to be a red flag, saying "I'm
+safe. A type conversion ought to be a red flag, saying "I'm
deliberately violating the type rules", but that doesn't work if you
-have to constantly "cry wolf". You can convert implicitly from T2 to
+have to constantly "cry wolf". You can convert implicitly from T2 to
T1'Class (where T2 is new T1) and you ought to be able to do the
-analogous thing for pointer-to-T2 and pointer-to-T1'Class. The
+analogous thing for pointer-to-T2 and pointer-to-T1'Class. The
'Class_Access idea solves that.
> I also think the proposed potentially-null anonymous access
@@ -783,7 +861,7 @@
> compilers hosted on memory-limited hosts. (Perhaps that doesn't matter
> anymore??)
-I'm not sure why it is expensive. But I do think nobody should be
+I'm not sure why it is expensive. But I do think nobody should be
running compilers on anything less than a 32-bit address space.
(Target machines are often smaller, though.)
@@ -858,10 +936,10 @@
> change people's minds, and I think there is considerable merit in the majority
> viewpoint, so I see no argument for reopening this issue.
-I see no merit whatsoever in the majority viewpoint. Most programs I've
+I see no merit whatsoever in the majority viewpoint. Most programs I've
seen (or written) declare exactly one access type per designated type,
-right after the designated type is declared. So in practise, people are
-*not* taking advantage of strongly typed access types. Contrast this
+right after the designated type is declared. So in practise, people are
+*not* taking advantage of strongly typed access types. Contrast this
with (for example) integer types, where most programmers define a new
integer type for each distinct purpose in the program.
@@ -870,16 +948,16 @@
conversions all over the place for perfectly safe cases (eg,
access-to-T2'Class converted to access-to-T1'Class, where T2 is derived
from T1, so conversions from T2'Class to T1'Class are of course
-implicit). These bogus type conversions damage readability. And part
+implicit). These bogus type conversions damage readability. And part
of the solution that has been discussed involves the T'Access idea.
> By the way, the idea of putting this unreferenced type where it is was
> precisely to provide a standard string access type, does anyone use it
> this way?
-I doubt it. Lots of programs don't use unbounded strings, so it
-wouldn't occur to the programmer to use this type. But it's harmless,
-so no change is needed. We're certainly not going to delete the type,
+I doubt it. Lots of programs don't use unbounded strings, so it
+wouldn't occur to the programmer to use this type. But it's harmless,
+so no change is needed. We're certainly not going to delete the type,
and we're certainly not going to add a new type to package Standard.
*************************************************************
@@ -919,7 +997,7 @@
Isn't it *always* the name of the instance? I mean, even if we chose to
call it T'Pointer, we would have a problem, because the attribute would
-be unusable inside the type. Not a big problem, but it would be
+be unusable inside the type. Not a big problem, but it would be
annoying, because access types are quite often used to make
self-referential record types.
@@ -943,7 +1021,7 @@
> Isn't it *always* the name of the instance? I mean, even if we chose to
> call it T'Pointer, we would have a problem, because the attribute would
-> be unusable inside the type. Not a big problem, but it would be
+> be unusable inside the type. Not a big problem, but it would be
> annoying, because access types are quite often used to make
> self-referential record types.
@@ -953,7 +1031,7 @@
of the object in the case of an object prefix, hmm.
Anywya, as you say, the restriction within a type is annoying but
-doesn't seem like a major problem. You could still use a workaround
+doesn't seem like a major problem. You could still use a workaround
such as applying 'Access to a subtype name.
*************************************************************
@@ -1019,8 +1097,8 @@
pragma-pure packages.
I agree with you that String_Access is in a weird place.
-But it's harmless. If you don't want to use it,
-you can easily declare your own. Not ideal, but it works.
+But it's harmless. If you don't want to use it,
+you can easily declare your own. Not ideal, but it works.
*************************************************************
@@ -1033,23 +1111,23 @@
>package Strings (RM A.4.1).
>
Doing this would require (under current rules) changing package Strings
-from pure to preelaborated. This potentially breaks existing code; it
+from pure to preelaborated. This potentially breaks existing code; it
seems unlikely that a user would write an existing pure package that
depends on Strings, but it's certainly imaginable (e.g., by renaming the
exceptions).
Earlier someone asked if anyone ever used the access type in
-Strings.Unbounded. I have, two or three times. In each case, I knew other
+Strings.Unbounded. I have, two or three times. In each case, I knew other
parts of the program were using unbounded strings, so there was no cost to
-doing so. I believe however that I would do it in any case, since IMO most
+doing so. I believe however that I would do it in any case, since IMO most
large programs use unbounded strings at least once, and a small program
-won't be made a large one just by including one extra package. Even so, I
+won't be made a large one just by including one extra package. Even so, I
agree the type doesn't belong where it's put, and I have encountered at
least one space-constrained program for which this consideration mattered.
Perhaps a least bad solution would be to put the type in its own small
child of Strings, and make the type in Strings.Unbounded be a "renaming as
-subtype" of that type. This would (I think) be entirely compatible with
+subtype" of that type. This would (I think) be entirely compatible with
the existing state of affairs.
*************************************************************
@@ -1064,7 +1142,7 @@
> Perhaps a least bad solution would be to put the type in its own small
> child of Strings, and make the type in Strings.Unbounded be a "renaming as
-> subtype" of that type. This would (I think) be entirely compatible with
+> subtype" of that type. This would (I think) be entirely compatible with
> the existing state of affairs.
Hey, I think that's a brilliant idea.
@@ -1118,7 +1196,7 @@
OK.
But it *was* brought up again, independently, as part of the solution to
-some other AI. I can't remember which. (*Editor's note: This one!*)
+some other AI. I can't remember which. (*Editor's note: This one!*)
*************************************************************
@@ -1186,14 +1264,14 @@
> in text books, not in the RM. Also notes in informative annexes are a bit
> odd I would think.
-I guess they would be doubly informative. ;-)
+I guess they would be doubly informative. ;-)
> Although this is a summary and is informative, it is definitely written
> in the style of normative text, ...
In fact, this text is identical to the normative text in the body of the
-RM that describes these attributes. So it's not surprising that it's in
-the same style. ;-)
+RM that describes these attributes. So it's not surprising that it's in
+the same style. ;-)
In the source code for the RM (in Scribe), the attributes are written as
macro calls, which generate the inline text, and also send the same text
@@ -1204,15 +1282,15 @@
I think to build the Postscript version of the RM, you had to run Scribe
three times in a row, because the output of one run would get sucked up
-into the next run as input, and it had to "settle down". Sort of like
+into the next run as input, and it had to "settle down". Sort of like
bootstrapping a compiler.
-Randy is in the process of modernizing this software. ;-)
+Randy is in the process of modernizing this software. ;-)
>... so a note still needs to be labeled a
> note I would think.
-I tend to think it's not the job of ARG to teach people Ada. As Robert
+I tend to think it's not the job of ARG to teach people Ada. As Robert
says, there are textbooks.
*************************************************************
@@ -1230,15 +1308,15 @@
> This is a good idea in any case (that is, it can be done for the type in
> Strings.Unbounded even if Strings.Yoder never becomes part of Ada0X :-).
-I guess you're going to be famous, Mike. Nobody else has a predefined
-Ada package named after them. Hey, maybe the ARG could make money by
-letting large corporations put their names on things. Package Calendar
+I guess you're going to be famous, Mike. Nobody else has a predefined
+Ada package named after them. Hey, maybe the ARG could make money by
+letting large corporations put their names on things. Package Calendar
could be renamed package FleetBank, and so on.
Anyway, I'm not sure what you guys are getting at with efficient storage
-pools. What's special about String_Access? The fact that the
+pools. What's special about String_Access? The fact that the
designated type is an unconstrained array? Surely not the fact that
-it's predefined. What sort of special pool are you talking about, and
+it's predefined. What sort of special pool are you talking about, and
whatever it is, why wouldn't it be a good idea for *any* "type Mumble is
access all Unconstrained_Array;" that appears anywhere in any program?
@@ -1249,7 +1327,7 @@
I wrote:
-> I guess you're going to be famous, Mike. Nobody else has a predefined
+> I guess you're going to be famous, Mike. Nobody else has a predefined
> Ada package named after them.
Except for Ada herself, of course!
@@ -1261,20 +1339,20 @@
Bob Duff wrote:
>Anyway, I'm not sure what you guys are getting at with efficient storage
->pools. What's special about String_Access? The fact that the
+>pools. What's special about String_Access? The fact that the
>designated type is an unconstrained array? Surely not the fact that
->it's predefined. What sort of special pool are you talking about, and
+>it's predefined. What sort of special pool are you talking about, and
>whatever it is, why wouldn't it be a good idea for *any* "type Mumble is
>access all Unconstrained_Array;" that appears anywhere in any program?
String_Access is special because you can probably improve performance by
-making assumptions about the frequency of allocation of various lengths. A
+making assumptions about the frequency of allocation of various lengths. A
simpler possibility is to choose the algorithm so as to specifically
support Strings.Unbounded : this can be done by usiing a binary-buddy
-allocator when the length is a power of 2, for example. (I haven't
+allocator when the length is a power of 2, for example. (I haven't
actually tried any such scheme, so I suppose I should qualify my enthusiasm
-by saying that the idea is potentially good rather than good. But the idea
-of exploring such schemes is good. :-)
+by saying that the idea is potentially good rather than good. But the idea
+of exploring such schemes is good. :-)
If Ada had a predefined generic for vectors of variable length, it could
probably use the same allocator as that for Strings.Unbounded.
@@ -1287,19 +1365,19 @@
Sent: Monday, May 15, 2000 11:36 AM
Robert Duff wrote:
->I guess you're going to be famous, Mike. Nobody else has a predefined
->Ada package named after them. Hey, maybe the ARG could make money by
->letting large corporations put their names on things. Package Calendar
+>I guess you're going to be famous, Mike. Nobody else has a predefined
+>Ada package named after them. Hey, maybe the ARG could make money by
+>letting large corporations put their names on things. Package Calendar
>could be renamed package FleetBank, and so on.
-I would hate to have to buy dark glasses in order to travel incognito. :-)
+I would hate to have to buy dark glasses in order to travel incognito. :-)
So, let me propose Ada.Strings.Accesses as a name for this supposed package.
>Anyway, I'm not sure what you guys are getting at with efficient storage
>pools.
I should perhaps state that my experience makes me at least as inclined to
-worry about fragmentation behavior as efficiency. In either case, there is
+worry about fragmentation behavior as efficiency. In either case, there is
potential benefit in treating strings specially.
*************************************************************
@@ -1318,10 +1396,10 @@
Sent: Monday, October 1, 2001 10:44 AM
I believe that is at least part of the intent of the "!problem"
-section. Apparently the "problem" section of this AI was inadequate.
+section. Apparently the "problem" section of this AI was inadequate.
Also, in this case, we discussed the need quite a bit at the last
ARG meeting, so I was more focused on writing up the technical
-aspects of the proposal, than justifying its need. I do agree with
+aspects of the proposal, than justifying its need. I do agree with
the important of having a good justification.
*************************************************************
@@ -1402,10 +1480,10 @@
> proposal grew out an attempt to save "with type"; now that that has been
> scuttled, the need for this one is much less compelling.
-I don't see that as the primary justification. The major
+I don't see that as the primary justification. The major
need relates to the large number of unnecessary explicit
conversions when using Ada 95 for "normal" OO-style
-programming. The connection with "with type" was pretty
+programming. The connection with "with type" was pretty
remote, in my view.
>
@@ -1420,17 +1498,17 @@
access_definitions in component subtype indications, but with the
same rules as for discriminants, namely that the accessibility level
of the anon subtype is the same as the level of the enclosing composite
-object. This jibes with the fact that typically a set of objects that
+object. This jibes with the fact that typically a set of objects that
point at each other all have the same lifetime.
-I didn't adequately deal with allocators. I think if an allocator appears
+I didn't adequately deal with allocators. I think if an allocator appears
as the expression of a return statement, where the return type is specified
using an access_definition, then the storage pool to use for the allocator
-is determined by the caller. This creates a very useful capability for
+is determined by the caller. This creates a very useful capability for
a function to do an allocation in a storage pool determined by context.
This is a fundamental requirement for region-based memory allocation,
which is becoming recognized as the "thinking person's alternative" to
-full garbage collection. This argues for a uniform treatment of
+full garbage collection. This argues for a uniform treatment of
such functions, namely that they are implicitly passed both the "caller"
accessibility level and the target storage pool for allocators.
@@ -1440,10 +1518,10 @@
Sent: Tuesday, October 2, 2001 5:22 AM
-<<I don't see that as the primary justification. The major
+<<I don't see that as the primary justification. The major
need relates to the large number of unnecessary explicit
conversions when using Ada 95 for "normal" OO-style
-programming. The connection with "with type" was pretty
+programming. The connection with "with type" was pretty
remote, in my view.
>>
@@ -1604,11 +1682,11 @@
> variables" :-)
Well, to some extent, declaring a global variable is an overt invitation
-for modification by any code within its scope. The covertness problem
+for modification by any code within its scope. The covertness problem
with IN OUT parameters on functions is that there is no indication at
the point of the call that parameters might be modified, where such
parameters are likely to be local variables with no signal to the
-reader that they are modified by the function call. I believe this
+reader that they are modified by the function call. I believe this
problem was pointed out in C.A.R. Hoare's famous 1973 paper "Hints
on Programming Language Design".
@@ -1649,7 +1727,7 @@
or some third-party verification tool to assume or to check
that the function has no side-effects, I'd rather do that
check with a pragma, and allow/trust the user to do the
-right thing at the right time. Certainly this has been
+right thing at the right time. Certainly this has been
a very painful restriction for interfacing with other languages
that do not accept this point of dogma :-)
Questions? Ask the ACAA Technical Agent