diff options
author | Jason Zaugg <jzaugg@gmail.com> | 2013-05-17 17:01:20 +0200 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2013-05-17 11:16:39 -0700 |
commit | b7c352a57f65458c66c78a368f75aaaa4a08e443 (patch) | |
tree | 4b2b7fcea439948c5de65b05a392091a66eea0a4 /src/compiler/scala/tools/nsc/symtab | |
parent | 4f8c306aca703c63282295c9f74f0cb35f9f85d4 (diff) | |
parent | be405eed9bef9736f0142d6ddf53b6bf8af08696 (diff) | |
download | scala-b7c352a57f65458c66c78a368f75aaaa4a08e443.tar.gz scala-b7c352a57f65458c66c78a368f75aaaa4a08e443.tar.bz2 scala-b7c352a57f65458c66c78a368f75aaaa4a08e443.zip |
Merge v2.10.1-326-g4f8c306' into merge/v2.10.1-326-g4f8c306-to-master
================================================================
Merge commit 'v2.10.1-326-g4f8c306' into merge/v2.10.1-326-g4f8c306-to-master
Conflicts:
src/compiler/scala/tools/nsc/typechecker/SuperAccessors.scala
src/reflect/scala/reflect/runtime/JavaMirrors.scala
================================================================
Merge -s ours 4e64a27 ([nomaster commit range])
================================================================
Merge commit '0ae7e55' into merge/v2.10.1-326-g4f8c306-to-master
Conflicts:
src/compiler/scala/tools/nsc/typechecker/Macros.scala
Diffstat (limited to 'src/compiler/scala/tools/nsc/symtab')
9 files changed, 545 insertions, 1690 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/BrowsingLoaders.scala b/src/compiler/scala/tools/nsc/symtab/BrowsingLoaders.scala index f2aab36b51..4e4efef607 100644 --- a/src/compiler/scala/tools/nsc/symtab/BrowsingLoaders.scala +++ b/src/compiler/scala/tools/nsc/symtab/BrowsingLoaders.scala @@ -6,7 +6,6 @@ package scala.tools.nsc package symtab -import scala.reflect.internal.util.BatchSourceFile import scala.tools.nsc.io.AbstractFile /** A subclass of SymbolLoaders that implements browsing behavior. @@ -28,7 +27,7 @@ abstract class BrowsingLoaders extends SymbolLoaders { override protected def enterIfNew(owner: Symbol, member: Symbol, completer: SymbolLoader): Symbol = { completer.sourcefile match { case Some(src) => - (if (member.isModule) member.moduleClass else member).sourceFile = src + (if (member.isModule) member.moduleClass else member).associatedFile = src case _ => } val decls = owner.info.decls diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala index 9e5186b731..98fb6bd0ef 100644 --- a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala +++ b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala @@ -10,10 +10,9 @@ import java.io.IOException import scala.compat.Platform.currentTime import scala.tools.nsc.util.{ ClassPath } import classfile.ClassfileParser -import scala.reflect.internal.Flags._ import scala.reflect.internal.MissingRequirementError import scala.reflect.internal.util.Statistics -import scala.tools.nsc.io.{ AbstractFile, MsilFile } +import scala.reflect.io.{ AbstractFile, NoAbstractFile } /** This class ... * @@ -31,6 +30,14 @@ abstract class SymbolLoaders { member } + protected def signalError(root: Symbol, ex: Throwable) { + if (settings.debug) ex.printStackTrace() + globalError(ex.getMessage() match { + case null => "i/o error while loading " + root.name + case msg => "error while loading " + root.name + ", " + msg + }) + } + /** Enter class with given `name` into scope of `root` * and give them `completer` as type. */ @@ -136,10 +143,10 @@ abstract class SymbolLoaders { ((classRep.binary, classRep.source) : @unchecked) match { case (Some(bin), Some(src)) if platform.needCompile(bin, src) && !binaryOnly(owner, classRep.name) => - if (settings.verbose.value) inform("[symloader] picked up newer source file for " + src.path) + if (settings.verbose) inform("[symloader] picked up newer source file for " + src.path) global.loaders.enterToplevelsFromSource(owner, classRep.name, src) case (None, Some(src)) => - if (settings.verbose.value) inform("[symloader] no class, picked up source file for " + src.path) + if (settings.verbose) inform("[symloader] no class, picked up source file for " + src.path) global.loaders.enterToplevelsFromSource(owner, classRep.name, src) case (Some(bin), _) => global.loaders.enterClassAndModule(owner, classRep.name, platform.newClassLoader(bin)) @@ -160,7 +167,7 @@ abstract class SymbolLoaders { def sourcefile: Option[AbstractFile] = None /** - * Description of the resource (ClassPath, AbstractFile, MsilFile) + * Description of the resource (ClassPath, AbstractFile) * being processed by this loader */ protected def description: String @@ -169,25 +176,13 @@ abstract class SymbolLoaders { private def setSource(sym: Symbol) { sourcefile foreach (sf => sym match { - case cls: ClassSymbol => cls.sourceFile = sf - case mod: ModuleSymbol => mod.moduleClass.sourceFile = sf + case cls: ClassSymbol => cls.associatedFile = sf + case mod: ModuleSymbol => mod.moduleClass.associatedFile = sf case _ => () }) } override def complete(root: Symbol) { - def signalError(ex: Exception) { - ok = false - if (settings.debug.value) ex.printStackTrace() - val msg = ex.getMessage() - // SI-5593 Scaladoc's current strategy is to visit all packages in search of user code that can be documented - // therefore, it will rummage through the classpath triggering errors whenever it encounters package objects - // that are not in their correct place (see bug for details) - if (!settings.isScaladoc) - globalError( - if (msg eq null) "i/o error while loading " + root.name - else "error while loading " + root.name + ", " + msg); - } try { val start = currentTime val currentphase = phase @@ -197,11 +192,11 @@ abstract class SymbolLoaders { ok = true setSource(root) setSource(root.companionSymbol) // module -> class, class -> module - } catch { - case ex: IOException => - signalError(ex) - case ex: MissingRequirementError => - signalError(ex) + } + catch { + case ex @ (_: IOException | _: MissingRequirementError) => + ok = false + signalError(root, ex) } initRoot(root) if (!root.isPackageClass) initRoot(root.companionSymbol) @@ -233,17 +228,20 @@ abstract class SymbolLoaders { assert(root.isPackageClass, root) root.setInfo(new PackageClassInfoType(newScope, root)) - val sourcepaths = classpath.sourcepaths if (!root.isRoot) { for (classRep <- classpath.classes if platform.doLoad(classRep)) { initializeFromClassPath(root, classRep) } } if (!root.isEmptyPackageClass) { + // Only enter packages which contain a class or a non-empty package for (pkg <- classpath.packages) { - enterPackage(root, pkg.name, new PackageLoader(pkg)) + if (pkg.isEmptyOfClassfiles) { + log(s"Discarding $root/$pkg as it contains no classfiles.") + } + else + enterPackage(root, pkg.name, new PackageLoader(pkg)) } - openPackageModule(root) } } @@ -259,7 +257,7 @@ abstract class SymbolLoaders { protected def doComplete(root: Symbol) { val start = if (Statistics.canEnable) Statistics.startTimer(classReadNanos) else null classfileParser.parse(classfile, root) - if (root.associatedFile eq null) { + if (root.associatedFile eq NoAbstractFile) { root match { // In fact, the ModuleSymbol forwards its setter to the module class case _: ClassSymbol | _: ModuleSymbol => @@ -274,16 +272,6 @@ abstract class SymbolLoaders { override def sourcefile: Option[AbstractFile] = classfileParser.srcfile } - class MsilFileLoader(msilFile: MsilFile) extends SymbolLoader with FlagAssigningCompleter { - private def typ = msilFile.msilType - private object typeParser extends clr.TypeParser { - val global: SymbolLoaders.this.global.type = SymbolLoaders.this.global - } - - protected def description = "MsilFile "+ typ.FullName + ", assembly "+ typ.Assembly.FullName - protected def doComplete(root: Symbol) { typeParser.parse(typ, root) } - } - class SourcefileLoader(val srcfile: AbstractFile) extends SymbolLoader with FlagAssigningCompleter { protected def description = "source file "+ srcfile.toString override def fromSource = true @@ -296,11 +284,6 @@ abstract class SymbolLoaders { protected def doComplete(root: Symbol) { root.sourceModule.initialize } } - object clrTypes extends clr.CLRTypes { - val global: SymbolLoaders.this.global.type = SymbolLoaders.this.global - if (global.forMSIL) init() - } - /** used from classfile parser to avoid cyclies */ var parentsLevel = 0 var pendingLoadActions: List[() => Unit] = Nil diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolTrackers.scala b/src/compiler/scala/tools/nsc/symtab/SymbolTrackers.scala index 7a84441e09..daaa625164 100644 --- a/src/compiler/scala/tools/nsc/symtab/SymbolTrackers.scala +++ b/src/compiler/scala/tools/nsc/symtab/SymbolTrackers.scala @@ -6,7 +6,6 @@ package scala.tools.nsc package symtab -import scala.collection.{ mutable, immutable } import scala.language.implicitConversions import scala.language.postfixOps @@ -17,9 +16,6 @@ trait SymbolTrackers { val global: Global import global._ - private implicit lazy val TreeOrdering: Ordering[Tree] = - Ordering by (x => (x.shortClass, x.symbol)) - private implicit lazy val SymbolOrdering: Ordering[Symbol] = Ordering by (x => (x.kindString, x.name.toString)) @@ -76,7 +72,6 @@ trait SymbolTrackers { private def isFlagsChange(sym: Symbol) = changed.flags contains sym private implicit def NodeOrdering: Ordering[Node] = Ordering by (_.root) - private def ownersString(sym: Symbol, num: Int) = sym.ownerChain drop 1 take num mkString " -> " object Node { def nodes(syms: Set[Symbol]): List[Node] = { @@ -114,7 +109,6 @@ trait SymbolTrackers { case Some(oldFlags) => val added = masked & ~oldFlags val removed = oldFlags & ~masked - val steady = masked & ~(added | removed) val all = masked | oldFlags val strs = 0 to 63 map { bit => val flag = 1L << bit @@ -133,7 +127,7 @@ trait SymbolTrackers { else " (" + Flags.flagsToString(masked) + ")" } def symString(sym: Symbol) = ( - if (settings.debug.value && sym.hasCompleteInfo) { + if (settings.debug && sym.hasCompleteInfo) { val s = sym.defString take 240 if (s.length == 240) s + "..." else s } @@ -181,7 +175,7 @@ trait SymbolTrackers { } def show(label: String): String = { val hierarchy = Node(current) - val Change(added, removed, symMap, owners, flags) = history.head + val Change(_, removed, symMap, _, _) = history.head def detailString(sym: Symbol) = { val ownerString = sym.ownerChain splitAt 3 match { case (front, back) => diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/AbstractFileReader.scala b/src/compiler/scala/tools/nsc/symtab/classfile/AbstractFileReader.scala index 427b5bf887..17e3b08ec2 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/AbstractFileReader.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/AbstractFileReader.scala @@ -29,11 +29,6 @@ class AbstractFileReader(val file: AbstractFile) { */ var bp: Int = 0 - /** return byte at offset 'pos' - */ - @throws(classOf[IndexOutOfBoundsException]) - def byteAt(pos: Int): Byte = buf(pos) - /** read a byte */ @throws(classOf[IndexOutOfBoundsException]) @@ -45,7 +40,7 @@ class AbstractFileReader(val file: AbstractFile) { /** read some bytes */ - def nextBytes(len: Int): Array[Byte] = { + def nextBytes(len: Int): Array[Byte] = { // used in ide bp += len buf.slice(bp - len, bp) } diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala index da117540b4..9afa1ba10d 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala @@ -3,7 +3,8 @@ * @author Martin Odersky */ -package scala.tools.nsc +package scala +package tools.nsc package symtab package classfile @@ -12,9 +13,11 @@ import java.lang.Integer.toHexString import scala.collection.{ mutable, immutable } import scala.collection.mutable.{ ListBuffer, ArrayBuffer } import scala.annotation.switch +import scala.reflect.internal.{ JavaAccFlags } import scala.reflect.internal.pickling.{PickleBuffer, ByteCodecs} import scala.tools.nsc.io.AbstractFile + /** This abstract class implements a class file parser. * * @author Martin Odersky @@ -23,15 +26,15 @@ import scala.tools.nsc.io.AbstractFile abstract class ClassfileParser { val global: Global import global._ - import definitions.{ AnnotationClass, ClassfileAnnotationClass } + import definitions._ import scala.reflect.internal.ClassfileConstants._ import Flags._ protected var in: AbstractFileReader = _ // the class file reader protected var clazz: Symbol = _ // the class symbol containing dynamic members protected var staticModule: Symbol = _ // the module symbol containing static members - protected var instanceScope: Scope = _ // the scope of all instance definitions - protected var staticScope: Scope = _ // the scope of all static definitions + protected var instanceScope: Scope = _ // the scope of all instance definitions + protected var staticScope: Scope = _ // the scope of all static definitions protected var pool: ConstantPool = _ // the classfile's constant pool protected var isScala: Boolean = _ // does class file describe a scala class? protected var isScalaAnnot: Boolean = _ // does class file describe a scala class with its pickled info in an annotation? @@ -41,21 +44,41 @@ abstract class ClassfileParser { protected var classTParams = Map[Name,Symbol]() protected var srcfile0 : Option[AbstractFile] = None protected def moduleClass: Symbol = staticModule.moduleClass + private var sawPrivateConstructor = false + + private def ownerForFlags(jflags: JavaAccFlags) = if (jflags.isStatic) moduleClass else clazz def srcfile = srcfile0 + private def optimized = global.settings.optimise.value private def currentIsTopLevel = !(currentClass.decodedName containsChar '$') + // u1, u2, and u4 are what these data types are called in the JVM spec. + // They are an unsigned byte, unsigned char, and unsigned int respectively. + // We bitmask u1 into an Int to make sure it's 0-255 (and u1 isn't used + // for much beyond tags) but leave u2 alone as it's already unsigned. + protected final def u1(): Int = in.nextByte & 0xFF + protected final def u2(): Char = in.nextChar + protected final def u4(): Int = in.nextInt + + private def readInnerClassFlags() = readClassFlags() + private def readClassFlags() = JavaAccFlags classFlags u2 + private def readMethodFlags() = JavaAccFlags methodFlags u2 + private def readFieldFlags() = JavaAccFlags fieldFlags u2 + private def readTypeName() = readName().toTypeName + private def readName() = pool getName u2 + private def readType() = pool getType u2 + private object unpickler extends scala.reflect.internal.pickling.UnPickler { val global: ClassfileParser.this.global.type = ClassfileParser.this.global } private def handleMissing(e: MissingRequirementError) = { - if (settings.debug.value) e.printStackTrace + if (settings.debug) e.printStackTrace throw new IOException(s"Missing dependency '${e.req}', required by ${in.file}") } private def handleError(e: Exception) = { - if (settings.debug.value) e.printStackTrace() + if (settings.debug) e.printStackTrace() throw new IOException(s"class file '${in.file}' is broken\n(${e.getClass}/${e.getMessage})") } private def mismatchError(c: Symbol) = { @@ -96,75 +119,67 @@ abstract class ClassfileParser { this.staticModule = if (root.isModule) root else root.companionModule this.isScala = false - parseHeader + parseHeader() this.pool = new ConstantPool parseClass() } } private def parseHeader() { - val magic = in.nextInt + val magic = u4 if (magic != JAVA_MAGIC) - throw new IOException("class file '" + in.file + "' " - + "has wrong magic number 0x" + toHexString(magic) - + ", should be 0x" + toHexString(JAVA_MAGIC)) - val minorVersion = in.nextChar.toInt - val majorVersion = in.nextChar.toInt - if ((majorVersion < JAVA_MAJOR_VERSION) || - ((majorVersion == JAVA_MAJOR_VERSION) && - (minorVersion < JAVA_MINOR_VERSION))) - throw new IOException("class file '" + in.file + "' " - + "has unknown version " - + majorVersion + "." + minorVersion - + ", should be at least " - + JAVA_MAJOR_VERSION + "." + JAVA_MINOR_VERSION) + abort(s"class file ${in.file} has wrong magic number 0x${toHexString(magic)}") + + val minor, major = u2 + if (major < JAVA_MAJOR_VERSION || major == JAVA_MAJOR_VERSION && minor < JAVA_MINOR_VERSION) + abort(s"class file ${in.file} has unknown version $major.$minor, should be at least $JAVA_MAJOR_VERSION.$JAVA_MINOR_VERSION") } class ConstantPool { - private val len = in.nextChar - private val starts = new Array[Int](len) - private val values = new Array[AnyRef](len) + private val len = u2 + private val starts = new Array[Int](len) + private val values = new Array[AnyRef](len) private val internalized = new Array[Name](len) { var i = 1 while (i < starts.length) { starts(i) = in.bp i += 1 - (in.nextByte.toInt: @switch) match { - case CONSTANT_UTF8 | CONSTANT_UNICODE => - in.skip(in.nextChar) - case CONSTANT_CLASS | CONSTANT_STRING | CONSTANT_METHODTYPE=> - in.skip(2) - case CONSTANT_METHODHANDLE => - in.skip(3) - case CONSTANT_FIELDREF | CONSTANT_METHODREF | CONSTANT_INTFMETHODREF - | CONSTANT_NAMEANDTYPE | CONSTANT_INTEGER | CONSTANT_FLOAT - | CONSTANT_INVOKEDYNAMIC => - in.skip(4) - case CONSTANT_LONG | CONSTANT_DOUBLE => - in.skip(8) - i += 1 - case _ => - errorBadTag(in.bp - 1) + (u1.toInt: @switch) match { + case CONSTANT_UTF8 | CONSTANT_UNICODE => in skip u2 + case CONSTANT_CLASS | CONSTANT_STRING | CONSTANT_METHODTYPE => in skip 2 + case CONSTANT_METHODHANDLE => in skip 3 + case CONSTANT_FIELDREF | CONSTANT_METHODREF | CONSTANT_INTFMETHODREF => in skip 4 + case CONSTANT_NAMEANDTYPE | CONSTANT_INTEGER | CONSTANT_FLOAT => in skip 4 + case CONSTANT_INVOKEDYNAMIC => in skip 4 + case CONSTANT_LONG | CONSTANT_DOUBLE => in skip 8 ; i += 1 + case _ => errorBadTag(in.bp - 1) } } } - /** Return the name found at given index. */ - def getName(index: Int): Name = { - if (index <= 0 || len <= index) - errorBadIndex(index) + def recordAtIndex[T <: AnyRef](value: T, idx: Int): T = { + values(idx) = value + value + } - values(index) match { + def firstExpecting(index: Int, expected: Int): Int = { + val start = starts(index) + val first = in.buf(start).toInt + if (first == expected) start + 1 + else this errorBadTag start + } + + /** Return the name found at given index. */ + def getName(index: Int): Name = ( + if (index <= 0 || len <= index) errorBadIndex(index) + else values(index) match { case name: Name => name - case null => - val start = starts(index) - if (in.buf(start).toInt != CONSTANT_UTF8) errorBadTag(start) - val name = newTermName(in.buf, start + 3, in.getChar(start + 1)) - values(index) = name - name + case _ => + val start = firstExpecting(index, CONSTANT_UTF8) + recordAtIndex(newTermName(in.buf, start + 2, in.getChar(start)), index) } - } + ) /** Return the name found at given index in the constant pool, with '/' replaced by '.'. */ def getExternalName(index: Int): Name = { @@ -179,28 +194,23 @@ abstract class ClassfileParser { def getClassSymbol(index: Int): Symbol = { if (index <= 0 || len <= index) errorBadIndex(index) - var c = values(index).asInstanceOf[Symbol] - if (c eq null) { - val start = starts(index) - if (in.buf(start).toInt != CONSTANT_CLASS) errorBadTag(start) - val name = getExternalName(in.getChar(start + 1)) - if (nme.isModuleName(name)) - c = rootMirror.getModule(nme.stripModuleSuffix(name)) - else - c = classNameToSymbol(name) - - values(index) = c + values(index) match { + case sym: Symbol => sym + case _ => + val result = getClassName(index) match { + case name if nme.isModuleName(name) => rootMirror getModuleByName name.dropModule + case name => classNameToSymbol(name) + } + recordAtIndex(result, index) } - c } /** Return the external name of the class info structure found at 'index'. * Use 'getClassSymbol' if the class is sure to be a top-level class. */ def getClassName(index: Int): Name = { - val start = starts(index) - if (in.buf(start).toInt != CONSTANT_CLASS) errorBadTag(start) - getExternalName(in.getChar(start + 1)) + val start = firstExpecting(index, CONSTANT_CLASS) + getExternalName(in getChar start) } /** Return the symbol of the class member at `index`. @@ -226,30 +236,30 @@ abstract class ClassfileParser { val (name0, tpe0) = getNameAndType(in.getChar(start + 3), ownerTpe) debuglog("getMemberSymbol: name and tpe: " + name0 + ": " + tpe0) - forceMangledName(tpe0.typeSymbol.name, false) + forceMangledName(tpe0.typeSymbol.name, module = false) val (name, tpe) = getNameAndType(in.getChar(start + 3), ownerTpe) if (name == nme.MODULE_INSTANCE_FIELD) { val index = in.getChar(start + 1) val name = getExternalName(in.getChar(starts(index) + 1)) //assert(name.endsWith("$"), "Not a module class: " + name) - f = forceMangledName(name dropRight 1, true) + f = forceMangledName(name dropRight 1, module = true) if (f == NoSymbol) - f = rootMirror.getModule(name dropRight 1) + f = rootMirror.getModuleByName(name dropRight 1) } else { - val origName = nme.originalName(name) + val origName = nme.unexpandedName(name) val owner = if (static) ownerTpe.typeSymbol.linkedClassOfClass else ownerTpe.typeSymbol - f = owner.info.findMember(origName, 0, 0, false).suchThat(_.tpe.widen =:= tpe) + f = owner.info.findMember(origName, 0, 0, stableOnly = false).suchThat(_.tpe.widen =:= tpe) if (f == NoSymbol) - f = owner.info.findMember(newTermName(origName + nme.LOCAL_SUFFIX_STRING), 0, 0, false).suchThat(_.tpe =:= tpe) + f = owner.info.findMember(newTermName(origName + nme.LOCAL_SUFFIX_STRING), 0, 0, stableOnly = false).suchThat(_.tpe =:= tpe) if (f == NoSymbol) { // if it's an impl class, try to find it's static member inside the class if (ownerTpe.typeSymbol.isImplClass) { - f = ownerTpe.findMember(origName, 0, 0, false).suchThat(_.tpe =:= tpe) + f = ownerTpe.findMember(origName, 0, 0, stableOnly = false).suchThat(_.tpe =:= tpe) } else { log("Couldn't find " + name + ": " + tpe + " inside: \n" + ownerTpe) f = tpe match { - case MethodType(_, _) => owner.newMethod(name, owner.pos) - case _ => owner.newVariable(name, owner.pos) + case MethodType(_, _) => owner.newMethod(name.toTermName, owner.pos) + case _ => owner.newVariable(name.toTermName, owner.pos) } f setInfo tpe log("created fake member " + f.fullName) @@ -274,94 +284,66 @@ abstract class ClassfileParser { */ private def getNameAndType(index: Int, ownerTpe: Type): (Name, Type) = { if (index <= 0 || len <= index) errorBadIndex(index) - var p = values(index).asInstanceOf[(Name, Type)] - if (p eq null) { - val start = starts(index) - if (in.buf(start).toInt != CONSTANT_NAMEANDTYPE) errorBadTag(start) - val name = getName(in.getChar(start + 1).toInt) - // create a dummy symbol for method types - val dummySym = ownerTpe.typeSymbol.newMethod(name, ownerTpe.typeSymbol.pos) - var tpe = getType(dummySym, in.getChar(start + 3).toInt) - - // fix the return type, which is blindly set to the class currently parsed - if (name == nme.CONSTRUCTOR) - tpe match { - case MethodType(formals, restpe) => - tpe = MethodType(formals, ownerTpe) + values(index) match { + case p: ((Name @unchecked, Type @unchecked)) => p + case _ => + val start = firstExpecting(index, CONSTANT_NAMEANDTYPE) + val name = getName(in.getChar(start).toInt) + // create a dummy symbol for method types + val dummy = ownerTpe.typeSymbol.newMethod(name.toTermName, ownerTpe.typeSymbol.pos) + val tpe = getType(dummy, in.getChar(start + 2).toInt) + // fix the return type, which is blindly set to the class currently parsed + val restpe = tpe match { + case MethodType(formals, _) if name == nme.CONSTRUCTOR => MethodType(formals, ownerTpe) + case _ => tpe } - - p = (name, tpe) + ((name, restpe)) } - p } /** Return the type of a class constant entry. Since * arrays are considered to be class types, they might * appear as entries in 'newarray' or 'cast' opcodes. */ - def getClassOrArrayType(index: Int): Type = { + def getClassOrArrayType(index: Int): Type = ( if (index <= 0 || len <= index) errorBadIndex(index) - val value = values(index) - var c: Type = null - if (value eq null) { - val start = starts(index) - if (in.buf(start).toInt != CONSTANT_CLASS) errorBadTag(start) - val name = getExternalName(in.getChar(start + 1)) - if (name.charAt(0) == ARRAY_TAG) { - c = sigToType(null, name) - values(index) = c - } else { - val sym = classNameToSymbol(name) - /*if (name.endsWith("$")) definitions.getModule(name.subName(0, name.length - 1)) - else if (name.endsWith("$class")) definitions.getModule(name) - else definitions.getClass(name)*/ - values(index) = sym - c = sym.tpe - } - } else c = value match { - case tp: Type => tp - case cls: Symbol => cls.tpe + else values(index) match { + case tp: Type => tp + case cls: Symbol => cls.tpe_* + case _ => + val name = getClassName(index) + name charAt 0 match { + case ARRAY_TAG => recordAtIndex(sigToType(null, name), index) + case _ => recordAtIndex(classNameToSymbol(name), index).tpe_* + } } - c - } - - def getType(index: Int): Type = getType(null, index) - - def getType(sym: Symbol, index: Int): Type = - sigToType(sym, getExternalName(index)) + ) - def getSuperClass(index: Int): Symbol = - if (index == 0) definitions.AnyClass else getClassSymbol(index) + def getType(index: Int): Type = getType(null, index) + def getType(sym: Symbol, index: Int): Type = sigToType(sym, getExternalName(index)) + def getSuperClass(index: Int): Symbol = if (index == 0) AnyClass else getClassSymbol(index) - def getConstant(index: Int): Constant = { + private def createConstant(index: Int): Constant = { + val start = starts(index) + Constant((in.buf(start).toInt: @switch) match { + case CONSTANT_STRING => getName(in.getChar(start + 1).toInt).toString + case CONSTANT_INTEGER => in.getInt(start + 1) + case CONSTANT_FLOAT => in.getFloat(start + 1) + case CONSTANT_LONG => in.getLong(start + 1) + case CONSTANT_DOUBLE => in.getDouble(start + 1) + case CONSTANT_CLASS => getClassOrArrayType(index).typeSymbol.tpe_* // !!! Is this necessary or desirable? + case _ => errorBadTag(start) + }) + } + def getConstant(index: Int): Constant = ( if (index <= 0 || len <= index) errorBadIndex(index) - var value = values(index) - if (value eq null) { - val start = starts(index) - value = (in.buf(start).toInt: @switch) match { - case CONSTANT_STRING => - Constant(getName(in.getChar(start + 1).toInt).toString) - case CONSTANT_INTEGER => - Constant(in.getInt(start + 1)) - case CONSTANT_FLOAT => - Constant(in.getFloat(start + 1)) - case CONSTANT_LONG => - Constant(in.getLong(start + 1)) - case CONSTANT_DOUBLE => - Constant(in.getDouble(start + 1)) - case CONSTANT_CLASS => - getClassOrArrayType(index).typeSymbol - case _ => - errorBadTag(start) - } - values(index) = value - } - value match { - case ct: Constant => ct - case cls: Symbol => Constant(cls.tpe) - case arr: Type => Constant(arr) + else values(index) match { + case const: Constant => const + case sym: Symbol => Constant(sym.tpe_*) + case tpe: Type => Constant(tpe) + case _ => recordAtIndex(createConstant(index), index) } - } + ) private def getSubArray(bytes: Array[Byte]): Array[Byte] = { val decodedLength = ByteCodecs.decode(bytes) @@ -370,46 +352,41 @@ abstract class ClassfileParser { arr } - def getBytes(index: Int): Array[Byte] = { + def getBytes(index: Int): Array[Byte] = ( if (index <= 0 || len <= index) errorBadIndex(index) - var value = values(index).asInstanceOf[Array[Byte]] - if (value eq null) { - val start = starts(index) - if (in.buf(start).toInt != CONSTANT_UTF8) errorBadTag(start) - val len = in.getChar(start + 1) - val bytes = new Array[Byte](len) - System.arraycopy(in.buf, start + 3, bytes, 0, len) - value = getSubArray(bytes) - values(index) = value + else values(index) match { + case xs: Array[Byte] => xs + case _ => + val start = firstExpecting(index, CONSTANT_UTF8) + val len = in getChar start + val bytes = new Array[Byte](len) + System.arraycopy(in.buf, start + 2, bytes, 0, len) + recordAtIndex(getSubArray(bytes), index) } - value - } + ) def getBytes(indices: List[Int]): Array[Byte] = { - assert(!indices.isEmpty, indices) - var value = values(indices.head).asInstanceOf[Array[Byte]] - if (value eq null) { - val bytesBuffer = ArrayBuffer.empty[Byte] - for (index <- indices) { - if (index <= 0 || ConstantPool.this.len <= index) errorBadIndex(index) - val start = starts(index) - if (in.buf(start).toInt != CONSTANT_UTF8) errorBadTag(start) - val len = in.getChar(start + 1) - bytesBuffer ++= in.buf.view(start + 3, start + 3 + len) - } - value = getSubArray(bytesBuffer.toArray) - values(indices.head) = value + val head = indices.head + values(head) match { + case xs: Array[Byte] => xs + case _ => + val arr: Array[Byte] = indices.toArray flatMap { index => + if (index <= 0 || ConstantPool.this.len <= index) errorBadIndex(index) + val start = firstExpecting(index, CONSTANT_UTF8) + val len = in getChar start + in.buf drop start + 2 take len + } + recordAtIndex(getSubArray(arr), head) } - value } /** Throws an exception signaling a bad constant index. */ private def errorBadIndex(index: Int) = - throw new RuntimeException("bad constant pool index: " + index + " at pos: " + in.bp) + abort(s"bad constant pool index: $index at pos: ${in.bp}") /** Throws an exception signaling a bad tag at given address. */ private def errorBadTag(start: Int) = - throw new RuntimeException("bad constant pool tag " + in.buf(start) + " at byte " + start) + abort("bad constant pool tag ${in.buf(start)} at byte $start") } /** Try to force the chain of enclosing classes for the given name. Otherwise @@ -420,9 +397,9 @@ abstract class ClassfileParser { var sym: Symbol = rootMirror.RootClass // was "at flatten.prev" - beforeFlatten { + enteringFlatten { for (part0 <- parts; if !(part0 == ""); part = newTermName(part0)) { - val sym1 = beforeIcode { + val sym1 = enteringIcode { sym.linkedClassOfClass.info sym.info.decl(part.encode) }//.suchThat(module == _.isModule) @@ -453,7 +430,7 @@ abstract class ClassfileParser { ss = name.subName(start, end) sym = owner.info.decls lookup ss if (sym == NoSymbol) { - sym = owner.newPackage(ss) setInfo completer + sym = owner.newPackage(ss.toTermName) setInfo completer sym.moduleClass setInfo completer owner.info.decls enter sym } @@ -468,6 +445,7 @@ abstract class ClassfileParser { sym } } + /** FIXME - we shouldn't be doing ad hoc lookups in the empty package. * The method called "getClassByName" should either return the class or not. */ @@ -487,30 +465,27 @@ abstract class ClassfileParser { catch { case _: FatalError => loadClassSymbol(name) } } - var sawPrivateConstructor = false - def parseClass() { - val jflags = in.nextChar - val isAnnotation = hasAnnotation(jflags) - var sflags = toScalaClassFlags(jflags) - var nameIdx = in.nextChar - currentClass = pool.getClassName(nameIdx) - - /** Parse parents for Java classes. For Scala, return AnyRef, since the real type will be unpickled. - * Updates the read pointer of 'in'. */ + val jflags = readClassFlags() + val sflags = jflags.toScalaFlags + val nameIdx = u2 + currentClass = pool.getClassName(nameIdx) + + /* Parse parents for Java classes. For Scala, return AnyRef, since the real type will be unpickled. + * Updates the read pointer of 'in'. */ def parseParents: List[Type] = { if (isScala) { - in.nextChar // skip superclass - val ifaces = in.nextChar - in.bp += ifaces * 2 // .. and iface count interfaces - List(definitions.AnyRefClass.tpe) // dummy superclass, will be replaced by pickled information + u2 // skip superclass + val ifaces = u2 + in.bp += ifaces * 2 // .. and iface count interfaces + List(AnyRefClass.tpe) // dummy superclass, will be replaced by pickled information } else raiseLoaderLevel { - val superType = if (isAnnotation) { in.nextChar; definitions.AnnotationClass.tpe } - else pool.getSuperClass(in.nextChar).tpe - val ifaceCount = in.nextChar - var ifaces = for (i <- List.range(0, ifaceCount)) yield pool.getSuperClass(in.nextChar).tpe - if (isAnnotation) ifaces = definitions.ClassfileAnnotationClass.tpe :: ifaces + val superType = if (jflags.isAnnotation) { u2; AnnotationClass.tpe } + else pool.getSuperClass(u2).tpe_* + val ifaceCount = u2 + var ifaces = for (i <- List.range(0, ifaceCount)) yield pool.getSuperClass(u2).tpe_* + if (jflags.isAnnotation) ifaces ::= ClassfileAnnotationClass.tpe superType :: ifaces } } @@ -533,31 +508,30 @@ abstract class ClassfileParser { val staticInfo = ClassInfoType(List(), staticScope, moduleClass) if (!isScala && !isScalaRaw) - enterOwnInnerClasses + enterOwnInnerClasses() val curbp = in.bp skipMembers() // fields skipMembers() // methods if (!isScala) { clazz setFlag sflags - importPrivateWithinFromJavaFlags(clazz, jflags) - importPrivateWithinFromJavaFlags(staticModule, jflags) - clazz.setInfo(classInfo) + propagatePackageBoundary(jflags, clazz, staticModule) + clazz setInfo classInfo moduleClass setInfo staticInfo - staticModule.setInfo(moduleClass.tpe) - staticModule.setFlag(JAVA) - staticModule.moduleClass.setFlag(JAVA) + staticModule setInfo moduleClass.tpe + staticModule setFlag JAVA + staticModule.moduleClass setFlag JAVA // attributes now depend on having infos set already parseAttributes(clazz, classInfo) def queueLoad() { in.bp = curbp - 0 until in.nextChar foreach (_ => parseField()) + 0 until u2 foreach (_ => parseField()) sawPrivateConstructor = false - 0 until in.nextChar foreach (_ => parseMethod()) + 0 until u2 foreach (_ => parseMethod()) val needsConstructor = ( !sawPrivateConstructor - && instanceScope.lookup(nme.CONSTRUCTOR) == NoSymbol + && !(instanceScope containsName nme.CONSTRUCTOR) && (sflags & INTERFACE) == 0 ) if (needsConstructor) @@ -588,26 +562,28 @@ abstract class ClassfileParser { } def parseField() { - val jflags = in.nextChar - var sflags = toScalaFieldFlags(jflags) - if ((sflags & PRIVATE) != 0L && !global.settings.optimise.value) { + val jflags = readFieldFlags() + val sflags = jflags.toScalaFlags + + if ((sflags & PRIVATE) != 0L && !optimized) { in.skip(4); skipAttributes() } else { - val name = pool.getName(in.nextChar) - val info = pool.getType(in.nextChar) - val sym = getOwner(jflags).newValue(name, NoPosition, sflags) - val isEnum = (jflags & JAVA_ACC_ENUM) != 0 + val name = readName() + val info = readType() + val sym = ownerForFlags(jflags).newValue(name.toTermName, NoPosition, sflags) + // Note: the info may be overrwritten later with a generic signature + // parsed from SignatureATTR sym setInfo { - if (isEnum) ConstantType(Constant(sym)) + if (jflags.isEnum) ConstantType(Constant(sym)) else info } - importPrivateWithinFromJavaFlags(sym, jflags) + propagatePackageBoundary(jflags, sym) parseAttributes(sym, info) - getScope(jflags).enter(sym) + getScope(jflags) enter sym // sealed java enums - if (isEnum) { + if (jflags.isEnum) { val enumClass = sym.owner.linkedClassOfClass if (!enumClass.isSealed) enumClass setFlag (SEALED | ABSTRACT) @@ -618,26 +594,27 @@ abstract class ClassfileParser { } def parseMethod() { - val jflags = in.nextChar.toInt - var sflags = toScalaMethodFlags(jflags) - if (isPrivate(jflags) && !global.settings.optimise.value) { - val name = pool.getName(in.nextChar) + val jflags = readMethodFlags() + val sflags = jflags.toScalaFlags + if (jflags.isPrivate && !optimized) { + val name = readName() if (name == nme.CONSTRUCTOR) sawPrivateConstructor = true in.skip(2); skipAttributes() - } else { - if ((sflags & PRIVATE) != 0L && global.settings.optimise.value) { + } + else { + if ((sflags & PRIVATE) != 0L && optimized) { in.skip(4); skipAttributes() } else { - val name = pool.getName(in.nextChar) - val sym = getOwner(jflags).newMethod(name, NoPosition, sflags) - var info = pool.getType(sym, (in.nextChar)) + val name = readName() + val sym = ownerForFlags(jflags).newMethod(name.toTermName, NoPosition, sflags) + var info = pool.getType(sym, u2) if (name == nme.CONSTRUCTOR) info match { case MethodType(params, restpe) => // if this is a non-static inner class, remove the explicit outer parameter val newParams = innerClasses getEntry currentClass match { - case Some(entry) if !isScalaRaw && !isStatic(entry.jflags) => + case Some(entry) if !isScalaRaw && !entry.jflags.isStatic => /* About `clazz.owner.isPackage` below: SI-5957 * For every nested java class A$B, there are two symbols in the scala compiler. * 1. created by SymbolLoader, because of the existence of the A$B.class file, owner: package @@ -652,13 +629,15 @@ abstract class ClassfileParser { } info = MethodType(newParams, clazz.tpe) } - sym.setInfo(info) - importPrivateWithinFromJavaFlags(sym, jflags) + // Note: the info may be overrwritten later with a generic signature + // parsed from SignatureATTR + sym setInfo info + propagatePackageBoundary(jflags, sym) parseAttributes(sym, info) - if ((jflags & JAVA_ACC_VARARGS) != 0) { - sym.setInfo(arrayToRepeated(sym.info)) - } - getScope(jflags).enter(sym) + if (jflags.isVarargs) + sym modifyInfo arrayToRepeated + + getScope(jflags) enter sym } } } @@ -678,15 +657,15 @@ abstract class ClassfileParser { def sig2type(tparams: immutable.Map[Name,Symbol], skiptvs: Boolean): Type = { val tag = sig.charAt(index); index += 1 tag match { - case BYTE_TAG => definitions.ByteClass.tpe - case CHAR_TAG => definitions.CharClass.tpe - case DOUBLE_TAG => definitions.DoubleClass.tpe - case FLOAT_TAG => definitions.FloatClass.tpe - case INT_TAG => definitions.IntClass.tpe - case LONG_TAG => definitions.LongClass.tpe - case SHORT_TAG => definitions.ShortClass.tpe - case VOID_TAG => definitions.UnitClass.tpe - case BOOL_TAG => definitions.BooleanClass.tpe + case BYTE_TAG => ByteClass.tpe + case CHAR_TAG => CharClass.tpe + case DOUBLE_TAG => DoubleClass.tpe + case FLOAT_TAG => FloatClass.tpe + case INT_TAG => IntClass.tpe + case LONG_TAG => LongClass.tpe + case SHORT_TAG => ShortClass.tpe + case VOID_TAG => UnitClass.tpe + case BOOL_TAG => BooleanClass.tpe case 'L' => def processInner(tp: Type): Type = tp match { case TypeRef(pre, sym, args) if (!sym.isStatic) => @@ -711,7 +690,7 @@ abstract class ClassfileParser { val tp = sig2type(tparams, skiptvs) // sig2type seems to return AnyClass regardless of the situation: // we don't want Any as a LOWER bound. - if (tp.typeSymbol == definitions.AnyClass) TypeBounds.empty + if (tp.typeSymbol == AnyClass) TypeBounds.empty else TypeBounds.lower(tp) case '*' => TypeBounds.empty } @@ -725,15 +704,14 @@ abstract class ClassfileParser { } accept('>') assert(xs.length > 0, tp) - newExistentialType(existentials.toList, typeRef(pre, classSym, xs.toList)) - } else if (classSym.isMonomorphicType) { - tp - } else { - // raw type - existentially quantify all type parameters - val eparams = typeParamsToExistentials(classSym, classSym.unsafeTypeParams) - val t = typeRef(pre, classSym, eparams.map(_.tpeHK)) - newExistentialType(eparams, t) + logResult("new existential")(newExistentialType(existentials.toList, typeRef(pre, classSym, xs.toList))) } + // isMonomorphicType is false if the info is incomplete, as it usually is here + // so have to check unsafeTypeParams.isEmpty before worrying about raw type case below, + // or we'll create a boatload of needless existentials. + else if (classSym.isMonomorphicType || classSym.unsafeTypeParams.isEmpty) tp + // raw type - existentially quantify all type parameters + else logResult(s"raw type from $classSym")(unsafeClassExistentialType(classSym)) case tp => assert(sig.charAt(index) != '<', s"sig=$sig, index=$index, tp=$tp") tp @@ -741,12 +719,14 @@ abstract class ClassfileParser { val classSym = classNameToSymbol(subName(c => c == ';' || c == '<')) assert(!classSym.isOverloaded, classSym.alternatives) - var tpe = processClassType(processInner(classSym.tpe)) + var tpe = processClassType(processInner(classSym.tpe_*)) while (sig.charAt(index) == '.') { accept('.') val name = subName(c => c == ';' || c == '<' || c == '.').toTypeName val clazz = tpe.member(name) - tpe = processClassType(processInner(clazz.tpe)) + val dummyArgs = Nil // the actual arguments are added in processClassType + val inner = typeRef(pre = tpe, sym = clazz, args = dummyArgs) + tpe = processClassType(inner) } accept(';') tpe @@ -759,11 +739,11 @@ abstract class ClassfileParser { // NOTE that the comparison to Object only works for abstract types bounded by classes that are strict subclasses of Object // if the bound is exactly Object, it will have been converted to Any, and the comparison will fail // see also RestrictJavaArraysMap (when compiling java sources directly) - if (elemtp.typeSymbol.isAbstractType && !(elemtp <:< definitions.ObjectClass.tpe)) { - elemtp = intersectionType(List(elemtp, definitions.ObjectClass.tpe)) + if (elemtp.typeSymbol.isAbstractType && !(elemtp <:< ObjectClass.tpe)) { + elemtp = intersectionType(List(elemtp, ObjectClass.tpe)) } - definitions.arrayType(elemtp) + arrayType(elemtp) case '(' => // we need a method symbol. given in line 486 by calling getType(methodSym, ..) assert(sym ne null, sig) @@ -774,14 +754,14 @@ abstract class ClassfileParser { index += 1 val restype = if (sym != null && sym.isClassConstructor) { accept('V') - clazz.tpe + clazz.tpe_* } else sig2type(tparams, skiptvs) JavaMethodType(sym.newSyntheticValueParams(paramtypes.toList), restype) case 'T' => val n = subName(';'.==).toTypeName index += 1 - if (skiptvs) definitions.AnyClass.tpe + if (skiptvs) AnyClass.tpe else tparams(n).typeConstructor } } // sig2type(tparams, skiptvs) @@ -806,14 +786,14 @@ abstract class ClassfileParser { val tpname = subName(':'.==).toTypeName val s = sym.newTypeParameter(tpname) tparams = tparams + (tpname -> s) - sig2typeBounds(tparams, true) + sig2typeBounds(tparams, skiptvs = true) newTParams += s } index = start while (sig.charAt(index) != '>') { val tpname = subName(':'.==).toTypeName val s = tparams(tpname) - s.setInfo(sig2typeBounds(tparams, false)) + s.setInfo(sig2typeBounds(tparams, skiptvs = false)) } accept('>') } @@ -822,36 +802,32 @@ abstract class ClassfileParser { sym.setInfo(new TypeParamsType(ownTypeParams)) val tpe = if ((sym eq null) || !sym.isClass) - sig2type(tparams, false) + sig2type(tparams, skiptvs = false) else { classTParams = tparams val parents = new ListBuffer[Type]() while (index < end) { - parents += sig2type(tparams, false) // here the variance doesnt'matter + parents += sig2type(tparams, skiptvs = false) // here the variance doesnt'matter } ClassInfoType(parents.toList, instanceScope, sym) } GenPolyType(ownTypeParams, tpe) } // sigToType - class TypeParamsType(override val typeParams: List[Symbol]) extends LazyType with FlagAgnosticCompleter { - override def complete(sym: Symbol) { throw new AssertionError("cyclic type dereferencing") } - } - def parseAttributes(sym: Symbol, symtype: Type) { def convertTo(c: Constant, pt: Type): Constant = { - if (pt.typeSymbol == definitions.BooleanClass && c.tag == IntTag) + if (pt.typeSymbol == BooleanClass && c.tag == IntTag) Constant(c.value != 0) else c convertTo pt } def parseAttribute() { - val attrName = pool.getName(in.nextChar).toTypeName - val attrLen = in.nextInt + val attrName = readTypeName() + val attrLen = u4 attrName match { case tpnme.SignatureATTR => if (!isScala && !isScalaRaw) { - val sig = pool.getExternalName(in.nextChar) + val sig = pool.getExternalName(u2) val newType = sigToType(sym, sig) sym.setInfo(newType) } @@ -860,14 +836,14 @@ abstract class ClassfileParser { sym.setFlag(SYNTHETIC | ARTIFACT) in.skip(attrLen) case tpnme.BridgeATTR => - sym.setFlag(BRIDGE) + sym.setFlag(BRIDGE | ARTIFACT) in.skip(attrLen) case tpnme.DeprecatedATTR => val arg = Literal(Constant("see corresponding Javadoc for more information.")) - sym.addAnnotation(definitions.DeprecatedAttr, arg, Literal(Constant(""))) + sym.addAnnotation(DeprecatedAttr, arg, Literal(Constant(""))) in.skip(attrLen) case tpnme.ConstantValueATTR => - val c = pool.getConstant(in.nextChar) + val c = pool.getConstant(u2) val c1 = convertTo(c, symtype) if (c1 ne null) sym.setInfo(ConstantType(c1)) else debugwarn(s"failure to convert $c to $symtype") @@ -881,7 +857,7 @@ abstract class ClassfileParser { isScalaRaw = true // Attribute on methods of java annotation classes when that method has a default case tpnme.AnnotationDefaultATTR => - sym.addAnnotation(definitions.AnnotationDefaultAttr) + sym.addAnnotation(AnnotationDefaultAttr) in.skip(attrLen) // Java annotations on classes / methods / fields with RetentionPolicy.RUNTIME case tpnme.RuntimeAnnotationATTR => @@ -911,7 +887,7 @@ abstract class ClassfileParser { parseExceptions(attrLen) case tpnme.SourceFileATTR => - val srcfileLeaf = pool.getName(in.nextChar).toString.trim + val srcfileLeaf = readName().toString.trim val srcpath = sym.enclosingPackage match { case NoSymbol => srcfileLeaf case rootMirror.EmptyPackage => srcfileLeaf @@ -930,8 +906,8 @@ abstract class ClassfileParser { } def parseAnnotArg: Option[ClassfileAnnotArg] = { - val tag = in.nextByte.toChar - val index = in.nextChar + val tag = u1 + val index = u2 tag match { case STRING_TAG => Some(LiteralAnnotArg(Constant(pool.getName(index).toString))) @@ -942,7 +918,7 @@ abstract class ClassfileParser { Some(LiteralAnnotArg(Constant(pool.getType(index)))) case ENUM_TAG => val t = pool.getType(index) - val n = pool.getName(in.nextChar) + val n = readName() val s = t.typeSymbol.companionModule.info.decls.lookup(n) assert(s != NoSymbol, t) Some(LiteralAnnotArg(Constant(s))) @@ -962,43 +938,43 @@ abstract class ClassfileParser { } def parseScalaSigBytes: Option[ScalaSigBytes] = { - val tag = in.nextByte.toChar + val tag = u1 assert(tag == STRING_TAG, tag) - Some(ScalaSigBytes(pool getBytes in.nextChar)) + Some(ScalaSigBytes(pool getBytes u2)) } def parseScalaLongSigBytes: Option[ScalaSigBytes] = { - val tag = in.nextByte.toChar + val tag = u1 assert(tag == ARRAY_TAG, tag) - val stringCount = in.nextChar + val stringCount = u2 val entries = for (i <- 0 until stringCount) yield { - val stag = in.nextByte.toChar + val stag = u1 assert(stag == STRING_TAG, stag) - in.nextChar.toInt + u2.toInt } Some(ScalaSigBytes(pool.getBytes(entries.toList))) } - /** Parse and return a single annotation. If it is malformed, - * return None. + /* Parse and return a single annotation. If it is malformed, + * return None. */ def parseAnnotation(attrNameIndex: Char): Option[AnnotationInfo] = try { val attrType = pool.getType(attrNameIndex) - val nargs = in.nextChar + val nargs = u2 val nvpairs = new ListBuffer[(Name, ClassfileAnnotArg)] var hasError = false for (i <- 0 until nargs) { - val name = pool.getName(in.nextChar) + val name = readName() // The "bytes: String" argument of the ScalaSignature attribute is parsed specially so that it is // available as an array of bytes (the pickled Scala signature) instead of as a string. The pickled signature // is encoded as a string because of limitations in the Java class file format. - if ((attrType == definitions.ScalaSignatureAnnotation.tpe) && (name == nme.bytes)) + if ((attrType == ScalaSignatureAnnotation.tpe) && (name == nme.bytes)) parseScalaSigBytes match { case Some(c) => nvpairs += ((name, c)) case None => hasError = true } - else if ((attrType == definitions.ScalaLongSignatureAnnotation.tpe) && (name == nme.bytes)) + else if ((attrType == ScalaLongSignatureAnnotation.tpe) && (name == nme.bytes)) parseScalaLongSigBytes match { case Some(c) => nvpairs += ((name, c)) case None => hasError = true @@ -1023,20 +999,20 @@ abstract class ClassfileParser { // with a `FatalError` exception, handled above. Here you'd end up after a NPE (for example), // and that should never be swallowed silently. warning(s"Caught: $ex while parsing annotations in ${in.file}") - if (settings.debug.value) ex.printStackTrace() + if (settings.debug) ex.printStackTrace() None // ignore malformed annotations } - /** + /* * Parse the "Exceptions" attribute which denotes the exceptions * thrown by a method. */ def parseExceptions(len: Int) { - val nClasses = in.nextChar + val nClasses = u2 for (n <- 0 until nClasses) { // FIXME: this performs an equivalent of getExceptionTypes instead of getGenericExceptionTypes (SI-7065) - val cls = pool.getClassSymbol(in.nextChar.toInt) + val cls = pool.getClassSymbol(u2) // we call initialize due to the fact that we call Symbol.isMonomorphicType in addThrowsAnnotation // and that method requires Symbol to be forced to give the right answers, see SI-7107 for details cls.initialize @@ -1044,16 +1020,16 @@ abstract class ClassfileParser { } } - /** Parse a sequence of annotations and attaches them to the - * current symbol sym, except for the ScalaSignature annotation that it returns, if it is available. */ + /* Parse a sequence of annotations and attaches them to the + * current symbol sym, except for the ScalaSignature annotation that it returns, if it is available. */ def parseAnnotations(len: Int): Option[AnnotationInfo] = { - val nAttr = in.nextChar + val nAttr = u2 var scalaSigAnnot: Option[AnnotationInfo] = None for (n <- 0 until nAttr) - parseAnnotation(in.nextChar) match { - case Some(scalaSig) if (scalaSig.atp == definitions.ScalaSignatureAnnotation.tpe) => + parseAnnotation(u2) match { + case Some(scalaSig) if (scalaSig.atp == ScalaSignatureAnnotation.tpe) => scalaSigAnnot = Some(scalaSig) - case Some(scalaSig) if (scalaSig.atp == definitions.ScalaLongSignatureAnnotation.tpe) => + case Some(scalaSig) if (scalaSig.atp == ScalaLongSignatureAnnotation.tpe) => scalaSigAnnot = Some(scalaSig) case Some(annot) => sym.addAnnotation(annot) @@ -1063,7 +1039,7 @@ abstract class ClassfileParser { } // begin parseAttributes - for (i <- 0 until in.nextChar) parseAttribute() + for (i <- 0 until u2) parseAttribute() } /** Enter own inner classes in the right scope. It needs the scopes to be set up, @@ -1073,11 +1049,12 @@ abstract class ClassfileParser { def className(name: Name): Name = name.subName(name.lastPos('.') + 1, name.length) - def enterClassAndModule(entry: InnerClassEntry, file: AbstractFile, jflags: Int) { + def enterClassAndModule(entry: InnerClassEntry, file: AbstractFile) { + def jflags = entry.jflags val completer = new global.loaders.ClassfileLoader(file) val name = entry.originalName - var sflags = toScalaClassFlags(jflags) - val owner = getOwner(jflags) + val sflags = jflags.toScalaFlags + val owner = ownerForFlags(jflags) val scope = getScope(jflags) val innerClass = owner.newClass(name.toTypeName, NoPosition, sflags) setInfo completer val innerModule = owner.newModule(name.toTermName, NoPosition, sflags) setInfo completer @@ -1106,7 +1083,7 @@ abstract class ClassfileParser { val file = global.classPath.findSourceFile(entry.externalName.toString) getOrElse { throw new AssertionError(entry.externalName) } - enterClassAndModule(entry, file, entry.jflags) + enterClassAndModule(entry, file) } } } @@ -1119,26 +1096,27 @@ abstract class ClassfileParser { skipSuperclasses() skipMembers() // fields skipMembers() // methods - val attrs = in.nextChar + val attrs = u2 for (i <- 0 until attrs) { - val attrName = pool.getName(in.nextChar).toTypeName - val attrLen = in.nextInt + val attrName = readTypeName() + val attrLen = u4 attrName match { case tpnme.SignatureATTR => in.skip(attrLen) case tpnme.ScalaSignatureATTR => isScala = true val pbuf = new PickleBuffer(in.buf, in.bp, in.bp + attrLen) - pbuf.readNat; pbuf.readNat; + pbuf.readNat(); pbuf.readNat() if (pbuf.readNat == 0) // a scala signature attribute with no entries means that the actual scala signature isScalaAnnot = true // is in a ScalaSignature annotation. in.skip(attrLen) case tpnme.ScalaATTR => isScalaRaw = true case tpnme.InnerClassesATTR if !isScala => - val entries = in.nextChar.toInt + val entries = u2 for (i <- 0 until entries) { - val innerIndex, outerIndex, nameIndex, jflags = in.nextChar.toInt + val innerIndex, outerIndex, nameIndex = u2 + val jflags = readInnerClassFlags() if (innerIndex != 0 && outerIndex != 0 && nameIndex != 0) innerClasses add InnerClassEntry(innerIndex, outerIndex, nameIndex, jflags) } @@ -1150,31 +1128,19 @@ abstract class ClassfileParser { } /** An entry in the InnerClasses attribute of this class file. */ - case class InnerClassEntry(external: Int, outer: Int, name: Int, jflags: Int) { + case class InnerClassEntry(external: Int, outer: Int, name: Int, jflags: JavaAccFlags) { def externalName = pool getClassName external def outerName = pool getClassName outer def originalName = pool getName name - def isStatic = ClassfileParser.this.isStatic(jflags) def isModule = originalName.isTermName - def scope = if (isStatic) staticScope else instanceScope - def enclosing = if (isStatic) enclModule else enclClass + def scope = if (jflags.isStatic) staticScope else instanceScope + def enclosing = if (jflags.isStatic) enclModule else enclClass // The name of the outer class, without its trailing $ if it has one. private def strippedOuter = nme stripModuleSuffix outerName private def isInner = innerClasses contains strippedOuter private def enclClass = if (isInner) innerClasses innerSymbol strippedOuter else classNameToSymbol(strippedOuter) private def enclModule = enclClass.companionModule - - private def staticWord = if (isStatic) "static " else "" - override def toString = s"$staticWord$originalName in $outerName ($externalName)" - } - - /** Return the Symbol of the top level class enclosing `name`, - * or the symbol of `name` itself if no enclosing classes are found. - */ - def topLevelClass(name: Name): Symbol = innerClasses getEntry name match { - case Some(entry) => topLevelClass(entry.outerName) - case _ => classNameToSymbol(name) } /** Return the class symbol for the given name. It looks it up in its outer class. @@ -1202,7 +1168,7 @@ abstract class ClassfileParser { // if loading during initialization of `definitions` typerPhase is not yet set. // in that case we simply load the member at the current phase @inline private def enteringTyperIfPossible(body: => Symbol): Symbol = - if (currentRun.typerPhase eq null) body else beforeTyper(body) + if (currentRun.typerPhase eq null) body else enteringTyper(body) private def innerSymbol(entry: InnerClassEntry): Symbol = { val name = entry.originalName.toTypeName @@ -1212,7 +1178,7 @@ abstract class ClassfileParser { else enclosing.info member name ) enteringTyperIfPossible(getMember) - /** There used to be an assertion that this result is not NoSymbol; changing it to an error + /* There used to be an assertion that this result is not NoSymbol; changing it to an error * revealed it had been going off all the time, but has been swallowed by a catch t: Throwable * in Repository.scala. Since it has been accomplishing nothing except misleading anyone who * thought it wasn't triggering, I removed it entirely. @@ -1220,6 +1186,9 @@ abstract class ClassfileParser { } } + class TypeParamsType(override val typeParams: List[Symbol]) extends LazyType with FlagAgnosticCompleter { + override def complete(sym: Symbol) { throw new AssertionError("cyclic type dereferencing") } + } class LazyAliasType(alias: Symbol) extends LazyType with FlagAgnosticCompleter { override def complete(sym: Symbol) { sym setInfo createFromClonedSymbols(alias.initialize.typeParams, alias.tpe)(typeFun) @@ -1227,32 +1196,29 @@ abstract class ClassfileParser { } def skipAttributes() { - val attrCount = in.nextChar - for (i <- 0 until attrCount) { - in.skip(2); in.skip(in.nextInt) + var attrCount: Int = u2 + while (attrCount > 0) { + in skip 2 + in skip u4 + attrCount -= 1 } } def skipMembers() { - val memberCount = in.nextChar - for (i <- 0 until memberCount) { - in.skip(6); skipAttributes() + var memberCount: Int = u2 + while (memberCount > 0) { + in skip 6 + skipAttributes() + memberCount -= 1 } } def skipSuperclasses() { in.skip(2) // superclass - val ifaces = in.nextChar + val ifaces = u2 in.skip(2 * ifaces) } - protected def getOwner(flags: Int): Symbol = - if (isStatic(flags)) moduleClass else clazz - - protected def getScope(flags: Int): Scope = - if (isStatic(flags)) staticScope else instanceScope - - private def isPrivate(flags: Int) = (flags & JAVA_ACC_PRIVATE) != 0 - private def isStatic(flags: Int) = (flags & JAVA_ACC_STATIC) != 0 - private def hasAnnotation(flags: Int) = (flags & JAVA_ACC_ANNOTATION) != 0 + protected def getScope(flags: JavaAccFlags): Scope = + if (flags.isStatic) staticScope else instanceScope } diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala index c304c18c4f..52ebb3b0a2 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala @@ -3,15 +3,15 @@ * @author Iulian Dragos */ -package scala.tools.nsc +package scala +package tools.nsc package symtab package classfile import scala.collection.{ mutable, immutable } import mutable.ListBuffer -import backend.icode._ import ClassfileConstants._ -import scala.reflect.internal.Flags._ +import scala.reflect.internal.JavaAccFlags /** ICode reader from Java bytecode. * @@ -33,7 +33,6 @@ abstract class ICodeReader extends ClassfileParser { * for non-static members. */ def readClass(cls: Symbol): (IClass, IClass) = { - var classFile: io.AbstractFile = null; cls.info // ensure accurate type information isScalaModule = cls.isModule && !cls.isJavaDefined @@ -48,58 +47,55 @@ abstract class ICodeReader extends ClassfileParser { (staticCode, instanceCode) } - /** If we're parsing a scala module, the owner of members is always - * the module symbol. - */ - override def getOwner(jflags: Int): Symbol = - if (isScalaModule) this.staticModule - else super.getOwner(jflags) - override def parseClass() { this.instanceCode = new IClass(clazz) this.staticCode = new IClass(staticModule) - val jflags = in.nextChar - val isAttribute = (jflags & JAVA_ACC_ANNOTATION) != 0 - val sflags = toScalaClassFlags(jflags) // what, this is never used?? - val c = pool getClassSymbol in.nextChar + u2 + pool getClassSymbol u2 parseInnerClasses() in.skip(2) // super class - in.skip(2 * in.nextChar) // interfaces - val fieldCount = in.nextChar + in.skip(2 * u2) // interfaces + val fieldCount = u2 for (i <- 0 until fieldCount) parseField() - val methodCount = in.nextChar - for (i <- 0 until methodCount) parseMethod(); + val methodCount = u2 + for (i <- 0 until methodCount) parseMethod() instanceCode.methods = instanceCode.methods.reverse staticCode.methods = staticCode.methods.reverse } override def parseField() { - val (jflags, sym) = parseMember(true) + val (jflags, sym) = parseMember(field = true) getCode(jflags) addField new IField(sym) skipAttributes() } - private def parseMember(field: Boolean): (Int, Symbol) = { - val jflags = in.nextChar - val name = pool getName in.nextChar - val owner = getOwner(jflags) - val dummySym = owner.newMethod(name, owner.pos, toScalaMethodFlags(jflags)) + private def parseMember(field: Boolean): (JavaAccFlags, Symbol) = { + val jflags = JavaAccFlags(u2) + val name = pool getName u2 + /* If we're parsing a scala module, the owner of members is always + * the module symbol. + */ + val owner = ( + if (isScalaModule) staticModule + else if (jflags.isStatic) moduleClass + else clazz + ) + val dummySym = owner.newMethod(name.toTermName, owner.pos, jflags.toScalaFlags) try { - val ch = in.nextChar + val ch = u2 val tpe = pool.getType(dummySym, ch) if ("<clinit>" == name.toString) (jflags, NoSymbol) else { - val owner = getOwner(jflags) - var sym = owner.info.findMember(name, 0, 0, false).suchThat(old => sameType(old.tpe, tpe)) + var sym = owner.info.findMember(name, 0, 0, stableOnly = false).suchThat(old => sameType(old.tpe, tpe)) if (sym == NoSymbol) - sym = owner.info.findMember(newTermName(name + nme.LOCAL_SUFFIX_STRING), 0, 0, false).suchThat(_.tpe =:= tpe) + sym = owner.info.findMember(newTermName(name + nme.LOCAL_SUFFIX_STRING), 0, 0, stableOnly = false).suchThat(_.tpe =:= tpe) if (sym == NoSymbol) { - sym = if (field) owner.newValue(name, owner.pos, toScalaFieldFlags(jflags)) else dummySym + sym = if (field) owner.newValue(name.toTermName, owner.pos, jflags.toScalaFlags) else dummySym sym setInfoAndEnter tpe log(s"ICodeReader could not locate ${name.decode} in $owner. Created ${sym.defString}.") } @@ -124,31 +120,31 @@ abstract class ICodeReader extends ClassfileParser { } override def parseMethod() { - val (jflags, sym) = parseMember(false) - var beginning = in.bp + val (jflags, sym) = parseMember(field = false) + val beginning = in.bp try { if (sym != NoSymbol) { this.method = new IMethod(sym) this.method.returnType = toTypeKind(sym.tpe.resultType) getCode(jflags).addMethod(this.method) - if ((jflags & JAVA_ACC_NATIVE) != 0) + if (jflags.isNative) this.method.native = true - val attributeCount = in.nextChar + val attributeCount = u2 for (i <- 0 until attributeCount) parseAttribute() } else { - debuglog("Skipping non-existent method."); - skipAttributes(); + debuglog("Skipping non-existent method.") + skipAttributes() } } catch { case e: MissingRequirementError => - in.bp = beginning; skipAttributes - debuglog("Skipping non-existent method. " + e.msg); + in.bp = beginning; skipAttributes() + debuglog("Skipping non-existent method. " + e.msg) } } def parseAttribute() { - val attrName = pool.getName(in.nextChar).toTypeName - val attrLen = in.nextInt + val attrName = pool.getName(u2).toTypeName + val attrLen = u4 attrName match { case tpnme.CodeATTR => parseByteCode() @@ -169,12 +165,12 @@ abstract class ICodeReader extends ClassfileParser { rootMirror.getClassByName(name) } else if (nme.isModuleName(name)) { - val strippedName = nme.stripModuleSuffix(name) - forceMangledName(newTermName(strippedName.decode), true) orElse rootMirror.getModule(strippedName) + val strippedName = name.dropModule + forceMangledName(newTermName(strippedName.decode), module = true) orElse rootMirror.getModuleByName(strippedName) } else { - forceMangledName(name, false) - afterFlatten(rootMirror.getClassByName(name.toTypeName)) + forceMangledName(name, module = false) + exitingFlatten(rootMirror.getClassByName(name.toTypeName)) } if (sym.isModule) sym.moduleClass @@ -192,9 +188,9 @@ abstract class ICodeReader extends ClassfileParser { /** Parse java bytecode into ICode */ def parseByteCode() { - maxStack = in.nextChar - maxLocals = in.nextChar - val codeLength = in.nextInt + maxStack = u2 + maxLocals = u2 + val codeLength = u4 val code = new LinearCode def parseInstruction() { @@ -202,27 +198,26 @@ abstract class ICodeReader extends ClassfileParser { import code._ var size = 1 // instruction size - /** Parse 16 bit jump target. */ + /* Parse 16 bit jump target. */ def parseJumpTarget = { size += 2 - val offset = in.nextChar.toShort + val offset = u2.toShort val target = pc + offset assert(target >= 0 && target < codeLength, "Illegal jump target: " + target) target } - /** Parse 32 bit jump target. */ + /* Parse 32 bit jump target. */ def parseJumpTargetW: Int = { size += 4 - val offset = in.nextInt + val offset = u4 val target = pc + offset assert(target >= 0 && target < codeLength, "Illegal jump target: " + target + "pc: " + pc + " offset: " + offset) target } - val instr = toUnsignedByte(in.nextByte) - instr match { - case JVM.nop => parseInstruction + u1 match { + case JVM.nop => parseInstruction() case JVM.aconst_null => code emit CONSTANT(Constant(null)) case JVM.iconst_m1 => code emit CONSTANT(Constant(-1)) case JVM.iconst_0 => code emit CONSTANT(Constant(0)) @@ -240,21 +235,21 @@ abstract class ICodeReader extends ClassfileParser { case JVM.dconst_0 => code emit CONSTANT(Constant(0.0)) case JVM.dconst_1 => code emit CONSTANT(Constant(1.0)) - case JVM.bipush => code.emit(CONSTANT(Constant(in.nextByte))); size += 1 - case JVM.sipush => code.emit(CONSTANT(Constant(in.nextChar))); size += 2 - case JVM.ldc => code.emit(CONSTANT(pool.getConstant(toUnsignedByte(in.nextByte)))); size += 1 - case JVM.ldc_w => code.emit(CONSTANT(pool.getConstant(in.nextChar))); size += 2 - case JVM.ldc2_w => code.emit(CONSTANT(pool.getConstant(in.nextChar))); size += 2 - case JVM.iload => code.emit(LOAD_LOCAL(code.getLocal(in.nextByte, INT))); size += 1 - case JVM.lload => code.emit(LOAD_LOCAL(code.getLocal(in.nextByte, LONG))); size += 1 - case JVM.fload => code.emit(LOAD_LOCAL(code.getLocal(in.nextByte, FLOAT))); size += 1 - case JVM.dload => code.emit(LOAD_LOCAL(code.getLocal(in.nextByte, DOUBLE))); size += 1 + case JVM.bipush => code.emit(CONSTANT(Constant(u1))); size += 1 + case JVM.sipush => code.emit(CONSTANT(Constant(u2))); size += 2 + case JVM.ldc => code.emit(CONSTANT(pool.getConstant(u1))); size += 1 + case JVM.ldc_w => code.emit(CONSTANT(pool.getConstant(u2))); size += 2 + case JVM.ldc2_w => code.emit(CONSTANT(pool.getConstant(u2))); size += 2 + case JVM.iload => code.emit(LOAD_LOCAL(code.getLocal(u1, INT))); size += 1 + case JVM.lload => code.emit(LOAD_LOCAL(code.getLocal(u1, LONG))); size += 1 + case JVM.fload => code.emit(LOAD_LOCAL(code.getLocal(u1, FLOAT))); size += 1 + case JVM.dload => code.emit(LOAD_LOCAL(code.getLocal(u1, DOUBLE))); size += 1 case JVM.aload => - val local = in.nextByte.toInt; size += 1 + val local = u1.toInt; size += 1 if (local == 0 && !method.isStatic) - code.emit(THIS(method.symbol.owner)); + code.emit(THIS(method.symbol.owner)) else - code.emit(LOAD_LOCAL(code.getLocal(local, ObjectReference))); + code.emit(LOAD_LOCAL(code.getLocal(local, ObjectReference))) case JVM.iload_0 => code.emit(LOAD_LOCAL(code.getLocal(0, INT))) case JVM.iload_1 => code.emit(LOAD_LOCAL(code.getLocal(1, INT))) @@ -274,9 +269,9 @@ abstract class ICodeReader extends ClassfileParser { case JVM.dload_3 => code.emit(LOAD_LOCAL(code.getLocal(3, DOUBLE))) case JVM.aload_0 => if (!method.isStatic) - code.emit(THIS(method.symbol.owner)); + code.emit(THIS(method.symbol.owner)) else - code.emit(LOAD_LOCAL(code.getLocal(0, ObjectReference))); + code.emit(LOAD_LOCAL(code.getLocal(0, ObjectReference))) case JVM.aload_1 => code.emit(LOAD_LOCAL(code.getLocal(1, ObjectReference))) case JVM.aload_2 => code.emit(LOAD_LOCAL(code.getLocal(2, ObjectReference))) case JVM.aload_3 => code.emit(LOAD_LOCAL(code.getLocal(3, ObjectReference))) @@ -290,11 +285,11 @@ abstract class ICodeReader extends ClassfileParser { case JVM.caload => code.emit(LOAD_ARRAY_ITEM(CHAR)) case JVM.saload => code.emit(LOAD_ARRAY_ITEM(SHORT)) - case JVM.istore => code.emit(STORE_LOCAL(code.getLocal(in.nextByte, INT))); size += 1 - case JVM.lstore => code.emit(STORE_LOCAL(code.getLocal(in.nextByte, LONG))); size += 1 - case JVM.fstore => code.emit(STORE_LOCAL(code.getLocal(in.nextByte, FLOAT))); size += 1 - case JVM.dstore => code.emit(STORE_LOCAL(code.getLocal(in.nextByte, DOUBLE))); size += 1 - case JVM.astore => code.emit(STORE_LOCAL(code.getLocal(in.nextByte, ObjectReference))); size += 1 + case JVM.istore => code.emit(STORE_LOCAL(code.getLocal(u1, INT))); size += 1 + case JVM.lstore => code.emit(STORE_LOCAL(code.getLocal(u1, LONG))); size += 1 + case JVM.fstore => code.emit(STORE_LOCAL(code.getLocal(u1, FLOAT))); size += 1 + case JVM.dstore => code.emit(STORE_LOCAL(code.getLocal(u1, DOUBLE))); size += 1 + case JVM.astore => code.emit(STORE_LOCAL(code.getLocal(u1, ObjectReference))); size += 1 case JVM.istore_0 => code.emit(STORE_LOCAL(code.getLocal(0, INT))) case JVM.istore_1 => code.emit(STORE_LOCAL(code.getLocal(1, INT))) case JVM.istore_2 => code.emit(STORE_LOCAL(code.getLocal(2, INT))) @@ -378,9 +373,9 @@ abstract class ICodeReader extends ClassfileParser { case JVM.lxor => code.emit(CALL_PRIMITIVE(Logical(XOR, LONG))) case JVM.iinc => size += 2 - val local = code.getLocal(in.nextByte, INT) + val local = code.getLocal(u1, INT) code.emit(LOAD_LOCAL(local)) - code.emit(CONSTANT(Constant(in.nextByte))) + code.emit(CONSTANT(Constant(u1))) code.emit(CALL_PRIMITIVE(Arithmetic(ADD, INT))) code.emit(STORE_LOCAL(local)) @@ -430,14 +425,14 @@ abstract class ICodeReader extends ClassfileParser { size += padding in.bp += padding assert((pc + size % 4) != 0, pc) -/* var byte1 = in.nextByte; size += 1; - while (byte1 == 0) { byte1 = in.nextByte; size += 1; } - val default = byte1 << 24 | in.nextByte << 16 | in.nextByte << 8 | in.nextByte; +/* var byte1 = u1; size += 1; + while (byte1 == 0) { byte1 = u1; size += 1; } + val default = byte1 << 24 | u1 << 16 | u1 << 8 | u1; size = size + 3 */ - val default = pc + in.nextInt; size += 4 - val low = in.nextInt - val high = in.nextInt + val default = pc + u4; size += 4 + val low = u4 + val high = u4 size += 8 assert(low <= high, "Value low not <= high for tableswitch.") @@ -450,13 +445,13 @@ abstract class ICodeReader extends ClassfileParser { size += padding in.bp += padding assert((pc + size % 4) != 0, pc) - val default = pc + in.nextInt; size += 4 - val npairs = in.nextInt; size += 4 + val default = pc + u4; size += 4 + val npairs = u4; size += 4 var tags: List[List[Int]] = Nil var targets: List[Int] = Nil var i = 0 while (i < npairs) { - tags = List(in.nextInt) :: tags; size += 4 + tags = List(u4) :: tags; size += 4 targets = parseJumpTargetW :: targets; // parseJumpTargetW updates 'size' itself i += 1 } @@ -471,41 +466,41 @@ abstract class ICodeReader extends ClassfileParser { case JVM.return_ => code.emit(RETURN(UNIT)) case JVM.getstatic => - val field = pool.getMemberSymbol(in.nextChar, true); size += 2 + val field = pool.getMemberSymbol(u2, static = true); size += 2 if (field.hasModuleFlag) code emit LOAD_MODULE(field) else - code emit LOAD_FIELD(field, true) + code emit LOAD_FIELD(field, isStatic = true) case JVM.putstatic => - val field = pool.getMemberSymbol(in.nextChar, true); size += 2 - code.emit(STORE_FIELD(field, true)) + val field = pool.getMemberSymbol(u2, static = true); size += 2 + code.emit(STORE_FIELD(field, isStatic = true)) case JVM.getfield => - val field = pool.getMemberSymbol(in.nextChar, false); size += 2 - code.emit(LOAD_FIELD(field, false)) + val field = pool.getMemberSymbol(u2, static = false); size += 2 + code.emit(LOAD_FIELD(field, isStatic = false)) case JVM.putfield => - val field = pool.getMemberSymbol(in.nextChar, false); size += 2 - code.emit(STORE_FIELD(field, false)) + val field = pool.getMemberSymbol(u2, static = false); size += 2 + code.emit(STORE_FIELD(field, isStatic = false)) case JVM.invokevirtual => - val m = pool.getMemberSymbol(in.nextChar, false); size += 2 + val m = pool.getMemberSymbol(u2, static = false); size += 2 code.emit(CALL_METHOD(m, Dynamic)) case JVM.invokeinterface => - val m = pool.getMemberSymbol(in.nextChar, false); size += 4 + val m = pool.getMemberSymbol(u2, static = false); size += 4 in.skip(2) code.emit(CALL_METHOD(m, Dynamic)) case JVM.invokespecial => - val m = pool.getMemberSymbol(in.nextChar, false); size += 2 - val style = if (m.name == nme.CONSTRUCTOR || m.isPrivate) Static(true) - else SuperCall(m.owner.name); + val m = pool.getMemberSymbol(u2, static = false); size += 2 + val style = if (m.name == nme.CONSTRUCTOR || m.isPrivate) Static(onInstance = true) + else SuperCall(m.owner.name) code.emit(CALL_METHOD(m, style)) case JVM.invokestatic => - val m = pool.getMemberSymbol(in.nextChar, true); size += 2 + val m = pool.getMemberSymbol(u2, static = true); size += 2 if (isBox(m)) code.emit(BOX(toTypeKind(m.info.paramTypes.head))) else if (isUnbox(m)) code.emit(UNBOX(toTypeKind(m.info.resultType))) else - code.emit(CALL_METHOD(m, Static(false))) + code.emit(CALL_METHOD(m, Static(onInstance = false))) case JVM.invokedynamic => // TODO, this is just a place holder. A real implementation must parse the class constant entry debuglog("Found JVM invokedynamic instructionm, inserting place holder ICode INVOKE_DYNAMIC.") @@ -515,10 +510,10 @@ abstract class ICodeReader extends ClassfileParser { code.emit(INVOKE_DYNAMIC(poolEntry)) case JVM.new_ => - code.emit(NEW(REFERENCE(pool.getClassSymbol(in.nextChar)))) + code.emit(NEW(REFERENCE(pool.getClassSymbol(u2)))) size += 2 case JVM.newarray => - val kind = in.nextByte match { + val kind = u1 match { case T_BOOLEAN => BOOL case T_CHAR => CHAR case T_FLOAT => FLOAT @@ -532,35 +527,35 @@ abstract class ICodeReader extends ClassfileParser { code.emit(CREATE_ARRAY(kind, 1)) case JVM.anewarray => - val tpe = pool.getClassOrArrayType(in.nextChar); size += 2 + val tpe = pool.getClassOrArrayType(u2); size += 2 code.emit(CREATE_ARRAY(toTypeKind(tpe), 1)) case JVM.arraylength => code.emit(CALL_PRIMITIVE(ArrayLength(ObjectReference))); // the kind does not matter case JVM.athrow => code.emit(THROW(definitions.ThrowableClass)) case JVM.checkcast => - code.emit(CHECK_CAST(toTypeKind(pool.getClassOrArrayType(in.nextChar)))); size += 2 + code.emit(CHECK_CAST(toTypeKind(pool.getClassOrArrayType(u2)))); size += 2 case JVM.instanceof => - code.emit(IS_INSTANCE(toTypeKind(pool.getClassOrArrayType(in.nextChar)))); size += 2 + code.emit(IS_INSTANCE(toTypeKind(pool.getClassOrArrayType(u2)))); size += 2 case JVM.monitorenter => code.emit(MONITOR_ENTER()) case JVM.monitorexit => code.emit(MONITOR_EXIT()) case JVM.wide => size += 1 - toUnsignedByte(in.nextByte) match { - case JVM.iload => code.emit(LOAD_LOCAL(code.getLocal(in.nextChar, INT))); size += 2 - case JVM.lload => code.emit(LOAD_LOCAL(code.getLocal(in.nextChar, LONG))); size += 2 - case JVM.fload => code.emit(LOAD_LOCAL(code.getLocal(in.nextChar, FLOAT))); size += 2 - case JVM.dload => code.emit(LOAD_LOCAL(code.getLocal(in.nextChar, DOUBLE))); size += 2 - case JVM.aload => code.emit(LOAD_LOCAL(code.getLocal(in.nextChar, ObjectReference))); size += 2 - case JVM.istore => code.emit(STORE_LOCAL(code.getLocal(in.nextChar, INT))); size += 2 - case JVM.lstore => code.emit(STORE_LOCAL(code.getLocal(in.nextChar, LONG))); size += 2 - case JVM.fstore => code.emit(STORE_LOCAL(code.getLocal(in.nextChar, FLOAT))); size += 2 - case JVM.dstore => code.emit(STORE_LOCAL(code.getLocal(in.nextChar, DOUBLE))); size += 2 - case JVM.astore => code.emit(STORE_LOCAL(code.getLocal(in.nextChar, ObjectReference))); size += 2 + u1 match { + case JVM.iload => code.emit(LOAD_LOCAL(code.getLocal(u2, INT))); size += 2 + case JVM.lload => code.emit(LOAD_LOCAL(code.getLocal(u2, LONG))); size += 2 + case JVM.fload => code.emit(LOAD_LOCAL(code.getLocal(u2, FLOAT))); size += 2 + case JVM.dload => code.emit(LOAD_LOCAL(code.getLocal(u2, DOUBLE))); size += 2 + case JVM.aload => code.emit(LOAD_LOCAL(code.getLocal(u2, ObjectReference))); size += 2 + case JVM.istore => code.emit(STORE_LOCAL(code.getLocal(u2, INT))); size += 2 + case JVM.lstore => code.emit(STORE_LOCAL(code.getLocal(u2, LONG))); size += 2 + case JVM.fstore => code.emit(STORE_LOCAL(code.getLocal(u2, FLOAT))); size += 2 + case JVM.dstore => code.emit(STORE_LOCAL(code.getLocal(u2, DOUBLE))); size += 2 + case JVM.astore => code.emit(STORE_LOCAL(code.getLocal(u2, ObjectReference))); size += 2 case JVM.ret => sys.error("Cannot handle jsr/ret") case JVM.iinc => size += 4 - val local = code.getLocal(in.nextChar, INT) - code.emit(CONSTANT(Constant(in.nextChar))) + val local = code.getLocal(u2, INT) + code.emit(CONSTANT(Constant(u2))) code.emit(CALL_PRIMITIVE(Arithmetic(ADD, INT))) code.emit(STORE_LOCAL(local)) case _ => sys.error("Invalid 'wide' operand") @@ -568,8 +563,8 @@ abstract class ICodeReader extends ClassfileParser { case JVM.multianewarray => size += 3 - val tpe = toTypeKind(pool getClassOrArrayType in.nextChar) - val dim = in.nextByte + val tpe = toTypeKind(pool getClassOrArrayType u2) + val dim = u1 // assert(dim == 1, "Cannot handle multidimensional arrays yet.") code emit CREATE_ARRAY(tpe, dim) @@ -593,16 +588,16 @@ abstract class ICodeReader extends ClassfileParser { } pc = 0 - while (pc < codeLength) parseInstruction + while (pc < codeLength) parseInstruction() - val exceptionEntries = in.nextChar.toInt + val exceptionEntries = u2.toInt code.containsEHs = (exceptionEntries != 0) var i = 0 while (i < exceptionEntries) { // skip start end PC in.skip(4) // read the handler PC - code.jmpTargets += in.nextChar + code.jmpTargets += u2 // skip the exception type in.skip(2) i += 1 @@ -638,15 +633,13 @@ abstract class ICodeReader extends ClassfileParser { /** Return the icode class that should include members with the given flags. * There are two possible classes, the static part and the instance part. */ - def getCode(flags: Int): IClass = - if (isScalaModule) staticCode - else if ((flags & JAVA_ACC_STATIC) != 0) staticCode - else instanceCode + def getCode(flags: JavaAccFlags): IClass = + if (isScalaModule || flags.isStatic) staticCode else instanceCode class LinearCode { - var instrs: ListBuffer[(Int, Instruction)] = new ListBuffer - var jmpTargets: mutable.Set[Int] = perRunCaches.newSet[Int]() - var locals: mutable.Map[Int, List[(Local, TypeKind)]] = perRunCaches.newMap() + val instrs: ListBuffer[(Int, Instruction)] = new ListBuffer + val jmpTargets: mutable.Set[Int] = perRunCaches.newSet[Int]() + val locals: mutable.Map[Int, List[(Local, TypeKind)]] = perRunCaches.newMap() var containsDUPX = false var containsNEW = false @@ -678,7 +671,6 @@ abstract class ICodeReader extends ClassfileParser { val blocks = makeBasicBlocks var otherBlock: BasicBlock = NoBasicBlock - var disableJmpTarget = false for ((pc, instr) <- instrs.iterator) { // Console.println("> " + pc + ": " + instr); @@ -686,7 +678,7 @@ abstract class ICodeReader extends ClassfileParser { otherBlock = blocks(pc) if (!bb.closed && otherBlock != bb) { bb.emit(JUMP(otherBlock)) - bb.close + bb.close() // Console.println("\t> closing bb: " + bb) } bb = otherBlock @@ -729,46 +721,44 @@ abstract class ICodeReader extends ClassfileParser { val tfa = new analysis.MethodTFA() { import analysis._ - import analysis.typeFlowLattice.IState /** Abstract interpretation for one instruction. */ override def mutatingInterpret(out: typeFlowLattice.Elem, i: Instruction): typeFlowLattice.Elem = { - val bindings = out.vars val stack = out.stack import stack.push i match { case DUP_X1 => val (one, two) = stack.pop2 - push(one); push(two); push(one); + push(one); push(two); push(one) case DUP_X2 => val (one, two, three) = stack.pop3 - push(one); push(three); push(two); push(one); + push(one); push(three); push(two); push(one) case DUP2_X1 => val (one, two) = stack.pop2 if (one.isWideType) { - push(one); push(two); push(one); + push(one); push(two); push(one) } else { val three = stack.pop - push(two); push(one); push(three); push(two); push(one); + push(two); push(one); push(three); push(two); push(one) } case DUP2_X2 => val (one, two) = stack.pop2 if (one.isWideType && two.isWideType) { - push(one); push(two); push(one); + push(one); push(two); push(one) } else if (one.isWideType) { val three = stack.pop assert(!three.isWideType, "Impossible") - push(one); push(three); push(two); push(one); + push(one); push(three); push(two); push(one) } else { val three = stack.pop if (three.isWideType) { - push(two); push(one); push(one); push(three); push(two); push(one); + push(two); push(one); push(one); push(three); push(two); push(one) } else { val four = stack.pop - push(two); push(one); push(four); push(one); push(three); push(two); push(one); + push(two); push(one); push(four); push(one); push(three); push(two); push(one) } } @@ -781,7 +771,7 @@ abstract class ICodeReader extends ClassfileParser { // method.dump tfa.init(method) - tfa.run + tfa.run() for (bb <- linearizer.linearize(method)) { var info = tfa.in(bb) for (i <- bb.toList) { @@ -796,7 +786,7 @@ abstract class ICodeReader extends ClassfileParser { STORE_LOCAL(tmp2), LOAD_LOCAL(tmp1), LOAD_LOCAL(tmp2), - LOAD_LOCAL(tmp1))); + LOAD_LOCAL(tmp1))) case DUP_X2 => val one = info.stack.types(0) @@ -809,30 +799,30 @@ abstract class ICodeReader extends ClassfileParser { STORE_LOCAL(tmp2), LOAD_LOCAL(tmp1), LOAD_LOCAL(tmp2), - LOAD_LOCAL(tmp1))); + LOAD_LOCAL(tmp1))) else { - val tmp3 = freshLocal(info.stack.types(2)); + val tmp3 = freshLocal(info.stack.types(2)) bb.replaceInstruction(i, List(STORE_LOCAL(tmp1), STORE_LOCAL(tmp2), STORE_LOCAL(tmp3), LOAD_LOCAL(tmp1), LOAD_LOCAL(tmp3), LOAD_LOCAL(tmp2), - LOAD_LOCAL(tmp1))); + LOAD_LOCAL(tmp1))) } case DUP2_X1 => val one = info.stack.types(0) val two = info.stack.types(1) - val tmp1 = freshLocal(one); - val tmp2 = freshLocal(two); + val tmp1 = freshLocal(one) + val tmp2 = freshLocal(two) if (one.isWideType) { assert(!two.isWideType, "Impossible") bb.replaceInstruction(i, List(STORE_LOCAL(tmp1), STORE_LOCAL(tmp2), LOAD_LOCAL(tmp1), LOAD_LOCAL(tmp2), - LOAD_LOCAL(tmp1))); + LOAD_LOCAL(tmp1))) } else { val tmp3 = freshLocal(info.stack.types(2)) bb.replaceInstruction(i, List(STORE_LOCAL(tmp1), @@ -841,7 +831,7 @@ abstract class ICodeReader extends ClassfileParser { LOAD_LOCAL(tmp1), LOAD_LOCAL(tmp3), LOAD_LOCAL(tmp2), - LOAD_LOCAL(tmp1))); + LOAD_LOCAL(tmp1))) } case DUP2_X2 => @@ -854,21 +844,21 @@ abstract class ICodeReader extends ClassfileParser { STORE_LOCAL(tmp2), LOAD_LOCAL(tmp1), LOAD_LOCAL(tmp2), - LOAD_LOCAL(tmp1))); + LOAD_LOCAL(tmp1))) } else if (one.isWideType) { val three = info.stack.types(2) assert(!two.isWideType && !three.isWideType, "Impossible") - val tmp3 = freshLocal(three); + val tmp3 = freshLocal(three) bb.replaceInstruction(i, List(STORE_LOCAL(tmp1), STORE_LOCAL(tmp2), STORE_LOCAL(tmp3), LOAD_LOCAL(tmp1), LOAD_LOCAL(tmp3), LOAD_LOCAL(tmp2), - LOAD_LOCAL(tmp1))); + LOAD_LOCAL(tmp1))) } else { val three = info.stack.types(2) - val tmp3 = freshLocal(three); + val tmp3 = freshLocal(three) if (three.isWideType) { bb.replaceInstruction(i, List(STORE_LOCAL(tmp1), STORE_LOCAL(tmp2), @@ -877,10 +867,10 @@ abstract class ICodeReader extends ClassfileParser { LOAD_LOCAL(tmp1), LOAD_LOCAL(tmp3), LOAD_LOCAL(tmp2), - LOAD_LOCAL(tmp1))); + LOAD_LOCAL(tmp1))) } else { val four = info.stack.types(3) - val tmp4 = freshLocal(three); + val tmp4 = freshLocal(three) assert(!four.isWideType, "Impossible") bb.replaceInstruction(i, List(STORE_LOCAL(tmp1), STORE_LOCAL(tmp2), @@ -891,7 +881,7 @@ abstract class ICodeReader extends ClassfileParser { LOAD_LOCAL(tmp4), LOAD_LOCAL(tmp3), LOAD_LOCAL(tmp2), - LOAD_LOCAL(tmp1))); + LOAD_LOCAL(tmp1))) } } case _ => @@ -906,11 +896,11 @@ abstract class ICodeReader extends ClassfileParser { import opcodes._ val rdef = new reachingDefinitions.ReachingDefinitionsAnalysis rdef.init(method) - rdef.run + rdef.run() for (bb <- method.code.blocks ; (i, idx) <- bb.toList.zipWithIndex) i match { case cm @ CALL_METHOD(m, Static(true)) if m.isClassConstructor => - def loop(bb0: BasicBlock, idx0: Int, depth: Int = 0): Unit = { + def loop(bb0: BasicBlock, idx0: Int, depth: Int): Unit = { rdef.findDefs(bb0, idx0, 1, depth) match { case ((bb1, idx1)) :: _ => bb1(idx1) match { @@ -947,7 +937,7 @@ abstract class ICodeReader extends ClassfileParser { locals.get(idx) match { case Some(ls) => - val l = ls find { loc => loc._2 <:< kind } + val l = ls find { loc => loc._2 isAssignabledTo kind } l match { case Some((loc, _)) => loc case None => @@ -958,8 +948,8 @@ abstract class ICodeReader extends ClassfileParser { l } case None => - checkValidIndex - val l = freshLocal(idx, kind, false) + checkValidIndex() + val l = freshLocal(idx, kind, isArg = false) debuglog("Added new local for idx " + idx + ": " + kind) locals += (idx -> List((l, kind))) l @@ -971,7 +961,7 @@ abstract class ICodeReader extends ClassfileParser { /** Return a fresh Local variable for the given index. */ private def freshLocal(idx: Int, kind: TypeKind, isArg: Boolean) = { - val sym = method.symbol.newVariable(newTermName("loc" + idx)).setInfo(kind.toType); + val sym = method.symbol.newVariable(newTermName("loc" + idx)).setInfo(kind.toType) val l = new Local(sym, kind, isArg) method.addLocal(l) l @@ -983,7 +973,7 @@ abstract class ICodeReader extends ClassfileParser { * the original method. */ def freshLocal(kind: TypeKind): Local = { count += 1 - freshLocal(maxLocals + count, kind, false) + freshLocal(maxLocals + count, kind, isArg = false) } /** add a method param with the given index. */ @@ -1001,7 +991,8 @@ abstract class ICodeReader extends ClassfileParser { jmpTargets += pc } - case class LJUMP(pc: Int) extends LazyJump(pc); + case class LJUMP(pc: Int) extends LazyJump(pc) + case class LCJUMP(success: Int, failure: Int, cond: TestOp, kind: TypeKind) extends LazyJump(success) { override def toString(): String = "LCJUMP (" + kind + ") " + success + " : " + failure diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala index ed7eb6d307..a5619871e6 100644 --- a/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala +++ b/src/compiler/scala/tools/nsc/symtab/classfile/Pickler.scala @@ -26,12 +26,8 @@ import Flags._ abstract class Pickler extends SubComponent { import global._ - private final val showSig = false - val phaseName = "pickler" - currentRun - def newPhase(prev: Phase): StdPhase = new PicklePhase(prev) class PicklePhase(prev: Phase) extends StdPhase(prev) { @@ -68,7 +64,7 @@ abstract class Pickler extends SubComponent { return } - if (!t.isDef && t.hasSymbol && t.symbol.isTermMacro) { + if (!t.isDef && t.hasSymbolField && t.symbol.isTermMacro) { unit.error(t.pos, "macro has not been expanded") return } @@ -134,11 +130,34 @@ abstract class Pickler extends SubComponent { true } + /** If the symbol is a type skolem, deskolemize and log it. + * If we fail to deskolemize, in a method like + * trait Trait[+A] { def f[CC[X]] : CC[A] } + * the applied type CC[A] will hold a different CC symbol + * than the type-constructor type-parameter CC. + */ + private def deskolemize(sym: Symbol) = { + if (sym.isTypeSkolem) { + val sym1 = sym.deSkolemize + log({ + val what0 = sym.defString + val what = sym1.defString match { + case `what0` => what0 + case other => what0 + "->" + other + } + val where = sym.enclMethod.fullLocationString + s"deskolemizing $what in $where" + }) + sym1 + } + else sym + } + /** Store symbol in index. If symbol is local, also store everything it references. - * - * @param sym ... */ - def putSymbol(sym: Symbol) { + def putSymbol(sym0: Symbol) { + val sym = deskolemize(sym0) + if (putEntry(sym)) { if (isLocal(sym)) { putEntry(sym.name) @@ -146,7 +165,7 @@ abstract class Pickler extends SubComponent { putSymbol(sym.privateWithin) putType(sym.info) if (sym.thisSym.tpeHK != sym.tpeHK) - putType(sym.typeOfThis); + putType(sym.typeOfThis) putSymbol(sym.alias) if (!sym.children.isEmpty) { val (locals, globals) = sym.children partition (_.isLocalClass) @@ -173,7 +192,7 @@ abstract class Pickler extends SubComponent { */ private def putType(tp: Type): Unit = if (putEntry(tp)) { tp match { - case NoType | NoPrefix /*| DeBruijnIndex(_, _) */ => + case NoType | NoPrefix => ; case ThisType(sym) => putSymbol(sym) @@ -203,7 +222,7 @@ abstract class Pickler extends SubComponent { case NullaryMethodType(restpe) => putType(restpe) case PolyType(tparams, restpe) => - /** no longer needed since all params are now local + /* no longer needed since all params are now local tparams foreach { tparam => if (!isLocal(tparam)) locals += tparam // similar to existential types, these tparams are local } @@ -213,14 +232,14 @@ abstract class Pickler extends SubComponent { // val savedBoundSyms = boundSyms // boundSyms are known to be local based on the EXISTENTIAL flag (see isLocal) // boundSyms = tparams ::: boundSyms // try { - putType(restpe); -// } finally { + putType(restpe) + // } finally { // boundSyms = savedBoundSyms // } putSymbols(tparams) case AnnotatedType(annotations, underlying, selfsym) => putType(underlying) - if (settings.selfInAnnots.value) putSymbol(selfsym) + if (settings.selfInAnnots) putSymbol(selfsym) putAnnotations(annotations filter (_.isStatic)) case _ => throw new FatalError("bad type: " + tp + "(" + tp.getClass + ")") @@ -231,7 +250,7 @@ abstract class Pickler extends SubComponent { private def putTree(tree: Tree): Unit = if (putEntry(tree)) { if (tree != EmptyTree) putType(tree.tpe) - if (tree.hasSymbol) + if (tree.hasSymbolField) putSymbol(tree.symbol) tree match { @@ -422,7 +441,7 @@ abstract class Pickler extends SubComponent { * argument of some Annotation */ private def putMods(mods: Modifiers) = if (putEntry(mods)) { // annotations in Modifiers are removed by the typechecker - val Modifiers(flags, privateWithin, Nil) = mods + val Modifiers(_, privateWithin, Nil) = mods putEntry(privateWithin) } @@ -490,7 +509,13 @@ abstract class Pickler extends SubComponent { /** Write a reference to object, i.e., the object's number in the map index. */ - private def writeRef(ref: AnyRef) { writeNat(index(ref)) } + private def writeRef(ref0: AnyRef) { + val ref = ref0 match { + case sym: Symbol => deskolemize(sym) + case _ => ref0 + } + writeNat(index(ref)) + } private def writeRefs(refs: List[AnyRef]) { refs foreach writeRef } private def writeRefsWithLength(refs: List[AnyRef]) { writeNat(refs.length) @@ -502,7 +527,7 @@ abstract class Pickler extends SubComponent { private def writeSymInfo(sym: Symbol) { writeRef(sym.name) writeRef(localizedOwner(sym)) - writeLongNat((rawToPickledFlags(sym.flags & PickledFlags))) + writeLongNat((rawToPickledFlags(sym.rawflags & PickledFlags))) if (sym.hasAccessBoundary) writeRef(sym.privateWithin) writeRef(sym.info) } @@ -563,7 +588,7 @@ abstract class Pickler extends SubComponent { tag case sym: ClassSymbol => writeSymInfo(sym) - if (sym.thisSym.tpe != sym.tpe) writeRef(sym.typeOfThis) + if (sym.thisSym.tpe_* != sym.tpe_*) writeRef(sym.typeOfThis) CLASSsym case sym: TypeSymbol => writeSymInfo(sym) @@ -604,8 +629,6 @@ abstract class Pickler extends SubComponent { writeRef(restpe); writeRefs(tparams); POLYtpe case ExistentialType(tparams, restpe) => writeRef(restpe); writeRefs(tparams); EXISTENTIALtpe - // case DeBruijnIndex(l, i) => - // writeNat(l); writeNat(i); DEBRUIJNINDEXtpe case c @ Constant(_) => if (c.tag == BooleanTag) writeLong(if (c.booleanValue) 1 else 0) else if (ByteTag <= c.tag && c.tag <= LongTag) writeLong(c.longValue) @@ -619,7 +642,7 @@ abstract class Pickler extends SubComponent { annotations filter (_.isStatic) match { case Nil => writeBody(tp) // write the underlying type if there are no annotations case staticAnnots => - if (settings.selfInAnnots.value && selfsym != NoSymbol) + if (settings.selfInAnnots && selfsym != NoSymbol) writeRef(selfsym) writeRef(tp) writeRefs(staticAnnots) @@ -988,115 +1011,6 @@ abstract class Pickler extends SubComponent { patchNat(startpos + 1, writeIndex - (startpos + 2)) } - /** Print entry for diagnostics */ - def printEntryAtIndex(idx: Int) = printEntry(entries(idx)) - def printEntry(entry: AnyRef) { - def printRef(ref: AnyRef) { - print(index(ref)+ - (if (ref.isInstanceOf[Name]) "("+ref+") " else " ")) - } - def printRefs(refs: List[AnyRef]) { refs foreach printRef } - def printSymInfo(sym: Symbol) { - var posOffset = 0 - printRef(sym.name) - printRef(localizedOwner(sym)) - print(flagsToString(sym.flags & PickledFlags)+" ") - if (sym.hasAccessBoundary) printRef(sym.privateWithin) - printRef(sym.info) - } - def printBody(entry: AnyRef) = entry match { - case name: Name => - print((if (name.isTermName) "TERMname " else "TYPEname ")+name) - case NoSymbol => - print("NONEsym") - case sym: Symbol if !isLocal(sym) => - if (sym.isModuleClass) { - print("EXTMODCLASSref "); printRef(sym.name.toTermName) - } else { - print("EXTref "); printRef(sym.name) - } - if (!sym.owner.isRoot) printRef(sym.owner) - case sym: ClassSymbol => - print("CLASSsym ") - printSymInfo(sym) - if (sym.thisSym.tpe != sym.tpe) printRef(sym.typeOfThis) - case sym: TypeSymbol => - print(if (sym.isAbstractType) "TYPEsym " else "ALIASsym ") - printSymInfo(sym) - case sym: TermSymbol => - print(if (sym.isModule) "MODULEsym " else "VALsym ") - printSymInfo(sym) - if (sym.alias != NoSymbol) printRef(sym.alias) - case NoType => - print("NOtpe") - case NoPrefix => - print("NOPREFIXtpe") - case ThisType(sym) => - print("THIStpe "); printRef(sym) - case SingleType(pre, sym) => - print("SINGLEtpe "); printRef(pre); printRef(sym); - case ConstantType(value) => - print("CONSTANTtpe "); printRef(value); - case TypeRef(pre, sym, args) => - print("TYPEREFtpe "); printRef(pre); printRef(sym); printRefs(args); - case TypeBounds(lo, hi) => - print("TYPEBOUNDStpe "); printRef(lo); printRef(hi); - case tp @ RefinedType(parents, decls) => - print("REFINEDtpe "); printRef(tp.typeSymbol); printRefs(parents); - case ClassInfoType(parents, decls, clazz) => - print("CLASSINFOtpe "); printRef(clazz); printRefs(parents); - case mt @ MethodType(formals, restpe) => - print("METHODtpe"); printRef(restpe); printRefs(formals) - case PolyType(tparams, restpe) => - print("POLYtpe "); printRef(restpe); printRefs(tparams); - case ExistentialType(tparams, restpe) => - print("EXISTENTIALtpe "); printRef(restpe); printRefs(tparams); - print("||| "+entry) - // case DeBruijnIndex(l, i) => - // print("DEBRUIJNINDEXtpe "); print(l+" "+i) - case c @ Constant(_) => - print("LITERAL ") - if (c.tag == BooleanTag) print("Boolean "+(if (c.booleanValue) 1 else 0)) - else if (c.tag == ByteTag) print("Byte "+c.longValue) - else if (c.tag == ShortTag) print("Short "+c.longValue) - else if (c.tag == CharTag) print("Char "+c.longValue) - else if (c.tag == IntTag) print("Int "+c.longValue) - else if (c.tag == LongTag) print("Long "+c.longValue) - else if (c.tag == FloatTag) print("Float "+c.floatValue) - else if (c.tag == DoubleTag) print("Double "+c.doubleValue) - else if (c.tag == StringTag) { print("String "); printRef(newTermName(c.stringValue)) } - else if (c.tag == ClazzTag) { print("Class "); printRef(c.typeValue) } - else if (c.tag == EnumTag) { print("Enum "); printRef(c.symbolValue) } - case AnnotatedType(annots, tp, selfsym) => - if (settings.selfInAnnots.value) { - print("ANNOTATEDWSELFtpe ") - printRef(tp) - printRef(selfsym) - printRefs(annots) - } else { - print("ANNOTATEDtpe ") - printRef(tp) - printRefs(annots) - } - case (target: Symbol, AnnotationInfo(atp, args, Nil)) => - print("SYMANNOT ") - printRef(target) - printRef(atp) - for (c <- args) printRef(c) - case (target: Symbol, children: List[_]) => - print("CHILDREN ") - printRef(target) - for (c <- children) printRef(c.asInstanceOf[Symbol]) - case AnnotationInfo(atp, args, Nil) => - print("ANNOTINFO") - printRef(atp) - for (c <- args) printRef(c) - case _ => - throw new FatalError("bad entry: " + entry + " " + entry.getClass) - } - printBody(entry); println() - } - /** Write byte array */ def writeArray() { assert(writeIndex == 0) diff --git a/src/compiler/scala/tools/nsc/symtab/clr/CLRTypes.scala b/src/compiler/scala/tools/nsc/symtab/clr/CLRTypes.scala deleted file mode 100644 index 40189b9444..0000000000 --- a/src/compiler/scala/tools/nsc/symtab/clr/CLRTypes.scala +++ /dev/null @@ -1,137 +0,0 @@ -/* NSC -- new scala compiler - * Copyright 2004-2013 LAMP/EPFL - */ - - -package scala.tools.nsc -package symtab -package clr - -import java.io.File -import java.util.{Comparator, StringTokenizer} -import scala.util.Sorting -import ch.epfl.lamp.compiler.msil._ -import scala.collection.{ mutable, immutable } -import scala.reflect.internal.util.{Position, NoPosition} - -/** - * Collects all types from all reference assemblies. - */ -abstract class CLRTypes { - - val global: Global - import global.Symbol - import global.definitions - - //########################################################################## - - var BYTE: Type = _ - var UBYTE: Type = _ - var SHORT: Type = _ - var USHORT: Type = _ - var CHAR: Type = _ - var INT: Type = _ - var UINT: Type = _ - var LONG: Type = _ - var ULONG: Type = _ - var FLOAT: Type = _ - var DOUBLE: Type = _ - var BOOLEAN: Type = _ - var VOID: Type = _ - var ENUM: Type = _ - var DELEGATE: Type = _ - - var OBJECT: Type = _ - var STRING: Type = _ - var STRING_ARRAY: Type = _ - - var VALUE_TYPE: Type = _ - - var SCALA_SYMTAB_ATTR: Type = _ - var SYMTAB_CONSTR: ConstructorInfo = _ - var SYMTAB_DEFAULT_CONSTR: ConstructorInfo = _ - - var DELEGATE_COMBINE: MethodInfo = _ - var DELEGATE_REMOVE: MethodInfo = _ - - val types: mutable.Map[Symbol,Type] = new mutable.HashMap - val constructors: mutable.Map[Symbol,ConstructorInfo] = new mutable.HashMap - val methods: mutable.Map[Symbol,MethodInfo] = new mutable.HashMap - val fields: mutable.Map[Symbol, FieldInfo] = new mutable.HashMap - val sym2type: mutable.Map[Type,Symbol] = new mutable.HashMap - val addressOfViews = new mutable.HashSet[Symbol] - val mdgptrcls4clssym: mutable.Map[ /*cls*/ Symbol, /*cls*/ Symbol] = new mutable.HashMap - - def isAddressOf(msym : Symbol) = addressOfViews.contains(msym) - - def isNonEnumValuetype(cls: Symbol) = { - val msilTOpt = types.get(cls) - val res = msilTOpt.isDefined && { - val msilT = msilTOpt.get - msilT.IsValueType && !msilT.IsEnum - } - res - } - - def isValueType(cls: Symbol): Boolean = { - val opt = types.get(cls) - opt.isDefined && opt.get.IsValueType - } - - def init() = try { // initialize - // the MsilClasspath (nsc/util/Classpath.scala) initializes the msil-library by calling - // Assembly.LoadFrom("mscorlib.dll"), so this type should be found - Type.initMSCORLIB(getTypeSafe("System.String").Assembly) - - BYTE = getTypeSafe("System.SByte") - UBYTE = getTypeSafe("System.Byte") - CHAR = getTypeSafe("System.Char") - SHORT = getTypeSafe("System.Int16") - USHORT = getTypeSafe("System.UInt16") - INT = getTypeSafe("System.Int32") - UINT = getTypeSafe("System.UInt32") - LONG = getTypeSafe("System.Int64") - ULONG = getTypeSafe("System.UInt64") - FLOAT = getTypeSafe("System.Single") - DOUBLE = getTypeSafe("System.Double") - BOOLEAN = getTypeSafe("System.Boolean") - VOID = getTypeSafe("System.Void") - ENUM = getTypeSafe("System.Enum") - DELEGATE = getTypeSafe("System.MulticastDelegate") - - OBJECT = getTypeSafe("System.Object") - STRING = getTypeSafe("System.String") - STRING_ARRAY = getTypeSafe("System.String[]") - VALUE_TYPE = getTypeSafe("System.ValueType") - - SCALA_SYMTAB_ATTR = getTypeSafe("scala.runtime.SymtabAttribute") - val bytearray: Array[Type] = Array(Type.GetType("System.Byte[]")) - SYMTAB_CONSTR = SCALA_SYMTAB_ATTR.GetConstructor(bytearray) - SYMTAB_DEFAULT_CONSTR = SCALA_SYMTAB_ATTR.GetConstructor(Type.EmptyTypes) - - val delegate: Type = getTypeSafe("System.Delegate") - val dargs: Array[Type] = Array(delegate, delegate) - DELEGATE_COMBINE = delegate.GetMethod("Combine", dargs) - DELEGATE_REMOVE = delegate.GetMethod("Remove", dargs) - } - catch { - case e: RuntimeException => - Console.println(e.getMessage) - throw e - } - - //########################################################################## - // type mapping and lookup - - def getType(name: String): Type = Type.GetType(name) - - def getTypeSafe(name: String): Type = { - val t = Type.GetType(name) - assert(t != null, name) - t - } - - def mkArrayType(elemType: Type): Type = getType(elemType.FullName + "[]") - - def isDelegateType(t: Type): Boolean = { t.BaseType() == DELEGATE } -} // CLRTypes diff --git a/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala b/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala deleted file mode 100644 index 5a0253c18b..0000000000 --- a/src/compiler/scala/tools/nsc/symtab/clr/TypeParser.scala +++ /dev/null @@ -1,850 +0,0 @@ -/* NSC -- new scala compiler - * Copyright 2004-2013 LAMP/EPFL - */ - -package scala.tools.nsc -package symtab -package clr - -import java.io.IOException -import io.MsilFile -import ch.epfl.lamp.compiler.msil.{Type => MSILType, Attribute => MSILAttribute, _} -import scala.collection.{ mutable, immutable } -import scala.reflect.internal.pickling.UnPickler -import ch.epfl.lamp.compiler.msil.Type.TMVarUsage -import scala.language.implicitConversions - -/** - * @author Nikolay Mihaylov - */ -abstract class TypeParser { - - val global: Global - - import global._ - import loaders.clrTypes - - //########################################################################## - - private var clazz: Symbol = _ - private var instanceDefs: Scope = _ // was members - private var staticModule: Symbol = _ // was staticsClass - private var staticDefs: Scope = _ // was statics - - protected def statics: Symbol = staticModule.moduleClass - - protected var busy: Boolean = false // lock to detect recursive reads - - private object unpickler extends UnPickler { - val global: TypeParser.this.global.type = TypeParser.this.global - } - - def parse(typ: MSILType, root: Symbol) { - - def handleError(e: Throwable) = { - if (settings.debug.value) e.printStackTrace() //debug - throw new IOException("type '" + typ.FullName + "' is broken\n(" + e.getMessage() + ")") - } - assert(!busy) - busy = true - - if (root.isModule) { - this.clazz = root.companionClass - this.staticModule = root - } else { - this.clazz = root - this.staticModule = root.companionModule - } - try { - parseClass(typ) - } catch { - case e: FatalError => handleError(e) - case e: RuntimeException => handleError(e) - } - busy = false - } - - class TypeParamsType(override val typeParams: List[Symbol]) extends LazyType with FlagAgnosticCompleter { - 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, - * therefore newTParams is redundant (other than for recording lexical order), - * it always contains the same elements as classTParams.value */ - val classTParams = scala.collection.mutable.Map[Int,Symbol]() // TODO should this be a stack? (i.e., is it possible for >1 invocation to getCLRType on the same TypeParser instance be active ) - val newTParams = new scala.collection.mutable.ListBuffer[Symbol]() - val methodTParams = scala.collection.mutable.Map[Int,Symbol]() - - private def sig2typeBounds(tvarCILDef: GenericParamAndConstraints): Type = { - val ts = new scala.collection.mutable.ListBuffer[Type] - for (cnstrnt <- tvarCILDef.Constraints) { - ts += getCLRType(cnstrnt) // TODO we're definitely not at or after erasure, no need to call objToAny, right? - } - TypeBounds.upper(intersectionType(ts.toList, clazz)) - // TODO variance??? - } - - private def createViewFromTo(viewSuffix : String, fromTpe : Type, toTpe : Type, - addToboxMethodMap : Boolean, isAddressOf : Boolean) : Symbol = { - val flags = Flags.JAVA | Flags.STATIC | Flags.IMPLICIT; // todo: static? shouldn't be final instead? - val viewMethodType = (msym: Symbol) => JavaMethodType(msym.newSyntheticValueParams(List(fromTpe)), toTpe) - val vmsym = createMethod(nme.view_ + viewSuffix, flags, viewMethodType, null, true); - // !!! this used to mutate a mutable map in definitions, but that map became - // immutable and this kept "working" with a no-op. So now it's commented out - // since I retired the deprecated code which allowed for that bug. - // - // if (addToboxMethodMap) definitions.boxMethod(clazz) = vmsym - - if (isAddressOf) clrTypes.addressOfViews += vmsym - vmsym - } - - private def createDefaultConstructor(typ: MSILType) { - val attrs = MethodAttributes.Public | MethodAttributes.RTSpecialName | MethodAttributes.SpecialName // TODO instance - val declType= typ - val method = new ConstructorInfo(declType, attrs, Array[MSILType]()) - val flags = Flags.JAVA - val owner = clazz - val methodSym = owner.newMethod(nme.CONSTRUCTOR, NoPosition, flags) - val rettype = clazz.tpe - val mtype = methodType(Array[MSILType](), rettype); - val mInfo = mtype(methodSym) - methodSym.setInfo(mInfo) - instanceDefs.enter(methodSym); - clrTypes.constructors(methodSym) = method - } - - private def parseClass(typ: MSILType) { - - { - val t4c = clrTypes.types.get(clazz) - assert(t4c == None || t4c == Some(typ)) - } - clrTypes.types(clazz) = typ - - { - val c4t = clrTypes.sym2type.get(typ) - assert(c4t == None || c4t == Some(clazz)) - } - clrTypes.sym2type(typ) = clazz - - if (typ.IsDefined(clrTypes.SCALA_SYMTAB_ATTR, false)) { - val attrs = typ.GetCustomAttributes(clrTypes.SCALA_SYMTAB_ATTR, false); - assert (attrs.length == 1, attrs.length); - val a = attrs(0).asInstanceOf[MSILAttribute]; - assert (a.getConstructor() == clrTypes.SYMTAB_CONSTR); - val symtab = a.getConstructorArguments()(0).asInstanceOf[Array[Byte]] - unpickler.unpickle(symtab, 0, clazz, staticModule, typ.FullName); - val mClass = clrTypes.getType(typ.FullName + "$"); - if (mClass != null) { - clrTypes.types(statics) = mClass; - val moduleInstance = mClass.GetField("MODULE$"); - assert (moduleInstance != null, mClass); - clrTypes.fields(statics) = moduleInstance; - } - return - } - val flags = translateAttributes(typ) - - var clazzBoxed : Symbol = NoSymbol - var clazzMgdPtr : Symbol = NoSymbol - - val canBeTakenAddressOf = (typ.IsValueType || typ.IsEnum) && (typ.FullName != "System.Enum") - - if(canBeTakenAddressOf) { - clazzBoxed = clazz.owner.newClass(clazz.name.toTypeName append newTypeName("Boxed")) - clazzMgdPtr = clazz.owner.newClass(clazz.name.toTypeName append newTypeName("MgdPtr")) - clrTypes.mdgptrcls4clssym(clazz) = clazzMgdPtr - /* adding typMgdPtr to clrTypes.sym2type should happen early (before metadata for supertypes is parsed, - before metadata for members are parsed) so that clazzMgdPtr can be found by getClRType. */ - val typMgdPtr = MSILType.mkByRef(typ) - clrTypes.types(clazzMgdPtr) = typMgdPtr - clrTypes.sym2type(typMgdPtr) = clazzMgdPtr - /* clazzMgdPtr but not clazzBoxed is mapped by clrTypes.types into an msil.Type instance, - because there's no metadata-level representation for a "boxed valuetype" */ - val instanceDefsMgdPtr = newScope - val classInfoMgdPtr = ClassInfoType(definitions.anyvalparam, instanceDefsMgdPtr, clazzMgdPtr) - clazzMgdPtr.setFlag(flags) - clazzMgdPtr.setInfo(classInfoMgdPtr) - } - -/* 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) - val tpsym = clazz.newTypeParameter(tpname) - classTParams.put(tvarCILDef.Number, tpsym) - newTParams += tpsym - // TODO wouldn't the following also be needed later, i.e. during getCLRType - tpsym.setInfo(definitions.AnyClass.tpe) - } - // second pass - for (tvarCILDef <- typ.getSortedTVars() ) { - 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 -/* 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 = newScope - staticDefs = newScope - - val classInfoAsInMetadata = { - val ifaces: Array[MSILType] = typ.getInterfaces() - val superType = if (typ.BaseType() != null) getCLRType(typ.BaseType()) - else if (typ.IsInterface()) definitions.ObjectClass.tpe - else definitions.AnyClass.tpe; // this branch activates for System.Object only. - // parents (i.e., base type and interfaces) - val parents = new scala.collection.mutable.ListBuffer[Type]() - parents += superType - for (iface <- ifaces) { - parents += getCLRType(iface) // here the variance doesn't matter - } - // methods, properties, events, fields are entered in a moment - if (canBeTakenAddressOf) { - val instanceDefsBoxed = newScope - ClassInfoType(parents.toList, instanceDefsBoxed, clazzBoxed) - } else - ClassInfoType(parents.toList, instanceDefs, clazz) - } - - val staticInfo = ClassInfoType(List(), staticDefs, statics) - - clazz.setFlag(flags) - - if (canBeTakenAddressOf) { - clazzBoxed.setInfo( if (ownTypeParams.isEmpty) classInfoAsInMetadata - else genPolyType(ownTypeParams, classInfoAsInMetadata) ) - clazzBoxed.setFlag(flags) - val rawValueInfoType = ClassInfoType(definitions.anyvalparam, instanceDefs, clazz) - clazz.setInfo( if (ownTypeParams.isEmpty) rawValueInfoType - else genPolyType(ownTypeParams, rawValueInfoType) ) - } else { - clazz.setInfo( if (ownTypeParams.isEmpty) classInfoAsInMetadata - else genPolyType(ownTypeParams, classInfoAsInMetadata) ) - } - - // TODO I don't remember if statics.setInfo and staticModule.setInfo should also know about type params - statics.setFlag(Flags.JAVA) - statics.setInfo(staticInfo) - staticModule.setFlag(Flags.JAVA) - staticModule.setInfo(statics.tpe) - - - if (canBeTakenAddressOf) { - // implicit conversions are owned by staticModule.moduleClass - createViewFromTo("2Boxed", clazz.tpe, clazzBoxed.tpe, addToboxMethodMap = true, isAddressOf = false) - // createViewFromTo("2Object", clazz.tpe, definitions.ObjectClass.tpe, addToboxMethodMap = true, isAddressOf = false) - createViewFromTo("2MgdPtr", clazz.tpe, clazzMgdPtr.tpe, addToboxMethodMap = false, isAddressOf = true) - // a return can't have type managed-pointer, thus a dereference-conversion is not needed - // similarly, a method can't declare as return type "boxed valuetype" - if (!typ.IsEnum) { - // a synthetic default constructor for raw-type allows `new X' syntax - createDefaultConstructor(typ) - } - } - - // import nested types - for (ntype <- typ.getNestedTypes() if !(ntype.IsNestedPrivate || ntype.IsNestedAssembly || ntype.IsNestedFamANDAssem) - || ntype.IsInterface /* TODO why shouldn't nested ifaces be type-parsed too? */ ) - { - val loader = new loaders.MsilFileLoader(new MsilFile(ntype)) - val nclazz = statics.newClass(ntype.Name) - val nmodule = statics.newModule(ntype.Name) - nclazz.setInfo(loader) - nmodule.setInfo(loader) - staticDefs.enter(nclazz) - staticDefs.enter(nmodule) - - assert(nclazz.companionModule == nmodule, nmodule) - assert(nmodule.companionClass == nclazz, nclazz) - } - - val fields = typ.getFields() - for (field <- fields - if !(field.IsPrivate() || field.IsAssembly() || field.IsFamilyAndAssembly) - if (getCLRType(field.FieldType) != null) - ) { - assert (!field.FieldType.IsPointer && !field.FieldType.IsByRef, "CLR requirement") - val flags = translateAttributes(field); - val name = newTermName(field.Name); - val fieldType = - if (field.IsLiteral && !field.FieldType.IsEnum && isDefinedAtgetConstant(getCLRType(field.FieldType))) - ConstantType(getConstant(getCLRType(field.FieldType), field.getValue)) - else - getCLRType(field.FieldType) - val owner = if (field.IsStatic()) statics else clazz; - val sym = owner.newValue(name, NoPosition, flags).setInfo(fieldType); - // TODO: set private within!!! -> look at typechecker/Namers.scala - (if (field.IsStatic()) staticDefs else instanceDefs).enter(sym); - clrTypes.fields(sym) = field; - } - - for (constr <- typ.getConstructors() if !constr.IsStatic() && !constr.IsPrivate() && - !constr.IsAssembly() && !constr.IsFamilyAndAssembly() && !constr.HasPtrParamOrRetType()) - createMethod(constr); - - // initially also contains getters and setters of properties. - val methodsSet = new mutable.HashSet[MethodInfo](); - methodsSet ++= typ.getMethods(); - - for (prop <- typ.getProperties) { - val propType: Type = getCLSType(prop.PropertyType); - if (propType != null) { - val getter: MethodInfo = prop.GetGetMethod(true); - val setter: MethodInfo = prop.GetSetMethod(true); - var gparamsLength: Int = -1; - if (!(getter == null || getter.IsPrivate || getter.IsAssembly - || getter.IsFamilyAndAssembly || getter.HasPtrParamOrRetType)) - { - assert(prop.PropertyType == getter.ReturnType); - val gparams: Array[ParameterInfo] = getter.GetParameters(); - gparamsLength = gparams.length; - val name: TermName = if (gparamsLength == 0) prop.Name else nme.apply; - val flags = translateAttributes(getter); - val owner: Symbol = if (getter.IsStatic) statics else clazz; - val methodSym = owner.newMethod(name, NoPosition, flags) - val mtype: Type = if (gparamsLength == 0) NullaryMethodType(propType) // .NET properties can't be polymorphic - else methodType(getter, getter.ReturnType)(methodSym) - methodSym.setInfo(mtype); - methodSym.setFlag(Flags.ACCESSOR); - (if (getter.IsStatic) staticDefs else instanceDefs).enter(methodSym) - clrTypes.methods(methodSym) = getter; - methodsSet -= getter; - } - if (!(setter == null || setter.IsPrivate || setter.IsAssembly - || setter.IsFamilyAndAssembly || setter.HasPtrParamOrRetType)) - { - val sparams: Array[ParameterInfo] = setter.GetParameters() - if(getter != null) - assert(getter.IsStatic == setter.IsStatic); - assert(setter.ReturnType == clrTypes.VOID); - if(getter != null) - assert(sparams.length == gparamsLength + 1, "" + getter + "; " + setter); - - val name: TermName = if (gparamsLength == 0) nme.getterToSetter(prop.Name) - else nme.update; - val flags = translateAttributes(setter); - val mtype = methodType(setter, definitions.UnitClass.tpe); - val owner: Symbol = if (setter.IsStatic) statics else clazz; - val methodSym = owner.newMethod(name, NoPosition, flags) - methodSym.setInfo(mtype(methodSym)) - methodSym.setFlag(Flags.ACCESSOR); - (if (setter.IsStatic) staticDefs else instanceDefs).enter(methodSym); - clrTypes.methods(methodSym) = setter; - methodsSet -= setter; - } - } - } - -/* for (event <- typ.GetEvents) { - // adding += and -= methods to add delegates to an event. - // raising the event ist not possible from outside the class (this is so - // generally in .net world) - val adder: MethodInfo = event.GetAddMethod(); - val remover: MethodInfo = event.GetRemoveMethod(); - if (!(adder == null || adder.IsPrivate || adder.IsAssembly - || adder.IsFamilyAndAssembly)) - { - assert(adder.ReturnType == clrTypes.VOID); - assert(adder.GetParameters().map(_.ParameterType).toList == List(event.EventHandlerType)); - val name = encode("+="); - val flags = translateAttributes(adder); - val mtype: Type = methodType(adder, adder.ReturnType); - createMethod(name, flags, mtype, adder, adder.IsStatic) - methodsSet -= adder; - } - if (!(remover == null || remover.IsPrivate || remover.IsAssembly - || remover.IsFamilyAndAssembly)) - { - assert(remover.ReturnType == clrTypes.VOID); - assert(remover.GetParameters().map(_.ParameterType).toList == List(event.EventHandlerType)); - val name = encode("-="); - val flags = translateAttributes(remover); - val mtype: Type = methodType(remover, remover.ReturnType); - createMethod(name, flags, mtype, remover, remover.IsStatic) - methodsSet -= remover; - } - } */ - -/* Adds view amounting to syntax sugar for a CLR implicit overload. - The long-form syntax can also be supported if "methodsSet -= method" (last statement) is removed. - - /* remember, there's typ.getMethods and type.GetMethods */ - for (method <- typ.getMethods) - if(!method.HasPtrParamOrRetType && - method.IsPublic && method.IsStatic && method.IsSpecialName && - method.Name == "op_Implicit") { - // create a view: typ => method's return type - val viewRetType: Type = getCLRType(method.ReturnType) - val viewParamTypes: List[Type] = method.GetParameters().map(_.ParameterType).map(getCLSType).toList; - /* The spec says "The operator method shall be defined as a static method on either the operand or return type." - * We don't consider the declaring type for the purposes of definitions.functionType, - * instead we regard op_Implicit's argument type and return type as defining the view's signature. - */ - if (viewRetType != null && !viewParamTypes.contains(null)) { - /* The check above applies e.g. to System.Decimal that has a conversion from UInt16, a non-CLS type, whose CLS-mapping returns null */ - val funType: Type = definitions.functionType(viewParamTypes, viewRetType); - val flags = Flags.JAVA | Flags.STATIC | Flags.IMPLICIT; // todo: static? shouldn't be final instead? - val viewMethodType = (msym: Symbol) => JavaMethodType(msym.newSyntheticValueParams(viewParamTypes), funType) - val vmsym = createMethod(nme.view_, flags, viewMethodType, method, true); - methodsSet -= method; - } - } -*/ - - for (method <- methodsSet.iterator) - if (!method.IsPrivate() && !method.IsAssembly() && !method.IsFamilyAndAssembly() - && !method.HasPtrParamOrRetType) - createMethod(method); - - // Create methods and views for delegate support - if (clrTypes.isDelegateType(typ)) { - createDelegateView(typ) - createDelegateChainers(typ) - } - - // for enumerations introduce comparison and bitwise logical operations; - // the backend will recognize them and replace them with comparison or - // bitwise logical operations on the primitive underlying type - - if (typ.IsEnum) { - val ENUM_CMP_NAMES = List(nme.EQ, nme.NE, nme.LT, nme.LE, nme.GT, nme.GE); - val ENUM_BIT_LOG_NAMES = List(nme.OR, nme.AND, nme.XOR); - - val flags = Flags.JAVA | Flags.FINAL - for (cmpName <- ENUM_CMP_NAMES) { - val enumCmp = clazz.newMethod(cmpName) - val enumCmpType = JavaMethodType(enumCmp.newSyntheticValueParams(List(clazz.tpe)), definitions.BooleanClass.tpe) - enumCmp.setFlag(flags).setInfo(enumCmpType) - instanceDefs.enter(enumCmp) - } - - for (bitLogName <- ENUM_BIT_LOG_NAMES) { - val enumBitLog = clazz.newMethod(bitLogName) - val enumBitLogType = JavaMethodType(enumBitLog.newSyntheticValueParams(List(clazz.tpe)), clazz.tpe /* was classInfo, infinite typer */) - enumBitLog.setFlag(flags).setInfo(enumBitLogType) - instanceDefs.enter(enumBitLog) - } - } - - } // parseClass - - private def populateMethodTParams(method: MethodBase, methodSym: MethodSymbol) : List[Symbol] = { - if(!method.IsGeneric) Nil - else { - methodTParams.clear - val newMethodTParams = new scala.collection.mutable.ListBuffer[Symbol]() - - // first pass - for (mvarCILDef <- method.getSortedMVars() ) { - val mtpname = newTypeName(mvarCILDef.Name.replaceAll("!", "")) // TODO are really all method-level-type-params named in all assemblies out there? (NO) - val mtpsym = methodSym.newTypeParameter(mtpname) - methodTParams.put(mvarCILDef.Number, mtpsym) - newMethodTParams += mtpsym - // TODO wouldn't the following also be needed later, i.e. during getCLRType - mtpsym.setInfo(definitions.AnyClass.tpe) - } - // second pass - for (mvarCILDef <- method.getSortedMVars() ) { - val mtpsym = methodTParams(mvarCILDef.Number) - mtpsym.setInfo(sig2typeBounds(mvarCILDef)) // we never skip bounds unlike in forJVM - } - - newMethodTParams.toList - } - } - - private def createMethod(method: MethodBase) { - - val flags = translateAttributes(method); - val owner = if (method.IsStatic()) statics else clazz; - val methodSym = owner.newMethod(getName(method), NoPosition, flags) - /* 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; -/* START CLR generics (snippet 4) */ - val mInfo = if (method.IsGeneric) genPolyType(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()) - clrTypes.constructors(methodSym) = method.asInstanceOf[ConstructorInfo] - else clrTypes.methods(methodSym) = method.asInstanceOf[MethodInfo]; - } - - private def createMethod(name: TermName, flags: Long, args: Array[MSILType], retType: MSILType, method: MethodInfo, statik: Boolean): Symbol = { - val mtype = methodType(args, getCLSType(retType)) - assert(mtype != null) - createMethod(name, flags, mtype, method, statik) - } - - private def createMethod(name: TermName, flags: Long, mtype: Symbol => Type, method: MethodInfo, statik: Boolean): Symbol = { - val methodSym: Symbol = (if (statik) statics else clazz).newMethod(name) - methodSym.setFlag(flags).setInfo(mtype(methodSym)) - (if (statik) staticDefs else instanceDefs).enter(methodSym) - if (method != null) - clrTypes.methods(methodSym) = method - methodSym - } - - private def createDelegateView(typ: MSILType) = { - val invoke: MethodInfo = typ.GetMember("Invoke")(0).asInstanceOf[MethodInfo]; - val invokeRetType: Type = getCLRType(invoke.ReturnType); - val invokeParamTypes: List[Type] =invoke.GetParameters().map(_.ParameterType).map(getCLSType).toList; - val funType: Type = definitions.functionType(invokeParamTypes, invokeRetType); - - val typClrType: Type = getCLRType(typ); - val flags = Flags.JAVA | Flags.STATIC | Flags.IMPLICIT; // todo: static? think not needed - - // create the forward view: delegate => function - val delegateParamTypes: List[Type] = List(typClrType); - // not ImplicitMethodType, this is for methods with implicit parameters (not implicit methods) - val forwardViewMethodType = (msym: Symbol) => JavaMethodType(msym.newSyntheticValueParams(delegateParamTypes), funType) - val fmsym = createMethod(nme.view_, flags, forwardViewMethodType, null, true); - - // create the backward view: function => delegate - val functionParamTypes: List[Type] = List(funType); - val backwardViewMethodType = (msym: Symbol) => JavaMethodType(msym.newSyntheticValueParams(functionParamTypes), typClrType) - val bmsym = createMethod(nme.view_, flags, backwardViewMethodType, null, true); - } - - private def createDelegateChainers(typ: MSILType) = { - val flags: Long = Flags.JAVA | Flags.FINAL - val args: Array[MSILType] = Array(typ) - - var s = createMethod(encode("+="), flags, args, clrTypes.VOID, clrTypes.DELEGATE_COMBINE, false); - s = createMethod(encode("-="), flags, args, clrTypes.VOID, clrTypes.DELEGATE_REMOVE, false); - - s = createMethod(nme.PLUS, flags, args, typ, clrTypes.DELEGATE_COMBINE, false); - s = createMethod(nme.MINUS, flags, args, typ, clrTypes.DELEGATE_REMOVE, false); - } - - private def getName(method: MethodBase): TermName = { - - def operatorOverload(name : String, paramsArity : Int) : Option[Name] = paramsArity match { - case 1 => name match { - // PartitionI.10.3.1 - case "op_Decrement" => Some(encode("--")) - case "op_Increment" => Some(encode("++")) - case "op_UnaryNegation" => Some(nme.UNARY_-) - case "op_UnaryPlus" => Some(nme.UNARY_+) - case "op_LogicalNot" => Some(nme.UNARY_!) - case "op_OnesComplement" => Some(nme.UNARY_~) - /* op_True and op_False have no operator symbol assigned, - Other methods that will have to be written in full are: - op_AddressOf & (unary) - op_PointerDereference * (unary) */ - case _ => None - } - case 2 => name match { - // PartitionI.10.3.2 - case "op_Addition" => Some(nme.ADD) - case "op_Subtraction" => Some(nme.SUB) - case "op_Multiply" => Some(nme.MUL) - case "op_Division" => Some(nme.DIV) - case "op_Modulus" => Some(nme.MOD) - case "op_ExclusiveOr" => Some(nme.XOR) - case "op_BitwiseAnd" => Some(nme.AND) - case "op_BitwiseOr" => Some(nme.OR) - case "op_LogicalAnd" => Some(nme.ZAND) - case "op_LogicalOr" => Some(nme.ZOR) - case "op_LeftShift" => Some(nme.LSL) - case "op_RightShift" => Some(nme.ASR) - case "op_Equality" => Some(nme.EQ) - case "op_GreaterThan" => Some(nme.GT) - case "op_LessThan" => Some(nme.LT) - case "op_Inequality" => Some(nme.NE) - case "op_GreaterThanOrEqual" => Some(nme.GE) - case "op_LessThanOrEqual" => Some(nme.LE) - - /* op_MemberSelection is reserved in Scala */ - - /* The standard does not assign operator symbols to op_Assign , op_SignedRightShift , op_UnsignedRightShift , - * and op_UnsignedRightShiftAssignment so those names will be used instead to invoke those methods. */ - - /* - The remaining binary operators are not overloaded in C# and are therefore not in widespread use. They have to be written in full. - - op_RightShiftAssignment >>= - op_MultiplicationAssignment *= - op_PointerToMemberSelection ->* - op_SubtractionAssignment -= - op_ExclusiveOrAssignment ^= - op_LeftShiftAssignment <<= - op_ModulusAssignment %= - op_AdditionAssignment += - op_BitwiseAndAssignment &= - op_BitwiseOrAssignment |= - op_Comma , - op_DivisionAssignment /= - */ - case _ => None - } - case _ => None - } - - if (method.IsConstructor()) return nme.CONSTRUCTOR; - val name = method.Name; - if (method.IsStatic()) { - if(method.IsSpecialName) { - val paramsArity = method.GetParameters().size - // handle operator overload, otherwise handle as any static method - val operName = operatorOverload(name, paramsArity) - if (operName.isDefined) { return operName.get; } - } - return newTermName(name); - } - val params = method.GetParameters(); - name match { - case "GetHashCode" if (params.length == 0) => nme.hashCode_; - case "ToString" if (params.length == 0) => nme.toString_; - case "Finalize" if (params.length == 0) => nme.finalize_; - case "Equals" if (params.length == 1 && params(0).ParameterType == clrTypes.OBJECT) => - nme.equals_; - case "Invoke" if (clrTypes.isDelegateType(method.DeclaringType)) => nme.apply; - case _ => newTermName(name); - } - } - - //########################################################################## - - private def methodType(method: MethodBase, rettype: MSILType): Symbol => Type = { - val rtype = getCLSType(rettype); - if (rtype == null) null else methodType(method, rtype); - } - - /** Return a method type for the given method. */ - private def methodType(method: MethodBase, rettype: Type): Symbol => Type = - methodType(method.GetParameters().map(_.ParameterType), rettype); - - /** Return a method type for the provided argument types and return type. */ - private def methodType(argtypes: Array[MSILType], rettype: Type): Symbol => Type = { - def paramType(typ: MSILType): Type = - if (typ eq clrTypes.OBJECT) definitions.AnyClass.tpe // TODO a hack to compile scalalib, should be definitions.AnyRefClass.tpe - else getCLSType(typ); - val ptypes = argtypes.map(paramType).toList; - if (ptypes.contains(null)) null - else method => JavaMethodType(method.newSyntheticValueParams(ptypes), rettype); - } - - //########################################################################## - - private def getClassType(typ: MSILType): Type = { - assert(typ != null); - val res = rootMirror.getClassByName(typ.FullName.replace('+', '.') : TypeName).tpe; - //if (res.isError()) - // global.reporter.error("unknown class reference " + type.FullName); - res - } - - private def getCLSType(typ: MSILType): Type = { // getCLS returns non-null for types GenMSIL can handle, be they CLS-compliant or not - if (typ.IsTMVarUsage()) - /* 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 */ - || typ.IsNotPublic() || typ.IsNestedPrivate() - || typ.IsNestedAssembly() || typ.IsNestedFamANDAssem() - || typ.IsPointer() - || (typ.IsArray() && getCLRType(typ.GetElementType()) == null) /* TODO hack: getCLR instead of getCLS */ - || (typ.IsByRef() && !typ.GetElementType().CanBeTakenAddressOf())) - null - else - getCLRType(typ) - } - - private def getCLRTypeIfPrimitiveNullOtherwise(typ: MSILType): Type = - if (typ == clrTypes.OBJECT) - definitions.ObjectClass.tpe; - else if (typ == clrTypes.VALUE_TYPE) - definitions.AnyValClass.tpe - else if (typ == clrTypes.STRING) - definitions.StringClass.tpe; - else if (typ == clrTypes.VOID) - definitions.UnitClass.tpe - else if (typ == clrTypes.BOOLEAN) - definitions.BooleanClass.tpe - else if (typ == clrTypes.CHAR) - definitions.CharClass.tpe - else if ((typ == clrTypes.BYTE) || (typ == clrTypes.UBYTE)) // TODO U... is a hack to compile scalalib - definitions.ByteClass.tpe - else if ((typ == clrTypes.SHORT) || (typ == clrTypes.SHORT)) // TODO U... is a hack to compile scalalib - definitions.ShortClass.tpe - else if ((typ == clrTypes.INT) || (typ == clrTypes.UINT)) // TODO U... is a hack to compile scalalib - definitions.IntClass.tpe - else if ((typ == clrTypes.LONG) || (typ == clrTypes.LONG)) // TODO U... is a hack to compile scalalib - definitions.LongClass.tpe - else if (typ == clrTypes.FLOAT) - definitions.FloatClass.tpe - else if (typ == clrTypes.DOUBLE) - definitions.DoubleClass.tpe - else null - - - private def getCLRType(tMSIL: MSILType): Type = { - var res = getCLRTypeIfPrimitiveNullOtherwise(tMSIL) - if (res != null) res - else if (tMSIL.isInstanceOf[ConstructedType]) { - val ct = tMSIL.asInstanceOf[ConstructedType] - /* 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]) { - /* 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 - // make unbounded Array[T] where T is a type variable into Array[T with Object] - // (this is necessary because such arrays have a representation which is incompatible - // with arrays of primitive types). - // TODO does that incompatibility also apply to .NET? - if (elemtp.typeSymbol.isAbstractType && !(elemtp <:< definitions.ObjectClass.tpe)) - elemtp = intersectionType(List(elemtp, definitions.ObjectClass.tpe)) - appliedType(definitions.ArrayClass.tpe, List(elemtp)) - } else { - res = clrTypes.sym2type.get(tMSIL) match { - case Some(sym) => sym.tpe - case None => if (tMSIL.IsByRef && tMSIL.GetElementType.IsValueType) { - val addressed = getCLRType(tMSIL.GetElementType) - val clasym = addressed.typeSymbolDirect // TODO should be .typeSymbol? - clasym.info.load(clasym) - val secondAttempt = clrTypes.sym2type.get(tMSIL) - secondAttempt match { case Some(sym) => sym.tpe - case None => null - } - } else getClassType(tMSIL) - } - if (res == null) - null // TODO new RuntimeException() - else res - } - } - - // the values are Java-Box-Classes (e.g. Integer, Boolean, Character) - // java.lang.Number to get the value (if a number, not for boolean, character) - // see ch.epfl.lamp.compiler.msil.util.PEStream.java - def getConstant(constType: Type, value: Object): Constant = { - val typeClass = constType.typeSymbol - if (typeClass == definitions.BooleanClass) - Constant(value.asInstanceOf[java.lang.Boolean].booleanValue) - else if (typeClass == definitions.ByteClass) - Constant(value.asInstanceOf[java.lang.Number].byteValue) - else if (typeClass == definitions.ShortClass) - Constant(value.asInstanceOf[java.lang.Number].shortValue) - else if (typeClass == definitions.CharClass) - Constant(value.asInstanceOf[java.lang.Character].charValue) - else if (typeClass == definitions.IntClass) - Constant(value.asInstanceOf[java.lang.Number].intValue) - else if (typeClass == definitions.LongClass) - Constant(value.asInstanceOf[java.lang.Number].longValue) - else if (typeClass == definitions.FloatClass) - Constant(value.asInstanceOf[java.lang.Number].floatValue) - else if (typeClass == definitions.DoubleClass) - Constant(value.asInstanceOf[java.lang.Number].doubleValue) - else if (typeClass == definitions.StringClass) - Constant(value.asInstanceOf[java.lang.String]) - else - abort("illegal value: " + value + ", class-symbol: " + typeClass) - } - - def isDefinedAtgetConstant(constType: Type): Boolean = { - val typeClass = constType.typeSymbol - if ( (typeClass == definitions.BooleanClass) - || (typeClass == definitions.ByteClass) - || (typeClass == definitions.ShortClass) - || (typeClass == definitions.CharClass) - || (typeClass == definitions.IntClass) - || (typeClass == definitions.LongClass) - || (typeClass == definitions.FloatClass) - || (typeClass == definitions.DoubleClass) - || (typeClass == definitions.StringClass) - ) - true - else - false - } - - private def translateAttributes(typ: MSILType): Long = { - var flags: Long = Flags.JAVA; - if (typ.IsNotPublic() || typ.IsNestedPrivate() - || typ.IsNestedAssembly() || typ.IsNestedFamANDAssem()) - flags = flags | Flags.PRIVATE; - else if (typ.IsNestedFamily() || typ.IsNestedFamORAssem()) - flags = flags | Flags.PROTECTED; - if (typ.IsAbstract()) - flags = flags | Flags.ABSTRACT; - if (typ.IsSealed()) - flags = flags | Flags.FINAL; - if (typ.IsInterface()) - flags = flags | Flags.INTERFACE | Flags.TRAIT | Flags.ABSTRACT; - - flags - } - - private def translateAttributes(field: FieldInfo): Long = { - var flags: Long = Flags.JAVA; - if (field.IsPrivate() || field.IsAssembly() || field.IsFamilyAndAssembly()) - flags = flags | Flags.PRIVATE; - else if (field.IsFamily() || field.IsFamilyOrAssembly()) - flags = flags | Flags.PROTECTED; - if (field.IsInitOnly() || field.IsLiteral()) - flags = flags | Flags.FINAL; - else - flags = flags | Flags.MUTABLE; - if (field.IsStatic) - flags = flags | Flags.STATIC - - flags - } - - private def translateAttributes(method: MethodBase): Long = { - var flags: Long = Flags.JAVA; - if (method.IsPrivate() || method.IsAssembly() || method.IsFamilyAndAssembly()) - flags = flags | Flags.PRIVATE; - else if (method.IsFamily() || method.IsFamilyOrAssembly()) - flags = flags | Flags.PROTECTED; - if (method.IsAbstract()) - flags = flags | Flags.DEFERRED; - if (method.IsStatic) - flags = flags | Flags.STATIC - - flags - } -} |