Continuing woes in reading the ES6 spec language

Allen Wirfs-Brock allen at wirfs-brock.com
Thu Sep 12 14:14:48 PDT 2013


On Sep 12, 2013, at 1:50 PM, Brendan Eich wrote:

> I thought we agreed with Andreas Rossberg's proposal to isolate default expressions from hoisted body declarations, as if (kind of) desugaring

Damned if I know...there is a big note in the draft that says: "This version reflects the consensus as of the Sept. 2012 TC39 meeting.  However, it now appears that the binding semantics of formal parameters  is likely to change again. "  So, this may not be the latest consensus and I'm not actually sure there is a current consensus. 

I know some of us weren't very happy with that de-sugaring.

I'm pretty sure some decisions were left hanging.  I'll need to review notes, etc.


Allen

"






> 
> var x = "outer";
> function f(a = x, b = y) {
> var x = "inner";
> function y() {}
> body code here;
> }
> 
> to
> 
> var x = "outer";
> function f(a) {
> if (a === undefined) a = x;
> if (b === undefined) b = y;
> return function () {
> var x = "inner";
> function y() {}
> body code here;
> }.call(this, a, b);
> }
> 
> 
> Did I misremember?
> 
> /be
>> *From:* Jason Orendorff <jason.orendorff at gmail.com>
>> *Date:* September 12, 2013 9:40 PM
>> *To:* Oliver Hunt <oliver at apple.com>
>> *CC:* discussion list <es-discuss at mozilla.org>
>> *Subject:* Continuing woes in reading the ES6 spec language
>> Just as a worked example, answering Oliver's question about default
>> expressions took me the better part of an hour.
>> 
>> The default-expression h() in code like
>> 
>> function f(x=h(), y) {
>> function h() { ... }
>> }
>> 
>> is evaluated in the scope of f, as I expected, so {x, h, y} are all in
>> scope there.
>> 
>> But I was surprised by the timing; h() is evaluated
>> (a) before y is populated with the actual argument value;
>> (b) before the arguments object is fully initialized.
>> 
>> That last surprise seems really unfortunate, since the expression can
>> access the arguments object, observing it before and after
>> CompleteMapped/StrictArgumentsObject, or even cause those to fail. Can
>> we change that?
>> 
>> It also means that we have to store actual arguments "somewhere else"
>> while default-expressions are being evaluated, since the spec requires
>> y to be undefined while the default-expression h() is being evaluated.
>> 
>> Here are the steps (many are elided).
>> 
>> - Start in 8.1.16.1 Ordinary Function [[Call]] (thisArgument, argumentsList).
>> - Step 8 or 9 creates localEnv (8 if we're calling an arrow function, 9
>> otherwise)
>> - Steps 10-12 make localEnv the current scope
>> - Step 13 calls 9.1.16.11 Function Declaration Initialisation, passing
>> localEnv
>> - Step 5 of that algorithm calls VarScopedDeclarations(code).
>> - 13.1.1 and 15.1.1 contain implementations of VarScopedDeclarations
>> and TopLevelVarScopedDeclarations.
>> - VarScopedDeclarations(code) returns a list of the top-level
>> VariableStatements and FunctionDeclarations in the function body.
>> Note that VariableStatements in blocks are not included. (A bug?)
>> - Step 8 creates bindings for nested functions.
>> - Step 9 creates bindings for parameters. They're all undefined so far.
>> - Step 11 creates a binding for "arguments".
>> - Step 13 creates bindings for vars (not using the result of step 5,
>> but a different static semantic routine, VarDeclaredNames, which
>> I assumed, but did not check, is accurate for this purpose).
>> - Step 15 creates bindings for let/const/class declarations.
>> - Step 16 actually creates functions (in the scope of the new
>> environment) to populate each nested function binding created in step 8.
>> - Steps 18-20 create the arguments object and populates the binding
>> created in step 11.
>> - Step 21 does Binding Instantiation, which is defined in many places
>> but here we care about 14.1.1.2.
>> - That invokes Indexed Binding Instantiation on the parts of the
>> FormalParameters, which is defined further down in 14.1.1.2.
>> - Which ultimately performs Indexed Binding Initialisation for each
>> FormalParameter. (This call site is step 3 of the 8th algorithm in
>> 14.1.1.2.)
>> - I wasn't able to find a definition for that, but syntactically
>> a FormalParameter is just a BindingElement, and Indexed Binding
>> Initialization
>> is defined for those, in the 15th algorithm in 13.2.3.2.
>> - Step 6 of that says, if an Initialiser_opt (that is, a default
>> value expression) is present, and the value is undefined,
>> we evaluate the Initializer. Since it doesn't say anything
>> about in what scope, I assume it uses the current scope,
>> established way back at the beginning of this adventure.
>> 
>> -j
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>> 
>> *From:* Oliver Hunt <oliver at apple.com>
>> *Date:* September 12, 2013 5:49 PM
>> *To:* Andreas Rossberg <rossberg at google.com>
>> *CC:* discussion list <es-discuss at mozilla.org>
>> *Subject:* Continuing woes in reading the ES6 spec language
>> On Sep 12, 2013, at 7:51 AM, Andreas Rossberg<rossberg at google.com>  wrote:
>> 
>>> On 12 September 2013 01:41, Allen Wirfs-Brock<allen at wirfs-brock.com>  wrote:
>>>> For now, I'm going to try giving each semantic routine in a subsection, a section number.  Note this may include multiple algorithms corresponding to various productions.  I'll also add a "see also" under each such heading that references other subsections that implement the same semantic action for other productions.  That should make it easier to navigate to all implementation of, for example, "BindingInitialisation".
>>>> 
>>>> What we have here is a highly polymorphic nonlinear program and as old Smalltalker knows, the best way to find your way around is at any reference to a name to be able to popup a navigable list of both implementaors and callers of that name.  Maybe that's something we could get working in the HTML version.  We're already halfway there with some of the definition links.
>>> Well, yes, but just to be clear, the readability problems are not due
>>> to polymorphism or non-linearity as such but mainly due to OO-style
>>> decomposition. That is simply not a good match for a language spec (to
>>> put it mildly). Tool support may be a viable work-around for dealing
>>> with code, but not for something whose primary communication form is
>>> in (physical or virtual) print.
>> 
>> I absolutely agree with this - the primary user of the spec document is implementers and ES developers, not tools.  For that reason the spec should be tailored to human readers, with machine readability seen as a nice optional extra.
>> 
>>> A spec is a system which (a) wants to be transparent (as opposed to
>>> encapsulated), and (b) is pretty much closed-world (extension points
>>> notwithstanding). Consequently, none of the advantages of OO apply,
>>> and it becomes primarily a barrier.
>>> 
>>> (I'm not proposing any change to that at this stage, obviously. But it
>>> is a growing technical debt that we might consider clearing at some
>>> point.)
>> 
>> I disagree here, a spec that is hard to read, is a spec that is hard to implement correctly.  It doesn't matter if it is technically unambiguous if it is hard enough to read that an implementer can't determine what the unambiguous behavior is.
>> 
>> I've spent a lot of time now trying to read this spec, and have still not been able to determine the semantics of a number of the new language features.  I guess it's possible i'm just being thick, but I'd like to imagine that after so many years I know how to read and implement a spec.
>> 
>>> /Andreas
>> 
>> --Oliver
>> 
>>> _______________________________________________
>>> es-discuss mailing list
>>> es-discuss at mozilla.org
>>> https://mail.mozilla.org/listinfo/es-discuss
>> 
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>> 
>> *From:* Andreas Rossberg <rossberg at google.com>
>> *Date:* September 12, 2013 3:51 PM
>> *To:* Allen Wirfs-Brock <allen at wirfs-brock.com>
>> *CC:* discussion list <es-discuss at mozilla.org>
>> *Subject:* Continuing woes in reading the ES6 spec language
>> 
>> Well, yes, but just to be clear, the readability problems are not due
>> to polymorphism or non-linearity as such but mainly due to OO-style
>> decomposition. That is simply not a good match for a language spec (to
>> put it mildly). Tool support may be a viable work-around for dealing
>> with code, but not for something whose primary communication form is
>> in (physical or virtual) print.
>> 
>> A spec is a system which (a) wants to be transparent (as opposed to
>> encapsulated), and (b) is pretty much closed-world (extension points
>> notwithstanding). Consequently, none of the advantages of OO apply,
>> and it becomes primarily a barrier.
>> 
>> (I'm not proposing any change to that at this stage, obviously. But it
>> is a growing technical debt that we might consider clearing at some
>> point.)
>> 
>> /Andreas
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>> 
>> *From:* Allen Wirfs-Brock <allen at wirfs-brock.com>
>> *Date:* September 12, 2013 12:41 AM
>> *To:* Jason Orendorff <jason.orendorff at gmail.com>
>> *CC:* discussion list <es-discuss at mozilla.org>
>> *Subject:* Continuing woes in reading the ES6 spec language
>> Thanks, for the great feedback.
>> 
>> Annex F was my own attempt and keeping track of all the algorithms, but I out grew it and it's too much trouble to manually keep it up to date while things are still in flux. The other tension I've run into between easy identification ia section numbers and a table of contents that's so big it's hard to get around within a navigation pane.
>> 
>> For now, I'm going to try giving each semantic routine in a subsection, a section number. Note this may include multiple algorithms corresponding to various productions. I'll also add a "see also" under each such heading that references other subsections that implement the same semantic action for other productions. That should make it easier to navigate to all implementation of, for example, "BindingInitialisation".
>> 
>> What we have here is a highly polymorphic nonlinear program and as old Smalltalker knows, the best way to find your way around is at any reference to a name to be able to popup a navigable list of both implementaors and callers of that name. Maybe that's something we could get working in the HTML version. We're already halfway there with some of the definition links.
>> 
>> For now, I need to mostly focus on getting the spec. feature complete by the end of the year. After that we will have some time where we can cleanup the presentation.
>> 
>> Still, keep the suggestions coming and feel free to file bugs on such things.
>> 
>> Allen
>> 
>> 
>> 
>> 
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
>> 
>> *From:* Jason Orendorff <jason.orendorff at gmail.com>
>> *Date:* September 11, 2013 11:28 PM
>> *To:* Allen Wirfs-Brock <allen at wirfs-brock.com>
>> *CC:* discussion list <es-discuss at mozilla.org>
>> *Subject:* Continuing woes in reading the ES6 spec language
>> 
>> Allen, here are a few concrete usability concerns that I think could
>> be addressed... it just takes time. :-|
>> 
>> 1. In the ES6 drafts, as opposed to ES5:
>> 
>> * many more algorithms do not have unique names.
>> 
>> * more sections contain a lot of algorithms (for example,
>> 14.1.1.2 contains 13 implementations of 5 different methods).
>> 
>> * more algorithms have names that are multiple words, like
>> "Binding Initialisation" (with a space between, as opposed to
>> "ToString", "GetValue", "CheckObjectCoercible").
>> 
>> These things combined have made it harder for me to talk about the
>> spec with others in practice. Just reporting a bug in an algorithm
>> requires figuring out how to refer to it.
>> 
>> Our implementation has comments like: `// ES5 8.12.9 Step 1`.
>> There is no similarly concise way to refer to some ES6 algorithms.
>> 
>> Proposed fixes:
>> 
>> * Give every algorithm (that is, every list of steps) its own
>> section heading and/or its own unique name. There will be a lot. It's
>> worth it. Ideally, we'd have a systematic naming scheme
>> ("OrdinaryFunction»[[Call]]",
>> "FormalParameterList#3»BindingInitialization" since
>> FormalParameterList has multiple productions)
>> 
>> These names could live in the document’s margins or something,
>> if making them all section headings is just too much.
>> 
>> * Run together all multiword method names ("BindingInitialisation").
>> 
>> 2. There is no way to find, for example, all Binding Initialisation
>> implementations. You can search the document. Having found one
>> implementation, you can't tell if there are others.
>> 
>> In ES6 many more methods have multiple implementations, and they
>> have more implementations on average.
>> 
>> Also it's not clear whether you're looking at all the
>> implementations or if there are others, possibly living in distant
>> sections. Algorithms are not grouped strictly by name
>> ("horizontally"), nor by class/grammar production ("vertically"). It's
>> a hybrid approach. I can see why. But it's surprising.
>> 
>> This is a major problem for people trying to read the spec. Right
>> now, if a step says "Perform Binding Instantiation for lhs..." there
>> is nothing for "Binding Instantiation" to link to.
>> 
>> I propose adding a section for each method that has multiple
>> implementations. This new section would (a) have the name of the
>> method as its heading, and serve as the link target for all the
>> method's call sites; (b) explain informally what the method is—its
>> purpose and roughly what you can expect to have happen when you see
>> it's being called—and (c) list all algorithms that implement it, with
>> links (except Evaluation, which has too many implementations to list).
>> The spec currently does this, for some methods, using tables (Table 4
>> and Table 5 in 6.1.6.2; and Annex F)—but not all, and the
>> implementation lists are out of date. I can see this sort of thing
>> being left until later in the ES6 cycle, but it would be awfully
>> useful to have (a) and (b) now.
>> 
>> 3. Along similar lines, it would be fantastic if every builtin class
>> had something like Table 37 — I don't know if a table is the right
>> format, but just a list of the data properties and an informal
>> description of what they're for.
>> 
>> "Show me your flow charts and conceal your tables and I shall
>> continue to be mystified;" and all that.
>> 
>> 4. Can we rename either PropertyDescriptor.[[Get/Set]] or
>> Object.[[Get/Set]]? Maybe PropertyDescriptor.[[GetAccessor]]; or else
>> Object.[[GetProperty]].
>> 
>> Not a new issue in ES6. But fixable in ES6.
>> 
>> -j
>> _______________________________________________
>> es-discuss mailing list
>> es-discuss at mozilla.org
>> https://mail.mozilla.org/listinfo/es-discuss
> _______________________________________________
> es-discuss mailing list
> es-discuss at mozilla.org
> https://mail.mozilla.org/listinfo/es-discuss
> 



More information about the es-discuss mailing list