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); } } }
/// <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); }
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; }
/// <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; }
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; }
public FieldSlotFactory(TypeGen typeGen, Slot instance) { this.typeGen = typeGen; this.instance = instance; }
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; }
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; }
/// <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>()); }
private static void FinishCustomDict(TypeGen tg, Namespace ns) { DictBuilder db = new DictBuilder(tg, ns); db.AddCustomDictMethods(); }
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 })); }
public DictBuilder(TypeGen tg, Namespace names) { this.tg = tg; this.names = names; }
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; }
internal static CodeGen GenerateModuleInitialize(CompilerContext context, GlobalSuite gs, TypeGen tg) { return GenerateModuleInitialize(context, gs, tg, false /*staticTypes*/, null); }
/// <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; }
public StackInfo(TypeGen typeGen, CodeGen classInit, CodeGen defaultCtor, List<Type> baseTypes) { type = typeGen; cctor = classInit; ctor = defaultCtor; bases = baseTypes; methods = new List<CodeGen>(); }
public StaticFieldSlotFactory(TypeGen typeGen) { this.typeGen = typeGen; }
/// <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); } } }
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; }
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; }
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; }
/// <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"); }