ToNumber() публичный статический Метод

Pops the value on the stack, converts it to a double, then pushes the double result onto the stack.
public static ToNumber ( ILGenerator generator, PrimitiveType fromType ) : void
generator ILGenerator The IL generator.
fromType PrimitiveType The type to convert from.
Результат void
Пример #1
0
        /// <summary>
        /// Generates CIL for the logical operators.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        private void GenerateLogical(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            // Get the statically-determined types of the left and right operands.
            PrimitiveType leftType  = this.Left.ResultType;
            PrimitiveType rightType = this.Right.ResultType;

            // Load the left-hand side operand.
            this.Left.GenerateCode(generator, optimizationInfo);

            // Make sure the output type is consistant.
            if (leftType != rightType)
            {
                if (PrimitiveTypeUtilities.IsNumeric(leftType) == true && PrimitiveTypeUtilities.IsNumeric(rightType) == true)
                {
                    EmitConversion.ToNumber(generator, leftType);
                    leftType = PrimitiveType.Number;
                }
                else
                {
                    EmitConversion.ToAny(generator, leftType);
                    leftType = PrimitiveType.Any;
                }
            }

            // Duplicate and convert to a Boolean.
            generator.Duplicate();
            EmitConversion.ToBool(generator, leftType);

            // Stack contains "left, (bool)left"
            var endOfIf = generator.CreateLabel();

            if (this.OperatorType == OperatorType.LogicalAnd)
            {
                generator.BranchIfFalse(endOfIf);
            }
            else
            {
                generator.BranchIfTrue(endOfIf);
            }

            // Stack contains "left".  Load the right-hand side operand.
            generator.Pop();
            this.Right.GenerateCode(generator, optimizationInfo);

            // Make sure the output type is consistant.
            if (leftType != rightType)
            {
                if (PrimitiveTypeUtilities.IsNumeric(leftType) == true && PrimitiveTypeUtilities.IsNumeric(rightType) == true)
                {
                    EmitConversion.ToNumber(generator, rightType);
                }
                else
                {
                    EmitConversion.ToAny(generator, rightType);
                }
            }

            // Define the label used above.
            generator.DefineLabelPosition(endOfIf);
        }
Пример #2
0
        /// <summary>
        /// Generates CIL for an increment or decrement expression.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        /// <param name="target"> The target to modify. </param>
        /// <param name="postfix"> <c>true</c> if this is the postfix version of the operator;
        /// <c>false</c> otherwise. </param>
        /// <param name="increment"> <c>true</c> if this is the increment operator; <c>false</c> if
        /// this is the decrement operator. </param>
        private void GenerateIncrementOrDecrement(ILGenerator generator, OptimizationInfo optimizationInfo, IReferenceExpression target, bool postfix, bool increment)
        {
            // Note: increment and decrement can produce a number that is out of range if the
            // target is of type Int32.  The only time this should happen is for a loop variable
            // where the range has been carefully checked to make sure an out of range condition
            // cannot happen.

            // Get the target value.
            target.GenerateGet(generator, optimizationInfo, true);

            // Convert it to a number.
            if (target.Type != PrimitiveType.Int32)
            {
                EmitConversion.ToNumber(generator, target.Type);
            }

            // If this is PostIncrement or PostDecrement, duplicate the value so it can be produced as the return value.
            if (postfix == true)
            {
                generator.Duplicate();
            }

            // Load the increment constant.
            if (target.Type == PrimitiveType.Int32)
            {
                generator.LoadInt32(1);
            }
            else
            {
                generator.LoadDouble(1.0);
            }

            // Add or subtract the constant to the target value.
            if (increment == true)
            {
                generator.Add();
            }
            else
            {
                generator.Subtract();
            }

            // If this is PreIncrement or PreDecrement, duplicate the value so it can be produced as the return value.
            if (postfix == false)
            {
                generator.Duplicate();
            }

            // Store the value.
            target.GenerateSet(generator, optimizationInfo, target.Type == PrimitiveType.Int32 ? PrimitiveType.Int32 : PrimitiveType.Number, optimizationInfo.StrictMode);
        }
