!standard 1.1.2(23) 11-10-26 AI05-0262-1/04 !standard 3.1(1) !standard 3.2.4(0) !standard 3.3(19) !standard 3.5(30/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(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(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(58/2) !standard A.18.6(74/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(81/2) !standard A.18.9(93/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.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 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" Add "access" to the list of anonymous types in 3.3.1(1). 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.] 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 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): "...subprogram {or entry}. {An exception raised by the evaluation of a precondition or postcondition expression is also 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 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. 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) and 10.1.1(12.3/3): "...{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 (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 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 (respectively UTF_8_String and 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 (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. 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 "set" by the name of the container] "Set'Write writes exactly Length(Set) elements of the set to the stream. It may write additional information about the set as well. Set'Read reads exactly Length(Set) elements of Set from the stream and consumes any additional information written by Set'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(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. 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 ..." Modify A.18.9(93/2): "...Otherwise{,} Previous returns a cursor designating the {predecessor }element {of}[that precedes] the one ..." 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..." In B.2(10.1/2), 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: 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(252/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(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) @dinsa @xbullet @dinst @xbullet !corrigendum 3.2.4(0) @dinsc Force a conflict; the real text is found in the conflict file. !corrigendum 3.3(19) @drepl @xbullet @dby @xbullet @xbullet !corrigendum 3.3.1(1) @drepl An @fa declares a @i 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 @fa may include the definition of the (anonymous) type of the object. !corrigendum 3.5(30/2) @drepl @xindent 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).> @dby @xindent 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.8.1(10) @drepl @xbullet that is an @fa covers a value if the value equals the value of the @fa converted to the expected type.> @dby @xbullet that is a @fa covers a value if the value equals the value of the @fa converted to the expected type.> !corrigendum 3.8.1(11) @drepl @xbullet that is a @fa covers all values (possibly none) that belong to the range.> @dby @xbullet that is a @fa covers all values (possibly none) that belong to the subtype and that satisfy the static predicate of the subtype (see 3.2.4).> @xbullet that is a @fa covers all values (possibly none) that belong to the range.> !corrigendum 3.8.1(15) @drepl @xbullet @fa shall cover only values in that subtype, and each value of that subtype shall be covered by some @fa (either explicitly or by others);> @dby @xbullet @fa shall cover only values in that subtype that satisfy its predicate (see 3.2.4), and each value of that subtype that satisfies its predicate shall be covered by some @fa (either explicitly or by others);> !corrigendum 3.9(25.1/2) @drepl 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. @dby 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) @drepl In the above rules, the operand of a view conversion, parenthesized expression or @fa is considered to be used in a context if the view conversion, parenthesized expression or @fa itself is used in that context. @dby In the above rules, the operand of a view conversion, parenthesized expression or @fa is considered to be used in a context if the view conversion, parenthesized expression or @fa itself is used in that context. Similarly, the @i@fa of a @fa is considered to be used in a context if the @fa itself is used in that context. !corrigendum 4.3.3(18) @drepl In a @fa with more than one @fa, no two @fas are allowed to cover the same value (see 3.8.1); if there is no @b choice, the @fas taken together shall exactly cover a contiguous sequence of values of the corresponding index type. @dby In a @fa where all @fas are static, no two @fas are allowed to cover the same value (see 3.8.1); if there is no @b choice, the @fas taken together shall exactly cover a contiguous sequence of values of the corresponding index type. !corrigendum 4.5.2(2) @drepl A @i, using @b or @b, 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. @dby A @i, using @b or @b, 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) @dinsa @xbullet @dinst 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) @drepl @xcode 1 .. 10 -- @ft<@i> Today @b Mon .. Fri -- @ft<@i> Today @b Weekday -- @ft<@i> Archive @b Disk_Unit -- @ft<@i> Tree.@b Addition'Class -- @ft<@i>> @dby @xcode 1 .. 10 -- @ft<@i> Today @b Mon .. Fri -- @ft<@i> Today @b Weekday -- @ft<@i> Card @b Clubs | Spades -- @ft<@i> Archive @b Disk_Unit -- @ft<@i> Tree.@b Addition'Class -- @ft<@i>> !corrigendum 4.5.7(0) @dinsc Force a conflict; the real text is found in the conflict file. !corrigendum 4.9(33) @dinsc Force a conflict; the real text is found in the conflict file. !corrigendum 4.9(34) @drepl @xbullet > @dby @xbullet !corrigendum 5.4(7) @drepl @Xbullet is a @fa (including a @fa or a @fa) having a static and constrained nominal subtype, or is a @fa whose @fa denotes a static and constrained scalar subtype, then each non-@b @fa shall cover only values in that subtype, and each value of that subtype shall be covered by some @fa (either explicitly or by @b).> @dby @Xbullet@fa is a @fa (including a @fa, @fa, or @fa) having a static and constrained nominal subtype, then each non-@b @fa shall cover only values in that subtype that satisfy its predicate (see 3.2.4), and each value of that subtype that satisfies its predicate shall be covered by some @fa (either explicitly or by @b).> !corrigendum 5.5(9) @drepl For the execution of a @fa with a @b @fa, the @fa is first elaborated. This elaboration creates the loop parameter and elaborates the @fa. If the @fa defines a subtype with a null range, the execution of the @fa is complete. Otherwise, the @fa is executed once for each value of the discrete subtype defined by the @fa (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 @b is present, in which case the values are assigned in decreasing order. @dby For the execution of a @fa with a @b @fa, the @fa is first elaborated. This elaboration creates the loop parameter and elaborates the @fa. If the @fa defines a subtype with a null range, the execution of the @fa is complete. Otherwise, the @fa is executed once for each value of the discrete subtype defined by the @fa 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 @b is present, in which case the values are assigned in decreasing order. For details about the execution of a @fa with the @fa being @b @fa, see 5.5.2. !corrigendum 6.1.1(0) @dinsc Force a conflict; the real text is found in the conflict file. !corrigendum 6.2(3) @drepl A type is a @i 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. @dby A type is a @i 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) @drepl Two profiles are @i 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. @dby Two profiles are @i if: @xbullet @xbullet @xbullet !corrigendum 6.3.1(18) @drepl Two profiles are @i if they are subtype-conformant, and corresponding parameters have the same names and default_expressions that are fully conformant with one another. @dby Two profiles are @i if they are subtype-conformant, if they have access-to-subprogram results whose designated profiles are fully conformant, and for corresponding parameters: @xbullet @xbullets; and> @xbullets, or they both have @fas that are fully conformant with one another; and> @xbullet !corrigendum 6.6(3) @drepl The @fa of a unary or binary operator shall have one or two parameters, respectively. A generic function instantiation whose @fa is an @fa is only allowed if the specification of the generic function has the corresponding number of parameters. @dby The @fa of a unary or binary operator shall have one or two parameters, respectively. The parameters shall be of mode @b. A generic function instantiation whose @fa is an @fa is only allowed if the specification of the generic function has the corresponding number of parameters, and they are all of mode @b. !corrigendum 6.8(0) @dinsc Force a conflict; the real text is found in the conflict file. !corrigendum 7.4(6/2) @drepl @xbullet that defines a constrained subtype, then the subtype defined by the @fa in the full declaration shall match it statically. On the other hand, if the subtype of the deferred constant is unconstrained, then the full declaration is still allowed to impose a constraint. The constant itself will be constrained, like all constants;> @dby @xbullet @i that defines a constrained subtype, then the constraint defined by the @fa in the full declaration shall match the constraint defined by @i statically. On the other hand, if the subtype of the deferred constant is unconstrained, then the full declaration is still allowed to impose a constraint. The constant itself will be constrained, like all constants;> !corrigendum 7.5(2.1/2) @drepl In the following contexts, an @fa of a limited type is not permitted unless it is an @fa, a @fa, or a parenthesized @fa or @fa whose operand is permitted by this rule: @dby In the following contexts, an @fa of a limited type is not permitted unless it is an @fa, a @fa, a parenthesized @fa, or @fa whose operand is permitted by this rule, or a @fa all of whose @i@fas are permitted by this rule: !corrigendum 7.6.1(13.1/2) @drepl In the case of an @fa that is a master, finalization of any (anonymous) objects occurs as the final part of evaluation of the @fa. @dby In the case of an @fa that is a master, finalization of any (anonymous) objects occurs after completing evaluation of the @fa and all use of the objects, prior to starting the execution of any subsequent construct. !corrigendum 7.6.1(20) @dinsa @xbullet @dinst @s8<@i> If the execution of an @fa 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 @fa. The implementation may finalize objects created by @fas 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) @drepl @xbullet or @fa.> @dby @xbullet or @fa;> !corrigendum 10.1.1(12.2/2) @drepl @xbullet, a declaration of the limited view of that package, with the same @fa.> @dby @xbullet immediately with the visible part, a declaration of the limited view of that package, with the same @fa.> !corrigendum 10.1.1(12.3/2) @drepl @xbullet in the visible part, an incomplete view of the type; if the @fa is tagged, then the view is a tagged incomplete view.> @dby @xbullet immediately within the visible part that is not an @fa, an incomplete view of the type with no @fa; if the @fa is tagged, then the view is a tagged incomplete view.> !corrigendum 10.1.2(21/2) @drepl @xbullet as, or within the scope of, a @fa that mentions the same library package; or> @dby @xbullet for a @fa that is within the scope of a @fa that mentions the same library package; or> !corrigendum 10.1.2(22/2) @drepl @xbullet as, or within the scope of, a @fa that names an entity declared within the declarative region of the library package.> @dby @xbullet for a @fa that is within the scope of a @fa that names an entity declared in the declarative region of the library package.> !corrigendum 13.11(21) @dinsa 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. @dinst For each of the calls of Allocate described above, @i

(equivalent to @i'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 @i'Max_Size_In_Storage_Elements, where @i is the designated subtype of @i. The Alignment parameter is at least @i'Alignment if @i 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 @i'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) @drepl 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 @fa for an access type whose pool is Name'Storage_Pool. @dby 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 @fa for an access type whose pool is Name'Storage_Pool. !corrigendum 13.11.3(4) @drepl The @i@fa of a @fa Controlled shall denote a non-derived access subtype. @dby The @i@fa shall denote a variable. If the @fa is used as a configuration pragma, the @fa shall be @b, and it defines the @i to be @b within all applicable compilation units (see 10.1.5), except within the immediate scope of another @fa 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 @i@fa, except within the immediate scope of a later pragma Default_Storage_Pool. Thus, an inner pragma overrides an outer one. A @fa 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 @fa Default_Storage_Pool. !corrigendum A.4.5(82.1/2) @drepl 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). @dby 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) @dinsc Force a conflict; the real text is found in the conflict file. !corrigendum A.13(14) @dinsa 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. @dinst 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) @drepl @xindent @dby @xindent !corrigendum A.16(110/2) @drepl @xindent @dby @xindent !corrigendum A.16(112/2) @drepl @xindent @dby @xindent !corrigendum A.18.1(7/2) @drepl 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. @dby Capacity_Error is raised when the capacity of a container is exceeded. !corrigendum A.18.2(88/2) @dinsa Execution of the default implementation of the Input, Output, Read, or Write attribute of type Cursor raises Program_Error. @dinst Vector'Write writes exactly Length(Vector) elements of the vector to the stream. It may write additional information about the vector as well. Vector'Read reads exactly Length(Vector) elements of Vector from the stream and consumes any additional information written by Vector'Write. !corrigendum A.18.2(147/2) @dinsa Force a conflict; the real text is found in the conflict file. @dinst Nothing. !corrigendum A.18.2(231/2) @drepl 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. @dby 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) @drepl @xbullet @dby @xbullet !corrigendum A.18.2(254/2) @drepl The execution of an @fa for a vector shall have the effect of copying the elements from the source vector object to the target vector object. @dby The execution of an @fa 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) @dinsa Execution of the default implementation of the Input, Output, Read, or Write attribute of type Cursor raises Program_Error. @dinst List'Write writes exactly Length(List) elements of the list to the stream. It may write additional information about the list as well. List'Read reads exactly Length(List) elements of List from the stream and consumes any additional information written by List'Write. !corrigendum A.18.3(88/2) @drepl @xindent @dby @xindent !corrigendum A.18.3(102/2) @drepl @xindent @dby @xindent !corrigendum A.18.3(145/2) @drepl 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. @dby 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) @drepl @xbullet @dby @xbullet !corrigendum A.18.3(159/2) @drepl The execution of an @fa for a list shall have the effect of copying the elements from the source list object to the target list object. @dby The execution of an @fa 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) @dinsa Execution of the default implementation of the Input, Output, Read, or Write attribute of type Cursor raises Program_Error. @dinst Map'Write writes exactly Length(Map) elements of the map to the stream. It may write additional information about the map as well. Map'Read reads exactly Length(Map) elements of Map from the stream and consumes any additional information written by Map'Write. !corrigendum A.18.4(43/2) @drepl @xindent @dby @xindent !corrigendum A.18.4(79/2) @drepl @xbullet @dby @xbullet !corrigendum A.18.4(82/2) @drepl The execution of an @fa for a map shall have the effect of copying the elements from the source map object to the target map object. @dby The execution of an @fa 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(58/2) @drepl 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. @dby The @i of a nonempty map is the one whose key is less than the key of all the other nodes in the map. The @i of a nonempty map is the one whose key is greater than the key of all the other elements in the map. The @i of a node is the node with the smallest key that is larger than the key of the given node. The @i 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) @drepl 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. @dby 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.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 writes exactly Length(Set) elements of the set to the stream. It may write additional information about the set as well. Set'Read reads exactly Length(Set) elements of Set from the stream and consumes any additional information written by Set'Write. !corrigendum A.18.7(100/2) @drepl @xbullet @dby @xbullet !corrigendum A.18.7(103/2) @drepl The execution of an @fa for a set shall have the effect of copying the elements from the source set object to the target set object. @dby The execution of an @fa 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(81/2) @drepl 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. @dby The @i of a nonempty set is the one which is less than all the other elements in the set. The @i of a nonempty set is the one which is greater than all the other elements in the set. The @i of an element is the smallest element that is larger than the given element. The @i 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) @drepl 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. @dby 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.10(0) @dinsc Force a conflict; the real text is found in the conflict file. !corrigendum A.18.18(0) @dinsc Force a conflict; the real text is found in the conflict file. !corrigendum A.18.26(5/2) @drepl @xindent @dby @xindent !corrigendum A.18.26(9/2) @drepl @xindent @dby @xindent !corrigendum A.18.27(0) @dinsc Force a conflict; the real text is found in the conflict file. !corrigendum A.18.30(0) @dinsc Force a conflict; the real text is found in the conflict file. !corrigendum B.2(10.1/2) @drepl 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. @dby 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) @drepl 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++. @dby 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) @drepl @xhang<@xterm 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 @fa or @fa corresponding to the @fa denoted by E.> @dby @xhang<@xterm 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 @fa or @fa (after the @fa) corresponding to the @fa denoted by E.> !corrigendum D.2.2(3.5/2) @drepl 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. @dby 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) @drepl 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. @dby 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) @dinsa @xhang<@xterm 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.> @dinss @xhang<@xterm> Specifies that an @fa using a standard storage pool (see 13.11) shall not occur within a parameterless library subprogram, nor within the @fa of a task body. For the purposes of this rule, an @fa of a type derived from a formal access type does not use a standard storage pool. @xindent using a standard storage pool is evaluated after the elaboration of the @fas of the partition has completed.> !corrigendum H.4(8/1) @dinsa @xhang<@xterm@fas are prohibited in subprograms, generic subprograms, tasks, and entry bodies.> @dinss @xhang<@xtermThere are no @fas of anonymous access types.> @xhang<@xtermThere are no coextensions. See 3.10.2.> @xhang<@xterm@fas 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: 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 . For Decodes: Returns the result of decoding Item, which is assumed . For Converts: Returns the value of Item, which is assumed , . 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 functions..." (57/3 and 58/3) getting moved before the "For all Convert and " 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. ****************************************************************