Show TypeGen.cs syntax highlighted
/* **********************************************************************************
*
* Copyright (c) Microsoft Corporation. All rights reserved.
*
* This source code is subject to terms and conditions of the Shared Source License
* for IronPython. A copy of the license can be found in the License.html file
* at the root of this distribution. If you can not locate the Shared Source License
* for IronPython, please send an email to ironpy@microsoft.com.
* By using this source code in any fashion, you are agreeing to be bound by
* the terms of the Shared Source License for IronPython.
*
* You must not remove this notice, or any other, from this software.
*
* **********************************************************************************/
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Reflection.Emit;
using System.Security.Permissions;
using IronPython.Runtime;
using IronMath;
namespace IronPython.Compiler.Generation {
class TypeGen {
public readonly AssemblyGen myAssembly;
public readonly TypeBuilder myType;
public Slot moduleSlot;
private ConstructorBuilder initializer; // The .cctor() of the type
private CodeGen initGen; // The IL generator for the .cctor()
private Dictionary<object, Slot> constants = new Dictionary<object, Slot>();
private Dictionary<SymbolId, Slot> indirectSymbolIds = new Dictionary<SymbolId, Slot>();
private List<TypeGen> nestedTypeGens = new List<TypeGen>();
internal ConstructorBuilder DefaultConstructor;
public TypeGen(AssemblyGen myAssembly, TypeBuilder myType) {
this.myAssembly = myAssembly;
this.myType = myType;
}
public override string ToString() {
return myType.ToString();
}
public CodeGen GetOrMakeInitializer() {
if (initializer == null) {
initializer = myType.DefineTypeInitializer();
initGen = new CodeGen(this, initializer, initializer.GetILGenerator(), Type.EmptyTypes);
}
return initGen;
}
public Type FinishType() {
if (initGen != null) initGen.Emit(OpCodes.Ret);
Type ret = myType.CreateType();
foreach (TypeGen ntb in nestedTypeGens) {
ntb.FinishType();
}
//Console.WriteLine("finished: " + ret.FullName);
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;
}
public void AddModuleField(Type moduleType) {
FieldBuilder moduleField = this.myType.DefineField(CompiledModule.ModuleFieldName,
moduleType, FieldAttributes.Public | FieldAttributes.Static);
moduleField.SetCustomAttribute(new CustomAttributeBuilder(typeof(PythonHiddenFieldAttribute).GetConstructor(new Type[0]), Runtime.Operations.Ops.EMPTY));
this.moduleSlot = new StaticFieldSlot(moduleField);
}
public Slot AddField(Type fieldType, string name) {
FieldBuilder fb = myType.DefineField(name, fieldType, FieldAttributes.Public);
return new FieldSlot(new ThisSlot(myType), fb);
}
public Slot AddStaticField(Type fieldType, string name) {
FieldBuilder fb = myType.DefineField(name, fieldType, FieldAttributes.Public | FieldAttributes.Static);
return new StaticFieldSlot(fb);
}
public Slot AddStaticField(Type fieldType, FieldAttributes attributes, string name) {
FieldBuilder fb = myType.DefineField(name, fieldType, attributes | FieldAttributes.Static);
return new StaticFieldSlot(fb);
}
public CodeGen DefineExplicitInterfaceImplementation(MethodInfo baseMethod) {
MethodAttributes attrs = baseMethod.Attributes & ~(MethodAttributes.Abstract | MethodAttributes.Public);
attrs |= MethodAttributes.NewSlot | MethodAttributes.Final;
MethodBuilder mb = myType.DefineMethod(
baseMethod.DeclaringType.Name + "." + baseMethod.Name,
attrs,
baseMethod.ReturnType,
CompilerHelpers.GetTypes(baseMethod.GetParameters()));
CodeGen ret = new CodeGen(this, mb, mb.GetILGenerator(), baseMethod.GetParameters());
ret.methodToOverride = baseMethod;
return ret;
}
public PropertyBuilder DefineProperty(string name, PropertyAttributes attrs, Type returnType) {
return myType.DefineProperty(name, attrs, returnType, new Type[0]);
}
private const MethodAttributes MethodAttributesToEraseInOveride =
MethodAttributes.Abstract | MethodAttributes.ReservedMask;
public CodeGen DefineMethodOverride(MethodAttributes extraAttrs, MethodInfo baseMethod) {
MethodAttributes finalAttrs = (baseMethod.Attributes & ~MethodAttributesToEraseInOveride) | extraAttrs;
MethodBuilder mb = myType.DefineMethod(baseMethod.Name, finalAttrs, baseMethod.ReturnType,
CompilerHelpers.GetTypes(baseMethod.GetParameters()));
CodeGen ret = new CodeGen(this, mb, mb.GetILGenerator(), baseMethod.GetParameters());
ret.methodToOverride = baseMethod;
return ret;
}
public CodeGen DefineMethodOverride(MethodInfo baseMethod) {
return DefineMethodOverride((MethodAttributes)0, baseMethod);
}
public CodeGen DefineMethod(string name, Type retType, Type[] paramTypes, string[] paramNames) {
return DefineMethod(CompilerHelpers.PublicStatic, name, retType, paramTypes, paramNames);
}
public CodeGen DefineMethod(string name, Type retType, Type[] paramTypes, string[] paramNames, object[] defaultVals) {
return DefineMethod(CompilerHelpers.PublicStatic, name, retType, paramTypes, paramNames, defaultVals);
}
public CodeGen DefineMethod(MethodAttributes attrs, string name, Type retType, Type[] paramTypes, string[] paramNames, object[] defaultVals) {
return DefineMethod(attrs, name, retType, paramTypes, paramNames, defaultVals, null);
}
public CodeGen DefineMethod(string name, Type retType, Type[] paramTypes, string[] paramNames, object[] defaultVals, CustomAttributeBuilder[] cabs) {
return DefineMethod(CompilerHelpers.PublicStatic, name, retType, paramTypes, paramNames, defaultVals, cabs);
}
public CodeGen DefineMethod(MethodAttributes attrs, string name, Type retType, Type[] paramTypes, string[] paramNames, object[] defaultVals, CustomAttributeBuilder[] cabs) {
MethodBuilder mb = myType.DefineMethod(name, attrs, retType, paramTypes);
CodeGen res = new CodeGen(this, mb, mb.GetILGenerator(), paramTypes);
for (int i = 0; i < paramTypes.Length; i++) {
// parameters are index from 1.
ParameterBuilder pb = res.DefineParameter(i + 1, ParameterAttributes.None, paramNames[i]);
if (defaultVals != null && i < defaultVals.Length && defaultVals[i] != DBNull.Value) {
pb.SetConstant(defaultVals[i]);
}
if (cabs != null && i < cabs.Length && cabs[i] != null) {
pb.SetCustomAttribute(cabs[i]);
}
}
return res;
}
public CodeGen DefineMethod(MethodAttributes attrs, string name, Type retType, Type[] paramTypes, string[] paramNames) {
return DefineMethod(attrs, name, retType, paramTypes, paramNames, null);
}
public CodeGen DefineUserHiddenMethod(MethodAttributes attrs, string name, Type retType, Type[] paramTypes) {
MethodBuilder mb = myType.DefineMethod(name, attrs, retType, paramTypes);
CodeGen res = new CodeGen(this, mb, mb.GetILGenerator(), paramTypes);
return res;
}
public CodeGen DefineConstructor(Type[] paramTypes) {
ConstructorBuilder cb = myType.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, paramTypes);
return new CodeGen(this, cb, cb.GetILGenerator(), paramTypes);
}
public CodeGen DefineStaticConstructor() {
ConstructorBuilder cb = myType.DefineTypeInitializer();
return new CodeGen(this, cb, cb.GetILGenerator(), new ParameterInfo[0]);
}
public void SetCustomAttribute(Type t, object[] values) {
Type[] types = new Type[values.Length];
for (int i = 0; i < types.Length; i++) {
if (values[i] != null) {
types[i] = values[i].GetType();
} else {
types[i] = typeof(object);
}
}
CustomAttributeBuilder cab = new CustomAttributeBuilder(t.GetConstructor(types), values);
myType.SetCustomAttribute(cab);
}
/// <summary>
/// Constants
/// </summary>
public Slot GetOrMakeConstant(object value) {
return GetOrMakeConstant(value, typeof(object));
}
public Slot GetOrMakeConstant(object value, Type type) {
Slot ret;
if (constants.TryGetValue(value, out ret)) return ret;
// Create a name like "c$3.141592$712"
string symbolicName = value.ToString();
if (symbolicName.Length > 20)
symbolicName = symbolicName.Substring(0, 20);
string name = "c$" + symbolicName + "$" + constants.Count;
FieldBuilder fb = myType.DefineField(name, type, FieldAttributes.Static | FieldAttributes.InitOnly);
ret = new StaticFieldSlot(fb);
GetOrMakeInitializer().EmitConstantBoxed(value);
initGen.EmitFieldSet(fb);
constants[value] = ret;
return ret;
}
public void EmitIndirectedSymbol(CodeGen cg, SymbolId id) {
Slot value;
if (!indirectSymbolIds.TryGetValue(id, out value)) {
// create field, emit fix-up...
value = AddStaticField(typeof(int), FieldAttributes.Private, "symbol_" + SymbolTable.IdToString(id));
CodeGen init = GetOrMakeInitializer();
Slot localTmp = init.GetLocalTmp(typeof(SymbolId));
init.EmitString((string)SymbolTable.IdToString(id));
init.EmitCall(typeof(SymbolTable), "StringToId");
localTmp.EmitSet(init);
localTmp.EmitGetAddr(init);
init.EmitFieldGet(typeof(SymbolId), "Id");
value.EmitSet(init);
cg.FreeLocalTmp(localTmp);
indirectSymbolIds[id] = value;
}
value.EmitGet(cg);
}
}
}
See more files for this project here