Пример #3
0
        /// <summary>
        /// Generates CIL for the relational operators.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        private void GenerateRelational(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            // Get the statically-determined types of the left and right operands.
            PrimitiveType leftType  = this.Left.ResultType;
            PrimitiveType rightType = this.Right.ResultType;

            // The relational operators compare strings if both of the operands are strings.
            if (leftType == PrimitiveType.String && rightType == PrimitiveType.String)
            {
                // Both of the operands are strings.

                // Load the left hand side operand onto the stack.
                this.Left.GenerateCode(generator, optimizationInfo);

                // Load the right hand side operand onto the stack.
                this.Right.GenerateCode(generator, optimizationInfo);

                // Compare the two strings.
                generator.Call(ReflectionHelpers.String_CompareOrdinal);
                switch (this.OperatorType)
                {
                case OperatorType.LessThan:
                    generator.LoadInt32(0);
                    generator.CompareLessThan();
                    break;

                case OperatorType.LessThanOrEqual:
                    generator.LoadInt32(1);
                    generator.CompareLessThan();
                    break;

                case OperatorType.GreaterThan:
                    generator.LoadInt32(0);
                    generator.CompareGreaterThan();
                    break;

                case OperatorType.GreaterThanOrEqual:
                    generator.LoadInt32(-1);
                    generator.CompareGreaterThan();
                    break;
                }
            }
            else if (leftType == PrimitiveType.Int32 && rightType == PrimitiveType.Int32)
            {
                // Both of the operands are integers.

                // Load the left hand side operand onto the stack.
                this.Left.GenerateCode(generator, optimizationInfo);

                // Load the right hand side operand onto the stack.
                this.Right.GenerateCode(generator, optimizationInfo);

                // Compare the two numbers.
                switch (this.OperatorType)
                {
                case OperatorType.LessThan:
                    generator.CompareLessThan();
                    break;

                case OperatorType.GreaterThan:
                    generator.CompareGreaterThan();
                    break;

                case OperatorType.LessThanOrEqual:
                    // a <= b   <-->   (a > b) == false
                    generator.CompareGreaterThan();
                    generator.LoadBoolean(false);
                    generator.CompareEqual();
                    break;

                case OperatorType.GreaterThanOrEqual:
                    // a >= b   <-->   (a < b) == false
                    generator.CompareLessThan();
                    generator.LoadBoolean(false);
                    generator.CompareEqual();
                    break;
                }
            }
            else if (PrimitiveTypeUtilities.IsNumeric(leftType) || PrimitiveTypeUtilities.IsNumeric(rightType))
            {
                // At least one of the operands is a number.

                // Load the left hand side operand onto the stack.
                this.Left.GenerateCode(generator, optimizationInfo);

                // Convert the operand to a number.
                EmitConversion.ToNumber(generator, leftType);

                // Load the right hand side operand onto the stack.
                this.Right.GenerateCode(generator, optimizationInfo);

                // Convert the operand to a number.
                EmitConversion.ToNumber(generator, rightType);

                // Compare the two numbers.
                switch (this.OperatorType)
                {
                case OperatorType.LessThan:
                    generator.CompareLessThan();
                    break;

                case OperatorType.GreaterThan:
                    generator.CompareGreaterThan();
                    break;

                case OperatorType.LessThanOrEqual:
                    // a <= b   <-->   (a > b) == false
                    generator.CompareGreaterThanUnsigned();
                    generator.LoadBoolean(false);
                    generator.CompareEqual();
                    break;

                case OperatorType.GreaterThanOrEqual:
                    // a >= b   <-->   (a < b) == false
                    generator.CompareLessThanUnsigned();
                    generator.LoadBoolean(false);
                    generator.CompareEqual();
                    break;
                }
            }
            else
            {
                // It is unknown whether one of the operands is a string.

                // Load the left hand side operand onto the stack.
                this.Left.GenerateCode(generator, optimizationInfo);
                EmitConversion.ToAny(generator, leftType);

                // Load the right hand side operand onto the stack.
                this.Right.GenerateCode(generator, optimizationInfo);
                EmitConversion.ToAny(generator, rightType);

                switch (this.OperatorType)
                {
                case OperatorType.LessThan:
                    generator.Call(ReflectionHelpers.TypeComparer_LessThan);
                    break;

                case OperatorType.LessThanOrEqual:
                    generator.Call(ReflectionHelpers.TypeComparer_LessThanOrEqual);
                    break;

                case OperatorType.GreaterThan:
                    generator.Call(ReflectionHelpers.TypeComparer_GreaterThan);
                    break;

                case OperatorType.GreaterThanOrEqual:
                    generator.Call(ReflectionHelpers.TypeComparer_GreaterThanOrEqual);
                    break;
                }
            }
        }
