|
JavaScript 2.0
Formal Description
Semantic Notation
|
Wednesday, May 12, 1999
To precisely specify the semantics of JavaScript 2.0, we use the notation described below to define the behavior of all JavaScript 2.0 constructs and their interactions.
The semantics describe the meaning of a JavaScript 2.0 program in terms of operations on simpler objects called semantic values. These semantic values include, among others, booleans, integers, rational numbers, characters, and strings.
Semantic values are held in semantic variables and can be passed to semantic functions. For documentation purposes we declare the semantic type of each semantic variable and function. A semantic type is a set of all semantic values that can be held in a semantic variable. Names of semantic types are shown in Capitalized Red Small Caps (if your browser supports them), and compound semantic type expressions are in red.
There is a special semantic value (pronounced as "bottom") that represents the result of an inconsistent or nonterminating computation. is a member of every semantic type. Unless specified otherwise, applying any semantic operator (such as +, *, etc.) to or calling a semantic function with as any argument also yields (in technical terms, semantic functions and operators are strict in all of their arguments unless specified otherwise).
If interpreting a JavaScript program according to the semantics here gives a result, an actual implementation executing that JavaScript program might signal a syntax error, throw an exception, fail to terminate, or return an implementation-defined result. Explanatory notes in the semantics specify in each case which of these behaviors an implementation should exhibit.
Semantic functions that do not return a useful value return the semantic value unit. The semantic type of unit is Void. There are no operations defined on unit.
The semantic type Boolean provides the semantic values true and false.
Let a and b be be two Boolean expressions. We use the following notation to indicate logical operations:
Like most other operators, and, or, and xor evaluate both operands before returning a result; these operators do not short-circuit. If either operand is , the result is also .
Unless specified otherwise, numbers in the semantics written without a slash or decimal point are mathematical integers: ..., -3, -2, -1, 0, 1, 2, 3, .... The infinite set of all integers is called Integer.
Let i and j be be two Integer expressions. We use the following notation to indicate arithmetic operations:
In addition to the operators above, all of the operators on rationals, such as division and comparisons, are also available for integers.
Numbers in the semantics written with a slash are mathematical rational numbers. Every integer is also a rational. Rational numbers include 0, 1, 2, -1, 1/2, -12/7, and -24/14; the last two are different ways of writing the same rational number. The infinite set of all rational numbers is called Rational, and it has Integer as a subtype.
Let x and y be be two Rational expressions. We use the following notation to indicate arithmetic operations:
Numbers in the semantics written with a decimal point are double-precision IEEE floating-point numbers, including distinct +0.0, -0.0, +, -, and NaN. The finite set of all of these numbers is called Double. These numbers are disjoint from integers and rationals; when writing Double numbers in the semantics, we always include a decimal point to distinguish them from Integer and Rational numbers.
We write single Unicode 16-bit code points enclosed in single quotes
and . The semantic type Character
is the set of all 65536 Unicode 16-bit code points: «u0000»,
«u0001»,
...,A,
B,
C,
..., «uFFFF»
(see also notation for non-ASCII characters).
Let c be a Character and i be an Integer. We use the following notation to indicate conversions between characters and integers:
| Notation | Result Type | Result Value |
|---|---|---|
| characterToCode(c) | Integer | The number of the Unicode code point c. |
| codeToCharacter(i) | Integer | The Unicode code point number c, or if i<0 or i>65535. |
A semantic vector contains zero or more elements, each of which is a semantic value of type t. The semantic type of vectors whose elements have type t is t[]. We write a vector value by enclosing a list of comma-separated values inside bold brackets:
[element0, element1, ... , elementn-1]t
The subscript following the close bracket denotes the type t of the vector's elements. We omit this subscript when the type is clear from context.
For example, the following semantic value is a vector of four strings and has the semantic type String[]:
[parsley, sage, rosemary, thyme]String
Let v = [e0, e1, ... , en-1]t, w = [f0, f1, ... , fm-1]u, and i be an integer. We use the following notation to indicate operations on vectors:
A semantic string is merely a vector of characters. The semantic type String is equivalent to Character[]. For notational convenience we can write a string literal as zero or more characters enclosed in double quotes. Thus,
Wonder«LF»
is equivalent to:
[W, o, n, d, e, r, «LF»]Character
In addition to the vector operations above, we can compare two Strings c and d for equality:
| Notation | Result Type | Result Value |
|---|---|---|
| c = d | Boolean | true if length(c) = length(d), and for every integer i between 0 inclusive and length(c) exclusive, c[i] = d[i]. |
A semantic tuple is an aggregate of several named semantic values with distinct semantic types. Tuples are sometimes called records or structures in other languages. A tuple's semantic type is written as
tuple {name1: type1; name2: type2; ... ; namen: typen}
where each namei is an identifier that names a field and each typei is the corresponding field's type.
Let t be the tuple type above. We write a tuple value of type t using the notation
f1, f2, ... , fnt
where each fi is an expression of type typei that gives the corresponding field's value. The subscript following the close bracket denotes the tuple type t.
Let w be an expression that evaluates to a tuple f1, f2, ... , fnt. We use the following notation to access its fields:
In the HTML versions of the semantics, each use of namei is linked back to its tuple type's definition.
A semantic oneof is a disjoint union of several named semantic values with distinct semantic types. Oneofs are sometimes called variants or tagged unions in other languages. A oneof's semantic type is written as
oneof {name1: type1; name2: type2; ... ; namen: typen}
where each namei is an identifier that names an alternative and each typei is the corresponding alternative's type. For brevity, if some typei is Void, we may omit that typei and its preceding colon when writing the oneof type.
Let t be the oneof type above. A oneof value of type t can hold exactly one of its alternatives. We write a oneof value of type t as
namei t a
where a is an expression of type typei that gives the corresponding alternative's value. The subscript following namei denotes the oneof type t. For brevity, we omit this subscript when the type is clear from context. We also sometimes omit the value a when it is unit.
Let o be an expression that evaluates to a oneof namei t a. We use the following notation to access o's alternative. In addition to these, the case statement evaluates one of several expressions based on a oneof alternative.
| Notation | Result Type | Result Value |
|---|---|---|
| w is namej | Boolean | true if i=j; false if ij. |
| w.namej | typej | The value a if i=j, or if ij. |
In the HTML versions of the semantics, each use of namei is linked back to its oneof type's definition.
A semantic function performs operations and/or returns a result computed from its arguments. We write a semantic function with parameters .
The table below lists the semantic operators's precedences from highest (tightest-binding) to lowest (loosest-binding). Operators on the same level of the table have the same precedence and associate left-to-right, so, for example, 7-3-2 is interpreted as (7-3)-2 instead of 7-(3-2). When needed, parentheses are used to group expressions.
A grammar can give a new name to a semantic type t by using the type definition, which should have the form:
type name = t
For example, the following notation defines RegExp as a shorthand for tuple {reBody: String; reFlags: String}:
type RegExp = tuple {reBody: String; reFlags: String}
In the HTML versions of the semantics, each reference to the semantic type name name is linked back to name's definition.