diff options
Diffstat (limited to 'src/msil/ch/epfl/lamp/compiler/msil/emit/TypeBuilder.scala')
-rw-r--r-- | src/msil/ch/epfl/lamp/compiler/msil/emit/TypeBuilder.scala | 230 |
1 files changed, 230 insertions, 0 deletions
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/TypeBuilder.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/TypeBuilder.scala new file mode 100644 index 0000000000..ca95a2b24d --- /dev/null +++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/TypeBuilder.scala @@ -0,0 +1,230 @@ +/* + * System.Reflection.Emit-like API for writing .NET assemblies to MSIL + */ + +// $Id: TypeBuilder.java 14655 2008-04-15 09:37:02Z lorch $ + +package ch.epfl.lamp.compiler.msil.emit + +import ch.epfl.lamp.compiler.msil._ +import java.util.HashMap +import java.util.ArrayList +import java.util.Iterator +import java.io.IOException + +/** + * Defines and creates new instances of classes during runtime. + * + * @author Nikolay Mihaylov + * @version 1.0 + */ +class TypeBuilder (module: Module, attributes: int, fullName: String, baseType: Type, interfaces: Array[Type], declType: Type) + extends Type(module, attributes, fullName, baseType, interfaces, declType, 0) + with ICustomAttributeSetter + with Visitable +{ + import TypeBuilder._ + + //########################################################################## + // public members + + /** 'Bakes' the type. */ + def CreateType(): Type = { + fields = fieldBuilders.toArray(new Array[FieldInfo](fieldBuilders.size())).asInstanceOf[Array[FieldInfo]] + methods = methodBuilders.toArray(new Array[MethodInfo](methodBuilders.size())).asInstanceOf[Array[MethodInfo]] + constructors = constructorBuilders.toArray(new Array[ConstructorInfo](constructorBuilders.size())).asInstanceOf[Array[ConstructorInfo]] + nestedTypes = nestedTypeBuilders.toArray(new Array[Type](nestedTypeBuilders.size())).asInstanceOf[Array[Type]] + + raw = false + if (DeclaringType == null) + Module.asInstanceOf[ModuleBuilder].addType(this) + return this + } + + /** + * Adds a new field to the class, with the given name, + * attributes and field type. + */ + def DefineField(name: String, `type`: Type, attrs: short): FieldBuilder = { + val field: FieldBuilder = new FieldBuilder(name, this, attrs, `type`) + fieldBuilders.add(field) + return field + } + + /** + * Adds a new method to the class, with the given name and + * method signature. + */ + def DefineMethod(name: String, attrs: short, returnType: Type, paramTypes: Array[Type]): MethodBuilder = { + val method = new MethodBuilder(name, this, attrs, returnType, paramTypes) + val methods = methodBuilders.iterator() + while(methods.hasNext()) { + val m = methods.next().asInstanceOf[MethodInfo] + if (methodsEqual(m, method)) + throw new RuntimeException("["+ Assembly() + + "] Method has already been defined: " + m) + } + methodBuilders.add(method) + return method + } + + /** + * Adds a new constructor to the class, with the given attributes + * and signature. + */ + def DefineConstructor(attrs: short, callingConvention: short, paramTypes: Array[Type]): ConstructorBuilder = { + val constr = new ConstructorBuilder(this, attrs, paramTypes) + constructorBuilders.add(constr) + return constr + } + + /** + * Defines a nested type given its name. + */ + def DefineNestedType(name: String, attributes: int, baseType: Type, interfaces: Array[Type]): TypeBuilder = { + val nested = nestedTypeBuilders.iterator() + while(nested.hasNext()) { + val nt = nested.next().asInstanceOf[TypeBuilder] + if (nt.Name.equals(name)) { + val message = "Nested type " + name + " has already been defined: " + nt + throw new RuntimeException(message) + } + } + val t = new TypeBuilder(Module, attributes, name, baseType, interfaces, this) + nestedTypeBuilders.add(t) + return t + } + + /** Get the field with the corresponding name. */ + override def GetField(name: String): FieldInfo = { + testRaw(name) + return super.GetField(name) + } + + /** Get all fields of the current Type. */ + override def GetFields(): Array[FieldInfo] = { + testRaw("<GetFields>") + return super.GetFields() + } + + /** + * Searches for a public instance constructor whose parameters + * match the types in the specified array. + */ + override def GetConstructor(params: Array[Type]): ConstructorInfo = { + testRaw(".ctor" + types2String(params)) + return super.GetConstructor(params) + } + + /** + * Returns all the public constructors defined for the current Type. + */ + override def GetConstructors(): Array[ConstructorInfo] = { + testRaw("<GetConstructors>") + return super.GetConstructors() + } + + /** + * Searches for the specified public method whose parameters + * match the specified argument types. + */ + override def GetMethod(name: String, params: Array[Type]): MethodInfo = { + testRaw(name + types2String(params)) + return super.GetMethod(name, params) + } + + /** Returns all the public methods of the current Type. */ + override def GetMethods(): Array[MethodInfo] = { + testRaw("<GetMethods>") + return super.GetMethods() + } + + /** Searches for the nested type with the specified name. */ + override def GetNestedType(name: String): Type = { + testRaw(name) + return super.GetNestedType(name) + } + + /** Returns all the types nested within the current Type. */ + override def GetNestedTypes(): Array[Type] = { + testRaw("<GetNestedTypes>") + return super.GetNestedTypes() + } + + /** Sets a custom attribute. */ + def SetCustomAttribute(constr: ConstructorInfo, value: Array[byte]) { + addCustomAttribute(constr, value) + } + + def setPosition(sourceLine: int, sourceFilename: String) { + this.sourceLine = sourceLine + this.sourceFilename = sourceFilename + } + + def setSourceFilepath(sourceFilepath: String) { + this.sourceFilepath = sourceFilepath + } + + //########################################################################## + // protected members + + var sourceLine: Int = _ + var sourceFilename: String = _ + var sourceFilepath: String = _ + + var fieldBuilders = new ArrayList[FieldBuilder]() + var methodBuilders = new ArrayList[MethodBuilder]() + var constructorBuilders = new ArrayList[ConstructorBuilder]() + var nestedTypeBuilders = new ArrayList[TypeBuilder]() + + // shows if the type is 'raw', i.e. still subject to changes + private var raw = true + + // throws an exception if the type is 'raw', + // i.e. not finalized by call to CreateType + protected def testRaw(member: String) { + if (raw) + throw new RuntimeException + ("Not supported for TypeBuilder before CreateType(): " + + FullName + "::" + member) + } + + //########################################################################## + // public members not part of the Reflection.Emit.TypeBuilder interface. + + /** The apply method for a visitor. */ + @throws(classOf[IOException]) + def apply(v: Visitor) { + v.caseTypeBuilder(this) + } + + //########################################################################## + +} // class TypeBuilder + +object TypeBuilder { + def types2String(types: Array[Type]): String = { + var s = new StringBuffer("(") + for(val i <- 0 until types.length) { + if (i > 0) s.append(", ") + s.append(types(i)) + } + s.append(")") + return s.toString() + } + + def methodsEqual(m1: MethodInfo, m2: MethodInfo): boolean = { + if (!m1.Name.equals(m2.Name)) + return false + if (m1.ReturnType != m2.ReturnType) + return false + val p1 = m1.GetParameters() + val p2 = m2.GetParameters() + if (p1.length != p2.length) + return false + for(val i <- 0 until p1.length) + if (p1(i).ParameterType != p2(i).ParameterType) + return false + return true + } +} |