Пример #4
0
        /// <summary>
        /// Generates CIL for the addition operation.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        private void GenerateAdd(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            // Get the statically-determined types of the left and right operands.
            PrimitiveType leftType  = this.Left.ResultType;
            PrimitiveType rightType = this.Right.ResultType;

            // The add operator adds two strings together if at least one of the operands
            // is a string, otherwise it adds two numbers.
            if (PrimitiveTypeUtilities.IsString(leftType) || PrimitiveTypeUtilities.IsString(rightType))
            {
                // If at least one of the operands is a string, then the add operator concatenates.

                // Load the left-hand side onto the stack.
                this.Left.GenerateCode(generator, optimizationInfo);

                // Convert the operand to a concatenated string.
                EmitConversion.ToPrimitive(generator, leftType, PrimitiveTypeHint.None);
                EmitConversion.ToConcatenatedString(generator, leftType);

                // Load the right-hand side onto the stack.
                this.Right.GenerateCode(generator, optimizationInfo);

                if (rightType == PrimitiveType.String)
                {
                    // Concatenate the two strings.
                    generator.Call(ReflectionHelpers.ConcatenatedString_Concatenate_String);
                }
                else if (rightType == PrimitiveType.ConcatenatedString)
                {
                    // Concatenate the two strings.
                    generator.Call(ReflectionHelpers.ConcatenatedString_Concatenate_ConcatenatedString);
                }
                else
                {
                    // Convert the operand to an object.
                    EmitConversion.ToPrimitive(generator, rightType, PrimitiveTypeHint.None);
                    EmitConversion.ToAny(generator, rightType);

                    // Concatenate the two strings.
                    generator.Call(ReflectionHelpers.ConcatenatedString_Concatenate_Object);
                }
            }
            else if (leftType != PrimitiveType.Any && leftType != PrimitiveType.Object &&
                     rightType != PrimitiveType.Any && rightType != PrimitiveType.Object)
            {
                // Neither of the operands are strings.

                // Load the left hand side onto the stack.
                this.Left.GenerateCode(generator, optimizationInfo);

                // Convert the operand to a number.
                EmitConversion.ToNumber(generator, leftType);

                // Load the right hand side onto the stack.
                this.Right.GenerateCode(generator, optimizationInfo);

                // Convert the operand to a number.
                EmitConversion.ToNumber(generator, rightType);

                // Add the two numbers.
                generator.Add();
            }
            else
            {
                // It is unknown whether the operands are strings.

                // Load the left hand side onto the stack.
                this.Left.GenerateCode(generator, optimizationInfo);
                EmitConversion.ToAny(generator, leftType);

                // Load the right hand side onto the stack.
                this.Right.GenerateCode(generator, optimizationInfo);
                EmitConversion.ToAny(generator, rightType);

                // Add the two objects.
                generator.Call(ReflectionHelpers.TypeUtilities_Add);
            }
        }
