On Nov 12, 2007, at 1:40 PM, YR Chen wrote: > Definitely like it. I wonder how convoluted the grammar change was > - did it require a new value_expr_no_conflicts_with_type_expr > production and all related productions/rules?
Not sure, but top-down parsers have it easy, discriminating on the leftmost token and if none of the short list of structural type tokens match, falling into a value-expression sub-parser invocation. As I noted elsewhere, we have such a grammar (not quite the same, consider '(' as the leftmost token of the new operand) for the new operator (see the overview, "Record and array types" section). > Yeah, I meant "anonymous interfaces". I know they're not the same > as interfaces, but they're similar in that they place a set of > restrictions or guarantees on a class or object that "implements" > them. Just FYI, we tried for self-types (see Kim Bruce's work) to make structural types with "methods" stronger, but deferred. See http://wiki.ecmascript.org/doku.php?id=proposals:self_type > I think that would be a good thing. Another thought: if |x is v|, > where |v| is a meta-object, works, then one would think that it > should also work for |like|, e.g. > > var x = int > 10 is x; // ok > 10 is like x; // ? > > But if that last statement is allowed, then so is |var y: like x|, > which is undecidable (if that's the correct term), so evidently | > like| shouldn't work with value exprs. This is a hot topic. We could indeed allow all sorts of type expressions, and define evaluation rules so that (I hope) nothing diverges and we don't need to set a watchdog timer on strict mode's type checker. The static guarantees go down because strict mode will punt anything it can't figure out to runtime, treating the compile- time type as *. It seems wiser at the moment to restrict type annotations and remain future proof, but make 'is' friendlier as you and I have been discussing. > Might want to mention this in any clarification you put into the > spec, even if it's strictly disallowed in the formal grammar - that > even though |is| allows a value expr on the right side, it cannot > be nested within a type expr. That means given |var x|, none of |10 > is like x|, |10 is (x)|, |10 is {p: x}|, etc. are syntactically > allowed. I think we're now inclined to allow those but insist on a type at runtime. But this is something to discuss more. > There are couple potential problems with upgrading |instanceof| to > match the syntax of the revised |is|: > > 1) Function expr syntax ambiguity. Consider: > > a) x is function(p: int): int // ok > b) x is function(p: int): int {} // syntax error > c) x instanceof function(p: int): int // ok? > d) x instanceof function(p: int): int {} // syntax error? Oh, I see -- on second thought I meant nothing like allowing (d) -- sorry. instanceof only takes a value expression on its right, but if that evaluates to a type meta-object, it does something sane and "instance-of"ish. > 2) Object literal syntax ambiguity. If it is possible to simulate a > constructor with an object literal, namely creating an object with > [[HasInstance]], we'll have a similar situation to (1). I'm not > sure if it's possible, so I'll make up some syntax in the following > example to indicate what I mean: > > x instanceof {meta::construct: function() {}} > > That object literal is supposed to create a constructor-like > object, but like I said, I'm not sure if it's really possible and > of the exact syntax required. Not possible, so if we want to allow {p: t, q: u} on the right of instanceof, we have the choice to treat that as a type expression (likewise for [a, b] and (c, d)). Again the new operator can handle array and object types similarly, because there's no way for you to write a constructible value initialiser (object or, needless to say, array initialiser). If we do not fear closing the door to future extensions that enable constructible or has-instance-able initialisers, then I think we're on solid ground. And I see no point in adding ways to make such things, given the alternative meanings competing for the same syntax here (value vs. type expressions with instanceof and new, I mean). > Anyway, that |{...}| is ambiguous in that it can either be treated > as a record structural type or an object literal. In ES3, there's > no way to create a constructor from an object literal (AFAIK), so > the above syntax (ignoring the namespace) would be a runtime error. > Thus, there is no backwards compat issue. If it were allowed in > ES3, as before, it is guaranteed to resolve to false. So the | > {...}| should be treated as a record structural type. > > 3) Parenthesis ambiguity. This is the most troublesome one. Consider: > > a) x is (int) // ok > b) x is (some_constructor) // syntax error > c) x is ({p: int}) // ok > d) x instanceof (int) // ok > e) x instanceof (some_constructor) // syntax error? > f) x instanceof ({p: int}) // how should this be treated? Yes, and parenthesized expression may follow operator new, so this is a hard limit. > If we really want to upgrade |instanceof| yet keep it coherent with > |is| in both semantics and syntax, we may have to visit the |type| > operator again, but that should be a last resort. > That unary type operator is still around in the spec space, awaiting hookup in the RI, at least as far as I can recall. But with the unification (partial, but practical) of type and (else) value expressions for 'is", or vice versa for instanceof/new, I agree we should avoid reaching for unary 'type'. /be _______________________________________________ Es4-discuss mailing list Es4-discuss@mozilla.org https://mail.mozilla.org/listinfo/es4-discuss