Version 1.1 of ai12s/ai12-0157-1.txt

Unformatted version of ai12s/ai12-0157-1.txt version 1.1
Other versions for file ai12s/ai12-0157-1.txt

!standard 3.10.2(19.2/4)          15-03-23 AI05-0157-1/01
!standard 3.10.2(19.3/4)
!standard 4.3.3(11/2)
!standard 6.8(2/3)
!standard 6.8(3/3)
!standard 6.8(5/3)
!standard 6.8(7/3)
!standard 7.5(2.9/3)
!standard 13.14(5.1/4)
!standard 13.14(5.2/4)
!standard 13.14(8/3)
!standard 13.14(10.1/3)
!standard 13.14(10.2/3)
!standard 13.14(10.3/3)
!class binding interpretation 15-03-23
!status work item 15-03-23
!status received 15-02-26
!priority Low
!difficulty Easy
!qualifier Omission
!subject Missing rules for expression functions
!summary
(1) Expression functions can directly use an aggregate as well as an expression surrounded by parentheses.
(2) The expression or aggregate of an expression function has a defined applicable index constraint.
(3) The statically deeper relationship is defined as for a return statement for the expression or aggregate of an expression function.
!question
(1) If an expression function needs to return an aggregate, the syntax requires double parens:
function Rounds return VExt is ((F732C00.Rounds with H => CNPriv));
as the syntax is
[overriding_indicator] function_specification is
(expression) [aspect_specification];
and an aggregate is also surrounded by parenthesis.
This is ugly, and inconsistent with the rest of Ada. In particular, it is inconsistent with the behavior of aggregates in qualified expressions and allocators, and the behavior of other things surrounded in parenthesis like conditional expressions and raise expressions.
Should aggregates be allowed here? (Yes.)
(2) 4.3.3(11/2) defines the applicable index constraint of an aggregate in many contexts. We surely want the return version to apply to an expression function as well, but it's not clear that the wording has that effect. We define an expression function dynamically to be equivalent to the execution of a simple_return_statement, but we treat the legality and static semantic rules explicitly in 6.8. 4.3.3(11/2) is a Legality Rule, thus it arguably is not covered by 6.8(7/3). Should it be updated to include expression functions? (Yes.)
(3) 3.10.2(19.2/4) and 3.10.2(19.3/4) define the statically deeper relationship for return statements inside a function. The same rules need to apply within an expression function. (Note that we don't need to make any changes to the dynamic accessibility level, such as 3.10.2(10.8/3), since 6.8(7/3) clearly does apply to runtime effects.) Should this be fixed? (Yes.)
!recommendation
(See Summary.)
!wording
Modify 3.10.2(19.2/4) [as modified by AI12-0089-1]:
* Inside a return statement that applies to a function or generic function F{, or the expression or aggregate of an expression function F}, when determining whether the accessibility level of an explicitly aliased parameter of F is statically deeper than the level of the return object of F, the level of the return object is considered to be the same as that of the level of the explicitly aliased parameter; for statically comparing with the level of other entities, an explicitly aliased parameter of F is considered to have the accessibility level of the body of F.
Modify 3.10.2(19.3/4) [as modified by AI12-0089-1]:
* For determining whether a level is statically deeper than the level of the anonymous access type of an access result of a function, when within a return statement that applies to the function {or the expression or aggregate of an expression function}, the level of the master of the call is presumed to be the same as that of the level of the master that elaborated the function body.
[Editor's note: I considered added an equivalence rule for the statically deeper relationship instead, either here or in 6.8, but that didn't seem to simplify anything, and having it in 6.8 potentially would cause someone to think that it wasn't defined (we want all of the rules for accessibility in the "Heart of Darkness"; it's hard enough to understand without having to jump all over the place to get the complete picture).]
Modify 4.3.3(11/2):
* For an explicit_actual_parameter, an explicit_generic_actual_parameter, the expression of a return statement {or the expression or aggregate of an expression function}, the initialization expression in an object_declaration, or a default_expression [(for a parameter or a component)], when the nominal subtype of the corresponding formal parameter, generic formal parameter, function return object, object, or component is a constrained array subtype, the applicable index constraint is the constraint of the subtype;
[Note: The weird "or" is needed so that the five items in the first list match up with the five items in the second list. An alternative would be to add a sixth item to the second list as well.]
Replace 6.8(2/3) by:
expression_function_declaration ::= [overriding_indicator] function_specification is (expression) [aspect_specification]; | [overriding_indicator] function_specification is aggregate [aspect_specification];
Modify 6.8(3/3):
The expected type for the expression {or aggregate} of an expression_function_declaration is the result type (see 6.5) of the function.
Modify 6.8(5/3):
If the result subtype has one or more unconstrained access discriminants, the accessibility level of the anonymous access type of each access discriminant, as determined by the expression {or aggregate} of the expression function, shall not be statically deeper than that of the master that elaborated the expression_function_declaration.
Modify 6.8(7/3):
The execution of an expression function is invoked by a subprogram call. For the execution of a subprogram call on an expression function, the execution of the subprogram_body executes an implicit function body containing only a simple_return_statement whose expression is [that]{the expression or aggregate} of the expression function.
Modify 7.5(2.9/3):
* the expression {or aggregate} of an expression_function_declaration (see 6.8)
[Editor's note: AARM 8.3(29.ee/3) also needs a similar update.]
Modify 13.14(5.1/4) [added by AI12-0103-1]:
* At the occurrence of an expression_function_declaration that is a completion, the expression {or aggregate} of the expression function causes freezing.
Modify 13.14(5.2/4) [added by AI12-0132-1]:
* At the occurrence of a renames-as-body whose callable_entity_name denotes an expression function, the expression {or aggregate} of the expression function causes freezing.
Modify 13.14(8/3):
A static expression (other than within an aspect_specification) causes freezing where it occurs. An object name or nonstatic expression causes freezing where it occurs, unless the name or expression is part of a default_expression, a default_name, the expression {or aggregate} of an expression function, an aspect_specification, or a per-object expression of a component's constraint, in which case, the freezing occurs later as part of another construct or at the freezing point of an associated entity.
Modify 13.14(10.1/3):
* At the place where a function call causes freezing, the profile of the function is frozen. Furthermore, if a parameter of the call is defaulted, the default_expression for that parameter causes freezing. If the function call is to an expression function, the expression {or aggregate} of the expression function causes freezing.
[Editor's note: AARM 13.14(10.g/4) also needs a similar update.]
Modify 13.14(10.2/3):
* At the place where a generic_instantiation causes freezing of a callable entity, the profile of that entity is frozen unless the formal subprogram corresponding to the callable entity has a parameter or result of a formal untagged incomplete type; if the callable entity is an expression function, the expression {or aggregate} of the expression function causes freezing.
Modify 13.14(10.3/3):
* At the place where a use of the Access or Unchecked_Access attribute whose prefix denotes an expression function causes freezing, the expression {or aggregate} of the expression function causes freezing.
!discussion
(1) Consistency with qualified expressions seems important here. An early implementation of Ada 2012 allows this syntax (presumably by accident), and an ACATS test-writer used it (definitely by accident, known because the author of this AI and that that test-writer are one and the same). It seems natural, and it's best if the syntax of Ada follows that as much as possible.
An alternative to the changes noted here would be to define (as in 4.4(1)) that expression of an expression function is the expression or aggregate of an expression_function_declaration. The latter uses of expression and aggregate being in the syntax font. Note that doing that would still require all of the changes noted here, as "expression" is in the syntax font in all 12 places noted here [10 normative, two AARM notes], which would have to be changed to the normal font. In addition, some of the text uses "expression of an expression_function_declaration", and that would have to be changed to "expression of an expression function" (no syntax font). Since no work is saved by introducing the term, and there doesn't seem to be a readability advantage to having another term that not quite the same as the equivalent syntax, we didn't do that.
(2) It appears that a strict reading of 4.3.3 says that
function Cool return Some_Array is ((others => 1));
or, with adoption of (1)
function Cool return Some_Array is (others => 1);
are illegal because an "applicable index constraint" isn't provided (this is none of the contexts listed in 4.3.3(11-15.1)). We don't want that, since the equivalent
function Cool return Some_Array is begin return (others => 1); end Cool;
is legal.
(3) This was raised by Steve Baird (who else?). It is unlikely but possible for these 3.10.2 rules to matter. They would matter in a case like:
function Bar (Obj : aliased in out Int_Cont; Index : in Natural) return access Integer is (Obj.Element(Index)'access);
We want this to be legal, as it is legal if this is written with an explicit body. (Bar here is similar to the construction of function Reference in the containers; we would want it to be possible for an expression function to be used in place of a full body for these routines.)
--!corrigendum 3.10.2(19.2/4) -- --@drepl --@dby
!ASIS
The ASIS operations for expression functions (whatever they are) will need to allow aggregates. Can't be more specific than that as the previous is not well-defined.
For (2) and (3), there is no ASIS effect.
!ACATS test
Problem (1) originated in ACATS test B732C01, so we already have an example. It would be nice for it to be used in an ACATS C-Test, but it's unlikely to not work. It would be nice to have tests for examples like the ones in the discussion for problems (2) and (3).
!appendix

From: Randy Brukardt
Sent: Thursday, February 26, 2015  4:07 PM

I've been sitting on this one for the last few days, both because I wasn't sure
what to think and because I didn't want to make even more work for myself before
the call. Since we decided to have another call next month to finish up, I
figured I better raise this, especially as I've decided what I think.

In an ACATS B-Test (based on Jeff's C-Tests for type invariants), I needed some
convenient function bodies, so I used expression functions:

     function Rounds return VExt is (F732C00.Rounds with H => CNPriv);

This is an extension aggregate.

GNAT happily compiles the test and reports the proper errors.

However, my new Janus/Ada reports syntax errors on this test (it suggests moving
the right paren from the end to before the with).

The Ada grammar for expression functions is:

expression_function_declaration ::=
   [overriding_indicator]
   function_specification is
      (expression)
      [aspect_specification];

An aggregate is an expression for this purpose, so the grammar requires
enclosing it in a double set of parens:

     function Rounds return VExt is ((F732C00.Rounds with H => CNPriv));

My initial reaction was of course that GNAT was wrong, but upon reflection,
there is a reasonable argument that the standard is wrong instead:

(1) In similar cases (conditional expressions, qualified expressions), we go to
    lengths to ensure that double parens are not needed.

(2) I wrote the above naturally (it didn't directly have anything to do with the
    test), so one can presume that at least some other Ada programmers would
    also expect the above to work. "It feels right." Obviously, whoever
    implemented that in GNAT thought the same way. (This was the point that I
    was wavering on, primarily because I thought that Jeff had written the test
    in question. There is a visceral difference between someone else
    accidentally misusing a feature and one's self doing the same. ;-)

(3) The double parens are UGLY!!! :-)

The above suggests that we should change the expression function syntax a-la the
similar syntax for qualified expressions:

expression_function_declaration ::=
    [overriding_indicator]
    function_specification is
       (expression)
       [aspect_specification];
  | [overriding_indicator]
    function_specification is
       aggregate
       [aspect_specification];

A bunch of the text also would need change (to "expression or aggregate").
Alternatively, we could add a new non-terminal to mean "(expression) or
aggregate" and use that in the grammar and text.

Thoughts??

---

A vaguely related question. 4.3.3(11/2) defines the applicable index constraint
of an aggregate in many contexts. We surely want the return version to apply to
an expression function as well, but it's not clear to me that the wording has
that effect. We define an expression function dynamically to be equivalent to
the execution of a simple_return_statement, but we treat the legality and static
semantic rules explicitly in 6.8. 4.3.3(11/2) is a Legality Rule, thus it
arguably is not covered by 6.8(7/3), particularly in cases where legality is
involved (for instance, whether an others choice is allowed).

Specifically, it appears that a strict reading says that

    function Cool return Some_Array is ((others => 1));

is illegal because an "applicable index constraint" isn't provided (this is none
of the contexts listed in 4.3.3(11-15.1)). That seems to violate the Dewar rule,
since

    function Cool return Some_Array is
    begin
        return (others => 1);
    end Cool;

is legal.

Probably we should add some wording somewhere to fix this.

****************************************************************

From: Robert Dewar
Sent: Thursday, February 26, 2015  4:21 PM

> A bunch of the text also would need change (to "expression or aggregate").
> Alternatively, we could add a new non-terminal to mean "(expression)
> or aggregate" and use that in the grammar and text.
>
> Thoughts??

I agree, the double parens are ugly, and we should avoid them here

****************************************************************

From: Gary Dismukes
Sent: Thursday, February 26, 2015  4:29 PM

...
> Thoughts??

Agreed that this should be fixed, and your suggestion for changing the syntax
seems reasonable.  Even more so since GNAT already supports this. ;-)

...
> Probably we should add some wording somewhere to fix this.

I agree with this suggested change as well.

****************************************************************

From: Tucker Taft
Sent: Thursday, February 26, 2015  8:26 PM

> ... My initial reaction was of course that GNAT was wrong, but upon
> reflection, there is a reasonable argument that the standard is wrong instead:
>
> (1) In similar cases (conditional expressions, qualified expressions),
> we go to lengths to ensure that double parens are not needed.

Also in qualified expressions, we allow a parenthesized expression or an
aggregate.

> A bunch of the text also would need change (to "expression or aggregate").
> Alternatively, we could add a new non-terminal to mean "(expression)
> or aggregate" and use that in the grammar and text.

I could see having a non-terminal for:

     (expression) | aggregate | (conditional_expression) | (quantified_expression)

perhaps "parenthesized_expression" ;-)

While we are at it, I presume "T'(if A then X else Y)" is legal due to the rules
that allow the elimination of extra parenthesizes around
conditional_expressions, but it seems like we could define qualified_expression
as subtype_mark'parenthesized_expression (or whatever we end up calling this new
non-terminal) and avoid the need to apply the special parenthesis elimination
rule in this context.

> Thoughts??

I agree we don't want to require double parentheses here.

>
> ---
>
> A vaguely related question. 4.3.3(11/2) defines the applicable index
> constraint of an aggregate in many contexts. We surely want the return
> version to apply to an expression function as well, but it's not clear
> to me that the wording has that effect.  ...
>
> Probably we should add some wording somewhere to fix this.

Agreed.

****************************************************************

From: Jean-Pierre Rosen
Sent: Friday, February 27, 2015  2:43 AM

> A bunch of the text also would need change (to "expression or aggregate").
> Alternatively, we could add a new non-terminal to mean "(expression)
> or aggregate" and use that in the grammar and text.
>
> Thoughts??

The syntax for aggregates was designed at a time when it was the only case of
required double parentheses. Then, we had conditional expressions, with explicit
wording to avoid double parentheses. Now the expression functions...

Isn't it time that we bite the bullet and have some wording (or syntax, I don't
know) to state that double parentheses are never required in Ada, so this
problem wouldn't appear any more in future additions to the language?

****************************************************************

From: Robert Dewar
Sent: Friday, February 27, 2015  2:56 AM

That seems wrong

    X ((1,2,3))

can have a totally different meaning from

    X (1,2,3)

where X are overloaded subprograms

****************************************************************

From: Jean-Pierre Rosen
Sent: Friday, February 27, 2015  3:22 AM