Пример #5
0
        /// <summary>
        /// Generates CIL for the expression.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        public override void GenerateCode(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            // If a return value is not expected, generate only the side-effects.

            /*if (optimizationInfo.SuppressReturnValue == true)
             * {
             *  this.GenerateSideEffects(generator, optimizationInfo);
             *  return;
             * }*/

            // Special case the addition operator.
            if (this.OperatorType == OperatorType.Add)
            {
                GenerateAdd(generator, optimizationInfo);
                return;
            }

            // Special case the instanceof operator.
            if (this.OperatorType == OperatorType.InstanceOf)
            {
                GenerateInstanceOf(generator, optimizationInfo);
                return;
            }

            // Special case the in operator.
            if (this.OperatorType == OperatorType.In)
            {
                GenerateIn(generator, optimizationInfo);
                return;
            }

            // Special case the relational operators.
            if (this.OperatorType == OperatorType.LessThan ||
                this.OperatorType == OperatorType.LessThanOrEqual ||
                this.OperatorType == OperatorType.GreaterThan ||
                this.OperatorType == OperatorType.GreaterThanOrEqual)
            {
                GenerateRelational(generator, optimizationInfo);
                return;
            }

            // Special case the logical operators.
            if (this.OperatorType == OperatorType.LogicalAnd ||
                this.OperatorType == OperatorType.LogicalOr)
            {
                GenerateLogical(generator, optimizationInfo);
                return;
            }

            // Load the left hand side onto the stack.
            this.Left.GenerateCode(generator, optimizationInfo);

            // Convert the left argument.
            switch (this.OperatorType)
            {
            // Arithmetic operations.
            case OperatorType.Subtract:
            case OperatorType.Multiply:
            case OperatorType.Divide:
            case OperatorType.Modulo:
            case OperatorType.Exponentiation:
                EmitConversion.ToNumber(generator, this.Left.ResultType);
                break;

            // Bitwise operations.
            case OperatorType.BitwiseAnd:
            case OperatorType.BitwiseOr:
            case OperatorType.BitwiseXor:
            case OperatorType.LeftShift:
            case OperatorType.SignedRightShift:
            case OperatorType.UnsignedRightShift:
                EmitConversion.ToInt32(generator, this.Left.ResultType);
                break;

            // Equality operations.
            case OperatorType.Equal:
            case OperatorType.StrictlyEqual:
            case OperatorType.NotEqual:
            case OperatorType.StrictlyNotEqual:
                EmitConversion.ToAny(generator, this.Left.ResultType);
                break;
            }

            // Load the right hand side onto the stack.
            this.Right.GenerateCode(generator, optimizationInfo);

            // Convert the right argument.
            switch (this.OperatorType)
            {
            // Arithmetic operations.
            case OperatorType.Subtract:
            case OperatorType.Multiply:
            case OperatorType.Divide:
            case OperatorType.Modulo:
            case OperatorType.Exponentiation:
                EmitConversion.ToNumber(generator, this.Right.ResultType);
                break;

            // Bitwise operations.
            case OperatorType.BitwiseAnd:
            case OperatorType.BitwiseOr:
            case OperatorType.BitwiseXor:
                EmitConversion.ToInt32(generator, this.Right.ResultType);
                break;

            case OperatorType.LeftShift:
            case OperatorType.SignedRightShift:
            case OperatorType.UnsignedRightShift:
                EmitConversion.ToUInt32(generator, this.Right.ResultType);
                generator.LoadInt32(0x1F);
                generator.BitwiseAnd();
                break;

            // Equality operations.
            case OperatorType.Equal:
            case OperatorType.StrictlyEqual:
            case OperatorType.NotEqual:
            case OperatorType.StrictlyNotEqual:
                EmitConversion.ToAny(generator, this.Right.ResultType);
                break;
            }

            // Apply the operator.
            switch (this.OperatorType)
            {
            // Arithmetic operations.
            case OperatorType.Subtract:
                generator.Subtract();
                break;

            case OperatorType.Multiply:
                generator.Multiply();
                break;

            case OperatorType.Divide:
                generator.Divide();
                break;

            case OperatorType.Modulo:
                generator.Remainder();
                break;

            case OperatorType.Exponentiation:
                generator.CallStatic(ReflectionHelpers.Math_Pow);
                break;

            // Bitwise operations.
            case OperatorType.BitwiseAnd:
                generator.BitwiseAnd();
                break;

            case OperatorType.BitwiseOr:
                generator.BitwiseOr();
                break;

            case OperatorType.BitwiseXor:
                generator.BitwiseXor();
                break;

            // Shift operations.
            case OperatorType.LeftShift:
                generator.ShiftLeft();
                break;

            case OperatorType.SignedRightShift:
                generator.ShiftRight();
                break;

            case OperatorType.UnsignedRightShift:
                generator.ShiftRightUnsigned();
                EmitConversion.ToNumber(generator, PrimitiveType.UInt32);
                break;

            // Equality operations.
            case OperatorType.Equal:
                generator.Call(ReflectionHelpers.TypeComparer_Equals);
                break;

            case OperatorType.StrictlyEqual:
                generator.Call(ReflectionHelpers.TypeComparer_StrictEquals);
                break;

            case OperatorType.NotEqual:
                generator.Call(ReflectionHelpers.TypeComparer_Equals);
                generator.LoadBoolean(false);
                generator.CompareEqual();
                break;

            case OperatorType.StrictlyNotEqual:
                generator.Call(ReflectionHelpers.TypeComparer_StrictEquals);
                generator.LoadBoolean(false);
                generator.CompareEqual();
                break;

            default:
                throw new NotImplementedException(string.Format("Unsupported operator {0}", this.OperatorType));
            }
        }
        /// <summary>
        /// Generates CIL for the expression.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        public override void GenerateCode(ILGenerator generator, OptimizationInfo optimizationInfo)
        {
            // Special-case the delete operator.
            if (this.OperatorType == OperatorType.Delete)
            {
                GenerateDelete(generator, optimizationInfo);
                return;
            }

            // If a return value is not expected, generate only the side-effects.

            /*if (optimizationInfo.SuppressReturnValue == true)
             * {
             *  this.GenerateSideEffects(generator, optimizationInfo);
             *  return;
             * }*/

            // Special-case the typeof operator.
            if (this.OperatorType == OperatorType.Typeof)
            {
                GenerateTypeof(generator, optimizationInfo);
                return;
            }

            // Load the operand onto the stack.
            this.Operand.GenerateCode(generator, optimizationInfo);

            // Convert the operand to the correct type.
            switch (this.OperatorType)
            {
            case OperatorType.Plus:
            case OperatorType.Minus:
                EmitConversion.ToNumber(generator, this.Operand.ResultType);
                break;

            case OperatorType.BitwiseNot:
                EmitConversion.ToInt32(generator, this.Operand.ResultType);
                break;

            case OperatorType.LogicalNot:
                EmitConversion.ToBool(generator, this.Operand.ResultType);
                break;
            }

            // Apply the operator.
            switch (this.OperatorType)
            {
            case OperatorType.Plus:
                break;

            case OperatorType.Minus:
                generator.Negate();
                break;

            case OperatorType.BitwiseNot:
                generator.BitwiseNot();
                break;

            case OperatorType.LogicalNot:
                generator.LoadBoolean(false);
                generator.CompareEqual();
                break;

            case OperatorType.Void:
                generator.Pop();
                EmitHelpers.EmitUndefined(generator);
                break;

            default:
                throw new NotImplementedException(string.Format("Unsupported operator {0}", this.OperatorType));
            }
        }
