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);
            }
Ejemplo n.º 3
0
        /// <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;
        }