Types
Semantics
type Value
  = oneof {
           undefinedValue;
           nullValue;
           booleanValue: Boolean;
           doubleValue: Double;
           stringValue: String;
           objectValue: Object}
type ObjectOrNull = oneof {nullObjectOrNull; objectObjectOrNull: Object}
type Object
  = tuple {
           properties: Property[];
           typeofName: String;
           prototype: ObjectOrNull;
           get: PropName  ValueOrException;
           put: PropName  Value  VoidOrException;
           delete: PropName  BooleanOrException;
           call: ObjectOrNull  Value[]  ReferenceOrException;
           construct: Value[]  ObjectOrException;
           defaultValue: DefaultValueHint  ValueOrException}
type DefaultValueHint = oneof {noHint; numberHint; stringHint}
type Property
  = tuple {
           name: String;
           readOnly: Boolean;
           enumerable: Boolean;
           permanent: Boolean;
           value: Value}
type PropName = String
type Place = tuple {base: Object; property: PropName}
type Reference
  = oneof {valueReference: Value; placeReference: Place; virtualReference: PropName}
type IntegerOrException = oneof {normal: Integer; abrupt: Exception}
type VoidOrException = oneof {normal; abrupt: Exception}
type BooleanOrException = oneof {normal: Boolean; abrupt: Exception}
type DoubleOrException = oneof {normal: Double; abrupt: Exception}
type StringOrException = oneof {normal: String; abrupt: Exception}
type ObjectOrException = oneof {normal: Object; abrupt: Exception}
type ValueOrException = oneof {normal: Value; abrupt: Exception}
type ReferenceOrException = oneof {normal: Reference; abrupt: Exception}
type ValueListOrException = oneof {normal: Value[]; abrupt: Exception}
Helper Functions
Semantics
objectOrNullToValue(o: ObjectOrNull) : Value
  = case o of
        nullObjectOrNull: nullValue;
        objectObjectOrNull(obj: Object): objectValue obj
        end
undefinedResult : ValueOrException = normal undefinedValue
nullResult : ValueOrException = normal nullValue
booleanResult(b: Boolean) : ValueOrException = normal booleanValue b
doubleResult(d: Double) : ValueOrException = normal doubleValue d
integerResult(i: Integer) : ValueOrException = doubleResult(rationalToDouble(i))
stringResult(s: String) : ValueOrException = normal stringValue s
objectResult(o: Object) : ValueOrException = normal objectValue o
Exceptions
Semantics
type Exception = oneof {exception: Value; error: Error}
type Error
  = oneof {
           coerceToPrimitiveError;
           coerceToObjectError;
           getValueError;
           putValueError;
           deleteError}
makeError(err: Error) : Exception = error err
Objects
Conversions
Semantics
referenceGetValue(rv: Reference) : ValueOrException
  = case rv of
        valueReference(v: Value): normal v;
        placeReference(r: Place): r.base.get(r.property);
        virtualReference: abruptValueOrException makeError(getValueError)
        end
referencePutValue(rv: Reference, v: Value) : VoidOrException
  = case rv of
        valueReference: abruptVoidOrException makeError(putValueError);
        placeReference(r: Place): r.base.put(r.property, v);
        virtualReference: 
        end
Coercions
Semantics
coerceToBoolean(v: Value) : Boolean
  = case v of
        undefinedValue, nullValue: false;
        booleanValue(b: Boolean): b;
        doubleValue(d: Double): not (doubleIsZero(d) or doubleIsNan(d));
        stringValue(s: String): |s| ≠ 0;
        objectValue: true
        end
coerceBooleanToDouble(b: Boolean) : Double
  = if b
     then 1.0
     else 0.0
coerceToDouble(v: Value) : DoubleOrException
  = case v of
        undefinedValue: normal NaN;
        nullValue: normal 0.0;
        booleanValue(b: Boolean): normal coerceBooleanToDouble(b);
        doubleValue(d: Double): normal d;
        stringValue: ;
        objectValue: 
        end
coerceToUint32(v: Value) : IntegerOrException
  = letexc d: Double = coerceToDouble(v)
     in normal doubleToUint32(d)
coerceToInt32(v: Value) : IntegerOrException
  = letexc d: Double = coerceToDouble(v)
     in normal uint32ToInt32(doubleToUint32(d))
uint32ToInt32(ui: Integer) : Integer
  = if ui < 2147483648
     then ui
     else ui – 4294967296
coerceToString(v: Value) : StringOrException
  = case v of
        undefinedValue: normal “undefined”;
        nullValue: normal “null”;
        booleanValue(b: Boolean):
              if b
              then normal “true”
              else normal “false”;
        doubleValue: ;
        stringValue(s: String): normal s;
        objectValue: 
        end
coerceToPrimitive(v: Value, hint: DefaultValueHint) : ValueOrException
  = case v of
        undefinedValue, nullValue, booleanValue, doubleValue, stringValue: normal v;
        objectValue(o: Object):
              letexc pv: Value = o.defaultValue(hint)
              in case pv of
                     undefinedValue, nullValue, booleanValue, doubleValue, stringValue:
                           normal pv;
                     objectValue: abruptValueOrException makeError(coerceToPrimitiveError)
                     end
        end
