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

Add aoid and update calling conventions for directed operations #955

Closed
wants to merge 17 commits into from

Conversation

bterlson
Copy link
Member

This is the ECMA262 changes necessary to use the upcoming support for polymorphic references. I've got a rendering of this here: https://bterlson.github.io/ecma262/#sec-declarative-environment-records. Sending this in case there are any thoughts on this approach before I convert the entire document and commit the ecmarkup change as well.

@bterlson
Copy link
Member Author

@jmdyck may have impacts on #545.

@jmdyck
Copy link
Collaborator

jmdyck commented Jul 25, 2017

Is StringValue singled out because it's special, or is it just the first of many?

@bterlson
Copy link
Member Author

First of many.

@jmdyck
Copy link
Collaborator

jmdyck commented Jul 25, 2017

Is "polymorphic references" explained somewhere?

@jmdyck
Copy link
Collaborator

jmdyck commented Jul 25, 2017

(Also, the change to calling conventions relates back to open issue #311.)

@bterlson
Copy link
Member Author

"polymorphic references" is not an ECMA262 term but how I call them for Ecmarkup purposes. For ECMA262, I will be updating the algorithm conventions to include these conventions both for syntax-directed operations and type-directed operations (where type might be any ECMAScript spec or language value).

@jmdyck
Copy link
Collaborator

jmdyck commented Jul 26, 2017

"polymorphic references" is not an ECMA262 term but how I call them for Ecmarkup purposes.

The word "references" made me wonder if they had something to do with the Reference specification type. Instead, it sounds like you're unifying (or at least bring closer together) the concepts of "concrete methods" (for Environment Records + Module Records) and syntax-directed operations. What they have in common (so far) is:

  1. Each such operation has, in effect, an implicit additional parameter, which is referenced (within the op's definition) and set (within an invocation of the op) in various ways (but never in the same way as a conventional parameter).
  2. Each such operation is defined by multiple separate algorithms, and which one to use (for any given invocation) is determined by the nature of the value being passed to the implicit parameter.

You could almost fit internal methods into the same scheme. Were you intending to do so?

@bterlson
Copy link
Member Author

bterlson commented Jul 26, 2017

Yeah my plan is to do this with internal methods as well. Can you elaborate on "almost"? 😛

My thinking in terms of algorithm conventions updates is that "directed operations" [editorial note: awkward name] are algorithms that take an implicit parameter of the receiver (but provides no way to access it "by default"). Syntax directed operations expose the receiver as parse nodes named by the receiver's non-terminals, internal methods expose it as an object O, and "concrete methods" (record-directed operations?) have the "Let thing be this Thing" convention.

My only concern is that "directed operations" is awkward...

@jmdyck
Copy link
Collaborator

jmdyck commented Jul 26, 2017

Yeah my plan is to do this with internal methods as well.

Ah, then you'll need to be careful about the word "receiver", as [[Get]] and [[Set]] already have an explicit parameter by that name.

Can you elaborate on "almost"?

I just meant that with 'concrete methods' and syntax-directed operations, the dispatching is based on an inherent/intrinsic aspect of the 'receiver', whereas with internal methods, the dispatch is just to execute whatever's in the appropriate internal slot of the 'receiver' (which isn't necessarily different in an implementation, but is different in the spec's model). But I didn't mean that that should stop you from putting them all into the same general category.

Syntax directed operations expose the receiver as parse nodes named by the receiver's non-terminals,

I would say that for an SDO, the receiver is a parse node. (More specifically, within an algorithm for an SDO, the receiver is an instance of one of the productions that that algorithm is associated with, and it is referenced via the form this |NT| where |NT| is the lhs-nonterminal of (one of) those production(s). (In the rare case that the alg is associated with multiple productions with different lhs-nonterminals, it turns out the algorithm doesn't need to refer to the receiver.)

internal methods expose it as an object O

Note that currently they don't all use the name _O_ (although you could make that change, of course). E.g., [[DefineOwnProperty]] uses _A_ for Array exotic object, _S_ for String exotic object, and _args_ (or the arguments object) for arguments exotic object.

and "concrete methods" (record-directed operations?) have the "Let thing be this Thing" convention.

Currently, some also use the form Let _envRec_ be the [foo] Environment Record for which the method was invoked. (So those could be made consistent.)

My only concern is that "directed operations" is awkward...

I don't think it would be incorrect to call them "polymorphic operations", but I'm not sure it would be clear. Maybe "dispatched operations"? "overloaded operations"?

@bterlson
Copy link
Member Author

Ah, then you'll need to be careful about the word "receiver", as [[Get]] and [[Set]] already have an explicit parameter by that name.

Hmm, can you think of a different name?

I would say that for an SDO, the receiver is a parse node.

I wanted to say this as well, but to further point out that the receiver is effectively destructured into various aliases the algorithm can access. I don't think the this |NT| convention is super necessary for SDOs, I like our current approach of having the NTs in scope.

Currently, some also use the form Let envRec be the [foo] ...

I want to get rid of these instances - the convention for module records is superior for terseness reasons :)

@jmdyck
Copy link
Collaborator

jmdyck commented Jul 26, 2017

Ah, then you'll need to be careful about the word "receiver", as [[Get]] and [[Set]] already have an explicit parameter by that name.

Hmm, can you think of a different name?

Nothing great so far.

You might instead rename [[Get]] and [[Set]]'s _Receiver_ parameter. Its description says:

If any ECMAScript code must be executed to [verb] the property value, _Receiver_ is used as the *this* value when evaluating the code.

So you could rename it to (say) _contingentThisValue_. (Probably not that, but something along those lines.)

I would say that for an SDO, the receiver is a parse node.

I wanted to say this as well, but to further point out that the receiver is effectively destructured into various aliases the algorithm can access.

I definitely wouldn't use that wording (because it doesn't feel like destructuring to me, and we're not talking about aliases in the sense that's been defined), but we can certainly talk about the forms that an SDO algorithm can use to access the children of the parse node that is the receiver.

I don't think the this |NT| convention is super necessary for SDOs,

What would you change such uses to?

I like our current approach of having the NTs in scope.

Did you think I was suggesting we do away with that? (I wasn't.)

spec.html Outdated
@@ -16743,7 +16743,7 @@ <h1 id="ao-issuperreference">IsSuperReference ( _V_ )</h1>
</emu-alg>
<emu-grammar>ContinueStatement : `continue` LabelIdentifier `;`</emu-grammar>
<emu-alg>
1. If the StringValue of |LabelIdentifier| is not an element of _iterationSet_, return *true*.
1. If the |LabelIdentifier|.StringValue() is not an element of _iterationSet_, return *true*.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably “If |LabelIdentifier|.StringValue()...” (extraneous “the”).

The current spec has “StringValue of ...” in some places and “the StringValue of ...” in other places.

@jmdyck
Copy link
Collaborator

jmdyck commented Aug 8, 2017

An alternative for "receiver" might be "subject".

@ljharb
Copy link
Member

ljharb commented Aug 8, 2017

fwiw, "receiver" is an established term for the "this value" of a function; it'd be ideal to stick with that definition.

@jmdyck
Copy link
Collaborator

jmdyck commented Aug 13, 2018

Just wondering what the status of this PR is.

@claudepache
Copy link
Contributor

ping?


<emu-clause id=sec-algorithm-conventions-object-directed-operations>
<h1>Object-Directed Operations</h1>
<p>Blah blah blah</p>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

?

</emu-alg>
<emu-clause id=sec-algorithm-conventions-directed-operations>
<h1>Directed Operations</h1>
<p>Some abstract operations, called <dfn>directed operations</dfn>, are implicitly parameterized with a target and have multiple definitions that may be selected depending on the value of the target. The target is referenced by callers of a directed operation using the method-like reference form `target.Operation()`. The target value may be referenced by the algorithm in a manner defined for that type of directed operation.</p>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

tbh using something like the bind operator might work better, like target::Operation(), if we had that available

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The spec is already using the syntax target.Operation(), and this PR generalizes its use (i.e., extends it in a compatible way).

Conversely, PR #1515 (BigInt) is proposing a target::Operation() syntax with different semantics from what you're suggesting. (In that PR, target is a type rather than a value.)

So why do you think that the :: syntax might work better for this PR?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I wasn’t making it as a concrete suggestion, since the bind operator isn’t a thing yet - more saying that using a dot, for a method that isn’t attached to the receiver, is confusingly non javascripty- so using an operator designed for this purpose seems nicer.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not really following you. Can you clarify what you mean by "attached to"? E.g., give cases where you think an abstract method is/isn't attached to a spec value?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It’s entirely possible I’m misreading this PR. It seemed to me that a standalone function was being called with an object as the implicit receiver, but perhaps these aren’t standalone functions.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

An abstract operation is a standalone function - it isn't attached to any object. It doesn't have a receiver, just like a strict-mode non-bound JS function invoked with parens without using member access doesn't.

Copy link
Collaborator

@jmdyck jmdyck Aug 20, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I think you're saying that you'd prefer to limit the spec notation X.Foo(args) to cases where Foo is defined to be a component / attribute / "property" of X, and use something other than dot (e.g., ::) when it isn't. This PR introduces notation like |RelationalExpression|.Evaluate(), but a syntax directed operation (like Evaluate) is not a component of a Parse Node, so you'd prefer the non-dot punctuation instead.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that sounds right :-)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay. So, applying that to existing constructs would go like this?:

  • _object_.[[InternalMethod]](...) would stick with the dot (because the spec tends to talk about internal methods as if they're "attached" to the object).
  • _envRec_.EnvRecMethod(...) would switch to the non-dot punctuation (because specific env record methods seem more like they belong to a particular env rec type).
  • _moduleRec_.ModuleRecMethod(...) ditto EnvRecMethod

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Perl user in me is suggesting:

envRec →EnvRecMethod(...)

and:

|ParseNode|→Evaluate()

where |ParseNode| is implicitly blessed into main.

@jmdyck jmdyck mentioned this pull request Aug 23, 2019
@bakkot bakkot added the editor call to be discussed in the next editor call label May 26, 2020
@bakkot
Copy link
Contributor

bakkot commented May 27, 2020

@bterlson is no longer editor and the current editor group doesn't intend to pick this up, so I'm going to close this for the moment. If anyone is strongly in favor of this change and is inclined to do the work, open a new issue where we can discuss it.

@bakkot bakkot closed this May 27, 2020
@jmdyck
Copy link
Collaborator

jmdyck commented May 28, 2020

I made a PR against this PR a couple years ago, but it never got incorporated. I suppose I'll re-mount the whole thing as a PR against master sometime.

@bakkot
Copy link
Contributor

bakkot commented May 28, 2020

@jmdyck Check with the editors before re-doing the work (by opening an issue); we weren't clear on whether we were in favor of the change.

@jmdyck
Copy link
Collaborator

jmdyck commented May 28, 2020

ok

@syg syg removed the editor call to be discussed in the next editor call label Jul 1, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants