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
83 changes: 57 additions & 26 deletions spec.html
Original file line number Diff line number Diff line change
Expand Up @@ -787,68 +787,98 @@ <h1>Throw an Exception</h1>

<emu-clause id="sec-returnifabrupt" aoid="ReturnIfAbrupt">
<h1>ReturnIfAbrupt</h1>
<p>Algorithms steps that say or are otherwise equivalent to:</p>
<p>An algorithm step that says:</p>
<emu-alg>
1. ReturnIfAbrupt(_argument_).
1. *[before]* ReturnIfAbrupt(_argument_) *[after]*
</emu-alg>
<p>mean the same thing as:</p>
<p>is equivalent to the sequence of steps:</p>
<emu-alg>
1. If _argument_ is an abrupt completion, return _argument_.
1. Else if _argument_ is a Completion Record, set _argument_ to _argument_.[[Value]].
michaelficarra marked this conversation as resolved.
Show resolved Hide resolved
1. *[before]* _argument_ *[after]*
</emu-alg>
<p>Algorithms steps that say or are otherwise equivalent to:</p>
<p>where</p>
<ul>
<li>*[before]*, if present, is any algorithm text that does not contain ReturnIfAbrupt.
<li>*[after]*, if present, is any algorithm text.
<li>_argument_ is any alias.
michaelficarra marked this conversation as resolved.
Show resolved Hide resolved
</ul>

<p>An algorithm step that says:</p>
<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).

</emu-alg>
<p>mean the same thing as:</p>
<p>is equivalent to the sequence of steps:</p>
<emu-alg>
1. Let _hygienicTemp_ be AbstractOperation().
1. Let _hygienicTemp_ be AbstractOperation(*[arguments]*).
1. If _hygienicTemp_ is an abrupt completion, return _hygienicTemp_.
1. Else if _hygienicTemp_ is a Completion Record, set _hygienicTemp_ to _hygienicTemp_.[[Value]].
1. *[before]* _hygienicTemp_ *[after]*
</emu-alg>
<p>Where _hygienicTemp_ is ephemeral and visible only in the steps pertaining to ReturnIfAbrupt.</p>
<p>Algorithms steps that say or are otherwise equivalent to:</p>
<p>where</p>
<ul>
<li>*[before]*, if present, is any algorithm text that does not contain ReturnIfAbrupt.
michaelficarra marked this conversation as resolved.
Show resolved Hide resolved
<li>*[after]*, if present, is any algorithm text.
<li>*[arguments]*, if present, is any algorithm text that provides an argument list to AbstractOperation.
<li>AbstractOperation is any abstract operation reference, regardless of the notation used to refer to it.
<li>_hygienicTemp_ is ephemeral and visible only in the steps pertaining to ReturnIfAbrupt.
</ul>

<p>For example, an algorithm step that says:</p>
<emu-alg>
1. Let _result_ be AbstractOperation(ReturnIfAbrupt(_argument_)).
1. Let _result_ be _someValue_ if ReturnIfAbrupt(_someValue_.OperationName(_firstArgument_, _secondArgument_)) is *true*, and _someOtherValue_ otherwise.
michaelficarra marked this conversation as resolved.
Show resolved Hide resolved
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.

</emu-alg>
<p>mean the same thing as:</p>
<p>is equivalent to the sequence of steps:</p>
<emu-alg>
1. If _argument_ is an abrupt completion, return _argument_.
1. If _argument_ is a Completion Record, set _argument_ to _argument_.[[Value]].
1. Let _result_ be AbstractOperation(_argument_).
1. Let _hygienicTemp_ be _someValue_.OperationName(_firstArgument_, _secondArgument_).
1. If _hygienicTemp_ is an abrupt completion, return _hygienicTemp_.
1. Else if _hygienicTemp_ is a Completion Record, set _hygienicTemp_ to _hygienicTemp_.[[Value]].
1. Let _result_ be _someValue_ if _hygienicTemp_ is *true*, and _someOtherValue_ otherwise.
michaelficarra marked this conversation as resolved.
Show resolved Hide resolved
</emu-alg>

<p>Note that the resulting steps of ReturnIfAbrupt expansion may themselves contain ReturnIfAbrupt. In these cases, expansion can be applied to the resulting steps until the steps no longer contain ReturnIfAbrupt.</p>
</emu-clause>

<emu-clause id="sec-returnifabrupt-shorthands">
<h1>ReturnIfAbrupt Shorthands</h1>
<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().
</emu-alg>
<p>is equivalent to the following step:</p>
<p>is equivalent to</p>
<emu-alg>
1. ReturnIfAbrupt(OperationName()).
</emu-alg>
michaelficarra marked this conversation as resolved.
Show resolved Hide resolved
<p>Similarly, for method application style, the step:</p>
<p>wherever it appears. Similarly, prefix `?` may be used to apply the ReturnIfAbrupt expansion to the result of applying a syntax-directed operation. For example,</p>
<emu-alg>
1. ? _someValue_.OperationName().
1. Let _result_ be ? SyntaxDirectedOperation of |NonTerminal|.
</emu-alg>
<p>is equivalent to:</p>
<p>is equivalent to the sequence of steps:</p>
<emu-alg>
1. ReturnIfAbrupt(_someValue_.OperationName()).
1. Let _result_ be SyntaxDirectedOperation of |NonTerminal|.
michaelficarra marked this conversation as resolved.
Show resolved Hide resolved
1. ReturnIfAbrupt(_result_).
</emu-alg>
<p>Similarly, prefix `!` is used to indicate that the following invocation of an abstract or syntax-directed operation will never return an abrupt completion and that the resulting Completion Record's [[Value]] field should be used in place of the return value of the operation. For example, the step:</p>

<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().
</emu-alg>
<p>is equivalent to the following steps:</p>
<p>is equivalent to the sequence of steps:</p>
<emu-alg>
1. Let _val_ be OperationName().
1. Assert: _val_ is never an abrupt completion.
1. If _val_ is a Completion Record, set _val_ to _val_.[[Value]].
</emu-alg>
<p>Syntax-directed operations for runtime semantics make use of this shorthand by placing `!` or `?` before the invocation of the operation:</p>
<p>Similarly, syntax-directed operations may make use of this shorthand by placing `!` before the invocation of the operation:</p>
<emu-alg>
1. Perform ! SyntaxDirectedOperation of |NonTerminal|.
1. Let _result_ be ! SyntaxDirectedOperation of |NonTerminal|.
</emu-alg>
<p>is equivalent to the sequence of steps:</p>
<emu-alg>
1. Let _result_ be SyntaxDirectedOperation of |NonTerminal|.
1. Assert: _result_ is never an abrupt completion.
1. If _result_ is a Completion Record, set _result_ to _result_.[[Value]].
</emu-alg>
</emu-clause>
</emu-clause>
Expand Down Expand Up @@ -7411,7 +7441,8 @@ <h1>[[Construct]] ( _argumentsList_, _newTarget_ )</h1>
1. If Type(_result_.[[Value]]) is Object, return NormalCompletion(_result_.[[Value]]).
1. If _kind_ is `"base"`, return NormalCompletion(_thisArgument_).
1. If _result_.[[Value]] is not *undefined*, throw a *TypeError* exception.
1. Else, ReturnIfAbrupt(_result_).
1. Else,
1. ReturnIfAbrupt(_result_).
1. Return ? _envRec_.GetThisBinding().
</emu-alg>
</emu-clause>
Expand Down