Version 1.6 of ai05s/ai05-0003-1.txt

Unformatted version of ai05s/ai05-0003-1.txt version 1.6
Other versions for file ai05s/ai05-0003-1.txt

!standard 3.3(11)          08-11-14 AI05-0003-1/03
!standard 3.3(21)
!standard 4.1(2)
!standard 4.4(7)
!standard 4.7(3)
!standard 5.4(7)
!class Amendment 05-10-24
!status ARG Approved 8-0-1 06-11-11
!status work item 06-03-15
!status received 05-09-20
!priority Medium
!difficulty Medium
!subject Qualified expressions and "names"
!summary
(See proposal.)
!problem
A function_call can be used as a "name". Thus, for example, it can be used as the prefix of a component selector or array index.
If a function is overloaded, one of the ways to disambiguate a function call is to use a qualified expression to tell the compiler what the return type of the function is supposed to be.
However, although the function_call can be used as a "name", a qualified expression can't---it's not in the syntax of "name". So if you want to use a function_call as a "name", but you need to use a qualified expression to disambiguate it, you can't. This should be fixed somehow.
!proposal
Treat qualified_expressions as names rather than as expressions. A qualified_expression is never considered a variable, however.
!wording
Add after 3.3(11):
* a qualified_expression whose operand denotes an object;
Add after 3.3(21):
* the result of evaluating a qualified_expression;
Modify 4.1(2) to add "| qualified_expression" somewhere
Modify 4.4(7) to remove "| qualified_expression"
Add a new paragraph after 4.7(3):
Static Semantics
If the operand of a qualified_expression denotes an object, the qualified_expression denotes a constant view of that object. The nominal subtype of a qualified_expression is the subtype denoted by the subtype_mark.
Change 5.4(7) as follows:
If the expression is a name [Redundant: (including a type_conversion{, a qualified_expression,} or a function_call)] having a static and constrained nominal subtype, [or is a qualified_expression whose subtype_mark denotes a static and constrained scalar subtype,] then each non-others discrete_choice shall cover only values in that subtype, and each value of that subtype shall be covered by some discrete_choice [Redundant: (either explicitly or by others)].
!discussion
We propose to allow qualified_expressions anywhere names are allowed (syntactically). The main purpose is to allow them as a prefix, but there seems no harm in allowing them more generally, in particular before ".all".
We do not consider a qualified_expression to be a variable, even if its operand denotes a variable. The added complexity of allowing certain qualified_expressions on the left-hand side of an assignment or as an [IN] OUT parameter does not seem to be justified. We considered allowing qualified_expressions whose operands denote variable objects of a tagged type to be variables (analogous to the rule for type_conversion), but it added complexity, without any obvious benefit. Ambiguity generally involves calls on overloaded functions, and the result of a function call is always a constant, so it is not clear there are enough ambiguous names of variables to even worry about.
One kind of overloaded variable name is "overloaded_function.all", but in that case, we would now allow "T'(overloaded_function).all" so there is no need to apply the qualification to the dereference as a whole, just to the pointer.
For an assignment statement to be ambiguous, both the left-hand side and the right-hand side would need to be overloaded, in which case the qualified_expression could be applied to the right-hand side rather than the left-hand side, again avoiding the need to have qualified_expressions that are variables.
We had considered defining a separate "qualified_name" construct which would require that the operand be a name, for the qualified construct to be considered a name. This was to prevent certain uses like:
T'(A => 3, X => 4).X or
Str'("this is fun")'Length
But these are already allowed by simply wrapping them in an identity conversion, such as:
T(T'(A => 3, X => 4)).X or
Str(Str'("this is fun"))'Length
so it is hard to imagine that there is any significant implementation or cognitive burden to allowing them directly.
Of course the main intent is to allow calls on overloaded functions to be qualified as necessary to eliminate ambiguity, without losing the ability to use them in contexts requiring names. But there also seems no justification in creating more complicated syntax rules just to prevent other kinds of qualified_expression usages that are effectively already possible in a somewhat uglier form.
We add the definition of the nominal subtype of a qualified_expression, since there is an assumption that names always have nominal subtypes (in particular, in the rules for case statements -- also see AI05-0006).
We define a qualified_expression of an object to be a constant view of that same object so that attributes like 'Address are well defined.
!example
Foo(Ptr'(Overloaded_Function_Returning_Ptr).all);
Rec_Ptr'(Overloaded_Function_Returning_Rec_Ptr).X := Y;
Z := Arr_Ptr'(Overloaded_Function_Returning_Arr_Ptr)(J);
L := Arr_Ptr'(Overloaded_Function_Returning_Arr_Ptr)'Length;
!corrigendum 3.3(11)
Insert after the paragraph:
the new paragraph:
!corrigendum 3.3(21)
the new paragraph:
a
the new paragraph:
t
!corrigendum 4.1(2)
Replace the paragraph:
name ::= direct_name | explicit_dereference | indexed_component | slice | selected_component | attribute_reference | type_conversion | function_call | character_literal
by:
name ::= direct_name | explicit_dereference | indexed_component | slice | selected_component | attribute_reference | type_conversion | function_call | character_literal | qualified_expression
!corrigendum 4.4(7)
Replace the paragraph:
primary ::= numeric_literal | null | string_literal | aggregate | name | qualified_expression | allocator | (expression)
by:
primary ::= numeric_literal | null | string_literal | aggregate | name | allocator | (expression)
!corrigendum 4.7(3)
Insert after the paragraph:
The operand (the expression or aggregate) shall resolve to be of the type determined by the subtype_mark, or a universal type that covers it.
Insert after the paragraph:
Static Semantics
If the operand of a qualified_expression denotes an object, the qualified_expression denotes a constant view of that object. The nominal subtype of a qualified_expression is the subtype denoted by the subtype_mark.
!corrigendum 5.4(7)
Replace the paragraph:
by:
!ACATS test
Add ACATS tests using qualified expressions as names, including cases like those in the examples, and function results renamed as objects.
!appendix

!topic Qualified expressions and "names"
!reference RM95 4.1(2), 4.7
!from Adam Beneschan 09-20-05
!discussion

This is a minor point, but it might be worth considering (probably not
for 0Y but maybe in the future).

A function_call can be used as a "name".  Thus, for example, it can be
used as the prefix of a component selector or array index.  I don't
know how often this is actually done in practice.  Also, now that
Object.Operation is one form of component selection (AI-252), it may
be that this will be done more often.

If a function is overloaded, one of the ways to disambiguate a
function call is to use a qualified expression to tell the compiler
what the return type of the function is supposed to be.

However, although the function_call can be used as a "name", a
qualified expression can't---it's not in the syntax of "name".  So if
you want to use a function_call as a "name", but you need to use a
qualified expression to disambiguate it, you can't.

May I suggest that the definition of "name" be expanded to include
qualified expressions of the form subtype_mark'(expression) where
"expression" is a function_call?

I'll admit that this isn't an important change---it's pretty obscure.
But it would plug what seems to be a little hole in the language.  It
shouldn't have much impact on the rest of the RM (he said hopefully),
since a qualified expression of that form would be semantically
exactly the same as the function call inside the qualified expression.
Plus it shouldn't be too difficult to implement.

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

From: Tucker Taft
Date: Tuesday, September 20, 2005  1:41 PM

This whole distinction between what is a name and what is an expression
is annoying, and should probably be eliminated.  We should have
done it in Ada 95, and probably should have done it in Ada 2005.
It just never made it up high enough on the priority list...

I suppose one option is to keep "name" as is, but make
"prefix" more flexible.  I don't think we are looking to
allow more things on the LHS of an assignment or as an OUT
parameter.  Mostly we want to be able to use <blah>.component
or <blah>(index) or <blah>.all, without getting slapped
on the wrist because <blah> is not "officially" a "name."

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

From: Adam Beneschan
Date: Tuesday, September 20, 2005  2:00 PM

> I suppose one option is to keep "name" as is, but make
> "prefix" more flexible.

I like that idea a lot better than the one I came up with.

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

Editor's note, August 3, 2007

One possible fix for the problem of the not quite equivalent equivalence
rule in 6.6(2) would be to reduce or eliminate the difference between
expressions and names. The problem is that an infix operator call is
an expression, not a name, while the supposedly equivalent function call
is a name. Thus is it illegal to rename the result of an expression:
    Val : Integer renames A + 3; -- Illegal
even though the equivalent prefix call is legal:
    Val : Integer renames "+"(A, 3); -- Legal

See AC-00143 for a thread about this problem and its effects.

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

From: Tucker Taft
Date: Monday, October 29, 2007 4:55 PM

Here is my other "low priority" AI [version /02 - ED], about
allowing qualified_expressions where names
are allowed.  I tried various approaches, but
ultimately ended up with the simplest, which
is basically just to move qualified_expression
in the grammar from "expression" to "name."

I considered only allowing them as prefixes,
but that didn't allow "T'(overloaded).all" which
seems pretty useful.  I also considered creating
a separate "qualified_name" construct, which was
a qualified_expression whose operand was a name,
but that didn't seem to buy much.  I think the
goal was to prevent things like Str'("this is a string")
from being names, but it turns out you can make
pretty much anything into a name by wrapping it
in an identity conversion:

    Str(Str'("this is a string"))

so it didn't seem worth sweating hard disallowing
such things.

The other thing I did was make qualified_expressions
constants, even if their operand was a variable.
I toyed with other rules, e.g. allowing tagged
variables to remain variable when qualified, but
I couldn't find compelling examples where that
would be useful.

So have fun reading!

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

From: Pascal Leroy
Date: Monday, November 5, 2007 3:11 PM

Shouldn't the same rules apply to parenthesized expressions?  I have
always thought that parenthesize expressions and qualifications should
be handled similarly.  Parentheses can help readability, so it should
be possible to add them freely, even before a .all.

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

From: Tucker Taft
Date: Monday, November 5, 2007 3:53 PM

I have no problem with that, but I think it should be
a separate AI, since I could imagine there are others
who feel that "(A + B)" doesn't look at all like a "name"
whereas "T'(A+B)" does.

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

Questions? Ask the ACAA Technical Agent