private static void EmitArgsToTuple(FunctionDefinition fd, CodeGen icg, SignatureInfo sigInfo, int cnt) { if ((fd.Flags & FunctionAttributes.ArgumentList) != 0) { // transform params object[] into tuple on call... LocalBuilder lb = icg.DeclareLocal(typeof(object)); Slot argsSlot = new LocalSlot(lb, icg); int index; if ((fd.Flags & FunctionAttributes.KeywordDictionary) != 0) { index = sigInfo.ParamNames.Length - 2; icg.EmitArgGet(cnt - 2); } else { index = sigInfo.ParamNames.Length - 1; icg.EmitArgGet(cnt - 1); } icg.EmitCall(typeof(Tuple), "MakeTuple"); argsSlot.EmitSet(icg); lb.SetLocalSymInfo(sigInfo.ParamNames[index].GetString()); icg.Names.SetSlot(sigInfo.ParamNames[index], argsSlot); } }
/// <summary> /// Propagates the module field to the inner type, or runs the /// module initialization if it hasn't already been run. /// </summary> private void EmitModuleInitialization(TypeGen newType, CodeGen classInit) { Debug.Assert(classInit != null); Label noModule = classInit.DefineLabel(); Label done = classInit.DefineLabel(); outerScope.moduleSlot.EmitGet(classInit); classInit.Emit(OpCodes.Ldnull); classInit.Emit(OpCodes.Beq, noModule); outerScope.moduleSlot.EmitGet(classInit); newType.moduleSlot.EmitSet(classInit); classInit.Emit(OpCodes.Br, done); classInit.MarkLabel(noModule); // module slot is un-initialized, we must // have been reloaded by some .NET code. // We'll create a new module now. Slot instance = new LocalSlot(classInit.DeclareLocal(outerScope.myType), classInit); List<string> refs = null; if (RemoteCompiler.Instance != null) { refs = new List<string>(RemoteCompiler.Instance.References.Count); for (int i = 0; i < RemoteCompiler.Instance.References.Count; i++) { string refName = RemoteCompiler.Instance.References[i]; if (refName.ToLower().EndsWith(".dll")) refName = refName.Substring(0, refName.Length - 4); if (refName.IndexOf('\\') != -1) { refs.Add(refName.Substring(refName.LastIndexOf('\\') + 1)); } else refs.Add(refName); } } OutputGenerator.EmitModuleConstruction(outerScope, classInit, outerScope.myType.Name, instance, refs); // module ctor leaves PythonModule on the stack. classInit.Emit(OpCodes.Dup); // store the new module in both locations outerScope.moduleSlot.EmitSet(classInit); newType.moduleSlot.EmitSet(classInit); // and finally run the modules initialize method instance.EmitGet(classInit); classInit.EmitCall(moduleInit.MethodInfo); classInit.MarkLabel(done); }
/// <summary> /// Generates a static entry point for stand-alone EXEs. We just new up our module dstructure /// and then call into Ops to get running. /// </summary> internal static CodeGen GenerateModuleEntryPoint(TypeGen tg, CodeGen init, string moduleName, IList<string> referencedAssemblies) { CodeGen main = tg.DefineMethod(MethodAttributes.Static | MethodAttributes.Public, "Main", typeof(int), Type.EmptyTypes, new string[] { }); main.SetCustomAttribute(new CustomAttributeBuilder(typeof(STAThreadAttribute).GetConstructor(Type.EmptyTypes), Ops.EMPTY)); // leaves our module instance on the stack, we save it to create the delegate. Slot instance = new LocalSlot(main.DeclareLocal(tg.myType), main); // notify the PythonEngine of the module. EmitModuleConstruction(tg, main, moduleName, instance, referencedAssemblies); main.Emit(OpCodes.Pop); // we don't care about the PythonModule. // Emit the delegate to the init method (init) main.EmitDelegate(init, typeof(InitializeModule), instance); // Call ExecuteCompiled main.EmitCall(typeof(Ops), "ExecuteCompiled", ExecuteCompiledSignature); main.EmitReturn(); return main; }