coerceToObject(v: Value) : ObjectOrException
  = case v of
        undefinedValue, nullValue: abruptObjectOrException makeError(coerceToObjectError);
        booleanValue: ;
        doubleValue: ;
        stringValue: ;
        objectValue(o: Object): normal o
        end
Environments
Semantics
type Env = tuple {this: ObjectOrNull}
lookupIdentifier(e: Env, id: String) : ReferenceOrException = 
Terminal Actions
Semantics
action EvalIdentifier[Identifier] : String
action EvalNumber[Number] : Double
action EvalString[String] : String
Primary Expressions
Syntax
PrimaryRvalue 
	this
|	null
|	true
|	false
|	Number
|	String
|	( CommaExpressionnoLValue )
PrimaryLvalue 
	Identifier
|	( Lvalue )
Semantics
action Eval[PrimaryRvalue] : Env  ValueOrException
Eval[PrimaryRvalue  this](e: Env) = normal objectOrNullToValue(e.this)
Eval[PrimaryRvalue  null](e: Env) = nullResult
Eval[PrimaryRvalue  true](e: Env) = booleanResult(true)
Eval[PrimaryRvalue  false](e: Env) = booleanResult(false)
Eval[PrimaryRvalue  Number](e: Env) = doubleResult(EvalNumber[Number])
Eval[PrimaryRvalue  String](e: Env) = stringResult(EvalString[String])
Eval[PrimaryRvalue  ( CommaExpressionnoLValue )] = Eval[CommaExpressionnoLValue]
action Eval[PrimaryLvalue] : Env  ReferenceOrException
Eval[PrimaryLvalue  Identifier](e: Env)
  = lookupIdentifier(e, EvalIdentifier[Identifier])
Eval[PrimaryLvalue  ( Lvalue )] = Eval[Lvalue]
Left-Side Expressions
Syntax
ExprKind  {anyValue, noLValue}
MemberExprKind  {call, noCall}
MemberLvaluenoCall 
	PrimaryLvalue
|	MemberExpressionnoCall,anyValue [ Expression ]
|	MemberExpressionnoCall,anyValue . Identifier
MemberLvaluecall 
	Lvalue Arguments
|	MemberExpressionnoCall,noLValue Arguments
|	MemberExpressioncall,anyValue [ Expression ]
|	MemberExpressioncall,anyValue . Identifier
MemberExpressionnoCall,noLValue 
	PrimaryRvalue
|	new MemberExpressionnoCall,anyValue Arguments
MemberExpressionnoCall,anyValue 
	PrimaryRvalue
|	MemberLvaluenoCall
|	new MemberExpressionnoCall,anyValue Arguments
MemberExpressioncall,anyValue  MemberLvaluecall
NewExpressionExprKind 
	MemberExpressionnoCall,ExprKind
|	new NewExpressionanyValue
Arguments 
	( )
|	( ArgumentList )
ArgumentList 
	AssignmentExpressionanyValue
|	ArgumentList , AssignmentExpressionanyValue
Lvalue 
	MemberLvaluecall
|	MemberLvaluenoCall
Semantics
action Eval[MemberLvalueMemberExprKind] : Env  ReferenceOrException
Eval[MemberLvaluenoCall  PrimaryLvalue] = Eval[PrimaryLvalue]
Eval[MemberLvaluecall  Lvalue Arguments](e: Env)
  = letexc fReference: Reference = Eval[Lvalue](e)
     in letexc f: Value = referenceGetValue(fReference)
     in letexc arguments: Value[] = Eval[Arguments](e)
     in let this: ObjectOrNull
             = case fReference of
                   valueReference, virtualReference: nullObjectOrNull;
                   placeReference(p: Place): objectObjectOrNull p.base
                   end
     in callObject(f, this, arguments)
Eval[MemberLvaluecall  MemberExpressionnoCall,noLValue Arguments](e: Env)
  = letexc f: Value = Eval[MemberExpressionnoCall,noLValue](e)
     in letexc arguments: Value[] = Eval[Arguments](e)
     in callObject(f, nullObjectOrNull, arguments)
Eval[MemberLvalueMemberExprKind  MemberExpressionMemberExprKind,anyValue [ Expression ]]
            (e: Env)
  = letexc container: Value = Eval[MemberExpressionMemberExprKind,anyValue](e)
     in letexc property: Value = Eval[Expression](e)
     in readProperty(container, property)
Eval[MemberLvalueMemberExprKind  MemberExpressionMemberExprKind,anyValue . Identifier]
            (e: Env)
  = letexc container: Value = Eval[MemberExpressionMemberExprKind,anyValue](e)
     in readProperty(container, stringValue EvalIdentifier[Identifier])
action Eval[MemberExpressionMemberExprKind,ExprKind] : Env  ValueOrException
Eval[MemberExpressionnoCall,ExprKind  PrimaryRvalue] = Eval[PrimaryRvalue]
Eval[MemberExpressionMemberExprKind,anyValue  MemberLvalueMemberExprKind](e: Env)
  = letexc ref: Reference = Eval[MemberLvalueMemberExprKind](e)
     in referenceGetValue(ref)
Eval[MemberExpressionnoCall,ExprKind  new MemberExpressionnoCall,anyValue1 Arguments]
            (e: Env)
  = letexc constructor: Value = Eval[MemberExpressionnoCall,anyValue1](e)
     in letexc arguments: Value[] = Eval[Arguments](e)
     in constructObject(constructor, arguments)
action Eval[NewExpressionExprKind] : Env  ValueOrException
Eval[NewExpressionExprKind  MemberExpressionnoCall,ExprKind]
  = Eval[MemberExpressionnoCall,ExprKind]
Eval[NewExpressionExprKind  new NewExpressionanyValue1](e: Env)
  = letexc constructor: Value = Eval[NewExpressionanyValue1](e)
     in constructObject(constructor, []Value)
action Eval[Arguments] : Env  ValueListOrException
Eval[Arguments  ( )](e: Env) = normal []Value
Eval[Arguments  ( ArgumentList )] = Eval[ArgumentList]
action Eval[ArgumentList] : Env  ValueListOrException
Eval[ArgumentList  AssignmentExpressionanyValue](e: Env)
  = letexc arg: Value = Eval[AssignmentExpressionanyValue](e)
     in normal [arg]
Eval[ArgumentList  ArgumentList1 , AssignmentExpressionanyValue](e: Env)
  = letexc args: Value[] = Eval[ArgumentList1](e)
     in letexc arg: Value = Eval[AssignmentExpressionanyValue](e)
     in normal (args  [arg])
action Eval[Lvalue] : Env  ReferenceOrException
Eval[Lvalue  MemberLvaluecall] = Eval[MemberLvaluecall]
Eval[Lvalue  MemberLvaluenoCall] = Eval[MemberLvaluenoCall]
readProperty(container: Value, property: Value) : ReferenceOrException
  = letexc obj: Object = coerceToObject(container)
     in letexc name: PropName = coerceToString(property)
     in normal placeReference base obj, property name
callObject(f: Value, this: ObjectOrNull, arguments: Value[]) : ReferenceOrException
  = case f of
        undefinedValue, nullValue, booleanValue, doubleValue, stringValue:
              abruptReferenceOrException makeError(coerceToObjectError);
        objectValue(o: Object): o.call(this, arguments)
        end
constructObject(constructor: Value, arguments: Value[]) : ValueOrException
  = case constructor of
        undefinedValue, nullValue, booleanValue, doubleValue, stringValue:
              abruptValueOrException makeError(coerceToObjectError);
        objectValue(o: Object):
              letexc res: Object = o.construct(arguments)
              in objectResult(res)
        end
Postfix Expressions
Syntax
PostfixExpressionanyValue 
	NewExpressionanyValue
|	MemberExpressioncall,anyValue
|	Lvalue ++
|	Lvalue --
PostfixExpressionnoLValue 
	NewExpressionnoLValue
|	Lvalue ++
|	Lvalue --
Semantics
action Eval[PostfixExpressionExprKind] : Env  ValueOrException
Eval[PostfixExpressionExprKind  NewExpressionExprKind] = Eval[NewExpressionExprKind]
Eval[PostfixExpressionanyValue  MemberExpressioncall,anyValue]
  = Eval[MemberExpressioncall,anyValue]
Eval[PostfixExpressionExprKind  Lvalue ++](e: Env)
  = letexc operandReference: Reference = Eval[Lvalue](e)
     in letexc operandValue: Value = referenceGetValue(operandReference)
     in letexc operand: Double = coerceToDouble(operandValue)
     in letexc u: Void
                  = referencePutValue(operandReference, doubleValue doubleAdd(operand, 1.0))
     in doubleResult(operand)
Eval[PostfixExpressionExprKind  Lvalue --](e: Env)
  = letexc operandReference: Reference = Eval[Lvalue](e)
     in letexc operandValue: Value = referenceGetValue(operandReference)
     in letexc operand: Double = coerceToDouble(operandValue)
     in letexc u: Void
                  = referencePutValue(operandReference, doubleValue doubleSubtract(operand, 1.0))
     in doubleResult(operand)
Unary Operators
Syntax
UnaryExpressionExprKind 
	PostfixExpressionExprKind
|	delete Lvalue
|	void UnaryExpressionanyValue
|	typeof Lvalue
|	typeof UnaryExpressionnoLValue
|	++ Lvalue
|	-- Lvalue
|	+ UnaryExpressionanyValue
|	- UnaryExpressionanyValue
|	~ UnaryExpressionanyValue
|	! UnaryExpressionanyValue
Semantics
action Eval[UnaryExpressionExprKind] : Env  ValueOrException
Eval[UnaryExpressionExprKind  PostfixExpressionExprKind]
  = Eval[PostfixExpressionExprKind]
Eval[UnaryExpressionExprKind  delete Lvalue](e: Env)
  = letexc rv: Reference = Eval[Lvalue](e)
     in case rv of
            valueReference: abruptValueOrException makeError(deleteError);
            placeReference(r: Place):
                  letexc b: Boolean = r.base.delete(r.property)
                  in booleanResult(b);
            virtualReference: booleanResult(true)
            end
