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

eliminating implicit conversions to/from Completion Records #497

Open
jmdyck opened this Issue Mar 26, 2016 · 5 comments

Comments

Projects
None yet
5 participants
@jmdyck
Collaborator

jmdyck commented Mar 26, 2016

Recap:

Section 6.2.2.2 "Implicit Completion Values" says:

Unless it is otherwise obvious from the context, an algorithm statement that returns a value that is not a Completion Record, such as: Return "Infinity" means the same thing as: Return NormalCompletion("Infinity").

and

Any reference to a Completion Record value that is in a context that does not explicitly require a complete Completion Record value is equivalent to an explicit reference to the [[Value]] field of the Completion Record value unless the Completion Record is an abrupt completion.

That is, there are implicit conversions to and from Completion Records.

Reaction:

In #253 (comment), @rossberg-chromium said:

The spec should not be optimised for maximum brevity but for maximum clarity. I think the implicit conversion from completion records to their values is actively harmful in that regard.

And in #486 (comment), @bterlson said:

There is a rule in 5.2 [sic] that allows us to treat a completion record as if it were a value but it's something I'd like to get away from.

In #253 (comment), I agreed, and said:

I've thought of an approach that I think would eliminate most of these conversions. I'll raise it in another issue when I have some time.

This post outlines that approach. (I was hoping to submit a pull request, but now I'm not sure I'll have time in the near future.)


The basic idea is to do away with "normal" completion records.

