this
/// <summary> /// Generates IL for the script. /// </summary> /// <param name="generator"> The generator to output the CIL to. </param> /// <param name="optimizationInfo"> Information about any optimizations that should be performed. </param> protected override void GenerateCode(ILGenerator generator, OptimizationInfo optimizationInfo) { // Method signature: object FunctionDelegate(Compiler.Scope scope, object thisObject, Library.FunctionInstance functionObject, object[] arguments) // Initialize the scope (note: the initial scope for a function is always declarative). this.InitialScope.GenerateScopeCreation(generator, optimizationInfo); // Verify the scope is correct. VerifyScope(generator); // In ES3 the "this" value must be an object. See 10.4.3 in the spec. if (this.StrictMode == false && this.MethodOptimizationHints.HasThis == true) { // if (thisObject == null || thisObject == Null.Value || thisObject == Undefined.Value) EmitHelpers.LoadThis(generator); generator.LoadNull(); generator.CompareEqual(); EmitHelpers.LoadThis(generator); EmitHelpers.EmitNull(generator); generator.CompareEqual(); generator.BitwiseOr(); EmitHelpers.LoadThis(generator); EmitHelpers.EmitUndefined(generator); generator.CompareEqual(); generator.BitwiseOr(); // { var startOfFalse = generator.CreateLabel(); generator.BranchIfFalse(startOfFalse); // thisObject = engine.Global; EmitHelpers.LoadScriptEngine(generator); generator.Call(ReflectionHelpers.ScriptEngine_Global); // } else { var endOfIf = generator.CreateLabel(); generator.Branch(endOfIf); generator.DefineLabelPosition(startOfFalse); // thisObject = TypeConverter.ToObject(thisObject); EmitHelpers.LoadThis(generator); EmitConversion.ToObject(generator, PrimitiveType.Any, optimizationInfo); // } generator.DefineLabelPosition(endOfIf); EmitHelpers.StoreThis(generator); } // Transfer the function name into the scope. if (string.IsNullOrEmpty(this.Name) == false && this.IncludeNameInScope == true && this.ArgumentNames.Contains(this.Name) == false && optimizationInfo.MethodOptimizationHints.HasVariable(this.Name)) { EmitHelpers.LoadFunction(generator); var functionName = new NameExpression(this.InitialScope, this.Name); functionName.GenerateSet(generator, optimizationInfo, PrimitiveType.Any, false); } // Transfer the arguments object into the scope. if (this.MethodOptimizationHints.HasArguments == true && this.ArgumentNames.Contains("arguments") == false) { // prototype EmitHelpers.LoadScriptEngine(generator); generator.Call(ReflectionHelpers.ScriptEngine_Object); generator.Call(ReflectionHelpers.FunctionInstance_InstancePrototype); // callee EmitHelpers.LoadFunction(generator); generator.CastClass(typeof(Library.UserDefinedFunction)); // scope EmitHelpers.LoadScope(generator); generator.CastClass(typeof(DeclarativeScope)); // argumentValues EmitHelpers.LoadArgumentsArray(generator); generator.NewObject(ReflectionHelpers.Arguments_Constructor); var arguments = new NameExpression(this.InitialScope, "arguments"); arguments.GenerateSet(generator, optimizationInfo, PrimitiveType.Any, false); } // Transfer the argument values into the scope. // Note: the arguments array can be smaller than expected. if (this.ArgumentNames.Count > 0) { var endOfArguments = generator.CreateLabel(); for (int i = 0; i < this.ArgumentNames.Count; i++) { // Check if a duplicate argument name exists. bool duplicate = false; for (int j = i + 1; j < this.ArgumentNames.Count; j++) { if (this.ArgumentNames[i] == this.ArgumentNames[j]) { duplicate = true; break; } } if (duplicate == true) { continue; } // Check if an array element exists. EmitHelpers.LoadArgumentsArray(generator); generator.LoadArrayLength(); generator.LoadInt32(i); generator.BranchIfLessThanOrEqual(endOfArguments); // Store the array element in the scope. EmitHelpers.LoadArgumentsArray(generator); generator.LoadInt32(i); generator.LoadArrayElement(typeof(object)); var argument = new NameExpression(this.InitialScope, this.ArgumentNames[i]); argument.GenerateSet(generator, optimizationInfo, PrimitiveType.Any, false); } generator.DefineLabelPosition(endOfArguments); } // Initialize any declarations. this.InitialScope.GenerateDeclarations(generator, optimizationInfo); //EmitHelpers.LoadScope(generator); //EmitConversion.ToObject(generator, PrimitiveType.Any); //generator.Pop(); // Generate code for the body of the function. this.AbstractSyntaxTree.GenerateCode(generator, optimizationInfo); // Define the return target - this is where the return statement jumps to. // ReturnTarget can be null if there were no return statements. if (optimizationInfo.ReturnTarget != null) { generator.DefineLabelPosition(optimizationInfo.ReturnTarget); } // Load the return value. If the variable is null, there were no return statements. if (optimizationInfo.ReturnVariable != null) { // Return the value stored in the variable. Will be null if execution hits the end // of the function without encountering any return statements. generator.LoadVariable(optimizationInfo.ReturnVariable); } else { // There were no return statements - return null. generator.LoadNull(); } }