Annotated Ada Reference Manual (Ada 202y Draft 1)Legal Information
Contents   Index   References   Search   Previous   Next 

4.5.7 Conditional Expressions

1/3
{AI05-0147-1} {AI05-0188-1} {AI05-0262-1} A conditional_expression selects for evaluation at most one of the enclosed dependent_expressions, depending on a decision among the alternatives. One kind of conditional_expression is the if_expression, which selects for evaluation a dependent_expression depending on the value of one or more corresponding conditions. The other kind of conditional_expression is the case_expression, which selects for evaluation one of a number of alternative dependent_expressions; the chosen alternative is determined by the value of a selecting_expression.

Language Design Principles

1.a/3
{AI05-0188-1} As previously noted, there are two kinds of conditional_expression, if_expressions and case_expressions. Whenever possible, we have written the rules in terms of conditional_expressions to avoid duplication.
1.b/3
{AI05-0147-1} The rules for conditional_expressions have been designed as much as possible to work similarly to a parenthesized expression. The intent is that as much as possible, wherever a parenthesized expression would be allowed, a conditional_expression would be allowed, and it should work the same way. 

Syntax

2/3
{AI05-0188-1} conditional_expression ::= if_expression | case_expression
3/3
{AI05-0147-1} {AI05-0188-1} if_expression ::= 
   if condition then dependent_expression
   {elsif condition then dependent_expression}
   [else dependent_expression]
4/3
{AI05-0147-1} condition ::= boolean_expression
5/3
{AI05-0188-1} case_expression ::= 
    case selecting_expression is
    case_expression_alternative {,
    case_expression_alternative}
6/3
{AI05-0188-1} case_expression_alternative ::= 
    when discrete_choice_list =>
        dependent_expression
7/3
{AI05-0147-1} Wherever 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.
7.a/3
Discussion: {AI05-0147-1} The syntactic category conditional_expression appears only as a primary that is parenthesized. The above rule allows it to additionally be used in other contexts where it would be directly surrounded by parentheses.
7.b/3
The grammar makes the following directly legal:
7.c/3
A := (if X then Y else Z); -- parentheses required
A := B + (if X then Y else Z) + C; -- parentheses required
7.d/3
The following procedure calls are syntactically legal; the first uses the above rule to eliminate the redundant parentheses found in the second:
7.e/3
P(if X then Y else Z);
P((if X then Y else Z)); -- redundant parentheses
7.f/3
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));
7.g/3
whereas the following are illegal:
7.h/3
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);
7.i/3
because in these latter cases, the conditional_expression is not immediately surrounded by parentheses (which means on both sides!).
7.j/3
The English-language rule applies in all places that could surround an expression with parentheses, including pragma arguments, type conversion and qualified expression operands, and array index expressions.
7.k/3
This English-language rule could have been implemented instead by adding a nonterminal expression_within_parentheses, which would consist of expressions and conditional_expressions. Then, that could be used in all of the syntax which could consist of parens directly around an expression. We did not do that because of the large amount of change required. A complete grammar is given in AI05-0147-1.
7.l/3
Implementation Note: {AI05-0147-1} Implementers are cautioned to consider error detection when implementing the syntax for conditional_expressions. An if_expression and an if_statement are very similar syntactically, (as are a case_expression and a case_statement) and simple mistakes can appear to change one into the other, potentially causing errors to be moved far away from their actual location. The absence of end if to terminate an if_expression (and end case for a case_expression) also may make error handling harder. 

Name Resolution Rules

