Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

change how ReturnIfAbrupt and its shorthands are specified #1573

Draft
wants to merge 11 commits into
base: main
Choose a base branch
from

Conversation

michaelficarra
Copy link
Member

@michaelficarra michaelficarra commented Jun 7, 2019

In #1570, we discussed how the way ReturnIfAbrupt and its shorthands are specified is unclear. I've made it clear that the ReturnIfAbrupt equivalence is on sequences of algorithm steps and the shorthand is a simple replacement in any context.

I've updated the ! shorthand in this PR as well, but in #1572 I give the option that we remove it, so we should resolve that first.

I recommend reading the current and proposed spec text separately to review. The diff will not be very helpful.

This will obsolete #1570.

@ljharb ljharb requested review from zenparsing and a team June 7, 2019 05:48
@michaelficarra
Copy link
Member Author

@ljharb I've moved the ! shorthand up to the "Implicit Completion Values" section for now while we decide its fate in #1572.

spec.html Show resolved Hide resolved
spec.html Show resolved Hide resolved
spec.html Show resolved Hide resolved
spec.html Show resolved Hide resolved
spec.html Show resolved Hide resolved
<emu-alg>
1. ReturnIfAbrupt(AbstractOperation()).
1. *[before]* ReturnIfAbrupt(AbstractOperation(*[arguments]*)) *[after]*
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than having 2 definitions, discriminated by the form of the argument, you could have one definition with a generalized argument.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since it's a structural rewrite, I'd like to keep it as simple as I can. Though one could argue that 1 rewrite rule is simpler overall than 2 individually simpler rewrite rules. I'll leave that one up to @tc39/ecma262-editors.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

1 seems probably simpler, but totes fine to do that in a followup.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've reduced the ReturnIfAbrupt definition to a single macro expansion, though it now has the peculiarity that, when used on an alias, as in ReturnIfAbrupt(_someAlias_), we are left with a step at the end that just references the alias. I think that's probably fine, but it may not be clear to everyone that that is meant to be a no-op. Let me know if you want me to switch it back to 2 expansions, I'm not tied to a particular choice.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this as a single expansion. I think the "step at the end that just references the alias" thing is unlikely to trip up readers, but if we're worried, we could say "the last line is omitted if *[before]* is not present" (or "is empty" or whatever).

spec.html Outdated

<p>Invocations of abstract operations may be prefixed by `!` to indicate that the result will never be an abrupt completion and that the resulting Completion Record's [[Value]] field should be used in place of the return value of the operation.</p>
<emu-alg>
1. Let _val_ be ! OperationName().
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As in the status quo, this is an illustrative example, not a real definition. You should maybe give it a proper definition as with 'ReturnIfAbupt'.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since the ! shorthand has no effect on the evaluation, I think it's a little less important to be as rigorous as we are with ReturnIfAbrupt expansion. If anything, the ? shorthand would deserve that level of rigour. I would do it for ? if the editors think that would help.

spec.html Outdated Show resolved Hide resolved
@michaelficarra
Copy link
Member Author

@jmdyck I've addressed your comments and left some responses. Please do another review.

spec.html Show resolved Hide resolved
spec.html Show resolved Hide resolved
@michaelficarra
Copy link
Member Author

Okay @jmdyck @ljharb ready for another round of reviews.

<p>Invocations of abstract operations and syntax-directed operations that are prefixed by `?` indicate that ReturnIfAbrupt should be applied to the resulting Completion Record. For example, the step:</p>
<h1>Shorthands Relating to Completion Records</h1>

<p>Invocations of abstract operations may be prefixed by `?` as shorthand for applying the ReturnIfAbrupt expansion.</p>
<emu-alg>
1. ? OperationName().
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not sure if we need to call out Perform (ie, Perform ? Op() or Perform ! Op()), or if that's a topic for a different PR.

@ljharb ljharb added the completion records Relates to completion records, and ? / ! notation. label Oct 4, 2019
@michaelficarra
Copy link
Member Author

A potential issue with this change as-written: multiple ReturnIfAbrupt are permitted within a single algorithm step, but are always evaluated right-to-left. This works fine for instances like

... ?A( ?B( ?C() ) ) ...

which I had in mind when writing it, but causes undesirable ordering for instances like

