diff --git a/spec.html b/spec.html index 1f45e05..8f83398 100644 --- a/spec.html +++ b/spec.html @@ -6,7 +6,7 @@ Binary AST
 status: proposal
-contributors: Shu-yu Guo, David Teller, Ecma International
+contributors: Shu-yu Guo, Tooru Fujisawa, David Teller, Ecma International
 

Binary AST

@@ -26,7 +26,14 @@

Tree Grammar

This section is derived from Shift AST Spec and parts are Copyright 2014-2017 Shape Security, Inc.

Unlike the Shift AST spec, interface types are not used to inherit fields to control over ordering of fields. Type hierarchies that are not used to discriminate are collapsed to make space costs simple. Nor are they used to discriminate types, for which explicitly discriminated unions types are used.

Whereas Shift AST's design principle is ease of search-and-replace of node types, binary AST's design principle is ease of verification and ease of associating different behaviors with syntactically different (but possibly lexically similar) productions. -

The grammar is presented in WebIDL with the `[TypeIndicator]` and `[NonEmpty]` extensions per Shift AST spec. The `[Lazy]` extension serves as a hint to the surface encoding that the `[Lazy]` attribute should be skippable in the byte stream in constant time. The `typedefs` of `or` types are to be read as recursive sum types. In text below, the "is a `Foo`" prose is shorthand for checking the node's `type` attribute being equal to `"Foo"`.

+

The grammar is presented in WebIDL with the `[TypeIndicator]` and `[NonEmpty]` extensions per Shift AST spec, as well as the listed extensions below.

+

 // Type aliases and enums.
@@ -193,6 +200,7 @@ 

Tree Grammar

EmptyStatement or ExpressionStatement or FunctionDeclaration or + LinkableFunctionDeclaration or IfStatement or IterationStatement or LabelledStatement or @@ -217,6 +225,7 @@

Tree Grammar

LiteralRegExpExpression or ArrayExpression or ArrowExpression or + LinkableArrowExpression or AssignmentExpression or BinaryExpression or CallExpression or @@ -225,6 +234,7 @@

Tree Grammar

ConditionalExpression or ClassExpression or FunctionExpression or + LinkableFunctionExpression or IdentifierExpression or NewExpression or NewTargetExpression or @@ -243,7 +253,12 @@

Tree Grammar

