!standard 03.04.01(06) 03-10-22 AI95-00230/08 !standard 03.06(07) !standard 03.06(22/1) !standard 03.07(10) !standard 03.08(18/1) !standard 03.10(12) !standard 03.10(17) !standard 03.10.2(12) !standard 04.02(02) !standard 04.02(08) !standard 04.05.02(07) !standard 04.05.02(09) !standard 04.06(13) !standard 04.06(18) !standard 08.05.01(02) !standard 08.05.01(03) !standard 08.05.01(06) !standard 13.11(25) !class amendment 00-04-13 !status work item 00-10-27 !status ARG Approved 10-0-0 03-10-03 !status work item 00-04-13 !status received 00-04-13 !priority Medium !difficulty Hard !subject Generalized use of anonymous access types !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 and in object renamings. 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. With the current situation, large numbers of explicit conversions are 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. 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 storage pool. !proposal The "access_definition" syntactic category (see 3.10(6); also 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 object renaming declarations, component definitions, and for discriminants of non-limited types. The type associated with the renaming or the 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, 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. In addition, a renaming inherits the accessibility level from the renamed/actual 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 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 renamings, and having them preserve the accessibility level information, we avoid this possible problem. Because allowing constants but not variables introduced a non-orthogonality, we chose to allow renamings which can be used in most cases where a constant would have been useful. NOTE 2: We also considered allowing generic formal objects. However, this adds significantly to the complexity of the proposal, with relatively little added benefit. Just supporting it for IN mode formal objects would be feasible, as it would be nearly identical to the support required for IN parameters, and presumably use similar syntax, with no "mode" allowed. This seems like a possible further extension, probably having both minor cost and minor benefit.] Applying this general philosophy to the specific cases means that for a renaming, the level is the same as the level of the type of the renamed object. 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 their level from the initial value, and discriminants of limited types take their level from the enclosing composite *object* (as opposed to enclosing type). 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 anonymous access type. This implies the addition of the type universal_access. Having added this type, it makes sense to change the literal NULL to be of this type as well, for symmetry with numeric literals, and to avoid the need for a preference rule in resolving the type of "null" when using the universal_access equality operators. The storage pool to be used for an allocator of an anonymous access type is determined by the context in which it appears: a) As the value for an IN parameter, an anonymous storage pool whose storage is reclaimed when the function returns, or at the end of the or instantiation'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. 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. !wording Change 3.4.1(6) as follows: Universal Types Universal types are defined for (and belong to) the integer, real, [and] fixed point{, and access} classes, and are referred to in this standard as respectively, universal_integer, universal_real, [and] universal_fixed{, and universal_access}. These are analogous to class-wide types for these language-defined [numeric] classes. ... 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: ... 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 component 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 eliminate the list of places where access_definition occurs. (In both cases, this text is not required, and listing four places (access discriminant, access parameter, component_definition, and object_renaming_declaration) is awkward. Besides, we don't use text to list where subtype_indication [for instance] is allowed.) Add the following paragraph before 3.10.2(12): The accessibility level of the anonymous access type defined by an access_definition of an object_renaming_declaration is the same as that of the renamed object (view). Change paragraph 3.10.2(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.} Delete paragraph 4.2(2). Change paragraph 4.2(8) as follows: ... is of type universal_real. {The literal NULL is of type universal_access.} Add the following after paragraph 4.5.2(7): The following additional equality operators for the universal_access type are declared in package Standard for use with anonymous access types: function "="(Left, Right : universal_access) return Boolean function "/="(Left, Right : universal_access) return Boolean Add the following after paragraph 4.5.2(9): Name Resolution Rules At least one of the operands of the equality operators for universal_access shall be of an anonymous access type. Legality Rules The operands of the equality operators for universal_access shall be convertible to one another (see 4.6). Change paragraph 4.6(13) as follows: {If the target type is universal_access, then the operand type shall be an access type.} If the target type is a general access{-to-object} type, then the operand shall be {universal_access or} an access-to-object type. Further{, if not universal_access}: Change paragraph 4.6(18) as follows: If the target type is an access-to-subprogram type, then the operand type shall be {universal_access or} an access-to-subprogram type. Further{, if not universal_access}: Change paragraph 8.5.1(2) as follows: object_renaming_declaration ::= defining_identifier : subtype_mark RENAMES object_name; | defining_identifier : access_definition RENAMES object_name; Change paragraph 8.5.1(3) as follows: The type of the object_name shall resolve to the type determined by the subtype_mark{, or in the case where the type is defined by an access_definition, to an anonymous access type whose designated type is the same as that of the access_definition}. [NOTE: If AI-231 is adopted, then 8.5.1(4) should include a legality rule that requires the access_definition to be access-to-constant if and only if the renamed object is access-to-constant. This is type-specific information, which is included in a renames declaration.] Change paragraph 8.5.1(6) as follows: ... any constraint implied by the subtype_mark {or access_definition} of the object_renaming_declaration is ignored. Replace paragraph 13.11(25) by: The storage pool used for an allocator of an anonymous access type should be determined as follows: * If the allocator is initializing an access discriminant of an object of a limited type, and the discriminant is itself a subcomponent of an object being created by an outer allocator, then the storage pool used for the outer allocator should also be used for the allocator initializing the access discriminant; * Otherwise, the storage pool should be created at the point of the allocator, and be reclaimed when the allocated object becomes inaccessible. !example package P is type T is ... type Rec(D : access String := new String'("")) is record F : access T; -- in the absence of AI-231, will raise Constraint_Error -- if allowed to default initialize to null. G : access T'class := new T; end record; R : Rec := (D => new String'("Hello"), F => new T, G => new T); Y : access String renames R.D; function Fun(X : access Rec) return Integer; end P; package body P is function Fun(X : access Rec) return Integer Disc : access String renames X.D; begin return 123; end Fun; end P; !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, 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 will make no further mention of this problem; see AI-231 for more discussion of this issue.] Explicit access type conversions can be used to provide the desired substitutability, but scattering type conversions around muddies the waters, and makes it harder to find the few type conversions that are really "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 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, Erhard Ploedereder reported significant concerns among his students with the 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 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, and are not needed if we allow anonymous access types in component declarations. We have proposed to allow anonymous access types in object renamings, component definitions, and possibly function results. We considered broadening this to include stand-alone object declarations, and variables declared as [IN] OUT parameters or 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, 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, 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 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: Object renaming declarations with access_definitions are no harder to support than other renamings. Component declarations with access_definitions have no special accessibility level issues, because the level is determined just like a named access type. Other alternatives considered: 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. d) Implementations which materialize all implicit types would have problems, as there is no limit to the types that could be constructed (T'Access'Access, T'Access'Access'Access, etc.) !corrigendum 3.4.1(6) @drepl @xhang<@xterm Universal types are defined for (and belong to) the integer, real, and fixed point classes, and are referred to in this standard as respectively, @i, @i, and @i. These are analogous to class-wide types for these language-defined numeric classes. As with class-wide types, if a formal parameter is of a universal type, then an actual parameter of any type in the corresponding class is acceptable. In addition, a value of a universal type (including an integer or real @fa) is ``universal'' in that it is acceptable where some particular type in the class is expected (see 8.6).> @dby @xhang<@xterm Universal types are defined for (and belong to) the integer, real, fixed, and access point classes, and are referred to in this standard as respectively, @i, @i, @i, and @i. These are analogous to class-wide types for these language-defined classes. As with class-wide types, if a formal parameter is of a universal type, then an actual parameter of any type in the corresponding class is acceptable. In addition, a value of a universal type (including an integer or real @fa) is ``universal'' in that it is acceptable where some particular type in the class is expected (see 8.6).> !corrigendum 3.6(7) @drepl @xcode<@fa@ft<@b>@fa<] subtype_indication>> @dby @xcode<@fa@ft<@b>@fa<] subtype_indication | access_definition>> !corrigendum 3.6(22/1) @drepl The elaboration of a @fa that does not contain any per-object expressions creates the discrete subtype, and consists of the elaboration of the @fa or the evaluation of the @fa. The elaboration of a @fa that contains one or more per-object expressions is defined in 3.8. The elaboration of a @fa in an @fa consists of the elaboration of the @fa. The elaboration of any @fas and the elaboration of the @fa are performed in an arbitrary order. @dby The elaboration of a @fa that does not contain any per-object expressions creates the discrete subtype, and consists of the elaboration of the @fa or the evaluation of the @fa. The elaboration of a @fa that contains one or more per-object expressions is defined in 3.8. The elaboration of a @fa in an @fa consists of the elaboration of the @fa or @fa. The elaboration of any @fas and the elaboration of the @fa are performed in an arbitrary order. !corrigendum 3.7(10) @ddel A @fa for an access discriminant shall appear only in the declaration for a task or protected type, or for a type with the reserved word @b in its (full) definition or in that of one of its ancestors. In addition to the places where Legality Rules normally apply (see 12.3), this rule applies also in the private part of an instance of a generic unit. !corrigendum 3.8(18/1) @drepl Within the definition of a composite type, if a @fa or @fa (see 9.5.2) includes a @fa that denotes a discriminant of the type, or that is an @fa whose @fa denotes the current instance of the type, the expression containing the @fa is called a @i, and the @fa or @fa being defined is called a @i. For the elaboration of a @fa of a @fa or the @fa of an @fa for an entry family (see 9.5.2), if the @fa or @fa of the @fa or @fa is not a per-object constraint, then the @fa or @fa is elaborated. On the other hand, if the @fa or @fa is a per-object constraint, then the elaboration consists of the evaluation of any included expression that is not part of a per-object expression. Each such expression is evaluated once unless it is part of a named association in a discriminant constraint, in which case it is evaluated once for each associated discriminant. @dby Within the definition of a composite type, if a @fa or @fa (see 9.5.2) includes a @fa that denotes a discriminant of the type, or that is an @fa whose @fa denotes the current instance of the type, the expression containing the @fa is called a @i, and the @fa or @fa being defined is called a @i. For the elaboration of a @fa of a @fa or the @fa of an @fa for an entry family (see 9.5.2), if the component subtype is defined by an @fa or if the @fa or @fa of the @fa or @fa is not a per-object constraint, then the @fa, @fa, or @fa is elaborated. On the other hand, if the @fa or @fa is a per-object constraint, then the elaboration consists of the evaluation of any included expression that is not part of a per-object expression. Each such expression is evaluated once unless it is part of a named association in a discriminant constraint, in which case it is evaluated once for each associated discriminant. !corrigendum 3.10(12) @drepl An @fa defines an anonymous general access-to-variable type; the @fa denotes its @i. An @fa is used in the specification of an access discriminant (see 3.7) or an access parameter (see 6.1). @dby An @fa defines an anonymous general access-to-variable type; the @fa denotes its @i. !corrigendum 3.10(17) @drepl The elaboration of an access_definition creates an anonymous general access-to-variable type [(this happens as part of the initialization of an access parameter or access discriminant)]. @dby The elaboration of an access_definition creates an anonymous general access-to-variable type. !corrigendum 3.10.2(12) @drepl @xbullet @dby @xbullet of an @fa is the same as that of the renamed object (view).> @xbullet !corrigendum 4.2(2) @ddel The expected type for a literal @b shall be a single access type. !corrigendum 4.2(8) @drepl An integer literal is of type @i. A real literal is of type @i. @dby An integer literal is of type @i. A real literal is of type @i. The literal @b is of type @i. !corrigendum 4.5.2(7) @dinsa @xcode<@b "=" (Left, Right : T) @b Boolean @b "/="(Left, Right : T) @b Boolean> @dinss The following additional equality operators for the @i type are declared in package Standard for use with anonymous access types: @xcode<@b "=" (Left, Right : @i) @b Boolean @b "/="(Left, Right : @i) @b Boolean> !corrigendum 4.5.2(9) @dinsa @xcode<@b "<" (Left, Right : T) @b Boolean @b "<="(Left, Right : T) @b Boolean @b "@>" (Left, Right : T) @b Boolean @b "@>="(Left, Right : T) @b Boolean> @dinss @i<@s8> At least one of the operands of the equality operators for @i shall be of an anonymous access type. @i<@s8> The operands of the equality operators for @i shall be convertible to one another (see 4.6). !corrigendum 4.6(13) @drepl If the target type is a general access type, then the operand type shall be an access-to-object type. Further: @dby If the target type is @i, then the operand type shall be an access type. If the target type is a general access-to-object type, then the operand shall be @i or an access-to-object type. Further, if not @i: !corrigendum 4.6(18) @drepl If the target type is an access-to-subprogram type, then the operand type shall be an access-to-subprogram type. Further: @dby If the target type is an access-to-subprogram type, then the operand type shall be @i or an access-to-subprogram type. Further, if not @i: !corrigendum 8.5.1(2) @drepl @xcode<@fa@ft<@b>@fa< object_name;>> @dby @xcode<@fa@ft<@b>@fa< object_name; | defining_identifier : access_definition >@ft<@b>@fa< object_name;>> !corrigendum 8.5.1(3) @drepl The type of the @fa shall resolve to the type determined by the @fa. @dby The type of the @fa shall resolve to the type determined by the @fa, or in the case where the type is defined by an @fa, to an anonymous access type whose designated type is the same as that of the @fa. !corrigendum 8.5.1(6) @drepl An @fa declares a new view of the renamed object whose properties are identical to those of the renamed view. Thus, the properties of the renamed object are not affected by the @fa. In particular, its value and whether or not it is a constant are unaffected; similarly, the constraints that apply to an object are not affected by renaming (any constraint implied by the @fa of the @fa is ignored). @dby An @fa declares a new view of the renamed object whose properties are identical to those of the renamed view. Thus, the properties of the renamed object are not affected by the @fa. In particular, its value and whether or not it is a constant are unaffected; similarly, the constraints that apply to an object are not affected by renaming (any constraint implied by the @fa or @fa of the @fa is ignored). !corrigendum 13.11(25) @drepl A storage pool for an anonymous access type should be created at the point of an allocator for the type, and be reclaimed when the designated object becomes inaccessible. @dby The storage pool used for an @fa of an anonymous access type should be determined as follows: @xbullet is initializing an access discriminant of an object of a limited type, and the discriminant is itself a subcomponent of an object being created by an outer @fa, then the storage pool used for the outer @fa should also be used for the @fa initializing the access discriminant;> @xbullet, and be reclaimed when the allocated object becomes inaccessible. !ACATS test Tests should be created to check on the implementation of this feature. !appendix Randy Brukardt 00-04-13 This proposal was split out of the "with type" proposal (AI-00217) in April 2000. Some early conversation on this feature can be found in that AI's appendix. ************************************************************* From: Tucker Taft Sent: Monday, April 03, 2000 5:29 PM 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 that may be used as the type of a stand-alone object, record or 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 the Storage_Size for T'Class_Access is defined to be 0. Such an access type would very closely match the reference-type implicit conversion semantics of Java and C++, providing "substitutability" for access-to-tagged types in much the way that T'Class supports 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 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). T'Class_Access avoids some of the difficulties associated with the more general T'Access proposal, since it doesn't need to worry, e.g., about thin versus fat pointers, and loosens conversion rules only in the place where they seem most critical, namely dealing with conversions to access-to-'class types. The hope is that when combined with "with type T is tagged;", T'Class_Access will make bindings to Java-like languages much more straightforward both to create and to use. ************************************************************* From: Robert A Duff Sent: Tuesday, April 04, 2000 10:46 AM > How about if we get an e-mail discussion going, then? 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 readable "^T" and C's somewhat ugly "T*". I'm not against verbosity when it imparts useful information, so let's not have a discussion of verbodity in general! >...Allocators would raise Storage_Error, because > the Storage_Size for T'Class_Access is defined to be 0. Does this mean I can use T'Class_Access in a pragma-Pure package? ************************************************************* From: Tucker Taft Sent: Tuesday, April 04, 2000 11:44 AM 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 > "Class_". 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 types, whereas T'Access seems like a perfectly reasonable thing to allow for any kind of type. > >...Allocators would raise Storage_Error, because > > the Storage_Size for T'Class_Access is defined to be 0. > > Does this mean I can use T'Class_Access in a pragma-Pure package? 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 are already allowed in pure packages, it seems unnecessary 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. 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. 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. Conceptually, we could think of Pure_Pkg.T'Class_Access being implicitly declared in a (virtual) impure child of Pure_Pkg, which is only visible to impure packages that "with" Pure_Pkg. ************************************************************* From: Robert A Duff Sent: Tuesday, April 04, 2000 12:02 PM > 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 > 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. Another idea would be to call it T'Class'Access, presumably allowing: type T is tagged...; subtype S is T'Class; ... S'Access ... I'm not particularly advocating that. > 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 > are already allowed in pure packages, it seems unnecessary > 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. ;-) > 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 be elsewhere (eg in an impure child). > 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. > > Conceptually, we could think of Pure_Pkg.T'Class_Access being implicitly > 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 can't do alligators. ************************************************************* From: Tucker Taft Sent: Tuesday, April 04, 2000 1:16 PM Robert A Duff wrote: > > > 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 > > 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 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. > Another idea would be to call it T'Class'Access, presumably allowing: > > type T is tagged...; > subtype S is T'Class; > ... S'Access ... > > 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 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 > 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 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 with access parameters and access discriminants, that is pretty 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 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 normal access-type declarations in pure packages, but with the storage size implicitly zero, while disallowing constants with aliased parts. Shared passive packages will need some amended rules to deal with the allowance of access types in pure packages. ************************************************************* From: Gary Dismukes Sent: Tuesday, April 04, 2000 2:11 PM > 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. Tuck, can you comment on the reason for not generalizing the implicit conversion capability to arbitrary designated types? At the September meeting we were talking in terms 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 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 and anticipated use is for those, or is there some fundamental difficulty with the generalization to other types? Or are you just being conservative in your old age? ;-) ************************************************************* From: Tucker Taft Sent: Tuesday, April 04, 2000 2:59 PM > Tuck, can you comment on the reason for not generalizing > the implicit conversion capability to arbitrary designated > types? There were some concerns about access-to-unconstrained-array, and whether it is thin or fat. I suppose there would also be a lot of anonymous access types popping up all over, with the associated "=" and "/=", if 'univ_access applied to all types. The minutes indicate there were some concerns about representation, but I don't remember the details. > ... Is it just because the main benefit > and anticipated use is for those, or is there some fundamental > difficulty with the generalization to other types? Or are > you just being conservative in your old age? ;-) These are all good reasons ;-) Since this is really trying to help with Java interfacing and "with type," the 'Class_Access seemed a smaller, more manageable change. I also think the proposed potentially-null anonymous access parameter "access all T"/"access constant T" solves the interfacing-to-C-pointer-parameter problems in a better way than would a more general T'Univ_Access. ************************************************************* From: Robert A Duff Sent: Tuesday, April 04, 2000 5:15 PM > 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 > 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. > 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 > with access parameters and access discriminants, that is pretty > much out the window. I thought the goal was to prevent silent side effects -- ie side effects on globals, whereas side effects on parameters (or what they point to) are OK. >... 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 > 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? > 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. ;-) >... -- force them to have storage size 0, > 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 > need some amended rules to deal with the allowance of > access types in pure packages. Sounds good to me. ************************************************************* From: Robert A Duff Sent: Tuesday, April 04, 2000 5:24 PM > There were some concerns about access-to-unconstrained-array, and > whether it is thin or fat. I think Pascal raised a concern about a 64-bit machine, where it might make sense to have both 32-bit and 64-bit access types, where the user chooses by writing a rep clause. Pascal? > Since this is really trying to help with Java interfacing > 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 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 deliberately violating the type rules", but that doesn't work if you 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 'Class_Access idea solves that. > I also think the proposed potentially-null anonymous access > parameter "access all T"/"access constant T" solves the > interfacing-to-C-pointer-parameter problems in a better way than > would a more general T'Univ_Access. Agreed. ************************************************************* From: Robert Dewar Sent: Wednesday, April 05, 2000 1:09 PM <> VMS being an obvious example, just so that this does not seem to be only a theoretical concern. ************************************************************* From: Pascal Leroy Sent: Thursday, April 06, 2000 4:22 AM Yes, any proposal which assumes that "all accesses look the same" is flawed. The 32-vs.-64-bit access types is not a theoretical issue, we do just that on Alpha because people don't want to pay for 64-bit pointers when their data structures are much smaller than 2Gb. ************************************************************* From: Christoph Grein Sent: Monday, May 08, 2000 11:45 PM Subject: [Ada-Comment] Predefined Access Types !topic Predefined Access Types !reference RM95-A.4.5(7,8), RM95-3.6.3, RM95-3.10 !from Christoph Grein 2000-05-09 !keywords access types, String_Access !discussion The type String_Access and corresponding function Free in A.4.5(7,8) seem misplaced in this package. They are not used there at all. In the light of the fact that when strings are handled, very often (I would even say, virtually always) an access type is also needed even if package Ada.Strings.Unbounded is not used, I would propose to shift these declarations to the place where type String is defined, 3.6.3. [And correspondingly for wide strings A.4.7.] This removes programmers' need to declare their own access types to strings all over the place. In a step further, I would propose a new 'Access attribute for types: Given any type T, T'Access would denote the following predefined general access type type T'Access is access all T; This would be implicitly defined where T is defined. Correspondingly also the type T'Class'Access would be predefined where 'Class is defined. [There would have to be rule to prevent recursion: Since T'Access is also a type, T'Access'Access and so on should be ruled out as being predefined.] If this is accepted, the type String_Access can be defined as subtype String_Access is String'Access; ************************************************************* From: Randy Brukardt Sent: Tuesday, May 09, 2000 6:31 PM To: 'Ada-Comment List' > In the light of the fact that when strings are handled, very often (I would > even say, virtually always) an access type is also needed even if package > Ada.Strings.Unbounded is not used, I would propose to shift these declarations > to the place where type String is defined, 3.6.3. [And correspondingly for > wide strings A.4.7.] This would be a very bad idea. Introducing names in Standard is *very* incompatible with existing code, as the names in Standard cannot be hidden, and would override any names currently accessible by a use clause. For instance, if a program contained: package P is type String_Access is access all My_String; end P; procedure M is use P; V : String_Access; ... Your proposal would change V's type (silently!) from P.String_Access to Standard.String_Access. One place that would happen is for the declarations in Ada.Strings.Unbounded that started the discussion! Besides, your second proposal is a better way to accomplish the same thing without polluting Standard. > In a step further, I would propose a new 'Access attribute for types: > Given any type T, T'Access would denote the following > predefined general access type > > type T'Access is access all T; This proposal looks rather attractive, but would be quite expensive on compilers hosted on memory-limited hosts. (Perhaps that doesn't matter anymore??) In any case, this exact proposal was made by Bob Duff in response to another proposal. I will attach your comment to that AI (AI-00230), because I don't want to spend anyone's time on the first proposal. ************************************************************* From: Robert A Duff Sent: Wednesday, May 10, 2000 10:14 AM > > type T'Access is access all T; > This proposal looks rather attractive, but would be quite expensive on > 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 running compilers on anything less than a 32-bit address space. (Target machines are often smaller, though.) > In any case, this exact proposal was made by Bob Duff in response to another > proposal. Actually, I think it was Robert Dewar's idea; I supported it. ************************************************************* From: Robert Dewar Sent: Tuesday, May 09, 2000 7:46 PM I strongly agree that introducing names into standard is a bad idea. As for type'Access, let's give credit where credit is due, I pushed this idea strongly during the design process, but it was rejected. note that the proposal in its current form is in any case incompatible with the current language design, which ascribes a quite different meaning top to type'Access in certain contexts. The objection to my proposal at the time was strong and clearly the majority viewpoint. The basis of this objection was that providing this distinguished anonymous type would tend to decrease type safety by encouraging the use of this type instead of properly typed access types. I see nothing that would change people's minds, and I think there is considerable merit in the majority viewpoint, so I see no argument for reopening this issue. 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? ************************************************************* From: Randy Brukardt Sent: Wednesday, May 10, 2000 11:44 AM > 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 didn't even realize this type was in Ada.Strings.Unbounded until this comment, so for me at least, the answer is no. ************************************************************* From: Robert A Duff Sent: Wednesday, May 10, 2000 3:26 PM > I strongly agree that introducing names into standard is a bad idea. As Tuck is fond of pointing out, it's almost the same thing as adding a new reserved word to the language. > As for type'Access, let's give credit where credit is due, I pushed this > idea strongly during the design process, but it was rejected. Right. >... note that > the proposal in its current form is in any case incompatible with the > current language design, which ascribes a quite different meaning top > to type'Access in certain contexts. Heh? What's type'Access? > The objection to my proposal at the time was strong and clearly the majority > viewpoint. The basis of this objection was that providing this distinguished > anonymous type would tend to decrease type safety by encouraging the use of > this type instead of properly typed access types. I see nothing that would > 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 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 with (for example) integer types, where most programmers define a new integer type for each distinct purpose in the program. I think there *is* new information on the subject: people have realized from experience with Ada 95 that it's a big pain to have type 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 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, and we're certainly not going to add a new type to package Standard. ************************************************************* From: Gary Dismukes [dismukes@gnat.com] Sent: Wednesday, May 10, 2000 5:08 PM > >... note that > > the proposal in its current form is in any case incompatible with the > > current language design, which ascribes a quite different meaning top > > to type'Access in certain contexts. > > Heh? What's type'Access? I'm guessing that Robert's referring to the case where the prefix is a current instance name (looks like a type name, though technically it's the name of an object of course). ************************************************************* From: Robert Dewar Sent: Wednesday, May 10, 2000 7:48 PM Yup! That's what I was referring to, that is indeed the only context in which type'access can appear in the current language. ************************************************************* From: Robert A Duff Sent: Thursday, May 11, 2000 9:46 AM > > Heh? What's type'Access? > > I'm guessing that Robert's referring to the case where the prefix > is a current instance name (looks like a type name, though technically > it's the name of an object of course). 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 annoying, because access types are quite often used to make self-referential record types. ************************************************************* From: Robert Dewar [dewar@gnat.com] Sent: Thursday, May 11, 2000 3:47 AM To: ada-comment@ada-auth.org Subject: Re: [Ada-Comment] Predefined Access Types <> Much more significantly, within tasks and protected objects to denote the current concurrent object. ************************************************************* From: Gary Dismukes Sent: Thursday, May 11, 2000 1:34 PM > 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 > annoying, because access types are quite often used to make > self-referential record types. Yes, that's right, it will always denote the instance within the type, though I suppose that if a new attribute such as 'Pointer or whatever were used it could be defined to apply to the type 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 such as applying 'Access to a subtype name. ************************************************************* From: Robert Dewar Sent: Wednesday, May 10, 2000 7:52 PM <> Ah Bob, if you supported it, then you can't move for a reconsideration. To convince ourselves it is worth refighting this, we have to have at least one person change their minds :-) ************************************************************* From: Christoph Grein Sent: Thursday, May 11, 2000 12:00 AM > I strongly agree that introducing names into standard is a bad idea. OK, I see the point. > .... note that > the proposal in its current form is in any case incompatible with the > current language design, which ascribes a quite different meaning top > to type'Access in certain contexts. RM K(2): P'Access where P denotes a subprogram RM K(4): X'Access where X denotes an object Where is T'Access defined? Oh - within record type definitions where it stands for the current instance of the type. > 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? > No, I dislike the idea of withing Strings.Unbounded just for this type when I do not use any other operations of the package. So the type is really misplaced. The proper place in light of all the arguments presented seems to be package Strings (RM A.4.1). ************************************************************* From: Robert A Duff Sent: Thursday, May 11, 2000 7:28 AM > The proper place in light of all the arguments presented seems to be > package Strings (RM A.4.1). Package Strings has pragma Pure, which disallows access types. Come to think of it, Standard has pragma Pure, too, which is *another* reason we can't put type String_Access in Standard. By the way, I wish there were a way to declare access types without allocators; then we could allow *those* kinds of access types in 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. ************************************************************* From: Michael Yoder Sent: Thursday, May 11, 2000 10:11 AM Christopher Grein wrote: > >The proper place in light of all the arguments presented seems to be >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 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 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 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 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 the existing state of affairs. ************************************************************* From: Christoph Grein Sent: Friday, May 12, 2000 12:01 AM > Doing this would require (under current rules) changing package Strings > from pure to preelaborated. ... OK, I again see the point. > 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 > the existing state of affairs. Hey, I think that's a brilliant idea. An access to String is so often needed that it should be predefined in the language, and Michael's proposal just does this in an innocuous way. package Ada.Strings.Yoder is pragma Preelaborate(Yoder); type String_Access is access all String; procedure Free (X : in out String_Access); end Ada.Strings.Yoder; ************************************************************* From: Robert Dewar Sent: Friday, May 12, 2000 12:59 AM You can even imagine a special implementation of Ada.Strings;Yoder that would use some special storage pool to handle string accesses especially efficiently??? ************************************************************* From: Michael Yoder Sent: Friday, May 12, 2000 2:30 PM 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 :-). ************************************************************* From: Robert A Duff Sent: Thursday, May 11, 2000 8:21 PM > Bob, were you for or against type'Access the first time around? > I can't remember :-) Sometimes I can't remember what I was for or against in the past ;-), but in this case I've been for it, or something like it, all along. ... > Ah Bob, if you supported it, then you can't move for a reconsideration. > To convince ourselves it is worth refighting this, we have to have at > least one person change their minds :-) 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!*) ************************************************************* From: Robert Dewar Sent: Friday, May 12, 2000 12:57 AM Well I sure would like to see something like typ'Access come back if it can be figured out how to do it cleanly. ************************************************************* From: Christoph Grein Sent: Friday, May 12, 2000 12:14 AM > < stands for the current instance of the type. > >> > > Much more significantly, within tasks and protected objects to denote > the current concurrent object. > Thank you, Robert, for the details. Wouldn't it be a good idea to include T'Access with such a hint in Annex K? This annex is "informative", so IMO a good place for a statement like this. ************************************************************* From: Robert Dewar Sent: Friday, May 12, 2000 1:05 AM <> Well this already is in Annex K: 4 X'Access For a prefix X that denotes an aliased view of an object: THe case of subtype_name'Access is just a special case where subtype_name is defined to denote a specific aliased view, namely the current instance. It would be confusing to have an entry saying T'Access For a prefix that denotes a subtype T, ... since in this case T does not denote a subtype. I suppose one could argue for a note, but my feeling is that notes belong in text books, not in the RM. Also notes in informative annexes are a bit odd I would think. Although this is a summary and is informative, it is definitely written in the style of normative text, so a note still needs to be labeled a note I would think. ************************************************************* From: Robert A Duff Sent: Friday, May 12, 2000 1:14 PM > I suppose one could argue for a note, but my feeling is that notes belong > 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. ;-) > 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. ;-) 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 to a separate file, which gets sorted by attribute name, and then re-included back into Annex K. The pragmas have a similar mechanism. 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 bootstrapping a compiler. 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 says, there are textbooks. ************************************************************* From: Robert A Duff Sent: Friday, May 12, 2000 4:04 PM Mike and Robert, > Robert Dewar wrote: > >You can even imagine a special implementation of Ada.Strings;Yoder that > >would use some special storage pool to handle string accesses > >especially efficiently??? > > 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 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 designated type is an unconstrained array? Surely not the fact that 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? ************************************************************* From: Robert A Duff Sent: Friday, May 12, 2000 4:38 PM I wrote: > 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! ************************************************************* From: Michael Yoder Sent: Monday, May 15, 2000 9:25 AM 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 >designated type is an unconstrained array? Surely not the fact that >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 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 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. :-) If Ada had a predefined generic for vectors of variable length, it could probably use the same allocator as that for Strings.Unbounded. If the above is still overly concise, I'm willing to elaborate further. ************************************************************* From: Michael Yoder 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 >could be renamed package FleetBank, and so on. 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 potential benefit in treating strings specially. ************************************************************* From: Robert Dewar Sent: Monday, October 1, 2001 5:57 AM I think that all AI's that propose new features should have a section discussing the need for any work in the area. I am afraid we are going into the mode of language experts writing up things that would be nice to have, if we are not careful. ************************************************************* From: Tucker Taft 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. 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 the important of having a good justification. ************************************************************* From: Robert Dewar Sent: Monday, October 1, 2001 11:00 AM The important thing here is that the justification include some evidence that this is a real world issue, i.e. a purely technical nice-to-have justification is dubious. We need some real world examples or input. ************************************************************* From: Randy Brukardt Sent: Monday, October 1, 2001 8:05 PM Robert said: > I think that all AI's that propose new features should have a section > discussing the need for any work in the area. I am afraid we are going > into the mode of language experts writing up things that would be nice > to have, if we are not careful. As Tucker responded, this is the propose of the !problem section. If the !problem of an AI isn't convincing, then the AI has a (ahem) problem, no matter what the merits of the proposal. > The important thing here is that the justification include some evidence > that this is a real world issue, i.e. a purely technical nice-to-have > justification is dubious. We need some real world examples or input. My own guess is that is going to be hard to come by on this one. This proposal grew out an attempt to save "with type"; now that that has been scuttled, the need for this one is much less compelling. At least, this proposal gets rid of the run-time accessibility for every object that we had discussed at the last meeting. But I'm still concerned that static accessibility might not be enough to implement this (especially in shared generics, where the static level /= instantiation level). If I ever get some spare time, I'll have to think about this one some more. ************************************************************* From: Robert Dewar Sent: Monday, October 1, 2001 8:27 PM <> The important thing to realize about proposals for additions is that the dynamics have in my view shifted completely. In the old days, the ARG could via WG9 and ACATS essentially command all implementors to implement feature X and they had to jump. Now, at least speaking for ACT, but I suspect for other vendors too, the issue of whether new features get implemented is far more dependent on what real customers want. If a new feature is approved, or even "mandated" it will not get implemented unless customers need/want it implemented and resources are consequently available. That's why it is so important to make sure that real demand exists before we sit around designing neat features that would be nice to have. ************************************************************* From: Tucker Taft Sent: Monday, October 1, 2001 11:29 PM Randy Brukardt wrote: > ... > > The important thing here is that the justification include some evidence > > that this is a real world issue, i.e. a purely technical nice-to-have > > justification is dubious. We need some real world examples or input. > > My own guess is that is going to be hard to come by on this one. This > 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 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 remote, in my view. > > At least, this proposal gets rid of the run-time accessibility for every > object that we had discussed at the last meeting. But I'm still concerned > that static accessibility might not be enough to implement this (especially > in shared generics, where the static level /= instantiation level). > > If I ever get some spare time, I'll have to think about this one some more. In thinking about this more, I have concluded that we should allow 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 point at each other all have the same lifetime. 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 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 such functions, namely that they are implicitly passed both the "caller" accessibility level and the target storage pool for allocators. ************************************************************* From: Robert Dewar Sent: Tuesday, October 2, 2001 5:22 AM <> That's one level remote to me, I need a "major need" to be expressed in terms of actual people writing actual code with actual needs and examples. I am afraid that the ARG is trying to take on the job of requirements gathering for language enhancements without sufficient connection to the outside world. We haven't even asked *vendors* what they think is important, let alone asking actual Ada users. Language designers are not the right people to be deciding on what is really important to add. For example, if you were to ask ACT what the single most important feature needed was, I suspect it would be C++ interfacing features. I certainly can't remember any customer asking about "large number of unnecessary explicit conversions" :-) ************************************************************* From: Randy Brukardt Sent: Tuesday, October 2, 2001 1:18 PM > I am afraid that the ARG is trying to take on the job of requirements > gathering for language enhancements without sufficient connection to > the outside world. We haven't even asked *vendors* what they think is > important, let alone asking actual Ada users. Many vendors participate in this group, and have rarely been shy about expressing their views. Certainly, ACT has been happy to provide this at every opportunity. :-) But I would caution against using requests to vendors as the only criteria. The Ada community has a strong commitment to following standards, and thus I would not expect most customers to ask their vendor to "break" the standard. Therefore, I'd expect enhancement requests to vendors to involve areas outside of the standard (interfacing to other languages, additional provided packages, performance issues, etc.), and most of that isn't interesting to the ARG any. To take a specific example. When we were building Claw, we wasted a lot of time tracking down "bugs" caused by broken overridding (where we thought some routine was overridding, but wasn't due to a spelling error or missing parameter). We didn't run to a vendor (even though I probably could have convinced one to do something :-) to fix this: we just put it down to bad language design and lived with it. The only thing we did is mention it toward the end of our paper on Claw. Only when I wrote up an amendment AI on the topic (mainly to provide a fully fleshed out example AI to get comments on the format of an amendment) did I find out that many other people shared this frustration. I doubt anyone ran to ACT to ask for an enhancement here (although they might now that there is a fully defined solution). > Language designers are not the right people to be deciding on what is > really important to add. This is true, but I would argue that the majority of the ARG membership aren't "language designers" per se, but vendors and/or users of Ada. Of course, everyone is a "language designer" from time-to-time. > I need a "major need" to be expressed > in terms of actual people writing actual code with actual needs and > examples. For this particular AI, I certainly agree. So far as I remember, the problem was driven by complaints from Erhard's students. While these are "actual people", I have my doubts that they meet the "actual needs" qualification. Moreover, we built Claw (certainly a large O-O system) without running into this problem. I would much rather have "in out" parameters on functions (as that would fix a real problem that we have had with O-O programs) than this proposal [access parameters are not a real replacement for "in out" parameters, as the calls are much more complex]. ************************************************************* From: Robert Dewar Sent: Tuesday, October 2, 2001 1:44 PM <> There is a different between having some technical person participating in the ARG meetings, and getting formal input from vendors. <> The ARG should be more interested in such issues. yes, I know it is more fun for language designers to design neat new features -- and that's my point. Surely we should not use requests to vendors as the only criterion, but it's a better sole criterion than using the input from language designers as the only criterion. In fact we get a wide variety of requests from customers, after all, WITH TYPE is there because customers needed it, not because there was some AI suggesting it, as an example. <> Remember that in our environment, customers ask us if they have any questions or problems whatsoever in using Ada. All the time, they are asking us "how do we do this in Ada", or "can't we find a better way of doing things than this". So indeed we have lots of input of this kind, but I can't find many things that would be worth new language features. Right now, I think there is a real danger of designing language features that no one will implement, and thus making an updated standard irrelevant. <> The lack of in out parameters in functions, a restriction that as far as I can tell is, like the peculiar declaration ordering rules in 83, there only because someone thinks it is more consistent with some particular coding philosophy (*), is indeed a significant problem. Robert Dewar (*) I continue to find it odd that the design principle for functions in the Ada language is "functions can have arbitrary side effects, but no hint of this is allowed in the function specification. If you want to make a state change in a function, it cannot be done using IN OUT parameters in the spec, instead it must be done covertly using global variables" :-) ************************************************************* From: Dan Eilers Sent: Tuesday, October 2, 2001 2:13 PM Robert Dewar wrote: > (*) I continue to find it odd that the design principle for functions in > the Ada language is "functions can have arbitrary side effects, but no > hint of this is allowed in the function specification. If you want to > make a state change in a function, it cannot be done using IN OUT > parameters in the spec, instead it must be done covertly using global > variables" :-) Well, to some extent, declaring a global variable is an overt invitation 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 problem was pointed out in C.A.R. Hoare's famous 1973 paper "Hints on Programming Language Design". ************************************************************* From: Randy Brukardt Sent: Tuesday, October 2, 2001 3:08 PM Which of course applies equally to procedure calls. And I have been occassionally surprised by procedures modifying parameters, and it would be nice if that was identified in the call. But it seems about 20 years too late to complain about that... ************************************************************* From: Robert Dewar Sent: Tuesday, October 2, 2001 10:39 PM Fine, people who have this point of view can restrict their use of the language. No one suggests removing USE clauses just because some people think they are a bad idea. ************************************************************* From: Dave Emery Sent: Tuesday, October 2, 2001 2:10 PM At 14:44 -0400 10/2/01, dewar@GNAT.COM wrote: >... >The lack of in out parameters in functions, a restriction that as far as >I can tell is, like the peculiar declaration ordering rules in 83, there >only because someone thinks it is more consistent with some particular >coding philosophy (*), is indeed a significant problem. Can I vote for reconsidering/removing this (stupid) restriction? If one argument in favor of keeping it is to allow the compiler 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 a very painful restriction for interfacing with other languages that do not accept this point of dogma :-) ************************************************************* From: Randy Brukardt Sent: Tuesday, October 2, 2001 3:03 PM > The ARG should be more interested in such issues. yes, I know it is more > fun for language designers to design neat new features -- and that's my > point. I understand, but in practice, there haven't been much in the way of expanding the language. When I proposed the Ada.Directories package, there was a lot of opposition of "not important enough" (and you originally led the charge on that). As far as C++ interfacing goes, we discussed this at the Westboro meeting (September 1999), but no one had any proposals on what to do. The existing work was all rather implementation-dependent. (Ed was at that meeting, and presented various GNAT features to the group, but I don't recall if he was there for this discussion.) And so far as I know, nothing has been proposed since. > Remember that in our environment, customers ask us if they have any > questions or problems whatsoever in using Ada. All the time, they > are asking us "how do we do this in Ada", or "can't we find a better > way of doing things than this". So indeed we have lots of input of > this kind, but I can't find many things that would be worth > new language features. I also get questions of the sort of "how do you do X?", but I'm never thinking about new language features when I answer them. "Wait until 2006" doesn't seem likely to satisfy many customers! > Right now, I think there is a real danger of designing language features > that no one will implement, and thus making an updated standard irrelevant. Understandable, and AI-230 is certainly a possible offender in this area. > The lack of in out parameters in functions, a restriction that as far as > I can tell is, like the peculiar declaration ordering rules in 83, there > only because someone thinks it is more consistent with some particular > coding philosophy (*), is indeed a significant problem. I've always figured that I should have the power to re-open this issue, as I was one of the people who fought tooth-and-nail to keep it in Ada 95. The main reason is that the Janus/Ada intermediate code does not allow copy-back for function calls -- and changing this would be a very large change to the optimizer and code generator. (Function calls always discard their parameters.) My mind was changed by our work on Claw. The first problem was a query function: function Is_Something (Window : in Root_Window_Type) return Boolean is begin -- Long calculation involving several system calls. return Answer; end Is_Something; Is_Something (I forget the exact function involved) was likely to be called frequently, so I wanted to save the result I calculated in the Window object. So I added a component to save the value and a component to say whether the first component was, and got a compile-time error trying to set them. Ugh. The problem has occurred repeatedly during the development of Claw. Some operations that we would have preferred to be functions ended up as procedures since we needed to modify the object. On a few occasions, we used the fact that Claw objects are assignable, and "clones" of each other to work around the problem: function Is_Something (Window : in Root_Window_Type) return Boolean is Writable_Copy : Root_Window_Type'Class := Window; begin -- Modify components of Writable_Copy, which modifies the original object. return Answer; end Is_Something; But that is horrible (and inefficient). I've tried to raise the "in out" issue at the ARG meetings without success. People are afraid that the same old bunch of opponents (minus at least one -- me!) would resurface. ************************************************************* From: Tucker Taft Sent: Friday, February 1, 2002 11:54 AM Here is an update to ai-00230 on anonymous access types. I was able to resolve the problems that I had with them last time, while eliminating the mind-bending named subtypes of anonymous access types, but adding back components of an anonymous access type. I think it all works safely and usefully now, especially presuming the syntax for "access_definition" is generalized (see ai-231) to allow control over nullness, and constantness of the designated object. [See AI body for current proposal - Ed.] ************************************************************* Editor's notes, October 22, 2003 In creating !corrigendum sections for this AI, I noticed that several wording changes are needed only if AI-231 is approved. I moved these wording changes to that AI. AI-231 should be written to presume that AI-230 is approved (as it is ahead of AI-231 in the ARG process); in particular, the needed change to 8.5.1(4) should be included in AI-231. *************************************************************