コード例 #1
0
            public GeneratorWalker(CodeGen codeGen)
            {
                Debug.Assert(codeGen.typeGen != null);

                assembly = codeGen.typeGen.myAssembly;

                compctx = codeGen.Context;
                moduleInit = codeGen;
                outerScope = codeGen.typeGen;
                namespaces = new List<string>();

                //!!! need to get type names already declared...
                PushNewType(codeGen.typeGen, codeGen, null, null);

                assemblies = new List<Assembly>();
                if (RemoteCompiler.Instance != null) {
                    StringCollection files = RemoteCompiler.Instance.References;
                    foreach (string file in files) {
                        Assembly asm = IronPython.Hosting.PythonCompiler.LoadAssembly(file);
                        assemblies.Add(asm);
                    }
                }
            }
コード例 #2
0
            /// <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);
            }
コード例 #3
0
            private CodeGen DefineClassInit(ClassDefinition cd, TypeGen newType)
            {
                CodeGen classInit = newType.GetOrMakeInitializer();

                EmitModuleInitialization(newType, classInit);

                classInit.Context = compctx;
                classInit.Names = CodeGen.CreateStaticFieldNamespace(newType);

                // prepare the class for compilation, this binds
                // all of our names into classInit's scope.  We'll then
                // recurse and add everything by hand.
                cd.PrepareForEmit(stack.Peek().StaticConstructor, classInit);

                return classInit;
            }
コード例 #4
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;
        }
コード例 #5
0
            private static CodeGen AddIDynamicObject(TypeGen newType, Slot dictSlot)
            {
                Slot classSlot = newType.AddStaticField(typeof(DynamicType), FieldAttributes.Private, "$class");

                newType.myType.AddInterfaceImplementation(typeof(ISuperDynamicObject));
                /* GetDynamicType */

                CodeGen gdtCg = newType.DefineMethodOverride(typeof(IDynamicObject).GetMethod("GetDynamicType"));

                CodeGen cg = newType.DefineUserHiddenMethod(MethodAttributes.FamORAssem | MethodAttributes.Static,
                    "$$GetOrMakeDynamicType", typeof(DynamicType), new Type[0]);
                DoLazyInitCheck(cg, classSlot,
                    delegate() {
                        // if not null, just return the value.
                        classSlot.EmitGet(cg);
                        cg.EmitReturn();
                    },
                    delegate() {
                        // initialization code

                        // CompiledType GetTypeForType(Type t)
                        cg.EmitType(newType.myType);
                        cg.EmitCall(typeof(CompiledType), "GetTypeForType");
                        cg.Emit(OpCodes.Dup);
                        classSlot.EmitSet(cg);

                        cg.EmitReturn();
                    });

                cg.Finish();
                CodeGen ret = cg;

                // just a call to the helper method
                gdtCg.EmitThis();
                gdtCg.EmitCall(typeof(object), "GetType");
                gdtCg.EmitType(newType.myType);
                Label differ = gdtCg.DefineLabel();
                gdtCg.Emit(OpCodes.Bne_Un, differ);

                gdtCg.EmitCall(cg.MethodInfo);
                gdtCg.EmitReturn();

                gdtCg.MarkLabel(differ);

                gdtCg.EmitThis();
                gdtCg.EmitCall(typeof(object), "GetType");
                gdtCg.EmitCall(typeof(Ops), "GetDynamicTypeFromType");
                gdtCg.EmitReturn();

                gdtCg.Finish();

                /* GetDict */
                cg = newType.DefineMethodOverride(typeof(ISuperDynamicObject).GetMethod("GetDict"));
                DoLazyInitCheck(cg, dictSlot,
                    delegate() {
                        // if not null, just return the value.
                        dictSlot.EmitGet(cg);
                        cg.EmitReturn();
                    },
                    delegate() {
                        // initialization code - dictSlot = new CustomOldClassDict()
                        cg.EmitNew(typeof(CustomOldClassDict).GetConstructor(new Type[0]));
                        cg.Emit(OpCodes.Dup);
                        dictSlot.EmitSet(cg);

                        cg.EmitReturn();
                    });
                cg.Finish();

                /* SetDict */
                cg = newType.DefineMethodOverride(typeof(ISuperDynamicObject).GetMethod("SetDict"));
                cg.EmitString("SetDict");
                cg.EmitInt(0);
                cg.Emit(OpCodes.Newarr, typeof(object));
                cg.EmitCall(typeof(Ops), "NotImplementedError");
                cg.Emit(OpCodes.Throw);

                /* SetDynamicType */
                cg = newType.DefineMethodOverride(typeof(ISuperDynamicObject).GetMethod("SetDynamicType"));
                cg.EmitString("SetDynamicType");
                cg.EmitInt(0);
                cg.Emit(OpCodes.Newarr, typeof(object));
                cg.EmitCall(typeof(Ops), "NotImplementedError");
                cg.Emit(OpCodes.Throw);

                return ret;
            }
