CVS difference for ai05s/ai05-0147-1.txt
--- ai05s/ai05-0147-1.txt 2010/01/22 00:32:47 1.9
+++ ai05s/ai05-0147-1.txt 2010/02/02 04:49:31 1.10
@@ -1,5 +1,5 @@
-!standard 4.3.3(15) 10-01-21 AI05-0147-1/07
-!standard 4.4(7)
+!standard 4.3.3(15) 10-02-01 AI05-0147-1/08
+!standard 4.4(1)
!standard 4.5.7(0)
!standard 4.7(2)
!standard 4.7(3)
@@ -65,13 +65,15 @@
Precondition => (not Param_1 >= 0) or Param_2 /= ""
but this sacrifices a lot of readability, when what is actually meant is
Precondition => (if Param_1 >= 0 then Param_2 /= "" else True)
+or even more simply
+ Precondition => (if Param_1 >= 0 then Param_2 /= "")
+(depending on an implicit else).
-
Another situation is renaming an object determined at runtime:
procedure S (A, B : Some_Type) is
Working_Object : Some_Type renames
- (if Some_Func(A) then A else B);
+ Some_Type'(if Some_Func(A) then A else B);
begin
-- Use Working_Object in a large chunk of code.
end S;
@@ -95,43 +97,14 @@
* For a conditional_expression, the applicable index constraint for
each *dependent_*expression is that, if any, defined for the
conditional_expression.
+
+Modify 4.4(1):
-Replace 4.4(7) by:
+ In this International Standard, the term "expression" refers to a construct
+ of the syntactic category expression or of any of the [other five syntactic
+ categories defined below]{following categories: relation,
+ simple_expression, term, factor, primary, conditional_expression}.
-primary ::=
- numeric_literal | null | string_literal | aggregate
- | name | allocator | (expression_within_parentheses)
-
-Add after 4.4(7):
-
-expression_within_parentheses ::=
- expression
- | conditional_expression
-
-If an expression appears directly inside of another set of parentheses,
-an expression_within_parentheses can be used instead. Redundant[This allows
-the use of a single set of parentheses in such cases.]
-
-AARM Reason: We could have written this as a syntax rule (as we did in
-4.7, for instance), but that would have required rewriting many semantic
-rules that depend on the syntax item expression (for instance, the 3rd,
-4th, and 7th paragraphs in 4.1.1, the 7th and 8th paragraphs of 4.1.4,
-the third paragraph of 4.6, and many more).
-
-AARM Ramification: This rule applies to
-attribute_designator and range_attribute_designator (4.1.4),
-type_conversion (4.6), entry_index (9.5.2), and to single (positional)
-items in pragma (2.8), discriminant_constraint (3.7.1),
-indexed_component (4.1.1), actual_parameter_part (6.4),
-and generic_actual_part (12.3).
-
-AARM Implementation Note: In order to avoid ambiguity, and preserve the
-ability to do useful error correction, it is recommended that the grammar
-for all of the above productions be modified to reflect this rule. For the
-four productions, replacing expression with expression_within_parentheses
-in the grammar will have the correct effect; for the latter productions,
-adding a parallel singleton_list ::= ( conditional_expression ) will have
-the correct effect without adding any ambiguity.
Add a new clause:
@@ -142,8 +115,101 @@
conditional_expression ::= if condition then *dependent*_expression
{elsif condition then *dependent*_expression}
[else *dependent*_expression]
+
+condition ::= *boolean_*expression
+
+Whereever the Syntax Rules allow an expression, a conditional_expression may be
+used in place of the expression, so long as it is immediately surrounded by
+parentheses.
+
+AARM Discussion: The syntactic category conditional_expression is not explicitly
+referenced by any other BNF syntax rules. The above rule "plugs it in" to the
+rest of the grammar, by allowing conditional_expression to play the syntactic
+role of expression, except that it must be parenthesized.
+
+One of the possibilities for primary is (expression). The above rule implies
+that we can use (conditional_expression) instead, so the following are
+syntactically legal:
+
+ A := (if X then Y else Z); -- parentheses required
+ A := B + (if X then Y else Z) + C; -- parentheses required
+
+The following procedure calls are syntactically legal:
+
+ P(if X then Y else Z);
+ P((if X then Y else Z)); -- redundant parentheses
+
+ P((if X then Y else Z), Some_Other_Param);
+ P(Some_Other_Param, (if X then Y else Z));
+ P(Formal => (if X then Y else Z));
+
+whereas the following are illegal:
+
+ P(if X then Y else Z, Some_Other_Param);
+ P(Some_Other_Param, if X then Y else Z);
+ P(Formal => if X then Y else Z);
+
+because in these latter cases, the conditional_expression is not immediately
+surrounded by parentheses (which means on both sides!).
+
+The above English-language rule is equivalent to modifying the BNF as follows,
+as far as syntax goes:
+
+ expression_within_parens ::=
+ expression |
+ conditional_expression
+
+ singleton_list ::= ( conditional_expression )
+
+ primary ::= numeric_literal | null | string_literal | aggregate |
+ name | allocator | (expression_within_parens)
+
+ pragma_argument_association_list ::=
+ (pragma_argument_association {, pragma_argument_association})
+ | singleton_list
+
+ pragma ::= Pragma identifier [pragma_argument_association_list] ;
+
+ discriminant_constraint ::=
+ (discriminant_association {, discriminant_association}) |
+ singleton_list
+
+ index_expression_list ::= (expression {, expression}) | singleton_list
+
+ indexed_component ::= prefix index_expression_list
+
+ attribute_designator ::=
+ identifier[(*static*_expression_within_parans)]
+
+ range_attribute_designator ::=
+ Range[(*static*_expression_within_parens)]
+
+ type_conversion ::=
+ subtype_mark (expression_within_parens)
+
+ qualified expression ::=
+ subtype_mark'(expression_within_parens)
+
+ actual_parameter_part ::=
+ (parameter_association {, parameter_association}) |
+ singleton_list
+
+ entry_index ::= expression_within_parens
+
+ generic_actual_part ::=
+ (generic_association {, generic_association}) |
+ singleton_list
+
+We chose not to make this modification because it is a huge change to the BNF
+grammar, and in addition would require a lot of English text that refers to
+syntactic categories to change.
+
+AARM Implementation Note: Implementers are cautioned to consider error
+detection when implementing the syntax for conditional_expressions.
+Conditional_expressions and if_statements are very similar syntactally,
+and simple mistakes can appear to change one into the other, potentially
+causing errors to be moved far away from their actual location.
-condition ::= Boolean_expression
Name Resolution Rules
@@ -165,15 +231,16 @@
(instead of a particular type), all *dependent_*expressions of the
conditional_expression shall have the same type.
-If there is no "else" *dependent_*expression, all of the *dependent_*expressions of
-the conditional_expression shall be of a boolean type.
+If there is no "else" *dependent_*expression, all of the *dependent_*expressions
+of the conditional_expression shall be of a boolean type.
If the expected type of a conditional_expression is a specific tagged type, all
-of the *dependent_*expressions of the conditional_expression shall be dynamically
-tagged, or none shall be dynamically tagged; the conditional_expression is
-dynamically tagged if all of the *dependent_*expressions are dynamically tagged,
-is tag-indeterminate if all of the *dependent_*expressions are tag-indeterminant,
-and is statically tagged otherwise.
+of the *dependent_*expressions of the conditional_expression shall be
+dynamically tagged, or none shall be dynamically tagged; the
+conditional_expression is dynamically tagged if all of the
+*dependent_*expressions are dynamically tagged, is tag-indeterminate if all of
+the *dependent_*expressions are tag-indeterminant, and is statically tagged
+otherwise.
[Editor's note: We don't try to define the type of the conditional expression;
it gets complex when implicit conversions are involved. There may not be a
@@ -194,16 +261,7 @@
intact. Note that the last otherwise can be true only for a boolean
conditional expression, as an "else" is required in all other cases.]
-Replace 4.7(2) by:
-
-qualified_expression ::=
- subtype_mark'(expression_within_parentheses) | subtype_mark'aggregate
-
-In 4.7(3), modify the start of the paragraph:
-The *operand* (the {expression_within_parentheses}[expression], or aggregate)
-shall...
-
Add after 4.9(12):
* A conditional_expression all of whose conditions and dependent_expressions are
@@ -248,15 +306,15 @@
In the following contexts, an expression of a limited type is not permitted
unless it is an aggregate, a function_call, [or ]a parenthesized expression or
qualified_expression whose operand is permitted by this rule{, or a
-conditional_expression all of whose *dependent_*expressions are permitted by this
-rule}:
+conditional_expression all of whose *dependent_*expressions are permitted by
+this rule}:
!discussion
The syntax of Ada requires that we require some sort of surrounding syntax to
-make a conditional expression different than a if statement. Without that
+make a conditional expression different than an if statement. Without that
requirement, we would have code like:
if if Func1 then Func2 then Proc1; end if;
@@ -7741,3 +7799,280 @@
****************************************************************
+From: Bob Duff
+Sent: Monday, February 1, 2010 3:22 PM
+
+Here's my homework for ai05-0147-1.
+
+The goal is to fix the syntax rules.
+My understanding is that we all agree on the rules, but we were having trouble
+expressing those rules in RM-ese.
+
+I realized we were mixing two approaches:
+
+ - Stick conditional_expression into the BNF grammar
+ where appropriate. We don't like this because
+ it involves too much change to the RM.
+
+ - Leave the BNF grammar alone, but describe in English
+ where conditional_expression is allowed in place
+ of the syntactic category expression. We don't
+ like this for the same reason we don't like
+ a similar ugly hack when used for pragmas.
+
+I decided to go entirely with the second approach (so there's only one "don't
+like").
+
+We had been using the first approach in primary and qualified_expression. I got
+rid of that -- the wording below eliminates the previously-proposed changes to
+those BNF rules; that is, the BNF syntax rules for primary and
+qualified_expression remain as in Ada 2005.
+
+This has the "interesting" property that conditional_expression is not
+referenced in BNF -- only in the English syntax rule that plugs it in (allows it
+to replace expression, sometimes).
+
+Here goes:
+
+[This is version /08 of the AI - Editor.]
+
+****************************************************************
+
+From: Tucker Taft
+Sent: Monday, February 1, 2010 4:07 PM
+
+I think we had also talked about allowing an unparenthesized conditional
+expression immediately following "=>". I think we certainly want that in the
+aspect specifications.
+
+****************************************************************
+
+From: Edmond Schonberg
+Sent: Monday, February 1, 2010 4:23 PM
+
+as long as it is followed by a ')', right? This is a little harder to phrase
+properly.
+
+****************************************************************
+
+From: Steve Baird
+Sent: Monday, February 1, 2010 4:31 PM
+
+Didn't we explicitly decide against
+this because of interactions with case
+expressions (and we wanted the same parenthesizing rules for conditional
+expressions as for case expressions)?
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Monday, February 1, 2010 5:20 PM
+
+That's what it says in the minutes, and is surely what I understood we had
+decided. Otherwise, case expressions become ambiguous, which would not be good.
+Or we have different rules for everything (aggregates, case exprs, cond exprs,
+...), which sounds like a nightmare.
+
+****************************************************************
+
+From: Bob Duff
+Sent: Monday, February 1, 2010 3:31 PM
+
+This is mostly nitpicking. I'd rather you review the proposed wording I sent a
+few minutes ago, if you don't have time for both.
+
+AI05-0147-1 says:
+
+> It is possible to write a Boolean expression like
+> Precondition => (not Param_1 >= 0) or Param_2 /= ""
+> but this sacrifices a lot of readability, when what is actually meant is
+> Precondition => (if Param_1 >= 0 then Param_2 /= "" else True)
+
+We allow "else True" to be defaulted, so this might be
+better:
+
+ Precondition => (if Param_1 >= 0 then Param_2 /= "")
+ where "else True" is implied by default.
+
+> Another situation is renaming an object determined at runtime:
+>
+> procedure S (A, B : Some_Type) is
+> Working_Object : Some_Type renames
+> (if Some_Func(A) then A else B);
+> begin
+> -- Use Working_Object in a large chunk of code.
+> end S;
+>
+> In Ada currently, you would have to either duplicate the working code
+> (a bad idea if it is large) or make the working code into a subprogram
+> (which adds overhead, and would complicate the use of exit and return control structures).
+
+I don't think we plan to allow that (even though it might be nice!).
+An object_renaming_decl requires a name, whereas a conditional_expression is
+merely an expression. Nor do we intend to allow:
+
+ (if Some_Func(...) then X else Y) := Toto;
+
+Right?
+
+On the other hand, I suppose this:
+
+ (if Some_Func(...) then X else Y).all := Toto;
+ ^^^^ will be allowed.
+
+Note redundant "Redundant" in:
+
+> If an expression appears directly inside of another set of
+> parentheses, an expression_within_parentheses can be used instead.
+> Redundant[This allows the use of a single set of parentheses in such
+> cases.]
+
+The following strikes me as overly paternalistic:
+
+> AARM Implementation Note: In order to avoid ambiguity, and preserve
+> the ability to do useful error correction, it is recommended that the
+> grammar for all of the above productions be modified to reflect this rule. ...
+
+We don't normally presume to tell implementers how best to do syntactic error
+correction.
+
+First para of !discussion: "a if" --> "an if".
+
+****************************************************************
+
+From: Randy Brukardt
+Sent: Monday, February 1, 2010 5:51 PM
+
+> > It is possible to write a Boolean expression like
+> > Precondition => (not Param_1 >= 0) or Param_2 /= ""
+> > but this sacrifices a lot of readability, when what is actually meant is
+> > Precondition => (if Param_1 >= 0 then Param_2 /= "" else True)
+>
+> We allow "else True" to be defaulted, so this might be
+> better:
+>
+> Precondition => (if Param_1 >= 0 then Param_2 /= "") where "else
+> True" is implied by default.
+
+I wanted to be crystal-clear about the equivalence, and the defaulted "else"
+is not crystal-clear to me. Indeed, I have to look it up each time to figure out
+what it is.
+
+Perhaps the thing to do is here to give both by adding:
+
+or even more simply
+ Precondition => (if Param_1 >= 0 then Param_2 /= "")
+
+to the AI.
+
+> > Another situation is renaming an object determined at runtime:
+> >
+> > procedure S (A, B : Some_Type) is
+> > Working_Object : Some_Type renames
+> > (if Some_Func(A) then A else B);
+> > begin
+> > -- Use Working_Object in a large chunk of code.
+> > end S;
+> >
+> > In Ada currently, you would have to either duplicate the working
+> > code (a bad idea if it is large) or make the working code into a
+> > subprogram (which adds overhead, and would complicate the use of
+> > exit and return control structures).
+>
+> I don't think we plan to allow that (even though it might be nice!).
+> An object_renaming_decl requires a name, whereas a
+> conditional_expression is merely an expression.
+
+Oh, sorry. I should have written:
+
+ Working_Object : Some_Type renames
+ Some_Type'(if Some_Func(A) then A else B);
+
+because you can make any expression a name by qualifying it (AI05-0003-1).
+And, as Tucker pointed out, you can do that in Ada 95-speak, without
+AI05-0003-1, too:
+
+ Working_Object : Some_Type renames
+ Some_Type(Some_Type'(if Some_Func(A) then A else B));
+
+But there is a weirdness here, because the name represents a constant view (at
+least according to AI05-0003-1). So it isn't a 100% replacement for the
+renaming.
+
+One wonders if we want a rule to disallow this case (is it more confusing than
+helpful??). I think it would have to be a specific rule.
+
+> Nor do we
+> intend to allow:
+>
+> (if Some_Func(...) then X else Y) := Toto;
+>
+> Right?
+
+ Some_Type'(if Some_Func(...) then X else Y) := Toto;
+
+is illegal because the LHS is a constant view.
+
+> On the other hand, I suppose this:
+>
+> (if Some_Func(...) then X else Y).all := Toto;
+> ^^^^ will be allowed.
+
+That won't work (the prefix is not a name), but of course:
+
+ Some_Type'(if Some_Func(...) then X else Y).all := Toto;
+
+would be legal.
+
+
+> Note redundant "Redundant" in:
+>
+> > If an expression appears directly inside of another set of
+> > parentheses, an expression_within_parentheses can be used instead.
+> > Redundant[This allows the use of a single set of parentheses in such
+> > cases.]
+
+We're started adding "Redundant" in front the square brackets, because we also
+use square brackets to mean deletion, and we've been confused on multiple
+occasions. This is text you replaced anyway, so it doesn't matter.
+
+> The following strikes me as overly paternalistic:
+>
+> > AARM Implementation Note: In order to avoid ambiguity, and preserve
+> > the ability to do useful error correction, it is recommended that
+> > the grammar for all of the above productions be modified to reflect
+> > this rule. ...
+>
+> We don't normally presume to tell implementers how best to do
+> syntactic error correction.
+
+I think this is a special case. The grammar in the standard is seriously
+ambiguous and since a reasonably easy solution is known and available, I think
+we should give it and explain why they would like to use it. That's especially
+true because my professional opinion was that it couldn't be done (I thought
+that inherent ambiguity, especially for "name", would have made it impossible).
+This is one case where I was happy to be proved wrong, and I don't want to lose
+that information as other implementers may have similar problems. (And not
+everyone one reads the AIs, or even knows what they are.)
+
+You could argue that there are existing cases like that in the Ada grammar; I
+agree with that but think they too ought to have AARM notes if the published
+grammar is problematic. Type_conversion comes to mind (this has to be treated as
+a form of name, especially as it is allowed to be *used* as a name). There are
+only a few such places in the standard; it's annoying that new Ada implementers
+are supposed to figure out these problems and solutions on their own.
+
+Anyway, there may be a better way to put this, but clearly every implementer
+will need a solution to avoid the ambiguity (unless they are using an ambiguous
+grammar parser, but that seems unlikely). So I think we ought to help. Your
+elimination of any grammar at all will make it even harder for readers to make
+sense of this. Maybe something like:
+
+AARM Implementation Note: Directly adding conditional_expression in place of
+expression causes a very ambiguous grammar. Instead, it is possible to modify
+the grammar for all of the above productions to reflect this rule.
+...
+
+or something like that.
+
+****************************************************************
Questions? Ask the ACAA Technical Agent