Formal JavaScript Semantics
Grammar
previousup

Wednesday, February 28, 2001

Types

Semantics

type Value
  = oneof {
           undefinedValue;
           nullValue;
           booleanValue: Boolean;
           numberValue: Float64;
           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 Float64OrException = oneof {normal: Float64; 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
float64Result(d: Float64) : ValueOrException = normal numberValue d
integerResult(i: Integer) : ValueOrException = float64Result(rationalToFloat64(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;
        numberValue(d: Float64): not (float64IsZero(d) or float64IsNaN(d));
        stringValue(s: String): |s|  0;
        objectValue: true
        end
coerceBooleanToFloat64(b: Boolean) : Float64 = if b then 1.0 else +0.0
coerceToFloat64(v: Value) : Float64OrException
  = case v of
        undefinedValue: normal NaN;
        nullValue: normal +0.0;
        booleanValue(b: Boolean): normal coerceBooleanToFloat64(b);
        numberValue(d: Float64): normal d;
        stringValue: ;
        objectValue: 
        end
float64ToUint32(x: Float64) : Integer
  = if float64IsNaN(x) or float64IsInfinite(x) then 0 else truncateFloat64(x)mod4294967296
coerceToUint32(v: Value) : IntegerOrException
  = letexc d: Float64 = coerceToFloat64(v)
     in normal float64ToUint32(d)
coerceToInt32(v: Value) : IntegerOrException
  = letexc d: Float64 = coerceToFloat64(v)
     in normal uint32ToInt32(float64ToUint32(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”;
        numberValue: ;
        stringValue(s: String): normal s;
        objectValue: 
        end
coerceToPrimitive(v: Value, hint: DefaultValueHint) : ValueOrException
  = case v of
        undefinedValue, nullValue, booleanValue, numberValue, stringValue: normal v;
        objectValue(o: Object):
              letexc pv: Value = o.defaultValue(hint)
              in case pv of
                     undefinedValue, nullValue, booleanValue, numberValue, stringValue:
                           normal pv;
                     objectValue: abruptValueOrException makeError(coerceToPrimitiveError)
                     end
        end
coerceToObject(v: Value) : ObjectOrException
  = case v of
        undefinedValue, nullValue: abruptObjectOrException makeError(coerceToObjectError);
        booleanValue: ;
        numberValue: ;
        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] : Float64
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) = float64Result(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, numberValue, stringValue:
              abruptReferenceOrException makeError(coerceToObjectError);
        objectValue(o: Object): o.call(this, arguments)
        end
constructObject(constructor: Value, arguments: Value[]) : ValueOrException
  = case constructor of
        undefinedValue, nullValue, booleanValue, numberValue, 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: Float64 = coerceToFloat64(operandValue)
     in letexc u: Void
                  = referencePutValue(operandReference, numberValue float64Add(operand, 1.0))
     in float64Result(operand)
Eval[PostfixExpressionExprKind  Lvalue --](e: Env)
  = letexc operandReference: Reference = Eval[Lvalue](e)
     in letexc operandValue: Value = referenceGetValue(operandReference)
     in letexc operand: Float64 = coerceToFloat64(operandValue)
     in letexc u: Void
                  = referencePutValue(
                         operandReference,
                         numberValue float64Subtract(operand, 1.0))
     in float64Result(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: Float64 = coerceToFloat64(operandValue)
     in let res: Float64 = float64Add(operand, 1.0)
     in letexc u: Void = referencePutValue(operandReference, numberValue res)
     in float64Result(res)
Eval[UnaryExpressionExprKind  -- Lvalue](e: Env)
  = letexc operandReference: Reference = Eval[Lvalue](e)
     in letexc operandValue: Value = referenceGetValue(operandReference)
     in letexc operand: Float64 = coerceToFloat64(operandValue)
     in let res: Float64 = float64Subtract(operand, 1.0)
     in letexc u: Void = referencePutValue(operandReference, numberValue res)
     in float64Result(res)
Eval[UnaryExpressionExprKind  + UnaryExpressionanyValue1](e: Env)
  = letexc operandValue: Value = Eval[UnaryExpressionanyValue1](e)
     in letexc operand: Float64 = coerceToFloat64(operandValue)
     in float64Result(operand)
Eval[UnaryExpressionExprKind  - UnaryExpressionanyValue1](e: Env)
  = letexc operandValue: Value = Eval[UnaryExpressionanyValue1](e)
     in letexc operand: Float64 = coerceToFloat64(operandValue)
     in float64Result(float64Negate(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”;
        numberValue: “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 applyBinaryFloat64Operator(float64Multiply, leftValue, rightValue)
Eval[MultiplicativeExpressionExprKind  MultiplicativeExpressionanyValue1 / UnaryExpressionanyValue]
            (e: Env)
  = letexc leftValue: Value = Eval[MultiplicativeExpressionanyValue1](e)
     in letexc rightValue: Value = Eval[UnaryExpressionanyValue](e)
     in applyBinaryFloat64Operator(float64Divide, leftValue, rightValue)
Eval[MultiplicativeExpressionExprKind  MultiplicativeExpressionanyValue1 % UnaryExpressionanyValue]
            (e: Env)
  = letexc leftValue: Value = Eval[MultiplicativeExpressionanyValue1](e)
     in letexc rightValue: Value = Eval[UnaryExpressionanyValue](e)
     in applyBinaryFloat64Operator(float64Remainder, leftValue, rightValue)
applyBinaryFloat64Operator(operator: Float64  Float64  Float64,
        leftValue: Value,
        rightValue: Value) : ValueOrException
  = letexc leftNumber: Float64 = coerceToFloat64(leftValue)
     in letexc rightNumber: Float64 = coerceToFloat64(rightValue)
     in float64Result(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 applyBinaryFloat64Operator(float64Add, leftPrimitive, rightPrimitive)
Eval[AdditiveExpressionExprKind  AdditiveExpressionanyValue1 - MultiplicativeExpressionanyValue]
            (e: Env)
  = letexc leftValue: Value = Eval[AdditiveExpressionanyValue1](e)
     in letexc rightValue: Value = Eval[MultiplicativeExpressionanyValue](e)
     in applyBinaryFloat64Operator(float64Subtract, 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: Float64 = coerceToFloat64(leftPrimitive)
               in letexc rightNumber: Float64 = coerceToFloat64(rightPrimitive)
               in booleanResult(
                       float64Compare(
                           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, numberValue, stringValue, objectValue: normal false
                 end;
        booleanValue(leftBool: Boolean):
              case rightValue of
                 undefinedValue, nullValue: normal false;
                 booleanValue(rightBool: Boolean): normal (not (leftBool xor rightBool));
                 numberValue, stringValue, objectValue:
                       compareFloat64ToValue(coerceBooleanToFloat64(leftBool), rightValue)
                 end;
        numberValue(leftNumber: Float64): compareFloat64ToValue(leftNumber, rightValue);
        stringValue(leftStr: String):
              case rightValue of
                 undefinedValue, nullValue: normal false;
                 booleanValue(rightBool: Boolean):
                       letexc leftNumber: Float64 = coerceToFloat64(leftValue)
                       in normal float64Equal(leftNumber, coerceBooleanToFloat64(rightBool));
                 numberValue(rightNumber: Float64):
                       letexc leftNumber: Float64 = coerceToFloat64(leftValue)
                       in normal float64Equal(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,
                               numberValue coerceBooleanToFloat64(rightBool));
                 numberValue, stringValue:
                       letexc leftPrimitive: Value = coerceToPrimitive(leftValue, noHint)
                       in compareValues(leftPrimitive, rightValue);
                 objectValue(rightObj: Object):
                       normal (leftObj.properties  rightObj.properties)
                 end
        end
compareFloat64ToValue(leftNumber: Float64, rightValue: Value) : BooleanOrException
  = case rightValue of
        undefinedValue, nullValue: normal false;
        booleanValue, numberValue, stringValue:
              letexc rightNumber: Float64 = coerceToFloat64(rightValue)
              in normal float64Equal(leftNumber, rightNumber);
        objectValue:
              letexc rightPrimitive: Value = coerceToPrimitive(rightValue, noHint)
              in compareFloat64ToValue(leftNumber, rightPrimitive)
        end
float64Equal(x: Float64, y: Float64) : Boolean
  = float64Compare(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, numberValue, stringValue, objectValue: false
                 end;
        numberValue(leftNumber: Float64):
              case rightValue of
                 numberValue(rightNumber: Float64): float64Equal(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, numberValue, objectValue: false
                 end;
        objectValue(leftObj: Object):
              case rightValue of
                 objectValue(rightObj: Object): leftObj.properties  rightObj.properties;
                 undefinedValue, nullValue, booleanValue, numberValue, 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)

Waldemar Horwat
Last modified Wednesday, February 28, 2001
previousup