8/3
{AI05-0147-1} If a conditional_expression is expected to be of a type T, then each dependent_expression of the conditional_expression is expected to be of type T. Similarly, if a conditional_expression is expected to be of some class of types, then each dependent_expression of the conditional_expression is subject to the same expectation. If a conditional_expression shall resolve to be of a type T, then each dependent_expression shall resolve to be of type T.
9/3
{AI05-0147-1} The possible types of a conditional_expression are further determined as follows:
10/3
If the conditional_expression is the operand of a type conversion, the type of the conditional_expression is the target type of the conversion; otherwise,
10.a/3
Reason: This rule distributes an enclosing type conversion to the dependent_expressions. This means that 
10.b/3
T(if C then A else B)
10.c/3
has the same semantics as 
10.d/3
(if C then T(A) else T(B))
11/3
If all of the dependent_expressions are of the same type, the type of the conditional_expression is that type; otherwise,
12/3
If a dependent_expression is of an elementary type, the type of the conditional_expression shall be covered by that type; otherwise,
12.a/3
Reason: This rule supports the use of numeric literals and universal expressions within a conditional_expression.
13/3
If the conditional_expression is expected to be of type T or shall resolve to type T, then the conditional_expression is of type T.
13.a/3
Ramification: If the type of the conditional_expression cannot be determined by one of these rules, then Name Resolution has failed for that expression, even if the dependent_expressions would resolve individually. 
14/3
{AI05-0147-1} A condition is expected to be of any boolean type. 
15/3
{AI05-0188-1} The expected type for the selecting_expression and the discrete_choices are as for case statements (see 5.4).

Legality Rules

16/3
{AI05-0147-1} {AI05-0188-1} All of the dependent_expressions shall be convertible (see 4.6) to the type of the conditional_expression.
17/3
{AI05-0147-1} {AI05-0188-1} {AI05-0269-1} 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. In this case, 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-indeterminate, and is statically tagged otherwise.
18/3
{AI05-0147-1} {AI05-0262-1} If there is no else dependent_expression, the if_expression shall be of a boolean type.
19/3
{AI05-0188-1} {AI05-0269-1} All Legality Rules that apply to the discrete_choices of a case_statement (see 5.4) also apply to the discrete_choices of a case_expression except within an instance of a generic unit. 
19.a/3
Reason: The exemption for a case expression that occurs in an instance allows the following example: 
19.b/3
generic
   with function Int_Func return Integer;
package G is
   X : Float := (case Int_Func is
                  when Integer'First .. -1 => -1.0,
                  when 0 => 0.0,
                  when Positive => 1.0);
end G;
19.c/3
function Nat_Func return Natural is (123);
19.d/3
package I is new G (Int_Func => Nat_Func); -- Legal
19.e/3
Note that the Legality Rules still apply in the generic unit itself; they are just not enforced in an instance of the unit. 

Dynamic Semantics

20/3
{AI05-0147-1} {AI05-0188-1} For the evaluation of an if_expression, the condition specified after if, and any conditions specified after elsif, are evaluated in succession (treating a final else as elsif True then), until one evaluates to True or all conditions are evaluated and yield False. If a condition evaluates to True, the associated dependent_expression is evaluated, converted to the type of the if_expression, and the resulting value is the value of the if_expression. Otherwise (when there is no else clause), the value of the if_expression is True.
20.a/3
Ramification: Else is required unless the if_expression has a boolean type, so the last sentence can only apply to if_expressions with a boolean type. 
21/3
{AI05-0188-1} For the evaluation of a case_expression, the selecting_expression is first evaluated. If the value of the selecting_expression is covered by the discrete_choice_list of some case_expression_alternative, then the dependent_expression of the case_expression_alternative is evaluated, converted to the type of the case_expression, and the resulting value is the value of the case_expression. Otherwise (the value is not covered by any discrete_choice_list, perhaps due to being outside the base range), Constraint_Error is raised.

Examples

22/5
{AI12-0429-1} Example of use of an if_expression:
23/5
{AI12-0312-1} Put_Line ("Casey is " &
      (if Casey.Sex = M then "Male" else "Female")); -- see 3.10.1
24/5
{AI12-0429-1} Example of use of a case_expression:
25/5
{AI12-0312-1} function Card_Color (Card : Suit) return Color is -- see 3.5.1
  (case Card is
      when Clubs  | Spades   => Black,
      when Hearts | Diamonds => Red);

Extensions to Ada 2005

25.a/3
{AI05-0147-1} If expressions and case expressions are new. 

Contents   Index   References   Search   Previous   Next 
Ada-Europe Ada 2005 and 2012 Editions sponsored in part by Ada-Europe