Rationale Update for Ada 2012

John Barnes
Contents   Index   References   Previous   Next 

Chapter 6: Iterators, pools, etc.

This area covers the new iterators introduced in Ada 2012 plus access types and storage pools but also various miscellaneous features.
The following Ada Issues cover this area:
Specifying the standard storage pool
Access values should never designate unaliased components
The actual for an untagged formal derived type cannot be tagged
Shared_Passive package restrictions
Details of the storage pool used when Storage_Size is specified
Enforcing legality for anonymous access components in record aggregates
Generalized iterators and discriminant-dependent components
Accessibility of explicitly aliased parameters of procedures and entries
9.3(2) does not work for anonymous access types
Missing rules for Discard_Names aspect
Variable state in pure packages
Missing aspect cases for Remote_Types
Accessibility rules need to take into account that a generic function is not a function
Iterator with indefinite cursor
Legality and exceptions of generalized loop iteration
Add Object'Image
Language-defined packages and aspect Default_Storage_Pool
Iterators of formal derived types
Bad subpool implementations
Pool_of_Subpool returns null when called too early
Dangling references
Meaning of subtype_indication in array component iterators 
These changes can be grouped as follows.
A number of issues concern default and standard storage pools in general (3, 43, 136) and some issues concern the newly introduced subpools (142, 145, 148).
Several issues concern clarifications and omissions regarding generalized iterators (47, 93, 120, 138, 151).
As ever there are issues regarding accessibility rules, anonymous access types and related topics (27, 46, 67, 70, 89).
There are some clarifications and omissions about package state such as Pure and Shared_Passive (38, 76, 85).
Finally, there are miscellaneous issues on derived types (36), Discard_Names (72), and Object'Image (124).

Remember that when we declare an access type we can specify which storage pool it is to use. If we do not specify one then the default is used. Originally this default was just the "standard pool". The pragma Default_Storage_Pool was introduced in Ada 2012. It enables the user to specify which pool is to be used by default if none is specified for the access type. Thus we might write
pragma Default_Storage_Pool(My_Pool);
Moreover, the parameter can be null thus
pragma Default_Storage_Pool(null);
which ensures that we must always specify the pool to be used and prevents any allocation by default. AI-3 enables us to go back to the standard pool by writing
pragma Default_Storage_Pool(Standard);
This additional argument means that there is a minor syntax change thus
storage_pool_indicator ::=
   storage_pool_name | null | Standard
Note that the indicator Standard has nothing to do with the package Standard as such.
AI-43 makes subtle changes to the behaviour of the aspect Storage_Size as applied to storage pools. Briefly, the pool used by an access type that has Storage_Size given must not allocate additional storage when the original amount is exhausted and no other type can use the same pool unless requested. So we might have
type T is access ...
for T'Storage_Size use 1000;
type S is access ...
for S'Storage_Pool use T'Storage_Pool;  -- share pools
Note that if we do give the aspect Storage_Size for a type then that implies the (implementation-defined) storage pool for the type and so we cannot also give the aspect Storage_Pool for that type. Contrariwise if we do give the pool explicitly by for example
for T'Storage_Pool use My_Pool;
then the storage size is determined by the behaviour of My_Pool and the aspect Storage_Size cannot be given explicitly (the writer of the pool will have had to declare a function Storage_Size as part of the implementation of the pool and that will act as the attribute.)
AI-136 concerns the use of default storage pools with language defined generic units. After some discussion it is concluded that the effect of specifying the aspect Default_Storage_Pool on an instance of a language-defined generic unit is implementation-defined. One consequence of this is that one cannot rely upon using the aspect Default_Storage_Pool to change the storage pool used by a container such as a linked list if the container is an instance of the language-defined container Doubly_Linked_List.
Three AIs concern subpools which were introduced in Ada 2012 and clarify a number of omissions. AI-142 simply says that Allocate_From_Subpool could be erroneous if not implemented in accordance with the given rules. AI-145 says that the function Pool_Of_Subpool returns null if called before calling the procedure Set_Pool_Of_Subpool (pretty obvious). AI-148 tidies up the loose wording regarding what happens when we deallocate subpools (all objects that were in them cease to exist of course so beware dangling references as usual).
There are some omissions regarding iterators which were added in Ada 2012. AI-138 concerns the inheritance of aspects such as Constant_Indexing and Iterator_Element. Remember that a type such as List in Doubly_Linked_Lists has aspects thus
type List is tagged private
   with Constant_Indexing => Constant_Reference,
              Variable_Indexing => Reference,
              Default_Iterator => Iterate,
              Iterator_Element => Element_Type;
