5 記法規約

5.1 構文文法と字句文法

5.1.1 文脈自由文法

文脈自由文法は複数の production から成る。各 production は、その left-hand side として nonterminal と呼ばれる抽象記号を持ち、その right-hand side として 0 個以上の nonterminal 記号および terminal 記号の列を持つ。各文法において、terminal 記号は指定されたアルファベットから取られる。

chain production とは、その右辺に terminal 記号が 0 個以上付随し、かつちょうど 1 個の nonterminal 記号を持つ production である。

goal symbol と呼ばれる、単一の特別な nonterminal から成る文から出発して、与えられた文脈自由文法は 1 つの language、すなわち、その列の中の任意の nonterminal を、その nonterminal を左辺とする production の右辺で繰り返し置き換えることにより得られる、terminal 記号列の(おそらく無限の)集合を規定する。

5.1.2 字句文法と RegExp 文法

ECMAScript の lexical grammar は節 12 に与えられている。この文法は、11.1 で定義される SourceCharacter の規則に適合する Unicode コードポイントを terminal 記号として持つ。この文法は、goal symbol InputElementDivInputElementTemplateTailInputElementRegExpInputElementRegExpOrTemplateTail、または InputElementHashbangOrRegExp から始まる複数の production を定義し、そのようなコードポイント列がどのように入力要素列へ変換されるかを記述する。

空白およびコメント以外の入力要素は、ECMAScript の構文文法の terminal 記号を成し、ECMAScript の token と呼ばれる。これらの token は、ECMAScript 言語の予約語、識別子、リテラル、および区切り記号である。さらに、行終端子は token とはみなされないが、入力要素ストリームの一部となり、自動セミコロン挿入(12.10)の処理を導く。単純な空白と単一行コメントは破棄され、構文文法の入力要素ストリームには現れない。MultiLineComment(すなわち /**/ 形式のコメントで、複数行にまたがるかどうかを問わない)も、行終端子を含まなければ同様に単に破棄される。しかし、MultiLineComment が 1 個以上の行終端子を含む場合、それは単一の行終端子に置き換えられ、それが構文文法の入力要素ストリームの一部となる。

ECMAScript の RegExp grammar22.2.1 に与えられている。この文法も SourceCharacter によって定義されるコードポイントを terminal 記号として持つ。この文法は、goal symbol Pattern から始まる複数の production を定義し、コードポイント列がどのように正規表現パターンへ変換されるかを記述する。

字句文法および RegExp 文法の production は、区切り記号として 2 つのコロン “::” を持つことで区別される。字句文法と RegExp 文法は一部の production を共有する。

5.1.3 数値文字列文法

numeric string grammar7.1.4.1 に現れる。これは SourceCharacter を terminal 記号として持ち、goal symbol StringNumericLiteral から始めて String を数値へ変換するために用いられる(これは 数値リテラルの字句文法 に似ているが別物である)。

numeric string grammar の production は、句読点として 3 つのコロン “:::” を持つことで区別され、ソーステキストの解析には決して用いられない。

5.1.4 構文文法

ECMAScript の syntactic grammar は、節 13 から 16 に与えられている。この文法は、その terminal 記号として字句文法で定義される ECMAScript token を持つ(5.1.2)。この文法は、2 つの代替 goal symbol Script および Module から始まる複数の production を定義し、token 列がどのように ECMAScript プログラムの構文的に正しい独立構成要素を形成するかを記述する。

コードポイントのストリームが ECMAScript の Script または Module として解析されるとき、まず字句文法の反復適用により入力要素のストリームへ変換される。その後、この入力要素ストリームは構文文法の単一適用によって解析される。入力要素ストリーム内の token が、余り token を残さず単一の goal nonterminal(Script または Module)の instance として解析できない場合、その入力ストリームは構文的に誤りである。

解析が成功すると、parse tree、すなわち各 node が Parse Node である根付き木構造が構築される。各 Parse Node は文法中の記号の instance であり、その記号から導出できるソーステキストの範囲を表す。ソーステキスト全体を表す parse tree の根 node は、解析の goal symbol の instance である。Parse Node が nonterminal の instance である場合、それはまた、その nonterminal を左辺に持ついずれかの production の instance でもある。さらに、その right-hand side 上の各記号に 1 つずつ対応する 0 個以上の children を持ち、各 child は対応する記号の instance である Parse Node である。

新しい Parse Node は parser の各呼出しごとに生成され、たとえ同一のソーステキストであっても解析間で再利用されることはない。Parse Node は、同じソーステキスト範囲を表し、同じ文法記号の instance であり、かつ同じ parser 呼出しから生じた場合に限り、同じ Parse Node とみなされる。

Note 1

同じ String を複数回解析すると、異なる Parse Node が生じる。たとえば、次を考える。

let str = "1 + 1;";
eval(str);
eval(str);

eval の各呼出しは、str の値を ECMAScript ソーステキストへ変換し、独立した解析を行って、それぞれ独自の別個の Parse Node 木を生成する。各解析は同じ String 値から導出されたソーステキストに対して行われるが、それらの木は別個である。

Note 2
Parse Node は仕様上の人工物であり、実装が類似のデータ構造を用いることは要求されない。

構文文法の production は、句読点としてただ 1 つのコロン “:” を持つことで区別される。

13 から 16 に示される構文文法は、どの token 列が正しい ECMAScript Script または Module として受理されるかについての完全な説明ではない。追加の token 列も受理される。すなわち、特定の箇所(たとえば行終端文字の前)にセミコロンを追加した場合にのみ、その列が文法によって記述されるものがそれに当たる。さらに、文法により記述される token 列のうち、特定の「扱いにくい」位置に行終端文字が現れる場合には、受理可能とみなされないものもある。

場合によっては、曖昧さを避けるために、構文文法は、有効な ECMAScript Script または Module を構成しない token 列を許す一般化された production を用いる。たとえば、この技法は object literal や object destructuring pattern に用いられる。そのような場合、受理可能な token 列をさらに制限する、より制約の強い supplemental grammar が提供される。通常、その後に early error rule が、特定の文脈において「p must cover an n」と述べる。ここで p は Parse Node(一般化された production の instance)であり、n は supplemental grammar の nonterminal である。これは次を意味する。

  1. もともと p に一致した token 列は、goal symbol として n を用いて再度解析される。n が文法パラメータを取るなら、p が最初に解析されたときと同じ値に設定される。
  2. その token 列が、余り token を残さず、単一の n の instance として解析できる場合、次が成り立つ。
    1. その n の instance(与えられた p に対して一意な Parse Node)を、「p によって covered される n」と呼ぶ。
    2. n およびその導出 production に対するすべての Early Error rule は、p によって covered される n にも適用される。
  3. それ以外の場合(解析に失敗した場合)、それは early Syntax Error である。

5.1.5 文法記法

5.1.5.1 終端記号

ECMAScript 文法では、一部の terminal 記号が fixed-width フォントで示される。これらは、ソーステキスト中に書かれたとおり正確に現れなければならない。この方法で指定されるすべての terminal 記号コードポイントは、他の Unicode 範囲の似た見た目のコードポイントではなく、Basic Latin ブロックの適切な Unicode コードポイントとして理解される。terminal 記号中のコードポイントは、\ UnicodeEscapeSequence で表現することはできない。

terminal 記号が個々の Unicode コードポイントである文法(すなわち、字句文法、RegExp 文法、および numeric string grammar)では、production 中に現れる複数の fixed-width コードポイントの連続列は、その同じコードポイント列を単独の terminal 記号として書いたものの単純な略記である。

たとえば、production:

HexIntegerLiteral :: 0x HexDigits

は、次の略記である。

HexIntegerLiteral :: 0 x HexDigits

これに対して、構文文法では、fixed-width コードポイントの連続列は単一の terminal 記号である。

terminal 記号にはさらに 2 つの形式がある。

  • 字句文法および RegExp 文法では、通常の印字表現を持たない Unicode コードポイントは、代わりに "<ABBREV>" の形式で示される。ここで "ABBREV" はそのコードポイントまたはコードポイント集合のニーモニックである。これらの形式は Unicode 書式制御文字White Space、および Line Terminator で定義される。
  • 構文文法では、特定の terminal 記号(たとえば IdentifierNameRegularExpressionLiteral)はイタリック体で示される。これは、それらが字句文法における同名の nonterminal を参照するためである。

5.1.5.2 非終端記号と生成規則

nonterminal 記号は italic 体で示される。nonterminal の定義(“production” とも呼ばれる)は、定義される nonterminal の名前に続いて 1 個以上のコロンを付けることで導入される。(コロンの数は、その production がどの文法に属するかを示す。)その後、nonterminal の 1 つ以上の代替 right-hand side が続く行に現れる。たとえば、構文定義:

WhileStatement : while ( Expression ) Statement

は、nonterminal WhileStatement が、token while、左括弧 token、Expression、右括弧 token、Statement の順に続くものを表すことを述べている。Expression および Statement の出現は、それ自体 nonterminal である。別の例として、構文定義:

ArgumentList : AssignmentExpression ArgumentList , AssignmentExpression

は、ArgumentList が、単一の AssignmentExpression か、あるいは ArgumentList に続けてコンマと AssignmentExpression が続くもののいずれかを表してよいことを述べている。この ArgumentList の定義は再帰的であり、すなわちそれ自体を用いて定義される。その結果、ArgumentList は、各引数式が AssignmentExpression である任意の正の個数の引数を、コンマ区切りで含んでよい。このような nonterminal の再帰的定義は一般的である。

5.1.5.3 オプション記号

terminal または nonterminal の後ろに現れることがある下付き接尾辞 “opt” は、省略可能な記号を示す。省略可能記号を含む選択肢は、実際には 2 つの right-hand side、すなわち省略可能要素を省いたものと含むものを指定している。これは次を意味する。

VariableDeclaration : BindingIdentifier Initializeropt

は、次の便利な略記である。

VariableDeclaration : BindingIdentifier BindingIdentifier Initializer

また、次も同様である。

ForStatement : for ( LexicalDeclaration Expressionopt ; Expressionopt ) Statement

は、次の便利な略記である。

ForStatement : for ( LexicalDeclaration ; Expressionopt ) Statement for ( LexicalDeclaration Expression ; Expressionopt ) Statement

これはさらに次の略記である。

ForStatement : for ( LexicalDeclaration ; ) Statement for ( LexicalDeclaration ; Expression ) Statement for ( LexicalDeclaration Expression ; ) Statement for ( LexicalDeclaration Expression ; Expression ) Statement

したがって、この例では nonterminal ForStatement は実際には 4 つの代替 right-hand side を持つ。

5.1.5.4 文法パラメータ

production は、定義される nonterminal 記号の接尾辞として現れる “[parameters]” 形式の下付き注記によってパラメータ化されてよい。“parameters” は単一の名前でも、コンマ区切りの名前列でもよい。パラメータ化された production は、パラメータ化された nonterminal 記号に、パラメータ名の前にアンダースコアを付けて追加した、パラメータ名のすべての組合せを定義する production 群の略記である。これは次を意味する。

StatementList[Return] : ReturnStatement ExpressionStatement

は、次の便利な略記である。

StatementList : ReturnStatement ExpressionStatement StatementList_Return : ReturnStatement ExpressionStatement

また、次も同様である。

StatementList[Return, In] : ReturnStatement ExpressionStatement

は、次の略記である。

StatementList : ReturnStatement ExpressionStatement StatementList_Return : ReturnStatement ExpressionStatement StatementList_In : ReturnStatement ExpressionStatement StatementList_Return_In : ReturnStatement ExpressionStatement

複数パラメータは組合せ的な数の production を生み、そのすべてが完全な文法内で実際に参照されるとは限らない。

production の right-hand side 上の nonterminal 参照もパラメータ化できる。たとえば、

StatementList : ReturnStatement ExpressionStatement[+In]

は、次と等価である。

StatementList : ReturnStatement ExpressionStatement_In

また、

StatementList : ReturnStatement ExpressionStatement[~In]

は、次と等価である。

StatementList : ReturnStatement ExpressionStatement

nonterminal 参照は、パラメータリストと “opt” 接尾辞の両方を持ってよい。たとえば、

VariableDeclaration : BindingIdentifier Initializer[+In]opt

は、次の略記である。

VariableDeclaration : BindingIdentifier BindingIdentifier Initializer_In

right-hand side の nonterminal 参照において、パラメータ名の前に “?” を付けると、そのパラメータ値は、現在の production の left-hand side 記号への参照におけるそのパラメータ名の有無に依存する。たとえば、

VariableDeclaration[In] : BindingIdentifier Initializer[?In]

は、次の略記である。

VariableDeclaration : BindingIdentifier Initializer VariableDeclaration_In : BindingIdentifier Initializer_In

right-hand side の選択肢の前に “[+parameter]” が付く場合、その選択肢は、その production の nonterminal 記号を参照する際に指定された parameter が用いられた場合にのみ利用可能である。right-hand side の選択肢の前に “[~parameter]” が付く場合、その選択肢は、その production の nonterminal 記号を参照する際に、その parameter が 用いられなかった 場合にのみ利用可能である。これは次を意味する。

StatementList[Return] : [+Return] ReturnStatement ExpressionStatement

は、次の略記である。

StatementList : ExpressionStatement StatementList_Return : ReturnStatement ExpressionStatement

また、次も同様である。

StatementList[Return] : [~Return] ReturnStatement ExpressionStatement

は、次の略記である。

StatementList : ReturnStatement ExpressionStatement StatementList_Return : ExpressionStatement

5.1.5.5 one of

文法定義において、コロンの後に “one of” という語が続く場合、それは次行または次行群にある各 terminal 記号が代替定義であることを示す。たとえば、ECMAScript の字句文法には次の production が含まれる。

NonZeroDigit :: one of 1 2 3 4 5 6 7 8 9

これは単に次の便利な略記である。

NonZeroDigit :: 1 2 3 4 5 6 7 8 9

5.1.5.6 [empty]

production の right-hand side として “[empty]” という句が現れる場合、それはその production の right-hand side に terminal も nonterminal も含まれないことを示す。

5.1.5.7 先読み制約

production の right-hand side に “[lookahead = seq]” という句が現れる場合、それは、直後の入力 token 列の接頭辞が token 列 seq である場合にのみ、その production を使用できることを示す。同様に、“[lookahead ∈ set]” で、set が有限非空の token 列集合である場合、その production は、set のいずれかの要素が直後の token 列の接頭辞である場合にのみ使用できる。便宜上、その集合は nonterminal として書かれてもよく、その場合それは、その nonterminal が展開しうるすべての token 列の集合を表す。その nonterminal が無限に多くの異なる token 列へ展開しうる場合、それは編集上の誤りとみなされる。

これらの条件は否定されてもよい。“[lookahead ≠ seq]” は、包含する production が、seq が直後の入力 token 列の接頭辞 ではない 場合にのみ使用できることを示し、“[lookahead ∉ set]” は、set のどの要素も直後の token 列の接頭辞 ではない 場合にのみ、その production を使用できることを示す。

例として、次の定義が与えられているとする。

DecimalDigit :: one of 0 1 2 3 4 5 6 7 8 9 DecimalDigits :: DecimalDigit DecimalDigits DecimalDigit

このとき、定義:

LookaheadExample :: n [lookahead ∉ { 1, 3, 5, 7, 9 }] DecimalDigits DecimalDigit [lookahead ∉ DecimalDigit]

は、文字 n に続いて最初の 1 文字が偶数である 1 個以上の 10 進数字が続くもの、または別の 10 進数字が後続しない単一の 10 進数字、のいずれかに一致する。

これらの句が構文文法で用いられる場合、後の位置でどの字句 goal symbol を用いるかを知る必要があるため、直後の token 列を曖昧さなく特定できないことがありうることに注意。そのため、これらが構文文法で用いられるとき、ある token 列 seq が先読み制約(列集合の一部として現れる場合を含む)に現れ、その結果の token 列において seq が接頭辞であるかどうかを字句 goal symbol の選択が変えうるならば、それは編集上の誤りとみなされる。

5.1.5.8 [no LineTerminator here]

構文文法の production の right-hand side に “[no LineTerminator here]” という句が現れる場合、それはその production が 制限付き production であることを示す。すなわち、示された位置で入力ストリーム中に LineTerminator が出現する場合、その production は使用できない。たとえば、production:

ThrowStatement : throw [no LineTerminator here] Expression ;

は、スクリプト中で throw token と Expression の間に LineTerminator が現れる場合、その production は使用できないことを示す。

LineTerminator の存在が制限付き production によって禁止されていない限り、入力要素ストリーム中の任意の 2 つの連続する token の間には、スクリプトの構文的受理可能性に影響を与えることなく、任意個の LineTerminator が現れてよい。

5.1.5.9 but not

production の right-hand side は、“but not” という句を用い、その後に除外される展開を示すことで、特定の展開が許されないことを指定してよい。たとえば、production:

Identifier :: IdentifierName but not ReservedWord

は、nonterminal Identifier が、IdentifierName を置き換えうる任意のコードポイント列で置き換えられてよいが、同じコードポイント列が ReservedWord を置き換えうる場合を除く、という意味である。

5.1.5.10 記述句

最後に、いくつかの nonterminal 記号は、すべての選択肢を列挙するのが実際的でない場合に、サンセリフ体の記述句によって説明される。

SourceCharacter :: 任意の Unicode コードポイント

5.2 アルゴリズム規約

この仕様では、アルゴリズムの手順を指定するために番号付きリストをしばしば用いる。これらのアルゴリズムは、ECMAScript 言語構成要素に要求される意味論を正確に規定するために用いられる。これらのアルゴリズムは、特定の実装技法の使用を示唆することを意図していない。実際には、ある機能を実装するために、より効率的なアルゴリズムが利用可能な場合がある。

アルゴリズムは、その位置で渡された引数を参照するためにアルゴリズム手順内で用いることができる別名の、順序付きかつコンマ区切りの列によって、明示的にパラメータ化されてよい。省略可能パラメータは、角括弧で囲むことで表される([ , name ])が、アルゴリズム手順内では必須パラメータと何ら異ならない。可変長パラメータはパラメータリストの末尾に現れてよく、先頭の省略記号(, ...name)によって示される。可変長パラメータは、必須および省略可能パラメータの後に与えられたすべての引数を List に取り込む。そのような追加引数が存在しない場合、その List は空である。

アルゴリズム手順は、順次的な下位手順に分割されてよい。下位手順はインデントされ、さらにその内部でより深い下位手順へ分割されてよい。アウトライン番号規約により、下位手順の第 1 レベルは小文字アルファベット、第 2 レベルは小文字ローマ数字で識別される。3 レベルを超える場合には、これらの規則が繰り返され、第 4 レベルでは数値ラベルが用いられる。たとえば、

  1. 最上位手順
    1. 下位手順。
    2. 下位手順。
      1. 下下位手順。
        1. 下下下位手順
          1. 下下下下位手順
            1. 下下下下下位手順

手順または下位手順は、その下位手順の適用条件となる “if” 述語として書かれてよい。この場合、その述語が真であるときにのみ下位手順が適用される。手順または下位手順が “else” という語で始まる場合、それは同じレベルにある直前の “if” 述語手順の否定である述語となる。

手順は “For each” または “Repeat” で始まり、その下位手順の反復適用を指定してよい。

Assert:” で始まる手順は、そのアルゴリズムの不変条件を表明する。そのような表明は、そうでなければ暗黙となるアルゴリズム上の不変条件を明示するために用いられる。同様に、“NOTE:” で始まる手順は、近接する手順に関連する文脈を提供する。Assert 手順および NOTE 手順は厳密には参考情報であり、追加の意味論的要件を加えないため、実装がそれらを検査する必要はない。

アルゴリズム手順は、“Let x be someValue” という形式を用いて任意の値に対する名前付き別名を宣言してよい。これらの別名は参照に似ており、xsomeValue の両方が同じ基底データを参照し、どちらへの変更も双方から見える。こうした参照的挙動を避けたいアルゴリズム手順は、右辺のコピーを明示的に作るべきである。“Let x be a copy of someValue” は someValue の浅いコピーを生成する。

一度宣言された別名は、それ以降の任意の手順で参照してよく、別名の宣言より前の手順から参照してはならない。別名は “Set x to someOtherValue” という形式で変更してよい。

5.2.1 評価順序

複雑な式がアルゴリズム手順に現れる場合、それらは左から右へ、内側から外側への順に評価されるものと理解される。たとえば、手順

  1. Return A(B(), C.[[D]]) + E(F()).

は、次と等価である。

  1. Let tmp1 be B().
  2. Let tmp2 be C.[[D]].
  3. Let tmp3 be A(tmp1, tmp2).
  4. Let tmp4 be F().
  5. Let tmp5 be E(tmp4).
  6. Let tmp6 be tmp3 + tmp5.
  7. Return tmp6.

ここで、各種 tmpN 別名は一時的なものであり、これらの手順内でのみ可視である。

5.2.2 抽象操作

この仕様の複数箇所での利用を容易にするために、一部のアルゴリズムは、abstract operation と呼ばれ、名前付きかつパラメータ化された関数形式で書かれる。これにより、他のアルゴリズム内から名前で参照できる。abstract operation は通常、OperationName(arg1, arg2) のような関数適用スタイルで参照される。一部の abstract operation は、クラス様の仕様抽象の多相ディスパッチされるメソッドとして扱われる。そのようなメソッド様 abstract operation は通常、someValue.OperationName(arg1, arg2) のようなメソッド適用スタイルで参照される。

5.2.3 構文指向操作

syntax-directed operation とは、その定義が ECMAScript 文法のいずれかの 1 つ以上の production に関連付けられたアルゴリズム群から成る名前付き操作である。複数の代替定義を持つ production には、通常、各代替ごとに別個のアルゴリズムがある。アルゴリズムが文法 production に関連付けられている場合、それはその production 代替の terminal 記号および nonterminal 記号を、あたかもアルゴリズムのパラメータであるかのように参照してよい。このように用いられるとき、nonterminal 記号は、ソーステキスト解析時に一致した実際の代替定義を参照する。文法 production、またはそれから導出された Parse Node一致するソーステキスト とは、その一致に関与した最初の terminal の先頭から、最後の terminal の末尾までのソーステキスト部分である。

アルゴリズムが production の代替に関連付けられている場合、その代替は通常、いかなる “[ ]” 文法注釈も付けずに示される。そのような注釈は代替の構文的認識にのみ影響し、代替に関連付けられた意味論には影響しない。

syntax-directed operation は、parse node と、任意でその他のパラメータを用いて、以下のアルゴリズムの手順 13、および 4 にある規約により呼び出される。

  1. Let status be SyntaxDirectedOperation of SomeNonTerminal.
  2. Let someParseNode be the parse of some source text.
  3. Perform SyntaxDirectedOperation of someParseNode.
  4. Perform SyntaxDirectedOperation of someParseNode with argument "value".

明示的に別段の指定がない限り、すべての chain production は、その production の left-hand side nonterminal に適用されうるあらゆる operation について暗黙の定義を持つ。暗黙の定義は、同じ operation を、同じパラメータがあるならそれとともに、その chain production の唯一の right-hand side nonterminal に再適用し、その結果を返すだけである。たとえば、あるアルゴリズムに “Return Evaluation of Block” という形式の手順があり、かつ次の production があるとする。

Block : { StatementList }

しかし Evaluation operation がその production にアルゴリズムを関連付けていない場合、そのとき Evaluation operation には暗黙的に次のような関連付けが含まれる。

Runtime Semantics: Evaluation

Block : { StatementList }
  1. Return Evaluation of StatementList.

5.2.4 実行時意味論

実行時に呼び出されなければならない意味論を規定するアルゴリズムは、runtime semantics と呼ばれる。runtime semantics は、abstract operation または syntax-directed operation によって定義される。

5.2.4.1 Completion ( completionRecord )

The abstract operation Completion takes argument completionRecord (a Completion Record) and returns a Completion Record. Completion Record が返されることを強調するために用いられる。 It performs the following steps when called:

  1. Assert: completionRecord is a Completion Record.
  2. Return completionRecord.

5.2.4.2 Throw

アルゴリズム手順において、"throw" という語は ThrowCompletion を呼び出した結果を返すことの略記である。たとえば、

  1. If result.[[Error]] is not none, throw result.[[Error]].

は、次と等価である。

  1. If result.[[Error]] is not none, return ThrowCompletion(result.[[Error]]).

特定の型の例外を投げるよう述べるアルゴリズム手順は、その型の例外を構築して投げる。たとえば、

  1. Throw a TypeError exception.

は、次と等価である。

  1. Return ThrowCompletion(a newly created TypeError object).

5.2.4.3 Completion Record を展開するための略記

接頭辞 ? および ! は、Completion Record を展開する略記として用いられる。?abrupt completion を呼出し元へ伝播するか、そうでなければ normal completion を展開するために用いられる。!Completion Record が normal であることを表明して展開するために用いられる。形式的には、手順

  1. Let result be ? record.

は、次と等価である。

  1. Assert: record is a Completion Record.
  2. If record is an abrupt completion, return record.
  3. Let result be record.[[Value]].

同様に、手順

  1. Let result be ! record.

は、次と等価である。

  1. Assert: record is a normal completion.
  2. Let result be record.[[Value]].

? または ! が他の文脈で用いられる場合、まず 評価順序 で与えられる書き換えを、この規則が適用できるようになるまで適用し、その後この規則を適用する。たとえば、手順

  1. Perform AO(? Other()).

は、次のように書き換えられる。

  1. Let tmp1 be Other().
  2. Let tmp2 be ? tmp1.
  3. Perform AO(tmp2).

これはさらに次のように展開される。

  1. Let tmp1 be Other().
  2. Assert: tmp1 is a Completion Record.
  3. If tmp1 is an abrupt completion, return tmp1.
  4. Let tmp2 be tmp1.[[Value]].
  5. Perform AO(tmp2).

5.2.4.4 暗黙の Normal Completion

Completion Record を返すと宣言された abstract operation 内のアルゴリズム、およびすべての built-in function 内では、返される値はまず NormalCompletion に渡され、その結果が代わりに用いられる。この規則は Completion アルゴリズム内では適用されず、またその手順で返される値が明らかに Completion Record として印付けされている場合にも適用されない。そのような場合とは次である。

そのような abstract operation から、他のいかなる手段によっても Completion Record が返される場合、それは編集上の誤りである。たとえば、これらの abstract operation 内では、

  1. Return true.

は、次のいずれとも同じ意味である。

  1. Return NormalCompletion(true).

または

  1. Let completion be NormalCompletion(true).
  2. Return Completion(completion).

または

  1. Return Completion Record { [[Type]]: normal, [[Value]]: true, [[Target]]: empty }.

? 略記の展開 によって、次の例は許容されることに注意。というのも、展開後の手順では abrupt の場合に Completion を適用した結果が直接返され、normal の場合には展開後に暗黙の NormalCompletion 適用が起こるからである。

  1. Return ? completion.

次の例は、その手順において注記されることなく Completion Record が返されているため、編集上の誤りである。

  1. Let completion be NormalCompletion(true).
  2. Return completion.

5.2.5 静的意味論

文脈自由文法は、入力要素ストリームが評価可能な有効な ECMAScript Script または Module を形成するかどうかを定義するすべての規則を表現するには十分に強力ではない。状況によっては、ECMAScript のアルゴリズム規約または文章による要件のいずれかを用いて表現できる追加規則が必要である。そのような規則は常に文法の production に関連付けられ、その production の static semantics と呼ばれる。

Static Semantic Rule には名前があり、通常はアルゴリズムを用いて定義される。名前付き Static Semantic Rule は文法 production に関連付けられ、複数の代替定義を持つ production では、通常、適用可能な各名前付き static semantic rule について、各代替ごとに別個のアルゴリズムがある。

static semantic rule の特別な種類として Early Error Rule がある。early error rule は、特定の文法 production に関連付けられる early error 条件(節 17 を参照)を定義する。ほとんどの early error rule の評価は、この仕様のアルゴリズム内で明示的に呼び出されない。適合実装は、Script または Module の最初の評価に先立ち、その Script または Module の解析に用いられた production のすべての early error rule を検証しなければならない。いずれかの early error rule に違反している場合、その Script または Module は無効であり、評価できない。

5.2.6 数学的演算

この仕様は、以下の種類の数値を参照する。

  • Mathematical values: デフォルトの数値型として用いられる任意の実数。
  • Extended mathematical values: Mathematical values に +∞ および -∞ を加えたもの。
  • Numbers: IEEE 754-2019 binary64(倍精度浮動小数点)値。
  • BigInts: 任意の整数を 1 対 1 に対応させて表す ECMAScript 言語値

この仕様の言語では、数値は下付き接尾辞を用いて異なる数値種別の間で区別される。下付き 𝔽 は Number を指し、下付き は BigInt を指す。下付き接尾辞のない数値は mathematical value を指す。この仕様は大半の数値を 10 進で表記するが、0x に続いて 0-9 または A-F の数字が現れる形式の数値も 16 進値として用いる。

一般に、この仕様が、たとえば “the length of y” や “the integer represented by the four hexadecimal digits ...” のように、数値の種別を明示せずに数値を参照する場合、その句は mathematical value を指す。Number または BigInt 値を参照する句は、明示的にその旨が注記される。たとえば “the Number value for the number of code points in …” や “the BigInt value for …” のように。

この仕様で integer という用語が用いられる場合、別段の記述がない限り、それは整数集合に属する mathematical value を指す。この仕様で integral Number という用語が用いられる場合、それはその mathematical value が整数集合に属する有限の Number 値を指す。

+, ×, =, ≥ のような数値演算子は、オペランドの型によって決定される演算を指す。mathematical value に適用されるとき、これらの演算子は通常の数学演算を指す。extended mathematical value に適用されるとき、これらの演算子は拡張実数上の通常の数学演算を指し、不定形は定義されず、この仕様におけるその使用は編集上の誤りとみなされる。Number に適用されるとき、これらの演算子は IEEE 754-2019 における対応する演算を指す。BigInt に適用されるとき、これらの演算子は BigInt の mathematical value に適用される通常の数学演算を指す。異なる型のオペランド(たとえば Number と mathematical value)に適用される数値演算子は定義されず、この仕様では編集上の誤りとみなされる。

mathematical value と Number または BigInt の間の変換は、この文書では常に明示的である。mathematical value または extended mathematical value x から Number への変換は、“the Number value for x” または 𝔽(x) と表され、6.1.6.1 で定義される。integer x から BigInt への変換は、“the BigInt value for x” または ℤ(x) と表される。Number または BigInt x から mathematical value への変換は、“the mathematical value of x” または ℝ(x) と表される。+0𝔽 および -0𝔽mathematical valuemathematical value 0 である。非有限値の mathematical value は定義されない。xextended mathematical value of とは、有限値については xmathematical value であり、+∞𝔽 および -∞𝔽 についてはそれぞれ +∞ および -∞ である。NaN については定義されない。

数学関数 abs(x)x の絶対値を生成し、x < 0 のときは -x、そうでなければ x 自身を生成する。

数学関数 ln(x)x の自然対数を生成する。数学関数 log10(x)x の 10 を底とする対数を生成する。数学関数 log2(x)x の 2 を底とする対数を生成する。

数学関数 min(x1, x2, … , xN)x1 から xN までのうち数学的に最小のものを生成する。数学関数 max(x1, x2, ..., xN)x1 から xN までのうち数学的に最大のものを生成する。これらの数学関数の定義域および値域は extended mathematical value である。

記法 “x modulo y”(y は有限かつ非零でなければならない)は、y と同符号(または零)の値 k を計算する。ここで abs(k) < abs(y) and x - k = q × y を満たす integer q が存在する。

“the result of clamping x between lower and upper” という句(ここで xextended mathematical valuelower および upperlowerupper を満たす mathematical value である)は、x < lower なら lower を、x > upper なら upper を、それ以外なら x を生成する。

数学関数 floor(x) は、x を超えない最大の integer(+∞ に最も近いもの)を生成する。

Note

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

数学関数 truncate(x) は、0 方向への丸めによって x の小数部分を除去する。x < 0 のときは -floor(-x) を生成し、それ以外では floor(x) を生成する。

数学関数 minmaxabsfloor、および truncate は Number や BigInt に対しては定義されず、数学的値でない引数にそれらのメソッドを用いるいかなる使用も、この仕様では編集上の誤りである。

下限 a から上限 b までの interval とは、同じ数値型の数値の、無限である場合も空である場合もある集合である。各境界は inclusive または exclusive のいずれかとして記述され、両方ではない。interval には次の 4 種類がある。

  • a(inclusive)から b(inclusive)までの interval は、a から b までの inclusive interval とも呼ばれ、同じ数値型の値 x のうち axb を満たすすべての値を含み、それ以外を含まない。
  • a(inclusive)から b(exclusive)までの interval は、同じ数値型の値 x のうち ax < b を満たすすべての値を含み、それ以外を含まない。
  • a(exclusive)から b(inclusive)までの interval は、同じ数値型の値 x のうち a < xb を満たすすべての値を含み、それ以外を含まない。
  • a(exclusive)から b(exclusive)までの interval は、同じ数値型の値 x のうち a < x < b を満たすすべての値を含み、それ以外を含まない。

たとえば、1(inclusive)から 2(exclusive)までの interval は、1 を含み 2 を含まない、1 と 2 の間のすべての mathematical value から成る。interval を定義する目的では、-0𝔽 < +0𝔽 である。したがって、たとえば下限が +0𝔽inclusive interval+0𝔽 を含むが -0𝔽 は含まない。NaNinterval に決して含まれない。

5.2.7 値の記法

この仕様では、ECMAScript 言語値bold で表示される。例には nulltrue、または "hello" がある。これらは Function.prototype.applylet n = 42; のような ECMAScript ソーステキストと区別される。

5.2.8 同一性

この仕様では、仕様値と ECMAScript 言語値の両方について等価性比較が行われる。等価性比較において、値は 2 つのカテゴリのいずれかに属する。同一性を持たない値 は、その本来的特性がすべて同じであるなら、他の同一性を持たない値と等しい。本来的特性とは、整数の大きさや列の長さのような特性である。同一性を持たない値は、その特性を完全に記述することによって、事前参照なしに顕現させることができる。これに対し、各 同一性を持つ値 は一意であり、したがって自分自身としか等しくない。同一性を持つ値は、同一性を持たない値に似ているが、さらに identity と呼ばれる、推測不可能・不変・普遍的一意の追加特性を持つ。既存の同一性を持つ値への参照は、その同一性自体が記述不可能であるため、単に記述するだけでは顕現できない。代わりに、それらの値への参照は、ある場所から別の場所へ明示的に渡されなければならない。同一性を持つ値の中には可変なものがあり、その場合、その特性(同一性を除く)はその場で変更されうるため、その値の保持者全員が新しい特性を観測することになる。同一性を持たない値が、同一性を持つ値と等しくなることは決してない。

この仕様の観点からは、“is” という語は 2 つの値を等価性比較するために用いられる。たとえば “If bool is true, then ...” のように。“contains” という語は、等価性比較を用いて list の中から値を探すために用いられる。たとえば "If list contains a Record r such that r.[[Foo]] is true, then ..." のように。値の specification identity がこれらの比較結果を決定し、それはこの仕様における公理である。

ECMAScript 言語の観点からは、言語値は SameValue 抽象操作およびそれが推移的に呼び出す抽象操作を用いて等価性比較される。これらの比較抽象操作のアルゴリズムが、ECMAScript 言語値language identity を決定する。

仕様値について、specification identity を持たない値の例には、これに限られないが、mathematical value および extended mathematical valueECMAScript ソーステキストsurrogate pairDirective Prologue など、UTF-16 code unit、Unicode コードポイント、enumsyntax-directed operationhost hook などを含む abstract operation、そして ordered pair がある。specification identity を持つ仕様値の例には、これに限られないが、Property DescriptorPrivateElement などを含むあらゆる種類の RecordParse NodeListSetRelationAbstract ClosureData BlockPrivate Nameexecution contextexecution context stackagent signifier、および WaiterList Record がある。

specification identity は、Symbol.for によって生成される Symbol 値を除くすべての ECMAScript 言語値について language identity と一致する。specification identity も language identity も持たない ECMAScript 言語値は、undefinednullBooleanStringNumber、および BigInt である。specification identity と language identity の両方を持つ ECMAScript 言語値は、Symbol のうち Symbol.for によって生成されないものと、Object である。Symbol.for によって生成される Symbol 値は specification identity を持つが、language identity は持たない。