diff --git a/spec.html b/spec.html index c1b7b200ce5..c9e4164b103 100644 --- a/spec.html +++ b/spec.html @@ -671,31 +671,11 @@

Grammar Notation

- +

Algorithm Conventions

The specification often uses a numbered list to specify steps in an algorithm. These algorithms are used to precisely specify the required semantics of ECMAScript language constructs. The algorithms are not intended to imply the use of any specific implementation technique. In practice, there may be more efficient algorithms available to implement a given feature.

-

Algorithms may be explicitly parameterized, in which case the names and usage of the parameters must be provided as part of the algorithm's definition. In order to facilitate their use in multiple parts of this specification, some algorithms, called abstract operations, are named and written in parameterized functional form so that they may be referenced by name from within other algorithms. Abstract operations are typically referenced using a functional application style such as operationName(_arg1_, _arg2_). Some abstract operations are treated as polymorphically dispatched methods of class-like specification abstractions. Such method-like abstract operations are typically referenced using a method application style such as _someValue_.operationName(_arg1_, _arg2_).

-

Calls to abstract operations return Completion Records. Abstract operations referenced using the functional application style and the method application style that are prefixed by `?` indicate that ReturnIfAbrupt should be applied to the resulting Completion Record. For example, ? operationName() is equivalent to ReturnIfAbrupt(operationName()). Similarly, ? _someValue_.operationName() is equivalent to ReturnIfAbrupt(_someValue_.operationName()).

-

The prefix `!` is used to indicate that an abstract operation will never return an abrupt completion and that the resulting Completion Record's value field should be used in place of the return value of the operation. For example, “Let _val_ be ! operationName()” is equivalent to the following algorithm steps:

- - 1. Let _val_ be operationName(). - 1. Assert: _val_ is never an abrupt completion. - 1. If _val_ is a Completion Record, let _val_ be _val_.[[Value]]. - -

Algorithms may be associated with productions of one of the ECMAScript grammars. A production that has multiple alternative definitions will typically have a distinct algorithm for each alternative. When an algorithm is associated with a grammar production, it may reference the terminal and nonterminal symbols of the production alternative as if they were parameters of the algorithm. When used in this manner, nonterminal symbols refer to the actual alternative definition that is matched when parsing the source text.

-

When an algorithm is associated with a production alternative, the alternative is typically shown without any “[ ]” grammar annotations. Such annotations should only affect the syntactic recognition of the alternative and have no effect on the associated semantics for the alternative.

-

Unless explicitly specified otherwise, all chain productions have an implicit definition for every algorithm that might be applied to that production's left-hand side nonterminal. The implicit definition simply reapplies the same algorithm name with the same parameters, if any, to the chain production's sole right-hand side nonterminal and then returns the result. For example, assume there is a production:

- - Block : - `{` StatementList `}` - -

but there is no corresponding Evaluation algorithm that is explicitly specified for that production. If in some algorithm there is a statement of the form: “Return the result of evaluating |Block|” it is implicit that an Evaluation algorithm exists of the form:

-

Runtime Semantics: Evaluation

- Block : `{` StatementList `}` - - 1. Return the result of evaluating |StatementList|. - -

For clarity of expression, algorithm steps may be subdivided into sequential substeps. Substeps are indented and may themselves be further divided into indented substeps. Outline numbering conventions are used to identify substeps with the first level of substeps labelled with lower case alphabetic characters and the second level of substeps labelled with lower case roman numerals. If more than three levels are required these rules repeat with the fourth level using numeric labels. For example:

+

Algorithms may be explicitly parameterized, in which case the names and usage of the parameters must be provided as part of the algorithm's definition.

+

Algorithm steps may be subdivided into sequential substeps. Substeps are indented and may themselves be further divided into indented substeps. Outline numbering conventions are used to identify substeps with the first level of substeps labelled with lower case alphabetic characters and the second level of substeps labelled with lower case roman numerals. If more than three levels are required these rules repeat with the fourth level using numeric labels. For example:

1. Top-level step 1. Substep. @@ -709,32 +689,171 @@

Algorithm Conventions

A step may specify the iterative application of its substeps.

A step that begins with “Assert:” asserts an invariant condition of its algorithm. Such assertions are used to make explicit algorithmic invariants that would otherwise be implicit. Such assertions add no additional semantic requirements and hence need not be checked by an implementation. They are used simply to clarify algorithms.

Algorithm steps may declare named aliases for any value using the form “Let _x_ be _someValue_”. These aliases are reference-like in that both _x_ and _someValue_ refer to the same underlying data and modifications to either are visible to both. Algorithm steps that want to avoid this reference-like behaviour should explicitly make a copy of the right-hand side: “Let _x_ be a copy of _someValue_” creates a shallow copy of _someValue_.

-

Mathematical operations such as addition, subtraction, negation, multiplication, division, and the mathematical functions defined later in this clause should always be understood as computing exact mathematical results on mathematical real numbers, which unless otherwise noted do not include infinities and do not include a negative zero that is distinguished from positive zero. Algorithms in this standard that model floating-point arithmetic include explicit steps, where necessary, to handle infinities and signed zero and to perform rounding. If a mathematical operation or function is applied to a floating-point number, it should be understood as being applied to the exact mathematical value represented by that floating-point number; such a floating-point number must be finite, and if it is *+0* or *-0* then the corresponding mathematical value is simply 0.

-

The mathematical function abs(_x_) produces the absolute value of _x_, which is -_x_ if _x_ is negative (less than zero) and otherwise is _x_ itself.

-

The mathematical function min(_x1_, _x2_, ..., _xN_) produces the mathematically smallest of _x1_ through _xN_. The mathematical function max(_x1_, _x2_, ..., _xN_) produces the mathematically largest of _x1_ through _xN_. The domain and range of these mathematical functions include *+∞* and *-∞*.

-

The notation “_x_ modulo _y_” (_y_ must be finite and nonzero) computes a value _k_ of the same sign as _y_ (or zero) such that abs(_k_) < abs(_y_) and _x_-_k_ = _q_ × _y_ for some integer _q_.

-

The mathematical function floor(_x_) produces the largest integer (closest to positive infinity) that is not larger than _x_.

- -

floor(_x_) = _x_-(_x_ modulo 1).

-
-
+ + +

Abstract Operations

+

In order to facilitate their use in multiple parts of this specification, some algorithms, called abstract operations, are named and written in parameterized functional form so that they may be referenced by name from within other algorithms. Abstract operations are typically referenced using a functional application style such as operationName(_arg1_, _arg2_). Some abstract operations are treated as polymorphically dispatched methods of class-like specification abstractions. Such method-like abstract operations are typically referenced using a method application style such as _someValue_.operationName(_arg1_, _arg2_).

+
- - -

Static Semantic Rules

-

Context-free grammars are not sufficiently powerful to express all the rules that define whether a stream of input elements form a valid ECMAScript |Script| or |Module| that may be evaluated. In some situations additional rules are needed that may be expressed using either ECMAScript algorithm conventions or prose requirements. Such rules are always associated with a production of a grammar and are called the static semantics of the production.

-

Static Semantic Rules have names and typically are defined using an algorithm. Named Static Semantic Rules are associated with grammar productions and a production that has multiple alternative definitions will typically have for each alternative a distinct algorithm for each applicable named static semantic rule.

-

Unless otherwise specified every grammar production alternative in this specification implicitly has a definition for a static semantic rule named Contains which takes an argument named _symbol_ whose value is a terminal or nonterminal of the grammar that includes the associated production. The default definition of Contains is:

- - 1. For each child node _child_ of this Parse Node, do - 1. If _child_ is an instance of _symbol_, return *true*. - 1. If _child_ is an instance of a nonterminal, then - 1. Let _contained_ be the result of _child_ Contains _symbol_. - 1. If _contained_ is *true*, return *true*. - 1. Return *false*. - -

The above definition is explicitly over-ridden for specific productions.

-

A special kind of static semantic rule is an Early Error Rule. Early error rules define early error conditions (see clause ) that are associated with specific grammar productions. Evaluation of most early error rules are not explicitly invoked within the algorithms of this specification. A conforming implementation must, prior to the first evaluation of a |Script| or |Module|, validate all of the early error rules of the productions used to parse that |Script| or |Module|. If any of the early error rules are violated the |Script| or |Module| is invalid and cannot be evaluated.

+ +

Production-Associated Algorithms

+

Algorithms may be associated with productions of one of the ECMAScript grammars. Such algorithms are called production-associated algorithms. A production that has multiple alternative definitions will typically have a distinct algorithm for each alternative. When an algorithm is associated with a grammar production, it may reference the terminal and nonterminal symbols of the production alternative as if they were parameters of the algorithm. When used in this manner, nonterminal symbols refer to the actual alternative definition that is matched when parsing the source text.

+

When an algorithm is associated with a production alternative, the alternative is typically shown without any “[ ]” grammar annotations. Such annotations should only affect the syntactic recognition of the alternative and have no effect on the associated semantics for the alternative.

+

Unless explicitly specified otherwise, all chain productions have an implicit definition for every algorithm that might be applied to that production's left-hand side nonterminal. The implicit definition simply reapplies the same algorithm name with the same parameters, if any, to the chain production's sole right-hand side nonterminal and then returns the result. For example, assume there is a production:

+ + Block : + `{` StatementList `}` + +

but there is no corresponding Evaluation algorithm that is explicitly specified for that production. If in some algorithm there is a statement of the form: “Return the result of evaluating |Block|” it is implicit that an Evaluation algorithm exists of the form:

+

Runtime Semantics: Evaluation

+ Block : `{` StatementList `}` + + 1. Return the result of evaluating |StatementList|. + +

Production-associated algorithms are referenced with a parse node by using the conventions on steps 1 and 3 in the following algorithm:

+ + 1. Let _status_ be the result of performing ProductionAssociatedAlgorithm of |SomeNonTerminal|. + 2. Let _someParseNode_ be the parse of some source text. + 2. Perform ProductionAssociatedAlgorithm of _someParseNode_. + +
+ + + +

Runtime Semantics

+

Algorithms which specify semantics which occurs at runtime (i.e. after parsing, during execution) are called Runtime Semantics. Runtime semantics might be abstract operations or production-associated algorithms. Such algorithms always return a completion record.

+ +

Implicit Completion Values

+

The algorithms of this specification often implicitly return Completion Records whose [[Type]] is ~normal~. Unless it is otherwise obvious from the context, an algorithm statement that returns a value that is not a Completion Record, such as:

+ + 1. Return `"Infinity"`. + +

means the same thing as:

+ + 1. Return NormalCompletion(`"Infinity"`). + +

However, if the value expression of a “return” statement is a Completion Record construction literal, the resulting Completion Record is returned. If the value expression is a call to an abstract operation, the “return” statement simply returns the Completion Record produced by the abstract operation.

+

The abstract operation Completion(_completionRecord_) is used to emphasize that a previously computed Completion Record is being returned. The Completion abstract operation takes a single argument, _completionRecord_, and performs the following steps:

+ + 1. Assert: _completionRecord_ is a Completion Record. + 1. Return _completionRecord_ as the Completion Record of this abstract operation. + +

A “return” statement without a value in an algorithm step means the same thing as:

+ + 1. Return NormalCompletion(*undefined*). + +

Any reference to a Completion Record value that is in a context that does not explicitly require a complete Completion Record value is equivalent to an explicit reference to the [[Value]] field of the Completion Record value unless the Completion Record is an abrupt completion.

+
+ + + +

Throw an Exception

+

Algorithms steps that say to throw an exception, such as

+ + 1. Throw a *TypeError* exception. + +

mean the same things as:

+ + 1. Return Completion{[[Type]]: ~throw~, [[Value]]: a newly created *TypeError* object, [[Target]]: ~empty~}. + +
+ + + +

ReturnIfAbrupt

+

Algorithms steps that say or are otherwise equivalent to:

+ + 1. ReturnIfAbrupt(_argument_). + +

mean the same thing as:

+ + 1. If _argument_ is an abrupt completion, return _argument_. + 1. Else if _argument_ is a Completion Record, let _argument_ be _argument_.[[Value]]. + +

Algorithms steps that say or are otherwise equivalent to:

+ + 1. ReturnIfAbrupt(AbstractOperation()). + +

mean the same thing as:

+ + 1. Let _hygienicTemp_ be AbstractOperation(). + 1. If _hygienicTemp_ is an abrupt completion, return _hygienicTemp_. + 1. Else if _hygienicTemp_ is a Completion Record, let _hygienicTemp_ be _hygienicTemp_.[[Value]]. + +

Where _hygienicTemp_ is ephemeral and visible only in the steps pertaining to ReturnIfAbrupt.

+

Algorithms steps that say or are otherwise equivalent to:

+ + 1. Let _result_ be AbstractOperation(ReturnIfAbrupt(_argument_)). + +

mean the same thing as:

+ + 1. If _argument_ is an abrupt completion, return _argument_. + 1. If _argument_ is a Completion Record, let _argument_ be _argument_.[[Value]]. + 1. Let _result_ be AbstractOperation(_argument_). + +
+ +

ReturnIfAbrupt Shorthands

+

Abstract operations referenced using the functional application style and the method application style that are prefixed by `?` indicate that ReturnIfAbrupt should be applied to the resulting Completion Record. For example, the algorithm:

+ + 1. ? operationName(). + +

is equivalent to the following algorithm:

+ + 1. ReturnIfAbrupt(operationName()). + +

Similarly, for method application style:

+ + 1. ? _someValue_.operationName(). + +

is equivalent to the following algorithm:

+ + 1. ReturnIfAbrupt(_someValue_.operationName()). + +

Similarly, prefix `!` is used to indicate that an abstract operation will never return an abrupt completion and that the resulting Completion Record's value field should be used in place of the return value of the operation. For example, the algorithm:

+ + 1. Let _val_ be ! operationName(). + +

is equivalent to the following algorithm steps:

+ + 1. Let _val_ be operationName(). + 1. Assert: _val_ is never an abrupt completion. + 1. If _val_ is a Completion Record, let _val_ be _val_.[[Value]]. + +

Production-associated algorithms for runtime semantics may also make use of this short-hand by placing `!` or `?` before the algorithm's name:

+ + 1. Perform ! ProductionAssociatedAlgorithm of |NonTerminal|. + +
+
+ + +

Static Semantics

+

Context-free grammars are not sufficiently powerful to express all the rules that define whether a stream of input elements form a valid ECMAScript |Script| or |Module| that may be evaluated. In some situations additional rules are needed that may be expressed using either ECMAScript algorithm conventions or prose requirements. Such rules are always associated with a production of a grammar and are called the static semantics of the production.

+

Static Semantic Rules have names and typically are defined using an algorithm. Named Static Semantic Rules are associated with grammar productions and a production that has multiple alternative definitions will typically have for each alternative a distinct algorithm for each applicable named static semantic rule.

+

Unless otherwise specified every grammar production alternative in this specification implicitly has a definition for a static semantic rule named Contains which takes an argument named _symbol_ whose value is a terminal or nonterminal of the grammar that includes the associated production. The default definition of Contains is:

+ + 1. For each child node _child_ of this Parse Node, do + 1. If _child_ is an instance of _symbol_, return *true*. + 1. If _child_ is an instance of a nonterminal, then + 1. Let _contained_ be the result of _child_ Contains _symbol_. + 1. If _contained_ is *true*, return *true*. + 1. Return *false*. + +

The above definition is explicitly over-ridden for specific productions.

+

A special kind of static semantic rule is an Early Error Rule. Early error rules define early error conditions (see clause ) that are associated with specific grammar productions. Evaluation of most early error rules are not explicitly invoked within the algorithms of this specification. A conforming implementation must, prior to the first evaluation of a |Script| or |Module|, validate all of the early error rules of the productions used to parse that |Script| or |Module|. If any of the early error rules are violated the |Script| or |Module| is invalid and cannot be evaluated.

+
+ +

Mathematical Operations

+

Mathematical operations such as addition, subtraction, negation, multiplication, division, and the mathematical functions defined later in this clause should always be understood as computing exact mathematical results on mathematical real numbers, which unless otherwise noted do not include infinities and do not include a negative zero that is distinguished from positive zero. Algorithms in this standard that model floating-point arithmetic include explicit steps, where necessary, to handle infinities and signed zero and to perform rounding. If a mathematical operation or function is applied to a floating-point number, it should be understood as being applied to the exact mathematical value represented by that floating-point number; such a floating-point number must be finite, and if it is *+0* or *-0* then the corresponding mathematical value is simply 0.

+

The mathematical function abs(_x_) produces the absolute value of _x_, which is -_x_ if _x_ is negative (less than zero) and otherwise is _x_ itself.

+

The mathematical function min(_x1_, _x2_, ..., _xN_) produces the mathematically smallest of _x1_ through _xN_. The mathematical function max(_x1_, _x2_, ..., _xN_) produces the mathematically largest of _x1_ through _xN_. The domain and range of these mathematical functions include *+∞* and *-∞*.

+

The notation “_x_ modulo _y_” (_y_ must be finite and nonzero) computes a value _k_ of the same sign as _y_ (or zero) such that abs(_k_) < abs(_y_) and _x_-_k_ = _q_ × _y_ for some integer _q_.

+

The mathematical function floor(_x_) produces the largest integer (closest to positive infinity) that is not larger than _x_.

+ +

floor(_x_) = _x_-(_x_ modulo 1).

+
+
@@ -2714,78 +2833,6 @@

NormalCompletion

- - -

Implicit Completion Values

-

The algorithms of this specification often implicitly return Completion Records whose [[Type]] is ~normal~. Unless it is otherwise obvious from the context, an algorithm statement that returns a value that is not a Completion Record, such as:

- - 1. Return `"Infinity"`. - -

means the same thing as:

- - 1. Return NormalCompletion(`"Infinity"`). - -

However, if the value expression of a “return” statement is a Completion Record construction literal, the resulting Completion Record is returned. If the value expression is a call to an abstract operation, the “return” statement simply returns the Completion Record produced by the abstract operation.

-

The abstract operation Completion(_completionRecord_) is used to emphasize that a previously computed Completion Record is being returned. The Completion abstract operation takes a single argument, _completionRecord_, and performs the following steps:

- - 1. Assert: _completionRecord_ is a Completion Record. - 1. Return _completionRecord_ as the Completion Record of this abstract operation. - -

A “return” statement without a value in an algorithm step means the same thing as:

- - 1. Return NormalCompletion(*undefined*). - -

Any reference to a Completion Record value that is in a context that does not explicitly require a complete Completion Record value is equivalent to an explicit reference to the [[Value]] field of the Completion Record value unless the Completion Record is an abrupt completion.

-
- - - -

Throw an Exception

-

Algorithms steps that say to throw an exception, such as

- - 1. Throw a *TypeError* exception. - -

mean the same things as:

- - 1. Return Completion{[[Type]]: ~throw~, [[Value]]: a newly created *TypeError* object, [[Target]]: ~empty~}. - -
- - - -

ReturnIfAbrupt

-

Algorithms steps that say or are otherwise equivalent to:

- - 1. ReturnIfAbrupt(_argument_). - -

mean the same thing as:

- - 1. If _argument_ is an abrupt completion, return _argument_. - 1. Else if _argument_ is a Completion Record, let _argument_ be _argument_.[[Value]]. - -

Algorithms steps that say or are otherwise equivalent to:

- - 1. ReturnIfAbrupt(AbstractOperation()). - -

mean the same thing as:

- - 1. Let _hygienicTemp_ be AbstractOperation(). - 1. If _hygienicTemp_ is an abrupt completion, return _hygienicTemp_. - 1. Else if _hygienicTemp_ is a Completion Record, let _hygienicTemp_ be _hygienicTemp_.[[Value]]. - -

Where _hygienicTemp_ is ephemeral and visible only in the steps pertaining to ReturnIfAbrupt.

-

Algorithms steps that say or are otherwise equivalent to:

- - 1. Let _result_ be AbstractOperation(ReturnIfAbrupt(_argument_)). - -

mean the same thing as:

- - 1. If _argument_ is an abrupt completion, return _argument_. - 1. If _argument_ is a Completion Record, let _argument_ be _argument_.[[Value]]. - 1. Let _result_ be AbstractOperation(_argument_). - -
-

UpdateEmpty ( _completionRecord_, _value_ )