-
Notifications
You must be signed in to change notification settings - Fork 1.3k
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
Sorting out completion records #1796
Comments
(cc @jmdyck, who I know has some interest in this topic) |
I am willing to help with this. Our work on JSRef and JSExplain are written in OCaml, so they are typed and we've had to deal with this issue. Regarding point 4 ("Ensure all callers of an abstract operation consume the returned value properly"), do you consider that monadic operators ( |
Yes, i think so. |
@brabalan That'd be great! Do you happen to have a link to your standard library definitions, and/or a list of places where the inconsistent typing in ECMA-262 has required workarounds?
Yup. Though I intend (as part of step 4) to change the parts of their current definitions which say "if argument is a Completion Record, set argument to argument.[[Value]]" to just "set argument to argument.[[Value]]". |
We define the type for completion records here https://gitlab.inria.fr/star-explain/jsexplain/blob/master/jsref/JsSyntax.ml#L619 (we already cheat because we allow references, we plan to change that). For "completion records" that contain other things, we use https://gitlab.inria.fr/star-explain/jsexplain/blob/master/jsref/JsSyntax.ml#L683. In https://gitlab.inria.fr/star-explain/jsexplain/blob/master/jsref/JsInterpreter.ml, anything that is bound with a |
You might also be able to glean some inconsistencies from usage of |
Maybe not quite any type of value: in particular, I suspect it would be confusing to allow a completion record in the [[Value]] field of a completion record.
Pertinent to that, over in PR #1907, @syg said that, post-reform:
Note that there's a 4th possibility: "Op can have effects on evaluation control flow. This particular callsite can return an abrupt completion, but it is not propagated immediately." (It's uncommon, but it certainly happens.) In such cases, you can't use |
It would certainly be confusing to put one there, but I'm not sure it's worth explicitly prohibiting it rather than just not doing that. Might be; I'll wordsmith both and see which I prefer.
To my mind the most important thing is that it does not immediately affect control flow, and there's no other implicit magic happening on its return value, so you can understand what's going on in the algorithm just be reading what it says. |
The thing is, if the spec simply doesn't do that, it isn't obvious to the reader that it doesn't (and won't ever). So I think it's worth saying.
Yeah, that's okay with me. But then be sure not to describe the meaning of |
There's nothing wrong with describing it in the way @syg did. The call of the AO doesn't affect the control flow. It doesn't matter if the AO returns a completion record and then somewhere else that completion record is acted upon in a way that affects control flow. That's a first-class value like any other and it is not strange. |
I'm fine with all of that. But when syg said "Op can have effects on evaluation control flow", that's not talking about a particular callsite, that's talking about all possible calls to Op. That is, Op can, under some circumstances, return an abrupt completion. (It has to mean that, otherwise you can't make sense of his description for |
I'm going to step away from @syg's quote, as I think the phrase "can affect control flow" may be muddying the waters. Instead, I gather that after the reform proposed by this issue, the following case analysis would hold:
Given this, my points boil down to:
|
No thanks. It's just another value at this point. |
Thinking some more about this, I'm inclined to do something like "1. Let foo be the Completion Record returned by Something()". We don't normally emphasize return types like this, but I think it's probably worth doing so in these unusual cases. |
Plans from the editor call:
|
Note that it may prove to be too noisy to wrap up AO return values in NormalCompletion, so we might end up wanting to do something else. |
For 4, can the assertion be terse, like ? and !, rather than an entire prose step? |
We already have an AO which does exactly this assertion: I don't want to be much more terse than this given how rare it is for callers of Completion Record-returning AOs to need to handle the Completion Record explicitly rather than via |
In that case, the AO call site could be wrapped in Completion(), and that would be a sufficient assertion? |
Yes. |
So as far as my earlier case analysis is concerned, am I right in thinking that the only update is that in 2.b.ii, the invocation looks like |
Yup. |
One possibility would be to allow implicit wrapping in Another possibility would be to do away with normal completions (as in #497), so that if an algorithm says (e.g.) |
Could we continue the above discussion? |
I am not in favor of the proposal to do away with NormalCompletion entirely. (This is mostly on aesthetic grounds - I really don't like untagged unions - but also because it makes it harder to clearly communicate to the reader when code is working with completions, because there's no obvious way to write the Regarding implicit wrapping: I'm personally fine with it, but I think @michaelficarra expressed more reluctance. @michaelficarra thoughts? |
But the spec is full of untagged unions. I count roughly 170 parameters that accept values of multiple types, and about 230 algorithms that can return values of multiple types (not even counting abrupt returns). E.g., InitializeBoundName's (From another point of view, all unions are tagged because all values are tagged.)
In a world without normal completions, we could analogously have |
Eh... with relatively rare exceptions (particularly for
By "tagged union" I mean specifically that it is impossible to consume the value without unwrapping it, so it is totally unambiguous to a reader whether a given line has accidentally neglected to consider some case of the union or has intentionally done so. So no, most unions in the spec are not tagged. Specifically, if we allowed the "normal" and "abrupt" cases to be untagged, then someone reading
can't tell if SomeAO happens not to return an abrupt completion in this case and the author of these lines is relying on that, or if the author has simply failed to consider the case where it returns an abrupt completion, or it never returns an abrupt completion. We could be disciplined in following an editorial convention of always using (Yes, there are other kinds of returned values in the spec which have the same problem. In most cases the unions are fairly bespoke, such that describing the wrapping and unwrapping would add a lot of mental overhead. This particular union is very common, so we can reasonably introduce shorthands to reduce that overhead, and you only have to learn what it means once and can then understand its use in many many places.)
Assertions should constrain the possible set of values. In the scheme you propose, every value is either a normal value or an abrupt completion. So there is nowhere you couldn't put such an assertion. We could be disciplined in only using |
I would like to get completion records sorted out. My current plan is to
I'm going to prepare a PR which does this as soon as I have time.
The text was updated successfully, but these errors were encountered: