summaryrefslogtreecommitdiff
path: root/src/msil/ch/epfl/lamp/compiler/msil/emit/TypeBuilder.scala
diff options
context:
space:
mode:
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.scala230
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
+ }
+}