Terminals
General tokens: Identifier Number RegularExpression String VirtualSemicolon
Punctuation tokens: ! != !== % %= & && &&= &= ( ) * *= + ++ += , - -- -= . ... / /= : :: ; < << <<= <= = == === > >= >> >>= >>> >>>= ? [ ] ^ ^= ^^ ^^= { | |= || ||= } ~
Reserved words: abstract as break case catch class const continue default delete do else export extends false final finally for function if implements import in instanceof interface is namespace new null package private public return static super switch this throw true try typeof use var void while with
Future reserved words: debugger enum goto native protected synchronized throws transient volatile
Non-reserved words: exclude get include named set
Data Model
Errors
tag syntaxError;
tag compileExpressionError;
tag referenceError;
tag uninitialisedError;
tag badValueError;
tag propertyAccessError;
tag definitionError;
tag argumentMismatchError;
SemanticError = {syntaxError, compileExpressionError, referenceError, uninitialisedError, badValueError, propertyAccessError, definitionError, argumentMismatchError};
tuple Break
value: Object,
label: Label
end tuple;
tuple Continue
value: Object,
label: Label
end tuple;
tuple ReturnedValue
value: Object
end tuple;
tuple ThrownValue
value: Object
end tuple;
EarlyExit = Break  Continue  ReturnedValue  ThrownValue;
SemanticException = EarlyExit  SemanticError;
Objects
tag none;
tag ok;
tag future;
tag uninitialised;
Object = Undefined  Null  Boolean  Float64  String  Namespace  CompoundAttribute  Class  MethodClosure  Prototype  Instance  Package  Global;
PrimitiveObject = Undefined  Null  Boolean  Float64  String;
DynamicObject = Prototype  DynamicInstance  Global;
ObjectOpt = Object  {none};
ObjectFut = Object  {future};
ObjectFutOpt = Object  {future, none};
ObjectUninit = Object  {uninitialised};
ObjectUninitFut = Object  {uninitialised, future};
Undefined
tag undefined;
Undefined = {undefined};
Null
tag null;
Null = {null};
Strings
StringOpt = String  {none};
Namespaces
record Namespace
name: String
end record;
publicNamespace: Namespace = new Namespacename: “public”;
enumerableNamespace: Namespace = new Namespacename: “enumerable”;
Qualified Names
tuple QualifiedName
namespace: Namespace,
id: String
end tuple;
QualifiedNameOpt = QualifiedName  {none};
Multiname = QualifiedName{};
Attributes
tag static;
tag constructor;
tag operator;
tag abstract;
tag virtual;
tag final;
MemberModifier = {none, static, constructor, operator, abstract, virtual, final};
OverrideModifier = {none, true, false, undefined};
tuple CompoundAttribute
namespaces: Namespace{},
explicit: Boolean,
dynamic: Boolean,
compile: Boolean,
memberMod: MemberModifier,
overrideMod: OverrideModifier,
prototype: Boolean,
unused: Boolean
end tuple;
Attribute = Boolean  Namespace  CompoundAttribute;
AttributeOptNotFalse = {none, true}  Namespace  CompoundAttribute;
Classes
record Class
staticReadBindings: StaticBinding{},
staticWriteBindings: StaticBinding{},
instanceReadBindings: InstanceBinding{},
instanceWriteBindings: InstanceBinding{},
instanceInitOrder: InstanceVariable[],
complete: Boolean,
super: ClassOpt,
prototype: Object,
privateNamespace: Namespace,
dynamic: Boolean,
primitive: Boolean,
final: Boolean,
call: Object  ArgumentList  Phase  Object,
construct: Object  ArgumentList  Phase  Object
end record;
ClassOpt = Class  {none};
Return an ordered list of class c’s ancestors, including c itself.
proc ancestors(c: Class): Class[]
s: ClassOpt  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(c: Class, d: Class): Boolean
if c = d then return true
else
s: ClassOpt  d.super;
if s = none then return false end if;
return isAncestor(c, s)
end if
end proc;
Return true if c is an ancestor of d other than d itself.
proc isProperAncestor(c: Class, d: Class): Boolean
return isAncestor(c, d) and c ≠ d
end proc;
Method Closures
tuple MethodClosure
this: Object,
method: InstanceMethod
end tuple;
Prototype Instances
record Prototype
parent: PrototypeOpt,
dynamicProperties: DynamicProperty{}
end record;
PrototypeOpt = Prototype  {none};
record DynamicProperty
name: String,
value: Object
end record;
Class Instances
Instance = FixedInstance  DynamicInstance;
record FixedInstance
type: Class,
call: Invoker,
construct: Invoker,
env: Environment,
typeofString: String,
slots: Slot{}
end record;
record DynamicInstance
type: Class,
call: Invoker,
construct: Invoker,
env: Environment,
typeofString: String,
slots: Slot{},
dynamicProperties: DynamicProperty{}
end record;
Slots
record Slot
id: InstanceVariable,
value: ObjectUninit
end record;
Packages
record Package
staticReadBindings: StaticBinding{},
staticWriteBindings: StaticBinding{},
internalNamespace: Namespace
end record;
Global Objects
record Global
staticReadBindings: StaticBinding{},
staticWriteBindings: StaticBinding{},
internalNamespace: Namespace,
dynamicProperties: DynamicProperty{}
end record;
Objects with Limits
instance must be an instance of limit or one of limit’s descendants.
tuple LimitedInstance
instance: Instance,
limit: Class
end tuple;
ObjOptionalLimit = Object  LimitedInstance;
References
tuple LexicalReference
env: Environment,
variableMultiname: Multiname,
cxt: Context
end tuple;
tuple DotReference
base: ObjOptionalLimit,
propertyMultiname: Multiname
end tuple;
tuple BracketReference
base: ObjOptionalLimit,
args: ArgumentList
end tuple;
Reference = LexicalReference  DotReference  BracketReference;
ObjOrRef = Object  Reference;
tuple LimitedObjOrRef
ref: ObjOrRef,
limit: Class
end tuple;
ObjOrRefOptionalLimit = ObjOrRef  LimitedObjOrRef;
Signatures
tuple Signature
requiredPositional: Class[],
optionalPositional: Class[],
optionalNamed: NamedParameter{},
rest: ClassOpt,
restAllowsNames: Boolean,
returnType: Class
end tuple;
tuple NamedParameter
name: String,
type: Class
end tuple;
Argument Lists
tuple NamedArgument
name: String,
value: Object
end tuple;
tuple ArgumentList
positional: Object[],
named: NamedArgument{}
end tuple;
The first Object is the this value. When the Phase parameter is compile, only compile-time expressions are allowed.
Invoker = Object  ArgumentList  Environment  Phase  Object;
Unary Operators
tuple UnaryMethod
operandType: Class,
f: Object  Object  ArgumentList  Phase  Object
end tuple;
Binary Operators
tuple BinaryMethod
leftType: Class,
rightType: Class,
f: Object  Object  Phase  Object
end tuple;
Modes of expression evaluation
tag compile;
tag run;
Phase = {compile, run};
Contexts
tuple Context
strict: Boolean,
openNamespaces: Namespace{}
end tuple;
initialContext: Context = Contextstrict: false, openNamespaces: {publicNamespace};
Labels
tag default;
Label = String  {default};
tuple JumpTargets
breakTargets: Label{},
continueTargets: Label{}
end tuple;
Environments
tag singular;
tag plural;
Plurality = {singular, plural};
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 the SystemFrame. The next-to-last frame is always a Package or Global frame.
Environment = Frame[];
Frame = SystemFrame  Global  Package  FunctionFrame  Class  BlockFrame;
record SystemFrame
staticReadBindings: StaticBinding{},
staticWriteBindings: StaticBinding{}
end record;
record FunctionFrame
staticReadBindings: StaticBinding{},
staticWriteBindings: StaticBinding{},
plurality: Plurality,
this: ObjectFutOpt,
thisFromPrototype: Boolean
end record;
record BlockFrame
staticReadBindings: StaticBinding{},
staticWriteBindings: StaticBinding{},
plurality: Plurality
end record;
initialEnvironment: Environment = [new SystemFramestaticReadBindings: {}, staticWriteBindings: {}];
Members
tuple StaticBinding
qname: QualifiedName,
content: StaticMember,
explicit: Boolean
end tuple;
tuple InstanceBinding
qname: QualifiedName,
content: InstanceMember
end tuple;
tag forbidden;
StaticMember = {forbidden}  Variable  HoistedVar  StaticMethod  Accessor;
StaticMemberOpt = StaticMember  {none};
record Variable
type: Class,
value: ObjectUninitFut,
immutable: Boolean
end record;
record HoistedVar
value: Object
end record;
record StaticMethod
type: Signature,
code: Instance,
modifier: {static, constructor}
end record;
record Accessor
type: Class,
code: Instance
end record;
InstanceMember = InstanceVariable  InstanceMethod  InstanceAccessor;
InstanceMemberOpt = InstanceMember  {none};
record InstanceVariable
type: Class,
evalInitialValue: ()  ObjectOpt,
immutable: Boolean,
final: Boolean
end record;
record InstanceMethod
type: Signature,
code: Instance  {abstract},
final: Boolean
end record;
record InstanceAccessor
type: Class,
code: Instance  {abstract},
final: Boolean
end record;
Data Operations
Numeric Utilities
proc uInt32ToInt32(i: Integer): Integer
if i < 231 then return i else return i – 232 end if
end proc;
proc toUInt32(x: Float64): Integer
if x  {+∞, –∞, NaN} then return 0 end if;
return truncateFiniteFloat64(x) mod 232
end proc;
proc toInt32(x: Float64): Integer
return uInt32ToInt32(toUInt32(x))
end proc;
Object Utilities
objectType
objectType(o) returns an Object o’s most specific type.
proc objectType(o: Object): Class
case o of
Undefined do return undefinedClass;
Null do return nullClass;
Boolean do return booleanClass;
Float64 do return numberClass;
String do if |o| = 1 then return characterClass else return stringClass end if;
Namespace do return namespaceClass;
CompoundAttribute do return attributeClass;
Class do return classClass;
MethodClosure do return functionClass;
Prototype do return prototypeClass;
Instance do return o.type;
Package  Global do return packageClass
end case
end proc;
hasType
There are two tests for determining whether an object o is an instance of class c. The first, hasType, is used for the purposes of method dispatch and helps determine whether a method of c can be called on o. The second, relaxedHasType, determines whether o can be stored in a variable of type c without conversion.
hasType(o, c) returns true if o is an instance of class c (or one of c’s subclasses). It considers null to be an instance of the classes Null and Object only.
proc hasType(o: Object, c: Class): Boolean
return isAncestor(c, objectType(o))
end proc;
relaxedHasType(o, c) returns true if o is an instance of class c (or one of c’s subclasses) but considers null to be an instance of the classes Null, Object, and all other non-primitive classes.
proc relaxedHasType(o: Object, c: Class): Boolean
t: Class  objectType(o);
return isAncestor(c, t) or (o = null and not c.primitive)
end proc;
toBoolean
toBoolean(o, phase) coerces an object o to a Boolean. If phase is compile, only compile-time conversions are permitted.
proc toBoolean(o: Object, phase: Phase): Boolean
case o of
Undefined  Null do return false;
Boolean do return o;
Float64 do return o  {+zero, –zero, NaN};
String do return o ≠ “”;
Namespace  CompoundAttribute  Class  MethodClosure  Prototype  Package  Global do
return true;
Instance do ????
end case
end proc;
toNumber
toNumber(o, phase) coerces an object o to a number. If phase is compile, only compile-time conversions are permitted.
proc toNumber(o: Object, phase: Phase): Float64
case o of
Undefined do return NaN;
Null  {false} do return +zero;
{true} do return 1.0;
Float64 do return o;
String do ????;
Namespace  CompoundAttribute  Class  MethodClosure  Package  Global do
throw badValueError;
Prototype  Instance do ????
end case
end proc;
toString
toString(o, phase) coerces an object o to a string. If phase is compile, only compile-time conversions are permitted.
proc toString(o: Object, phase: Phase): String
case o of
Undefined do return “undefined”;
Null do return “null”;
{false} do return “false”;
{true} do return “true”;
Float64 do ????;
String do return o;
Namespace do ????;
CompoundAttribute do ????;
Class do ????;
MethodClosure do ????;
Prototype  Instance do ????;
Package  Global do ????
end case
end proc;
toPrimitive
proc toPrimitive(o: Object, hint: Object, phase: Phase): PrimitiveObject
case o of
PrimitiveObject do return o;
Namespace  CompoundAttribute  Class  MethodClosure  Prototype  Instance  Package  Global do
return toString(o, phase)
end case
end proc;
assignmentConversion
proc assignmentConversion(o: Object, type: Class): Object
if relaxedHasType(o, type) then return o end if;
????
end proc;
unaryPlus
unaryPlus(o, phase) returns the value of the unary expression +o. If phase is compile, only compile-time operations are permitted.
proc unaryPlus(a: ObjOptionalLimit, phase: Phase): Object
return unaryDispatch(plusTable, null, a, ArgumentListpositional: [], named: {}, phase)
end proc;
unaryNot
unaryNot(o, phase) returns the value of the unary expression !o. If phase is compile, only compile-time operations are permitted.
proc unaryNot(a: Object, phase: Phase): Object
return not toBoolean(a, phase)
end proc;
Attributes
combineAttributes(a, b) returns the attribute that results from concatenating the attributes a and b.
proc combineAttributes(a: AttributeOptNotFalse, b: Attribute): Attribute
if b = false then return false
elsif a  {none, true} then return b
elsif b = true then return a
elsif a  Namespace then
if a = b then return a
elsif b  Namespace then
return CompoundAttributenamespaces: {a, b}, explicit: false, dynamic: false, compile: false, memberMod: none, overrideMod: none, prototype: false, unused: false
else return CompoundAttributenamespaces: b.namespaces  {a}, other fields from b
end if
elsif b  Namespace then
return CompoundAttributenamespaces: a.namespaces  {b}, other fields from a
else
Both a and b are compound attributes. Ensure that they have no conflicting contents.
if (a.memberMod ≠ none and b.memberMod ≠ none and a.memberMod ≠ b.memberMod) or (a.overrideMod ≠ none and b.overrideMod ≠ none and a.overrideMod ≠ b.overrideMod) then
throw badValueError
else
return CompoundAttributenamespaces: a.namespaces  b.namespaces, explicit: a.explicit or b.explicit, dynamic: a.dynamic or b.dynamic, compile: a.compile or b.compile, memberMod: a.memberMod ≠ none ? a.memberMod : b.memberMod, overrideMod: a.overrideMod ≠ none ? a.overrideMod : b.overrideMod, prototype: a.prototype or b.prototype, unused: a.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(a: AttributeOptNotFalse): CompoundAttribute
case a of
{none, true} do
return CompoundAttributenamespaces: {}, explicit: false, dynamic: false, compile: false, memberMod: none, overrideMod: none, prototype: false, unused: false;
Namespace do
return CompoundAttributenamespaces: {a}, explicit: false, dynamic: false, compile: false, memberMod: none, overrideMod: none, prototype: false, unused: false;
CompoundAttribute do return a
end case
end proc;
Objects with Limits
getObject(o) returns o without its limit, if any.
proc getObject(o: ObjOptionalLimit): Object
case o of
Object do return o;
LimitedInstance do return o.instance
end case
end proc;
getObjectLimit(o) returns o’s limit or none if none is provided.
proc getObjectLimit(o: ObjOptionalLimit): ClassOpt
case o of
Object do return none;
LimitedInstance do return o.limit
end case
end proc;
References
If r is an Object, readReference(r, phase) returns it unchanged.  If r is a Reference, this function reads r and returns the result. If phase is compile, only compile-time expressions can be evaluated in the process of reading r.
proc readReference(r: ObjOrRef, phase: Phase): Object
case r of
Object do return r;
LexicalReference do return lexicalRead(r.env, r.variableMultiname, phase);
DotReference do
result: ObjectOpt  readProperty(r.base, r.propertyMultiname, propertyLookup, phase);
if result = none then throw propertyAccessError else return result end if;
BracketReference do
return unaryDispatch(bracketReadTable, null, r.base, r.args, phase)
end case
end proc;
readRefWithLimit(r, phase) reads the reference, if any, inside r and returns the result, retaining the same limit as r. If r has a limit limit, then the object read from the reference is checked to make sure that it is an instance of limit or one of its descendants. If phase is compile, only compile-time expressions can be evaluated in the process of reading r.
proc readRefWithLimit(r: ObjOrRefOptionalLimit, phase: Phase): ObjOptionalLimit
case r of
ObjOrRef do return readReference(r, phase);
LimitedObjOrRef do
o: Object  readReference(r.ref, phase);
limit: Class  r.limit;
if o = null then return null end if;
if o  Instance or not hasType(o, limit) then throw badValueError end if;
return LimitedInstanceinstance: o, limit: limit
end case
end proc;
If r is a reference, writeReference(r, o) writes o into r. An error occurs if r is not a reference. r’s limit, if any, is ignored. writeReference is never called from a compile-time expression.
proc writeReference(r: ObjOrRefOptionalLimit, o: Object, phase: {run})
case r of
Object do throw referenceError;
LexicalReference do
lexicalWrite(r.env, r.variableMultiname, o, not r.cxt.strict, phase);
DotReference do
result: {none, ok}  writeProperty(r.base, r.propertyMultiname, propertyLookup, true, o, phase);
if result = none then throw propertyAccessError end if;
BracketReference do
args: ArgumentList  ArgumentListpositional: [o]  r.args.positional, named: r.args.named;
unaryDispatch(bracketWriteTable, null, r.base, args, phase);
LimitedObjOrRef do writeReference(r.ref, o, phase)
end case
end proc;
If r is a Reference, deleteReference(r) deletes it. If r is an Object, this function signals an error. deleteReference is never called from a compile-time expression.
proc deleteReference(r: ObjOrRef, phase: {run}): Object
case r of
Object do throw referenceError;
LexicalReference do return lexicalDelete(r.env, r.variableMultiname, phase);
DotReference do return deleteProperty(r.base, r.propertyMultiname, phase);
BracketReference do
return unaryDispatch(bracketDeleteTable, null, r.base, r.args, phase)
end case
end proc;
referenceBase(r) returns Reference r’s base or null if there is none. r’s limit and the base’s limit, if any, are ignored.
proc referenceBase(r: ObjOrRefOptionalLimit): Object
case r of
Object  LexicalReference do return null;
DotReference  BracketReference do return getObject(r.base);
LimitedObjOrRef do return referenceBase(r.ref)
end case
end proc;
Slots
proc findSlot(o: Object, id: InstanceVariable): Slot
o must be an Instance;
matchingSlots: Slot{}  {s | s  o.slots such that s.id = id};
return the one element of matchingSlots
end proc;
Environments
If env is from within a class’s body, getEnclosingClass(env) returns the innermost such class; otherwise, it returns none.
proc getEnclosingClass(env: Environment): 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;
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 local block frame or a local block frame whose immediate enclosing frame is a class.
proc getRegionalEnvironment(env: Environment): Frame[]
i: Integer  0;
while env[i]  BlockFrame do i  i + 1 end while;
if i ≠ 0 and env[i]  Class then i  i – 1 end if;
return env[0 ... i]
end proc;
getRegionalFrame(env)Returns the most specific regional frame in env.
proc getRegionalFrame(env: Environment): Frame
regionalEnv: Frame[]  getRegionalEnvironment(env);
return regionalEnv[|regionalEnv| – 1]
end proc;
proc getPackageOrGlobalFrame(env: Environment): Package  Global
g: Frame  env[|env| – 2];
The penultimate frame g is always a Package or Global frame.
return g
end proc;
Adding Static Definitions
tag read;
tag write;
tag readWrite;
Access = {read, write, readWrite};
tag readNoWrite;
DefinitionAccess = {read, write, readWrite, readNoWrite};
VariableAccess = {readWrite, readNoWrite};
proc bindDefinition(env: Environment, id: String, a: CompoundAttribute, defaultMemberMod: MemberModifier, access: DefinitionAccess, makeStaticMember: ()  StaticMember, makeInstanceMember: ()  InstanceMember)
memberMod: MemberModifier  a.memberMod;
if memberMod = none then
if a.compile then memberMod  static else memberMod  defaultMemberMod end if
end if;
regionalEnv: Frame[]  getRegionalEnvironment(env);
innerFrame: Frame  regionalEnv[0];
otherFramesInRegion: Frame[]  regionalEnv[1 ...];
regionalFrame: Frame  regionalEnv[|regionalEnv| – 1];
namespaces: Namespace{}  a.namespaces;
c: ClassOpt  none;
if regionalFrame  Class then c  regionalFrame end if;
if namespaces = {} then namespaces  {publicNamespace} end if;
***** If in a class, consider overrides and adjust list of namespaces.
multiname: Multiname  {QualifiedNamenamespace: ns, id: id | ns  namespaces};
if some b  innerFrame.staticReadBindings  innerFrame.staticWriteBindings satisfies b.qname  multiname then
throw definitionError
end if;
for each frame  otherFramesInRegion do
if some b  frame.staticReadBindings  frame.staticWriteBindings satisfies b.qname  multiname and b.content ≠ forbidden then
throw definitionError
end if
end for each;
if regionalFrame  Global and (some dp  regionalFrame.dynamicProperties satisfies QualifiedNamenamespace: publicNamespace, id: dp.name  multiname) then
throw definitionError
end if;
v: Variable;
????
end proc;
proc defineHoistedVar(env: Environment, id: String)
qname: QualifiedName  QualifiedNamenamespace: publicNamespace, id: id;
regionalEnv: Frame[]  getRegionalEnvironment(env);
regionalFrame: Frame  regionalEnv[|regionalEnv| – 1];
env is either the Global frame or a FunctionFrame because hoisting only occurs into global or function scope.
existingBindings: StaticBinding{}  {b | b  regionalFrame.staticReadBindings  regionalFrame.staticWriteBindings such that b.qname = qname};
if existingBindings = {} then
if regionalFrame  Global and (some dp  regionalFrame.dynamicProperties satisfies dp.name = id) then
throw definitionError
end if;
v: HoistedVar  new HoistedVarvalue: undefined;
newBindings: StaticBinding{}  {StaticBindingqname: qname, content: v, explicit: false};
regionalFrame.staticReadBindings  regionalFrame.staticReadBindings  newBindings;
regionalFrame.staticWriteBindings  regionalFrame.staticWriteBindings  newBindings
elsif some b  existingBindings satisfies b.content  HoistedVar then
throw definitionError
else
A hoisted binding of the same var already exists, so there is no need to create another one.
end if
end proc;
proc instantiateBlockFrame(template: BlockFrame): BlockFrame
????
end proc;
Adding Instance Definitions
tuple OverrideStatusPair
readStatus: OverrideStatus,
writeStatus: OverrideStatus
end tuple;
tag potentialConflict;
tuple OverrideStatus
overriddenMember: InstanceMember  {none, potentialConflict},
multiname: Multiname
end tuple;
proc searchForOverrides(c: Class, id: String, namespaces: Namespace{}, access: {read, write}): OverrideStatus
multiname: Multiname  {};
overriddenMember: InstanceMemberOpt  none;
s: ClassOpt  c.super;
for each ns  namespaces do
qname: QualifiedName  QualifiedNamenamespace: ns, id: id;
m: InstanceMemberOpt  findInstanceMember(s, qname, access);
if m ≠ none then
multiname  multiname  {qname};
if overriddenMember = none then overriddenMember  m
elsif overriddenMember ≠ m then throw definitionError
end if
end if
end for each;
return OverrideStatusoverriddenMember: overriddenMember, multiname: multiname
end proc;
proc resolveOverrides(c: Class, cxt: Context, id: String, namespaces: Namespace{}, access: {read, write}, expectMethod: Boolean): OverrideStatus
os: OverrideStatus;
if namespaces = {} then
os  searchForOverrides(c, id, cxt.openNamespaces, access);
if os.overriddenMember = none then
os  OverrideStatusoverriddenMember: none, multiname: {QualifiedNamenamespace: publicNamespace, id: id}
end if
else
definedMultiname: Multiname  {QualifiedNamenamespace: ns, id: id | ns  namespaces};
os2: OverrideStatus  searchForOverrides(c, id, namespaces, access);
if os2.overriddenMember = none then
os3: OverrideStatus  searchForOverrides(c, id, cxt.openNamespaces – namespaces, access);
if os3.overriddenMember = none then
os  OverrideStatusoverriddenMember: none, multiname: definedMultiname
else
os  OverrideStatusoverriddenMember: potentialConflict, multiname: definedMultiname
end if
else
os  OverrideStatusoverriddenMember: os2.overriddenMember, multiname: os2.multiname  definedMultiname
end if
end if;
instanceBindings: InstanceBinding{};
case access of
{read} do instanceBindings  c.instanceReadBindings;
{write} do instanceBindings  c.instanceWriteBindings
end case;
if some b  instanceBindings satisfies b.qname  os.multiname then
throw definitionError
end if;
if expectMethod then
if os.overriddenMember  {none, potentialConflict}  InstanceMethod then
throw definitionError
end if
else
if os.overriddenMember  {none, potentialConflict}  InstanceVariable  InstanceAccessor then
throw definitionError
end if
end if;
return os
end proc;
proc defineInstanceMember(c: Class, cxt: Context, id: String, namespaces: Namespace{}, overrideMod: OverrideModifier, access: Access, m: InstanceMember): OverrideStatusPair
expectMethod: Boolean  m  InstanceMethod;
readStatus: OverrideStatus  access  {read, readWrite} ? resolveOverrides(c, cxt, id, namespaces, read, expectMethod) : OverrideStatusoverriddenMember: none, multiname: {};
writeStatus: OverrideStatus  access  {write, readWrite} ? resolveOverrides(c, cxt, id, namespaces, write, expectMethod) : OverrideStatusoverriddenMember: none, multiname: {};
if readStatus.overriddenMember  InstanceMember or writeStatus.overriddenMember  InstanceMember then
if overrideMod  {true, undefined} then throw definitionError end if
elsif readStatus.overriddenMember = potentialConflict or writeStatus.overriddenMember = potentialConflict then
if overrideMod  {false, undefined} then throw definitionError end if
else if overrideMod  {none, false, undefined} then throw definitionError end if
end if;
newReadBindings: InstanceBinding{}  {InstanceBindingqname: qname, content: m | qname  readStatus.multiname};
c.instanceReadBindings  c.instanceReadBindings  newReadBindings;
newWriteBindings: InstanceBinding{}  {InstanceBindingqname: qname, content: m | qname  writeStatus.multiname};
c.instanceWriteBindings  c.instanceWriteBindings  newWriteBindings;
return OverrideStatusPairreadStatus: readStatus, writeStatus: writeStatus
end proc;
Environmental Lookup
findThis(env, allowPrototypeThis) returns the value of this. If allowPrototypeThis is true, allow this to be defined by either an instance member of a class or a prototype function. If allowPrototypeThis is false, allow this to be defined only by an instance member of a class.
proc findThis(env: Environment, allowPrototypeThis: Boolean): ObjectFutOpt
for each frame  env do
if frame  FunctionFrame and frame.this ≠ none then
if allowPrototypeThis or not frame.thisFromPrototype then return frame.this
end if
end if
end for each;
return none
end proc;
proc lexicalRead(env: Environment, multiname: Multiname, phase: Phase): Object
kind: LookupKind  LexicalLookupthis: findThis(env, false);
i: Integer  0;
while i < |env| do
frame: Frame  env[i];
result: ObjectOpt  readProperty(frame, multiname, kind, phase);
if result ≠ none then return result end if;
i  i + 1
end while;
throw referenceError
end proc;
proc lexicalWrite(env: Environment, multiname: Multiname, newValue: Object, createIfMissing: Boolean, phase: {run})
kind: LookupKind  LexicalLookupthis: findThis(env, false);
i: Integer  0;
while i < |env| do
frame: Frame  env[i];
result: {none, ok}  writeProperty(frame, multiname, kind, false, newValue, phase);
if result = ok then return end if;
i  i + 1
end while;
if createIfMissing then
g: Package  Global  getPackageOrGlobalFrame(env);
if g  Global then
Now try to write the variable into g again, this time allowing new dynamic bindings to be created dynamically.
result: {none, ok}  writeProperty(g, multiname, kind, true, newValue, phase);
if result = ok then return end if
end if
end if;
throw referenceError
end proc;
proc lexicalDelete(env: Environment, multiname: Multiname, phase: {run}): Boolean
????
end proc;
Property Lookup
tag propertyLookup;
tuple LexicalLookup
this: ObjectFutOpt
end tuple;
LookupKind = {propertyLookup}  LexicalLookup;
proc selectPublicName(multiname: Multiname): StringOpt
if some qname  multiname satisfies qname.namespace = publicNamespace then
return qname.id
end if;
return none
end proc;
proc findFlatMember(frame: Frame, multiname: Multiname, access: {read, write}, phase: Phase): StaticMemberOpt
bindings: StaticBinding{};
case access of
{read} do bindings  frame.staticReadBindings;
{write} do bindings  frame.staticWriteBindings
end case;
matchingBindings: StaticBinding{}  {b | b  bindings such that b.qname  multiname};
if matchingBindings = {} then return none end if;
matchingMembers: StaticMember{}  {b.content | b  matchingBindings};
Note that if the same member was found via several different bindings b, then it will appear only once in the set matchingMembers.
if |matchingMembers| > 1 then
This access is ambiguous because the bindings it found belong to several different members in the same class.
throw propertyAccessError
end if;
return the one element of matchingMembers
end proc;
proc findStaticMember(c: ClassOpt, multiname: Multiname, access: {read, write}, phase: Phase): {none}  StaticMember  QualifiedName
s: ClassOpt  c;
while s ≠ none do
staticBindings: StaticBinding{};
case access of
{read} do staticBindings  s.staticReadBindings;
{write} do staticBindings  s.staticWriteBindings
end case;
matchingStaticBindings: StaticBinding{}  {b | b  staticBindings such that b.qname  multiname};
Note that if the same member was found via several different bindings b, then it will appear only once in the set matchingStaticMembers.
matchingStaticMembers: StaticMember{}  {b.content | b  matchingStaticBindings};
if matchingStaticMembers ≠ {} then
if |matchingStaticMembers| = 1 then
return the one element of matchingStaticMembers
else
This access is ambiguous because the bindings it found belong to several different static members in the same class.
throw propertyAccessError
end if
end if;
If a static member wasn't found in a class, look for an instance member in that class as well.
instanceBindings: InstanceBinding{};
case access of
{read} do instanceBindings  s.instanceReadBindings;
{write} do instanceBindings  s.instanceWriteBindings
end case;
matchingInstanceBindings: InstanceBinding{}  {b | b  instanceBindings such that b.qname  multiname};
Note that if the same InstanceMember was found via several different bindings b, then it will appear only once in the set matchingInstanceMembers.
matchingInstanceMembers: InstanceMember{}  {b.content | b  matchingInstanceBindings};
if matchingInstanceMembers ≠ {} then
if |matchingInstanceMembers| = 1 then
Return the qualified name of any matching binding.  It doesn’t matter which because they all refer to the same InstanceMember, and if one is overridden by a subclass then all must be overridden in the same way by that subclass.
b: InstanceBinding  any element of matchingInstanceBindings;
return b.qname
else
This access is ambiguous because the bindings it found belong to several different members in the same class.
throw propertyAccessError
end if
end if;
s  s.super
end while;
return none
end proc;
proc resolveInstanceMemberName(c: Class, multiname: Multiname, access: {read, write}, phase: Phase): QualifiedNameOpt
Start from the root class (Object) and proceed through more specific classes that are ancestors of c.
for each s  ancestors(c) do
instanceBindings: InstanceBinding{};
case access of
{read} do instanceBindings  s.instanceReadBindings;
{write} do instanceBindings  s.instanceWriteBindings
end case;
matchingInstanceBindings: InstanceBinding{}  {b | b  instanceBindings such that b.qname  multiname};
Note that if the same InstanceMember was found via several different bindings b, then it will appear only once in the set matchingMembers.
matchingInstanceMembers: InstanceMember{}  {b.content | b  matchingInstanceBindings};
if matchingInstanceMembers ≠ {} then
if |matchingInstanceMembers| = 1 then
Return the qualified name of any matching binding.  It doesn’t matter which because they all refer to the same InstanceMember, and if one is overridden by a subclass then all must be overridden in the same way by that subclass.
b: InstanceBinding  any element of matchingInstanceBindings;
return b.qname
else
This access is ambiguous because the bindings it found belong to several different members in the same class.
throw propertyAccessError
end if
end if
end for each;
return none
end proc;
proc findInstanceMember(c: ClassOpt, qname: QualifiedNameOpt, access: {read, write}): InstanceMemberOpt
if qname = none then return none end if;
s: ClassOpt  c;
while s ≠ none do
instanceBindings: InstanceBinding{};
case access of
{read} do instanceBindings  s.instanceReadBindings;
{write} do instanceBindings  s.instanceWriteBindings
end case;
if some b  instanceBindings satisfies b.qname = qname then return b.content
end if;
s  s.super
end while;
return none
end proc;
Reading a Property
tag generic;
proc readProperty(container: ObjOptionalLimit  Frame, multiname: Multiname, kind: LookupKind, phase: Phase): ObjectOpt
case container of
Undefined  Null  Boolean  Float64  String  Namespace  CompoundAttribute  MethodClosure  Instance do
c: Class  objectType(container);
qname: QualifiedNameOpt  resolveInstanceMemberName(c, multiname, read, phase);
if qname = none and container  DynamicInstance then
return readDynamicProperty(container, multiname, kind, phase)
else return readInstanceMember(container, c, qname, phase)
end if;
SystemFrame  Global  Package  FunctionFrame  BlockFrame do
m: StaticMemberOpt  findFlatMember(container, multiname, read, phase);
if m = none and container  Global then
return readDynamicProperty(container, multiname, kind, phase)
else return readStaticMember(m, phase)
end if;
Class do
this: Object  {future, none, generic};
case kind of
{propertyLookup} do this  generic;
LexicalLookup do this  kind.this
end case;
m2: {none}  StaticMember  QualifiedName  findStaticMember(container, multiname, read, phase);
if m2  QualifiedName then return readStaticMember(m2, phase) end if;
case this of
{none} do throw propertyAccessError;
{future} do throw uninitialisedError;
{generic} do ????;
Object do return readInstanceMember(this, objectType(this), m2, phase)
end case;
Prototype do return readDynamicProperty(container, multiname, kind, phase);
LimitedInstance do
superclass: ClassOpt  container.limit.super;
if superclass = none then return none end if;
qname: QualifiedNameOpt  resolveInstanceMemberName(superclass, multiname, read, phase);
return readInstanceMember(container.instance, superclass, qname, phase)
end case
end proc;
proc readInstanceMember(this: Object, c: Class, qname: QualifiedNameOpt, phase: Phase): ObjectOpt
m: InstanceMemberOpt  findInstanceMember(c, qname, read);
case m of
{none} do return none;
InstanceVariable do
if phase = compile and not m.immutable then throw compileExpressionError
end if;
v: ObjectUninit  findSlot(this, m).value;
if v = uninitialised then throw uninitialisedError end if;
return v;
InstanceMethod do return MethodClosurethis: this, method: m;
InstanceAccessor do
code: Instance  {abstract}  m.code;
case code of
Instance do
return code.call(this, ArgumentListpositional: [], named: {}, code.env, phase);
{abstract} do throw propertyAccessError
end case
end case
end proc;
proc readStaticMember(m: StaticMemberOpt, phase: Phase): ObjectOpt
case m of
{none} do return none;
{forbidden} do throw propertyAccessError;
Variable do return readVariable(m, phase);
HoistedVar do return m.value;
StaticMethod do return m.code;
Accessor do
code: Instance  m.code;
return code.call(null, ArgumentListpositional: [], named: {}, code.env, phase)
end case
end proc;
proc readDynamicProperty(container: DynamicObject, multiname: Multiname, kind: LookupKind, phase: Phase): ObjectOpt
name: StringOpt  selectPublicName(multiname);
if name = none then return none end if;
if phase = compile then throw compileExpressionError end if;
if some dp  container.dynamicProperties satisfies dp.name = name then
return dp.value
end if;
if container  Prototype then
parent: PrototypeOpt  container.parent;
if parent ≠ none then return readDynamicProperty(parent, multiname, kind, phase)
end if
end if;
if kind = propertyLookup then return undefined end if;
return none
end proc;
proc readVariable(v: Variable, phase: Phase): Object
if phase = compile and not v.immutable then throw compileExpressionError end if;
value: ObjectUninitFut  v.value;
if value  {uninitialised, future} then throw uninitialisedError end if;
return value
end proc;
Writing a Property
proc writeProperty(container: ObjOptionalLimit  Frame, multiname: Multiname, kind: LookupKind, createIfMissing: Boolean, newValue: Object, phase: {run}): {none, ok}
case container of
Undefined  Null  Boolean  Float64  String  Namespace  CompoundAttribute  MethodClosure do
return none;
SystemFrame  Global  Package  FunctionFrame  BlockFrame do
m: StaticMemberOpt  findFlatMember(container, multiname, write, phase);
if m = none and container  Global then
return writeDynamicProperty(container, multiname, createIfMissing, newValue, phase)
else return writeStaticMember(m, newValue, phase)
end if;
Class do
this: ObjectFutOpt;
case kind of
{propertyLookup} do this  none;
LexicalLookup do this  kind.this
end case;
m2: {none}  StaticMember  QualifiedName  findStaticMember(container, multiname, write, phase);
if m2  QualifiedName then return writeStaticMember(m2, newValue, phase)
elsif this = none then throw propertyAccessError
elsif this = future then throw uninitialisedError
else return writeInstanceMember(this, objectType(this), m2, newValue, phase)
end if;
Prototype do
return writeDynamicProperty(container, multiname, createIfMissing, newValue, phase);
Instance do
c: Class  objectType(container);
qname: QualifiedNameOpt  resolveInstanceMemberName(objectType(container), multiname, write, phase);
if qname = none and container  DynamicInstance then
return writeDynamicProperty(container, multiname, createIfMissing, newValue, phase)
else return writeInstanceMember(container, c, qname, newValue, phase)
end if;
LimitedInstance do
superclass: ClassOpt  container.limit.super;
if superclass = none then return none end if;
qname: QualifiedNameOpt  resolveInstanceMemberName(superclass, multiname, write, phase);
return writeInstanceMember(container.instance, superclass, qname, newValue, phase)
end case
end proc;
proc writeInstanceMember(this: Object, c: Class, qname: QualifiedNameOpt, newValue: Object, phase: {run}): {none, ok}
m: InstanceMemberOpt  findInstanceMember(c, qname, write);
case m of
{none} do return none;
InstanceVariable do
s: Slot  findSlot(this, m);
if m.immutable and s.value ≠ uninitialised then throw propertyAccessError
end if;
coercedValue: Object  assignmentConversion(newValue, m.type);
s.value  coercedValue;
return ok;
InstanceMethod do throw propertyAccessError;
InstanceAccessor do
coercedValue: Object  assignmentConversion(newValue, m.type);
code: Instance  {abstract}  m.code;
case code of
Instance do
code.call(this, ArgumentListpositional: [coercedValue], named: {}, code.env, phase);
{abstract} do throw propertyAccessError
end case;
return ok
end case
end proc;
proc writeStaticMember(m: StaticMemberOpt, newValue: Object, phase: {run}): {none, ok}
case m of
{none} do return none;
{forbidden}  StaticMethod do throw propertyAccessError;
Variable do writeVariable(m, newValue, phase); return ok;
HoistedVar do m.value  newValue; return ok;
Accessor do
coercedValue: Object  assignmentConversion(newValue, m.type);
code: Instance  m.code;
code.call(null, ArgumentListpositional: [coercedValue], named: {}, code.env, phase);
return ok
end case
end proc;
proc writeDynamicProperty(container: DynamicObject, multiname: Multiname, createIfMissing: Boolean, newValue: Object, phase: {run}): {none, ok}
name: StringOpt  selectPublicName(multiname);
if name = none then return none end if;
if some dp  container.dynamicProperties satisfies dp.name = name then
dp.value  newValue;
return ok
end if;
if not createIfMissing then return none end if;
Before trying to create a new dynamic property, check that there is no read-only fixed property with the same name.
m: {none}  StaticMember  QualifiedName;
case container of
Prototype do m  none;
DynamicInstance do
m  resolveInstanceMemberName(objectType(container), multiname, read, phase);
Global do m  findFlatMember(container, multiname, read, phase)
end case;
if m ≠ none then return none end if;
container.dynamicProperties  container.dynamicProperties  {new DynamicPropertyname: name, value: newValue};
return ok
end proc;
proc writeVariable(v: Variable, newValue: Object, phase: {run})
type: Class  v.type;
if v.value = future then throw uninitialisedError end if;
if v.immutable and v.value ≠ uninitialised then throw propertyAccessError end if;
coercedValue: Object  assignmentConversion(newValue, type);
v.value  coercedValue
end proc;
Deleting a Property
proc deleteProperty(o: ObjOptionalLimit, multiname: Multiname, phase: {run}): Boolean
????
end proc;
proc deleteQualifiedProperty(o: Object, name: String, ns: Namespace, kind: LookupKind, phase: {run}): Boolean
????
end proc;
Operator Dispatch
Unary Operators
unaryDispatch(table, this, operand, args, phase) dispatches the unary operator described by table applied to the this value this, the operand operand, and zero or more positional and/or named arguments args. If operand has a limit class, lookup is restricted to operators defined on the proper ancestors of that limit. If phase is compile, only compile-time expressions can be evaluated in the process of dispatching and calling the operator.
proc unaryDispatch(table: UnaryMethod{}, this: Object, operand: ObjOptionalLimit, args: ArgumentList, phase: Phase): Object
applicableOps: UnaryMethod{}  {m | m  table such that limitedHasType(operand, m.operandType)};
if some best  applicableOps satisfies (every m2  applicableOps satisfies isAncestor(m2.operandType, best.operandType)) then
return best.f(this, getObject(operand), args, phase)
end if;
throw propertyAccessError
end proc;
limitedHasType(o, c) returns true if o is a member of class c with the added condition that, if o has a limit class limit, c is a proper ancestor of limit.
proc limitedHasType(o: ObjOptionalLimit, c: Class): Boolean
a: Object  getObject(o);
limit: ClassOpt  getObjectLimit(o);
if hasType(a, c) then
if limit = none then return true else return isProperAncestor(c, limit) end if
else return false
end if
end proc;
Binary Operators
isBinaryDescendant(m1, m2) is true if m1 is at least as specific as m2 as defined by the procedure below.
proc isBinaryDescendant(m1: BinaryMethod, m2: BinaryMethod): Boolean
return isAncestor(m2.leftType, m1.leftType) and isAncestor(m2.rightType, m1.rightType)
end proc;
binaryDispatch(table, left, right, phase) dispatches the binary operator described by table applied to the operands left and right. If left has a limit leftLimit, the lookup is restricted to operator definitions with an ancestor of leftLimit for the left operand. Similarly, if right has a limit rightLimit, the lookup is restricted to operator definitions with an ancestor of rightLimit for the right operand. If phase is compile, only compile-time expressions can be evaluated in the process of dispatching and calling the operator.
proc binaryDispatch(table: BinaryMethod{}, left: ObjOptionalLimit, right: ObjOptionalLimit, phase: Phase): Object
applicableOps: BinaryMethod{}  {m | m  table such that limitedHasType(left, m.leftType) and limitedHasType(right, m.rightType)};
if some best  applicableOps satisfies (every m2  applicableOps satisfies isBinaryDescendant(best, m2)) then
return best.f(getObject(left), getObject(right), phase)
end if;
throw propertyAccessError
end proc;
Deferred Validation
deferredValidators: (()  ())[]  [];
Expressions
Syntax
  {allowIn, noIn}
Terminal Actions
Name[Identifier]: String;
Value[Number]: Float64;
Value[String]: String;
Identifiers
Syntax
Identifier 
	Identifier
|	get
|	set
|	exclude
|	include
|	named
Semantics
Name[Identifier]: String;
Name[Identifier  Identifier] = Name[Identifier];
Name[Identifier  get] = “get”;
Name[Identifier  set] = “set”;
Name[Identifier  exclude] = “exclude”;
Name[Identifier  include] = “include”;
Name[Identifier  named] = “named”;
Qualified Identifiers
Syntax
Qualifier 
	Identifier
|	public
|	private
SimpleQualifiedIdentifier 
	Identifier
|	Qualifier :: Identifier
ExpressionQualifiedIdentifier  ParenExpression :: Identifier
QualifiedIdentifier 
	SimpleQualifiedIdentifier
|	ExpressionQualifiedIdentifier
Validation and Evaluation
proc Validate[Qualifier] (cxt: Context, env: Environment): Namespace
[Qualifier  Identifier] do
multiname: Multiname  {QualifiedNamenamespace: ns, id: Name[Identifier] | ns  cxt.openNamespaces};
a: Object  lexicalRead(env, multiname, compile);
if a  Namespace then throw badValueError end if;
return a;
[Qualifier  public] do return publicNamespace;
[Qualifier  private] do
c: ClassOpt  getEnclosingClass(env);
if c = none then throw syntaxError end if;
return c.privateNamespace
end proc;
Multiname[SimpleQualifiedIdentifier]: Multiname;
proc Validate[SimpleQualifiedIdentifier] (cxt: Context, env: Environment)
[SimpleQualifiedIdentifier  Identifier] do
multiname: Multiname  {QualifiedNamenamespace: ns, id: Name[Identifier] | ns  cxt.openNamespaces};
Multiname[SimpleQualifiedIdentifier]  multiname;
[SimpleQualifiedIdentifier  Qualifier :: Identifier] do
q: Namespace  Validate[Qualifier](cxt, env);
Multiname[SimpleQualifiedIdentifier]  {QualifiedNamenamespace: q, id: Name[Identifier]}
end proc;
Multiname[ExpressionQualifiedIdentifier]: Multiname;
proc Validate[ExpressionQualifiedIdentifier  ParenExpression :: Identifier] (cxt: Context, env: Environment)
Validate[ParenExpression](cxt, env);
r: ObjOrRef  Eval[ParenExpression](env, compile);
q: Object  readReference(r, compile);
if q  Namespace then throw badValueError end if;
Multiname[ExpressionQualifiedIdentifier]  {QualifiedNamenamespace: q, id: Name[Identifier]}
end proc;
Multiname[QualifiedIdentifier]: Multiname;
proc Validate[QualifiedIdentifier] (cxt: Context, env: Environment)
[QualifiedIdentifier  SimpleQualifiedIdentifier] do
Validate[SimpleQualifiedIdentifier](cxt, env);
Multiname[QualifiedIdentifier]  Multiname[SimpleQualifiedIdentifier];
[QualifiedIdentifier  ExpressionQualifiedIdentifier] do
Validate[ExpressionQualifiedIdentifier](cxt, env);
Multiname[QualifiedIdentifier]  Multiname[ExpressionQualifiedIdentifier]
end proc;
Unit Expressions
Syntax
UnitExpression 
	ParenListExpression