Eval[UnaryExpressionExprKind  void UnaryExpressionanyValue1](e: Env)
  = letexc operand: Value = Eval[UnaryExpressionanyValue1](e)
     in undefinedResult
Eval[UnaryExpressionExprKind  typeof Lvalue](e: Env)
  = letexc rv: Reference = Eval[Lvalue](e)
     in case rv of
            valueReference(v: Value): stringResult(valueTypeof(v));
            placeReference(r: Place):
                  letexc v: Value = r.base.get(r.property)
                  in stringResult(valueTypeof(v));
            virtualReference: stringResult(“undefined”)
            end
Eval[UnaryExpressionExprKind  typeof UnaryExpressionnoLValue1](e: Env)
  = letexc v: Value = Eval[UnaryExpressionnoLValue1](e)
     in stringResult(valueTypeof(v))
Eval[UnaryExpressionExprKind  ++ Lvalue](e: Env)
  = letexc operandReference: Reference = Eval[Lvalue](e)
     in letexc operandValue: Value = referenceGetValue(operandReference)
     in letexc operand: Double = coerceToDouble(operandValue)
     in let res: Double = doubleAdd(operand, 1.0)
     in letexc u: Void = referencePutValue(operandReference, doubleValue res)
     in doubleResult(res)
Eval[UnaryExpressionExprKind  -- Lvalue](e: Env)
  = letexc operandReference: Reference = Eval[Lvalue](e)
     in letexc operandValue: Value = referenceGetValue(operandReference)
     in letexc operand: Double = coerceToDouble(operandValue)
     in let res: Double = doubleSubtract(operand, 1.0)
     in letexc u: Void = referencePutValue(operandReference, doubleValue res)
     in doubleResult(res)
Eval[UnaryExpressionExprKind  + UnaryExpressionanyValue1](e: Env)
  = letexc operandValue: Value = Eval[UnaryExpressionanyValue1](e)
     in letexc operand: Double = coerceToDouble(operandValue)
     in doubleResult(operand)
Eval[UnaryExpressionExprKind  - UnaryExpressionanyValue1](e: Env)
  = letexc operandValue: Value = Eval[UnaryExpressionanyValue1](e)
     in letexc operand: Double = coerceToDouble(operandValue)
     in doubleResult(doubleNegate(operand))
Eval[UnaryExpressionExprKind  ~ UnaryExpressionanyValue1](e: Env)
  = letexc operandValue: Value = Eval[UnaryExpressionanyValue1](e)
     in letexc operand: Integer = coerceToInt32(operandValue)
     in integerResult(bitwiseXor(operand, -1))
Eval[UnaryExpressionExprKind  ! UnaryExpressionanyValue1](e: Env)
  = letexc operandValue: Value = Eval[UnaryExpressionanyValue1](e)
     in booleanResult(not coerceToBoolean(operandValue))
valueTypeof(v: Value) : String
  = case v of
        undefinedValue: “undefined”;
        nullValue: “object”;
        booleanValue: “boolean”;
        doubleValue: “number”;
        stringValue: “string”;
        objectValue(o: Object): o.typeofName
        end
Multiplicative Operators
Syntax
MultiplicativeExpressionExprKind 
	UnaryExpressionExprKind
|	MultiplicativeExpressionanyValue * UnaryExpressionanyValue
|	MultiplicativeExpressionanyValue / UnaryExpressionanyValue
|	MultiplicativeExpressionanyValue % UnaryExpressionanyValue
Semantics
action Eval[MultiplicativeExpressionExprKind] : Env  ValueOrException
Eval[MultiplicativeExpressionExprKind  UnaryExpressionExprKind]
  = Eval[UnaryExpressionExprKind]
Eval[MultiplicativeExpressionExprKind  MultiplicativeExpressionanyValue1 * UnaryExpressionanyValue]
            (e: Env)
  = letexc leftValue: Value = Eval[MultiplicativeExpressionanyValue1](e)
     in letexc rightValue: Value = Eval[UnaryExpressionanyValue](e)
     in applyBinaryDoubleOperator(doubleMultiply, leftValue, rightValue)
Eval[MultiplicativeExpressionExprKind  MultiplicativeExpressionanyValue1 / UnaryExpressionanyValue]
            (e: Env)
  = letexc leftValue: Value = Eval[MultiplicativeExpressionanyValue1](e)
     in letexc rightValue: Value = Eval[UnaryExpressionanyValue](e)
     in applyBinaryDoubleOperator(doubleDivide, leftValue, rightValue)
Eval[MultiplicativeExpressionExprKind  MultiplicativeExpressionanyValue1 % UnaryExpressionanyValue]
            (e: Env)
  = letexc leftValue: Value = Eval[MultiplicativeExpressionanyValue1](e)
     in letexc rightValue: Value = Eval[UnaryExpressionanyValue](e)
     in applyBinaryDoubleOperator(doubleRemainder, leftValue, rightValue)
applyBinaryDoubleOperator(operator: Double  Double  Double, leftValue: Value, rightValue: Value)
  : ValueOrException
  = letexc leftNumber: Double = coerceToDouble(leftValue)
     in letexc rightNumber: Double = coerceToDouble(rightValue)
     in doubleResult(operator(leftNumber, rightNumber))
