Version 1.8 of ai05s/ai05-0262-1.txt

Unformatted version of ai05s/ai05-0262-1.txt version 1.8
Other versions for file ai05s/ai05-0262-1.txt

!standard 1.1.2(23)          11-12-15 AI05-0262-1/05
!standard 1.1.4(14.1/2)
!standard 2.1(4/2)
!standard 2.1(13/2)
!standard 2.1(14/2)
!standard 2.2(2/2)
!standard 2.2(5/2)
!standard 3.1(1)
!standard 3.2.4(0)
!standard 3.3(19)
!standard 3.5(30/2)
!standard 3.5.2(2/3)
!standard 3.5.2(3/2)
!standard 3.5.2(3.1/2)
!standard 3.5.2(3.2/2)
!standard 3.8.1(10)
!standard 3.8.1(11)
!standard 3.8.1(15)
!standard 3.9(25.1/2)
!standard 3.10.2(16.1/2)
!standard 4.3.3(18)
!standard 4.5.2(2)
!standard 4.5.2(9.7/2)
!standard 4.5.2(39)
!standard 4.5.7(0)
!standard 4.9(33)
!standard 4.9(34)
!standard 5.4(7)
!standard 5.5(9)
!standard 6.1.1(0)
!standard 6.2(3)
!standard 6.3.1(16/2)
!standard 6.3.1(18)
!standard 6.4.1(6)
!standard 6.6(3)
!standard 6.8(0)
!standard 7.4(6)
!standard 7.5(2.1/2)
!standard 7.6.1(13.1/2)
!standard 7.6.1(20)
!standard 9.10(7)
!standard 10.1.1(12.2/2)
!standard 10.1.1(12.3/2)
!standard 10.1.2(21/2)
!standard 10.1.2(22/2)
!standard 13.11(21)
!standard 13.11.2(16)
!standard 13.11.3(4)
!standard A.4.5(82.1/2)
!standard A.4.11(0)
!standard A.13(14)
!standard A.16(104/2)
!standard A.16(110/2)
!standard A.16(112/2)
!standard A.18.1(7/2)
!standard A.18.2(88/2)
!standard A.18.2(147/2)
!standard A.18.2(230/2)
!standard A.18.2(231/2)
!standard A.18.2(251/2)
!standard A.18.2(254/2)
!standard A.18.3(60/2)
!standard A.18.3(88/2)
!standard A.18.3(102/2)
!standard A.18.3(144/2)
!standard A.18.3(145/2)
!standard A.18.3(156/2)
!standard A.18.3(159/2)
!standard A.18.4(19/2)
!standard A.18.4(43/2)
!standard A.18.4(79/2)
!standard A.18.4(82/2)
!standard A.18.6(46/2)
!standard A.18.6(58/2)
!standard A.18.6(74/2)
!standard A.18.6(94/2)
!standard A.18.7(18/2)
!standard A.18.7(38/2)
!standard A.18.7(100/2)
!standard A.18.7(103/2)
!standard A.18.9(61/2)
!standard A.18.9(81/2)
!standard A.18.9(93/2)
!standard A.18.9(113/2)
!standard A.18.10(0)
!standard A.18.18(0)
!standard A.18.26(5/2)
!standard A.18.26(9/2)
!standard A.18.27(0)
!standard A.18.30(0)
!standard B(1)
!standard B.2(10.1/2)
!standard B.3(2/2)
!standard C.7.1(14)
!standard D.2.2(3.5/2)
!standard D.2.2(6.2/2)
!standard D.7(19.1/2)
!standard H.4(8/1)
!class presentation 11-07-27
!status Amendment 2012 11-07-27
!status ARG Approved 9-0-0 11-12-11
!status work item 11-07-27
!status received 11-07-21
!priority Medium
!difficulty Easy
!subject Rewordings from the Second Editorial Review
!summary
Change wording of existing approved AIs as suggested by various ARG members and the public during the second editorial review of the draft standard.
!question
Some of the new wording in the standard is unnecessarily confusing. Should we improve it? (Yes.)
!recommendation
(See Summary.)
!wording
[Note: /3 paragraph numbers are from draft 13.]
Add after 1.1.2(23):
* Annex Q, "Language-Defined Entities"
Modify 1.1.4(14.1/3), 2.2(2/2), 2.2(5/2), 3.5.2(3.2/2):
"...whose code [position]{point} is ..."
Modify 2.1(4/3), 2.1(14/2):
"...whose relative code [position]{point} ..."
Modify 2.1(13/2):
"...whose code [positions] {points} ..."
Add "access" to the list of anonymous types in 3.3.1(1).
Modify 3.2.4(12/3):
"...where [both operands are]{each operand is} predicate-static; or"
Add after 3.2.4(14/3):
A predicate shall not be specified for an incomplete subtype.
Replace 3.2.4(16/3) with:
The discrete_subtype_definition of a loop_parameter_specification shall not denote a subtype to which Dynamic_Predicate specifications apply.
The discrete_choice of a named_array_aggregate shall not denote a non-static subtype to which predicate specifications apply.
[Editor's note: The former rule is included in the new one, as a Dynamic_Predicate necessarily makes the subtype non-static.]
AARM Reason: This rule prevents non-contiguous dynamically bounded array aggregates, which could be expensive to check for. (Array aggregates have rules to prevent problems with static subtypes.) We define this rule here so that the runtime generic body check applies.
Add after 3.2.4(18/3):
A value satisfies a predicate if the predicate is True for that value.
Replace 3.3(19) by:
* a loop parameter unless specified to be a variable for a generalized loop (see 5.5.2);
* a choice parameter or entry index;
In 3.5(30/3), "sequence of character" should be "sequence of graphic characters". [This is the wording used in 'Image, this should be the same.]
Modify 3.5(56/3):
"...with a code [position] {point} smaller ..."
Modify 3.5.2(2/3, 3/2, 3.1/2):
"...code [positions]{points} of..."
Move the second sentence of 3.2.4(19/3) to after 3.2.4(16/3), and make it plural. Delete the second line of the AARM note after 3.2.4(19/3).
In 3.8.1(10), replace "expression" with "choice_expression" (two places).
Modify 3.8.1(10.1/3):
* A discrete_choice that is a subtype_indication covers all values (possibly none)
that belong to the subtype{ and that satisify the static predicate of the subtype (see 3.2.4)}.
AARM Ramification: A dynamic predicate is never allowed in this case (for variants and case_statements, a subtype with a dynamic predicate isn't static and thus isn't allowed in a discrete_choice, and for a choice in an aggregate, a dynamic predicate is explicitly disallowed - see 3.2.4).
Modify 3.8.1(15/3):
Replace "satisfy the predicate" with "satisfy its predicate" (two places).
Add "Is_Abstract, " to the list of 3.9(25.1/3).
Add to 3.10.2(16.1/2):
Similarly, the dependent_expression of a conditional_expression is considered to be used in a context if the conditional_expression itself is used in that context.
Modify 4.3.3(18):
In a named_array_aggregate {where all discrete_choices are static}[with more than one discrete_choice], no two discrete_choices are allowed to cover the same value (see 3.8.1); if there is no others choice, the discrete_choices taken together shall exactly cover a contiguous sequence of values of the corresponding index type.
AARM Reason: This has to apply even if there is only one static discrete_choice; a single choice has to represent a contiguous range (a subtype_mark with a static predicate might represent a discontiguous set of values). If the (single) choice is a dynamic subtype, we don't need to make this check as no predicates are allowed (see 3.2.4) and thus the range has to be contiguous.
Modify 4.5.2(2):
A membership test, using in or not in, determines whether or not a value belongs to {any} [a] given subtype or range, {is equal to any given value,} [or] has a tag that identifies a type that is covered by a given type{, or is convertible to and with accessibility level appropriate for a given access type}. Membership tests are allowed for all types.
Modify 4.5.2(9.8/3):
Replace the first sentence the the first word of the second sentence by:
If the profile of an explicitly declared primitive equality operator of an untagged record type is type conformant with that of the corresponding predefined equality operator, the declaration shall occur before the type is frozen. In addition, if ...
Add to 4.5.2(39):
Card in Clubs | Spades -- list membership test (see 3.5.1)
Modify 4.5.7(1/3):
[Another]{The other} kind of conditional_expression...
Replace 4.5.7(18/3) by:
If there is no else dependent_expression, the if_expression shall be of a boolean type.
Modify 4.9(32.6/3):
Replace "which" by "that" (two places).
Modify 4.9(34):
The expression is illegal if its evaluation fails a language-defined check other than Overflow_Check. {For the purposes of this evaluation, the assertion policy is assumed to be Check.}
AARM Reason: Assertion policies can control whether checks are made, but we don't want assertion policies to affect legality. For Ada 2012, subtype predicates are the only checks controlled by the assertion policy that can appear in static expressions.
Modify 5.4(7/3):
Replace "satisfy the predicate" with "satisfy its predicate" (two places), and add (see 3.2.4) after the first occurrence of "predicate". Remove last to "a"s in "If the selecting_expression is a name (including a type_conversion, a qualified_expression, or a function_call) having a static and..."
Modify 5.5(9):
... Otherwise, the sequence_of_statements is executed once for each value of the discrete subtype defined by the discrete_subtype_definition {that satisfies the predicate of the subtype} (or until the loop is left as a consequence of a transfer of control).
AARM Ramification: The predicate (if any) necessarily has to be a static predicate as a dynamic predicate is explicitly disallowed - see 3.2.4.
Add after 5.5(9):
Redundant[For details about the execution of a loop_statement with the iteration_scheme being for iterator_specification, see 5.5.2.]
Modify 6.1.1(3/3):
This aspect specifies a class-wide precondition for {an operation of a tagged type}[a callable entity] and its descendants; ...
Modify 6.1.1(5/3):
This aspect specifies a class-wide postcondition for {an operation of a tagged type}[a callable entity] and its descendants; ...
Modify 6.1.1(7/3):
"... This ensures {that }the expression..."
Insert after 6.1.1(18/3):
If the Assertion_Policy in effect at the point of a subprogram or entry declaration is Check, then preconditions and postconditions are considered to be @i<enabled> for that subprogram or entry.
Modify 6.1.1(20/3):
"{Within a postcondition expression, d}[D]enotes the value of X at the beginning of the execution of the subprogram or entry {to which the postcondition applies}..."
Split from 6.1.1(23/3):
"Use of this attribute is allowed only within a postcondition expression for F."
Modify 6.1.1(27/3):
"... For [a task or protected]{an} entry call..."
Modify 6.1.1(28/3):
"...[Ada.]Assertions.Assertion_Error..."
Modify 6.1.1(29/3):
If a precondition or postcondition check fails, the exception is raised at the point of the call[. The]{; the }exception cannot be handled inside the called subprogram{ or entry}. {Similarly, any exception raised by the evaluation of a precondition or postcondition expression is raised at the point of call.}
Modify 6.1.1(30/3): "... the checks that are performed [that]{to} verify ..."
Modify 6.1.1(33/3) by deleting the last sentence and replacing it by:
For a dispatching call, if the assertion policy in effect at the point of the declaration of the denoted callable entity is not the same as the assertion policy in effect at the point of the declaration of the invoked callable entity, it is unspecified whether any precondition or postcondition checks are made.
AARM Discussion: For a dispatching call with different policies, whether a check is made probably will be different for different checks, depending on whether the implementation makes them at the call site, in a wrapper, or inside the called subprogram or entry.
Modify 6.1.1(35/3):
"...[may]{need} not..." ["May not" is not allowed by ISO drafting rules - ED].
Replace the last sentence of 6.2(3/3) with: "A parameter of a by-copy type is passed by copy, unless the formal parameter is explicitly aliased."
Add "and" to the end of 6.3.1(16.1/3).
Modify 6.3.1(18/3): "...and {for} corresponding parameters [have]:"
Replace 6.3.1(18.1/3) by "* they have the same names; and"
Modify 6.6(3/3):
"...has the corresponding number of parameters{, and they are all of mode in}[of mode in and no other parameters]."
Modify 6.8(7/3):
"...subprogram_body {executes an implicit}[is equivalent to a] function body
Modify 7.4(6/3): "If the deferred constant declaration includes a subtype_indication {S} that defines a constrained subtype, then the constraint defined by the subtype_indication in the full declaration shall match [it]{the constraint defined by S} statically. ..."
Modify 7.5(2.1/3): "...a parenthesized expression{,} or qualified_expression..."
Modify 7.6.1(13.1/3): "...and {all} use of the objects..."
Modify 7.6.1(20.2/3): "...instead of {at} the first freezing point..."
Modify 9.10(7): "...accept_statement[.]{;}"
Modify 10.1.1(12.2/3): "For each [nested] package_declaration {occurring immediately within}[directly in]...
Modify 10.1.1(12.3/3): "...{occurring immediately within}[directly in]..."
Modify 10.1.2(21/3) and 10.1.2(22/3) by replacing "which" with "that".
Modify the end of 13.11(21.1/3): "...whose pool is P[ and]{, only at the following points}:
Modify the start of 13.11(21.5/3):
For [one]{each} of the calls of Allocate described above, P (equivalent to T'Storage_Pool) is passed as the Pool parameter. ...
Replace the first sentence of 13.11.2(16/3) with: "Evaluating a name that denotes a nonexistent object, or a protected subprogram or subprogram renaming whose associated object (if any) is nonexistent, is erroneous."
Add to the end of AARM 13.11.2(16.a/3): "The part about a subprogram renaming is intended to cover the case of a renaming of a prefixed view where the prefix object has been deallocated, or the case of a renaming of an entry or protected subprogram where the associated task or protected object has been deallocated."
Modify A.4.5(82.1/2): "...[routines]{subprograms}..."
Modify A.4.11(46/3):
"...defined by Annex C of ISO/IEC 10646 in 8 bits, big{-}endian {order}; and UTF_16LE corresponds to the UTF-16 encoding scheme {in}[on] 8 bits, little{-}endian {order}.
Modify A.4.11(48/3): "...BOM-16LE{,} and..."
Replace A.4.11(49/3-50/3) with:
Each of the Convert and Encode functions returns a UTF_String, UTF_8_String, or UTF_16_String value whose characters have position values that correspond to the encoding of the Item parameter according to the encoding scheme required by the function or specified by its Output_Scheme parameter. For UTF_8, no overlong encoding is returned. A BOM is included at the start of the returned string if the Output_BOM parameter is set to True. The lower bound of the returned string is 1.
Each of the Encode functions takes a String, Wide_String, or Wide_Wide_String Item parameter that is assumed to be an array of unencoded characters. Each of the Convert functions takes a UTF_String, UTF_8_String, or UTF_16_String Item parameter that is assumed to contain characters whose position values correspond to a valid encoding sequence according to the encoding scheme required by the function or specified by its Input_Scheme parameter.
Each of the Decode functions takes a UTF_String, UTF_8_String, or UTF_16_String Item parameter which is assumed to contain characters whose position values correspond to a valid encoding sequence according to the encoding scheme required by the function or specified by its Input_Scheme parameter, and returns the corresponding String, Wide_String, or value. The lower bound of the returned string is 1.
for each of the Convert and Decode functions, an initial BOM in the input that matches the expected encoding scheme is ignored, and a different initial BOM causes Encoding_Error to be propagated.
Modify A.4.11(54/3 and 55/3):
"...code[-]{ }point..."
Modify A.4.11(56/3): "... In particular{,} the characters ..."
Delete A.4.11(57/3-58/3) [these were moved above].
Modify A.4.11(72/3, 84/3, 96/3): "... UTF-16LE{,} ..."
For the description of all of the Encode functions in A.4.11, modify them similarly to the below:
{Returns the value of Item}[Encodes from String input, and generates an output] encoded in UTF-8, UTF-16LE or UTF-16BE [encoding] as specified by Output_Scheme.
For the description of all of the Decode functions in A.4.11, modify them similarly to the below:
{Returns the result of decoding Item, which is}[Decodes from input] encoded in UTF-8[, and returns the corresponding String value].
For the description of all of the Convert functions in A.4.11, modify them similarly to the below:
{Returns the value of Item (}[Converts from input] originally encoded in UTF-16{)}[ and generates an output] encoded in UTF-8.
Add after A.13(14):
These exceptions are also propagated by various other language-defined packages and operations, see the definition of those entities for other reasons that these exceptions are propagated.
AARM Reason: This clause is based in Ada 95. Later versions of Ada (starting with Technical Corrigendum 1) have added a number of additional places and reasons that cause these exceptions. In particular, TC1 says that stream attributes need to raise End_Error in some circumstances; Ada 2005 adds Ada.Directories and a number of new places and reasons that Name_Error and Use_Error are raised. There are more. We don't want to try to update this text (or even this note!) for every possible reason and place that might raise one of these exceptions, so we add this blanket statement.
[It's unfortunate that all of the places that exceptions are "propagated" by language-defined subprograms is not indexed, but that would be a huge amount of work - Editor.]
Modify the first sentence of A.16(104/3, 112/3): "... matching Pattern {and Filter}. ..."
Modify A.16(110/2): "...[routine]{subprogram}..."
Add after A.18.1(7/2):
"Capacity_Error is raised when the capacity of a container is exceeded."
Replace A.18.2(88.1/3), A.18.3(60.1/3), A.18.4(19.1/3), A.18.7(18.1/3), and A.18.10(78/3) with [replacing "<Vector>" by the name of the container, and <V> by the initial of the container]:
<Vector>'Write for a <Vector> object <V> writes Length(<V>) elements of the <vector> to the stream. It also may write additional information about the <vector>.
<Vector>'Read reads the representation of a <vector> from the stream, and assigns to Item a <vector> with the same length and elements as was written by <Vector>'Write.
Modify A.18.2(147.20/3): "...setting [Target's] {the} length {of Target} to be that of Source)."
Modify A.18.2(231/3), A.18.3(145/3), A.18.26(5/3), A.18.26(9/3): "... [How many]{The number of} times..."
Modify A.18.2(230.4/3) and A.18.3(144.4/3): "...If Start is No_Element, {then Constraint_Error is propogated}[the call is equivalent to Iterate (Container)]."
Modify A.18.2(251/2), A.18.3(156/2), A.18.4(79/2), A.18.7(100/2): "...that [contains]{previously contained} the ..."
Modify A.18.2(254/2), A.18.3(159/2), A.18.4(82/2), A.18.7(103/2): "...object{ and changing the length of the target object to the length of the source object}."
Modify A.18.3(88/3), A.18.4(43/3), A.18.7(38/3): "... Otherwise, {the operation is} equivalent..."
Replace A.18.3(102/3):
If Length (Container) <= Count, then Delete_First is equivalent to Clear (Container). Otherwise, it removes the first Count nodes from Container.
Add after A.18.6(46.1/3):
function Iterate (Container : in Map; Start : in Cursor) return Map_Iterator_Interfaces.Reversible_Iterator'Class;
In A.18.6(58/2) and A.18.9(81/2), put "predecessor" in italics and add an index entry.
Modify A.18.6(74/2): "...Otherwise{,} Previous returns a cursor designating the {predecessor }node {of}[that precedes] the one ..."
Add after A.18.6(94.2/3):
function Iterate (Container : in Map; Start : in Cursor) return Map_Iterator_Interfaces.Reversible_Iterator'Class;
if Start is not No_Element and does not designate an item in Container, then Program_Error is propagated. if Start is No_Element, then Constraint_Error is propagated. Iterate returns a reversible iterator object that will generate a value for the loop parameter designating each node in Container, starting with the node designated by Start and moving the cursor according to the successor relation when used as a forward iterator, or moving the cursor according to the predecessor relation when used as a reverse iterator. Tampering with the cursors of Container is prohibited while the iterator object exists (in particular, in the sequence_of_statements of the loop_statement whose iterator_specification denotes this object). The iterator object needs finalization.
Add after A.18.9(61.1/3):
function Iterate (Container : in Set; Start : in Cursor) return Set_Iterator_Interfaces.Reversible_Iterator'Class;
Modify A.18.9(93/2): "...Otherwise{,} Previous returns a cursor designating the {predecessor }element {of}[that precedes] the one ..."
Add after A.18.9(113.2/3):
function Iterate (Container : in Set; Start : in Cursor) return Set_Iterator_Interfaces.Reversible_Iterator'Class;
if Start is not No_Element and does not designate an item in Container, then Program_Error is propagated. if Start is No_Element, then Constraint_Error is propagated. Iterate returns a reversible iterator object that will generate a value for the loop parameter designating each element in Container, starting with the element designated by Start and moving the cursor according to the successor relation when used as a forward iterator, or moving the cursor according to the predecessor relation when used as a reverse iterator. Tampering with the cursors of Container is prohibited while the iterator object exists (in particular, in the <sequence_of_statements of the loop_statement whose iterator_specification denotes this object). The iterator object needs finalization.
Modify A.18.10(3/3):
...and has [no]{neither an} associated element value {nor any parent node}. ...
Modify A.18.10(5/3): "...[could]{can} be visited..."
Add "Delete_Subtree" and "Copy_Subtree" to the list in A.18.10(81/3).
Modify A.18.10(92/3): "... and a cursor [designated] {designating} the corresponding child..."
Modify A.18.10(94/3): "... with [a] cursor{s} designating the root node{s} of Left and Right."
Modify A.18.10(143/3): "... The search [checks] {traverses}..."
Modify A.18.10(145/3): "Find_In_Subtree searches [a subtree of the elements of Container] {the subtree rooted by Position} for an element equal to Item (using..." "... The search [checks] {traverses}..."
Modify A.18.10(161/3): "...; [in this case] Program_Error..."
Modify A.18.10(162/3, 165/3, 167/3):
"...and {Parent does not designate the parent node of of the node designated by Before}[Container.Parent (Before) is not equal to Parent], then..."
Replace "dependent elements" in A.18.10(173/3) with "descendant nodes".
Modify A.18.10(175/3, 177/3, 180/3):
"...and {Parent does not designate the parent node of of the node designated by Before}[Target.Parent (Before) is not equal to Parent], then..."
Modify A.18.10(182/3, 189/3):
"...and {Target_Parent does not designate the parent node of of the node designated by Before}[Target.Parent (Before) is not equal to Target_Parent], then..."
Modify A.18.10(228/3): "..object{ and changing the node count of the target object to that of the source object}."
Modify A.18.18(29/3, 30/3, 48/3, 49/3, 57/3, 60/3, 67/3): "tamper with elements" should be "tamper with the element".
Modify A.18.27(10/3): "...{is allowed to}[may]..."
Modify A.18.30(17/3): "... otherwise{,} Success..."
Move B.2(10.1/3) after B(1), add "...not provide any {optional} aspect, ...", and delete "following".
Modify B.3(2/2): "...types, constants{,} and ..."
Modify C.7.1(14):
"... Use of this attribute is allowed only inside an [entry_body or] accept_statement{, or entry_body after the entry_barrier,} corresponding to the entry_declaration denoted by E."
Modify D.2.2(3.5/2): "...one or more Priority_Specific_Dispatching pragmas{,} the dispatching policy..."
Modify D.2.2(6.2/2): "...one or more Priority_Specific_Dispatching pragmas{,} a task dispatching point..."
Modify D.7(19.3/3): "At run[-]{ }time, ..."
Replace H.4(8.1/3) with "There are no allocators of anonymous access types."
!discussion
These wording changes seem to be an improvement in readability and understandability, but are not intended to change the meaning of the words, except in the case of clear mistakes. The latter are listed below:
1.1.4(14.1/3), 2.1(4/3), 2.1(13/2), 2.1(14/2), 2.2(2/2), 3.5(56/3), 3.5.2(2-3/2): ISO/IEC 10646:2011 defines the term "code point", and defines "code position" as meaning the same. However, 10646 never uses "code position" other than this single definition while it uses "code point" extensively. We want to be consistent with the 10646 usage, as we mean the 10646 definition here. Moreover, "code position" (defined by 10646) can be possibly confused with "position number" (defined by 8652).
3.3(19): 5.5.2(8/3) specifies that some loop parameters are variables; this wording had better reflect that.
6.1.1(3/3, 5/3): the term "descendant" is not defined for subprograms, so the original wording is dubious. The formal definition in 6.1.1(18/3) is correct, but too wordy to use in this introductory text.
6.1.1(29/3): All exceptions that could be raised from the evaluation of a pre- or postcondition should be raised at the point of the call. It's best to say that, since the expressions could be evaluated inside the body.
6.1.1(33/3): We don't want the fact that checks can be turned on or off to affect the implementation. In the case of a dispatching call, checks made at the call site might have a different assertion policy than checks made in the subprogram body (or in a wrapper). So we don't specify whether those checks are made in that case. We expect that most users will turn assertions on or off for the whole program anyway, in which case this won't make any difference.
7.4(6/3): There is no matching defined between constraints and subtypes. We have to match two constraints.
10.1.1(12.2/3, 12.3/3): "directly in" is not defined, while "immediately within" is a defined term, so we prefer that.
13.11.2(16/3): It was pointed out that there were similar cases for subprogram renamings, as explained in the AARM note.
A.4.11(58/3): We need to say that the parameters to Encode and Convert are assumed to be of the right form; for some reason, we only said that for Decode. In particular, none of the Encode functions make any effort to determine whether the Item parameter is already encoded (beyond checking for illegal characters).
A.4.11 function descriptions: The only purpose to these descriptions is to give the encodings for the parameter and/or result; all of the other rules are given in the blanket paragraphs at the start. Thus we want these are simple as possible.
A.18.2(88/2) and similar: An unfriendly reading of this text could lead one to believe that ONLY elements can be written to the stream, and not additional information about empty elements, ordering, hashing, keys, and so on. Thus we rewrite it.
A.18.2(230.4/3) and A.18.3(144.4/3) [also in A.18.6(94.2/3) and A.18.9(113.2/3) changes]: We change Start = No_Element to raise Constraint_Error, because no other semantics seems right for most uses. Starting nowhere does not make much sense.
A.18.2(254/2), A.18.3(159/2), A.18.4(82/2), A.18.7(103/2), A.18.10(228/3): An unfriendly reading of this text could cause one to imagine that the Length of the target is unchanged (if long enough). So we added some additional wording to ensure that no one thinks that.
A.18.3(102/3): We replace the wording proposed in AI05-0021-1 with wording parallel to that for Delete_Last. The previous wording raised Constraint_Error when deleting from an empty container using Delete_First, but that doesn't make much sense: the result of the operation ought to be a empty container (it is always allowed to ask to delete more nodes than are present).
A.18.6(46.1/3), A.18.6(94.2/3), A.18.9(49.1/3), A.18.9(99.2/3): There should be versions of the iterators that start at a particular position for the ordered forms. It's more dubious to iterate only part of a mapped form (as there is no defined ordering) and part of a subtree (starting a depth-first traversal in the middle doesn't make much sense).
A.18.6(58/2) and A.18.9(81/2): These are the defining occurrences; only ordered forms have "predecessors".
A.18.10(162/3, 165/3, 167/3, 175/3, 177/3, 180/3, 182/3, 189/3): The Container.Parent (Before) text was supposed to represent a prefix call. Unfortunately, the function Parent has no Container parameter, so this call is impossible. In addition, most of these functions have a Parent parameter, so just saying "Parent" would be ambiguous. Thus we change the wording to give the full definition of the Parent operation; it's not that much longer and it prevents any confusion.
B.2(10.1/3): This text occurs in the middle of B.2, and then talks about the "following" clauses. It should apply to the whole Annex, because clearly we don't want people supporting, say, the Export aspect in some bizarre way for a foreign language.
C.7.1(14): A barrier should get the same result for any caller (presuming the same family index); that isn't likely to be true of 'Caller is included. Note that no compilers tested allowed E'Caller in a barrier; it is only the wording that seems to allow it.
!corrigendum 1.1.2(23)
Insert after the paragraph:
the new paragraph:
!corrigendum 1.1.4(14.1/2)
Replace the paragraph:
The delimiters, compound delimiters, reserved words, and numeric_literals are exclusively made of the characters whose code position is between 16#20# and 16#7E#, inclusively. The special characters for which names are defined in this International Standard (see 2.1) belong to the same range. For example, the character E in the definition of exponent is the character whose name is "LATIN CAPITAL LETTER E", not "GREEK CAPITAL LETTER EPSILON".
by:
The delimiters, compound delimiters, reserved words, and numeric_literals are exclusively made of the characters whose code point is between 16#20# and 16#7E#, inclusively. The special characters for which names are defined in this International Standard (see 2.1) belong to the same range. For example, the character E in the definition of exponent is the character whose name is "LATIN CAPITAL LETTER E", not "GREEK CAPITAL LETTER EPSILON".
!corrigendum 2.1(4/2)
Replace the paragraph:
The coded representation for characters is implementation defined (it need not be a representation defined within ISO/IEC 10646:2003). A character whose relative code position in its plane is 16#FFFE# or 16#FFFF# is not allowed anywhere in the text of a program.
by:
The coded representation for characters is implementation defined (it need not be a representation defined within ISO/IEC 10646:2003). A character whose relative code point in its plane is 16#FFFE# or 16#FFFF# is not allowed anywhere in the text of a program. The only characters allowed outside of comments are those in categories other_format, format_effector, and graphic_character.
!corrigendum 2.1(13/2)
Replace the paragraph:
format_effector
The characters whose code positions are 16#09# (CHARACTER TABULATION), 16#0A# (LINE FEED), 16#0B# (LINE TABULATION), 16#0C# (FORM FEED), 16#0D# (CARRIAGE RETURN), 16#85# (NEXT LINE), and the characters in categories separator_line and separator_paragraph.
by:
format_effector
The characters whose code points are 16#09# (CHARACTER TABULATION), 16#0A# (LINE FEED), 16#0B# (LINE TABULATION), 16#0C# (FORM FEED), 16#0D# (CARRIAGE RETURN), 16#85# (NEXT LINE), and the characters in categories separator_line and separator_paragraph.
!corrigendum 2.1(14/2)
Replace the paragraph:
graphic_character
Any character which is not in the categories other_control, other_private_use, other_surrogate, other_format, format_effector, and whose code position is neither 16#FFFE# nor 16#FFFF#.
by:
graphic_character
Any character which is not in the categories other_control, other_private_use, other_surrogate, other_format, format_effector, and whose code point is neither 16#FFFE# nor 16#FFFF#.
!corrigendum 2.2(2/2)
Replace the paragraph:
The text of a compilation is divided into lines. In general, the representation for an end of line is implementation defined. However, a sequence of one or more format_effectors other than the character whose code position is 16#09# (CHARACTER TABULATION) signifies at least one end of line.
by:
The text of a compilation is divided into lines. In general, the representation for an end of line is implementation defined. However, a sequence of one or more format_effectors other than the character whose code point is 16#09# (CHARACTER TABULATION) signifies at least one end of line.
!corrigendum 2.2(5/2)
Replace the paragraph:
by:
!corrigendum 3.2.4(0)
Insert new clause:
Force a conflict; the real text is found in the conflict file.
!corrigendum 3.3(19)
Replace the paragraph:
by:
!corrigendum 3.3.1(1)
Replace the paragraph:
An object_declaration declares a stand-alone object with a given nominal subtype and, optionally, an explicit initial value given by an initialization expression. For an array, task, or protected object, the object_declaration may include the definition of the (anonymous) type of the object.
!corrigendum 3.5(30/2)
Replace the paragraph:
The function returns an image of the value of Arg as a Wide_String. The lower bound of the result is one. The image has the same sequence of character as defined for S'Wide_Wide_Image if all the graphic characters are defined in Wide_Character; otherwise the sequence of characters is implementation defined (but no shorter than that of S'Wide_Wide_Image for the same value of Arg).
by:
The function returns an image of the value of Arg as a Wide_String. The lower bound of the result is one. The image has the same sequence of graphic characters as defined for S'Wide_Wide_Image if all the graphic characters are defined in Wide_Character; otherwise, the sequence of characters is implementation defined (but no shorter than that of S'Wide_Wide_Image for the same value of Arg).
!corrigendum 3.5(56/2)
Replace the paragraph:
An implementation may extend the Wide_Wide_Value, Wide_Value, Value, Wide_Wide_Image, Wide_Image, and Image attributes of a floating point type to support special values such as infinities and NaNs.
by:
An implementation may extend the Wide_Wide_Value, Wide_Value, and Value attributes of a character type to accept strings starting with "Hex_" (ignoring case) for graphics characters and those with a code point smaller than 16#100#, and three character strings of the form "'nongraphic character'".
!corrigendum 3.5.2(2/2)
Replace the paragraph:
The predefined type Character is a character type whose values correspond to the 256 code positions of Row 00 (also known as Latin-1) of the ISO/IEC 10646:2003 Basic Multilingual Plane (BMP). Each of the graphic characters of Row 00 of the BMP has a corresponding character_literal in Character. Each of the nongraphic positions of Row 00 (0000-001F and 007F-009F) has a corresponding language-defined name, which is not usable as an enumeration literal, but which is usable with the attributes Image, Wide_Image, Wide_Wide_Image, Value, Wide_Value, and Wide_Wide_Value; these names are given in the definition of type Character in A.1, "The Package Standard", but are set in italics.
by:
The predefined type Character is a character type whose values correspond to the 256 code points of Row 00 (also known as Latin-1) of the ISO/IEC 10646:2003 Basic Multilingual Plane (BMP). Each of the graphic characters of Row 00 of the BMP has a corresponding character_literal in Character. Each of the nongraphic characters of Row 00 has a corresponding language-defined name, which is not usable as an enumeration literal, but which is usable with the attributes Image, Wide_Image, Wide_Wide_Image, Value, Wide_Value, and Wide_Wide_Value; these names are given in the definition of type Character in A.1, "The Package Standard", but are set in italics.
!corrigendum 3.5.2(3/2)
Replace the paragraph:
The predefined type Wide_Character is a character type whose values correspond to the 65536 code positions of the ISO/IEC 10646:2003 Basic Multilingual Plane (BMP). Each of the graphic characters of the BMP has a corresponding character_literal in Wide_Character. The first 256 values of Wide_Character have the same character_literal or language-defined name as defined for Character. Each of the graphic_characters has a corresponding character_literal.
by:
The predefined type Wide_Character is a character type whose values correspond to the 65536 code points of the ISO/IEC 10646:2003 Basic Multilingual Plane (BMP). Each of the graphic characters of the BMP has a corresponding character_literal in Wide_Character. The first 256 values of Wide_Character have the same character_literal or language-defined name as defined for Character. Each of the graphic_characters has a corresponding character_literal.
!corrigendum 3.5.2(3.1/2)
Replace the paragraph:
The predefined type Wide_Wide_Character is a character type whose values correspond to the 2147483648 code positions of the ISO/IEC 10646:2003 character set. Each of the graphic_characters has a corresponding character_literal in Wide_Wide_Character. The first 65536 values of Wide_Wide_Character have the same character_literal or language-defined name as defined for Wide_Character.
by:
The predefined type Wide_Wide_Character is a character type whose values correspond to the 2147483648 code points of the ISO/IEC 10646:2003 character set. Each of the graphic_characters has a corresponding character_literal in Wide_Wide_Character. The first 65536 values of Wide_Wide_Character have the same character_literal or language-defined name as defined for Wide_Character.
!corrigendum 3.5.2(3.2/2)
Replace the paragraph:
The characters whose code position is larger than 16#FF# and which are not graphic_characters have language-defined names which are formed by appending to the string "Hex_" the representation of their code position in hexadecimal as eight extended digits. As with other language-defined names, these names are usable only with the attributes (Wide_)Wide_Image and (Wide_)Wide_Value; they are not usable as enumeration literals.
by:
The characters whose code point is larger than 16#FF# and which are not graphic_characters have language-defined names which are formed by appending to the string "Hex_" the representation of their code point in hexadecimal as eight extended digits. As with other language-defined names, these names are usable only with the attributes (Wide_)Wide_Image and (Wide_)Wide_Value; they are not usable as enumeration literals.
!corrigendum 3.8.1(10)
Replace the paragraph:
by:
!corrigendum 3.8.1(11)
Replace the paragraph:
by:
!corrigendum 3.8.1(15)
Replace the paragraph:
by:
!corrigendum 3.9(25.1/2)
Replace the paragraph:
Tag_Error is raised by a call of Descendant_Tag, Expanded_Name, External_Tag, Interface_Ancestor_Tag, Is_Descendant_At_Same_Level, or Parent_Tag if any tag passed is No_Tag.
by:
Tag_Error is raised by a call of Descendant_Tag, Expanded_Name, External_Tag, Interface_Ancestor_Tags, Is_Abstract, Is_Descendant_At_Same_Level, Parent_Tag, Wide_Expanded_Name, or Wide_Wide_Expanded_Name if any tag passed is No_Tag.
!corrigendum 3.10.2(16.1/2)
Replace the paragraph:
In the above rules, the operand of a view conversion, parenthesized expression or qualified_expression is considered to be used in a context if the view conversion, parenthesized expression or qualified_expression itself is used in that context.
by:
In the above rules, the operand of a view conversion, parenthesized expression or qualified_expression is considered to be used in a context if the view conversion, parenthesized expression or qualified_expression itself is used in that context. Similarly, the dependent_expression of a conditional_expression is considered to be used in a context if the conditional_expression itself is used in that context.
!corrigendum 4.3.3(18)
Replace the paragraph:
In a named_array_aggregate with more than one discrete_choice, no two discrete_choices are allowed to cover the same value (see 3.8.1); if there is no others choice, the discrete_choices taken together shall exactly cover a contiguous sequence of values of the corresponding index type.
by:
In a named_array_aggregate where all discrete_choices are static, no two discrete_choices are allowed to cover the same value (see 3.8.1); if there is no others choice, the discrete_choices taken together shall exactly cover a contiguous sequence of values of the corresponding index type.
!corrigendum 4.5.2(2)
Replace the paragraph:
A membership test, using in or not in, determines whether or not a value belongs to a given subtype or range, or has a tag that identifies a type that is covered by a given type. Membership tests are allowed for all types.
by:
A membership test, using in or not in, determines whether or not a value belongs to any given subtype or range, is equal to any given value, has a tag that identifies a type that is covered by a given type, or is convertible to and with accessibility level appropriate for a given access type. Membership tests are allowed for all types.
!corrigendum 4.5.2(9.7/2)
Insert after the paragraph:
the new paragraph:
If the profile of an explicitly declared primitive equality operator of an untagged record type is type conformant with that of the corresponding predefined equality operator, the declaration shall occur before the type is frozen. In addition, if the untagged record type has a nonlimited partial view, then the declaration shall occur in the visible part of the enclosing package. 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 4.5.2(39)
Replace the paragraph:
N not in 1 .. 10 -- range membership test Today in Mon .. Fri -- range membership test Today in Weekday -- subtype membership test (see 3.5.1) Archive in Disk_Unit -- subtype membership test (see 3.8.1) Tree.all in Addition'Class -- class membership test (see 3.9.1)
by:
N not in 1 .. 10 -- range membership test Today in Mon .. Fri -- range membership test Today in Weekday -- subtype membership test (see 3.5.1) Card in Clubs | Spades -- list membership test (see 3.5.1) Archive in Disk_Unit -- subtype membership test (see 3.8.1) Tree.all in Addition'Class -- class membership test (see 3.9.1)
!corrigendum 4.5.7(0)
Insert new clause:
Force a conflict; the real text is found in the conflict file.
!corrigendum 4.9(33)
Insert new clause:
Force a conflict; the real text is found in the conflict file.
!corrigendum 4.9(34)
Replace the paragraph:
>
by:
!corrigendum 5.4(7)
Replace the paragraph:
by:
!corrigendum 5.5(9)
Replace the paragraph:
For the execution of a loop_statement with a for iteration_scheme, the loop_parameter_specification is first elaborated. This elaboration creates the loop parameter and elaborates the discrete_subtype_definition. If the discrete_subtype_definition defines a subtype with a null range, the execution of the loop_statement is complete. Otherwise, the sequence_of_statements is executed once for each value of the discrete subtype defined by the discrete_subtype_definition (or until the loop is left as a consequence of a transfer of control). Prior to each such iteration, the corresponding value of the discrete subtype is assigned to the loop parameter. These values are assigned in increasing order unless the reserved word reverse is present, in which case the values are assigned in decreasing order.
by:
For the execution of a loop_statement with a for iteration_scheme, the loop_parameter_specification is first elaborated. This elaboration creates the loop parameter and elaborates the discrete_subtype_definition. If the discrete_subtype_definition defines a subtype with a null range, the execution of the loop_statement is complete. Otherwise, the sequence_of_statements is executed once for each value of the discrete subtype defined by the discrete_subtype_definition that satisfy the predicate of the subtype (or until the loop is left as a consequence of a transfer of control). Prior to each such iteration, the corresponding value of the discrete subtype is assigned to the loop parameter. These values are assigned in increasing order unless the reserved word reverse is present, in which case the values are assigned in decreasing order.
For details about the execution of a loop_statement with the iteration_scheme being for iterator_specification, see 5.5.2.
!corrigendum 6.1.1(0)
Insert new clause:
Force a conflict; the real text is found in the conflict file.
!corrigendum 6.2(3)
Replace the paragraph:
A type is a by-copy type if it is an elementary type, or if it is a descendant of a private type whose full type is a by-copy type. A parameter of a by-copy type is passed by copy.
by:
A type is a by-copy type if it is an elementary type, or if it is a descendant of a private type whose full type is a by-copy type. A parameter of a by-copy type is passed by copy, unless the formal parameter is explicitly aliased.
!corrigendum 6.3.1(16/2)
Replace the paragraph:
Two profiles are mode conformant if they are type-conformant, and corresponding parameters have identical modes, and, for access parameters or access result types, the designated subtypes statically match, or the designated profiles are subtype conformant.
by:
Two profiles are mode conformant if:
!corrigendum 6.3.1(18)
Replace the paragraph:
Two profiles are fully conformant if they are subtype-conformant, and corresponding parameters have the same names and default_expressions that are fully conformant with one another.
by:
Two profiles are fully conformant if they are subtype-conformant, if they have access-to-subprogram results whose designated profiles are fully conformant, and for corresponding parameters:
!corrigendum 6.6(3)
Replace the paragraph:
The subprogram_specification of a unary or binary operator shall have one or two parameters, respectively. A generic function instantiation whose designator is an operator_symbol is only allowed if the specification of the generic function has the corresponding number of parameters.
by:
The subprogram_specification of a unary or binary operator shall have one or two parameters, respectively. The parameters shall be of mode in. A generic function instantiation whose designator is an operator_symbol is only allowed if the specification of the generic function has the corresponding number of parameters, and they are all of mode in.
!corrigendum 6.8(0)
Insert new clause:
Force a conflict; the real text is found in the conflict file.
!corrigendum 7.4(6/2)
Replace the paragraph:
by:
!corrigendum 7.5(2.1/2)
Replace the paragraph:
In the following contexts, an expression of a limited type is not permitted unless it is an aggregate, a function_call, or a parenthesized expression or qualified_expression whose operand is permitted by this rule:
by:
In the following contexts, an expression of a limited type is not permitted unless it is an aggregate, a function_call, a parenthesized expression, or qualified_expression whose operand is permitted by this rule, or a conditional_expression all of whose dependent_expressions are permitted by this rule:
!corrigendum 7.6.1(13.1/2)
Replace the paragraph:
In the case of an expression that is a master, finalization of any (anonymous) objects occurs as the final part of evaluation of the expression.
by:
In the case of an expression that is a master, finalization of any (anonymous) objects occurs after completing evaluation of the expression and all use of the objects, prior to starting the execution of any subsequent construct.
!corrigendum 7.6.1(20)
Insert after the paragraph:
the new paragraph:
Implementation Permissions
If the execution of an allocator propagates an exception, any parts of the allocated object that were successfully initialized may be finalized as part of the finalization of the innermost master enclosing the allocator.
The implementation may finalize objects created by allocators for an access type whose storage pool supports subpools (see 13.11.4) as if the objects were created (in an arbitrary order) at the point where the storage pool was elaborated instead of at the first freezing point of the access type.
!corrigendum 9.10(7)
Replace the paragraph:
by:
!corrigendum 10.1.1(12.2/2)
Replace the paragraph:
by:
!corrigendum 10.1.1(12.3/2)
Replace the paragraph:
by:
!corrigendum 10.1.2(21/2)
Replace the paragraph:
by:
!corrigendum 10.1.2(22/2)
Replace the paragraph:
by:
!corrigendum 13.11(21)
Insert after the paragraph:
If Storage_Pool is specified for an access type, then if Allocate can satisfy the request, it should allocate a contiguous block of memory, and return the address of the first storage element in Storage_Address. The block should contain Size_In_Storage_Elements storage elements, and should be aligned according to Alignment. The allocated storage should not be used for any other purpose while the pool element remains in existence. If the request cannot be satisfied, then Allocate should propagate an exception (such as Storage_Error). If Allocate behaves in any other manner, then the program execution is erroneous.
the new paragraph:
For each of the calls of Allocate described above, P (equivalent to T'Storage_Pool) is passed as the Pool parameter. The Size_In_Storage_Elements parameter indicates the number of storage elements to be allocated, and is no more than D'Max_Size_In_Storage_Elements, where D is the designated subtype of T. The Alignment parameter is at least D'Alignment if D is a specific type, and otherwise is at least the alignment of the specific type identified by the tag of the object being created. The Alignment parameter is no more than D'Max_Alignment_For_Allocation. The result returned in the Storage_Address parameter is used as the address of the allocated storage, which is a contiguous block of memory of Size_In_Storage_Elements storage elements. Any exception propagated by Allocate is propagated by the construct that contained the call.
!corrigendum 13.11.2(16)
Replace the paragraph:
Evaluating a name that denotes a nonexistent object is erroneous. The execution of a call to an instance of Unchecked_Deallocation is erroneous if the object was created other than by an allocator for an access type whose pool is Name'Storage_Pool.
by:
Evaluating a name that denotes a nonexistent object, or a protected subprogram or subprogram renaming whose associated object (if any) is nonexistent, is erroneous. The execution of a call to an instance of Unchecked_Deallocation is erroneous if the object was created other than by an allocator for an access type whose pool is Name'Storage_Pool.
!corrigendum 13.11.3(4)
Replace the paragraph:
The first_subtype_local_name of a pragma Controlled shall denote a non-derived access subtype.
by:
The storage_pool_name shall denote a variable.
If the pragma is used as a configuration pragma, the storage_pool_indicator shall be null, and it defines the default pool to be null within all applicable compilation units (see 10.1.5), except within the immediate scope of another pragma Default_Storage_Pool. Otherwise, Redundant[the pragma occurs immediately within a sequence of declarations, and] it defines the default pool within the immediate scope of the pragma to be either null or the pool denoted by the storage_pool_name, except within the immediate scope of a later pragma Default_Storage_Pool. Thus, an inner pragma overrides an outer one.
A pragma Default_Storage_Pool shall not be used as a configuration pragma that applies to a compilation unit that is within the immediate scope of another pragma Default_Storage_Pool.
!corrigendum A.4.5(82.1/2)
Replace the paragraph:
The function Unbounded_Slice returns the slice at positions Low through High in the string represented by Source as an Unbounded_String. The procedure Unbounded_Slice sets Target to the Unbounded_String representing the slice at positions Low through High in the string represented by Source. Both routines propagate Index_Error if Low > Length(Source)+1 or High > Length(Source).
by:
The function Unbounded_Slice returns the slice at positions Low through High in the string represented by Source as an Unbounded_String. The procedure Unbounded_Slice sets Target to the Unbounded_String representing the slice at positions Low through High in the string represented by Source. Both subprograms propagate Index_Error if Low > Length(Source)+1 or High > Length(Source).
!corrigendum A.4.11(0)
Insert new clause:
Force a conflict; the real text is found in the conflict file.
!corrigendum A.13(14)
Insert after the paragraph:
The exception Layout_Error is propagated (in text input-output) by Col, Line, or Page if the value returned exceeds Count'Last. The exception Layout_Error is also propagated on output by an attempt to set column or line numbers in excess of specified maximum line or page lengths, respectively (excluding the unbounded cases). It is also propagated by an attempt to Put too many characters to a string.
the new paragraph:
These exceptions are also propagated by various other language-defined packages and operations, see the definition of those entities for other reasons that these exceptions are propagated.
!corrigendum A.16(104/2)
Replace the paragraph:
Starts a search in the directory named by Directory for entries matching Pattern. Pattern represents a pattern for matching file names. If Pattern is null, all items in the directory are matched; otherwise, the interpretation of Pattern is implementation-defined. Only items that match Filter will be returned. After a successful call on Start_Search, the object Search may have entries available, but it may have no entries available if no files or directories match Pattern and Filter. The exception Name_Error is propagated if the string given by Directory does not identify an existing directory, or if Pattern does not allow the identification of any possible external file or directory. The exception Use_Error is propagated if the external environment does not support the searching of the directory with the given name (in the absence of Name_Error). When Start_Search propagates Name_Error or Use_Error, the object Search will have no entries available.
by:
Starts a search in the directory named by Directory for entries matching Pattern and Filter. Pattern represents a pattern for matching file names. If Pattern is the null string, all items in the directory are matched; otherwise, the interpretation of Pattern is implementation-defined. Only items that match Filter will be returned. After a successful call on Start_Search, the object Search may have entries available, but it may have no entries available if no files or directories match Pattern and Filter. The exception Name_Error is propagated if the string given by Directory does not identify an existing directory, or if Pattern does not allow the identification of any possible external file or directory. The exception Use_Error is propagated if the external environment does not support the searching of the directory with the given name (in the absence of Name_Error). When Start_Search propagates Name_Error or Use_Error, the object Search will have no entries available.
!corrigendum A.16(110/2)
Replace the paragraph:
Returns the next Directory_Entry for the search described by Search that matches the pattern and filter. If no further matches are available, Status_Error is raised. It is implementation-defined as to whether the results returned by this routine are altered if the contents of the directory are altered while the Search object is valid (for example, by another program). The exception Use_Error is propagated if the external environment does not support continued searching of the directory represented by Search.
by:
Returns the next Directory_Entry for the search described by Search that matches the pattern and filter. If no further matches are available, Status_Error is raised. It is implementation-defined as to whether the results returned by this subprogram are altered if the contents of the directory are altered while the Search object is valid (for example, by another program). The exception Use_Error is propagated if the external environment does not support continued searching of the directory represented by Search.
!corrigendum A.16(112/2)
Replace the paragraph:
Searches in the directory named by Directory for entries matching Pattern. The subprogram designated by Process is called with each matching entry in turn. Pattern represents a pattern for matching file names. If Pattern is null, all items in the directory are matched; otherwise, the interpretation of Pattern is implementation-defined. Only items that match Filter will be returned. The exception Name_Error is propagated if the string given by Directory does not identify an existing directory, or if Pattern does not allow the identification of any possible external file or directory. The exception Use_Error is propagated if the external environment does not support the searching of the directory with the given name (in the absence of Name_Error).
by:
Searches in the directory named by Directory for entries matching Pattern and Filter. The subprogram designated by Process is called with each matching entry in turn. Pattern represents a pattern for matching file names. If Pattern is the null string, all items in the directory are matched; otherwise, the interpretation of Pattern is implementation-defined. Only items that match Filter will be returned. The exception Name_Error is propagated if the string given by Directory does not identify an existing directory, or if Pattern does not allow the identification of any possible external file or directory. The exception Use_Error is propagated if the external environment does not support the searching of the directory with the given name (in the absence of Name_Error).
!corrigendum A.18.1(7/2)
Replace the paragraph:
Hash_Type represents the range of the result of a hash function. Count_Type represents the (potential or actual) number of elements of a container.
by:
Capacity_Error is raised when the capacity of a container is exceeded.
!corrigendum A.18.2(88/2)
Insert after the paragraph:
Execution of the default implementation of the Input, Output, Read, or Write attribute of type Cursor raises Program_Error.
the new paragraph:
Vector'Write for a Vector object V writes Length(V) elements of the vector to the stream. It also may write additional information about the vector.
Vector'Read reads the representation of a vector from the stream, and assigns to Item a vector with the same length and elements as was written by Vector'Write.
!corrigendum A.18.2(147/2)
Insert after the paragraph:
Force a conflict; the real text is found in the conflict file.
the new paragraph:
Nothing.
!corrigendum A.18.2(230/2)
Replace the paragraph:
Iterates over the elements in Container as per Iterate, except that elements are traversed in reverse index order.
by:
Iterates over the elements in Container as per procedure Iterate, except that elements are traversed in reverse index order.
function Iterate (Container : in Vector) return Vector_Iterator_Interfaces.Reversible_Iterator'Class;
Iterate returns a reversible iterator object that will generate a value for the loop parameter designating each node in Container, starting with the first node and moving the cursor as per the Next function when used as a forward iterator, and starting with the last node and moving the cursor as per the Previous function when used as a reverse iterator. Tampering with the cursors of Container is prohibited while the iterator object exists (in particular, in the sequence_of_statements of the loop_statement whose iterator_specification denotes this object). The iterator object needs finalization.
function Iterate (Container : in Vector; Start : in Cursor) return Vector_Iterator_Interfaces.Reversible_Iterator'Class;
If Start is not No_Element and does not designate an item in Container, then Program_Error is propagated. If Start is No_Element, then Constraint_Error is propagated. Otherwise, Iterate returns a reversible iterator object that will generate a value for the loop parameter designating each node in Container, starting with the node designated by Start and moving the cursor as per the Next function when used as a forward iterator, or moving the cursor as per the Previous function when used as a reverse iterator. Tampering with the cursors of Container is prohibited while the iterator object exists (in particular, in the sequence_of_statements of the loop_statement whose iterator_specification denotes this object). The iterator object needs finalization.
!corrigendum A.18.2(231/2)
Replace the paragraph:
The actual function for the generic formal function "<" of Generic_Sorting is expected to return the same value each time it is called with a particular pair of element values. It should define a strict ordering relationship, that is, be irreflexive, asymmetric, and transitive; it should not modify Container. If the actual for "<" behaves in some other manner, the behavior of the subprograms of Generic_Sorting are unspecified. How many times the subprograms of Generic_Sorting call "<" is unspecified.
by:
The actual function for the generic formal function "<" of Generic_Sorting is expected to return the same value each time it is called with a particular pair of element values. It should define a strict weak ordering relationship (see A.18); it should not modify Container. If the actual for "<" behaves in some other manner, the behavior of the subprograms of Generic_Sorting are unspecified. The number of times the subprograms of Generic_Sorting call "<" is unspecified.
!corrigendum A.18.2(251/2)
Replace the paragraph:
by:
!corrigendum A.18.2(254/2)
Replace the paragraph:
The execution of an assignment_statement for a vector shall have the effect of copying the elements from the source vector object to the target vector object.
by:
The execution of an assignment_statement for a vector shall have the effect of copying the elements from the source vector object to the target vector object and changing the length of the target object to that of the source object.
!corrigendum A.18.3(60/2)
Insert after the paragraph:
Execution of the default implementation of the Input, Output, Read, or Write attribute of type Cursor raises Program_Error.
the new paragraph:
List'Write for a List object L writes Length(L) elements of the list to the stream. It also may write additional information about the list.
List'Read reads the representation of a list from the stream, and assigns to Item a list with the same length and elements as was written by List'Write.
!corrigendum A.18.3(88/2)
Replace the paragraph:
If Target denotes the same object as Source, then Move has no effect. Otherwise, Move first calls Clear (Target). Then, the nodes in Source are moved to Target (in the original order). The length of Target is set to the length of Source, and the length of Source is set to 0.
by:
If Target denotes the same object as Source, then the operation has no effect. Otherwise, the operation is equivalent to Assign (Target, Source) followed by Clear (Source).
!corrigendum A.18.3(102/2)
Replace the paragraph:
Equivalent to Delete (Container, First (Container), Count).
by:
If Length (Container) <= Count, then Delete_First is equivalent to Clear (Container). Otherwise, it removes the first Count nodes from Container.
!corrigendum A.18.3(144/2)
Replace the paragraph:
Iterates over the nodes in Container as per Iterate, except that elements are traversed in reverse order, starting with the last node and moving the cursor as per the Previous function.
by:
Iterates over the nodes in Container as per procedure Iterate, except that elements are traversed in reverse order, starting with the last node and moving the cursor as per the Previous function.
function Iterate (Container : in List) return List_Iterator_Interfaces.Reversible_Iterator'Class;
Iterate returns a reversible iterator object that will generate a value for the loop parameter designating each node in Container, starting with the first node and moving the cursor as per the Next function when used as a forward iterator, and starting with the last node and moving the cursor as per the Previous function when used as a reverse iterator. Tampering with the cursors of Container is prohibited while the iterator object exists (in particular, in the sequence_of_statements of the loop_statement whose iterator_specification denotes this object). The iterator object needs finalization.
function Iterate (Container : in List; Start : in Cursor) return List_Iterator_Interfaces.Reversible_Iterator'Class;
If Start is not No_Element and does not designate an item in Container, then Program_Error is propagated. If Start is No_Element, then Constraint_Error is propogated. Otherwise, Iterate returns a reversible iterator object that will generate a value for the loop parameter designating each node in Container, starting with the node designated by Start and moving the cursor as per the Next function when used as a forward iterator, or moving the cursor as per the Previous function when used as a reverse iterator. Tampering with the cursors of Container is prohibited while the iterator object exists (in particular, in the sequence_of_statements of the loop_statement whose iterator_specification denotes this object). The iterator object needs finalization.
!corrigendum A.18.3(145/2)
Replace the paragraph:
The actual function for the generic formal function "<" of Generic_Sorting is expected to return the same value each time it is called with a particular pair of element values. It should define a strict ordering relationship, that is, be irreflexive, asymmetric, and transitive; it should not modify Container. If the actual for "<" behaves in some other manner, the behavior of the subprograms of Generic_Sorting are unspecified. How many times the subprograms of Generic_Sorting call "<" is unspecified.
by:
The actual function for the generic formal function "<" of Generic_Sorting is expected to return the same value each time it is called with a particular pair of element values. It should define a strict weak ordering relationship (see A.18); it should not modify Container. If the actual for "<" behaves in some other manner, the behavior of the subprograms of Generic_Sorting are unspecified. The number of times the subprograms of Generic_Sorting call "<" is unspecified.
!corrigendum A.18.3(156/2)
Replace the paragraph:
by:
!corrigendum A.18.3(159/2)
Replace the paragraph:
The execution of an assignment_statement for a list shall have the effect of copying the elements from the source list object to the target list object.
by:
The execution of an assignment_statement for a list shall have the effect of copying the elements from the source list object to the target list object and changing the length of the target object to that of the source object.
!corrigendum A.18.4(19/2)
Insert after the paragraph:
Execution of the default implementation of the Input, Output, Read, or Write attribute of type Cursor raises Program_Error.
the new paragraph:
Map'Write for a Map object M writes Length(M) elements of the map to the stream. It also may write additional information about the map.
Map'Read reads the representation of a map from the stream, and assigns to Item a map with the same length and elements as was written by Map'Write.
!corrigendum A.18.4(43/2)
Replace the paragraph:
If Target denotes the same object as Source, then Move has no effect. Otherwise, Move first calls Clear (Target). Then, each node from Source is removed from Source and inserted into Target. The length of Source is 0 after a successful call to Move.
by:
If Target denotes the same object as Source, then the operation has no effect. Otherwise, the operation is equivalent to Assign (Target, Source) followed by Clear (Source).
!corrigendum A.18.4(79/2)
Replace the paragraph:
by:
!corrigendum A.18.4(82/2)
Replace the paragraph:
The execution of an assignment_statement for a map shall have the effect of copying the elements from the source map object to the target map object.
by:
The execution of an assignment_statement for a map shall have the effect of copying the elements from the source map object to the target map object and changing the length of the target object to that of the source object.
!corrigendum A.18.6(46/2)
Insert after the paragraph:
procedure Reverse_Iterate (Container : in Map; Process : not null access procedure (Position : in Cursor));
the new paragraphs:
function Iterate (Container : in Map) return Map_Iterator_Interfaces.Reversible_Iterator'Class;
function Iterate (Container : in Map; Start : in Cursor) return Map_Iterator_Interfaces.Reversible_Iterator'Class;
!corrigendum A.18.6(58/2)
Replace the paragraph:
The first node of a nonempty map is the one whose key is less than the key of all the other nodes in the map. The last node of a nonempty map is the one whose key is greater than the key of all the other elements in the map. The successor of a node is the node with the smallest key that is larger than the key of the given node. The predecessor of a node is the node with the largest key that is smaller than the key of the given node. All comparisons are done using the generic formal "<" operator for keys.
by:
The first node of a nonempty map is the one whose key is less than the key of all the other nodes in the map. The last node of a nonempty map is the one whose key is greater than the key of all the other elements in the map. The successor of a node is the node with the smallest key that is larger than the key of the given node. The predecessor of a node is the node with the largest key that is smaller than the key of the given node. All comparisons are done using the generic formal "<" operator for keys.
!corrigendum A.18.6(74/2)
Replace the paragraph:
If Position equals No_Element, then Previous returns No_Element. Otherwise, Previous returns a cursor designating the node that precedes the one designated by Position. If Position designates the first element, then Previous returns No_Element.
by:
If Position equals No_Element, then Previous returns No_Element. Otherwise, Previous returns a cursor designating the predecessor node of the one designated by Position. If Position designates the first element, then Previous returns No_Element.
!corrigendum A.18.6(94/2)
Replace the paragraph:
Iterates over the nodes in Container as per Iterate, with the difference that the nodes are traversed in predecessor order, starting with the last node.
by:
Iterates over the nodes in Container as per procedure Iterate, with the difference that the nodes are traversed in predecessor order, starting with the last node.
function Iterate (Container : in Map) return Map_Iterator_Interfaces.Reversible_Iterator'Class;
Iterate returns a reversible iterator object that will generate a value for the loop parameter designating each node in Container, starting with the first node and moving the cursor according to the successor relation when used as a forward iterator, and starting with the last node and moving the cursor according to the predecessor relation when used as a reverse iterator. Tampering with the cursors of Container is prohibited while the iterator object exists (in particular, in the sequence_of_statements of the loop_statement whose iterator_specification denotes this object). The iterator object needs finalization.
function Iterate (Container : in Map; Start : in Cursor) return Map_Iterator_Interfaces.Reversible_Iterator'Class;
If Start is not No_Element and does not designate an item in Container, then Program_Error is propagated. If Start is No_Element, then Constraint_Error is propagated. Iterate returns a reversible iterator object that will generate a value for the loop parameter designating each node in Container, starting with the node designated by Start and moving the cursor according to the successor relation when used as a forward iterator, or moving the cursor according to the predecessor relation when used as a reverse iterator. Tampering with the cursors of Container is prohibited while the iterator object exists (in particular, in the sequence_of_statements of the loop_statement whose iterator_specification denotes this object). The iterator object needs finalization.
!corrigendum A.18.7(18/2)
!AI-0001-1
!AI-0212-1
!AI-0262-1
@dinsa Execution of the default implementation of the Input, Output, Read, or Write attribute of type Cursor raises Program_Error. @dinst Set'Write for a Set object @i<S> writes Length(@i<S>) elements of the set to the stream. It also may write additional information about the set.
Set'Read reads the representation of a set from the stream, and assigns to @i<Item> a set with the same length and elements as was written by Set'Write.
!corrigendum A.18.7(100/2)
Replace the paragraph:
by:
!corrigendum A.18.7(103/2)
Replace the paragraph:
The execution of an assignment_statement for a set shall have the effect of copying the elements from the source set object to the target set object.
by:
The execution of an assignment_statement for a set shall have the effect of copying the elements from the source set object to the target set object and changing the length of the target object to that of the source object.
!corrigendum A.18.9(61/2)
Insert after the paragraph:
procedure Iterate (Container : in Set; Process : not null access procedure (Position : in Cursor));
the new paragraphs:
function Iterate (Container : in Set) return Set_Iterator_Interfaces.Reversible_Iterator'Class;
function Iterate (Container : in Set; Start : in Cursor) return Set_Iterator_Interfaces.Reversible_Iterator'Class;
!corrigendum A.18.9(81/2)
Replace the paragraph:
The first element of a nonempty set is the one which is less than all the other elements in the set. The last element of a nonempty set is the one which is greater than all the other elements in the set. The successor of an element is the smallest element that is larger than the given element. The predecessor of an element is the largest element that is smaller than the given element. All comparisons are done using the generic formal "<" operator for elements.
by:
The first element of a nonempty set is the one which is less than all the other elements in the set. The last element of a nonempty set is the one which is greater than all the other elements in the set. The successor of an element is the smallest element that is larger than the given element. The predecessor of an element is the largest element that is smaller than the given element. All comparisons are done using the generic formal "<" operator for elements.
!corrigendum A.18.9(93/2)
Replace the paragraph:
If Position equals No_Element, then Previous returns No_Element. Otherwise Previous returns a cursor designating the element that precedes the one designated by Position. If Position designates the first element, then Previous returns No_Element.
by:
If Position equals No_Element, then Previous returns No_Element. Otherwise, Previous returns a cursor designating the predecessor element of the one designated by Position. If Position designates the first element, then Previous returns No_Element.
!corrigendum A.18.9(113/2)
!AI-0212-1
!AI-0262-1
!AI-0265-1
@drepl @xindent<Iterates over the elements in Container as per Iterate, with the difference that elements are traversed in predecessor order, starting with the last element.> @dby @xindent<Iterates over the elements in Container as per procedure Iterate, with the difference that the elements are traversed in predecessor order, starting with the last element.>
@xcode<@b<function> Iterate (Container : @b<in> Set)
@b<return> Map_Iterator_Interfaces.Reversible_Iterator'Class;>
@xindent<Iterate returns a reversible iterator object that will generate a value for the loop parameter designating each element in Container, starting with the first element and moving the cursor according to the successor relation when used as a forward iterator, and starting with the last element and moving the cursor according to the predecessor relation when used as a reverse iterator. Tampering with the cursors of Container is prohibited while the iterator object exists (in particular, in the @fa<sequence_of_statements> of the @fa<loop_statement> whose @fa<iterator_specification> denotes this object). The iterator object needs finalization.>
@xcode<@b<function> Iterate (Container : @b<in> Set; Start : @b<in> Cursor)
@b<return> Map_Iterator_Interfaces.Reversible_Iterator'Class;>
@xindent<If Start is not No_Element and does not designate an item in Container, then Program_Error is propagated. If Start is No_Element, then Constraint_Error is propagated. Iterate returns a reversible iterator object that will generate a value for the loop parameter designating each element in Container, starting with the element designated by Start and moving the cursor according to the successor relation when used as a forward iterator, or moving the cursor according to the predecessor relation when used as a reverse iterator. Tampering with the cursors of Container is prohibited while the iterator object exists (in particular, in the @fa<sequence_of_statements> of the @fa<loop_statement> whose @fa<iterator_specification> denotes this object). The iterator object needs finalization.>
!corrigendum A.18.10(0)
Insert new clause:
Force a conflict; the real text is found in the conflict file.
!corrigendum A.18.18(0)
Insert new clause:
Force a conflict; the real text is found in the conflict file.
!corrigendum A.18.26(5/2)
Replace the paragraph:
The actual function for the generic formal function "<" of Generic_Array_Sort is expected to return the same value each time it is called with a particular pair of element values. It should define a strict ordering relationship, that is, be irreflexive, asymmetric, and transitive; it should not modify Container. If the actual for "<" behaves in some other manner, the behavior of the instance of Generic_Array_Sort is unspecified. How many times Generic_Array_Sort calls "<" is unspecified.
by:
The actual function for the generic formal function "<" of Generic_Array_Sort is expected to return the same value each time it is called with a particular pair of element values. It should define a strict weak ordering relationship (see A.18); it should not modify Container. If the actual for "<" behaves in some other manner, the behavior of the instance of Generic_Array_Sort is unspecified. The number of times Generic_Array_Sort calls "<" is unspecified.
!corrigendum A.18.26(9/2)
Replace the paragraph:
The actual function for the generic formal function "<" of Generic_Constrained_Array_Sort is expected to return the same value each time it is called with a particular pair of element values. It should define a strict ordering relationship, that is, be irreflexive, asymmetric, and transitive; it should not modify Container. If the actual for "<" behaves in some other manner, the behavior of the instance of Generic_Constrained_Array_Sort is unspecified. How many times Generic_Constrained_Array_Sort calls "<" is unspecified.
by:
The actual function for the generic formal function "<" of Generic_Constrained_Array_Sort is expected to return the same value each time it is called with a particular pair of element values. It should define a strict weak ordering relationship (see A.18); it should not modify Container. If the actual for "<" behaves in some other manner, the behavior of the instance of Generic_Constrained_Array_Sort is unspecified. The number of times Generic_Constrained_Array_Sort calls "<" is unspecified.
!corrigendum A.18.27(0)
Insert new clause:
Force a conflict; the real text is found in the conflict file.
!corrigendum A.18.30(0)
Insert new clause:
Force a conflict; the real text is found in the conflict file.
!corrigendum B(1)
Insert after the paragraph:
This Annex describes features for writing mixed-language programs. General interface support is presented first; then specific support for C, COBOL, and Fortran is defined, in terms of language interface packages for each of these languages.
the new paragraph:
Support for interfacing to any foreign language is optional. However, an implementation shall not provide any optional aspect, attribute, library unit, or pragma having the same name as an aspect, attribute, library unit, or pragma (respectively) specified in the clauses of this Annex unless the provided construct is either as specified in those clauses or is more limited in capability than that required by those clauses. A program that attempts to use an unsupported capability of this Annex shall either be identified by the implementation before run time or shall raise an exception at run time.
!corrigendum B.2(10.1/2)
Delete the paragraph:
Support for interfacing to any foreign language is optional. However, an implementation shall not provide any attribute, library unit, or pragma having the same name as an attribute, library unit, or pragma (respectively) specified in the following clauses of this Annex unless the provided construct is either as specified in those clauses or is more limited in capability than that required by those clauses. A program that attempts to use an unsupported capability of this Annex shall either be identified by the implementation before run time or shall raise an exception at run time.
!corrigendum B.2(10.1/2)
Replace the paragraph:
Support for interfacing to any foreign language is optional. However, an implementation shall not provide any attribute, library unit, or pragma having the same name as an attribute, library unit, or pragma (respectively) specified in the following clauses of this Annex unless the provided construct is either as specified in those clauses or is more limited in capability than that required by those clauses. A program that attempts to use an unsupported capability of this Annex shall either be identified by the implementation before run time or shall raise an exception at run time.
by:
Support for interfacing to any foreign language is optional. However, an implementation shall not provide any aspect, attribute, library unit, or pragma having the same name as an aspect, attribute, library unit, or pragma (respectively) specified in the clauses of this Annex unless the provided construct is either as specified in those clauses or is more limited in capability than that required by those clauses. A program that attempts to use an unsupported capability of this Annex shall either be identified by the implementation before run time or shall raise an exception at run time.
!corrigendum B.3(2/2)
Replace the paragraph:
The package Interfaces.C contains the basic types, constants and subprograms that allow an Ada program to pass scalars and strings to C and C++ functions. When this clause mentions a C entity, the reference also applies to the corresponding entity in C++.
by:
The package Interfaces.C contains the basic types, constants, and subprograms that allow an Ada program to pass scalars and strings to C and C++ functions. When this clause mentions a C entity, the reference also applies to the corresponding entity in C++.
!corrigendum C.7.1(14)
Replace the paragraph:
E'Caller
Yields a value of the type Task_Id that identifies the task whose call is now being serviced. Use of this attribute is allowed only inside an entry_body or accept_statement corresponding to the entry_declaration denoted by E.
by:
E'Caller
Yields a value of the type Task_Id that identifies the task whose call is now being serviced. Use of this attribute is allowed only inside an accept_statement, or entry_body after the entry_barrier, corresponding to the entry_declaration denoted by E.
!corrigendum D.2.2(3.5/2)
Replace the paragraph:
If a partition contains one or more Priority_Specific_Dispatching pragmas the dispatching policy for priorities not covered by any Priority_Specific_Dispatching pragmas is FIFO_Within_Priorities.
by:
If a partition contains one or more Priority_Specific_Dispatching pragmas, the dispatching policy for priorities not covered by any Priority_Specific_Dispatching pragmas is FIFO_Within_Priorities.
!corrigendum D.2.2(6.2/2)
Replace the paragraph:
If a partition contains one or more Priority_Specific_Dispatching pragmas a task dispatching point occurs for the currently running task of a processor whenever there is a non-empty ready queue for that processor with a higher priority than the priority of the running task.
by:
If a partition contains one or more Priority_Specific_Dispatching pragmas, a task dispatching point occurs for the currently running task of a processor whenever there is a non-empty ready queue for that processor with a higher priority than the priority of the running task.
!corrigendum D.7(19.1/2)
Insert after the paragraph:
Max_Entry_Queue_Length
Max_Entry_Queue_Length defines the maximum number of calls that are queued on an entry. Violation of this restriction results in the raising of Program_Error at the point of the call or requeue.
the new paragraphs:
No_Standard_Allocators_After_Elaboration
Specifies that an allocator using a standard storage pool (see 13.11) shall not occur within a parameterless library subprogram, nor within the handled_sequence_of_statements of a task body. For the purposes of this rule, an allocator of a type derived from a formal access type does not use a standard storage pool.
At run time, Storage_Error is raised if an allocator using a standard storage pool is evaluated after the elaboration of the library_items of the partition has completed.
!corrigendum H.4(8/1)
Insert after the paragraph:
No_Local_Allocators
Allocators are prohibited in subprograms, generic subprograms, tasks, and entry bodies.
the new paragraphs:
No_Anonymous_Allocators
There are no allocators of anonymous access types.
No_Coextensions
There are no coextensions. See 3.10.2.
No_Access_Parameter_Allocators
Allocators are not permitted as the actual parameter to an access parameter. See 6.1.
!ACATS Test
None needed.
!ASIS
No change needed.
!appendix

From: Randy Brukardt
Sent: Monday, July 18, 2011  10:23 PM

Question of very low importance:

Grein, Christoph wrote:
...
> 5.5 seems incomplete.
> 5.5(7) says: "The loop_statement is complete when a transfer of
> control occurs that transfers control out of the loop, or, in the case
> of an iteration_scheme, as specified below."
> But there is nothing said about iterator_specification.
> Perhaps a reference to 5.5.2 should be added.

"iteration_scheme" clearly includes "iterator_specification", so there is
nothing missing in 5.5(7). The "completion" conditions for iterator
specifications are specified in 5.5.2(10/3, 11/3, and 13/3), so these are in
fact defined. "below" in technical writing generally means "anywhere after this
point in the text" (it is not restricted to the same subclause), and 5.5.2
surely follows 5.5, and even is part of the same clause (all being parts of
5.5), so there is nothing actually wrong here.

However, that is the pedantic answer. It probably wouldn't hurt to put a
cross-reference into the text somewhere. The best way to do that is less than
obvious, however.

We could stick something on the end of 5.5(7):

"The loop_statement is complete when a transfer of control occurs that transfers
control out of the loop, or, in the case of an iteration_scheme, as specified
below. (For iterator_specifications, see 5.5.2.)"

But that doesn't read well, because it seems to contradict "below". (Also see
the next item.)

An alternative is to put the text as a redundant paragraph following 5.5(9):

Redundant[For the details of iterator_specifications, see 5.5.2.]

That reads better, but it is common that part of the semantics of something is
in another clause in the Standard. So it's a bit weird to say this explicitly
here.

Finally, we could just make it an AARM note as above:

Discussion: For the details of iterator_specifications, see 5.5.2.

Any thoughts??

****************************************************************

From: Christoph Grein
Sent: Tuesday, July 19, 2011  1:37 AM

I tend to this solution:

> Redundant[For the details of iterator_specifications, see 5.5.2.]
>
> That reads better, but it is common that part of the semantics of
> something is in another clause in the Standard. So it's a bit weird to
> say this explicitly here.
> ...
> Any thoughts??

This provides the most information for the (non-language-lawyer) reader at the
correct place. After all, the RM is already hard enough to read.

****************************************************************

From: Christoph Grein
Sent: Thursday, July 21, 2011  2:04 AM

13.11(21.5/3) For [one]{each} of the calls of Allocate described above, P
(equivalent to T'Storage_Pool) is passed as the Pool parameter.

I think *one* is confusing here - it makes the reader wonder what about
the others. I think it should say *each* instead - or am I missing something?

****************************************************************

!topic Possible incorrect terminology in 6.1.1
!reference 6.1.1(3/3, 5/3), AARM 6.1.1(22.a/3)
!from Adam Beneschan 11-07-28
!discussion

6.1.1(3/3) says about Pre'Class, "This aspect specifies a class-wide
precondition for a callable entity and its descendants".  However,
nowhere in the RM is a "descendant" of a callable entity defined.
"Descendants" are defined for types, library units, and nodes in
Containers.Multiway_Trees, but not for subprograms.  Also, aside from
paragraphs 3 and 5, and possibly 22.a in the AARM, the term
"descendant" is never used to refer to anything besides a type,
library unit, or Multiway_Trees node.  Since paragraph 14 explains
just what the semantics are, I don't think the meaning of the RM is
unclear; but since paragraphs 3 and 5 are in a normative part of the
RM, the language they use should probably be correct.

Side note: The glossary (appendix N) contains a definition of
"descendant", but that definition covers only the meaning that applies
to types, not the one that applies to library units.  I'm not sure if
this is a problem.

****************************************************************

From: Randy Brukardt
Sent: Saturday, July 30, 2011  1:21 AM

> 6.1.1(3/3) says about Pre'Class, "This aspect specifies a class-wide
> precondition for a callable entity and its descendants".  However,
> nowhere in the RM is a "descendant"
> of a callable entity defined.
> "Descendants" are defined for types, library units, and nodes in
> Containers.Multiway_Trees, but not for subprograms.  Also, aside from
> paragraphs 3 and 5, and possibly 22.a in the AARM, the term
> "descendant" is never used to refer to anything besides a type,
> library unit, or Multiway_Trees node.  Since paragraph 14 explains
> just what the semantics are, I don't think the meaning of the RM is
> unclear; but since paragraphs
> 3 and 5 are in a normative part of the RM, the language they use
> should probably be correct.

Actually, the normative description of class-wide aspects applied to subprograms
(no entries can be primitive operations of a tagged type) is in
13.3.1(28/3) [this paragraph number may have changed since draft 12]:

If the aspect_mark includes 'Class, then:
...
if the associated entity is a primitive subprogram of a tagged type T, the
specification applies to the corresponding primitive subprogram of all descendants
of T.

The wording in 6.1.1(3/3) and 6.1.1(5/3) is intended to be a more informal
description. And I wouldn't call it "incorrect" (since the semantics are defined
formally elsewhere), just "undefined".

But I do agree that it is somewhat uncomfortable to have undefined terminology in
the normative wording, especially as it is the first description of the aspects.
Repeating 6.1.1(18/3) [probably was 14/3 in draft 12, but 6.1.1 was changed a lot
in Edinburgh] isn't helpful and would potentially cause a maintenance problem.

So I have no better idea than the current wording.

****************************************************************

From: Tucker Taft
Sent: Tuesday, August 2, 2011  11:16 AM

How about:

3/3
Pre'Class
This aspect specifies a class-wide precondition for an operation of a tagged
type and its descendants; ...

5/3
Post'Class
This aspect specifies a class-wide postcondition for an operation of a tagged
type and its descendants; ...

****************************************************************

From: Adam Beneschan
Sent: Thursday, July 28, 2011  4:20 PM

!topic Assertion_Policy and inherited subprograms with preconditions
!reference 6.1.1(26,28)
!from Adam Beneschan 11-07-28
!discussion

6.1.1(26) says, "For any subprogram or entry call (including
dispatching calls), the specific precondition check and the
postcondition check that is performed is determined by those of the
subprogram or entry actually invoked".