|	Number [no line break] String
|	UnitExpression [no line break] String
Validation
proc Validate[UnitExpression] (cxt: Context, env: Environment)
[UnitExpression  ParenListExpression] do Validate[ParenListExpression](cxt, env);
[UnitExpression  Number [no line break] String] do ????;
[UnitExpression  UnitExpression [no line break] String] do ????
end proc;
Evaluation
proc Eval[UnitExpression] (env: Environment, phase: Phase): ObjOrRef
[UnitExpression  ParenListExpression] do
return Eval[ParenListExpression](env, phase);
[UnitExpression  Number [no line break] String] do ????;
[UnitExpression  UnitExpression [no line break] String] do ????
end proc;
Primary Expressions
Syntax
PrimaryExpression 
	null
|	true
|	false
|	public
|	Number
|	String
|	this
|	RegularExpression
|	UnitExpression
|	ArrayLiteral
|	ObjectLiteral
|	FunctionExpression
ParenExpression  ( AssignmentExpressionallowIn )
ParenListExpression 
	ParenExpression
|	( ListExpressionallowIn , AssignmentExpressionallowIn )
Validation
proc Validate[PrimaryExpression] (cxt: Context, env: Environment)
[PrimaryExpression  null] do nothing;
[PrimaryExpression  true] do nothing;
[PrimaryExpression  false] do nothing;
[PrimaryExpression  public] do nothing;
[PrimaryExpression  Number] do nothing;
[PrimaryExpression  String] do nothing;
[PrimaryExpression  this] do
if findThis(env, true) = none then throw syntaxError end if;
[PrimaryExpression  RegularExpression] do nothing;
[PrimaryExpression  UnitExpression] do Validate[UnitExpression](cxt, env);
[PrimaryExpression  ArrayLiteral] do ????;
[PrimaryExpression  ObjectLiteral] do ????;
[PrimaryExpression  FunctionExpression] do Validate[FunctionExpression](cxt, env)
end proc;
Validate[ParenExpression  ( AssignmentExpressionallowIn )]: Context  Environment  () = Validate[AssignmentExpressionallowIn];
proc Validate[ParenListExpression] (cxt: Context, env: Environment)
[ParenListExpression  ParenExpression] do Validate[ParenExpression](cxt, env);
[ParenListExpression  ( ListExpressionallowIn , AssignmentExpressionallowIn )] do
Validate[ListExpressionallowIn](cxt, env);
Validate[AssignmentExpressionallowIn](cxt, env)
end proc;
Evaluation
proc Eval[PrimaryExpression] (env: Environment, phase: Phase): ObjOrRef
[PrimaryExpression  null] do return null;
[PrimaryExpression  true] do return true;
[PrimaryExpression  false] do return false;
[PrimaryExpression  public] do return publicNamespace;
[PrimaryExpression  Number] do return Value[Number];
[PrimaryExpression  String] do return Value[String];
[PrimaryExpression  this] do
this: ObjectFutOpt  findThis(env, true);
Note that Validate ensured that this cannot be none at this point.
if this = future then throw uninitialisedError end if;
return this;
[PrimaryExpression  RegularExpression] do ????;
[PrimaryExpression  UnitExpression] do return Eval[UnitExpression](env, phase);
[PrimaryExpression  ArrayLiteral] do ????;
[PrimaryExpression  ObjectLiteral] do ????;
[PrimaryExpression  FunctionExpression] do
return Eval[FunctionExpression](env, phase)
end proc;
Eval[ParenExpression  ( AssignmentExpressionallowIn )]: Environment  Phase  ObjOrRef = Eval[AssignmentExpressionallowIn];
proc Eval[ParenListExpression] (env: Environment, phase: Phase): ObjOrRef
[ParenListExpression  ParenExpression] do return Eval[ParenExpression](env, phase);
[ParenListExpression  ( ListExpressionallowIn , AssignmentExpressionallowIn )] do
ra: ObjOrRef  Eval[ListExpressionallowIn](env, phase);
readReference(ra, phase);
rb: ObjOrRef  Eval[AssignmentExpressionallowIn](env, phase);
return readReference(rb, phase)
end proc;
proc EvalAsList[ParenListExpression] (env: Environment, phase: Phase): Object[]
[ParenListExpression  ParenExpression] do
r: ObjOrRef  Eval[ParenExpression](env, phase);
elt: Object  readReference(r, phase);
return [elt];
[ParenListExpression  ( ListExpressionallowIn , AssignmentExpressionallowIn )] do
elts: Object[]  EvalAsList[ListExpressionallowIn](env, phase);
r: ObjOrRef  Eval[AssignmentExpressionallowIn](env, phase);
elt: Object  readReference(r, phase);
return elts  [elt]
end proc;
Function Expressions
Syntax
FunctionExpression 
	function FunctionSignature Block
|	function Identifier FunctionSignature Block
Validation
proc Validate[FunctionExpression] (cxt: Context, env: Environment)
[FunctionExpression  function FunctionSignature Block] do ????;
[FunctionExpression  function Identifier FunctionSignature Block] do ????
end proc;
Evaluation
proc Eval[FunctionExpression] (env: Environment, phase: Phase): ObjOrRef
[FunctionExpression  function FunctionSignature Block] do ????;
[FunctionExpression  function Identifier FunctionSignature Block] do ????
end proc;
Object Literals
Syntax
ObjectLiteral 
	{ }
|	{ FieldList }
FieldList 
	LiteralField
|	FieldList , LiteralField
LiteralField  FieldName : AssignmentExpressionallowIn
FieldName 
	Identifier
|	String
|	Number
|	ParenExpression
Validation
proc Validate[LiteralField  FieldName : AssignmentExpressionallowIn] (cxt: Context, env: Environment): String{}
names: String{}  Validate[FieldName](cxt, env);
Validate[AssignmentExpressionallowIn](cxt, env);
return names
end proc;
proc Validate[FieldName] (cxt: Context, env: Environment): String{}
[FieldName  Identifier] do return {Name[Identifier]};
[FieldName  String] do return {Value[String]};
[FieldName  Number] do ????;
[FieldName  ParenExpression] do ????
end proc;
Evaluation
proc Eval[LiteralField  FieldName : AssignmentExpressionallowIn] (env: Environment, phase: Phase): NamedArgument
name: String  Eval[FieldName](env, phase);
r: ObjOrRef  Eval[AssignmentExpressionallowIn](env, phase);
value: Object  readReference(r, phase);
return NamedArgumentname: name, value: value
end proc;
proc Eval[FieldName] (env: Environment, phase: Phase): String
[FieldName  Identifier] do return Name[Identifier];
[FieldName  String] do return Value[String];
[FieldName  Number] do ????;
[FieldName  ParenExpression] do ????
end proc;
Array Literals
Syntax
ArrayLiteral  [ ElementList ]
ElementList 
	LiteralElement
|	ElementList , LiteralElement
LiteralElement 
	«empty»
|	AssignmentExpressionallowIn
Super Expressions
Syntax
SuperExpression 
	super
|	FullSuperExpression
FullSuperExpression  super ParenExpression
Validation
proc Validate[SuperExpression] (cxt: Context, env: Environment)
[SuperExpression  super] do
if getEnclosingClass(env) = none or findThis(env, false) = none then
throw syntaxError
end if;
[SuperExpression  FullSuperExpression] do Validate[FullSuperExpression](cxt, env)
end proc;
proc Validate[FullSuperExpression  super ParenExpression] (cxt: Context, env: Environment)
if getEnclosingClass(env) = none then throw syntaxError end if;
Validate[ParenExpression](cxt, env)
end proc;
Evaluation
proc Eval[SuperExpression] (env: Environment, phase: Phase): ObjOrRefOptionalLimit
[SuperExpression  super] do
this: ObjectFutOpt  findThis(env, false);
Note that Validate ensured that this cannot be none at this point.
if this = future then throw uninitialisedError end if;
limit: ClassOpt  getEnclosingClass(env);
Note that Validate ensured that limit cannot be none at this point.
return LimitedObjOrRefref: this, limit: limit;
[SuperExpression  FullSuperExpression] do
return Eval[FullSuperExpression](env, phase)
end proc;
proc Eval[FullSuperExpression  super ParenExpression] (env: Environment, phase: Phase): ObjOrRefOptionalLimit
r: ObjOrRef  Eval[ParenExpression](env, phase);
limit: ClassOpt  getEnclosingClass(env);
Note that Validate ensured that limit cannot be none at this point.
return LimitedObjOrRefref: r, limit: limit
end proc;
Postfix Expressions
Syntax
PostfixExpression 
	AttributeExpression
|	FullPostfixExpression
|	ShortNewExpression
PostfixExpressionOrSuper 
	PostfixExpression
|	SuperExpression
AttributeExpression 
	SimpleQualifiedIdentifier
|	AttributeExpression MemberOperator
|	AttributeExpression Arguments
FullPostfixExpression 
	PrimaryExpression
|	ExpressionQualifiedIdentifier
|	FullNewExpression
|	FullPostfixExpression MemberOperator
|	SuperExpression DotOperator
|	FullPostfixExpression Arguments
|	FullSuperExpression Arguments
|	PostfixExpressionOrSuper [no line break] ++
|	PostfixExpressionOrSuper [no line break] --
FullNewExpression 
	new FullNewSubexpression Arguments
|	new FullSuperExpression Arguments
FullNewSubexpression 
	PrimaryExpression
|	QualifiedIdentifier
|	FullNewExpression
|	FullNewSubexpression MemberOperator
|	SuperExpression DotOperator
ShortNewExpression 
	new ShortNewSubexpression
|	new SuperExpression
ShortNewSubexpression 
	FullNewSubexpression
|	ShortNewExpression
Validation
Validate[PostfixExpression]: Context  Environment  ();
Validate[PostfixExpression  AttributeExpression] = Validate[AttributeExpression];
Validate[PostfixExpression  FullPostfixExpression] = Validate[FullPostfixExpression];
Validate[PostfixExpression  ShortNewExpression] = Validate[ShortNewExpression];
Validate[PostfixExpressionOrSuper]: Context  Environment  ();
Validate[PostfixExpressionOrSuper  PostfixExpression] = Validate[PostfixExpression];
Validate[PostfixExpressionOrSuper  SuperExpression] = Validate[SuperExpression];
Context[AttributeExpression]: Context;
proc Validate[AttributeExpression] (cxt: Context, env: Environment)
[AttributeExpression  SimpleQualifiedIdentifier] do
Validate[SimpleQualifiedIdentifier](cxt, env);
Context[AttributeExpression]  cxt;
[AttributeExpression0  AttributeExpression1 MemberOperator] do
Validate[AttributeExpression1](cxt, env);
Validate[MemberOperator](cxt, env);
[AttributeExpression0  AttributeExpression1 Arguments] do
Validate[AttributeExpression1](cxt, env);
Validate[Arguments](cxt, env)
end proc;
Context[FullPostfixExpression]: Context;
proc Validate[FullPostfixExpression] (cxt: Context, env: Environment)
[FullPostfixExpression  PrimaryExpression] do
Validate[PrimaryExpression](cxt, env);
[FullPostfixExpression  ExpressionQualifiedIdentifier] do
Validate[ExpressionQualifiedIdentifier](cxt, env);
Context[FullPostfixExpression]  cxt;
[FullPostfixExpression  FullNewExpression] do
Validate[FullNewExpression](cxt, env);
[FullPostfixExpression0  FullPostfixExpression1 MemberOperator] do
Validate[FullPostfixExpression1](cxt, env);
Validate[MemberOperator](cxt, env);
[FullPostfixExpression  SuperExpression DotOperator] do
Validate[SuperExpression](cxt, env);
Validate[DotOperator](cxt, env);
[FullPostfixExpression0  FullPostfixExpression1 Arguments] do
Validate[FullPostfixExpression1](cxt, env);
Validate[Arguments](cxt, env);
[FullPostfixExpression  FullSuperExpression Arguments] do
Validate[FullSuperExpression](cxt, env);
Validate[Arguments](cxt, env);
[FullPostfixExpression  PostfixExpressionOrSuper [no line break] ++] do
Validate[PostfixExpressionOrSuper](cxt, env);
[FullPostfixExpression  PostfixExpressionOrSuper [no line break] --] do
Validate[PostfixExpressionOrSuper](cxt, env)
end proc;
proc Validate[FullNewExpression] (cxt: Context, env: Environment)
[FullNewExpression  new FullNewSubexpression Arguments] do
Validate[FullNewSubexpression](cxt, env);
Validate[Arguments](cxt, env);
[FullNewExpression  new FullSuperExpression Arguments] do
Validate[FullSuperExpression](cxt, env);
Validate[Arguments](cxt, env)
end proc;
Context[FullNewSubexpression]: Context;
proc Validate[FullNewSubexpression] (cxt: Context, env: Environment)
[FullNewSubexpression  PrimaryExpression] do Validate[PrimaryExpression](cxt, env);
[FullNewSubexpression  QualifiedIdentifier] do
Validate[QualifiedIdentifier](cxt, env);
Context[FullNewSubexpression]  cxt;
[FullNewSubexpression  FullNewExpression] do Validate[FullNewExpression](cxt, env);
[FullNewSubexpression0  FullNewSubexpression1 MemberOperator] do
Validate[FullNewSubexpression1](cxt, env);
Validate[MemberOperator](cxt, env);
[FullNewSubexpression  SuperExpression DotOperator] do
Validate[SuperExpression](cxt, env);
Validate[DotOperator](cxt, env)
end proc;
proc Validate[ShortNewExpression] (cxt: Context, env: Environment)
[ShortNewExpression  new ShortNewSubexpression] do
Validate[ShortNewSubexpression](cxt, env);
[ShortNewExpression  new SuperExpression] do Validate[SuperExpression](cxt, env)
end proc;
Validate[ShortNewSubexpression]: Context  Environment  ();
Validate[ShortNewSubexpression  FullNewSubexpression] = Validate[FullNewSubexpression];
Validate[ShortNewSubexpression  ShortNewExpression] = Validate[ShortNewExpression];
Evaluation
Eval[PostfixExpression]: Environment  Phase  ObjOrRef;
Eval[PostfixExpression  AttributeExpression] = Eval[AttributeExpression];
Eval[PostfixExpression  FullPostfixExpression] = Eval[FullPostfixExpression];
Eval[PostfixExpression  ShortNewExpression] = Eval[ShortNewExpression];
Eval[PostfixExpressionOrSuper]: Environment  Phase  ObjOrRefOptionalLimit;
Eval[PostfixExpressionOrSuper  PostfixExpression] = Eval[PostfixExpression];
Eval[PostfixExpressionOrSuper  SuperExpression] = Eval[SuperExpression];
proc Eval[AttributeExpression] (env: Environment, phase: Phase): ObjOrRef
[AttributeExpression  SimpleQualifiedIdentifier] do
return LexicalReferenceenv: env, variableMultiname: Multiname[SimpleQualifiedIdentifier], cxt: Context[AttributeExpression];
[AttributeExpression0  AttributeExpression1 MemberOperator] do
r: ObjOrRef  Eval[AttributeExpression1](env, phase);
a: Object  readReference(r, phase);
return Eval[MemberOperator](env, a, phase);
[AttributeExpression0  AttributeExpression1 Arguments] do
r: ObjOrRef  Eval[AttributeExpression1](env, phase);
f: Object  readReference(r, phase);
base: Object  referenceBase(r);
args: ArgumentList  Eval[Arguments](env, phase);
return unaryDispatch(callTable, base, f, args, phase)
end proc;
proc Eval[FullPostfixExpression] (env: Environment, phase: Phase): ObjOrRef
[FullPostfixExpression  PrimaryExpression] do
return Eval[PrimaryExpression](env, phase);
[FullPostfixExpression  ExpressionQualifiedIdentifier] do
return LexicalReferenceenv: env, variableMultiname: Multiname[ExpressionQualifiedIdentifier], cxt: Context[FullPostfixExpression];
[FullPostfixExpression  FullNewExpression] do
return Eval[FullNewExpression](env, phase);
[FullPostfixExpression0  FullPostfixExpression1 MemberOperator] do
r: ObjOrRef  Eval[FullPostfixExpression1](env, phase);
a: Object  readReference(r, phase);
return Eval[MemberOperator](env, a, phase);
[FullPostfixExpression  SuperExpression DotOperator] do
r: ObjOrRefOptionalLimit  Eval[SuperExpression](env, phase);
a: ObjOptionalLimit  readRefWithLimit(r, phase);
return Eval[DotOperator](env, a, phase);
[FullPostfixExpression0  FullPostfixExpression1 Arguments] do
r: ObjOrRef  Eval[FullPostfixExpression1](env, phase);
f: Object  readReference(r, phase);
base: Object  referenceBase(r);
args: ArgumentList  Eval[Arguments](env, phase);
return unaryDispatch(callTable, base, f, args, phase);
[FullPostfixExpression  FullSuperExpression Arguments] do
r: ObjOrRefOptionalLimit  Eval[FullSuperExpression](env, phase);
f: ObjOptionalLimit  readRefWithLimit(r, phase);
base: Object  referenceBase(r);
args: ArgumentList  Eval[Arguments](env, phase);
return unaryDispatch(callTable, base, f, args, phase);
[FullPostfixExpression  PostfixExpressionOrSuper [no line break] ++] do
if phase = compile then throw compileExpressionError end if;
r: ObjOrRefOptionalLimit  Eval[PostfixExpressionOrSuper](env, phase);
a: ObjOptionalLimit  readRefWithLimit(r, phase);
b: Object  unaryDispatch(incrementTable, null, a, ArgumentListpositional: [], named: {}, phase);
writeReference(r, b, phase);
return getObject(a);
[FullPostfixExpression  PostfixExpressionOrSuper [no line break] --] do
if phase = compile then throw compileExpressionError end if;
r: ObjOrRefOptionalLimit  Eval[PostfixExpressionOrSuper](env, phase);
a: ObjOptionalLimit  readRefWithLimit(r, phase);
b: Object  unaryDispatch(decrementTable, null, a, ArgumentListpositional: [], named: {}, phase);
writeReference(r, b, phase);
return getObject(a)
end proc;
proc Eval[FullNewExpression] (env: Environment, phase: Phase): ObjOrRef
[FullNewExpression  new FullNewSubexpression Arguments] do
r: ObjOrRef  Eval[FullNewSubexpression](env, phase);
f: Object  readReference(r, phase);
args: ArgumentList  Eval[Arguments](env, phase);
return unaryDispatch(constructTable, null, f, args, phase);
[FullNewExpression  new FullSuperExpression Arguments] do
r: ObjOrRefOptionalLimit  Eval[FullSuperExpression](env, phase);
f: ObjOptionalLimit  readRefWithLimit(r, phase);
args: ArgumentList  Eval[Arguments](env, phase);
return unaryDispatch(constructTable, null, f, args, phase)
end proc;
proc Eval[FullNewSubexpression] (env: Environment, phase: Phase): ObjOrRef
[FullNewSubexpression  PrimaryExpression] do
return Eval[PrimaryExpression](env, phase);
[FullNewSubexpression  QualifiedIdentifier] do
return LexicalReferenceenv: env, variableMultiname: Multiname[QualifiedIdentifier], cxt: Context[FullNewSubexpression];
[FullNewSubexpression  FullNewExpression] do
return Eval[FullNewExpression](env, phase);
[FullNewSubexpression0  FullNewSubexpression1 MemberOperator] do
r: ObjOrRef  Eval[FullNewSubexpression1](env, phase);
a: Object  readReference(r, phase);
return Eval[MemberOperator](env, a, phase);
[FullNewSubexpression  SuperExpression DotOperator] do
r: ObjOrRefOptionalLimit  Eval[SuperExpression](env, phase);
a: ObjOptionalLimit  readRefWithLimit(r, phase);
return Eval[DotOperator](env, a, phase)
end proc;
proc Eval[ShortNewExpression] (env: Environment, phase: Phase): ObjOrRef
[ShortNewExpression  new ShortNewSubexpression] do
r: ObjOrRef  Eval[ShortNewSubexpression](env, phase);
f: Object  readReference(r, phase);
return unaryDispatch(constructTable, null, f, ArgumentListpositional: [], named: {}, phase);
[ShortNewExpression  new SuperExpression] do
r: ObjOrRefOptionalLimit  Eval[SuperExpression](env, phase);
f: ObjOptionalLimit  readRefWithLimit(r, phase);
return unaryDispatch(constructTable, null, f, ArgumentListpositional: [], named: {}, phase)
end proc;
Eval[ShortNewSubexpression]: Environment  Phase  ObjOrRef;
Eval[ShortNewSubexpression  FullNewSubexpression] = Eval[FullNewSubexpression];
Eval[ShortNewSubexpression  ShortNewExpression] = Eval[ShortNewExpression];
Member Operators
Syntax
MemberOperator 
	DotOperator