Additive Operators
Syntax
AdditiveExpressionExprKind 
	MultiplicativeExpressionExprKind
|	AdditiveExpressionanyValue + MultiplicativeExpressionanyValue
|	AdditiveExpressionanyValue - MultiplicativeExpressionanyValue
Semantics
action Eval[AdditiveExpressionExprKind] : Env  ValueOrException
Eval[AdditiveExpressionExprKind  MultiplicativeExpressionExprKind]
  = Eval[MultiplicativeExpressionExprKind]
Eval[AdditiveExpressionExprKind  AdditiveExpressionanyValue1 + MultiplicativeExpressionanyValue]
            (e: Env)
  = letexc leftValue: Value = Eval[AdditiveExpressionanyValue1](e)
     in letexc rightValue: Value = Eval[MultiplicativeExpressionanyValue](e)
     in letexc leftPrimitive: Value = coerceToPrimitive(leftValue, noHint)
     in letexc rightPrimitive: Value = coerceToPrimitive(rightValue, noHint)
     in if leftPrimitive is stringValue or rightPrimitive is stringValue
         then letexc leftString: String = coerceToString(leftPrimitive)
                in letexc rightString: String = coerceToString(rightPrimitive)
                in stringResult(leftString  rightString)
         else applyBinaryDoubleOperator(doubleAdd, leftPrimitive, rightPrimitive)
Eval[AdditiveExpressionExprKind  AdditiveExpressionanyValue1 - MultiplicativeExpressionanyValue]
            (e: Env)
  = letexc leftValue: Value = Eval[AdditiveExpressionanyValue1](e)
     in letexc rightValue: Value = Eval[MultiplicativeExpressionanyValue](e)
     in applyBinaryDoubleOperator(doubleSubtract, leftValue, rightValue)
Bitwise Shift Operators
Syntax
ShiftExpressionExprKind 
	AdditiveExpressionExprKind
|	ShiftExpressionanyValue << AdditiveExpressionanyValue
|	ShiftExpressionanyValue >> AdditiveExpressionanyValue
|	ShiftExpressionanyValue >>> AdditiveExpressionanyValue
Semantics
action Eval[ShiftExpressionExprKind] : Env  ValueOrException
Eval[ShiftExpressionExprKind  AdditiveExpressionExprKind]
  = Eval[AdditiveExpressionExprKind]
Eval[ShiftExpressionExprKind  ShiftExpressionanyValue1 << AdditiveExpressionanyValue]
            (e: Env)
  = letexc bitmapValue: Value = Eval[ShiftExpressionanyValue1](e)
     in letexc countValue: Value = Eval[AdditiveExpressionanyValue](e)
     in letexc bitmap: Integer = coerceToUint32(bitmapValue)
     in letexc count: Integer = coerceToUint32(countValue)
     in integerResult(
             uint32ToInt32(bitwiseAnd(bitwiseShift(bitmap, bitwiseAnd(count, 31)), 4294967295)))
Eval[ShiftExpressionExprKind  ShiftExpressionanyValue1 >> AdditiveExpressionanyValue]
            (e: Env)
  = letexc bitmapValue: Value = Eval[ShiftExpressionanyValue1](e)
     in letexc countValue: Value = Eval[AdditiveExpressionanyValue](e)
     in letexc bitmap: Integer = coerceToInt32(bitmapValue)
     in letexc count: Integer = coerceToUint32(countValue)
     in integerResult(bitwiseShift(bitmap, –bitwiseAnd(count, 31)))
Eval[ShiftExpressionExprKind  ShiftExpressionanyValue1 >>> AdditiveExpressionanyValue]
            (e: Env)
  = letexc bitmapValue: Value = Eval[ShiftExpressionanyValue1](e)
     in letexc countValue: Value = Eval[AdditiveExpressionanyValue](e)
     in letexc bitmap: Integer = coerceToUint32(bitmapValue)
     in letexc count: Integer = coerceToUint32(countValue)
     in integerResult(bitwiseShift(bitmap, –bitwiseAnd(count, 31)))
Relational Operators
Syntax
RelationalExpressionExprKind 
	ShiftExpressionExprKind
|	RelationalExpressionanyValue < ShiftExpressionanyValue
|	RelationalExpressionanyValue > ShiftExpressionanyValue
|	RelationalExpressionanyValue <= ShiftExpressionanyValue
|	RelationalExpressionanyValue >= ShiftExpressionanyValue
Semantics
action Eval[RelationalExpressionExprKind] : Env  ValueOrException
Eval[RelationalExpressionExprKind  ShiftExpressionExprKind]
  = Eval[ShiftExpressionExprKind]
Eval[RelationalExpressionExprKind  RelationalExpressionanyValue1 < ShiftExpressionanyValue]
            (e: Env)
  = letexc leftValue: Value = Eval[RelationalExpressionanyValue1](e)
     in letexc rightValue: Value = Eval[ShiftExpressionanyValue](e)
     in orderValues(leftValue, rightValue, true, false)
