At the Harmony portion of the recent EcmaScript meeting, we took up
the classes as sugar discussion. For background, the relevant recent
threads on es-discuss are:
"Look ma, no this" thread starting at
https://mail.mozilla.org/pipermail/es-discuss/2008-November/008181.html"How much sugar do classes need?" thread starting at
https://mail.mozilla.org/pipermail/es-discuss/2008-November/008181.htmlespecially Peter Michaux's
https://mail.mozilla.org/pipermail/es-discuss/2008-November/008185.html"Block exprs as better object literals" thread starting at
https://mail.mozilla.org/pipermail/es-discuss/2008-December/008521.htmlcontinuing in January starting at
https://mail.mozilla.org/pipermail/es-discuss/2009-January/008525.htmlThe discussion was a bit frustrating because the committee was largely
unaware of the last two of these threads. Although I do recommend
reviewing them, I will here restate and refine my last suggestion in
a self contained pair of messages. Again, I would like to thank Peter
Michaux for the general approach.
Since the proposal I'm about to make will be in terms of a desugaring
to other elements of ES-Harmony, In this first message I will recap
and speculate on the needed elements of ES-Harmony. Since "lambda" is
still controversial, I will avoid it. But I will introduce instead the
minimal replacement I still need -- a "let" expression which respects
Tennent Correspondence. I would hope that this "let" actually desugars
to "lambda", but I do not assume this here. If we do adopt "lambda",
then all the desugaring I present to functions should instead be to
lambdas.
We need to refactor the ES5 grammar a bit. ES5 has two statement-level
declaration productions, VariableStatement and FunctionDeclaration. In
ES5, VariableStatement is included in Statement, whereas
FunctionDeclaration is included in SourceElement, which reads
SourceElement: // ES5
Statement
| FunctionDeclaration
The reason is that ES5 prohibits FunctionDeclarations in nested
blocks, permitting them only at the top level of Program and
FunctionBody.
Since ES-Harmony will allow lexically nested FunctionDeclarations as
well as "let" and "const" declarations, all with proper block-level
lexical scope, let's rename VariableStatement to VariableDeclaration
and refactor the grammar as:
Declaration:
VariableDeclaration
| FunctionDeclaration
| ConstFunctionDeclaration
| LetDeclaration
| ConstDeclaration
| ClassDeclaration
with ClassDeclaration explained in the next message. The important
point for now is that ClassDeclaration desugars to, in effect, declare
a function. Like a harmonious FunctionDeclaration, the name declared
by a ClassDeclaration has proper block-level lexical scope, and the
initialization of this name to the function is hoisted to the
beginning of the block so no uninitialized state is observable.
LetDeclaration:
"let" Identifier (":" Expression)_opt "=" Expression
ConstDeclaration:
"const" Identifier (":" Expression)_opt "=" Expression
The optional (":" Expression) is for dynamic type checking, where the
expression is evaluated to a guard value in the current lexical scope,
and that guard value is somehow used to represent type-like
constraints on the values that may be bound to the variable it guards.
Statement:
// current Statement contents without VariableStatement
SourceElement:
Statement
| Declaration
Block:
"{" SourceElements_opt "}"
MemberExpression:
// current MemberExpression contents
| LetExpression
| ObjectExpression
with ObjectExpression explained in the next message.
LetExpression:
"let" Bindings_opt "{" SourceElements_opt Expression "}"
For purposes of this note, we can assume Bindings_opt is
absent. Likewise, this note has no need for a LetStatement.
The semantics of the LetExpression (due, IIRC, to a suggestion of Dave
Herman) is to evaluate the parts between the curlies as a nested
block, where the value of the LetExpression is the value of the
terminal Expression in its body.
The ConstFunctionDeclaration above elaborates on someone's suggestion,
I forget who, for a syntax like:
ConstFunctionDeclaration:
"const" Identifier "(" FormalParameterList_opt ")" "{" FunctionBody "}"
This is just like the FunctionDeclaration syntax except for the use of
"const" in the position where "function" normally appears. Like a
FunctionDeclaration and a ClassDeclaration, a ConstFunctionDeclaration
declares a block-scoped hoisted function. For example,
const foo(p1, p2) { body; }
desugars to
const foo = Object.freeze(function foo(p1, p2) { body; });
Object.freeze(foo.prototype);
where this pair is hoisted to the top of its enclosing block. It would
have been more elegant if we could have desugared directly to a
FunctionDeclaration, in order to reuse the latter's hoisting
machinery. However, we can't since the variable introduced by
FunctionDeclaration is mutable ("let"-like) and there's no way to get
the freezing of the function or its prototype to be automagically
hoisted as well. Hopefully the introduction of "lambda" will provide a
more elegant way to address this need. If neither lambda nor
ConstFunctionDeclaration are accepted into ES-Harmony, then consider
the latter as only an explanatory device for other desugarings to be
presented shortly.
--
Cheers,
--MarkM
_______________________________________________
Es-discuss mailing list
Es-discuss@...
https://mail.mozilla.org/listinfo/es-discuss