|	. ParenExpression
DotOperator 
	. QualifiedIdentifier
|	Brackets
Brackets 
	[ ]
|	[ ListExpressionallowIn ]
|	[ NamedArgumentList ]
Arguments 
	ParenExpressions
|	( NamedArgumentList )
ParenExpressions 
	( )
|	ParenListExpression
NamedArgumentList 
	LiteralField
|	ListExpressionallowIn , LiteralField
|	NamedArgumentList , LiteralField
Validation
proc Validate[MemberOperator] (cxt: Context, env: Environment)
[MemberOperator  DotOperator] do Validate[DotOperator](cxt, env);
[MemberOperator  . ParenExpression] do Validate[ParenExpression](cxt, env)
end proc;
proc Validate[DotOperator] (cxt: Context, env: Environment)
[DotOperator  . QualifiedIdentifier] do Validate[QualifiedIdentifier](cxt, env);
[DotOperator  Brackets] do Validate[Brackets](cxt, env)
end proc;
proc Validate[Brackets] (cxt: Context, env: Environment)
[Brackets  [ ]] do nothing;
[Brackets  [ ListExpressionallowIn ]] do Validate[ListExpressionallowIn](cxt, env);
[Brackets  [ NamedArgumentList ]] do Validate[NamedArgumentList](cxt, env)
end proc;
proc Validate[Arguments] (cxt: Context, env: Environment)
[Arguments  ParenExpressions] do Validate[ParenExpressions](cxt, env);
[Arguments  ( NamedArgumentList )] do Validate[NamedArgumentList](cxt, env)
end proc;
proc Validate[ParenExpressions] (cxt: Context, env: Environment)
[ParenExpressions  ( )] do nothing;
[ParenExpressions  ParenListExpression] do Validate[ParenListExpression](cxt, env)
end proc;
proc Validate[NamedArgumentList] (cxt: Context, env: Environment): String{}
[NamedArgumentList  LiteralField] do return Validate[LiteralField](cxt, env);
[NamedArgumentList  ListExpressionallowIn , LiteralField] do
Validate[ListExpressionallowIn](cxt, env);
return Validate[LiteralField](cxt, env);
[NamedArgumentList0  NamedArgumentList1 , LiteralField] do
names1: String{}  Validate[NamedArgumentList1](cxt, env);
names2: String{}  Validate[LiteralField](cxt, env);
if names1  names2 ≠ {} then throw syntaxError end if;
return names1  names2
end proc;
Evaluation
proc Eval[MemberOperator] (env: Environment, base: Object, phase: Phase): ObjOrRef
[MemberOperator  DotOperator] do return Eval[DotOperator](env, base, phase);
[MemberOperator  . ParenExpression] do ????
end proc;
proc Eval[DotOperator] (env: Environment, base: ObjOptionalLimit, phase: Phase): ObjOrRef
[DotOperator  . QualifiedIdentifier] do
return DotReferencebase: base, propertyMultiname: Multiname[QualifiedIdentifier];
[DotOperator  Brackets] do
args: ArgumentList  Eval[Brackets](env, phase);
return BracketReferencebase: base, args: args
end proc;
proc Eval[Brackets] (env: Environment, phase: Phase): ArgumentList
[Brackets  [ ]] do return ArgumentListpositional: [], named: {};
[Brackets  [ ListExpressionallowIn ]] do
positional: Object[]  EvalAsList[ListExpressionallowIn](env, phase);
return ArgumentListpositional: positional, named: {};
[Brackets  [ NamedArgumentList ]] do return Eval[NamedArgumentList](env, phase)
end proc;
proc Eval[Arguments] (env: Environment, phase: Phase): ArgumentList
[Arguments  ParenExpressions] do return Eval[ParenExpressions](env, phase);
[Arguments  ( NamedArgumentList )] do return Eval[NamedArgumentList](env, phase)
end proc;
proc Eval[ParenExpressions] (env: Environment, phase: Phase): ArgumentList
[ParenExpressions  ( )] do return ArgumentListpositional: [], named: {};
[ParenExpressions  ParenListExpression] do
positional: Object[]  EvalAsList[ParenListExpression](env, phase);
return ArgumentListpositional: positional, named: {}
end proc;
proc Eval[NamedArgumentList] (env: Environment, phase: Phase): ArgumentList
[NamedArgumentList  LiteralField] do
na: NamedArgument  Eval[LiteralField](env, phase);
return ArgumentListpositional: [], named: {na};
[NamedArgumentList  ListExpressionallowIn , LiteralField] do
positional: Object[]  EvalAsList[ListExpressionallowIn](env, phase);
na: NamedArgument  Eval[LiteralField](env, phase);
return ArgumentListpositional: positional, named: {na};
[NamedArgumentList0  NamedArgumentList1 , LiteralField] do
args: ArgumentList  Eval[NamedArgumentList1](env, phase);
na: NamedArgument  Eval[LiteralField](env, phase);
if some na2  args.named satisfies na2.name = na.name then
throw argumentMismatchError
end if;
return ArgumentListpositional: args.positional, named: args.named  {na}
end proc;
Unary Operators
Syntax
UnaryExpression 
	PostfixExpression
|	delete PostfixExpression
|	void UnaryExpression
|	typeof UnaryExpression
|	++ PostfixExpressionOrSuper
|	-- PostfixExpressionOrSuper
|	+ UnaryExpressionOrSuper
|	- UnaryExpressionOrSuper
|	~ UnaryExpressionOrSuper
|	! UnaryExpression
UnaryExpressionOrSuper 
	UnaryExpression
|	SuperExpression
Validation
proc Validate[UnaryExpression] (cxt: Context, env: Environment)
[UnaryExpression  PostfixExpression] do Validate[PostfixExpression](cxt, env);
[UnaryExpression  delete PostfixExpression] do
Validate[PostfixExpression](cxt, env);
[UnaryExpression0  void UnaryExpression1] do Validate[UnaryExpression1](cxt, env);
[UnaryExpression0  typeof UnaryExpression1] do
Validate[UnaryExpression1](cxt, env);
[UnaryExpression  ++ PostfixExpressionOrSuper] do
Validate[PostfixExpressionOrSuper](cxt, env);
[UnaryExpression  -- PostfixExpressionOrSuper] do
Validate[PostfixExpressionOrSuper](cxt, env);
[UnaryExpression  + UnaryExpressionOrSuper] do
Validate[UnaryExpressionOrSuper](cxt, env);
[UnaryExpression  - UnaryExpressionOrSuper] do
Validate[UnaryExpressionOrSuper](cxt, env);
[UnaryExpression  ~ UnaryExpressionOrSuper] do
Validate[UnaryExpressionOrSuper](cxt, env);
[UnaryExpression0  ! UnaryExpression1] do Validate[UnaryExpression1](cxt, env)
end proc;
Validate[UnaryExpressionOrSuper]: Context  Environment  ();
Validate[UnaryExpressionOrSuper  UnaryExpression] = Validate[UnaryExpression];
Validate[UnaryExpressionOrSuper  SuperExpression] = Validate[SuperExpression];
Evaluation
proc Eval[UnaryExpression] (env: Environment, phase: Phase): ObjOrRef
[UnaryExpression  PostfixExpression] do return Eval[PostfixExpression](env, phase);
[UnaryExpression  delete PostfixExpression] do
if phase = compile then throw compileExpressionError end if;
r: ObjOrRef  Eval[PostfixExpression](env, phase);
return deleteReference(r, phase);
[UnaryExpression0  void UnaryExpression1] do
r: ObjOrRef  Eval[UnaryExpression1](env, phase);
readReference(r, phase);
return undefined;
[UnaryExpression0  typeof UnaryExpression1] do
r: ObjOrRef  Eval[UnaryExpression1](env, phase);
a: Object  readReference(r, phase);
case a of
Undefined do return “undefined”;
Null  Prototype  Package  Global do return “object”;
Boolean do return “boolean”;
Float64 do return “number”;
String do return “string”;
Namespace do return “namespace”;
CompoundAttribute do return “attribute”;
Class  MethodClosure do return “function”;
Instance do return a.typeofString
end case;
[UnaryExpression  ++ PostfixExpressionOrSuper] do
if phase = compile then throw compileExpressionError end if;
r: ObjOrRefOptionalLimit  Eval[PostfixExpressionOrSuper](env, phase);
a: ObjOptionalLimit  readRefWithLimit(r, phase);
b: Object  unaryDispatch(incrementTable, null, a, ArgumentListpositional: [], named: {}, phase);
writeReference(r, b, phase);
return b;
[UnaryExpression  -- PostfixExpressionOrSuper] do
if phase = compile then throw compileExpressionError end if;
r: ObjOrRefOptionalLimit  Eval[PostfixExpressionOrSuper](env, phase);
a: ObjOptionalLimit  readRefWithLimit(r, phase);
b: Object  unaryDispatch(decrementTable, null, a, ArgumentListpositional: [], named: {}, phase);
writeReference(r, b, phase);
return b;
[UnaryExpression  + UnaryExpressionOrSuper] do
r: ObjOrRefOptionalLimit  Eval[UnaryExpressionOrSuper](env, phase);
a: ObjOptionalLimit  readRefWithLimit(r, phase);
return unaryPlus(a, phase);
[UnaryExpression  - UnaryExpressionOrSuper] do
r: ObjOrRefOptionalLimit  Eval[UnaryExpressionOrSuper](env, phase);
a: ObjOptionalLimit  readRefWithLimit(r, phase);
return unaryDispatch(minusTable, null, a, ArgumentListpositional: [], named: {}, phase);
[UnaryExpression  ~ UnaryExpressionOrSuper] do
r: ObjOrRefOptionalLimit  Eval[UnaryExpressionOrSuper](env, phase);
a: ObjOptionalLimit  readRefWithLimit(r, phase);
return unaryDispatch(bitwiseNotTable, null, a, ArgumentListpositional: [], named: {}, phase);
[UnaryExpression0  ! UnaryExpression1] do
r: ObjOrRef  Eval[UnaryExpression1](env, phase);
a: Object  readReference(r, phase);
return unaryNot(a, phase)
end proc;
Eval[UnaryExpressionOrSuper]: Environment  Phase  ObjOrRefOptionalLimit;
Eval[UnaryExpressionOrSuper  UnaryExpression] = Eval[UnaryExpression];
Eval[UnaryExpressionOrSuper  SuperExpression] = Eval[SuperExpression];
Multiplicative Operators
Syntax
MultiplicativeExpression 
	UnaryExpression
|	MultiplicativeExpressionOrSuper * UnaryExpressionOrSuper
|	MultiplicativeExpressionOrSuper / UnaryExpressionOrSuper
|	MultiplicativeExpressionOrSuper % UnaryExpressionOrSuper
MultiplicativeExpressionOrSuper 
	MultiplicativeExpression
|	SuperExpression
Validation
proc Validate[MultiplicativeExpression] (cxt: Context, env: Environment)
[MultiplicativeExpression  UnaryExpression] do Validate[UnaryExpression](cxt, env);
[MultiplicativeExpression  MultiplicativeExpressionOrSuper * UnaryExpressionOrSuper] do
Validate[MultiplicativeExpressionOrSuper](cxt, env);
Validate[UnaryExpressionOrSuper](cxt, env);
[MultiplicativeExpression  MultiplicativeExpressionOrSuper / UnaryExpressionOrSuper] do
Validate[MultiplicativeExpressionOrSuper](cxt, env);
Validate[UnaryExpressionOrSuper](cxt, env);
[MultiplicativeExpression  MultiplicativeExpressionOrSuper % UnaryExpressionOrSuper] do
Validate[MultiplicativeExpressionOrSuper](cxt, env);
Validate[UnaryExpressionOrSuper](cxt, env)
end proc;
Validate[MultiplicativeExpressionOrSuper]: Context  Environment  ();
Validate[MultiplicativeExpressionOrSuper  MultiplicativeExpression] = Validate[MultiplicativeExpression];
Validate[MultiplicativeExpressionOrSuper  SuperExpression] = Validate[SuperExpression];
Evaluation
proc Eval[MultiplicativeExpression] (env: Environment, phase: Phase): ObjOrRef
[MultiplicativeExpression  UnaryExpression] do
return Eval[UnaryExpression](env, phase);
[MultiplicativeExpression  MultiplicativeExpressionOrSuper * UnaryExpressionOrSuper] do
ra: ObjOrRefOptionalLimit  Eval[MultiplicativeExpressionOrSuper](env, phase);
a: ObjOptionalLimit  readRefWithLimit(ra, phase);
rb: ObjOrRefOptionalLimit  Eval[UnaryExpressionOrSuper](env, phase);
b: ObjOptionalLimit  readRefWithLimit(rb, phase);
return binaryDispatch(multiplyTable, a, b, phase);
[MultiplicativeExpression  MultiplicativeExpressionOrSuper / UnaryExpressionOrSuper] do
ra: ObjOrRefOptionalLimit  Eval[MultiplicativeExpressionOrSuper](env, phase);
a: ObjOptionalLimit  readRefWithLimit(ra, phase);
rb: ObjOrRefOptionalLimit  Eval[UnaryExpressionOrSuper](env, phase);
b: ObjOptionalLimit  readRefWithLimit(rb, phase);
return binaryDispatch(divideTable, a, b, phase);
[MultiplicativeExpression  MultiplicativeExpressionOrSuper % UnaryExpressionOrSuper] do
ra: ObjOrRefOptionalLimit  Eval[MultiplicativeExpressionOrSuper](env, phase);
a: ObjOptionalLimit  readRefWithLimit(ra, phase);
rb: ObjOrRefOptionalLimit  Eval[UnaryExpressionOrSuper](env, phase);
b: ObjOptionalLimit  readRefWithLimit(rb, phase);
return binaryDispatch(remainderTable, a, b, phase)
end proc;
Eval[MultiplicativeExpressionOrSuper]: Environment  Phase  ObjOrRefOptionalLimit;
Eval[MultiplicativeExpressionOrSuper  MultiplicativeExpression] = Eval[MultiplicativeExpression];
Eval[MultiplicativeExpressionOrSuper  SuperExpression] = Eval[SuperExpression];
Additive Operators
Syntax
AdditiveExpression 
	MultiplicativeExpression
|	AdditiveExpressionOrSuper + MultiplicativeExpressionOrSuper
|	AdditiveExpressionOrSuper - MultiplicativeExpressionOrSuper
AdditiveExpressionOrSuper 
	AdditiveExpression
|	SuperExpression
Validation
proc Validate[AdditiveExpression] (cxt: Context, env: Environment)
[AdditiveExpression  MultiplicativeExpression] do
Validate[MultiplicativeExpression](cxt, env);
[AdditiveExpression  AdditiveExpressionOrSuper + MultiplicativeExpressionOrSuper] do
Validate[AdditiveExpressionOrSuper](cxt, env);
Validate[MultiplicativeExpressionOrSuper](cxt, env);
[AdditiveExpression  AdditiveExpressionOrSuper - MultiplicativeExpressionOrSuper] do
Validate[AdditiveExpressionOrSuper](cxt, env);
Validate[MultiplicativeExpressionOrSuper](cxt, env)
end proc;
Validate[AdditiveExpressionOrSuper]: Context  Environment  ();
Validate[AdditiveExpressionOrSuper  AdditiveExpression] = Validate[AdditiveExpression];
Validate[AdditiveExpressionOrSuper  SuperExpression] = Validate[SuperExpression];
Evaluation
proc Eval[AdditiveExpression] (env: Environment, phase: Phase): ObjOrRef
[AdditiveExpression  MultiplicativeExpression] do
return Eval[MultiplicativeExpression](env, phase);
[AdditiveExpression  AdditiveExpressionOrSuper + MultiplicativeExpressionOrSuper] do
ra: ObjOrRefOptionalLimit  Eval[AdditiveExpressionOrSuper](env, phase);
a: ObjOptionalLimit  readRefWithLimit(ra, phase);
rb: ObjOrRefOptionalLimit  Eval[MultiplicativeExpressionOrSuper](env, phase);
b: ObjOptionalLimit  readRefWithLimit(rb, phase);
return binaryDispatch(addTable, a, b, phase);
[AdditiveExpression  AdditiveExpressionOrSuper - MultiplicativeExpressionOrSuper] do
ra: ObjOrRefOptionalLimit  Eval[AdditiveExpressionOrSuper](env, phase);
a: ObjOptionalLimit  readRefWithLimit(ra, phase);
rb: ObjOrRefOptionalLimit  Eval[MultiplicativeExpressionOrSuper](env, phase);
b: ObjOptionalLimit  readRefWithLimit(rb, phase);
return binaryDispatch(subtractTable, a, b, phase)
end proc;
Eval[AdditiveExpressionOrSuper]: Environment  Phase  ObjOrRefOptionalLimit;
Eval[AdditiveExpressionOrSuper  AdditiveExpression] = Eval[AdditiveExpression];
Eval[AdditiveExpressionOrSuper  SuperExpression] = Eval[SuperExpression];
Bitwise Shift Operators
Syntax
ShiftExpression 
	AdditiveExpression
|	ShiftExpressionOrSuper << AdditiveExpressionOrSuper
|	ShiftExpressionOrSuper >> AdditiveExpressionOrSuper
|	ShiftExpressionOrSuper >>> AdditiveExpressionOrSuper
ShiftExpressionOrSuper 
	ShiftExpression
|	SuperExpression
Validation
proc Validate[ShiftExpression] (cxt: Context, env: Environment)
[ShiftExpression  AdditiveExpression] do Validate[AdditiveExpression](cxt, env);
[ShiftExpression  ShiftExpressionOrSuper << AdditiveExpressionOrSuper] do
Validate[ShiftExpressionOrSuper](cxt, env);
Validate[AdditiveExpressionOrSuper](cxt, env);
[ShiftExpression  ShiftExpressionOrSuper >> AdditiveExpressionOrSuper] do
Validate[ShiftExpressionOrSuper](cxt, env);
Validate[AdditiveExpressionOrSuper](cxt, env);
[ShiftExpression  ShiftExpressionOrSuper >>> AdditiveExpressionOrSuper] do
Validate[ShiftExpressionOrSuper](cxt, env);
Validate[AdditiveExpressionOrSuper](cxt, env)
end proc;
Validate[ShiftExpressionOrSuper]: Context  Environment  ();
Validate[ShiftExpressionOrSuper  ShiftExpression] = Validate[ShiftExpression];
Validate[ShiftExpressionOrSuper  SuperExpression] = Validate[SuperExpression];
Evaluation
proc Eval[ShiftExpression] (env: Environment, phase: Phase): ObjOrRef
[ShiftExpression  AdditiveExpression] do
return Eval[AdditiveExpression](env, phase);
[ShiftExpression  ShiftExpressionOrSuper << AdditiveExpressionOrSuper] do
ra: ObjOrRefOptionalLimit  Eval[ShiftExpressionOrSuper](env, phase);
a: ObjOptionalLimit  readRefWithLimit(ra, phase);
rb: ObjOrRefOptionalLimit  Eval[AdditiveExpressionOrSuper](env, phase);
b: ObjOptionalLimit  readRefWithLimit(rb, phase);
return binaryDispatch(shiftLeftTable, a, b, phase);
[ShiftExpression  ShiftExpressionOrSuper >> AdditiveExpressionOrSuper] do
ra: ObjOrRefOptionalLimit  Eval[ShiftExpressionOrSuper](env, phase);
a: ObjOptionalLimit  readRefWithLimit(ra, phase);
rb: ObjOrRefOptionalLimit  Eval[AdditiveExpressionOrSuper](env, phase);
b: ObjOptionalLimit  readRefWithLimit(rb, phase);
return binaryDispatch(shiftRightTable, a, b, phase);
[ShiftExpression  ShiftExpressionOrSuper >>> AdditiveExpressionOrSuper] do
ra: ObjOrRefOptionalLimit  Eval[ShiftExpressionOrSuper](env, phase);
a: ObjOptionalLimit  readRefWithLimit(ra, phase);
rb: ObjOrRefOptionalLimit  Eval[AdditiveExpressionOrSuper](env, phase);
b: ObjOptionalLimit  readRefWithLimit(rb, phase);
return binaryDispatch(shiftRightUnsignedTable, a, b, phase)
end proc;
Eval[ShiftExpressionOrSuper]: Environment  Phase  ObjOrRefOptionalLimit;
Eval[ShiftExpressionOrSuper  ShiftExpression] = Eval[ShiftExpression];
Eval[ShiftExpressionOrSuper  SuperExpression] = Eval[SuperExpression];
Relational Operators
Syntax
RelationalExpressionallowIn 
	ShiftExpression
|	RelationalExpressionOrSuperallowIn < ShiftExpressionOrSuper
|	RelationalExpressionOrSuperallowIn > ShiftExpressionOrSuper
|	RelationalExpressionOrSuperallowIn <= ShiftExpressionOrSuper
|	RelationalExpressionOrSuperallowIn >= ShiftExpressionOrSuper
|	RelationalExpressionallowIn is ShiftExpression
|	RelationalExpressionallowIn as ShiftExpression
|	RelationalExpressionallowIn in ShiftExpressionOrSuper
|	RelationalExpressionallowIn instanceof ShiftExpression
RelationalExpressionnoIn 
	ShiftExpression
|	RelationalExpressionOrSupernoIn < ShiftExpressionOrSuper
|	RelationalExpressionOrSupernoIn > ShiftExpressionOrSuper
|	RelationalExpressionOrSupernoIn <= ShiftExpressionOrSuper
|	RelationalExpressionOrSupernoIn >= ShiftExpressionOrSuper
|	RelationalExpressionnoIn is ShiftExpression
|	RelationalExpressionnoIn as ShiftExpression
|	RelationalExpressionnoIn instanceof ShiftExpression
RelationalExpressionOrSuper 
	RelationalExpression
|	SuperExpression
Validation
proc Validate[RelationalExpression] (cxt: Context, env: Environment)
[RelationalExpression  ShiftExpression] do Validate[ShiftExpression](cxt, env);
[RelationalExpression  RelationalExpressionOrSuper < ShiftExpressionOrSuper] do
Validate[RelationalExpressionOrSuper](cxt, env);
Validate[ShiftExpressionOrSuper](cxt, env);
[RelationalExpression  RelationalExpressionOrSuper > ShiftExpressionOrSuper] do
Validate[RelationalExpressionOrSuper](cxt, env);
Validate[ShiftExpressionOrSuper](cxt, env);
[RelationalExpression  RelationalExpressionOrSuper <= ShiftExpressionOrSuper] do
Validate[RelationalExpressionOrSuper](cxt, env);
Validate[ShiftExpressionOrSuper](cxt, env);
[RelationalExpression  RelationalExpressionOrSuper >= ShiftExpressionOrSuper] do
Validate[RelationalExpressionOrSuper](cxt, env);
Validate[ShiftExpressionOrSuper](cxt, env);
[RelationalExpression0  RelationalExpression1 is ShiftExpression] do
Validate[RelationalExpression1](cxt, env);
Validate[ShiftExpression](cxt, env);
[RelationalExpression0  RelationalExpression1 as ShiftExpression] do
Validate[RelationalExpression1](cxt, env);
Validate[ShiftExpression](cxt, env);
[RelationalExpressionallowIn0  RelationalExpressionallowIn1 in ShiftExpressionOrSuper] do
Validate[RelationalExpressionallowIn1](cxt, env);
Validate[ShiftExpressionOrSuper](cxt, env);
[RelationalExpression0  RelationalExpression1 instanceof ShiftExpression] do
Validate[RelationalExpression1](cxt, env);
Validate[ShiftExpression](cxt, env)
end proc;
Validate[RelationalExpressionOrSuper]: Context  Environment  ();
Validate[RelationalExpressionOrSuper  RelationalExpression] = Validate[RelationalExpression];
Validate[RelationalExpressionOrSuper  SuperExpression] = Validate[SuperExpression];
Evaluation
proc Eval[RelationalExpression] (env: Environment, phase: Phase): ObjOrRef
[RelationalExpression  ShiftExpression] do
return Eval[ShiftExpression](env, phase);
[RelationalExpression  RelationalExpressionOrSuper < ShiftExpressionOrSuper] do
ra: ObjOrRefOptionalLimit  Eval[RelationalExpressionOrSuper](env, phase);
a: ObjOptionalLimit  readRefWithLimit(ra, phase);
rb: ObjOrRefOptionalLimit  Eval[ShiftExpressionOrSuper](env, phase);
b: ObjOptionalLimit  readRefWithLimit(rb, phase);
return binaryDispatch(lessTable, a, b, phase);
[RelationalExpression  RelationalExpressionOrSuper > ShiftExpressionOrSuper] do
ra: ObjOrRefOptionalLimit  Eval[RelationalExpressionOrSuper](env, phase);
a: ObjOptionalLimit  readRefWithLimit(ra, phase);
rb: ObjOrRefOptionalLimit  Eval[ShiftExpressionOrSuper](env, phase);
b: ObjOptionalLimit  readRefWithLimit(rb, phase);
return binaryDispatch(lessTable, b, a, phase);
[RelationalExpression  RelationalExpressionOrSuper <= ShiftExpressionOrSuper] do
ra: ObjOrRefOptionalLimit  Eval[RelationalExpressionOrSuper](env, phase);
a: ObjOptionalLimit  readRefWithLimit(ra, phase);
rb: ObjOrRefOptionalLimit  Eval[ShiftExpressionOrSuper](env, phase);
b: ObjOptionalLimit  readRefWithLimit(rb, phase);
return binaryDispatch(lessOrEqualTable, a, b, phase);
[RelationalExpression  RelationalExpressionOrSuper >= ShiftExpressionOrSuper] do
ra: ObjOrRefOptionalLimit  Eval[RelationalExpressionOrSuper](env, phase);
a: ObjOptionalLimit  readRefWithLimit(ra, phase);
rb: ObjOrRefOptionalLimit  Eval[ShiftExpressionOrSuper](env, phase);
b: ObjOptionalLimit  readRefWithLimit(rb, phase);
return binaryDispatch(lessOrEqualTable, b, a, phase);
[RelationalExpression  RelationalExpression is ShiftExpression] do ????;
[RelationalExpression  RelationalExpression as ShiftExpression] do ????;
[RelationalExpressionallowIn  RelationalExpressionallowIn in ShiftExpressionOrSuper] do
????;
[RelationalExpression  RelationalExpression instanceof ShiftExpression] do ????
end proc;
Eval[RelationalExpressionOrSuper]: Environment  Phase  ObjOrRefOptionalLimit;
Eval[RelationalExpressionOrSuper  RelationalExpression] = Eval[RelationalExpression];
Eval[RelationalExpressionOrSuper  SuperExpression] = Eval[SuperExpression];
Equality Operators
Syntax
EqualityExpression 
	RelationalExpression
|	EqualityExpressionOrSuper == RelationalExpressionOrSuper
|	EqualityExpressionOrSuper != RelationalExpressionOrSuper
|	EqualityExpressionOrSuper === RelationalExpressionOrSuper
|	EqualityExpressionOrSuper !== RelationalExpressionOrSuper
EqualityExpressionOrSuper 
	EqualityExpression
|	SuperExpression
Validation
proc Validate[EqualityExpression] (cxt: Context, env: Environment)
[EqualityExpression  RelationalExpression] do
Validate[RelationalExpression](cxt, env);
[EqualityExpression  EqualityExpressionOrSuper == RelationalExpressionOrSuper] do
Validate[EqualityExpressionOrSuper](cxt, env);
Validate[RelationalExpressionOrSuper](cxt, env);
[EqualityExpression  EqualityExpressionOrSuper != RelationalExpressionOrSuper] do
Validate[EqualityExpressionOrSuper](cxt, env);
Validate[RelationalExpressionOrSuper](cxt, env);
[EqualityExpression  EqualityExpressionOrSuper === RelationalExpressionOrSuper] do
Validate[EqualityExpressionOrSuper](cxt, env);
Validate[RelationalExpressionOrSuper](cxt, env);
[EqualityExpression  EqualityExpressionOrSuper !== RelationalExpressionOrSuper] do
Validate[EqualityExpressionOrSuper](cxt, env);
Validate[RelationalExpressionOrSuper](cxt, env)
end proc;
Validate[EqualityExpressionOrSuper]: Context  Environment  ();
Validate[EqualityExpressionOrSuper  EqualityExpression] = Validate[EqualityExpression];
Validate[EqualityExpressionOrSuper  SuperExpression] = Validate[SuperExpression];
Evaluation
proc Eval[EqualityExpression] (env: Environment, phase: Phase): ObjOrRef
[EqualityExpression  RelationalExpression] do
return Eval[RelationalExpression](env, phase);
[EqualityExpression  EqualityExpressionOrSuper == RelationalExpressionOrSuper] do
ra: ObjOrRefOptionalLimit  Eval[EqualityExpressionOrSuper](env, phase);
a: ObjOptionalLimit  readRefWithLimit(ra, phase);
rb: ObjOrRefOptionalLimit  Eval[RelationalExpressionOrSuper](env, phase);
b: ObjOptionalLimit  readRefWithLimit(rb, phase);
return binaryDispatch(equalTable, a, b, phase);
[EqualityExpression  EqualityExpressionOrSuper != RelationalExpressionOrSuper] do
ra: ObjOrRefOptionalLimit  Eval[EqualityExpressionOrSuper](env, phase);
a: ObjOptionalLimit  readRefWithLimit(ra, phase);
rb: ObjOrRefOptionalLimit  Eval[RelationalExpressionOrSuper](env, phase);
b: ObjOptionalLimit  readRefWithLimit(rb, phase);
c: Object  binaryDispatch(equalTable, a, b, phase);
return unaryNot(c, phase);
[EqualityExpression  EqualityExpressionOrSuper === RelationalExpressionOrSuper] do
ra: ObjOrRefOptionalLimit  Eval[EqualityExpressionOrSuper](env, phase);
a: ObjOptionalLimit  readRefWithLimit(ra, phase);
rb: ObjOrRefOptionalLimit  Eval[RelationalExpressionOrSuper](env, phase);
b: ObjOptionalLimit  readRefWithLimit(rb, phase);
return binaryDispatch(strictEqualTable, a, b, phase);
[EqualityExpression  EqualityExpressionOrSuper !== RelationalExpressionOrSuper] do
ra: ObjOrRefOptionalLimit  Eval[EqualityExpressionOrSuper](env, phase);
a: ObjOptionalLimit  readRefWithLimit(ra, phase);
rb: ObjOrRefOptionalLimit  Eval[RelationalExpressionOrSuper](env, phase);
b: ObjOptionalLimit  readRefWithLimit(rb, phase);
c: Object  binaryDispatch(strictEqualTable, a, b, phase);
return unaryNot(c, phase)
end proc;
Eval[EqualityExpressionOrSuper]: Environment  Phase  ObjOrRefOptionalLimit;
Eval[EqualityExpressionOrSuper  EqualityExpression] = Eval[EqualityExpression];
Eval[EqualityExpressionOrSuper  SuperExpression] = Eval[SuperExpression];
Binary Bitwise Operators
Syntax
BitwiseAndExpression 
	EqualityExpression
|	BitwiseAndExpressionOrSuper & EqualityExpressionOrSuper
BitwiseXorExpression 
	BitwiseAndExpression
|	BitwiseXorExpressionOrSuper ^ BitwiseAndExpressionOrSuper
BitwiseOrExpression 
	BitwiseXorExpression
|	BitwiseOrExpressionOrSuper | BitwiseXorExpressionOrSuper
BitwiseAndExpressionOrSuper 
	BitwiseAndExpression
|	SuperExpression
BitwiseXorExpressionOrSuper 
	BitwiseXorExpression
|	SuperExpression
BitwiseOrExpressionOrSuper 
	BitwiseOrExpression
|	SuperExpression
Validation
proc Validate[BitwiseAndExpression] (cxt: Context, env: Environment)
[BitwiseAndExpression  EqualityExpression] do
Validate[EqualityExpression](cxt, env);
[BitwiseAndExpression  BitwiseAndExpressionOrSuper & EqualityExpressionOrSuper] do
Validate[BitwiseAndExpressionOrSuper](cxt, env);
Validate[EqualityExpressionOrSuper](cxt, env)
end proc;
proc Validate[BitwiseXorExpression] (cxt: Context, env: Environment)
[BitwiseXorExpression  BitwiseAndExpression] do
Validate[BitwiseAndExpression](cxt, env);
[BitwiseXorExpression  BitwiseXorExpressionOrSuper ^ BitwiseAndExpressionOrSuper] do
Validate[BitwiseXorExpressionOrSuper](cxt, env);
Validate[BitwiseAndExpressionOrSuper](cxt, env)
end proc;
proc Validate[BitwiseOrExpression] (cxt: Context, env: Environment)
[BitwiseOrExpression  BitwiseXorExpression] do
Validate[BitwiseXorExpression](cxt, env);
[BitwiseOrExpression  BitwiseOrExpressionOrSuper | BitwiseXorExpressionOrSuper] do
Validate[BitwiseOrExpressionOrSuper](cxt, env);
Validate[BitwiseXorExpressionOrSuper](cxt, env)
end proc;
Validate[BitwiseAndExpressionOrSuper]: Context  Environment  ();
Validate[BitwiseAndExpressionOrSuper  BitwiseAndExpression] = Validate[BitwiseAndExpression];
Validate[BitwiseAndExpressionOrSuper  SuperExpression] = Validate[SuperExpression];
Validate[BitwiseXorExpressionOrSuper]: Context  Environment  ();
Validate[BitwiseXorExpressionOrSuper  BitwiseXorExpression] = Validate[BitwiseXorExpression];
Validate[BitwiseXorExpressionOrSuper  SuperExpression] = Validate[SuperExpression];
Validate[BitwiseOrExpressionOrSuper]: Context  Environment  ();
Validate[BitwiseOrExpressionOrSuper  BitwiseOrExpression] = Validate[BitwiseOrExpression];
Validate[BitwiseOrExpressionOrSuper  SuperExpression] = Validate[SuperExpression];
Evaluation
proc Eval[BitwiseAndExpression] (env: Environment, phase: Phase): ObjOrRef
[BitwiseAndExpression  EqualityExpression] do
return Eval[EqualityExpression](env, phase);
[BitwiseAndExpression  BitwiseAndExpressionOrSuper & EqualityExpressionOrSuper] do
ra: ObjOrRefOptionalLimit  Eval[BitwiseAndExpressionOrSuper](env, phase);
a: ObjOptionalLimit  readRefWithLimit(ra, phase);
rb: ObjOrRefOptionalLimit  Eval[EqualityExpressionOrSuper](env, phase);
b: ObjOptionalLimit  readRefWithLimit(rb, phase);
return binaryDispatch(bitwiseAndTable, a, b, phase)
end proc;
proc Eval[BitwiseXorExpression] (env: Environment, phase: Phase): ObjOrRef
[BitwiseXorExpression  BitwiseAndExpression] do
return Eval[BitwiseAndExpression](env, phase);
[BitwiseXorExpression  BitwiseXorExpressionOrSuper ^ BitwiseAndExpressionOrSuper] do
ra: ObjOrRefOptionalLimit  Eval[BitwiseXorExpressionOrSuper](env, phase);
a: ObjOptionalLimit  readRefWithLimit(ra, phase);
rb: ObjOrRefOptionalLimit  Eval[BitwiseAndExpressionOrSuper](env, phase);
b: ObjOptionalLimit  readRefWithLimit(rb, phase);
return binaryDispatch(bitwiseXorTable, a, b, phase)
end proc;
proc Eval[BitwiseOrExpression] (env: Environment, phase: Phase): ObjOrRef
[BitwiseOrExpression  BitwiseXorExpression] do
return Eval[BitwiseXorExpression](env, phase);
[BitwiseOrExpression  BitwiseOrExpressionOrSuper | BitwiseXorExpressionOrSuper] do
ra: ObjOrRefOptionalLimit  Eval[BitwiseOrExpressionOrSuper](env, phase);
a: ObjOptionalLimit  readRefWithLimit(ra, phase);
rb: ObjOrRefOptionalLimit  Eval[BitwiseXorExpressionOrSuper](env, phase);
b: ObjOptionalLimit  readRefWithLimit(rb, phase);
return binaryDispatch(bitwiseOrTable, a, b, phase)
end proc;
Eval[BitwiseAndExpressionOrSuper]: Environment  Phase  ObjOrRefOptionalLimit;
Eval[BitwiseAndExpressionOrSuper  BitwiseAndExpression] = Eval[BitwiseAndExpression];
Eval[BitwiseAndExpressionOrSuper  SuperExpression] = Eval[SuperExpression];
Eval[BitwiseXorExpressionOrSuper]: Environment  Phase  ObjOrRefOptionalLimit;
Eval[BitwiseXorExpressionOrSuper  BitwiseXorExpression] = Eval[BitwiseXorExpression];
Eval[BitwiseXorExpressionOrSuper  SuperExpression] = Eval[SuperExpression];
Eval[BitwiseOrExpressionOrSuper]: Environment  Phase  ObjOrRefOptionalLimit;
Eval[BitwiseOrExpressionOrSuper  BitwiseOrExpression] = Eval[BitwiseOrExpression];
Eval[BitwiseOrExpressionOrSuper  SuperExpression] = Eval[SuperExpression];
Binary Logical Operators
Syntax
LogicalAndExpression 
	BitwiseOrExpression
|	LogicalAndExpression && BitwiseOrExpression
LogicalXorExpression 
	LogicalAndExpression
|	LogicalXorExpression ^^ LogicalAndExpression
LogicalOrExpression 
	LogicalXorExpression
|	LogicalOrExpression || LogicalXorExpression
Validation
proc Validate[LogicalAndExpression] (cxt: Context, env: Environment)
[LogicalAndExpression  BitwiseOrExpression] do
Validate[BitwiseOrExpression](cxt, env);
[LogicalAndExpression0  LogicalAndExpression1 && BitwiseOrExpression] do
Validate[LogicalAndExpression1](cxt, env);
Validate[BitwiseOrExpression](cxt, env)
end proc;
proc Validate[LogicalXorExpression] (cxt: Context, env: Environment)
[LogicalXorExpression  LogicalAndExpression] do
Validate[LogicalAndExpression](cxt, env);
[LogicalXorExpression0  LogicalXorExpression1 ^^ LogicalAndExpression] do
Validate[LogicalXorExpression1](cxt, env);
Validate[LogicalAndExpression](cxt, env)
end proc;
proc Validate[LogicalOrExpression] (cxt: Context, env: Environment)
[LogicalOrExpression  LogicalXorExpression] do
Validate[LogicalXorExpression](cxt, env);
[LogicalOrExpression0  LogicalOrExpression1 || LogicalXorExpression] do
Validate[LogicalOrExpression1](cxt, env);
Validate[LogicalXorExpression](cxt, env)
end proc;
Evaluation
proc Eval[LogicalAndExpression] (env: Environment, phase: Phase): ObjOrRef
[LogicalAndExpression  BitwiseOrExpression] do
return Eval[BitwiseOrExpression](env, phase);
[LogicalAndExpression0  LogicalAndExpression1 && BitwiseOrExpression] do
ra: ObjOrRef  Eval[LogicalAndExpression1](env, phase);
a: Object  readReference(ra, phase);
if toBoolean(a, phase) then
rb: ObjOrRef  Eval[BitwiseOrExpression](env, phase);
return readReference(rb, phase)
else return a
end if
end proc;
proc Eval[LogicalXorExpression] (env: Environment, phase: Phase): ObjOrRef
[LogicalXorExpression  LogicalAndExpression] do
return Eval[LogicalAndExpression](env, phase);
[LogicalXorExpression0  LogicalXorExpression1 ^^ LogicalAndExpression] do
ra: ObjOrRef  Eval[LogicalXorExpression1](env, phase);
a: Object  readReference(ra, phase);
rb: ObjOrRef  Eval[LogicalAndExpression](env, phase);
b: Object  readReference(rb, phase);
ba: Boolean  toBoolean(a, phase);
bb: Boolean  toBoolean(b, phase);
return ba xor bb
end proc;
proc Eval[LogicalOrExpression] (env: Environment, phase: Phase): ObjOrRef
[LogicalOrExpression  LogicalXorExpression] do
return Eval[LogicalXorExpression](env, phase);
[LogicalOrExpression0  LogicalOrExpression1 || LogicalXorExpression] do
ra: ObjOrRef  Eval[LogicalOrExpression1](env, phase);
a: Object  readReference(ra, phase);
if toBoolean(a, phase) then return a
else
rb: ObjOrRef  Eval[LogicalXorExpression](env, phase);
return readReference(rb, phase)
end if
end proc;
Conditional Operator
Syntax
ConditionalExpression 
	LogicalOrExpression
|	LogicalOrExpression ? AssignmentExpression : AssignmentExpression
NonAssignmentExpression 
	LogicalOrExpression
|	LogicalOrExpression ? NonAssignmentExpression : NonAssignmentExpression
Validation
proc Validate[ConditionalExpression] (cxt: Context, env: Environment)
[ConditionalExpression  LogicalOrExpression] do
Validate[LogicalOrExpression](cxt, env);
[ConditionalExpression  LogicalOrExpression ? AssignmentExpression1 : AssignmentExpression2] do
Validate[LogicalOrExpression](cxt, env);
Validate[AssignmentExpression1](cxt, env);
Validate[AssignmentExpression2](cxt, env)
end proc;
proc Validate[NonAssignmentExpression] (cxt: Context, env: Environment)
[NonAssignmentExpression  LogicalOrExpression] do
Validate[LogicalOrExpression](cxt, env);
[NonAssignmentExpression0  LogicalOrExpression ? NonAssignmentExpression1 : NonAssignmentExpression2] do
Validate[LogicalOrExpression](cxt, env);
Validate[NonAssignmentExpression1](cxt, env);
Validate[NonAssignmentExpression2](cxt, env)
end proc;
Evaluation
proc Eval[ConditionalExpression] (env: Environment, phase: Phase): ObjOrRef
[ConditionalExpression  LogicalOrExpression] do
return Eval[LogicalOrExpression](env, phase);
[ConditionalExpression  LogicalOrExpression ? AssignmentExpression1 : AssignmentExpression2] do
ra: ObjOrRef  Eval[LogicalOrExpression](env, phase);
a: Object  readReference(ra, phase);
if toBoolean(a, phase) then
rb: ObjOrRef  Eval[AssignmentExpression1](env, phase);
return readReference(rb, phase)
else
rc: ObjOrRef  Eval[AssignmentExpression2](env, phase);
return readReference(rc, phase)
end if
end proc;
proc Eval[NonAssignmentExpression] (env: Environment, phase: Phase): ObjOrRef
[NonAssignmentExpression  LogicalOrExpression] do
return Eval[LogicalOrExpression](env, phase);
[NonAssignmentExpression0  LogicalOrExpression ? NonAssignmentExpression1 : NonAssignmentExpression2] do
ra: ObjOrRef  Eval[LogicalOrExpression](env, phase);
a: Object  readReference(ra, phase);
if toBoolean(a, phase) then
rb: ObjOrRef  Eval[NonAssignmentExpression1](env, phase);
return readReference(rb, phase)
else
rc: ObjOrRef  Eval[NonAssignmentExpression2](env, phase);
return readReference(rc, phase)
end if
end proc;
Assignment Operators
Syntax
AssignmentExpression 
	ConditionalExpression