Does this imply that the Assertion_Policy that is in effect is also
determined by the subprogram actually invoked?

pragma Assertion_Policy(Check);
package Pack1 is
    type T1 is tagged record
        F1 : Integer;
    end record;
    procedure Op1 (Obj : T1; Value : Integer)
       with Pre => Is_Prime(Value);
end Pack1;

pragma Assertion_Policy(Ignore);
package Pack2 is
    type T2 is new Pack1.T1 with record
        F2 : Integer;
    end record;
--  procedure Op1 (Obj : T1; Value : Integer) is inherited and
--     not overridden
end Pack1;

Suppose we call Pack2.Op1.  Is the precondition check on Value
performed?

6.1.1(28) talks about "the assertion policy in effect at the point of
a subprogram declaration".  Here, Ignore is the policy in effect at
the implicit declaration of Pack2.Op1.  However, how 6.1.1(28) is
applied in this case depends on how "call on that subprogram" is
interpreted: is "that subprogram" the one denoted by the call
(Pack2.Op1), or the one whose body is invoked (Pack1.Op1)?  I'm not
clear on whether 6.1.1(26) or 3.9.2(20.4) answer this sufficiently.

If the answer is that the Ignore policy applies when Pack2.Op1 is
called, this means that Pack2.Op1 (probably) can't simply be
implemented by having calls to Pack2.Op1 be direct calls to Pack1.Op1.
The Implementation Note in 6.1.1(27.c) says (I think) that specific
preconditions must be checked inside the subprogram body.  But we're
not allowed to perform those checks if Pack2.Op1 is called.  So it
looks to me that a primitive operation of a tagged type that has a
specific precondition (such as Pack1.Op1) needs to be implemented in
two parts---the body will check the precondition, and then call
another Op1_Work routine that does the actual work---because Pack1.Op1
could be inherited in a package with an Ignore policy, and we'd want
Pack2.Op1 to be implemented as a call to Op1_Work without the checks.
Is that pretty much correct?  Is that the intent?