Eval[RelationalExpressionExprKind  RelationalExpressionanyValue1 > ShiftExpressionanyValue]
            (e: Env)
  = letexc leftValue: Value = Eval[RelationalExpressionanyValue1](e)
     in letexc rightValue: Value = Eval[ShiftExpressionanyValue](e)
     in orderValues(rightValue, leftValue, true, false)
Eval[RelationalExpressionExprKind  RelationalExpressionanyValue1 <= ShiftExpressionanyValue]
            (e: Env)
  = letexc leftValue: Value = Eval[RelationalExpressionanyValue1](e)
     in letexc rightValue: Value = Eval[ShiftExpressionanyValue](e)
     in orderValues(rightValue, leftValue, false, true)
Eval[RelationalExpressionExprKind  RelationalExpressionanyValue1 >= ShiftExpressionanyValue]
            (e: Env)
  = letexc leftValue: Value = Eval[RelationalExpressionanyValue1](e)
     in letexc rightValue: Value = Eval[ShiftExpressionanyValue](e)
     in orderValues(leftValue, rightValue, false, true)
orderValues(leftValue: Value, rightValue: Value, less: Boolean, greaterOrEqual: Boolean)
  : ValueOrException
  = letexc leftPrimitive: Value = coerceToPrimitive(leftValue, numberHint)
     in letexc rightPrimitive: Value = coerceToPrimitive(rightValue, numberHint)
     in if leftPrimitive is stringValue and rightPrimitive is stringValue
         then booleanResult(
                    compareStrings(
                        leftPrimitive.stringValue,
                        rightPrimitive.stringValue,
                        less,
                        greaterOrEqual,
                        greaterOrEqual))
         else letexc leftNumber: Double = coerceToDouble(leftPrimitive)
               in letexc rightNumber: Double = coerceToDouble(rightPrimitive)
               in booleanResult(
                       doubleCompare(
                           leftNumber,
                           rightNumber,
                           less,
                           greaterOrEqual,
                           greaterOrEqual,
                           false))
compareStrings(left: String, right: String, less: Boolean, equal: Boolean, greater: Boolean)
  : Boolean
  = if |left| = 0 and |right| = 0
     then equal
     else if |left| = 0
     then less
     else if |right| = 0
     then greater
     else let leftCharCode: Integer = characterToCode(left[0]);
               rightCharCode: Integer = characterToCode(right[0])
           in if leftCharCode < rightCharCode
               then less
               else if leftCharCode > rightCharCode
               then greater
               else compareStrings(left[1 ...], right[1 ...], less, equal, greater)
Equality Operators
Syntax
EqualityExpressionExprKind 
	RelationalExpressionExprKind
|	EqualityExpressionanyValue == RelationalExpressionanyValue
|	EqualityExpressionanyValue != RelationalExpressionanyValue
|	EqualityExpressionanyValue === RelationalExpressionanyValue
|	EqualityExpressionanyValue !== RelationalExpressionanyValue
Semantics
action Eval[EqualityExpressionExprKind] : Env  ValueOrException
Eval[EqualityExpressionExprKind  RelationalExpressionExprKind]
  = Eval[RelationalExpressionExprKind]
Eval[EqualityExpressionExprKind  EqualityExpressionanyValue1 == RelationalExpressionanyValue]
            (e: Env)
  = letexc leftValue: Value = Eval[EqualityExpressionanyValue1](e)
     in letexc rightValue: Value = Eval[RelationalExpressionanyValue](e)
     in letexc eq: Boolean = compareValues(leftValue, rightValue)
     in booleanResult(eq)
Eval[EqualityExpressionExprKind  EqualityExpressionanyValue1 != RelationalExpressionanyValue]
            (e: Env)
  = letexc leftValue: Value = Eval[EqualityExpressionanyValue1](e)
     in letexc rightValue: Value = Eval[RelationalExpressionanyValue](e)
     in letexc eq: Boolean = compareValues(leftValue, rightValue)
     in booleanResult(not eq)
Eval[EqualityExpressionExprKind  EqualityExpressionanyValue1 === RelationalExpressionanyValue]
            (e: Env)
  = letexc leftValue: Value = Eval[EqualityExpressionanyValue1](e)
     in letexc rightValue: Value = Eval[RelationalExpressionanyValue](e)
     in booleanResult(strictCompareValues(leftValue, rightValue))
Eval[EqualityExpressionExprKind  EqualityExpressionanyValue1 !== RelationalExpressionanyValue]
            (e: Env)
  = letexc leftValue: Value = Eval[EqualityExpressionanyValue1](e)
     in letexc rightValue: Value = Eval[RelationalExpressionanyValue](e)
     in booleanResult(not strictCompareValues(leftValue, rightValue))