|	PostfixExpression = AssignmentExpression
|	PostfixExpressionOrSuper CompoundAssignment AssignmentExpression
|	PostfixExpressionOrSuper CompoundAssignment SuperExpression
|	PostfixExpression LogicalAssignment AssignmentExpression
CompoundAssignment 
	*=
|	/=
|	%=
|	+=
|	-=
|	<<=
|	>>=
|	>>>=
|	&=
|	^=
|	|=
LogicalAssignment 
	&&=
|	^^=
|	||=
Semantics
tag andEq;
tag xorEq;
tag orEq;
Validation
proc Validate[AssignmentExpression] (cxt: Context, env: Environment)
[AssignmentExpression  ConditionalExpression] do
Validate[ConditionalExpression](cxt, env);
[AssignmentExpression0  PostfixExpression = AssignmentExpression1] do
Validate[PostfixExpression](cxt, env);
Validate[AssignmentExpression1](cxt, env);
[AssignmentExpression0  PostfixExpressionOrSuper CompoundAssignment AssignmentExpression1] do
Validate[PostfixExpressionOrSuper](cxt, env);
Validate[AssignmentExpression1](cxt, env);
[AssignmentExpression  PostfixExpressionOrSuper CompoundAssignment SuperExpression] do
Validate[PostfixExpressionOrSuper](cxt, env);
Validate[SuperExpression](cxt, env);
[AssignmentExpression0  PostfixExpression LogicalAssignment AssignmentExpression1] do
Validate[PostfixExpression](cxt, env);
Validate[AssignmentExpression1](cxt, env)
end proc;
Evaluation
proc Eval[AssignmentExpression] (env: Environment, phase: Phase): ObjOrRef
[AssignmentExpression  ConditionalExpression] do
return Eval[ConditionalExpression](env, phase);
[AssignmentExpression0  PostfixExpression = AssignmentExpression1] do
if phase = compile then throw compileExpressionError end if;
ra: ObjOrRef  Eval[PostfixExpression](env, phase);
rb: ObjOrRef  Eval[AssignmentExpression1](env, phase);
b: Object  readReference(rb, phase);
writeReference(ra, b, phase);
return b;
[AssignmentExpression0  PostfixExpressionOrSuper CompoundAssignment AssignmentExpression1] do
if phase = compile then throw compileExpressionError end if;
return evalAssignmentOp(Table[CompoundAssignment], Eval[PostfixExpressionOrSuper], Eval[AssignmentExpression1], env, phase);
[AssignmentExpression  PostfixExpressionOrSuper CompoundAssignment SuperExpression] do
if phase = compile then throw compileExpressionError end if;
return evalAssignmentOp(Table[CompoundAssignment], Eval[PostfixExpressionOrSuper], Eval[SuperExpression], env, phase);
[AssignmentExpression0  PostfixExpression LogicalAssignment AssignmentExpression1] do
if phase = compile then throw compileExpressionError end if;
rLeft: ObjOrRef  Eval[PostfixExpression](env, phase);
oLeft: Object  readReference(rLeft, phase);
bLeft: Boolean  toBoolean(oLeft, phase);
result: Object  oLeft;
case Operator[LogicalAssignment] of
{andEq} do
if bLeft then
result  readReference(Eval[AssignmentExpression1](env, phase), phase)
end if;
{xorEq} do
bRight: Boolean  toBoolean(readReference(Eval[AssignmentExpression1](env, phase), phase), phase);
result  bLeft xor bRight;
{orEq} do
if not bLeft then
result  readReference(Eval[AssignmentExpression1](env, phase), phase)
end if
end case;
writeReference(rLeft, result, phase);
return result
end proc;
Table[CompoundAssignment]: BinaryMethod{};
Table[CompoundAssignment  *=] = multiplyTable;
Table[CompoundAssignment  /=] = divideTable;
Table[CompoundAssignment  %=] = remainderTable;
Table[CompoundAssignment  +=] = addTable;
Table[CompoundAssignment  -=] = subtractTable;
Table[CompoundAssignment  <<=] = shiftLeftTable;
Table[CompoundAssignment  >>=] = shiftRightTable;
Table[CompoundAssignment  >>>=] = shiftRightUnsignedTable;
Table[CompoundAssignment  &=] = bitwiseAndTable;
Table[CompoundAssignment  ^=] = bitwiseXorTable;
Table[CompoundAssignment  |=] = bitwiseOrTable;
Operator[LogicalAssignment]: {andEq, xorEq, orEq};
Operator[LogicalAssignment  &&=] = andEq;
Operator[LogicalAssignment  ^^=] = xorEq;
Operator[LogicalAssignment  ||=] = orEq;
proc evalAssignmentOp(table: BinaryMethod{}, leftEval: Environment  Phase  ObjOrRefOptionalLimit, rightEval: Environment  Phase  ObjOrRefOptionalLimit, env: Environment, phase: {run}): ObjOrRef
rLeft: ObjOrRefOptionalLimit  leftEval(env, phase);
oLeft: ObjOptionalLimit  readRefWithLimit(rLeft, phase);
rRight: ObjOrRefOptionalLimit  rightEval(env, phase);
oRight: ObjOptionalLimit  readRefWithLimit(rRight, phase);
result: Object  binaryDispatch(table, oLeft, oRight, phase);
writeReference(rLeft, result, phase);
return result
end proc;
Comma Expressions
Syntax
ListExpression 
	AssignmentExpression
|	ListExpression , AssignmentExpression
OptionalExpression 
	ListExpressionallowIn
