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

eliminating implicit conversions to/from Completion Records #497

Closed
jmdyck opened this issue Mar 26, 2016 · 6 comments · Fixed by #2547
Closed

eliminating implicit conversions to/from Completion Records #497

jmdyck opened this issue Mar 26, 2016 · 6 comments · Fixed by #2547
Labels
completion records Relates to completion records, and ? / ! notation.

Comments

@jmdyck
Copy link
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 mentioned this issue Mar 26, 2016
@domenic
Copy link
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
Copy link
Collaborator Author

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
Copy link
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?

@jmdyck
Copy link
Collaborator Author

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
Copy link
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.

@jmdyck
Copy link
Collaborator Author

jmdyck commented May 12, 2019

@claudepache:

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,

Are you talking about notation for constructing or deconstructing?

  • For constructing, AbruptCompletion { ... } vs PropertyDescriptor { ... } seem pretty clearly differentiated.
  • For deconstructing, I agree that (say) _ac_.[[Value]] vs _pd_.[[Value]] are similar, but I don't think that the way to differentiate them is by introducing a different notation for abrupt completions. Rather, we can differentiate them by choosing alias names that clearly convey the nature of the value they're bound to.

that emphasises their unique behaviour in algorithm flow.

Note that there's already lots of notation that emphasizes this:

  • Throw a *FooError* exception
  • ReturnIfAbrupt(...)
  • ? / !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
completion records Relates to completion records, and ? / ! notation.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants