forked from tc39/ecma262
-
Notifications
You must be signed in to change notification settings - Fork 14
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
7383dbb
commit 4fe65d1
Showing
6 changed files
with
1,555 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,380 @@ | ||
<emu-clause id="sec-abstract-operations"> | ||
<h1>Abstract Operations</h1> | ||
<p>These operations are not a part of the ECMAScript language; they are defined here to solely to aid the specification of the semantics of the ECMAScript language. Other, more specialized abstract operations are defined throughout this specification.</p> | ||
|
||
<!-- es6num="7.1" --> | ||
<emu-clause id="sec-type-conversion"> | ||
<h1>Type Conversion</h1> | ||
<p>The ECMAScript language implicitly performs automatic type conversion as needed. To clarify the semantics of certain constructs it is useful to define a set of conversion abstract operations. The conversion abstract operations are polymorphic; they can accept a value of any ECMAScript language type. But no other specification types are used with these operations.</p> | ||
|
||
<!-- es6num="7.1.1" --> | ||
<emu-clause id="sec-toprimitive" aoid="ToPrimitive" oldids="table-9"> | ||
<h1>ToPrimitive ( _input_ [ , _PreferredType_ ] )</h1> | ||
<p>The abstract operation ToPrimitive takes an _input_ argument and an optional argument _PreferredType_. The abstract operation ToPrimitive converts its _input_ argument to a non-Object type. If an object is capable of converting to more than one primitive type, it may use the optional hint _PreferredType_ to favour that type. Conversion occurs according to the following algorithm:</p> | ||
<emu-alg> | ||
1. Assert: _input_ is an ECMAScript language value. | ||
1. If Type(_input_) is Object, then | ||
1. If _PreferredType_ is not present, let _hint_ be `"default"`. | ||
1. Else if _PreferredType_ is hint String, let _hint_ be `"string"`. | ||
1. Else _PreferredType_ is hint Number, let _hint_ be `"number"`. | ||
1. Let _exoticToPrim_ be ? GetMethod(_input_, @@toPrimitive). | ||
1. If _exoticToPrim_ is not *undefined*, then | ||
1. Let _result_ be ? Call(_exoticToPrim_, _input_, « _hint_ »). | ||
1. If Type(_result_) is not Object, return _result_. | ||
1. Throw a *TypeError* exception. | ||
1. If _hint_ is `"default"`, set _hint_ to `"number"`. | ||
1. Return ? OrdinaryToPrimitive(_input_, _hint_). | ||
1. Return _input_. | ||
</emu-alg> | ||
<emu-note> | ||
<p>When ToPrimitive is called with no hint, then it generally behaves as if the hint were Number. However, objects may over-ride this behaviour by defining a @@toPrimitive method. Of the objects defined in this specification only Date objects (see <emu-xref href="#sec-date.prototype-@@toprimitive"></emu-xref>) and Symbol objects (see <emu-xref href="#sec-symbol.prototype-@@toprimitive"></emu-xref>) over-ride the default ToPrimitive behaviour. Date objects treat no hint as if the hint were String.</p> | ||
</emu-note> | ||
|
||
<emu-clause id="sec-ordinarytoprimitive" aoid="OrdinaryToPrimitive"> | ||
<h1>OrdinaryToPrimitive ( _O_, _hint_ )</h1> | ||
<p>When the abstract operation OrdinaryToPrimitive is called with arguments _O_ and _hint_, the following steps are taken:</p> | ||
<emu-alg> | ||
1. Assert: Type(_O_) is Object. | ||
1. Assert: Type(_hint_) is String and its value is either `"string"` or `"number"`. | ||
1. If _hint_ is `"string"`, then | ||
1. Let _methodNames_ be « `"toString"`, `"valueOf"` ». | ||
1. Else, | ||
1. Let _methodNames_ be « `"valueOf"`, `"toString"` ». | ||
1. For each _name_ in _methodNames_ in List order, do | ||
1. Let _method_ be ? Get(_O_, _name_). | ||
1. If IsCallable(_method_) is *true*, then | ||
1. Let _result_ be ? Call(_method_, _O_). | ||
1. If Type(_result_) is not Object, return _result_. | ||
1. Throw a *TypeError* exception. | ||
</emu-alg> | ||
</emu-clause> | ||
</emu-clause> | ||
|
||
<!-- es6num="7.1.2" --> | ||
<emu-clause id="sec-toboolean" aoid="ToBoolean"> | ||
<h1>ToBoolean ( _argument_ )</h1> | ||
<p>The abstract operation ToBoolean converts _argument_ to a value of type Boolean according to <emu-xref href="#table-10"></emu-xref>:</p> | ||
<emu-table id="table-10" caption="ToBoolean Conversions"> | ||
<table> | ||
<tbody> | ||
<tr> | ||
<th> | ||
Argument Type | ||
</th> | ||
<th> | ||
Result | ||
</th> | ||
</tr> | ||
<tr> | ||
<td> | ||
Undefined | ||
</td> | ||
<td> | ||
Return *false*. | ||
</td> | ||
</tr> | ||
<tr> | ||
<td> | ||
Null | ||
</td> | ||
<td> | ||
Return *false*. | ||
</td> | ||
</tr> | ||
<tr> | ||
<td> | ||
Boolean | ||
</td> | ||
<td> | ||
Return _argument_. | ||
</td> | ||
</tr> | ||
<tr> | ||
<td> | ||
Number | ||
</td> | ||
<td> | ||
If _argument_ is *+0*, *-0*, or *NaN*, return *false*; otherwise return *true*. | ||
</td> | ||
</tr> | ||
<tr> | ||
<td> | ||
String | ||
</td> | ||
<td> | ||
If _argument_ is the empty String (its length is zero), return *false*; otherwise return *true*. | ||
</td> | ||
</tr> | ||
<tr> | ||
<td> | ||
Symbol | ||
</td> | ||
<td> | ||
Return *true*. | ||
</td> | ||
</tr> | ||
<tr> | ||
<td> | ||
Object | ||
</td> | ||
<td> | ||
Return *true*. | ||
</td> | ||
</tr> | ||
</tbody> | ||
</table> | ||
</emu-table> | ||
</emu-clause> | ||
|
||
<!-- es6num="7.1.3" --> | ||
<emu-clause id="sec-tonumber" aoid="ToNumber"> | ||
<h1>ToNumber ( _argument_ )</h1> | ||
<p>The abstract operation ToNumber converts _argument_ to a value of type Number according to <emu-xref href="#table-11"></emu-xref>:</p> | ||
<emu-table id="table-11" caption="ToNumber Conversions"> | ||
<table> | ||
<tbody> | ||
<tr> | ||
<th> | ||
Argument Type | ||
</th> | ||
<th> | ||
Result | ||
</th> | ||
</tr> | ||
<tr> | ||
<td> | ||
Undefined | ||
</td> | ||
<td> | ||
Return *NaN*. | ||
</td> | ||
</tr> | ||
<tr> | ||
<td> | ||
Null | ||
</td> | ||
<td> | ||
Return *+0*. | ||
</td> | ||
</tr> | ||
<tr> | ||
<td> | ||
Boolean | ||
</td> | ||
<td> | ||
If _argument_ is *true*, return 1. If _argument_ is *false*, return *+0*. | ||
</td> | ||
</tr> | ||
<tr> | ||
<td> | ||
Number | ||
</td> | ||
<td> | ||
Return _argument_ (no conversion). | ||
</td> | ||
</tr> | ||
<tr> | ||
<td> | ||
String | ||
</td> | ||
<td> | ||
See grammar and conversion algorithm below. | ||
</td> | ||
</tr> | ||
<tr> | ||
<td> | ||
Symbol | ||
</td> | ||
<td> | ||
Throw a *TypeError* exception. | ||
</td> | ||
</tr> | ||
<tr> | ||
<td> | ||
Object | ||
</td> | ||
<td> | ||
<p>Apply the following steps:</p> | ||
<emu-alg> | ||
1. Let _primValue_ be ? ToPrimitive(_argument_, hint Number). | ||
1. Return ? ToNumber(_primValue_). | ||
</emu-alg> | ||
</td> | ||
</tr> | ||
</tbody> | ||
</table> | ||
</emu-table> | ||
|
||
<!-- es6num="7.1.3.1" --> | ||
<emu-clause id="sec-tonumber-applied-to-the-string-type"> | ||
<h1>ToNumber Applied to the String Type</h1> | ||
<p>ToNumber applied to Strings applies the following grammar to the input String interpreted as a sequence of UTF-16 encoded code points (<emu-xref href="#sec-ecmascript-language-types-string-type"></emu-xref>). If the grammar cannot interpret the String as an expansion of |StringNumericLiteral|, then the result of ToNumber is *NaN*.</p> | ||
<emu-note> | ||
<p>The terminal symbols of this grammar are all composed of Unicode BMP code points so the result will be *NaN* if the string contains the UTF-16 encoding of any supplementary code points or any unpaired surrogate code points.</p> | ||
</emu-note> | ||
<h2>Syntax</h2> | ||
<emu-grammar type="definition"> | ||
StringNumericLiteral ::: | ||
StrWhiteSpace? | ||
StrWhiteSpace? StrNumericLiteral StrWhiteSpace? | ||
|
||
StrWhiteSpace ::: | ||
StrWhiteSpaceChar StrWhiteSpace? | ||
|
||
StrWhiteSpaceChar ::: | ||
WhiteSpace | ||
LineTerminator | ||
|
||
StrNumericLiteral ::: | ||
StrDecimalLiteral | ||
BinaryIntegerLiteral | ||
OctalIntegerLiteral | ||
HexIntegerLiteral | ||
|
||
StrDecimalLiteral ::: | ||
StrUnsignedDecimalLiteral | ||
`+` StrUnsignedDecimalLiteral | ||
`-` StrUnsignedDecimalLiteral | ||
|
||
StrUnsignedDecimalLiteral ::: | ||
`Infinity` | ||
DecimalDigits `.` DecimalDigits? ExponentPart? | ||
`.` DecimalDigits ExponentPart? | ||
DecimalDigits ExponentPart? | ||
</emu-grammar> | ||
<p>All grammar symbols not explicitly defined above have the definitions used in the Lexical Grammar for numeric literals (<emu-xref href="#sec-literals-numeric-literals"></emu-xref>)</p> | ||
<emu-note> | ||
<p>Some differences should be noted between the syntax of a |StringNumericLiteral| and a |NumericLiteral|:</p> | ||
<ul> | ||
<li> | ||
A |StringNumericLiteral| may include leading and/or trailing white space and/or line terminators. | ||
</li> | ||
<li> | ||
A |StringNumericLiteral| that is decimal may have any number of leading `0` digits. | ||
</li> | ||
<li> | ||
A |StringNumericLiteral| that is decimal may include a `+` or `-` to indicate its sign. | ||
</li> | ||
<li> | ||
A |StringNumericLiteral| that is empty or contains only white space is converted to *+0*. | ||
</li> | ||
<li> | ||
`Infinity` and `-Infinity` are recognized as a |StringNumericLiteral| but not as a |NumericLiteral|. | ||
</li> | ||
</ul> | ||
</emu-note> | ||
|
||
<!-- es6num="7.1.3.1.1" --> | ||
<emu-clause id="sec-runtime-semantics-mv-s"> | ||
<h1>Runtime Semantics: MV</h1> | ||
<p>The conversion of a String to a Number value is similar overall to the determination of the Number value for a numeric literal (see <emu-xref href="#sec-literals-numeric-literals"></emu-xref>), but some of the details are different, so the process for converting a String numeric literal to a value of Number type is given here. This value is determined in two steps: first, a mathematical value (MV) is derived from the String numeric literal; second, this mathematical value is rounded as described below. The MV on any grammar symbol, not provided below, is the MV for that symbol defined in <emu-xref href="#sec-static-semantics-mv"></emu-xref>.</p> | ||
<ul> | ||
<li> | ||
The MV of <emu-grammar>StringNumericLiteral ::: [empty]</emu-grammar> is 0. | ||
</li> | ||
<li> | ||
The MV of <emu-grammar>StringNumericLiteral ::: StrWhiteSpace</emu-grammar> is 0. | ||
</li> | ||
<li> | ||
The MV of <emu-grammar>StringNumericLiteral ::: StrWhiteSpace? StrNumericLiteral StrWhiteSpace?</emu-grammar> is the MV of |StrNumericLiteral|, no matter whether white space is present or not. | ||
</li> | ||
<li> | ||
The MV of <emu-grammar>StrNumericLiteral ::: StrDecimalLiteral</emu-grammar> is the MV of |StrDecimalLiteral|. | ||
</li> | ||
<li> | ||
The MV of <emu-grammar>StrNumericLiteral ::: BinaryIntegerLiteral</emu-grammar> is the MV of |BinaryIntegerLiteral|. | ||
</li> | ||
<li> | ||
The MV of <emu-grammar>StrNumericLiteral ::: OctalIntegerLiteral</emu-grammar> is the MV of |OctalIntegerLiteral|. | ||
</li> | ||
<li> | ||
The MV of <emu-grammar>StrNumericLiteral ::: HexIntegerLiteral</emu-grammar> is the MV of |HexIntegerLiteral|. | ||
</li> | ||
<li> | ||
The MV of <emu-grammar>StrDecimalLiteral ::: StrUnsignedDecimalLiteral</emu-grammar> is the MV of |StrUnsignedDecimalLiteral|. | ||
</li> | ||
<li> | ||
The MV of <emu-grammar>StrDecimalLiteral ::: `+` StrUnsignedDecimalLiteral</emu-grammar> is the MV of |StrUnsignedDecimalLiteral|. | ||
</li> | ||
<li> | ||
The MV of <emu-grammar>StrDecimalLiteral ::: `-` StrUnsignedDecimalLiteral</emu-grammar> is the negative of the MV of |StrUnsignedDecimalLiteral|. (Note that if the MV of |StrUnsignedDecimalLiteral| is 0, the negative of this MV is also 0. The rounding rule described below handles the conversion of this signless mathematical zero to a floating-point *+0* or *-0* as appropriate.) | ||
</li> | ||
<li> | ||
The MV of <emu-grammar>StrUnsignedDecimalLiteral ::: `Infinity`</emu-grammar> is 10<sup>10000</sup> (a value so large that it will round to *+∞*). | ||
</li> | ||
<li> | ||
The MV of <emu-grammar>StrUnsignedDecimalLiteral ::: DecimalDigits `.`</emu-grammar> is the MV of |DecimalDigits|. | ||
</li> | ||
<li> | ||
The MV of <emu-grammar>StrUnsignedDecimalLiteral ::: DecimalDigits `.` DecimalDigits</emu-grammar> is the MV of the first |DecimalDigits| plus (the MV of the second |DecimalDigits| times 10<sup>-_n_</sup>), where _n_ is the number of code points in the second |DecimalDigits|. | ||
</li> | ||
<li> | ||
The MV of <emu-grammar>StrUnsignedDecimalLiteral ::: DecimalDigits `.` ExponentPart</emu-grammar> is the MV of |DecimalDigits| times 10<sup>_e_</sup>, where _e_ is the MV of |ExponentPart|. | ||
</li> | ||
<li> | ||
The MV of <emu-grammar>StrUnsignedDecimalLiteral ::: DecimalDigits `.` DecimalDigits ExponentPart</emu-grammar> is (the MV of the first |DecimalDigits| plus (the MV of the second |DecimalDigits| times 10<sup>-_n_</sup>)) times 10<sup>_e_</sup>, where _n_ is the number of code points in the second |DecimalDigits| and _e_ is the MV of |ExponentPart|. | ||
</li> | ||
<li> | ||
The MV of <emu-grammar>StrUnsignedDecimalLiteral ::: `.` DecimalDigits</emu-grammar> is the MV of |DecimalDigits| times 10<sup>-_n_</sup>, where _n_ is the number of code points in |DecimalDigits|. | ||
</li> | ||
<li> | ||
The MV of <emu-grammar>StrUnsignedDecimalLiteral ::: `.` DecimalDigits ExponentPart</emu-grammar> is the MV of |DecimalDigits| times 10<sup>_e_-_n_</sup>, where _n_ is the number of code points in |DecimalDigits| and _e_ is the MV of |ExponentPart|. | ||
</li> | ||
<li> | ||
The MV of <emu-grammar>StrUnsignedDecimalLiteral ::: DecimalDigits</emu-grammar> is the MV of |DecimalDigits|. | ||
</li> | ||
<li> | ||
The MV of <emu-grammar>StrUnsignedDecimalLiteral ::: DecimalDigits ExponentPart</emu-grammar> is the MV of |DecimalDigits| times 10<sup>_e_</sup>, where _e_ is the MV of |ExponentPart|. | ||
</li> | ||
</ul> | ||
<p>Once the exact MV for a String numeric literal has been determined, it is then rounded to a value of the Number type. If the MV is 0, then the rounded value is *+0* unless the first non white space code point in the String numeric literal is `"-"`, in which case the rounded value is *-0*. Otherwise, the rounded value must be the Number value for the MV (in the sense defined in <emu-xref href="#sec-ecmascript-language-types-number-type"></emu-xref>), unless the literal includes a |StrUnsignedDecimalLiteral| and the literal has more than 20 significant digits, in which case the Number value may be either the Number value for the MV of a literal produced by replacing each significant digit after the 20th with a 0 digit or the Number value for the MV of a literal produced by replacing each significant digit after the 20th with a 0 digit and then incrementing the literal at the 20th digit position. A digit is significant if it is not part of an |ExponentPart| and</p> | ||
<ul> | ||
<li> | ||
it is not `0`; or | ||
</li> | ||
<li> | ||
there is a nonzero digit to its left and there is a nonzero digit, not in the |ExponentPart|, to its right. | ||
</li> | ||
</ul> | ||
</emu-clause> | ||
</emu-clause> | ||
</emu-clause> | ||
|
||
<!-- es6num="7.1.4" --> | ||
<emu-clause id="sec-tointeger" aoid="ToInteger"> | ||
<h1>ToInteger ( _argument_ )</h1> | ||
<p>The abstract operation ToInteger converts _argument_ to an integral numeric value. This abstract operation functions as follows:</p> | ||
<emu-alg> | ||
1. Let _number_ be ? ToNumber(_argument_). | ||
1. If _number_ is *NaN*, return *+0*. | ||
1. If _number_ is *+0*, *-0*, *+∞*, or *-∞*, return _number_. | ||
1. Return the number value that is the same sign as _number_ and whose magnitude is floor(abs(_number_)). | ||
</emu-alg> | ||
</emu-clause> | ||
|
||
<!-- es6num="7.1.5" --> | ||
<emu-clause id="sec-toint32" aoid="ToInt32"> | ||
<h1>ToInt32 ( _argument_ )</h1> | ||
<p>The abstract operation ToInt32 converts _argument_ to one of 2<sup>32</sup> integer values in the range <emu-eqn>-2<sup>31</sup></emu-eqn> through <emu-eqn>2<sup>31</sup>-1</emu-eqn>, inclusive. This abstract operation functions as follows:</p> | ||
<emu-alg> | ||
1. Let _number_ be ? ToNumber(_argument_). | ||
1. If _number_ is *NaN*, *+0*, *-0*, *+∞*, or *-∞*, return *+0*. | ||
1. Let _int_ be the mathematical value that is the same sign as _number_ and whose magnitude is floor(abs(_number_)). | ||
1. Let _int32bit_ be _int_ modulo 2<sup>32</sup>. | ||
1. If _int32bit_ ≥ 2<sup>31</sup>, return _int32bit_ - 2<sup>32</sup>; otherwise return _int32bit_. | ||
</emu-alg> | ||
<emu-note> | ||
<p>Given the above definition of ToInt32:</p> | ||
<ul> | ||
<li> | ||
The ToInt32 abstract operation is idempotent: if applied to a result that it produced, the second application leaves that value unchanged. | ||
</li> | ||
<li> | ||
ToInt32(ToUint32(_x_)) is equal to ToInt32(_x_) for all values of _x_. (It is to preserve this latter property that *+∞* and *-∞* are mapped to *+0*.) | ||
</li> | ||
<li> | ||
ToInt32 maps *-0* to *+0*. | ||
</li> | ||
</ul> | ||
</emu-note> | ||
</emu-clause> |
Oops, something went wrong.