****************************************************************

From: Randy Brukardt
Sent: Wednesday, August 3, 2011  8:45 PM

> Does this imply that the Assertion_Policy that is in effect is also
> determined by the subprogram actually invoked?

Of course, nothing else makes sense.

> pragma Assertion_Policy(Check);
> package Pack1 is
>     type T1 is tagged record
>         F1 : Integer;
>     end record;
>     procedure Op1 (Obj : T1; Value : Integer)
>        with Pre => Is_Prime(Value);
> end Pack1;
>
> pragma Assertion_Policy(Ignore);
> package Pack2 is
>     type T2 is new Pack1.T1 with record
>         F2 : Integer;
>     end record;
> --  procedure Op1 (Obj : T1; Value : Integer) is inherited and
> --     not overridden
> end Pack1;
>
> Suppose we call Pack2.Op1.  Is the precondition check on Value
> performed?
>
> 6.1.1(28) talks about "the assertion policy in effect at the point of
> a subprogram declaration".  Here, Ignore is the policy in effect at
> the implicit declaration of Pack2.Op1.
> However, how 6.1.1(28) is applied in this case depends on how "call on
> that subprogram" is
> interpreted: is "that subprogram" the one denoted by the call
> (Pack2.Op1), or the one whose body is invoked (Pack1.Op1)?
> I'm not clear on whether 6.1.1(26) or 3.9.2(20.4) answer this
> sufficiently.

