Rationale Update for Ada 2012
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
generic
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
Put(My_Nice_Integer_Type'Image(N));
And now thanks to
AI-124,
this becomes
Put(N'Image);
Note that GNAT users have been writing N'Img
for a long time.
© 2016 John Barnes Informatics.