summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMiguel Garcia <magarcia@epfl.ch>2010-11-18 15:30:51 +0000
committerMiguel Garcia <magarcia@epfl.ch>2010-11-18 15:30:51 +0000
commit13a20ba71ae1805c7361e95d66360bd0a9a7f3d8 (patch)
tree02b643e8a58e74e0572d6564b81824982a7e33e2 /src
parenta86453a5eed21abf5dfa5fd1d0321c8eb0298302 (diff)
downloadscala-13a20ba71ae1805c7361e95d66360bd0a9a7f3d8.tar.gz
scala-13a20ba71ae1805c7361e95d66360bd0a9a7f3d8.tar.bz2
scala-13a20ba71ae1805c7361e95d66360bd0a9a7f3d8.zip
Improvements forMSIL:
(1) the Scala types in ch.epfl.lamp.compiler.msil.emit now use Scala collections instead of Java's, (2) a few bug fixes regarding metadata parsing, (3) GenMSIL emits output useful for IDE debugging, (4) TypeParser now enters symbols for generics in case the assemblies being linked sport them, (5) a few fixes for bytecode verif in GenMSIL. review by rytz
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala70
-rw-r--r--src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala43
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/ConstructedType.java2
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/PEFile.java15
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/PEModule.java6
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/Type.java2
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/emit/AssemblyBuilder.scala25
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/emit/ILGenerator.scala64
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/emit/ILPrinterVisitor.scala139
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/emit/ModuleBuilder.scala19
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/emit/MultipleFilesILPrinterVisitor.scala7
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/emit/SingleFileILPrinterVisitor.scala4
-rw-r--r--src/msil/ch/epfl/lamp/compiler/msil/emit/TypeBuilder.scala64
13 files changed, 283 insertions, 177 deletions
diff --git a/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala b/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala
index 4268d999a0..75ee6f8e42 100644
--- a/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala
+++ b/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala
@@ -481,6 +481,12 @@ abstract class GenMSIL extends SubComponent {
}
}
+ private[GenMSIL] def ilasmFileName(iclass: IClass) : String = {
+ val singleBackslashed = iclass.cunit.source.file.toString
+ val doubleBackslashed = singleBackslashed.replace("\\", "\\\\")
+ doubleBackslashed
+ }
+
private[GenMSIL] def genClass(iclass: IClass) {
val sym = iclass.symbol
if (settings.debug.value)
@@ -510,7 +516,7 @@ abstract class GenMSIL extends SubComponent {
}
val line = sym.pos.line
- tBuilder.setPosition(line, iclass.cunit.source.file.name)
+ tBuilder.setPosition(line, ilasmFileName(iclass))
if (isTopLevelModule(sym)) {
if (sym.companionClass == NoSymbol)
@@ -949,7 +955,7 @@ abstract class GenMSIL extends SubComponent {
}
if (currentLineNr != lastLineNr) {
- mcode.setPosition(currentLineNr)
+ mcode.setPosition(currentLineNr, ilasmFileName(clasz)) // method.sourceFile contains just the filename
lastLineNr = currentLineNr
}
@@ -1097,7 +1103,8 @@ abstract class GenMSIL extends SubComponent {
case SuperCall(_) =>
mcode.Emit(OpCodes.Call, constructorInfo)
if (isStaticModule(clasz.symbol) &&
- notInitializedModules.contains(clasz.symbol))
+ notInitializedModules.contains(clasz.symbol) &&
+ method.symbol.isClassConstructor)
{
notInitializedModules -= clasz.symbol
mcode.Emit(OpCodes.Ldarg_0)
@@ -1252,11 +1259,6 @@ abstract class GenMSIL extends SubComponent {
// is permitted in the host environment."
case CHECK_CAST(tpknd) =>
val tMSIL = msilType(tpknd)
- if (tMSIL.IsValueType) {
- // calling emitUnbox does nothing because there's no unbox method for tMSIL
- mcode.Emit(OpCodes.Unbox, tMSIL)
- mcode.Emit(OpCodes.Ldobj, tMSIL)
- } else
mcode.Emit(OpCodes.Castclass, tMSIL)
// no SWITCH is generated when there's
@@ -1683,7 +1685,7 @@ abstract class GenMSIL extends SubComponent {
if (!sym.isClassConstructor) {
if (sym.isStaticMember)
- mf = mf | FieldAttributes.Static
+ mf = mf | FieldAttributes.Static // coincidentally, same value as for MethodAttributes.Static ...
else {
mf = mf | MethodAttributes.Virtual
if (sym.isFinal && !getType(sym.owner).IsInterface)
@@ -1693,6 +1695,16 @@ abstract class GenMSIL extends SubComponent {
}
}
+ if (sym.isStaticMember) {
+ mf = mf | MethodAttributes.Static
+ }
+
+ // constructors of module classes should be private
+ if (sym.isPrimaryConstructor && isTopLevelModule(sym.owner)) {
+ mf |= MethodAttributes.Private
+ mf &= ~(MethodAttributes.Public)
+ }
+
mf.toShort
}
@@ -1902,6 +1914,21 @@ abstract class GenMSIL extends SubComponent {
addAttributes(fBuilder, sym.annotations)
} // all iclass.fields iterated over
+ if (isStaticModule(iclass.symbol)) {
+ val sc = iclass.lookupStaticCtor
+ if (sc.isDefined) {
+ val m = sc.get
+ val oldLastBlock = m.code.blocks.last
+ val lastBlock = m.code.newBlock
+ oldLastBlock.replaceInstruction(oldLastBlock.length - 1, JUMP(lastBlock))
+ // call object's private ctor from static ctor
+ lastBlock.emit(CIL_NEWOBJ(iclass.symbol.primaryConstructor))
+ lastBlock.emit(DROP(toTypeKind(iclass.symbol.tpe)))
+ lastBlock emit RETURN(UNIT)
+ lastBlock.close
+ }
+ }
+
if (iclass.symbol != definitions.ArrayClass) {
for (m: IMethod <- iclass.methods) {
val sym = m.symbol
@@ -1941,7 +1968,9 @@ abstract class GenMSIL extends SubComponent {
if (isStaticModule(iclass.symbol)) {
addModuleInstanceField(iclass.symbol)
notInitializedModules += iclass.symbol
- addStaticInit(iclass.symbol)
+ if (iclass.lookupStaticCtor.isEmpty) {
+ addStaticInit(iclass.symbol)
+ }
}
} // createClassMembers0
@@ -1995,7 +2024,8 @@ abstract class GenMSIL extends SubComponent {
case Some(sym) => sym
case None =>
//val mclass = types(moduleClassSym)
- val mClass = clrTypes.getType(moduleClassSym.fullName + "$")
+ val nameInMetadata = nestingAwareFullClassname(moduleClassSym)
+ val mClass = clrTypes.getType(nameInMetadata)
val mfield = mClass.GetField("MODULE$")
assert(mfield ne null, "module not found " + showsym(moduleClassSym))
fields(moduleClassSym) = mfield
@@ -2005,6 +2035,21 @@ abstract class GenMSIL extends SubComponent {
//fields(moduleClassSym)
}
+ def nestingAwareFullClassname(csym: Symbol) : String = {
+ val suffix = moduleSuffix(csym)
+ val res = if (csym.isNestedClass)
+ nestingAwareFullClassname(csym.owner) + "+" + csym.encodedName
+ else
+ csym.fullName
+ res + suffix
+ }
+
+ /** cut&pasted from GenJVM */
+ def moduleSuffix(sym: Symbol) =
+ if (sym.hasFlag(Flags.MODULE) && !sym.isMethod &&
+ !sym.isImplClass && !sym.hasFlag(Flags.JAVA)) "$"
+ else "";
+
/** Adds a static initializer which creates an instance of the module
* class (calls the primary constructor). A special primary constructor
* will be generated (notInitializedModules) which stores the new instance
@@ -2050,7 +2095,8 @@ abstract class GenMSIL extends SubComponent {
for (m <- sym.tpe.nonPrivateMembers
if m.owner != definitions.ObjectClass && !m.isProtected &&
- m.isMethod && !m.isClassConstructor && !m.isStaticMember && !m.isCase)
+ m.isMethod && !m.isClassConstructor && !m.isStaticMember && !m.isCase &&
+ !m.isDeferred)
{
if (settings.debug.value)
log(" Mirroring method: " + m)
diff --git a/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala b/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala
index 975b6bfc49..cf2b7f6b8e 100644
--- a/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala
+++ b/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala
@@ -65,6 +65,10 @@ abstract class TypeParser {
busy = false
}
+ class TypeParamsType(override val typeParams: List[Symbol]) extends LazyType {
+ override def complete(sym: Symbol) { throw new AssertionError("cyclic type dereferencing") }
+ }
+
/* the names `classTParams' and `newTParams' stem from the forJVM version (ClassfileParser.sigToType())
* but there are differences that should be kept in mind.
* forMSIL, a nested class knows nothing about any type-params in the nesting class,
@@ -162,7 +166,7 @@ abstract class TypeParser {
clazzMgdPtr.setInfo(classInfoMgdPtr)
}
-/* TODO CLR generics
+/* START CLR generics (snippet 1) */
// first pass
for (tvarCILDef <- typ.getSortedTVars() ) {
val tpname = newTypeName(tvarCILDef.Name.replaceAll("!", "")) // TODO are really all type-params named in all assemblies out there? (NO)
@@ -177,16 +181,16 @@ abstract class TypeParser {
val tpsym = classTParams(tvarCILDef.Number)
tpsym.setInfo(sig2typeBounds(tvarCILDef)) // we never skip bounds unlike in forJVM
}
-*/
+/* END CLR generics (snippet 1) */
val ownTypeParams = newTParams.toList
-/* TODO CLR generics
+/* START CLR generics (snippet 2) */
if (!ownTypeParams.isEmpty) {
clazz.setInfo(new TypeParamsType(ownTypeParams))
if(typ.IsValueType && !typ.IsEnum) {
clazzBoxed.setInfo(new TypeParamsType(ownTypeParams))
}
}
-*/
+/* END CLR generics (snippet 2) */
instanceDefs = new Scope
staticDefs = new Scope
@@ -461,18 +465,22 @@ abstract class TypeParser {
val flags = translateAttributes(method);
val owner = if (method.IsStatic()) statics else clazz;
val methodSym = owner.newMethod(NoPosition, getName(method)).setFlag(flags)
- // TODO CLR generics val newMethodTParams = populateMethodTParams(method, methodSym)
+ /* START CLR generics (snippet 3) */
+ val newMethodTParams = populateMethodTParams(method, methodSym)
+ /* END CLR generics (snippet 3) */
val rettype = if (method.IsConstructor()) clazz.tpe
else getCLSType(method.asInstanceOf[MethodInfo].ReturnType);
if (rettype == null) return;
val mtype = methodType(method, rettype);
if (mtype == null) return;
-/* TODO CLR generics
+/* START CLR generics (snippet 4) */
val mInfo = if (method.IsGeneric) polyType(newMethodTParams, mtype(methodSym))
else mtype(methodSym)
-*/
+/* END CLR generics (snippet 4) */
+/* START CLR non-generics (snippet 4)
val mInfo = mtype(methodSym)
+ END CLR non-generics (snippet 4) */
methodSym.setInfo(mInfo)
(if (method.IsStatic()) staticDefs else instanceDefs).enter(methodSym);
if (method.IsConstructor())
@@ -647,7 +655,12 @@ abstract class TypeParser {
private def getCLSType(typ: MSILType): Type = { // getCLS returns non-null for types GenMSIL can handle, be they CLS-compliant or not
if (typ.IsTMVarUsage())
- null // TODO after generics: getCLRType(typ)
+ /* START CLR generics (snippet 5) */
+ getCLRType(typ)
+ /* END CLR generics (snippet 5) */
+ /* START CLR non-generics (snippet 5)
+ null
+ END CLR non-generics (snippet 5) */
else if ( /* TODO hack if UBYE, uncommented, "ambiguous reference to overloaded definition" ensues, for example for System.Math.Max(x, y) */
typ == clrTypes.USHORT || typ == clrTypes.UINT || typ == clrTypes.ULONG
/* || typ == clrTypes.UBYTE */
@@ -694,19 +707,23 @@ abstract class TypeParser {
if (res != null) res
else if (tMSIL.isInstanceOf[ConstructedType]) {
val ct = tMSIL.asInstanceOf[ConstructedType]
- /* TODO CLR generics: uncomment next two lines and comment out the hack after them
+ /* START CLR generics (snippet 6) */
val cttpArgs = ct.typeArgs.map(tmsil => getCLRType(tmsil)).toList
appliedType(getCLRType(ct.instantiatedType), cttpArgs)
- */
+ /* END CLR generics (snippet 6) */
+ /* START CLR non-generics (snippet 6)
getCLRType(ct.instantiatedType)
+ END CLR non-generics (snippet 6) */
} else if (tMSIL.isInstanceOf[TMVarUsage]) {
- /* TODO CLR generics: uncomment next lines and comment out the hack after them
+ /* START CLR generics (snippet 7) */
val tVarUsage = tMSIL.asInstanceOf[TMVarUsage]
val tVarNumber = tVarUsage.Number
if (tVarUsage.isTVar) classTParams(tVarNumber).typeConstructor // shouldn't fail, just return definitions.AnyClass.tpe at worst
else methodTParams(tVarNumber).typeConstructor // shouldn't fail, just return definitions.AnyClass.tpe at worst
- */
+ /* END CLR generics (snippet 7) */
+ /* START CLR non-generics (snippet 7)
null // definitions.ObjectClass.tpe
+ END CLR non-generics (snippet 7) */
} else if (tMSIL.IsArray()) {
var elemtp = getCLRType(tMSIL.GetElementType())
// cut&pasted from ClassfileParser
@@ -803,7 +820,7 @@ abstract class TypeParser {
flags = flags | Flags.PRIVATE;
else if (field.IsFamily() || field.IsFamilyOrAssembly())
flags = flags | Flags.PROTECTED;
- if (field.IsInitOnly())
+ if (field.IsInitOnly() || field.IsLiteral())
flags = flags | Flags.FINAL;
else
flags = flags | Flags.MUTABLE;
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/ConstructedType.java b/src/msil/ch/epfl/lamp/compiler/msil/ConstructedType.java
index dee67fda43..8c82cb4876 100644
--- a/src/msil/ch/epfl/lamp/compiler/msil/ConstructedType.java
+++ b/src/msil/ch/epfl/lamp/compiler/msil/ConstructedType.java
@@ -11,7 +11,7 @@ public class ConstructedType extends Type {
public final Type[] typeArgs;
public ConstructedType(Type instantiatedType, Type[] typeArgs) {
- super (null, instantiatedType.Attributes, "", null, null, null, instantiatedType.auxAttr /*AuxAttr.None*/ , null);
+ super(instantiatedType.Module, instantiatedType.Attributes, "", null, null, null, instantiatedType.auxAttr /*AuxAttr.None*/ , null);
this.instantiatedType = instantiatedType;
this.typeArgs = typeArgs;
}
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/PEFile.java b/src/msil/ch/epfl/lamp/compiler/msil/PEFile.java
index 3ac90291b4..d6d12c8b4a 100644
--- a/src/msil/ch/epfl/lamp/compiler/msil/PEFile.java
+++ b/src/msil/ch/epfl/lamp/compiler/msil/PEFile.java
@@ -911,20 +911,17 @@ public class PEFile {
while (getByte() == ELEMENT_TYPE_CMOD_OPT
|| getByte() == ELEMENT_TYPE_CMOD_REQD)
{
+ boolean isREQD = (getByte() == ELEMENT_TYPE_CMOD_REQD);
// skip the tag 23.2.7
readByte();
// skip the TypeDefOrRefEncoded (23.2.8)
- readByte();
- readByte();
-
- // @FIXME: could be 4 bytes, not always 2...
-
- //Type t = decodeType();
- //System.err.println("CMOD: " + t);
- //if (getByte() == ELEMENT_TYPE_CMOD_REQD)
- //throw new RuntimeException("Reqired CMOD: " + t);
+ Type ignored = pemodule.getTypeDefOrRef(decodeInt());
+ if(isREQD) {
+ // System.err.println("ELEMENT_TYPE_CMOD_REQD: " + ignored);
+ // throw new RuntimeException("Reqired CMOD: " + ignored);
}
}
+ }
//######################################################################
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/PEModule.java b/src/msil/ch/epfl/lamp/compiler/msil/PEModule.java
index 5cf3e964a7..cb8cd8f098 100644
--- a/src/msil/ch/epfl/lamp/compiler/msil/PEModule.java
+++ b/src/msil/ch/epfl/lamp/compiler/msil/PEModule.java
@@ -161,7 +161,7 @@ final class PEModule extends Module {
int tableId = Table.getTableId(Table._ResolutionScope,
tr.ResolutionScope);
int refRow = tr.ResolutionScope >> Table.NoBits[Table._ResolutionScope];
- String typeName = tr.getFullName();
+ final String typeName = tr.getFullName();
pefile.getTable(tableId).readRow(refRow);
switch (tableId) {
case AssemblyRef.ID:
@@ -190,7 +190,9 @@ final class PEModule extends Module {
//assert type != null;
break;
case TypeRef.ID:
- type = getTypeRef(refRow);
+ Type nestingType = getTypeRef(refRow);
+ String nestedName = typeName;
+ type = nestingType.GetNestedType(nestedName);
break;
case ModuleRef.ID:
type = getAssembly(pefile.ModuleRef.getName()).GetType(typeName);
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/Type.java b/src/msil/ch/epfl/lamp/compiler/msil/Type.java
index a4de4ae11b..b2489ab66e 100644
--- a/src/msil/ch/epfl/lamp/compiler/msil/Type.java
+++ b/src/msil/ch/epfl/lamp/compiler/msil/Type.java
@@ -154,7 +154,7 @@ public abstract class Type extends MemberInfo {
fullName.length()),
declType);
- Module = module;
+ Module = module; // null only for TMVarUsage and for PrimitiveType
Attributes = attr;
this.baseType = baseType;
if (DeclaringType == null) {
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/AssemblyBuilder.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/AssemblyBuilder.scala
index 2c4011eeb0..3110ccd1ce 100644
--- a/src/msil/ch/epfl/lamp/compiler/msil/emit/AssemblyBuilder.scala
+++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/AssemblyBuilder.scala
@@ -6,9 +6,6 @@
package ch.epfl.lamp.compiler.msil.emit
import ch.epfl.lamp.compiler.msil._
-import java.util.HashMap
-import java.util.HashSet
-import java.util.ArrayList
import java.io.IOException
/**
@@ -50,19 +47,19 @@ class AssemblyBuilder(name: AssemblyName)
/** Saves this dynamic assembly to disk. */
@throws(classOf[IOException])
def Save(fileName: String) {
- generatedFiles = new ArrayList()
+ generatedFiles = scala.collection.mutable.ArrayBuffer.empty[String]
ILPrinterVisitor.printAssembly(this, fileName)
}
@throws(classOf[IOException])
def Save(destPath: String, sourceFilesPath: String) {
- generatedFiles = new ArrayList()
+ generatedFiles = scala.collection.mutable.ArrayBuffer.empty[String]
ILPrinterVisitor.printAssembly(this, destPath, sourceFilesPath)
}
/** Returns the list of generated files from calling Save(). */
def GetGeneratedFiles(): Array[String] = {
- return generatedFiles.toArray(new Array[String](generatedFiles.size())).asInstanceOf[Array[String]]
+ return generatedFiles.toArray // (new Array[String](generatedFiles.size())).asInstanceOf[Array[String]]
}
/** Sets the entry point for this dynamic assembly. */
@@ -82,24 +79,28 @@ class AssemblyBuilder(name: AssemblyName)
private var access : Int = _
// all extern assemblies used in this assembly builder
- protected var externAssemblies = new HashSet[Assembly]()
+ protected var externAssemblies = scala.collection.mutable.Set.empty[Assembly]
// register an extern assembly
protected def registerExternAssembly(assembly: Assembly) {
- externAssemblies.add(assembly)
+ externAssemblies += assembly
}
// get all extern Assemblies used in this Assembly Builder
def getExternAssemblies(): Array[Assembly] = {
- externAssemblies = new HashSet[Assembly](Assembly.assemblies.values().asInstanceOf[java.util.Collection[Assembly]])
- externAssemblies.remove(this)
- return externAssemblies.toArray(new Array[Assembly](0)).asInstanceOf[Array[Assembly]]
+ externAssemblies = scala.collection.mutable.Set[Assembly]()
+ val iter = Assembly.assemblies.values().iterator
+ while (iter.hasNext) {
+ externAssemblies += iter.next.asInstanceOf[Assembly]
+ }
+ externAssemblies -= this
+ return externAssemblies.toArray
}
def loadModules() {}
// contains list of generated .msil files after calling Save()
- var generatedFiles: ArrayList[String] = new ArrayList[String]()
+ var generatedFiles = scala.collection.mutable.ArrayBuffer.empty[String]
//##########################################################################
//##########################################################################
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/ILGenerator.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/ILGenerator.scala
index 40888a9b83..c7899c7f54 100644
--- a/src/msil/ch/epfl/lamp/compiler/msil/emit/ILGenerator.scala
+++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/ILGenerator.scala
@@ -7,11 +7,7 @@ package ch.epfl.lamp.compiler.msil.emit
import ch.epfl.lamp.compiler.msil._
import ch.epfl.lamp.compiler.msil.util.Table
-import java.util.ArrayList
import java.util.Stack
-import java.util.Iterator
-import java.util.Map
-import java.util.HashMap
import java.io.IOException
import ILGenerator._
@@ -293,7 +289,7 @@ import ILGenerator._
def DeclareLocal(localType: Type): LocalBuilder = {
val l: LocalBuilder = new LocalBuilder(locals, localType)
locals = locals + 1
- localList.add(l)
+ localList += l
return l
}
@@ -415,19 +411,13 @@ import ILGenerator._
lineNums.put(lastLabel, line + " '" + filename + "'")
}
- def getLocals(): Array[LocalBuilder] = {
- localList.toArray(new Array[LocalBuilder](0)).asInstanceOf[Array[LocalBuilder]]
- }
+ def getLocals(): Array[LocalBuilder] = localList.toArray
- def getLabelIterator(): Iterator[Label] = {
- labelList.iterator()
- }
- def getOpcodeIterator(): Iterator[OpCode] = {
- opcodeList.iterator()
- }
- def getArgumentIterator(): Iterator[Object] = {
- argumentList.iterator()
- }
+ def getLabelIterator() = labelList.iterator
+
+ def getOpcodeIterator() = opcodeList.iterator
+
+ def getArgumentIterator() = argumentList.iterator
//##########################################################################
// private implementation details
@@ -435,15 +425,15 @@ import ILGenerator._
// the local variable list
- private final val localList: ArrayList[LocalBuilder] = new ArrayList[LocalBuilder]()
+ private final val localList = scala.collection.mutable.ArrayBuffer.empty[LocalBuilder]
// the label list, the opcode list and the opcode argument list
// labelList is an array of Label
// opcodeList is an array of OpCode
// argumentList is an array of Object (null if no argument)
- private final val labelList: ArrayList[Label] = new ArrayList[Label]()
- private final val opcodeList: ArrayList[OpCode] = new ArrayList[OpCode]()
- private final val argumentList: ArrayList[Object] = new ArrayList[Object]()
+ private final val labelList = scala.collection.mutable.ArrayBuffer.empty[Label]
+ private final val opcodeList = scala.collection.mutable.ArrayBuffer.empty[OpCode]
+ private final val argumentList = scala.collection.mutable.ArrayBuffer.empty[Object]
// the program counter (pc)
// also called the stream's current position
@@ -464,7 +454,7 @@ import ILGenerator._
// the method info owner of this ILGenerator
var owner: MethodBase = _owner
- val lineNums: Map[Label, String] = new HashMap[Label, String]()
+ val lineNums = scala.collection.mutable.Map.empty[Label, String]
def getMaxStacksize(): Int = { this.maxstack }
@@ -477,13 +467,15 @@ import ILGenerator._
// private emit with Object Argument and override POPUSH
private def emit(opcode: OpCode, arg: Object, overridePOPUSH: Int) {
// add label, opcode and argument
- labelList.add(lastLabel)
- opcodeList.add(opcode)
- argumentList.add(arg)
+ labelList += lastLabel
+ opcodeList += opcode
+ argumentList += arg
// compute new lastLabel (next label)
val stackSize: Int = lastLabel.getStacksize() + overridePOPUSH
if (stackSize < 0) {
- throw new RuntimeException("ILGenerator.emit(): Stack underflow in method: " + owner)
+ val msg = "ILGenerator.emit(): Stack underflow in method: " + owner
+ scala.Console.println(msg)
+ // throw new RuntimeException(msg)
}
if (stackSize > maxstack)
maxstack = stackSize
@@ -498,7 +490,7 @@ import ILGenerator._
def Ldarg0WasJustEmitted() : Boolean = {
if(opcodeList.isEmpty)
return false
- val lastEmitted = opcodeList.get(opcodeList.size - 1)
+ val lastEmitted = opcodeList(opcodeList.size - 1)
lastEmitted eq OpCode.Ldarg_0
}
@@ -506,9 +498,9 @@ import ILGenerator._
emitSpecialLabel(l, null)
}
private def emitSpecialLabel(l: Label, catchType: Type) {
- labelList.add(l)
- opcodeList.add(null)
- argumentList.add(catchType)
+ labelList += l
+ opcodeList += null
+ argumentList += catchType
}
//##########################################################################
@@ -528,16 +520,16 @@ object ILGenerator {
val NO_LABEL: String = ""
private final class ExceptionStack {
- private val labels: Stack[Label] = new Stack[Label]()
- private val kinds: Stack[Label] = new Stack[Label]()
+ private val labels = new scala.collection.mutable.Stack[Label]()
+ private val kinds = new scala.collection.mutable.Stack[Label]()
def ExceptionStack() {}
- def pop() { labels.pop(); kinds.pop() }
+ def pop() { labels.pop; kinds.pop }
def push(kind: Label, label: Label) {
kinds.push(kind); labels.push(label)
}
- def peekKind(): Label.Kind = {kinds.peek().asInstanceOf[Label].getKind() }
- def peekLabel(): Label = { labels.peek().asInstanceOf[Label] }
- def popLabel(): Label = { kinds.pop(); labels.pop().asInstanceOf[Label]}
+ def peekKind(): Label.Kind = kinds.top.getKind
+ def peekLabel(): Label = labels.top
+ def popLabel(): Label = { kinds.pop(); labels.pop() }
}
}
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/ILPrinterVisitor.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/ILPrinterVisitor.scala
index 66f53b8132..73bc0f435c 100644
--- a/src/msil/ch/epfl/lamp/compiler/msil/emit/ILPrinterVisitor.scala
+++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/ILPrinterVisitor.scala
@@ -10,9 +10,6 @@ import java.io.FileWriter
import java.io.BufferedWriter
import java.io.PrintWriter
import java.io.IOException
-import java.util.Iterator
-import java.util.HashMap
-import java.util.Arrays
import java.util.Comparator
import ch.epfl.lamp.compiler.msil._
@@ -33,8 +30,8 @@ abstract class ILPrinterVisitor extends Visitor {
//##########################################################################
protected final val assemblyNameComparator =
- new Comparator[Assembly]() {
- def compare(o1: Assembly, o2: Assembly): Int = {
+ new scala.math.Ordering[Assembly]() {
+ override def compare(o1: Assembly, o2: Assembly): Int = {
val a1 = o1.asInstanceOf[Assembly]
val a2 = o2.asInstanceOf[Assembly]
return a1.GetName().Name.compareTo(a2.GetName().Name)
@@ -101,7 +98,7 @@ abstract class ILPrinterVisitor extends Visitor {
protected def printName(name: String) {
var ch = name.charAt(0)
//if (Character.isLetter(ch) && Character.isLowerCase(ch)) {
- if (ch != '.') {
+ if ((ch != '.') && (ch != '!')) {
print('\''); print(name); print('\'')
} else
print(name)
@@ -236,23 +233,23 @@ abstract class ILPrinterVisitor extends Visitor {
printAttributes(`type`)
}
// print nested classes
- val nested = `type`.nestedTypeBuilders.iterator()
- while(nested.hasNext())
+ val nested = `type`.nestedTypeBuilders.iterator
+ while(nested.hasNext)
print(nested.next().asInstanceOf[TypeBuilder])
// print each field
- val fields = `type`.fieldBuilders.iterator()
- while(fields.hasNext())
+ val fields = `type`.fieldBuilders.iterator
+ while(fields.hasNext)
print(fields.next().asInstanceOf[FieldBuilder])
// print each constructor
- val constrs = `type`.constructorBuilders.iterator()
- while (constrs.hasNext())
+ val constrs = `type`.constructorBuilders.iterator
+ while (constrs.hasNext)
print(constrs.next().asInstanceOf[ConstructorBuilder])
// print each method
- val methods = `type`.methodBuilders.iterator()
- while (methods.hasNext()) {
+ val methods = `type`.methodBuilders.iterator
+ while (methods.hasNext) {
val method = methods.next().asInstanceOf[MethodBuilder]
assert(method.DeclaringType == `type`)
print(method)
@@ -308,29 +305,9 @@ abstract class ILPrinterVisitor extends Visitor {
print((value.asInstanceOf[Long]).longValue())
print(")")
} else if (value.isInstanceOf[Float]) {
- // !!! check if encoding is correct
- val bits = java.lang.Float.floatToRawIntBits((value.asInstanceOf[Float]).floatValue())
- // float32(float32(...)) != float32(...)
- print("float32 (float32 (")
- /* see p. 170 in Lidin's book Expert .NET 2.0 IL Assembler */
- val valFlo = value.asInstanceOf[Float]
- if (java.lang.Float.NaN == valFlo) print("0xFFC00000 /* NaN */ ") /* TODO this is 'quiet NaN, http://www.savrola.com/resources/NaN.html , what's the difference with a 'signaling NaN'?? */
- else if (java.lang.Float.NEGATIVE_INFINITY == valFlo) print("0xFF800000 /* NEGATIVE_INFINITY */ ")
- else if (java.lang.Float.POSITIVE_INFINITY == valFlo) print("0x7F800000 /* POSITIVE_INFINITY */ ")
- else print(bits)
- print("))")
+ print(msilSyntaxFloat(value.asInstanceOf[Float]))
} else if (value.isInstanceOf[Double]) {
- // !!! check if encoding is correct
- var bits = java.lang.Double.doubleToRawLongBits((value.asInstanceOf[Double]).doubleValue())
- // float64(float64(...)) != float64(...)
- print("float64 (float64 (")
- /* see p. 170 in Lidin's book Expert .NET 2.0 IL Assembler */
- val valDou = value.asInstanceOf[Double]
- if (java.lang.Double.NaN == valDou) print("0xffffffffffffffff /* NaN */ ") /* TODO this is 'quiet NaN, http://www.savrola.com/resources/NaN.html , what's the difference with a 'signaling NaN'?? */
- else if (java.lang.Double.NEGATIVE_INFINITY == valDou) print("0xfff0000000000000 /* NEGATIVE_INFINITY */ ")
- else if (java.lang.Double.POSITIVE_INFINITY == valDou) print("0x7ff0000000000000 /* POSITIVE_INFINITY */ ")
- else print(bits)
- print("))")
+ print(msilSyntaxDouble(value.asInstanceOf[Double]))
} else {
throw new Error("ILPrinterVisitor: Illegal default value: "
+ value.getClass())
@@ -340,6 +317,31 @@ abstract class ILPrinterVisitor extends Visitor {
printAttributes(field)
}
+ def msilSyntaxFloat(valFlo: java.lang.Float) : String = {
+ // !!! check if encoding is correct
+ val bits = java.lang.Float.floatToRawIntBits(valFlo.floatValue())
+ /* see p. 170 in Lidin's book Expert .NET 2.0 IL Assembler */
+ /* Note: no value is equal to Nan, including NaN. Thus, x == Float.NaN always evaluates to false. */
+ val res = if (valFlo.isNaN) "0xFFC00000 /* NaN */ " /* TODO this is 'quiet NaN, http://www.savrola.com/resources/NaN.html , what's the difference with a 'signaling NaN'?? */
+ else if (java.lang.Float.NEGATIVE_INFINITY == valFlo.floatValue) "0xFF800000 /* NEGATIVE_INFINITY */ "
+ else if (java.lang.Float.POSITIVE_INFINITY == valFlo.floatValue) "0x7F800000 /* POSITIVE_INFINITY */ "
+ else bits
+ "float32 (" + res + ")"
+ }
+
+ def msilSyntaxDouble(valDou: java.lang.Double) : String = {
+ // !!! check if encoding is correct
+ var bits = java.lang.Double.doubleToRawLongBits(valDou.doubleValue())
+ /* see p. 170 in Lidin's book Expert .NET 2.0 IL Assembler */
+ /* Note: no value is equal to Nan, including NaN. Thus, x == Double.NaN always evaluates to false. */
+ val res = if (valDou.isNaN) "0xffffffffffffffff /* NaN */ " /* TODO this is 'quiet NaN, http://www.savrola.com/resources/NaN.html , what's the difference with a 'signaling NaN'?? */
+ else if (java.lang.Double.NEGATIVE_INFINITY == valDou.doubleValue) "0xfff0000000000000 /* NEGATIVE_INFINITY */ "
+ else if (java.lang.Double.POSITIVE_INFINITY == valDou.doubleValue) "0x7ff0000000000000 /* POSITIVE_INFINITY */ "
+ else bits
+ // float64(float64(...)) != float64(...)
+ "float64 (" + res + ")"
+ }
+
/**
* Visit a ConstructorBuilder
*/
@@ -402,6 +404,7 @@ abstract class ILPrinterVisitor extends Visitor {
print(' '); printName(param.Name)
}
+ var locals: Array[LocalBuilder] = null
/**
* Visit an ILGenerator
*/
@@ -410,7 +413,7 @@ abstract class ILPrinterVisitor extends Visitor {
// print maxstack
println(".maxstack " + code.getMaxStacksize())
// get the local variables
- var locals: Array[LocalBuilder] = code.getLocals()
+ locals = code.getLocals()
if (locals.length > 0) {
println(".locals init (")
indent()
@@ -426,15 +429,16 @@ abstract class ILPrinterVisitor extends Visitor {
val itO = code.getOpcodeIterator()
val itA = code.getArgumentIterator()
// iterate over each opcode
- while (itO.hasNext()) {
+ while (itO.hasNext) {
// first print label
- val label = itL.next().asInstanceOf[Label]
- var o = code.lineNums.get(label)
- if (o != null)
- println(".line " + o)
- argument = itA.next().asInstanceOf[Object]
+ val label = itL.next
+ val oOpt = code.lineNums.get(label)
+ if (oOpt.isDefined) {
+ println(".line " + oOpt.get)
+ }
+ argument = itA.next.asInstanceOf[Object]
printLabel(label)
- val o2 = itO.next()
+ val o2 = itO.next
if (o2 != null) {
print(" ")
print(o2.asInstanceOf[OpCode])
@@ -483,6 +487,14 @@ abstract class ILPrinterVisitor extends Visitor {
print(loc.slot); print("\t// "); printSignature(loc.LocalType)
print(" \'"); print(loc.name); print("\'")
//print("'") print(((LocalBuilder)argument).name) print("'")
+ } else if (opCode == OpCode.Ldloc_0 || opCode == OpCode.Ldloc_1 || opCode == OpCode.Ldloc_2 || opCode == OpCode.Ldloc_3 ) {
+ val loc = locals(opCode.CEE_opcode - OpCode.CEE_LDLOC_0)
+ print("\t// "); printSignature(loc.LocalType)
+ print(" \'"); print(loc.name); print("\'")
+ } else if (opCode == OpCode.Stloc_0 || opCode == OpCode.Stloc_1 || opCode == OpCode.Stloc_2 || opCode == OpCode.Stloc_3 ) {
+ val loc = locals(opCode.CEE_opcode - OpCode.CEE_STLOC_0)
+ print("\t// "); printSignature(loc.LocalType)
+ print(" \'"); print(loc.name); print("\'")
} else if (opCode == OpCode.Readonly) {
// nothing to do
} else if (opCode == OpCode.Constrained) {
@@ -491,8 +503,21 @@ abstract class ILPrinterVisitor extends Visitor {
printReference(argument.asInstanceOf[Type])
} else {
// by default print toString argument if any
- if (argument != null)
- print(argument)
+ if (argument != null) {
+ val strArgument = java.lang.String.valueOf(argument)
+ if ( argument.isInstanceOf[java.lang.Float]
+ && ( strArgument.equals("NaN")
+ || strArgument.equals("-Infinity")
+ || strArgument.equals("Infinity")))
+ print(msilSyntaxFloat(argument.asInstanceOf[java.lang.Float]))
+ else if ( argument.isInstanceOf[java.lang.Double]
+ && ( strArgument.equals("NaN")
+ || strArgument.equals("-Infinity")
+ || strArgument.equals("Infinity")))
+ print(msilSyntaxDouble(argument.asInstanceOf[java.lang.Double]))
+ else print(strArgument)
+ }
+
} // end switch
}
@@ -646,12 +671,11 @@ abstract class ILPrinterVisitor extends Visitor {
}
def printSignature(`type`: Type) {
- val sig : Object = primitive.get(`type`)
- if (sig != null) {
- print(sig)
+ val sigOpt = primitive.get(`type`)
+ if (sigOpt.isDefined) {
+ print(sigOpt.get)
return
}
-
if (`type`.HasElementType()) {
printSignature(`type`.GetElementType())
if (`type`.IsArray())
@@ -661,29 +685,36 @@ abstract class ILPrinterVisitor extends Visitor {
else if (`type`.IsByRef())
print('&')
} else {
- print(if(`type`.IsValueType()) "valuetype " else "class ")
+ val preref = if (`type`.isInstanceOf[Type.TMVarUsage]) ""
+ else if(`type`.IsValueType()) "valuetype "
+ else "class "
+ print(preref)
printReference(`type`)
}
}
def printReference(`type`: Type) {
+ if (`type`.Module != null) { // i.e. not PrimitiveType and not TMVarUsage
if (`type`.Assembly() != currentModule.Assembly) {
print('['); print(`type`.Assembly().GetName().Name); print("]")
} else if (`type`.Module != currentModule) {
print("[.module "); print(`type`.Module.Name); print("]")
}
+ }
printTypeName(`type`)
}
def printTypeName(`type`: Type) {
if (`type`.isInstanceOf[ConstructedType]) {
val ct = `type`.asInstanceOf[ConstructedType]
- printSignature(ct.instantiatedType)
+ printTypeName(ct.instantiatedType)
print("<")
var i = 0
while (i < ct.typeArgs.length) {
val ta = ct.typeArgs(i)
- printTypeName(ta); /* should be printSignature, but don't want `class' or `valuetype'
+ val sigOpt = primitive.get(ta)
+ if (sigOpt.isDefined) print(sigOpt.get)
+ else printTypeName(ta); /* should be printSignature, but don't want `class' or `valuetype'
appearing before a type param usage. */
i = i + 1;
if (i < ct.typeArgs.length) {
@@ -789,7 +820,7 @@ object ILPrinterVisitor {
/** The current assembly */
var currAssembly: Assembly = _
- final var primitive = new HashMap[Type, String]()
+ final var primitive = scala.collection.mutable.Map.empty[Type, String]
def addPrimitive(name: String, sig: String) {
var `type` =
Type.GetType(name)
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/ModuleBuilder.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/ModuleBuilder.scala
index a2d284865f..981e855e0e 100644
--- a/src/msil/ch/epfl/lamp/compiler/msil/emit/ModuleBuilder.scala
+++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/ModuleBuilder.scala
@@ -6,8 +6,6 @@
package ch.epfl.lamp.compiler.msil.emit
import ch.epfl.lamp.compiler.msil._
-import java.util.HashMap
-import java.util.ArrayList
import java.io.IOException
/**
@@ -36,8 +34,8 @@ class ModuleBuilder(name: String, fullname: String, scopeName: String, assembly:
def CreateGlobalFunctions() {
if (globalsCreated)
throw new RuntimeException("Global functions are already created")
- this.fields = fieldBuilders.toArray(fields).asInstanceOf[Array[FieldInfo]]
- this.methods = methodBuilders.toArray(methods).asInstanceOf[Array[MethodInfo]]
+ this.fields = fieldBuilders.toArray // (fields).asInstanceOf[Array[FieldInfo]]
+ this.methods = methodBuilders.toArray // (methods).asInstanceOf[Array[MethodInfo]]
globalsCreated = true
}
@@ -94,13 +92,18 @@ class ModuleBuilder(name: String, fullname: String, scopeName: String, assembly:
{
val method =
new MethodBuilder(name, null, attributes, returnType, paramTypes)
- methodBuilders.add(method)
+ methodBuilders += method
return method
}
override def GetTypes(): Array[Type] = {
- return typesMap.values().toArray(Type.EmptyTypes).asInstanceOf[Array[Type]]
+ val res = scala.collection.mutable.ArrayBuffer.empty[Type]
+ val iter = typesMap.values().iterator
+ while (iter.hasNext) {
+ res += iter.next.asInstanceOf[Type]
+ }
+ return res.toArray
}
/** Sets a custom attribute. */
@@ -112,8 +115,8 @@ class ModuleBuilder(name: String, fullname: String, scopeName: String, assembly:
// internal members
var globalsCreated = false
- protected var fieldBuilders = new ArrayList[FieldInfo]()
- protected var methodBuilders = new ArrayList[MethodInfo]()
+ protected var fieldBuilders = scala.collection.mutable.ArrayBuffer.empty[FieldInfo]
+ protected var methodBuilders = scala.collection.mutable.ArrayBuffer.empty[MethodInfo]
override def addType(t: Type): Type = {
return super.addType(t)
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/MultipleFilesILPrinterVisitor.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/MultipleFilesILPrinterVisitor.scala
index afd2d5d556..43333ef825 100644
--- a/src/msil/ch/epfl/lamp/compiler/msil/emit/MultipleFilesILPrinterVisitor.scala
+++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/MultipleFilesILPrinterVisitor.scala
@@ -11,7 +11,6 @@ import java.io.BufferedWriter
import java.io.PrintWriter
import java.io.IOException
import java.util.Iterator
-import java.util.HashMap
import java.util.Arrays
import ch.epfl.lamp.compiler.msil._
@@ -39,7 +38,7 @@ final class MultipleFilesILPrinterVisitor(destPath: String, sourceFilesPath: Str
// all external assemblies
as = assemblyBuilder.getExternAssemblies()
- Arrays.sort(as, assemblyNameComparator)
+ scala.util.Sorting.quickSort(as)(assemblyNameComparator) // Arrays.sort(as, assemblyNameComparator)
// print each module
var m: Array[Module] = assemblyBuilder.GetModules()
@@ -91,7 +90,7 @@ final class MultipleFilesILPrinterVisitor(destPath: String, sourceFilesPath: Str
append = true
} else {
fileName.getParentFile().mkdirs()
- assemblyBuilder.generatedFiles.add(fileName.getPath)
+ assemblyBuilder.generatedFiles += (fileName.getPath)
}
out = new PrintWriter(new BufferedWriter(new FileWriter(fileName, append)))
@@ -115,7 +114,7 @@ final class MultipleFilesILPrinterVisitor(destPath: String, sourceFilesPath: Str
out = new PrintWriter(new BufferedWriter(new FileWriter(globalMethods, append)))
// make sure we're the first in the list (ilasm uses the first file name to guess the output file name)
- assemblyBuilder.generatedFiles.add(0, globalMethods.getPath)
+ assemblyBuilder.generatedFiles.insert(0, globalMethods.getPath)
// if this file hasn't been created by one of the classes, write boilerplate
if(!append) {
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/SingleFileILPrinterVisitor.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/SingleFileILPrinterVisitor.scala
index d1b13054bc..0f2e7d7ecf 100644
--- a/src/msil/ch/epfl/lamp/compiler/msil/emit/SingleFileILPrinterVisitor.scala
+++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/SingleFileILPrinterVisitor.scala
@@ -42,9 +42,9 @@ final class SingleFileILPrinterVisitor(_fileName: String) extends ILPrinterVisit
// all external assemblies
as = assemblyBuilder.getExternAssemblies()
- Arrays.sort(as, assemblyNameComparator)
+ scala.util.Sorting.quickSort(as)(assemblyNameComparator) // Arrays.sort(as, assemblyNameComparator)
- assemblyBuilder.generatedFiles.add(fileName)
+ assemblyBuilder.generatedFiles += fileName
printAssemblyBoilerplate()
// print each module
diff --git a/src/msil/ch/epfl/lamp/compiler/msil/emit/TypeBuilder.scala b/src/msil/ch/epfl/lamp/compiler/msil/emit/TypeBuilder.scala
index 8667098cdb..663b2c5cb0 100644
--- a/src/msil/ch/epfl/lamp/compiler/msil/emit/TypeBuilder.scala
+++ b/src/msil/ch/epfl/lamp/compiler/msil/emit/TypeBuilder.scala
@@ -6,9 +6,6 @@
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
/**
@@ -29,10 +26,10 @@ class TypeBuilder (module: Module, attributes: Int, fullName: String, baseType:
/** '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]]
+ 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)
@@ -46,7 +43,7 @@ class TypeBuilder (module: Module, attributes: Int, fullName: String, baseType:
*/
def DefineField(name: String, `type`: Type, attrs: Short): FieldBuilder = {
val field: FieldBuilder = new FieldBuilder(name, this, attrs, `type`)
- fieldBuilders.add(field)
+ fieldBuilders += field
return field
}
@@ -56,14 +53,14 @@ class TypeBuilder (module: Module, attributes: Int, fullName: String, baseType:
*/
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 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)
+ if (methodsEqual(m, method)) {
+ throw new RuntimeException("["+ Assembly() + "] Method has already been defined: " + m)
}
- methodBuilders.add(method)
+ }
+ methodBuilders += method
return method
}
@@ -73,7 +70,14 @@ class TypeBuilder (module: Module, attributes: Int, fullName: String, baseType:
*/
def DefineConstructor(attrs: Short, callingConvention: Short, paramTypes: Array[Type]): ConstructorBuilder = {
val constr = new ConstructorBuilder(this, attrs, paramTypes)
- constructorBuilders.add(constr)
+ val iter = constructorBuilders.iterator
+ while(iter.hasNext) {
+ val c = iter.next().asInstanceOf[ConstructorInfo]
+ if (constructorsEqual(c, constr)) {
+ throw new RuntimeException("["+ Assembly() + "] Constructor has already been defined: " + c)
+ }
+ }
+ constructorBuilders += constr
return constr
}
@@ -81,16 +85,16 @@ class TypeBuilder (module: Module, attributes: Int, fullName: String, baseType:
* 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]
+ val nested = nestedTypeBuilders.iterator
+ while(nested.hasNext) {
+ val nt = nested.next
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)
+ nestedTypeBuilders += t
return t
}
@@ -176,10 +180,10 @@ class TypeBuilder (module: Module, attributes: Int, fullName: String, baseType:
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]()
+ var fieldBuilders = scala.collection.mutable.ArrayBuffer.empty[FieldBuilder]
+ var methodBuilders = scala.collection.mutable.ArrayBuffer.empty[MethodBuilder]
+ var constructorBuilders = scala.collection.mutable.ArrayBuffer.empty[ConstructorBuilder]
+ var nestedTypeBuilders = scala.collection.mutable.ArrayBuffer.empty[TypeBuilder]
// shows if the type is 'raw', i.e. still subject to changes
private var raw = true
@@ -230,4 +234,18 @@ object TypeBuilder {
return false
return true
}
+
+ def constructorsEqual(c1: ConstructorInfo, c2: ConstructorInfo): Boolean = {
+ if (c1.IsStatic != c2.IsStatic)
+ return false
+ val p1 = c1.GetParameters()
+ val p2 = c2.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
+}
+
}