|	«empty»
Validation
proc Validate[ListExpression] (cxt: Context, env: Environment)
[ListExpression  AssignmentExpression] do
Validate[AssignmentExpression](cxt, env);
[ListExpression0  ListExpression1 , AssignmentExpression] do
Validate[ListExpression1](cxt, env);
Validate[AssignmentExpression](cxt, env)
end proc;
Evaluation
proc Eval[ListExpression] (env: Environment, phase: Phase): ObjOrRef
[ListExpression  AssignmentExpression] do
return Eval[AssignmentExpression](env, phase);
[ListExpression0  ListExpression1 , AssignmentExpression] do
ra: ObjOrRef  Eval[ListExpression1](env, phase);
readReference(ra, phase);
rb: ObjOrRef  Eval[AssignmentExpression](env, phase);
return readReference(rb, phase)
end proc;
proc EvalAsList[ListExpression] (env: Environment, phase: Phase): Object[]
[ListExpression  AssignmentExpression] do
r: ObjOrRef  Eval[AssignmentExpression](env, phase);
elt: Object  readReference(r, phase);
return [elt];
[ListExpression0  ListExpression1 , AssignmentExpression] do
elts: Object[]  EvalAsList[ListExpression1](env, phase);
r: ObjOrRef  Eval[AssignmentExpression](env, phase);
elt: Object  readReference(r, phase);
return elts  [elt]
end proc;
Type Expressions
Syntax
TypeExpression  NonAssignmentExpression
Validation
proc Validate[TypeExpression  NonAssignmentExpression] (cxt: Context, env: Environment)
Validate[NonAssignmentExpression](cxt, env)
end proc;
Evaluation
proc Eval[TypeExpression  NonAssignmentExpression] (env: Environment): Class
r: ObjOrRef  Eval[NonAssignmentExpression](env, compile);
o: Object  readReference(r, compile);
if o  Class then throw badValueError end if;
return o
end proc;
Statements
Syntax
  {abbrev, noShortIf, full}
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] (cxt: Context, env: Environment, sl: Label{}, jt: JumpTargets, pl: Plurality)
[Statement  ExpressionStatement Semicolon] do
Validate[ExpressionStatement](cxt, env);
[Statement  SuperStatement Semicolon] do Validate[SuperStatement](cxt, env);
[Statement  Block] do Validate[Block](cxt, env, jt, pl);
[Statement  LabeledStatement] do Validate[LabeledStatement](cxt, env, sl, jt);
[Statement  IfStatement] do Validate[IfStatement](cxt, env, jt);
[Statement  SwitchStatement] do ????;
[Statement  DoStatement Semicolon] do Validate[DoStatement](cxt, env, sl, jt);
[Statement  WhileStatement] do Validate[WhileStatement](cxt, env, sl, jt);
[Statement  ForStatement] do ????;
[Statement  WithStatement] do ????;
[Statement  ContinueStatement Semicolon] do Validate[ContinueStatement](jt);
[Statement  BreakStatement Semicolon] do Validate[BreakStatement](jt);
[Statement  ReturnStatement Semicolon] do Validate[ReturnStatement](cxt, env);
[Statement  ThrowStatement Semicolon] do Validate[ThrowStatement](cxt, env);
[Statement  TryStatement] do ????
end proc;
Enabled[Substatement]: Boolean;
proc Validate[Substatement] (cxt: Context, env: Environment, sl: Label{}, jt: JumpTargets)
[Substatement  EmptyStatement] do nothing;
[Substatement  Statement] do Validate[Statement](cxt, env, sl, jt, plural);
[Substatement  SimpleVariableDefinition Semicolon] do
Validate[SimpleVariableDefinition](cxt, env);
[Substatement  Attributes [no line break] { Substatements }] do
Validate[Attributes](cxt, env);
attr: Attribute  Eval[Attributes](env, compile);
if attr  Boolean then throw badValueError end if;
Enabled[Substatement]  attr;
if attr then Validate[Substatements](cxt, env, jt) end if
end proc;
proc Validate[Substatements] (cxt: Context, env: Environment, jt: JumpTargets)
[Substatements  «empty»] do nothing;
[Substatements  SubstatementsPrefix Substatementabbrev] do
Validate[SubstatementsPrefix](cxt, env, jt);
Validate[Substatementabbrev](cxt, env, {}, jt)
end proc;
proc Validate[SubstatementsPrefix] (cxt: Context, env: Environment, jt: JumpTargets)
[SubstatementsPrefix  «empty»] do nothing;
[SubstatementsPrefix0  SubstatementsPrefix1 Substatementfull] do
Validate[SubstatementsPrefix1](cxt, env, jt);
Validate[Substatementfull](cxt, env, {}, jt)
end proc;
Evaluation
proc Eval[Statement] (env: Environment, d: Object): Object
[Statement  ExpressionStatement Semicolon] do
return Eval[ExpressionStatement](env);
[Statement  SuperStatement Semicolon] do return Eval[SuperStatement](env);
[Statement  Block] do return Eval[Block](env, d);
[Statement  LabeledStatement] do return Eval[LabeledStatement](env, d);
[Statement  IfStatement] do return Eval[IfStatement](env, d);
[Statement  SwitchStatement] do ????;
[Statement  DoStatement Semicolon] do return Eval[DoStatement](env, d);
[Statement  WhileStatement] do return Eval[WhileStatement](env, d);
[Statement  ForStatement] do ????;
[Statement  WithStatement] do ????;
[Statement  ContinueStatement Semicolon] do
return Eval[ContinueStatement](env, d);
[Statement  BreakStatement Semicolon] do return Eval[BreakStatement](env, d);
[Statement  ReturnStatement Semicolon] do return Eval[ReturnStatement](env);
[Statement  ThrowStatement Semicolon] do return Eval[ThrowStatement](env);
[Statement  TryStatement] do ????
end proc;
proc Eval[Substatement] (env: Environment, d: Object): Object
[Substatement  EmptyStatement] do return d;
[Substatement  Statement] do return Eval[Statement](env, d);
[Substatement  SimpleVariableDefinition Semicolon] do
return Eval[SimpleVariableDefinition](env, d);
[Substatement  Attributes [no line break] { Substatements }] do
if Enabled[Substatement] then return Eval[Substatements](env, d)
else return d
end if
end proc;
proc Eval[Substatements] (env: Environment, d: Object): Object
[Substatements  «empty»] do return d;
[Substatements  SubstatementsPrefix Substatementabbrev] do
o: Object  Eval[SubstatementsPrefix](env, d);
return Eval[Substatementabbrev](env, o)
end proc;
proc Eval[SubstatementsPrefix] (env: Environment, d: Object): Object
[SubstatementsPrefix  «empty»] do return d;
[SubstatementsPrefix0  SubstatementsPrefix1 Substatementfull] do
o: Object  Eval[SubstatementsPrefix1](env, d);
return Eval[Substatementfull](env, o)
end proc;
Empty Statement
Syntax
EmptyStatement  ;
Expression Statement
Syntax
ExpressionStatement  [lookahead{function, {}] ListExpressionallowIn
Validation
proc Validate[ExpressionStatement  [lookahead{function, {}] ListExpressionallowIn] (cxt: Context, env: Environment)
Validate[ListExpressionallowIn](cxt, env)
end proc;
Evaluation
proc Eval[ExpressionStatement  [lookahead{function, {}] ListExpressionallowIn] (env: Environment): Object
r: ObjOrRef  Eval[ListExpressionallowIn](env, run);
return readReference(r, run)
end proc;
Super Statement
Syntax
SuperStatement  super Arguments
Validation
proc Validate[SuperStatement  super Arguments] (cxt: Context, env: Environment)
????
end proc;
Evaluation
proc Eval[SuperStatement  super Arguments] (env: Environment): Object
????
end proc;
Block Statement
Syntax
Block  { Directives }
Validation
proc Validate[Block  { Directives }] (cxt: Context, env: Environment, jt: JumpTargets, pl: Plurality)
compileFrame: BlockFrame  new BlockFramestaticReadBindings: {}, staticWriteBindings: {}, plurality: pl;
CompileFrame[Block]  compileFrame;
Validate[Directives](cxt, [compileFrame]  env, jt, pl, none)
end proc;
proc ValidateUsingFrame[Block  { Directives }] (cxt: Context, env: Environment, jt: JumpTargets, pl: Plurality, frame: Frame)
Validate[Directives](cxt, [frame]  env, jt, pl, none)
end proc;
Evaluation
proc Eval[Block  { Directives }] (env: Environment, d: Object): Object
compileFrame: BlockFrame  CompileFrame[Block];
runtimeFrame: BlockFrame  instantiateBlockFrame(compileFrame);
return Eval[Directives]([runtimeFrame]  env, d)
end proc;
proc EvalUsingFrame[Block  { Directives }] (env: Environment, frame: Frame, d: Object): Object
return Eval[Directives]([frame]  env, d)
end proc;
CompileFrame[Block]: BlockFrame;
Labeled Statements
Syntax
LabeledStatement  Identifier : Substatement
Validation
proc Validate[LabeledStatement  Identifier : Substatement] (cxt: Context, env: Environment, sl: Label{}, jt: JumpTargets)
name: String  Name[Identifier];
if name  jt.breakTargets then throw syntaxError end if;
jt2: JumpTargets  JumpTargetsbreakTargets: jt.breakTargets  {name}, continueTargets: jt.continueTargets;
Validate[Substatement](cxt, env, sl  {name}, jt2)
end proc;
Evaluation
proc Eval[LabeledStatement  Identifier : Substatement] (env: Environment, d: Object): Object
try return Eval[Substatement](env, d)
catch x: SemanticException do
if x  Break and x.label = Name[Identifier] then 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] (cxt: Context, env: Environment, jt: JumpTargets)
[IfStatementabbrev  if ParenListExpression Substatementabbrev] do
Validate[ParenListExpression](cxt, env);
Validate[Substatementabbrev](cxt, env, {}, jt);
[IfStatementfull  if ParenListExpression Substatementfull] do
Validate[ParenListExpression](cxt, env);
Validate[Substatementfull](cxt, env, {}, jt);
[IfStatement  if ParenListExpression SubstatementnoShortIf1 else Substatement2] do
Validate[ParenListExpression](cxt, env);
Validate[SubstatementnoShortIf1](cxt, env, {}, jt);
Validate[Substatement2](cxt, env, {}, jt)
end proc;
Evaluation
proc Eval[IfStatement] (env: Environment, d: Object): Object
[IfStatementabbrev  if ParenListExpression Substatementabbrev] do
r: ObjOrRef  Eval[ParenListExpression](env, run);
o: Object  readReference(r, run);
if toBoolean(o, run) then return Eval[Substatementabbrev](env, d)
else return d
end if;
[IfStatementfull  if ParenListExpression Substatementfull] do
r: ObjOrRef  Eval[ParenListExpression](env, run);
o: Object  readReference(r, run);
if toBoolean(o, run) then return Eval[Substatementfull](env, d)
else return d
end if;
[IfStatement  if ParenListExpression SubstatementnoShortIf1 else Substatement2] do
r: ObjOrRef  Eval[ParenListExpression](env, run);
o: Object  readReference(r, run);
if toBoolean(o, run) then return Eval[SubstatementnoShortIf1](env, d)
else return Eval[Substatement2](env, d)
end if
end proc;
Switch Statement
Syntax
SwitchStatement  switch ParenListExpression { CaseStatements }
CaseStatements 
	«empty»
|	CaseLabel
|	CaseLabel CaseStatementsPrefix CaseStatementabbrev
CaseStatementsPrefix 
	«empty»
|	CaseStatementsPrefix CaseStatementfull
CaseStatement 
	Substatement
|	CaseLabel
CaseLabel 
	case ListExpressionallowIn :
|	default :
Do-While Statement
Syntax
DoStatement  do Substatementabbrev while ParenListExpression
Validation
Labels[DoStatement]: Label{};
proc Validate[DoStatement  do Substatementabbrev while ParenListExpression] (cxt: Context, env: Environment, sl: Label{}, jt: JumpTargets)
continueLabels: Label{}  sl  {default};
Labels[DoStatement]  continueLabels;
jt2: JumpTargets  JumpTargetsbreakTargets: jt.breakTargets  {default}, continueTargets: jt.continueTargets  continueLabels;
Validate[Substatementabbrev](cxt, env, {}, jt2);
Validate[ParenListExpression](cxt, env)
end proc;
Evaluation
proc Eval[DoStatement  do Substatementabbrev while ParenListExpression] (env: Environment, d: Object): Object
try
d1: Object  d;
while true do
try d1  Eval[Substatementabbrev](env, d1)
catch x: SemanticException do
if x  Continue and x.label  Labels[DoStatement] then d1  x.value
else throw x
end if
end try;
r: ObjOrRef  Eval[ParenListExpression](env, run);
o: Object  readReference(r, run);
if not toBoolean(o, run) then return d1 end if
end while
catch x: SemanticException 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] (cxt: Context, env: Environment, sl: Label{}, jt: JumpTargets)
Validate[ParenListExpression](cxt, env);
continueLabels: Label{}  sl  {default};
Labels[WhileStatement]  continueLabels;
jt2: JumpTargets  JumpTargetsbreakTargets: jt.breakTargets  {default}, continueTargets: jt.continueTargets  continueLabels;
Validate[Substatement](cxt, env, {}, jt2)
end proc;
Evaluation
proc Eval[WhileStatement  while ParenListExpression Substatement] (env: Environment, d: Object): Object
try
d1: Object  d;
while toBoolean(readReference(Eval[ParenListExpression](env, run), run), run) do
try d1  Eval[Substatement](env, d1)
catch x: SemanticException do
if x  Continue and x.label  Labels[WhileStatement] then
d1  x.value
else throw x
end if
end try
end while;
return d1
catch x: SemanticException 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 ( ForInitialiser ; OptionalExpression ; OptionalExpression ) Substatement
|	for ( ForInBinding in ListExpressionallowIn ) Substatement
ForInitialiser 
	«empty»
|	ListExpressionnoIn
|	VariableDefinitionKind VariableBindingListnoIn
|	Attributes [no line break] VariableDefinitionKind VariableBindingListnoIn
ForInBinding 
	PostfixExpression
|	VariableDefinitionKind VariableBindingnoIn
|	Attributes [no line break] VariableDefinitionKind VariableBindingnoIn
With Statement
Syntax
WithStatement  with ParenListExpression Substatement
Continue and Break Statements
Syntax
ContinueStatement 
	continue
|	continue [no line break] Identifier
BreakStatement 
	break
|	break [no line break] Identifier
Validation
proc Validate[ContinueStatement] (jt: JumpTargets)
[ContinueStatement  continue] do
if default  jt.continueTargets then throw syntaxError end if;
[ContinueStatement  continue [no line break] Identifier] do
if Name[Identifier]  jt.continueTargets then throw syntaxError end if
end proc;
proc Validate[BreakStatement] (jt: JumpTargets)
[BreakStatement  break] do
if default  jt.breakTargets then throw syntaxError end if;
[BreakStatement  break [no line break] Identifier] do
if Name[Identifier]  jt.breakTargets then throw syntaxError end if
end proc;
Evaluation
proc Eval[ContinueStatement] (env: Environment, d: Object): Object
[ContinueStatement  continue] do throw Continuevalue: d, label: default;
[ContinueStatement  continue [no line break] Identifier] do
throw Continuevalue: d, label: Name[Identifier]
end proc;
proc Eval[BreakStatement] (env: Environment, d: Object): Object
[BreakStatement  break] do throw Breakvalue: d, label: default;
[BreakStatement  break [no line break] Identifier] do
throw Breakvalue: d, label: Name[Identifier]
end proc;
Return Statement
Syntax
ReturnStatement 
	return
|	return [no line break] ListExpressionallowIn
Validation
proc Validate[ReturnStatement] (cxt: Context, env: Environment)
[ReturnStatement  return] do
if getRegionalFrame(env)  FunctionFrame then throw syntaxError end if;
[ReturnStatement  return [no line break] ListExpressionallowIn] do
if getRegionalFrame(env)  FunctionFrame then throw syntaxError end if;
Validate[ListExpressionallowIn](cxt, env)
end proc;
Evaluation
proc Eval[ReturnStatement] (env: Environment): Object
[ReturnStatement  return] do throw ReturnedValuevalue: undefined;
[ReturnStatement  return [no line break] ListExpressionallowIn] do
r: ObjOrRef  Eval[ListExpressionallowIn](env, run);
a: Object  readReference(r, run);
throw ReturnedValuevalue: a
end proc;
Throw Statement
Syntax
ThrowStatement  throw [no line break] ListExpressionallowIn
Validation
Validate[ThrowStatement  throw [no line break] ListExpressionallowIn]: Context  Environment  () = Validate[ListExpressionallowIn];
Evaluation
proc Eval[ThrowStatement  throw [no line break] ListExpressionallowIn] (env: Environment): Object
r: ObjOrRef  Eval[ListExpressionallowIn](env, run);
a: Object  readReference(r, run);
throw ThrownValuevalue: a
end proc;
Try Statement
Syntax
TryStatement 
	try Block CatchClauses
|	try Block FinallyClause
|	try Block CatchClauses FinallyClause
CatchClauses 
	CatchClause
|	CatchClauses CatchClause
CatchClause  catch ( Parameter ) Block
FinallyClause  finally Block
Directives
Syntax
Directive 
	EmptyStatement
|	Statement
|	AnnotatableDirective
|	Attributes [no line break] AnnotatableDirective
|	Attributes [no line break] { Directives }
|	PackageDefinition
|	IncludeDirective Semicolon
|	Pragma Semicolon
AnnotatableDirective 
	ExportDefinition Semicolon
|	VariableDefinition Semicolon
|	FunctionDefinition
|	ClassDefinition
|	NamespaceDefinition Semicolon
|	InterfaceDefinition
|	ImportDirective Semicolon
|	UseDirective Semicolon
Directives 
	«empty»
|	DirectivesPrefix Directiveabbrev
DirectivesPrefix 
	«empty»
|	DirectivesPrefix Directivefull
Validation
proc Validate[Directive] (cxt: Context, env: Environment, jt: JumpTargets, pl: Plurality, attr: AttributeOptNotFalse): Context
[Directive  EmptyStatement] do return cxt;
[Directive  Statement] do
if attr  {none, true} then throw syntaxError end if;
Validate[Statement](cxt, env, {}, jt, pl);
return cxt;
[Directive  AnnotatableDirective] do
return Validate[AnnotatableDirective](cxt, env, pl, attr);
[Directive  Attributes [no line break] AnnotatableDirective] do
Validate[Attributes](cxt, env);
attr2: Attribute  Eval[Attributes](env, compile);
attr3: Attribute  combineAttributes(attr, attr2);
Enabled[Directive]  attr3 ≠ false;
if attr3 ≠ false then return Validate[AnnotatableDirective](cxt, env, pl, attr3)
else return cxt
end if;
[Directive  Attributes [no line break] { Directives }] do
Validate[Attributes](cxt, env);
attr2: Attribute  Eval[Attributes](env, compile);
attr3: Attribute  combineAttributes(attr, attr2);
Enabled[Directive]  attr3 ≠ false;
if attr3 = false then return cxt end if;
return Validate[Directives](cxt, env, jt, pl, attr3);
[Directive  PackageDefinition] do
if attr  {none, true} then ???? else throw syntaxError end if;
[Directive  IncludeDirective Semicolon] do
if attr  {none, true} then ???? else throw syntaxError end if;
[Directive  Pragma Semicolon] do
if attr  {none, true} then return Validate[Pragma](cxt)
else throw syntaxError
end if
end proc;
proc Validate[AnnotatableDirective] (cxt: Context, env: Environment, pl: Plurality, attr: AttributeOptNotFalse): Context
[AnnotatableDirective  ExportDefinition Semicolon] do ????;
[AnnotatableDirective  VariableDefinition Semicolon] do
Validate[VariableDefinition](cxt, env, attr);
return cxt;
[AnnotatableDirective  FunctionDefinition] do ????;
[AnnotatableDirective  ClassDefinition] do
Validate[ClassDefinition](cxt, env, pl, attr);
return cxt;
[AnnotatableDirective  NamespaceDefinition Semicolon] do ????;
[AnnotatableDirective  InterfaceDefinition] do ????;
[AnnotatableDirective  ImportDirective Semicolon] do ????;
[AnnotatableDirective  UseDirective Semicolon] do
if attr  {none, true} then return Validate[UseDirective](cxt, env)
else throw syntaxError
end if
end proc;
proc Validate[Directives] (cxt: Context, env: Environment, jt: JumpTargets, pl: Plurality, attr: AttributeOptNotFalse): Context
[Directives  «empty»] do return cxt;
[Directives  DirectivesPrefix Directiveabbrev] do
cxt2: Context  Validate[DirectivesPrefix](cxt, env, jt, pl, attr);
return Validate[Directiveabbrev](cxt2, env, jt, pl, attr)
end proc;
proc Validate[DirectivesPrefix] (cxt: Context, env: Environment, jt: JumpTargets, pl: Plurality, attr: AttributeOptNotFalse): Context
[DirectivesPrefix  «empty»] do return cxt;
[DirectivesPrefix0  DirectivesPrefix1 Directivefull] do
cxt2: Context  Validate[DirectivesPrefix1](cxt, env, jt, pl, attr);
return Validate[Directivefull](cxt2, env, jt, pl, attr)
end proc;
Evaluation
proc Eval[Directive] (env: Environment, d: Object): Object
[Directive  EmptyStatement] do return d;
[Directive  Statement] do return Eval[Statement](env, d);
[Directive  AnnotatableDirective] do return Eval[AnnotatableDirective](env, d);
[Directive  Attributes [no line break] AnnotatableDirective] do
if Enabled[Directive] then return Eval[AnnotatableDirective](env, d)
else return d
end if;
[Directive  Attributes [no line break] { Directives }] do
if Enabled[Directive] then return Eval[Directives](env, d) else return d end if;
[Directive  PackageDefinition] do ????;
[Directive  IncludeDirective Semicolon] do ????;
[Directive  Pragma Semicolon] do return d
end proc;
proc Eval[AnnotatableDirective] (env: Environment, d: Object): Object
[AnnotatableDirective  ExportDefinition Semicolon] do ????;
[AnnotatableDirective  VariableDefinition Semicolon] do
return Eval[VariableDefinition](env, d);
[AnnotatableDirective  FunctionDefinition] do ????;
[AnnotatableDirective  ClassDefinition] do return Eval[ClassDefinition](env, d);
[AnnotatableDirective  NamespaceDefinition Semicolon] do ????;
[AnnotatableDirective  InterfaceDefinition] do ????;
[AnnotatableDirective  ImportDirective Semicolon] do ????;
[AnnotatableDirective  UseDirective Semicolon] do return d
end proc;
proc Eval[Directives] (env: Environment, d: Object): Object
[Directives  «empty»] do return d;
[Directives  DirectivesPrefix Directiveabbrev] do
o: Object  Eval[DirectivesPrefix](env, d);
return Eval[Directiveabbrev](env, o)
end proc;
proc Eval[DirectivesPrefix] (env: Environment, d: Object): Object
[DirectivesPrefix  «empty»] do return d;
[DirectivesPrefix0  DirectivesPrefix1 Directivefull] do
o: Object  Eval[DirectivesPrefix1](env, d);
return Eval[Directivefull](env, o)
end proc;
Enabled[Directive]: Boolean;
Attributes
Syntax
Attributes 
	Attribute
|	AttributeCombination
AttributeCombination  Attribute [no line break] Attributes
Attribute 
	AttributeExpression
|	true
|	false
|	public
|	NonexpressionAttribute
NonexpressionAttribute 
	abstract
|	final
|	private
|	static
Validation
proc Validate[Attributes] (cxt: Context, env: Environment)
[Attributes  Attribute] do Validate[Attribute](cxt, env);
[Attributes  AttributeCombination] do Validate[AttributeCombination](cxt, env)
end proc;
proc Validate[AttributeCombination  Attribute [no line break] Attributes] (cxt: Context, env: Environment)
Validate[Attribute](cxt, env);
Validate[Attributes](cxt, env)
end proc;
proc Validate[Attribute] (cxt: Context, env: Environment)
[Attribute  AttributeExpression] do Validate[AttributeExpression](cxt, env);
[Attribute  true] do nothing;
[Attribute  false] do nothing;
[Attribute  public] do nothing;
[Attribute  NonexpressionAttribute] do Validate[NonexpressionAttribute](env)
end proc;
proc Validate[NonexpressionAttribute] (env: Environment)
[NonexpressionAttribute  abstract] do nothing;
[NonexpressionAttribute  final] do nothing;
[NonexpressionAttribute  private] do
if getEnclosingClass(env) = none then throw syntaxError end if;
[NonexpressionAttribute  static] do nothing
end proc;
Evaluation
proc Eval[Attributes] (env: Environment, phase: Phase): Attribute
[Attributes  Attribute] do return Eval[Attribute](env, phase);
[Attributes  AttributeCombination] do return Eval[AttributeCombination](env, phase)
end proc;
proc Eval[AttributeCombination  Attribute [no line break] Attributes] (env: Environment, phase: Phase): Attribute
a: Attribute  Eval[Attribute](env, phase);
if a = false then return false end if;
b: Attribute  Eval[Attributes](env, phase);
return combineAttributes(a, b)
end proc;
proc Eval[Attribute] (env: Environment, phase: Phase): Attribute
[Attribute  AttributeExpression] do
r: ObjOrRef  Eval[AttributeExpression](env, phase);
a: Object  readReference(r, phase);
if a  Attribute then throw badValueError end if;
return a;
[Attribute  true] do return true;
[Attribute  false] do return false;
[Attribute  public] do return publicNamespace;
[Attribute  NonexpressionAttribute] do
return Eval[NonexpressionAttribute](env, phase)
end proc;
proc Eval[NonexpressionAttribute] (env: Environment, phase: Phase): Attribute
[NonexpressionAttribute  abstract] do
return CompoundAttributenamespaces: {}, explicit: false, dynamic: false, compile: false, memberMod: abstract, overrideMod: none, prototype: false, unused: false;
[NonexpressionAttribute  final] do
return CompoundAttributenamespaces: {}, explicit: false, dynamic: false, compile: false, memberMod: final, overrideMod: none, prototype: false, unused: false;
[NonexpressionAttribute  private] do
c: ClassOpt  getEnclosingClass(env);
Note that Validate ensured that c cannot be none at this point.
return c.privateNamespace;
[NonexpressionAttribute  static] do
return CompoundAttributenamespaces: {}, explicit: false, dynamic: false, compile: false, memberMod: static, overrideMod: none, prototype: false, unused: false
end proc;
Use Directive
Syntax
UseDirective  use namespace ParenListExpression
Validation
proc Validate[UseDirective  use namespace ParenListExpression] (cxt: Context, env: Environment): Context
Validate[ParenListExpression](cxt, env);
values: Object[]  EvalAsList[ParenListExpression](env, compile);
namespaces: Namespace{}  {};
for each v  values do
if v  Namespace or v  namespaces then throw badValueError end if;
namespaces  namespaces  {v}
end for each;
return ContextopenNamespaces: cxt.openNamespaces  namespaces, other fields from cxt
end proc;
Import Directive
Syntax
ImportDirective 
	import ImportBinding IncludesExcludes
|	import ImportBinding , namespace ParenListExpression IncludesExcludes
ImportBinding 
	ImportSource
|	Identifier = ImportSource
ImportSource 
	String
|	PackageName
IncludesExcludes 
	«empty»
|	, exclude ( NamePatterns )
|	, include ( NamePatterns )
NamePatterns 
	«empty»
|	NamePatternList
NamePatternList 
	QualifiedIdentifier
|	NamePatternList , QualifiedIdentifier
Include Directive
Syntax
IncludeDirective  include [no line break] String
Pragma
Syntax
Pragma  use PragmaItems
PragmaItems 
	PragmaItem
|	PragmaItems , PragmaItem
PragmaItem 
	PragmaExpr
|	PragmaExpr ?
PragmaExpr 
	Identifier
|	Identifier ( PragmaArgument )
PragmaArgument 
	true
|	false
|	Number
|	- Number
|	String
Validation
proc Validate[Pragma  use PragmaItems] (cxt: Context): Context
return Validate[PragmaItems](cxt)
end proc;
proc Validate[PragmaItems] (cxt: Context): Context
[PragmaItems  PragmaItem] do return Validate[PragmaItem](cxt);
[PragmaItems0  PragmaItems1 , PragmaItem] do
cxt2: Context  Validate[PragmaItems1](cxt);
return Validate[PragmaItem](cxt2)
end proc;
proc Validate[PragmaItem] (cxt: Context): Context
[PragmaItem  PragmaExpr] do return Validate[PragmaExpr](cxt, false);
[PragmaItem  PragmaExpr ?] do return Validate[PragmaExpr](cxt, true)
end proc;
proc Validate[PragmaExpr] (cxt: Context, optional: Boolean): Context
[PragmaExpr  Identifier] do
return processPragma(cxt, Name[Identifier], undefined, optional);
[PragmaExpr  Identifier ( PragmaArgument )] do
arg: Object  Value[PragmaArgument];
return processPragma(cxt, Name[Identifier], arg, optional)
end proc;
Value[PragmaArgument]: Object;
Value[PragmaArgument  true] = true;
Value[PragmaArgument  false] = false;
Value[PragmaArgument  Number] = Value[Number];
Value[PragmaArgument  - Number] = float64Negate(Value[Number]);
Value[PragmaArgument  String] = Value[String];
proc processPragma(cxt: Context, name: String, value: Object, optional: Boolean): Context
if name = “strict” then
if value  {true, undefined} then
return Contextstrict: true, other fields from cxt
end if;
if value = false then return Contextstrict: false, other fields from cxt end if
end if;
if name = “ecmascript” then
if value  {undefined, 4.0} then return cxt end if;
if value  {1.0, 2.0, 3.0} then
An implementation may optionally modify cxt to disable features not available in ECMAScript Edition value other than subsequent pragmas.
return cxt
end if
end if;
if optional then return cxt else throw badValueError end if
end proc;
Definitions
Export Definition
Syntax
ExportDefinition  export ExportBindingList
ExportBindingList 
	ExportBinding
|	ExportBindingList , ExportBinding
ExportBinding 
	FunctionName
|	FunctionName = FunctionName
Variable Definition
Syntax
VariableDefinition  VariableDefinitionKind VariableBindingListallowIn
VariableDefinitionKind 
	var
|	const
VariableBindingList 
	VariableBinding
|	VariableBindingList , VariableBinding
Semantics
tag hoisted;
tag staticCompiled;
tag staticRun;
tag instanceRun;
Syntax
VariableBinding  TypedIdentifier VariableInitialisation
VariableInitialisation 
	«empty»
|	= VariableInitialiser
VariableInitialiser 
	AssignmentExpression
|	NonexpressionAttribute
|	AttributeCombination
TypedIdentifier 
	Identifier
|	Identifier : TypeExpression
Validation
proc Validate[VariableDefinition  VariableDefinitionKind VariableBindingListallowIn] (cxt: Context, env: Environment, attr: AttributeOptNotFalse)
immutable: Boolean  Immutable[VariableDefinitionKind];
Validate[VariableBindingListallowIn](cxt, env, attr, immutable)
end proc;
Immutable[VariableDefinitionKind]: Boolean;
Immutable[VariableDefinitionKind  var] = false;
Immutable[VariableDefinitionKind  const] = true;
proc Validate[VariableBindingList] (cxt: Context, env: Environment, attr: AttributeOptNotFalse, immutable: Boolean)
[VariableBindingList  VariableBinding] do
Validate[VariableBinding](cxt, env, attr, immutable);
[VariableBindingList0  VariableBindingList1 , VariableBinding] do
Validate[VariableBindingList1](cxt, env, attr, immutable);
Validate[VariableBinding](cxt, env, attr, immutable)
end proc;
Kind[VariableBinding]: {hoisted, staticCompiled, staticRun, instanceRun};
Multiname[VariableBinding]: Multiname;
proc Validate[VariableBinding  TypedIdentifier VariableInitialisation] (cxt: Context, env: Environment, attr: AttributeOptNotFalse, immutable: Boolean)
Validate[TypedIdentifier](cxt, env);
Validate[VariableInitialisation](cxt, env);
name: String  Name[TypedIdentifier];
if not cxt.strict and getRegionalFrame(env)  Global  FunctionFrame and not immutable and attr = none and not TypePresent[TypedIdentifier] then
Kind[VariableBinding]  hoisted;
qname: QualifiedName  QualifiedNamenamespace: publicNamespace, id: name;
Multiname[VariableBinding]  {qname};
defineHoistedVar(env, name)
else
a: CompoundAttribute  toCompoundAttribute(attr);
memberMod: MemberModifier  a.memberMod;
namespaces: Namespace{}  a.namespaces;
localFrame: Frame  env[0];
if a.dynamic or a.prototype or (a.explicit and localFrame  Package) or (a.compile and not immutable) then
throw definitionError
end if;
if localFrame  Class then
if memberMod = none then memberMod  a.compile ? static : final end if
else if memberMod ≠ none then throw definitionError end if
end if;
case memberMod of
{none, static} do
if a.overrideMod ≠ none then throw definitionError end if;
if namespaces = {} then namespaces  {publicNamespace} end if;
multiname: Multiname  {QualifiedNamenamespace: ns, id: name | ns  namespaces};
Multiname[VariableBinding]  multiname;
regionalEnv: Frame[]  getRegionalEnvironment(env);
regionalFrame: Frame  regionalEnv[|regionalEnv| – 1];
if some b  localFrame.staticReadBindings  localFrame.staticWriteBindings satisfies b.qname  multiname then
throw definitionError
end if;
for each frame  regionalEnv[1 ...] do
if some b  frame.staticReadBindings  frame.staticWriteBindings satisfies b.qname  multiname and b.content ≠ forbidden then
throw definitionError
end if
end for each;
if regionalFrame  Global and (some dp  regionalFrame.dynamicProperties satisfies QualifiedNamenamespace: publicNamespace, id: dp.name  multiname) then
throw definitionError
end if;
v: Variable  new Variablevalue: future, immutable: immutable;
newBindings: StaticBinding{}  {StaticBindingqname: qname, content: v, explicit: a.explicit | qname  multiname};
localFrame.staticReadBindings  localFrame.staticReadBindings  newBindings;
localFrame.staticWriteBindings  localFrame.staticWriteBindings  newBindings;
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.
newForbiddenBindings: StaticBinding{}  {StaticBindingqname: qname, content: forbidden, explicit: true | qname  multiname};
for each frame  regionalEnv[1 ...] do
frame.staticReadBindings  frame.staticReadBindings  newForbiddenBindings;
frame.staticWriteBindings  frame.staticWriteBindings  newForbiddenBindings
end for each;
proc deferredStaticValidate()
t: ClassOpt  Eval[TypedIdentifier](env);
if t = none then t  objectClass end if;
v.type  t
end proc;
if a.compile then
deferredStaticValidate();
value: ObjectOpt  Eval[VariableInitialisation](env, compile);
if value = none then throw definitionError end if;
coercedValue: Object  assignmentConversion(value, v.type);
v.value  coercedValue;
Kind[VariableBinding]  staticCompiled
else
deferredValidators  deferredValidators  [deferredStaticValidate];
Kind[VariableBinding]  staticRun
end if;
{abstract, virtual, final} do
At this point localFrame  Class;
proc evalInitialValue(): ObjectOpt
return Eval[VariableInitialisation](env, run)
end proc;
m: InstanceVariable  InstanceAccessor;
case memberMod of
{abstract} do
if HasInitialiser[VariableInitialisation] then throw syntaxError
end if;
m  new InstanceAccessorcode: abstract, final: false;
{virtual} do
m  new InstanceVariableevalInitialValue: evalInitialValue, immutable: immutable, final: false;
{final} do
m  new InstanceVariableevalInitialValue: evalInitialValue, immutable: immutable, final: true
end case;
os: OverrideStatusPair  defineInstanceMember(localFrame, cxt, name, namespaces, a.overrideMod, readWrite, m);
proc deferredInstanceValidate()
t: ClassOpt  Eval[TypedIdentifier](env);
if t = none then
overriddenRead: InstanceMember  {none, potentialConflict}  os.readStatus.overriddenMember;
overriddenWrite: InstanceMember  {none, potentialConflict}  os.writeStatus.overriddenMember;
if overriddenRead  {none, potentialConflict} then
Note that defineInstanceMember already ensured that overriddenRead  InstanceMethod.
t  overriddenRead.type
elsif overriddenWrite  {none, potentialConflict} then
Note that defineInstanceMember already ensured that overriddenWrite  InstanceMethod.
t  overriddenWrite.type
else t  objectClass
end if
end if;
m.type  t
end proc;
deferredValidators  deferredValidators  [deferredInstanceValidate];
Kind[VariableBinding]  instanceRun;
{constructor, operator} do throw definitionError
end case
end if
end proc;
HasInitialiser[VariableInitialisation]: Boolean;
HasInitialiser[VariableInitialisation  «empty»] = false;
HasInitialiser[VariableInitialisation  = VariableInitialiser] = true;
proc Validate[VariableInitialisation] (cxt: Context, env: Environment)
[VariableInitialisation  «empty»] do nothing;
[VariableInitialisation  = VariableInitialiser] do
Validate[VariableInitialiser](cxt, env)
end proc;
proc Validate[VariableInitialiser] (cxt: Context, env: Environment)
[VariableInitialiser  AssignmentExpression] do
Validate[AssignmentExpression](cxt, env);
[VariableInitialiser  NonexpressionAttribute] do
Validate[NonexpressionAttribute](env);
[VariableInitialiser  AttributeCombination] do
Validate[AttributeCombination](cxt, env)
end proc;
Name[TypedIdentifier]: String;
Name[TypedIdentifier  Identifier] = Name[Identifier];
Name[TypedIdentifier  Identifier : TypeExpression] = Name[Identifier];
TypePresent[TypedIdentifier]: Boolean;
TypePresent[TypedIdentifier  Identifier] = false;
TypePresent[TypedIdentifier  Identifier : TypeExpression] = true;
proc Validate[TypedIdentifier] (cxt: Context, env: Environment)
[TypedIdentifier  Identifier] do nothing;
[TypedIdentifier  Identifier : TypeExpression] do
Validate[TypeExpression](cxt, env)
end proc;
Evaluation
proc Eval[VariableDefinition  VariableDefinitionKind VariableBindingListallowIn] (env: Environment, d: Object): Object
immutable: Boolean  Immutable[VariableDefinitionKind];
Eval[VariableBindingListallowIn](env, immutable);
return d
end proc;
proc Eval[VariableBindingList] (env: Environment, immutable: Boolean)
[VariableBindingList  VariableBinding] do Eval[VariableBinding](env, immutable);
[VariableBindingList0  VariableBindingList1 , VariableBinding] do
Eval[VariableBindingList1](env, immutable);
Eval[VariableBinding](env, immutable)
end proc;
proc Eval[VariableBinding  TypedIdentifier VariableInitialisation] (env: Environment, immutable: Boolean)
case Kind[VariableBinding] of
{hoisted} do
value: ObjectOpt  Eval[VariableInitialisation](env, run);
if value ≠ none then
lexicalWrite(env, Multiname[VariableBinding], value, false, run)
end if;
{staticCompiled} do nothing;
{staticRun} do
localFrame: Frame  env[0];
members: StaticMember{}  {b.content | b  localFrame.staticWriteBindings such that b.qname  Multiname[VariableBinding]};
Note that the members set consists of exactly one Variable element because localFrame was constructed with that Variable inside Validate.
v: Variable  the one element of members;
value: ObjectOpt  Eval[VariableInitialisation](env, compile);
t: Class  v.type;
coercedValue: ObjectUninit;
if value ≠ none then coercedValue  assignmentConversion(value, t)
elsif immutable then coercedValue  uninitialised
else coercedValue  assignmentConversion(undefined, t)
end if;
v.value  coercedValue;
{instanceRun} do nothing
end case
end proc;
proc Eval[VariableInitialisation] (env: Environment, phase: Phase): ObjectOpt
[VariableInitialisation  «empty»] do return none;
[VariableInitialisation  = VariableInitialiser] do
return Eval[VariableInitialiser](env, phase)
end proc;
proc Eval[VariableInitialiser] (env: Environment, phase: Phase): Object
[VariableInitialiser  AssignmentExpression] do
r: ObjOrRef  Eval[AssignmentExpression](env, phase);
return readReference(r, phase);
[VariableInitialiser  NonexpressionAttribute] do
return Eval[NonexpressionAttribute](env, phase);
[VariableInitialiser  AttributeCombination] do
return Eval[AttributeCombination](env, phase)
end proc;
proc Eval[TypedIdentifier] (env: Environment): ClassOpt
[TypedIdentifier  Identifier] do return none;
[TypedIdentifier  Identifier : TypeExpression] do
return Eval[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] (cxt: Context, env: Environment)
if cxt.strict or getRegionalFrame(env)  Global  FunctionFrame then
throw syntaxError
end if;
Validate[UntypedVariableBindingList](cxt, env)
end proc;
proc Validate[UntypedVariableBindingList] (cxt: Context, env: Environment)
[UntypedVariableBindingList  UntypedVariableBinding] do
Validate[UntypedVariableBinding](cxt, env);
[UntypedVariableBindingList0  UntypedVariableBindingList1 , UntypedVariableBinding] do
Validate[UntypedVariableBindingList1](cxt, env);
Validate[UntypedVariableBinding](cxt, env)
end proc;
proc Validate[UntypedVariableBinding  Identifier VariableInitialisationallowIn] (cxt: Context, env: Environment)
Validate[VariableInitialisationallowIn](cxt, env);
defineHoistedVar(env, Name[Identifier])
end proc;
Evaluation
proc Eval[SimpleVariableDefinition  var UntypedVariableBindingList] (env: Environment, d: Object): Object
Eval[UntypedVariableBindingList](env);
return d
end proc;
proc Eval[UntypedVariableBindingList] (env: Environment)
[UntypedVariableBindingList  UntypedVariableBinding] do
Eval[UntypedVariableBinding](env);
[UntypedVariableBindingList0  UntypedVariableBindingList1 , UntypedVariableBinding] do
Eval[UntypedVariableBindingList1](env);
Eval[UntypedVariableBinding](env)
end proc;
proc Eval[UntypedVariableBinding  Identifier VariableInitialisationallowIn] (env: Environment)
value: ObjectOpt  Eval[VariableInitialisationallowIn](env, run);
if value ≠ none then
qname: QualifiedName  QualifiedNamenamespace: publicNamespace, id: Name[Identifier];
lexicalWrite(env, {qname}, value, false, run)
end if
end proc;
Function Definition
Syntax
FunctionDefinition 
	FunctionDeclaration Block
|	FunctionDeclaration Semicolon
FunctionDeclaration  function FunctionName FunctionSignature
FunctionName 
	Identifier
|	get [no line break] Identifier
|	set [no line break] Identifier
|	String
FunctionSignature  ParameterSignature ResultSignature
ParameterSignature  ( Parameters )
Parameters 
	«empty»
|	AllParameters
AllParameters 
	Parameter
|	Parameter , AllParameters
|	OptionalParameters
OptionalParameters 
	OptionalParameter
|	OptionalParameter , OptionalParameters
|	RestAndNamedParameters
RestAndNamedParameters 
	NamedParameters
|	RestParameter
|	RestParameter , NamedParameters
|	NamedRestParameter
NamedParameters 
	NamedParameter
|	NamedParameter , NamedParameters
Parameter 
	TypedIdentifierallowIn
|	const TypedIdentifierallowIn
OptionalParameter  Parameter = AssignmentExpressionallowIn
TypedInitialiser  TypedIdentifierallowIn = AssignmentExpressionallowIn
NamedParameter 
	named TypedInitialiser
|	const named TypedInitialiser
|	named const TypedInitialiser
RestParameter 
	...
|	... Parameter
NamedRestParameter 
	... named Identifier
|	... const named Identifier
|	... named const Identifier
ResultSignature 
	«empty»
|	: TypeExpressionallowIn
Class Definition
Syntax
ClassDefinition  class Identifier Inheritance Block
Inheritance 
	«empty»
|	extends TypeExpressionallowIn
|	implements TypeExpressionList
|	extends TypeExpressionallowIn implements TypeExpressionList
Validation
Class[ClassDefinition]: Class;
proc Validate[ClassDefinition  class Identifier Inheritance Block] (cxt: Context, env: Environment, pl: Plurality, attr: AttributeOptNotFalse)
if pl ≠ singular then throw syntaxError end if;
superclass: Class  Validate[Inheritance](cxt, env);
if not superclass.complete or superclass.final then throw definitionError end if;
a: CompoundAttribute  toCompoundAttribute(attr);
if a.compile then throw definitionError end if;
proc call(this: Object, args: ArgumentList, phase: Phase): Object
????
end proc;
proc construct(this: Object, args: ArgumentList, phase: Phase): Object
????
end proc;
prototype: Object  null;
if a.prototype then ???? end if;
final: Boolean  false;
if a.memberMod = final then
final  true;
a  CompoundAttributememberMod: none, other fields from a
end if;
privateNamespace: Namespace  new Namespacename: “private”;
dynamic: Boolean  a.dynamic or superclass.dynamic;
c: Class  new ClassstaticReadBindings: {}, staticWriteBindings: {}, instanceReadBindings: {}, instanceWriteBindings: {}, instanceInitOrder: [], complete: false, super: superclass, prototype: prototype, privateNamespace: privateNamespace, dynamic: dynamic, primitive: false, final: final, call: call, construct: construct;
Class[ClassDefinition]  c;
proc makeStaticMember(): StaticMember
return new Variabletype: classClass, value: c, immutable: true
end proc;
proc makeInstanceMember(): InstanceMember
????
end proc;
bindDefinition(env, Name[Identifier], a, static, readNoWrite, makeStaticMember, makeInstanceMember);
ValidateUsingFrame[Block](cxt, env, JumpTargetsbreakTargets: {}, continueTargets: {}, pl, c)
end proc;
proc Validate[Inheritance] (cxt: Context, env: Environment): Class
[Inheritance  «empty»] do return objectClass;
[Inheritance  extends TypeExpressionallowIn] do
Validate[TypeExpressionallowIn](cxt, env);
return Eval[TypeExpressionallowIn](env);
[Inheritance  implements TypeExpressionList] do return objectClass;
[Inheritance  extends TypeExpressionallowIn implements TypeExpressionList] do
return objectClass
end proc;
Evaluation
proc Eval[ClassDefinition  class Identifier Inheritance Block] (env: Environment, d: Object): Object
c: Class  Class[ClassDefinition];
return EvalUsingFrame[Block](env, c, d)
end proc;
Interface Definition
Syntax
InterfaceDefinition 
	interface Identifier ExtendsList Block
|	interface Identifier Semicolon
ExtendsList 
	«empty»
|	extends TypeExpressionList
TypeExpressionList 
	TypeExpressionallowIn
|	TypeExpressionList , TypeExpressionallowIn
Namespace Definition
Syntax
NamespaceDefinition  namespace Identifier
Package Definition
Syntax
PackageDefinition 
	package Block
|	package PackageName Block
PackageName 
	Identifier
|	PackageName . Identifier
Programs
Syntax
Program  Directives
Predefined Identifiers
Built-in Classes
proc makeBuiltInClass(superclass: ClassOpt, dynamic: Boolean, primitive: Boolean, final: Boolean): Class
proc call(this: Object, args: ArgumentList, phase: Phase): Object
????
end proc;
proc construct(this: Object, args: ArgumentList, phase: Phase): Object
????
end proc;
privateNamespace: Namespace  new Namespacename: “private”;
return new ClassstaticReadBindings: {}, staticWriteBindings: {}, instanceReadBindings: {}, instanceWriteBindings: {}, instanceInitOrder: [], complete: true, super: superclass, prototype: null, privateNamespace: privateNamespace, dynamic: dynamic, primitive: primitive, final: final, call: call, construct: construct
end proc;
objectClass: Class = makeBuiltInClass(none, false, true, false);
undefinedClass: Class = makeBuiltInClass(objectClass, false, true, true);
nullClass: Class = makeBuiltInClass(objectClass, false, true, true);
booleanClass: Class = makeBuiltInClass(objectClass, false, true, true);
numberClass: Class = makeBuiltInClass(objectClass, false, true, true);
stringClass: Class = makeBuiltInClass(objectClass, false, false, true);
characterClass: Class = makeBuiltInClass(stringClass, false, false, true);
namespaceClass: Class = makeBuiltInClass(objectClass, false, false, true);
attributeClass: Class = makeBuiltInClass(objectClass, false, false, true);
classClass: Class = makeBuiltInClass(objectClass, false, false, true);
functionClass: Class = makeBuiltInClass(objectClass, false, false, true);
prototypeClass: Class = makeBuiltInClass(objectClass, true, false, true);
packageClass: Class = makeBuiltInClass(objectClass, true, false, true);
Built-in Functions
Built-in Attributes
Built-in Operators
Unary Operators
proc plusObject(this: Object, a: Object, args: ArgumentList, phase: Phase): Object
return toNumber(a, phase)
end proc;
proc minusObject(this: Object, a: Object, args: ArgumentList, phase: Phase): Object
return float64Negate(toNumber(a, phase))
end proc;
proc bitwiseNotObject(this: Object, a: Object, args: ArgumentList, phase: Phase): Object
i: Integer  toInt32(toNumber(a, phase));
return realToFloat64(bitwiseXor(i, –1))
end proc;
proc incrementObject(this: Object, a: Object, args: ArgumentList, phase: Phase): Object
x: Object  unaryPlus(a, phase);
return binaryDispatch(addTable, x, 1.0, phase)
end proc;
proc decrementObject(this: Object, a: Object, args: ArgumentList, phase: Phase): Object
x: Object  unaryPlus(a, phase);
return binaryDispatch(subtractTable, x, 1.0, phase)
end proc;
proc callObject(this: Object, a: Object, args: ArgumentList, phase: Phase): Object
case a of
Undefined  Null  Boolean  Float64  String  Namespace  CompoundAttribute  Prototype  Package  Global do
throw badValueError;
Class do return a.call(this, args, phase);
Instance do return a.call(this, args, a.env, phase);
MethodClosure do
code: {abstract}  Instance  a.method.code;
case code of
Instance do return callObject(a.this, code, args, phase);
{abstract} do throw propertyAccessError
end case
end case
end proc;
proc constructObject(this: Object, a: Object, args: ArgumentList, phase: Phase): Object
case a of
Undefined  Null  Boolean  Float64  String  Namespace  CompoundAttribute  MethodClosure  Prototype  Package  Global do
throw badValueError;
Class do return a.construct(this, args, phase);
Instance do return a.construct(this, args, a.env, phase)
end case
end proc;
proc bracketReadObject(this: Object, a: Object, args: ArgumentList, phase: Phase): Object
if |args.positional| ≠ 1 or args.named ≠ {} then throw argumentMismatchError end if;
name: String  toString(args.positional[0], phase);
result: ObjectOpt  readProperty(a, {QualifiedNamenamespace: publicNamespace, id: name}, propertyLookup, phase);
if result = none then throw propertyAccessError else return result end if
end proc;
proc bracketWriteObject(this: Object, a: Object, args: ArgumentList, phase: Phase): Object
if phase = compile then throw compileExpressionError end if;
if |args.positional| ≠ 2 or args.named ≠ {} then throw argumentMismatchError end if;
newValue: Object  args.positional[0];
name: String  toString(args.positional[1], phase);
result: {none, ok}  writeProperty(a, {QualifiedNamenamespace: publicNamespace, id: name}, propertyLookup, true, newValue, phase);
if result = none then throw propertyAccessError end if;
return undefined
end proc;
proc bracketDeleteObject(this: Object, a: Object, args: ArgumentList, phase: Phase): Object
if phase = compile then throw compileExpressionError end if;
if |args.positional| ≠ 1 or args.named ≠ {} then throw argumentMismatchError end if;
name: String  toString(args.positional[0], phase);
return deleteQualifiedProperty(a, name, publicNamespace, propertyLookup, phase)
end proc;
plusTable: UnaryMethod{}  {UnaryMethodoperandType: objectClass, f: plusObject};
minusTable: UnaryMethod{}  {UnaryMethodoperandType: objectClass, f: minusObject};
bitwiseNotTable: UnaryMethod{}  {UnaryMethodoperandType: objectClass, f: bitwiseNotObject};
incrementTable: UnaryMethod{}  {UnaryMethodoperandType: objectClass, f: incrementObject};
decrementTable: UnaryMethod{}  {UnaryMethodoperandType: objectClass, f: decrementObject};
callTable: UnaryMethod{}  {UnaryMethodoperandType: objectClass, f: callObject};
constructTable: UnaryMethod{}  {UnaryMethodoperandType: objectClass, f: constructObject};
bracketReadTable: UnaryMethod{}  {UnaryMethodoperandType: objectClass, f: bracketReadObject};
bracketWriteTable: UnaryMethod{}  {UnaryMethodoperandType: objectClass, f: bracketWriteObject};
bracketDeleteTable: UnaryMethod{}  {UnaryMethodoperandType: objectClass, f: bracketDeleteObject};
Binary Operators
proc addObjects(a: Object, b: Object, phase: Phase): Object
ap: PrimitiveObject  toPrimitive(a, null, phase);
bp: PrimitiveObject  toPrimitive(b, null, phase);
if ap  String or bp  String then
return toString(ap, phase)  toString(bp, phase)
else return float64Add(toNumber(ap, phase), toNumber(bp, phase))
end if
end proc;
proc subtractObjects(a: Object, b: Object, phase: Phase): Object
return float64Subtract(toNumber(a, phase), toNumber(b, phase))
end proc;
proc multiplyObjects(a: Object, b: Object, phase: Phase): Object
return float64Multiply(toNumber(a, phase), toNumber(b, phase))
end proc;
proc divideObjects(a: Object, b: Object, phase: Phase): Object
return float64Divide(toNumber(a, phase), toNumber(b, phase))
end proc;
proc remainderObjects(a: Object, b: Object, phase: Phase): Object
return float64Remainder(toNumber(a, phase), toNumber(b, phase))
end proc;
proc lessObjects(a: Object, b: Object, phase: Phase): Object
ap: PrimitiveObject  toPrimitive(a, null, phase);
bp: PrimitiveObject  toPrimitive(b, null, phase);
if ap  String and bp  String then return ap < bp
else return float64Compare(toNumber(ap, phase), toNumber(bp, phase)) = less
end if
end proc;
proc lessOrEqualObjects(a: Object, b: Object, phase: Phase): Object
ap: PrimitiveObject  toPrimitive(a, null, phase);
bp: PrimitiveObject  toPrimitive(b, null, phase);
if ap  String and bp  String then return ap ≤ bp
else return float64Compare(toNumber(ap, phase), toNumber(bp, phase))  {less, equal}
end if
end proc;
proc equalObjects(a: Object, b: Object, phase: Phase): Object
case a of
Undefined  Null do return b  Undefined  Null;
Boolean do
if b  Boolean then return a = b
else return equalObjects(toNumber(a, phase), b, phase)
end if;
Float64 do
bp: PrimitiveObject  toPrimitive(b, null, phase);
case bp of
Undefined  Null do return false;
Boolean  Float64  String do
return float64Compare(a, toNumber(bp, phase)) = equal
end case;
String do
bp: PrimitiveObject  toPrimitive(b, null, phase);
case bp of
Undefined  Null do return false;
Boolean  Float64 do
return float64Compare(toNumber(a, phase), toNumber(bp, phase)) = equal;
String do return a = bp
end case;
Namespace  CompoundAttribute  Class  MethodClosure  Prototype  Instance  Package  Global do
case b of
Undefined  Null do return false;
Namespace  CompoundAttribute  Class  MethodClosure  Prototype  Instance  Package  Global do
return strictEqualObjects(a, b, phase);
Boolean  Float64  String do
ap: PrimitiveObject  toPrimitive(a, null, phase);
case ap of
Undefined  Null do return false;
Boolean  Float64  String do return equalObjects(ap, b, phase)
end case
end case
end case
end proc;
proc strictEqualObjects(a: Object, b: Object, phase: Phase): Object
if a  Float64 and b  Float64 then return float64Compare(a, b) = equal
else return a = b
end if
end proc;
proc shiftLeftObjects(a: Object, b: Object, phase: Phase): Object
i: Integer  toUInt32(toNumber(a, phase));
count: Integer  bitwiseAnd(toUInt32(toNumber(b, phase)), 0x1F);
return realToFloat64(uInt32ToInt32(bitwiseAnd(bitwiseShift(i, count), 0xFFFFFFFF)))
end proc;
proc shiftRightObjects(a: Object, b: Object, phase: Phase): Object
i: Integer  toInt32(toNumber(a, phase));
count: Integer  bitwiseAnd(toUInt32(toNumber(b, phase)), 0x1F);
return realToFloat64(bitwiseShift(i, –count))
end proc;
proc shiftRightUnsignedObjects(a: Object, b: Object, phase: Phase): Object
i: Integer  toUInt32(toNumber(a, phase));
count: Integer  bitwiseAnd(toUInt32(toNumber(b, phase)), 0x1F);
return realToFloat64(bitwiseShift(i, –count))
end proc;
proc bitwiseAndObjects(a: Object, b: Object, phase: Phase): Object
i: Integer  toInt32(toNumber(a, phase));
j: Integer  toInt32(toNumber(b, phase));
return realToFloat64(bitwiseAnd(i, j))
end proc;
proc bitwiseXorObjects(a: Object, b: Object, phase: Phase): Object
i: Integer  toInt32(toNumber(a, phase));
j: Integer  toInt32(toNumber(b, phase));
return realToFloat64(bitwiseXor(i, j))
end proc;
proc bitwiseOrObjects(a: Object, b: Object, phase: Phase): Object
i: Integer  toInt32(toNumber(a, phase));
j: Integer  toInt32(toNumber(b, phase));
return realToFloat64(bitwiseOr(i, j))
end proc;
addTable: BinaryMethod{}  {BinaryMethodleftType: objectClass, rightType: objectClass, f: addObjects};
subtractTable: BinaryMethod{}  {BinaryMethodleftType: objectClass, rightType: objectClass, f: subtractObjects};
multiplyTable: BinaryMethod{}  {BinaryMethodleftType: objectClass, rightType: objectClass, f: multiplyObjects};
divideTable: BinaryMethod{}  {BinaryMethodleftType: objectClass, rightType: objectClass, f: divideObjects};
remainderTable: BinaryMethod{}  {BinaryMethodleftType: objectClass, rightType: objectClass, f: remainderObjects};
lessTable: BinaryMethod{}  {BinaryMethodleftType: objectClass, rightType: objectClass, f: lessObjects};
lessOrEqualTable: BinaryMethod{}  {BinaryMethodleftType: objectClass, rightType: objectClass, f: lessOrEqualObjects};
equalTable: BinaryMethod{}  {BinaryMethodleftType: objectClass, rightType: objectClass, f: equalObjects};
strictEqualTable: BinaryMethod{}  {BinaryMethodleftType: objectClass, rightType: objectClass, f: strictEqualObjects};
shiftLeftTable: BinaryMethod{}  {BinaryMethodleftType: objectClass, rightType: objectClass, f: shiftLeftObjects};
shiftRightTable: BinaryMethod{}  {BinaryMethodleftType: objectClass, rightType: objectClass, f: shiftRightObjects};
shiftRightUnsignedTable: BinaryMethod{}  {BinaryMethodleftType: objectClass, rightType: objectClass, f: shiftRightUnsignedObjects};
bitwiseAndTable: BinaryMethod{}  {BinaryMethodleftType: objectClass, rightType: objectClass, f: bitwiseAndObjects};
bitwiseXorTable: BinaryMethod{}  {BinaryMethodleftType: objectClass, rightType: objectClass, f: bitwiseXorObjects};
bitwiseOrTable: BinaryMethod{}  {BinaryMethodleftType: objectClass, rightType: objectClass, f: bitwiseOrObjects};
Built-in Namespaces
Built-in Units
EvalProgram[Program  Directives]: Object
begin
savedDeferredValidators: (()  ())[]  deferredValidators;
deferredValidators  [];
Validate[Directives](initialContext, initialEnvironment, JumpTargetsbreakTargets: {}, continueTargets: {}, singular, none);
for each v  deferredValidators do v() end for each;
deferredValidators  savedDeferredValidators;
return Eval[Directives](initialEnvironment, undefined)
end;
Index
Nonterminals
Update fields to generate this index
Tags
Update fields to generate this index
Semantic Domains
Update fields to generate this index
Globals
Update fields to generate this index