コード例 #6
0
 public FieldSlotFactory(TypeGen typeGen, Slot instance)
 {
     this.typeGen = typeGen;
     this.instance = instance;
 }
コード例 #7
0
        private Type CreateNewType()
        {
            AssemblyGen ag = OutputGenerator.Snippets;

            string name = GetName();
            tg = ag.DefinePublicType(TypePrefix + name, baseType);

            ImplementInterfaces();

            GetOrDefineClass();

            GetOrDefineDict();

            ImplementSlots();

            ImplementPythonObject();

            ImplementConstructors();

            Dictionary<string, bool> specialNames = new Dictionary<string, bool>();

            OverrideVirtualMethods(baseType, specialNames);

            Dictionary<Type, bool> doneTypes = new Dictionary<Type, bool>();
            foreach (Type interfaceType in interfaceTypes) {
                DoInterfaceType(interfaceType, doneTypes, specialNames);
            }

            InitializeVTableStrings();

            // Hashtable slots = collectSlots(dict, tg);
            // if (slots != null) tg.createAttrMethods(slots);

            Type ret = tg.FinishType();

            AddBaseMethods(ret, specialNames);

            return ret;
        }
コード例 #8
0
        public TypeGen DefineNestedType(string name, Type parent)
        {
            TypeBuilder tb = myType.DefineNestedType(name, TypeAttributes.NestedPublic);
            tb.SetParent(parent);
            TypeGen ret = new TypeGen(myAssembly, tb);
            nestedTypeGens.Add(ret);

            ret.AddModuleField(typeof(PythonModule));

            return ret;
        }
コード例 #9
0
 /// <summary>
 /// Pushes a new type onto the stack for cases where we have
 /// nested class definitions.
 /// </summary>
 private void PushNewType(TypeGen newType, CodeGen classInit, CodeGen init, List<Type> baseTypes)
 {
     stack.Push(new StackInfo(newType, classInit, init, baseTypes));
     declaredTypes.Add(new Dictionary<string, TypeGen>());
 }
コード例 #10
0
 private static void FinishCustomDict(TypeGen tg, Namespace ns)
 {
     DictBuilder db = new DictBuilder(tg, ns);
     db.AddCustomDictMethods();
 }
コード例 #11
0
 public void AddPythonModuleAttribute(TypeGen tg, string moduleName)
 {
     myAssembly.SetCustomAttribute(new CustomAttributeBuilder(
        typeof(PythonModuleAttribute).GetConstructor(
        new Type[] { typeof(string), typeof(Type) }),
        new Object[] { moduleName, tg.myType }));
 }
コード例 #12
0
 public DictBuilder(TypeGen tg, Namespace names)
 {
     this.tg = tg;
     this.names = names;
 }
