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