If we derive a type from List then we cannot change Iterator_Element into something other than Element_Type. We say that these aspects are non-overridable (they could be confirmed).
The other AIs in this group (47, 93, 120, 151) concern the new generalized iterators and address a number of curious omissions.
It might be recalled that if we have an array of type T thus
type ATT is array (1 .. N) of T;
The_Array: ATT;
then rather than express iteration as
for I in The_Array'Range loop
   The_Array(I) := 99;    -- do something to The_Array(I)
end loop;
we can more briefly use of rather than in and write
for E of The_Array loop
   E := 99;              -- do something to component E
end loop;
Optionally we can give the subtype of E thus
for E: T of The_Array loop ...
AI-151 says that any subtype given must statically match that of the component of the array (obvious really). Adding T is essentially a comment to aid the reader but the kindly compiler checks that it is correct.
The other AIs of this group essentially come down to the same thing. Generalized iteration enables us to write something in a shorthand way. When the shorthand is expanded, what is done using the resulting long form must not be illegal. For example AI-AI-47 shows how we might appear to make the array object vanish, AI-93 says that exceptions might be raised and 120 covers problems with limitedness and constantness.
Access types and particularly the anonymous access types introduced in Ada 2005 are often a source of problems. AI-27 clarifies the behaviour of value conversions of composite objects. AI-67 clarifies the accessibility of explicitly aliased parameters. AI-46 addresses the issue of the legality of record components of anonymous access types. 70 covers issues of the master of tasks created by anonymous access types.
AI-89 is more interesting. It suggests that Ada programmers should carefully remember the golden rules "a generic function is not a function", "a generic procedure is not a procedure", and "a generic package is not a package". The details of the AI are a bit elusive but revolve around the above rules.
Another group of issues concern matters such as the state of packages. AI-76 shows how an apparently pure package could seem to have its state changed via tricks such as using a self-referential type. Such trickery is deemed erroneous.
AI-85 notes that we cannot permit giving the aspects Storage_Size or Storage_Pool for remote access to class wide types which are given in a package with the aspect Remote_Types.
AI-38 concerns packages that are Shared_Passive. Various rules concerning the misuse of access types are strengthened.
A curious error in the matching rules for generic parameters has long been overlooked and is corrected by AI-36. If a formal parameter of a generic unit is derived untagged, then a corresponding actual parameter must also be untagged. Thus if we have
   type T is private;
   type TT is new T;
package P ...
then we cannot instantiate P with a tagged type for TT. This has been wrong ever since Ada 95.
The pragma Discard_Names was introduced in Ada 95. It tells the compiler to throw away tedious tables of names at runtime associated with things such as Image and Value. AI-72 points out that Ada 2012 forgot to say that Discard_Names is now an aspect and can be given as such. So if we have an enumeration type with lots of long identifiers such as
type Greek is (alpha, beta, gamma, ... , omega);
then rather than separately giving
pragma Discard_Names(Greek);
we can add the aspect when the type is declared thus
type Greek is (alpha, beta, gamma, ... , omega)
   with Discard_Names;
Finally, AI-124 proudly announces the extension of the attribute Image to apply to objects as well as to types.
At the moment if a slovenly programmer wants to avoid the majesty of the full might of Integer_Text_IO to print out the value of N of some integer type such as My_Nice_Integer_Type (perhaps for diagnostic purposes) then they write
And now thanks to AI-124, this becomes
Note that GNAT users have been writing N'Img for a long time. 

Contents   Index   References   Previous   Next 
© 2016 John Barnes Informatics.