ToBool() 공개 정적인 메소드

Pops the value on the stack, converts it to a boolean, then pushes the boolean result onto the stack.
public static ToBool ( 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 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;
             * }*/

            // Emit the condition.
            var condition = this.GetOperand(0);

            condition.GenerateCode(generator, optimizationInfo);

            // Convert the condition to a boolean.
            EmitConversion.ToBool(generator, condition.ResultType);

            // Branch if the condition is false.
            var startOfElse = generator.CreateLabel();

            generator.BranchIfFalse(startOfElse);

            // Calculate the result type.
            var outputType = this.ResultType;

            // Emit the second operand and convert it to the result type.
            var operand2 = this.GetOperand(1);

            operand2.GenerateCode(generator, optimizationInfo);
            EmitConversion.Convert(generator, operand2.ResultType, outputType, optimizationInfo);

            // Branch to the end.
            var end = generator.CreateLabel();

            generator.Branch(end);
            generator.DefineLabelPosition(startOfElse);

            // Emit the third operand and convert it to the result type.
            var operand3 = this.GetOperand(2);

            operand3.GenerateCode(generator, optimizationInfo);
            EmitConversion.Convert(generator, operand3.ResultType, outputType, optimizationInfo);

            // Define the end label.
            generator.DefineLabelPosition(end);
        }
예제 #3
0
        /// <summary>
        /// Generates CIL for the statement.
        /// </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)
        {
            // Generate code for the start of the statement.
            var statementLocals = new StatementLocals();

            GenerateStartOfStatement(generator, optimizationInfo, statementLocals);

            // Generate code for the condition and coerce to a boolean.
            this.Condition.GenerateCode(generator, optimizationInfo);
            EmitConversion.ToBool(generator, this.Condition.ResultType);

            // We will need a label at the end of the if statement.
            var endOfEverything = generator.CreateLabel();

            if (this.ElseClause == null)
            {
                // Jump to the end if the condition is false.
                generator.BranchIfFalse(endOfEverything);

                // Generate code for the if clause.
                this.IfClause.GenerateCode(generator, optimizationInfo);
            }
            else
            {
                // Branch to the else clause if the condition is false.
                var startOfElseClause = generator.CreateLabel();
                generator.BranchIfFalse(startOfElseClause);

                // Generate code for the if clause.
                this.IfClause.GenerateCode(generator, optimizationInfo);

                // Branch to the end of the if statement.
                generator.Branch(endOfEverything);

                // Generate code for the else clause.
                generator.DefineLabelPosition(startOfElseClause);
                this.ElseClause.GenerateCode(generator, optimizationInfo);
            }

            // Define the label at the end of the if statement.
            generator.DefineLabelPosition(endOfEverything);

            // Generate code for the end of the statement.
            GenerateEndOfStatement(generator, optimizationInfo, statementLocals);
        }
예제 #4
0
        /// <summary>
        /// Generates CIL for the statement.
        /// </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)
        {
            // Generate code for the start of the statement.
            var statementLocals = new StatementLocals()
            {
                NonDefaultBreakStatementBehavior = true, NonDefaultDebugInfoBehavior = true
            };

            GenerateStartOfStatement(generator, optimizationInfo, statementLocals);

            // <initializer>
            // if (<condition>)
            // {
            //   <loop body>
            //   <increment>
            //   while (true) {
            //     if (<condition> == false)
            //       break;
            //
            //     <body statements>
            //
            //     continue-target:
            //     <increment>
            //   }
            // }
            // break-target:

            // Set up some labels.
            var continueTarget = generator.CreateLabel();
            var breakTarget1   = generator.CreateLabel();
            var breakTarget2   = generator.CreateLabel();

            // Emit the initialization statement.
            if (this.InitStatement != null)
            {
                this.InitStatement.GenerateCode(generator, optimizationInfo);
            }

            // Check the condition and jump to the end if it is false.
            if (this.CheckConditionAtEnd == false && this.ConditionStatement != null)
            {
#if !XBOX
                if (optimizationInfo.DebugDocument != null)
                {
                    generator.MarkSequencePoint(optimizationInfo.DebugDocument, this.ConditionStatement.DebugInfo);
                }
#endif
                this.Condition.GenerateCode(generator, optimizationInfo);
                EmitConversion.ToBool(generator, this.Condition.ResultType);
                generator.BranchIfFalse(breakTarget1);
            }

            // Emit the loop body.
            optimizationInfo.PushBreakOrContinueInfo(this.Labels, breakTarget1, continueTarget, false);
            this.Body.GenerateCode(generator, optimizationInfo);
            optimizationInfo.PopBreakOrContinueInfo();

            // Increment the loop variable.
            if (this.IncrementStatement != null)
            {
                this.IncrementStatement.GenerateCode(generator, optimizationInfo);
            }

            // Strengthen the variable types.
            List <KeyValuePair <Scope.DeclaredVariable, RevertInfo> > previousVariableTypes = null;
            var previousInsideTryCatchOrFinally = optimizationInfo.InsideTryCatchOrFinally;
            if (optimizationInfo.OptimizeInferredTypes == true)
            {
                // Keep a record of the variable types before strengthening.
                previousVariableTypes = new List <KeyValuePair <Scope.DeclaredVariable, RevertInfo> >();

                var typedVariables = FindTypedVariables();
                foreach (var variableAndType in typedVariables)
                {
                    var variable     = variableAndType.Key;
                    var variableInfo = variableAndType.Value;
                    if (variableInfo.Conditional == false && variableInfo.Type != variable.Type)
                    {
                        // Save the previous type so we can restore it later.
                        var previousType = variable.Type;
                        previousVariableTypes.Add(new KeyValuePair <Scope.DeclaredVariable, RevertInfo>(variable, new RevertInfo()
                        {
                            Type = previousType, Variable = variable.Store
                        }));

                        // Load the existing value.
                        var nameExpression = new NameExpression(variable.Scope, variable.Name);
                        nameExpression.GenerateGet(generator, optimizationInfo, false);

                        // Store the typed value.
                        variable.Store = generator.DeclareVariable(variableInfo.Type);
                        variable.Type  = variableInfo.Type;
                        nameExpression.GenerateSet(generator, optimizationInfo, previousType, false);
                    }
                }

                // The variables must be reverted even in the presence of exceptions.
                if (previousVariableTypes.Count > 0)
                {
                    generator.BeginExceptionBlock();

                    // Setting the InsideTryCatchOrFinally flag converts BR instructions into LEAVE
                    // instructions so that the finally block is executed correctly.
                    optimizationInfo.InsideTryCatchOrFinally = true;
                }
            }

            // The inner loop starts here.
            var startOfLoop = generator.DefineLabelPosition();

            // Check the condition and jump to the end if it is false.
            if (this.ConditionStatement != null)
            {
#if !XBOX
                if (optimizationInfo.DebugDocument != null)
                {
                    generator.MarkSequencePoint(optimizationInfo.DebugDocument, this.ConditionStatement.DebugInfo);
                }
#endif
                this.Condition.GenerateCode(generator, optimizationInfo);
                EmitConversion.ToBool(generator, this.Condition.ResultType);
                generator.BranchIfFalse(breakTarget2);
            }

            // Emit the loop body.
            optimizationInfo.PushBreakOrContinueInfo(this.Labels, breakTarget2, continueTarget, labelledOnly: false);
            this.Body.GenerateCode(generator, optimizationInfo);
            optimizationInfo.PopBreakOrContinueInfo();

            // The continue statement jumps here.
            generator.DefineLabelPosition(continueTarget);

            // Increment the loop variable.
            if (this.IncrementStatement != null)
            {
                this.IncrementStatement.GenerateCode(generator, optimizationInfo);
            }

            // Unconditionally branch back to the start of the loop.
            generator.Branch(startOfLoop);

            // Define the end of the loop (actually just after).
            generator.DefineLabelPosition(breakTarget2);

            // Revert the variable types.
            if (previousVariableTypes != null && previousVariableTypes.Count > 0)
            {
                // Revert the InsideTryCatchOrFinally flag.
                optimizationInfo.InsideTryCatchOrFinally = previousInsideTryCatchOrFinally;

                // Revert the variable types within a finally block.
                generator.BeginFinallyBlock();

                foreach (var previousVariableAndType in previousVariableTypes)
                {
                    var variable           = previousVariableAndType.Key;
                    var variableRevertInfo = previousVariableAndType.Value;

                    // Load the existing value.
                    var nameExpression = new NameExpression(variable.Scope, variable.Name);
                    nameExpression.GenerateGet(generator, optimizationInfo, false);

                    // Store the typed value.
                    var previousType = variable.Type;
                    variable.Store = variableRevertInfo.Variable;
                    variable.Type  = variableRevertInfo.Type;
                    nameExpression.GenerateSet(generator, optimizationInfo, previousType, false);
                }

                // End the exception block.
                generator.EndExceptionBlock();
            }

            // Define the end of the loop (actually just after).
            generator.DefineLabelPosition(breakTarget1);

            // Generate code for the end of the statement.
            GenerateEndOfStatement(generator, optimizationInfo, statementLocals);
        }
        /// <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));
            }
        }
예제 #6
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);
            }
        }