Join GitHub today
GitHub is home to over 28 million developers working together to host and review code, manage projects, and build software together.
Sign upNotate abstract ops that can and cannot throw #253
Comments
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
ljharb
Dec 15, 2015
Member
What about the case where the result of AbstractOp is not needed? That's usually the cases where "Perform" appears. Having a useless _result_ doesn't seem ideal. Do you have an alternative suggestion for an abstract op that solely causes side effects (some of which can throw, and some of which can't)?
In general I love this idea - being explicit about what can throw and what can't seems like an overall improvement.
|
What about the case where the result of In general I love this idea - being explicit about what can throw and what can't seems like an overall improvement. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
domenic
Dec 15, 2015
Member
Do you have an alternative suggestion for an abstract op that solely causes side effects (some of which can throw, and some of which can't)?
1. ? AbstractOp() to bubble errors, or 1. ! AbstractOp() to assert it never errors. You could introduce the "perform" verb for that but I'd like it to be defined this time.
|
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
ljharb
Dec 15, 2015
Member
Sounds good - I like having an explicit "this is for side effects" mechanism like "Perform".
|
Sounds good - I like having an explicit "this is for side effects" mechanism like "Perform". |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
jmdyck
Dec 15, 2015
Collaborator
Here's what I said when this was raised in the ecmarkup repo:
Presumably "Perform AbstractOp(x)" implies not just that AbstractOp doesn't throw, but also that it doesn't return anything useful (via normal completion). (Or at least, that these things are known to be true for the particular arguments being passed.)
I think it would be ideal if Ecmarkup supported this, e.g.
<h1 aoid="..." nothrow>...</h1>.
To generalize your suggestion, I think it would be useful (though even more work) if every operation had a "header" that systematically listed/described the operation's inputs (parameters) and outputs (returns). (Currently, preambles give some of this info, but not consistently or completely.) E.g., outputs/returns might say something like:
normal returns: Boolean
abrupt returns: TypeError
So the throw/nothrow distinction would be captured by whether any abrupt returns are listed.
|
Here's what I said when this was raised in the ecmarkup repo: Presumably "Perform AbstractOp(x)" implies not just that AbstractOp doesn't throw, but also that it doesn't return anything useful (via normal completion). (Or at least, that these things are known to be true for the particular arguments being passed.)
To generalize your suggestion, I think it would be useful (though even more work) if every operation had a "header" that systematically listed/described the operation's inputs (parameters) and outputs (returns). (Currently, preambles give some of this info, but not consistently or completely.) E.g., outputs/returns might say something like:
So the throw/nothrow distinction would be captured by whether any abrupt returns are listed. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
bterlson
Dec 15, 2015
Member
@jmdyck: that would be amazing, but much work... I think we can probably get there eventually by going down the path of incrementally adding !.
Note that Perform X() is not about implying that AbstractOp doesn't throw (note further the many instances of Perform ? Op()). It's simply ecmaspeak for "the result of X()" where x doesn't have a useful result. In other words, with bang, if an abstract op doesn't have a useful result, we'd want Perform ! Op().
I fully support ! as a short-hand for "Assert: previous thing is not an abrupt completion". We can probably just start the incremental addition by doing a similar regexp replace as we did to kick off the ? conversion.
|
@jmdyck: that would be amazing, but much work... I think we can probably get there eventually by going down the path of incrementally adding !. Note that I fully support ! as a short-hand for "Assert: previous thing is not an abrupt completion". We can probably just start the incremental addition by doing a similar regexp replace as we did to kick off the ? conversion. |
bterlson
referenced this issue
Dec 15, 2015
Closed
Editorial: Add new convention for abstract ops that don't throw #256
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
zenparsing
Dec 16, 2015
Contributor
I'm a little worried about extending the ECMASpeak programming language too fast. The RIA shorthand was a good buy in terms of readability/writability, but I'm not so sure about "!".
|
I'm a little worried about extending the ECMASpeak programming language too fast. The RIA shorthand was a good buy in terms of readability/writability, but I'm not so sure about "!". |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
jmdyck
Dec 16, 2015
Collaborator
@jmdyck: that would be amazing, but much work...
I'm prepared to do the work if we can agree on a "header" syntax.
I'm prepared to do the work if we can agree on a "header" syntax. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
domenic
Dec 16, 2015
Member
I'm a fan of !. It fixes two important problems with the current spec:
- There are many cases where a completion value v is used, but v.[[value]] is expected. For example, CreateDataProperty(array, ToString(n), e). ToString returns a completion value, but CreateDataProperty does not accept completion values as its second argument. This is just a bug in the current spec really. (Or if you prefer, an intentional type mismatch for the sake of brevity.)
- There are several (39) places in the spec where we assert something is not an abrupt completion. This is a bit distracting, but is honestly probably something we should be doing more! It should be easy to say something is expected to never throw.
I am less of a fan of the header syntax, but some mock-up screenshots could possibly convince me.
|
I'm a fan of !. It fixes two important problems with the current spec:
I am less of a fan of the header syntax, but some mock-up screenshots could possibly convince me. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
anba
Dec 16, 2015
Contributor
ToString returns a completion value, but CreateDataProperty does not accept completion values as its second argument. This is just a bug in the current spec really. (Or if you prefer, an intentional type mismatch for the sake of brevity.)
No, it is a specified and documented feature of completion records to allow implicit access to the [[value]] field (cf. 6.2.2.2).
How about doing it the other way around: Explicitly state with ! when a caller needs to receive a completion record. I think that should be more ergonomic than adding ! after every infallible operation.
No, it is a specified and documented feature of completion records to allow implicit access to the [[value]] field (cf. 6.2.2.2). How about doing it the other way around: Explicitly state with |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
rossberg
Dec 16, 2015
Member
@anba, please no. 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. There are already too many hidden conventions going on in the spec (a criticism I keep hearing from fellow V8 implementers trying to make sense of it every other day).
|
@anba, please no. 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. There are already too many hidden conventions going on in the spec (a criticism I keep hearing from fellow V8 implementers trying to make sense of it every other day). |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
domenic
Dec 16, 2015
Member
No, it is a specified and documented feature of completion records to allow implicit access to the [[value]] field (cf. 6.2.2.2).
Yes, that is what I meant in the parenthetical.
Yes, that is what I meant in the parenthetical. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
jmdyck
Dec 16, 2015
Collaborator
I think the implicit conversion from completion records to their values is actively harmful in that regard.
I agree. (And also the reverse implicit conversion.)
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.
I agree. (And also the reverse implicit conversion.) 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 comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
allenwb
Dec 16, 2015
Member
I want to support the general position expressed by @rossberg-chromium above.
Maximizing clarity (and particularly for occasional readers should be among the highest priorities. Most readers of the spec. are not spending 8 hours a day emerged within it. More likely they are occasionally looking up some specific details. They may or may not have read the clause 5 conversions and even if they have they may not remember them what they read.
@domenic things like CreateDataProperty(array, ToString(n), e) is used in situations where n is known to have a value that will convert to a string, without error. Most typically this is an integer valued index variable of a algorithmic loop. I considered making the conversion from completion to value explicit but found that formulation to be less readable.
|
I want to support the general position expressed by @rossberg-chromium above. Maximizing clarity (and particularly for occasional readers should be among the highest priorities. Most readers of the spec. are not spending 8 hours a day emerged within it. More likely they are occasionally looking up some specific details. They may or may not have read the clause 5 conversions and even if they have they may not remember them what they read. @domenic things like CreateDataProperty(array, ToString(n), e) is used in situations where n is known to have a value that will convert to a string, without error. Most typically this is an integer valued index variable of a algorithmic loop. I considered making the conversion from completion to value explicit but found that formulation to be less readable. |
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
bterlson
Feb 18, 2016
Member
Going to close this issue as I believe we have satisfied the original request.
|
Going to close this issue as I believe we have satisfied the original request. |
bterlson
closed this
Feb 18, 2016
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
domenic
Feb 18, 2016
Member
I don't believe we have. The first bullet point is mostly implemented, but the overall request motivating it (as outlined in the subsequent ones) remains open.
|
I don't believe we have. The first bullet point is mostly implemented, but the overall request motivating it (as outlined in the subsequent ones) remains open. |
domenic
reopened this
Feb 18, 2016
This comment has been minimized.
Show comment
Hide comment
This comment has been minimized.
|
Oh I see, sorry about that. |
domenic commentedDec 15, 2015
In streams, which is heavily promise-based, there are a lot of abstract operations that cannot throw. The ES spec has these too, in smaller number.
Of course, this kind of nothrow vs. throw characteristic can be contagious. If you only use nothrow abstract ops in your abstract op, then your abstract op is nothrow. Whereas if you use any throwing ops, you are now throwing. Unless you are certain for external reasons that the given throw operation will not throw in this context, in which case you might want to assert that it is a non-abrupt-completion.
There are a couple action items here, some of which can be done independently:
Let _result_ be ! AbstractOp(). Use it throughout. A lot of places in the spec currently use "perform" for this purpose, which is not defined anywhere.<emu-clause nothrow>or<emu-clause flair="nothrow">.