compareValues(leftValue: Value, rightValue: Value) : BooleanOrException
  = case leftValue of
        undefinedValue, nullValue:
              case rightValue of
                 undefinedValue, nullValue: normal true;
                 booleanValue, doubleValue, stringValue, objectValue: normal false
                 end;
        booleanValue(leftBool: Boolean):
              case rightValue of
                 undefinedValue, nullValue: normal false;
                 booleanValue(rightBool: Boolean): normal (not (leftBool xor rightBool));
                 doubleValue, stringValue, objectValue:
                       compareDoubleToValue(coerceBooleanToDouble(leftBool), rightValue)
                 end;
        doubleValue(leftNumber: Double): compareDoubleToValue(leftNumber, rightValue);
        stringValue(leftStr: String):
              case rightValue of
                 undefinedValue, nullValue: normal false;
                 booleanValue(rightBool: Boolean):
                       letexc leftNumber: Double = coerceToDouble(leftValue)
                       in normal doubleEqual(leftNumber, coerceBooleanToDouble(rightBool));
                 doubleValue(rightNumber: Double):
                       letexc leftNumber: Double = coerceToDouble(leftValue)
                       in normal doubleEqual(leftNumber, rightNumber);
                 stringValue(rightStr: String):
                       normal compareStrings(leftStr, rightStr, false, true, false);
                 objectValue:
                       letexc rightPrimitive: Value = coerceToPrimitive(rightValue, noHint)
                       in compareValues(leftValue, rightPrimitive)
                 end;
        objectValue(leftObj: Object):
              case rightValue of
                 undefinedValue, nullValue: normal false;
                 booleanValue(rightBool: Boolean):
                       letexc leftPrimitive: Value = coerceToPrimitive(leftValue, noHint)
                       in compareValues(
                               leftPrimitive,
                               doubleValue coerceBooleanToDouble(rightBool));
                 doubleValue, stringValue:
                       letexc leftPrimitive: Value = coerceToPrimitive(leftValue, noHint)
                       in compareValues(leftPrimitive, rightValue);
                 objectValue(rightObj: Object):
                       normal (leftObj.properties  rightObj.properties)
                 end
        end
compareDoubleToValue(leftNumber: Double, rightValue: Value) : BooleanOrException
  = case rightValue of
        undefinedValue, nullValue: normal false;
        booleanValue, doubleValue, stringValue:
              letexc rightNumber: Double = coerceToDouble(rightValue)
              in normal doubleEqual(leftNumber, rightNumber);
        objectValue:
              letexc rightPrimitive: Value = coerceToPrimitive(rightValue, noHint)
              in compareDoubleToValue(leftNumber, rightPrimitive)
        end
doubleEqual(x: Double, y: Double) : Boolean
  = doubleCompare(x, y, false, true, false, false)
strictCompareValues(leftValue: Value, rightValue: Value) : Boolean
  = case leftValue of
        undefinedValue: rightValue is undefinedValue;
        nullValue: rightValue is nullValue;
        booleanValue(leftBool: Boolean):
              case rightValue of
                 booleanValue(rightBool: Boolean): not (leftBool xor rightBool);
                 undefinedValue, nullValue, doubleValue, stringValue, objectValue: false
                 end;
        doubleValue(leftNumber: Double):
              case rightValue of
                 doubleValue(rightNumber: Double): doubleEqual(leftNumber, rightNumber);
                 undefinedValue, nullValue, booleanValue, stringValue, objectValue: false
                 end;
        stringValue(leftStr: String):
              case rightValue of
                 stringValue(rightStr: String):
                       compareStrings(leftStr, rightStr, false, true, false);
                 undefinedValue, nullValue, booleanValue, doubleValue, objectValue: false
                 end;
        objectValue(leftObj: Object):
              case rightValue of
                 objectValue(rightObj: Object): leftObj.properties  rightObj.properties;
                 undefinedValue, nullValue, booleanValue, doubleValue, stringValue: false
                 end
        end
Binary Bitwise Operators
Syntax
BitwiseAndExpressionExprKind 
	EqualityExpressionExprKind
|	BitwiseAndExpressionanyValue & EqualityExpressionanyValue
BitwiseXorExpressionExprKind 
	BitwiseAndExpressionExprKind
|	BitwiseXorExpressionanyValue ^ BitwiseAndExpressionanyValue
BitwiseOrExpressionExprKind 
	BitwiseXorExpressionExprKind
|	BitwiseOrExpressionanyValue | BitwiseXorExpressionanyValue
Semantics
action Eval[BitwiseAndExpressionExprKind] : Env  ValueOrException
Eval[BitwiseAndExpressionExprKind  EqualityExpressionExprKind]
  = Eval[EqualityExpressionExprKind]
Eval[BitwiseAndExpressionExprKind  BitwiseAndExpressionanyValue1 & EqualityExpressionanyValue]
            (e: Env)
  = letexc leftValue: Value = Eval[BitwiseAndExpressionanyValue1](e)
     in letexc rightValue: Value = Eval[EqualityExpressionanyValue](e)
     in applyBinaryBitwiseOperator(bitwiseAnd, leftValue, rightValue)
action Eval[BitwiseXorExpressionExprKind] : Env  ValueOrException
Eval[BitwiseXorExpressionExprKind  BitwiseAndExpressionExprKind]
  = Eval[BitwiseAndExpressionExprKind]
Eval[BitwiseXorExpressionExprKind  BitwiseXorExpressionanyValue1 ^ BitwiseAndExpressionanyValue]
            (e: Env)
  = letexc leftValue: Value = Eval[BitwiseXorExpressionanyValue1](e)
     in letexc rightValue: Value = Eval[BitwiseAndExpressionanyValue](e)
     in applyBinaryBitwiseOperator(bitwiseXor, leftValue, rightValue)
action Eval[BitwiseOrExpressionExprKind] : Env  ValueOrException
Eval[BitwiseOrExpressionExprKind  BitwiseXorExpressionExprKind]
  = Eval[BitwiseXorExpressionExprKind]
Eval[BitwiseOrExpressionExprKind  BitwiseOrExpressionanyValue1 | BitwiseXorExpressionanyValue]
            (e: Env)
  = letexc leftValue: Value = Eval[BitwiseOrExpressionanyValue1](e)
     in letexc rightValue: Value = Eval[BitwiseXorExpressionanyValue](e)
     in applyBinaryBitwiseOperator(bitwiseOr, leftValue, rightValue)
applyBinaryBitwiseOperator(operator: Integer  Integer  Integer, leftValue: Value, rightValue: Value)
  : ValueOrException
  = letexc leftInt: Integer = coerceToInt32(leftValue)
     in letexc rightInt: Integer = coerceToInt32(rightValue)
     in integerResult(operator(leftInt, rightInt))
Binary Logical Operators
Syntax
LogicalAndExpressionExprKind 
	BitwiseOrExpressionExprKind
|	LogicalAndExpressionanyValue && BitwiseOrExpressionanyValue
LogicalOrExpressionExprKind 
	LogicalAndExpressionExprKind
|	LogicalOrExpressionanyValue || LogicalAndExpressionanyValue
Semantics
action Eval[LogicalAndExpressionExprKind] : Env  ValueOrException
Eval[LogicalAndExpressionExprKind  BitwiseOrExpressionExprKind]
  = Eval[BitwiseOrExpressionExprKind]
Eval[LogicalAndExpressionExprKind  LogicalAndExpressionanyValue1 && BitwiseOrExpressionanyValue]
            (e: Env)
  = letexc leftValue: Value = Eval[LogicalAndExpressionanyValue1](e)
     in if coerceToBoolean(leftValue)
         then Eval[BitwiseOrExpressionanyValue](e)
         else normal leftValue
action Eval[LogicalOrExpressionExprKind] : Env  ValueOrException
Eval[LogicalOrExpressionExprKind  LogicalAndExpressionExprKind]
  = Eval[LogicalAndExpressionExprKind]
Eval[LogicalOrExpressionExprKind  LogicalOrExpressionanyValue1 || LogicalAndExpressionanyValue]
            (e: Env)
  = letexc leftValue: Value = Eval[LogicalOrExpressionanyValue1](e)
     in if coerceToBoolean(leftValue)
         then normal leftValue
         else Eval[LogicalAndExpressionanyValue](e)
Conditional Operator
Syntax
ConditionalExpressionExprKind 
	LogicalOrExpressionExprKind
|	LogicalOrExpressionanyValue ? AssignmentExpressionanyValue : AssignmentExpressionanyValue
Semantics
action Eval[ConditionalExpressionExprKind] : Env  ValueOrException
Eval[ConditionalExpressionExprKind  LogicalOrExpressionExprKind]
  = Eval[LogicalOrExpressionExprKind]
Eval[ConditionalExpressionExprKind  LogicalOrExpressionanyValue ? AssignmentExpressionanyValue1 : AssignmentExpressionanyValue2]
            (e: Env)
  = letexc condition: Value = Eval[LogicalOrExpressionanyValue](e)
     in if coerceToBoolean(condition)
         then Eval[AssignmentExpressionanyValue1](e)
         else Eval[AssignmentExpressionanyValue2](e)
Assignment Operators
Syntax
AssignmentExpressionExprKind 
	ConditionalExpressionExprKind
|	Lvalue = AssignmentExpressionanyValue
Expressions
Syntax
CommaExpressionExprKind  AssignmentExpressionExprKind
Semantics
action Eval[AssignmentExpressionExprKind] : Env  ValueOrException
Eval[AssignmentExpressionExprKind  ConditionalExpressionExprKind]
  = Eval[ConditionalExpressionExprKind]
Eval[AssignmentExpressionExprKind  Lvalue = AssignmentExpressionanyValue1](e: Env)
  = letexc leftReference: Reference = Eval[Lvalue](e)
     in letexc rightValue: Value = Eval[AssignmentExpressionanyValue1](e)
     in letexc u: Void = referencePutValue(leftReference, rightValue)
     in normal rightValue
action Eval[CommaExpressionExprKind] : Env  ValueOrException
Eval[CommaExpressionExprKind  AssignmentExpressionExprKind]
  = Eval[AssignmentExpressionExprKind]
Syntax
Expression  CommaExpressionanyValue
Semantics
action Eval[Expression] : Env  ValueOrException
Eval[Expression  CommaExpressionanyValue] = Eval[CommaExpressionanyValue]
Programs
Syntax
Program  Expression End
Semantics
action Eval[Program] : ValueOrException
Eval[Program  Expression End] = Eval[Expression](this nullObjectOrNull)