summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2010-02-04 13:33:06 +0000
committerPaul Phillips <paulp@improving.org>2010-02-04 13:33:06 +0000
commita1a6ab90ac5fe7d5db2f6fba788ce14c1613d9c6 (patch)
treea70c578ce72906368a8e733ac8aff914ae8cbf42 /src
parent9ee1f2f3b8ed91897bb298592f8a600ff5e4622d (diff)
downloadscala-a1a6ab90ac5fe7d5db2f6fba788ce14c1613d9c6.tar.gz
scala-a1a6ab90ac5fe7d5db2f6fba788ce14c1613d9c6.tar.bz2
scala-a1a6ab90ac5fe7d5db2f6fba788ce14c1613d9c6.zip
The remainder of isolating MSIL from the rest o...
The remainder of isolating MSIL from the rest of the classpath code. To accomplish this I made ClassRep an inner class of ClassPath (which given the broad definition of ClassPath already in place, it conceptually is already) and as a bonus this allowed dropping its type parameter. Review by rytz.
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala9
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala6
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala17
-rw-r--r--src/compiler/scala/tools/nsc/util/ClassPath.scala217
-rw-r--r--src/compiler/scala/tools/nsc/util/MsilClassPath.scala154
-rw-r--r--src/scalap/scala/tools/scalap/Main.scala3
6 files changed, 211 insertions, 195 deletions
diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
index 23e525d8c8..a3751f0c48 100644
--- a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
+++ b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
@@ -14,7 +14,7 @@ import ch.epfl.lamp.compiler.msil.{Type => MSILType, Attribute => MSILAttribute}
import scala.collection.mutable.{HashMap, HashSet}
import scala.compat.Platform.currentTime
import scala.tools.nsc.io.AbstractFile
-import scala.tools.nsc.util.{ClassPath, ClassRep, JavaClassPath, MsilClassPath}
+import scala.tools.nsc.util.{ ClassPath, JavaClassPath }
import classfile.ClassfileParser
import Flags._
@@ -136,7 +136,7 @@ abstract class SymbolLoaders {
* (anonymous classes, implementation classes, module classes), their
* symtab is encoded in the pickle of another class.
*/
- protected def doLoad(cls: ClassRep[T]): Boolean
+ protected def doLoad(cls: classpath.AnyClassRep): Boolean
protected def newClassLoader(bin: T): SymbolLoader
@@ -197,12 +197,11 @@ abstract class SymbolLoaders {
}
}
-
class JavaPackageLoader(classpath: ClassPath[AbstractFile]) extends PackageLoader(classpath) {
protected def needCompile(bin: AbstractFile, src: AbstractFile) =
(src.lastModified >= bin.lastModified)
- protected def doLoad(cls: ClassRep[AbstractFile]) = true
+ protected def doLoad(cls: classpath.AnyClassRep) = true
protected def newClassLoader(bin: AbstractFile) =
new ClassfileLoader(bin)
@@ -215,7 +214,7 @@ abstract class SymbolLoaders {
protected def needCompile(bin: MSILType, src: AbstractFile) =
false // always use compiled file on .net
- protected def doLoad(cls: ClassRep[MSILType]) = {
+ protected def doLoad(cls: classpath.AnyClassRep) = {
if (cls.binary.isDefined) {
val typ = cls.binary.get
if (typ.IsDefined(clrTypes.SCALA_SYMTAB_ATTR, false)) {
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
index 34b7f9f8af..538a606243 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
@@ -14,7 +14,6 @@ import java.lang.Integer.toHexString
import scala.collection.immutable.{Map, ListMap}
import scala.collection.mutable.{ListBuffer, ArrayBuffer}
import scala.tools.nsc.io.AbstractFile
-import scala.tools.nsc.util.ClassRep
import scala.annotation.switch
/** This abstract class implements a class file parser.
@@ -953,9 +952,8 @@ abstract class ClassfileParser {
for (entry <- innerClasses.valuesIterator) {
// create a new class member for immediate inner classes
if (entry.outerName == externalName) {
- val file = global.classPath.findClass(entry.externalName.toString) match {
- case Some(ClassRep(Some(binary: AbstractFile), _)) => binary
- case _ => throw new AssertionError(entry.externalName)
+ val file = global.classPath.findAbstractFile(entry.externalName.toString) getOrElse {
+ throw new AssertionError(entry.externalName)
}
enterClassAndModule(entry, new global.loaders.ClassfileLoader(file), entry.jflags)
}
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
index 0c466e24f5..8a77be6d83 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
@@ -14,7 +14,6 @@ import scala.collection.mutable._
import scala.tools.nsc._
import scala.tools.nsc.backend.icode._
import scala.tools.nsc.io._
-import scala.tools.nsc.util.ClassRep
import ClassfileConstants._
import Flags._
@@ -50,18 +49,10 @@ abstract class ICodeReader extends ClassfileParser {
isScalaModule = cls.isModule && !cls.hasFlag(JAVA)
log("Reading class: " + cls + " isScalaModule?: " + isScalaModule)
val name = cls.fullName('.') + (if (sym.hasFlag(MODULE)) "$" else "")
- classPath.findClass(name) match {
- case Some(ClassRep(bin, _)) =>
- assert(bin.isDefined, "No classfile for " + cls)
- classFile = bin.get.asInstanceOf[AbstractFile]
-// if (isScalaModule)
-// sym = cls.linkedClassOfModule
-
-// for (s <- cls.info.members)
-// Console.println("" + s + ": " + s.tpe)
- parse(classFile, sym)
- case _ =>
- log("Could not find: " + cls)
+
+ classPath.findAbstractFile(name) match {
+ case Some(classFile) => parse(classFile, sym)
+ case _ => log("Could not find: " + cls)
}
(staticCode, instanceCode)
diff --git a/src/compiler/scala/tools/nsc/util/ClassPath.scala b/src/compiler/scala/tools/nsc/util/ClassPath.scala
index a5e62ff542..db559891df 100644
--- a/src/compiler/scala/tools/nsc/util/ClassPath.scala
+++ b/src/compiler/scala/tools/nsc/util/ClassPath.scala
@@ -16,9 +16,6 @@ import scala.util.Sorting
import scala.collection.mutable.{ListBuffer, ArrayBuffer, HashSet => MutHashSet}
import scala.tools.nsc.io.AbstractFile
-import ch.epfl.lamp.compiler.msil.{Type => MSILType, Assembly}
-
-
/** <p>
* This module provides star expansion of '-classpath' option arguments, behaves the same as
* java, see [http://java.sun.com/javase/6/docs/technotes/tools/windows/classpath.html]
@@ -61,59 +58,46 @@ object ClassPath {
def expandPath(path: String, expandStar: Boolean = true): List[String] =
if (expandStar) splitPath(path).flatMap(expandS(_))
else splitPath(path)
-
- var XO = false
-
- def collectTypes(assemFile: AbstractFile) = {
- var res: Array[MSILType] = MSILType.EmptyTypes
- val assem = Assembly.LoadFrom(assemFile.path)
- if (assem != null) {
- // DeclaringType == null: true for non-inner classes
- res = assem.GetTypes() filter (_.DeclaringType == null)
- Sorting.stableSort(res, (t1: MSILType, t2: MSILType) => (t1.FullName compareTo t2.FullName) < 0)
- }
- res
- }
-}
-
-/**
- * Represents classes which can be loaded with a ClassfileLoader/MSILTypeLoader
- * and / or a SourcefileLoader.
- */
-case class ClassRep[T](binary: Option[T], source: Option[AbstractFile]) {
- def name = {
- if (binary.isDefined) binary.get match {
- case f: AbstractFile =>
- assert(f.name.endsWith(".class"), f.name)
- f.name dropRight 6
- case t: MSILType =>
- t.Name
- case c =>
- throw new FatalError("Unexpected binary class representation: "+ c)
- } else {
- assert(source.isDefined)
- val nme = source.get.name
- if (nme.endsWith(".scala"))
- nme dropRight 6
- else if (nme.endsWith(".java"))
- nme dropRight 5
- else
- throw new FatalError("Unexpected source file ending: " + nme)
- }
- }
}
/**
* Represents a package which contains classes and other packages
*/
abstract class ClassPath[T] {
+ type AnyClassRep = ClassPath[T]#ClassRep
/**
* The short name of the package (without prefix)
*/
def name: String
- val classes: List[ClassRep[T]]
+ val classes: List[AnyClassRep]
val packages: List[ClassPath[T]]
val sourcepaths: List[AbstractFile]
+ protected def nameOfBinaryRepresentation(binary: T): String = binary match {
+ case f: AbstractFile =>
+ assert(f.name endsWith ".class", f.name)
+ f.name dropRight 6
+ case _ =>
+ throw new FatalError("Unexpected binary class representation: " + binary)
+ }
+
+ /**
+ * Represents classes which can be loaded with a ClassfileLoader/MSILTypeLoader
+ * and / or a SourcefileLoader.
+ */
+ case class ClassRep(binary: Option[T], source: Option[AbstractFile]) {
+ def name: String = binary match {
+ case Some(x) => nameOfBinaryRepresentation(x)
+ case _ =>
+ assert(source.isDefined)
+ val nme = source.get.name
+ if (nme.endsWith(".scala"))
+ nme dropRight 6
+ else if (nme.endsWith(".java"))
+ nme dropRight 5
+ else
+ throw new FatalError("Unexpected source file ending: " + nme)
+ }
+ }
/** Whether this classpath is being used for an optimized build.
* Why this is necessary is something which should really be documented,
@@ -136,14 +120,23 @@ abstract class ClassPath[T] {
* Find a ClassRep given a class name of the form "package.subpackage.ClassName".
* Does not support nested classes on .NET
*/
- def findClass(name: String): Option[ClassRep[T]] = {
+ def findClass(name: String): Option[AnyClassRep] = {
val i = name.indexOf('.')
if (i < 0) {
- classes.find(c => c.name == name)
+ classes.find(_.name == name)
} else {
val pkg = name take i
val rest = name drop (i + 1)
- packages.find(p => p.name == pkg).flatMap(_.findClass(rest))
+ (packages find (_.name == pkg) flatMap (_ findClass rest)) map {
+ case x: ClassRep => x
+ case x => throw new FatalError("Unexpected ClassRep '%s' found searching for name '%s'".format(x, name))
+ }
+ }
+ }
+ def findAbstractFile(name: String): Option[AbstractFile] = {
+ findClass(name) match {
+ case Some(ClassRep(Some(x: AbstractFile), _)) => Some(x)
+ case _ => None
}
}
}
@@ -155,10 +148,10 @@ class SourcePath[T](dir: AbstractFile, val isOptimized: Boolean) extends ClassPa
def name = dir.name
lazy val classes = {
- val cls = new ListBuffer[ClassRep[T]]
+ val cls = new ListBuffer[ClassRep]
for (f <- dir.iterator) {
if (!f.isDirectory && validSourceFile(f.name))
- cls += ClassRep[T](None, Some(f))
+ cls += ClassRep(None, Some(f))
}
cls.toList
}
@@ -184,7 +177,7 @@ class DirectoryClassPath(dir: AbstractFile, val isOptimized: Boolean) extends Cl
def name = dir.name
lazy val classes = {
- val cls = new ListBuffer[ClassRep[AbstractFile]]
+ val cls = new ListBuffer[ClassRep]
for (f <- dir.iterator) {
if (!f.isDirectory && validClassFile(f.name))
cls += ClassRep(Some(f), None)
@@ -206,69 +199,6 @@ class DirectoryClassPath(dir: AbstractFile, val isOptimized: Boolean) extends Cl
override def toString() = "directory classpath: "+ dir.toString()
}
-
-
-/**
- * A assembly file (dll / exe) containing classes and namespaces
- */
-class AssemblyClassPath(types: Array[MSILType], namespace: String, val isOptimized: Boolean) extends ClassPath[MSILType] {
- def name = {
- val i = namespace.lastIndexOf('.')
- if (i < 0) namespace
- else namespace drop (i + 1)
- }
-
- def this(assemFile: AbstractFile, isOptimized: Boolean) {
- this(ClassPath.collectTypes(assemFile), "", isOptimized)
- }
-
- private lazy val first: Int = {
- var m = 0
- var n = types.length - 1
- while (m < n) {
- val l = (m + n) / 2
- val res = types(l).FullName.compareTo(namespace)
- if (res < 0) m = l + 1
- else n = l
- }
- if (types(m).FullName.startsWith(namespace)) m else types.length
- }
-
- lazy val classes = {
- val cls = new ListBuffer[ClassRep[MSILType]]
- var i = first
- while (i < types.length && types(i).Namespace.startsWith(namespace)) {
- // CLRTypes used to exclude java.lang.Object and java.lang.String (no idea why..)
- if (types(i).Namespace == namespace)
- cls += ClassRep(Some(types(i)), None)
- i += 1
- }
- cls.toList
- }
-
- lazy val packages = {
- val nsSet = new MutHashSet[String]
- var i = first
- while (i < types.length && types(i).Namespace.startsWith(namespace)) {
- val subns = types(i).Namespace
- if (subns.length > namespace.length) {
- // example: namespace = "System", subns = "System.Reflection.Emit"
- // => find second "." and "System.Reflection" to nsSet.
- val end = subns.indexOf('.', namespace.length + 1)
- nsSet += (if (end < 0) subns
- else subns.substring(0, end))
- }
- i += 1
- }
- for (ns <- nsSet.toList)
- yield new AssemblyClassPath(types, ns, isOptimized)
- }
-
- val sourcepaths: List[AbstractFile] = Nil
-
- override def toString() = "assembly classpath "+ namespace
-}
-
/**
* A classpath unifying multiple class- and sourcepath entries.
*/
@@ -279,8 +209,8 @@ abstract class MergedClassPath[T] extends ClassPath[T] {
def name = entries.head.name
- lazy val classes: List[ClassRep[T]] = {
- val cls = new ListBuffer[ClassRep[T]]
+ lazy val classes: List[AnyClassRep] = {
+ val cls = new ListBuffer[AnyClassRep]
for (e <- entries; c <- e.classes) {
val name = c.name
val idx = cls.indexWhere(cl => cl.name == name)
@@ -337,6 +267,7 @@ class JavaClassPath(boot: String, ext: String, user: String, source: String, Xco
extends MergedClassPath[AbstractFile] {
protected val entries: List[ClassPath[AbstractFile]] = assembleEntries()
+
private def assembleEntries(): List[ClassPath[AbstractFile]] = {
import ClassPath._
val etr = new ListBuffer[ClassPath[AbstractFile]]
@@ -392,59 +323,3 @@ extends MergedClassPath[AbstractFile] {
etr.toList
}
}
-
-/**
- * The classpath when compiling with target:msil. Binary files are represented as
- * MSILType values.
- */
-class MsilClassPath(ext: String, user: String, source: String, val isOptimized: Boolean) extends MergedClassPath[MSILType] {
- protected val entries: List[ClassPath[MSILType]] = assembleEntries()
-
- private def assembleEntries(): List[ClassPath[MSILType]] = {
- import ClassPath._
- val etr = new ListBuffer[ClassPath[MSILType]]
- val names = new MutHashSet[String]
-
- // 1. Assemblies from -Xassem-extdirs
- for (dirName <- expandPath(ext, expandStar = false)) {
- val dir = AbstractFile.getDirectory(dirName)
- if (dir ne null) {
- for (file <- dir) {
- val name = file.name.toLowerCase
- if (name.endsWith(".dll") || name.endsWith(".exe")) {
- names += name
- etr += new AssemblyClassPath(file, isOptimized)
- }
- }
- }
- }
-
- // 2. Assemblies from -Xassem-path
- for (fileName <- expandPath(user, expandStar = false)) {
- val file = AbstractFile.getFile(fileName)
- if (file ne null) {
- val name = file.name.toLowerCase
- if (name.endsWith(".dll") || name.endsWith(".exe")) {
- names += name
- etr += new AssemblyClassPath(file, isOptimized)
- }
- }
- }
-
- def check(n: String) {
- if (!names.contains(n))
- throw new AssertionError("Cannot find assembly "+ n +
- ". Use -Xassem-extdirs or -Xassem-path to specify its location")
- }
- check("mscorlib.dll")
- check("scalaruntime.dll")
-
- // 3. Source path
- for (dirName <- expandPath(source, expandStar = false)) {
- val file = AbstractFile.getDirectory(dirName)
- if (file ne null) etr += new SourcePath[MSILType](file, isOptimized)
- }
-
- etr.toList
- }
-}
diff --git a/src/compiler/scala/tools/nsc/util/MsilClassPath.scala b/src/compiler/scala/tools/nsc/util/MsilClassPath.scala
new file mode 100644
index 0000000000..3f69e67233
--- /dev/null
+++ b/src/compiler/scala/tools/nsc/util/MsilClassPath.scala
@@ -0,0 +1,154 @@
+/* NSC -- new Scala compiler
+ * Copyright 2006-2010 LAMP/EPFL
+ * @author Martin Odersky
+ */
+
+// $Id$
+
+package scala.tools.nsc
+package util
+
+import java.io.File
+import java.net.URL
+import java.util.StringTokenizer
+import scala.util.Sorting
+
+import scala.collection.mutable.{ListBuffer, ArrayBuffer, HashSet => MutHashSet}
+import scala.tools.nsc.io.AbstractFile
+
+import ch.epfl.lamp.compiler.msil.{Type => MSILType, Assembly}
+
+/** Keeping the MSIL classpath code in its own file is important to make sure
+ * we don't accidentally introduce a dependency on msil.jar in the jvm.
+ */
+
+object MsilClassPath {
+ def collectTypes(assemFile: AbstractFile) = {
+ var res: Array[MSILType] = MSILType.EmptyTypes
+ val assem = Assembly.LoadFrom(assemFile.path)
+ if (assem != null) {
+ // DeclaringType == null: true for non-inner classes
+ res = assem.GetTypes() filter (_.DeclaringType == null)
+ Sorting.stableSort(res, (t1: MSILType, t2: MSILType) => (t1.FullName compareTo t2.FullName) < 0)
+ }
+ res
+ }
+}
+
+/**
+ * A assembly file (dll / exe) containing classes and namespaces
+ */
+class AssemblyClassPath(types: Array[MSILType], namespace: String, val isOptimized: Boolean) extends ClassPath[MSILType] {
+ def name = {
+ val i = namespace.lastIndexOf('.')
+ if (i < 0) namespace
+ else namespace drop (i + 1)
+ }
+
+ def this(assemFile: AbstractFile, isOptimized: Boolean) {
+ this(MsilClassPath.collectTypes(assemFile), "", isOptimized)
+ }
+
+ private lazy val first: Int = {
+ var m = 0
+ var n = types.length - 1
+ while (m < n) {
+ val l = (m + n) / 2
+ val res = types(l).FullName.compareTo(namespace)
+ if (res < 0) m = l + 1
+ else n = l
+ }
+ if (types(m).FullName.startsWith(namespace)) m else types.length
+ }
+
+ lazy val classes = {
+ val cls = new ListBuffer[ClassRep]
+ var i = first
+ while (i < types.length && types(i).Namespace.startsWith(namespace)) {
+ // CLRTypes used to exclude java.lang.Object and java.lang.String (no idea why..)
+ if (types(i).Namespace == namespace)
+ cls += ClassRep(Some(types(i)), None)
+ i += 1
+ }
+ cls.toList
+ }
+
+ lazy val packages = {
+ val nsSet = new MutHashSet[String]
+ var i = first
+ while (i < types.length && types(i).Namespace.startsWith(namespace)) {
+ val subns = types(i).Namespace
+ if (subns.length > namespace.length) {
+ // example: namespace = "System", subns = "System.Reflection.Emit"
+ // => find second "." and "System.Reflection" to nsSet.
+ val end = subns.indexOf('.', namespace.length + 1)
+ nsSet += (if (end < 0) subns
+ else subns.substring(0, end))
+ }
+ i += 1
+ }
+ for (ns <- nsSet.toList)
+ yield new AssemblyClassPath(types, ns, isOptimized)
+ }
+
+ val sourcepaths: List[AbstractFile] = Nil
+
+ override def toString() = "assembly classpath "+ namespace
+}
+
+/**
+ * The classpath when compiling with target:msil. Binary files are represented as
+ * MSILType values.
+ */
+class MsilClassPath(ext: String, user: String, source: String, val isOptimized: Boolean) extends MergedClassPath[MSILType] {
+ protected val entries: List[ClassPath[MSILType]] = assembleEntries()
+ override protected def nameOfBinaryRepresentation(binary: MSILType) = binary.Name
+
+ private def assembleEntries(): List[ClassPath[MSILType]] = {
+ import ClassPath._
+ val etr = new ListBuffer[ClassPath[MSILType]]
+ val names = new MutHashSet[String]
+
+ // 1. Assemblies from -Xassem-extdirs
+ for (dirName <- expandPath(ext, expandStar = false)) {
+ val dir = AbstractFile.getDirectory(dirName)
+ if (dir ne null) {
+ for (file <- dir) {
+ val name = file.name.toLowerCase
+ if (name.endsWith(".dll") || name.endsWith(".exe")) {
+ names += name
+ etr += new AssemblyClassPath(file, isOptimized)
+ }
+ }
+ }
+ }
+
+ // 2. Assemblies from -Xassem-path
+ for (fileName <- expandPath(user, expandStar = false)) {
+ val file = AbstractFile.getFile(fileName)
+ if (file ne null) {
+ val name = file.name.toLowerCase
+ if (name.endsWith(".dll") || name.endsWith(".exe")) {
+ names += name
+ etr += new AssemblyClassPath(file, isOptimized)
+ }
+ }
+ }
+
+ def check(n: String) {
+ if (!names.contains(n))
+ throw new AssertionError("Cannot find assembly "+ n +
+ ". Use -Xassem-extdirs or -Xassem-path to specify its location")
+ }
+ check("mscorlib.dll")
+ check("scalaruntime.dll")
+
+ // 3. Source path
+ for (dirName <- expandPath(source, expandStar = false)) {
+ val file = AbstractFile.getDirectory(dirName)
+ if (file ne null) etr += new SourcePath[MSILType](file, isOptimized)
+ }
+
+ etr.toList
+ }
+} \ No newline at end of file
diff --git a/src/scalap/scala/tools/scalap/Main.scala b/src/scalap/scala/tools/scalap/Main.scala
index dcc028d489..3a4779c6b7 100644
--- a/src/scalap/scala/tools/scalap/Main.scala
+++ b/src/scalap/scala/tools/scalap/Main.scala
@@ -279,12 +279,11 @@ object Main {
}
object EmptyClasspath extends ClassPath[AbstractFile] {
- import tools.nsc.util.ClassRep
/**
* The short name of the package (without prefix)
*/
def name: String = ""
- val classes: List[ClassRep[AbstractFile]] = Nil
+ val classes: List[ClassRep] = Nil
val packages: List[ClassPath[AbstractFile]] = Nil
val sourcepaths: List[AbstractFile] = Nil
def isOptimized = false