コード例 #13
0
        internal static CodeGen GenerateModuleInitialize(CompilerContext context, GlobalSuite gs, TypeGen tg, bool staticTypes, CustomModuleInit customInit)
        {
            CodeGen ncg = tg.DefineMethodOverride(typeof(CompiledModule).GetMethod("Initialize", BindingFlags.Public | BindingFlags.Instance));
            ncg.Context = context;
            ncg.EmitSetTraceBackUpdateStatus(false);

            ncg.Names = CodeGen.CreateStaticFieldNamespace(tg);

            if (context.TrueDivision) {
                ncg.ModuleSlot.EmitGet(ncg);
                ncg.EmitInt(1);
                ncg.EmitCall(typeof(ICallerContext), "set_TrueDivision");
            }

            // Add __doc__ and __name__
            ncg.Names.CreateGlobalSlot(SymbolTable.Doc);
            ncg.Names.CreateGlobalSlot(SymbolTable.Name);

            string doc = gs.Documentation;
            ncg.EmitStringOrNull(doc);
            ncg.EmitSet(SymbolTable.Doc);

            if (customInit != null) customInit(ncg);

            if (staticTypes) {
                UserTypeGenerator.DoStaticCompilation(gs, ncg);
            } else {
                gs.Emit(ncg);
            }

            ncg.EmitPosition(Location.None, Location.None);
            ncg.EmitReturn();
            ncg.Finish();

            FinishCustomDict(tg, ncg.Names);

            return ncg;
        }
コード例 #14
0
 internal static CodeGen GenerateModuleInitialize(CompilerContext context, GlobalSuite gs, TypeGen tg)
 {
     return GenerateModuleInitialize(context, gs, tg, false /*staticTypes*/, null);
 }
コード例 #15
0
            /// <summary>
            /// Gets the basetype for the class.  
            /// </summary>
            private List<Type> GetBaseType(ClassDefinition cd, out TypeGen tg)
            {
                //!!! need to handle types declared before us
                // but within our module's scope, and what do
                // we do if we don't know the base type?
                List<Type> types = new List<Type>(cd.Bases.Count);
                tg = null;
                if (cd.Bases.Count == 0) {
                    types.Add(typeof(object));
                    return types;
                }
                Type baseType = typeof(object);
                string baseName = null;
                for (int i = 0; i < cd.Bases.Count; i++) {
                    NameExpression ne = cd.Bases[i] as NameExpression;
                    FieldExpression fe;
                    if (ne != null) {
                        baseName = ne.Name.GetString();
                    } else if ((fe = cd.Bases[i] as FieldExpression) != null) {
                        baseName = CodeDom.CodeWalker.GetFieldString(fe);
                    } else {
                        throw new NotImplementedException(String.Format("non-name expr base type {0}", cd.Bases[i].GetType()));
                    }

                    if (baseName == null) throw new InvalidOperationException("couldn't find basetype");
                    if (baseName != "object" && baseName != "System.Object") {
                        for (int j = declaredTypes.Count - 1; j >= 0; j--) {
                            Dictionary<string, TypeGen> curDict = declaredTypes[j];

                            if (curDict.TryGetValue(baseName, out tg)) {
                                baseType = tg.myType;
                                break;
                            }
                        }

                        if (baseType == typeof(object) && RemoteCompiler.Instance != null) {
                            List<Assembly> assms = this.assemblies;

                            for (int j = 0; j < assms.Count; j++) {
                                Debug.Assert(assms[j] != null);
                                Type t = assms[j].GetType(baseName);
                                if (t != null) {
                                    baseType = t;
                                    break;
                                }
                            }
                        }

                        if (baseType == typeof(object) && Ops.compiledEngine != null) {
                            foreach (Assembly asm in Ops.compiledEngine.Sys.TopPackage.LoadedAssemblies.Keys) {
                                Type t = asm.GetType(baseName);
                                if (t != null) {
                                    baseType = t;
                                    break;
                                }
                            }
                        }

                        Debug.Assert(baseType != null, "Failed to find type for " + baseName);

                        if (baseType.IsInterface) {
                            types.Add(baseType);
                        } else if (baseType != typeof(object)) {
                            Debug.Assert(types.Count == 0 || types[0].IsInterface, "adding multiple classes",
                                String.Format("Had: {0}\r\nAdding{1} {2}", types.Count == 0 ? "" : types[0].FullName, baseType, baseName));

                            types.Insert(0, baseType);
                        } else {
                            return null;
                        }
                    } else {
                        types.Add(typeof(object));
                    }
                    baseType = typeof(object);
                }

                // if we only got interfaces object is our base
                if (types[0].IsInterface) {
                    types.Insert(0, typeof(object));
                }

                return types;
            }