Right. What about:
double parentheses are never required if the type is determined from context ?

****************************************************************

From: Bob Duff
Sent: Friday, February 27, 2015  9:49 AM

> An aggregate is an expression for this purpose, so the grammar
> requires enclosing it in a double set of parens:
>
>      function Rounds return VExt is ((F732C00.Rounds with H =>
> CNPriv));
...
> The above suggests that we should change the expression function
> syntax a-la the similar syntax for qualified expressions:

I agree we should not require double parens in this case.

> expression_function_declaration ::=
>     [overriding_indicator] function_specification is (expression)
> [aspect_specification];
>   | [overriding_indicator] function_specification is aggregate
> [aspect_specification];
>
> A bunch of the text also would need change (to "expression or aggregate").
> Alternatively, we could add a new non-terminal to mean "(expression)
> or aggregate" and use that in the grammar and text.

I count six such places (searched for expression function).  Not so horrible.

Or we could say,

    The term "expression of an expression function" refers to the
    expression or aggregate of the expression_function_declaration.
    ^^^^^^^^^^
    ...and put that one in syntax font.

echoing 4.4(1).

Tucker wrote:

> I could see having a non-terminal for:
>
>      (expression) | aggregate | (conditional_expression) |
> (quantified_expression)
>
> perhaps "parenthesized_expression" ;-)

