public static EmitDefaultValue ( |
||
generator | The IL generator. | |
type | PrimitiveType | The type of value to generate. |
Résultat | void |
/// <summary> /// Generates a method that does type conversion and calls the bound method. /// </summary> /// <param name="generator"> The ILGenerator used to output the body of the method. </param> /// <param name="argumentCount"> The number of arguments that will be passed to the delegate. </param> /// <returns> A delegate that does type conversion and calls the method represented by this /// object. </returns> protected override void GenerateStub(ILGenerator generator, int argumentCount) { // Check for the correct number of arguments. if (argumentCount != 0) { EmitHelpers.EmitThrow(generator, ErrorType.TypeError, "Wrong number of arguments"); EmitHelpers.EmitDefaultValue(generator, PrimitiveType.Any); generator.Complete(); return; } if (this.field.IsStatic == false) { generator.LoadArgument(1); ClrBinder.EmitConversionToType(generator, this.field.DeclaringType, convertToAddress: true); } generator.LoadField(this.field); ClrBinder.EmitConversionToObject(generator, this.field.FieldType); generator.Complete(); }
/// <summary> /// Generates a method that does type conversion and calls the bound method. /// </summary> /// <param name="generator"> The ILGenerator used to output the body of the method. </param> /// <param name="argumentCount"> The number of arguments that will be passed to the delegate. </param> /// <returns> A delegate that does type conversion and calls the method represented by this /// object. </returns> protected override void GenerateStub(ILGenerator generator, int argumentCount) { // Check for the correct number of arguments. if (argumentCount != 1) { EmitHelpers.EmitThrow(generator, "TypeError", "Wrong number of arguments"); EmitHelpers.EmitDefaultValue(generator, PrimitiveType.Any); generator.Complete(); return; } if (this.field.IsStatic == false) { generator.LoadArgument(1); ClrBinder.EmitConversionToType(generator, this.field.DeclaringType, convertToAddress: true); } generator.LoadArgument(2); generator.LoadInt32(0); generator.LoadArrayElement(typeof(object)); ClrBinder.EmitConversionToType(generator, this.field.FieldType, convertToAddress: false); generator.StoreField(this.field); EmitHelpers.EmitUndefined(generator); generator.Complete(); }
/// <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) { // The left hand side needs to be a variable reference or member access. var target = this.GetOperand(0) as IReferenceExpression; if (target == null) { // Emit an error message. switch (this.OperatorType) { case OperatorType.PostIncrement: case OperatorType.PostDecrement: EmitHelpers.EmitThrow(generator, "ReferenceError", "Invalid left-hand side in postfix operation", optimizationInfo); break; case OperatorType.PreIncrement: case OperatorType.PreDecrement: EmitHelpers.EmitThrow(generator, "ReferenceError", "Invalid left-hand side in prefix operation", optimizationInfo); break; case OperatorType.Assignment: default: EmitHelpers.EmitThrow(generator, "ReferenceError", "Invalid left-hand side in assignment", optimizationInfo); break; } //if (optimizationInfo.SuppressReturnValue == false) EmitHelpers.EmitDefaultValue(generator, this.ResultType); return; } // The left hand side cannot be "arguments" or "eval" in strict mode. if (optimizationInfo.StrictMode == true && target is NameExpression) { if (((NameExpression)target).Name == "eval") { throw new JavaScriptException(optimizationInfo.Engine, "SyntaxError", "The variable 'eval' cannot be modified in strict mode.", optimizationInfo.SourceSpan.StartLine, optimizationInfo.Source.Path, optimizationInfo.FunctionName); } if (((NameExpression)target).Name == "arguments") { throw new JavaScriptException(optimizationInfo.Engine, "SyntaxError", "The variable 'arguments' cannot be modified in strict mode.", optimizationInfo.SourceSpan.StartLine, optimizationInfo.Source.Path, optimizationInfo.FunctionName); } } switch (this.OperatorType) { case OperatorType.Assignment: // Standard assignment operator. GenerateAssignment(generator, optimizationInfo, target); break; case OperatorType.PostIncrement: GenerateIncrementOrDecrement(generator, optimizationInfo, target, postfix: true, increment: true); break; case OperatorType.PostDecrement: GenerateIncrementOrDecrement(generator, optimizationInfo, target, postfix: true, increment: false); break; case OperatorType.PreIncrement: GenerateIncrementOrDecrement(generator, optimizationInfo, target, postfix: false, increment: true); break; case OperatorType.PreDecrement: GenerateIncrementOrDecrement(generator, optimizationInfo, target, postfix: false, increment: false); break; case OperatorType.CompoundAdd: // Special case += GenerateCompoundAddAssignment(generator, optimizationInfo, target); break; default: // All other compound operators. GenerateCompoundAssignment(generator, optimizationInfo, target); break; } }
/// <summary> /// Gets an enumerable list of argument objects, equal in size to /// <paramref name="argumentCount"/> while generating code to prepare those arguments for /// a method call. /// </summary> /// <param name="argumentCount"> The number of arguments to return. </param> /// <param name="generator"> The IL generator used to create an array if the method has a /// ParamArray parameter. </param> /// <returns> An enumerable list of argument objects. </returns> public IEnumerable <BinderArgument> GenerateArguments(ILGenerator generator, int argumentCount) { if (generator == null) { throw new ArgumentNullException(nameof(generator)); } int paramArrayIndex = 0; foreach (var argument in this.GetArguments(argumentCount)) { if (argument.IsParamArrayArgument == true) { if (paramArrayIndex == 0) { // This is the start of the ParamArray arguments. // Create an array. int paramArraySize = Math.Max(0, argumentCount - this.OptionalParameterCount - this.RequiredParameterCount); generator.LoadInt32(paramArraySize); generator.NewArray(argument.Type); } // Load the array and index. generator.Duplicate(); generator.LoadInt32(paramArrayIndex++); } // Yield will have the side effect of generating a value. yield return(argument); if (argument.IsParamArrayArgument == true) { // Store the value in the ParamArray array. generator.StoreArrayElement(argument.Type); } } // Populate any missing optional arguments with the default value. if (this.RequiredParameterCount + this.OptionalParameterCount - argumentCount > 0) { var parameters = this.GetParameters(); for (int i = 0; i < this.RequiredParameterCount + this.OptionalParameterCount - argumentCount; i++) { var optionalParameter = parameters[argumentCount + i]; if ((optionalParameter.Attributes & ParameterAttributes.HasDefault) == ParameterAttributes.HasDefault) { // Emit the default value. EmitHelpers.EmitValue(generator, new BinderArgument(optionalParameter, 0).DefaultValue); } else { // Emit default(T). EmitHelpers.EmitDefaultValue(generator, optionalParameter.ParameterType); } } } // Create an empty array if a ParamArray argument exists but no arguments were provided. if (this.HasParamArray == true && paramArrayIndex == 0) { // Create an array. generator.LoadInt32(0); generator.NewArray(this.ParamArrayElementType); } }
/// <summary> /// Generates a method that does type conversion and calls the bound method. /// </summary> /// <param name="generator"> The ILGenerator used to output the body of the method. </param> /// <param name="argumentCount"> The number of arguments that will be passed to the delegate. </param> /// <returns> A delegate that does type conversion and calls the method represented by this /// object. </returns> protected override void GenerateStub(ILGenerator generator, int argumentCount) { // Determine the methods that have the correct number of arguments. var candidateMethods = new List <BinderMethod>(); foreach (var candidateMethod in this.targetMethods) { if (candidateMethod.IsArgumentCountCompatible(argumentCount) == true) { candidateMethods.Add(candidateMethod); } } // Zero candidates means no overload had the correct number of arguments. if (candidateMethods.Count == 0) { EmitHelpers.EmitThrow(generator, ErrorType.TypeError, string.Format("No overload for method '{0}' takes {1} arguments", this.Name, argumentCount)); EmitHelpers.EmitDefaultValue(generator, PrimitiveType.Any); generator.Complete(); return; } // Select the method to call at run time. generator.LoadInt32(candidateMethods.Count); generator.NewArray(typeof(RuntimeMethodHandle)); for (int i = 0; i < candidateMethods.Count; i++) { generator.Duplicate(); generator.LoadInt32(i); generator.LoadToken(candidateMethods[i]); generator.StoreArrayElement(typeof(RuntimeMethodHandle)); } generator.LoadArgument(0); generator.LoadArgument(1); generator.LoadArgument(2); generator.Call(ReflectionHelpers.BinderUtilities_ResolveOverloads); var endOfMethod = generator.CreateLabel(); for (int i = 0; i < candidateMethods.Count; i++) { // Check if this is the selected method. ILLabel endOfIf = null; if (i < candidateMethods.Count - 1) { generator.Duplicate(); generator.LoadInt32(i); endOfIf = generator.CreateLabel(); generator.BranchIfNotEqual(endOfIf); } generator.Pop(); var targetMethod = candidateMethods[i]; // Convert the arguments. foreach (var argument in targetMethod.GenerateArguments(generator, argumentCount)) { // Load the input parameter value. switch (argument.Source) { case BinderArgumentSource.ScriptEngine: generator.LoadArgument(0); break; case BinderArgumentSource.ThisValue: generator.LoadArgument(1); break; case BinderArgumentSource.InputParameter: generator.LoadArgument(2); generator.LoadInt32(argument.InputParameterIndex); generator.LoadArrayElement(typeof(object)); break; } // Convert to the target type. EmitConversionToType(generator, argument.Type, convertToAddress: argument.Source == BinderArgumentSource.ThisValue); } // Call the target method. targetMethod.GenerateCall(generator); // Convert the return value. if (targetMethod.ReturnType == typeof(void)) { EmitHelpers.EmitUndefined(generator); } else { EmitConversionToObject(generator, targetMethod.ReturnType); } // Branch to the end of the method if this was the selected method. if (endOfIf != null) { generator.Branch(endOfMethod); generator.DefineLabelPosition(endOfIf); } } generator.DefineLabelPosition(endOfMethod); generator.Complete(); }