need some clarification on compile-time type vs. run-time type

Graydon Hoare graydon at mozilla.com
Fri Nov 9 23:43:36 PST 2007


Yuh-Ruey Chen wrote:

>>> I'm not sure how to phrase this, but it seems to me that ES4 is trying
>>> to make fixed properties and non-fixed properties (and by extension,
>>> type expressions and value expressions, and compile-time features and
>>> run-time features) as similar and compatible as possible (e.g. |10 is
>>> int| and |10 instanceof int|), yet there are evidently many cases  
>>> where
>>> they can't be interchanged (e.g. my first example).

I think you just said it very well. This is an excellent articulation of 
the problem you're perceiving.

> Probably :) This is all relatively new terminology to me. This is how I
> currently understand it:
> 
> There are type expressions and value expressions. Type expressions are
> adequately defined on the wiki. The identifiers in type expressions
> refer to fixed properties. |class|, |interface|, and |type| statements
> all define types and bind those types to fixed properties. |class| and
> |interface| bind runtime class and interface objects, respectively, to
> fixed properties. A value expression is the typical ES3 expression with
> all the new ES4 syntax extensions, but it can include certain type
> expressions in certain circumstances. Type expressions that refer to a
> class (or parameterized class) resolve to the runtime class object (this
> is why |let myint = int| isn't a syntax error). Ditto for interfaces.
> Type exprs are used in |like|, |is|, |to|, |wrap|, and |cast|
> expressions as the second operand (or the only operand in the case of
> unary operators). Type expressions are also used as type annotations in
> value expressions. All other cases of type expressions appearing in
> value expressions are syntax errors.
> 
> Is that all correct?

Yes.

It is worth keeping in mind that -- unfortunately! -- we must decide 
ahead of time whether we wish to make an operand a type expression or a 
value expression. Neither is a proper syntactic subset of the other, 
though an identifier can occur in each, as can the parameter-apply 
operator ".<>".

So for example we have "<vexpr> is <texpr>", not "<vexpr> is <vexpr>". 
This might be the source of some misery, I'll grant. More curiously, in 
the value-expression context .<> takes value-expression arguments; 
whereas in the type-expression context .<> takes type-expression 
arguments. This too might tickle your sense of "too similar to be 
different".

One alternative is to mark type expression operands for these operators 
explicitly: define the "is" operator as taking two value expressions -- 
"<vexpr> is <vexpr>" -- and let users escape into type expressions using 
the "type" syntactic operator. In other words, let "x is T" be valid for 
non-type, non-fixed bindings of T -- though obviously, if T is not fixed 
in that context it will cause the type evaluator to suspend evaluation 
until the absolute last moment, always -- and require writing "x is type 
{p:int,q:int}" for more complicated structural type expressions. 
Currently we have it the other way, but we could change it.

> Offtopic rant: TBH, all this talk of the new features being optional
> detracts from other issues. Sure, saying a feature is optional is nice
> for compatibility and all, but I think more effort should be spent
> elaborating on how the new features mesh with the existing features in a
> coherent matter. 

Agreed. This is a very worthwhile discussion, I'm glad you've raised it. 
Let's keep wearing down any rough spots until it looks clean.

-Graydon



More information about the Es4-discuss mailing list