public static ToBool ( |
||
generator | The IL generator. | |
fromType | PrimitiveType | The type to convert from. |
리턴 | void |
/// <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); }
/// <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); }
/// <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); }
/// <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)); } }
/// <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); } }