Пример #7
0
        /// <summary>
        /// Pops the value on the stack, converts it from an object to the given type, then pushes
        /// the result onto the stack.
        /// </summary>
        /// <param name="generator"> The IL generator. </param>
        /// <param name="toType"> The type to convert to. </param>
        /// <param name="convertToAddress"> <c>true</c> if the value is intended for use as an
        /// instance pointer; <c>false</c> otherwise. </param>
        internal static void EmitConversionToType(ILGenerator generator, Type toType, bool convertToAddress)
        {
            // Convert Null.Value to null if the target type is a reference type.
            ILLabel endOfNullCheck = null;

            if (toType.IsValueType == false)
            {
                var startOfElse = generator.CreateLabel();
                endOfNullCheck = generator.CreateLabel();
                generator.Duplicate();
                EmitHelpers.EmitNull(generator);
                generator.BranchIfNotEqual(startOfElse);
                generator.Pop();
                generator.LoadNull();
                generator.Branch(endOfNullCheck);
                generator.DefineLabelPosition(startOfElse);
            }

            switch (Type.GetTypeCode(toType))
            {
            case TypeCode.Boolean:
                EmitConversion.ToBool(generator, PrimitiveType.Any);
                break;

            case TypeCode.Byte:
                EmitConversion.ToInt32(generator, PrimitiveType.Any);
                break;

            case TypeCode.Char:
                EmitConversion.ToString(generator, PrimitiveType.Any);
                generator.Duplicate();
                generator.Call(ReflectionHelpers.String_Length);
                generator.LoadInt32(1);
                var endOfCharCheck = generator.CreateLabel();
                generator.BranchIfEqual(endOfCharCheck);
                EmitHelpers.EmitThrow(generator, ErrorType.TypeError, "Cannot convert string to char - the string must be exactly one character long");
                generator.DefineLabelPosition(endOfCharCheck);
                generator.LoadInt32(0);
                generator.Call(ReflectionHelpers.String_GetChars);
                break;

            case TypeCode.DBNull:
                throw new NotSupportedException("DBNull is not a supported parameter type.");

            case TypeCode.Decimal:
                EmitConversion.ToNumber(generator, PrimitiveType.Any);
                generator.NewObject(ReflectionHelpers.Decimal_Constructor_Double);
                break;

            case TypeCode.Double:
                EmitConversion.ToNumber(generator, PrimitiveType.Any);
                break;

            case TypeCode.Empty:
                throw new NotSupportedException("Empty is not a supported return type.");

            case TypeCode.Int16:
                EmitConversion.ToInt32(generator, PrimitiveType.Any);
                break;

            case TypeCode.Int32:
                EmitConversion.ToInt32(generator, PrimitiveType.Any);
                break;

            case TypeCode.Int64:
                EmitConversion.ToNumber(generator, PrimitiveType.Any);
                generator.ConvertToInt64();
                break;

            case TypeCode.DateTime:
            case TypeCode.Object:
                // Check if the type must be unwrapped.
                generator.Duplicate();
                generator.IsInstance(typeof(Jurassic.Library.ClrInstanceWrapper));
                var endOfUnwrapCheck = generator.CreateLabel();
                generator.BranchIfFalse(endOfUnwrapCheck);

                // Unwrap the wrapped instance.
                generator.Call(ReflectionHelpers.ClrInstanceWrapper_GetWrappedInstance);
                generator.DefineLabelPosition(endOfUnwrapCheck);

                // Value types must be unboxed.
                if (toType.IsValueType == true)
                {
                    if (convertToAddress == true)
                    {
                        // Unbox.
                        generator.Unbox(toType);
                    }
                    else
                    {
                        // Unbox and copy to the stack.
                        generator.UnboxAny(toType);
                    }

                    //// Calling methods on value required the address of the value type, not the value type itself.
                    //if (argument.Source == BinderArgumentSource.ThisValue && argument.Type.IsValueType == true)
                    //{
                    //    var temp = generator.CreateTemporaryVariable(argument.Type);
                    //    generator.StoreVariable(temp);
                    //    generator.LoadAddressOfVariable(temp);
                    //    generator.ReleaseTemporaryVariable(temp);
                    //}
                }


                break;

            case TypeCode.SByte:
                EmitConversion.ToInt32(generator, PrimitiveType.Any);
                break;

            case TypeCode.Single:
                EmitConversion.ToNumber(generator, PrimitiveType.Any);
                break;

            case TypeCode.String:
                EmitConversion.ToString(generator, PrimitiveType.Any);
                break;

            case TypeCode.UInt16:
                EmitConversion.ToInt32(generator, PrimitiveType.Any);
                break;

            case TypeCode.UInt32:
                EmitConversion.ToUInt32(generator, PrimitiveType.Any);
                break;

            case TypeCode.UInt64:
                EmitConversion.ToNumber(generator, PrimitiveType.Any);
                generator.ConvertToUnsignedInt64();
                break;
            }

            // Label the end of the null check.
            if (toType.IsValueType == false)
            {
                generator.DefineLabelPosition(endOfNullCheck);
            }
        }
