!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) @dinsa @xbullet;> @dinst @xbullet whose operand denotes an object;> !corrigendum 3.3(21) @dinsa @xbullet or an @fa;> @dinst @xbullet;> !corrigendum 4.1(2) @drepl @xcode<@fa ::= @fa | @fa | @fa | @fa | @fa | @fa | @fa | @fa | @fa> @dby @xcode<@fa ::= @fa | @fa | @fa | @fa | @fa | @fa | @fa | @fa | @fa | @fa> !corrigendum 4.4(7) @drepl @xcode<@fa ::= @fa | @b | @fa | @fa | @fa | @fa | @fa | (@fa)> @dby @xcode<@fa ::= @fa | @b | @fa | @fa | @fa | @fa | (@fa)> !corrigendum 4.7(3) @dinsa The @i (the @fa or @fa) shall resolve to be of the type determined by the @fa, or a universal type that covers it. @dinst @s8<@b> If the operand of a @fa denotes an object, the @fa denotes a constant view of that object. The nominal subtype of a @fa is the subtype denoted by the @fa. !corrigendum 5.4(7) @drepl @Xbullet is a @fa (including a @fa or a @fa) having a static and constrained nominal subtype, or is a @fa whose @fa denotes a static and constrained scalar subtype, then each non-@b @fa shall cover only values in that subtype, and each value of that subtype shall be covered by some @fa (either explicitly or by @b).> @dby @Xbullet is a @fa (including a @fa, a @fa, or a @fa) having a static and constrained nominal subtype, then each non-@b @fa shall cover only values in that subtype, and each value of that subtype shall be covered by some @fa (either explicitly or by @b).> !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 .component or (index) or .all, without getting slapped on the wrist because 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. ****************************************************************