Since parts of these clause were extensively rewritten during the June meeting,
I'm not sure what rules you are referring to or whether they even are in the
Standard anymore. I didn't see anything that answers this question even remotely
adequately.

> If the answer is that the Ignore policy applies when
> Pack2.Op1 is called, this means that Pack2.Op1 (probably) can't simply
> be implemented by having calls to Pack2.Op1 be direct calls to
> Pack1.Op1.
> The Implementation Note in 6.1.1(27.c) says (I think) that specific
> preconditions must be checked inside the subprogram body.  But we're
> not allowed to perform those checks if
> Pack2.Op1 is called.  So it looks to me that a primitive operation of
> a tagged type that has a specific precondition (such as Pack1.Op1)
> needs to be implemented in two parts---the body will check the
> precondition, and then call another Op1_Work routine that does the
> actual work---because
> Pack1.Op1 could be inherited in a package with an Ignore policy, and
> we'd want
> Pack2.Op1 to be implemented as a call to Op1_Work without the checks.
> Is that pretty much correct?  Is that the intent?

Well, this interpretation clearly violates Dewar's Rule (that the Standard never
says anything silly). Assuming that *every* primitive operation (which might be
inherited) has to be compiled in two parts if it has any pre or post-conditions
because some other unit *might* be compiled with Ignore surely qualifies as
silly!