コード例 #16
0
 public StackInfo(TypeGen typeGen, CodeGen classInit, CodeGen defaultCtor, List<Type> baseTypes)
 {
     type = typeGen;
     cctor = classInit;
     ctor = defaultCtor;
     bases = baseTypes;
     methods = new List<CodeGen>();
 }
コード例 #17
0
 public StaticFieldSlotFactory(TypeGen typeGen)
 {
     this.typeGen = typeGen;
 }
コード例 #18
0
            /// <summary>
            /// Pops the last class defintion from the stack, updating
            /// the available type names so other classes can derive
            /// from them
            /// </summary>
            public override void PostWalk(ClassDefinition cd)
            {
                TypeGen baseTg;
                List<Type> baseTypes = GetBaseType(cd, out baseTg);

                if (baseTypes == null || IsNamespace(cd)) {
                    namespaces.RemoveAt(namespaces.Count - 1);
                    if (stack.Count == 1 && namespaces.Count == 0) {
                        // outer item is a namespace, we need to load it.
                        CodeGen cg = stack.Peek().StaticConstructor;

                        cg.EmitCallerContext();
                        cg.EmitCall(typeof(Assembly), "GetExecutingAssembly");
                        cg.EmitString(cd.Name.GetString());
                        cg.EmitCall(typeof(Ops), "GetNamespace");
                        cg.EmitSet(cd.Name);
                    }
                    return;
                }

                StackInfo info = stack.Pop();
                finished = info.Type;

                info.StaticConstructor.Emit(OpCodes.Ret);
                declaredTypes.RemoveAt(declaredTypes.Count - 1);
                declaredTypes[declaredTypes.Count - 1][cd.Name.GetString()] = finished;

                Type baseType = baseTypes[0];

                info.DefaultConstructor.Emit(OpCodes.Ldarg_0);
                ConstructorInfo baseCtor;
                if (baseTg != null) {
                    baseCtor = baseTg.DefaultConstructor;
                } else {
                    baseCtor = baseType.GetConstructor(new Type[0]);
                }
                Debug.Assert(baseCtor != null, "baseCtor is null", String.Format("type: {0} base: {1}", info.Type.myType.Name, baseType.FullName));

                info.DefaultConstructor.Emit(OpCodes.Call, baseCtor);

                info.DefaultConstructor.EmitReturn();

                if (stack.Count == 1) {
                    info.Type.FinishType();
                    CodeGen cg = stack.Peek().StaticConstructor;

                    if (namespaces.Count == 0) {
                        cg.EmitCall(info.GetCompiledType.MethodInfo);
                        cg.EmitSet(cd.Name);
                    }
                }
            }
コード例 #19
0
        internal static CodeGen CreateVirtualMethodHelper(TypeGen tg, MethodInfo mi)
        {
            ParameterInfo[] parms = mi.GetParameters();
            Type[] types = CompilerHelpers.GetTypes(parms);
            string[] paramNames = new string[parms.Length];
            Type miType = mi.DeclaringType;
            for (int i = 0; i < types.Length; i++) {
                paramNames[i] = parms[i].Name;
                if (types[i] == miType) {
                    types[i] = tg.myType;
                }
            }
            CodeGen cg = tg.DefineMethod(MethodAttributes.Public | MethodAttributes.HideBySig,
                                         "#base#" + mi.Name, mi.ReturnType, types, paramNames);

            EmitBaseMethodDispatch(mi, cg);
            cg.Finish();
            return cg;
        }
コード例 #20
0
            private static CodeGen AddDefaultCtor(TypeGen newType, string[] slots)
            {
                CodeGen cg = newType.DefineConstructor(new Type[0]);
                if (slots != null) {

                    for (int i = 0; i < slots.Length; i++) {
                        Slot fld;
                        // getting other types would be nice here...
                        if (slots[i].StartsWith("__") && !slots[i].EndsWith("__")) {
                            fld = newType.AddField(typeof(object), "_" + newType.myType.Name + slots[i]);
                        } else {
                            fld = newType.AddField(typeof(object), slots[i]);
                        }

                        cg.EmitUninitialized();
                        fld.EmitSet(cg);
                    }

                    newType.DefaultConstructor = cg.methodInfo as ConstructorBuilder;
                    slots = null;
                }
                newType.DefaultConstructor = cg.methodInfo as ConstructorBuilder;
                return cg;
            }
