!standard 5.2.1(5/5) 19-03-07 AI12-0322-1/01 !class Amendment 19-03-07 !status work item 19-03-07 !status received 19-03-07 !priority Low !difficulty Easy !subject Equivalence for the target name symbol !summary Replace the equivalence for the target name symbol with some rules. !problem The equivalence for the target name symbol seems very complicated, verging on incomprehensible. !proposal (See Summary.) !wording Change the redundant markings in 5.2.1(3/5): Redundant[If a target_name occurs in an assignment_statement A, the variable_name V of A is a complete context.] The target name Redundant[is a constant view of V,] having the nominal subtype of V. Modify AARM 5.2.1(3.a/5): The complete context rule is formally given in 8.6. The constant view rule is formally given in 3.3[; the nominal subtype follows from the equivalence given below in Static Semantics]. Replace 5.2.1 (5/5) with: Dynamic Semantics For the execution of an assignment_statement with one or more target_names appearing in its expression, the /variable_/name V of the assignment statement is evaluated first to determine the object denoted by V, and then the expression of the assignment_statement is evaluated with the evaluation of each target_name yielding a constant view of the object denoted by V. The remainder of the execution of the assignment_statement is as given in subclause 5.2. AARM Ramification: Use of a target_name can be erroneous if the /variable_/name V is a discriminant-dependent component, and some other constituent of the expression modifies the discriminant governing V. While this is possible with assignment_statements that don't use a target_name, it is more likely when using a target_name as there is potentially more time between the evaluation of the name and the use of the value. See 3.7.2. !discussion We are replacing the old equivalence which was based on an implicit procedure, with an explicit dynamic semantics defining what it means to evaluate a target_name. !ASIS [Not sure. It seems like some new capabilities might be needed, but I didn't check - Editor.] !ACATS test ACATS B- and C-Tests are needed to check that the new capabilities are supported. !appendix From: Randy Brukardt Sent: Wednesday, March 6, 2019 4:46 PM Bob's RM review includes the following: >5.2.1(5/5): >[The variable_name is evaluated only once.] In particular, if a >target_name with nominal subtype S appears in the expression of an >assignment_statement A, then A is equivalent to a call on a local >anonymous procedure with the actual parameter being the variable_name >of A, where the local anonymous procedure has an in out parameter with >unique name P of subtype S, with a body being A with the variable_name >being replaced by P, and any target_names being replaced by the >qualified expression S'(P). >That looks like Steve's handiwork. ;-) Just say "A target_name denotes >the value of the variable_name (before the assignment). The >variable_name is evaluated only once." >All this business about anonymous procedures is totally >incomprehensible. Or at least move it to the AARM. > >Not sure "(before the assignment)" is necessary -- seems pretty obvious. > >Also, this is about "evaluation", so shouldn't it be under Dynamic >Semantics? I don't know how to handle this one. My first inclination is to ignore it -- this topic was fairly throughly hashed over during the discussion of this AI. But that doesn't seem to be appropriate. So let me explain this a bit and ruminate over options. The reason for all of this babble is to clearly define what happens in various corner cases. Without it, we're leaving lots of semantics undefined, and there are questions about Legality, accessibility, finalization, and erroneousness that are left unanswered. For instance, this model defines how @ is handled for the anti-order-dependence Legality Rules. It defines what happens if a discriminant governing the target is changed by the expression. It defines what happens to the value of the target itself is changed by the expression. It defines how @ is finalized (it isn't). And probably a bunch of other things I haven't thought of (and perhaps that no one has thought of)). We talked about defining all of these things explicitly, but it seems like it would require a lot of duplication and wording. And, unlike parens, we can't really get away without some definition, since there is no intuitive answer that applies (especially in corner-cases). Additionally, an equivalence rule like this allows us to be certain that we can answer any weird case that Steve can come up with; explicit rules can't do that. So, is there any other viable suggestion, or should I ignore this comment? Or do I have to put it on the agenda?? *************************************************************** From: Tucker Taft Sent: Wednesday, March 6, 2019 5:07 PM I think should go on the agenda, but with a time-limited discussion. It would *really* help if Bob and/or Steve could identify exactly what problems Steve's wording solves, i.e., what corner cases are not covered by Bob's wording. If they are extremely rare, then a "To Be Honest" might be the right choice. *************************************************************** From: Randy Brukardt Sent: Wednesday, March 6, 2019 5:38 PM > I think should go on the agenda, but with a time-limited discussion. 10 seconds? :-) > It would *really* help if Bob and/or Steve could identify exactly what > problems Steve's wording solves, i.e., what corner cases are not > covered by Bob's wording. If they are extremely rare, then a "To Be > Honest" might be the right choice. I listed some of them in my original note: (1) What happens if the target is modified by evaluating the expression? Glob : Natural := 0; function Side_Effect return Natural is begin Glob := Glob + 1; return 1; end Side_Effect; Glob := @ + Side_Effect; Steve's wording says that Glob = 1 after this call, regardless of when Side_Effect is evaluated. Bob's wording leaves it unspecified (because it leaves *everything* unspecified). (2) What happens if the target is discriminant-dependent and the discriminant is changed? Glob.F := @ + Change_Glob; Steve's wording says this is erroneous (by the rule that says doing this to a parameter is erroneous), Bob's wording says nothing. (3) How is the anti-order-dependence rules enforced? Targ := @.F + Func_with_In_Out (@.F.all); Steve's wording gives an unequivocal answer, no idea for Bob's (since it says nothing about anything). *************************************************************** From: Steve Baird Sent: Wednesday, March 6, 2019 5:41 PM >> All this business about anonymous procedures is totally >> incomprehensible. Or at least move it to the AARM. Guilty as charged (and unrepentant). We want the rules to correctly handle cases where the evaluation of the RHS modifies the LHS, as well as all the other issues that Randy mentioned. An equivalence rule seemed like the way to go, for the reasons Randy described. Originally, the idea was to use renaming semantics, so that LHS := Some_Func (@); could be treated as declare @ : T renames LHS; begin @ := Some_Func (@); end; But that didn't work if the LHS was something that was illegal to rename, such as Unconstrained_Variable.Discriminant_Dependent_Component So we instead said that the assignment is equivalent to declare procedure Foo (Param : in out T) is begin Param := Some_Func (T'(Param)); end; begin Foo (Lhs); end; The point is that while you cannot rename Unconstrained_Variable.Discriminant_Dependent_Component , you can pass it as an actual parameter. I don't recall the reason for the S'(P) qualification mentioned in the current wording. At the very least, Bob's suggestion would need to be augmented to state that the LHS name is evaluated before the RHS value. *************************************************************** From: Randy Brukardt Sent: Wednesday, March 6, 2019 5:57 PM ... > I don't recall the reason for the S'(P) qualification mentioned in the > current wording. I think it is a cutesy way to ensure that @ is a constant view. Since the parameter of the implicit subprogram is defined to be in out, it's a variable. I don't recall if there was a real issue with @ being a variable, or if we were just being pedantic. *************************************************************** From: Steve Baird Sent: Wednesday, March 6, 2019 6:07 PM Sounds right. *************************************************************** From: Bob Duff Sent: Wednesday, March 6, 2019 6:22 PM > I don't know how to handle this one. My first inclination is to ignore > it -- My intention for the RM review was that the editor would decide what to do -- agree or disagree with my suggestions. Perhaps in rare cases bring it up for discussion. But in any case, I'm not going to complain if you decide my suggestions are wrong. I certainly don't want to have endless arguments about these things. *************************************************************** From: Tucker Taft Sent: Wednesday, March 6, 2019 6:27 PM > I listed some of them in my original note: > > (1) What happens if the target is modified by evaluating the expression? > > Glob : Natural := 0; > > function Side_Effect return Natural is > begin > Glob := Glob + 1; > return 1; > end Side_Effect; > > Glob := @ + Side_Effect; > > Steve's wording says that Glob = 1 after this call, regardless of when > Side_Effect is evaluated. Bob's wording leaves it unspecified (because > it leaves *everything* unspecified). This would still seem to depend on whether Glob is passed by copy or by reference, which is implementation-defined for cases where Glob is something like a Big_Num. I agree for a by-copy type, the equivalence eliminates doubt in this case, though perhaps a couple of added words would resolve this, and we could in fact eliminate the by-ref vs. by-copy uncertainty should we so choose. In fact, if programmers use @ to be a short hand for simply writing the name again, they might be surprised the use of @ somehow eliminates an order dependence, and might not want to rely on that, but instead, would want to eliminate any possibility of such an order dependence. I certainly didn't think of "@" as eliminating such bizarro order dependencies, and I don't see it as a valuable feature of "@." If the semantics were that the order dependence still remained, I don't think anyone would complain. > (2) What happens if the target is discriminant-dependent and the > discriminant is changed? > > Glob.F := @ + Change_Glob; > > Steve's wording says this is erroneous (by the rule that says doing > this to a parameter is erroneous), Bob's wording says nothing. This is still erroneous without Steve's circumlocutions, per 3.7.2(4): "The execution of a construct is erroneous if the construct has a constituent that is a name denoting a subcomponent that depends on discriminants, and the value of any of these discriminants is changed by this execution between evaluating the name and the last use (within this execution) of the subcomponent denoted by the name. " > (3) How is the anti-order-dependence rules enforced? > > Targ := @.F + Func_with_In_Out (@.F.all); I presume you meant: "@.F.all + Func_With_In_Out(@.F.all);" unless you are doing "access type" arithmetic. I'm not sure I see the problem here, since @ is a name which denotes something (namely the same thing denoted by Targ), and the rules of 6.4.1(6.5-6.25) are all compile-time checks, so only compile-time properties matter. > Steve's wording gives an unequivocal answer, no idea for Bob's (since > it says nothing about anything). Not sure I agree, though it is helpful to lay out these specific issues, so we can discuss them as a group (for 10 minutes, say ;-) *************************************************************** From: John Barnes Sent: Thursday, March 7, 2019 1:44 AM Maybe this discussion reveals that @ was a bad idea after all. *************************************************************** From: Tucker Taft Sent: Thursday, March 7, 2019 2:45 AM > Maybe this discussion reveals that @ was a bad idea after all. Let's not go there! ;-) I would suggest that perhaps we adopt an object-renaming equivalence rather than the implicit procedure-call equivalence, and simply say the rule disallowing certain renamings of discriminant-dependent components (RM 8.5.1(5/3)) is relaxed in this equivalence. That seems pretty simple and matches the programmer's intuition better, I would argue. Note that the only reason for 8.5.1(5/3) is to reduce the likelihood of the erroneousness identified in 3.7.2(4), given that an object renaming could be quite long-lived. Given that "@" implies a much shorter extent for the (implicit) renaming, it is reasonable to suspend RM 8.5.1(5/3) and fall back on 3.7.2(4) to handle the possibility of side effects that change the value of a discriminant. I think a renaming equivalence would be much easier to understand, and more closely matches the programmer's intuition about what "@" means. It is also somewhat easier to implement, I would claim, since it doesn't depend on faking the semantics of parameter passing, with all of the by-copy vs. by-reference shenanigans. The renaming model is equivalent to a pure by-reference model, and will actually reduce the amount of implementation dependence. *************************************************************** From: Richard Wai Sent: Thursday, March 7, 2019 8:57 AM > Let's not go there! ;-) > > I would suggest that perhaps we adopt an object-renaming equivalence > rather than the implicit procedure-call equivalence, and simply say the rule > disallowing certain renamings of discriminant-dependent components (RM > 8.5.1(5/3)) is relaxed in this equivalence. That seems pretty simple > and matches the programmer's intuition better, I would argue. Hear, hear! > Glob : Natural := 0; > > function Side_Effect return Natural is > begin > Glob := Glob + 1; > return 1; > end Side_Effect; > Glob := @ + Side_Effect; In this example, I find it honestly inconceivable that the last statement would somehow not be _exactly_ equivalent to "Glob := Glob + Side_Effect;". That is the whole point of '@', and I cannot imagine a programmer who would not see it that way. It is a simple concept too, no need to make it do crazy things, it's ugly enough as it is! *************************************************************** From: Steve Baird Sent: Thursday, March 7, 2019 1:13 PM > I think a renaming equivalence would be much easier to understand, and more > closely matches the programmer's intuition about what "@" means. Agreed. The objection to that was that, without the rules relaxation you propose, it would cause certain reasonable uses of "@" to be illegal. I agree that the rules relaxation you propose is another good solution to the problem. And it makes it clear that the LHS is evaluated before we begin evaluation of the RHS. *************************************************************** From: Randy Brukardt Sent: Thursday, March 7, 2019 2:04 PM ... > That seems pretty simple > and matches the programmer's intuition better, I would argue. This seems like a reasonable approach to be, subject the next oddity raised by Steve. ;-) I presume that we would be renaming a qualified expression, so as to preserve the requirement that @ is a constant view. Could you propose some wording along these lines so I can write something up for the meeting? Preferably before the deadline, along with your RM review and the rewording of AI12-0282-1. :-) [As always, tell me if you're going to be a bit late, just so I'm not surprised by late submissions.] *************************************************************** From: Bob Duff Sent: Thursday, March 7, 2019 4:42 PM > And it makes it clear that the LHS is evaluated before we begin > evaluation of the RHS. I admit that things are not as simple as I implied in my note to Randy. I expected Randy to "take it or leave it", not start a long discussion. But I do think the renaming suggestion from Tucker is rather less arcane. *************************************************************** From: Randy Brukardt Sent: Thursday, March 7, 2019 9:20 PM > I admit that things are not as simple as I implied in my note to > Randy. I expected Randy to "take it or leave it", not start a long > discussion. I couldn't decide how to handle the comment. I had thought about it periodically for parts of three days, it was starting to drive me nuts, and concluded "if in doubt, ask the group" (especially better than obsessing over something not very important). > But I do think the renaming > suggestion from Tucker is rather less arcane. ...which is why I couldn't decide on what to do. You had a good point, just not a good replacement. And I'm trying not to write the *whole* standard by myself. *************************************************************** From: Tucker Taft Sent: Thursday, March 7, 2019 4:38 PM Here is an attempt to simplify the handling of target_name (aka "@"). I abandoned using an equivalence completely, because the dynamic semantics are so straightforward. ------- !subject Define target_name without recourse to an implicit procedure Replace RM 5.2.1 (5/5) with: Dynamic Semantics For the execution of an assignment_statement with one or more target_names appearing in its expression, the /variable_/name V of the assignment statement is evaluated first to determine the object denoted by V, and then the expression of the assignment_statement is evaluated with the evaluation of each target_name yielding a constant view of the object denoted by V. The remainder of the execution of the assignment_statement is as given in subclause 5.2. !discussion We are replacing the old equivalence which was based on an implicit procedure, with an explicit dynamic semantics defining what it means to evaluate a target_name. *************************************************************** From: Randy Brukardt Sent: Thursday, March 7, 2019 9:44 PM > Replace RM 5.2.1 (5/5) with: > > Dynamic Semantics > > For the execution of an assignment_statement with one or more > target_names appearing in its expression, the /variable_/name V of the > assignment statement is evaluated first to determine the object > denoted by V, and then the expression of the assignment_statement is > evaluated with the evaluation of each target_name yielding a constant > view of the object denoted by V. The remainder of the execution of > the assignment_statement is as given in subclause 5.2. There's at least one problem with this: the Name Resolution Rules are marked Redundant because "the nominal subtype is determined by the equivalence rules given below". It's weird and usually not the case that we define Static Semantics in Dynamic Semantic rules; that matters for properties like static accessibility and aliasedness. All of the cases I can think of are rare corner cases, though. (Yes, @'Access is possible, but not very likely.) I'm not sure about the anti-order-dependence rules, though, and particularly "known to denote the same object" and it's cousin. These depend on "statically denote", so one has to ask if '@' statically denotes anything. Maybe it doesn't matter enough, as those rules aren't expected to catch everything. I think we also want at least an AARM note about the erroneousness that can occur if the discriminant governing the target is changed; it's not at all obvious that such things can happen here. Although really that a problem with assignment statements as a whole -- they truly need such a note. (A cross-reference to 3.7.2(4) would be a big help, as it seems impossible to find that rule when it comes up in discussion. I would *never* have looked in 3.7.2, as the title of the clause says that it defines some attributes.) *************************************************************** From: Randy Brukardt Sent: Thursday, March 7, 2019 10:16 PM > I'm not sure about the anti-order-dependence rules, though, and > particularly "known to denote the same object" and it's cousin. These > depend on "statically denote", so one has to ask if '@' statically > denotes anything. > Maybe it doesn't matter enough, as those rules aren't expected to > catch everything. To expand on this a bit. The rule in question is 6.4.1(6.6/3): * both names statically denote the same stand-alone object or parameter; or This is clearly False for "@", at least as it stands: it doesn't statically denote anything (it can't do that in general in any case). Skimming the rest of it, it seems we were trying to avoid anything dynamic in the names, so just allowing identical names to match wouldn't work in every case (think function call), so this would need a complex definition to trigger. So my example from yesterday: Targ := @.F.all + Func_with_In_Out (@.F.all); is legal using @ as defined in your AI, but illegal as defined in with Steve's anonymous procedure (or even with a renames sans Legality, there's special rules for that case) and definitely if one wrote it without using @: Targ := Targ.F.all + Func_with_In_Out (Targ.F.all); One could argue that this isn't particularly important as the anti-order-dependence rules aren't intended to be complete anyway, but it seems bad that introducing a short-hand makes this particular case legal when it otherwise would not be as it was judged to be too non-portable to allow. ***************************************************************