What the Standard means to say, however, is a difficult problem IMHO and will
need to wait for an Ada 2012 AI. (There are other such topics.) My feeling is
that Ignore should be treated like Suppress -- it is a *permission* to not make
a check, not a *requirement* to not make a check. Suppress is that way in part
because of cases like this - sometimes checks are suppressed on code inherited
from a unit that does not have checks suppressed - in such cases, the compiler
can do what it wants. I think the same ought to apply here. Compilers aren't
going to leave checks that they can easily eliminate just because of laziness -
there clearly is a performance hit to making the checks - so I don't think that
the Standard has to require behavior here.

(That's especially true as these checks are in the same "seatbelt" category as
other checks, depending on them being eliminated should be a rarity. It's silly
to turn off checks unless you absolutely have to for performance reasons; the
results should never vary either way.)

The alternative of rewording the standard to say that it is the subprogram that
is invoked that determines whether or not the checks are performed would require
completely rewriting the entirety of 6.1.1(24-33/3) [Draft 13 numbers]. (The
text would have to say that the checks are always performed, but the evaluation
of expressions does not happen if Ignore is set for the declaration. Or
something like that. That's not the model currently worded.)

****************************************************************

From: Tucker Taft
Sent: Wednesday, August 3, 2011  9:09 PM

I would recommend something simple, namely that if the policy differs between
the explicit declaration of the subprogram actually invoked, the implicit
declaration of some inherited subprogram, and the declaration through which a
dispatching call is made, it is implementation-defined which policy applies.

I don't agree that "Ignore" and/or "Check" can be treated merely as "advice."
But I do agree that if one of the relevant declarations says Check and one says
Ignore, either behavior should be permitted.  This will allow implementations
maximum freedom in terms of where they do the checks, which I think is
important.

****************************************************************

From: Randy Brukardt
Sent: Wednesday, August 3, 2011  9:43 PM

I don't find much different between these (I find it hard to believe that
compilers would make checks that they don't have to make, unless there is some
important implementation reason). But this would be fine to me. But how to
accomplish that??

