Completion reform changes are still incomplete. I've tried to fill in the missing pieces, but I'm not sure whether or not I've covered everything (e.g. completion values for loops with break/continue).
Completion semantics in rev35:
https://gist.github.com/anba/2288c4501bf3799c44a1
Completion semantics with completion reform applied:
https://gist.github.com/anba/24438972880d30327480
Diff:
https://gist.github.com/anba/d1671fc7deff21a4ead9
I've also removed a few LoopContinues calls, because there are currently not needed and complicate things.
I which of the algorithms are the changes specifically covering cases that were missing?
I'm trying to avoid unnecessary churn and want to focus on things that are missing or buggy.
- Finally block completion values should be ignored (except for throw and return).
- CaseBlockEvaluation is a complete mess, e.g.
Completion value for this switch statement is empty:
`switch(1){ case 1: ; }`
Completion value for this switch statement is `undefined`:
`switch(1){ case 0: ; default: ; case 1: ; }`
- break with and without labels, e.g.
Completion value is empty:
`var i=0; L: do { if(++i==2)break L; i; } while (1);`
Completion value is `undefined`:
`var i=0; do { if(++i==2)break; i; } while (1);`
General question:
```
var i = 0;
while (true) {
if (++i == 2) break;
42;
}
```
What is the expected completion value for the while loop according to the completion reform - `42` or `undefined`? With the rev35 semantics it's `undefined`.
Unfortunately completion value semantics aren't really popular, so there is little to no interest to review this part of the spec. And
http://wiki.ecmascript.org/doku.php?id=harmony:completion_reform doesn't provide enough information to say how things should work. :-(
This is a less invasive patch to handle finally-blocks and labeled statements, remove dead steps with LoopContinues and CaseSelectorEvaluation, and fix an empty completion value issue in CaseBlockEvaluation:
https://gist.github.com/anba/03e1aa285ca8808d149d
Those changes don't handle loops and empty completions values from break/continue.
(In reply to André Bargull from comment #4)
>
> General question:
> ```
> var i = 0;
> while (true) {
> if (++i == 2) break;
> 42;
> }
> ```
>
> What is the expected completion value for the while loop according to the
> completion reform - `42` or `undefined`? With the rev35 semantics it's
> `undefined`.
My call is undefined: Because we have started evaluation of the statement block, the completion value of the previous evaluation is irrelevant. However, at the point of the break, the completion value of the statement list is empty. Because the while statement under completion reform never produces an empty completion value, the empty is transformed into undefined.
(In reply to André Bargull from comment #4)
> - Finally block completion values should be ignored (except for throw and
> return).
why do you think this should be the case. consider
while (true)
try {1} finally{2; break};
// we reach here because the finally took over exit control
// completion value: 1 or 2?
Why should the completion value be 1? By executing a break (or throw/return/continue) the finally block has taken control completely away from the try block. why should that transfer of the locus of control also imply a transfer of the responsibility of providing the return value?
(In reply to Allen Wirfs-Brock from comment #8)
> (In reply to André Bargull from comment #4)
> > - Finally block completion values should be ignored (except for throw and
> > return).
>
> why do you think this should be the case. consider
>
"Additional changes" from http://wiki.ecmascript.org/doku.php?id=harmony:completion_reform describes this semantics.
(In reply to Allen Wirfs-Brock from comment #7)
> (In reply to André Bargull from comment #4)
>
> >
> > General question:
> > ```
> > var i = 0;
> > while (true) {
> > if (++i == 2) break;
> > 42;
> > }
> > ```
> >
> > What is the expected completion value for the while loop according to the
> > completion reform - `42` or `undefined`? With the rev35 semantics it's
> > `undefined`.
>
> My call is undefined: Because we have started evaluation of the statement
> block, the completion value of the previous evaluation is irrelevant.
> However, at the point of the break, the completion value of the statement
> list is empty. Because the while statement under completion reform never
> produces an empty completion value, the empty is transformed into undefined.
```
var i = 0;
while (i < 2) {
if (++i == 2) continue;
42;
}
```
And here? Currently it's `42`.
(In reply to André Bargull from comment #9)
> (In reply to Allen Wirfs-Brock from comment #8)
> > (In reply to André Bargull from comment #4)
> > > - Finally block completion values should be ignored (except for throw and
> > > return).
> >
> > why do you think this should be the case. consider
> >
>
> "Additional changes" from
> http://wiki.ecmascript.org/doku.php?id=harmony:completion_reform describes
> this semantics.
Yes, but that and the es-scuss message it references only talks about normal completion of the finally block. I don't see anything from (the very limited discussion) or from legacy ES that suggests that the completion value of a break/continue in a finally block should be ignored.
From the perspective of the try statement such a break/continue is an abnormal exit just like return or throw.
(In reply to Allen Wirfs-Brock from comment #11)
> Yes, but that and the es-scuss message it references only talks about normal
> completion of the finally block. I don't see anything from (the very limited
> discussion) or from legacy ES that suggests that the completion value of a
> break/continue in a finally block should be ignored.
(Unfortunately) the es-discuss message doesn't event get into the details of normal and abrupt completions, so it's more or less open for interpretation what he meant when he said "without changing the completion value of the expression". The same goes for the initial revision of http://wiki.ecmascript.org/doku.php?id=harmony:completion_reform&rev=1321054410.
I interpreted the sentence:
> should make the completion of a try-finally be the result of the try block
that completion values from break/continue abrupt completions should be dropped.
If completion values from break/continue abrupt completions are not dropped, implementations will need to store the try-block's completion value somehow in case the finally block returns with a normal completion. Correct?
Example:
---
L: try {
1;
} finally {
2;
if (cond) break L;
}
---
If [cond = false], the completion value is `1`.
If [cond = true], the completion value is `2`.
(In reply to André Bargull from comment #12)
...
>
> If completion values from break/continue abrupt completions are not dropped,
> implementations will need to store the try-block's completion value somehow
> in case the finally block returns with a normal completion. Correct?
>
> Example:
> ---
> L: try {
> 1;
> } finally {
> 2;
> if (cond) break L;
> }
> ---
>
> If [cond = false], the completion value is `1`.
> If [cond = true], the completion value is `2`.
Already have to do that for return and throw:
try {
return 1}
} finally {
if (cond) return 2
}
(In reply to Allen Wirfs-Brock from comment #13)
> Already have to do that for return and throw:
Yes, in function contexts. I don't know how engines (other than my own) implement script completion values. Therefore I wanted to make it clear that completion values need to be stored temporarily, so other implementors are aware of this change. It may not be a change within the spec, but definitely for implementations:
https://bugzilla.mozilla.org/show_bug.cgi?id=819125
https://code.google.com/p/v8/issues/detail?id=2446
(In reply to André Bargull from comment #14)
> (In reply to Allen Wirfs-Brock from comment #13)
> > Already have to do that for return and throw:
>
> Yes, in function contexts. I don't know how engines (other than my own)
> implement script completion values. Therefore I wanted to make it clear that
> completion values need to be stored temporarily, so other implementors are
> aware of this change. It may not be a change within the spec, but definitely
> for implementations:
>
> https://bugzilla.mozilla.org/show_bug.cgi?id=819125
> https://code.google.com/p/v8/issues/detail?id=2446
yes, they're all buggy according to ES specs going back to ES3 when try-catch was added.
It probably doesn't make much difference today, but if we add do expressions in ES7 it will become more easily observable so now might be a good time for implementations to start thinking about fixing it.
fixed in rev36 editor's draft
in rev36