Version 1.10 of ai05s/ai05-0003-1.txt
!standard 3.3(11) 09-04-23 AI05-0003-1/04
!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 Amendment 201Z 08-11-26
!status WG9 Approved 09-06-12
!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
A qualified expression is treated as a name rather than as a primary.
!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 or 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 access value.
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 result of evaluating an aggregate;
the new paragraph:
- a qualified_expression whose operand denotes an object;
!corrigendum 3.3(21)
Insert after the paragraph:
- the result of evaluating a function_call or an aggregate;
the new paragraph:
- the result of evaluating a qualified_expression;
!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.
the new 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:
- If the expression is a name (including a
type_conversion 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
(either explicitly or by others).
by:
- If the expression is a name (including a
type_conversion, a qualified_expression, or a function_call)
having a static and constrained nominal 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
(either explicitly or by others).
!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