loop unrolling and completion values in ES6
Alan Schmitt
alan.schmitt at polytechnique.org
Fri Apr 10 07:18:15 UTC 2015
Hello,
On 2015-04-09 17:01, Allen Wirfs-Brock <allen at wirfs-brock.com> writes:
>> On Apr 9, 2015, at 10:44 AM, Alan Schmitt <alan.schmitt at polytechnique.org> wrote:
>>
>> 1. Let sl be the result of evaluating StatementList.
>> 2. ReturnIfAbrupt(sl).
>> 3. Let s be the result of evaluating StatementListItem.
>> 4. If s.[[type]] is throw, return Completion(s).
>> 5. If s.[[value]] is empty, let V = sl.[[value]], otherwise let V = s.[[value]].
>> 6. Return Completion{[[type]]: s.[[type]], [[value]]: V, [[target]]: s.[[target]]}.
>>
>> The problem happens when the first statement of the body of the while
>> loop is a break: in that case the value from the previous iteration is
>> not carried over.
>
> I agree, each kind of loop needs to do its equivalent of step 5 above before
> checking for exit conditions, that is the opposite of what is currently
> specified.
Here is a proposal to solve this.
We define an abstract operation UpdateCompletion with two arguments,
a completion and a (possibly empty) value, such as:
1. Return UpdateCompletion(s, v).
Is a shorthand that is defined as follows:
1. If s.[[type]] is throw or if s.[[value]] is not empty, return
Completion(s).
2. Return Completion{[[type]]:s.[[type]],[[value]]:v,[[target]]:s.[[target]]}.
We next update the spec:
- 13.1.13: replace steps 4 to 6 with
4. Return UpdateCompletion(s,sl.[[value]]).
This does not change the behavior.
- 13.6.1.6: replace step 2.b with
b. If LoopContinues(stmt, labelSet) is false, return UpdateCompletion(stmt,V).
This changes the behavior: completion values from previous iterations
are patched in the abrupt completion.
- 13.6.2.6: replace step 2.f with
f. If LoopContinues(stmt, labelSet) is false, return UpdateCompletion(stmt,V).
Same change.
- 13.6.3.8: replace step 4.c with
c. If LoopContinues(result, labelSet) is false, return UpdateCompletion(result,V).
Same change.
I'm much less confident about 13.6.4.13 (evaluation of ForIn/Of).
I would replace step 5.n with:
n. If LoopContinues(status,labelSet) is false then
i. let status = UpdateCompletion(status,V).
ii. Return IteratorClose(iterator,status).
This would ensure that if the "return" method of the iterator is
undefined or if it does not throw, and if we get out of the loop through
a break at the beginning of the loop body, then the last value computed
is in the completion record.
Regarding Switch, I think we can make the following changes:
- 13.11.9, both evaluations. Replace 4.b.iii with
iii. If R is an abrupt completion, return UpdateCompletion(R,V).
In the second evaluation (CaseBlock : { CaseClausesopt DefaultClause
CaseClausesopt }), also replace 7.a.ii.3 with
3. If R is an abrupt completion, return UpdateCompletion(R,V).
and 11 with
11. If R is an abrupt completion, return UpdateCompletion(R,V).
and 12.c with
c. If R is an abrupt completion, return UpdateCompletion(R,V).
This does not change the semantics, assuming that throw completion
records never contain the empty value. I think it is the case:
- 6.2.2.3 defines the generic completion for throwing exceptions, it
creates an object for the value,
- 13.13.1 is the throw statement, where the value is the result of the
evaluation of the expression … this should never be empty, shouldn't it?
- 23.1.1.1 (Map) creates an object for the value,
- 23.3.1.1 (WeakMap) creates an object for the value,
- 25.3.1.4 (Generator.prototype.throw) uses the exception passed as
argument as value,
- 25.4.2.1 (PromiseReactionJob) uses its argument as value.
Best,
Alan
--
OpenPGP Key ID : 040D0A3B4ED2E5C7
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 494 bytes
Desc: not available
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20150410/344477ce/attachment.sig>
More information about the es-discuss
mailing list