LiteralPropertyName) PropertyName; -typedef (Method or Getter or Setter) MethodDefinition; +typedef (Method or + Getter or + Setter or + LinkableMethod or + LinkableGetter or + LinkableSetter) MethodDefinition; typedef (MethodDefinition or DataProperty or @@ -462,14 +477,20 @@

Tree Grammar

// `export VariableStatement`, `export Declaration` interface Export : Node { - attribute (FunctionDeclaration or ClassDeclaration or VariableDeclaration) declaration; + attribute (FunctionDeclaration or + LinkableFunctionDeclaration or + ClassDeclaration or + VariableDeclaration) declaration; }; // `export default HoistableDeclaration`, // `export default ClassDeclaration`, // `export default AssignmentExpression` interface ExportDefault : Node { - attribute (FunctionDeclaration or ClassDeclaration or Expression) body; + attribute (FunctionDeclaration or + LinkableFunctionDeclaration or + ClassDeclaration or + Expression) body; }; // `ExportSpecifier`, as part of an `ExportFrom`. @@ -513,8 +534,12 @@

Tree Grammar

// `length` property of this method. attribute unsigned long length; attribute FrozenArray<Directive> directives; + attribute FrozenArray<NodeLink> directChildFunctions; [Lazy] attribute FunctionOrMethodContents contents; }; +interface LinkableMethod : Node { + [Linkable] attribute Method method; +}; // `get PropertyName ( ) { FunctionBody }` interface EagerGetter : Node { @@ -525,8 +550,12 @@

Tree Grammar

interface LazyGetter : Node { attribute PropertyName name; attribute FrozenArray<Directive> directives; + attribute FrozenArray<NodeLink> directChildFunctions; [Lazy] attribute GetterContents contents; }; +interface LinkableGetter : Node { + [Linkable] Getter getter; +}; interface GetterContents : Node { attribute boolean isThisCaptured; @@ -547,8 +576,12 @@

Tree Grammar

// `length` property of this setter function. attribute unsigned long length; attribute FrozenArray<Directive> directives; + attribute FrozenArray<NodeLink> directChildFunctions; [Lazy] attribute SetterContents contents; }; +interface LinkableSetter : Node { + [Linkable] attribute Setter setter; +}; interface SetterContents : Node { attribute boolean isThisCaptured; @@ -635,6 +668,7 @@

Tree Grammar

// `length` property of this arrow function. attribute unsigned long length; attribute FrozenArray<Directive> directives; + attribute FrozenArray<NodeLink> directChildFunctions; [Lazy] attribute ArrowExpressionContentsWithFunctionBody contents; }; interface EagerArrowExpressionWithExpression : Node { @@ -649,8 +683,12 @@

Tree Grammar

attribute boolean isAsync; // `length` property of this arrow function. attribute unsigned long length; + attribute FrozenArray<NodeLink> directChildFunctions; [Lazy] attribute ArrowExpressionContentsWithExpression contents; }; +interface LinkableArrowExpression : Node { + [Linkable] attribute ArrowExpression arrow; +}; interface ArrowExpressionContentsWithFunctionBody : Node { attribute AssertedParameterScope parameterScope; @@ -743,8 +781,12 @@

Tree Grammar

// `length` property of this function. attribute unsigned long length; attribute FrozenArray<Directive> directives; + attribute FrozenArray<NodeLink> directChildFunctions; [Lazy] attribute FunctionExpressionContents contents; }; +interface LinkableFunctionExpression : Node { + [Linkable] attribute FunctionExpression fun; +}; interface FunctionExpressionContents : Node { attribute boolean isFunctionNameCaptured; @@ -1000,7 +1042,6 @@

Tree Grammar

attribute FrozenArray<Directive> directives; attribute FunctionOrMethodContents contents; }; - interface LazyFunctionDeclaration : Node { attribute boolean isAsync; attribute boolean isGenerator; @@ -1008,8 +1049,12 @@

Tree Grammar

// `length` property of this function. attribute unsigned long length; attribute FrozenArray<Directive> directives; + attribute FrozenArray<NodeLink> directChildFunctions; [Lazy] attribute FunctionOrMethodContents contents; }; +interface LinkableFunctionDeclaration : Node { + [Linkable] attribute FunctionDeclaration fun; +} interface FunctionOrMethodContents : Node { attribute boolean isThisCaptured; @@ -1096,7 +1141,7 @@

StatementListEcmaify ( _stmts_ )

1. Let _emptyStmt_ be |StatementListItem| : |EmptyStatement|. 1. Set _list_ to |StatementList| : _emptyStmt_. 1. For each _stmt_ in _stmts_, do - 1. If _stmt_ is a `FunctionDeclaration`, then + 1. If _stmt_ is a `FunctionDeclaration` or a `LinkableFunctionDeclaration`, then 1. Set _n_ to |HoistableDeclaration|: ? Ecmaify(_stmt_). 1. Set _n_ to be |Declaration| : _n_. 1. Else if _stmt_ an `ExpressionStatement` and _stmt_`.expression` is a `LiteralStringExpression`: @@ -1307,7 +1352,7 @@

PrimaryExpressionEcmaify ( _e_ )

1. Assert: _e_ is an `Expression`, an `AssignmentTarget`, or an `AssignmentTargetWithInitializer`. 1. If _e_ is a `ThisExpression`, then return ? Ecmaify(_e_). - 1. Else if _pn_ is an `IdentifierExpression`, a `Literal`, an `ArrayExpression`, an `ObjectExpression`, a `FunctionExpression`, a `ClassExpression`, a `LiteralRegExpExpression`, a `TemplateExpression`, an `AssignmentTargetIdentifier`, an `ArrayAssignmentExpression`, or an `ObjectAssignmentExpression`, then return |PrimaryExpression| : ? Ecmaify(_e_). + 1. Else if _pn_ is an `IdentifierExpression`, a `Literal`, an `ArrayExpression`, an `ObjectExpression`, a `FunctionExpression`, a `LinkableFunctionExpression`, a `ClassExpression`, a `LiteralRegExpExpression`, a `TemplateExpression`, an `AssignmentTargetIdentifier`, an `ArrayAssignmentExpression`, or an `ObjectAssignmentExpression`, then return |PrimaryExpression| : ? Ecmaify(_e_). 1. Else, 1. Let _parenthesized_ be |ParenthesizedExpression| : ( ? ExpressionEcmaify(_e_) ). 1. Return |PrimaryExpression| : _parenthesized_. @@ -1501,7 +1546,7 @@

AssignmentExpressionEcmaify ( _e_ )

1. Assert: _e_ is an `Expression`, an `AssignmentTarget`, or an `AssignmentTargetWithInitializer`. 1. If _e_ is an `AssignmentExpression`, a `CompoundAssignmentExpression`, or an `AssignmentTargetWithInitializer`, then return ? Ecmaify(_e_). - 1. Else if _e_ is a `YieldExpression` or an `ArrowExpression`, then return |AssignmentExpression| : ? Ecmaify(_e_). + 1. Else if _e_ is a `YieldExpression`, an `ArrowExpression`, or a `LinkableArrowExpression`, then return |AssignmentExpression| : ? Ecmaify(_e_). 1. Else, 1. Let _n_ be ? ConditionalExpressionEcmaify(_e_). 1. Return |AssignmentExpression| : _n_. @@ -2004,8 +2049,10 @@

EcmaifyLabelledStatement ( _labelled_ )

1. Assert _labelled_ is a `LabelledStatement`. 1. Let _body_ be an empty Parse Node. - 1. If _labelled_`.body` is a `FunctionDeclaration`, then - 1. If _labelled_`.body.isAsync` is true or _labelled_`.body.isGenerator` is *true*, then throw a *SyntaxError* exception. + 1. If _labelled_`.body` is a `FunctionDeclaration` or a `LinkableFunctionDeclaration`, then + 1. Let _funNode_ be _labelled_`.body`. + 1. If _funNode_ is a `LinkableFunctionDeclaration`, then set _funNode_ to _funNode_`.fun`. + 1. If _funNode_`.isAsync` is true or _funNode_`.isGenerator` is *true*, then throw a *SyntaxError* exception. 1. Set _body_ to ? Ecmaify(_labelled_`.body`). 1. Else set _body_ to ? StatementEcmaify(_labelled_`.body`). 1. Let _item_ be |LabelledItem| : _body_. @@ -2785,6 +2832,7 @@

Ecmaify ( _node_ )

1. Else if _node_ is a `EmptyStatement`, then return ? EcmaifyEmptyStatement(_node_). 1. Else if _node_ is a `ExpressionStatement`, then return ? EcmaifyExpressionStatement(_node_). 1. Else if _node_ is a `FunctionDeclaration`, then return ? EcmaifyFunctionDeclaration(_node_). + 1. Else if _node_ is a `LinkableFunctionDeclaration`, then return ? EcmaifyFunctionDeclaration(_node_`.fun`). 1. Else if _node_ is a `IfStatement`, then return ? EcmaifyIfStatement(_node_). 1. Else if _node_ is a `DoWhileStatement`, then return ? EcmaifyDoWhileStatement(_node_). 1. Else if _node_ is a `ForInStatement`, then return ? EcmaifyForInStatement(_node_). @@ -2808,6 +2856,7 @@

Ecmaify ( _node_ )

1. Else if _node_ is a `LiteralRegExpExpression`, then return ? EcmaifyLiteralRegExpExpression(_node_). 1. Else if _node_ is a `ArrayExpression`, then return ? EcmaifyArrayExpression(_node_). 1. Else if _node_ is a `ArrowExpression`, then return ? EcmaifyArrowExpression(_node_). + 1. Else if _node_ is a `LinkableArrowExpression`, then return ? EcmaifyArrowExpression(_node_`.arrow`). 1. Else if _node_ is a `AssignmentExpression`, then return ? EcmaifyAssignmentExpression(_node_). 1. Else if _node_ is a `BinaryExpression`, then return ? EcmaifyBinaryExpression(_node_). 1. Else if _node_ is a `CallExpression`, then return ? EcmaifyCallExpression(_node_). @@ -2816,6 +2865,7 @@

Ecmaify ( _node_ )

1. Else if _node_ is a `ConditionalExpression`, then return ? EcmaifyConditionalExpression(_node_). 1. Else if _node_ is a `ClassExpression`, then return ? EcmaifyClassExpression(_node_). 1. Else if _node_ is a `FunctionExpression`, then return ? EcmaifyFunctionExpression(_node_). + 1. Else if _node_ is a `LinkableFunctionExpression`, then return ? EcmaifyFunctionExpression(_node_`.fun`). 1. Else if _node_ is a `IdentifierExpression`, then return ? EcmaifyIdentifierExpression(_node_). 1. Else if _node_ is a `NewExpression`, then return ? EcmaifyNewExpression(_node_). 1. Else if _node_ is a `NewTargetExpression`, then return ? EcmaifyNewTargetExpression(_node_). @@ -2832,8 +2882,11 @@

Ecmaify ( _node_ )

1. Else if _node_ is a `LiteralPropertyName`, then return ? EcmaifyLiteralPropertyName(_node_). 1. Else if _node_ is a `LiteralPropertyName`, then return ? EcmaifyLiteralPropertyName(_node_). 1. Else if _node_ is a `Method`, then return ? EcmaifyMethod(_node_). + 1. Else if _node_ is a `LinkableMethod`, then return ? EcmaifyMethod(_node_`.method`). 1. Else if _node_ is a `Getter`, then return ? EcmaifyGetter(_node_). + 1. Else if _node_ is a `LinkableGetter`, then return ? EcmaifyGetter(_node_`.getter`). 1. Else if _node_ is a `Setter`, then return ? EcmaifySetter(_node_). + 1. Else if _node_ is a `LinkableSetter`, then return ? EcmaifySetter(_node_`.setter`). 1. Else if _node_ is a `DataProperty`, then return ? EcmaifyDataProperty(_node_). 1. Else if _node_ is a `ShorthandProperty`, then return ? EcmaifyShorthandProperty(_node_). 1. Else if _node_ is a `ExportAllFrom`, then return ? EcmaifyExportAllFrom(_node_). @@ -3029,7 +3082,7 @@

CheckRestParameterName ( _expectedParams_, _restParameterName_ )

- +

CheckBoundNames ( _expectedBound_, _actualBound_ )

1. Let _unseen_ be a new empty List. @@ -3042,6 +3095,31 @@

CheckBoundNames ( _expectedBound_, _actualBound_ )

+ +

CheckDirectChildFunctions ( _funcNode_ )

+ + 1. Assert: _funcNode_ is a `LazyFunctionDeclaration`, a `LazyFunctionExpression`, a `LazyMethod`, a `LazyGetter`, a `LazySetter`, or a `LazyArrowExpression`. + 1. NOTE: All asserted direct child functions (i.e. not nested within another inner function) in _funcNode_`.directChildFunctions` must be found. It is not required that all direct child functions be in _funcNode_`.directChildFunctions`. + 1. Let _directChildFunctions_ be a new empty List. + 1. For each _link_ in _funcNode_`.directChildFunctions`, do + 1. Let _linkedNode_ be the node linked to by _link_. + 1. NOTE: The above step is up to the surface encoding. + 1. If _linkedNode_ is a `LinkableFunctionDeclaration`, then set _linkedNode_ to _linkedNode_`.fun`. + 1. Else if _linkedNode_ is a `LinkableFunctionExpression`, then set _linkedNode_ to _linkedNode_`.fun`. + 1. Else if _linkedNode_ is a `LinkableMethod`, then set _linkedNode_ to _linkedNode_`.method`. + 1. Else if _linkedNode_ is a `LinkableGetter`, then set _linkedNode_ to _linkedNode_`.getter`. + 1. Else if _linkedNode_ is a `LinkableSetter`, then set _linkedNode_ to _linkedNode_`.setter`. + 1. Else, + 1. Assert: _linkedNode_ is a `LinkableArrowExpression`. + 1. Set _linkedNode_ to _linkedNode_`.arrow`. + 1. Add _linkedNode_ as the last element of _directChildFunctions_. + 1. For each `FunctionDeclaration`, `FunctionExpression`, `Method`, `Getter`, `Setter`, or `ArrowExpression` _candidateChildFunction_ contained in _funcNode_, do + 1. If the the path from _funcNode_ to _candidateChildFunction_ contains no other `FunctionDeclaration`, `FunctionExpression`, `Method`, `Getter`, `Setter`, or `ArrowExpression`, then + 1. If _candidateChildFunction_ is in _directChildFunctions_, then remove _candidateChildFunction_ from _directChildFunctions_. + 1. If _directChildFunctions_ is not empty, then throw a *SyntaxError* exception. + +
+

CheckAssertedScope ( _scope_ , _parseTree_ )

@@ -3609,6 +3687,7 @@

Runtime Semantics: Delazify

1. Let _delazifiedBody_ be ? EcmaifyFunctionBody(_funcNode_). 1. Perform ? ValidateAndUpdateFunctionObject(_funcNode_, _functionObject_, _delazifiedBody_, _delazifiedParams_). 1. If _funcNode_ is not a `LazyGetter`, then perform ? CheckAssertedScope(_contents_`.parameterScope`, _delazifiedParams_). + 1. Perform ? CheckDirectChildFunctions(_funcNode_). 1. Perform ? CheckAssertedScope(_contents_`.bodyScope`, _delazifiedBody_). 1. If _funcNode_ is a `LazyArrowExpression`, then 1. Perform ? CheckThisCapture(_contents_`.parameterScope`, _delazifiedParams_).