コード例 #21
0
        private CodeGen CompileModuleInit(CompilerContext context, GlobalSuite gs, TypeGen tg, string moduleName)
        {
            CodeGen init;
            if (!AutoImportAll) {
                init = OutputGenerator.GenerateModuleInitialize(context, gs, tg);
            } else {
                // auto-import all compiled modules, useful for CodeDom scenarios.
                init = OutputGenerator.GenerateModuleInitialize(context, gs, tg, staticTypes, delegate(CodeGen cg) {

                    Location dummyLocation = new Location(1, 1);

                    for (int i = 0; i < sourceFiles.Count; i++) {
                        string otherModName = GetModuleFromFilename(sourceFiles[i]);
                        if (otherModName == moduleName) continue;

                        FromImportStatement stmt = new FromImportStatement(
                            new DottedName(new SymbolId[] { SymbolTable.StringToId(otherModName) }),
                            FromImportStatement.Star, null);
                        stmt.Start = dummyLocation;
                        stmt.End = dummyLocation;
                        stmt.Emit(cg);
                    }

                    // Import the first part of all namespaces in all referenced assemblies

                    // First, determine the set of unique such prefixes
                    Dictionary<string, object> nsPrefixes = new Dictionary<string, object>();
                    foreach (string name in ReferencedAssemblies) {
                        Assembly a = LoadAssembly(name);

                        foreach (Type t in a.GetTypes()) {
                            // We only care about public types
                            if (!t.IsPublic) continue;

                            // Ignore types that don't have a namespace
                            if (t.Namespace == null) continue;

                            string nsPrefix = t.Namespace.Split('.')[0];
                            nsPrefixes[nsPrefix] = null;
                        }
                    }

                    // Import all the uniquer prefixes we found
                    foreach (string nsPrefix in nsPrefixes.Keys) {
                        SymbolId symbolId = SymbolTable.StringToId(nsPrefix);
                        cg.Names.CreateGlobalSlot(symbolId);
                        DottedName dottedName = new DottedName(new SymbolId[] { symbolId });
                        ImportStatement importStmt = new ImportStatement(
                            new DottedName[] { dottedName },
                            new SymbolId[] { SymbolTable.Empty });
                        importStmt.Start = dummyLocation;
                        importStmt.End = dummyLocation;
                        importStmt.Emit(cg);
                    }
                });
            }
            return init;
        }
コード例 #22
0
        /// <summary>
        /// Emits a call into the PythonModule to register this module, and then
        /// returns the resulting PythonModule 
        /// </summary>
        public static void EmitModuleConstruction(TypeGen tg, CodeGen main, string moduleName, Slot initialize, IList<string> referencedAssemblies)
        {
            // calling PythonModule InitializeModule(CustomDict compiled, string fullName)

            main.EmitNew(tg.DefaultConstructor); // Emit instance for the InitializeModule call (compiled)

            initialize.EmitSet(main);
            initialize.EmitGet(main);

            main.EmitString(moduleName);         // emit module name (fullName)

            // emit the references assemblies
            if (referencedAssemblies != null) {
                for (int i = 0; i < referencedAssemblies.Count; i++) {
                    if (referencedAssemblies[i].ToLower().EndsWith("\\ironpython.dll")) {
                        referencedAssemblies.RemoveAt(i);
                        i--;
                    } else {
                        if (referencedAssemblies[i].IndexOf(Path.DirectorySeparatorChar) != -1) {
                            referencedAssemblies[i] = referencedAssemblies[i].Substring(referencedAssemblies[i].LastIndexOf(Path.DirectorySeparatorChar) + 1);
                        }

                        if (referencedAssemblies[i].ToLower().EndsWith(".dll")) {
                            referencedAssemblies[i] = referencedAssemblies[i].Substring(0, referencedAssemblies[i].Length - 4);
                        }
                    }
                }
                main.EmitStringArray(referencedAssemblies);
            } else main.Emit(OpCodes.Ldnull);

            // Call InitializeModule
            main.EmitCall(typeof(Ops), "InitializeModule");
        }