(1) Do you really mean "implementation-defined" (which would require
    documentation of the choice -- that would seem hard to provide as the choice
    might depend on the calling sequence (which might depend on the parameter
    types and or modes), inlining, generic instances, dispatching,
    access-to-subprograms, inheritance, and overriding. (Hopefully not the phase
    of the moon, but it's close.) I'd think "unspecified" would be better.

(2) If you agree with the above, perhaps all we need is a To Be Honest (or do we
    need "Adam Clarification:" in the AARM? ;-):

   To Be Honest: If the assertion policy for the declaration of a callable
   entity differs from that of the subprogram actually invoked or from that of
   any subprogram from which it is inherited, whether a precondition or
   postcondition check is executed is unspecified.

(3) Or we could put the above text (or something like it) directly after
    6.1.1(33/3) [the last paragraph in the dynamic semantics, the one that talks
    about the Ignore policy].

(4) Or we could write the above as an Implementation Permission.

We can probably do any of the above as a last-minute fix; none of them would
have much chance of breaking anything (none would apply if Ignore wasn't used).

****************************************************************

From: Tucker Taft
Sent: Wednesday, August 3, 2011  9:50 PM

> (1) Do you really mean "implementation-defined" (which would require
> documentation of the choice -- that would seem hard to provide as the
> choice might depend on the calling sequence (which might depend on the
> parameter types and or modes), inlining, generic instances,
> dispatching, access-to-subprograms, inheritance, and overriding.
> (Hopefully not the phase of the moon, but it's close.) I'd think "unspecified" would be better.

I could live with either one.  Unspecified is certainly easier to implement!

>
> (2) If you agree with the above, perhaps all we need is a To Be Honest
> (or do we need "Adam Clarification:" in the AARM? ;-):
>
>     To Be Honest: If the assertion policy for the declaration of a
> callable entity differs from that of the subprogram actually invoked
> or from that of any subprogram from which it is inherited, whether a
> precondition or postcondition check is executed is unspecified.

I think it probably should be normative.
>
> (3) Or we could put the above text (or something like it) directly
> after
> 6.1.1(33/3) [the last paragraph in the dynamic semantics, the one that
> talks about the Ignore policy].

Yes, this seems like the right place.
>
> (4) Or we could write the above as an Implementation Permission.

I don't think it makes sense as a permission, since without the paragraph, the "correct" implementation isn't really defined.
Normally an implementation permission allows an implementation to do something that to some degree goes against the "official"
semantics.  But here, we seem to agree that the "official"
semantics aren't well defined when policies differ.
>
> We can probably do any of the above as a last-minute fix; none of them
> would have much chance of breaking anything (none would apply if
> Ignore wasn't used).

Agreed, or just make it an early Ada 2012 AI.

****************************************************************

From: John Barnes
Sent: Thursday, August 18, 2011  4:02 PM

I've started and immediately run into trouble with the phrase "satisfy the
predicate" which doesn't seem to be defined. See 3.8.1.

****************************************************************

From: Randy Brukardt
Sent: Thursday, August 18, 2011  4:22 PM

Specifically, 3.8.1(15/3).

I can't find any attempt to define it in AI05-0153-3, so it just isn't done. The
language specifically defines what it means to "satisfy" each individual kind of
constraint (see, for instance, 3.6.1(7), 3.5(4), 3.7.1(11)). There has to be
such a statement in 3.2.4. "A value *satisfies* a predicate if the predicate
evaluates to True for the value." Or something like that. But...

I also note that "satisfy" is typically defined as a dynamic property. The rule
John was referring to is a legality rule, so that could be trouble. ("Satisfy"
as typically defined ignores privacy; that would be a bad idea for a legality
rule!)

So I think this is the wrong term to use (given that it already has a dynamic,
privacy breaking meaning) AND whatever term is used needs to be defined as
"static semantics" (so it is view-dependent). [Note that we could give
"satisfies a predicate" a static meaning here, and that would work properly, but
that would be confusing at best.]

Suggestions welcome.

****************************************************************

From: Tucker Taft
Sent: Thursday, August 18, 2011  7:30 PM

I don't see the problem with using "satisfies" in a static context.  We do lots
of "dynamic" things when evaluating expressions statically, including worry
about exceptions.

****************************************************************

From: Bob Duff
Sent: Thursday, August 18, 2011  8:23 PM

> I don't see the problem with using "satisfies" in a static context.
> We do lots of "dynamic" things when evaluating expressions statically,
> including worry about exceptions.

I agree.

...
> > Specifically, 3.8.1(15/3).
> >
> > I can't find any attempt to define it in AI05-0153-3, so it just isn't done.

OK, that's my handiwork, so let me defend it:  In plain English, "predicate"
and "satifies" (of a predicate) are well-understood.  OK, maybe not "plain
English", but at least plain English as understood by maths guys. Can't we rely
on math-guy English in the RM?

A predicate is satisfied if it's true.  Pretty simple.

> > The language specifically defines what it means to "satisfy" each
> > individual kind of constraint (see, for instance, 3.6.1(7), 3.5(4), 3.7.1(11)).

OK, but those are really just telling us what the predicate (math-wise) is.

> > ...There
> > has to be such a statement in 3.2.4. "A value *satisfies* a
> > predicate if the predicate evaluates to True for the value." Or something like that. But...

If you insist on such wording, please can't we make it simple:
"A value *satisfies* a predicate if it is True for that value."
"evaluates to" adds nothing.

****************************************************************

From: John Barnes
Sent: Friday, August 19, 2011  3:03 AM

> OK, that's my handiwork, so let me defend it:  In plain English,
> "predicate"
> and "satifies" (of a predicate) are well-understood.  OK, maybe not
> "plain English", but at least plain English as understood by maths guys.
> Can't we rely on math-guy English in the RM?

My problem is that it doesn't say what predicate we are talking about. In other
words, it doesn't define "predicate" in the context. I am happy with satisfy.

And  I totally disagree with Bob that predicate is plain English as understood
my maths folk in general. I certainly never used the word when I did maths at
Cambridge. I must admit we never studied logic - probably considered too
elementary. It's OK for formal methods folk - a very specialzed community - and
we ought to make the RM understandable by typcial programmers if possible. When
I encountered it, I was looking for a bit of syntax called predicate or some
such.

****************************************************************

From: Randy Brukardt
Sent: Friday, August 19, 2011  3:40 PM

> I don't see the problem with using "satisfies" in a static context.
> We do lots of "dynamic" things when evaluating expressions statically,
> including worry about exceptions.

But that wasn't my concern! My concern was that dynamic rules ignore privacy,
and using such a concept in a Legality Rule thus is potentially privacy
breaking.

It would be OK to use "satisfies" so long as we are sure that it will never
appear in a legality rule where privacy could matter. The one in 3.8.1(15) isn't
a problem (which I had forgotten about yesterday) because it requires the type
to be discrete, and a private type is never discrete. So there probably is no
problem with using "satisfies" in Ada 2012.

****************************************************************

From: Randy Brukardt
Sent: Friday, August 19, 2011  4:16 PM

...
> > > I can't find any attempt to define it in AI05-0153-3, so it just
> > > isn't done.
>
> OK, that's my handiwork, so let me defend it:  In plain English,
> "predicate"
> and "satifies" (of a predicate) are well-understood.  OK, maybe not
> "plain English", but at least plain English as understood by maths
> guys.
> Can't we rely on math-guy English in the RM?

No, with the exception of technical terms. The standard explicitly says that we
rely on the meaning of words from some particular dictionary if they are not
defined by the Standard.

So, I disagree that "satisfies" is that well defined. I realize that anyone that
basically understands Ada can figure out what is meant, but "satisfies" doesn't
add anything to that -- you could have said that the "value bellywomps the
predicate" and it would have made just as much sense.

Worse, "satisfied" has a technical meaning in the Standard (its in the index),
and it is very, very bad to use a defined term in an English meaning. We've had
all kinds of trouble with wording where some word was intended to be English but
the defined meaning causes some unusual side-effect. (I recall discussions over
"mentioned", "named", and "corresponding".) This case is especially bad because
of the clear definition of similar cases. In any case, "if in doubt, spell it
out"!! Electrons are cheap.

As for "predicate" goes, the term is defined in paragraph 3.2.4(6/3) [you
apparently thought *that* term needed to be defined!], it's in the index as
such, and therefore I have no idea what John is complaining about there. Even if
you are worried that the defined term is "predicate of a subtype", the actual
sentence "value of that subtype that satisfies the predicate" surely makes it
clear enough that it is the predicate of the subtype that we're talking about.

> A predicate is satisfied if it's true.  Pretty simple.
>
> > > The language specifically defines what it means to "satisfy" each
> > > individual kind of constraint (see, for instance,
> 3.6.1(7), 3.5(4), 3.7.1(11)).
>
> OK, but those are really just telling us what the predicate
> (math-wise) is.

Give me a break. This defines the technical meaning of "satisfies", no more and
no less -- there is no predicate to be seen here, even in an expansive sense.

I think you are making this up as you go along...

> > > ...There
> > > has to be such a statement in 3.2.4. "A value *satisfies* a
> > > predicate if the predicate evaluates to True for the
> > > value." Or something like that. But...
>
> If you insist on such wording, please can't we make it simple:
> "A value *satisfies* a predicate if it is True for that value."
> "evaluates to" adds nothing.

I do insist on such wording, but I don't care that much about the exact details.
I was just echoing the wording of 3.2.4(18/3) -- this rule will be very close to
that one (probably directly following it). Given that this is a dynamic term
that potentially could apply to dynamic predicates (even if the current wording
doesn't use it that way), it seemed best to use similar wording. (And it still
does.)

****************************************************************

From: Bob Duff
Sent: Friday, August 19, 2011  4:45 PM

> > Can't we rely on math-guy English in the RM?

> No, with the exception of technical terms. The standard explicitly
> says that we rely on the meaning of words from some particular
> dictionary if they are not defined by the Standard.

That part is fairly bogus.

> So, I disagree that "satisfies" is that well defined. I realize that
> anyone that basically understands Ada can figure out what is meant, but "satisfies"
> doesn't add anything to that -- you could have said that the "value
> bellywomps the predicate" and it would have made just as much sense.

[snipped all sorts of useful and correct argumentation]

OK, I cry "Uncle!".

****************************************************************

From: John Barnes
Sent: Monday, August 22, 2011  4:12 AM

...
> My problem is that it doesn't say what predicate we are talking about.
> In other words, it doesn't define "predicate" in the context. I am
> happy with satisfy.
>
> And  I totally disagree with Bob that predicate is plain English as
> understood my maths folk in general. I certainly never used the word
> when I did maths at Cambridge. I must admit we never studied logic -
> probably considered too elementary. It's OK for formal methods folk -
> a very specialzed community - and we ought to make the RM
> understandable by typcial programmers if possible. When I encountered
> it, I was looking for a bit of syntax called predicate or some such.

I see now that in 3.2.4(6/3) it defines the predicate of a subtype. Is that what
we are talking about?  It also says that if no subtype predicates apply then the
predicate is true.  Sounds like a null event then.

In 3.8.1(15/3) again says "that satisfy the predicate" . I ask again what
predicate?  Is this really all about subtype predicates in which case there
should be a reference to 3.2.4 in the appropriate places.

Maybe it would be clearer to say "that satisfies its predicate" in which case we
would know to look for the predicate of the subtype and not to some other
predicate which does not exist.

I hadn't realised that the (evil) tentacles of subtype predicates had spread all
over the language. You may recall that I was unwell when this was dscussed and
missed a couple of meetings. And of course we didn't do a formal editorial
review of these later AIs otherwise I would have mentioned this earlier.

I found subtype predicates distasteful when writing the intro to teh rat.


Incidentally, a fellow member of the ARG (of mathematical inclination) sent me a
private mesage to say that a predicate is verb plus object. Indeed, if you had
asked me what a predicate was when I had just finished my maths degree at
Cambridge I would have said just that.

Anyway, we need to make this stuff intelligible to a bright programmer writing
Ada programs for real applications. So it has to be accessible to hairy
electronic engineers as well as to pure program provers.

****************************************************************

From: Randy Brukardt
Sent: Thursday, September 22, 2011  7:22 PM

To reply to John's old message that came while I was on vacation:

...
> I see now that in 3.2.4(6/3) it defines the predicate of a subtype. Is
> that what we are talking about?  It also says that if no subtype
> predicates apply then the predicate is true.  Sounds like a null event
> then.

Yes, that is what we're talking about. It's the only use of "predicate" in the
Ada language, so there can't be any confusion.

> In 3.8.1(15/3) again says "that satisfy the predicate" . I ask again
> what predicate?  Is this really all about subtype predicates in which
> case there should be a reference to 3.2.4 in the appropriate places.

Generally, we only put in cross-references if the reference is a forward
reference to a term not yet defined. In this case, the term is defined earlier
in the Standard, so we don't put in a cross-reference.

Given that the Standard is rarely read in a linear fashion, it would make some
sense to relax that principle. But it would be hard to know where to draw the
line. This case is close enough to the line to add the reference (so I did so).

In any case, the first thing to do when confronted with a term that is
unfamiliar is to look it up in the index. If that doesn't help, then complain
(loudly) both about the term AND the index.

> Maybe it would be clearer to say "that satisfies its predicate" in
> which case we would know to look for the predicate of the subtype and
> not to some other predicate which does not exist.

I suppose. Or we could add "of the subtype" after predicate. But that seems like
more words, and "its" is probably good enough here.

> I hadn't realised that the (evil) tentacles of subtype predicates had
> spread all over the language. You may recall that I was unwell when
> this was dscussed and missed a couple of meetings. And of course we
> didn't do a formal editorial review of these later AIs otherwise I
> would have mentioned this earlier.

That's kinda the point of this review, so don't worry about that. As far as
"predicates all over the language" goes, that also was kinda the point -- the
whole idea was to allow static predicates in case statements, so it is necessary
to explain what that means for case coverage. Anytime we add anything, it ends
up having consequences "all over the language" (think of the number of places
that we've had to add aspects or conditional expressions).

> I found subtype predicates distasteful when writing the intro to teh
> rat.

I think you're just getting grumpy. I see that happening to me, too, because
changes mean more work for me but usually not more money. But I think most of
these changes are for the better (especially aspects and predicates).

> Incidentally, a fellow member of the ARG (of mathematical
> inclination) sent me a private mesage to say that a predicate is verb
> plus object.
> Indeed, if you had asked me what a predicate was when I had just
> finished my maths degree at Cambridge I would have said just that.
>
> Anyway, we need to make this stuff intelligible to a bright programmer
> writing Ada programs for real applications. So it has to be accessible
> to hairy electronic engineers as well as to pure program provers.

Fair enough - again, that's the point of these reviews.

****************************************************************

From: John Barnes
Sent: Friday, September 23, 2011  10:23 AM

Many thanks for your reply which settles that one nicely. And I do know
that I am getting more grumpy!

****************************************************************

From: Tucker Taft
Sent: Sunday, September 18, 2011  9:43 AM

Not really an "editorial" comment, but I did bump into an ambiguity today when
looking at the description of the 'Caller attribute.  It says it is allowed only
within the entry body or accept statement, but that seems to imply it might be
allowed in the entry barrier.  But that clearly wouldn't work since the same
value of the entry barrier must be used for all callers of a given entry, so the
entry barrier can't depend on 'Caller.  So if we are in the mood for clarifying
this section, which does have some Ada 2012 changes, we might say:

E'Caller
     Yields a value of the type Task_Id that identifies
     the task whose call is now being serviced. Use of
     this attribute is allowed only inside an [entry_body or]
     accept_statement {or entry_body (after the entry_barrier)}
     corresponding to the entry_declaration denoted by E.

I moved accept_statement before entry_body because the parenthetical clause made
the sentence harder to understand if the clause was followed by "or
accept_statement."

Certainly not a biggie, but I at least was confused by this when I read it
today, and actually wrote a test program to see what our compiler actually did
(it disallowed the attribute, luckily!).

****************************************************************

From: Tullio Vardanega
Sent: Sunday, September 18, 2011 10:01 AM

Yes, please.

****************************************************************

From: Tucker Taft
Sent: Sunday, September 18, 2011 10:27 AM

Interestingly, I just noticed the following in this same section:

17.c/2
     Ramification: {AI95-00237-01} An entry barrier is syntactically
     part of an entry_body, so a call to Current_Task from an entry barrier
     is also covered by this rule.

So this makes it clear that an entry barrier *is* considered part of an
entry_body, so paragraph (14) is no longer just ambiguous -- it is wrong.

By the way, GNAT rejects use of 'Caller in an entry barrier as well, with the
following message:

    Caller must appear in matching accept or body

AdaMagic rejects it with:

    LRM:C.7.1(13), The use of 'CALLER must be in an entry body
    or accept statement for the entry denoted by the prefix

I have attached the test program caller2.adb

----

with Ada.Task_Identification;
use Ada.Task_Identification;
procedure caller2 is
    protected type PT is
        entry Test(Integer range -10 .. 10)(X : Integer);
    private
        Data : Integer := 0;
    end PT;

    protected body PT is
        entry Test(for I in Integer range -10 .. 10)(X : Integer)
          when Test'Caller /= Null_Task_Id and then I > 0 is
        begin
            Data := X;
        end Test;
    end PT;
    PO : PT;
begin
    PO.Test(3)(5);
end;

****************************************************************

From: Randy Brukardt
Sent: Wednesday, October 26, 2011 10:11 PM

> I have attached the test program caller2.adb

For what it's worth (not much :-), Janus/Ada rejects this with the not very
useful message:

*ERROR* Prefix must name a task or PT entry (6.4.1) [RM C.7.1(14)]

Interestingly, it does the same in the entry body if this is an entry family (as
in the original test program), but if the family is removed, then it allows it
in the body but not the barrier. (All with the same almost useless message.) The
family bit is a another bug for the pile; otherwise, the behavior matches the
other two compilers.

****************************************************************

From: Randy Brukardt
Sent: Tuesday, September 27, 2011  9:58 PM

Bob has in his review:

> > 6.1.1(33/3)  If the assertion policy in effect at the point of a
> > subprogram or entry
> > declaration is Ignore, then no precondition or postcondition check
> > is performed on a call on that subprogram or entry. If the assertion
> > policy in
> > effect at the point of a subprogram or entry declaration is Check,
> > then preconditions and postconditions are considered to be enabled
> > for that subprogram or entry.
>
> I'm concerned that we're not allowing preconditions to be checked at
> the point of call, here, because at that point, we don't know (for
> indirect calls) what assertion policy is in effect at the point of the
> subp decl.
>
> I think perhaps the rules about policies should be relaxed.
> Maybe we should say that Ignore really means "the implementation is
> allowed to ignore", rather than "shall ignore".  Similar to check
> suppression.

I agree with this idea on general principles (note that I said something
similar last week). But it's a pretty significant model change, and one
that make the policy name "Ignore" much less intuitive.

So we need to discuss this.

Some points (in a Baird-like list):

(1) Indirect calls via access-to-subprogram aren't very interesting WRT to
    this, as the preconditions cannot be checked at the call site for those
    in any case. (Access-to-subprogram types don't have preconditions, the
    precondition of the designated subprogram has to be used, which means
    at best a wrapper needs to be used. There would be no problem with a
    wrapper.)

(2) Formal subprograms have similar issues in a sharing implementation;
    those also would use a wrapper.

(3) Direct calls don't have a problem; they'll necessarily know what state
    applies to the declaration.

(4) What we really care about is dispatching calls. Here, specific preconditions
    cannot be done at the call site anyway (by definition - they depend on the
    actual subprogram). We definitely want the class-wide preconditions to be
    done at the call site (the semantics essentially require that). That might
    pose a problem with above definition.

(5) We can solve this one case with a targeted rule (just as we did to allow
    class-wide preconditions at the call site in the first place). The idea
    would be that it is the definition of subprogram that is (statically)
    called that determines the state, not necessarily the subprogram that is
    (dynamically) called. That's where the class-wide precondition comes from,
    and it would make sense that that is also where the policy should come.

(6) I'm not as certain about what rule should apply to class-wide
    postconditions; I can imagine either implementation being used and it
    would be best if either policy could be used.

(7) Maybe a better choice would be to say that if the policy of the
    (statically) called subprogram and the subprogram dispatched to differ,
    then it is unspecified which policy applies to a dispatching call.

(8) Did I miss anything??

(9) Any other ideas?

(10) I do think we need to resolve this before publishing the Standard, as
    it is pretty fundamental to the implementation of this feature, and it
    would be nasty for the Standard to say something different than
    implementations do. (Especially if we adopt Bob's original suggestion.)

(11) Steve would find a generic contract violation or something, I'm afraid
     I can't manage that.

(12) I see the Red Sox managed to win a game, despite their best efforts to
     blow it. [Editor's note: The Boston Red Sox managed to successfully (?)
     complete (argubly) the worst collapse in Major League Baseball history,
     blowing a 9 game lead with 24 games left in the season, the next night.
     And the team that passed them in the standings lost 8 games during that
     time.]

(13) Do I have enough list points yet? ;-)

(14) You can skip the points after #10, they are just me getting loopy.

****************************************************************

From: Bob Duff
Sent: Wednesday, September 28, 2011  7:18 AM

> ...[7 good points snipped]

> (8) Did I miss anything??

Any rules that complicate the implementation are of little value to users,
because I suspect most people will turn the assertions on and off globally,
rather than in a fine-grained manner.

If this were the from-scratch design of a new language, I'd probably insist
on nailing down the rule very tightly. But that's not our situation.

****************************************************************

From: Tucker Taft
Sent: Wednesday, September 28, 2011  7:42 AM

> (6) I'm not as certain about what rule should apply to class-wide
> postconditions; I can imagine either implementation being used and it
> would be best if either policy could be used.
>
> (7) Maybe a better choice would be to say that if the policy of the
> (statically) called subprogram and the subprogram dispatched to
> differ, then it is unspecified which policy applies to a dispatching call.

This seems fine to me.  We don't want this particular issue to significantly
affect the overall implementation approach.

I believe the reason we chose "ignore" was that we didn't want adding a
precondition/postcondition ever to make programs *less* safe, presuming the
setting is "Ignore."  Other policies such as "Assume_Without_Checking" could
fall in the category of making the program less safe.  The rules on "suppress"
are somewhat written that way, namely it is erroneous if you violate
a check that is suppressed.   We did *not* want to make it erroneous
to violate a precondition that is being "Ignore"d.

****************************************************************

From: Randy Brukardt
Sent: Wednesday, September 28, 2011  8:02 PM

> This seems fine to me.  We don't want this particular issue to
> significantly affect the overall implementation approach.

OK, so here's a stab at wording that:

Add after the first sentence of 6.1.1(33/3) [note: the second sentence
was moved to Static Semantics since the definition it makes it is used there.]

For a dispatching call, if the assertion policy in effect at the point of the
declaration of the denoted callable entity is not that same as the assertion
policy in effect at the point of the declaration of the invoked callable entity,
it is implementation-defined whether any precondition or postcondition checks
are made.

AARM Discussion: For a dispatching call with different policies, whether a check
is made probably will be different for different checks, depending on whether
the implementation makes them at the call site, in a wrapper, or inside the
called subprogram or entry.

Q. Should this be implementation-defined (requiring documentation) or unspecified?
It's not clear to me that there is any real benefit to knowing how this is done,
as (as Bob notes) most users will turn the checks on or off globally.

> I believe the reason we chose "ignore" was that we didn't want adding
> a precondition/postcondition ever to make programs
> *less* safe, presuming the setting is "Ignore."  Other policies such
> as "Assume_Without_Checking" could fall in the category of making the
> program less safe.  The rules on "suppress" are somewhat written that
> way, namely it is erroneous if you violate
> a check that is suppressed.   We did *not* want to make it erroneous
> to violate a precondition that is being "Ignore"d.

That makes some sense, although it wouldn't necessarily prevent allowing the check
to be made. One could imagine a rule where either the check is made, or it is not
made and no assumptions can be made. Pure function calls are rather like that:
you can assume that the result is the same, but if you make the call, you have
to be prepared for a different result (you can't just ignore the result).

Anyway, evaluating a precondition is a lot more likely to make a program less safe
(via side-effects, erroneousness, etc.) than assuming that it is true (since it
is rare that a compiler could usefully make such an assumption, since it probably
doesn't have any body visibility, and Ada doesn't have a strong enough
categorization to allow assuming a "safe" call). So I view your argument as weak.
Even so, I think it is too late to change this unless there is a really strong
reason, and clearly the above problem doesn't come anywhere near that level.

****************************************************************

From: Randy Brukardt
Sent: Friday, September 30, 2011  8:11 PM

Erhard had the following comment in his review:

> A.4.11. 72/3 thru 106/3:
>
> drop the "," before the "and". Or else introduce it in 66 thru 70. Or
> else ... whatever you do, do something consistent for the chapter.

I asked Gary about this, and he had a similar set of reactions to mine:
(1) The comma shouldn't be there;
(2) But it seems to help readability in some of the paragraphs (especially 78/3,
    90/3, 102/3);
(3) Consistency is important;
(4) Not quite sure what to do - either would be OK.

I note that many of the functions elsewhere in the Standard start "Returns ...".

In thinking about this, many of these sentences seem awkward. Consider the
various encoding functions, exemplified by 86/3:

   Encodes from Wide_String input, and generates an output encoded in UTF-8
   encoding.

"and generates an output"?? What's wrong with "returns"? And why is the type
name in this text? -- anybody can see the type of the input from reading the
profile on the line above. It would be a lot simpler to say:

   Returns Item encoded in UTF-8 encoding.

(or maybe "Returns the value of Item encoded in UTF-8 encoding.")

and then we don't have to discuss whether a comma is needed or not. (I'm not
sure if there is some important reason that J-P chose this wording, I'll let him
tell us if there is.)

In this case, it might be valuable to note that Item is not encoded (since a
UTF_16_String would match this parameter), so maybe we should add:

   Returns Item (which is assumed to not be encoded) encoded in UTF-8 encoding.

But an alternative to that would be to mention that in a new paragraph following
59/3 (so we only have to say it once):

   The Item parameter to Encode functions is assumed to not be encoded; it is
   treated as just an array of characters.

We already have global sentences talking about the behavior of these functions,
and the above is a lot clearer than anything stuck in the middle of the text.

----

The Decodes sentences are fine, and I'd leave the comma because it helps the
readability as in 78/3:

Decodes from input encoded in UTF-8, UTF-16LE, or UTF-16BE as specified by
Input_Scheme, and returns the corresponding String value.

I probably would have mentioned that parameter name rather than the generic
"input", but it doesn't help enough to bother with changing:

Decodes Item, which is assumed encoded in UTF-8, UTF-16LE, or UTF-16BE as
specified by Input_Scheme, and returns the corresponding String value.

(But at least here there is no argument about the comma :-)

We probably don't need "corresponding" in the above, nor "String" (which is
obvious from the function profile). So:

Decodes Item, which is assumed encoded in UTF-8, UTF-16LE, or UTF-16BE as
specified by Input_Scheme, and returns the value.

Probably we can move the last part to the front:

Returns the result of decoding Item, which is assumed encoded in UTF-8,
UTF-16LE, or UTF-16BE as specified by Input_Scheme.

----

The Converts sentences is where the inconsistency arose, and seem to be the
hardest to clean up. Consider 70/3:

   Converts from input encoded in UTF-16 and generates an output encoded in
   UTF-8.

Combining the previous suggestions, we get:

   Converts Item, which is assumed encoded in UTF-16, and returns the value
   encoded in UTF-8.

which doesn't seem quite right somehow.

Maybe

   Returns the value of Item, which is assumed encoded in UTF-16, encoded in
   UTF-8.

There being no important need to mention "Converts" here.

--------------------------------

Note in all of the above, I used "assumed" to be encoded or not encoded; that's
because this interface has no strong typing and thus it is possible to pass a
UTF-8 string to Encode (for instance). That's not going to cause Encode to
magically morph into Convert, and it seems valuable to emphasize that fact.

--------------------------------

So to summarize, I'm proposing to overhaul A.4.11:

Add a sentence after 59/3:

   The Item parameter to each of the Encode functions is assumed to not be
   encoded; it is treated as just an array of characters.

and simplify all of the even numbered paragraphs starting with 62/3 (the parts
in angle brackets would come from the similar text in the current wording):

For Encodes:

   Returns the value of Item <encoded in UTF-8 encoding>.

For Decodes:

   Returns the result of decoding Item, which is assumed <encoded in UTF-8,
   UTF-16LE, or UTF-16BE as specified by Input_Scheme>.

For Converts:

   Returns the value of Item, which is assumed <encoded in UTF-16>, <encoded in
   UTF-8>.

This would allow me to not answer the question about the commas, and simplify
the wording at the same time. (Given I've already spent more than an hour on
this question, and the fix will take most of another hour in any case, it's
probably worth the effort.)

Further suggestions/simplifications welcome.

****************************************************************

From: Jean-Pierre Rosen
Sent: Saturday, October 1, 2011  12:33 AM

> It would be a lot simpler to say:
>
>    Returns Item encoded in UTF-8 encoding.
>
> (or maybe "Returns the value of Item encoded in UTF-8 encoding.")
>
> and then we don't have to discuss whether a comma is needed or not.
> (I'm not sure if there is some important reason that J-P chose this
> wording, I'll let him tell us if there is.)

This is all brand new text, don't assume some sophisticated hidden secret behind
it... Just my misuse of english commas (there are some subtle differences in the
use of comas between french and english).

> Note in all of the above, I used "assumed" to be encoded or not
> encoded; that's because this interface has no strong typing and thus
> it is possible to pass a UTF-8 string to Encode (for instance). That's
> not going to cause Encode to magically morph into Convert, and it
> seems valuable to emphasize that fact.

Interesting... Even if the string starts with a BOM? Maybe raising an exception
would be appropriate. After all, if you encode an already encoded string, it is
very likely to be a bug.

****************************************************************

From: Randy Brukardt
Sent: Saturday, October 1, 2011  2:03 AM

> > It would be a lot simpler to say:
> >
> >    Returns Item encoded in UTF-8 encoding.
> >
> > (or maybe "Returns the value of Item encoded in UTF-8 encoding.")
> >
> > and then we don't have to discuss whether a comma is needed or not.
> > (I'm not sure if there is some important reason that J-P chose this
> > wording, I'll let him tell us if there is.)
>
> This is all brand new text, don't assume some sophisticated hidden
> secret behind it... Just my misuse of english commas (there are some
> subtle differences in the use of comas between french and english).

That's what I expected, but I thought it was important to ask...

> > Note in all of the above, I used "assumed" to be encoded or not
> > encoded; that's because this interface has no strong typing and thus
> > it is possible to pass a UTF-8 string to Encode (for instance).
> > That's not going to cause Encode to magically morph into Convert,
> > and it seems valuable to emphasize that fact.
>
> Interesting... Even if the string starts with a BOM? Maybe raising an
> exception would be appropriate. After all, if you encode an already
> encoded string, it is very likely to be a bug.

You're asking me to justify the design decisions in a package you created??
OK, here goes.

You do have a check for "invalid" characters in a Wide_String; these include the
BOM characters, so those would be detected (raising Encoding_Error). But you
don't have any check for String (which makes sense, in that everything is valid
there).

That seems right to me. I wouldn't expect the Encoding routines to check for
BOMs, since they are just taking raw Strings. It obviously would be a
performance hit when encoding a lot of small strings, and it isn't trivial to
implement correctly (you'd have to check the first three string characters, and
you'd have to be careful to avoid going past the end of the string), although no
worse than any other string operations.

And of course checking for BOMs would do no good 90% of the time when a part of
a string is encoded, and it isn't the part with the BOM that's passed. I don't
think it would catch enough errors to be worth the overhead.

Note that you have similar issues with Decode; you detect invalid sequences, but
if the given sequence happens to be valid, nothing will be detected (and you'll
still get the wrong answer).

Anyway, as I previously said, the functions "assume" the encoding expected for
the parameter. There is no way (in general) for the function to tell if it got
what it is expecting. If the assumption is violated, they have varying amounts
of checking -- they'll reject obviously bad contents, but anything else will get
though.

So back to my proposed wording changes. Are they an improvement (or not); any
specific suggestions; etc.??

****************************************************************

From: Robert Dewar
Sent: Saturday, October 1, 2011  9:02 AM

> It would be a lot simpler to say:
>
>     Returns Item encoded in UTF-8 encoding.
>
> (or maybe "Returns the value of Item encoded in UTF-8 encoding.")

Reads ugly, surely "encoded in UTF-8."

is just fine, or perhaps "encoded using UTF-8."

****************************************************************

From: Randy Brukardt
Sent: Tuesday, October 11, 2011  9:21 PM

"UTF-8 encoding" is what ISO 10646 defines, so I think we have to say that.
The first "encoded" could (and should) go, however:

Returns the value of Item represented in UTF-8 encoding.

****************************************************************

From: Randy Brukardt
Sent: Tuesday, October 11, 2011  9:29 PM

Having said that, I see that the text for Convert and Decode does not include
the "encoding". That being the case (and adding it to those is awkward), I think
Robert is right and just dropping the trailing "encoding" is what needs to be
done.

****************************************************************

From: Randy Brukardt
Sent: Tuesday, October 11, 2011  10:55 PM

> So back to my proposed wording changes. Are they an improvement (or
> not); any specific suggestions; etc.??

I didn't get much back on these, and I tweaked them a bit more. Following is the
Static Semantics part of A.4.11 in !corrigendum format (starting after the reasons
exceptions are raised) after simplifying the wording. I included the 3 overview
paragraphs as they cover the important assumptions for the parameter encodings --
we don't have to mention these in each description.

One could imagine distributing this information to each individual function, but that
would be a bigger change. The effect of the overview paragraphs is that the actual
descriptions really only are for specifying the input and/or output encodings.

Complain now or wait until 2017 to make changes...

[Followed by the version /03 of the A.4.11 changes - Editor]

****************************************************************

From: Robert Dewar
Sent: Wednesday, October 12, 2011  5:27 AM

> "UTF-8 encoding" is what ISO 10646 defines, so I think we have to say that.
> The first "encoded" could (and should) go, however:
>
> Returns the value of Item represented in UTF-8 encoding.

that's of course just fine ...

****************************************************************

From: Robert Dewar
Sent: Wednesday, October 12, 2011  5:27 AM

> Having said that, I see that the text for Convert and Decode does not
> include the "encoding". That being the case (and adding it to those is
> awkward), I think Robert is right and just dropping the trailing "encoding"
> is what needs to be done.

I agree this is the better choice

****************************************************************

From: Tucker Taft
Sent: Wednesday, October 12, 2011  7:34 AM

Seems fine.  I'll admit I am not focused on this issue...

****************************************************************

From: Jean-Pierre Rosen
Sent: Wednesday, October 12, 2011  9:26 AM

> Complain now or wait until 2017 to make changes...

There should be the following sentence /somewhere/ (i.e. either in the general
description, or for each appropriate function):

The returned string includes an appropriate BOM if the Output_BOM parameter has
the value True.

****************************************************************

From: Randy Brukardt
Sent: Wednesday, October 12, 2011  6:34 PM

There already is such a sentence; it preceeds the list of reasons exceptions are
raised. (A.4.11(50/3)).

It *is* weird that the general semantics comes after the list of reasons
exceptions are raised. Perhaps all three of these general paragraphs should be
earlier in the Static Semantics section?

You can see what I'm talking about in the existing draft of A.4.11 if you
imagine the two paragraphs that start with "each of the <something>
functions..." (57/3 and 58/3) getting moved before the "For all Convert and
<something>" paragraphs (49/3 and 50/3).

Is that a good idea??

****************************************************************

From: Jean-Pierre Rosen
Sent: Thursday, October 13, 2011  3:04 AM

Rereading the section, I propose to reorganize current paragraphs 49 to
58 as follows:

Each of the Convert and Encode functions returns a UTF_String (respectively
UTF_8_String and UTF_16_String) value whose characters have position values that
correspond to the encoding of the Item parameter according to the encoding scheme
required by the function or specified by its Output_Scheme parameter. For UTF_8,
no overlong encoding is returned. A BOM is included at the start of the returned
string if the Output_BOM parameter is set to True. The lower bound of the returned
string is 1.

Each of the Decode functions takes a UTF_String (respectively UTF_8_String and
UTF_16_String) Item parameter which is assumed to contain characters whose
position values correspond to a valid encoding sequence according to the encoding
scheme required by the function or specified by its Input_Scheme parameter, and
returns the corresponding String, Wide_String, or value. The lower bound of the
returned string is 1.

For each of the Convert and Decode functions, an initial BOM in the input that
matches the expected encoding scheme is ignored, and a different initial BOM causes
Encoding_Error to be propagated.

The exception Encoding_Error is also propagated in the following
situations: ...

****************************************************************

From: Matthew Heaney
Sent: Monday, October 17, 2011  2:05 PM

I'm reading from AI05-0021 rev 1.6 here:

http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ai05s/ai05-0021-1.txt?rev=1.6

!standard A.18.3(102/2)  07-05-17  AI05-0021-1/03
!standard A.18.2(139/2)
!standard A.18.3(83/2)
!standard A.18.4(38/2)
!standard A.18.7(36/2)
!standard A.18.2(237/2)
!standard A.18.3(151/2)
!class binding interpretation 06-11-10
!status Amendment 201Z 08-11-26
!status WG9 Approved 07-06-29
!status ARG Approved  10-0-1  06-11-18
!status work item 06-11-10
!status received 06-08-31
!priority Medium
!difficulty Easy
!qualifier Error
!subject Issues with containers


 From the text of the AI, the !question is:

(1) A.18.3(102/2) says "Equivalent to Delete (Container, First
(Container), Count)",
but the second parameter of Delete has mode "in out", and thus cannot be
passed
a function call. Should this be fixed? (Yes.)


The !wording is:

(1) Replace A.18.3(102/2) with words:

If Container is empty, Constraint_Error is propagated. Otherwise,
Delete_First
removes (from Container) Count elements starting at the first element in
Container
(or all of the elements if there are fewer than Count elements in
Container).


I think that !wording is wrong.  You should always be able to delete
items from an empty container, without an exception being raised.

The other problem is that if we are to believe the wording of the AI (it
applies specifically to the doubly-linked list), then the behavior of
Delete_First for the doubly-linked list no longer matches the behavior
for the vector.  That has never been the case, as the vector and list
were designed to differ only in their time and space complexity, not
semantics.

The intent of AI05-0021 was to make the specification of the behavior of
Delete_First more precise, not to change its semantics.  However, the
wording of the AI really does change the semantics, and not in a benign way.

Here is what I think happened.  We have the original Delete operation:

procedure Delete (Container : in out List;
                   Position  : in out Cursor;
                   Count     : in     Count_Type := 1);

We also have the original Delete_First operation:

procedure Delete_First (Container : in out List;
                         Count     : in     Count_Type := 1);

Delete_First was defined in terms of Delete:

Equivalent to Delete (Container, First (Container), Count).

Yes, the Position parameter of operation Delete has mode in-out, so the
description of Delete_First is technically incorrect, but we all knew
what we meant.  However, Pascal wanted to make the description
technically correct, but the fix ended up breaking things.

Some history, if memory serves me correctly: Way back in the mists of
time, the Position parameter of operation Delete was allowed to be null
(by which I mean that the Has_Element predicate function returned
False).  Late in the design stage, the semantics were changed such that
if the Position parameter were null, then Delete would raise
Constraint_Error.  At that time no other changes were made to the
Delete_First operation.

When the description of Delete_First was changed (per AI05-0021), it was
a mechanical change, based on the newer semantics of Delete.  But such a
mechanical replacement doesn't work for Delete_First.

First of all, it should never be an error to delete 0 items from a
container.  However, using the new semantics described in AI05-0021,
attempting to delete 0 items from an empty container would raise
Constraint_Error.

However, there's nothing special about the 0 case.  If Delete_First is
called with N as the count value, and the list contains M items, then
for any N >= M, the effect is to clear the container.  It doesn't matter
that M happens to be 0 (that is, the container is empty).

At a minimum, I think the semantics of Delete_First should be described
something like this:

"If Container is empty, then the operation does nothing.  Otherwise,
Delete_First removes (from Container) Count elements starting at the
first element in Container (or all elements if there are fewer than
Count elements in Container)."

This at least makes the description of Delete_First internally consistent.

However, I would also make one small change to the semantics of
operation Delete, to make the behavior of Delete and Delete_First
consistent with each other: if the Count parameter is 0, then the
operation does nothing, irrespective of the value of Position parameter,
and irrespective of the current length of the container.  As it stands
now, operation Delete raises Constraint_Error if the Position parameter
is null, even for an empty container.  This seems wrong to
me, since attempting to delete 0 items from a container should never
raise an exception.  (When the container is empty, a cursor can only
have the value No_Element, which is why we should allow this value, at
least in this one case.)

Note that the index-based Delete operation for the vector container does
the right thing, and says explicitly that if the Count is 0, then the
operation does nothing.  The cursor-based version of Delete for vector
seems to suffer from the same problem as for the list, in which it is
impossible to request that 0 items be deleted from an empty container.
I think that when the Count is 0, it should not matter what value the
Position parameter has, and Delete should be a no-op.

****************************************************************

From: Randy Brukardt
Sent: Monday, October 17, 2011  3:18 PM

> I'm reading from AI05-0021 rev 1.6 here:
>
> http://www.ada-auth.org/cgi-bin/cvsweb.cgi/ai05s/ai05-0021-1.txt?rev=1
> .6

Please start with the draft standard first, and only read AIs if you have a need
to find out why a change was made. (You may have done this, but I can't tell
from your message.) At this point, AIs don't matter, only the wording of the
Standard matters (it's rarely the same because of many changes).

Now I do see something interesting here: This AI never made it into the Standard
at all! None of the changes requested by this AI are in any of the drafts,
somehow I must have missed it. (Hope there aren't any others like that.)

...
> At a minimum, I think the semantics of Delete_First should be
> described something like this:
>
> "If Container is empty, then the operation does nothing.
> Otherwise, Delete_First removes (from Container) Count elements
> starting at the first element in Container (or all elements if there
> are fewer than Count elements in Container)."
>
> This at least makes the description of Delete_First internally
> consistent.

Huh? Maybe you mean consistent with Vectors. The wording as given is consistent
with the Ada 2005 wording for Delete_First for Lists. (Which might have been
wrong.)

> However, I would also make one small change to the semantics of
> operation Delete, to make the behavior of Delete and Delete_First
> consistent with each other: if the Count parameter is 0, then the
> operation does nothing, irrespective of the value of Position
> parameter, and irrespective of the current length of the container.

I think this is a bad idea. Passing a null position into an operation that is
supposed to do something with that position is always a mistake. If you don't
have a good position, then don't call Delete.

> As it stands now, operation
> Delete raises Constraint_Error if the Position parameter is null, even
> for an empty container.

Yes, that makes sense to me. If cursors were instead access types, this would
clearly have been a null-excluding parameter. There is no reason to ever pass
null into this routine.

> This seems wrong to me,
> since attempting to delete 0 items from a container should never raise
> an exception.  (When the container is empty, a cursor can only have
> the value No_Element, which is why we should allow this value, at
> least in this one case.)

That's just too tricky. It doesn't make sense to call Delete of a particular
element if you don't have any elements. I can see why it might make sense to
call Delete_First and Delete_Last in that case (because no positions are
involved), but the specific item Delete is a different beast.

> Note that the index-based Delete operation for the vector container
> does the right thing, and says explicitly that if the Count is 0, then
> the operation does nothing.

That seems like a bug to me; if I index into an empty vector, I get
Constraint_Error. You can't do an element-by-element delete this way. It takes
great care to do such a delete correctly if you are using slices. Null ranges do
help some, as numbers (indexes) do work a bit differently than pointers
(cursors), so I can understand a difference in behavior.

> The cursor-based version of Delete for vector seems to suffer from the
> same problem as for the list, in which it is impossible to request
> that 0 items be deleted from an empty container.

It seems right to me. I would never allow passing "null" into a subprogram in a
similar circumstance, and probably would use a null-excluding parameter to have
it checked at the call site. One could imagine using a subtype predicate to do a
similar check in this package (something we might very well have done had they
existed in Ada 2005).

> I think that when the Count is 0, it should not matter what value the
> Position parameter has, and Delete should be a no-op.

Yeah, you're always confused about what should happen when Count = 0. :-)

It's clear that this case is really unlikely to occur in practice (you'd have to
explicitly code it to use a null position, and if you did that, you could have
just as easily avoided the Delete call in the first place). So the important
question here is one of compatibility. You are suggesting a silent change in
behavior which could break existing programs. That seems like a bad idea unless
the issue is important (and this one [Delete] is clearly not).

Of course, if GNAT is currently doing this "wrong" (that is, doing what you want
rather than what the Standard says), that would suggest that the change would be
less of an issue in practice. So, what did the GNAT code do in this case last
month? (I'm asking about last month so that there is no possibility of gaming
the answer by making a last-minute change and claiming that's the "current
behavior".)

****************************************************************

From: Randy Brukardt
Sent: Tuesday, October 18, 2011  1:18 AM

> > However, I would also make one small change to the semantics of
> > operation Delete, to make the behavior of Delete and Delete_First
> > consistent with each other: if the Count parameter is 0, then the
> > operation does nothing, irrespective of the value of Position
> > parameter, and irrespective of the current length of the container.
>
> I think this is a bad idea. Passing a null position into an operation
> that is supposed to do something with that position is always a
> mistake. If you don't have a good position, then don't call Delete.

I was just looking at the mail in AI05-0021-1, and noticed the following from
Pascal (Sept 29, 2006):

>To me this is just another case where Matt and the rest of us have
>different views of what exceptions are for.  If you look at the minutes
>of the 2004 Atlanta meeting, you'll see a very similar discussion
>regarding the version of Delete that takes a cursor: should it raise an
>exception or be a no-op if the cursor is null?  Matt wanted a no-op
>because the post-condition (the element designated by the cursor is no
>longer in the container) is true.  We decided for C_E on the ground
>that such a usage pattern was more likely to be a bug, and also because
>we thought that the post-condition didn't make much sense anyway (what
>is the element designated by a null cursor anyway?).

This reminds me that we've already had this discussion vis-a-vis Delete, and I'm
pretty sure that the wording in the Standard is correct.

OTOH, your original query about Delete_First does seem like it is wrong; there
doesn't seem to be any sensible reason to raise Constraint_Error just because
the container is empty. There is no problem deleting elements from an empty
container (it just does nothing). Indeed, all we need to do is drop the first
sentence and the "otherwise":

"Delete_First removes (from Container) Count elements starting at the first
element in Container (or all elements if there are fewer than Count elements in
Container)."

We don't need to mention an empty container, because we are removing all of the
elements if there are fewer than Count elements: if Count = 0, we remove all
(which is to say none) of the elements in the container.

Probably a better alternative would be to use the same wording as Delete_Last
uses (which makes sense because these are next to each other and ought to be
parallel):

"If Length (Container) <= Count, then Delete_First is equivalent to Clear
(Container). Otherwise, it removes the first Count nodes from Container."

I've put the above wording into the editorial review AI.

****************************************************************

From: Matthew Heaney
Sent: Tuesday, October 18, 2011  10:02 AM

> This reminds me that we've already had this discussion vis-a-vis
> Delete, and I'm pretty sure that the wording in the Standard is correct.

Agreed.  I just thought it was odd that Delete_First allows you to delete from
an empty container, but Delete does not.

> Probably a better alternative would be to use the same wording as
> Delete_Last uses (which makes sense because these are next to each other and
> ought to be parallel):
>
> "If Length (Container)<= Count, then Delete_First is equivalent to Clear
> (Container). Otherwise, it removes the first Count nodes from Container."
>
> I've put the above wording into the editorial review AI.

OK, thanks for looking into that.

****************************************************************

From: Randy Brukardt
Sent: Wednesday, October 12, 2011  8:41 PM

Erhard writes in one of his reviews:

>A.18.7(18.1/3) reads
>> Set'Write writes the length of Set elements to the stream. Set'Read
>> reads the length of Set elements from the stream.

>I am not into Sets, but it seems very unlikely to me that the semantics
>should be that the 'Read and 'Write attributes would
>
>  - not write the set itself, but (only) some length; note that only the
>    default version composes automatically. The above should probably say
>    "The default implementation of Set'Write ... to the stream prior to
>    the streaming of the
>     components. The default implementation of Set'read reads....
>
>  - write the length of the ELEMENTS (i.e., of the next dimension down),
>    instead of the the "length" of the SET (quite a misnomer for a set size,
>    but that is old stuff).
>
>This comment applies to many subsections; see AI05-00001 for where they are.

It looks to me that someone tried to "improve" the readability of this text, and
turned it into hash. It is supposed to say

Set'Write writes Length (Set) elements to the stream. Set'Read reads Length
(Set) elements from the stream.

the point here being that the number of elements written is Length (Set) [or
whatever container], and not some more convinient number. In particular, it does
*not* stream the entire Capacity of elements for a bounded form (which would be
the "natural" implementation). There is an AARM Implementation Note under
Vectors which explains this (A.18.2(88.b/3). It's a bit weird that there isn't a
similar note in the other places (usually a shorter one referring to Vectors for
details) -- we usually do that -- but in any case that note makes the intent
clear.

[Aside: We could use the prefix form Set.Length rather than the call form Length
(Set), but reviewers have generally hated the use of the prefix form. So I'm not
suggesting that.]

But I note that this wording seems to imply that this is *all* that Set'Write
does, and that is not the intent -- this is intended solely to specify the
number of calls to Element'Write, and not to say anything about any other
contents. (Other than that there is a requirement that bounded and unbounded
containers use the same contents -- this is given in the various bounded forms.)
So I think we need a more extensive rewording, but I'm not sure what it should
be.

The best I can come up with is:

Set'Write writes exactly Length (Set) elements to the stream and may write other
information about the Set as well. Set'Read reads exactly Length (Set) elements
from the stream along with any other information written by Set'Write.

But this seems rather wordy and vaguely over-specified. Does anyone have any
better ideas??

****************************************************************

From: Erhard Ploedereder
Sent: Thursday, October 13, 2011  1:04 PM

My stab at it....

Set'Write writes Length(Set) elements of the SET to the stream. It may write
additional information about the Set as well. Set'Read reads Length(Set)
elements of Set from the stream and consumes any additional information written
by Set'Write.

It's difficult to get it shorter (unless is is implicitly acceptable that Read
and Writes generally stream hidden information as well. Then one could drop the
second parts and put this only into the AARM.)

****************************************************************

From: Randy Brukardt
Sent: Friday, October 15, 2011  10:18 PM

Tucker, Bob, someone, help us out here. The problem with the original wording is
that it appears to say that *only* elements are written to the stream, which
isn't possible in general. (And in some versions, it also appears to say that
only the length is written, which is balmy.)

****************************************************************

From: Tucker Taft
Sent: Saturday, October 15, 2011 10:42 AM

I think we want the stream representation of containers to be as portable as
possible.  What could you possibly need for a Set over and above the elements
themselves, and some way to know when you have read all the elements?
Furthermore, didn't we have a desire that you could read a bounded container
having written an unbounded one, and vice-versa? Or do I misremember that?

****************************************************************

From: Edmond Schonberg
Sent: Saturday, October 15, 2011  11:20 AM

You remember correctly, this is AI05-0184 : compatibility of streaming of
containers.

****************************************************************

From: Randy Brukardt
Sent: Saturday, October 15, 2011  6:43 PM

> Or do I misremember that?

You're not helping. :-)

First, this wording is used for all of the containers; it's not specific to
Sets. It just happens that Erhard was reviewing the sets when this came up.

One could imagine that for Sets and Lists, that you would require the streaming
to be a length following by the elements. But that doesn't make sense for the
other containers. (And it's not a great idea even for the sets, see below.)

* For vectors, we have to handle "empty elements". In the case the indefinite
  forms, "empty elements" probably don't exist at all and cannot be streamed. So
  there has to be an empty vs. non-empty bit in the stream for each element. And
  I don't think we want to prevent definite containers from having and streaming
  such a bit (although it is not required to have such a bit). Janus/Ada will
  have a empty element bit for the definite containers - it's safer than
  ignoring the error.

* For maps, we clearly need to stream the keys in some way.

* For trees, we have to stream the relationship of the elements in some way.
  Else the stream would lose the structure, which would be bad news.

* For hashed maps and sets, we ought to allow streaming some form of the hash
  table. Requiring the hash table to be rebuilt on a read could be quite
  expensive (every element would have to be hashed), especially with large
  containers and a slow hash function.

* For ordered maps and sets, it might make sense to stream some indication of
  the red/black tree structure. Again, it might be expensive to rebuild that for
  large containers. (I don't know enough about red-black trees to know for sure
  on this one, and I'd hate for the language to make such a decision.)

* Even for holders, we have to stream an indication of whether the holder is
  empty or not: it's not just an element.

The point is that implementations may want to stream other information to make
recreating the structure cheaper (or possible!). I don't think the language
should get in the way of that.

The only properties that we intended to guarentee:

(1) That unbounded and bounded forms of a particular container use the same
    stream format. A.18.19(11-14/3) does this for vectors, similar wording
    exists for all of the other containers.

(2) That the stream contains only elements that are in use, not the entire
    capacity of the container. Specifically, Length of container elements are
    written (for containers that have lengths). That's what this text was
    supposed to ensure. But it reads as if it means a lot more than that, which
    is the problem.

So, please suggest some improved wording -- I know you're good at it.

I had again:

> Set'Write writes exactly Length (Set) elements to the stream and may
> write other information about the Set as well. Set'Read reads exactly
> Length (Set) elements from the stream along with any other information
> written by Set'Write.

Erhard had:

> Set'Write writes Length(Set) elements of the SET to the stream. It may  write
> additional information about the Set as well. Set'Read reads Length(Set)
> elements of Set from the stream and consumes any additional information
> written by Set'Write.

P.S. Queues are limited, and thus don't have stream attributes by default, and
none are defined. I think this is intended, but I don't think we ever discussed
it. Should the queues have explicitly declared stream attributes??

****************************************************************

From: Tucker Taft
Sent: Saturday, October 15, 2011  7:15 PM

I mildly prefer Erhard's wording.

> P.S. Queues are limited, and thus don't have stream attributes by
> default, and none are defined. I think this is intended, but I don't
> think we ever discussed it. Should the queues have explicitly declared stream attributes??

No, no need in my view.  And how would it deal with concurrent changes to the
queue?  This seems like a race-condition waiting to happen.

****************************************************************

From: Brad Moore
Sent: Saturday, October 15, 2011  11:35 PM

I mildly prefer a mix of Randy's and Erhards, :-) I had suggested wording for
this in my review as well, if I mix in my version with Randy's and Erhards,
would this be an improvement?

Set'Write writes the elements of Set to the stream, and may write other
information about the Set as well. Set'Read reads Length (Set) elements from the
stream, along with any other information written by Set'Write.

****************************************************************

From: Randy Brukardt
Sent: Sunday, October 16, 2011  7:14 PM

Not exactly like this, because the Write wording doesn't say how many elements
are written, which is the entire point of the wording. (We could probably leave
that information out of 'Read, since it has to "work", but for 'Write, anything
would work so long as 'Read is the same.)

The whole (original) point of this wording was to say that writing
*capacity* elements (rather than length elements) is wrong. That needs to be
fairly clear, as writing capacity elements is easier (it probably will happen
"naturally" for bounded forms).

I note that neither my wording nor Erhard's makes it crystal clear that the
elements written are the "active" ones, but I don't think that is necessary, as
'Read would not "work" if some other elements are written (and the right number
is written as well).

****************************************************************

From: Erhard Ploedereder
Sent: Monday, October 17, 2011  8:43 AM

> Set'Write writes the elements of Set to the stream, and may write
> other information about the Set as well.
> Set'Read reads Length (Set) elements from the stream, along with any
> other information written by Set'Write.

Please a symmetric wording. If Read talks about Length(Set), Write should do,
too. Or neither should (which would be fine by me, but others have obviously
argued that one needs to make clear that unoccupied slots in the container for
Set are not written).

****************************************************************

From: Jean-Pierre Rosen
Sent: Monday, October 17, 2011 12:09 AM

> The whole (original) point of this wording was to say that writing
> *capacity* elements (rather than length elements) is wrong. That needs
> to be fairly clear, as writing capacity elements is easier (it
> probably will happen "naturally" for bounded forms).

But an implementation could write capacity elements, and argue that the extra
ones are just "service" information... Oh well, there are so many ways to make
unfriendly implementations. But maybe, turning this sentence into IA would be
more honest.

****************************************************************

From: Erhard Ploedereder
Sent: Sunday, October 16, 2011  7:16 AM

I noticed that all descriptions of predicates are completely silent on what
happens if any (dynamic) predicate expression raises an exception.

Presumably canonical semantics apply: the exception is raised at the point where
the predicate expression is evaluated. These points are sufficiently precisely
described for subtype predicates and for type invariants.

For preconditions (and maybe postconditions?), however, that does not seem to be
the case, and the RM caters to it by stating for the Assertion_Error exception:
6.1.1 29/3
{AI05-0145-2} If a precondition or postcondition check fails, the exception is
raised at the point of the call. [The exception cannot be handled inside the
called subprogram.]

The sentence needs to be extended to cover exceptions raised by the evaluation
of the predicate expressions.

Add a sentence to 29/3: The same applies to exceptions raised by the evaluation
of precondition or postcondition expressions.

----
I tried to merge it into the first sentence, but ultimately I preferred the
above version. Just in case, here is the combined version, if you prefer that.

{AI05-0145-2} If the evaluation of a precondition or postcondition expression
raises an exception, or if a failed precondition or postcondition check raises
Assertion_Error, the exception is raised at the point of the call. [The
exception cannot be handled inside the called subprogram.]

****************************************************************

From: Randy Brukardt
Sent: Thursday, October 27, 2011  9:21 PM

I understand your concern, but am not very happy with this wording. For one thing,
there is only one exception raised, so wording that is plural is suspicious. (I
recall some reviewer complaining about similar wording elsewhere.) And I don't
find it clear what "The same" refers to.

So I used:
"An exception raised by the evaluation of a precondition or postcondition
expression is also raised at the point of call."

****************************************************************

From: Erhard Ploedereder
Sent: Friday, October 28, 2011  9:23 AM

Fine by me.

****************************************************************

From: Edmond Schonberg
Sent: Wednesday, November 9, 2011  9:09 AM

The last paragraph of 5.5.2 describes the behavior of a reverse iteration as
replacing  First and Next with Last and Previous in the behavior of a forward
iteration.  It is not clear what should happen if the iterator is created with
an explicit Start cursor.  The iteration might proceed for the given start to
the "bottom" of the container (i.e. until Has_Element becomes false).  It might
proceed from the Last value of the cursor down to the specified First in the
iterator.   Which is the intended reading?

****************************************************************

From: Edmond Schonberg
Sent: Wednesday, November 9, 2011  9:43 AM

Answering my own question: I expect the proper reading to  be the second: from
Last of container down to the specified First, inclusive, because elsewhere the
"reverse" does not affect the domain of iteration.  An AARM note might still be
in order.

****************************************************************

From: Matthew Heaney
Sent: Wednesday, November 9, 2011  12:23 PM

There are 4 things you could want to do.  Given the cursor range

  F <= X <= L

you would want to:

(1)  Forward iterate over the (inclusive) range [F, X]:

procedure Op (Container : Container_Type) is begin
    for C in Container.Iterate loop
       E := Element (C);
       exit when C = X;
    end loop;
end Op;

Is this correct?


(2) Forward iterate over the (inclusive) range [X, L]:

procedure Op (Container : Container_Type) is begin
    for C in Container.Iterate (X) loop
       E := Element (C);
    end loop;
end Op;

Is this correct?


(3) Reverse iterate over the (inclusive) range [F, X]:

procedure Op (Container : Container_Type) is begin

   --  ???

end Op;

I don't know how to do (3), except the old-fashioned way.  (But maybe that is
the intended mechanism).


(4) Reverse iterate over the (inclusive) range [X, L]:

procedure Op (Container : Container_Type) is
begin
    for C in reverse Container.Iterate (X) loop
       E := Element (C);
    end loop;
end Op;

Is this correct?

That interpretation seems less useful (IMHO), since it duplicates:

procedure Op (Container : Container_Type) is
begin
    for C in reverse Container.Iterate loop
       E := Element (C);
       exit when C = X;
    end loop;
end Op;


BTW, What is the interpretation of:

   for C in reverse Container.Iterate (No_Element) loop ...;

?

****************************************************************

From: Edmond Schonberg
Sent: Wednesday, November 9, 2011  12:52 PM

...
>(1)  Forward iterate over the (inclusive) range [F, X]:
...
>Is this correct?

Yes.

>(2) Forward iterate over the (inclusive) range [X, L]:
...
>Is this correct?

Yes.

(3) Reverse iterate over the (inclusive) range [F, X]:
...
>I don't know how to do (3), except the old-fashioned way.  (But maybe that is
>the intended mechanism).

A.18.2 (230) would indicate that this is what you obtain with reverse:

If Start is not No_Element and does not designate an item in Container, then
Program_Error is propagated. If Start is No_Element, the call is equivalent to
Iterate (Container). Otherwise, Iterate returns a reversible iterator object
that will generate a value for the loop parameter designating each node in
Container, starting with the node designated by Start and moving the cursor as
per the Next function when used as a forward iterator, or moving the cursor as
per the Previous function when used as a reverse iterator. Tampering with the
cursors of Container is prohibited while the iterator object exists (in
particular, in the sequence_of_statements of the loop_statement whose
iterator_specificationdenotes this object). The iterator object needs
finalization.

>(4) Reverse iterate over the (inclusive) range [X, L]:
...
>Is this correct?

That would have been my understanding, but the quoted paragraph indicates
otherwise.  I have a problem with this interpretation because it means that
reverse changes the domain of iteration over containers, when it has no such
effect on numeric loops.

>That interpretation seems less useful (IMHO), since it duplicates:
...

See above.

>BTW, What is the interpretation of:
>
> for C in reverse Container.Iterate (No_Element) loop ...;
>
>?

As per the quoted paragraph, equivalent to Container.Iterate

****************************************************************

From: Matthew Heaney
Sent: Wednesday, November 9, 2011  1:06 PM

> As per the quoted paragraph, equivalent to Container.Iterate

Just so I understand, do you mean:

   for C in reverse Container.Iterate (No_Elem) loop ...;

is equivalent to:

   for C in reverse Container.Iterate loop ...;

?

****************************************************************

From: Matthew Heaney
Sent: Wednesday, November 9, 2011  2:19 PM

>> (4) Reverse iterate over the (inclusive) range [X, L]:
>>
>> procedure Op (Container : Container_Type) is begin for C in reverse
>> Container.Iterate (X) loop E := Element (C); end loop; end Op;
>>
>> Is this correct?
>
> That would have been my understanding, but the quoted paragraph
> indicates otherwise. I have a problem with this interpretation because
> it means that reverse changes the domain of iteration over containers,
> when it has no such effect on numeric loops.

A different line of reasoning is that you cannot compare iteration over a
container to iteration over a discrete range, because in the former case you
only specify one end of the range (but which one?), and in the latter case you
specify both ends of the range.

If the cursor value is always interpreted as the start of the iteration, then in
the reverse iteration case:

   for Cur in Cont.Iterate (X) loop ...;

means reverse iteration over the range [F, X].

(I'm not saying this line of reasoning is correct, just that it's
different.)

There is also the matter of how to specify an empty range.

If I have a classical iteration loop, like this:

procedure Op (Container : Container_Type) is
   Start : Cursor;
begin
   Start := ...;  -- some value, could be No_Elem
   while Has_Element (Start) loop ...;
end Op;

then if Start = No_Element, the loop does not execute.

The second form of the Iterate operation doesn't work like this, and if you say:

   Start := No_Element;
   for C in Container.Iterate (Start) loop

then this is interpreted as iterating over all elements, instead of none of
them.

Is there a way to specify an empty range, for the form of Iterate that accepts a
Start parameter?

****************************************************************

From: Edmond Schonberg
Sent: Wednesday, November 9, 2011  2:52 PM

> Is there a way to specify an empty range, for the form of Iterate that accepts
> a Start parameter?


The need for such functionality does not strike me as terribly urgent....

****************************************************************

From: Matthew Heaney
Sent: Wednesday, November 9, 2011  3:15 PM

Fair enough.  I guess the motivation for the question was about preventing
accidental endless loops.  I can imagine a scenario in which the intent is for
the iteration to terminate when you fall off the end of the range, as is the
case when you have a classical loop and the cursor value is No_Element.  But you
cannot use the second form of Iterate that way.  If a value of No_Element for
the Start value been given that interpretation ("no iteration occurs if Start
equals No_Element"), then there would have been symmetry across different styles
of iteration.

****************************************************************

From: Randy Brukardt
Sent: Wednesday, November 9, 2011  11:26 PM

> 1)  Forward iterate over the (inclusive) range [F, X]:
...
>Is this correct?

Yes, there is an AARM note suggesting using exit to prematurely exit a loop.

>(2) Forward iterate over the (inclusive) range [X, L]:
...
>Is this correct?

Yes.

>(3) Reverse iterate over the (inclusive) range [F, X]:

>I don't know how to do (3), except the old-fashioned way.  (But maybe that is
>the intended mechanism).

This is how the reverse iterator is defined, IMHO: the iteration starts at X and
proceeds toward F.

procedure Op (Container : Container_Type) is
begin
  for C in reverse Container.Iterate (X) loop
     E := Element (C);
  end loop;
end Op;

Is the correct answer.

>(4) Reverse iterate over the (inclusive) range [X, L]:
>
>procedure Op (Container : Container_Type) is
>begin
>  for C in reverse Container.Iterate (X) loop
>     E := Element (C);
>  end loop;
>end Op;
>
>Is this correct?

No. (3) is the correct answer (given the current wording).

>That interpretation seems less useful (IMHO), since it duplicates:
>
>procedure Op (Container : Container_Type) is
>begin
>  for C in reverse Container.Iterate loop
>     E := Element (C);
>     exit when C = X;
>  end loop;
>end Op;

Right, which is why the wording means (3).

>BTW, What is the interpretation of:
>
> for C in reverse Container.Iterate (No_Element) loop ...;
>
> ?

The meaning as defined by the Standard [Draft 14] is that the whole container
iteration is performed. Not sure that's ideal, but that's what it says and there
has to have been some reason for selecting that.

****************************************************************

From: Randy Brukardt
Sent: Wednesday, November 9, 2011  11:37 PM

> That would have been my understanding, but the quoted paragraph indicates
> otherwise.  I have a problem with this interpretation because
> it means that reverse changes the domain of iteration over containers,
> when it has no such effect on numeric loops.


There are two good reasons for this behavior:
(1) As Matt has shown, the behavior you are suggesting is easy to write without
    the Start parameter, while the behavior as defined in the RM is impossible
    to write with an iterator if your semantics is adopted.
(2) The parameter name is "Start"; you're suggesting that the iteration end at
    Start. That's just plain mind-bending.

I think that you are making a mistake assuming that these are like numeric cases
-- as Matt notes, you are only giving the starting position, not both ends.

The only counterargument is that the indexed forms of vectors will work like a
numeric range (because they ARE a numeric range). I'd rather fix that by
providing an iterator for them, too.

Anyway, we'll need to discuss.

>> That interpretation seems less useful (IMHO), since it duplicates:

>See above.

"See above" doesn't seem to me to be much of an answer to much "less useful". If
we have to trade utility for intellectual purity, I surely would select utility.
(Both is best of course, but in this case your suggestion is much less useful,
indeed it is pointless. I'd rather get rid of reverse possibility altogether
than adopt your semantics.)

****************************************************************

From: Matthew Heaney
Sent: Wednesday, November 9, 2011  11:42 PM

> The meaning as defined by the Standard is that the whole container
> iteration is performed. Not sure that's ideal, but that's what it says
> and there has to have been some reason for selecting that.

You can see the potential problem via a kind of inductive argument:

If, to iterate over the range [X, L], you do this:

for C in Container.Iterate (X) loop ...;

Then, to iterate over range [Next(X), L], you do this:

for C in Container.Iterate (Next (X)) loop ...;

This is true for all cursor values, except when X = L.  This strikes me as
error-prone.

****************************************************************

From: Randy Brukardt
Sent: Wednesday, November 9, 2011  11:53 AM

I admit, I think it would be better to just raise Constraint_Error, because it
is impossible to *Start* at No_Element. And the parameter name is "Start" (and
as previously discussed, that seems like the best thing for it to do). I don't
like tricky interpretations (and any interpretation of No_Element here is going
to be tricky). But I realize this doesn't match your "inductive argument".

****************************************************************

From: Matthew Heaney
Sent: Thursday, November 10, 2011  12:08 AM

Well you know what I always say: "you have to have a zero".  (Well, it was EWD
who said it about Red, but never mind.)  I would argue that the second iterator
form should have a way for the loop to execute 0 times.

The canonical case is iterating over an empty container: it would be nice for
the iterator to do nothing, instead of raising CE, just like for a normal
for-loop.  Generalize from an empty container to an empty sequence, and the
argument is the same.

****************************************************************

From: Matthew Heaney
Sent: Thursday, November 10, 2011  12:19 AM

I had a question about implementing the second form of Iterate (the version with
the Start parameter, as above).

The factory function Iterate doesn't know whether this is a forward or reverse
iteration, so it doesn't know whether First or Last will be called to get the
initial value of the sequence.  So both functions must return the same value
(the value of the Start parameter -- X in our present examples).

Is this correct?

I think this means that there must be two distinct concrete types: (1) one for
the first Iterate form, and (2) another for the second Iterate form.

In the case of (1), First (Iterator) returns Container.First, and Last
(Iterator) returns Container.Last.

In the case of (2), First (Iterator) and Last (Iterator) both return the value
of the Start parameter.

Does this make sense?  This follows from my reading of RM12 5.5.2.

****************************************************************

From: Randy Brukardt
Sent: Wednesday, December 14, 2011  11:38 PM

I didn't notice this question before (and nobody answered it), sorry.

Matthew Heaney writes: (Back on November 10th) ...

> > This is how the reverse iterator is defined, IMHO: the iteration
> > starts at X and proceeds toward F.
> >
> > procedure Op (Container : Container_Type) is begin
> >    for C in reverse Container.Iterate (X) loop
> >       E := Element (C);
> >    end loop;
> > end Op;
> >
> > Is the correct answer.
>
>
> I had a question about implementing the second form of Iterate (the
> version with the Start parameter, as above).
>
> The factory function Iterate doesn't know whether this is a forward or
> reverse iteration, so it doesn't know whether First or Last will be
> called to get the initial value of the sequence.  So both functions
> must return the same value (the value of the Start parameter -- X in
> our present examples).
>
> Is this correct?
>
> I think this means that there must be two distinct concrete
> types: (1) one for the first Iterate form, and (2) another for the
> second Iterate form.
>
> In the case of (1), First (Iterator) returns Container.First, and Last
> (Iterator) returns Container.Last.
>
> In the case of (2), First (Iterator) and Last (Iterator) both return
> the value of the Start parameter.
>
> Does this make sense?  This follows from my reading of RM12 5.5.2.

Yes, that was my expectation for these iterators: each one will need a separate
concrete implementation (all hidden in either the private part or the body of
the container packages). One can argue that that is a downside of the interface
model for these things: everything has to be defined as a function because
components aren't supported in interfaces. One could imagine a model that would
have left determining the start point to "magic" (more likely a discriminant or
constructor function's initialization), but that would have been a lot harder to
describe. (And it's too late to redo the underlying iterator model now, unless
of course there is a major problem with it. This doesn't come close.)

****************************************************************

From: Matthew Heaney
Sent: Thursday, December 15, 2011  9:05 AM

Ed and I were able to figure out how to do it in GNAT with just a single concrete
iterator type.  The iterator object caches either the start position (if this form
(2) as above), or null (if this is form (1) above).  The First and Last iterator
operations inspect the cursor value cached by the iterator object, and either return
the cached value (if it's non-null, as in (2)), or the corresponding container
position (as in (1), by forwarding the request to the container operation).

****************************************************************

From: Matthew Heaney
Sent: Thursday, November 10, 2011  10:46 AM

Which containers support partial iterators?

(By "partial iterator" I mean the iterator factory function that accepts a
cursor as the Start parameter, a value designating the position from which to
begin the iteration.)

I have been searching the Ada Issues databases, and grepping the text files from
the version of RM12 that I downloaded this morning, and haven't been able to
answer this question to my satisfaction.

My copy of RM12 seems to suggest that only vectors and lists support the form
for partial iteration.

However, I'm skeptical that this is the case.  My assumption is that all
containers should support partial iteration.  (Of course not all containers
support reverse iteration, but that is an orthogonal issue.)

Can someone confirm whether all containers do in fact support partial iteration?

***************************************************************

From: Randy Brukardt
Sent: Thursday, November 10, 2011   6:22 PM

Only list and vectors support "partial iteration", because they have a natural
order. Trees have a separate Iterate_Subtree, but there is no support for
starting in the middle somewhere. (It wouldn't mean much.) Perhaps the ordered
sets and maps should also support it, but surely not the hashed sets and maps
(those also do not support reverse iterators, since the order is unspecified --
it makes no sense to depend on the order in any way).

****************************************************************

From: Matthew Heaney
Sent: Thursday, November 10, 2011   8:52 PM

> Perhaps the ordered sets and maps should also support it, but surely
> not the hashed sets and maps (those also do not support reverse
> iterators, since the order is unspecified -- it makes no sense to
> depend on the order in any way).

But isn't the syntax:

   for C in M.Iterate (X) loop ...;

defined as equivalent to:

   C := X;
   while Has_Element (C) loop
      ...
      Next (C);
   end loop;

?

Agreed that it doesn't make sense to depend on order in any way, but that
argument is true even for the case of iteration using a classical loop, as
above.

Anyway, no big deal.  For now I'll assume that the second form can be used for
ordered sets and maps (but not for hashed sets or maps).

****************************************************************

From: John Barnes
Sent: Saturday, November 12, 2011   8:41 AM

While writing the wrat, I noticed that a static predicate cannot use the operator not
but it can use and or xor. The rule says both operands must be predicate static but not
has only one operand. See 3.2.4(12/3 etc)

Also cannot have a static conditional exoression but canhave a ststic case expression.
Strange becuase a conditional can be mapped onto a case.

****************************************************************

From: Bob Duff
Sent: Saturday, November 12, 2011  11:30 AM

> While writing the wrat,

You misspelled "righting the wrat".

>... I noticed that a static predicate cannot use the operator not but 
>it can use and or xor. The rule says both operands must be predicate 
>static but not has only one operand. See 3.2.4(12/3 etc)

Clearly a mistake.  The discussion section of the AI says "not" is allowed.
Should be:

* a call to a predefined boolean logical operator, where both operands (or the
  single operand, in the case of "not") are predicate-static; or

> Also cannot have a static conditional exoression but canhave a ststic 
> case expression. Strange becuase a conditional can be mapped onto a case.

I agree that's strange.  I've no idea why I left that out.

****************************************************************

Questions? Ask the ACAA Technical Agent