That is, anywhere that an algorithm currently deals with a Completion Record whose [[Type]] is normal, instead just use whatever the [[Value]] of that record is. (You can ignore the [[Target]], it's always empty.)

Things that would disappear:

  • All of 6.2.2.2.
  • NormalCompletion()
  • Completion()
  • Steps of the form If val is Completion Record, let val be val.[[Value]] in the definition of ReturnIfAbrupt and "!".

Section 6.2.2, rather than defining "Completion Record", would define "AbruptCompletion Record".

For terminology, you could say something like: a "completion value" is either an "abrupt completion value" (i.e., an AbruptCompletion Record) or a "normal completion value" (i.e., empty or an ECMAScript language value).

The part of this approach that requires some work is to find all the algorithmic steps that currently deal with a Completion Record that might be a Normal Completion, and re-code them to deal with a 'completion value' that might be a 'normal completion value'. I'm guessing you could find all the places that might need to change by searching for [[Type]], [[Target]], and [[Value]], but that's just a guess.

I can volunteer to do the work, but as I say above, I'm not sure how soon I could deliver, so someone else might like to take it on.

@annevk annevk referenced this issue Mar 26, 2016

Open

!? usage #486

@domenic

This comment has been minimized.

Show comment
Hide comment
@domenic

domenic Mar 26, 2016

Member

Strong -1. Having abstract operations return sometimes-JS-values, sometimes-abrupt-completions is much worse than just having them always return a completion record. It seems the motivation here is brevity (omitting !), in direct contradiction to

The spec should not be optimised for maximum brevity but for maximum clarity.

Having completion records be uniformly used as the way of representing JS completions greatly improves the spec's readability. This proposal would destroy that.

The correct route for eliminating implicit conversions is simply to introduce !s or ?s as appropriate.

Member

domenic commented Mar 26, 2016

Strong -1. Having abstract operations return sometimes-JS-values, sometimes-abrupt-completions is much worse than just having them always return a completion record. It seems the motivation here is brevity (omitting !), in direct contradiction to

The spec should not be optimised for maximum brevity but for maximum clarity.

Having completion records be uniformly used as the way of representing JS completions greatly improves the spec's readability. This proposal would destroy that.

The correct route for eliminating implicit conversions is simply to introduce !s or ?s as appropriate.

@jmdyck

This comment has been minimized.

Show comment
Hide comment
@jmdyck

jmdyck Mar 27, 2016

Collaborator

Having abstract operations return sometimes-JS-values, sometimes-abrupt-completions is much worse than just having them always return a completion record.

Well, that's a valid opinion, but to my thinking, it's worse to have an abstract operation return sometimes-what-it-says, and sometimes-not-what-it-says.

It seems the motivation here is brevity (omitting !)

Not sure how you got that idea, I didn't say anything about omitting "!". As far as I can see, "!" wouldn't need to be omitted.

My motivation is not brevity, but clarity/transparency. That appears to be @rossberg-chromium's as well. I'm not sure what @bterlson's motivation is.

Collaborator

jmdyck commented Mar 27, 2016

Having abstract operations return sometimes-JS-values, sometimes-abrupt-completions is much worse than just having them always return a completion record.

Well, that's a valid opinion, but to my thinking, it's worse to have an abstract operation return sometimes-what-it-says, and sometimes-not-what-it-says.

It seems the motivation here is brevity (omitting !)

Not sure how you got that idea, I didn't say anything about omitting "!". As far as I can see, "!" wouldn't need to be omitted.

My motivation is not brevity, but clarity/transparency. That appears to be @rossberg-chromium's as well. I'm not sure what @bterlson's motivation is.

@bterlson

This comment has been minimized.

Show comment
Hide comment
@bterlson

bterlson Mar 29, 2016

Member

Well, that's a valid opinion, but to my thinking, it's worse to have an abstract operation return sometimes-what-it-says, and sometimes-not-what-it-says.

Can you elaborate on this case? I'm not sure which situation you're referring to.

Regardless, your approach seems to have the benefit of unifying the models of static semantics algorithms and normal algorithms (they're the same, except that static semantics will never result in an Abrupt Completion Record).

It would allow for omitting ! in cases where you know that the abstract operation will never result in an abrupt completion record, but we could simply say we must include !/? anyway.

I'm not sure I see where the big win here is though. Perhaps you can share more about your mental model?

Member

bterlson commented Mar 29, 2016

Well, that's a valid opinion, but to my thinking, it's worse to have an abstract operation return sometimes-what-it-says, and sometimes-not-what-it-says.

Can you elaborate on this case? I'm not sure which situation you're referring to.

Regardless, your approach seems to have the benefit of unifying the models of static semantics algorithms and normal algorithms (they're the same, except that static semantics will never result in an Abrupt Completion Record).

It would allow for omitting ! in cases where you know that the abstract operation will never result in an abrupt completion record, but we could simply say we must include !/? anyway.

I'm not sure I see where the big win here is though. Perhaps you can share more about your mental model?

@jmdyck

This comment has been minimized.

Show comment
Hide comment
@jmdyck

jmdyck Mar 30, 2016

Collaborator

... to my thinking, it's worse to have an abstract operation return sometimes-what-it-says, and sometimes-not-what-it-says.

Can you elaborate on this case? I'm not sure which situation you're referring to.

Just that if you see Return _foo_ in an algorithm, it looks like the algorithm returns whatever value is currently bound to _foo_, but that might or might not be the case:

  • If _foo_ is bound to a Completion Record, that is returned.
  • If _foo_ is bound to some other 'spec' value, that is returned (unless that changes).
  • If _foo_ is bound to an ECMAScript language value (or empty), what's returned isn't that value, but rather a normal Completion Record containing that value. Unless it's "otherwise obvious from the context" (whatever that means) that the value itself is returned.

The mental model I'd like to have is that algorithms mean what they say. If an algorithm step says it's doing something with (say) a Number (returning it, or passing it to an operation, or taking it from a parameter, or binding it to a metavariable), then I want to know that it's actually handling a Number, and not a Completion Record whose [[Value]] is a Number. (Or at least, I'd like there to be no impediment to my interpreting the step that way.)

And don't get me wrong, I'm not saying that the approach I proposed above is the only way to accomplish that, or even the best way, it's just what currently seems most sensible to me.

Collaborator

jmdyck commented Mar 30, 2016

... to my thinking, it's worse to have an abstract operation return sometimes-what-it-says, and sometimes-not-what-it-says.

Can you elaborate on this case? I'm not sure which situation you're referring to.

Just that if you see Return _foo_ in an algorithm, it looks like the algorithm returns whatever value is currently bound to _foo_, but that might or might not be the case:

  • If _foo_ is bound to a Completion Record, that is returned.
  • If _foo_ is bound to some other 'spec' value, that is returned (unless that changes).
  • If _foo_ is bound to an ECMAScript language value (or empty), what's returned isn't that value, but rather a normal Completion Record containing that value. Unless it's "otherwise obvious from the context" (whatever that means) that the value itself is returned.

The mental model I'd like to have is that algorithms mean what they say. If an algorithm step says it's doing something with (say) a Number (returning it, or passing it to an operation, or taking it from a parameter, or binding it to a metavariable), then I want to know that it's actually handling a Number, and not a Completion Record whose [[Value]] is a Number. (Or at least, I'd like there to be no impediment to my interpreting the step that way.)

And don't get me wrong, I'm not saying that the approach I proposed above is the only way to accomplish that, or even the best way, it's just what currently seems most sensible to me.

@claudepache

This comment has been minimized.

Show comment
Hide comment
@claudepache

claudepache Jul 22, 2016

Contributor

Currently, the spec uses some notations and wordings (like "ReturnIfAbrupt", "Throw an exception", "!", etc.) that strongly agrees with the mental model proposed in this issue; but it adds above that a sometimes implicit machinery to wrap and unwrap into completions "unless it is otherwise obvious from context" (even when it is not so obvious). So, +1 for me.

However, in order to differentiate more clearly between abrupt completions and non-completion Records (like Property Descriptor), I suggest to replace the proposed AbruptCompletion Record with an ad-hoc structure (just as we have for References) with a distinctive notation, that emphasises their unique behaviour in algorithm flow.

Contributor

claudepache commented Jul 22, 2016

Currently, the spec uses some notations and wordings (like "ReturnIfAbrupt", "Throw an exception", "!", etc.) that strongly agrees with the mental model proposed in this issue; but it adds above that a sometimes implicit machinery to wrap and unwrap into completions "unless it is otherwise obvious from context" (even when it is not so obvious). So, +1 for me.

However, in order to differentiate more clearly between abrupt completions and non-completion Records (like Property Descriptor), I suggest to replace the proposed AbruptCompletion Record with an ad-hoc structure (just as we have for References) with a distinctive notation, that emphasises their unique behaviour in algorithm flow.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment