/// <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) { // Note: we use GetRawOperand() so that grouping operators are not ignored. var operand = this.GetRawOperand(0); var functionCallExpressionOperand = operand as FunctionCallExpression; // There is only one operand, and it can be either a reference or a function call. // We need to split the operand into a function and some arguments. // If the operand is a reference, it is equivalent to a function call with no arguments. if (functionCallExpressionOperand != null) { // Emit the function instance first. var function = functionCallExpressionOperand.Target; function.GenerateCode(generator, optimizationInfo); EmitConversion.ToAny(generator, function.ResultType); } else { // Emit the function instance first. operand.GenerateCode(generator, optimizationInfo); EmitConversion.ToAny(generator, operand.ResultType); } // Check the object really is a function - if not, throw an exception. generator.IsInstance(typeof(Library.FunctionInstance)); generator.Duplicate(); var endOfTypeCheck = generator.CreateLabel(); generator.BranchIfNotNull(endOfTypeCheck); // Throw an nicely formatted exception. var targetValue = generator.CreateTemporaryVariable(typeof(object)); generator.StoreVariable(targetValue); EmitHelpers.LoadScriptEngine(generator); generator.LoadString("TypeError"); generator.LoadString("The new operator requires a function, found a '{0}' instead"); generator.LoadInt32(1); generator.NewArray(typeof(object)); generator.Duplicate(); generator.LoadInt32(0); generator.LoadVariable(targetValue); generator.Call(ReflectionHelpers.TypeUtilities_TypeOf.Value); generator.StoreArrayElement(typeof(object)); generator.Call(ReflectionHelpers.String_Format.Value); generator.LoadInt32(optimizationInfo.SourceSpan.StartLine); generator.LoadStringOrNull(optimizationInfo.Source.Path); generator.LoadStringOrNull(optimizationInfo.FunctionName); generator.NewObject(ReflectionHelpers.JavaScriptException_Constructor_Error.Value); generator.Throw(); generator.DefineLabelPosition(endOfTypeCheck); generator.ReleaseTemporaryVariable(targetValue); if (functionCallExpressionOperand != null) { // Emit an array containing the function arguments. ((FunctionCallExpression)operand).GenerateArgumentsArray(generator, optimizationInfo); } else { // Emit an empty array. generator.LoadInt32(0); generator.NewArray(typeof(object)); } // Call FunctionInstance.ConstructLateBound(argumentValues) generator.Call(ReflectionHelpers.FunctionInstance_ConstructLateBound.Value); }