/// <summary> /// Returns the index of the given search element in the array, searching backwards from /// <paramref name="fromIndex"/>. /// </summary> /// <param name="searchElement"> The value to search for. </param> /// <param name="fromIndex"> The array index to start searching. </param> /// <returns> The index of the given search element in the array, or <c>-1</c> if the /// element wasn't found. </returns> public int LastIndexOf(object searchElement, int fromIndex) { // If fromIndex is less than zero, it is an offset from the end of the array. if (fromIndex < 0) { fromIndex += Length; } for (int i = Math.Min(Length - 1, fromIndex); i >= 0; i--) { // Get the value of the array element. object elementValue = this[i]; // Compare the given search element with the array element. if (elementValue != null && TypeComparer.StrictEquals(searchElement, elementValue) == true) { return(i); } } // The search element wasn't found. return(-1); }
/// <summary> /// Evaluates the expression, if possible. /// </summary> /// <returns> The result of evaluating the expression, or <c>null</c> if the expression can /// not be evaluated. </returns> public override object Evaluate() { // Evaluate the operands. var left = this.Left.Evaluate(); if (left == null) { return(null); } var right = this.Right.Evaluate(); if (right == null) { return(null); } // Apply the binary operator logic. switch (this.OperatorType) { case OperatorType.Add: { var leftPrimitive = TypeConverter.ToPrimitive(left, PrimitiveTypeHint.None); var rightPrimitive = TypeConverter.ToPrimitive(right, PrimitiveTypeHint.None); if (TypeUtilities.IsString(leftPrimitive) == true || TypeUtilities.IsString(rightPrimitive) == true) { return(TypeConverter.ToString(leftPrimitive) + TypeConverter.ToString(rightPrimitive)); } return(TypeConverter.ToNumber(leftPrimitive) + TypeConverter.ToNumber(rightPrimitive)); } // Arithmetic operations. case OperatorType.Subtract: return(TypeConverter.ToNumber(left) - TypeConverter.ToNumber(right)); case OperatorType.Multiply: return(TypeConverter.ToNumber(left) * TypeConverter.ToNumber(right)); case OperatorType.Divide: return(TypeConverter.ToNumber(left) / TypeConverter.ToNumber(right)); case OperatorType.Modulo: return(TypeConverter.ToNumber(left) % TypeConverter.ToNumber(right)); case OperatorType.Exponentiation: return(Library.MathObject.Pow(TypeConverter.ToNumber(left), TypeConverter.ToNumber(right))); // Bitwise operations. case OperatorType.BitwiseAnd: return(TypeConverter.ToInt32(left) & TypeConverter.ToInt32(right)); case OperatorType.BitwiseOr: return(TypeConverter.ToInt32(left) | TypeConverter.ToInt32(right)); case OperatorType.BitwiseXor: return(TypeConverter.ToInt32(left) ^ TypeConverter.ToInt32(right)); case OperatorType.LeftShift: return(TypeConverter.ToInt32(left) << (int)(TypeConverter.ToUint32(right) & 0x1F)); case OperatorType.SignedRightShift: return(TypeConverter.ToInt32(left) >> (int)(TypeConverter.ToUint32(right) & 0x1F)); case OperatorType.UnsignedRightShift: return((uint)TypeConverter.ToInt32(left) >> (int)(TypeConverter.ToUint32(right) & 0x1F)); // Relational operations. case OperatorType.LessThan: case OperatorType.LessThanOrEqual: case OperatorType.GreaterThan: case OperatorType.GreaterThanOrEqual: return(PrimitiveType.Bool); // Equality operations. case OperatorType.Equal: return(TypeComparer.Equals(left, right) == true); case OperatorType.StrictlyEqual: return(TypeComparer.StrictEquals(left, right) == true); case OperatorType.NotEqual: return(TypeComparer.Equals(left, right) == false); case OperatorType.StrictlyNotEqual: return(TypeComparer.StrictEquals(left, right) == false); // Logical operations. case OperatorType.LogicalAnd: if (TypeConverter.ToBoolean(left) == false) { return(left); } return(right); case OperatorType.LogicalOr: if (TypeConverter.ToBoolean(left) == true) { return(left); } return(right); // Misc case OperatorType.InstanceOf: case OperatorType.In: return(null); default: throw new NotImplementedException(string.Format("Unsupported operator {0}", this.OperatorType)); } }
public void StrictEquals() { var engine = new ScriptEngine(); // Undefined. Assert.AreEqual(true, TypeComparer.StrictEquals(Undefined.Value, Undefined.Value)); Assert.AreEqual(false, TypeComparer.StrictEquals(Undefined.Value, Null.Value)); Assert.AreEqual(false, TypeComparer.StrictEquals(Undefined.Value, false)); Assert.AreEqual(false, TypeComparer.StrictEquals(Undefined.Value, true)); Assert.AreEqual(false, TypeComparer.StrictEquals(Undefined.Value, 0)); Assert.AreEqual(false, TypeComparer.StrictEquals(Undefined.Value, 0.0)); Assert.AreEqual(false, TypeComparer.StrictEquals(Undefined.Value, 5.5)); Assert.AreEqual(false, TypeComparer.StrictEquals(Undefined.Value, double.NaN)); Assert.AreEqual(false, TypeComparer.StrictEquals(Undefined.Value, "")); Assert.AreEqual(false, TypeComparer.StrictEquals(Undefined.Value, " ")); Assert.AreEqual(false, TypeComparer.StrictEquals(Undefined.Value, "5.5")); Assert.AreEqual(false, TypeComparer.StrictEquals(Undefined.Value, "foo")); Assert.AreEqual(false, TypeComparer.StrictEquals(Undefined.Value, engine.Object.Construct())); // Null. Assert.AreEqual(false, TypeComparer.StrictEquals(Null.Value, Undefined.Value)); Assert.AreEqual(true, TypeComparer.StrictEquals(Null.Value, Null.Value)); Assert.AreEqual(false, TypeComparer.StrictEquals(Null.Value, false)); Assert.AreEqual(false, TypeComparer.StrictEquals(Null.Value, true)); Assert.AreEqual(false, TypeComparer.StrictEquals(Null.Value, 0)); Assert.AreEqual(false, TypeComparer.StrictEquals(Null.Value, 0.0)); Assert.AreEqual(false, TypeComparer.StrictEquals(Null.Value, 5.5)); Assert.AreEqual(false, TypeComparer.StrictEquals(Null.Value, double.NaN)); Assert.AreEqual(false, TypeComparer.StrictEquals(Null.Value, "")); Assert.AreEqual(false, TypeComparer.StrictEquals(Null.Value, " ")); Assert.AreEqual(false, TypeComparer.StrictEquals(Null.Value, "5.5")); Assert.AreEqual(false, TypeComparer.StrictEquals(Null.Value, "foo")); Assert.AreEqual(false, TypeComparer.StrictEquals(Null.Value, engine.Object.Construct())); // Boolean. Assert.AreEqual(false, TypeComparer.StrictEquals(false, Undefined.Value)); Assert.AreEqual(false, TypeComparer.StrictEquals(false, Null.Value)); Assert.AreEqual(true, TypeComparer.StrictEquals(false, false)); Assert.AreEqual(false, TypeComparer.StrictEquals(false, true)); Assert.AreEqual(false, TypeComparer.StrictEquals(false, 0)); Assert.AreEqual(false, TypeComparer.StrictEquals(false, 0.0)); Assert.AreEqual(false, TypeComparer.StrictEquals(false, 5.5)); Assert.AreEqual(false, TypeComparer.StrictEquals(false, double.NaN)); Assert.AreEqual(false, TypeComparer.StrictEquals(false, "")); Assert.AreEqual(false, TypeComparer.StrictEquals(false, " ")); Assert.AreEqual(false, TypeComparer.StrictEquals(false, "5.5")); Assert.AreEqual(false, TypeComparer.StrictEquals(false, "foo")); Assert.AreEqual(false, TypeComparer.StrictEquals(false, engine.Object.Construct())); Assert.AreEqual(false, TypeComparer.StrictEquals(false, engine.Boolean.Construct(false))); Assert.AreEqual(false, TypeComparer.StrictEquals(false, engine.Boolean.Construct(true))); Assert.AreEqual(false, TypeComparer.StrictEquals(false, engine.Number.Construct(0))); Assert.AreEqual(false, TypeComparer.StrictEquals(false, engine.Number.Construct(1))); // Number. Assert.AreEqual(false, TypeComparer.StrictEquals(5.5, Undefined.Value)); Assert.AreEqual(false, TypeComparer.StrictEquals(5.5, Null.Value)); Assert.AreEqual(false, TypeComparer.StrictEquals(5.5, false)); Assert.AreEqual(false, TypeComparer.StrictEquals(5.5, true)); Assert.AreEqual(false, TypeComparer.StrictEquals(5.5, 0)); Assert.AreEqual(false, TypeComparer.StrictEquals(5.5, 0.0)); Assert.AreEqual(true, TypeComparer.StrictEquals(5.5, 5.5)); Assert.AreEqual(false, TypeComparer.StrictEquals(5.5, double.NaN)); Assert.AreEqual(false, TypeComparer.StrictEquals(5.5, "")); Assert.AreEqual(false, TypeComparer.StrictEquals(5.5, " ")); Assert.AreEqual(false, TypeComparer.StrictEquals(5.5, "5.5")); Assert.AreEqual(false, TypeComparer.StrictEquals(5.5, "foo")); Assert.AreEqual(false, TypeComparer.StrictEquals(5.5, engine.Object.Construct())); Assert.AreEqual(false, TypeComparer.StrictEquals(5.5, engine.Number.Construct(5.5))); Assert.AreEqual(true, TypeComparer.StrictEquals(0, 0.0)); Assert.AreEqual(true, TypeComparer.StrictEquals(5, 5.0)); Assert.AreEqual(false, TypeComparer.StrictEquals(double.NaN, double.NaN)); // String. Assert.AreEqual(false, TypeComparer.StrictEquals("5.5", Undefined.Value)); Assert.AreEqual(false, TypeComparer.StrictEquals("5.5", Null.Value)); Assert.AreEqual(false, TypeComparer.StrictEquals("5.5", false)); Assert.AreEqual(false, TypeComparer.StrictEquals("5.5", true)); Assert.AreEqual(false, TypeComparer.StrictEquals("5.5", 0)); Assert.AreEqual(false, TypeComparer.StrictEquals("5.5", 0.0)); Assert.AreEqual(false, TypeComparer.StrictEquals("5.5", 5.5)); Assert.AreEqual(false, TypeComparer.StrictEquals("5.5", double.NaN)); Assert.AreEqual(false, TypeComparer.StrictEquals("5.5", "")); Assert.AreEqual(false, TypeComparer.StrictEquals("5.5", " ")); Assert.AreEqual(true, TypeComparer.StrictEquals("5.5", "5.5")); Assert.AreEqual(false, TypeComparer.StrictEquals("5.5", "foo")); Assert.AreEqual(false, TypeComparer.StrictEquals("5.5", engine.Object.Construct())); Assert.AreEqual(false, TypeComparer.StrictEquals("5.5", engine.Number.Construct(5.5))); Assert.AreEqual(false, TypeComparer.StrictEquals("5.5", engine.String.Construct("5.5"))); // Object. var temp = engine.Object.Construct(); Assert.AreEqual(true, TypeComparer.StrictEquals(temp, temp)); Assert.AreEqual(false, TypeComparer.StrictEquals(engine.Object.Construct(), engine.Object.Construct())); Assert.AreEqual(false, TypeComparer.StrictEquals(engine.Number.Construct(5.5), engine.Number.Construct(5.5))); Assert.AreEqual(false, TypeComparer.StrictEquals(engine.String.Construct("5.5"), engine.String.Construct("5.5"))); }