Пример #8
0
        /// <summary>
        /// Generates CIL for an increment or decrement expression.
        /// </summary>
        /// <param name="generator"> The generator to output the CIL to. </param>
        /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param>
        /// <param name="target"> The target to modify. </param>
        /// <param name="postfix"> <c>true</c> if this is the postfix version of the operator;
        /// <c>false</c> otherwise. </param>
        /// <param name="increment"> <c>true</c> if this is the increment operator; <c>false</c> if
        /// this is the decrement operator. </param>
        private void GenerateIncrementOrDecrement(ILGenerator generator, OptimizationInfo optimizationInfo, IReferenceExpression target, bool postfix, bool increment)
        {
            // Note: increment and decrement can produce a number that is out of range if the
            // target is of type Int32.  The only time this should happen is for a loop variable
            // where the range has been carefully checked to make sure an out of range condition
            // cannot happen.

            // Evaluate the left hand side only once.
            target.GenerateReference(generator, optimizationInfo);
            target.DuplicateReference(generator, optimizationInfo); // For the GenerateSet, later on.

            // Get the target value.
            target.GenerateGet(generator, optimizationInfo, true);

            // Convert it to a number.
            if (target.Type != PrimitiveType.Int32)
            {
                EmitConversion.ToNumber(generator, target.Type);
            }

            ILLocalVariable result = null;

            if (optimizationInfo.IgnoreReturnValue != this && postfix == true)
            {
                // If this is PostIncrement or PostDecrement, store the value so it can be returned later.
                result = generator.CreateTemporaryVariable(target.Type == PrimitiveType.Int32 ? PrimitiveType.Int32 : PrimitiveType.Number);
                generator.Duplicate();
                generator.StoreVariable(result);
            }

            // Load the increment constant.
            if (target.Type == PrimitiveType.Int32)
            {
                generator.LoadInt32(1);
            }
            else
            {
                generator.LoadDouble(1.0);
            }

            // Add or subtract the constant to the target value.
            if (increment == true)
            {
                generator.Add();
            }
            else
            {
                generator.Subtract();
            }

            if (optimizationInfo.IgnoreReturnValue != this && postfix == false)
            {
                // If this is PreIncrement or PreDecrement, store the value so it can be returned later.
                result = generator.CreateTemporaryVariable(target.Type == PrimitiveType.Int32 ? PrimitiveType.Int32 : PrimitiveType.Number);
                generator.Duplicate();
                generator.StoreVariable(result);
            }

            // Store the value.
            target.GenerateSet(generator, optimizationInfo, target.Type == PrimitiveType.Int32 ? PrimitiveType.Int32 : PrimitiveType.Number);

            if (optimizationInfo.IgnoreReturnValue != this)
            {
                // Restore the expression result.
                generator.LoadVariable(result);
                generator.ReleaseTemporaryVariable(result);
            }
            else
            {
                optimizationInfo.ReturnValueWasNotGenerated = true;
            }
        }