April 2002 Draft
JavaScript 2.0
Core Language
Expressions
previousupnext

Tuesday, December 18, 2001

Most of the behavior of expressions is the same as in JavaScript 1.5. Differences are highlighted below. One general difference is that most expression operators can be overridden.

  {allowInnoIn}

Identifiers

Identifier 
   Identifier
|  get
|  set
|  exclude
|  include
|  named

The above keywords are not reserved and may be used in identifiers.

Qualified Identifiers

Qualifier 
   Identifier
|  public
|  private
SimpleQualifiedIdentifier 
   Identifier
|  Qualifier :: Identifier
ExpressionQualifiedIdentifier  ParenExpression :: Identifier
QualifiedIdentifier 
   SimpleQualifiedIdentifier
|  ExpressionQualifiedIdentifier

Just like in ECMAScript Edition 3, an identifier evaluates to an internal data structure called a reference. However, JavaScript 2.0 references can be qualified by a qualifier, which, in the general syntax, is a ParenExpression that must be a compile-time constant expression that evaluates to a namespace. For convenience, if the ParenExpression consists of a single identifier, the parentheses may be omitted: (a)::m may be written as a::m.

The reserved words public and private may also be used as qualifiers. public evaluates to the public namespace. internal (which is not a reserved word) evaluates to the containing package’s anonymous namespace. private can only be used inside a class and evaluates to the containing class’s anonymous namespace.

See the name lookup section for more information on the :: operator.

Unit Expressions

UnitExpression 
   ParenListExpression
|  Number [no line break] String
|  UnitExpression [no line break] String

A Number literal, ParenListExpression, or UnitExpression followed by a String literal is a unit expression, which is evaluated as follows:

Evaluate the String literal to obtain a string S. Parse that string according to the unit grammar and semantics to obtain a list of identifiers and exponents [id1e1, id2e2, ..., idnen]. If the parse fails, signal a syntax error. If the list is empty, let U be the function nullUnit, which accepts one required and one optional argument and returns its first argument, ignoring the optional argument.

If the list is not empty, for each i between 1 and n, let Vi be the value of looking up the class property idi of the Unit class. If ei is 1, let Fi = Vi; otherwise, let Fi = Vi.pow(ei). Then let U = F1*F2*...*Fn. For example, if S is "Kg*m^2/s^2*q", then U is the value of Unit.Kg*Unit.m.pow(2)*Unit.s.pow(–2)*Unit.q.pow(–1).

The result U should be callable as a function that accepts one required and one optional argument. The unit expression calls U, providing the numeric value of the Number literal, ParenListExpression, or UnitExpression as the first argument. The second argument is present only for the UnitExpression  Number [no line break] String production, in which case it is the original Number literal expressed as a string. Continuing the example above, the unit expression 32.50 "Kg*m^2/s^2*q", evaluates to the result of (Unit.Kg*Unit.m.pow(2)*Unit.s.pow(–2)*Unit.q.pow(–1))(32.5, "32.50").

U’s second argument allows user-defined unit classes to define extended syntaxes for numbers. For instance, a long-integer package might define a unit called "L" that treats the Number literal as a full 64-bit number without rounding it to a float64 first. Such a unit can be combined with other units by listing the units one after another; note that the lexer allows the first unit to be unquoted if it directly follows the number: 3L "cm" is the same as 3 "L" "cm" and evaluates to the result of Unit.cm(Unit.L(3, "3")).

The Unit class is predefined by the system. A program can define additional units by using a class extension. The unit attribute is conveniently provided to make a definition into a class extension. For example:

unit const µm = Unit.m/1e6;
unit const Å = Unit.m/1e10;
unit const dm = Unit.m/10;
unit const \_in = Unit.m*0.0254;
unit const liter = Unit.dm.pow(3);

\_ must be used to define the unit in because in is a reserved word. However, the unit in may be used without quoting it, as in the expression 3in + 5cm.

Primary Expressions

PrimaryExpression 
   null
|  true
|  false
|  public
|  Number
|  String
|  this
|  RegularExpression
|  UnitExpression
|  ArrayLiteral
|  ObjectLiteral
|  FunctionExpression
ParenExpression  ( AssignmentExpressionallowIn )
ParenListExpression 
   ParenExpression
|  ( ListExpressionallowIn , AssignmentExpressionallowIn )

public evaluates to the public namespace.

this may only be used in methods, constructors, or functions with the prototype attribute set.

Function Expressions

FunctionExpression 
   function FunctionSignature Block
|  function Identifier FunctionSignature Block

A FunctionExpression creates and returns an anonymous function.

Object Literals

ObjectLiteral 
   { }
|  { FieldList }
FieldList 
   LiteralField
|  FieldList , LiteralField
LiteralField  FieldName : AssignmentExpressionallowIn
FieldName 
   Identifier
|  String
|  Number

A ParenExpression must evaluate to a string.

Array Literals

ArrayLiteral  [ ElementList ]
ElementList 
   LiteralElement
|  ElementList , LiteralElement
LiteralElement 
   «empty»
|  AssignmentExpressionallowIn

Super Expressions

SuperExpression 
   super
|  FullSuperExpression
FullSuperExpression  super ParenExpression

super, which may only be used inside a class C, can be applied to a subexpression that evaluates to an instance v of C. That subexpression can be either a ParenExpression or omitted, in which case it defaults to this.

As specified in the grammar below, the SuperExpression must be embedded as an operand to one of the following operators:

super changes the behavior of the operator in which it is embedded by limiting its property search to definitions inherited from class C’s superclass. See property lookup and operator dispatch.

Postfix Expressions

PostfixExpression 
   AttributeExpression
|  FullPostfixExpression
|  ShortNewExpression
PostfixExpressionOrSuper 
   PostfixExpression
|  SuperExpression
AttributeExpression 
   SimpleQualifiedIdentifier
|  AttributeExpression MemberOperator
|  AttributeExpression Arguments
FullPostfixExpression 
   PrimaryExpression
|  ExpressionQualifiedIdentifier
|  FullNewExpression
|  FullPostfixExpression MemberOperator
|  SuperExpression DotOperator
|  FullPostfixExpression Arguments
|  FullSuperExpression Arguments
|  PostfixExpressionOrSuper [no line break] ++
|  PostfixExpressionOrSuper [no line break] --
FullNewExpression 
   new FullNewSubexpression Arguments
|  new FullSuperExpression Arguments
FullNewSubexpression 
   PrimaryExpression
|  QualifiedIdentifier
|  FullNewExpression
|  FullNewSubexpression MemberOperator
|  SuperExpression DotOperator
ShortNewExpression 
   new ShortNewSubexpression
|  new SuperExpression
ShortNewSubexpression 
   FullNewSubexpression
|  ShortNewExpression

A SimpleQualifiedIdentifier or ExpressionQualifiedIdentifier expression id resolves to the binding of id in the innermost enclosing scope that has a visible binding of id. If a qualifier q is present before the id, then the QualifiedIdentifier expression resolves to the binding of id in the innermost enclosing scope that has a visible binding of id in the namespace q.

Member Operators

MemberOperator 
   DotOperator
|  . ParenExpression
DotOperator 
   . QualifiedIdentifier
|  Brackets

The . operator accepts a QualifiedIdentifier as the second operand and performs a property lookup.

The [] operator can take multiple (or even named) arguments. This allows programmers to define data structures such as multidimensional arrays via operator overriding.

Unless the [] operator is overridden for an object o, the expression o[m] explicitly coerces m to a String s and returns the result of o.s, limiting the name lookup to the public indexable properties of o. See property lookup.

Brackets 
   [ ]
|  [ ListExpressionallowIn ]
|  [ NamedArgumentList ]
Arguments 
   ParenExpressions
|  ( NamedArgumentList )
ParenExpressions 
   ( )
|  ParenListExpression
NamedArgumentList 
   LiteralField
|  ListExpressionallowIn , LiteralField
|  NamedArgumentList , LiteralField

A list of arguments can contain both positional and named arguments. The positional arguments are the subexpressions separated by commas within the ListExpressionallowIn. Named arguments use the same syntax as object literals. All strings except those consisting entirely of digits are legal for argument names. No two arguments may have the same name. The order of named arguments is immaterial.

Unary Operators

UnaryExpression 
   PostfixExpression
