RuntimeObj BitwiseShift(RuntimeObj val, RuntimeObj shift, bool right) { if (val == JSEvalNumber.Zero) { return(val); } double dR = shift.ToDouble(); int iShift; if (Double.IsNaN(dR) || (iShift = (dR < 0 ? (int)Math.Ceiling(dR) : (int)Math.Floor(dR)) % 64) == 0) { return(Global.CreateNumber(val)); } if (right && iShift < 0) { return(JSEvalNumber.Zero); } Int32 lN = JSSupport.ToInt32(val.ToDouble()); if (lN == 0) { return(JSEvalNumber.Zero); } return(Global.CreateNumber(right ? lN >> iShift : lN << iShift)); }
RuntimeObj BitwiseShiftRightUnsigned(RuntimeObj left, RuntimeObj right) { if (left == JSEvalNumber.Zero) { return(left); } double dR = right.ToDouble(); if (Double.IsNaN(dR)) { return(Global.CreateNumber(left)); } int iShift = (dR < 0 ? (int)Math.Ceiling(dR) : (int)Math.Floor(dR)) % 64; if (iShift < 0) { return(JSEvalNumber.Zero); } UInt32 lN = (UInt32)JSSupport.ToInt64(left.ToDouble()); if (lN == 0) { return(JSEvalNumber.Zero); } return(Global.CreateNumber(lN >> iShift)); }
RuntimeObj BitwiseShiftRightUnsigned(RuntimeObj left, RuntimeObj right) { if (left == DoubleObj.Zero) { return(left); } double dR = right.ToDouble(); if (double.IsNaN(dR)) { return(left is DoubleObj ? left : DoubleObj.Create(left.ToDouble())); } int iShift = (dR < 0 ? (int)Math.Ceiling(dR) : (int)Math.Floor(dR)) % 64; if (iShift < 0) { return(DoubleObj.Zero); } uint lN = (uint)JSSupport.ToInt64(left.ToDouble()); if (lN == 0) { return(DoubleObj.Zero); } return(DoubleObj.Create(lN >> iShift)); }
RuntimeObj BitwiseShift(RuntimeObj val, RuntimeObj shift, bool right) { if (val == DoubleObj.Zero) { return(val); } double dR = shift.ToDouble(); int iShift; if (double.IsNaN(dR) || (iShift = (dR < 0 ? (int)Math.Ceiling(dR) : (int)Math.Floor(dR)) % 64) == 0) { return(val.ToValue() as DoubleObj ?? DoubleObj.Create(val.ToDouble())); } if (right && iShift < 0) { return(DoubleObj.Zero); } int lN = JSSupport.ToInt32(val.ToDouble()); if (lN == 0) { return(DoubleObj.Zero); } return(DoubleObj.Create(right ? lN >> iShift : lN << iShift)); }
protected override PExpr DoVisit() { if (IsPendingOrSignal(ref _expression, Expr.Expression)) { return(PendingOrSignal(_expression)); } RuntimeObj result = _expression.Result; // Minus and Plus are classified as a binary operator. // Handle those special cases here. if (Expr.TokenType == JSTokenizerToken.Minus) { result = Global.CreateNumber(-result.ToDouble()); } else if (Expr.TokenType == JSTokenizerToken.Plus) { result = Global.CreateNumber(result.ToDouble()); } else { switch ((int)Expr.TokenType & 15) { case (int)JSTokenizerToken.Not & 15: { result = Global.CreateBoolean(!result.ToBoolean()); break; } case (int)JSTokenizerToken.BitwiseNot & 15: { result = Global.CreateNumber(~JSSupport.ToInt64(result.ToDouble())); break; } case (int)JSTokenizerToken.TypeOf & 15: { // Well known Javascript bug: typeof null === "object". if (result == RuntimeObj.Null) { result = Global.CreateString(RuntimeObj.TypeObject); } else { result = Global.CreateString(result.Type); } break; } case (int)JSTokenizerToken.Void & 15: { result = RuntimeObj.Undefined; break; } default: throw UnsupportedOperatorException(); } } return(SetResult(result)); }
public override PExpr Visit(IAccessorFrame frame) { var s = frame.GetState(c => c.On("toString").OnCall((f, args) => { return(f.SetResult(f.Global.CreateString(JSSupport.ToString(_value)))); } )); return(s != null?s.Visit() : frame.SetError()); }
public override PExpr Visit(IAccessorFrame frame) { var s = frame.GetState(c => c.On("toString").OnCall((f, args) => { int radix = 10; if (args.Count == 1) { radix = JSSupport.ToInt32(args[0].ToDouble()); } if (radix < 2 || radix > 36) { return(f.SetError("Radix must be between 2 and 36.")); } return(f.SetResult(f.Global.CreateString(JSSupport.ToString(_value, radix)))); } )); return(s != null?s.Visit() : frame.SetError()); }
public override PExpr Visit(IAccessorFrame frame) { var s = frame.GetState(c => c.On("charAt").OnCall((f, args) => { int idx = args.Count > 0 ? JSSupport.ToInt32(args[0].ToDouble()) : 0; if (idx < 0 || idx >= _value.Length) { return(f.SetResult(JSEvalString.EmptyString)); } return(f.SetResult(f.Global.CreateString(new String(_value[idx], 1)))); }) .On("toString").OnCall((f, args) => { return(f.SetResult(this)); } )); return(s != null?s.Visit() : frame.SetError()); }
public override PExpr Visit(IAccessorFrame frame) { var s = frame.GetImplementationState(c => c.OnIndex((f, arg) => { int idx = JSSupport.ToInt32(arg.ToDouble()); if (idx < 0 || idx >= _value.Length) { return(f.SetResult(EmptyString)); } return(f.SetResult(Create(new string( _value[idx], 1 )))); }) .On("ToString").OnCall((f, args) => { return(f.SetResult(this)); } )); return(s != null?s.Visit() : frame.SetError()); }
protected override PExpr DoVisit() { if (IsPendingOrSignal(ref _left, Expr.Left)) { return(PendingOrSignal(_left)); } // Do not evaluate right expression if it is useless: short-circuit boolean evaluation. if ((Expr.BinaryOperatorToken == JSTokenizerToken.And && !_left.Result.ToBoolean()) || (Expr.BinaryOperatorToken == JSTokenizerToken.Or && _left.Result.ToBoolean())) { return(SetResult(_left.Result)); } if (IsPendingOrSignal(ref _right, Expr.Right)) { return(PendingOrSignal(_right)); } RuntimeObj left = _left.Result; RuntimeObj right = _right.Result; // Right value is the result for And and Or. RuntimeObj result = right; if (Expr.BinaryOperatorToken != JSTokenizerToken.And && Expr.BinaryOperatorToken != JSTokenizerToken.Or) { if ((Expr.BinaryOperatorToken & JSTokenizerToken.IsCompareOperator) != 0) { #region ==, <, >, <=, >=, !=, === and !== int compareValue; switch ((int)Expr.BinaryOperatorToken & 15) { case (int)JSTokenizerToken.StrictEqual & 15: { result = Global.CreateBoolean(new RuntimeObjComparer(left, right).AreEqualStrict(Global)); break; } case (int)JSTokenizerToken.StrictDifferent & 15: { result = Global.CreateBoolean(!new RuntimeObjComparer(left, right).AreEqualStrict(Global)); break; } case (int)JSTokenizerToken.Greater & 15: { result = Global.CreateBoolean(new RuntimeObjComparer(left, right).Compare(Global, out compareValue) && compareValue > 0); break; } case (int)JSTokenizerToken.GreaterOrEqual & 15: { result = Global.CreateBoolean(new RuntimeObjComparer(left, right).Compare(Global, out compareValue) && compareValue >= 0); break; } case (int)JSTokenizerToken.Less & 15: { result = Global.CreateBoolean(new RuntimeObjComparer(left, right).Compare(Global, out compareValue) && compareValue < 0); break; } case (int)JSTokenizerToken.LessOrEqual & 15: { result = Global.CreateBoolean(new RuntimeObjComparer(left, right).Compare(Global, out compareValue) && compareValue <= 0); break; } case (int)JSTokenizerToken.Equal & 15: { result = Global.CreateBoolean(new RuntimeObjComparer(left, right).AreEqual(Global)); break; } case (int)JSTokenizerToken.Different & 15: { result = Global.CreateBoolean(!new RuntimeObjComparer(left, right).AreEqual(Global)); break; } default: throw UnsupportedOperatorException(); } #endregion } else if ((Expr.BinaryOperatorToken & JSTokenizerToken.IsBinaryOperator) != 0) { #region |, ^, &, >>, <<, >>>, +, -, /, * and %. switch ((int)Expr.BinaryOperatorToken & 15) { case (int)JSTokenizerToken.Plus & 15: { if (ReferenceEquals(left.Type, RuntimeObj.TypeNumber) && ReferenceEquals(right.Type, RuntimeObj.TypeNumber)) { result = Global.CreateNumber(left.ToDouble() + right.ToDouble()); } else { result = Global.CreateString(String.Concat(left.ToString(), right.ToString())); } break; } case (int)JSTokenizerToken.Minus & 15: { result = Global.CreateNumber(left.ToDouble() - right.ToDouble()); break; } case (int)JSTokenizerToken.Mult & 15: { result = Global.CreateNumber(left.ToDouble() * right.ToDouble()); break; } case (int)JSTokenizerToken.Divide & 15: { result = Global.CreateNumber(left.ToDouble() / right.ToDouble()); break; } case (int)JSTokenizerToken.Modulo & 15: { if (right == JSEvalNumber.Zero || left == JSEvalNumber.NegativeInfinity || left == JSEvalNumber.Infinity) { result = JSEvalNumber.NaN; } else if (left == JSEvalNumber.NegativeInfinity || left == JSEvalNumber.Infinity) { result = right; } else { result = Global.CreateNumber(left.ToDouble() % right.ToDouble()); } break; } case (int)JSTokenizerToken.BitwiseAnd & 15: { Int64 l = JSSupport.ToInt64(left.ToDouble()); Int64 rO = JSSupport.ToInt64(right.ToDouble()); result = Global.CreateNumber(l & rO); break; } case (int)JSTokenizerToken.BitwiseOr & 15: { Int64 l = JSSupport.ToInt64(left.ToDouble()); Int64 rO = JSSupport.ToInt64(right.ToDouble()); result = Global.CreateNumber(l | rO); break; } case (int)JSTokenizerToken.BitwiseXOr & 15: { Int64 l = JSSupport.ToInt64(left.ToDouble()); Int64 rO = JSSupport.ToInt64(right.ToDouble()); result = Global.CreateNumber(l ^ rO); break; } case (int)JSTokenizerToken.BitwiseShiftLeft & 15: { result = BitwiseShift(left, right, false); break; } case (int)JSTokenizerToken.BitwiseShiftRight & 15: { result = BitwiseShift(left, right, true); break; } case (int)JSTokenizerToken.BitwiseShiftRightNoSignBit & 15: { result = BitwiseShiftRightUnsigned(left, right); break; } default: throw UnsupportedOperatorException(); } #endregion } else { throw UnsupportedOperatorException(); } } return(SetResult(result)); }
public override string ToString() { return(JSSupport.ToString(_value)); }
public override double ToDouble() { return(JSSupport.ToNumber(_value)); }
public override bool ToBoolean() { return(JSSupport.ToBoolean(_value)); }
protected override PExpr DoVisit() { if (IsPendingOrSignal(ref _expression, Expr.Expression)) { RuntimeError e = _expression.AsErrorResult; if (e != null && e.IsReferenceError && ((int)Expr.TokenType & 15) == ((int)TokenizerToken.TypeOf & 15)) { return(SetResult(StringObj.Create(RuntimeObj.TypeUndefined))); } return(PendingOrSignal(_expression)); } RuntimeObj result = _expression.Result; // Minus and Plus are classified as a binary operator. // Handle those special cases here. if (Expr.TokenType == TokenizerToken.Minus) { result = DoubleObj.Create(-result.ToDouble()); } else if (Expr.TokenType == TokenizerToken.Plus) { result = DoubleObj.Create(result.ToDouble()); } else { switch ((int)Expr.TokenType & 15) { case (int)TokenizerToken.Not & 15: { result = result.ToBoolean() ? BooleanObj.False : BooleanObj.True; break; } case (int)TokenizerToken.BitwiseNot & 15: { result = DoubleObj.Create(~JSSupport.ToInt64(result.ToDouble())); break; } case (int)TokenizerToken.TypeOf & 15: { // Well known Javascript bug: typeof null === "object". if (result == RuntimeObj.Null) { result = StringObj.Create(RuntimeObj.TypeObject); } else { result = StringObj.Create(result.Type); } break; } case (int)TokenizerToken.IndexOf & 15: { RefRuntimeIndexedObj iO = result as RefRuntimeIndexedObj; if (iO == null) { result = new RuntimeError(Expr, "No associated index. indexof must be used on a foreach variable."); } else { result = iO.Index; } break; } case (int)TokenizerToken.Void & 15: { result = RuntimeObj.Undefined; break; } default: throw UnsupportedOperatorException(); } } return(SetResult(result)); }