I agree that's cleaner in some ways, but it seems like a bigger change than necessary.

> While we are at it, I presume "T'(if A then X else Y)" is legal due to
> the rules that allow the elimination of extra parenthesizes around
> conditional_expressions,...

Yes, that's legal.

>...but it seems
> like we could define qualified_expression as
>subtype_mark'parenthesized_expression
> (or whatever we end up calling this new non-terminal) and avoid the
>need to apply the  special parenthesis elimination rule in this context.

That seems like a gratuitous change at this point.  If it eliminated the need
for the special paren-elimination rules, it might be worth it, but eliminating
those rules just for qual_exp doesn't gain us anything.

Also, if we go that way, there's a possible confusion between
"parenthesized_expression" and "parenthesized expression". The latter is used 10
times, and "parenthesized" is used 24 times, and it's not formally defined,
which is just fine in the absence of this new parenthesized_expression
nonterminal.

My mental model of Ada contains this syntax rule:

    parenthesized_expression ::= (expression)

which is not in the RM.  ;-)

****************************************************************

From: Bob Duff
Sent: Friday, February 27, 2015  9:42 AM

> Right. What about:
> double parentheses are never required if the type is determined from
> context ?

It is important that aggregates be detected syntactically.
We really don't want to mix semantics into that (e.g. if
X(1,2,3) is allowed when there is just one X that takes one parameter).  That
would damage readability IMHO, and would be an earthquake for compilers.