|  delete PostfixExpression
|  void UnaryExpression
|  typeof UnaryExpression
|  ++ PostfixExpressionOrSuper
|  -- PostfixExpressionOrSuper
|  + UnaryExpressionOrSuper
|  - UnaryExpressionOrSuper
|  ~ UnaryExpressionOrSuper
|  ! UnaryExpression
UnaryExpressionOrSuper 
   UnaryExpression
|  SuperExpression

The typeof operator is deprecated. It returns a string as in JavaScript 1.5. To get the type of an object x, use x.class instead.

Multiplicative Operators

MultiplicativeExpression 
   UnaryExpression
|  MultiplicativeExpressionOrSuper * UnaryExpressionOrSuper
|  MultiplicativeExpressionOrSuper / UnaryExpressionOrSuper
|  MultiplicativeExpressionOrSuper % UnaryExpressionOrSuper
MultiplicativeExpressionOrSuper 
   MultiplicativeExpression
|  SuperExpression

Additive Operators

AdditiveExpression 
   MultiplicativeExpression
|  AdditiveExpressionOrSuper + MultiplicativeExpressionOrSuper
|  AdditiveExpressionOrSuper - MultiplicativeExpressionOrSuper
AdditiveExpressionOrSuper 
   AdditiveExpression
|  SuperExpression

Bitwise Shift Operators

ShiftExpression 
   AdditiveExpression
|  ShiftExpressionOrSuper << AdditiveExpressionOrSuper
|  ShiftExpressionOrSuper >> AdditiveExpressionOrSuper
|  ShiftExpressionOrSuper >>> AdditiveExpressionOrSuper
ShiftExpressionOrSuper 
   ShiftExpression
|  SuperExpression

Relational Operators

RelationalExpressionallowIn 
   ShiftExpression
|  RelationalExpressionOrSuperallowIn < ShiftExpressionOrSuper
|  RelationalExpressionOrSuperallowIn > ShiftExpressionOrSuper
|  RelationalExpressionOrSuperallowIn <= ShiftExpressionOrSuper
|  RelationalExpressionOrSuperallowIn >= ShiftExpressionOrSuper
|  RelationalExpressionallowIn is ShiftExpression
|  RelationalExpressionallowIn as ShiftExpression
|  RelationalExpressionallowIn in ShiftExpressionOrSuper
|  RelationalExpressionallowIn instanceof ShiftExpression
RelationalExpressionnoIn 
   ShiftExpression
|  RelationalExpressionOrSupernoIn < ShiftExpressionOrSuper
|  RelationalExpressionOrSupernoIn > ShiftExpressionOrSuper
|  RelationalExpressionOrSupernoIn <= ShiftExpressionOrSuper
|  RelationalExpressionOrSupernoIn >= ShiftExpressionOrSuper
|  RelationalExpressionnoIn is ShiftExpression
|  RelationalExpressionnoIn as ShiftExpression
|  RelationalExpressionnoIn instanceof ShiftExpression
RelationalExpressionOrSuper 
   RelationalExpression
|  SuperExpression

The expression a is b takes an expression that must evaluate to a type as its second operand b. When a is not null, the expression a is b returns true if a is a member of type b and false otherwise; this is equivalent to testing whether a can be stored in a variable of type b without coercion. When a is null, a is b behaves analogously to method dispatch and returns true if b is either Object or Null and false otherwise. As a special case, when a is –0.0 and b is sbyte, byte, short, ushort, int, or uint, a is b returns true.

The expression a as b returns a if a is a member of type b. Otherwise, if a can be implicitly coerced to type b, then the result is the result of that implicit coercion. Otherwise, a as b returns null if null is a member of type b or throws an exception otherwise. In any case b must evaluate to a type.

The instanceof operator is deprecated and behaves in the same way as in JavaScript 1.5 — a instanceof b follows a’s prototype chain.

Equality Operators

EqualityExpression 
   RelationalExpression
|  EqualityExpressionOrSuper == RelationalExpressionOrSuper
|  EqualityExpressionOrSuper != RelationalExpressionOrSuper
|  EqualityExpressionOrSuper === RelationalExpressionOrSuper
|  EqualityExpressionOrSuper !== RelationalExpressionOrSuper
EqualityExpressionOrSuper 
   EqualityExpression
|  SuperExpression

Binary Bitwise Operators

BitwiseAndExpression 
   EqualityExpression
|  BitwiseAndExpressionOrSuper & EqualityExpressionOrSuper
BitwiseXorExpression 
   BitwiseAndExpression
|  BitwiseXorExpressionOrSuper ^ BitwiseAndExpressionOrSuper
BitwiseOrExpression 
   BitwiseXorExpression
|  BitwiseOrExpressionOrSuper | BitwiseXorExpressionOrSuper
BitwiseAndExpressionOrSuper 
   BitwiseAndExpression
|  SuperExpression
BitwiseXorExpressionOrSuper 
   BitwiseXorExpression
|  SuperExpression
BitwiseOrExpressionOrSuper 
   BitwiseOrExpression
|  SuperExpression

Binary Logical Operators

LogicalAndExpression 
   BitwiseOrExpression
|  LogicalAndExpression && BitwiseOrExpression
LogicalXorExpression 
   LogicalAndExpression
|  LogicalXorExpression ^^ LogicalAndExpression

The ^^ operator is a logical exclusive-or operator. It evaluates both operands. If they both convert to true or both convert to false, then ^^ returns false; otherwise ^^ returns the unconverted value of whichever argument converted to true.

LogicalOrExpression 
   LogicalXorExpression
|  LogicalOrExpression || LogicalXorExpression

Conditional Operator

ConditionalExpression 
   LogicalOrExpression
|  LogicalOrExpression ? AssignmentExpression : AssignmentExpression
NonAssignmentExpression 
   LogicalOrExpression
|  LogicalOrExpression ? NonAssignmentExpression : NonAssignmentExpression

Assignment Operators

AssignmentExpression 
   ConditionalExpression
|  PostfixExpression = AssignmentExpression
|  PostfixExpressionOrSuper CompoundAssignment AssignmentExpression
|  PostfixExpressionOrSuper CompoundAssignment SuperExpression
|  PostfixExpression LogicalAssignment AssignmentExpression
CompoundAssignment 
   *=
|  /=
|  %=
|  +=
|  -=
|  <<=
|  >>=
|  >>>=
|  &=
|  ^=
|  |=
LogicalAssignment 
   &&=
|  ^^=
|  ||=

Comma Expressions

ListExpression 
   AssignmentExpression
|  ListExpression , AssignmentExpression
OptionalExpression 
   ListExpressionallowIn
|  «empty»

Type Expressions

TypeExpression  NonAssignmentExpression

Compile-Time Constant Expressions

A compile-time constant expression is an expression that either produces an error or evaluates to a value that can be determined at compile time.

The reason that a compile-time constant expression is not guaranteed to always evaluate successfully at run time is that global name lookup cannot be guaranteed to succeed. It is possible for a program to import a package P that defines a global constant P::A that can be accessed as A and then dynamically define another top-level variable Q::A that collides with A. It does not appear to be practical to restrict compile-time constant expressions to only qualified names to eliminate the possibility of such collisions.

A compile-time expression can consist of the following:

A pure function cannot have any read or write side effects or create any objects. A pure function’s result depends only on its arguments. A JavaScript host embedding may define some pure functions. Currently there is no way for a script to define any such functions, but a future language extension may permit that.

A reference R to a definition D of a compile-time constant is allowed inside a compile-time constant expression as long as the conditions below are met. If D was imported from another package, then the location of D is considered to be the location of the import directive. If D is visible to R by virtue of an intervening use directive U, then the conditions below have to be satisfied both with respect to D and R and with respect to U and R.

Some compile-time constant expressions only allow references to definitions that are textually prior to the point of the reference. Other compile-time constant expressions allow forward references to later compile-time constant definitions.

Restrictions

JavaScript 2.0 imposes the following restrictions:

A statement A dominates statement B if any of the following conditions are met:

Note that the above definition is conservative. If statement A dominates statement B, then it is guaranteed that, if B is executed then A must have been executed earlier; however, there may be some other statements A' that also are guaranteed to have been executed before B but which do not dominate B by the above definition.

A statement A is dead if any of the following conditions are met:

Note that the above definition is conservative. If a statement is dead, then it is guaranteed that it cannot be executed; however, there may be statements that cannot be executed that are not dead by the above definition.

A statement is live if it is not dead.


Waldemar Horwat
Last modified Tuesday, December 18, 2001
previousupnext