Re: July TC39 meeting notes, day 2
On Aug 4, 2011, at 9:50 PM, Oliver Hunt wrote: The grammar at http://wiki.ecmascript.org/doku.php?id=harmony:classes does not restrict Statement at all, currently. The return-the-result-of-an-expression restriction could be done grammatically but it is easier to do with semantics, prose in this case. Indeed, one way to support this would be to have modes in the grammar. If memory serves me correctly ANTLR supports such a concept, although I'm not sure how widely the idea ever spread. Logically this is syntactic sugar around the large expansion of productions that would typically be necessary. Parameterized productions are cool, but we have an LR(1) normative grammar and the reasons for keeping and validating LR(1) have been covered quite a bit, even this year, on es-discuss. Generally, losing parameterization means duplication (the -NoIn vs. unsuffixed productions in ES1-5's grammar), or a semantic restriction (which can be an early error, e.g. return outside of a function, break outside of a loop, switch, or labeled statement, etc. -- even now we do not overcomplicate the grammar to forbid such things from parsing). I think part of what's confusing is I am still unclear whether class member functions are expected to apply to arbitrary objects. My assumption has always been that member functions would throw when applied to an object of the wrong class, and I don't see a good argument for an instance of a class having (essentially) a mutable shape. Please read the classes proposal. It's just syntax, this is required for Harmony. We are not adding new runtime or (horrors) static semantics by which classes would make objects you could not make otherwise. True, we could freeze -- 'const class' does some freezing and sealing -- but not by default. And we could insert |this| class checks in all methods, but those too are the exception, not the rule. I'm not sure 'const class' binds methods. If we accept arrow function syntax, then using it in classes to allow this-binding is plausible, but this creates a bound method object per method per class instance. Heavy tax, akin to closuer pattern. Doing this avoids the |this| class check, of course. To me when a developer says class ... { they are opting out of an object is a generic map semantics, and actually want a fixed object shape. Including the class prototype? I think not. Anyway, classes that restrict instance and prototype shape, thereby allowing private foo to be referenced via 'foo', do not address the other.foo issue. Ruby after Smalltalk has *instance-private* instance variables, not class-private as we propose. That's why @x works in Ruby and you don't need other@x. We agreed to class-private not instance-private, and that's what the harmony:classes proposal aims at (even with the straw and now burned private(this)/private(other) syntax). But per last week's meeting, we're going to take out private magic syntax from classes and try using private name objects: this[foo], other[foo] for private name object denoted foo. I'm open to @ for private access, personally. (We can also support decorators using @ syntax if need be, but that's not currently proposed.) But any such @ for private access would also be an infix operator, so you could say other@foo. Private name objects used with or without magic syntax for privacy in class instance variables are class-private, not instance-private. You could use private name objects freshly generated per instance, too, if you wanted to -- but we aren't even deferring syntax for that use-case. /be___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
July TC39 meeting notes, day 2
A week late, I missed some of the morning due to a conflict. Thanks to Alex Russell for whiteboard photos. Others in attendance, please fill in and correct as needed. Thanks. == Overview of initial working draft for 6th edition and discuss work flow for developing 6th edition draft == Allen presented the draft 6th edition and how best to develop it: http://wiki.ecmascript.org/doku.php?id=harmony:specification_drafts The phrase extended code as a way of specifying semantics for Harmony above and beyond strict mode code received some discussion (I missed most of it). In the end no one had a better term than extended. Allen also presented the use of cover grammars (Supplemental Syntax) to specify destructuring assignment and possibly other syntactic extensions. The problem here is that an LR(1) grammar cannot distinguish an object or array literal from a destructuring pattern of the same form, until parsing reaches the '=' after the pattern. GLR or ordered choice top-down parsing techniques can cope, but LR(1) and therefore LL(1) cannot -- such an LR(1) grammar is ambiguous. Note that ES1-5 cope with the existing ambiguity where x.y.z and x.y.z = w both start with a member expression by pushing the ambiguity off to the semantics, creating a spec-internal Reference type, which remembers the base object (what x.y evaluated to) and property name ('z'), and only getting the value (GetValue) if the x.y.z expression is an rvalue, otherwise using the Reference type lvalue to assign to the named property (PutValue). Computing a Reference tree or minimal AST for whole and arbitrarily large literal patterns, to defer evaluation till an assignment operator is parsed and we know the pattern is a destructuring lvalue rather than an object/array literal rvalue (after which GetValue or PutValue would process the tree according to its rvalue or lvalue nature) is not feasible. This is due to the generality of the PropertyAssignment and ElementList productions' AssignmentExpressions, which may embed function expressions and thus most of the grammar. We do not want to add an explicit and nearly-complete parse tree or AST to the spec. The committee seemed to agree that the cover grammar approach seems like the best technique. == Review/resolve open issues and change requests for 6 edition == https://bugs.ecmascript.org/buglist.cgi?order=Importancelist_id=384field0-0-0=flagtypes.nameresolution=---query_format=advancedtype0-0-0=substringvalue0-0-0=TC39product=Draft%20for%206th%20Edition (Bug rows from the above query follow, starting with bug numbers.) 145 nor Normal All al...@wirfs-brock.com CONF --- eliminate uint32 length restriction the the length of array objects. 146 nor Normal All al...@wirfs-brock.com CONF --- Array generic array methods should not ToUint32 covert the length of non-generic arrays We deferred these, agreeing that they seem worth trying to make as relaxations of existing index/length semantics for arrays, to align with String and avoid bogus uint32-domain work that cannot handle the overflow case of length == 2^32. They will change edge-case behavior. The changes may break only testsuites, but you never know. 178 nor Normal All al...@wirfs-brock.com CONF --- Must settle scoping details for block-scoped bindings Much discussion here. The issue is whether let and const bindings hoist to block top, or start a new implicit scope (the let* or, let's call it, C++ rule). The prior work was nicely diagrammed by Waldemar in: https://mail.mozilla.org/pipermail/es-discuss/2008-October/007807.html Quoting from Waldemar's message (note the future-proofing for guards): --- begin quote --- There are four ways to do this: A1. Lexical dead zone. References textually prior to a definition in the same block are an error. A2. Lexical window. References textually prior to a definition in the same block go to outer scope. B1. Temporal dead zone. References temporally prior to a definition in the same block are an error. B2. Temporal window. References temporally prior to a definition in the same block go to outer scope. Let's take a look at an example: let x = outer; function g() {return outer} { g(); function f() { ... x ... g ... g() ... } f(); var t = some_runtime_type; const x:t = inner; function g() { ... x ... } g(); f(); } B2 is bad because then the x inside g would sometimes refer to outer and sometimes to inner. A1 and A2 introduce extra complexity but doesn't solve the problem. You'd need to come up with a value for x to use in the very first call to g(). Furthermore, for A2 whether the window occurred or not would also depend on whether something was a function or not; users would be surprised that x shows through the window inside f but g doesn't. That leaves B1, which matches the semantic model (we need to avoid referencing variables before we know their types and before we know the values of constants). --- end quote ---
Re: July TC39 meeting notes, day 2
On Aug 4, 2011, at 2:29 PM, Brendan Eich wrote: 1. return allowed from constructor? ... Consensus is: RESOLVED, return disallowed from class constructor body. What about return with no value -- there are cases where such early returns are useful, and you would not be allowed to specify your own value (eg. there's an implicit return of |this|). Most class-oriented languages have this behaviour (C++, Java, C#, etc), those that don't support early returns, frequently don't support return-statements at all (eg. the various object-pascal dialects). 3. private variable use-syntax My 2c: i've always felt a prefix should be required to access a globally scoped variable/property in general, but no doubt people would complain about that degree of verbosity. That said I'm unsure why there's such a desire to avoid standard scoping rules of every other language (where the properties of |this| are implicitly in scope), with a mechanism to disambiguate access to the global scope if necessary (As C++ does, although i'm not suggesting C++'s syntax). --Oliver ___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: July TC39 meeting notes, day 2
On Aug 4, 2011, at 3:15 PM, Oliver Hunt wrote: On Aug 4, 2011, at 2:29 PM, Brendan Eich wrote: 1. return allowed from constructor? ... Consensus is: RESOLVED, return disallowed from class constructor body. What about return with no value -- there are cases where such early returns are useful, and you would not be allowed to specify your own value (eg. there's an implicit return of |this|). Most class-oriented languages have this behaviour (C++, Java, C#, etc), those that don't support early returns, frequently don't support return-statements at all (eg. the various object-pascal dialects). That is a good point, one I think someone raised at the meeting (my note-taking failed there). This resolution was about banning return expression; in constructors, but not banning return; used well to avoid tortured and over-indented control flow. The grammar at http://wiki.ecmascript.org/doku.php?id=harmony:classes does not restrict Statement at all, currently. The return-the-result-of-an-expression restriction could be done grammatically but it is easier to do with semantics, prose in this case. 3. private variable use-syntax My 2c: i've always felt a prefix should be required to access a globally scoped variable/property in general, but no doubt people would complain about that degree of verbosity. That said I'm unsure why there's such a desire to avoid standard scoping rules of every other language (where the properties of |this| are implicitly in scope), You must mean languages that have static typing. We have covered this before: https://mail.mozilla.org/pipermail/es-discuss/2011-June/015125.html https://mail.mozilla.org/pipermail/es-discuss/2011-June/015129.html https://mail.mozilla.org/pipermail/es-discuss/2011-June/015196.html with a mechanism to disambiguate access to the global scope if necessary (As C++ does, although i'm not suggesting C++'s syntax). Object != scope, the Harmony scoping model is lexical. Mutable instances with mutable prototypes violate lexical scope if injected into scope environments. Even if you managed to put just the private names that were declared by the class as private instance variable names (we agreed to take out the syntax for this, for the moment), how would you know whether other.foo where foo was private in the class should be the private name object, or the string-equated 'foo'? Think of Point with private x, y and an equals method. Another method has to access a plain old object with public property x. You can't try private and then public (won't be right for edge cases with both names mapped, possibly differently along the prototype chain; won't be efficient). Unlike languages with static type information about |this| and other parameters, in JS you need to say when you mean to access a private-name-keyed property. /be___ es-discuss mailing list es-discuss@mozilla.org https://mail.mozilla.org/listinfo/es-discuss
Re: July TC39 meeting notes, day 2
On Aug 4, 2011, at 6:45 PM, Brendan Eich wrote: On Aug 4, 2011, at 3:15 PM, Oliver Hunt wrote: On Aug 4, 2011, at 2:29 PM, Brendan Eich wrote: 1. return allowed from constructor? ... Consensus is: RESOLVED, return disallowed from class constructor body. What about return with no value -- there are cases where such early returns are useful, and you would not be allowed to specify your own value (eg. there's an implicit return of |this|). Most class-oriented languages have this behaviour (C++, Java, C#, etc), those that don't support early returns, frequently don't support return-statements at all (eg. the various object-pascal dialects). That is a good point, one I think someone raised at the meeting (my note-taking failed there). This resolution was about banning return expression; in constructors, but not banning return; used well to avoid tortured and over-indented control flow. The grammar at http://wiki.ecmascript.org/doku.php?id=harmony:classes does not restrict Statement at all, currently. The return-the-result-of-an-expression restriction could be done grammatically but it is easier to do with semantics, prose in this case. Indeed, one way to support this would be to have modes in the grammar. If memory serves me correctly ANTLR supports such a concept, although I'm not sure how widely the idea ever spread. Logically this is syntactic sugar around the large expansion of productions that would typically be necessary. 3. private variable use-syntax My 2c: i've always felt a prefix should be required to access a globally scoped variable/property in general, but no doubt people would complain about that degree of verbosity. That said I'm unsure why there's such a desire to avoid standard scoping rules of every other language (where the properties of |this| are implicitly in scope), You must mean languages that have static typing. We have covered this before: https://mail.mozilla.org/pipermail/es-discuss/2011-June/015125.html https://mail.mozilla.org/pipermail/es-discuss/2011-June/015129.html https://mail.mozilla.org/pipermail/es-discuss/2011-June/015196.html with a mechanism to disambiguate access to the global scope if necessary (As C++ does, although i'm not suggesting C++'s syntax). Object != scope, the Harmony scoping model is lexical. Mutable instances with mutable prototypes violate lexical scope if injected into scope environments. Even if you managed to put just the private names that were declared by the class as private instance variable names (we agreed to take out the syntax for this, for the moment), how would you know whether other.foo where foo was private in the class should be the private name object, or the string-equated 'foo'? Think of Point with private x, y and an equals method. Another method has to access a plain old object with public property x. You can't try private and then public (won't be right for edge cases with both names mapped, possibly differently along the prototype chain; won't be efficient). Unlike languages with static type information about |this| and other parameters, in JS you need to say when you mean to access a private-name-keyed property. I think part of what's confusing is I am still unclear whether class member functions are expected to apply to arbitrary objects. My assumption has always been that member functions would throw when applied to an object of the wrong class, and I don't see a good argument for an instance of a class having (essentially) a mutable shape. To me when a developer says class ... { they are opting out of an object is a generic map semantics, and actually want a fixed object shape. Essentially any class definition and any instance of a class is |sealed| -- at this point lexical scoping can be performed as it is in other languages. This isn't about having mutable objects on the scope chain, if you see a property access that references a property name that is present in the lexical scope, you statically bind to it -- the scope chain is not involved, you know that if you're a member of class X, and you access a property P that is defined in the class X, you will be performing a lookup off of |this|, you're not exposed to mutation. I don't buy the parameter vs. property name argument as most modern languages have this problem and it doesn't appear to be a significant issue. The remaining problem is the equals issue, and while i recognise that as a problem that would need to be solved (syntactically or otherwise) but i don't see why we must therefore add a penalty to the _common_ case where you want to access a member. Given the amount of noise made about removing parentheses, etc it seems stunning to then say adding syntactic overhead to basic member access is a good thing. If you want classes to produce mutable objects, and to prefix access to members of said class in instances then you might