ECMAScript 4 Netscape Proposal
Formal Description
Syntactic Semantics
previousupnext

Monday, June 30, 2003

The syntactic semantics describe the actions the parser takes to evaluate an ECMAScript 4 program. For convenience, the syntactic grammar is repeated here. The starting nonterminal is Program. See also the description of the semantic notation.

The semantics are under construction. Many execution paths resulting in ???? represent semantics yet to be implemented.

This document is also available as a Word RTF file.

Terminals

General tokens: Identifier NegatedMinLong Number RegularExpression String VirtualSemicolon

Punctuation tokens: ! != !== % %= & && &&= &= ( ) * *= + ++ += , - -- -= . ... / /= : :: ; < << <<= <= = == === > >= >> >>= >>> >>>= ? [ ] ^ ^= ^^ ^^= { | |= || ||= } ~

Reserved words: as break case catch class const continue default delete do else extends false finally for function if import in instanceof is namespace new null package private public return super switch this throw true try typeof use var void while with

Future reserved words: abstract debugger enum export goto implements interface native protected synchronized throws transient volatile

Non-reserved words: get set

Data Model

Semantic Exceptions

tuple Break
valueObject,
labelLabel
end tuple;
tuple Continue
valueObject,
labelLabel
end tuple;
tuple Return
valueObject
end tuple;
ControlTransfer = Break  Continue  Return;
SemanticException = Object  ControlTransfer;

Extended integers and rationals

tag +zero;
tag –zero;
tag +;
tag ;
tag NaN;
ExtendedRational = (Rational – {0})  {+zero–zero+NaN};
ExtendedInteger = Integer  {+NaN};

Objects

tag none;
tag ok;
tag reject;
ObjectUndefined  Null  Boolean  Long  ULong  Float32  Float64  Char16  String  Namespace  CompoundAttribute  Class  SimpleInstance  MethodClosure  Date  RegExp  Package;
PrimitiveObjectUndefined  Null  Boolean  Long  ULong  Float32  Float64  Char16  String;
NonprimitiveObjectNamespace  CompoundAttribute  Class  SimpleInstance  MethodClosure  Date  RegExp  Package;
BindingObject = Class  SimpleInstance  RegExp  Date  Package;
ObjectOpt = Object  {none};
BooleanOpt = Boolean  {none};
IntegerOpt = Integer  {none};

Undefined

tag undefined;
Undefined = {undefined};

Null

tag null;
Null = {null};

Strings

StringOpt = String  {none};

Namespaces

record Namespace
nameString
end record;

Qualified Names

tuple QualifiedName
namespaceNamespace,
idString
end tuple;
The notation ns::id is a shorthand for QualifiedNamenamespacensidid.
Multiname = QualifiedName{};

Attributes

tag static;
tag virtual;
tag final;
PropertyCategory = {nonestaticvirtualfinal};
OverrideModifier = {nonetruefalseundefined};
tuple CompoundAttribute
namespacesNamespace{},
explicitBoolean,
enumerableBoolean,
dynamicBoolean,
categoryPropertyCategory,
overrideModOverrideModifier,
prototypeBoolean,
unusedBoolean
end tuple;
Attribute = Boolean  Namespace  CompoundAttribute;
AttributeOptNotFalse = {nonetrue Namespace  CompoundAttribute;

Classes

record Class
localBindingsLocalBinding{},
instancePropertiesInstanceProperty{},
superClassOpt,
prototypeObjectOpt,
completeBoolean,
nameString,
typeofStringString,
privateNamespaceNamespace,
dynamicBoolean,
finalBoolean,
defaultValueObjectOpt,
defaultHintHint,
hasPropertyObject  Class  Object  Boolean  Phase  Boolean,
bracketReadObject  Class  Object[]  Boolean  Phase  ObjectOpt,
bracketWriteObject  Class  Object[]  Object  Boolean  {run {noneok},
bracketDeleteObject  Class  Object[]  {run BooleanOpt,
readObject  Class  Multiname  EnvironmentOpt  Boolean  Phase  ObjectOpt,
writeObject  Class  Multiname  EnvironmentOpt  Object  Boolean  {run {none, ok},
deleteObject  Class  Multiname  EnvironmentOpt  {run BooleanOpt,
enumerateObject  Object{},
callObject  Class  Object[]  Phase  Object,
constructClass  Object[]  Phase  Object,
init: (SimpleInstance  Object[]  {run ())  {none},
isObject  Class  Boolean,
coerceObject  Class  ObjectOpt
end record;
ClassOpt = Class  {none};

Simple Instances

record SimpleInstance
localBindingsLocalBinding{},
archetypeObjectOpt,
sealedBoolean,
typeClass,
slotsSlot{},
call: (Object  SimpleInstance  Object[]  Phase  Object {none},
construct: (SimpleInstance  Object[]  Phase  Object {none},
end record;

Slots

record Slot
valueObjectOpt
end record;

Uninstantiated Functions

record UninstantiatedFunction
typeClass,
lengthInteger,
call: (Object  SimpleInstance  Object[]  Phase  Object {none},
construct: (SimpleInstance  Object[]  Phase  Object {none},
instantiationsSimpleInstance{}
end record;

Method Closures

tuple MethodClosure
thisObject,
methodInstanceMethod,
slotsSlot{}
end tuple;

Dates

record Date
localBindingsLocalBinding{},
archetypeObjectOpt,
sealedBoolean,
timeValueInteger
end record;

Regular Expressions

record RegExp
localBindingsLocalBinding{},
archetypeObjectOpt,
sealedBoolean,
sourceString,
lastIndexInteger,
globalBoolean,
ignoreCaseBoolean,
multilineBoolean
end record;

Packages

record Package
localBindingsLocalBinding{},
archetypeObjectOpt,
nameString,
initialize: (()  ())  {nonebusy},
sealedBoolean,
internalNamespaceNamespace
end record;

Objects with Limits

instance must be an instance of one of limit’s descendants.
tuple LimitedInstance
instanceObject,
limitClass
end tuple;
ObjOptionalLimit = Object  LimitedInstance;

References

tuple LexicalReference
variableMultinameMultiname,
strictBoolean
end tuple;
tuple DotReference
baseObject,
limitClass,
multinameMultiname
end tuple;
tuple BracketReference
baseObject,
limitClass,
argsObject[]
end tuple;
Reference = LexicalReference  DotReference  BracketReference;
ObjOrRef = Object  Reference;

Modes of expression evaluation

tag compile;
tag run;
Phase = {compilerun};

Contexts

record Context
strictBoolean,
openNamespacesNamespace{}
end record;

Labels

tag default;
Label = String  {default};
tuple JumpTargets
breakTargetsLabel{},
continueTargetsLabel{}
end tuple;

Function Support

tag normal;
tag get;
tag set;
Handling = {normalgetset};
tag plainFunction;
tag uncheckedFunction;
tag prototypeFunction;
tag instanceFunction;
tag constructorFunction;
StaticFunctionKind = {plainFunctionuncheckedFunctionprototypeFunction};
FunctionKind = {plainFunction, uncheckedFunction, prototypeFunction, instanceFunction, constructorFunction};

Environments

An Environment is a list of two or more frames. Each frame corresponds to a scope. More specific frames are listed first—each frame’s scope is directly contained in the following frame’s scope. The last frame is always a Package. A WithFrame is always preceded by a LocalFrame, so the first frame is never a WithFrame.
Environment = Frame[];
EnvironmentOpt = Environment  {none};
Frame = NonWithFrame  WithFrame;
NonWithFrame = Package  ParameterFrame  Class  LocalFrame;
record ParameterFrame
localBindingsLocalBinding{},
kindFunctionKind,
handlingHandling,
callsSuperconstructorBoolean,
superconstructorCalledBoolean,
thisObjectOpt,
parametersParameter[],
restVariableOpt,
returnTypeClass
end record;
ParameterFrameOpt = ParameterFrame  {none};
tuple Parameter
varVariable  DynamicVar,
defaultObjectOpt
end tuple;
record LocalFrame
localBindingsLocalBinding{}
end record;
record WithFrame
valueObjectOpt
end record;

Properties

tag read;
tag write;
tag readWrite;
Access = {readwrite};
AccessSet = {readwritereadWrite};
tuple LocalBinding
qnameQualifiedName,
accessesAccessSet,
explicitBoolean,
enumerableBoolean,
end tuple;
tag forbidden;
SingletonProperty = {forbidden Variable  DynamicVar  Getter  Setter;
SingletonPropertyOpt = SingletonProperty  {none};
VariableValue = {none Object  UninstantiatedFunction;
tag busy;
Initializer = Environment  Phase  Object;
InitializerOpt = Initializer  {none};
record Variable
typeClass,
valueVariableValue,
immutableBoolean,
setup: (()  ClassOpt {nonebusy},
initializerInitializer  {nonebusy},
initializerEnvEnvironment
end record;
VariableOpt = Variable  {none};
record DynamicVar
valueObject  UninstantiatedFunction,
sealedBoolean
end record;
record Getter
callEnvironment  Phase  Object,
end record;
record Setter
callObject  Environment  Phase  (),
end record;
InstanceProperty = InstanceVariable  InstanceMethod  InstanceGetter  InstanceSetter;
InstancePropertyOpt = InstanceProperty  {none};
record InstanceVariable
multinameMultiname,
finalBoolean,
enumerableBoolean,
typeClass,
defaultValueObjectOpt,
immutableBoolean
end record;
InstanceVariableOpt = InstanceVariable  {none};
record InstanceMethod
multinameMultiname,
finalBoolean,
enumerableBoolean,
signatureParameterFrame,
lengthInteger,
callObject  Object[]  Phase  Object
end record;
record InstanceGetter
multinameMultiname,
finalBoolean,
enumerableBoolean,
signatureParameterFrame,
callObject  Phase  Object
end record;
record InstanceSetter
multinameMultiname,
finalBoolean,
enumerableBoolean,
signatureParameterFrame,
callObject  Object  Phase  ()
end record;
PropertyOpt = SingletonProperty  InstanceProperty  {none};

Miscellaneous

tag hintString;
tag hintNumber;
Hint = {hintStringhintNumber};
HintOpt = Hint  {none};
tag less;
tag equal;
tag greater;
tag unordered;
Order = {lessequalgreaterunordered};

Data Operations

Numeric Utilities

unsignedWrap32(i) returns i converted to a value between 0 and 232–1 inclusive, wrapping around modulo 232 if necessary.
proc unsignedWrap32(iInteger): {0 ... 232 – 1}
return bitwiseAnd(i, 0xFFFFFFFF)
end proc;
signedWrap32(i) returns i converted to a value between –231 and 231–1 inclusive, wrapping around modulo 232 if necessary.
proc signedWrap32(iInteger): {–231 ... 231 – 1}
jInteger  bitwiseAnd(i, 0xFFFFFFFF);
if j  231 then j  j – 232 end if;
return j
end proc;
unsignedWrap64(i) returns i converted to a value between 0 and 264–1 inclusive, wrapping around modulo 264 if necessary.
proc unsignedWrap64(iInteger): {0 ... 264 – 1}
return bitwiseAnd(i, 0xFFFFFFFFFFFFFFFF)
end proc;
signedWrap64(i) returns i converted to a value between –263 and 263–1 inclusive, wrapping around modulo 264 if necessary.
proc signedWrap64(iInteger): {–263 ... 263 – 1}
jInteger  bitwiseAnd(i, 0xFFFFFFFFFFFFFFFF);
if j  263 then j  j – 264 end if;
return j
end proc;
truncateToInteger(x) returns x converted to an integer by rounding towards zero. If x is an infinity or a NaN, the result is 0.
proc truncateToInteger(xGeneralNumber): Integer
case x of
{NaNf32NaNf64+f32+f64f32f64do return 0;
Long  ULong do return x.value
end case
end proc;
pinExtendedInteger(ilimitnegativeFromEnd) returns i pinned to the set {0 ... limit}, where limit is a nonnegative integer. If negativeFromEnd is true, then negative values of i from –limit through –1 are treated as 0 through limit – 1 respectively.
proc pinExtendedInteger(iExtendedIntegerlimitIntegernegativeFromEndBoolean): Integer
case i of
{NaNdo throw a RangeError exception;
{do return 0;
{+do return limit;
jInteger  i;
if j > limit then j  limit end if;
if negativeFromEnd and j < 0 then j  j + limit end if;
if j < 0 then j  0 end if;
note  0  j  limit;
return j
end case
end proc;
checkInteger(x) returns x converted to an integer if its mathematical value is, in fact, an integer. If x is an infinity or a NaN or has a fractional part, the result is none.
proc checkInteger(xGeneralNumber): IntegerOpt
case x of
{NaNf32NaNf64+f32+f64f32f64do return none;
{+zerof32+zerof64–zerof32–zerof64do return 0;
Long  ULong do return x.value;
NonzeroFiniteFloat32  NonzeroFiniteFloat64 do
rRational  x.value;
if r  Integer then return none end if;
return r
end case
end proc;
integerToLong(i) converts i to the first of the types Long, ULong, or Float64 that can contain the value i. If necessary, the Float64 result may be rounded or converted to an infinity using the IEEE 754 “round to nearest” mode.
proc integerToLong(iInteger): GeneralNumber
if –263  i  263 – 1 then return ilong
elsif 263  i  264 – 1 then return iulong
else return if64
end if
end proc;
integerToULong(i) converts i to the first of the types ULong, Long, or Float64 that can contain the value i. If necessary, the Float64 result may be rounded or converted to an infinity using the IEEE 754 “round to nearest” mode.
proc integerToULong(iInteger): GeneralNumber
if 0  i  264 – 1 then return iulong
elsif –263  i  –1 then return ilong
else return if64
end if
end proc;
rationalToLong(q) converts q to one of the types Long, ULong, or Float64, whichever one can come the closest to representing the true value of q. If several of these types can come equally close to the value of q, then one of them is chosen according to the algorithm below.
proc rationalToLong(qRational): GeneralNumber
if q  Integer then return integerToLong(q)
elsif |q 253 then return qf64
elsif q < –263 – 1/2 or q  264 – 1/2 then return qf64
else
Let i be the integer closest to q. If q is halfway between two integers, pick i so that it is even.
note  –263  i  264 – 1;
if i < 263 then return ilong else return iulong end if
end if
end proc;
rationalToULong(q) converts q to one of the types ULong, Long, or Float64, whichever one can come the closest to representing the true value of q. If several of these types can come equally close to the value of q, then one of them is chosen according to the algorithm below.
proc rationalToULong(qRational): GeneralNumber
if q  Integer then return integerToULong(q)
elsif |q 253 then return qf64
elsif q < –263 – 1/2 or q  264 – 1/2 then return qf64
else
Let i be the integer closest to q. If q is halfway between two integers, pick i so that it is even.
note  –263  i  264 – 1;
if i  0 then return iulong else return ilong end if
end if
end proc;
proc extendedRationalToFloat32(qExtendedRational): Float32
case q of
Rational do return qf32;
{+zerodo return +zerof32;
{–zerodo return –zerof32;
{+do return +f32;
{do return f32;
{NaNdo return NaNf32
end case
end proc;
proc extendedRationalToFloat64(qExtendedRational): Float64
case q of
Rational do return qf64;
{+zerodo return +zerof64;
{–zerodo return –zerof64;
{+do return +f64;
{do return f64;
{NaNdo return NaNf64
end case
end proc;
toRational(x) returns the exact Rational value of x.
proc toRational(xFiniteGeneralNumber): Rational
case x of
{+zerof32+zerof64–zerof32–zerof64do return 0;
NonzeroFiniteFloat32  NonzeroFiniteFloat64  Long  ULong do return x.value
end case
end proc;
toFloat32(x) converts x to a Float32, using the IEEE 754 “round to nearest” mode.
proc toFloat32(xGeneralNumber): Float32
case x of
Long  ULong do return (x.value)f32;
Float32 do return x;
{f64do return f32;
{–zerof64do return –zerof32;
{+zerof64do return +zerof32;
{+f64do return +f32;
{NaNf64do return NaNf32;
NonzeroFiniteFloat64 do return (x.value)f32
end case
end proc;
toFloat64(x) converts x to a Float64, using the IEEE 754 “round to nearest” mode.
proc toFloat64(xGeneralNumber): Float64
case x of
Long  ULong do return (x.value)f64;
Float32 do return float32ToFloat64(x);
Float64 do return x
end case
end proc;
generalNumberCompare(xy) compares x with y using the IEEE 754 rules and returns less if x<y, equal if x=y, greater if x>y, or unordered if either x or y is a NaN. The comparison is done using the exact values of x and y, even if they have different types. Positive infinities compare equal to each other and greater than any other non-NaN values. Negative infinities compare equal to each other and less than any other non-NaN values. Positive and negative zeroes compare equal to each other.
proc generalNumberCompare(xGeneralNumberyGeneralNumber): Order
if x  {NaNf32NaNf64or y  {NaNf32NaNf64then return unordered
elsif x  {+f32+f64and y  {+f32+f64then return equal
elsif x  {f32f64and y  {f32f64then return equal
elsif x  {+f32+f64or y  {f32f64then return greater
elsif x  {f32f64or y  {+f32+f64then return less
else
xrRational  toRational(x);
yrRational  toRational(y);
if xr < yr then return less
elsif xr > yr then return greater
else return equal
end if
end if
end proc;

Character Utilities

proc integerToUTF16(i: {0 ... 0x10FFFF}): String
if 0  i  0xFFFF then return [integerToChar16(i)]
else
j: {0 ... 0xFFFFF}  i – 0x10000;
highChar16  integerToChar16(0xD800 + bitwiseShift(j, –10));
lowChar16  integerToChar16(0xDC00 + bitwiseAnd(j, 0x3FF));
return [highlow]
end if
end proc;
proc char21ToUTF16(chChar21): String
end proc;
proc surrogatePairToSupplementaryChar(hChar16lChar16): SupplementaryChar
codePoint: {0x10000 ... 0x10FFFF}  0x10000 + (char16ToInteger(h) – 0xD800)0x400 + char16ToInteger(l) – 0xDC00;
return integerToSupplementaryChar(codePoint)
end proc;
proc stringToUTF32(sString): Char21[]
iInteger  0;
resultChar21[]  [];
while i  |sdo
chChar21;
if s[i {‘«uD800»’ ... ‘«uDBFF»’} and i + 1  |sand s[i + 1]  {‘«uDC00»’ ... ‘«uDFFF»’} then
ch  surrogatePairToSupplementaryChar(s[i], s[i + 1]);
i  i + 2
else ch  s[i]; i  i + 1
end if;
result  result  [ch]
end while;
return result
end proc;
proc charToLowerFull(chChar21): String
return ch converted to a lower case character using the Unicode full, locale-independent case mapping. A single character may be converted to multiple characters. If ch has no lower case equivalent, then the result is the string char21ToUTF16(ch).
end proc;
proc charToLowerLocalized(chChar21): String
return ch converted to a lower case character using the Unicode full case mapping in the host environment’s current locale. A single character may be converted to multiple characters. If ch has no lower case equivalent, then the result is the string char21ToUTF16(ch).
end proc;
proc charToUpperFull(chChar21): String
return ch converted to a upper case character using the Unicode full, locale-independent case mapping. A single character may be converted to multiple characters. If ch has no upper case equivalent, then the result is the string char21ToUTF16(ch).
end proc;
proc charToUpperLocalized(chChar21): String
return ch converted to a upper case character using the Unicode full case mapping in the host environment’s current locale. A single character may be converted to multiple characters. If ch has no upper case equivalent, then the result is the string char21ToUTF16(ch).
end proc;

Object Utilities

Object Class Inquiries

objectType(o) returns an Object o’s most specific type. Although objectType is used internally throughout this specification, in order to allow one programmer-visible class to be implemented as an ensemble of implementation-specific classes, no way is provided for a user program to directly obtain the result of calling objectType on an object.
proc objectType(oObject): Class
case o of
Undefined do return Void;
Null do return Null;
Boolean do return Boolean;
Long do return long;
ULong do return ulong;
Float32 do return float;
Float64 do return Number;
Char16 do return char;
String do return String;
Namespace do return Namespace;
Class do return Class;
SimpleInstance do return o.type;
MethodClosure do return Function;
Date do return Date;
RegExp do return RegExp;
Package do return Package
end case
end proc;
is(oc) returns true if o is an instance of class c or one of its subclasses.
proc is(oObjectcClass): Boolean
return c.is(oc)
end proc;
ordinaryIs(oc) is the implementation of is for a native class unless specified otherwise in the class’s definition. Host classes may either also use ordinaryIs or define a different procedure to perform this test.
proc ordinaryIs(oObjectcClass): Boolean
return isAncestor(cobjectType(o))
end proc;
Return an ordered list of class c’s ancestors, including c itself.
proc ancestors(cClass): Class[]
sClassOpt  c.super;
if s = none then return [c] else return ancestors(s [c] end if
end proc;
Return true if c is d or an ancestor of d.
proc isAncestor(cClassdClass): Boolean
if c = d then return true
else
sClassOpt  d.super;
if s = none then return false end if;
return isAncestor(cs)
end if
end proc;

Object to Boolean Conversion

objectToBoolean(o) returns o converted to a Boolean.
proc objectToBoolean(oObject): Boolean
case o of
Undefined  Null do return false;
Boolean do return o;
Long  ULong do return o.value  0;
Float32 do return o  {+zerof32–zerof32NaNf32};
Float64 do return o  {+zerof64–zerof64NaNf64};
String do return o  “”;
Char16  Namespace  CompoundAttribute  Class  SimpleInstance  MethodClosure  Date  RegExp  Package do
return true
end case
end proc;

Object to Primitive Conversion

proc objectToPrimitive(oObjecthintHintOptphasePhase): PrimitiveObject
if o  PrimitiveObject then return o end if;
cClass  objectType(o);
hHint;
if hint  Hint then h  hint else h  c.defaultHint end if;
case h of
toStringMethodObjectOpt  c.read(oc, {public::“toString”}, nonefalsephase);
if toStringMethod  none then
rObject  call(otoStringMethod[]phase);
if r  PrimitiveObject then return r end if
end if;
valueOfMethodObjectOpt  c.read(oc, {public::“valueOf”}, nonefalsephase);
if valueOfMethod  none then
rObject  call(ovalueOfMethod[]phase);
if r  PrimitiveObject then return r end if
end if;
valueOfMethodObjectOpt  c.read(oc, {public::“valueOf”}, nonefalsephase);
if valueOfMethod  none then
rObject  call(ovalueOfMethod[]phase);
if r  PrimitiveObject then return r end if
end if;
toStringMethodObjectOpt  c.read(oc, {public::“toString”}, nonefalsephase);
if toStringMethod  none then
rObject  call(otoStringMethod[]phase);
if r  PrimitiveObject then return r end if
end if
end case;
throw a TypeError exception — cannot convert this object to a primitive
end proc;

Object to Number Conversions

objectToGeneralNumber(ophase) returns o converted to a GeneralNumber. If phase is compile, only constant conversions are permitted.
proc objectToGeneralNumber(oObjectphasePhase): GeneralNumber
aPrimitiveObject  objectToPrimitive(ohintNumberphase);
case a of
Undefined do return NaNf64;
Null  {falsedo return +zerof64;
{truedo return 1f64;
GeneralNumber do return a;
Char16  String do return stringToFloat64(toString(a))
end case
end proc;
objectToFloat32(ophase) returns o converted to a Float32. If phase is compile, only constant conversions are permitted.
proc objectToFloat32(oObjectphasePhase): Float32
aPrimitiveObject  objectToPrimitive(ohintNumberphase);
case a of
Undefined do return NaNf32;
Null  {falsedo return +zerof32;
{truedo return 1f32;
GeneralNumber do return toFloat32(a);
Char16  String do return stringToFloat32(toString(a))
end case
end proc;
objectToFloat64(ophase) returns o converted to a Float64. If phase is compile, only constant conversions are permitted.
proc objectToFloat64(oObjectphasePhase): Float64
return toFloat64(objectToGeneralNumber(ophase))
end proc;
objectToExtendedInteger(ophase) returns o converted to an ExtendedInteger. An error occurs if o has a fractional part or is a NaN. If o is a string, then it is converted exactly. If phase is compile, only constant conversions are permitted.
proc objectToExtendedInteger(oObjectphasePhase): ExtendedInteger
aPrimitiveObject  objectToPrimitive(ohintNumberphase);
case a of
Null  {falsedo return 0;
{truedo return 1;
{undefinedNaNf32NaNf64do return NaN;
{+f32+f64do return +;
{f32f64do return ;
{+zerof32+zerof64–zerof32–zerof64do return 0;
Long  ULong do return a.value;
NonzeroFiniteFloat32  NonzeroFiniteFloat64 do
rRational  a.value;
if r  Integer then
throw a RangeError exception — the value a is not an integer
end if;
return r;
Char16  String do return stringToExtendedInteger(toString(a))
end case
end proc;
objectToInteger(ophase) returns o converted to an Integer. An error occurs if o has a fractional part or is not finite. If o is a string, then it is converted exactly. If phase is compile, only constant conversions are permitted.
proc objectToInteger(oObjectphasePhase): Integer
iExtendedInteger  objectToExtendedInteger(ophase);
case i of
{+NaNdo throw a RangeError exception — i is not an integer;
Integer do return i
end case
end proc;
proc stringToFloat32(sString): Float32
Apply the lexer grammar with the start symbol StringNumericLiteral to the string s.
if the grammar cannot interpret the entire string as an expansion of StringNumericLiteral then
return NaNf32
else
qExtendedRational the value of the action Lex applied to the obtained expansion of the nonterminal StringNumericLiteral;
end if
end proc;
proc stringToFloat64(sString): Float64
Apply the lexer grammar with the start symbol StringNumericLiteral to the string s.
if the grammar cannot interpret the entire string as an expansion of StringNumericLiteral then
return NaNf64
else
qExtendedRational the value of the action Lex applied to the obtained expansion of the nonterminal StringNumericLiteral;
end if
end proc;
proc stringToExtendedInteger(sString): ExtendedInteger
Apply the lexer grammar with the start symbol StringNumericLiteral to the string s.
if the grammar cannot interpret the entire string as an expansion of StringNumericLiteral then
throw a TypeError exception — the string s does not contain a number
else
qExtendedRational the value of the action Lex applied to the obtained expansion of the nonterminal StringNumericLiteral;
case q of
{+zero–zerodo return 0;
if q  Integer then return q
else throw a RangeError exception — the value should be an integer
end if
end case
end if
end proc;

Object to String Conversions

objectToString(ophase) returns o converted to a String. If phase is compile, only constant conversions are permitted.
proc objectToString(oObjectphasePhase): String
aPrimitiveObject  objectToPrimitive(ohintStringphase);
case a of
Undefined do return “undefined”;
Null do return “null”;
{falsedo return “false”;
{truedo return “true”;
Char16 do return [a];
String do return a
end case
end proc;
proc toString(oChar16  String): String
case o of
Char16 do return [o];
String do return o
end case
end proc;
proc generalNumberToString(xGeneralNumber): String
case x of
Long  ULong do return integerToString(x.value);
Float32 do return float32ToString(x);
Float64 do return float64ToString(x)
end case
end proc;
integerToString(i) converts an integer i to a string of one or more decimal digits. If i is negative, the string is preceded by a minus sign.
proc integerToString(iInteger): String
if i < 0 then return [-]  integerToString(–iend if;
qInteger  i/10;
rInteger  i – q10;
cChar16  integerToChar16(r + char16ToInteger(‘0’));
if q = 0 then return [c] else return integerToString(q [c] end if
end proc;
integerToStringWithSign(i) is the same as integerToString(i) except that the resulting string always begins with a plus or minus sign.
proc integerToStringWithSign(iInteger): String
if i  0 then return [+]  integerToString(i)
else return [-]  integerToString(–i)
end if
end proc;
proc exponentialNotationString(digitsStringeInteger): String
mantissaString;
if |digits| = 1 then mantissa  digits
else mantissa  [digits[0]]  “.”  digits[1 ...]
end if;
return mantissa  “e”  integerToStringWithSign(e)
end proc;
float32ToString(x) converts a Float32 x to a string using fixed-point notation if the absolute value of x is between 10–6 inclusive and 1021 exclusive, and exponential notation otherwise. The result has the fewest significant digits possible while still ensuring that converting the string back into a Float32 value would result in the same value x (except that –zerof32 would become +zerof32).
proc float32ToString(xFloat32): String
case x of
{NaNf32do return “NaN”;
{+zerof32–zerof32do return “0”;
{+f32do return “Infinity”;
{f32do return “-Infinity”;
rRational  x.value;
if r < 0 then return “-”  float32ToString(float32Negate(x))
else
Let e, k, and s be integers such that k 1, 10k–1 s 10k, (s10e+1–k)f32 = x, and k is as small as possible.
note  k is the number of digits in the decimal representation of s, s is not divisible by 10, and the least significant digit of s is not necessarily uniquely determined by the above criteria.
When there are multiple possibilities for s according to the rules above, implementations are encouraged but not required to select the one according to the following rule: Select the value of s for which s10e+1–k is closest in value to r; if there are two such possible values of s, choose the one that is even.
digitsString  integerToString(s)
if k – 1  e  20 then return digits  repeat(‘0’, e + 1 – k)
elsif 0  e  20 then return digits[0 ... e “.”  digits[e + 1 ...]
elsif –6  e < 0 then return “0.”  repeat(‘0’, –(e + 1))  digits
else return exponentialNotationString(digitse)
end if
end if
end case
end proc;
float64ToString(x) converts a Float64 x to a string using fixed-point notation if the absolute value of x is between 10–6 inclusive and 1021 exclusive, and exponential notation otherwise. The result has the fewest significant digits possible while still ensuring that converting the string back into a Float64 value would result in the same value x (except that –zerof64 would become +zerof64).
proc float64ToString(xFloat64): String
case x of
{NaNf64do return “NaN”;
{+zerof64–zerof64do return “0”;
{+f64do return “Infinity”;
{f64do return “-Infinity”;
rRational  x.value;
if r < 0 then return “-”  float64ToString(float64Negate(x))
else
Let e, k, and s be integers such that k 1, 10k–1 s 10k, (s10e+1–k)f64 = x, and k is as small as possible.
note  k is the number of digits in the decimal representation of s, s is not divisible by 10, and the least significant digit of s is not necessarily uniquely determined by the above criteria.
When there are multiple possibilities for s according to the rules above, implementations are encouraged but not required to select the one according to the following rule: Select the value of s for which s10e+1–k is closest in value to r; if there are two such possible values of s, choose the one that is even.
digitsString  integerToString(s)
if k – 1  e  20 then return digits  repeat(‘0’, e + 1 – k)
elsif 0  e  20 then return digits[0 ... e “.”  digits[e + 1 ...]
elsif –6  e < 0 then return “0.”  repeat(‘0’, –(e + 1))  digits
else return exponentialNotationString(digitse)
end if
end if
end case
end proc;

Object to Qualified Name Conversion

objectToQualifiedName(ophase) coerces an object o to a qualified name. If phase is compile, only constant conversions are permitted.
proc objectToQualifiedName(oObjectphasePhase): QualifiedName
return public::(objectToString(ophase))
end proc;

Object to Class Conversion

objectToClass(o) returns o converted to a non-null Class.
proc objectToClass(oObject): Class
if o  Class then return o else throw a TypeError exception end if
end proc;

Object to Attribute Conversion

objectToAttribute(o) returns o converted to an attribute.
proc objectToAttribute(oObjectphasePhase): Attribute
if o  Attribute then return o
else
note  If o is not an attribute, try to call it with no arguments.
aObject  call(nullo[]phase);
if a  Attribute then return a else throw a TypeError exception end if
end if
end proc;

Implicit Coercions

coerce(oc) attempts to implicitly coerce o to class c. If the coercion succeeds, coerce returns the coerced value. If not, coerce throws a TypeError.
The coercion always succeeds and returns o unchanged if o is already a member of class c. The value returned from coerce always is a member of class c.
proc coerce(oObjectcClass): Object
resultObjectOpt  c.coerce(oc);
if result  none then return result
else throw a TypeError exception — coercion failed
end if
end proc;
coerceOrNull(oc) attempts to implicitly coerce o to class c. If the coercion succeeds, coerceOrNull returns the coerced value. If not, then coerceOrNull returns null if null is a member of type c; otherwise, coerceOrNull throws a TypeError.
The coercion always succeeds and returns o unchanged if o is already a member of class c. The value returned from coerceOrNull always is a member of class c.
proc coerceOrNull(oObjectcClass): Object
resultObjectOpt  c.coerce(oc);
if result  none then return result
elsif c.coerce(nullc) = null then return null
else throw a TypeError exception — coercion failed
end if
end proc;
coerceNonNull(oc) attempts to implicitly coerce o to class c. If the coercion succeeds and the result is not null, then coerceNonNull returns the coerced value. If not, coerceNonNull throws a TypeError.
proc coerceNonNull(oObjectcClass): Object
resultObjectOpt  c.coerce(oc);
if result  {nonenullthen return result
else throw a TypeError exception — coercion failed
end if
end proc;
ordinaryCoerce(oc) is the implementation of coercion for a native class unless specified otherwise in the class’s definition. Host classes may define a different procedure to perform this coercion.
proc ordinaryCoerce(oObjectcClass): ObjectOpt
if o = null or is(octhen return o else return none end if
end proc;

Attributes

combineAttributes(ab) returns the attribute that results from concatenating the attributes a and b.
proc combineAttributes(aAttributeOptNotFalsebAttribute): Attribute
if b = false then return false
elsif a  {nonetruethen return b
elsif b = true then return a
elsif a  Namespace then
if a = b then return a
elsif b  Namespace then
return CompoundAttributenamespaces: {ab}, explicitfalse, enumerablefalse, dynamicfalse, categorynone, overrideModnone, prototypefalse, unusedfalse
else return CompoundAttributenamespacesb.namespaces  {a}, other fields from b
end if
elsif b  Namespace then
return CompoundAttributenamespacesa.namespaces  {b}, other fields from a
else
note  At this point both a and b are compound attributes.
if (a.category  none and b.category  none and a.category  b.categoryor (a.overrideMod  none and b.overrideMod  none and a.overrideMod  b.overrideModthen
throw an AttributeError exception — attributes a and b have conflicting contents
else
return CompoundAttributenamespacesa.namespaces  b.namespaces, explicita.explicit or b.explicit, enumerablea.enumerable or b.enumerable, dynamica.dynamic or b.dynamic, categorya.category  none ? a.category : b.category, overrideModa.overrideMod  none ? a.overrideMod : b.overrideMod, prototypea.prototype or b.prototype, unuseda.unused or b.unused
end if
end if
end proc;
toCompoundAttribute(a) returns a converted to a CompoundAttribute even if it was a simple namespace, true, or none.
proc toCompoundAttribute(aAttributeOptNotFalse): CompoundAttribute
case a of
{nonetruedo
return CompoundAttributenamespaces: {}, explicitfalse, enumerablefalse, dynamicfalse, categorynone, overrideModnone, prototypefalse, unusedfalse;
return CompoundAttributenamespaces: {a}, explicitfalse, enumerablefalse, dynamicfalse, categorynone, overrideModnone, prototypefalse, unusedfalse;
CompoundAttribute do return a
end case
end proc;

Access Utilities

accessesOverlap(accesses1accesses2) returns true if the two AccessSets have a nonempty intersection.
proc accessesOverlap(accesses1AccessSetaccesses2AccessSet): Boolean
return accesses1 = accesses2 or accesses1 = readWrite or accesses2 = readWrite
end proc;
proc archetype(oObject): ObjectOpt
case o of
Undefined  Null do return none;
Boolean do return Boolean.prototype;
Long do return long.prototype;
ULong do return ulong.prototype;
Float32 do return float.prototype;
Float64 do return Number.prototype;
Char16 do return char.prototype;
String do return String.prototype;
Class do return Class.prototype;
SimpleInstance  RegExp  Date  Package do return o.archetype
end case
end proc;
archetypes(o) returns the set of o’s archetypes, not including o itself.
proc archetypes(oObject): Object{}
aObjectOpt  archetype(o);
if a = none then return {} end if;
return {a archetypes(a)
end proc;
o is an object that is known to have slot id. findSlot(oid) returns that slot.
proc findSlot(oObjectidInstanceVariable): Slot
note  o must be a SimpleInstance or a MethodClosure in order to have slots.
matchingSlotsSlot{}  {s | s  o.slots such that s.id = id};
return the one element of matchingSlots
end proc;
setupVariable(v) runs Setup and initialises the type of the variable v, making sure that Setup is done at most once and does not reenter itself.
proc setupVariable(vVariable)
setup: (()  ClassOpt {nonebusy v.setup;
case setup of
()  ClassOpt do
v.setup  busy;
typeClassOpt  setup();
if type = none then type  Object end if;
v.type  type;
v.setup  none;
{nonedo nothing;
{busydo
throw a ConstantError exception — a constant’s type or initialiser cannot depend on the value of that constant
end case
end proc;
writeVariable(vnewValueclearInitializer) writes the value newValue into the mutable or immutable variable v. newValue is coerced to v’s type. If the clearInitializer flag is set, then the caller has just evaluated v’s initialiser and is supplying its result in newValue. In this case writeVariable atomically clears v.initializer while writing v.value. In all other cases the presence of an initialiser or an existing value will prevent an immutable variable’s value from being written.
proc writeVariable(vVariablenewValueObjectclearInitializerBoolean): Object
coercedValueObject  coerce(newValuev.type);
if clearInitializer then v.initializer  none end if;
if v.immutable and (v.value  none or v.initializer  nonethen
throw a ReferenceError exception — cannot initialise a const variable twice
end if;
v.value  coercedValue;
return coercedValue
end proc;

Environmental Utilities

If env is from within a class’s body, getEnclosingClass(env) returns the innermost such class; otherwise, it returns none.
proc getEnclosingClass(envEnvironment): ClassOpt
if some c  env satisfies c  Class then
Let c be the first element of env that is a Class.
return c
end if;
return none
end proc;
If env is from within a function’s body, getEnclosingParameterFrame(env) returns the ParameterFrame for the innermost such function; otherwise, it returns none.
proc getEnclosingParameterFrame(envEnvironment): ParameterFrameOpt
for each frame  env do
case frame of
LocalFrame  WithFrame do nothing;
ParameterFrame do return frame;
Package  Class do return none
end case
end for each;
return none
end proc;
getRegionalEnvironment(env) returns all frames in env up to and including the first regional frame. A regional frame is either any frame other than a with frame or local block frame, a local block frame directly enclosed in a class, or a local block frame directly enclosed in a with frame directly enclosed in a class.
proc getRegionalEnvironment(envEnvironment): Frame[]
iInteger  0;
while env[i LocalFrame  WithFrame do i  i + 1 end while;
if env[i Class then while i  0 and env[i LocalFrame do i  i – 1 end while
end if;
return env[0 ... i]
end proc;
getRegionalFrame(env) returns the most specific regional frame in env.
proc getRegionalFrame(envEnvironment): Frame
regionalEnvFrame[]  getRegionalEnvironment(env);
return regionalEnv[|regionalEnv| – 1]
end proc;
getPackageFrame(env) returns the innermost package frame in env.
proc getPackageFrame(envEnvironment): Package
iInteger  0;
while env[i Package do i  i + 1 end while;
note  Every environment ends with a Package frame, so one will always be found.
return env[i]
end proc;

Property Lookup

findLocalSingletonProperty(omultinameaccess) looks in o for a local singleton property with one of the names in multiname and access that includes access. If there is no such property, findLocalSingletonProperty returns none. If there is exactly one such property, findLocalSingletonProperty returns it. If there is more than one such property, findLocalSingletonProperty throws an error.
proc findLocalSingletonProperty(oNonWithFrame  SimpleInstance  RegExp  Date, multinameMultiname, accessAccess): SingletonPropertyOpt
matchingLocalBindingsLocalBinding{}  {b | b  o.localBindings such that b.qname  multiname and accessesOverlap(b.accessesaccess)};
note  If the same property was found via several different bindings b, then it will appear only once in the set matchingProperties.
matchingPropertiesSingletonProperty{}  {b.content | b  matchingLocalBindings};
if matchingProperties = {} then return none
elsif |matchingProperties| = 1 then return the one element of matchingProperties
else
throw a ReferenceError exception — this access is ambiguous because the bindings it found belong to several different local properties
end if
end proc;
instancePropertyAccesses(m) returns instance property’s AccessSet.
proc instancePropertyAccesses(mInstanceProperty): AccessSet
case m of
InstanceVariable  InstanceMethod do return readWrite;
InstanceGetter do return read;
InstanceSetter do return write
end case
end proc;
findLocalInstanceProperty(cmultinameaccesses) looks in class c for a local instance property with one of the names in multiname and accesses that have a nonempty intersection with accesses. If there is no such property, findLocalInstanceProperty returns none. If there is exactly one such property, findLocalInstanceProperty returns it. If there is more than one such property, findLocalInstanceProperty throws an error.
proc findLocalInstanceProperty(cClassmultinameMultinameaccessesAccessSet): InstancePropertyOpt
matchesInstanceProperty{}  {m | m  c.instanceProperties such that m.multiname  multiname  {} and accessesOverlap(instancePropertyAccesses(m), accesses)};
if matches = {} then return none
elsif |matches| = 1 then return the one element of matches
else
throw a ReferenceError exception — this access is ambiguous because it found several different instance properties in the same class
end if
end proc;
findArchetypeProperty(omultinameaccessflat) looks in object o for any local or inherited property with one of the names in multiname and access that includes access. If flat is true, then properties inherited from the archetype are not considered in the search. If it finds no property, findArchetypeProperty returns none. If it finds one property, findArchetypeProperty returns it. If it finds more than one property, findArchetypeProperty prefers the more local one in the list of o’s superclasses or archetypes; if two or more properties remain, the singleton one is preferred; if two or more properties still remain, findArchetypeProperty throws an error.
Note that findArchetypeProperty(omultinameaccessflat) searches o itself rather than o’s class for properties. findArchetypeProperty will not find instance properties unless o is a class.
proc findArchetypeProperty(oObjectmultinameMultinameaccessAccessflatBoolean): PropertyOpt
case o of
Undefined  Null  Boolean  Long  ULong  Float32  Float64  Char16  String  Namespace  CompoundAttribute  MethodClosure do
m  none;
SimpleInstance  RegExp  Date  Package do
m  findLocalSingletonProperty(omultinameaccess);
Class do m  findClassProperty(omultinameaccess)
end case;
if m  none then return m end if;
if flat then return none end if;
aObjectOpt  archetype(o);
if a = none then return none end if;
return findArchetypeProperty(amultinameaccessflat)
end proc;
proc findClassProperty(cClassmultinameMultinameaccessAccess): PropertyOpt
mPropertyOpt  findLocalSingletonProperty(cmultinameaccess);
if m = none then
m  findLocalInstanceProperty(cmultinameaccess);
if m = none then
superClassOpt  c.super;
if super  none then m  findClassProperty(supermultinameaccessend if
end if
end if;
return m
end proc;
findBaseInstanceProperty(cmultinameaccesses) looks in class c and its ancestors for an instance property with one of the names in multiname and accesses that have a nonempty intersection with accesses. If there is no such property, findBaseInstanceProperty returns none. If there is exactly one such property, findBaseInstanceProperty returns it. If there is more than one such property, findBaseInstanceProperty prefers the one defined in the least specific class; if two or more properties still remain, findBaseInstanceProperty throws an error.
proc findBaseInstanceProperty(cClassmultinameMultinameaccessesAccessSet): InstancePropertyOpt
note  Start from the root class (Object) and proceed through more specific classes that are ancestors of c.
for each s  ancestors(cdo
mInstancePropertyOpt  findLocalInstanceProperty(smultinameaccesses);
if m  none then return m end if
end for each;
return none
end proc;
getDerivedInstanceProperty(cmBaseaccesses) returns the most derived instance property whose name includes that of mBase and whose accesses that have a nonempty intersection with accesses. The caller of getDerivedInstanceProperty ensures that such an instance property always exists. If accesses is readWrite then it is possible that this search could find both a getter and a setter defined in the same class; in this case either the getter or the setter is returned at the implementation’s discretion.
proc getDerivedInstanceProperty(cClassmBaseInstancePropertyaccessesAccessSet): InstanceProperty
if some m  c.instanceProperties satisfies mBase.multiname  m.multiname and accessesOverlap(instancePropertyAccesses(m), accessesthen
return m
else return getDerivedInstanceProperty(c.supermBaseaccesses)
end if
end proc;
readImplicitThis(env) returns the value of implicit this to be used to access instance properties within a class’s scope without using the . operator. An implicit this is well-defined only inside instance methods and constructors; readImplicitThis throws an error if there is no well-defined implicit this value or if an attempt is made to read it before it has been initialised.
proc readImplicitThis(envEnvironment): Object
frameParameterFrameOpt  getEnclosingParameterFrame(env);
if frame = none then
throw a ReferenceError exception — can’t access instance properties outside an instance method without supplying an instance object
end if;
thisObjectOpt  frame.this;
if this = none then
throw a ReferenceError exception — can’t access instance properties inside a non-instance method without supplying an instance object
end if;
if frame.kind  {instanceFunctionconstructorFunctionthen
throw a ReferenceError exception — can’t access instance properties inside a non-instance method without supplying an instance object
end if;
if not frame.superconstructorCalled then
throw an UninitializedError exception — can’t access instance properties from within a constructor before the superconstructor has been called
end if;
return this
end proc;
hasProperty(opropertyflatphase) returns true if o has a readable or writable property named property. If flat is true, then properties inherited from the archetype are not considered.
proc hasProperty(oObjectpropertyObjectflatBooleanphasePhase): Boolean
cClass  objectType(o);
return c.hasProperty(ocpropertyflatphase)
end proc;
hasProperty(ocpropertyflatphase) is the implementation of hasProperty for a native class unless specified otherwise in the class’s definition. Host classes may either also use ordinaryHasProperty or define a different procedure to perform this test. c is o’s type.
proc ordinaryHasProperty(oObject, cClass, propertyObject, flatBoolean, phasePhase): Boolean
qnameQualifiedName  objectToQualifiedName(propertyphase);
return findBaseInstanceProperty(c, {qname}, read none or findBaseInstanceProperty(c, {qname}, write none or findArchetypeProperty(o, {qname}, readflat none or findArchetypeProperty(o, {qname}, writeflat none
end proc;

Reading

If r is an Object, readReference(rphase) returns it unchanged. If r is a Reference, readReference reads r and returns the result. If phase is compile, only constant expressions can be evaluated in the process of reading r.
proc readReference(rObjOrRefphasePhase): Object
resultObjectOpt;
case r of
Object do result  r;
LexicalReference do result  lexicalRead(r.envr.variableMultinamephase);
result  r.limit.read(r.baser.limitr.multinamenonetruephase);
result  r.limit.bracketRead(r.baser.limitr.argstruephase)
end case;
if result  none then return result
else
throw a ReferenceError exception — property not found, and no default value is available
end if
end proc;
dotRead(omultinamephase) reads and returns the value of the multiname property of o. dotRead throws an error if the property does not exist and no default value was available for it.
proc dotRead(oObjectmultinameMultinamephasePhase): Object
limitClass  objectType(o);
resultObjectOpt  limit.read(olimitmultinamenonetruephase);
if result = none then
throw a ReferenceError exception — property not found, and no default value is available
end if;
return result
end proc;
readLength(ophase) reads and returns the value of the length property of o, ensuring that it is an integer between 0 and arrayLimit inclusive.
proc readLength(oObjectphasePhase): Integer
valueObject  dotRead(o, {public::“length”}, phase);
if value  GeneralNumber then throw a TypeError exception — length not an integer
end if;
lengthIntegerOpt  checkInteger(value);
if length = none then throw a RangeError exception — length not an integer
elsif 0  length  arrayLimit then return length
else throw a RangeError exception — length out of range
end if
end proc;
indexRead(oiphase) returns the value of o[i] or none if no such property was found; unlike dotRead, indexRead does not return a default value for missing properties. i should always be a valid array index.
proc indexRead(oObjectiIntegerphasePhase): ObjectOpt
note  0  i < arrayLimit;
limitClass  objectType(o);
xFloat64  if64;
resultObjectOpt  limit.bracketRead(olimit[x]falsephase);
if result  none and not hasProperty(oxtruephasethen
At the implementation’s discretion either do nothing, set result to none, or throw a ReferenceError.
end if;
return result
end proc;
ordinaryBracketRead(olimitargsundefinedIfMissingphase) evaluates the expression o[args] when o is a native object. Host objects may either also use ordinaryBracketRead or choose a different procedure P to evaluate o[args] by writing P into objectType(o).bracketRead.
limit is used to handle the expression super(o)[args], in which case limit is the superclass of the class inside which the super expression appears. Otherwise, limit is set to objectType(o).
proc ordinaryBracketRead(oObject, limitClass, argsObject[], undefinedIfMissingBoolean, phasePhase): ObjectOpt
if |args 1 then
throw an ArgumentError exception — exactly one argument must be supplied
end if;
qnameQualifiedName  objectToQualifiedName(args[0], phase);
return limit.read(olimit, {qname}, noneundefinedIfMissingphase)
end proc;
proc lexicalRead(envEnvironmentmultinameMultinamephasePhase): Object
iInteger  0;
while i < |envdo
frameFrame  env[i];
resultObjectOpt  none;
case frame of
Package  Class do
limitClass  objectType(frame);
result  limit.read(framelimitmultinameenvfalsephase);
ParameterFrame  LocalFrame do
mSingletonPropertyOpt  findLocalSingletonProperty(framemultinameread);
if m  none then result  readSingletonProperty(mphaseend if;
valueObjectOpt  frame.value;
if value = none then
case phase of
{compiledo
throw a ConstantError exception — cannot read a with statement’s frame from a constant expression;
{rundo
throw an UninitializedError exception — cannot read a with statement’s frame before that statement’s expression has been evaluated
end case
end if;
limitClass  objectType(value);
result  limit.read(valuelimitmultinameenvfalsephase)
end case;
if result  none then return result end if;
i  i + 1
end while;
throw a ReferenceError exception — no property found with the name multiname
end proc;
proc ordinaryRead(oObject, limitClass, multinameMultiname, envEnvironmentOpt, undefinedIfMissingBoolean, phasePhase): ObjectOpt
mBaseInstancePropertyOpt  findBaseInstanceProperty(limitmultinameread);
if mBase  none then return readInstanceProperty(olimitmBasephaseend if;
if limit  objectType(othen return none end if;
flatBoolean  env  none and o  Class;
mPropertyOpt  findArchetypeProperty(omultinamereadflat);
case m of
{nonedo
if undefinedIfMissing and o  SimpleInstance  Date  RegExp  Package and not o.sealed then
case phase of
{compiledo
throw a ConstantError exception — a constant expression cannot read dynamic properties;
{rundo return undefined
end case
else return none
end if;
SingletonProperty do return readSingletonProperty(mphase);
if o  Class or env = none then
throw a ReferenceError exception — cannot read an instance property without supplying an instance
end if;
thisObject  readImplicitThis(env);
return readInstanceProperty(thisobjectType(this), mphase)
end case
end proc;
readInstanceProperty(oqnamephase) is a simplified interface to ordinaryRead used to read instance slots that are known to exist.
proc readInstanceSlot(oObjectqnameQualifiedNamephasePhase): Object
cClass  objectType(o);
mBaseInstancePropertyOpt  findBaseInstanceProperty(c, {qname}, read);
note  readInstanceProperty is only called in cases where the instance property is known to exist, so mBase cannot be none here.
return readInstanceProperty(ocmBasephase)
end proc;
proc readInstanceProperty(thisObjectcClassmBaseInstancePropertyphasePhase): Object
mInstanceProperty  getDerivedInstanceProperty(cmBaseread);
case m of
if phase = compile and not m.immutable then
throw a ConstantError exception — a constant expression cannot read mutable variables
end if;
vObjectOpt  findSlot(thism).value;
if v = none then
case phase of
{compiledo
throw a ConstantError exception — cannot read uninitalised const variables from a constant expression;
{rundo
throw an UninitializedError exception — cannot read a const instance variable before it is initialised
end case
end if;
return v;
slotsSlot{}  {new SlotidivarFunctionLengthvalue: (m.length)f64};
return MethodClosurethisthismethodmslotsslots;
InstanceGetter do return m.call(thisphase);
m cannot be an InstanceSetter because these are only represented as write-only properties.
end case
end proc;
proc readSingletonProperty(mSingletonPropertyphasePhase): Object
case m of
{forbiddendo
throw a ReferenceError exception — cannot access a property defined in a scope outside the current region if any block inside the current region shadows it;
if phase = compile then
throw a ConstantError exception — a constant expression cannot read mutable variables
end if;
valueObject  UninstantiatedFunction  m.value;
note  value can be an UninstantiatedFunction only during the compile phase, which was ruled out above.
return value;
if phase = compile and not m.immutable then
throw a ConstantError exception — a constant expression cannot read mutable variables
end if;
valueVariableValue  m.value;
case value of
Object do return value;
{nonedo
if not m.immutable then throw an UninitializedError exception end if;
note  Try to run a const variable’s initialiser if there is one.
Evaluate setupVariable(m) and ignore its result;
initializerInitializer  {nonebusy m.initializer;
if initializer  {nonebusythen
case phase of
{compiledo
throw a ConstantError exception — a constant expression cannot access a constant with a missing or recursive initialiser;
{rundo throw an UninitializedError exception
end case
end if;
m.initializer  busy;
coercedValueObject;
try
newValueObject  initializer(m.initializerEnvcompile);
coercedValue  writeVariable(mnewValuetrue)
catch xSemanticException do
note  If initialisation failed, restore m.initializer to its original value so it can be tried later.
m.initializer  initializer;
throw x
end try;
return coercedValue;
note  An uninstantiated function can only be found when phase = compile.
throw a ConstantError exception — an uninstantiated function is not a constant expression
end case;
Getter do
envEnvironmentOpt  m.env;
if env = none then
note  An uninstantiated getter can only be found when phase = compile.
throw a ConstantError exception — an uninstantiated getter is not a constant expression
end if;
return m.call(envphase);
Setter do
m cannot be a Setter because these are only represented as write-only properties.
end case
end proc;

Writing

If r is a reference, writeReference(rnewValue) writes newValue into r. An error occurs if r is not a reference. writeReference is never called from a constant expression.
proc writeReference(rObjOrRefnewValueObjectphase: {run})
result: {noneok};
case r of
Object do
throw a ReferenceError exception — a non-reference is not a valid target of an assignment;
Evaluate lexicalWrite(r.envr.variableMultinamenewValuenot r.strictphase) and ignore its result;
result  ok;
result  r.limit.write(r.baser.limitr.multinamenonenewValuetruephase);
result  r.limit.bracketWrite(r.baser.limitr.argsnewValuetruephase)
end case;
if result = none then
throw a ReferenceError exception — property not found and could not be created
end if
end proc;
dotWrite(omultinamenewValuephase) is a simplified interface to write newValue into the multiname property of o.
proc dotWrite(oObjectmultinameMultinamenewValueObjectphase: {run})
limitClass  objectType(o);
result: {noneok limit.write(olimitmultinamenonenewValuetruephase);
if result = none then
throw a ReferenceError exception — property not found and could not be created
end if
end proc;
writeLength(olengthphase) ensures that length is between 0 and arrayLimit inclusive and then writes it into the length property of o. Note that if o is an Array, the act of writing its length property will invoke the Array_setLength setter.
proc writeLength(oObjectlengthIntegerphase: {run})
if length < 0 or length > arrayLimit then
throw a RangeError exception — length out of range
end if;
Evaluate dotWrite(o, {public::“length”}, lengthf64phase) and ignore its result
end proc;
proc indexWrite(oObjectiIntegernewValueObjectOptphase: {run})
if i < 0 or i  arrayLimit then throw a RangeError exception — index out of range
end if;
limitClass  objectType(o);
if newValue = none then
deleteResultBooleanOpt  limit.bracketDelete(olimit[if64]phase);
if deleteResult = false then
throw a ReferenceError exception — cannot delete element
end if
else
writeResult: {noneok limit.bracketWrite(olimit[if64]newValuetruephase);
if writeResult = none then
throw a ReferenceError exception — element not found and could not be created
end if
end if
end proc;
proc ordinaryBracketWrite(oObject, limitClass, argsObject[], newValueObject, createIfMissingBoolean, phase: {run}): {noneok}
if |args 1 then
throw an ArgumentError exception — exactly one argument must be supplied
end if;
qnameQualifiedName  objectToQualifiedName(args[0], phase);
return limit.write(olimit, {qname}, nonenewValuecreateIfMissingphase)
end proc;
proc lexicalWrite(envEnvironment, multinameMultiname, newValueObject, createIfMissingBoolean, phase: {run})
iInteger  0;
while i < |envdo
frameFrame  env[i];
result: {noneok none;
case frame of
Package  Class do
limitClass  objectType(frame);
result  limit.write(framelimitmultinameenvnewValuefalsephase);
ParameterFrame  LocalFrame do
mSingletonPropertyOpt  findLocalSingletonProperty(framemultinamewrite);
if m  none then
Evaluate writeSingletonProperty(mnewValuephase) and ignore its result;
result  ok
end if;
valueObjectOpt  frame.value;
if value = none then
throw an UninitializedError exception — cannot read a with statement’s frame before that statement’s expression has been evaluated
end if;
limitClass  objectType(value);
result  limit.write(valuelimitmultinameenvnewValuefalsephase)
end case;
if result = ok then return end if;
i  i + 1
end while;
if createIfMissing then
pkgPackage  getPackageFrame(env);
note  Try to write the variable into pkg again, this time allowing new dynamic bindings to be created dynamically.
limitClass  objectType(pkg);
result: {noneok limit.write(pkglimitmultinameenvnewValuetruephase);
if result = ok then return end if
end if;
throw a ReferenceError exception — no existing property found with the name multiname and one could not be created
end proc;
proc ordinaryWrite(oObject, limitClass, multinameMultiname, envEnvironmentOpt, newValueObject, createIfMissingBoolean, phase: {run}): {noneok}
mBaseInstancePropertyOpt  findBaseInstanceProperty(limitmultinamewrite);
if mBase  none then
Evaluate writeInstanceProperty(olimitmBasenewValuephase) and ignore its result;
return ok
end if;
if limit  objectType(othen return none end if;
mPropertyOpt  findArchetypeProperty(omultinamewritetrue);
case m of
{nonedo
if createIfMissing and o  SimpleInstance  Date  RegExp  Package and not o.sealed and (some qname  multiname satisfies qname.namespace = publicthen
note  Before trying to create a new dynamic property named qname, check that there is no read-only fixed property with the same name.
if findBaseInstanceProperty(objectType(o), {qname}, read) = none and findArchetypeProperty(o, {qname}, readtrue) = none then
Evaluate createDynamicProperty(oqnamefalsetruenewValue) and ignore its result;
return ok
end if
end if;
return none;
Evaluate writeSingletonProperty(mnewValuephase) and ignore its result;
return ok;
if o  Class or env = none then
throw a ReferenceError exception — cannot write an instance property without supplying an instance
end if;
thisObject  readImplicitThis(env);
Evaluate writeInstanceProperty(thisobjectType(this), mnewValuephase) and ignore its result;
return ok
end case
end proc;
The caller must make sure that the created property does not already exist and does not conflict with any other property.
proc createDynamicProperty(oSimpleInstance  Date  RegExp  Package, qnameQualifiedName, sealedBoolean, enumerableBoolean, newValueObject)
dvDynamicVar  new DynamicVarvaluenewValuesealedsealed;
o.localBindings  o.localBindings  {LocalBindingqnameqname, accessesreadWrite, explicitfalse, enumerableenumerable, contentdv}
end proc;
proc writeInstanceProperty(thisObject, cClass, mBaseInstanceProperty, newValueObject, phase: {run})
mInstanceProperty  getDerivedInstanceProperty(cmBasewrite);
case m of
sSlot  findSlot(thism);
coercedValueObject  coerce(newValuem.type);
if m.immutable and s.value  none then
throw a ReferenceError exception — cannot initialise a const instance variable twice
end if;
s.value  coercedValue;
throw a ReferenceError exception — cannot write to an instance method;
m cannot be an InstanceGetter because these are only represented as read-only properties.
InstanceSetter do Evaluate m.call(thisnewValuephase) and ignore its result
end case
end proc;
proc writeSingletonProperty(mSingletonPropertynewValueObjectphase: {run})
case m of
{forbiddendo
throw a ReferenceError exception — cannot access a property defined in a scope outside the current region if any block inside the current region shadows it;
Variable do Evaluate writeVariable(mnewValuefalse) and ignore its result;
DynamicVar do m.value  newValue;
Getter do
m cannot be a Getter because these are only represented as read-only properties.
Setter do
envEnvironmentOpt  m.env;
note  All instances are resolved for the run phase, so env  none.
Evaluate m.call(newValueenvphase) and ignore its result
end case
end proc;

Deleting

If r is a Reference, deleteReference(r) deletes it. If r is an Object, this function signals an error in strict mode or returns true in non-strict mode. deleteReference is never called from a constant expression.
proc deleteReference(rObjOrRefstrictBooleanphase: {run}): Boolean
resultBooleanOpt;
case r of
Object do
if strict then
throw a ReferenceError exception — a non-reference is not a valid target for delete in strict mode
else result  true
end if;
LexicalReference do result  lexicalDelete(r.envr.variableMultinamephase);
result  r.limit.delete(r.baser.limitr.multinamenonephase);
result  r.limit.bracketDelete(r.baser.limitr.argsphase)
end case;
if result  none then return result else return true end if
end proc;
proc ordinaryBracketDelete(oObjectlimitClassargsObject[], phase: {run}): BooleanOpt
if |args 1 then
throw an ArgumentError exception — exactly one argument must be supplied
end if;
qnameQualifiedName  objectToQualifiedName(args[0], phase);
return limit.delete(olimit, {qname}, nonephase)
end proc;
proc lexicalDelete(envEnvironmentmultinameMultinamephase: {run}): Boolean
iInteger  0;
while i < |envdo
frameFrame  env[i];
resultBooleanOpt  none;
case frame of
Package  Class do
limitClass  objectType(frame);
result  limit.delete(framelimitmultinameenvphase);
ParameterFrame  LocalFrame do
if findLocalSingletonProperty(framemultinamewrite none then
result  false
end if;
valueObjectOpt  frame.value;
if value = none then
throw an UninitializedError exception — cannot read a with statement’s frame before that statement’s expression has been evaluated
end if;
limitClass  objectType(value);
result  limit.delete(valuelimitmultinameenvphase)
end case;
if result  none then return result end if;
i  i + 1
end while;
return true
end proc;
proc ordinaryDelete(oObject, limitClass, multinameMultiname, envEnvironmentOpt, phase: {run}): BooleanOpt
if findBaseInstanceProperty(limitmultinamewrite none then return false end if;
if limit  objectType(othen return none end if;
mPropertyOpt  findArchetypeProperty(omultinamewritetrue);
case m of
{nonedo return none;
{forbiddendo
throw a ReferenceError exception — cannot access a property defined in a scope outside the current region if any block inside the current region shadows it;
Variable  Getter  Setter do return false;
if m.sealed then return false
else
o.localBindings  {b | b  o.localBindings such that b.qname  multiname or b.content  m};
return true
end if;
if o  Class or env = none then return false end if;
Evaluate readImplicitThis(env) and ignore its result;
return false
end case
end proc;

Enumerating

proc ordinaryEnumerate(oObject): Object{}
e1Object{}  enumerateInstanceProperties(objectType(o));
e2Object{}  enumerateArchetypeProperties(o);
return e1  e2
end proc;
proc enumerateInstanceProperties(cClass): Object{}
eObject{}  {};
for each m  c.instanceProperties do
if m.enumerable then
e  e  {qname.id | qname  m.multiname such that qname.namespace = public}
end if
end for each;
superClassOpt  c.super;
if super = none then return e
else return e  enumerateInstanceProperties(super)
end if
end proc;
proc enumerateArchetypeProperties(oObject): Object{}
eObject{}  {};
for each a  {o archetypes(odo
if a  BindingObject then e  e  enumerateSingletonProperties(aend if
end for each;
return e
end proc;
proc enumerateSingletonProperties(oBindingObject): Object{}
eObject{}  {};
for each b  o.localBindings do
if b.enumerable and b.qname.namespace = public then e  e  {b.qname.idend if
end for each;
if o  Class then
superClassOpt  o.super;
if super  none then e  e  enumerateSingletonProperties(superend if
end if;
return e
end proc;

Calling Instances

proc call(thisObjectaObjectargsObject[], phasePhase): Object
case a of
Undefined  Null  Boolean  GeneralNumber  Char16  String  Namespace  CompoundAttribute  Date  RegExp  Package do
throw a TypeError exception;
Class do return a.call(thisaargsphase);
f: (Object  SimpleInstance  Object[]  Phase  Object {none a.call;
if f = none then throw a TypeError exception end if;
return f(thisaargsphase);
MethodClosure do mInstanceMethod  a.methodreturn m.call(a.thisargsphase)
end case
end proc;
proc ordinaryCall(thisObjectcClassargsObject[], phasePhase): Object
note  This function can be used in a constant expression.
if not c.complete then
throw a ConstantError exception — cannot call a class before its definition has been compiled
end if;
if |args 1 then
throw an ArgumentError exception — exactly one argument must be supplied
end if;
return coerce(args[0], c)
end proc;
proc sameAsConstruct(thisObjectcClassargsObject[], phasePhase): Object
return construct(cargsphase)
end proc;

Creating Instances

proc construct(aObjectargsObject[], phasePhase): Object
case a of
Undefined  Null  Boolean  GeneralNumber  Char16  String  Namespace  CompoundAttribute  MethodClosure  Date  RegExp  Package do
throw a TypeError exception;
Class do return a.construct(aargsphase);
f: (SimpleInstance  Object[]  Phase  Object {none a.construct;
if f = none then throw a TypeError exception end if;
return f(aargsphase)
end case
end proc;
proc ordinaryConstruct(cClassargsObject[], phasePhase): Object
if not c.complete then
throw a ConstantError exception — cannot construct an instance of a class before its definition has been compiled
end if;
if phase = compile then
throw a ConstantError exception — a class constructor call is not a constant expression because it evaluates to a new object each time it is evaluated
end if;
thisSimpleInstance  createSimpleInstance(cc.prototypenonenonenone);
Evaluate callInit(thiscargsphase) and ignore its result;
return this
end proc;
proc createSimpleInstance(cClass, archetypeObjectOpt, call: (Object  SimpleInstance  Object[]  Phase  Object {none}, construct: (SimpleInstance  Object[]  Phase  Object {none}, envEnvironmentOpt): SimpleInstance
slotsSlot{}  {};
for each s  ancestors(cdo
for each m  s.instanceProperties do
if m  InstanceVariable then
slotSlot  new Slotidmvaluem.defaultValue;
slots  slots  {slot}
end if
end for each
end for each;
return new SimpleInstancelocalBindings: {}, archetypearchetype, sealednot c.dynamic, typec, slotsslots, callcall, constructconstruct, envenv
end proc;
proc callInit(thisSimpleInstancecClassOptargsObject[], phase: {run})
init: (SimpleInstance  Object[]  {run ())  {none none;
if c  none then init  c.init end if;
if init  none then Evaluate init(thisargsphase) and ignore its result
else
if args  [] then
throw an ArgumentError exception — the default constructor does not take any arguments
end if
end if
end proc;

Adding Local Definitions

proc defineSingletonProperty(envEnvironment, idString, namespacesNamespace{}, overrideModOverrideModifier, explicitBoolean, accessesAccessSet, mSingletonProperty): Multiname
innerFrameNonWithFrame  env[0];
if overrideMod  none then
throw an AttributeError exception — a local definition cannot have the override attribute
end if;
if explicit and innerFrame  Package then
throw an AttributeError exception — the explicit attribute can only be used at the top level of a package
end if;
namespaces2Namespace{}  namespaces;
if namespaces2 = {} then namespaces2  {publicend if;
multinameMultiname  {ns::id | ns  namespaces2};
regionalEnvFrame[]  getRegionalEnvironment(env);
if some b  innerFrame.localBindings satisfies b.qname  multiname and accessesOverlap(b.accessesaccessesthen
throw a DefinitionError exception — duplicate definition in the same scope
end if;
if innerFrame  Class and id = innerFrame.name then
throw a DefinitionError exception — a static property of a class cannot have the same name as the class, regardless of the namespace
end if;
for each frame  regionalEnv[1 ...] do
if frame  WithFrame and (some b  frame.localBindings satisfies b.qname  multiname and accessesOverlap(b.accessesaccessesand b.content  forbiddenthen
throw a DefinitionError exception — this definition would shadow a property defined in an outer scope within the same region
end if
end for each;
newBindingsLocalBinding{}  {LocalBindingqnameqname, accessesaccesses, explicitexplicit, enumerabletrue, contentm | qname  multiname};
innerFrame.localBindings  innerFrame.localBindings  newBindings;
note  Mark the bindings of multiname as forbidden in all non-innermost frames in the current region if they haven’t been marked as such already.
newForbiddenBindingsLocalBinding{}  {LocalBindingqnameqname, accessesaccesses, explicittrue, enumerabletrue, contentforbidden | qname  multiname};
for each frame  regionalEnv[1 ...] do
note  Since frame  Class here, a Class frame never gets a forbidden binding.
if frame  WithFrame then
frame.localBindings  frame.localBindings  newForbiddenBindings
end if
end for each;
return multiname
end proc;
defineHoistedVar(envidinitialValue) defines a hoisted variable with the name id in the environment env. Hoisted variables are hoisted to the package or enclosing function scope. Multiple hoisted variables may be defined in the same scope, but they may not coexist with non-hoisted variables with the same name. A hoisted variable can be defined using either a var or a function statement. If it is defined using var, then initialValue is always undefined (if the var statement has an initialiser, then the variable’s value will be written later when the var statement is executed). If it is defined using function, then initialValue must be a function instance or open instance. A var hoisted variable may be hoisted into the ParameterFrame if there is already a parameter with the same name; a function hoisted variable is never hoisted into the ParameterFrame and will shadow a parameter with the same name for compatibility with ECMAScript Edition 3. If there are multiple function definitions, the initial value is the last function definition.
proc defineHoistedVar(envEnvironment, idString, initialValueObject  UninstantiatedFunction): DynamicVar
qnameQualifiedName  public::id;
regionalEnvFrame[]  getRegionalEnvironment(env);
regionalFrameFrame  regionalEnv[|regionalEnv| – 1];
note  env is either a Package or a ParameterFrame because hoisting only occurs into package or function scope.
existingBindingsLocalBinding{}  {b | b  regionalFrame.localBindings such that b.qname = qname};
if (existingBindings = {} or initialValue  undefinedand regionalFrame  ParameterFrame and |regionalEnv 2 then
regionalFrame  regionalEnv[|regionalEnv| – 2];
existingBindings  {b | b  regionalFrame.localBindings such that b.qname = qname}
end if;
if existingBindings = {} then
vDynamicVar  new DynamicVarvalueinitialValuesealedtrue;
regionalFrame.localBindings  regionalFrame.localBindings  {LocalBindingqnameqname, accessesreadWrite, explicitfalse, enumerabletrue, contentv};
return v
elsif |existingBindings 1 then
throw a DefinitionError exception — a hoisted definition conflicts with a non-hoisted one
else
bLocalBinding  the one element of existingBindings;
mSingletonProperty  b.content;
if b.accesses  readWrite or m  DynamicVar then
throw a DefinitionError exception — a hoisted definition conflicts with a non-hoisted one
end if;
note  At this point a hoisted binding of the same var already exists, so there is no need to create another one. Overwrite its initial value if the new definition is a function definition.
if initialValue  undefined then m.value  initialValue end if;
m.sealed  true;
regionalFrame.localBindings  regionalFrame.localBindings – {b};
regionalFrame.localBindings  regionalFrame.localBindings  {LocalBindingenumerabletrue, other fields from b};
return m
end if
end proc;

Adding Instance Definitions

proc searchForOverrides(cClassmultinameMultinameaccessesAccessSet): InstancePropertyOpt
mBaseInstancePropertyOpt  none;
sClassOpt  c.super;
if s  none then
for each qname  multiname do
mInstancePropertyOpt  findBaseInstanceProperty(s, {qname}, accesses);
if mBase = none then mBase  m
elsif m  none and m  mBase then
throw a DefinitionError exception — cannot override two separate superclass methods at the same time
end if
end for each
end if;
return mBase
end proc;
proc defineInstanceProperty(cClass, cxtContext, idString, namespacesNamespace{}, overrideModOverrideModifier, explicitBoolean, mInstanceProperty): InstancePropertyOpt
if explicit then
throw an AttributeError exception — the explicit attribute can only be used at the top level of a package
end if;
accessesAccessSet  instancePropertyAccesses(m);
requestedMultinameMultiname  {ns::id | ns  namespaces};
openMultinameMultiname  {ns::id | ns  cxt.openNamespaces};
definedMultinameMultiname;
searchedMultinameMultiname;
if requestedMultiname = {} then
definedMultiname  {public::id};
searchedMultiname  openMultiname;
note  definedMultiname  searchedMultiname because the public namespace is always open.
else definedMultiname  requestedMultinamesearchedMultiname  requestedMultiname
end if;
mBaseInstancePropertyOpt  searchForOverrides(csearchedMultinameaccesses);
mOverriddenInstancePropertyOpt  none;
if mBase  none then
mOverridden  getDerivedInstanceProperty(cmBaseaccesses);
definedMultiname  mOverridden.multiname;
if not (requestedMultiname  definedMultinamethen
throw a DefinitionError exception — cannot extend the set of a property’s namespaces when overriding it
end if;
goodKindBoolean;
case m of
InstanceVariable do goodKind  mOverridden  InstanceVariable;
goodKind  mOverridden  InstanceVariable  InstanceGetter;
goodKind  mOverridden  InstanceVariable  InstanceSetter;
InstanceMethod do goodKind  mOverridden  InstanceMethod
end case;
if not goodKind then
throw a DefinitionError exception — a method can override only another method, a variable can override only another variable, a getter can override only a getter or a variable, and a setter can override only a setter or a variable
end if;
if mOverridden.final then
throw a DefinitionError exception — cannot override a final property
end if
end if;
if some m2  c.instanceProperties satisfies m2.multiname  definedMultiname  {} and accessesOverlap(instancePropertyAccesses(m2), accessesthen
throw a DefinitionError exception — duplicate definition in the same scope
end if;
case overrideMod of
{nonedo
if mBase  none then
throw a DefinitionError exception — a definition that overrides a superclass’s property must be marked with the override attribute
end if;
if searchForOverrides(copenMultinameaccesses none then
throw a DefinitionError exception — this definition is hidden by one in a superclass when accessed without a namespace qualifier; in the rare cases where this is intentional, use the override(false) attribute
end if;
{falsedo
if mBase  none then
throw a DefinitionError exception — this definition is marked with override(false) but it overrides a superclass’s property
end if;
{truedo
if mBase = none then
throw a DefinitionError exception — this definition is marked with override or override(true) but it doesn’t override a superclass’s property
end if;
{undefineddo nothing
end case;
m.multiname  definedMultiname;
c.instanceProperties  c.instanceProperties  {m};
return mOverridden
end proc;

Instantiation

proc instantiateFunction(ufUninstantiatedFunctionenvEnvironment): SimpleInstance
cClass  uf.type;
iSimpleInstance  createSimpleInstance(cc.prototypeuf.calluf.constructenv);
Evaluate dotWrite(i, {public::“length”}, (uf.length)f64run) and ignore its result;
if c = PrototypeFunction then
prototypeObject  construct(Object[]run);
Evaluate dotWrite(prototype, {public::“constructor”}, irun) and ignore its result;
Evaluate dotWrite(i, {public::“prototype”}, prototyperun) and ignore its result
end if;
instantiationsSimpleInstance{}  uf.instantiations;
if instantiations  {} then
Suppose that instantiateFunction were to choose at its discretion some element i2 of instantiations, assign i2.env  env, and return i. If the behaviour of doing that assignment were observationally indistinguishable by the rest of the program from the behaviour of returning i without modifying i2.env, then the implementation may, but does not have to, return i2 now, discarding (or not even bothering to create) the value of i.
note  The above rule allows an implementation to avoid creating a fresh closure each time a local function is instantiated if it can show that the closures would behave identically. This optimisation is not transparent to the programmer because the instantiations will be === to each other and share one set of properties (including the prototype property, if applicable) rather than each having its own. ECMAScript programs should not rely on this distinction.
end if;
uf.instantiations  instantiations  {i};
return i
end proc;
proc instantiateProperty(mSingletonPropertyenvEnvironment): SingletonProperty
case m of
{forbiddendo return m;
note  m.setup = none because Setup must have been called on a frame before that frame can be instantiated.
valueVariableValue  m.value;
if value  UninstantiatedFunction then
value  instantiateFunction(valueenv)
end if;
return new Variabletypem.type, valuevalue, immutablem.immutable, setupnone, initializerm.initializer, initializerEnvenv;
valueObject  UninstantiatedFunction  m.value;
if value  UninstantiatedFunction then
value  instantiateFunction(valueenv)
end if;
return new DynamicVarvaluevaluesealedm.sealed;
Getter do
case m.env of
Environment do return m;
{nonedo return new Gettercallm.callenvenv
end case;
Setter do
case m.env of
Environment do return m;
{nonedo return new Settercallm.callenvenv
end case
end case
end proc;
tuple PropertyTranslation
end tuple;
proc instantiateLocalFrame(frameLocalFrameenvEnvironment): LocalFrame
instantiatedFrameLocalFrame  new LocalFramelocalBindings: {};
propertiesSingletonProperty{}  {b.content | b  frame.localBindings};
propertyTranslationsPropertyTranslation{}  {PropertyTranslationfromm, toinstantiateProperty(m[instantiatedFrame]  env) | m  properties};
proc translateProperty(mSingletonProperty): SingletonProperty
miPropertyTranslation  the one element mi  propertyTranslations that satisfies mi.from = m;
return mi.to
end proc;
instantiatedFrame.localBindings  {LocalBindingcontenttranslateProperty(b.content), other fields from b | b  frame.localBindings};
return instantiatedFrame
end proc;
proc instantiateParameterFrame(frameParameterFrame, envEnvironment, singularThisObjectOpt): ParameterFrame
note  frame.superconstructorCalled must be true if and only if frame.kind is not constructorFunction.
instantiatedFrameParameterFrame  new ParameterFramelocalBindings: {}, kindframe.kind, handlingframe.handling, callsSuperconstructorframe.callsSuperconstructor, superconstructorCalledframe.superconstructorCalled, thissingularThis, returnTypeframe.returnType;
note  properties will contain the set of all SingletonProperty records found in the frame.
propertiesSingletonProperty{}  {b.content | b  frame.localBindings};
note  If any of the parameters (including the rest parameter) are anonymous, their bindings will not be present in frame.localBindings. In this situation, the following steps add their SingletonProperty records to properties.
for each p  frame.parameters do properties  properties  {p.varend for each;
restVariableOpt  frame.rest;
if rest  none then properties  properties  {restend if;
propertyTranslationsPropertyTranslation{}  {PropertyTranslationfromm, toinstantiateProperty(m[instantiatedFrame]  env) | m  properties};
proc translateProperty(mSingletonProperty): SingletonProperty
miPropertyTranslation  the one element mi  propertyTranslations that satisfies mi.from = m;
return mi.to
end proc;
instantiatedFrame.localBindings  {LocalBindingcontenttranslateProperty(b.content), other fields from b | b  frame.localBindings};
instantiatedFrame.parameters  [ParametervartranslateProperty(op.var), defaultop.default | op  frame.parameters];
if rest = none then instantiatedFrame.rest  none
else instantiatedFrame.rest  translateProperty(rest)
end if;
return instantiatedFrame
end proc;

Sealing

proc sealObject(oObject)
if o  SimpleInstance  RegExp  Date  Package then o.sealed  true end if
end proc;
proc sealAllLocalProperties(oObject)
if o  BindingObject then
for each b  o.localBindings do
mSingletonProperty  b.content;
if m  DynamicVar then m.sealed  true end if
end for each
end if
end proc;
proc sealLocalProperty(oObjectqnameQualifiedName)
cClass  objectType(o);
if findBaseInstanceProperty(c, {qname}, read) = none and findBaseInstanceProperty(c, {qname}, write) = none and o  BindingObject then
matchingPropertiesSingletonProperty{}  {b.content | b  o.localBindings such that b.qname = qname};
for each m  matchingProperties do
if m  DynamicVar then m.sealed  true end if
end for each
end if
end proc;

Standard Class Utilities

proc defaultArg(argsObject[], nIntegerdefaultObject): Object
if n  |argsthen return default end if;
argObject  args[n];
if arg = undefined then return default else return arg end if
end proc;
proc stdConstBinding(qnameQualifiedNametypeClassvalueObject): LocalBinding
return LocalBindingqnameqname, accessesreadWrite, explicitfalse, enumerablefalse, content: new Variabletypetype, valuevalue, immutabletrue, setupnone, initializernone
end proc;
proc stdExplicitConstBinding(qnameQualifiedNametypeClassvalueObject): LocalBinding
return LocalBindingqnameqname, accessesreadWrite, explicittrue, enumerablefalse, content: new Variabletypetype, valuevalue, immutabletrue, setupnone, initializernone
end proc;
proc stdVarBinding(qnameQualifiedNametypeClassvalueObject): LocalBinding
return LocalBindingqnameqname, accessesreadWrite, explicitfalse, enumerablefalse, content: new Variabletypetype, valuevalue, immutablefalse, setupnone, initializernone
end proc;
proc stdFunction(qnameQualifiedName, callObject  SimpleInstance  Object[]  Phase  Object, lengthInteger): LocalBinding
slotsSlot{}  {new SlotidivarFunctionLengthvaluelengthf64};
fSimpleInstance  new SimpleInstancelocalBindings: {}, archetypeFunctionPrototype, sealedtrue, typeFunction, slotsslots, callcall, constructnone, envnone;
return LocalBindingqnameqname, accessesreadWrite, explicitfalse, enumerablefalse, content: new VariabletypeFunction, valuef, immutabletrue, setupnone, initializernone
end proc;
stdReserve(qnamearchetype) is used during the creation of system objects. It returns an alias of the local binding of qname in archetype, which should be the archetype of the object being created. The alias that stdReserve defines serves to prevent qname from being later redefined by users in the object being created while at the same time retaining the definition of qname that would normally be inherited from archetype.
proc stdReserve(qnameQualifiedNamearchetypeSimpleInstance): LocalBinding
matchingBindingsLocalBinding{}  {b | b  archetype.localBindings such that b.qname = qname};
return the one element of matchingBindings
end proc;

Expressions

Syntax

  {allowInnoIn}

Terminal Actions

Name[Identifier]: String;
Value[Number]: GeneralNumber;
Value[String]: String;
Body[RegularExpression]: String;
Flags[RegularExpression]: String;

Identifiers

Syntax

Identifier 
   Identifier
|  get
|  set

Semantics

Name[Identifier]: String;
Name[Identifier  Identifier] = Name[Identifier];
Name[Identifier  get] = “get”;
Name[Identifier  set] = “set”;

Qualified Identifiers

Syntax

SimpleQualifiedIdentifier 
   Identifier
|  Identifier :: Identifier
|  ReservedNamespace :: Identifier
ExpressionQualifiedIdentifier  ParenExpression :: Identifier
QualifiedIdentifier 
   SimpleQualifiedIdentifier
|  ExpressionQualifiedIdentifier

Validation

OpenNamespaces[SimpleQualifiedIdentifier]: Namespace{};
Strict[SimpleQualifiedIdentifier]: Boolean;
proc Validate[SimpleQualifiedIdentifier] (cxtContextenvEnvironment)
[SimpleQualifiedIdentifier  Identifierdo
OpenNamespaces[SimpleQualifiedIdentifier cxt.openNamespaces;
Strict[SimpleQualifiedIdentifier cxt.strict;
[SimpleQualifiedIdentifier  Identifier :: Identifierdo
OpenNamespaces[SimpleQualifiedIdentifier cxt.openNamespaces;
[SimpleQualifiedIdentifier  ReservedNamespace :: Identifierdo
Evaluate Validate[ReservedNamespace](cxtenv) and ignore its result
end proc;
Strict[ExpressionQualifiedIdentifier]: Boolean;
proc Validate[ExpressionQualifiedIdentifier  ParenExpression :: Identifier] (cxtContextenvEnvironment)
Strict[ExpressionQualifiedIdentifier cxt.strict;
Evaluate Validate[ParenExpression](cxtenv) and ignore its result
end proc;
Strict[QualifiedIdentifier]: Boolean;
proc Validate[QualifiedIdentifier] (cxtContextenvEnvironment)
[QualifiedIdentifier  SimpleQualifiedIdentifierdo
Strict[QualifiedIdentifier cxt.strict;
Evaluate Validate[SimpleQualifiedIdentifier](cxtenv) and ignore its result;
[QualifiedIdentifier  ExpressionQualifiedIdentifierdo
Strict[QualifiedIdentifier cxt.strict;
Evaluate Validate[ExpressionQualifiedIdentifier](cxtenv) and ignore its result
end proc;

Setup

proc Setup[SimpleQualifiedIdentifier] ()
[SimpleQualifiedIdentifier  Identifierdo nothing;
[SimpleQualifiedIdentifier  Identifier :: Identifierdo nothing;
[SimpleQualifiedIdentifier  ReservedNamespace :: Identifierdo
Evaluate Setup[ReservedNamespace]() and ignore its result
end proc;
proc Setup[ExpressionQualifiedIdentifier  ParenExpression :: Identifier] ()
Evaluate Setup[ParenExpression]() and ignore its result
end proc;
Setup[QualifiedIdentifier] () propagates the call to Setup to nonterminals in the expansion of QualifiedIdentifier.

Evaluation

proc Eval[SimpleQualifiedIdentifier] (envEnvironmentphasePhase): Multiname
[SimpleQualifiedIdentifier  Identifierdo
return {ns::(Name[Identifier]) | ns  OpenNamespaces[SimpleQualifiedIdentifier]};
[SimpleQualifiedIdentifier  Identifier1 :: Identifier2do
multinameMultiname  {ns::(Name[Identifier1]) | ns  OpenNamespaces[SimpleQualifiedIdentifier]};
aObject  lexicalRead(envmultinamephase);
if a  Namespace then
throw a TypeError exception — the qualifier must be a namespace
end if;
return {a::(Name[Identifier2])};
[SimpleQualifiedIdentifier  ReservedNamespace :: Identifierdo
qNamespace  Eval[ReservedNamespace](envphase);
return {q::(Name[Identifier])}
end proc;
proc Eval[ExpressionQualifiedIdentifier  ParenExpression :: Identifier] (envEnvironmentphasePhase): Multiname
qObject  readReference(Eval[ParenExpression](envphase), phase);
if q  Namespace then throw a TypeError exception — the qualifier must be a namespace
end if;
return {q::(Name[Identifier])}
end proc;
Eval[QualifiedIdentifier] (envEnvironmentphasePhase): Multiname propagates the call to Eval to nonterminals in the expansion of QualifiedIdentifier.

Primary Expressions

Syntax

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

Validation

proc Validate[PrimaryExpression] (cxtContextenvEnvironment)
[PrimaryExpression  nulldo nothing;
[PrimaryExpression  truedo nothing;
[PrimaryExpression  falsedo nothing;
[PrimaryExpression  Numberdo nothing;
[PrimaryExpression  Stringdo nothing;
[PrimaryExpression  thisdo
frameParameterFrameOpt  getEnclosingParameterFrame(env);
if frame = none then
if cxt.strict then
throw a SyntaxError exception — this can be used outside a function only in non-strict mode
end if
elsif frame.kind = plainFunction then
throw a SyntaxError exception — this function does not define this
end if;
[PrimaryExpression  RegularExpressiondo nothing;
[PrimaryExpression  ReservedNamespacedo
Evaluate Validate[ReservedNamespace](cxtenv) and ignore its result;
[PrimaryExpression  ParenListExpressiondo
Evaluate Validate[ParenListExpression](cxtenv) and ignore its result;
[PrimaryExpression  ArrayLiteraldo
Evaluate Validate[ArrayLiteral](cxtenv) and ignore its result;
[PrimaryExpression  ObjectLiteraldo
Evaluate Validate[ObjectLiteral](cxtenv) and ignore its result;
[PrimaryExpression  FunctionExpressiondo
Evaluate Validate[FunctionExpression](cxtenv) and ignore its result
end proc;
proc Validate[ReservedNamespace] (cxtContextenvEnvironment)
[ReservedNamespace  publicdo nothing;
[ReservedNamespace  privatedo
if getEnclosingClass(env) = none then
throw a SyntaxError exception — private is meaningful only inside a class
end if
end proc;
Validate[ParenExpression] (cxtContextenvEnvironment) propagates the call to Validate to nonterminals in the expansion of ParenExpression.
Validate[ParenListExpression] (cxtContextenvEnvironment) propagates the call to Validate to nonterminals in the expansion of ParenListExpression.

Setup

Setup[PrimaryExpression] () propagates the call to Setup to nonterminals in the expansion of PrimaryExpression.
proc Setup[ReservedNamespace] ()
[ReservedNamespace  publicdo nothing;
[ReservedNamespace  privatedo nothing
end proc;
Setup[ParenExpression] () propagates the call to Setup to nonterminals in the expansion of ParenExpression.
Setup[ParenListExpression] () propagates the call to Setup to nonterminals in the expansion of ParenListExpression.

Evaluation

proc Eval[PrimaryExpression] (envEnvironmentphasePhase): ObjOrRef
[PrimaryExpression  nulldo return null;
[PrimaryExpression  truedo return true;
[PrimaryExpression  falsedo return false;
[PrimaryExpression  Numberdo return Value[Number];
[PrimaryExpression  Stringdo return Value[String];
[PrimaryExpression  thisdo
frameParameterFrameOpt  getEnclosingParameterFrame(env);
if frame = none then return getPackageFrame(envend if;
note  Validate ensured that frame.kind  plainFunction at this point.
thisObjectOpt  frame.this;
if this = none then
note  If Validate passed, this can be uninitialised only when phase = compile.
throw a ConstantError exception — a constant expression cannot read an uninitialised this parameter
end if;
if not frame.superconstructorCalled then
throw an UninitializedError exception — can’t access this from within a constructor before the superconstructor has been called
end if;
return this;
[PrimaryExpression  RegularExpressiondo
return Body[RegularExpression “#”  Flags[RegularExpression];
[PrimaryExpression  ReservedNamespacedo
return Eval[ReservedNamespace](envphase);
[PrimaryExpression  ParenListExpressiondo
return Eval[ParenListExpression](envphase);
[PrimaryExpression  ArrayLiteraldo return Eval[ArrayLiteral](envphase);
[PrimaryExpression  ObjectLiteraldo return Eval[ObjectLiteral](envphase);
[PrimaryExpression  FunctionExpressiondo
return Eval[FunctionExpression](envphase)
end proc;
proc Eval[ReservedNamespace] (envEnvironmentphasePhase): Namespace
[ReservedNamespace  publicdo return public;
[ReservedNamespace  privatedo
cClassOpt  getEnclosingClass(env);
note  Validate already ensured that c  none.
end proc;
Eval[ParenExpression] (envEnvironmentphasePhase): ObjOrRef propagates the call to Eval to nonterminals in the expansion of ParenExpression.
proc Eval[ParenListExpression] (envEnvironmentphasePhase): ObjOrRef
[ParenListExpression  ParenExpressiondo return Eval[ParenExpression](envphase);
[ParenListExpression  ( ListExpressionallowIn , AssignmentExpressionallowIn )do
Evaluate readReference(Eval[ListExpressionallowIn](envphase), phase) and ignore its result;
return readReference(Eval[AssignmentExpressionallowIn](envphase), phase)
end proc;
proc EvalAsList[ParenListExpression] (envEnvironmentphasePhase): Object[]
[ParenListExpression  ParenExpressiondo
eltObject  readReference(Eval[ParenExpression](envphase), phase);
return [elt];
[ParenListExpression  ( ListExpressionallowIn , AssignmentExpressionallowIn )do
eltsObject[]  EvalAsList[ListExpressionallowIn](envphase);
eltObject  readReference(Eval[AssignmentExpressionallowIn](envphase), phase);
return elts  [elt]
end proc;

Function Expressions

Syntax

FunctionExpression 
   function FunctionCommon
|  function Identifier FunctionCommon

Validation

F[FunctionExpression]: UninstantiatedFunction;
proc Validate[FunctionExpression] (cxtContextenvEnvironment)
[FunctionExpression  function FunctionCommondo
kindStaticFunctionKind  plainFunction;
if not cxt.strict and Plain[FunctionCommonthen kind  uncheckedFunction end if;
F[FunctionExpression ValidateStaticFunction[FunctionCommon](cxtenvkind);
[FunctionExpression  function Identifier FunctionCommondo
vVariable  new VariabletypeFunction, valuenone, immutabletrue, setupnone, initializerbusy;
bLocalBinding  LocalBindingqnamepublic::(Name[Identifier]), accessesreadWrite, explicitfalse, enumerabletrue, contentv;
compileFrameLocalFrame  new LocalFramelocalBindings: {b};
kindStaticFunctionKind  plainFunction;
if not cxt.strict and Plain[FunctionCommonthen kind  uncheckedFunction end if;
F[FunctionExpression ValidateStaticFunction[FunctionCommon](cxt[compileFrame]  envkind)
end proc;

Setup

proc Setup[FunctionExpression] ()
[FunctionExpression  function FunctionCommondo
Evaluate Setup[FunctionCommon]() and ignore its result;
[FunctionExpression  function Identifier FunctionCommondo
Evaluate Setup[FunctionCommon]() and ignore its result
end proc;

Evaluation

proc Eval[FunctionExpression] (envEnvironmentphasePhase): ObjOrRef
[FunctionExpression  function FunctionCommondo
if phase = compile then
throw a ConstantError exception — a function expression is not a constant expression because it can evaluate to different values
end if;
[FunctionExpression  function Identifier FunctionCommondo
if phase = compile then
throw a ConstantError exception — a function expression is not a constant expression because it can evaluate to different values
end if;
vVariable  new VariabletypeFunction, valuenone, immutabletrue, setupnone, initializernone;
bLocalBinding  LocalBindingqnamepublic::(Name[Identifier]), accessesreadWrite, explicitfalse, enumerabletrue, contentv;
runtimeFrameLocalFrame  new LocalFramelocalBindings: {b};
fSimpleInstance  instantiateFunction(F[FunctionExpression], [runtimeFrame]  env);
v.value  f;
return f
end proc;

Object Literals

Syntax

ObjectLiteral  { FieldList }
FieldList 
   «empty»
|  NonemptyFieldList
NonemptyFieldList 
   LiteralField
|  LiteralField , NonemptyFieldList
LiteralField  FieldName : AssignmentExpressionallowIn
FieldName 
   QualifiedIdentifier
|  String
|  Number
|  ParenExpression

Validation

Validate[ObjectLiteral] (cxtContextenvEnvironment) propagates the call to Validate to nonterminals in the expansion of ObjectLiteral.
Validate[FieldList] (cxtContextenvEnvironment) propagates the call to Validate to nonterminals in the expansion of FieldList.
Validate[NonemptyFieldList] (cxtContextenvEnvironment) propagates the call to Validate to nonterminals in the expansion of NonemptyFieldList.
Validate[LiteralField] (cxtContextenvEnvironment) propagates the call to Validate to nonterminals in the expansion of LiteralField.
Validate[FieldName] (cxtContextenvEnvironment) propagates the call to Validate to nonterminals in the expansion of FieldName.

Setup

Setup[ObjectLiteral] () propagates the call to Setup to nonterminals in the expansion of ObjectLiteral.
Setup[FieldList] () propagates the call to Setup to nonterminals in the expansion of FieldList.
Setup[NonemptyFieldList] () propagates the call to Setup to nonterminals in the expansion of NonemptyFieldList.
Setup[LiteralField] () propagates the call to Setup to nonterminals in the expansion of LiteralField.
Setup[FieldName] () propagates the call to Setup to nonterminals in the expansion of FieldName.

Evaluation

proc Eval[ObjectLiteral  { FieldList }] (envEnvironmentphasePhase): ObjOrRef
if phase = compile then
throw a ConstantError exception — an object literal is not a constant expression because it evaluates to a new object each time it is evaluated
end if;
oObject  construct(Object[]phase);
Evaluate Eval[FieldList](envophase) and ignore its result;
return o
end proc;
Eval[FieldList] (envEnvironmentoObjectphase: {run}) propagates the call to Eval to nonterminals in the expansion of FieldList.
Eval[NonemptyFieldList] (envEnvironmentoObjectphase: {run}) propagates the call to Eval to nonterminals in the expansion of NonemptyFieldList.
proc Eval[LiteralField  FieldName : AssignmentExpressionallowIn] (envEnvironmentoObjectphase: {run})
multinameMultiname  Eval[FieldName](envphase);
valueObject  readReference(Eval[AssignmentExpressionallowIn](envphase), phase);
Evaluate dotWrite(omultinamevaluephase) and ignore its result
end proc;
proc Eval[FieldName] (envEnvironmentphasePhase): Multiname
[FieldName  QualifiedIdentifierdo return Eval[QualifiedIdentifier](envphase);
[FieldName  Stringdo return {objectToQualifiedName(Value[String], phase)};
[FieldName  Numberdo return {objectToQualifiedName(Value[Number], phase)};
[FieldName  ParenExpressiondo
aObject  readReference(Eval[ParenExpression](envphase), phase);
return {objectToQualifiedName(aphase)}
end proc;

Array Literals

Syntax

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

Validation

Validate[ArrayLiteral] (cxtContextenvEnvironment) propagates the call to Validate to nonterminals in the expansion of ArrayLiteral.
Validate[ElementList] (cxtContextenvEnvironment) propagates the call to Validate to nonterminals in the expansion of ElementList.
Validate[LiteralElement] (cxtContextenvEnvironment) propagates the call to Validate to nonterminals in the expansion of LiteralElement.

Setup

Setup[ArrayLiteral] () propagates the call to Setup to nonterminals in the expansion of ArrayLiteral.
Setup[ElementList] () propagates the call to Setup to nonterminals in the expansion of ElementList.
Setup[LiteralElement] () propagates the call to Setup to nonterminals in the expansion of LiteralElement.

Evaluation

proc Eval[ArrayLiteral  [ ElementList ]] (envEnvironmentphasePhase): ObjOrRef
if phase = compile then
throw a ConstantError exception — an array literal is not a constant expression because it evaluates to a new object each time it is evaluated
end if;
oObject  construct(Array[]phase);
lengthInteger  Eval[ElementList](env, 0, ophase);
Evaluate writeArrayPrivateLength(olengthphase) and ignore its result;
return o
end proc;
proc Eval[ElementList] (envEnvironmentlengthIntegeroObjectphase: {run}): Integer
[ElementList  «empty»] do return length;
[ElementList  LiteralElementdo
Evaluate Eval[LiteralElement](envlengthophase) and ignore its result;
return length + 1;
[ElementList0  , ElementList1do
return Eval[ElementList1](envlength + 1, ophase);
[ElementList0  LiteralElement , ElementList1do
Evaluate Eval[LiteralElement](envlengthophase) and ignore its result;
return Eval[ElementList1](envlength + 1, ophase)
end proc;
proc Eval[LiteralElement  AssignmentExpressionallowIn] (envEnvironmentlengthIntegeroObjectphase: {run})
valueObject  readReference(Eval[AssignmentExpressionallowIn](envphase), phase);
Evaluate indexWrite(olengthvaluephase) and ignore its result
end proc;

Super Expressions

Syntax

SuperExpression 
   super
|  super ParenExpression

Validation

proc Validate[SuperExpression] (cxtContextenvEnvironment)
[SuperExpression  superdo
cClassOpt  getEnclosingClass(env);
if c = none then
throw a SyntaxError exception — a super expression is meaningful only inside a class
end if;
frameParameterFrameOpt  getEnclosingParameterFrame(env);
if frame = none or frame.kind  StaticFunctionKind then
throw a SyntaxError exception — a super expression without an argument is meaningful only inside an instance method or a constructor
end if;
if c.super = none then
throw a SyntaxError exception — a super expression is meaningful only if the enclosing class has a superclass
end if;
[SuperExpression  super ParenExpressiondo
cClassOpt  getEnclosingClass(env);
if c = none then
throw a SyntaxError exception — a super expression is meaningful only inside a class
end if;
if c.super = none then
throw a SyntaxError exception — a super expression is meaningful only if the enclosing class has a superclass
end if;
Evaluate Validate[ParenExpression](cxtenv) and ignore its result
end proc;

Setup

Setup[SuperExpression] () propagates the call to Setup to nonterminals in the expansion of SuperExpression.

Evaluation

proc Eval[SuperExpression] (envEnvironmentphasePhase): ObjOptionalLimit
[SuperExpression  superdo
frameParameterFrameOpt  getEnclosingParameterFrame(env);
note  Validate ensured that frame  none and frame.kind  StaticFunctionKind at this point.
thisObjectOpt  frame.this;
if this = none then
note  If Validate passed, this can be uninitialised only when phase = compile.
throw a ConstantError exception — a constant expression cannot read an uninitialised this parameter
end if;
if not frame.superconstructorCalled then
throw an UninitializedError exception — can’t access super from within a constructor before the superconstructor has been called
end if;
return makeLimitedInstance(thisgetEnclosingClass(env), phase);
[SuperExpression  super ParenExpressiondo
rObjOrRef  Eval[ParenExpression](envphase);
return makeLimitedInstance(rgetEnclosingClass(env), phase)
end proc;
proc makeLimitedInstance(rObjOrRefcClassphasePhase): ObjOptionalLimit
oObject  readReference(rphase);
limitClassOpt  c.super;
note  Validate ensured that limit cannot be none at this point.
coercedObject  coerce(olimit);
if coerced = null then return null end if;
return LimitedInstanceinstancecoercedlimitlimit
end proc;

Postfix Expressions

Syntax

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

Validation

Validate[PostfixExpression] (cxtContextenvEnvironment) propagates the call to Validate to nonterminals in the expansion of PostfixExpression.
Validate[AttributeExpression] (cxtContextenvEnvironment) propagates the call to Validate to nonterminals in the expansion of AttributeExpression.
Validate[FullPostfixExpression] (cxtContextenvEnvironment) propagates the call to Validate to nonterminals in the expansion of FullPostfixExpression.
Validate[FullNewExpression] (cxtContextenvEnvironment) propagates the call to Validate to nonterminals in the expansion of FullNewExpression.
Validate[FullNewSubexpression] (cxtContextenvEnvironment) propagates the call to Validate to nonterminals in the expansion of FullNewSubexpression.
Validate[ShortNewExpression] (cxtContextenvEnvironment) propagates the call to Validate to nonterminals in the expansion of ShortNewExpression.
Validate[ShortNewSubexpression] (cxtContextenvEnvironment) propagates the call to Validate to nonterminals in the expansion of ShortNewSubexpression.

Setup

Setup[PostfixExpression] () propagates the call to Setup to nonterminals in the expansion of PostfixExpression.
Setup[AttributeExpression] () propagates the call to Setup to nonterminals in the expansion of AttributeExpression.
Setup[FullPostfixExpression] () propagates the call to Setup to nonterminals in the expansion of FullPostfixExpression.
Setup[FullNewExpression] () propagates the call to Setup to nonterminals in the expansion of FullNewExpression.
Setup[FullNewSubexpression] () propagates the call to Setup to nonterminals in the expansion of FullNewSubexpression.
Setup[ShortNewExpression] () propagates the call to Setup to nonterminals in the expansion of ShortNewExpression.
Setup[ShortNewSubexpression] () propagates the call to Setup to nonterminals in the expansion of ShortNewSubexpression.

Evaluation

Eval[PostfixExpression] (envEnvironmentphasePhase): ObjOrRef propagates the call to Eval to nonterminals in the expansion of PostfixExpression.
proc Eval[AttributeExpression] (envEnvironmentphasePhase): ObjOrRef
[AttributeExpression  SimpleQualifiedIdentifierdo
mMultiname  Eval[SimpleQualifiedIdentifier](envphase);
return LexicalReferenceenvenv, variableMultinamem, strictStrict[SimpleQualifiedIdentifier];
[AttributeExpression0  AttributeExpression1 PropertyOperatordo
aObject  readReference(Eval[AttributeExpression1](envphase), phase);
return Eval[PropertyOperator](envaphase);
[AttributeExpression0  AttributeExpression1 Argumentsdo
rObjOrRef  Eval[AttributeExpression1](envphase);
fObject  readReference(rphase);
baseObject;
case r of
Object  LexicalReference do base  null;
DotReference  BracketReference do base  r.base
end case;
argsObject[]  Eval[Arguments](envphase);
return call(basefargsphase)
end proc;
proc Eval[FullPostfixExpression] (envEnvironmentphasePhase): ObjOrRef
[FullPostfixExpression  PrimaryExpressiondo
return Eval[PrimaryExpression](envphase);
mMultiname  Eval[ExpressionQualifiedIdentifier](envphase);
return LexicalReferenceenvenv, variableMultinamem, strictStrict[ExpressionQualifiedIdentifier];
[FullPostfixExpression  FullNewExpressiondo
return Eval[FullNewExpression](envphase);
aObject  readReference(Eval[FullPostfixExpression1](envphase), phase);
return Eval[PropertyOperator](envaphase);
aObjOptionalLimit  Eval[SuperExpression](envphase);
return Eval[PropertyOperator](envaphase);
[FullPostfixExpression0  FullPostfixExpression1 Argumentsdo
rObjOrRef  Eval[FullPostfixExpression1](envphase);
fObject  readReference(rphase);
baseObject;
case r of
Object  LexicalReference do base  null;
DotReference  BracketReference do base  r.base
end case;
argsObject[]  Eval[Arguments](envphase);
return call(basefargsphase);
[FullPostfixExpression  PostfixExpression [no line break] ++do
if phase = compile then
throw a ConstantError exception — ++ cannot be used in a constant expression
end if;
rObjOrRef  Eval[PostfixExpression](envphase);
aObject  readReference(rphase);
bObject  plus(aphase);
cObject  add(b, 1f64phase);
Evaluate writeReference(rcphase) and ignore its result;
return b;
[FullPostfixExpression  PostfixExpression [no line break] --do
if phase = compile then
throw a ConstantError exception — -- cannot be used in a constant expression
end if;
rObjOrRef  Eval[PostfixExpression](envphase);
aObject  readReference(rphase);
bObject  plus(aphase);
cObject  subtract(b, 1f64phase);
Evaluate writeReference(rcphase) and ignore its result;
return b
end proc;
proc Eval[FullNewExpression  new FullNewSubexpression Arguments] (envEnvironmentphasePhase): ObjOrRef
fObject  readReference(Eval[FullNewSubexpression](envphase), phase);
argsObject[]  Eval[Arguments](envphase);
return construct(fargsphase)
end proc;
proc Eval[FullNewSubexpression] (envEnvironmentphasePhase): ObjOrRef
[FullNewSubexpression  PrimaryExpressiondo
return Eval[PrimaryExpression](envphase);
[FullNewSubexpression  QualifiedIdentifierdo
mMultiname  Eval[QualifiedIdentifier](envphase);
return LexicalReferenceenvenv, variableMultinamem, strictStrict[QualifiedIdentifier];
[FullNewSubexpression  FullNewExpressiondo
return Eval[FullNewExpression](envphase);
aObject  readReference(Eval[FullNewSubexpression1](envphase), phase);
return Eval[PropertyOperator](envaphase);
[FullNewSubexpression  SuperExpression PropertyOperatordo
aObjOptionalLimit  Eval[SuperExpression](envphase);
return Eval[PropertyOperator](envaphase)
end proc;
proc Eval[ShortNewExpression  new ShortNewSubexpression] (envEnvironmentphasePhase): ObjOrRef
fObject  readReference(Eval[ShortNewSubexpression](envphase), phase);
return construct(f[]phase)
end proc;
Eval[ShortNewSubexpression] (envEnvironmentphasePhase): ObjOrRef propagates the call to Eval to nonterminals in the expansion of ShortNewSubexpression.

Property Operators

Syntax

PropertyOperator 
   . QualifiedIdentifier
|  Brackets
Brackets 
   [ ]
|  [ ListExpressionallowIn ]
|  [ ExpressionsWithRest ]
Arguments 
   ( )
|  ParenListExpression
|  ( ExpressionsWithRest )
ExpressionsWithRest 
   RestExpression
|  ListExpressionallowIn , RestExpression
RestExpression  ... AssignmentExpressionallowIn

Validation

Validate[PropertyOperator] (cxtContextenvEnvironment) propagates the call to Validate to nonterminals in the expansion of PropertyOperator.
Validate[Brackets] (cxtContextenvEnvironment) propagates the call to Validate to nonterminals in the expansion of Brackets.
Validate[Arguments] (cxtContextenvEnvironment) propagates the call to Validate to nonterminals in the expansion of Arguments.
Validate[ExpressionsWithRest] (cxtContextenvEnvironment) propagates the call to Validate to nonterminals in the expansion of ExpressionsWithRest.
Validate[RestExpression] (cxtContextenvEnvironment) propagates the call to Validate to nonterminals in the expansion of RestExpression.

Setup

Setup[PropertyOperator] () propagates the call to Setup to nonterminals in the expansion of PropertyOperator.
Setup[Brackets] () propagates the call to Setup to nonterminals in the expansion of Brackets.
Setup[Arguments] () propagates the call to Setup to nonterminals in the expansion of Arguments.
Setup[ExpressionsWithRest] () propagates the call to Setup to nonterminals in the expansion of ExpressionsWithRest.
Setup[RestExpression] () propagates the call to Setup to nonterminals in the expansion of RestExpression.

Evaluation

proc Eval[PropertyOperator] (envEnvironmentbaseObjOptionalLimitphasePhase): ObjOrRef
[PropertyOperator  . QualifiedIdentifierdo
mMultiname  Eval[QualifiedIdentifier](envphase);
case base of
Object do
return DotReferencebasebaselimitobjectType(base), multinamem;
return DotReferencebasebase.instancelimitbase.limitmultinamem
end case;
[PropertyOperator  Bracketsdo
argsObject[]  Eval[Brackets](envphase);
case base of
Object do
return BracketReferencebasebaselimitobjectType(base), argsargs;
return BracketReferencebasebase.instancelimitbase.limitargsargs
end case
end proc;
proc Eval[Brackets] (envEnvironmentphasePhase): Object[]
[Brackets  [ ]do return [];
[Brackets  [ ListExpressionallowIn ]do
return EvalAsList[ListExpressionallowIn](envphase);
[Brackets  [ ExpressionsWithRest ]do return Eval[ExpressionsWithRest](envphase)
end proc;
proc Eval[Arguments] (envEnvironmentphasePhase): Object[]
[Arguments  ( )do return [];
[Arguments  ParenListExpressiondo
return EvalAsList[ParenListExpression](envphase);
[Arguments  ( ExpressionsWithRest )do
return Eval[ExpressionsWithRest](envphase)
end proc;
proc Eval[ExpressionsWithRest] (envEnvironmentphasePhase): Object[]
[ExpressionsWithRest  RestExpressiondo return Eval[RestExpression](envphase);
[ExpressionsWithRest  ListExpressionallowIn , RestExpressiondo
args1Object[]  EvalAsList[ListExpressionallowIn](envphase);
args2Object[]  Eval[RestExpression](envphase);
return args1  args2
end proc;
proc Eval[RestExpression  ... AssignmentExpressionallowIn] (envEnvironmentphasePhase): Object[]
aObject  readReference(Eval[AssignmentExpressionallowIn](envphase), phase);
lengthInteger  readLength(aphase);
iInteger  0;
argsObject[]  [];
while i  length do
argObjectOpt  indexRead(aiphase);
if arg = none then
An implementation may, at its discretion, either throw a ReferenceError or treat the hole as a missing argument, substituting the called function’s default parameter value if there is one, undefined if the called function is unchecked, or throwing an ArgumentError exception otherwise. An implementation must not replace such a hole with undefined except when the called function is unchecked or happens to have undefined as its default parameter value.
end if;
args  args  [arg];
i  i + 1
end while;
return args
end proc;

Unary Operators

Syntax

UnaryExpression 
   PostfixExpression
|  delete PostfixExpression
|  void UnaryExpression
|  typeof UnaryExpression
|  ++ PostfixExpression
|  -- PostfixExpression
|  + UnaryExpression
|  - UnaryExpression
|  - NegatedMinLong
|  ~ UnaryExpression
|  ! UnaryExpression

Validation

Strict[UnaryExpression]: Boolean;
proc Validate[UnaryExpression] (cxtContextenvEnvironment)
[UnaryExpression  PostfixExpressiondo
Evaluate Validate[PostfixExpression](cxtenv) and ignore its result;
[UnaryExpression  delete PostfixExpressiondo
Evaluate Validate[PostfixExpression](cxtenv) and ignore its result;
Strict[UnaryExpression cxt.strict;
[UnaryExpression0  void UnaryExpression1do
Evaluate Validate[UnaryExpression1](cxtenv) and ignore its result;
[UnaryExpression0  typeof UnaryExpression1do
Evaluate Validate[UnaryExpression1](cxtenv) and ignore its result;
[UnaryExpression  ++ PostfixExpressiondo
Evaluate Validate[PostfixExpression](cxtenv) and ignore its result;
[UnaryExpression  -- PostfixExpressiondo
Evaluate Validate[PostfixExpression](cxtenv) and ignore its result;
[UnaryExpression0  + UnaryExpression1do
Evaluate Validate[UnaryExpression1](cxtenv) and ignore its result;
[UnaryExpression0  - UnaryExpression1do
Evaluate Validate[UnaryExpression1](cxtenv) and ignore its result;
[UnaryExpression  - NegatedMinLongdo nothing;
[UnaryExpression0  ~ UnaryExpression1do
Evaluate Validate[UnaryExpression1](cxtenv) and ignore its result;
[UnaryExpression0  ! UnaryExpression1do
Evaluate Validate[UnaryExpression1](cxtenv) and ignore its result
end proc;

Setup

Setup[UnaryExpression] () propagates the call to Setup to nonterminals in the expansion of UnaryExpression.

Evaluation

proc Eval[UnaryExpression] (envEnvironmentphasePhase): ObjOrRef
[UnaryExpression  PostfixExpressiondo return Eval[PostfixExpression](envphase);
[UnaryExpression  delete PostfixExpressiondo
if phase = compile then
throw a ConstantError exception — delete cannot be used in a constant expression
end if;
rObjOrRef  Eval[PostfixExpression](envphase);
return deleteReference(rStrict[UnaryExpression], phase);
[UnaryExpression0  void UnaryExpression1do
Evaluate readReference(Eval[UnaryExpression1](envphase), phase) and ignore its result;
return undefined;
[UnaryExpression0  typeof UnaryExpression1do
aObject  readReference(Eval[UnaryExpression1](envphase), phase);
cClass  objectType(a);
return c.typeofString;
[UnaryExpression  ++ PostfixExpressiondo
if phase = compile then
throw a ConstantError exception — ++ cannot be used in a constant expression
end if;
rObjOrRef  Eval[PostfixExpression](envphase);
aObject  readReference(rphase);
bObject  plus(aphase);
cObject  add(b, 1f64phase);
Evaluate writeReference(rcphase) and ignore its result;
return c;
[UnaryExpression  -- PostfixExpressiondo
if phase = compile then
throw a ConstantError exception — -- cannot be used in a constant expression
end if;
rObjOrRef  Eval[PostfixExpression](envphase);
aObject  readReference(rphase);
bObject  plus(aphase);
cObject  subtract(b, 1f64phase);
Evaluate writeReference(rcphase) and ignore its result;
return c;
[UnaryExpression0  + UnaryExpression1do
aObject  readReference(Eval[UnaryExpression1](envphase), phase);
return plus(aphase);
[UnaryExpression0  - UnaryExpression1do
aObject  readReference(Eval[UnaryExpression1](envphase), phase);
return minus(aphase);
[UnaryExpression  - NegatedMinLongdo return (–263)long;
[UnaryExpression0  ~ UnaryExpression1do
aObject  readReference(Eval[UnaryExpression1](envphase), phase);
return bitNot(aphase);
[UnaryExpression0  ! UnaryExpression1do
aObject  readReference(Eval[UnaryExpression1](envphase), phase);
return logicalNot(aphase)
end proc;
plus(aphase) returns the value of the unary expression +a. If phase is compile, only constant operations are permitted.
proc plus(aObjectphasePhase): Object
return objectToGeneralNumber(aphase)
end proc;
minus(aphase) returns the value of the unary expression -a. If phase is compile, only constant operations are permitted.
proc minus(aObjectphasePhase): Object
xGeneralNumber  objectToGeneralNumber(aphase);
end proc;
proc generalNumberNegate(xGeneralNumber): GeneralNumber
case x of
Long do return integerToLong(–x.value);
ULong do return integerToULong(–x.value);
Float32 do return float32Negate(x);
Float64 do return float64Negate(x)
end case
end proc;
proc bitNot(aObjectphasePhase): Object
xGeneralNumber  objectToGeneralNumber(aphase);
case x of
Long do i: {–263 ... 263 – 1}  x.valuereturn (bitwiseXor(i, –1))long;
ULong do
i: {0 ... 264 – 1}  x.value;
return (bitwiseXor(i, 0xFFFFFFFFFFFFFFFF))ulong;
Float32  Float64 do
i: {–231 ... 231 – 1}  signedWrap32(truncateToInteger(x));
return (bitwiseXor(i, –1))f64
end case
end proc;
logicalNot(aphase) returns the value of the unary expression !a. If phase is compile, only constant operations are permitted.
proc logicalNot(aObjectphasePhase): Object
return not objectToBoolean(a)
end proc;

Multiplicative Operators

Syntax

MultiplicativeExpression 
   UnaryExpression
|  MultiplicativeExpression * UnaryExpression
|  MultiplicativeExpression / UnaryExpression
|  MultiplicativeExpression % UnaryExpression

Validation

Validate[MultiplicativeExpression] (cxtContextenvEnvironment) propagates the call to Validate to nonterminals in the expansion of MultiplicativeExpression.

Setup

Setup[MultiplicativeExpression] () propagates the call to Setup to nonterminals in the expansion of MultiplicativeExpression.

Evaluation

proc Eval[MultiplicativeExpression] (envEnvironmentphasePhase): ObjOrRef
[MultiplicativeExpression  UnaryExpressiondo
return Eval[UnaryExpression](envphase);
aObject  readReference(Eval[MultiplicativeExpression1](envphase), phase);
bObject  readReference(Eval[UnaryExpression](envphase), phase);
return multiply(abphase);
aObject  readReference(Eval[MultiplicativeExpression1](envphase), phase);
bObject  readReference(Eval[UnaryExpression](envphase), phase);
return divide(abphase);
aObject  readReference(Eval[MultiplicativeExpression1](envphase), phase);
bObject  readReference(Eval[UnaryExpression](envphase), phase);
return remainder(abphase)
end proc;
proc multiply(aObjectbObjectphasePhase): Object
xGeneralNumber  objectToGeneralNumber(aphase);
yGeneralNumber  objectToGeneralNumber(bphase);
if x  Long  ULong or y  Long  ULong then
iIntegerOpt  checkInteger(x);
jIntegerOpt  checkInteger(y);
if i  none and j  none then
kInteger  ij;
if x  ULong or y  ULong then return integerToULong(k)
else return integerToLong(k)
end if
end if
end if;
end proc;
proc divide(aObjectbObjectphasePhase): Object
xGeneralNumber  objectToGeneralNumber(aphase);
yGeneralNumber  objectToGeneralNumber(bphase);
if x  Long  ULong or y  Long  ULong then
iIntegerOpt  checkInteger(x);
jIntegerOpt  checkInteger(y);
if i  none and j  none and j  0 then
qRational  i/j;
if x  ULong or y  ULong then return rationalToULong(q)
else return rationalToLong(q)
end if
end if
end if;
end proc;
proc remainder(aObjectbObjectphasePhase): Object
xGeneralNumber  objectToGeneralNumber(aphase);
yGeneralNumber  objectToGeneralNumber(bphase);
if x  Long  ULong or y  Long  ULong then
iIntegerOpt  checkInteger(x);
jIntegerOpt  checkInteger(y);
if i  none and j  none and j  0 then
qRational  i/j;
kInteger  q  0 ? q : q;
rInteger  i – jk;
if x  ULong or y  ULong then return integerToULong(r)
else return integerToLong(r)
end if
end if
end if;
end proc;

Additive Operators

Syntax

AdditiveExpression 
   MultiplicativeExpression
|  AdditiveExpression + MultiplicativeExpression
|  AdditiveExpression - MultiplicativeExpression

Validation

Validate[AdditiveExpression] (cxtContextenvEnvironment) propagates the call to Validate to nonterminals in the expansion of AdditiveExpression.

Setup

Setup[AdditiveExpression] () propagates the call to Setup to nonterminals in the expansion of AdditiveExpression.

Evaluation

proc Eval[AdditiveExpression] (envEnvironmentphasePhase): ObjOrRef
[AdditiveExpression  MultiplicativeExpressiondo
return Eval[MultiplicativeExpression](envphase);
aObject  readReference(Eval[AdditiveExpression1](envphase), phase);
bObject  readReference(Eval[MultiplicativeExpression](envphase), phase);
return add(abphase);
aObject  readReference(Eval[AdditiveExpression1](envphase), phase);
bObject  readReference(Eval[MultiplicativeExpression](envphase), phase);
return subtract(abphase)
end proc;
proc add(aObjectbObjectphasePhase): Object
apPrimitiveObject  objectToPrimitive(anonephase);
bpPrimitiveObject  objectToPrimitive(bnonephase);
if ap  Char16  String or bp  Char16  String then
return objectToString(apphase objectToString(bpphase)
end if;
xGeneralNumber  objectToGeneralNumber(apphase);
yGeneralNumber  objectToGeneralNumber(bpphase);
if x  Long  ULong or y  Long  ULong then
iIntegerOpt  checkInteger(x);
jIntegerOpt  checkInteger(y);
if i  none and j  none then
kInteger  i + j;
if x  ULong or y  ULong then return integerToULong(k)
else return integerToLong(k)
end if
end if
end if;
return float64Add(toFloat64(x), toFloat64(y))
end proc;
proc subtract(aObjectbObjectphasePhase): Object
xGeneralNumber  objectToGeneralNumber(aphase);
yGeneralNumber  objectToGeneralNumber(bphase);
if x  Long  ULong or y  Long  ULong then
iIntegerOpt  checkInteger(x);
jIntegerOpt  checkInteger(y);
if i  none and j  none then
kInteger  i – j;
if x  ULong or y  ULong then return integerToULong(k)
else return integerToLong(k)
end if
end if
end if;
end proc;

Bitwise Shift Operators

Syntax

ShiftExpression 
   AdditiveExpression
|  ShiftExpression << AdditiveExpression
|  ShiftExpression >> AdditiveExpression
|  ShiftExpression >>> AdditiveExpression

Validation

Validate[ShiftExpression] (cxtContextenvEnvironment) propagates the call to Validate to nonterminals in the expansion of ShiftExpression.

Setup

Setup[ShiftExpression] () propagates the call to Setup to nonterminals in the expansion of ShiftExpression.

Evaluation

proc Eval[ShiftExpression] (envEnvironmentphasePhase): ObjOrRef
[ShiftExpression  AdditiveExpressiondo
return Eval[AdditiveExpression](envphase);
[ShiftExpression0  ShiftExpression1 << AdditiveExpressiondo
aObject  readReference(Eval[ShiftExpression1](envphase), phase);
bObject  readReference(Eval[AdditiveExpression](envphase), phase);
return shiftLeft(abphase);
[ShiftExpression0  ShiftExpression1 >> AdditiveExpressiondo
aObject  readReference(Eval[ShiftExpression1](envphase), phase);
bObject  readReference(Eval[AdditiveExpression](envphase), phase);
return shiftRight(abphase);
[ShiftExpression0  ShiftExpression1 >>> AdditiveExpressiondo
aObject  readReference(Eval[ShiftExpression1](envphase), phase);
bObject  readReference(Eval[AdditiveExpression](envphase), phase);
return shiftRightUnsigned(abphase)
end proc;
proc shiftLeft(aObjectbObjectphasePhase): Object
xGeneralNumber  objectToGeneralNumber(aphase);
countInteger  truncateToInteger(objectToGeneralNumber(bphase));
case x of
Float32  Float64 do
count  bitwiseAnd(count, 0x1F);
i: {–231 ... 231 – 1}  signedWrap32(bitwiseShift(truncateToInteger(x), count));
return if64;
Long do
count  bitwiseAnd(count, 0x3F);
i: {–263 ... 263 – 1}  signedWrap64(bitwiseShift(x.valuecount));
return ilong;
ULong do
count  bitwiseAnd(count, 0x3F);
i: {0 ... 264 – 1}  unsignedWrap64(bitwiseShift(x.valuecount));
return iulong
end case
end proc;
proc shiftRight(aObjectbObjectphasePhase): Object
xGeneralNumber  objectToGeneralNumber(aphase);
countInteger  truncateToInteger(objectToGeneralNumber(bphase));
case x of
Float32  Float64 do
i: {–231 ... 231 – 1}  signedWrap32(truncateToInteger(x));
count  bitwiseAnd(count, 0x1F);
i  bitwiseShift(i, –count);
return if64;
Long do
count  bitwiseAnd(count, 0x3F);
i: {–263 ... 263 – 1}  bitwiseShift(x.value, –count);
return ilong;
ULong do
count  bitwiseAnd(count, 0x3F);
i: {–263 ... 263 – 1}  bitwiseShift(signedWrap64(x.value), –count);
return (unsignedWrap64(i))ulong
end case
end proc;
proc shiftRightUnsigned(aObjectbObjectphasePhase): Object
xGeneralNumber  objectToGeneralNumber(aphase);
countInteger  truncateToInteger(objectToGeneralNumber(bphase));
case x of
Float32  Float64 do
i: {0 ... 232 – 1}  unsignedWrap32(truncateToInteger(x));
count  bitwiseAnd(count, 0x1F);
i  bitwiseShift(i, –count);
return if64;
Long do
count  bitwiseAnd(count, 0x3F);
i: {0 ... 264 – 1}  bitwiseShift(unsignedWrap64(x.value), –count);
return (signedWrap64(i))long;
ULong do
count  bitwiseAnd(count, 0x3F);
i: {0 ... 264 – 1}  bitwiseShift(x.value, –count);
return iulong
end case
end proc;

Relational Operators

Syntax

RelationalExpressionallowIn 
   ShiftExpression
|  RelationalExpressionallowIn < ShiftExpression
|  RelationalExpressionallowIn > ShiftExpression
|  RelationalExpressionallowIn <= ShiftExpression
|  RelationalExpressionallowIn >= ShiftExpression
|  RelationalExpressionallowIn is ShiftExpression
|  RelationalExpressionallowIn as ShiftExpression
|  RelationalExpressionallowIn in ShiftExpression
|  RelationalExpressionallowIn instanceof ShiftExpression
RelationalExpressionnoIn 
   ShiftExpression
|  RelationalExpressionnoIn < ShiftExpression
|  RelationalExpressionnoIn > ShiftExpression
|  RelationalExpressionnoIn <= ShiftExpression
|  RelationalExpressionnoIn >= ShiftExpression
|  RelationalExpressionnoIn is ShiftExpression
|  RelationalExpressionnoIn as ShiftExpression
|  RelationalExpressionnoIn instanceof ShiftExpression

Validation

Validate[RelationalExpression] (cxtContextenvEnvironment) propagates the call to Validate to nonterminals in the expansion of RelationalExpression.

Setup

Setup[RelationalExpression] () propagates the call to Setup to nonterminals in the expansion of RelationalExpression.

Evaluation

proc Eval[RelationalExpression] (envEnvironmentphasePhase): ObjOrRef
[RelationalExpression  ShiftExpressiondo
return Eval[ShiftExpression](envphase);
[RelationalExpression0  RelationalExpression1 < ShiftExpressiondo
aObject  readReference(Eval[RelationalExpression1](envphase), phase);
bObject  readReference(Eval[ShiftExpression](envphase), phase);
return isLess(abphase);
[RelationalExpression0  RelationalExpression1 > ShiftExpressiondo
aObject  readReference(Eval[RelationalExpression1](envphase), phase);
bObject  readReference(Eval[ShiftExpression](envphase), phase);
return isLess(baphase);
[RelationalExpression0  RelationalExpression1 <= ShiftExpressiondo
aObject  readReference(Eval[RelationalExpression1](envphase), phase);
bObject  readReference(Eval[ShiftExpression](envphase), phase);
return isLessOrEqual(abphase);
[RelationalExpression0  RelationalExpression1 >= ShiftExpressiondo
aObject  readReference(Eval[RelationalExpression1](envphase), phase);
bObject  readReference(Eval[ShiftExpression](envphase), phase);
return isLessOrEqual(baphase);
[RelationalExpression0  RelationalExpression1 is ShiftExpressiondo
aObject  readReference(Eval[RelationalExpression1](envphase), phase);
bObject  readReference(Eval[ShiftExpression](envphase), phase);
cClass  objectToClass(b);
return is(ac);
[RelationalExpression0  RelationalExpression1 as ShiftExpressiondo
aObject  readReference(Eval[RelationalExpression1](envphase), phase);
bObject  readReference(Eval[ShiftExpression](envphase), phase);
cClass  objectToClass(b);
return coerceOrNull(ac);
[RelationalExpressionallowIn0  RelationalExpressionallowIn1 in ShiftExpressiondo
aObject  readReference(Eval[RelationalExpressionallowIn1](envphase), phase);
bObject  readReference(Eval[ShiftExpression](envphase), phase);
return hasProperty(bafalsephase);
[RelationalExpression0  RelationalExpression1 instanceof ShiftExpressiondo
aObject  readReference(Eval[RelationalExpression1](envphase), phase);
bObject  readReference(Eval[ShiftExpression](envphase), phase);
if b  Class then return is(ab)
elsif is(bPrototypeFunctionthen
prototypeObject  dotRead(b, {public::“prototype”}, phase);
return prototype  archetypes(a)
else throw a TypeError exception
end if
end proc;
proc isLess(aObjectbObjectphasePhase): Boolean
apPrimitiveObject  objectToPrimitive(ahintNumberphase);
bpPrimitiveObject  objectToPrimitive(bhintNumberphase);
if ap  Char16  String and bp  Char16  String then
return toString(ap) < toString(bp)
end if;
end proc;
proc isLessOrEqual(aObjectbObjectphasePhase): Boolean
apPrimitiveObject  objectToPrimitive(ahintNumberphase);
bpPrimitiveObject  objectToPrimitive(bhintNumberphase);
if ap  Char16  String and bp  Char16  String then
return toString(ap toString(bp)
end if;
return generalNumberCompare(objectToGeneralNumber(apphase), objectToGeneralNumber(bpphase))  {lessequal}
end proc;

Equality Operators

Syntax

EqualityExpression 
   RelationalExpression
|  EqualityExpression == RelationalExpression
|  EqualityExpression != RelationalExpression
|  EqualityExpression === RelationalExpression
|  EqualityExpression !== RelationalExpression

Validation

Validate[EqualityExpression] (cxtContextenvEnvironment) propagates the call to Validate to nonterminals in the expansion of EqualityExpression.

Setup

Setup[EqualityExpression] () propagates the call to Setup to nonterminals in the expansion of EqualityExpression.

Evaluation

proc Eval[EqualityExpression] (envEnvironmentphasePhase): ObjOrRef
[EqualityExpression  RelationalExpressiondo
return Eval[RelationalExpression](envphase);
[EqualityExpression0  EqualityExpression1 == RelationalExpressiondo
aObject  readReference(Eval[EqualityExpression1](envphase), phase);
bObject  readReference(Eval[RelationalExpression](envphase), phase);
return isEqual(abphase);
[EqualityExpression0  EqualityExpression1 != RelationalExpressiondo
aObject  readReference(Eval[EqualityExpression1](envphase), phase);
bObject  readReference(Eval[RelationalExpression](envphase), phase);
return not isEqual(abphase);
[EqualityExpression0  EqualityExpression1 === RelationalExpressiondo
aObject  readReference(Eval[EqualityExpression1](envphase), phase);
bObject  readReference(Eval[RelationalExpression](envphase), phase);
return isStrictlyEqual(abphase);
[EqualityExpression0  EqualityExpression1 !== RelationalExpressiondo
aObject  readReference(Eval[EqualityExpression1](envphase), phase);
bObject  readReference(Eval[RelationalExpression](envphase), phase);
return not isStrictlyEqual(abphase)
end proc;
proc isEqual(aObjectbObjectphasePhase): Boolean
case a of
Undefined  Null do return b  Undefined  Null;
if b  Boolean then return a = b
else return isEqual(objectToGeneralNumber(aphase), bphase)
end if;
bpPrimitiveObject  objectToPrimitive(bnonephase);
case bp of
Undefined  Null do return false;
Boolean  GeneralNumber  Char16  String do
end case;
Char16  String do
bpPrimitiveObject  objectToPrimitive(bnonephase);
case bp of
Undefined  Null do return false;
Boolean  GeneralNumber do
Char16  String do return toString(a) = toString(bp)
end case;
Namespace  CompoundAttribute  Class  MethodClosure  SimpleInstance  Date  RegExp  Package do
case b of
Undefined  Null do return false;
Namespace  CompoundAttribute  Class  MethodClosure  SimpleInstance  Date  RegExp  Package do
return isStrictlyEqual(abphase);
Boolean  GeneralNumber  Char16  String do
apPrimitiveObject  objectToPrimitive(anonephase);
return isEqual(apbphase)
end case
end case
end proc;
proc isStrictlyEqual(aObjectbObjectphasePhase): Boolean
if a  GeneralNumber and b  GeneralNumber then
return generalNumberCompare(ab) = equal
else return a = b
end if
end proc;

Binary Bitwise Operators

Syntax

BitwiseAndExpression 
   EqualityExpression
|  BitwiseAndExpression & EqualityExpression
BitwiseXorExpression 
   BitwiseAndExpression
|  BitwiseXorExpression ^ BitwiseAndExpression
BitwiseOrExpression 
   BitwiseXorExpression
|  BitwiseOrExpression | BitwiseXorExpression

Validation

Validate[BitwiseAndExpression] (cxtContextenvEnvironment) propagates the call to Validate to nonterminals in the expansion of BitwiseAndExpression.
Validate[BitwiseXorExpression] (cxtContextenvEnvironment) propagates the call to Validate to nonterminals in the expansion of BitwiseXorExpression.
Validate[BitwiseOrExpression] (cxtContextenvEnvironment) propagates the call to Validate to nonterminals in the expansion of BitwiseOrExpression.

Setup

Setup[BitwiseAndExpression] () propagates the call to Setup to nonterminals in the expansion of BitwiseAndExpression.
Setup[BitwiseXorExpression] () propagates the call to Setup to nonterminals in the expansion of BitwiseXorExpression.
Setup[BitwiseOrExpression] () propagates the call to Setup to nonterminals in the expansion of BitwiseOrExpression.

Evaluation

proc Eval[BitwiseAndExpression] (envEnvironmentphasePhase): ObjOrRef
[BitwiseAndExpression  EqualityExpressiondo
return Eval[EqualityExpression](envphase);
[BitwiseAndExpression0  BitwiseAndExpression1 & EqualityExpressiondo
aObject  readReference(Eval[BitwiseAndExpression1](envphase), phase);
bObject  readReference(Eval[EqualityExpression](envphase), phase);
return bitAnd(abphase)
end proc;
proc Eval[BitwiseXorExpression] (envEnvironmentphasePhase): ObjOrRef
[BitwiseXorExpression  BitwiseAndExpressiondo
return Eval[BitwiseAndExpression](envphase);
[BitwiseXorExpression0  BitwiseXorExpression1 ^ BitwiseAndExpressiondo
aObject  readReference(Eval[BitwiseXorExpression1](envphase), phase);
bObject  readReference(Eval[BitwiseAndExpression](envphase), phase);
return bitXor(abphase)
end proc;
proc Eval[BitwiseOrExpression] (envEnvironmentphasePhase): ObjOrRef
[BitwiseOrExpression  BitwiseXorExpressiondo
return Eval[BitwiseXorExpression](envphase);
[BitwiseOrExpression0  BitwiseOrExpression1 | BitwiseXorExpressiondo
aObject  readReference(Eval[BitwiseOrExpression1](envphase), phase);
bObject  readReference(Eval[BitwiseXorExpression](envphase), phase);
return bitOr(abphase)
end proc;
proc bitAnd(aObjectbObjectphasePhase): GeneralNumber
xGeneralNumber  objectToGeneralNumber(aphase);
yGeneralNumber  objectToGeneralNumber(bphase);
if x  Long  ULong or y  Long  ULong then
i: {–263 ... 263 – 1}  signedWrap64(truncateToInteger(x));
j: {–263 ... 263 – 1}  signedWrap64(truncateToInteger(y));
k: {–263 ... 263 – 1}  bitwiseAnd(ij);
if x  ULong or y  ULong then return (unsignedWrap64(k))ulong
else return klong
end if
else
i: {–231 ... 231 – 1}  signedWrap32(truncateToInteger(x));
j: {–231 ... 231 – 1}  signedWrap32(truncateToInteger(y));
return (bitwiseAnd(ij))f64
end if
end proc;
proc bitXor(aObjectbObjectphasePhase): GeneralNumber
xGeneralNumber  objectToGeneralNumber(aphase);
yGeneralNumber  objectToGeneralNumber(bphase);
if x  Long  ULong or y  Long  ULong then
i: {–263 ... 263 – 1}  signedWrap64(truncateToInteger(x));
j: {–263 ... 263 – 1}  signedWrap64(truncateToInteger(y));
k: {–263 ... 263 – 1}  bitwiseXor(ij);
if x  ULong or y  ULong then return (unsignedWrap64(k))ulong
else return klong
end if
else
i: {–231 ... 231 – 1}  signedWrap32(truncateToInteger(x));
j: {–231 ... 231 – 1}  signedWrap32(truncateToInteger(y));
return (bitwiseXor(ij))f64
end if
end proc;
proc bitOr(aObjectbObjectphasePhase): GeneralNumber
xGeneralNumber  objectToGeneralNumber(aphase);
yGeneralNumber  objectToGeneralNumber(bphase);
if x  Long  ULong or y  Long  ULong then
i: {–263 ... 263 – 1}  signedWrap64(truncateToInteger(x));
j: {–263 ... 263 – 1}  signedWrap64(truncateToInteger(y));
k: {–263 ... 263 – 1}  bitwiseOr(ij);
if x  ULong or y  ULong then return (unsignedWrap64(k))ulong
else return klong
end if
else
i: {–231 ... 231 – 1}  signedWrap32(truncateToInteger(x));
j: {–231 ... 231 – 1}  signedWrap32(truncateToInteger(y));
return (bitwiseOr(ij))f64
end if
end proc;

Binary Logical Operators

Syntax

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

Validation

Validate[LogicalAndExpression] (cxtContextenvEnvironment) propagates the call to Validate to nonterminals in the expansion of LogicalAndExpression.
Validate[LogicalXorExpression] (cxtContextenvEnvironment) propagates the call to Validate to nonterminals in the expansion of LogicalXorExpression.
Validate[LogicalOrExpression] (cxtContextenvEnvironment) propagates the call to Validate to nonterminals in the expansion of LogicalOrExpression.

Setup

Setup[LogicalAndExpression] () propagates the call to Setup to nonterminals in the expansion of LogicalAndExpression.
Setup[LogicalXorExpression] () propagates the call to Setup to nonterminals in the expansion of LogicalXorExpression.
Setup[LogicalOrExpression] () propagates the call to Setup to nonterminals in the expansion of LogicalOrExpression.

Evaluation

proc Eval[LogicalAndExpression] (envEnvironmentphasePhase): ObjOrRef
[LogicalAndExpression  BitwiseOrExpressiondo
return Eval[BitwiseOrExpression](envphase);
[LogicalAndExpression0  LogicalAndExpression1 && BitwiseOrExpressiondo
aObject  readReference(Eval[LogicalAndExpression1](envphase), phase);
if objectToBoolean(athen
return readReference(Eval[BitwiseOrExpression](envphase), phase)
else return a
end if
end proc;
proc Eval[LogicalXorExpression] (envEnvironmentphasePhase): ObjOrRef
[LogicalXorExpression  LogicalAndExpressiondo
return Eval[LogicalAndExpression](envphase);
[LogicalXorExpression0  LogicalXorExpression1 ^^ LogicalAndExpressiondo
aObject  readReference(Eval[LogicalXorExpression1](envphase), phase);
bObject  readReference(Eval[LogicalAndExpression](envphase), phase);
baBoolean  objectToBoolean(a);
bbBoolean  objectToBoolean(b);
return ba xor bb
end proc;
proc Eval[LogicalOrExpression] (envEnvironmentphasePhase): ObjOrRef
[LogicalOrExpression  LogicalXorExpressiondo
return Eval[LogicalXorExpression](envphase);
[LogicalOrExpression0  LogicalOrExpression1 || LogicalXorExpressiondo
aObject  readReference(Eval[LogicalOrExpression1](envphase), phase);
if objectToBoolean(athen return a
else return readReference(Eval[LogicalXorExpression](envphase), phase)
end if
end proc;

Conditional Operator

Syntax

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

Validation

Validate[ConditionalExpression] (cxtContextenvEnvironment) propagates the call to Validate to nonterminals in the expansion of ConditionalExpression.
Validate[NonAssignmentExpression] (cxtContextenvEnvironment) propagates the call to Validate to nonterminals in the expansion of NonAssignmentExpression.

Setup

Setup[ConditionalExpression] () propagates the call to Setup to nonterminals in the expansion of ConditionalExpression.
Setup[NonAssignmentExpression] () propagates the call to Setup to nonterminals in the expansion of NonAssignmentExpression.

Evaluation

proc Eval[ConditionalExpression] (envEnvironmentphasePhase): ObjOrRef
[ConditionalExpression  LogicalOrExpressiondo
return Eval[LogicalOrExpression](envphase);
[ConditionalExpression  LogicalOrExpression ? AssignmentExpression1 : AssignmentExpression2do
aObject  readReference(Eval[LogicalOrExpression](envphase), phase);
if objectToBoolean(athen
return readReference(Eval[AssignmentExpression1](envphase), phase)
else return readReference(Eval[AssignmentExpression2](envphase), phase)
end if
end proc;
proc Eval[NonAssignmentExpression] (envEnvironmentphasePhase): ObjOrRef
[NonAssignmentExpression  LogicalOrExpressiondo
return Eval[LogicalOrExpression](envphase);
[NonAssignmentExpression0  LogicalOrExpression ? NonAssignmentExpression1 : NonAssignmentExpression2do
aObject  readReference(Eval[LogicalOrExpression](envphase), phase);
if objectToBoolean(athen
return readReference(Eval[NonAssignmentExpression1](envphase), phase)
else return readReference(Eval[NonAssignmentExpression2](envphase), phase)
end if
end proc;

Assignment Operators

Syntax

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

Semantics

tag andEq;
tag xorEq;
tag orEq;

Validation

proc Validate[AssignmentExpression] (cxtContextenvEnvironment)
[AssignmentExpression  ConditionalExpressiondo
Evaluate Validate[ConditionalExpression](cxtenv) and ignore its result;
[AssignmentExpression0  PostfixExpression = AssignmentExpression1do
Evaluate Validate[PostfixExpression](cxtenv) and ignore its result;
Evaluate Validate[AssignmentExpression1](cxtenv) and ignore its result;
[AssignmentExpression0  PostfixExpression CompoundAssignment AssignmentExpression1do
Evaluate Validate[PostfixExpression](cxtenv) and ignore its result;
Evaluate Validate[AssignmentExpression1](cxtenv) and ignore its result;
[AssignmentExpression0  PostfixExpression LogicalAssignment AssignmentExpression1do
Evaluate Validate[PostfixExpression](cxtenv) and ignore its result;
Evaluate Validate[AssignmentExpression1](cxtenv) and ignore its result
end proc;

Setup

proc Setup[AssignmentExpression] ()
[AssignmentExpression  ConditionalExpressiondo
Evaluate Setup[ConditionalExpression]() and ignore its result;
[AssignmentExpression0  PostfixExpression = AssignmentExpression1do
Evaluate Setup[PostfixExpression]() and ignore its result;
Evaluate Setup[AssignmentExpression1]() and ignore its result;
[AssignmentExpression0  PostfixExpression CompoundAssignment AssignmentExpression1do
Evaluate Setup[PostfixExpression]() and ignore its result;
Evaluate Setup[AssignmentExpression1]() and ignore its result;
[AssignmentExpression0  PostfixExpression LogicalAssignment AssignmentExpression1do
Evaluate Setup[PostfixExpression]() and ignore its result;
Evaluate Setup[AssignmentExpression1]() and ignore its result
end proc;

Evaluation

proc Eval[AssignmentExpression] (envEnvironmentphasePhase): ObjOrRef
[AssignmentExpression  ConditionalExpressiondo
return Eval[ConditionalExpression](envphase);
[AssignmentExpression0  PostfixExpression = AssignmentExpression1do
if phase = compile then
throw a ConstantError exception — assignment cannot be used in a constant expression
end if;
raObjOrRef  Eval[PostfixExpression](envphase);
bObject  readReference(Eval[AssignmentExpression1](envphase), phase);
Evaluate writeReference(rabphase) and ignore its result;
return b;
[AssignmentExpression0  PostfixExpression CompoundAssignment AssignmentExpression1do
if phase = compile then
throw a ConstantError exception — assignment cannot be used in a constant expression
end if;
rLeftObjOrRef  Eval[PostfixExpression](envphase);
oLeftObject  readReference(rLeftphase);
oRightObject  readReference(Eval[AssignmentExpression1](envphase), phase);
resultObject  Op[CompoundAssignment](oLeftoRightphase);
Evaluate writeReference(rLeftresultphase) and ignore its result;
return result;
[AssignmentExpression0  PostfixExpression LogicalAssignment AssignmentExpression1do
if phase = compile then
throw a ConstantError exception — assignment cannot be used in a constant expression
end if;
rLeftObjOrRef  Eval[PostfixExpression](envphase);
oLeftObject  readReference(rLeftphase);
bLeftBoolean  objectToBoolean(oLeft);
resultObject  oLeft;
case Operator[LogicalAssignmentof
{andEqdo
if bLeft then
result  readReference(Eval[AssignmentExpression1](envphase), phase)
end if;
{xorEqdo
bRightBoolean  objectToBoolean(readReference(Eval[AssignmentExpression1](envphase), phase));
result  bLeft xor bRight;
{orEqdo
if not bLeft then
result  readReference(Eval[AssignmentExpression1](envphase), phase)
end if
end case;
Evaluate writeReference(rLeftresultphase) and ignore its result;
return result
end proc;
Op[CompoundAssignment]: Object  Object  Phase  Object;
Op[CompoundAssignment  *=] = multiply;
Op[CompoundAssignment  /=] = divide;
Op[CompoundAssignment  %=] = remainder;
Op[CompoundAssignment  +=] = add;
Op[CompoundAssignment  -=] = subtract;
Op[CompoundAssignment  <<=] = shiftLeft;
Op[CompoundAssignment  >>=] = shiftRight;
Op[CompoundAssignment  >>>=] = shiftRightUnsigned;
Op[CompoundAssignment  &=] = bitAnd;
Op[CompoundAssignment  ^=] = bitXor;
Op[CompoundAssignment  |=] = bitOr;
Operator[LogicalAssignment]: {andEqxorEqorEq};
Operator[LogicalAssignment  &&=] = andEq;
Operator[LogicalAssignment  ^^=] = xorEq;
Operator[LogicalAssignment  ||=] = orEq;

Comma Expressions

Syntax

ListExpression 
   AssignmentExpression
|  ListExpression , AssignmentExpression

Validation

Validate[ListExpression] (cxtContextenvEnvironment) propagates the call to Validate to nonterminals in the expansion of ListExpression.

Setup

Setup[ListExpression] () propagates the call to Setup to nonterminals in the expansion of ListExpression.

Evaluation

proc Eval[ListExpression] (envEnvironmentphasePhase): ObjOrRef
[ListExpression  AssignmentExpressiondo
return Eval[AssignmentExpression](envphase);
[ListExpression0  ListExpression1 , AssignmentExpressiondo
Evaluate readReference(Eval[ListExpression1](envphase), phase) and ignore its result;
return readReference(Eval[AssignmentExpression](envphase), phase)
end proc;
proc EvalAsList[ListExpression] (envEnvironmentphasePhase): Object[]
[ListExpression  AssignmentExpressiondo
eltObject  readReference(Eval[AssignmentExpression](envphase), phase);
return [elt];
[ListExpression0  ListExpression1 , AssignmentExpressiondo
eltsObject[]  EvalAsList[ListExpression1](envphase);
eltObject  readReference(Eval[AssignmentExpression](envphase), phase);
return elts  [elt]
end proc;

Type Expressions

Syntax

TypeExpression  NonAssignmentExpression

Validation

Validate[TypeExpression] (cxtContextenvEnvironment) propagates the call to Validate to nonterminals in the expansion of TypeExpression.

Setup and Evaluation

proc SetupAndEval[TypeExpression  NonAssignmentExpression] (envEnvironment): Class
Evaluate Setup[NonAssignmentExpression]() and ignore its result;
oObject  readReference(Eval[NonAssignmentExpression](envcompile), compile);
return objectToClass(o)
end proc;

Statements

Syntax

  {abbrevnoShortIffull}
Statement 
   ExpressionStatement Semicolon
|  SuperStatement Semicolon
|  Block
|  LabeledStatement
|  IfStatement
|  SwitchStatement
|  DoStatement Semicolon
|  WhileStatement
|  ForStatement
|  WithStatement
|  ContinueStatement Semicolon
|  BreakStatement Semicolon
|  ReturnStatement Semicolon
|  ThrowStatement Semicolon
|  TryStatement
Substatement 
   EmptyStatement
|  Statement
|  SimpleVariableDefinition Semicolon
|  Attributes [no line break] { Substatements }
Substatements 
   «empty»
|  SubstatementsPrefix Substatementabbrev
SubstatementsPrefix 
   «empty»
|  SubstatementsPrefix Substatementfull
Semicolonabbrev 
   ;
|  VirtualSemicolon
|  «empty»
SemicolonnoShortIf 
   ;
|  VirtualSemicolon
|  «empty»
Semicolonfull 
   ;
|  VirtualSemicolon

Validation

proc Validate[Statement] (cxtContextenvEnvironmentslLabel{}, jtJumpTargetspreinstBoolean)
[Statement  ExpressionStatement Semicolondo
Evaluate Validate[ExpressionStatement](cxtenv) and ignore its result;
[Statement  SuperStatement Semicolondo
Evaluate Validate[SuperStatement](cxtenv) and ignore its result;
[Statement  Blockdo
Evaluate Validate[Block](cxtenvjtpreinst) and ignore its result;
[Statement  LabeledStatementdo
Evaluate Validate[LabeledStatement](cxtenvsljt) and ignore its result;
[Statement  IfStatementdo
Evaluate Validate[IfStatement](cxtenvjt) and ignore its result;
[Statement  SwitchStatementdo
Evaluate Validate[SwitchStatement](cxtenvjt) and ignore its result;
[Statement  DoStatement Semicolondo
Evaluate Validate[DoStatement](cxtenvsljt) and ignore its result;
[Statement  WhileStatementdo
Evaluate Validate[WhileStatement](cxtenvsljt) and ignore its result;
[Statement  ForStatementdo
Evaluate Validate[ForStatement](cxtenvsljt) and ignore its result;
[Statement  WithStatementdo
Evaluate Validate[WithStatement](cxtenvjt) and ignore its result;
[Statement  ContinueStatement Semicolondo
Evaluate Validate[ContinueStatement](jt) and ignore its result;
[Statement  BreakStatement Semicolondo
Evaluate Validate[BreakStatement](jt) and ignore its result;
[Statement  ReturnStatement Semicolondo
Evaluate Validate[ReturnStatement](cxtenv) and ignore its result;
[Statement  ThrowStatement Semicolondo
Evaluate Validate[ThrowStatement](cxtenv) and ignore its result;
[Statement  TryStatementdo
Evaluate Validate[TryStatement](cxtenvjt) and ignore its result
end proc;
Enabled[Substatement]: Boolean;
proc Validate[Substatement] (cxtContextenvEnvironmentslLabel{}, jtJumpTargets)
[Substatement  EmptyStatementdo nothing;
[Substatement  Statementdo
Evaluate Validate[Statement](cxtenvsljtfalse) and ignore its result;
[Substatement  SimpleVariableDefinition Semicolondo
Evaluate Validate[SimpleVariableDefinition](cxtenv) and ignore its result;
[Substatement  Attributes [no line break] { Substatements }do
Evaluate Validate[Attributes](cxtenv) and ignore its result;
Evaluate Setup[Attributes]() and ignore its result;
attrAttribute  Eval[Attributes](envcompile);
if attr  Boolean then
throw a TypeError exception — attributes other than true and false may be used in a statement but not a substatement
end if;
Enabled[Substatement attr;
if attr then Evaluate Validate[Substatements](cxtenvjt) and ignore its result
end if
end proc;
proc Validate[Substatements] (cxtContextenvEnvironmentjtJumpTargets)
[Substatements  «empty»] do nothing;
[Substatements  SubstatementsPrefix Substatementabbrevdo
Evaluate Validate[SubstatementsPrefix](cxtenvjt) and ignore its result;
Evaluate Validate[Substatementabbrev](cxtenv, {}, jt) and ignore its result
end proc;
proc Validate[SubstatementsPrefix] (cxtContextenvEnvironmentjtJumpTargets)
[SubstatementsPrefix  «empty»] do nothing;
[SubstatementsPrefix0  SubstatementsPrefix1 Substatementfulldo
Evaluate Validate[SubstatementsPrefix1](cxtenvjt) and ignore its result;
Evaluate Validate[Substatementfull](cxtenv, {}, jt) and ignore its result
end proc;

Setup

Setup[Statement] () propagates the call to Setup to nonterminals in the expansion of Statement.
proc Setup[Substatement] ()
[Substatement  EmptyStatementdo nothing;
[Substatement  Statementdo Evaluate Setup[Statement]() and ignore its result;
[Substatement  SimpleVariableDefinition Semicolondo
Evaluate Setup[SimpleVariableDefinition]() and ignore its result;
[Substatement  Attributes [no line break] { Substatements }do
if Enabled[Substatementthen
Evaluate Setup[Substatements]() and ignore its result
end if
end proc;
Setup[Substatements] () propagates the call to Setup to nonterminals in the expansion of Substatements.
Setup[SubstatementsPrefix] () propagates the call to Setup to nonterminals in the expansion of SubstatementsPrefix.
proc Setup[Semicolon] ()
[Semicolon  ;do nothing;
[Semicolon  VirtualSemicolondo nothing;
[Semicolonabbrev  «empty»] do nothing;
[SemicolonnoShortIf  «empty»] do nothing
end proc;

Evaluation

proc Eval[Statement] (envEnvironmentdObject): Object
[Statement  ExpressionStatement Semicolondo
return Eval[ExpressionStatement](env);
[Statement  SuperStatement Semicolondo return Eval[SuperStatement](env);
[Statement  Blockdo return Eval[Block](envd);
[Statement  LabeledStatementdo return Eval[LabeledStatement](envd);
[Statement  IfStatementdo return Eval[IfStatement](envd);
[Statement  SwitchStatementdo return Eval[SwitchStatement](envd);
[Statement  DoStatement Semicolondo return Eval[DoStatement](envd);
[Statement  WhileStatementdo return Eval[WhileStatement](envd);
[Statement  ForStatementdo return Eval[ForStatement](envd);
[Statement  WithStatementdo return Eval[WithStatement](envd);
[Statement  ContinueStatement Semicolondo
return Eval[ContinueStatement](envd);
[Statement  BreakStatement Semicolondo return Eval[BreakStatement](envd);
[Statement  ReturnStatement Semicolondo return Eval[ReturnStatement](env);
[Statement  ThrowStatement Semicolondo return Eval[ThrowStatement](env);
[Statement  TryStatementdo return Eval[TryStatement](envd)
end proc;
proc Eval[Substatement] (envEnvironmentdObject): Object
[Substatement  EmptyStatementdo return d;
[Substatement  Statementdo return Eval[Statement](envd);
[Substatement  SimpleVariableDefinition Semicolondo
return Eval[SimpleVariableDefinition](envd);
[Substatement  Attributes [no line break] { Substatements }do
if Enabled[Substatementthen return Eval[Substatements](envd)
else return d
end if
end proc;
proc Eval[Substatements] (envEnvironmentdObject): Object
[Substatements  «empty»] do return d;
[Substatements  SubstatementsPrefix Substatementabbrevdo
oObject  Eval[SubstatementsPrefix](envd);
return Eval[Substatementabbrev](envo)
end proc;
proc Eval[SubstatementsPrefix] (envEnvironmentdObject): Object
[SubstatementsPrefix  «empty»] do return d;
[SubstatementsPrefix0  SubstatementsPrefix1 Substatementfulldo
oObject  Eval[SubstatementsPrefix1](envd);
return Eval[Substatementfull](envo)
end proc;

Empty Statement

Syntax

EmptyStatement  ;

Expression Statement

Syntax

ExpressionStatement  [lookahead{function{}] ListExpressionallowIn

Validation

Validate[ExpressionStatement] (cxtContextenvEnvironment) propagates the call to Validate to nonterminals in the expansion of ExpressionStatement.

Setup

Setup[ExpressionStatement] () propagates the call to Setup to nonterminals in the expansion of ExpressionStatement.

Evaluation

proc Eval[ExpressionStatement  [lookahead{function{}] ListExpressionallowIn] (envEnvironment): Object
return readReference(Eval[ListExpressionallowIn](envrun), run)
end proc;

Super Statement

Syntax

SuperStatement  super Arguments

Validation

proc Validate[SuperStatement  super Arguments] (cxtContextenvEnvironment)
frameParameterFrameOpt  getEnclosingParameterFrame(env);
if frame = none or frame.kind  constructorFunction then
throw a SyntaxError exception — a super statement is meaningful only inside a constructor
end if;
Evaluate Validate[Arguments](cxtenv) and ignore its result;
frame.callsSuperconstructor  true
end proc;

Setup

Setup[SuperStatement] () propagates the call to Setup to nonterminals in the expansion of SuperStatement.

Evaluation

proc Eval[SuperStatement  super Arguments] (envEnvironment): Object
frameParameterFrameOpt  getEnclosingParameterFrame(env);
note  Validate already ensured that frame  none and frame.kind = constructorFunction.
argsObject[]  Eval[Arguments](envrun);
if frame.superconstructorCalled = true then
throw a ReferenceError exception — the superconstructor cannot be called twice
end if;
cClass  getEnclosingClass(env);
thisObjectOpt  frame.this;
note  this  SimpleInstance;
Evaluate callInit(thisc.superargsrun) and ignore its result;
frame.superconstructorCalled  true;
return this
end proc;

Block Statement

Syntax

Block  { Directives }

Validation

CompileFrame[Block]: LocalFrame;
Preinstantiate[Block]: Boolean;
proc ValidateUsingFrame[Block  { Directives }] (cxtContextenvEnvironmentjtJumpTargetspreinstBooleanframeFrame)
localCxtContext  new Contextstrictcxt.strictopenNamespacescxt.openNamespaces;
Evaluate Validate[Directives](localCxt[frame]  envjtpreinstnone) and ignore its result
end proc;
proc Validate[Block  { Directives }] (cxtContextenvEnvironmentjtJumpTargetspreinstBoolean)
compileFrameLocalFrame  new LocalFramelocalBindings: {};
CompileFrame[Block compileFrame;
Preinstantiate[Block preinst;
Evaluate ValidateUsingFrame[Block](cxtenvjtpreinstcompileFrame) and ignore its result
end proc;

Setup

Setup[Block] () propagates the call to Setup to nonterminals in the expansion of Block.

Evaluation

proc Eval[Block  { Directives }] (envEnvironmentdObject): Object
compileFrameLocalFrame  CompileFrame[Block];
runtimeFrameLocalFrame;
if Preinstantiate[Blockthen runtimeFrame  compileFrame
else runtimeFrame  instantiateLocalFrame(compileFrameenv)
end if;
return Eval[Directives]([runtimeFrame]  envd)
end proc;
proc EvalUsingFrame[Block  { Directives }] (envEnvironmentframeFramedObject): Object
return Eval[Directives]([frame]  envd)
end proc;

Labeled Statements

Syntax

LabeledStatement  Identifier : Substatement

Validation

proc Validate[LabeledStatement  Identifier : Substatement] (cxtContextenvEnvironmentslLabel{}, jtJumpTargets)
nameString  Name[Identifier];
if name  jt.breakTargets then
throw a SyntaxError exception — nesting labeled statements with the same label is not permitted
end if;
jt2JumpTargets  JumpTargetsbreakTargetsjt.breakTargets  {name}, continueTargetsjt.continueTargets;
Evaluate Validate[Substatement](cxtenvsl  {name}, jt2) and ignore its result
end proc;

Setup

proc Setup[LabeledStatement  Identifier : Substatement] ()
Evaluate Setup[Substatement]() and ignore its result
end proc;

Evaluation

proc Eval[LabeledStatement  Identifier : Substatement] (envEnvironmentdObject): Object
try return Eval[Substatement](envd)
catch xSemanticException do
if x  Break and x.label = Name[Identifierthen return x.value
else throw x
end if
end try
end proc;

If Statement

Syntax

IfStatementabbrev 
   if ParenListExpression Substatementabbrev
|  if ParenListExpression SubstatementnoShortIf else Substatementabbrev
IfStatementfull 
   if ParenListExpression Substatementfull
|  if ParenListExpression SubstatementnoShortIf else Substatementfull
IfStatementnoShortIf  if ParenListExpression SubstatementnoShortIf else SubstatementnoShortIf

Validation

proc Validate[IfStatement] (cxtContextenvEnvironmentjtJumpTargets)
[IfStatementabbrev  if ParenListExpression Substatementabbrevdo
Evaluate Validate[ParenListExpression](cxtenv) and ignore its result;
Evaluate Validate[Substatementabbrev](cxtenv, {}, jt) and ignore its result;
[IfStatementfull  if ParenListExpression Substatementfulldo
Evaluate Validate[ParenListExpression](cxtenv) and ignore its result;
Evaluate Validate[Substatementfull](cxtenv, {}, jt) and ignore its result;
[IfStatement  if ParenListExpression SubstatementnoShortIf1 else Substatement2do
Evaluate Validate[ParenListExpression](cxtenv) and ignore its result;
Evaluate Validate[SubstatementnoShortIf1](cxtenv, {}, jt) and ignore its result;
Evaluate Validate[Substatement2](cxtenv, {}, jt) and ignore its result
end proc;

Setup

Setup[IfStatement] () propagates the call to Setup to nonterminals in the expansion of IfStatement.

Evaluation

proc Eval[IfStatement] (envEnvironmentdObject): Object
[IfStatementabbrev  if ParenListExpression Substatementabbrevdo
oObject  readReference(Eval[ParenListExpression](envrun), run);
if objectToBoolean(othen return Eval[Substatementabbrev](envd)
else return d
end if;
[IfStatementfull  if ParenListExpression Substatementfulldo
oObject  readReference(Eval[ParenListExpression](envrun), run);
if objectToBoolean(othen return Eval[Substatementfull](envd)
else return d
end if;
[IfStatement  if ParenListExpression SubstatementnoShortIf1 else Substatement2do
oObject  readReference(Eval[ParenListExpression](envrun), run);
if objectToBoolean(othen return Eval[SubstatementnoShortIf1](envd)
else return Eval[Substatement2](envd)
end if
end proc;

Switch Statement

Semantics

tuple SwitchKey
keyObject
end tuple;
SwitchGuard = SwitchKey  {default Object;

Syntax

SwitchStatement  switch ParenListExpression { CaseElements }
CaseElements 
   «empty»
|  CaseLabel
|  CaseLabel CaseElementsPrefix CaseElementabbrev
CaseElementsPrefix 
   «empty»
|  CaseElementsPrefix CaseElementfull
CaseElement 
   Directive
|  CaseLabel
CaseLabel 
   case ListExpressionallowIn :
|  default :

Validation

CompileFrame[SwitchStatement]: LocalFrame;
proc Validate[SwitchStatement  switch ParenListExpression { CaseElements }] (cxtContextenvEnvironmentjtJumpTargets)
if NDefaults[CaseElements] > 1 then
throw a SyntaxError exception — a case statement may have at most one default clause
end if;
Evaluate Validate[ParenListExpression](cxtenv) and ignore its result;
jt2JumpTargets  JumpTargetsbreakTargetsjt.breakTargets  {default}, continueTargetsjt.continueTargets;
compileFrameLocalFrame  new LocalFramelocalBindings: {};
CompileFrame[SwitchStatement compileFrame;
localCxtContext  new Contextstrictcxt.strictopenNamespacescxt.openNamespaces;
Evaluate Validate[CaseElements](localCxt[compileFrame]  envjt2) and ignore its result
end proc;
NDefaults[CaseElements]: Integer;
NDefaults[CaseElements  «empty»] = 0;
NDefaults[CaseElements  CaseLabel] = NDefaults[CaseLabel];
NDefaults[CaseElements  CaseLabel CaseElementsPrefix CaseElementabbrev] = NDefaults[CaseLabel] + NDefaults[CaseElementsPrefix] + NDefaults[CaseElementabbrev];
Validate[CaseElements] (cxtContextenvEnvironmentjtJumpTargets) propagates the call to Validate to nonterminals in the expansion of CaseElements.
NDefaults[CaseElementsPrefix]: Integer;
NDefaults[CaseElementsPrefix  «empty»] = 0;
NDefaults[CaseElementsPrefix0  CaseElementsPrefix1 CaseElementfull] = NDefaults[CaseElementsPrefix1] + NDefaults[CaseElementfull];
Validate[CaseElementsPrefix] (cxtContextenvEnvironmentjtJumpTargets) propagates the call to Validate to nonterminals in the expansion of CaseElementsPrefix.
NDefaults[CaseElement]: Integer;
NDefaults[CaseElement  Directive] = 0;
NDefaults[CaseElement  CaseLabel] = NDefaults[CaseLabel];
proc Validate[CaseElement] (cxtContextenvEnvironmentjtJumpTargets)
[CaseElement  Directivedo
Evaluate Validate[Directive](cxtenvjtfalsenone) and ignore its result;
[CaseElement  CaseLabeldo
Evaluate Validate[CaseLabel](cxtenvjt) and ignore its result
end proc;
NDefaults[CaseLabel]: Integer;
NDefaults[CaseLabel  case ListExpressionallowIn :] = 0;
NDefaults[CaseLabel  default :] = 1;
proc Validate[CaseLabel] (cxtContextenvEnvironmentjtJumpTargets)
[CaseLabel  case ListExpressionallowIn :do
Evaluate Validate[ListExpressionallowIn](cxtenv) and ignore its result;
[CaseLabel  default :do nothing
end proc;

Setup

Setup[SwitchStatement] () propagates the call to Setup to nonterminals in the expansion of SwitchStatement.
Setup[CaseElements] () propagates the call to Setup to nonterminals in the expansion of CaseElements.
Setup[CaseElementsPrefix] () propagates the call to Setup to nonterminals in the expansion of CaseElementsPrefix.
Setup[CaseElement] () propagates the call to Setup to nonterminals in the expansion of CaseElement.
Setup[CaseLabel] () propagates the call to Setup to nonterminals in the expansion of CaseLabel.

Evaluation

proc Eval[SwitchStatement  switch ParenListExpression { CaseElements }] (envEnvironmentdObject): Object
keyObject  readReference(Eval[ParenListExpression](envrun), run);
compileFrameLocalFrame  CompileFrame[SwitchStatement];
runtimeFrameLocalFrame  instantiateLocalFrame(compileFrameenv);
runtimeEnvEnvironment  [runtimeFrame]  env;
resultSwitchGuard  Eval[CaseElements](runtimeEnvSwitchKeykeykeyd);
if result  Object then return result end if;
note  result = SwitchKeykeykey;
result  Eval[CaseElements](runtimeEnvdefaultd);
if result  Object then return result end if;
note  result = default;
return d
end proc;
proc Eval[CaseElements] (envEnvironmentguardSwitchGuarddObject): SwitchGuard
[CaseElements  «empty»] do return guard;
[CaseElements  CaseLabeldo return Eval[CaseLabel](envguardd);
[CaseElements  CaseLabel CaseElementsPrefix CaseElementabbrevdo
guard2SwitchGuard  Eval[CaseLabel](envguardd);
guard3SwitchGuard  Eval[CaseElementsPrefix](envguard2d);
return Eval[CaseElementabbrev](envguard3d)
end proc;
proc Eval[CaseElementsPrefix] (envEnvironmentguardSwitchGuarddObject): SwitchGuard
[CaseElementsPrefix  «empty»] do return guard;
[CaseElementsPrefix0  CaseElementsPrefix1 CaseElementfulldo
guard2SwitchGuard  Eval[CaseElementsPrefix1](envguardd);
return Eval[CaseElementfull](envguard2d)
end proc;
proc Eval[CaseElement] (envEnvironmentguardSwitchGuarddObject): SwitchGuard
[CaseElement  Directivedo
case guard of
SwitchKey  {defaultdo return guard;
Object do return Eval[Directive](envguard)
end case;
[CaseElement  CaseLabeldo return Eval[CaseLabel](envguardd)
end proc;
proc Eval[CaseLabel] (envEnvironmentguardSwitchGuarddObject): SwitchGuard
[CaseLabel  case ListExpressionallowIn :do
case guard of
{default Object do return guard;
labelObject  readReference(Eval[ListExpressionallowIn](envrun), run);
if isStrictlyEqual(guard.keylabelrunthen return d
else return guard
end if
end case;
[CaseLabel  default :do
case guard of
SwitchKey  Object do return guard;
{defaultdo return d
end case
end proc;

Do-While Statement

Syntax

DoStatement  do Substatementabbrev while ParenListExpression

Validation

Labels[DoStatement]: Label{};
proc Validate[DoStatement  do Substatementabbrev while ParenListExpression] (cxtContextenvEnvironmentslLabel{}, jtJumpTargets)
continueLabelsLabel{}  sl  {default};
Labels[DoStatement continueLabels;
jt2JumpTargets  JumpTargetsbreakTargetsjt.breakTargets  {default}, continueTargetsjt.continueTargets  continueLabels;
Evaluate Validate[Substatementabbrev](cxtenv, {}, jt2) and ignore its result;
Evaluate Validate[ParenListExpression](cxtenv) and ignore its result
end proc;

Setup

Setup[DoStatement] () propagates the call to Setup to nonterminals in the expansion of DoStatement.

Evaluation

proc Eval[DoStatement  do Substatementabbrev while ParenListExpression] (envEnvironmentdObject): Object
try
d1Object  d;
while true do
try d1  Eval[Substatementabbrev](envd1)
catch xSemanticException do
if x  Continue and x.label  Labels[DoStatementthen d1  x.value
else throw x
end if
end try;
oObject  readReference(Eval[ParenListExpression](envrun), run);
if not objectToBoolean(othen return d1 end if
end while
catch xSemanticException do
if x  Break and x.label = default then return x.value else throw x end if
end try
end proc;

While Statement

Syntax

WhileStatement  while ParenListExpression Substatement

Validation

Labels[WhileStatement]: Label{};
proc Validate[WhileStatement  while ParenListExpression Substatement] (cxtContextenvEnvironmentslLabel{}, jtJumpTargets)
continueLabelsLabel{}  sl  {default};
Labels[WhileStatement continueLabels;
jt2JumpTargets  JumpTargetsbreakTargetsjt.breakTargets  {default}, continueTargetsjt.continueTargets  continueLabels;
Evaluate Validate[ParenListExpression](cxtenv) and ignore its result;
Evaluate Validate[Substatement](cxtenv, {}, jt2) and ignore its result
end proc;

Setup

Setup[WhileStatement] () propagates the call to Setup to nonterminals in the expansion of WhileStatement.

Evaluation

proc Eval[WhileStatement  while ParenListExpression Substatement] (envEnvironmentdObject): Object
try
d1Object  d;
try d1  Eval[Substatement](envd1)
catch xSemanticException do
if x  Continue and x.label  Labels[WhileStatementthen d1  x.value
else throw x
end if
end try
end while;
return d1
catch xSemanticException do
if x  Break and x.label = default then return x.value else throw x end if
end try
end proc;

For Statements

Syntax

ForStatement 
   for ( ForInitializer ; OptionalExpression ; OptionalExpression ) Substatement
|  for ( ForInBinding in ListExpressionallowIn ) Substatement
ForInitializer 
   «empty»
|  ListExpressionnoIn
|  VariableDefinitionnoIn
|  Attributes [no line break] VariableDefinitionnoIn
ForInBinding 
   PostfixExpression
|  VariableDefinitionKind VariableBindingnoIn
|  Attributes [no line break] VariableDefinitionKind VariableBindingnoIn
OptionalExpression 
   ListExpressionallowIn
|  «empty»

Validation

Labels[ForStatement]: Label{};
CompileLocalFrame[ForStatement]: LocalFrame;
proc Validate[ForStatement] (cxtContextenvEnvironmentslLabel{}, jtJumpTargets)
[ForStatement  for ( ForInitializer ; OptionalExpression1 ; OptionalExpression2 ) Substatementdo
continueLabelsLabel{}  sl  {default};
Labels[ForStatement continueLabels;
jt2JumpTargets  JumpTargetsbreakTargetsjt.breakTargets  {default}, continueTargetsjt.continueTargets  continueLabels;
compileLocalFrameLocalFrame  new LocalFramelocalBindings: {};
CompileLocalFrame[ForStatement compileLocalFrame;
compileEnvEnvironment  [compileLocalFrame]  env;
Evaluate Validate[ForInitializer](cxtcompileEnv) and ignore its result;
Evaluate Validate[OptionalExpression1](cxtcompileEnv) and ignore its result;
Evaluate Validate[OptionalExpression2](cxtcompileEnv) and ignore its result;
Evaluate Validate[Substatement](cxtcompileEnv, {}, jt2) and ignore its result;
[ForStatement  for ( ForInBinding in ListExpressionallowIn ) Substatementdo
continueLabelsLabel{}  sl  {default};
Labels[ForStatement continueLabels;
jt2JumpTargets  JumpTargetsbreakTargetsjt.breakTargets  {default}, continueTargetsjt.continueTargets  continueLabels;
Evaluate Validate[ListExpressionallowIn](cxtenv) and ignore its result;
compileLocalFrameLocalFrame  new LocalFramelocalBindings: {};
CompileLocalFrame[ForStatement compileLocalFrame;
compileEnvEnvironment  [compileLocalFrame]  env;
Evaluate Validate[ForInBinding](cxtcompileEnv) and ignore its result;
Evaluate Validate[Substatement](cxtcompileEnv, {}, jt2) and ignore its result
end proc;
Enabled[ForInitializer]: Boolean;
proc Validate[ForInitializer] (cxtContextenvEnvironment)
[ForInitializer  «empty»] do nothing;
[ForInitializer  ListExpressionnoIndo
Evaluate Validate[ListExpressionnoIn](cxtenv) and ignore its result;
[ForInitializer  VariableDefinitionnoIndo
Evaluate Validate[VariableDefinitionnoIn](cxtenvnone) and ignore its result;
[ForInitializer  Attributes [no line break] VariableDefinitionnoIndo
Evaluate Validate[Attributes](cxtenv) and ignore its result;
Evaluate Setup[Attributes]() and ignore its result;
attrAttribute  Eval[Attributes](envcompile);
Enabled[ForInitializer attr  false;
if attr  false then
Evaluate Validate[VariableDefinitionnoIn](cxtenvattr) and ignore its result
end if
end proc;
proc Validate[ForInBinding] (cxtContextenvEnvironment)
[ForInBinding  PostfixExpressiondo
Evaluate Validate[PostfixExpression](cxtenv) and ignore its result;
[ForInBinding  VariableDefinitionKind VariableBindingnoIndo
Evaluate Validate[VariableBindingnoIn](cxt, env, none, Immutable[VariableDefinitionKind], true) and ignore its result;
[ForInBinding  Attributes [no line break] VariableDefinitionKind VariableBindingnoIndo
Evaluate Validate[Attributes](cxtenv) and ignore its result;
Evaluate Setup[Attributes]() and ignore its result;
attrAttribute  Eval[Attributes](envcompile);
if attr = false then
throw an AttributeError exception — the false attribute canot be applied to a for-in variable definition
end if;
Evaluate Validate[VariableBindingnoIn](cxt, env, attr, Immutable[VariableDefinitionKind], true) and ignore its result
end proc;
Validate[OptionalExpression] (cxtContextenvEnvironment) propagates the call to Validate to nonterminals in the expansion of OptionalExpression.

Setup

Setup[ForStatement] () propagates the call to Setup to nonterminals in the expansion of ForStatement.
proc Setup[ForInitializer] ()
[ForInitializer  «empty»] do nothing;
[ForInitializer  ListExpressionnoIndo
Evaluate Setup[ListExpressionnoIn]() and ignore its result;
[ForInitializer  VariableDefinitionnoIndo
Evaluate Setup[VariableDefinitionnoIn]() and ignore its result;
[ForInitializer  Attributes [no line break] VariableDefinitionnoIndo
if Enabled[ForInitializerthen
Evaluate Setup[VariableDefinitionnoIn]() and ignore its result
end if
end proc;
proc Setup[ForInBinding] ()
[ForInBinding  PostfixExpressiondo
Evaluate Setup[PostfixExpression]() and ignore its result;
[ForInBinding  VariableDefinitionKind VariableBindingnoIndo
Evaluate Setup[VariableBindingnoIn]() and ignore its result;
[ForInBinding  Attributes [no line break] VariableDefinitionKind VariableBindingnoIndo
Evaluate Setup[VariableBindingnoIn]() and ignore its result
end proc;
Setup[OptionalExpression] () propagates the call to Setup to nonterminals in the expansion of OptionalExpression.

Evaluation

proc Eval[ForStatement] (envEnvironmentdObject): Object
[ForStatement  for ( ForInitializer ; OptionalExpression1 ; OptionalExpression2 ) Substatementdo
runtimeLocalFrameLocalFrame  instantiateLocalFrame(CompileLocalFrame[ForStatement], env);
runtimeEnvEnvironment  [runtimeLocalFrame]  env;
try
Evaluate Eval[ForInitializer](runtimeEnv) and ignore its result;
d1Object  d;
while objectToBoolean(readReference(Eval[OptionalExpression1](runtimeEnvrun), run)) do
try d1  Eval[Substatement](runtimeEnvd1)
catch xSemanticException do
if x  Continue and x.label  Labels[ForStatementthen
d1  x.value
else throw x
end if
end try;
Evaluate readReference(Eval[OptionalExpression2](runtimeEnvrun), run) and ignore its result
end while;
return d1
catch xSemanticException do
if x  Break and x.label = default then return x.value else throw x end if
end try;
[ForStatement  for ( ForInBinding in ListExpressionallowIn ) Substatementdo
try
oObject  readReference(Eval[ListExpressionallowIn](envrun), run);
cClass  objectType(o);
oldIndicesObject{}  c.enumerate(o);
remainingIndicesObject{}  oldIndices;
d1Object  d;
while remainingIndices  {} do
runtimeLocalFrameLocalFrame  instantiateLocalFrame(CompileLocalFrame[ForStatement], env);
runtimeEnvEnvironment  [runtimeLocalFrame]  env;
indexObject  any element of remainingIndices;
remainingIndices  remainingIndices – {index};
Evaluate WriteBinding[ForInBinding](runtimeEnvindex) and ignore its result;
try d1  Eval[Substatement](runtimeEnvd1)
catch xSemanticException do
if x  Continue and x.label  Labels[ForStatementthen
d1  x.value
else throw x
end if
end try;
newIndicesObject{}  c.enumerate(o);
if newIndices  oldIndices then
The implementation may, at its discretion, add none, some, or all of the objects in the set difference newIndicesoldIndices to remainingIndices;
The implementation may, at its discretion, remove none, some, or all of the objects in the set difference oldIndicesnewIndices from remainingIndices;
end if;
oldIndices  newIndices
end while;
return d1
catch xSemanticException do
if x  Break and x.label = default then return x.value else throw x end if
end try
end proc;
proc Eval[ForInitializer] (envEnvironment)
[ForInitializer  «empty»] do nothing;
[ForInitializer  ListExpressionnoIndo
Evaluate readReference(Eval[ListExpressionnoIn](envrun), run) and ignore its result;
[ForInitializer  VariableDefinitionnoIndo
Evaluate Eval[VariableDefinitionnoIn](envundefined) and ignore its result;
[ForInitializer  Attributes [no line break] VariableDefinitionnoIndo
if Enabled[ForInitializerthen
Evaluate Eval[VariableDefinitionnoIn](envundefined) and ignore its result
end if
end proc;
proc WriteBinding[ForInBinding] (envEnvironmentnewValueObject)
[ForInBinding  PostfixExpressiondo
rObjOrRef  Eval[PostfixExpression](envrun);
Evaluate writeReference(rnewValuerun) and ignore its result;
[ForInBinding  VariableDefinitionKind VariableBindingnoIndo
Evaluate WriteBinding[VariableBindingnoIn](envnewValue) and ignore its result;
[ForInBinding  Attributes [no line break] VariableDefinitionKind VariableBindingnoIndo
Evaluate WriteBinding[VariableBindingnoIn](envnewValue) and ignore its result
end proc;
proc Eval[OptionalExpression] (envEnvironmentphasePhase): ObjOrRef
[OptionalExpression  ListExpressionallowIndo
return Eval[ListExpressionallowIn](envphase);
[OptionalExpression  «empty»] do return true
end proc;

With Statement

Syntax

WithStatement  with ParenListExpression Substatement

Validation

CompileLocalFrame[WithStatement]: LocalFrame;
proc Validate[WithStatement  with ParenListExpression Substatement] (cxtContextenvEnvironmentjtJumpTargets)
Evaluate Validate[ParenListExpression](cxtenv) and ignore its result;
compileWithFrameWithFrame  new WithFramevaluenone;
compileLocalFrameLocalFrame  new LocalFramelocalBindings: {};
CompileLocalFrame[WithStatement compileLocalFrame;
compileEnvEnvironment  [compileLocalFrame]  [compileWithFrame]  env;
Evaluate Validate[Substatement](cxtcompileEnv, {}, jt) and ignore its result
end proc;

Setup

Setup[WithStatement] () propagates the call to Setup to nonterminals in the expansion of WithStatement.

Evaluation

proc Eval[WithStatement  with ParenListExpression Substatement] (envEnvironmentdObject): Object
valueObject  readReference(Eval[ParenListExpression](envrun), run);
runtimeWithFrameWithFrame  new WithFramevaluevalue;
runtimeLocalFrameLocalFrame  instantiateLocalFrame(CompileLocalFrame[WithStatement], [runtimeWithFrame]  env);
runtimeEnvEnvironment  [runtimeLocalFrame]  [runtimeWithFrame]  env;
return Eval[Substatement](runtimeEnvd)
end proc;

Continue and Break Statements

Syntax

ContinueStatement 
   continue
|  continue [no line break] Identifier
BreakStatement 
   break
|  break [no line break] Identifier

Validation

proc Validate[ContinueStatement] (jtJumpTargets)
[ContinueStatement  continuedo
if default  jt.continueTargets then
throw a SyntaxError exception — there is no enclosing statement to which to continue
end if;
[ContinueStatement  continue [no line break] Identifierdo
if Name[Identifier jt.continueTargets then
throw a SyntaxError exception — there is no enclosing labeled statement to which to continue
end if
end proc;
proc Validate[BreakStatement] (jtJumpTargets)
[BreakStatement  breakdo
if default  jt.breakTargets then
throw a SyntaxError exception — there is no enclosing statement to which to break
end if;
[BreakStatement  break [no line break] Identifierdo
if Name[Identifier jt.breakTargets then
throw a SyntaxError exception — there is no enclosing labeled statement to which to break
end if
end proc;

Setup

proc Setup[ContinueStatement] ()
[ContinueStatement  continuedo nothing;
[ContinueStatement  continue [no line break] Identifierdo nothing
end proc;
proc Setup[BreakStatement] ()
[BreakStatement  breakdo nothing;
[BreakStatement  break [no line break] Identifierdo nothing
end proc;

Evaluation

proc Eval[ContinueStatement] (envEnvironmentdObject): Object
[ContinueStatement  continuedo throw Continuevaluedlabeldefault;
[ContinueStatement  continue [no line break] Identifierdo
throw ContinuevaluedlabelName[Identifier]
end proc;
proc Eval[BreakStatement] (envEnvironmentdObject): Object
[BreakStatement  breakdo throw Breakvaluedlabeldefault;
[BreakStatement  break [no line break] Identifierdo
throw BreakvaluedlabelName[Identifier]
end proc;

Return Statement

Syntax

ReturnStatement 
   return
|  return [no line break] ListExpressionallowIn

Validation

proc Validate[ReturnStatement] (cxtContextenvEnvironment)
[ReturnStatement  returndo
if getEnclosingParameterFrame(env) = none then
throw a SyntaxError exception — a return statement must be located inside a function
end if;
[ReturnStatement  return [no line break] ListExpressionallowIndo
frameParameterFrameOpt  getEnclosingParameterFrame(env);
if frame = none then
throw a SyntaxError exception — a return statement must be located inside a function
end if;
if cannotReturnValue(framethen
throw a SyntaxError exception — a return statement inside a setter or constructor cannot return a value
end if;
Evaluate Validate[ListExpressionallowIn](cxtenv) and ignore its result
end proc;

Setup

Setup[ReturnStatement] () propagates the call to Setup to nonterminals in the expansion of ReturnStatement.

Evaluation

proc Eval[ReturnStatement] (envEnvironment): Object
[ReturnStatement  returndo throw Returnvalueundefined;
[ReturnStatement  return [no line break] ListExpressionallowIndo
aObject  readReference(Eval[ListExpressionallowIn](envrun), run);
throw Returnvaluea
end proc;
cannotReturnValue(frame) returns true if the function represented by frame cannot return a value because it is a setter or constructor.
proc cannotReturnValue(frameParameterFrame): Boolean
return frame.kind = constructorFunction or frame.handling = set
end proc;

Throw Statement

Syntax

ThrowStatement  throw [no line break] ListExpressionallowIn

Validation

Validate[ThrowStatement] (cxtContextenvEnvironment) propagates the call to Validate to nonterminals in the expansion of ThrowStatement.

Setup

Setup[ThrowStatement] () propagates the call to Setup to nonterminals in the expansion of ThrowStatement.

Evaluation

proc Eval[ThrowStatement  throw [no line break] ListExpressionallowIn] (envEnvironment): Object
aObject  readReference(Eval[ListExpressionallowIn](envrun), run);
throw a
end proc;

Try Statement

Syntax

TryStatement 
   try Block CatchClauses
|  try Block CatchClausesOpt finally Block
CatchClausesOpt 
   «empty»
|  CatchClauses
CatchClauses 
   CatchClause
|  CatchClauses CatchClause
CatchClause  catch ( Parameter ) Block

Validation

proc Validate[TryStatement] (cxtContextenvEnvironmentjtJumpTargets)
[TryStatement  try Block CatchClausesdo
Evaluate Validate[Block](cxtenvjtfalse) and ignore its result;
Evaluate Validate[CatchClauses](cxtenvjt) and ignore its result;
[TryStatement  try Block1 CatchClausesOpt finally Block2do
Evaluate Validate[Block1](cxtenvjtfalse) and ignore its result;
Evaluate Validate[CatchClausesOpt](cxtenvjt) and ignore its result;
Evaluate Validate[Block2](cxtenvjtfalse) and ignore its result
end proc;
Validate[CatchClausesOpt] (cxtContextenvEnvironmentjtJumpTargets) propagates the call to Validate to nonterminals in the expansion of CatchClausesOpt.
Validate[CatchClauses] (cxtContextenvEnvironmentjtJumpTargets) propagates the call to Validate to nonterminals in the expansion of CatchClauses.
CompileEnv[CatchClause]: Environment;
CompileFrame[CatchClause]: LocalFrame;
proc Validate[CatchClause  catch ( Parameter ) Block] (cxtContextenvEnvironmentjtJumpTargets)
compileFrameLocalFrame  new LocalFramelocalBindings: {};
compileEnvEnvironment  [compileFrame]  env;
CompileFrame[CatchClause compileFrame;
CompileEnv[CatchClause compileEnv;
Evaluate Validate[Parameter](cxtcompileEnvcompileFrame) and ignore its result;
Evaluate Validate[Block](cxtcompileEnvjtfalse) and ignore its result
end proc;

Setup

Setup[TryStatement] () propagates the call to Setup to nonterminals in the expansion of TryStatement.
Setup[CatchClausesOpt] () propagates the call to Setup to nonterminals in the expansion of CatchClausesOpt.
Setup[CatchClauses] () propagates the call to Setup to nonterminals in the expansion of CatchClauses.
proc Setup[CatchClause  catch ( Parameter ) Block] ()
Evaluate Setup[Parameter](CompileEnv[CatchClause], CompileFrame[CatchClause], none) and ignore its result;
Evaluate Setup[Block]() and ignore its result
end proc;

Evaluation

proc Eval[TryStatement] (envEnvironmentdObject): Object
[TryStatement  try Block CatchClausesdo
try return Eval[Block](envd)
catch xSemanticException do
if x  ControlTransfer then throw x
else
rObject  {reject Eval[CatchClauses](envx);
if r  reject then return r else throw x end if
end if
end try;
[TryStatement  try Block1 CatchClausesOpt finally Block2do
resultObjectOpt  none;
exceptionSemanticException  {none none;
try result  Eval[Block1](envd)
catch xSemanticException do exception  x
end try;
note  At this point exactly one of result and exception has a non-none value.
if exception  Object then
try
rObject  {reject Eval[CatchClausesOpt](envexception);
if r  reject then
note  The exception has been handled, so clear it.
result  r;
exception  none
end if
catch xSemanticException do
note  The catch clause threw another exception or ControlTransfer x, so replace the original exception with x.
exception  x
end try
end if;
note  The finally clause is executed even if the original block exited due to a ControlTransfer (break, continue, or return).
note  The finally clause is not inside a try-catch semantic statement, so if it throws another exception or ControlTransfer, then the original exception or ControlTransfer exception is dropped.
Evaluate Eval[Block2](envundefined) and ignore its result;
note  At this point exactly one of result and exception has a non-none value.
if exception  none then throw exception else return result end if
end proc;
proc Eval[CatchClausesOpt] (envEnvironmentexceptionObject): Object  {reject}
[CatchClausesOpt  «empty»] do return reject;
[CatchClausesOpt  CatchClausesdo return Eval[CatchClauses](envexception)
end proc;
proc Eval[CatchClauses] (envEnvironmentexceptionObject): Object  {reject}
[CatchClauses  CatchClausedo return Eval[CatchClause](envexception);
[CatchClauses0  CatchClauses1 CatchClausedo
rObject  {reject Eval[CatchClauses1](envexception);
if r  reject then return r else return Eval[CatchClause](envexceptionend if
end proc;
proc Eval[CatchClause  catch ( Parameter ) Block] (envEnvironmentexceptionObject): Object  {reject}
compileFrameLocalFrame  CompileFrame[CatchClause];
runtimeFrameLocalFrame  instantiateLocalFrame(compileFrameenv);
runtimeEnvEnvironment  [runtimeFrame]  env;
qnameQualifiedName  public::(Name[Parameter]);
vSingletonPropertyOpt  findLocalSingletonProperty(runtimeFrame, {qname}, write);
note  Validate created one local variable with the name in qname, so v  Variable.
if is(exceptionv.typethen
Evaluate writeSingletonProperty(vexceptionrun) and ignore its result;
return Eval[Block](runtimeEnvundefined)
else return reject
end if
end proc;

Directives

Syntax

Directive 
   EmptyStatement
|  Statement
|  AnnotatableDirective
|  Attributes [no line break] AnnotatableDirective
|  Attributes [no line break] { Directives }
|  Pragma Semicolon
AnnotatableDirective 
   VariableDefinitionallowIn Semicolon
|  FunctionDefinition
|  ClassDefinition
|  NamespaceDefinition Semicolon
|  ImportDirective Semicolon
|  UseDirective Semicolon
Directives 
   «empty»
|  DirectivesPrefix Directiveabbrev
DirectivesPrefix 
   «empty»
|  DirectivesPrefix Directivefull

Validation

Enabled[Directive]: Boolean;
proc Validate[Directive] (cxtContext, envEnvironment, jtJumpTargets, preinstBoolean, attrAttributeOptNotFalse)
[Directive  EmptyStatementdo nothing;
[Directive  Statementdo
if attr  {nonetruethen
throw an AttributeError exception — an ordinary statement only permits the attributes true and false
end if;
Evaluate Validate[Statement](cxtenv, {}, jtpreinst) and ignore its result;
[Directive  AnnotatableDirectivedo
Evaluate Validate[AnnotatableDirective](cxtenvpreinstattr) and ignore its result;
[Directive  Attributes [no line break] AnnotatableDirectivedo
Evaluate Validate[Attributes](cxtenv) and ignore its result;
Evaluate Setup[Attributes]() and ignore its result;
attr2Attribute  Eval[Attributes](envcompile);
attr3Attribute  combineAttributes(attrattr2);
if attr3 = false then Enabled[Directive false
else
Enabled[Directive true;
Evaluate Validate[AnnotatableDirective](cxtenvpreinstattr3) and ignore its result
end if;
[Directive  Attributes [no line break] { Directives }do
Evaluate Validate[Attributes](cxtenv) and ignore its result;
Evaluate Setup[Attributes]() and ignore its result;
attr2Attribute  Eval[Attributes](envcompile);
attr3Attribute  combineAttributes(attrattr2);
if attr3 = false then Enabled[Directive false
else
Enabled[Directive true;
localCxtContext  new Contextstrictcxt.strictopenNamespacescxt.openNamespaces;
Evaluate Validate[Directives](localCxtenvjtpreinstattr3) and ignore its result
end if;
[Directive  Pragma Semicolondo
if attr  {nonetruethen Evaluate Validate[Pragma](cxt) and ignore its result
else
throw an AttributeError exception — a pragma directive only permits the attributes true and false
end if
end proc;
proc Validate[AnnotatableDirective] (cxtContextenvEnvironmentpreinstBooleanattrAttributeOptNotFalse)
[AnnotatableDirective  VariableDefinitionallowIn Semicolondo
Evaluate Validate[VariableDefinitionallowIn](cxtenvattr) and ignore its result;
[AnnotatableDirective  FunctionDefinitiondo
Evaluate Validate[FunctionDefinition](cxtenvpreinstattr) and ignore its result;
[AnnotatableDirective  ClassDefinitiondo
Evaluate Validate[ClassDefinition](cxtenvpreinstattr) and ignore its result;
[AnnotatableDirective  NamespaceDefinition Semicolondo
Evaluate Validate[NamespaceDefinition](cxtenvpreinstattr) and ignore its result;
[AnnotatableDirective  ImportDirective Semicolondo
Evaluate Validate[ImportDirective](cxtenvpreinstattr) and ignore its result;
[AnnotatableDirective  UseDirective Semicolondo
if attr  {nonetruethen
Evaluate Validate[UseDirective](cxtenv) and ignore its result
else
throw an AttributeError exception — a use directive only permits the attributes true and false
end if
end proc;
Validate[Directives] (cxtContext, envEnvironment, jtJumpTargets, preinstBoolean, attrAttributeOptNotFalse) propagates the call to Validate to nonterminals in the expansion of Directives.
Validate[DirectivesPrefix] (cxtContext, envEnvironment, jtJumpTargets, preinstBoolean, attrAttributeOptNotFalse) propagates the call to Validate to nonterminals in the expansion of DirectivesPrefix.

Setup

proc Setup[Directive] ()
[Directive  EmptyStatementdo nothing;
[Directive  Statementdo Evaluate Setup[Statement]() and ignore its result;
[Directive  AnnotatableDirectivedo
Evaluate Setup[AnnotatableDirective]() and ignore its result;
[Directive  Attributes [no line break] AnnotatableDirectivedo
if Enabled[Directivethen
Evaluate Setup[AnnotatableDirective]() and ignore its result
end if;
[Directive  Attributes [no line break] { Directives }do
if Enabled[Directivethen Evaluate Setup[Directives]() and ignore its result
end if;
[Directive  Pragma Semicolondo nothing
end proc;
proc Setup[AnnotatableDirective] ()
[AnnotatableDirective  VariableDefinitionallowIn Semicolondo
Evaluate Setup[VariableDefinitionallowIn]() and ignore its result;
[AnnotatableDirective  FunctionDefinitiondo
Evaluate Setup[FunctionDefinition]() and ignore its result;
[AnnotatableDirective  ClassDefinitiondo
Evaluate Setup[ClassDefinition]() and ignore its result;
[AnnotatableDirective  NamespaceDefinition Semicolondo nothing;
[AnnotatableDirective  ImportDirective Semicolondo nothing;
[AnnotatableDirective  UseDirective Semicolondo nothing
end proc;
Setup[Directives] () propagates the call to Setup to nonterminals in the expansion of Directives.
Setup[DirectivesPrefix] () propagates the call to Setup to nonterminals in the expansion of DirectivesPrefix.

Evaluation

proc Eval[Directive] (envEnvironmentdObject): Object
[Directive  EmptyStatementdo return d;
[Directive  Statementdo return Eval[Statement](envd);
[Directive  AnnotatableDirectivedo return Eval[AnnotatableDirective](envd);
[Directive  Attributes [no line break] AnnotatableDirectivedo
if Enabled[Directivethen return Eval[AnnotatableDirective](envd)
else return d
end if;
[Directive  Attributes [no line break] { Directives }do
if Enabled[Directivethen return Eval[Directives](envdelse return d end if;
[Directive  Pragma Semicolondo return d
end proc;
proc Eval[AnnotatableDirective] (envEnvironmentdObject): Object
[AnnotatableDirective  VariableDefinitionallowIn Semicolondo
return Eval[VariableDefinitionallowIn](envd);
[AnnotatableDirective  FunctionDefinitiondo return d;
[AnnotatableDirective  ClassDefinitiondo return Eval[ClassDefinition](envd);
[AnnotatableDirective  NamespaceDefinition Semicolondo return d;
[AnnotatableDirective  ImportDirective Semicolondo return d;
[AnnotatableDirective  UseDirective Semicolondo return d
end proc;
proc Eval[Directives] (envEnvironmentdObject): Object
[Directives  «empty»] do return d;
[Directives  DirectivesPrefix Directiveabbrevdo
oObject  Eval[DirectivesPrefix](envd);
return Eval[Directiveabbrev](envo)
end proc;
proc Eval[DirectivesPrefix] (envEnvironmentdObject): Object
[DirectivesPrefix  «empty»] do return d;
[DirectivesPrefix0  DirectivesPrefix1 Directivefulldo
oObject  Eval[DirectivesPrefix1](envd);
return Eval[Directivefull](envo)
end proc;

Attributes

Syntax

Attributes 
   Attribute
|  AttributeCombination
AttributeCombination  Attribute [no line break] Attributes
Attribute 
   AttributeExpression
|  true
|  false
|  ReservedNamespace

Validation

Validate[Attributes] (cxtContextenvEnvironment) propagates the call to Validate to nonterminals in the expansion of Attributes.
Validate[AttributeCombination] (cxtContextenvEnvironment) propagates the call to Validate to nonterminals in the expansion of AttributeCombination.
Validate[Attribute] (cxtContextenvEnvironment) propagates the call to Validate to nonterminals in the expansion of Attribute.

Setup

Setup[Attributes] () propagates the call to Setup to nonterminals in the expansion of Attributes.
Setup[AttributeCombination] () propagates the call to Setup to nonterminals in the expansion of AttributeCombination.
Setup[Attribute] () propagates the call to Setup to nonterminals in the expansion of Attribute.

Evaluation

proc Eval[Attributes] (envEnvironmentphasePhase): Attribute
[Attributes  Attributedo return Eval[Attribute](envphase);
[Attributes  AttributeCombinationdo return Eval[AttributeCombination](envphase)
end proc;
proc Eval[AttributeCombination  Attribute [no line break] Attributes] (envEnvironmentphasePhase): Attribute
aAttribute  Eval[Attribute](envphase);
if a = false then return false end if;
bAttribute  Eval[Attributes](envphase);
return combineAttributes(ab)
end proc;
proc Eval[Attribute] (envEnvironmentphasePhase): Attribute
[Attribute  AttributeExpressiondo
aObject  readReference(Eval[AttributeExpression](envphase), phase);
return objectToAttribute(aphase);
[Attribute  truedo return true;
[Attribute  falsedo return false;
[Attribute  ReservedNamespacedo return Eval[ReservedNamespace](envphase)
end proc;

Use Directive

Syntax

UseDirective  use namespace ParenListExpression

Validation

proc Validate[UseDirective  use namespace ParenListExpression] (cxtContextenvEnvironment)
Evaluate Validate[ParenListExpression](cxtenv) and ignore its result;
Evaluate Setup[ParenListExpression]() and ignore its result;
valuesObject[]  EvalAsList[ParenListExpression](envcompile);
namespacesNamespace{}  {};
for each v  values do
if v  Namespace then throw a TypeError exception end if;
namespaces  namespaces  {v}
end for each;
cxt.openNamespaces  cxt.openNamespaces  namespaces
end proc;

Import Directive

Syntax

ImportDirective 
   import PackageName
|  import Identifier = PackageName

Validation

proc Validate[ImportDirective] (cxtContextenvEnvironmentpreinstBooleanattrAttributeOptNotFalse)
[ImportDirective  import PackageNamedo
if not preinst then
throw a SyntaxError exception — a package may be imported only in a preinstantiated scope
end if;
frameFrame  env[0];
if frame  Package then
throw a SyntaxError exception — a package may be imported only into a package scope
end if;
if attr  {nonetruethen
throw an AttributeError exception — an unnamed import directive only permits the attributes true and false
end if;
pkgNameString  Name[PackageName];
pkgPackage  locatePackage(pkgName);
Evaluate importPackageInto(pkgframe) and ignore its result;
[ImportDirective  import Identifier = PackageNamedo
if not preinst then
throw a SyntaxError exception — a package may be imported only in a preinstantiated scope
end if;
frameFrame  env[0];
if frame  Package then
throw a SyntaxError exception — a package may be imported only into a package scope
end if;
aCompoundAttribute  toCompoundAttribute(attr);
if a.dynamic then
throw an AttributeError exception — a package definition cannot have the dynamic attribute
end if;
if a.prototype then
throw an AttributeError exception — a package definition cannot have the prototype attribute
end if;
pkgNameString  Name[PackageName];
pkgPackage  locatePackage(pkgName);
vVariable  new VariabletypePackage, valuepkg, immutabletrue, setupnone, initializernone;
Evaluate defineSingletonProperty(env, Name[Identifier], a.namespaces, a.overrideMod, a.explicit, readWrite, v) and ignore its result;
Evaluate importPackageInto(pkgframe) and ignore its result
end proc;
proc locatePackage(nameString): Package
Look for a package bound to name in the implementation’s list of available packages. If one is found, let pkgPackage be that package; otherwise, throw an implementation-defined error.
initialize: (()  ())  {nonebusy pkg.initialize;
case initialize of
{nonedo nothing;
{busydo throw an UninitializedError exception — circular package dependency;
()  () do
Evaluate initialize() and ignore its result;
note  pkg.initialize = none;
end case;
return pkg
end proc;
proc importPackageInto(sourcePackagedestinationPackage)
for each b  source.localBindings do
if not (b.explicit or b.content = forbidden or (some d  destination.localBindings satisfies b.qname = d.qname and accessesOverlap(b.accessesd.accesses))) then
destination.localBindings  destination.localBindings  {b}
end if
end for each
end proc;

Pragma

Syntax

Pragma  use PragmaItems
PragmaItems 
   PragmaItem
|  PragmaItems , PragmaItem
PragmaItem 
   PragmaExpr
|  PragmaExpr ?
PragmaExpr 
   Identifier
|  Identifier ( PragmaArgument )
PragmaArgument 
   true
|  false
|  Number
|  - Number
|  - NegatedMinLong
|  String

Validation

Validate[Pragma] (cxtContext) propagates the call to Validate to nonterminals in the expansion of Pragma.
Validate[PragmaItems] (cxtContext) propagates the call to Validate to nonterminals in the expansion of PragmaItems.
proc Validate[PragmaItem] (cxtContext)
[PragmaItem  PragmaExprdo
Evaluate Validate[PragmaExpr](cxtfalse) and ignore its result;
[PragmaItem  PragmaExpr ?do
Evaluate Validate[PragmaExpr](cxttrue) and ignore its result
end proc;
proc Validate[PragmaExpr] (cxtContextoptionalBoolean)
[PragmaExpr  Identifierdo
Evaluate processPragma(cxtName[Identifier], undefinedoptional) and ignore its result;
[PragmaExpr  Identifier ( PragmaArgument )do
argObject  Value[PragmaArgument];
Evaluate processPragma(cxtName[Identifier], argoptional) and ignore its result
end proc;
Value[PragmaArgument]: Object;
Value[PragmaArgument  true] = true;
Value[PragmaArgument  false] = false;
Value[PragmaArgument  Number] = Value[Number];
Value[PragmaArgument  - Number] = generalNumberNegate(Value[Number]);
Value[PragmaArgument  - NegatedMinLong] = (–263)long;
Value[PragmaArgument  String] = Value[String];
proc processPragma(cxtContextnameStringvalueObjectoptionalBoolean)
if name = “strict” then
if value  {trueundefinedthen cxt.strict  truereturn end if;
if value = false then cxt.strict  falsereturn end if
end if;
if name = “ecmascript” then
if value  {undefined, 4f64then return end if;
if value  {1f64, 2f64, 3f64then
An implementation may optionally modify cxt to disable features not available in ECMAScript Edition value other than subsequent pragmas.
return
end if
end if;
if not optional then throw a SyntaxError exception end if
end proc;

Definitions

Variable Definition

Syntax

VariableDefinition  VariableDefinitionKind VariableBindingList
VariableDefinitionKind 
   var
|  const
VariableBindingList 
   VariableBinding
|  VariableBindingList , VariableBinding
VariableBinding  TypedIdentifier VariableInitialisation
VariableInitialisation 
   «empty»
|  = VariableInitializer
VariableInitializer 
   AssignmentExpression
|  AttributeCombination
TypedIdentifier 
   Identifier
|  Identifier : TypeExpression

Validation

proc Validate[VariableDefinition  VariableDefinitionKind VariableBindingList] (cxtContextenvEnvironmentattrAttributeOptNotFalse)
Evaluate Validate[VariableBindingList](cxt, env, attr, Immutable[VariableDefinitionKind], false) and ignore its result
end proc;
Immutable[VariableDefinitionKind]: Boolean;
Immutable[VariableDefinitionKind  var] = false;
Immutable[VariableDefinitionKind  const] = true;
Validate[VariableBindingList] (cxtContext, envEnvironment, attrAttributeOptNotFalse, immutableBoolean, noInitializerBoolean) propagates the call to Validate to nonterminals in the expansion of VariableBindingList.
CompileEnv[VariableBinding]: Environment;
CompileVar[VariableBinding]: Variable  DynamicVar  InstanceVariable;
OverriddenVar[VariableBinding]: InstanceVariableOpt;
Multiname[VariableBinding]: Multiname;
proc Validate[VariableBinding  TypedIdentifier VariableInitialisation] (cxtContext, envEnvironment, attrAttributeOptNotFalse, immutableBoolean, noInitializerBoolean)
Evaluate Validate[TypedIdentifier](cxtenv) and ignore its result;
Evaluate Validate[VariableInitialisation](cxtenv) and ignore its result;
CompileEnv[VariableBinding env;
nameString  Name[TypedIdentifier];
if not cxt.strict and getRegionalFrame(env Package  ParameterFrame and not immutable and attr = none and Plain[TypedIdentifierthen
qnameQualifiedName  public::name;
Multiname[VariableBinding {qname};
CompileVar[VariableBinding defineHoistedVar(envnameundefined)
else
aCompoundAttribute  toCompoundAttribute(attr);
if a.dynamic then
throw an AttributeError exception — a variable definition cannot have the dynamic attribute
end if;
if a.prototype then
throw an AttributeError exception — a variable definition cannot have the prototype attribute
end if;
categoryPropertyCategory  a.category;
if env[0]  Class then if category = none then category  final end if
else
if category  none then
throw an AttributeError exception — non-class variables cannot have a static, virtual, or final attribute
end if
end if;
case category of
{nonestaticdo
initializerInitializerOpt  Initializer[VariableInitialisation];
if noInitializer and initializer  none then
throw a SyntaxError exception — a for-in statement’s variable definition must not have an initialiser
end if;
proc variableSetup(): ClassOpt
typeClassOpt  SetupAndEval[TypedIdentifier](env);
Evaluate Setup[VariableInitialisation]() and ignore its result;
return type
end proc;
vVariable  new Variablevaluenone, immutableimmutable, setupvariableSetup, initializerinitializer, initializerEnvenv;
multinameMultiname  defineSingletonProperty(env, name, a.namespaces, a.overrideMod, a.explicit, readWrite, v);
Multiname[VariableBinding multiname;
CompileVar[VariableBinding v;
{virtualfinaldo
note  not noInitializer;
cClass  env[0];
vInstanceVariable  new InstanceVariablefinalcategory = finalimmutableimmutable;
vOverriddenInstanceVariableOpt  defineInstanceProperty(c, cxt, name, a.namespaces, a.overrideMod, a.explicit, v);
enumerableBoolean  a.enumerable;
if vOverridden  none and vOverridden.enumerable then enumerable  true
end if;
v.enumerable  enumerable;
OverriddenVar[VariableBinding vOverridden;
CompileVar[VariableBinding v
end case
end if
end proc;
Validate[VariableInitialisation] (cxtContextenvEnvironment) propagates the call to Validate to nonterminals in the expansion of VariableInitialisation.
Validate[VariableInitializer] (cxtContextenvEnvironment) propagates the call to Validate to nonterminals in the expansion of VariableInitializer.
Name[TypedIdentifier]: String;
Name[TypedIdentifier  Identifier] = Name[Identifier];
Name[TypedIdentifier  Identifier : TypeExpression] = Name[Identifier];
Plain[TypedIdentifier]: Boolean;
Plain[TypedIdentifier  Identifier] = true;
Plain[TypedIdentifier  Identifier : TypeExpression] = false;
proc Validate[TypedIdentifier] (cxtContextenvEnvironment)
[TypedIdentifier  Identifierdo nothing;
[TypedIdentifier  Identifier : TypeExpressiondo
Evaluate Validate[TypeExpression](cxtenv) and ignore its result
end proc;

Setup

proc Setup[VariableDefinition  VariableDefinitionKind VariableBindingList] ()
Evaluate Setup[VariableBindingList]() and ignore its result
end proc;
Setup[VariableBindingList] () propagates the call to Setup to nonterminals in the expansion of VariableBindingList.
proc Setup[VariableBinding  TypedIdentifier VariableInitialisation] ()
envEnvironment  CompileEnv[VariableBinding];
vVariable  DynamicVar  InstanceVariable  CompileVar[VariableBinding];
case v of
Evaluate setupVariable(v) and ignore its result;
if not v.immutable then
defaultValueObjectOpt  v.type.defaultValue;
if defaultValue = none then
throw an UninitializedError exception — Cannot declare a mutable variable of type Never
end if;
v.value  defaultValue
end if;
DynamicVar do Evaluate Setup[VariableInitialisation]() and ignore its result;
tClassOpt  SetupAndEval[TypedIdentifier](env);
if t = none then
overriddenVarInstanceVariableOpt  OverriddenVar[VariableBinding];
if overriddenVar  none then t  overriddenVar.type
else t  Object
end if
end if;
v.type  t;
Evaluate Setup[VariableInitialisation]() and ignore its result;
initializerInitializerOpt  Initializer[VariableInitialisation];
defaultValueObjectOpt  none;
if initializer  none then defaultValue  initializer(envcompile)
elsif not v.immutable then
defaultValue  t.defaultValue;
if defaultValue = none then
throw an UninitializedError exception — Cannot declare a mutable instance variable of type Never
end if
end if;
v.defaultValue  defaultValue
end case
end proc;
Setup[VariableInitialisation] () propagates the call to Setup to nonterminals in the expansion of VariableInitialisation.
Setup[VariableInitializer] () propagates the call to Setup to nonterminals in the expansion of VariableInitializer.

Evaluation

proc Eval[VariableDefinition  VariableDefinitionKind VariableBindingList] (envEnvironmentdObject): Object
Evaluate Eval[VariableBindingList](env) and ignore its result;
return d
end proc;
Eval[VariableBindingList] (envEnvironment) propagates the call to Eval to nonterminals in the expansion of VariableBindingList.
proc Eval[VariableBinding  TypedIdentifier VariableInitialisation] (envEnvironment)
case CompileVar[VariableBindingof
innerFrameNonWithFrame  env[0];
propertiesSingletonProperty{}  {b.content | b  innerFrame.localBindings such that b.qname  Multiname[VariableBinding]};
note  The properties set consists of exactly one Variable element because innerFrame was constructed with that Variable inside Validate.
vVariable  the one element of properties;
initializerInitializer  {nonebusy v.initializer;
case initializer of
{nonedo nothing;
{busydo throw a ReferenceError exception;
v.initializer  busy;
valueObject  initializer(v.initializerEnvrun);
Evaluate writeVariable(vvaluetrue) and ignore its result
end case;
initializerInitializerOpt  Initializer[VariableInitialisation];
if initializer  none then
valueObject  initializer(envrun);
Evaluate lexicalWrite(envMultiname[VariableBinding], valuefalserun) and ignore its result
end if;
InstanceVariable do nothing
end case
end proc;
proc WriteBinding[VariableBinding  TypedIdentifier VariableInitialisation] (envEnvironmentnewValueObject)
case CompileVar[VariableBindingof
innerFrameNonWithFrame  env[0];
propertiesSingletonProperty{}  {b.content | b  innerFrame.localBindings such that b.qname  Multiname[VariableBinding]};
note  The properties set consists of exactly one Variable element because innerFrame was constructed with that Variable inside Validate.
vVariable  the one element of properties;
Evaluate writeVariable(vnewValuefalse) and ignore its result;
Evaluate lexicalWrite(envMultiname[VariableBinding], newValuefalserun) and ignore its result
end case
end proc;
Initializer[VariableInitialisation]: InitializerOpt;
Initializer[VariableInitialisation  «empty»] = none;
Initializer[VariableInitialisation  = VariableInitializer] = Eval[VariableInitializer];
proc Eval[VariableInitializer] (envEnvironmentphasePhase): Object
[VariableInitializer  AssignmentExpressiondo
return readReference(Eval[AssignmentExpression](envphase), phase);
[VariableInitializer  AttributeCombinationdo
return Eval[AttributeCombination](envphase)
end proc;
proc SetupAndEval[TypedIdentifier] (envEnvironment): ClassOpt
[TypedIdentifier  Identifierdo return none;
[TypedIdentifier  Identifier : TypeExpressiondo
return SetupAndEval[TypeExpression](env)
end proc;

Simple Variable Definition

Syntax

A SimpleVariableDefinition represents the subset of VariableDefinition expansions that may be used when the variable definition is used as a Substatement instead of a Directive in non-strict mode. In strict mode variable definitions may not be used as substatements.

SimpleVariableDefinition  var UntypedVariableBindingList
UntypedVariableBindingList 
   UntypedVariableBinding
|  UntypedVariableBindingList , UntypedVariableBinding
UntypedVariableBinding  Identifier VariableInitialisationallowIn

Validation

proc Validate[SimpleVariableDefinition  var UntypedVariableBindingList] (cxtContextenvEnvironment)
if cxt.strict or getRegionalFrame(env Package  ParameterFrame then
throw a SyntaxError exception — a variable may not be defined in a substatement except inside a non-strict function or non-strict top-level code; to fix this error, place the definition inside a block
end if;
Evaluate Validate[UntypedVariableBindingList](cxtenv) and ignore its result
end proc;
Validate[UntypedVariableBindingList] (cxtContextenvEnvironment) propagates the call to Validate to nonterminals in the expansion of UntypedVariableBindingList.
proc Validate[UntypedVariableBinding  Identifier VariableInitialisationallowIn] (cxtContextenvEnvironment)
Evaluate Validate[VariableInitialisationallowIn](cxtenv) and ignore its result;
Evaluate defineHoistedVar(envName[Identifier], undefined) and ignore its result
end proc;

Setup

Setup[SimpleVariableDefinition] () propagates the call to Setup to nonterminals in the expansion of SimpleVariableDefinition.
Setup[UntypedVariableBindingList] () propagates the call to Setup to nonterminals in the expansion of UntypedVariableBindingList.
proc Setup[UntypedVariableBinding  Identifier VariableInitialisationallowIn] ()
Evaluate Setup[VariableInitialisationallowIn]() and ignore its result
end proc;

Evaluation

proc Eval[SimpleVariableDefinition  var UntypedVariableBindingList] (envEnvironmentdObject): Object
Evaluate Eval[UntypedVariableBindingList](env) and ignore its result;
return d
end proc;
Eval[UntypedVariableBindingList] (envEnvironment) propagates the call to Eval to nonterminals in the expansion of UntypedVariableBindingList.
proc Eval[UntypedVariableBinding  Identifier VariableInitialisationallowIn] (envEnvironment)
initializerInitializerOpt  Initializer[VariableInitialisationallowIn];
if initializer  none then
valueObject  initializer(envrun);
qnameQualifiedName  public::(Name[Identifier]);
Evaluate lexicalWrite(env, {qname}, valuefalserun) and ignore its result
end if
end proc;

Function Definition

Syntax

FunctionDefinition  function FunctionName FunctionCommon
FunctionName 
   Identifier
|  get [no line break] Identifier
|  set [no line break] Identifier
FunctionCommon  ( Parameters ) Result Block

Validation

OverriddenProperty[FunctionDefinition]: InstancePropertyOpt;
proc ValidateStatic[FunctionDefinition  function FunctionName FunctionCommon] (cxtContext, envEnvironment, preinstBoolean, aCompoundAttribute, uncheckedBoolean, hoistedBoolean)
nameString  Name[FunctionName];
handlingHandling  Handling[FunctionName];
case handling of
{normaldo
if unchecked then kind  uncheckedFunction
elsif a.prototype then kind  prototypeFunction
else kind  plainFunction
end if;
fSimpleInstance  UninstantiatedFunction  ValidateStaticFunction[FunctionCommon](cxtenvkind);
if preinst then f  instantiateFunction(fenvend if;
if hoisted then Evaluate defineHoistedVar(envnamef) and ignore its result
else
vVariable  new VariabletypeFunction, valuef, immutabletrue, setupnone, initializernone;
Evaluate defineSingletonProperty(env, name, a.namespaces, a.overrideMod, a.explicit, readWrite, v) and ignore its result
end if;
{getsetdo
if a.prototype then
throw an AttributeError exception — a getter or setter cannot have the prototype attribute
end if;
note  not (unchecked or hoisted);
Evaluate Validate[FunctionCommon](cxtenvplainFunctionhandling) and ignore its result;
boundEnvEnvironmentOpt  none;
if preinst then boundEnv  env end if;
case handling of
{getdo
getterGetter  new GettercallEvalStaticGet[FunctionCommon], envboundEnv;
Evaluate defineSingletonProperty(env, name, a.namespaces, a.overrideMod, a.explicit, read, getter) and ignore its result;
{setdo
setterSetter  new SettercallEvalStaticSet[FunctionCommon], envboundEnv;
Evaluate defineSingletonProperty(env, name, a.namespaces, a.overrideMod, a.explicit, write, setter) and ignore its result
end case
end case;
OverriddenProperty[FunctionDefinition none
end proc;
proc ValidateInstance[FunctionDefinition  function FunctionName FunctionCommon] (cxtContextenvEnvironmentcClassaCompoundAttributefinalBoolean)
if a.prototype then
throw an AttributeError exception — an instance method cannot have the prototype attribute
end if;
handlingHandling  Handling[FunctionName];
Evaluate Validate[FunctionCommon](cxtenvinstanceFunctionhandling) and ignore its result;
signatureParameterFrame  CompileFrame[FunctionCommon];
case handling of
{normaldo
m  new InstanceMethodfinalfinal, signaturesignature, lengthsignatureLength(signature), callEvalInstanceCall[FunctionCommon];
{getdo
m  new InstanceGetterfinalfinal, signaturesignature, callEvalInstanceGet[FunctionCommon];
{setdo
m  new InstanceSetterfinalfinal, signaturesignature, callEvalInstanceSet[FunctionCommon]
end case;
mOverriddenInstancePropertyOpt  defineInstanceProperty(c, cxt, Name[FunctionName], a.namespaces, a.overrideMod, a.explicit, m);
enumerableBoolean  a.enumerable;
if mOverridden  none and mOverridden.enumerable then enumerable  true end if;
m.enumerable  enumerable;
OverriddenProperty[FunctionDefinition mOverridden
end proc;
proc ValidateConstructor[FunctionDefinition  function FunctionName FunctionCommon] (cxtContextenvEnvironmentcClassaCompoundAttribute)
if a.prototype then
throw an AttributeError exception — a class constructor cannot have the prototype attribute
end if;
if Handling[FunctionName {getsetthen
throw a SyntaxError exception — a class constructor cannot be a getter or a setter
end if;
Evaluate Validate[FunctionCommon](cxtenvconstructorFunctionnormal) and ignore its result;
if c.init  none then
throw a DefinitionError exception — duplicate constructor definition
end if;
c.init  EvalInstanceInit[FunctionCommon];
OverriddenProperty[FunctionDefinition none
end proc;
proc Validate[FunctionDefinition  function FunctionName FunctionCommon] (cxtContextenvEnvironmentpreinstBooleanattrAttributeOptNotFalse)
aCompoundAttribute  toCompoundAttribute(attr);
if a.dynamic then
throw an AttributeError exception — a function cannot have the dynamic attribute
end if;
frameFrame  env[0];
if frame  Class then
note  preinst;
case a.category of
{staticdo
Evaluate ValidateStatic[FunctionDefinition](cxtenvpreinstafalsefalse) and ignore its result;
{nonedo
if Name[FunctionName] = frame.name then
Evaluate ValidateConstructor[FunctionDefinition](cxtenvframea) and ignore its result
else
Evaluate ValidateInstance[FunctionDefinition](cxtenvframeafalse) and ignore its result
end if;
{virtualdo
Evaluate ValidateInstance[FunctionDefinition](cxtenvframeafalse) and ignore its result;
{finaldo
Evaluate ValidateInstance[FunctionDefinition](cxtenvframeatrue) and ignore its result
end case
else
if a.category  none then
throw an AttributeError exception — non-class functions cannot have a static, virtual, or final attribute
end if;
uncheckedBoolean  not cxt.strict and Handling[FunctionName] = normal and Plain[FunctionCommon];
hoistedBoolean  unchecked and attr = none and (frame  Package or (frame  LocalFrame and env[1]  ParameterFrame));
Evaluate ValidateStatic[FunctionDefinition](cxtenvpreinstauncheckedhoisted) and ignore its result
end if
end proc;
Handling[FunctionName]: Handling;
Handling[FunctionName  Identifier] = normal;
Handling[FunctionName  get [no line break] Identifier] = get;
Handling[FunctionName  set [no line break] Identifier] = set;
Name[FunctionName]: String;
Name[FunctionName  Identifier] = Name[Identifier];
Name[FunctionName  get [no line break] Identifier] = Name[Identifier];
Name[FunctionName  set [no line break] Identifier] = Name[Identifier];
Plain[FunctionCommon  ( Parameters ) Result Block]: BooleanPlain[Parametersand Plain[Result];
CompileEnv[FunctionCommon]: Environment;
CompileFrame[FunctionCommon]: ParameterFrame;
proc Validate[FunctionCommon  ( Parameters ) Result Block] (cxtContextenvEnvironmentkindFunctionKindhandlingHandling)
localCxtContext  new Contextstrictcxt.strictopenNamespacescxt.openNamespaces;
superconstructorCalledBoolean  kind  constructorFunction;
compileFrameParameterFrame  new ParameterFramelocalBindings: {}, kindkind, handlinghandling, callsSuperconstructorfalse, superconstructorCalledsuperconstructorCalled, thisnone, parameters[], restnone;
compileEnvEnvironment  [compileFrame]  env;
CompileFrame[FunctionCommon compileFrame;
CompileEnv[FunctionCommon compileEnv;
if kind = uncheckedFunction then
Evaluate defineHoistedVar(compileEnv, “arguments”, undefined) and ignore its result
end if;
Evaluate Validate[Parameters](localCxtcompileEnvcompileFrame) and ignore its result;
Evaluate Validate[Result](localCxtcompileEnv) and ignore its result;
Evaluate Validate[Block](localCxt, compileEnv, JumpTargetsbreakTargets: {}, continueTargets: {}, false) and ignore its result
end proc;
proc ValidateStaticFunction[FunctionCommon  ( Parameters ) Result Block] (cxtContextenvEnvironmentkindStaticFunctionKind): UninstantiatedFunction
Evaluate Validate[FunctionCommon](cxtenvkindnormal) and ignore its result;
lengthInteger  ParameterCount[Parameters];
case kind of
return new UninstantiatedFunctiontypeFunction, lengthlength, callEvalStaticCall[FunctionCommon], constructnone, instantiations: {};
return new UninstantiatedFunctiontypePrototypeFunction, lengthlength, callEvalStaticCall[FunctionCommon], constructEvalPrototypeConstruct[FunctionCommon], instantiations: {}
end case
end proc;

Setup

proc Setup[FunctionDefinition  function FunctionName FunctionCommon] ()
overriddenPropertyInstancePropertyOpt  OverriddenProperty[FunctionDefinition];
case overriddenProperty of
{nonedo Evaluate Setup[FunctionCommon]() and ignore its result;
InstanceMethod  InstanceGetter  InstanceSetter do
Evaluate SetupOverride[FunctionCommon](overriddenProperty.signature) and ignore its result;
overriddenSignatureParameterFrame;
case Handling[FunctionNameof
{normaldo
This cannot happen because ValidateInstance already ensured that a function cannot override an instance variable.
{getdo
overriddenSignature  new ParameterFramelocalBindings: {}, kindinstanceFunction, handlingget, callsSuperconstructorfalse, superconstructorCalledfalse, thisnone, parameters[], restnone, returnTypeoverriddenProperty.type;
{setdo
vVariable  new VariabletypeoverriddenProperty.type, valuenone, immutablefalse, setupnone, initializernone;
parametersParameter[]  [Parametervarvdefaultnone];
overriddenSignature  new ParameterFramelocalBindings: {}, kindinstanceFunction, handlingset, callsSuperconstructorfalse, superconstructorCalledfalse, thisnone, parametersparameters, restnone, returnTypeVoid
end case;
Evaluate SetupOverride[FunctionCommon](overriddenSignature) and ignore its result
end case
end proc;
proc Setup[FunctionCommon  ( Parameters ) Result Block] ()
compileEnvEnvironment  CompileEnv[FunctionCommon];
compileFrameParameterFrame  CompileFrame[FunctionCommon];
Evaluate Setup[Parameters](compileEnvcompileFrame) and ignore its result;
Evaluate checkAccessorParameters(compileFrame) and ignore its result;
Evaluate Setup[Result](compileEnvcompileFrame) and ignore its result;
Evaluate Setup[Block]() and ignore its result
end proc;
proc SetupOverride[FunctionCommon  ( Parameters ) Result Block] (overriddenSignatureParameterFrame)
compileEnvEnvironment  CompileEnv[FunctionCommon];
compileFrameParameterFrame  CompileFrame[FunctionCommon];
Evaluate SetupOverride[Parameters](compileEnvcompileFrameoverriddenSignature) and ignore its result;
Evaluate checkAccessorParameters(compileFrame) and ignore its result;
Evaluate SetupOverride[Result](compileEnvcompileFrameoverriddenSignature) and ignore its result;
Evaluate Setup[Block]() and ignore its result
end proc;

Evaluation

proc EvalStaticCall[FunctionCommon  ( Parameters ) Result Block] (thisObjectfSimpleInstanceargsObject[], phasePhase): Object
note  The check that phase compile also ensures that Setup has been called.
if phase = compile then
throw a ConstantError exception — a constant expression cannot call user-defined functions
end if;
runtimeEnvEnvironment  f.env;
runtimeThisObjectOpt  none;
compileFrameParameterFrame  CompileFrame[FunctionCommon];
if compileFrame.kind  {uncheckedFunctionprototypeFunctionthen
if this  PrimitiveObject then runtimeThis  getPackageFrame(runtimeEnv)
else runtimeThis  this
end if
end if;
runtimeFrameParameterFrame  instantiateParameterFrame(compileFrameruntimeEnvruntimeThis);
Evaluate assignArguments(runtimeFramefargsphase) and ignore its result;
resultObject;
try
Evaluate Eval[Block]([runtimeFrame]  runtimeEnvundefined) and ignore its result;
result  undefined
catch xSemanticException do
if x  Return then result  x.value else throw x end if
end try;
return coerce(resultruntimeFrame.returnType)
end proc;
proc EvalStaticGet[FunctionCommon  ( Parameters ) Result Block] (runtimeEnvEnvironmentphasePhase): Object
note  The check that phase compile also ensures that Setup has been called.
if phase = compile then
throw a ConstantError exception — a constant expression cannot call user-defined getters
end if;
compileFrameParameterFrame  CompileFrame[FunctionCommon];
runtimeFrameParameterFrame  instantiateParameterFrame(compileFrameruntimeEnvnone);
Evaluate assignArguments(runtimeFramenone[]phase) and ignore its result;
resultObject;
try
Evaluate Eval[Block]([runtimeFrame]  runtimeEnvundefined) and ignore its result;
throw a SyntaxError exception — a getter must return a value and may not return by falling off the end of its code
catch xSemanticException do
if x  Return then result  x.value else throw x end if
end try;
return coerce(resultruntimeFrame.returnType)
end proc;
proc EvalStaticSet[FunctionCommon  ( Parameters ) Result Block] (newValueObjectruntimeEnvEnvironmentphasePhase)
note  The check that phase compile also ensures that Setup has been called.
if phase = compile then
throw a ConstantError exception — a constant expression cannot call setters
end if;
compileFrameParameterFrame  CompileFrame[FunctionCommon];
runtimeFrameParameterFrame  instantiateParameterFrame(compileFrameruntimeEnvnone);
Evaluate assignArguments(runtimeFramenone[newValue]phase) and ignore its result;
try
Evaluate Eval[Block]([runtimeFrame]  runtimeEnvundefined) and ignore its result
catch xSemanticException do if x  Return then throw x end if
end try
end proc;
proc EvalInstanceCall[FunctionCommon  ( Parameters ) Result Block] (thisObjectargsObject[], phasePhase): Object
note  The check that phase compile also ensures that Setup has been called.
if phase = compile then
throw a ConstantError exception — a constant expression cannot call user-defined functions
end if;
note  Class frames are always preinstantiated, so the run environment is the same as compile environment.
envEnvironment  CompileEnv[FunctionCommon];
compileFrameParameterFrame  CompileFrame[FunctionCommon];
runtimeFrameParameterFrame  instantiateParameterFrame(compileFrameenvthis);
Evaluate assignArguments(runtimeFramenoneargsphase) and ignore its result;
resultObject;
try
Evaluate Eval[Block]([runtimeFrame]  envundefined) and ignore its result;
result  undefined
catch xSemanticException do
if x  Return then result  x.value else throw x end if
end try;
return coerce(resultruntimeFrame.returnType)
end proc;
proc EvalInstanceGet[FunctionCommon  ( Parameters ) Result Block] (thisObjectphasePhase): Object
note  The check that phase compile also ensures that Setup has been called.
if phase = compile then
throw a ConstantError exception — a constant expression cannot call user-defined getters
end if;
note  Class frames are always preinstantiated, so the run environment is the same as compile environment.
envEnvironment  CompileEnv[FunctionCommon];
compileFrameParameterFrame  CompileFrame[FunctionCommon];
runtimeFrameParameterFrame  instantiateParameterFrame(compileFrameenvthis);
Evaluate assignArguments(runtimeFramenone[]phase) and ignore its result;
resultObject;
try
Evaluate Eval[Block]([runtimeFrame]  envundefined) and ignore its result;
throw a SyntaxError exception — a getter must return a value and may not return by falling off the end of its code
catch xSemanticException do
if x  Return then result  x.value else throw x end if
end try;
return coerce(resultruntimeFrame.returnType)
end proc;
proc EvalInstanceSet[FunctionCommon  ( Parameters ) Result Block] (thisObjectnewValueObjectphasePhase)
note  The check that phase compile also ensures that Setup has been called.
if phase = compile then
throw a ConstantError exception — a constant expression cannot call setters
end if;
note  Class frames are always preinstantiated, so the run environment is the same as compile environment.
envEnvironment  CompileEnv[FunctionCommon];
compileFrameParameterFrame  CompileFrame[FunctionCommon];
runtimeFrameParameterFrame  instantiateParameterFrame(compileFrameenvthis);
Evaluate assignArguments(runtimeFramenone[newValue]phase) and ignore its result;
try Evaluate Eval[Block]([runtimeFrame]  envundefined) and ignore its result
catch xSemanticException do if x  Return then throw x end if
end try
end proc;
proc EvalInstanceInit[FunctionCommon  ( Parameters ) Result Block] (thisSimpleInstanceargsObject[], phase: {run})
note  Class frames are always preinstantiated, so the run environment is the same as compile environment.
envEnvironment  CompileEnv[FunctionCommon];
compileFrameParameterFrame  CompileFrame[FunctionCommon];
runtimeFrameParameterFrame  instantiateParameterFrame(compileFrameenvthis);
Evaluate assignArguments(runtimeFramenoneargsphase) and ignore its result;
if not runtimeFrame.callsSuperconstructor then
cClass  getEnclosingClass(env);
Evaluate callInit(thisc.super[]run) and ignore its result;
runtimeFrame.superconstructorCalled  true
end if;
try Evaluate Eval[Block]([runtimeFrame]  envundefined) and ignore its result
catch xSemanticException do if x  Return then throw x end if
end try;
if not runtimeFrame.superconstructorCalled then
throw an UninitializedError exception — the superconstructor must be called before returning normally from a constructor
end if
end proc;
proc EvalPrototypeConstruct[FunctionCommon  ( Parameters ) Result Block] (fSimpleInstanceargsObject[], phasePhase): Object
note  The check that phase compile also ensures that Setup has been called.
if phase = compile then
throw a ConstantError exception — a constant expression cannot call user-defined prototype constructors
end if;
runtimeEnvEnvironment  f.env;
archetypeObject  dotRead(f, {public::“prototype”}, phase);
if archetype  {nullundefinedthen archetype  ObjectPrototype
elsif objectType(archetype Object then
throw a TypeError exception — bad prototype value
end if;
oObject  createSimpleInstance(Objectarchetypenonenonenone);
compileFrameParameterFrame  CompileFrame[FunctionCommon];
runtimeFrameParameterFrame  instantiateParameterFrame(compileFrameruntimeEnvo);
Evaluate assignArguments(runtimeFramefargsphase) and ignore its result;
resultObject;
try
Evaluate Eval[Block]([runtimeFrame]  runtimeEnvundefined) and ignore its result;
result  undefined
catch xSemanticException do
if x  Return then result  x.value else throw x end if
end try;
coercedResultObject  coerce(resultruntimeFrame.returnType);
if coercedResult  PrimitiveObject then return o else return coercedResult end if
end proc;
proc checkAccessorParameters(frameParameterFrame)
parametersParameter[]  frame.parameters;
restVariableOpt  frame.rest;
case frame.handling of
{normaldo nothing;
{getdo
if parameters  [] or rest  none then
throw a SyntaxError exception — a getter cannot take any parameters
end if;
{setdo
if |parameters 1 or rest  none then
throw a SyntaxError exception — a setter must take exactly one parameter
end if;
if parameters[0].default  none then
throw a SyntaxError exception — a setter’s parameter cannot be optional
end if
end case
end proc;
proc assignArguments(runtimeFrameParameterFrame, fSimpleInstance  {none}, argsObject[], phase: {run})
This procedure performs a number of checks on the arguments, including checking their count, names, and values. Although this procedure performs these checks in a specific order for expository purposes, an implementation may perform these checks in a different order, which could have the effect of reporting a different error if there are multiple errors. For example, if a function only allows between 2 and 4 arguments, the first of which must be a Number and is passed five arguments the first of which is a String, then the implementation may throw an exception either about the argument count mismatch or about the type coercion error in the first argument.
argumentsObjectObjectOpt  none;
if runtimeFrame.kind = uncheckedFunction then
argumentsObject  construct(Array[]phase);
Evaluate createDynamicProperty(argumentsObjectpublic::“callee”, falsefalsef) and ignore its result;
Evaluate writeArrayPrivateLength(argumentsObject, |args|, phase) and ignore its result
end if;
restObjectObjectOpt  none;
restVariable  {none runtimeFrame.rest;
if rest  none then restObject  construct(Array[]phaseend if;
parametersParameter[]  runtimeFrame.parameters;
iInteger  0;
jInteger  0;
for each arg  args do
if i < |parametersthen
parameterParameter  parameters[i];
defaultObjectOpt  parameter.default;
argOrDefaultObject  arg;
if argOrDefault = undefined and default  none then argOrDefault  default
end if;
vDynamicVar  Variable  parameter.var;
Evaluate writeSingletonProperty(vargOrDefaultphase) and ignore its result;
if argumentsObject  none then
note  Create an alias of v as the ith entry of the arguments object.
note  v  DynamicVar;
qnameQualifiedName  objectToQualifiedName(if64phase);
argumentsObject.localBindings  argumentsObject.localBindings  {LocalBindingqnameqname, accessesreadWrite, explicitfalse, enumerablefalse, contentv}
end if
elsif restObject  none then
if j  arrayLimit then throw a RangeError exception end if;
Evaluate indexWrite(restObjectjargphase) and ignore its result;
note  argumentsObject = none because a function can't have both a rest parameter and an arguments object.
j  j + 1
elsif argumentsObject  none then
Evaluate indexWrite(argumentsObjectiargphase) and ignore its result
else
throw an ArgumentError exception — more arguments than parameters were supplied, and the called function does not have a ... parameter and is not unchecked.
end if;
i  i + 1
end for each;
while i < |parametersdo
parameterParameter  parameters[i];
defaultObjectOpt  parameter.default;
if default = none then
if argumentsObject  none then default  undefined
else
throw an ArgumentError exception — fewer arguments than parameters were supplied, and the called function does not supply default values for the missing parameters and is not unchecked.
end if
end if;
Evaluate writeSingletonProperty(parameter.vardefaultphase) and ignore its result;
i  i + 1
end while
end proc;
proc signatureLength(signatureParameterFrame): Integer
return |signature.parameters|
end proc;

Syntax

Parameters 
   «empty»
|  NonemptyParameters
NonemptyParameters 
   ParameterInit
|  ParameterInit , NonemptyParameters
|  RestParameter
Parameter  ParameterAttributes TypedIdentifierallowIn
ParameterAttributes 
   «empty»
|  const
ParameterInit 
   Parameter
|  Parameter = AssignmentExpressionallowIn
RestParameter 
   ...
|  ... ParameterAttributes Identifier
Result 
   «empty»
|  : TypeExpressionallowIn

Validation

Plain[Parameters]: Boolean;
Plain[Parameters  «empty»] = true;
Plain[Parameters  NonemptyParameters] = Plain[NonemptyParameters];
ParameterCount[Parameters]: Integer;
ParameterCount[Parameters  «empty»] = 0;
ParameterCount[Parameters  NonemptyParameters] = ParameterCount[NonemptyParameters];
Validate[Parameters] (cxtContextenvEnvironmentcompileFrameParameterFrame) propagates the call to Validate to nonterminals in the expansion of Parameters.
Plain[NonemptyParameters]: Boolean;
Plain[NonemptyParameters  ParameterInit] = Plain[ParameterInit];
Plain[NonemptyParameters0  ParameterInit , NonemptyParameters1] = Plain[ParameterInitand Plain[NonemptyParameters1];
Plain[NonemptyParameters  RestParameter] = false;
ParameterCount[NonemptyParameters]: Integer;
ParameterCount[NonemptyParameters  ParameterInit] = 1;
ParameterCount[NonemptyParameters0  ParameterInit , NonemptyParameters1] = 1 + ParameterCount[NonemptyParameters1];
ParameterCount[NonemptyParameters  RestParameter] = 0;
Validate[NonemptyParameters] (cxtContextenvEnvironmentcompileFrameParameterFrame) propagates the call to Validate to nonterminals in the expansion of NonemptyParameters.
Name[Parameter  ParameterAttributes TypedIdentifierallowIn]: StringName[TypedIdentifierallowIn];
Plain[Parameter  ParameterAttributes TypedIdentifierallowIn]: BooleanPlain[TypedIdentifierallowInand not HasConst[ParameterAttributes];
CompileVar[Parameter]: DynamicVar  Variable;
proc Validate[Parameter  ParameterAttributes TypedIdentifierallowIn] (cxtContextenvEnvironmentcompileFrameParameterFrame  LocalFrame)
Evaluate Validate[TypedIdentifierallowIn](cxtenv) and ignore its result;
immutableBoolean  HasConst[ParameterAttributes];
nameString  Name[TypedIdentifierallowIn];
vDynamicVar  Variable;
if compileFrame  ParameterFrame and compileFrame.kind = uncheckedFunction then
note  not immutable;
v  defineHoistedVar(envnameundefined)
else
v  new Variablevaluenoneimmutableimmutablesetupnoneinitializernone;
Evaluate defineSingletonProperty(envname, {public}, nonefalsereadWritev) and ignore its result
end if;
CompileVar[Parameter v
end proc;
HasConst[ParameterAttributes]: Boolean;
HasConst[ParameterAttributes  «empty»] = false;
HasConst[ParameterAttributes  const] = true;
Plain[ParameterInit]: Boolean;
Plain[ParameterInit  Parameter] = Plain[Parameter];
Plain[ParameterInit  Parameter = AssignmentExpressionallowIn] = false;
proc Validate[ParameterInit] (cxtContextenvEnvironmentcompileFrameParameterFrame)
[ParameterInit  Parameterdo
Evaluate Validate[Parameter](cxtenvcompileFrame) and ignore its result;
[ParameterInit  Parameter = AssignmentExpressionallowIndo
Evaluate Validate[Parameter](cxtenvcompileFrame) and ignore its result;
Evaluate Validate[AssignmentExpressionallowIn](cxtenv) and ignore its result
end proc;
proc Validate[RestParameter] (cxtContextenvEnvironmentcompileFrameParameterFrame)
[RestParameter  ...do
note  compileFrame.kind  uncheckedFunction;
vVariable  new VariabletypeArray, valuenone, immutabletrue, setupnone, initializernone;
compileFrame.rest  v;
[RestParameter  ... ParameterAttributes Identifierdo
note  compileFrame.kind  uncheckedFunction;
vVariable  new VariabletypeArray, valuenone, immutableHasConst[ParameterAttributes], setupnone, initializernone;
compileFrame.rest  v;
nameString  Name[Identifier];
Evaluate defineSingletonProperty(envname, {public}, nonefalsereadWritev) and ignore its result
end proc;
Plain[Result]: Boolean;
Plain[Result  «empty»] = true;
Plain[Result  : TypeExpressionallowIn] = false;
Validate[Result] (cxtContextenvEnvironment) propagates the call to Validate to nonterminals in the expansion of Result.

Setup

Setup[Parameters] (compileEnvEnvironmentcompileFrameParameterFrame) propagates the call to Setup to nonterminals in the expansion of Parameters.
proc SetupOverride[Parameters] (compileEnvEnvironment, compileFrameParameterFrame, overriddenSignatureParameterFrame)
[Parameters  «empty»] do
if overriddenSignature.parameters  [] or overriddenSignature.rest  none then
throw a DefinitionError exception — mismatch with the overridden method’s signature
end if;
[Parameters  NonemptyParametersdo
Evaluate SetupOverride[NonemptyParameters](compileEnv, compileFrame, overriddenSignature, overriddenSignature.parameters) and ignore its result
end proc;
proc Setup[NonemptyParameters] (compileEnvEnvironmentcompileFrameParameterFrame)
[NonemptyParameters  ParameterInitdo
Evaluate Setup[ParameterInit](compileEnvcompileFrame) and ignore its result;
[NonemptyParameters0  ParameterInit , NonemptyParameters1do
Evaluate Setup[ParameterInit](compileEnvcompileFrame) and ignore its result;
Evaluate Setup[NonemptyParameters1](compileEnvcompileFrame) and ignore its result;
[NonemptyParameters  RestParameterdo nothing
end proc;
proc SetupOverride[NonemptyParameters] (compileEnvEnvironment, compileFrameParameterFrame, overriddenSignatureParameterFrame, overriddenParametersParameter[])
[NonemptyParameters  ParameterInitdo
if overriddenParameters = [] then
throw a DefinitionError exception — mismatch with the overridden method’s signature
end if;
Evaluate SetupOverride[ParameterInit](compileEnvcompileFrameoverriddenParameters[0]) and ignore its result;
if |overriddenParameters 1 or overriddenSignature.rest  none then
throw a DefinitionError exception — mismatch with the overridden method’s signature
end if;
[NonemptyParameters0  ParameterInit , NonemptyParameters1do
if overriddenParameters = [] then
throw a DefinitionError exception — mismatch with the overridden method’s signature
end if;
Evaluate SetupOverride[ParameterInit](compileEnvcompileFrameoverriddenParameters[0]) and ignore its result;
Evaluate SetupOverride[NonemptyParameters1](compileEnv, compileFrame, overriddenSignature, overriddenParameters[1 ...]) and ignore its result;
[NonemptyParameters  RestParameterdo
if overriddenParameters  [] then
throw a DefinitionError exception — mismatch with the overridden method’s signature
end if;
overriddenRestVariable  {none overriddenSignature.rest;
if overriddenRest = none or overriddenRest.type  Array then
throw a DefinitionError exception — mismatch with the overridden method’s signature
end if
end proc;
proc Setup[Parameter  ParameterAttributes TypedIdentifierallowIn] (compileEnvEnvironmentcompileFrameParameterFrame  LocalFramedefaultObjectOpt)
if compileFrame  ParameterFrame and default = none and (some p2  compileFrame.parameters satisfies p2.default  nonethen
throw a SyntaxError exception — a required parameter cannot follow an optional one
end if;
vDynamicVar  Variable  CompileVar[Parameter];
case v of
DynamicVar do nothing;
typeClassOpt  SetupAndEval[TypedIdentifierallowIn](compileEnv);
if type = none then type  Object end if;
v.type  type
end case;
if compileFrame  ParameterFrame then
pParameter  Parametervarvdefaultdefault;
compileFrame.parameters  compileFrame.parameters  [p]
end if
end proc;
proc SetupOverride[Parameter  ParameterAttributes TypedIdentifierallowIn] (compileEnvEnvironment, compileFrameParameterFrame, defaultObjectOpt, overriddenParameterParameter)
newDefaultObjectOpt  default;
if newDefault = none then newDefault  overriddenParameter.default end if;
if default = none and (some p2  compileFrame.parameters satisfies p2.default  nonethen
throw a SyntaxError exception — a required parameter cannot follow an optional one
end if;
vDynamicVar  Variable  CompileVar[Parameter];
note  v  DynamicVar;
typeClassOpt  SetupAndEval[TypedIdentifierallowIn](compileEnv);
if type = none then type  Object end if;
if type  overriddenParameter.var.type then
throw a DefinitionError exception — mismatch with the overridden method’s signature
end if;
v.type  type;
pParameter  ParametervarvdefaultnewDefault;
compileFrame.parameters  compileFrame.parameters  [p]
end proc;
proc Setup[ParameterInit] (compileEnvEnvironmentcompileFrameParameterFrame)
[ParameterInit  Parameterdo
Evaluate Setup[Parameter](compileEnvcompileFramenone) and ignore its result;
[ParameterInit  Parameter = AssignmentExpressionallowIndo
Evaluate Setup[AssignmentExpressionallowIn]() and ignore its result;
defaultObject  readReference(Eval[AssignmentExpressionallowIn](compileEnvcompile), compile);
Evaluate Setup[Parameter](compileEnvcompileFramedefault) and ignore its result
end proc;
proc SetupOverride[ParameterInit] (compileEnvEnvironmentcompileFrameParameterFrameoverriddenParameterParameter)
[ParameterInit  Parameterdo
Evaluate SetupOverride[Parameter](compileEnvcompileFramenoneoverriddenParameter) and ignore its result;
[ParameterInit  Parameter = AssignmentExpressionallowIndo
Evaluate Setup[AssignmentExpressionallowIn]() and ignore its result;
defaultObject  readReference(Eval[AssignmentExpressionallowIn](compileEnvcompile), compile);
Evaluate SetupOverride[Parameter](compileEnvcompileFramedefaultoverriddenParameter) and ignore its result
end proc;
proc Setup[Result] (compileEnvEnvironmentcompileFrameParameterFrame)
[Result  «empty»] do
defaultReturnTypeClass  Object;
if cannotReturnValue(compileFramethen defaultReturnType  Void end if;
compileFrame.returnType  defaultReturnType;
[Result  : TypeExpressionallowIndo
if cannotReturnValue(compileFramethen
throw a SyntaxError exception — a setter or constructor cannot define a return type
end if;
compileFrame.returnType  SetupAndEval[TypeExpressionallowIn](compileEnv)
end proc;
proc SetupOverride[Result] (compileEnvEnvironment, compileFrameParameterFrame, overriddenSignatureParameterFrame)
[Result  «empty»] do compileFrame.returnType  overriddenSignature.returnType;
[Result  : TypeExpressionallowIndo
tClass  SetupAndEval[TypeExpressionallowIn](compileEnv);
if overriddenSignature.returnType  t then
throw a DefinitionError exception — mismatch with the overridden method’s signature
end if;
compileFrame.returnType  t
end proc;

Class Definition

Syntax

ClassDefinition  class Identifier Inheritance Block
Inheritance 
   «empty»
|  extends TypeExpressionallowIn

Validation

Class[ClassDefinition]: Class;
proc Validate[ClassDefinition  class Identifier Inheritance Block] (cxtContextenvEnvironmentpreinstBooleanattrAttributeOptNotFalse)
if not preinst then
throw a SyntaxError exception — a class may be defined only in a preinstantiated scope
end if;
superClass  Validate[Inheritance](cxtenv);
if not super.complete then
throw a ConstantError exception — cannot override a class before its definition has been compiled
end if;
if super.final then throw a DefinitionError exception — can’t override a final class
end if;
aCompoundAttribute  toCompoundAttribute(attr);
if a.prototype then
throw an AttributeError exception — a class definition cannot have the prototype attribute
end if;
finalBoolean;
case a.category of
{nonedo final  false;
{staticdo
if env[0]  Class then
throw an AttributeError exception — non-class property definitions cannot have a static attribute
end if;
final  false;
{finaldo final  true;
{virtualdo
throw an AttributeError exception — a class definition cannot have the virtual attribute
end case;
privateNamespaceNamespace  new Namespacename: “private;
dynamicBoolean  a.dynamic or (super.dynamic and super  Object);
cClass  new ClasslocalBindings: {}, instanceProperties: {}, supersuper, prototypesuper.prototype, completefalse, nameName[Identifier], typeofString: “object”, privateNamespaceprivateNamespace, dynamicdynamic, finalfinal, defaultValuenull, defaultHinthintNumber, hasPropertysuper.hasProperty, bracketReadsuper.bracketRead, bracketWritesuper.bracketWrite, bracketDeletesuper.bracketDelete, readsuper.read, writesuper.write, deletesuper.delete, enumeratesuper.enumerate, callordinaryCall, constructordinaryConstruct, initnone, isordinaryIs, coerceordinaryCoerce;
Class[ClassDefinition c;
vVariable  new VariabletypeClass, valuec, immutabletrue, setupnone, initializernone;
Evaluate defineSingletonProperty(env, Name[Identifier], a.namespaces, a.overrideMod, a.explicit, readWrite, v) and ignore its result;
innerCxtContext  new Contextstrictcxt.strict, openNamespacescxt.openNamespaces  {privateNamespace};
Evaluate ValidateUsingFrame[Block](innerCxt, env, JumpTargetsbreakTargets: {}, continueTargets: {}, preinst, c) and ignore its result;
if c.init = none then c.init  super.init end if;
c.complete  true
end proc;
proc Validate[Inheritance] (cxtContextenvEnvironment): Class
[Inheritance  «empty»] do return Object;
[Inheritance  extends TypeExpressionallowIndo
Evaluate Validate[TypeExpressionallowIn](cxtenv) and ignore its result;
return SetupAndEval[TypeExpressionallowIn](env)
end proc;

Setup

proc Setup[ClassDefinition  class Identifier Inheritance Block] ()
Evaluate Setup[Block]() and ignore its result
end proc;

Evaluation

proc Eval[ClassDefinition  class Identifier Inheritance Block] (envEnvironmentdObject): Object
cClass  Class[ClassDefinition];
return EvalUsingFrame[Block](envcd)
end proc;

Namespace Definition

Syntax

NamespaceDefinition  namespace Identifier

Validation

proc Validate[NamespaceDefinition  namespace Identifier] (cxtContextenvEnvironmentpreinstBooleanattrAttributeOptNotFalse)
if not preinst then
throw a SyntaxError exception — a namespace may be defined only in a preinstantiated scope
end if;
aCompoundAttribute  toCompoundAttribute(attr);
if a.dynamic then
throw an AttributeError exception — a namespace definition cannot have the dynamic attribute
end if;
if a.prototype then
throw an AttributeError exception — a namespace definition cannot have the prototype attribute
end if;
case a.category of
{nonedo nothing;
{staticdo
if env[0]  Class then
throw an AttributeError exception — non-class property definitions cannot have a static attribute
end if;
{virtualfinaldo
throw an AttributeError exception — a namespace definition cannot have the virtual or final attribute
end case;
nameString  Name[Identifier];
nsNamespace  new Namespacenamename;
vVariable  new VariabletypeNamespace, valuens, immutabletrue, setupnone, initializernone;
Evaluate defineSingletonProperty(env, name, a.namespaces, a.overrideMod, a.explicit, readWrite, v) and ignore its result
end proc;

Programs

Syntax

Program 
   Directives
|  PackageDefinition Program

Processing

Process[Program]: Object;
Process[Program  Directives]
begin
cxtContext  new ContextstrictfalseopenNamespaces: {publicinternal};
initialEnvironmentEnvironment  [createGlobalObject()];
Evaluate Validate[Directives](cxt, initialEnvironment, JumpTargetsbreakTargets: {}, continueTargets: {}, true, none) and ignore its result;
Evaluate Setup[Directives]() and ignore its result;
return Eval[Directives](initialEnvironmentundefined)
end;
Process[Program0  PackageDefinition Program1]
begin
Evaluate Process[PackageDefinition] and ignore its result;
return Process[Program1]
end;

Package Definition

Syntax

PackageDefinition  package PackageNameOpt Block
PackageNameOpt 
   «empty»
|  PackageName
PackageName 
   String
|  PackageIdentifiers
PackageIdentifiers 
   Identifier
|  PackageIdentifiers . Identifier

Processing

Process[PackageDefinition  package PackageNameOpt Block]: Void
begin
nameString  Name[PackageNameOpt];
cxtContext  new ContextstrictfalseopenNamespaces: {publicinternal};
globalObjectPackage  createGlobalObject();
pkgInternalNamespace  new Namespacename: “internal;
pkgPackage  new PackagelocalBindings: {stdExplicitConstBinding(internal::“internal”, Namespaceinternal)}, archetypeObjectPrototype, namename, initializebusy, sealedtrue, internalNamespacepkgInternal;
initialEnvironmentEnvironment  [pkgglobalObject];
Evaluate Validate[Block](cxt, initialEnvironment, JumpTargetsbreakTargets: {}, continueTargets: {}, true) and ignore its result;
Evaluate Setup[Block]() and ignore its result;
proc evalPackage()
pkg.initialize  busy;
Evaluate Eval[Block](initialEnvironmentundefined) and ignore its result;
pkg.initialize  none
end proc;
pkg.initialize  evalPackage;
Bind name to package pkg in the system’s list of packages in an implementation-defined manner.
end;
Name[PackageNameOpt]: String;
Name[PackageNameOpt  «empty»] = an implementation-supplied name;
Name[PackageNameOpt  PackageName] = Name[PackageName];
Name[PackageName]: String;
Name[PackageName  String] = Value[String] processed in an implementation-defined manner;
Name[PackageName  PackageIdentifiers] = Names[PackageIdentifiers] processed in an implementation-defined manner;
Names[PackageIdentifiers]: String[];
Names[PackageIdentifiers  Identifier] = [Name[Identifier]];
Names[PackageIdentifiers0  PackageIdentifiers1 . Identifier] = Names[PackageIdentifiers1 [Name[Identifier]];
packageDatabasePackage{}  {};

Predefined Identifiers

proc createGlobalObject(): Package
return new PackagelocalBindings: {
stdExplicitConstBinding(internal::“internal”, Namespaceinternal),
stdConstBinding(public::“explicit”, Attributeglobal_explicit),
stdConstBinding(public::“enumerable”, Attributeglobal_enumerable),
stdConstBinding(public::“dynamic”, Attributeglobal_dynamic),
stdConstBinding(public::“static”, Attributeglobal_static),
stdConstBinding(public::“virtual”, Attributeglobal_virtual),
stdConstBinding(public::“final”, Attributeglobal_final),
stdConstBinding(public::“prototype”, Attributeglobal_prototype),
stdConstBinding(public::“unused”, Attributeglobal_unused),
stdFunction(public::“override”, global_override, 1),
stdConstBinding(public::“NaN”, NumberNaNf64),
stdConstBinding(public::“Infinity”, Number+f64),
stdConstBinding(public::“fNaN”, floatNaNf32),
stdConstBinding(public::“fInfinity”, float+f32),
stdConstBinding(public::“undefined”, Voidundefined),
stdFunction(public::“eval”, global_eval, 1),
stdFunction(public::“parseInt”, global_parseint, 2),
stdFunction(public::“parseLong”, global_parselong, 2),
stdFunction(public::“parseFloat”, global_parsefloat, 1),
stdFunction(public::“isNaN”, global_isnan, 1),
stdFunction(public::“isFinite”, global_isfinite, 1),
stdFunction(public::“decodeURI”, global_decodeuri, 1),
stdFunction(public::“decodeURIComponent”, global_decodeuricomponent, 1),
stdFunction(public::“encodeURI”, global_encodeuri, 1),
stdFunction(public::“encodeURIComponent”, global_encodeuricomponent, 1),
stdConstBinding(public::“Object”, ClassObject),
stdConstBinding(public::“Never”, ClassNever),
stdConstBinding(public::“Void”, ClassVoid),
stdConstBinding(public::“Null”, ClassNull),
stdConstBinding(public::“Boolean”, ClassBoolean),
stdConstBinding(public::“GeneralNumber”, ClassGeneralNumber),
stdConstBinding(public::“long”, Classlong),
stdConstBinding(public::“ulong”, Classulong),
stdConstBinding(public::“float”, Classfloat),
stdConstBinding(public::“Number”, ClassNumber),
stdConstBinding(public::“sbyte”, Classsbyte),
stdConstBinding(public::“byte”, Classbyte),
stdConstBinding(public::“short”, Classshort),
stdConstBinding(public::“ushort”, Classushort),
stdConstBinding(public::“int”, Classint),
stdConstBinding(public::“uint”, Classuint),
stdConstBinding(public::“char”, Classchar),
stdConstBinding(public::“String”, ClassString),
stdConstBinding(public::“Array”, ClassArray),
stdConstBinding(public::“Namespace”, ClassNamespace),
stdConstBinding(public::“Attribute”, ClassAttribute),
stdConstBinding(public::“Date”, ClassDate),
stdConstBinding(public::“RegExp”, ClassRegExp),
stdConstBinding(public::“Class”, ClassClass),
stdConstBinding(public::“Function”, ClassFunction),
stdConstBinding(public::“PrototypeFunction”, ClassPrototypeFunction),
stdConstBinding(public::“Package”, ClassPackage),
stdConstBinding(public::“Error”, ClassError),
stdConstBinding(public::“ArgumentError”, ClassArgumentError),
stdConstBinding(public::“AttributeError”, ClassAttributeError),
stdConstBinding(public::“ConstantError”, ClassConstantError),
stdConstBinding(public::“DefinitionError”, ClassDefinitionError),
stdConstBinding(public::“EvalError”, ClassEvalError),
stdConstBinding(public::“RangeError”, ClassRangeError),
stdConstBinding(public::“ReferenceError”, ClassReferenceError),
stdConstBinding(public::“SyntaxError”, ClassSyntaxError),
stdConstBinding(public::“TypeError”, ClassTypeError),
stdConstBinding(public::“UninitializedError”, ClassUninitializedError),
stdConstBinding(public::“URIError”, ClassURIError)},
archetypeObjectPrototype, name: “”, initializenone, sealedfalse, internalNamespaceinternal
end proc;

Built-in Namespaces

publicNamespace = new Namespacename: “public;
internalNamespace = new Namespacename: “internal;

Built-in Attributes

global_explicitCompoundAttributeCompoundAttributenamespaces: {}, explicittrue, enumerablefalse, dynamicfalse, categorynone, overrideModnone, prototypefalse, unusedfalse;
global_enumerableCompoundAttributeCompoundAttributenamespaces: {}, explicitfalse, enumerabletrue, dynamicfalse, categorynone, overrideModnone, prototypefalse, unusedfalse;
global_dynamicCompoundAttributeCompoundAttributenamespaces: {}, explicitfalse, enumerablefalse, dynamictrue, categorynone, overrideModnone, prototypefalse, unusedfalse;
global_staticCompoundAttributeCompoundAttributenamespaces: {}, explicitfalse, enumerablefalse, dynamicfalse, categorystatic, overrideModnone, prototypefalse, unusedfalse;
global_virtualCompoundAttributeCompoundAttributenamespaces: {}, explicitfalse, enumerablefalse, dynamicfalse, categoryvirtual, overrideModnone, prototypefalse, unusedfalse;
global_finalCompoundAttributeCompoundAttributenamespaces: {}, explicitfalse, enumerablefalse, dynamicfalse, categoryfinal, overrideModnone, prototypefalse, unusedfalse;
global_prototypeCompoundAttributeCompoundAttributenamespaces: {}, explicitfalse, enumerablefalse, dynamicfalse, categorynone, overrideModnone, prototypetrue, unusedfalse;
global_unusedCompoundAttributeCompoundAttributenamespaces: {}, explicitfalse, enumerablefalse, dynamicfalse, categorynone, overrideModnone, prototypefalse, unusedtrue;
proc global_override(thisObjectfSimpleInstanceargsObject[], phasePhase): Object
note  This function does not check phase and therefore can be used in a constant expression.
overrideModOverrideModifier;
if args = [] then overrideMod  true
elsif |args| = 1 then
argObject  args[0];
if arg  {truefalseundefinedthen throw a TypeError exception end if;
overrideMod  arg
else throw an ArgumentError exception — too many arguments supplied
end if;
return CompoundAttributenamespaces: {}, explicitfalse, enumerablefalse, dynamicfalse, categorynone, overrideModoverrideMod, prototypefalse, unusedfalse
end proc;

Built-in Functions

proc global_eval(thisObjectfSimpleInstanceargsObject[], phasePhase): Object
Evaluate ???? and ignore its result
end proc;
proc global_parseint(thisObjectfSimpleInstanceargsObject[], phasePhase): Float64
note  This function can be used in a constant expression if the arguments can be converted to primitives in constant expressions.
if |args {1, 2} then
throw an ArgumentError exception — at least one and at most two arguments must be supplied
end if;
sString  objectToString(args[0], phase);
radixInteger  objectToInteger(defaultArg(args, 1, +zerof64), phase);
i: (Integer – {0})  {+zero–zeroNaN stringPrefixToInteger(sradix);
end proc;
proc stringPrefixToInteger(sStringradixInteger): (Integer – {0})  {+zero–zeroNaN}
rInteger  radix;
if r  {0, 2 ... 36} then throw a RangeError exception — radix out of range end if;
iInteger  0;
while i < |sand the nonterminal WhiteSpaceOrLineTerminatorChar can expand into [s[i]] do
i  i + 1
end while;
sign: {–1, 1}  1;
if i < |sthen
if s[i] = ‘+’ then i  i + 1 elsif s[i] = ‘-’ then sign  –1; i  i + 1 end if
end if;
if r  {0, 16} and i + 2  |sand s[i ... i + 1]  {“0x”, “0X”} then
r  16;
i  i + 2
end if;
if r = 0 then r  10 end if;
nInteger  0;
startInteger  i;
digitIntegerOpt  0;
while i < |sand digit  none do
chChar16  s[i];
if ch  {‘0’ ... ‘9’} then digit  char16ToInteger(ch) – char16ToInteger(‘0’)
elsif ch  {‘A’ ... ‘Z’} then
digit  char16ToInteger(ch) – char16ToInteger(‘A’) + 10
elsif ch  {‘a’ ... ‘z’} then
digit  char16ToInteger(ch) – char16ToInteger(‘a’) + 10
else digit  none
end if;
if digit  none and digit  r then digit  none end if;
if digit  none then n  nr + digiti  i + 1 end if
end while;
if i = start then return NaN end if;
if n  0 then return nsign
elsif sign > 0 then return +zero
else return –zero
end if
end proc;
proc global_parselong(thisObjectfSimpleInstanceargsObject[], phasePhase): GeneralNumber
note  This function can be used in a constant expression if the arguments can be converted to primitives in constant expressions.
if |args {1, 2} then
throw an ArgumentError exception — at least one and at most two arguments must be supplied
end if;
sString  objectToString(args[0], phase);
radixInteger  objectToInteger(defaultArg(args, 1, +zerof64), phase);
i: (Integer – {0})  {+zero–zeroNaN stringPrefixToInteger(sradix);
case i of
{+zero–zerodo return 0long;
Integer do return integerToLong(i);
{NaNdo return NaNf64
end case
end proc;
proc global_parsefloat(thisObjectfSimpleInstanceargsObject[], phasePhase): Float64
note  This function can be used in a constant expression if its argument can be converted to a primitive in a constant expression.
if |args 1 then
throw an ArgumentError exception — exactly one argument must be supplied
end if;
sString  objectToString(args[0], phase);
Apply the lexer grammar with the start symbol StringDecimalLiteral to the string s. If the grammar can interpret neither s nor any prefix of s as an expansion of StringDecimalLiteral, then return NaNf64. Otherwise, let p be the longest prefix of s (possibly s itself) such that p is an expansion of StringDecimalLiteral.
qExtendedRational the value of the action Lex applied to p’s expansion of the nonterminal StringDecimalLiteral;
end proc;
proc global_isnan(thisObjectfSimpleInstanceargsObject[], phasePhase): Boolean
note  This function can be used in a constant expression if its argument can be converted to a primitive in a constant expression.
if |args 1 then
throw an ArgumentError exception — exactly one argument must be supplied
end if;
xGeneralNumber  objectToGeneralNumber(args[0], phase);
return x  {NaNf32NaNf64}
end proc;
proc global_isfinite(thisObjectfSimpleInstanceargsObject[], phasePhase): Boolean
note  This function can be used in a constant expression if its argument can be converted to a primitive in a constant expression.
if |args 1 then
throw an ArgumentError exception — exactly one argument must be supplied
end if;
xGeneralNumber  objectToGeneralNumber(args[0], phase);
return x  {NaNf32NaNf64+f32+f64f32f64}
end proc;
proc global_decodeuri(thisObjectfSimpleInstanceargsObject[], phasePhase): Object
Evaluate ???? and ignore its result
end proc;
proc global_decodeuricomponent(thisObject, fSimpleInstance, argsObject[], phasePhase): Object
Evaluate ???? and ignore its result
end proc;
proc global_encodeuri(thisObjectfSimpleInstanceargsObject[], phasePhase): Object
Evaluate ???? and ignore its result
end proc;
proc global_encodeuricomponent(thisObject, fSimpleInstance, argsObject[], phasePhase): Object
Evaluate ???? and ignore its result
end proc;

Built-in Classes

proc dummyCall(thisObjectcClassargsObject[], phasePhase): Object
Evaluate ???? and ignore its result
end proc;
proc dummyConstruct(cClassargsObject[], phasePhase): Object
Evaluate ???? and ignore its result
end proc;
prototypesSealedBoolean = false;

Object

ObjectClassnew ClasslocalBindings: {}, instanceProperties: {}, supernone, prototypeObjectPrototype, completetrue, name: “Object”, typeofString: “object”, dynamictrue, finalfalse, defaultValueundefined, defaultHinthintNumber, hasPropertyordinaryHasProperty, bracketReadordinaryBracketRead, bracketWriteordinaryBracketWrite, bracketDeleteordinaryBracketDelete, readordinaryRead, writeordinaryWrite, deleteordinaryDelete, enumerateordinaryEnumerate, callcallObject, constructconstructObject, initnone, isordinaryIs, coercecoerceObject;
proc callObject(thisObjectcClassargsObject[], phasePhase): Object
note  This function does not check phase and therefore can be used in a constant expression.
if |args| = 0 then return undefined
elsif |args| = 1 then return args[0]
else throw an ArgumentError exception — at most one argument can be supplied
end if
end proc;
proc constructObject(cClassargsObject[], phasePhase): Object
note  This function does not check phase and therefore can be used in a constant expression.
if |args| > 1 then
throw an ArgumentError exception — at most one argument can be supplied
end if;
oObject  defaultArg(args, 0, undefined);
if o  {nullundefinedthen
else return o
end if
end proc;
proc coerceObject(oObjectcClass): ObjectOpt
return o
end proc;
ObjectPrototypeSimpleInstancenew SimpleInstancelocalBindings: {
stdConstBinding(public::“constructor”, ClassObject),
stdFunction(public::“toString”, Object_toString, 0),
stdFunction(public::“toLocaleString”, Object_toLocaleString, 0),
stdFunction(public::“valueOf”, Object_valueOf, 0),
stdFunction(public::“hasOwnProperty”, Object_hasOwnProperty, 1),
stdFunction(public::“isPrototypeOf”, Object_isPrototypeOf, 1),
stdFunction(public::“propertyIsEnumerable”, Object_propertyIsEnumerable, 1),
stdFunction(public::“sealProperty”, Object_sealProperty, 1)},
archetypenone, sealedprototypesSealed, typeObject, slots: {}, callnone, constructnone, envnone;
proc Object_toString(thisObjectfSimpleInstanceargsObject[], phasePhase): String
note  This function does not check phase and therefore can be used in a constant expression.
note  This function ignores any arguments passed to it in args.
cClass  objectType(this);
return “[object ”  c.name  “]
end proc;
proc Object_toLocaleString(thisObjectfSimpleInstanceargsObject[], phasePhase): Object
if phase = compile then
throw a ConstantError exception — toLocaleString cannot be called from a constant expression
end if;
toStringMethodObject  dotRead(this, {public::“toString”}, phase);
return call(thistoStringMethodargsphase)
end proc;
proc Object_valueOf(thisObjectfSimpleInstanceargsObject[], phasePhase): Object
note  This function does not check phase and therefore can be used in a constant expression.
note  This function ignores any arguments passed to it in args.
return this
end proc;
proc Object_hasOwnProperty(thisObjectfSimpleInstanceargsObject[], phasePhase): Boolean
if phase = compile then
throw a ConstantError exception — hasOwnProperty cannot be called from a constant expression
end if;
if |args 1 then
throw an ArgumentError exception — exactly one argument must be supplied
end if;
return hasProperty(thisargs[0], truephase)
end proc;
proc Object_isPrototypeOf(thisObjectfSimpleInstanceargsObject[], phasePhase): Boolean
if phase = compile then
throw a ConstantError exception — isPrototypeOf cannot be called from a constant expression
end if;
if |args 1 then
throw an ArgumentError exception — exactly one argument must be supplied
end if;
oObject  args[0];
return this  archetypes(o)
end proc;
proc Object_propertyIsEnumerable(thisObject, fSimpleInstance, argsObject[], phasePhase): Boolean
if phase = compile then
throw a ConstantError exception — propertyIsEnumerable cannot be called from a constant expression
end if;
if |args 1 then
throw an ArgumentError exception — exactly one argument must be supplied
end if;
qnameQualifiedName  objectToQualifiedName(args[0], phase);
cClass  objectType(this);
mBaseInstancePropertyOpt  findBaseInstanceProperty(c, {qname}, read);
if mBase  none then
mInstanceProperty  getDerivedInstanceProperty(cmBaseread);
if m.enumerable then return true end if
end if;
mBase  findBaseInstanceProperty(c, {qname}, write);
if mBase  none then
mInstanceProperty  getDerivedInstanceProperty(cmBasewrite);
if m.enumerable then return true end if
end if;
if this  BindingObject then return false end if;
return some b  this.localBindings satisfies b.qname = qname and b.enumerable
end proc;
proc Object_sealProperty(thisObjectfSimpleInstanceargsObject[], phasePhase): Undefined
if phase = compile then
throw a ConstantError exception — sealProperty cannot be called from a constant expression
end if;
if |args| > 1 then
throw an ArgumentError exception — at most one argument can be supplied
end if;
argObject  defaultArg(args, 0, true);
if arg = false then Evaluate sealObject(this) and ignore its result
elsif arg = true then
Evaluate sealObject(this) and ignore its result;
Evaluate sealAllLocalProperties(this) and ignore its result
elsif arg  Char16  String then
if not hasProperty(thisargtruephasethen
throw a ReferenceError exception — property not found
end if;
qnameQualifiedName  objectToQualifiedName(argphase);
Evaluate sealLocalProperty(thisqname) and ignore its result
end if;
return undefined
end proc;

Never

NeverClassnew ClasslocalBindings: {}, instanceProperties: {}, superObject, prototypenone, completetrue, name: “Never”, typeofString: “”, dynamicfalse, finaltrue, defaultValuenone, hasPropertyordinaryHasProperty, bracketReadordinaryBracketRead, bracketWriteordinaryBracketWrite, bracketDeleteordinaryBracketDelete, readordinaryRead, writeordinaryWrite, deleteordinaryDelete, enumerateordinaryEnumerate, callsameAsConstruct, constructconstructNever, initnone, isordinaryIs, coercecoerceNever;
proc constructNever(cClassargsObject[], phasePhase): Object
if |args| > 1 then
throw an ArgumentError exception — at most one argument can be supplied
end if;
throw a TypeError exception — no coercions to Never are possible
end proc;
proc coerceNever(oObjectcClass): {none}
return none
end proc;

Void

VoidClassnew ClasslocalBindings: {}, instanceProperties: {}, superObject, prototypenone, completetrue, name: “Void”, typeofString: “undefined”, dynamicfalse, finaltrue, defaultValueundefined, hasPropertyordinaryHasProperty, bracketReadordinaryBracketRead, bracketWriteordinaryBracketWrite, bracketDeleteordinaryBracketDelete, readordinaryRead, writeordinaryWrite, deleteordinaryDelete, enumerateordinaryEnumerate, callcallVoid, constructconstructVoid, initnone, isordinaryIs, coercecoerceVoid;
proc callVoid(thisObjectcClassargsObject[], phasePhase): Undefined
note  This function does not check phase and therefore can be used in a constant expression.
if |args| > 1 then
throw an ArgumentError exception — at most one argument can be supplied
end if;
return undefined
end proc;
proc constructVoid(cClassargsObject[], phasePhase): Undefined
note  This function does not check phase and therefore can be used in a constant expression.
if |args 0 then throw an ArgumentError exception — no arguments can be supplied
end if;
return undefined
end proc;
proc coerceVoid(oObjectcClass): {undefinednone}
if o  Null  Undefined then return undefined else return none end if
end proc;

Null

NullClassnew ClasslocalBindings: {}, instanceProperties: {}, superObject, prototypenone, completetrue, name: “Null”, typeofString: “object”, dynamicfalse, finaltrue, defaultValuenull, hasPropertyordinaryHasProperty, bracketReadordinaryBracketRead, bracketWriteordinaryBracketWrite, bracketDeleteordinaryBracketDelete, readordinaryRead, writeordinaryWrite, deleteordinaryDelete, enumerateordinaryEnumerate, callcallNull, constructconstructNull, initnone, isordinaryIs, coercecoerceNull;
proc callNull(thisObjectcClassargsObject[], phasePhase): Null
note  This function does not check phase and therefore can be used in a constant expression.
if |args| > 1 then
throw an ArgumentError exception — at most one argument can be supplied
end if;
return null
end proc;
proc constructNull(cClassargsObject[], phasePhase): Null
note  This function does not check phase and therefore can be used in a constant expression.
if |args 0 then throw an ArgumentError exception — no arguments can be supplied
end if;
return null
end proc;
proc coerceNull(oObjectcClass): {nullnone}
if o = null then return o else return none end if
end proc;

Boolean

BooleanClassnew ClasslocalBindings: {}, instanceProperties: {}, superObject, prototypeBooleanPrototype, completetrue, name: “Boolean”, typeofString: “boolean”, dynamicfalse, finaltrue, defaultValuefalse, hasPropertyordinaryHasProperty, bracketReadordinaryBracketRead, bracketWriteordinaryBracketWrite, bracketDeleteordinaryBracketDelete, readordinaryRead, writeordinaryWrite, deleteordinaryDelete, enumerateordinaryEnumerate, callsameAsConstruct, constructconstructBoolean, initnone, isordinaryIs, coercecoerceBoolean;
proc constructBoolean(cClassargsObject[], phasePhase): Boolean
note  This function does not check phase and therefore can be used in a constant expression.
if |args| > 1 then
throw an ArgumentError exception — at most one argument can be supplied
end if;
return objectToBoolean(defaultArg(args, 0, false))
end proc;
proc coerceBoolean(oObjectcClass): BooleanOpt
if o  Boolean then return o else return none end if
end proc;
BooleanPrototypeSimpleInstancenew SimpleInstancelocalBindings: {
stdConstBinding(public::“constructor”, ClassBoolean),
stdFunction(public::“toString”, Boolean_toString, 0),
stdReserve(public::“valueOf”, ObjectPrototype)},
archetypeObjectPrototype, sealedprototypesSealed, typeObject, slots: {}, callnone, constructnone, envnone;
proc Boolean_toString(thisObjectfSimpleInstanceargsObject[], phasePhase): String
note  This function can be used in a constant expression.
note  This function ignores any arguments passed to it in args.
aBoolean  objectToBoolean(this);
return objectToString(aphase)
end proc;

GeneralNumber

GeneralNumberClassnew ClasslocalBindings: {}, instanceProperties: {}, superObject, prototypeGeneralNumberPrototype, completetrue, name: “GeneralNumber”, typeofString: “object”, dynamicfalse, finaltrue, defaultValueNaNf64, defaultHinthintNumber, hasPropertyordinaryHasProperty, bracketReadordinaryBracketRead, bracketWriteordinaryBracketWrite, bracketDeleteordinaryBracketDelete, readordinaryRead, writeordinaryWrite, deleteordinaryDelete, enumerateordinaryEnumerate, callsameAsConstruct, constructconstructGeneralNumber, initnone, isordinaryIs, coercecoerceGeneralNumber;
proc constructGeneralNumber(cClassargsObject[], phasePhase): GeneralNumber
note  This function can be used in a constant expression if the argument can be converted to a primitive in a constant expression.
if |args| = 0 then return +zerof64
elsif |args| = 1 then return objectToGeneralNumber(args[0], phase)
else throw an ArgumentError exception — at most one argument can be supplied
end if
end proc;
proc coerceGeneralNumber(oObjectcClass): GeneralNumber  {none}
if o  GeneralNumber then return o else return none end if
end proc;
GeneralNumberPrototypeSimpleInstancenew SimpleInstancelocalBindings: {
stdConstBinding(public::“constructor”, ClassGeneralNumber),
stdFunction(public::“toString”, GeneralNumber_toString, 1),
stdReserve(public::“valueOf”, ObjectPrototype),
stdFunction(public::“toFixed”, GeneralNumber_toFixed, 1),
stdFunction(public::“toExponential”, GeneralNumber_toExponential, 1),
stdFunction(public::“toPrecision”, GeneralNumber_toPrecision, 1)},
archetypeObjectPrototype, sealedprototypesSealed, typeObject, slots: {}, callnone, constructnone, envnone;
proc GeneralNumber_toString(thisObjectfSimpleInstanceargsObject[], phasePhase): String
note  This function can be used in a constant expression if this and the argument can be converted to primitives in constant expressions.
note  This function is generic and can be applied even if this is not a general number.
xGeneralNumber  objectToGeneralNumber(thisphase);
radixInteger  objectToInteger(defaultArg(args, 0, 10f64), phase);
if radix < 2 or radix > 36 then throw a RangeError exception — bad radix end if;
if radix = 10 then return generalNumberToString(x)
else
return x converted to a string containing a base-radix number in an implementation-defined manner
end if
end proc;
precisionLimitInteger = an implementation-defined integer not less than 20;
proc GeneralNumber_toFixed(thisObjectfSimpleInstanceargsObject[], phasePhase): String
note  This function can be used in a constant expression if this and the argument can be converted to primitives in constant expressions.
note  This function is generic and can be applied even if this is not a general number.
if |args| > 1 then
throw an ArgumentError exception — at most one argument can be supplied
end if;
xGeneralNumber  objectToGeneralNumber(thisphase);
fractionDigitsInteger  objectToInteger(defaultArg(args, 0, +zerof64), phase);
if fractionDigits < 0 or fractionDigits > precisionLimit then
throw a RangeError exception
end if;
if x  FiniteGeneralNumber then return generalNumberToString(xend if;
rRational  toRational(x);
if |r 1021 then return generalNumberToString(xend if;
signString  “”;
if r < 0 then sign  “-”; r  –r end if;
nInteger  r10fractionDigits + 1/2;
digitsString  integerToString(n);
if fractionDigits = 0 then return sign  digits
else
if |digits fractionDigits then
digits  repeat(‘0’, fractionDigits + 1 – |digits|)  digits
end if;
kInteger  |digits| – fractionDigits;
return sign  digits[0 ... k – 1]  “.”  digits[k ...]
end if
end proc;
proc GeneralNumber_toExponential(thisObject, fSimpleInstance, argsObject[], phasePhase): String
note  This function can be used in a constant expression if this and the argument can be converted to primitives in constant expressions.
note  This function is generic and can be applied even if this is not a general number.
if |args| > 1 then
throw an ArgumentError exception — at most one argument can be supplied
end if;
xGeneralNumber  objectToGeneralNumber(thisphase);
fractionDigitsExtendedInteger  objectToExtendedInteger(defaultArg(args, 0, NaNf64), phase);
if fractionDigits  {+or (fractionDigits  NaN and (fractionDigits < 0 or fractionDigits > precisionLimit)) then
throw a RangeError exception
end if;
if x  FiniteGeneralNumber then return generalNumberToString(xend if;
rRational  toRational(x);
signString  “”;
if r < 0 then sign  “-”; r  –r end if;
digitsString;
eInteger;
if fractionDigits  NaN then
if r = 0 then digits  repeat(‘0’, fractionDigits + 1); e  0
else
e  log10(r);
nInteger  r10fractionDigitse + 1/2;
note  At this point 10fractionDigits  n  10fractionDigits+1
if n = 10fractionDigits+1 then n  n/10; e  e + 1 end if;
digits  integerToString(n)
end if;
note  At this point the string digits has exactly fractionDigits + 1 digits
elsif r = 0 then digits  “0”; e  0
elsif x  Long  ULong then
digits  integerToString(r);
e  |digits| – 1;
while digits[|digits| – 1] = ‘0’ do digits  digits[0 ... |digits| – 2] end while
else
kInteger;
sInteger;
case x of
Let e, k, and s be integers such that k 1, 10k–1 s 10k, (s10e+1–k)f32 = x, and k is as small as possible.
Let e, k, and s be integers such that k 1, 10k–1 s 10k, (s10e+1–k)f64 = x, and k is as small as possible.
end case;
note  k is the number of digits in the decimal representation of s, s is not divisible by 10, and the least significant digit of s is not necessarily uniquely determined by the above criteria.
When there are multiple possibilities for s according to the rules above, implementations are encouraged but not required to select the one according to the following rules: Select the value of s for which s10e+1–k is closest in value to r; if there are two such possible values of s, choose the one that is even.
digits  integerToString(s)
end if;
return sign  exponentialNotationString(digitse)
end proc;
proc GeneralNumber_toPrecision(thisObject, fSimpleInstance, argsObject[], phasePhase): String
note  This function can be used in a constant expression if this and the argument can be converted to primitives in constant expressions.
note  This function is generic and can be applied even if this is not a general number.
if |args| > 1 then
throw an ArgumentError exception — at most one argument can be supplied
end if;
xGeneralNumber  objectToGeneralNumber(thisphase);
precisionExtendedInteger  objectToExtendedInteger(defaultArg(args, 0, NaNf64), phase);
if precision = NaN then return generalNumberToString(xend if;
if precision  {+or precision < 1 or precision > precisionLimit + 1 then
throw a RangeError exception
end if;
if x  FiniteGeneralNumber then return generalNumberToString(xend if;
rRational  toRational(x);
signString  “”;
if r < 0 then sign  “-”; r  –r end if;
digitsString;
eInteger;
if r = 0 then digits  repeat(‘0’, precision); e  0
else
e  log10(r);
nInteger  r10precision–1–e + 1/2;
note  At this point 10precision–1  n  10precision
if n = 10precision then n  n/10; e  e + 1 end if;
digits  integerToString(n)
end if;
note  At this point the string digits has exactly precision digits
if e < –6 or e  precision then return sign  exponentialNotationString(digitse)
elsif e = precision – 1 then return sign  digits
elsif e  0 then return sign  digits[0 ... e “.”  digits[e + 1 ...]
else return sign  “0.”  repeat(‘0’, –(e + 1))  digits
end if
end proc;

long

longClassnew ClasslocalBindings: {
stdConstBinding(public::“MAX_VALUE”, ulong, (263 – 1)long),
stdConstBinding(public::“MIN_VALUE”, ulong, (–263)long)},
instanceProperties: {}, superGeneralNumber, prototypelongPrototype, completetrue, name: “long”, typeofString: “long”, dynamicfalse, finaltrue, defaultValue: 0long, hasPropertyordinaryHasProperty, bracketReadordinaryBracketRead, bracketWriteordinaryBracketWrite, bracketDeleteordinaryBracketDelete, readordinaryRead, writeordinaryWrite, deleteordinaryDelete, enumerateordinaryEnumerate, callsameAsConstruct, constructconstructLong, initnone, isordinaryIs, coercecoerceLong;
proc constructLong(cClassargsObject[], phasePhase): Long
note  This function can be used in a constant expression if the argument can be converted to a primitive in a constant expression.
if |args| > 1 then
throw an ArgumentError exception — at most one argument can be supplied
end if;
argObject  defaultArg(args, 0, +zerof64);
iInteger  objectToInteger(argphase);
if –263  i  263 – 1 then return ilong
else throw a RangeError exception — i is out of the Long range
end if
end proc;
proc coerceLong(oObjectcClass): Long  {none}
if o  GeneralNumber then return none end if;
iIntegerOpt  checkInteger(o);
if i  none and –263  i  263 – 1 then return ilong
else throw a RangeError exception — i is out of the Long range
end if
end proc;
longPrototypeSimpleInstancenew SimpleInstancelocalBindings: {
stdConstBinding(public::“constructor”, Classlong),
stdReserve(public::“toString”, GeneralNumberPrototype),
stdReserve(public::“valueOf”, GeneralNumberPrototype)},
archetypeGeneralNumberPrototype, sealedprototypesSealed, typeObject, slots: {}, callnone, constructnone, envnone;

ulong

ulongClassnew ClasslocalBindings: {
stdConstBinding(public::“MAX_VALUE”, ulong, (264 – 1)ulong),
stdConstBinding(public::“MIN_VALUE”, ulong, 0ulong)},
instanceProperties: {}, superGeneralNumber, prototypeulongPrototype, completetrue, name: “ulong”, typeofString: “ulong”, dynamicfalse, finaltrue, defaultValue: 0ulong, hasPropertyordinaryHasProperty, bracketReadordinaryBracketRead, bracketWriteordinaryBracketWrite, bracketDeleteordinaryBracketDelete, readordinaryRead, writeordinaryWrite, deleteordinaryDelete, enumerateordinaryEnumerate, callsameAsConstruct, constructconstructULong, initnone, isordinaryIs, coercecoerceULong;
proc constructULong(cClassargsObject[], phasePhase): ULong
note  This function can be used in a constant expression if the argument can be converted to a primitive in a constant expression.
if |args| > 1 then
throw an ArgumentError exception — at most one argument can be supplied
end if;
argObject  defaultArg(args, 0, +zerof64);
iInteger  objectToInteger(argphase);
if 0  i  264 – 1 then return iulong
else throw a RangeError exception — i is out of the ULong range
end if
end proc;
proc coerceULong(oObjectcClass): ULong  {none}
if o  GeneralNumber then return none end if;
iIntegerOpt  checkInteger(o);
if i  none and 0  i  264 – 1 then return iulong
else throw a RangeError exception — i is out of the ULong range
end if
end proc;
ulongPrototypeSimpleInstancenew SimpleInstancelocalBindings: {
stdConstBinding(public::“constructor”, Classulong),
stdReserve(public::“toString”, GeneralNumberPrototype),
stdReserve(public::“valueOf”, GeneralNumberPrototype)},
archetypeGeneralNumberPrototype, sealedprototypesSealed, typeObject, slots: {}, callnone, constructnone, envnone;

float

floatClassnew ClasslocalBindings: {
stdConstBinding(public::“MAX_VALUE”, float, (3.40282351038)f32),
stdConstBinding(public::“MIN_VALUE”, float, (10–45)f32),
stdConstBinding(public::“NaN”, floatNaNf32),
stdConstBinding(public::“NEGATIVE_INFINITY”, floatf32),
stdConstBinding(public::“POSITIVE_INFINITY”, float+f32)},
instanceProperties: {}, superGeneralNumber, prototypefloatPrototype, completetrue, name: “float”, typeofString: “float”, dynamicfalse, finaltrue, defaultValueNaNf32, hasPropertyordinaryHasProperty, bracketReadordinaryBracketRead, bracketWriteordinaryBracketWrite, bracketDeleteordinaryBracketDelete, readordinaryRead, writeordinaryWrite, deleteordinaryDelete, enumerateordinaryEnumerate, callsameAsConstruct, constructconstructFloat, initnone, isordinaryIs, coercecoerceFloat;
proc constructFloat(cClassargsObject[], phasePhase): Float32
note  This function can be used in a constant expression if the argument can be converted to a primitive in a constant expression.
if |args| = 0 then return +zerof32
elsif |args| = 1 then return objectToFloat32(args[0], phase)
else throw an ArgumentError exception — at most one argument can be supplied
end if
end proc;
proc coerceFloat(oObjectcClass): Float32  {none}
if o  GeneralNumber then return toFloat32(oelse return none end if
end proc;
floatPrototypeSimpleInstancenew SimpleInstancelocalBindings: {
stdConstBinding(public::“constructor”, Classfloat),
stdReserve(public::“toString”, GeneralNumberPrototype),
stdReserve(public::“valueOf”, GeneralNumberPrototype)},
archetypeGeneralNumberPrototype, sealedprototypesSealed, typeObject, slots: {}, callnone, constructnone, envnone;

Number

NumberClassnew ClasslocalBindings: {
stdConstBinding(public::“MAX_VALUE”, Number, (1.797693134862315710308)f64),
stdConstBinding(public::“MIN_VALUE”, Number, (510–324)f64),
stdConstBinding(public::“NaN”, NumberNaNf64),
stdConstBinding(public::“NEGATIVE_INFINITY”, Numberf64),
stdConstBinding(public::“POSITIVE_INFINITY”, Number+f64)},
instanceProperties: {}, superGeneralNumber, prototypeNumberPrototype, completetrue, name: “Number”, typeofString: “number”, dynamicfalse, finaltrue, defaultValueNaNf64, hasPropertyordinaryHasProperty, bracketReadordinaryBracketRead, bracketWriteordinaryBracketWrite, bracketDeleteordinaryBracketDelete, readordinaryRead, writeordinaryWrite, deleteordinaryDelete, enumerateordinaryEnumerate, callsameAsConstruct, constructconstructNumber, initnone, isordinaryIs, coercecoerceNumber;
proc constructNumber(cClassargsObject[], phasePhase): Float64
note  This function can be used in a constant expression if the argument can be converted to a primitive in a constant expression.
if |args| = 0 then return +zerof64
elsif |args| = 1 then return objectToFloat64(args[0], phase)
else throw an ArgumentError exception — at most one argument can be supplied
end if
end proc;
proc coerceNumber(oObjectcClass): Float64  {none}
if o  GeneralNumber then return toFloat64(oelse return none end if
end proc;
NumberPrototypeSimpleInstancenew SimpleInstancelocalBindings: {
stdConstBinding(public::“constructor”, ClassNumber),
stdReserve(public::“toString”, GeneralNumberPrototype),
stdReserve(public::“valueOf”, GeneralNumberPrototype)},
archetypeGeneralNumberPrototype, sealedprototypesSealed, typeObject, slots: {}, callnone, constructnone, envnone;
proc makeBuiltInIntegerClass(nameStringlowIntegerhighInteger): Class
proc construct(cClassargsObject[], phasePhase): Float64
note  This function can be used in a constant expression if the argument can be converted to a primitive in a constant expression.
if |args| > 1 then
throw an ArgumentError exception — at most one argument can be supplied
end if;
argObject  defaultArg(args, 0, +zerof64);
xFloat64  objectToFloat64(argphase);
iIntegerOpt  checkInteger(x);
if i  none and low  i  high then
note  –zerof64 is coerced to +zerof64.
return if64
end if;
throw a RangeError exception
end proc;
proc is(oObjectcClass): Boolean
if o  Float64 then return false end if;
iIntegerOpt  checkInteger(o);
return i  none and low  i  high
end proc;
proc coerce(oObjectcClass): Float64  {none}
if o  GeneralNumber then return none end if;
iIntegerOpt  checkInteger(o);
if i  none and low  i  high then
note  –zerof32, +zerof32, and –zerof64 are all coerced to +zerof64.
return if64
end if;
throw a RangeError exception
end proc;
return new ClasslocalBindings: {
stdConstBinding(public::“MAX_VALUE”, Numberhighf64),
stdConstBinding(public::“MIN_VALUE”, Numberlowf64)},
instanceProperties: {}, superNumber, prototypeNumber.prototype, completetrue, namename, typeofString: “number”, dynamicfalse, finaltrue, defaultValue+zerof64, hasPropertyNumber.hasProperty, bracketReadNumber.bracketRead, bracketWriteNumber.bracketWrite, bracketDeleteNumber.bracketDelete, readNumber.read, writeNumber.write, deleteNumber.delete, enumerateNumber.enumerate, callsameAsConstruct, constructconstruct, initnone, isis, coercecoerce
end proc;
sbyteClass = makeBuiltInIntegerClass(“sbyte”, –128, 127);
byteClass = makeBuiltInIntegerClass(“byte”, 0, 255);
shortClass = makeBuiltInIntegerClass(“short”, –32768, 32767);
ushortClass = makeBuiltInIntegerClass(“ushort”, 0, 65535);
intClass = makeBuiltInIntegerClass(“int”, –2147483648, 2147483647);
uintClass = makeBuiltInIntegerClass(“uint”, 0, 4294967295);

char

charClassnew ClasslocalBindings: {stdFunction(public::“fromCharCode”, char_fromCharCode, 1)}, instanceProperties: {}, superObject, prototypecharPrototype, completetrue, name: “char”, typeofString: “char”, dynamicfalse, finaltrue, defaultValue: ‘«NUL»’, hasPropertyordinaryHasProperty, bracketReadordinaryBracketRead, bracketWriteordinaryBracketWrite, bracketDeleteordinaryBracketDelete, readordinaryRead, writeordinaryWrite, deleteordinaryDelete, enumerateordinaryEnumerate, callsameAsConstruct, constructconstructChar, initnone, isordinaryIs, coercecoerceChar;
proc callChar(thisObjectcClassargsObject[], phasePhase): Char16
note  This function can be used in a constant expression if the argument can be converted to a primitive in a constant expression.
if |args 1 then
throw an ArgumentError exception — exactly one argument must be supplied
end if;
sString  objectToString(args[0], phase);
if |s 1 then throw a RangeError exception — only one character may be given end if;
return s[0]
end proc;
proc constructChar(cClassargsObject[], phasePhase): Char16
note  This function can be used in a constant expression if the argument can be converted to a primitive in a constant expression.
if |args| > 1 then
throw an ArgumentError exception — at most one argument can be supplied
end if;
argObject  defaultArg(args, 0, undefined);
if arg = undefined then return ‘«NUL»
elsif arg  Char16 then return arg
else
sString  objectToString(args[0], phase);
if |s 1 then throw a RangeError exception — only one character may be given
end if;
return s[0]
end if
end proc;
proc coerceChar(oObjectcClass): Char16  {none}
if o  Char16 then return o else return none end if
end proc;
proc char_fromCharCode(thisObjectfSimpleInstanceargsObject[], phasePhase): Object
note  This function can be used in a constant expression if the argument can be converted to a primitive in a constant expression.
if |args 1 then
throw an ArgumentError exception — exactly one argument must be supplied
end if;
iInteger  objectToInteger(args[0], phase);
if 0  i  0xFFFF then return integerToChar16(i)
else throw a RangeError exception — character code out of range
end if
end proc;
charPrototypeSimpleInstancenew SimpleInstancelocalBindings: {
stdConstBinding(public::“constructor”, Classchar),
stdReserve(public::“toString”, StringPrototype),
stdReserve(public::“valueOf”, StringPrototype)},
archetypeStringPrototype, sealedprototypesSealed, typeObject, slots: {}, callnone, constructnone, envnone;

String

StringClassnew ClasslocalBindings: {stdFunction(public::“fromCharCode”, String_fromCharCode, 1)}, instanceProperties: {
new InstanceGettermultiname: {public::“length”}, finaltrue, enumerablefalse, callString_length},
superObject, prototypeStringPrototype, completetrue, name: “String”, typeofString: “string”, dynamicfalse, finaltrue, defaultValuenull, hasPropertystringHasProperty, bracketReadordinaryBracketRead, bracketWriteordinaryBracketWrite, bracketDeleteordinaryBracketDelete, readreadString, writeordinaryWrite, deleteordinaryDelete, enumerateordinaryEnumerate, callsameAsConstruct, constructconstructString, initnone, isordinaryIs, coercecoerceString;
proc stringHasProperty(oObjectcClasspropertyObjectflatBooleanphasePhase): Boolean
note  o  String because stringHasProperty is only called on instances of class String.
qnameQualifiedName  objectToQualifiedName(propertyphase);
iIntegerOpt  multinameToUnsignedInteger({qname});
if i  none then return i < |o|
else
return findBaseInstanceProperty(c, {qname}, read none or findBaseInstanceProperty(c, {qname}, write none or findArchetypeProperty(o, {qname}, readflat none or findArchetypeProperty(o, {qname}, writeflat none
end if
end proc;
proc readString(oObject, limitClass, multinameMultiname, envEnvironmentOpt, undefinedIfMissingBoolean, phasePhase): ObjectOpt
note  o  String because readString is only called on instances of class String.
if limit = String then
iIntegerOpt  multinameToUnsignedInteger(multiname);
if i  none then
if i < |othen return o[i]
elsif undefinedIfMissing then return undefined
else return none
end if
end if
end if;
return ordinaryRead(olimitmultinameenvundefinedIfMissingphase)
end proc;
proc constructString(cClassargsObject[], phasePhase): String
note  This function can be used in a constant expression if the argument can be converted to a primitive in a constant expression.
if |args| = 0 then return “”
elsif |args| = 1 then return objectToString(args[0], phase)
else throw an ArgumentError exception — at most one argument can be supplied
end if
end proc;
proc coerceString(oObjectcClass): String  Null  {none}
if o  Null  String then return o
elsif o  Char16 then return [o]
else return none
end if
end proc;
proc String_length(thisObjectphasePhase): Object
note  this  String because this getter cannot be extracted from the String class.
lengthInteger  |this|;
return lengthf64
end proc;
proc String_fromCharCode(thisObjectfSimpleInstanceargsObject[], phasePhase): Object
note  This function can be used in a constant expression if the arguments can be converted to primitives in constant expressions.
sString  “”;
for each arg  args do
iInteger  objectToInteger(argphase);
if 0  i  0x10FFFF then s  s  integerToUTF16(i)
else throw a RangeError exception — character code out of range
end if
end for each;
return s
end proc;
StringPrototypeSimpleInstancenew SimpleInstancelocalBindings: {
stdConstBinding(public::“constructor”, ClassString),
stdFunction(public::“toString”, String_toString, 0),
stdReserve(public::“valueOf”, ObjectPrototype),
stdFunction(public::“charAt”, String_charAt, 1),
stdFunction(public::“charCodeAt”, String_charCodeAt, 1),
stdFunction(public::“concat”, String_concat, 1),
stdFunction(public::“indexOf”, String_indexOf, 1),
stdFunction(public::“lastIndexOf”, String_lastIndexOf, 1),
stdFunction(public::“localeCompare”, String_localeCompare, 1),
stdFunction(public::“match”, String_match, 1),
stdFunction(public::“replace”, String_replace, 1),
stdFunction(public::“search”, String_search, 1),
stdFunction(public::“slice”, String_slice, 2),
stdFunction(public::“split”, String_split, 2),
stdFunction(public::“substring”, String_substring, 2),
stdFunction(public::“toLowerCase”, String_toLowerCase, 0),
stdFunction(public::“toLocaleLowerCase”, String_toLocaleLowerCase, 0),
stdFunction(public::“toUpperCase”, String_toUpperCase, 0),
stdFunction(public::“toLocaleUpperCase”, String_toLocaleUpperCase, 0)},
archetypeObjectPrototype, sealedprototypesSealed, typeObject, slots: {}, callnone, constructnone, envnone;
proc String_toString(thisObjectfSimpleInstanceargsObject[], phasePhase): String
note  This function can be used in a constant expression if this can be converted to a primitive in a constant expression.
note  This function is generic and can be applied even if this is not a string.
note  This function ignores any arguments passed to it in args.
return objectToString(thisphase)
end proc;
proc String_charAt(thisObjectfSimpleInstanceargsObject[], phasePhase): String
note  This function can be used in a constant expression if this and the argument can be converted to primitives in constant expressions.
note  This function is generic and can be applied even if this is not a string.
if |args| > 1 then
throw an ArgumentError exception — at most one argument can be supplied
end if;
sString  objectToString(thisphase);
positionExtendedInteger  objectToExtendedInteger(defaultArg(args, 0, +zerof64), phase);
if position = NaN then throw a RangeError exception
elsif position  {+and 0  position < |sthen return [s[position]]
else return “”
end if
end proc;
proc String_charCodeAt(thisObjectfSimpleInstanceargsObject[], phasePhase): Float64
note  This function can be used in a constant expression if this and the argument can be converted to primitives in constant expressions.
note  This function is generic and can be applied even if this is not a string.
if |args| > 1 then
throw an ArgumentError exception — at most one argument can be supplied
end if;
sString  objectToString(thisphase);
positionExtendedInteger  objectToExtendedInteger(defaultArg(args, 0, +zerof64), phase);
if position = NaN then throw a RangeError exception
elsif position  {+and 0  position < |sthen
return (char16ToInteger(s[position]))f64
else return NaNf64
end if
end proc;
proc String_concat(thisObjectfSimpleInstanceargsObject[], phasePhase): String
note  This function can be used in a constant expression if this and the argument can be converted to primitives in constant expressions.
note  This function is generic and can be applied even if this is not a string.
sString  objectToString(thisphase);
for each arg  args do s  s  objectToString(argphaseend for each;
return s
end proc;
proc String_indexOf(thisObjectfSimpleInstanceargsObject[], phasePhase): Float64
note  This function can be used in a constant expression if this and the arguments can be converted to primitives in constant expressions.
note  This function is generic and can be applied even if this is not a string.
if |args {1, 2} then
throw an ArgumentError exception — at least one and at most two arguments must be supplied
end if;
sString  objectToString(thisphase);
patternString  objectToString(args[0], phase);
argObject  defaultArg(args, 1, +zerof64);
positionInteger  pinExtendedInteger(objectToExtendedInteger(argphase), |s|, false);
while position + |pattern |sdo
if s[position ... position + |pattern| – 1] = pattern then return positionf64
end if;
position  position + 1
end while;
return (–1)f64
end proc;
proc String_lastIndexOf(thisObjectfSimpleInstanceargsObject[], phasePhase): Float64
note  This function can be used in a constant expression if this and the arguments can be converted to primitives in constant expressions.
note  This function is generic and can be applied even if this is not a string.
if |args {1, 2} then
throw an ArgumentError exception — at least one and at most two arguments must be supplied
end if;
sString  objectToString(thisphase);
patternString  objectToString(args[0], phase);
argObject  defaultArg(args, 1, +f64);
positionInteger  pinExtendedInteger(objectToExtendedInteger(argphase), |s|, false);
if position + |pattern| > |sthen position  |s| – |patternend if;
while position  0 do
if s[position ... position + |pattern| – 1] = pattern then return positionf64
end if;
position  position – 1
end while;
return (–1)f64
end proc;
proc String_localeCompare(thisObjectfSimpleInstanceargsObject[], phasePhase): Float64
note  This function is generic and can be applied even if this is not a string.
if phase = compile then
throw a ConstantError exception — localeCompare cannot be called from a constant expression
end if;
if |args| < 1 then
throw an ArgumentError exception — at least one argument must be supplied
end if;
s1String  objectToString(thisphase);
s2String  objectToString(args[0], phase);
Let resultObject be a value of type Number that is the result of a locale-sensitive string comparison of s1 and s2. The two strings are compared in an implementation-defined fashion. The result is intended to order strings in the sort order specified by the system default locale, and will be negative, zero, or positive, depending on whether s1 comes before s2 in the sort order, they are equal, or s1 comes after s2 in the sort order, respectively. The result shall not be NaNf64. The comparison shall be a consistent comparison function on the set of all strings.
return result
end proc;
proc String_match(thisObjectfSimpleInstanceargsObject[], phasePhase): Object
note  This function is generic and can be applied even if this is not a string.
if phase = compile then
throw a ConstantError exception — match cannot be called from a constant expression
end if;
if |args 1 then
throw an ArgumentError exception — exactly one argument must be supplied
end if;
sString  objectToString(thisphase);
Evaluate ???? and ignore its result
end proc;
proc String_replace(thisObjectfSimpleInstanceargsObject[], phasePhase): Object
note  This function is generic and can be applied even if this is not a string.
if phase = compile then
throw a ConstantError exception — replace cannot be called from a constant expression
end if;
if |args 2 then
throw an ArgumentError exception — exactly two arguments must be supplied
end if;
sString  objectToString(thisphase);
Evaluate ???? and ignore its result
end proc;
proc String_search(thisObjectfSimpleInstanceargsObject[], phasePhase): Object
note  This function is generic and can be applied even if this is not a string.
if phase = compile then
throw a ConstantError exception — search cannot be called from a constant expression
end if;
if |args 1 then
throw an ArgumentError exception — exactly one argument must be supplied
end if;
sString  objectToString(thisphase);
Evaluate ???? and ignore its result
end proc;
proc String_slice(thisObjectfSimpleInstanceargsObject[], phasePhase): String
note  This function can be used in a constant expression if this and the arguments can be converted to primitives in constant expressions.
note  This function is generic and can be applied even if this is not a string.
if |args| > 2 then
throw an ArgumentError exception — at most two arguments can be supplied
end if;
sString  objectToString(thisphase);
startArgObject  defaultArg(args, 0, +zerof64);
endArgObject  defaultArg(args, 1, +f64);
startInteger  pinExtendedInteger(objectToExtendedInteger(startArgphase), |s|, true);
endInteger  pinExtendedInteger(objectToExtendedInteger(endArgphase), |s|, true);
if start < end then return s[start ... end – 1] else return “” end if
end proc;
proc String_split(thisObjectfSimpleInstanceargsObject[], phasePhase): Object
note  This function is generic and can be applied even if this is not a string.
if phase = compile then
throw a ConstantError exception — split cannot be called from a constant expression
end if;
if |args| > 2 then
throw an ArgumentError exception — at most two arguments can be supplied
end if;
sString  objectToString(thisphase);
Evaluate ???? and ignore its result
end proc;
proc String_substring(thisObjectfSimpleInstanceargsObject[], phasePhase): String
note  This function can be used in a constant expression if this and the arguments can be converted to primitives in constant expressions.
note  This function is generic and can be applied even if this is not a string.
if |args| > 2 then
throw an ArgumentError exception — at most two arguments can be supplied
end if;
sString  objectToString(thisphase);
startArgObject  defaultArg(args, 0, +zerof64);
endArgObject  defaultArg(args, 1, +f64);
startInteger  pinExtendedInteger(objectToExtendedInteger(startArgphase), |s|, false);
endInteger  pinExtendedInteger(objectToExtendedInteger(endArgphase), |s|, false);
if start  end then return s[start ... end – 1]
else return s[end ... start – 1]
end if
end proc;
proc String_toLowerCase(thisObjectfSimpleInstanceargsObject[], phasePhase): String
note  This function can be used in a constant expression if this can be converted to a primitive in a constant expression.
note  This function is generic and can be applied even if this is not a string.
sString  objectToString(thisphase);
s32Char21[]  stringToUTF32(s);
rString  “”;
for each ch  s32 do r  r  charToLowerFull(chend for each;
return r
end proc;
proc String_toLocaleLowerCase(thisObject, fSimpleInstance, argsObject[], phasePhase): String
note  This function is generic and can be applied even if this is not a string.
if phase = compile then
throw a ConstantError exception — toLocaleLowerCase cannot be called from a constant expression
end if;
sString  objectToString(thisphase);
s32Char21[]  stringToUTF32(s);
rString  “”;
for each ch  s32 do r  r  charToLowerLocalized(chend for each;
return r
end proc;
proc String_toUpperCase(thisObjectfSimpleInstanceargsObject[], phasePhase): String
note  This function can be used in a constant expression if this can be converted to a primitive in a constant expression.
note  This function is generic and can be applied even if this is not a string.
sString  objectToString(thisphase);
s32Char21[]  stringToUTF32(s);
rString  “”;
for each ch  s32 do r  r  charToUpperFull(chend for each;
return r
end proc;
proc String_toLocaleUpperCase(thisObject, fSimpleInstance, argsObject[], phasePhase): String
note  This function is generic and can be applied even if this is not a string.
if phase = compile then
throw a ConstantError exception — toLocaleUpperCase cannot be called from a constant expression
end if;
sString  objectToString(thisphase);
s32Char21[]  stringToUTF32(s);
rString  “”;
for each ch  s32 do r  r  charToUpperLocalized(chend for each;
return r
end proc;

Array

ArrayClassnew ClasslocalBindings: {}, instanceProperties: {
new InstanceVariablemultiname: {arrayPrivate::“length”}, finaltrue, enumerablefalse, typeNumber, defaultValue+zerof64, immutablefalse,
new InstanceGettermultiname: {public::“length”}, finaltrue, enumerablefalse, callArray_getLength,
new InstanceSettermultiname: {public::“length”}, finaltrue, enumerablefalse, callArray_setLength},
superObject, prototypeArrayPrototype, completetrue, name: “Array”, typeofString: “object”, privateNamespacearrayPrivate, dynamictrue, finaltrue, defaultValuenull, defaultHinthintNumber, hasPropertyordinaryHasProperty, bracketReadordinaryBracketRead, bracketWriteordinaryBracketWrite, bracketDeleteordinaryBracketDelete, readordinaryRead, writewriteArray, deleteordinaryDelete, enumerateordinaryEnumerate, callsameAsConstruct, constructordinaryConstruct, initinitArray, isordinaryIs, coerceordinaryCoerce;
arrayLimitInteger = an implementation-defined integer value between 232 – 1 and 253 inclusive;
arrayPrivateNamespace = new Namespacename: “private;
proc writeArray(oObject, limitClass, multinameMultiname, envEnvironmentOpt, newValueObject, createIfMissingBoolean, phase: {run}): {noneok}
result: {noneok ordinaryWrite(olimitmultinameenvnewValuecreateIfMissingphase);
if result = ok then
iIntegerOpt  multinameToUnsignedInteger(multiname);
if i  none then
if i  arrayLimit then
throw a RangeError exception — array index out of range
end if;
lengthInteger  readArrayPrivateLength(ophase);
if i  length then
length  i + 1;
Evaluate writeArrayPrivateLength(olengthphase) and ignore its result
end if
end if
end if;
return result
end proc;
readArrayPrivateLength(arrayphase) returns an Array’s private length. See also readLength, which can work on non-Array objects.
proc readArrayPrivateLength(arrayObjectphasePhase): Integer
lengthFloat64  readInstanceSlot(arrayarrayPrivate::“length”, phase);
note  length  {NaNf64+f64f64};
nRational  toRational(length);
note  n  Integer and 0  n  arrayLimit;
return n
end proc;
writeArrayPrivateLength(arraylengthphase) sets an Array’s private length to length after ensuring that length is between 0 and arrayLimit inclusive. See also writeLength, which can work on non-Array objects.
proc writeArrayPrivateLength(arrayObjectlengthIntegerphase: {run})
if length < 0 or length > arrayLimit then
throw a RangeError exception — array length out of range
end if;
Evaluate dotWrite(array, {arrayPrivate::“length”}, lengthf64phase) and ignore its result
end proc;
proc multinameToUnsignedInteger(multinameMultiname): IntegerOpt
if |multiname 1 then return none end if;
qnameQualifiedName  the one element of multiname;
if qname.namespace  public then return none end if;
nameString  qname.id;
if name  [] then
if name = “0” then return 0
elsif name[0]  ‘0’ and (every ch  name satisfies ch  {‘0’ ... ‘9’}) then
end if
end if;
return none
end proc;
proc initArray(thisSimpleInstanceargsObject[], phase: {run})
if |args| = 1 then
argObject  args[0];
if arg  GeneralNumber then
lengthIntegerOpt  checkInteger(arg);
if length = none then
throw a RangeError exception — array length must be an integer
end if;
Evaluate writeArrayPrivateLength(thislengthphase) and ignore its result;
return
end if
end if;
iInteger  0;
for each arg  args do
Evaluate indexWrite(thisiargphase) and ignore its result;
i  i + 1
end for each;
note  The call to indexWrite above also set the array’s length to i.
end proc;
proc Array_getLength(thisObjectphasePhase): Float64
note  is(thisArray) because this getter cannot be extracted from the Array class.
note  An array’s length is mutable, so reading it will throw ConstantError when phase = compile.
return readInstanceSlot(thisarrayPrivate::“length”, phase)
end proc;
proc Array_setLength(thisObjectlengthObjectphasePhase)
note  is(thisArray) because this setter cannot be extracted from the Array class.
if phase = compile then
throw a ConstantError exception — an array’s length cannot be set from a constant expression
end if;
newLengthIntegerOpt  checkInteger(objectToGeneralNumber(lengthphase));
if newLength = none or newLength < 0 or newLength > arrayLimit then
throw a RangeError exception — array length out of range or not an integer
end if;
oldLengthInteger  readArrayPrivateLength(thisphase);
if newLength < oldLength then
note  Delete all indexed properties greater than or equal to the new length
proc qnameInDeletedRange(qnameQualifiedName): Boolean
iIntegerOpt  multinameToUnsignedInteger({qname});
return i  none and newLength  i < oldLength
end proc;
this.localBindings  {b | b  this.localBindings such that not qnameInDeletedRange(b.qname)}
end if;
Evaluate writeArrayPrivateLength(thisnewLengthphase) and ignore its result
end proc;
ArrayPrototypeSimpleInstancenew SimpleInstancelocalBindings: {
stdConstBinding(public::“constructor”, ClassArray),
stdFunction(public::“toString”, Array_toString, 0),
stdFunction(public::“toLocaleString”, Array_toLocaleString, 0),
stdFunction(public::“concat”, Array_concat, 1),
stdFunction(public::“join”, Array_join, 1),
stdFunction(public::“pop”, Array_pop, 0),
stdFunction(public::“push”, Array_push, 1),
stdFunction(public::“reverse”, Array_reverse, 0),
stdFunction(public::“shift”, Array_shift, 0),
stdFunction(public::“slice”, Array_slice, 2),
stdFunction(public::“sort”, Array_sort, 1),
stdFunction(public::“splice”, Array_splice, 2),
stdFunction(public::“unshift”, Array_unshift, 1)},
archetypeObjectPrototype, sealedprototypesSealed, typeObject, slots: {}, callnone, constructnone, envnone;
proc Array_toString(thisObjectfSimpleInstanceargsObject[], phasePhase): String
if phase = compile then
throw a ConstantError exception — toString cannot be called on an Array from a constant expression
end if;
note  This function is generic and can be applied even if this is not an Array.
note  This function ignores any arguments passed to it in args.
return internalJoin(this, “,”, phase)
end proc;
proc Array_toLocaleString(thisObjectfSimpleInstanceargsObject[], phasePhase): String
if phase = compile then
throw a ConstantError exception — toLocaleString cannot be called on an Array from a constant expression
end if;
note  This function is generic and can be applied even if this is not an Array.
note  This function passes any arguments passed to it in args to toLocaleString applied to the elements of the array.
separatorString  the list-separator string appropriate for the host’s current locale, derived in an implementation-defined way;
lengthInteger  readLength(thisphase);
resultString  “”;
iInteger  0;
while i  length do
eltObjectOpt  indexRead(thisiphase);
if elt  {undefinednullnonethen
toLocaleStringMethodObject  dotRead(elt, {public::“toLocaleString”}, phase);
sObject  call(elttoLocaleStringMethodargsphase);
if s  Char16  String then
throw a TypeError exception — toLocaleString should return a string
end if;
result  result  toString(s)
end if;
i  i + 1;
if i  length then result  result  separator end if
end while;
return result
end proc;
proc Array_concat(thisObjectfSimpleInstanceargsObject[], phasePhase): Object
if phase = compile then
throw a ConstantError exception — concat cannot be called from a constant expression
end if;
note  This function is generic and can be applied even if this is not an Array.
constituentsObject[]  [this]  args;
arrayObject  construct(Array[]phase);
iInteger  0;
for each o  constituents do
if is(oArraythen
oLengthInteger  readLength(ophase);
kInteger  0;
while k  oLength do
eltObjectOpt  indexRead(okphase);
if elt  none then
Evaluate indexWrite(arrayieltphase) and ignore its result
end if;
k  k + 1;
i  i + 1
end while
else Evaluate indexWrite(arrayiophase) and ignore its result; i  i + 1
end if
end for each;
Evaluate writeArrayPrivateLength(arrayiphase) and ignore its result;
return array
end proc;
proc Array_join(thisObjectfSimpleInstanceargsObject[], phasePhase): String
if phase = compile then
throw a ConstantError exception — join cannot be called from a constant expression
end if;
note  This function is generic and can be applied even if this is not an Array.
if |args| > 1 then
throw an ArgumentError exception — at most one argument can be supplied
end if;
argObject  defaultArg(args, 0, undefined);
separatorString  “,”;
if arg  undefined then separator  objectToString(argphaseend if;
return internalJoin(thisseparatorphase)
end proc;
proc internalJoin(thisObjectseparatorStringphase: {run}): String
lengthInteger  readLength(thisphase);
resultString  “”;
iInteger  0;
while i  length do
eltObjectOpt  indexRead(thisiphase);
if elt  {undefinednullnonethen
result  result  objectToString(eltphase)
end if;
i  i + 1;
if i  length then result  result  separator end if
end while;
return result
end proc;
proc Array_pop(thisObjectfSimpleInstanceargsObject[], phasePhase): Object
if phase = compile then
throw a ConstantError exception — pop cannot be called from a constant expression
end if;
note  This function is generic and can be applied even if this is not an Array.
if |args 0 then throw an ArgumentError exception — no arguments can be supplied
end if;
lengthInteger  readLength(thisphase);
resultObject  undefined;
if length  0 then
length  length – 1;
eltObjectOpt  indexRead(thislengthphase);
if elt  none then
result  elt;
Evaluate indexWrite(thislengthnonephase) and ignore its result
end if
end if;
Evaluate writeLength(thislengthphase) and ignore its result;
return result
end proc;
proc Array_push(thisObjectfSimpleInstanceargsObject[], phasePhase): Object
if phase = compile then
throw a ConstantError exception — push cannot be called from a constant expression
end if;
note  This function is generic and can be applied even if this is not an Array.
lengthInteger  readLength(thisphase);
for each arg  args do
Evaluate indexWrite(thislengthargphase) and ignore its result;
length  length + 1
end for each;
Evaluate writeLength(thislengthphase) and ignore its result;
return lengthf64
end proc;
proc Array_reverse(thisObjectfSimpleInstanceargsObject[], phasePhase): Object
if phase = compile then
throw a ConstantError exception — reverse cannot be called from a constant expression
end if;
note  This function is generic and can be applied even if this is not an Array.
if |args 0 then throw an ArgumentError exception — no arguments can be supplied
end if;
lengthInteger  readLength(thisphase);
loInteger  0;
hiInteger  length – 1;
while lo < hi do
loEltObjectOpt  indexRead(thislophase);
hiEltObjectOpt  indexRead(thishiphase);
Evaluate indexWrite(thislohiEltphase) and ignore its result;
Evaluate indexWrite(thishiloEltphase) and ignore its result;
lo  lo + 1;
hi  hi – 1
end while;
return this
end proc;
proc Array_shift(thisObjectfSimpleInstanceargsObject[], phasePhase): Object
if phase = compile then
throw a ConstantError exception — shift cannot be called from a constant expression
end if;
note  This function is generic and can be applied even if this is not an Array.
if |args 0 then throw an ArgumentError exception — no arguments can be supplied
end if;
lengthInteger  readLength(thisphase);
resultObject  undefined;
if length  0 then
eltObjectOpt  indexRead(this, 0, phase);
if elt  none then result  elt end if;
iInteger  1;
while i  length do
elt  indexRead(thisiphase);
Evaluate indexWrite(thisi – 1, eltphase) and ignore its result;
i  i + 1
end while;
length  length – 1;
Evaluate indexWrite(thislengthnonephase) and ignore its result
end if;
Evaluate writeLength(thislengthphase) and ignore its result;
return result
end proc;
proc Array_slice(thisObjectfSimpleInstanceargsObject[], phasePhase): Object
if phase = compile then
throw a ConstantError exception — slice cannot be called on an Array from a constant expression
end if;
note  This function is generic and can be applied even if this is not an Array.
if |args| > 2 then
throw an ArgumentError exception — at most two arguments can be supplied
end if;
lengthInteger  readLength(thisphase);
startArgObject  defaultArg(args, 0, +zerof64);
endArgObject  defaultArg(args, 1, +f64);
startInteger  pinExtendedInteger(objectToExtendedInteger(startArgphase), lengthtrue);
endInteger  pinExtendedInteger(objectToExtendedInteger(endArgphase), lengthtrue);
return makeArraySlice(thisstartendphase)
end proc;
proc makeArraySlice(arrayObjectstartIntegerendIntegerphase: {run}): Object
sliceObject  construct(Array[]phase);
iInteger  start;
jInteger  0;
while i < end do
eltObjectOpt  indexRead(arrayiphase);
Evaluate indexWrite(slicejeltphase) and ignore its result;
i  i + 1;
j  j + 1
end while;
Evaluate writeLength(slicejphase) and ignore its result;
return slice
end proc;
proc Array_sort(thisObjectfSimpleInstanceargsObject[], phasePhase): Object
if phase = compile then
throw a ConstantError exception — sort cannot be called from a constant expression
end if;
note  This function is generic and can be applied even if this is not an Array.
if |args| > 1 then
throw an ArgumentError exception — at most one argument can be supplied
end if;
Evaluate ???? and ignore its result
end proc;
proc Array_splice(thisObjectfSimpleInstanceargsObject[], phasePhase): Object
if phase = compile then
throw a ConstantError exception — splice cannot be called from a constant expression
end if;
note  This function is generic and can be applied even if this is not an Array.
if |args| < 2 then
throw an ArgumentError exception — at least two arguments must be supplied
end if;
lengthInteger  readLength(thisphase);
startArgObject  defaultArg(args, 0, +zerof64);
deleteCountArgObject  defaultArg(args, 1, +zerof64);
startInteger  pinExtendedInteger(objectToExtendedInteger(startArgphase), lengthtrue);
deleteCountInteger  pinExtendedInteger(objectToExtendedInteger(deleteCountArgphase), length – start, false);
deletedSliceObject  makeArraySlice(thisstartstart + deleteCountphase);
newEltsObject[]  args[2 ...];
newEltCountInteger  |newElts|;
countDiffInteger  newEltCount – deleteCount;
iInteger;
if countDiff < 0 then
i  start + deleteCount;
while i  length do
eltObjectOpt  indexRead(thisiphase);
Evaluate indexWrite(thisi + countDiffeltphase) and ignore its result;
i  i + 1
end while;
i  0;
while i  countDiff do
i  i – 1;
Evaluate indexWrite(thislength + inonephase) and ignore its result
end while
elsif countDiff > 0 then
i  length;
while i  start + deleteCount do
i  i – 1;
eltObjectOpt  indexRead(thisiphase);
Evaluate indexWrite(thisi + countDiffeltphase) and ignore its result
end while
end if;
Evaluate writeLength(thislength + countDiffphase) and ignore its result;
i  start;
for each arg  newElts do
Evaluate indexWrite(thisiargphase) and ignore its result;
i  i + 1
end for each;
return deletedSlice
end proc;
proc Array_unshift(thisObjectfSimpleInstanceargsObject[], phasePhase): Float64
if phase = compile then
throw a ConstantError exception — unshift cannot be called from a constant expression
end if;
note  This function is generic and can be applied even if this is not an Array.
iInteger  readLength(thisphase);
nArgsInteger  |args|;
newLengthInteger  nArgs + i;
if nArgs = 0 then
At the implementation’s discretion, either do nothing or return newLengthf64
end if;
Evaluate writeLength(thisnewLengthphase) and ignore its result;
while i  0 do
i  i – 1;
eltObjectOpt  indexRead(thisiphase);
Evaluate indexWrite(thisi + nArgseltphase) and ignore its result
end while;
for each arg  args do
Evaluate indexWrite(thisiargphase) and ignore its result;
i  i + 1
end for each;
return newLengthf64
end proc;

Namespace

NamespaceClassnew ClasslocalBindings: {}, instanceProperties: {}, superObject, prototypeNamespacePrototype, completetrue, name: “Namespace”, typeofString: “namespace”, dynamicfalse, finaltrue, defaultValuenull, defaultHinthintString, hasPropertyordinaryHasProperty, bracketReadordinaryBracketRead, bracketWriteordinaryBracketWrite, bracketDeleteordinaryBracketDelete, readordinaryRead, writeordinaryWrite, deleteordinaryDelete, enumerateordinaryEnumerate, callordinaryCall, constructconstructNamespace, initnone, isordinaryIs, coerceordinaryCoerce;
proc constructNamespace(cClassargsObject[], phasePhase): Namespace
note  This function can be used in a constant expression if its argument is a string.
if |args| > 1 then
throw an ArgumentError exception — at most one argument can be supplied
end if;
argObject  defaultArg(args, 0, undefined);
if arg  Null  Undefined then
if phase = compile then
throw a ConstantError exception — a constant expression cannot construct new anonymous namespaces
end if;
return new Namespacename: “anonymous
elsif arg  Char16  String then
nameString  toString(arg);
if name = “” then return public
elsif some ns  namedNamespaces satisfies ns.name = name then return ns
else
ns2Namespace  new Namespacenamename;
namedNamespaces  namedNamespaces  {ns2};
return ns2
end if
else throw a TypeError exception
end if
end proc;
namedNamespacesNamespace{}  {};
NamespacePrototypeSimpleInstancenew SimpleInstancelocalBindings: {
stdFunction(public::“toString”, Namespace_toString, 0),
stdReserve(public::“valueOf”, ObjectPrototype)},
archetypeObjectPrototype, sealedprototypesSealed, typeObject, slots: {}, callnone, constructnone, envnone;
proc Namespace_toString(thisObjectfSimpleInstanceargsObject[], phasePhase): String
note  This function does not check phase and therefore can be used in a constant expression.
note  This function ignores any arguments passed to it in args.
if this  Namespace then throw a TypeError exception end if;
return this.name
end proc;

Attribute

AttributeClassnew ClasslocalBindings: {}, instanceProperties: {}, superObject, prototypeObjectPrototype, completetrue, name: “Attribute”, typeofString: “object”, dynamicfalse, finaltrue, defaultValuenull, defaultHinthintString, hasPropertyordinaryHasProperty, bracketReadordinaryBracketRead, bracketWriteordinaryBracketWrite, bracketDeleteordinaryBracketDelete, readordinaryRead, writeordinaryWrite, deleteordinaryDelete, enumerateordinaryEnumerate, calldummyCall, constructdummyConstruct, initnone, isordinaryIs, coerceordinaryCoerce;

Date

DateClassnew ClasslocalBindings: {}, instanceProperties: {}, superObject, prototypeDatePrototype, completetrue, name: “Date”, typeofString: “object”, dynamictrue, finaltrue, defaultValuenull, defaultHinthintString, hasPropertyordinaryHasProperty, bracketReadordinaryBracketRead, bracketWriteordinaryBracketWrite, bracketDeleteordinaryBracketDelete, readordinaryRead, writeordinaryWrite, deleteordinaryDelete, enumerateordinaryEnumerate, calldummyCall, constructdummyConstruct, initnone, isordinaryIs, coerceordinaryCoerce;
DatePrototypeSimpleInstancenew SimpleInstancelocalBindings: {}, archetypeObjectPrototype, sealedprototypesSealed, typeObject, slots: {}, callnone, constructnone, envnone;

RegExp

RegExpClassnew ClasslocalBindings: {}, instanceProperties: {}, superObject, prototypeRegExpPrototype, completetrue, name: “RegExp”, typeofString: “object”, dynamictrue, finaltrue, defaultValuenull, defaultHinthintNumber, hasPropertyordinaryHasProperty, bracketReadordinaryBracketRead, bracketWriteordinaryBracketWrite, bracketDeleteordinaryBracketDelete, readordinaryRead, writeordinaryWrite, deleteordinaryDelete, enumerateordinaryEnumerate, calldummyCall, constructdummyConstruct, initnone, isordinaryIs, coerceordinaryCoerce;
RegExpPrototypeSimpleInstancenew SimpleInstancelocalBindings: {}, archetypeObjectPrototype, sealedprototypesSealed, typeObject, slots: {}, callnone, constructnone, envnone;

Class

ClassClassnew ClasslocalBindings: {}, instanceProperties: {classPrototypeGetter}, superObject, prototypeClassPrototype, completetrue, name: “Class”, typeofString: “function”, dynamicfalse, finaltrue, defaultValuenull, defaultHinthintString, hasPropertyordinaryHasProperty, bracketReadordinaryBracketRead, bracketWriteordinaryBracketWrite, bracketDeleteordinaryBracketDelete, readordinaryRead, writeordinaryWrite, deleteordinaryDelete, enumerateordinaryEnumerate, calldummyCall, constructdummyConstruct, initnone, isordinaryIs, coerceordinaryCoerce;
classPrototypeGetterInstanceGetternew InstanceGettermultiname: {public::“prototype”}, finaltrue, enumerablefalse, callClass_prototype;
proc Class_prototype(thisObjectphasePhase): Object
note  this  Class because this getter cannot be extracted from the Class class.
prototypeObjectOpt  this.prototype;
if prototype = none then return undefined else return prototype end if
end proc;
ClassPrototypeSimpleInstancenew SimpleInstancelocalBindings: {
stdConstBinding(public::“constructor”, ClassClass),
stdFunction(public::“toString”, Class_toString, 0),
stdReserve(public::“valueOf”, ObjectPrototype),
stdConstBinding(public::“length”, Number, 1f64)},
archetypeObjectPrototype, sealedprototypesSealed, typeObject, slots: {}, callnone, constructnone, envnone;
proc Class_toString(thisObjectfSimpleInstanceargsObject[], phasePhase): String
note  This function does not check phase and therefore can be used in a constant expression.
note  This function ignores any arguments passed to it in args.
cClass  objectToClass(this);
return “[class ”  c.name  “]
end proc;

Function

FunctionClassnew ClasslocalBindings: {}, instanceProperties: {ivarFunctionLength}, superObject, prototypeFunctionPrototype, completetrue, name: “Function”, typeofString: “function”, dynamicfalse, finaltrue, defaultValuenull, defaultHinthintString, hasPropertyordinaryHasProperty, bracketReadordinaryBracketRead, bracketWriteordinaryBracketWrite, bracketDeleteordinaryBracketDelete, readordinaryRead, writeordinaryWrite, deleteordinaryDelete, enumerateordinaryEnumerate, calldummyCall, constructdummyConstruct, initnone, isordinaryIs, coerceordinaryCoerce;
ivarFunctionLengthInstanceVariablenew InstanceVariablemultiname: {public::“length”}, finaltrue, enumerablefalse, typeNumber, defaultValuenone, immutabletrue;
FunctionPrototypeSimpleInstancenew SimpleInstancelocalBindings: {}, archetypeObjectPrototype, sealedprototypesSealed, typeObject, slots: {}, callnone, constructnone, envnone;

PrototypeFunction

PrototypeFunctionClassnew ClasslocalBindings: {}, instanceProperties: {new InstanceVariablemultiname: {public::“prototype”}, finaltrue, enumerablefalse, typeObject, defaultValueundefined, immutablefalse}, superFunction, prototypeFunctionPrototype, completetrue, name: “Function”, typeofString: “function”, dynamictrue, finaltrue, defaultValuenull, defaultHinthintString, hasPropertyordinaryHasProperty, bracketReadordinaryBracketRead, bracketWriteordinaryBracketWrite, bracketDeleteordinaryBracketDelete, readordinaryRead, writeordinaryWrite, deleteordinaryDelete, enumerateordinaryEnumerate, calldummyCall, constructdummyConstruct, initnone, isordinaryIs, coerceordinaryCoerce;

Package

PackageClassnew ClasslocalBindings: {}, instanceProperties: {}, superObject, prototypeObjectPrototype, completetrue, name: “Package”, typeofString: “object”, dynamictrue, finaltrue, defaultValuenull, defaultHinthintString, hasPropertyordinaryHasProperty, bracketReadordinaryBracketRead, bracketWriteordinaryBracketWrite, bracketDeleteordinaryBracketDelete, readordinaryRead, writeordinaryWrite, deleteordinaryDelete, enumerateordinaryEnumerate, calldummyCall, constructdummyConstruct, initnone, isordinaryIs, coerceordinaryCoerce;

Error

ErrorClassnew ClasslocalBindings: {}, instanceProperties: {
new InstanceVariablemultiname: {public::“name”}, finalfalse, enumerabletrue, typeString, defaultValuenull, immutablefalse,
new InstanceVariablemultiname: {public::“message”}, finalfalse, enumerabletrue, typeString, defaultValuenull, immutablefalse},
superObject, prototypeErrorPrototype, completetrue, name: “Error”, typeofString: “object”, dynamictrue, finalfalse, defaultValuenull, defaultHinthintNumber, hasPropertyordinaryHasProperty, bracketReadordinaryBracketRead, bracketWriteordinaryBracketWrite, bracketDeleteordinaryBracketDelete, readordinaryRead, writeordinaryWrite, deleteordinaryDelete, enumerateordinaryEnumerate, callcallError, constructordinaryConstruct, initinitError, isordinaryIs, coerceordinaryCoerce;
proc callError(thisObjectcClassargsObject[], phasePhase): Object
if |args| > 1 then
throw an ArgumentError exception — at most one argument can be supplied
end if;
argObject  defaultArg(args, 0, undefined);
if arg = null or is(argErrorthen return arg
else return construct(cargsphase)
end if
end proc;
proc initError(thisSimpleInstanceargsObject[], phase: {run})
if |args| > 1 then
throw an ArgumentError exception — at most one argument can be supplied
end if;
nameString  Null  dotRead(ErrorPrototype, {public::“name”}, phase);
Evaluate dotWrite(this, {public::“name”}, namephase) and ignore its result;
argObject  defaultArg(args, 0, undefined);
messageString  Null;
if arg = undefined then message  dotRead(ErrorPrototype, {public::“message”}, phase)
else message  objectToString(argphase)
end if;
Evaluate dotWrite(this, {public::“message”}, messagephase) and ignore its result
end proc;
ErrorPrototypeSimpleInstancenew SimpleInstancelocalBindings: {
stdConstBinding(public::“constructor”, ClassError),
stdFunction(public::“toString”, Error_toString, 1),
stdVarBinding(public::“name”, String, “Error”),
stdVarBinding(public::“message”, String, an implementation-defined string)},
archetypeObjectPrototype, sealedprototypesSealed, typeObject, slots: {}, callnone, constructnone, envnone;
proc Error_toString(thisObjectfSimpleInstanceargsObject[], phasePhase): String
if phase = compile then
throw a ConstantError exception — toString cannot be called on an Error from a constant expression
end if;
note  This function ignores any arguments passed to it in args.
errObject  coerceNonNull(thisError);
nameString  Null  dotRead(err, {public::“name”}, phase);
messageString  Null  dotRead(err, {public::“message”}, phase);
return an implementation-defined string derived from name, message, and optionally other properties of err
end proc;
proc systemError(eClassmsgString  Undefined): Object
return construct(e[msg]run)
end proc;

Error Subclasses

proc makeBuiltInErrorSubclass(nameString): Class
proc call(thisObjectcClassargsObject[], phasePhase): Object
if |args| > 1 then
throw an ArgumentError exception — at most one argument can be supplied
end if;
argObject  defaultArg(args, 0, undefined);
if arg = null or is(argErrorthen return coerce(argc)
else return construct(cargsphase)
end if
end proc;
cClass  new ClasslocalBindings: {}, instanceProperties: {}, superError, completefalse, namename, typeofString: “object”, dynamictrue, finalfalse, defaultValuenull, defaultHinthintNumber, hasPropertyError.hasProperty, bracketReadError.bracketRead, bracketWriteError.bracketWrite, bracketDeleteError.bracketDelete, readError.read, writeError.write, deleteError.delete, enumerateError.enumerate, callcall, constructordinaryConstruct, initnone, isordinaryIs, coerceordinaryCoerce;
prototypeSimpleInstance  new SimpleInstancelocalBindings: {
stdConstBinding(public::“constructor”, Classc),
stdVarBinding(public::“name”, Stringname),
stdVarBinding(public::“message”, String, an implementation-defined string)},
archetypeErrorPrototype, sealedprototypesSealed, typeObject, slots: {}, callnone, constructnone, envnone;
proc init(thisSimpleInstanceargsObject[], phase: {run})
if |args| > 1 then
throw an ArgumentError exception — at most one argument can be supplied
end if;
name2String  Null  dotRead(prototype, {public::“name”}, phase);
Evaluate dotWrite(this, {public::“name”}, name2phase) and ignore its result;
argObject  defaultArg(args, 0, undefined);
messageString  Null;
if arg = undefined then message  dotRead(prototype, {public::“message”}, phase)
else message  objectToString(argphase)
end if;
Evaluate dotWrite(this, {public::“message”}, messagephase) and ignore its result
end proc;
c.prototype  prototype;
c.init  init;
c.complete  true;
return c
end proc;
ArgumentErrorClass = makeBuiltInErrorSubclass(“ArgumentError”);
AttributeErrorClass = makeBuiltInErrorSubclass(“AttributeError”);
ConstantErrorClass = makeBuiltInErrorSubclass(“ConstantError”);
DefinitionErrorClass = makeBuiltInErrorSubclass(“DefinitionError”);
EvalErrorClass = makeBuiltInErrorSubclass(“EvalError”);
RangeErrorClass = makeBuiltInErrorSubclass(“RangeError”);
ReferenceErrorClass = makeBuiltInErrorSubclass(“ReferenceError”);
SyntaxErrorClass = makeBuiltInErrorSubclass(“SyntaxError”);
TypeErrorClass = makeBuiltInErrorSubclass(“TypeError”);
UninitializedErrorClass = makeBuiltInErrorSubclass(“UninitializedError”);
URIErrorClass = makeBuiltInErrorSubclass(“URIError”);

Waldemar Horwat
Last modified Monday, June 30, 2003
previousupnext