/// <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:
                EmitConversion.ToNumber(generator, this.Left.GetResultType(optimizationInfo));
                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.GetResultType(optimizationInfo));
                break;

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

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

            // If the return isn't in use, pop them both:
            if (optimizationInfo.RootExpression == this)
            {
                generator.Pop();
                generator.Pop();
                return;
            }

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

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

            case OperatorType.LeftShift:
            case OperatorType.SignedRightShift:
            case OperatorType.UnsignedRightShift:
                EmitConversion.ToUInt32(generator, this.Right.GetResultType(optimizationInfo));
                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.GetResultType(optimizationInfo));
                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;

            // 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, typeof(uint));
                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));
            }
        }