!standard 3.3(11) 07-10-29 AI05-0003-1/02 !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 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; !ACATS test !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! ****************************************************************