Version 1.9 of ai12s/ai12-0039-1.txt
!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 Corrigendum 2015 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
!qualifier Omission
!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)
Replace the paragraph:
- a membership test whose simple_expression is the current instance,
and whose membership_choice_list meets the requirements for a static
membership test (see 4.9);
by:
- a membership test whose tested_simple_expression is the current
instance, and whose membership_choice_list meets the requirements for a static
membership test (see 4.9);
!corrigendum 4.4(3/3)
Replace the paragraph:
relation ::=
simple_expression [relational_operator simple_expression]
| simple_expression [not] in membership_choice_list
by:
relation ::=
simple_expression [relational_operator simple_expression]
| tested_simple_expression [not] in membership_choice_list
!corrigendum 4.4(3.2/3)
Replace the paragraph:
membership_choice ::= choice_expression | range | subtype_mark
by:
membership_choice ::= choice_simple_expression | range | subtype_mark
!corrigendum 4.5.2(3.1/3)
Replace the paragraph:
If the tested type is tagged, then the simple_expression shall
resolve to be of a type that is convertible (see 4.6) to the tested
type; if untagged, the expected type for the simple_expression is
the tested type. The expected type of a choice_expression in a
membership_choice, and of a simple_expression of a range
in a membership_choice, is the tested type of the membership operation.
by:
If the tested type is tagged, then the tested_simple_expression shall
resolve to be of a type that is convertible (see 4.6) to the tested
type; if untagged, the expected type for the tested_simple_expression is
the tested type. The expected type of a choice_simple_expression in a
membership_choice, and of a simple_expression of a range
in a membership_choice, is the tested type of the membership operation.
!corrigendum 4.5.2(4)
Replace the paragraph:
For a membership test, if the simple_expression is of a tagged class-wide
type, then the tested type shall be (visibly) tagged.
by:
For a membership test, if the tested_simple_expression is of a tagged
class-wide type, then the tested type shall be (visibly) tagged.
!corrigendum 4.5.2(4.1/3)
Replace the paragraph:
If a membership test includes one or more choice_expressions 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.
by:
If a membership test includes one or more choice_simple_expressions 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)
Replace the paragraph:
For the evaluation of a membership test using in whose membership_choice_list
has a single membership_choice, the simple_expression and the membership_choice
are evaluated in an arbitrary order; the result is the result of the individual
membership test for the membership_choice.
by:
For the evaluation of a membership test using in whose membership_choice_list
has a single membership_choice, the tested_simple_expression and the
membership_choice are evaluated in an arbitrary order; the result is the result
of the individual membership test for the membership_choice.
!corrigendum 4.5.2(27.1/3)
Replace the paragraph:
For the evaluation of a membership test using in whose membership_choice_list
has more than one membership_choice, the simple_expression 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 membership_choice
combined with the short-circuit control form or else.
by:
For the evaluation of a membership test using in whose membership_choice_list
has more than one membership_choice, the tested_simple_expression 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 membership_choice
combined with the short-circuit control form or else.
!corrigendum 4.5.2(28.1/3)
Replace the paragraph:
- The membership_choice is a choice_expression, and the simple_expression
is equal to the value of the membership_choice. 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.
by:
- The membership_choice is a choice_simple_expression, and the
tested_simple_expression is equal to the value of the membership_choice. 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)
Replace the paragraph:
- The membership_choice is a range and the value of the
simple_expression belongs to the given range.
by:
- The membership_choice is a range and the value of the
tested_simple_expression belongs to the given range.
!corrigendum 4.5.2(29/3)
Replace the paragraph:
- The membership_choice is a subtype_mark, the tested type is scalar,
the value of the simple_expression belongs to the range of the named subtype, and
the predicate of the named subtype evaluates to True.
by:
- The membership_choice is a subtype_mark, the tested type is scalar,
the value of the tested_simple_expression belongs to the range of the named
subtype, and the predicate of the named subtype evaluates to True.
!corrigendum 4.5.2(30/3)
Replace the paragraph:
- The membership_choice is a subtype_mark, the tested type is not
scalar, the value of the simple_expression satisfies any
constraints of the named subtype, the predicate of the named subtype
evaluates to True, and:
by:
- The membership_choice is a subtype_mark, the tested type is not
scalar, the value of the tested_simple_expression satisfies any
constraints of the named subtype, the predicate of the named subtype
evaluates to True, and:
!corrigendum 4.5.2(30.1/2)
Replace the paragraph:
if the type of the simple_expression is class-wide, the value has a tag that
identifies a type covered by the tested type;
by:
if the type of the tested_simple_expression is class-wide, the value has
a tag that identifies a type covered by the tested type;
!corrigendum 4.5.2(30.2/3)
Replace the paragraph:
- if the tested type is an access type and the named subtype excludes null,
the value of the simple_expression is not null;
by:
- if the tested type is an access type and the named subtype excludes null,
the value of the tested_simple_expression is not null;
!corrigendum 4.5.2(30.3/3)
Replace the paragraph:
- if the tested type is a general access-to-object type, the type of the
simple_expression 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
simple_expression is nonnull, the tag of the object designated by the value of the
simple_expression is covered by the designated type of the tested type.
by:
- if the tested type is a general access-to-object type, the type of the
tested_simple_expression 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
tested_simple_expression is nonnull, the tag of the object designated by
the value of the tested_simple_expression is covered by the designated type
of the tested type.
!corrigendum 4.9(11/3)
Replace the paragraph:
- a membership test whose simple_expression is a static expression,
and whose membership_choice_list consists only of membership_choices
that are either static choice_expressions, static ranges,
or subtype_marks that denote a static (scalar or string) subtype;
by:
- a membership test whose tested_simple_expression is a static
expression, and whose membership_choice_list consists only of
membership_choices that are either static choice_simple_expressions,
static ranges, or subtype_marks that denote a static (scalar or string)
subtype;
!corrigendum 4.9(32.6/3)
Replace the paragraph:
- a choice_expression (or a simple_expression of a range that
occurs as a membership_choice of a membership_choice_list) of a static
membership test that is preceded in the enclosing membership_choice_list by
another item whose individual membership test (see 4.5.2) statically yields True.
by:
- a choice_simple_expression (or a simple_expression of a
range that
occurs as a membership_choice of a membership_choice_list) of a static
membership test that is preceded in the enclosing membership_choice_list by
another item whose individual membership test (see 4.5.2) statically yields True.
!corrigendum 8.6(27.1/3)
Replace the paragraph:
Other than for the simple_expression of a membership test, if the
expected type for a name or expression is not the same as the actual
type of the name or expression, 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 D1 and the actual type
is an anonymous access-to-object type with designated type D2, then D1
shall cover D2, and the name or expression 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.
by:
Other than for the tested_simple_expression of a membership test, if the
expected type for a name or expression is not the same as the actual
type of the name or expression, 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 D1 and the actual type
is an anonymous access-to-object type with designated type D2, then D1
shall cover D2, and the name or expression 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.
****************************************************************
Questions? Ask the ACAA Technical Agent