!standard 4.5.7 (0) 09-11-03 AI05-0188-1/01 !class amendment 09-11-03 !status work item 09-11-03 !status received 09-11-03 !priority Low !difficulty Medium !subject Case expressions !summary Case expressions are added to Ada. !problem Conditional_expressions are added by AI05-0147-1. This proposal is to add an analogous contruct -- the case expression. The full coverage rules for case statements and aggregates are a huge benefit to maintenance of Ada programs: If you add an enumeration literal, the compiler tells you about all the case statements and aggregates that need to be modified (assuming you don't defeat the full coverage rules by using "others"). In cases where conditional_expressions are useful, we don't want to lose the benefits of full coverage rules. A common example is in preconditions. Suppose we have: procedure Add_To_Fruit_Salad( -- In a package spec. Fruit : in out Fruit_Type; Bowl : in out Bowl_Type); procedure Add_To_Fruit_Salad( -- In the body. Fruit : in out Fruit_Type; Bowl : in out Bowl_Type) is begin -- Check if ready to add to fruit salad case Fruit.Kind is when Apple => pragma Assert(Fruit.Is_Crisp); null; when Banana => pragma Assert(Fruit.Is_Peeled); null; when Pineapple => pragma Assert(Fruit.Is_Cored); null; end case; Cut_Up(Fruit); Add_To_Bowl(Fruit, Bowl); end Add_To_Fruit_Salad; We would like to remove those assertions, and make them into preconditions: procedure Add_To_Fruit_Salad( Fruit : in out Fruit_Type; Bowl : in out Bowl_Type) with Pre => (if Fruit.Kind = Apple then Fruit.Is_Crisp elsif Fruit.Kind = Banana then Fruit.Is_Peeled elsif Fruit.Kind = Pineapple then Fruit.Is_Cored); But then if we add Orange to the Fruit_Kind type, we might be missing a precondition. It would be better to write it like this: procedure Add_To_Fruit_Salad( Fruit : in out Fruit_Type; Bowl : in out Bowl_Type) with Pre => (case Fruit.Kind is when Apple => Fruit.Is_Crisp, when Banana => Fruit.Is_Peeled, when Pineapple => Fruit.Is_Cored); Now if we add Orange, we will get an error, prompting us to add "when Orange => Fruit.Is_Juicy", or "when Orange => True", or whatever is appropriate. Without case expressions, we are left with a nasty choice: put the assertions in the body, where they don't belong, or lose the full coverage rules. !proposal (See wording.) !wording In 4.4(7), add: primary ::= numeric_literal | null | string_literal | aggregate | name | allocator | (expression) | conditional_expression Add a new clause: 4.5.7 Conditional expressions Syntax case_expression ::= (case expression is case_expression_alternative {, case_expression_alternative} ) case_expression_alternative ::= when discrete_choice_list => expression ???I don't have time to write up all the rules right now. Let's first see if this idea will fly at all. Basically, the rules can be patterned after the rules for case statements, especially the full coverage rules. "when others" is allowed, and as for case statements, should be used with discretion. We also want to add it to qualified_expression, as for conditional_expression: qualified_expression ::= subtype_mark'(expression) | subtype_mark'aggregate | subtype_mark'conditional_expression subtype_mark'case_expression There is nothing corresponding to the implicit "else False" for conditional_expressions. We need rules for static expressions. !discussion !examples !ACATS test ACATS B and C tests are needed. !appendix From: Bob Duff Sent: Tuesday, November 3, 2009 1:10 PM Here's an AI on case expressions, to complement conditional expressions. [This is version /01 of the AI - ED] **************************************************************** From: Robert Dewar Sent: Tuesday, November 3, 2009 1:19 PM > Case expressions are added to Ada. looks good to me, I am going to go ahead and implement this in GNAT ****************************************************************