... ?A( ?B(), ?C() ) ...

These both would evaluate C, then B, then A. I'm not sure how we'd go about writing a macro expansion that correctly orders the latter case. Is it necessary to support those?

@devsnek
Copy link
Member

devsnek commented Nov 14, 2019

... ?A( ?B(), ?C() ) ...

At that point you should probably be using multiple lines just for the sake of clarity.

@michaelficarra
Copy link
Member Author

Okay, then to be clear @devsnek, you think it would be okay forbidding that usage? If so, I should add a non-normative note to spec/proposal authors that describes this potentially erroneous usage.

@jmdyck
Copy link
Collaborator

jmdyck commented Nov 14, 2019

A potential issue with this change as-written: multiple ReturnIfAbrupt are permitted within a single algorithm step, but are always evaluated right-to-left. This works fine for instances like

... ?A( ?B( ?C() ) ) ...

which I had in mind when writing it, but causes undesirable ordering for instances like

... ?A( ?B(), ?C() ) ...

These both would evaluate C, then B, then A. I'm not sure how we'd go about writing a macro expansion that correctly orders the latter case.

Tangent:

I'm guessing you mean that the correct ordering for the latter case is B then C then A, but I don't think the spec actually says that. 5.2.1 Abstract Operations says:

Abstract operations are typically referenced using a functional application style such as OperationName(arg1, arg2).

but it doesn't then go on to say anything about the order in which the args are 'evaluated'.

I'd be inclined to say that any case where the order is observable is a spec bug. (Detecting such bugs is another matter though.)

@devsnek
Copy link
Member

devsnek commented Nov 14, 2019

You can detect the order by making them both throw

@jmdyck
Copy link
Collaborator

jmdyck commented Nov 14, 2019

You can detect the order by making them both throw

I was talking about detecting (just by examining the spec) places where the order of 'evaluation' of operation arguments could be observed. I think you're saying that, once such a place has been identified, you can construct a test case that will reveal which order an implementation is using.

@michaelficarra michaelficarra added the editor call to be discussed in the next editor call label Mar 4, 2021
@michaelficarra
Copy link
Member Author

This is blocked until completion record reform work has been completed.

@michaelficarra michaelficarra removed the editor call to be discussed in the next editor call label Mar 31, 2021
@ljharb ljharb force-pushed the master branch 3 times, most recently from 3d0c24c to 7a79833 Compare June 29, 2021 02:21
@ljharb ljharb removed the request for review from zenparsing October 13, 2021 22:26
@michaelficarra michaelficarra marked this pull request as draft June 13, 2022 22:24
@bakkot
Copy link
Contributor

bakkot commented Aug 18, 2022

These both would evaluate C, then B, then A. I'm not sure how we'd go about writing a macro expansion that correctly orders the latter case. Is it necessary to support those?

My preference would be to define an evaluation order for spec steps more generally - not rigorously, just say something like "Evaluation of each algorithm step follows a left-to-right, inside-to-outside evaluation order, so that the step Let _x_ be A(B(), C()) + D(E()). evaluates B, then C, then A, then E, then D" or something like that.

And then in this macro you can say that if there are multiple occurrences of ReturnIfAbrupt within one step, they are expanded in evaluation order, with the first to be evaluated being expanded first.

@jugglinmike
Copy link
Contributor

@michaelficarra was gh-2547 the completion reform which blocked this work?

@michaelficarra
Copy link
Member Author

@jugglinmike Yes, this should be unblocked now.

@jugglinmike
Copy link
Contributor

Thanks, Michael! I can't commit to moving this along, but it helps to understand the status.

@michaelficarra
Copy link
Member Author

@jugglinmike That's okay, I plan on revisiting it soon(-ish). Let me know if you want to take it over, though. I don't remember what work it needs.

@bakkot
Copy link
Contributor

bakkot commented Jan 27, 2024

What if we just do away with ReturnIfAbrupt entirely, and instead just define ? directly? That's probably simpler, since it doesn't need to rebind any aliases. And after #3268 there's only 4 uses of ReturnIfAbrupt left, so getting rid of it is straightforward.

(In es2015 there were closer to 100, but we've been chipping away at them in #1571, #2744, etc.)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
completion records Relates to completion records, and ? / ! notation. editorial change
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants