Ejemplo n.º 1
0
        /// <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.
            object left = this.Left.Evaluate();

            if (left == null)
            {
                return(null);
            }

            object right;

            if (OperatorType == OperatorType.In)
            {
                right = null;

                if (ResolvedPrototype == null)
                {
                    return(null);
                }
            }
            else
            {
                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));

            // 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:
                return(TypeComparer.LessThan(left, right));

            case OperatorType.LessThanOrEqual:
                return(TypeComparer.LessThanOrEqual(left, right));

            case OperatorType.GreaterThan:
                return(TypeComparer.GreaterThan(left, right));

            case OperatorType.GreaterThanOrEqual:
                return(TypeComparer.GreaterThanOrEqual(left, right));

            // 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.In:

                // Constant property! Convert it to a string:
                string propertyName = TypeConverter.ToString(left);

                // Exists?
                return(ResolvedPrototype.GetProperty(propertyName) != null);

            case OperatorType.InstanceOf:
                return(null);

            default:
                throw new NotImplementedException(string.Format("Unsupported operator {0}", this.OperatorType));
            }
        }