!standard 4.4(3/3) 13-05-08 AI12-0039-1/03 !standard 4.4(3.2/3) !standard 4.5.2(3.1/3) !standard 4.5.2(4) !standard 4.5.2(4.1/3) !standard 4.5.2(27/3) !standard 4.5.2(27.1/3) !standard 4.5.2(28.1/3) !standard 4.5.2(28.2/3) !standard 4.5.2(29/3) !standard 4.5.2(30/3) !standard 4.5.2(30.1/3) !standard 4.5.2(30.2/3) !standard 4.5.2(30.3/3) !standard 4.9(11/3) !standard 4.9(32.6/3) !standard 8.6(27.1/3) !standard 3.2.4(17/3) !class binding interpretation 12-11-29 !status Amendment 202x 12-12-17 !status WG9 Approved 13-06-14 !status ARG Approved 8-0-2 12-12-06 !status work item 12-11-29 !status received 12-10-09 !priority High !difficulty Easy !subject Ambiguity in syntax for membership expression removed !summary The choices of a membership are syntactically simple_expressions, not choice_expressions. !question It appears that the Ada 2012 syntax for membership expressions introduces ambiguities. Assume A, B, C, and D are all objects of type Boolean. Consider A in B and C This could be interpreted as equivalent to either of these valid Ada expressions: (A in B) and C --or as A in (B and C) Similarly: A in B in C | D can be interpreted as A in (B in C) | D --or as A in (B in C | D) And: A in B | C and D can be interpreted as (A in B | C) and D --or as A in B | (C and D) Should the syntax be corrected to eliminate these ambiguities? (Yes.) !recommendation (See summary.) !wording Replace the last line of 4.4(3) with: | *tested_*simple_expression [not] in membership_choice_list Replace 4.4(3.2/3) with: membership_choice ::= *choice_*simple_expression | range | subtype_mark [Note: The change here is to replace "choice_expression" with "*choice_*simple_expression"; it would be ambiguous to use the usual insertion and deletion marks in syntax, so this was not done here.] In 4.5.2, paragraphs 3.1/3 [only the two uses], 3.b/2, 4, 27/3, 27.1/3, 28.1/3, 28.2/3, 29/3, 30/3, 30.a, 30.1/2, 30.2/2, 30.3/2, and 32.a/3, in 4.9(11/3), in 3.2.4(17/3), and in 8.6(27.1/3): replace "simple_expression" with "*tested_*simple_expression". In 4.5.2, paragraphs 3.1/3, 4.1/3, 28.1/3, in 4.9(11/3), and in 4.9(32.6/3): replace "choice_expression" with "*choice_*simple_expression". [Editor's note: There are a few cases where we don't have to use the new prefixes, especially for the latter cases (where we often say "of a membership_choice") but it's going to be clearer to just use them globally.] In AARM 3.9.2(9.b/2), "expression" probably should be "*tested_*simple_expression", although this isn't absolutely required. [Editor's note: I searched for "membership", "choice_expression", and "simple_expression" everywhere in the Standard (and AARM), and the above are the changes that I found.] !discussion The basic intent was that the choice of a membership was syntactically equivalent to the other uses of a choice (such as in a case statement). Choice_expression was introduced to minimize the incompatibility with existing choices in case statements. Unfortunately, we failed to notice that doing so made the grammar ambiguous. Clearly, the constituents of a membership choice either have to have higher precedence than a membership or have to be enclosed in parentheses. If a membership or logical operator is used in a membership choice, it has to be parenthesized. This is most easily accomplished by making a membership choice a simple expression; this gives the proper precedence. It is annoying that choices for memberships and case statements are subtly different. Had this been a concern in 1994, probably choices would never have been changed from simple_expression (in Ada 83) to expression (in Ada 95) to choice_expression (in Ada 2012). But today, minimizing compatibility issues with Ada 95 has to be more important than having everything exactly the same. Note that this change has no effect the interpretation of on any syntax or construct that existed in Ada 2005 or before; it only could change the interpretation of new Ada 2012 expressions (of which there are hopefully very few taking advantage of this ambiguity). Unfortunately, changing the syntax this way makes all of the rules that talk about "the simple_expression" and "a choice_expression" in 4.5.2 ambiguous. As such, we have to give these syntax items prefixes to eliminate any confusion. Thus we talk about "tested_simple_expression" and "choice_simple_expression". !corrigendum 3.2.4(17/3) @drepl @xbullet is the current instance, and whose @fa meets the requirements for a static membership test (see 4.9);> @dby @xbullet@fa is the current instance, and whose @fa meets the requirements for a static membership test (see 4.9);> !corrigendum 4.4(3/3) @drepl @xcode<@fa@ft<@b>@fa<] >@ft<@b>@fa< membership_choice_list>> @dby @xcode<@fasimple_expression [>@ft<@b>@fa<] >@ft<@b>@fa< membership_choice_list>> !corrigendum 4.4(3.2/3) @drepl @xcode<@fa> @dby @xcode<@fasimple_expression | range | subtype_mark>> !corrigendum 4.5.2(3.1/3) @drepl If the tested type is tagged, then the @fa shall resolve to be of a type that is convertible (see 4.6) to the tested type; if untagged, the expected type for the @fa is the tested type. The expected type of a @fa in a @fa, and of a @fa of a @fa in a @fa, is the tested type of the membership operation. @dby If the tested type is tagged, then the @i@fa shall resolve to be of a type that is convertible (see 4.6) to the tested type; if untagged, the expected type for the @i@fa is the tested type. The expected type of a @i@fa in a @fa, and of a @fa of a @fa in a @fa, is the tested type of the membership operation. !corrigendum 4.5.2(4) @drepl For a membership test, if the @fa is of a tagged class-wide type, then the tested type shall be (visibly) tagged. @dby For a membership test, if the @i@fa is of a tagged class-wide type, then the tested type shall be (visibly) tagged. !corrigendum 4.5.2(4.1/3) @drepl If a membership test includes one or more @fas and the tested type of the membership test is limited, then the tested type of the membership test shall have a visible primitive equality operator. @dby If a membership test includes one or more @i@fas and the tested type of the membership test is limited, then the tested type of the membership test shall have a visible primitive equality operator. !corrigendum 4.5.2(27/3) @drepl For the evaluation of a membership test using @b whose @fa has a single @fa, the @fa and the @fa are evaluated in an arbitrary order; the result is the result of the individual membership test for the @fa. @dby For the evaluation of a membership test using @b whose @fa has a single @fa, the @i@fa and the @fa are evaluated in an arbitrary order; the result is the result of the individual membership test for the @fa. !corrigendum 4.5.2(27.1/3) @drepl For the evaluation of a membership test using @b whose @fa has more than one @fa, the @fa of the membership test is evaluated first and the result of the operation is equivalent to that of a sequence consisting of an individual membership test on each @fa combined with the short-circuit control form @b. @dby For the evaluation of a membership test using @b whose @fa has more than one @fa, the @i@fa of the membership test is evaluated first and the result of the operation is equivalent to that of a sequence consisting of an individual membership test on each @fa combined with the short-circuit control form @b. !corrigendum 4.5.2(28.1/3) @drepl @xbullet is a @fa, and the @fa is equal to the value of the @fa. If the tested type is a record type or a limited type, the test uses the primitive equality for the type; otherwise, the test uses predefined equality.> @dby @xbullet is a @i@fa, and the @i@fa is equal to the value of the @fa. If the tested type is a record type or a limited type, the test uses the primitive equality for the type; otherwise, the test uses predefined equality.> !corrigendum 4.5.2(28.2/3) @drepl @xbullet is a @fa and the value of the @fa belongs to the given @fa.> @dby @xbullet is a @fa and the value of the @i@fa belongs to the given @fa.> !corrigendum 4.5.2(29/3) @drepl @xbullet is a @fa, the tested type is scalar, the value of the @fa belongs to the range of the named subtype, and the predicate of the named subtype evaluates to True.> @dby @xbullet is a @fa, the tested type is scalar, the value of the @i@fa belongs to the range of the named subtype, and the predicate of the named subtype evaluates to True.> !corrigendum 4.5.2(30/3) @drepl @xbullet is a @fa, the tested type is not scalar, the value of the @fa satisfies any constraints of the named subtype, the predicate of the named subtype evaluates to True, and:> @dby @xbullet is a @fa, the tested type is not scalar, the value of the @i@fa satisfies any constraints of the named subtype, the predicate of the named subtype evaluates to True, and:> !corrigendum 4.5.2(30.1/2) @drepl if the type of the @fa is class-wide, the value has a tag that identifies a type covered by the tested type; @dby if the type of the @i@fa is class-wide, the value has a tag that identifies a type covered by the tested type; !corrigendum 4.5.2(30.2/3) @drepl @xbullet is not null;> @dby @xbullet@fa is not null;> !corrigendum 4.5.2(30.3/3) @drepl @xbullet is convertible to the tested type and its accessibility level is no deeper than that of the tested type; further, if the designated type of the tested type is tagged and the @fa is nonnull, the tag of the object designated by the value of the @fa is covered by the designated type of the tested type.> @dby @xbullet@fa is convertible to the tested type and its accessibility level is no deeper than that of the tested type; further, if the designated type of the tested type is tagged and the @i@fa is nonnull, the tag of the object designated by the value of the @i@fa is covered by the designated type of the tested type.> !corrigendum 4.9(11/3) @drepl @xbullet is a static expression, and whose @fa consists only of @fas that are either static @fas, static @fas, or @fas that denote a static (scalar or string) subtype;> @dby @xbullet@fa is a static expression, and whose @fa consists only of @fas that are either static @i@fas, static @fas, or @fas that denote a static (scalar or string) subtype;> !corrigendum 4.9(32.6/3) @drepl @xbullet (or a @fa of a @fa that occurs as a @fa of a @fa) of a static membership test that is preceded in the enclosing @fa by another item whose individual membership test (see 4.5.2) statically yields True.> @dby @xbullet@fa (or a @fa of a @fa that occurs as a @fa of a @fa) of a static membership test that is preceded in the enclosing @fa by another item whose individual membership test (see 4.5.2) statically yields True.> !corrigendum 8.6(27.1/3) @drepl Other than for the @fa of a membership test, if the expected type for a @fa or @fa is not the same as the actual type of the @fa or @fa, the actual type shall be convertible to the expected type (see 4.6); further, if the expected type is a named access-to-object type with designated type @i and the actual type is an anonymous access-to-object type with designated type @i, then @i shall cover @i, and the @fa or @fa shall denote a view with an accessibility level for which the statically deeper relationship applies; in particular it shall not denote an access parameter nor a stand-alone access object. @dby Other than for the @i@fa of a membership test, if the expected type for a @fa or @fa is not the same as the actual type of the @fa or @fa, the actual type shall be convertible to the expected type (see 4.6); further, if the expected type is a named access-to-object type with designated type @i and the actual type is an anonymous access-to-object type with designated type @i, then @i shall cover @i, and the @fa or @fa shall denote a view with an accessibility level for which the statically deeper relationship applies; in particular it shall not denote an access parameter nor a stand-alone access object. !ACATS test An ACATS B-Test could be created to test these rules, but we generally don't test syntax rules (and the rules given in the Ada 2012 Standard cannot be usefully implemented). !ASIS No ASIS impact. !appendix !topic Ambiguous grammar related to new membership test !reference 4.4(2-3.2/3) !from Adam Beneschan 12-10-09 !discussion It appears to me that the new syntax for membership choice lists (AI05-158) has introduced some ambiguities into the grammar. I found this out while looking into a comp.lang.ada post from Maxim Reznik (https://groups.google.com/forum/?hl=en&fromgroups=#!topic/comp.lang.ada/UYjxb612B_s). Assume A, B, C, and D are all objects of type Boolean. Here are some cases that I believe are ambiguous: A in B and C [Maxim's original example] can be interpreted as equivalent to either of these valid Ada expressions: (A in B) and C --or as A in (B and C) The problem is that in the second interpretation, the membership_choice_list can be one or more membership_choices, and a membership_choice can be a choice_expression, and a choice_expression can be two choice_relations connected by a logical operator ("and"). A couple other examples: A in B in C | D can be interpreted as A in (B in C) | D --or as A in (B in C | D) A in B | C and D can be interpreted as (A in B | C) and D --or as A in B | (C and D) (Note: Although I cannot imagine ever writing a membership test with a Boolean as the left-hand value, except in a simple case such as A in Arr'Range where Arr is an array (Boolean range <>) of something, I think it needs to be fixed since it's not good to have an ambiguous grammar.) I think the solution is probably to change membership_choice ::= choice_expression | range | subtype_mark to membership_choice ::= simple_expression | range | subtype_mark which means that in the new multiple-choice membership test, the choices on the right side could not use logical or relational operators except in parentheses. This wouldn't introduce any incompatibilities except with the new form of membership test; in particular, since discrete_choice_lists would still use choice_expressions, rather than simple_expressions, CASE statements, variant parts, and array aggregates wouldn't be affected. If this change is made, then it might no longer make sense for choice_expression and choice_relation to be defined in 4.4 since they wouldn't be used in an expression; maybe it could be moved to 3.8.1. But that's a less important issue. Also, if this change is made, some wording changes would be needed in 4.5.2, and maybe elsewhere (I haven't checked). **************************************************************** From: Tucker Taft Sent: Wednesday, October 10, 2012 7:47 AM ... > I think the solution is probably to change > > membership_choice ::= choice_expression | range | subtype_mark > > to > > membership_choice ::= simple_expression | range | subtype_mark I agree with your analysis. > which means that in the new multiple-choice membership test, the > choices on the right side could not use logical or relational > operators except in parentheses. This wouldn't introduce any > incompatibilities except with the new form of membership test; in > particular, since discrete_choice_lists would still use > choice_expressions, rather than simple_expressions, CASE statements, > variant parts, and array aggregates wouldn't be affected. > > If this change is made, then it might no longer make sense for > choice_expression and choice_relation to be defined in 4.4 since they > wouldn't be used in an expression; maybe it could be moved to 3.8.1. > But that's a less important issue. Also, if this change is made, some > wording changes would be needed in 4.5.2, and maybe elsewhere (I > haven't checked). Yes, I agree it might make sense to move choice_expression, but that is a bigger change which at this stage is probably not worth it. ****************************************************************