Besides, this syntax goes back to Ada 83, and I haven't heard any complaints
from users.

****************************************************************

From: Robert Dewar
Sent: Friday, February 27, 2015  9:58 AM

> It is important that aggregates be detected syntactically.
> We really don't want to mix semantics into that (e.g. if
> X(1,2,3) is allowed when there is just one X that takes one
> parameter).  That would damage readability IMHO, and would be an
> earthquake for compilers.

I strongly agree, let's leave aggregates alone in this discussion.
Aggregates always require a level of parens that is part of the aggregate, we
have been used to this for 20 years, and we should not even consider a change.

> Besides, this syntax goes back to Ada 83, and I haven't heard any
> complaints from users.

Exactly!

****************************************************************

From: Randy Brukardt
Sent: Friday, February 27, 2015  3:32 PM

...
> > A bunch of the text also would need change (to "expression or aggregate").
> > Alternatively, we could add a new non-terminal to mean "(expression)
> > or aggregate" and use that in the grammar and text.
>
> I count six such places (searched for expression function).
> Not so horrible.

Right, pretty mechanical to change. I just wanted to note that it would need to
be done (the change is more than just adding the production in question).

> Or we could say,
>
>     The term "expression of an expression function" refers to the
>     expression or aggregate of the expression_function_declaration.
>     ^^^^^^^^^^
>     ...and put that one in syntax font.
>
> echoing 4.4(1).

I don't think we want to introduce any more cases into the RM where the English
text means something subtly different than the syntax term.

After all, we already have body (syntax font) /= body (text font) /= body
(keyword font). And we had to add some weasel wording so that "function_call"
(syntax font) = "function call" (text font), else everything using the former
did not allow infix operators!

Your proposal that "expression (text font) of an expression function" means
something different than "expression (syntax font) of an expression function"
falls into the category.

Of course, there's an argument that "expression" (text font) already means
something subtly different than "expression" syntax font (the former generally
is taken to include things that aren't technically expressions, like
simple_expressions and choice_expressions -- indeed I used it that way in one
place in yesterday's approved changes). So it's not a terrible idea.

But given that we have to change all of the wording either way, I'd probably say
just use "expression or aggregate" and avoid introducing yet another term.
Especially if there's only six places. Didn't you (Bob) write a message
complaining about introducing excessive terms earlier this week?

****************************************************************

From: Robert Dewar
Sent: Friday, February 27, 2015  3:38 PM

Boy this reminds me of a discussion in the Algol-68 maintenance committee where
the font of a comma made a critical difference :-)

****************************************************************

Questions? Ask the ACAA Technical Agent