new classpaths. cleaned up scopes. removed scope kinds. cleaned up symbol loading, integrated msil types, fix separate compilation for msil. Symbol.sourceFile only set for classes which are being compiled.

git-svn-id: http://lampsvn.epfl.ch/svn-repos/scala/scala/trunk@19285 5e8d7ff9-d8ef-0310-90f0-a4852d11357a
This commit is contained in:
rytz 2009-10-26 09:56:33 +00:00
parent 1b2fcb0c1e
commit d6ef73c9a2
54 changed files with 829 additions and 1050 deletions

View File

@ -245,6 +245,7 @@ INITIALISATION
<pathelement location="${lib.starr.jar}"/>
<pathelement location="${comp.starr.jar}"/>
<pathelement location="${lib.dir}/fjbg.jar"/>
<pathelement location="${lib.dir}/msil.jar"/>
<pathelement location="${ant.jar}"/>
</path>
<taskdef resource="scala/tools/ant/sabbus/antlib.xml" classpathref="starr.classpath"/>
@ -371,6 +372,7 @@ LOCAL REFERENCE BUILD (LOCKER)
<pathelement location="${build-locker.dir}/classes/library"/>
<pathelement location="${build-locker.dir}/classes/compiler"/>
<pathelement location="${lib.dir}/fjbg.jar"/>
<pathelement location="${lib.dir}/msil.jar"/>
<pathelement location="${ant.jar}"/>
</path>
</target>
@ -688,6 +690,7 @@ QUICK BUILD (QUICK)
<pathelement location="${build-quick.dir}/classes/compiler"/>
<pathelement location="${build-quick.dir}/classes/scalap"/>
<pathelement location="${fjbg.jar}"/>
<pathelement location="${msil.jar}"/>
<pathelement location="${jline.jar}"/>
</path>
<taskdef name="quick-bin" classname="scala.tools.ant.ScalaTool" classpathref="quick.bin.classpath"/>
@ -730,6 +733,7 @@ QUICK BUILD (QUICK)
<pathelement location="${build-quick.dir}/classes/library"/>
<pathelement location="${build-quick.dir}/classes/compiler"/>
<pathelement location="${fjbg.jar}"/>
<pathelement location="${msil.jar}"/>
<pathelement location="${ant.jar}"/>
</path>
</target>

View File

@ -52,11 +52,15 @@ class ScalacFork extends MatchingTask with TaskArgs {
if (!compTarget.isEmpty) settings.target = compTarget.get
if (!compilationPath.isEmpty) settings.classpath = compilationPath.get
if (!sourcePath.isEmpty) settings.sourcepath = sourcePath.get
if (compTarget.isDefined && compTarget.get == "msil") settings.sourcedir = sourceDir.get
if (!params.isEmpty) settings.more = params.get
// not yet used: compilerPath, sourcedir (used in mapper), failonerror, timeout
val mapper = new GlobPatternMapper()
if (compTarget.isDefined && compTarget.get == "msil")
mapper.setTo("*.msil")
else
mapper.setTo("*.class")
mapper.setFrom("*.scala")
val includedFiles: Array[File] =

View File

@ -33,6 +33,10 @@ class Settings {
def sourcepath = sourcepathBf.get
def sourcepath_=(p: Path): this.type = { sourcepathBf = Some(p); this }
private var sourcedirBf: Option[File] = None
def sourcedir = sourcedirBf.get
def sourcedir_=(p: File): this.type = { sourcedirBf = Some(p); this }
private var bootclasspathBf: Option[Path] = None
def bootclasspath = bootclasspathBf.get
def bootclasspath_=(p: Path): this.type = { bootclasspathBf = Some(p); this }
@ -66,6 +70,7 @@ class Settings {
(if (uncheckedBf) "-unchecked" :: Nil else Nil) :::
(if (!classpathBf.isEmpty) "-classpath" :: classpath.toString :: Nil else Nil) :::
(if (!sourcepathBf.isEmpty) "-sourcepath" :: sourcepath.toString :: Nil else Nil) :::
(if (!sourcedirBf.isEmpty) "-Xsourcedir" :: sourcedir.toString :: Nil else Nil) :::
(if (!bootclasspathBf.isEmpty) "-bootclasspath" :: bootclasspath.toString :: Nil else Nil) :::
(if (!extdirsBf.isEmpty) "-extdirs" :: extdirs.toString :: Nil else Nil) :::
(if (!dBf.isEmpty) "-d" :: d.getAbsolutePath :: Nil else Nil) :::
@ -80,6 +85,7 @@ class Settings {
this.uncheckedBf == cs.uncheckedBf &&
this.classpathBf == cs.classpathBf &&
this.sourcepathBf == cs.sourcepathBf &&
this.sourcedirBf == cs.sourcedirBf &&
this.bootclasspathBf == cs.bootclasspathBf &&
this.extdirsBf == cs.extdirsBf &&
this.dBf == cs.dBf &&

View File

@ -67,4 +67,4 @@ if [ -z "$JAVACMD" -a -n "$JAVA_HOME" -a -x "$JAVA_HOME/bin/java" ]; then
JAVACMD="$JAVA_HOME/bin/java"
fi
exec "${JAVACMD:=java}" $JAVA_OPTS -cp "$TOOL_CLASSPATH" -Dscala.home="$SCALA_HOME" -Denv.classpath="$CLASSPATH" -Denv.emacs="$EMACS" @properties@ @class@ @toolflags@ "$@@"
exec "${JAVACMD:=java}" $JAVA_OPTS -cp "$TOOL_CLASSPATH" -Dscala.home="$SCALA_HOME" -Denv.emacs="$EMACS" @properties@ @class@ @toolflags@ "$@@"

View File

@ -47,7 +47,7 @@ if "%_TOOL_CLASSPATH%"=="" (
)
)
set _PROPS=-Dscala.home="%_SCALA_HOME%" -Denv.classpath="%CLASSPATH%" -Denv.emacs="%EMACS%" @properties@
set _PROPS=-Dscala.home="%_SCALA_HOME%" -Denv.emacs="%EMACS%" @properties@
rem echo "%_JAVACMD%" %_JAVA_OPTS% %_PROPS% -cp "%_TOOL_CLASSPATH%" @class@ @toolflags@ %_ARGS%
"%_JAVACMD%" %_JAVA_OPTS% %_PROPS% -cp "%_TOOL_CLASSPATH%" @class@ @toolflags@ %_ARGS%

View File

@ -12,7 +12,7 @@ import java.nio.charset._
import compat.Platform.currentTime
import scala.tools.nsc.io.{SourceReader, AbstractFile}
import scala.tools.nsc.reporters._
import scala.tools.nsc.util.{ClassPath, SourceFile, BatchSourceFile, OffsetPosition, RangePosition}
import scala.tools.nsc.util.{ClassPath, MsilClassPath, JavaClassPath, SourceFile, BatchSourceFile, OffsetPosition, RangePosition}
import scala.collection.mutable.{HashSet, HashMap, ListBuffer}
@ -252,23 +252,15 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
}
}
lazy val classPath0 = new ClassPath(false && onlyPresentation)
lazy val classPath =
lazy val classPath = {
ClassPath.XO = settings.XO.value
if (forMSIL)
new classPath0.Build(settings.sourcepath.value, settings.outdir.value)
new MsilClassPath(settings.assemextdirs.value, settings.assemrefs.value,
settings.sourcepath.value)
else
new classPath0.Build(settings.classpath.value, settings.sourcepath.value,
settings.outdir.value, settings.bootclasspath.value,
settings.extdirs.value, settings.Xcodebase.value)
/* .NET's equivalent of a classpath */
lazy val assemrefs = {
import java.util.{StringTokenizer}
val set = new HashSet[File]
val assems = new StringTokenizer(settings.assemrefs.value, File.pathSeparator)
while (assems.hasMoreTokens())
set += new java.io.File(assems.nextToken())
set
new JavaClassPath(settings.bootclasspath.value, settings.extdirs.value,
settings.classpath.value, settings.sourcepath.value,
settings.Xcodebase.value)
}
if (settings.verbose.value) {
@ -286,20 +278,13 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
getSourceFile(f)
}
def getSourceFile(clazz: Symbol): SourceFile = {
val ret = classPath.root.find(clazz.fullNameString(File.separatorChar), false)
if (!ret.isSourceFile) throw new FileNotFoundException(
"source file for " + clazz + " could not be found")
getSourceFile(ret.sourceFile)
lazy val loaders = new SymbolLoaders {
val global: Global.this.type = Global.this
}
lazy val loaders : SymbolLoaders { val global : Global.this.type } = new {
val global: Global.this.type = Global.this
} with SymbolLoaders
def rootLoader: LazyType =
if (forMSIL) new loaders.NamespaceLoader(classPath.root)
else new loaders.PackageLoader(classPath.root /* getRoot() */)
if (forMSIL) new loaders.NamespaceLoader(classPath.asInstanceOf[MsilClassPath])
else new loaders.JavaPackageLoader(classPath.asInstanceOf[JavaClassPath])
// ------------ Phases -------------------------------------------}
@ -905,8 +890,7 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
" was found\n(This file cannot be loaded as a source file)"
inform(msg)
throw new FatalError(msg)
}
else if (!(fileset contains file)) {
} else if (!(fileset contains file)) {
compileLate(new CompilationUnit(getSourceFile(file)))
}
}
@ -963,7 +947,7 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
inform("" + sym.name + ":" +(if (module) sym.tpe.typeSymbol.info else sym.info))
}
/** Returns the file with the given suffix for the given class. */
/** Returns the file with the given suffix for the given class. Used for icode writing. */
def getFile(clazz: Symbol, suffix: String): File = {
val outdirname = settings.outputDirs.outputDirFor(clazz.sourceFile)
var outdir = new File(if (outdirname.path == "") "." else outdirname.path)
@ -1002,8 +986,4 @@ class Global(var settings: Settings, var reporter: Reporter) extends SymbolTable
def forJVM : Boolean = settings.target.value startsWith "jvm"
def forMSIL: Boolean = settings.target.value == "msil"
def onlyPresentation = false
private val unpickleIDEHook0 : (( => Type) => Type) = f => f
def unpickleIDEHook : (( => Type) => Type) = unpickleIDEHook0
def doPickleHash = false
}

View File

@ -39,7 +39,14 @@ object MainGenericRunner {
lazy val jarsInLib = listDir("lib") filter (_.getName endsWith ".jar")
lazy val dirsInClasses = listDir("classes") filter (_.isDirectory)
val cpScala =
if (scalaHome == null) Nil
if (scalaHome == null) {
// this is to make the interpreter work when running without the scala script
// (e.g. from eclipse). Before, "java.class.path" was added to the user classpath
// in Settings; this was changed to match the behavior of Sun's javac.
val javacp = System.getProperty("java.class.path")
if (javacp == null) Nil
else ClassPath.expandPath(javacp)
}
else (jarsInLib ::: dirsInClasses) map (_.toString)
// either prepend existing classpath or append "."

View File

@ -17,6 +17,7 @@ class Settings(errorFn: String => Unit) extends ScalacSettings {
// optionizes a system property
private def syspropopt(name: String): Option[String] = onull(System.getProperty(name))
private def sysenvopt(name: String): Option[String] = onull(System.getenv(name))
// given any number of possible path segments, flattens down to a
// :-separated style path
@ -24,7 +25,7 @@ class Settings(errorFn: String => Unit) extends ScalacSettings {
segments.toList.flatMap(x => x) mkString File.pathSeparator
protected def classpathDefault =
syspropopt("env.classpath") orElse syspropopt("java.class.path") getOrElse ""
sysenvopt("CLASSPATH") getOrElse "."
protected def bootclasspathDefault =
concatPath(syspropopt("sun.boot.class.path"), guessedScalaBootClassPath)
@ -36,6 +37,9 @@ class Settings(errorFn: String => Unit) extends ScalacSettings {
protected def extdirsDefault =
concatPath(syspropopt("java.ext.dirs"), guessedScalaExtDirs)
protected def assemExtdirsDefault =
concatPath(guessedScalaExtDirs)
protected def pluginsDirDefault =
guess(List("misc", "scala-devel", "plugins"), _.isDirectory) getOrElse ""
@ -759,8 +763,10 @@ trait ScalacSettings {
* -X "Advanced" settings
*/
val Xhelp = BooleanSetting ("-X", "Print a synopsis of advanced options")
val assemname = StringSetting ("-Xassem", "file", "Name of the output assembly (only relevant with -target:msil)", "").dependsOn(target, "msil")
val assemname = StringSetting ("-Xassem-name", "file", "Name of the output assembly (only relevant with -target:msil)", "").dependsOn(target, "msil")
val assemrefs = StringSetting ("-Xassem-path", "path", "List of assemblies referenced by the program (only relevant with -target:msil)", ".").dependsOn(target, "msil")
val assemextdirs = StringSetting ("-Xassem-extdirs", "dirs", "List of directories containing assemblies, defaults to `lib'", assemExtdirsDefault).dependsOn(target, "msil")
val sourcedir = StringSetting ("-Xsourcedir", "directory", "When -target:msil, the source folder structure is mirrored in output directory.", ".").dependsOn(target, "msil")
val checkInit = BooleanSetting ("-Xcheckinit", "Add runtime checks on field accessors. Uninitialized accesses result in an exception being thrown.")
val noassertions = BooleanSetting ("-Xdisable-assertions", "Generate no assertions and assumptions")
val elideLevel = IntSetting ("-Xelide-level", "Generate calls to @elidable-marked methods only method priority is greater than argument.",

View File

@ -337,14 +337,15 @@ abstract class TreeInfo {
/** Compilation unit is the predef object
*/
def isPredefUnit(tree: Tree): Boolean = tree match {
case PackageDef(Ident(nme.scala_), List(obj)) => isPredefObj(obj)
case PackageDef(Ident(nme.scala_), defs) => isPredefObj(defs)
case _ => false
}
private def isPredefObj(tree: Tree): Boolean = tree match {
case ModuleDef(_, nme.Predef, _) => true
case DocDef(_, tree1) => isPredefObj(tree1)
case Annotated(_, tree1) => isPredefObj(tree1)
private def isPredefObj(trees: List[Tree]): Boolean = trees match {
case Import(_, _) :: xs => isPredefObj(xs)
case ModuleDef(_, nme.Predef, _) :: Nil => true
case DocDef(_, tree1) :: Nil => isPredefObj(List(tree1))
case Annotated(_, tree1) :: Nil => isPredefObj(List(tree1))
case _ => false
}

View File

@ -54,7 +54,7 @@ abstract class GenICode extends SubComponent {
val SCALA_ALLREF = REFERENCE(definitions.NullClass)
val THROWABLE = REFERENCE(ThrowableClass)
val BoxesRunTime_equals =
lazy val BoxesRunTime_equals =
if (!forMSIL)
definitions.getMember(definitions.BoxesRunTimeClass, nme.equals_)
else

View File

@ -18,8 +18,6 @@ import scala.tools.nsc.util.Position
import ch.epfl.lamp.compiler.msil.{Type => MsilType, _}
import ch.epfl.lamp.compiler.msil.emit._
/**
*/
abstract class GenMSIL extends SubComponent {
import global._
import loaders.clrTypes
@ -75,7 +73,7 @@ abstract class GenMSIL extends SubComponent {
import clrTypes.{VOID => MVOID, BOOLEAN => MBOOL, UBYTE => MBYTE, SHORT => MSHORT,
CHAR => MCHAR, INT => MINT, LONG => MLONG, FLOAT => MFLOAT,
DOUBLE => MDOUBLE, OBJECT => MOBJECT, STRING => MSTRING,
STRING_ARRAY => MSTRING_ARRAY, SCALA_SYMTAB_ATTR => SYMTAB_ATTRIBUTE,
STRING_ARRAY => MSTRING_ARRAY,
SYMTAB_CONSTR => SYMTAB_ATTRIBUTE_CONSTRUCTOR,
SYMTAB_DEFAULT_CONSTR => SYMTAB_ATTRIBUTE_EMPTY_CONSTRUCTOR}
@ -118,7 +116,7 @@ abstract class GenMSIL extends SubComponent {
val toDouble: MethodInfo = SystemConvert.GetMethod("ToDouble", objParam)
//val boxedUnit: FieldInfo = msilType(definitions.BoxedUnitModule.info).GetField("UNIT")
val boxedUnit: FieldInfo = fields(definitions.BoxedUnit_UNIT.asInstanceOf[clrTypes.global.Symbol])
val boxedUnit: FieldInfo = fields(definitions.BoxedUnit_UNIT)
// Scala attributes
// symtab.Definitions -> object (singleton..)
@ -133,8 +131,8 @@ abstract class GenMSIL extends SubComponent {
val dynToStatMapped: HashSet[Symbol] = new HashSet()
initMappings()
// ********************************************************************
// Create the mappings
/** Create the mappings between java and .net classes and methods */
private def initMappings() {
mapType(definitions.AnyClass, MOBJECT)
mapType(definitions.AnyRefClass, MOBJECT)
@ -231,7 +229,7 @@ abstract class GenMSIL extends SubComponent {
assemName = assemName.substring(0, assemName.length() - 1)
} else {
// assuming filename of first source file
assert(firstSourceName.endsWith(".scala"), "Source file doesn't end with .scala")
assert(firstSourceName.endsWith(".scala"), firstSourceName)
assemName = firstSourceName.substring(0, firstSourceName.length() - 6)
}
} else {
@ -245,7 +243,7 @@ abstract class GenMSIL extends SubComponent {
outDir = new File(settings.outdir.value)
srcPath = new File(settings.sourcepath.value)
srcPath = new File(settings.sourcedir.value)
val assemblyName = new AssemblyName()
assemblyName.Name = assemName
@ -263,35 +261,44 @@ abstract class GenMSIL extends SubComponent {
* Form of the custom Attribute parameter (Ecma-335.pdf)
* - p. 163 for CustomAttrib Form,
* - p. 164 for FixedArg Form (Array and Element) (if array or not is known!)
* !! least significant *byte* first if values longer than one byte !!
* !! least significant byte first if values longer than one byte !!
*
* 1: Prolog (unsigned int16, value 0x0001) -> symtab[0] = 0x01, symtab[1] = 0x00
* 2: FixedArgs (directly the data, get number and types from related constructor)
* 2.1: length of the array (unsigned int32, take care on order of the 4 bytes)
* 2.1: length of the array (unsigned int32, 4 bytes, least significant first)
* 2.2: the byte array data
* 3: NumNamed (unsigned int16, number of named fields and properties, 0x0000)
*
**/
*/
def addSymtabAttribute(sym: Symbol, tBuilder: TypeBuilder) {
def addMarker() {
val markerSymtab = new Array[Byte](4)
markerSymtab(0) = 1.toByte
tBuilder.SetCustomAttribute(SYMTAB_ATTRIBUTE_EMPTY_CONSTRUCTOR, markerSymtab)
}
// both conditions are needed (why exactly..?)
if (tBuilder.Name.endsWith("$") || sym.isModuleClass) {
addMarker()
} else {
currentRun.symData.get(sym) match {
case Some(pickle) =>
val symtab: Array[Byte] = new Array[Byte](pickle.writeIndex + 8)
var size = pickle.writeIndex
val symtab = new Array[Byte](size + 8)
symtab(0) = 1.toByte
var size:Int = pickle.writeIndex
for (i <- 2 until 6) {
symtab(i) = (size & 0xff).toByte
size = size >> 8
}
System.arraycopy(pickle.bytes, 0, symtab, 6, pickle.writeIndex)
tBuilder.SetCustomAttribute(SYMTAB_ATTRIBUTE_CONSTRUCTOR, symtab)
currentRun.symData -= sym
currentRun.symData -= sym.linkedSym
//log("Generated ScalaSig Attr for " + sym)//debug
case _ =>
log("Could not find pickle information for " + sym)
addMarker()
}
}
}
@ -437,8 +444,8 @@ abstract class GenMSIL extends SubComponent {
def writeAssembly() {
if (entryPoint != null) {
assert(entryPoint.enclClass.isModuleClass, "main-method not defined in a module")
val mainMethod = methods(entryPoint.asInstanceOf[clrTypes.global.Symbol])
assert(entryPoint.enclClass.isModuleClass, entryPoint.enclClass)
val mainMethod = methods(entryPoint)
val stringArrayTypes: Array[MsilType] = Array(MSTRING_ARRAY)
val globalMain = mmodule.DefineGlobalMethod(
"Main", MethodAttributes.Public | MethodAttributes.Static,
@ -466,7 +473,7 @@ abstract class GenMSIL extends SubComponent {
private def createTypes() {
for (sym <- classes.keysIterator) {
val iclass = classes(sym)
val tBuilder = types(sym.asInstanceOf[clrTypes.global.Symbol]).asInstanceOf[TypeBuilder]
val tBuilder = types(sym).asInstanceOf[TypeBuilder]
if (settings.debug.value)
log("Calling CreatType for " + sym + ", " + tBuilder.toString)
@ -508,30 +515,14 @@ abstract class GenMSIL extends SubComponent {
tBuilder.setPosition(line, iclass.cunit.source.file.name)
if (isTopLevelModule(sym)) {
if (settings.debug.value)
log("TopLevelModule: " + sym)
if (sym.linkedClassOfModule == NoSymbol) {
if (settings.debug.value)
log(" no linked class: " + sym)
if (sym.linkedClassOfModule == NoSymbol)
dumpMirrorClass(sym)
} else if (!currentRun.compiles(sym.linkedClassOfModule)) {
if (settings.debug.value)
log(" not compiling linked class: " + sym)
dumpMirrorClass(sym)
}
}
// the pickling info is not written to the module class, but to it's
// linked class (the mirror class eventually dumped)
if (!(tBuilder.Name.endsWith("$") && sym.isModuleClass)){
// think the if inside could be removed, because in this case, addSymtabAttribute is
// called in the dumpMirrorClass method
addSymtabAttribute(if (isTopLevelModule(sym)) sym.sourceModule else sym, tBuilder)
// TODO: remove; check the above think:
assert(!isTopLevelModule(sym), "can't remove the 'if'")
else
log("No mirror class for module with linked class: " +
sym.fullNameString)
}
addSymtabAttribute(sym, tBuilder)
addAttributes(tBuilder, sym.annotations)
if (iclass.symbol != definitions.ArrayClass)
@ -549,9 +540,9 @@ abstract class GenMSIL extends SubComponent {
computeLocalVarsIndex(m)
if (m.symbol.isClassConstructor) {
mcode = constructors(m.symbol.asInstanceOf[clrTypes.global.Symbol]).asInstanceOf[ConstructorBuilder].GetILGenerator()
mcode = constructors(m.symbol).asInstanceOf[ConstructorBuilder].GetILGenerator()
} else {
val mBuilder = methods(m.symbol.asInstanceOf[clrTypes.global.Symbol]).asInstanceOf[MethodBuilder]
val mBuilder = methods(m.symbol).asInstanceOf[MethodBuilder]
if (!mBuilder.IsAbstract())
try {
mcode = mBuilder.GetILGenerator()
@ -1287,11 +1278,11 @@ abstract class GenMSIL extends SubComponent {
log("LOAD_FIELD with owner: " + field.owner +
" flags: " + Flags.flagsToString(field.owner.flags))
var fieldInfo: FieldInfo = fields.get(field.asInstanceOf[clrTypes.global.Symbol]) match {
var fieldInfo: FieldInfo = fields.get(field) match {
case Some(fInfo) => fInfo
case None =>
val fInfo = getType(field.owner).GetField(msilName(field))
fields(field.asInstanceOf[clrTypes.global.Symbol]) = fInfo
fields(field) = fInfo
fInfo
}
mcode.Emit(if (isStatic) OpCodes.Ldsfld else OpCodes.Ldfld, fieldInfo)
@ -1350,11 +1341,11 @@ abstract class GenMSIL extends SubComponent {
mcode.Emit(OpCodes.Starg_S, 0)
case STORE_FIELD(field, isStatic) =>
val fieldInfo: FieldInfo = fields.get(field.asInstanceOf[clrTypes.global.Symbol]) match {
val fieldInfo: FieldInfo = fields.get(field) match {
case Some(fInfo) => fInfo
case None =>
val fInfo = getType(field.owner).GetField(msilName(field))
fields(field.asInstanceOf[clrTypes.global.Symbol]) = fInfo
fields(field) = fInfo
fInfo
}
mcode.Emit(if (isStatic) OpCodes.Stsfld else OpCodes.Stfld, fieldInfo)
@ -1399,7 +1390,7 @@ abstract class GenMSIL extends SubComponent {
}
var doEmit: Boolean = true
types.get(msym.owner.asInstanceOf[clrTypes.global.Symbol]) match {
types.get(msym.owner) match {
case Some(typ) if (typ.IsEnum) => {
def negBool = {
mcode.Emit(OpCodes.Ldc_I4_0)
@ -1882,9 +1873,9 @@ abstract class GenMSIL extends SubComponent {
mf = mf | FieldAttributes.Static
else {
mf = mf | MethodAttributes.Virtual
if (sym.isFinal && !types(sym.owner.asInstanceOf[clrTypes.global.Symbol]).IsInterface)
if (sym.isFinal && !types(sym.owner).IsInterface)
mf = mf | MethodAttributes.Final
if (sym.hasFlag(Flags.DEFERRED) || types(sym.owner.asInstanceOf[clrTypes.global.Symbol]).IsInterface)
if (sym.hasFlag(Flags.DEFERRED) || types(sym.owner).IsInterface)
mf = mf | MethodAttributes.Abstract
}
}
@ -1977,35 +1968,39 @@ abstract class GenMSIL extends SubComponent {
sym.tpe.paramTypes.map(msilType).toArray
}
def getType(sym: Symbol): MsilType = types.get(sym.asInstanceOf[clrTypes.global.Symbol]) match {
def getType(sym: Symbol): MsilType = types.get(sym) match {
case Some(typ) => typ
case None =>
val name = if (sym.isModuleClass && !sym.isTrait) sym.fullNameString + "$"
def typeString(sym: Symbol): String = {
val s = if (sym.isNestedClass) typeString(sym.owner) +"+"+ sym.simpleName
else sym.fullNameString
if (sym.isModuleClass && !sym.isTrait) s + "$" else s
}
val name = typeString(sym)
val typ = clrTypes.getType(name)
if (typ == null)
throw new Error(showsym(sym) + " with name " + name)
else {
clrTypes.types(sym.asInstanceOf[clrTypes.global.Symbol]) = typ
clrTypes.types(sym) = typ
typ
}
}
def mapType(sym: Symbol, mType: MsilType) {
assert(mType != null, showsym(sym))
types(sym.asInstanceOf[clrTypes.global.Symbol]) = mType
types(sym) = mType
}
def createTypeBuilder(iclass: IClass) {
def msilTypeFromSym(sym: Symbol): MsilType = {
types.get(sym.asInstanceOf[clrTypes.global.Symbol]) match {
types.get(sym) match {
case Some(mtype) => mtype
case None => createTypeBuilder(classes(sym)); types(sym.asInstanceOf[clrTypes.global.Symbol])
case None => createTypeBuilder(classes(sym)); types(sym)
}
}
val sym = iclass.symbol
if (types contains sym.asInstanceOf[clrTypes.global.Symbol]) return
if (types contains sym) return
def isInterface(s: Symbol) = s.isTrait && !s.isImplClass
val parents: List[Type] =
@ -2060,7 +2055,7 @@ abstract class GenMSIL extends SubComponent {
var attributes = msilFieldFlags(sym)
val fBuilder = mtype.DefineField(msilName(sym), msilType(sym.tpe), attributes)
fields(sym.asInstanceOf[clrTypes.global.Symbol]) = fBuilder
fields(sym) = fBuilder
addAttributes(fBuilder, sym.annotations)
}
@ -2091,7 +2086,7 @@ abstract class GenMSIL extends SubComponent {
for (i <- 0.until(paramTypes.length)) {
method.DefineParameter(i, ParameterAttributes.None, msilName(m.params(i).sym))
}
if (!methods.contains(sym.asInstanceOf[clrTypes.global.Symbol]))
if (!methods.contains(sym))
mapMethod(sym, method)
addAttributes(method, sym.annotations)
if (settings.debug.value)
@ -2137,7 +2132,7 @@ abstract class GenMSIL extends SubComponent {
(FieldAttributes.Public |
//FieldAttributes.InitOnly |
FieldAttributes.Static).toShort)
fields(sym.asInstanceOf[clrTypes.global.Symbol]) = fb
fields(sym) = fb
}
@ -2152,20 +2147,25 @@ abstract class GenMSIL extends SubComponent {
// TODO: get module field for modules not defined in the
// source currently compiling (e.g. Console)
fields get moduleClassSym.asInstanceOf[clrTypes.global.Symbol] match {
fields get moduleClassSym match {
case Some(sym) => sym
case None =>
//val mclass = types(moduleClassSym)
val mClass = clrTypes.getType(moduleClassSym.fullNameString + "$")
val mfield = mClass.GetField("MODULE$")
assert(mfield ne null, "module not found " + showsym(moduleClassSym))
fields(moduleClassSym.asInstanceOf[clrTypes.global.Symbol]) = mfield
fields(moduleClassSym) = mfield
mfield
}
//fields(moduleClassSym)
}
/** Adds a static initializer which creates an instance of the module
* class (calls the primary constructor). A special primary constructor
* will be generated (notInitializedModules) which stores the new intance
* in the MODULE$ field right after the super call.
*/
private def addStaticInit(sym: Symbol) {
val tBuilder = getType(sym).asInstanceOf[TypeBuilder]
@ -2176,7 +2176,7 @@ abstract class GenMSIL extends SubComponent {
val sicode = staticInit.GetILGenerator()
val instanceConstructor = constructors(sym.primaryConstructor.asInstanceOf[clrTypes.global.Symbol])
val instanceConstructor = constructors(sym.primaryConstructor)
// there are no constructor parameters. assuming the constructor takes no parameter
// is fine: we call (in the static constructor) the constructor of the module class,
@ -2199,7 +2199,6 @@ abstract class GenMSIL extends SubComponent {
TypeAttributes.Class |
TypeAttributes.Public |
TypeAttributes.Sealed,
//FIXME: an object may have a super-type (a class, not an object) -> not in mirror class?
MOBJECT,
MsilType.EmptyTypes)
@ -2328,7 +2327,7 @@ abstract class GenMSIL extends SubComponent {
// #####################################################################
// get and create methods / constructors
def getConstructor(sym: Symbol): ConstructorInfo = constructors.get(sym.asInstanceOf[clrTypes.global.Symbol]) match {
def getConstructor(sym: Symbol): ConstructorInfo = constructors.get(sym) match {
case Some(constr) => constr
case None =>
val mClass = getType(sym.owner)
@ -2345,7 +2344,7 @@ abstract class GenMSIL extends SubComponent {
}
def mapConstructor(sym: Symbol, cInfo: ConstructorInfo) = {
constructors(sym.asInstanceOf[clrTypes.global.Symbol]) = cInfo
constructors(sym) = cInfo
}
private def getMethod(sym: Symbol): MethodInfo = {
@ -2360,7 +2359,7 @@ abstract class GenMSIL extends SubComponent {
// case SRToShort => toShort
// case _ =>
methods.get(sym.asInstanceOf[clrTypes.global.Symbol]) match {
methods.get(sym) match {
case Some(method) => method
case None =>
val mClass = getType(sym.owner)
@ -2391,7 +2390,7 @@ abstract class GenMSIL extends SubComponent {
*/
private def mapMethod(sym: Symbol, mInfo: MethodInfo) {
assert (mInfo != null, mInfo)
methods(sym.asInstanceOf[clrTypes.global.Symbol]) = mInfo
methods(sym) = mInfo
}
/*

View File

@ -156,7 +156,7 @@ trait Definitions {
)
lazy val EqualsPatternClass = {
val clazz = newClass(ScalaPackageClass, nme.EQUALS_PATTERN_NAME, Nil)
clazz setInfo PolyType(List(newTypeParam(clazz, 0)), ClassInfoType(anyparam, newClassScope(clazz), clazz))
clazz setInfo PolyType(List(newTypeParam(clazz, 0)), ClassInfoType(anyparam, new Scope, clazz))
clazz
}
@ -460,7 +460,7 @@ trait Definitions {
private def newClass(owner: Symbol, name: Name, parents: List[Type]): Symbol = {
val clazz = owner.newClass(NoPosition, name.toTypeName)
clazz.setInfo(ClassInfoType(parents, newClassScope(clazz), clazz))
clazz.setInfo(ClassInfoType(parents, new Scope, clazz))
owner.info.decls.enter(clazz)
clazz
}
@ -478,7 +478,7 @@ trait Definitions {
clazz.setInfo(
PolyType(
List(tparam),
ClassInfoType(List(AnyRefClass.tpe, p), newClassScope(clazz), clazz)))
ClassInfoType(List(AnyRefClass.tpe, p), new Scope, clazz)))
}
private def newAlias(owner: Symbol, name: Name, alias: Type): Symbol = {
@ -553,7 +553,7 @@ trait Definitions {
val module = ScalaPackageClass.newModule(NoPosition, name)
ScalaPackageClass.info.decls.enter(module)
val mclass = module.moduleClass
mclass.setInfo(ClassInfoType(List(), newClassScope(mclass), mclass))
mclass.setInfo(ClassInfoType(List(), new Scope, mclass))
module.setInfo(mclass.tpe)
val box = newMethod(mclass, nme.box, List(clazz.typeConstructor),
@ -720,7 +720,7 @@ trait Definitions {
if (isInitialized) return
isInitialized = true
EmptyPackageClass.setInfo(ClassInfoType(List(), newClassScope(EmptyPackageClass), EmptyPackageClass))
EmptyPackageClass.setInfo(ClassInfoType(List(), new Scope, EmptyPackageClass))
EmptyPackage.setInfo(EmptyPackageClass.tpe)
RootClass.info.decls.enter(EmptyPackage)
RootClass.info.decls.enter(RootPackage)

View File

@ -16,9 +16,6 @@ package symtab
// done for performance (and could be reviewed).
// Another addition is a lookupAll method that returns all symbols with
// a name in a scopein an iterator.
// I still have to remove all the cruft about PackageScope's and the like
// that's a leftover from the old Eclipse plugin days.
//
trait Scopes {
self: SymbolTable =>
@ -40,92 +37,14 @@ trait Scopes {
* @param owner ...
* @return ...
*/
def newScopeEntry(sym: Symbol, owner: Scope): ScopeEntry = {
private def newScopeEntry(sym: Symbol, owner: Scope): ScopeEntry = {
val e = new ScopeEntry(sym, owner)
e.next = owner.elems
owner.elems = e
e
}
// Martin: This code contains a lot of stuff for the old Eclipse plugin.
// Now it's just needless complexity, which should be eleminated.
// We should make the elems list doubly-linked,
// and have scopes inherit from LinearSeq,
// that way, we need to do way fewer toList than before.
/**
* @param initElems ...
* @return ...
*/
def newScope(initElems: ScopeEntry): Scope = new NormalScope(initElems)
final def newScope: Scope = newScope(null: ScopeEntry)
trait PackageScopeDependMap {
def createDepend(from : Symbol, name : Name) : Unit
}
def newPackageScope(depends0 : PackageScopeDependMap) : PackageScope = {
object MyPackageScope extends NormalScope(null : ScopeEntry) with PackageScope {
val depends = depends0
}
MyPackageScope
}
def newTempScope = newScope(null : ScopeEntry)
class ScopeKind(name : String) { override def toString = name }
def allocateScopeKind(name : String) = new ScopeKind(name)
lazy val Constructor0ScopeKind : ScopeKind = allocateScopeKind("constructors0")
lazy val Constructor1ScopeKind : ScopeKind = allocateScopeKind("constructors1")
lazy val InnerScopeKind : ScopeKind = allocateScopeKind("inner")
lazy val FinishWithScopeKind : ScopeKind = allocateScopeKind("finishWith")
lazy val TypeSigScopeKind : ScopeKind = allocateScopeKind("typeSig")
lazy val PolyTypeCompleterScopeKind : ScopeKind = allocateScopeKind("polyType")
lazy val CompoundTreeScopeKind : ScopeKind = allocateScopeKind("compoundTree")
lazy val FreshArgScopeKind : ScopeKind = allocateScopeKind("freshArgs")
lazy val LabelScopeKind : ScopeKind = allocateScopeKind("label")
lazy val TypedCasesScopeKind : ScopeKind = allocateScopeKind("typedCases")
lazy val TypedDefScopeKind : ScopeKind = allocateScopeKind("typedDef")
//lazy val ParentTypesScopeKind : ScopeKind = allocateScopeKind("parentType")
lazy val TypedScopeKind : ScopeKind = allocateScopeKind("typed")
// have to sometimes use constructor depth unfortunately.
case class ParentTypesScopeKind(clazz : Symbol) extends ScopeKind("parentType") { override def toString = super.toString + "-" + clazz }
case class BlockScopeKind(depth : Int) extends ScopeKind("block") { override def toString = super.toString + "-" + depth }
def newClassScope(clazz : Symbol) = newScope // for use in ClassInfoType creation
def scopeFor( tree : Tree, kind : ScopeKind) : Scope = newScope
def scopeFor(old : Scope, tree : Tree, kind : ScopeKind) : Scope = newScope(old)
final def newScope(base: Scope) : Scope = newScope(base.elems)
final def newScope(decls: List[Symbol]) : Scope = {
val ret = newScope
decls foreach ret.enter
ret
}
def newThrowAwayScope(decls : List[Symbol]) : Scope = newScope(decls)
// for symbols that don't exist in scopes!
def recycle(sym : Symbol) : Symbol = sym
def newLocalDummy(clazz : Symbol, pos : util.Position) = clazz.newLocalDummy(pos)
private class NormalScope(initElems: ScopeEntry) extends Scope(initElems)
trait PackageScope extends Scope {
val depends : PackageScopeDependMap
override def lookupEntryWithContext(name : Name)(from : Symbol) = {
if (from != NoSymbol && depends != null) {
depends.createDepend(from,name)
}
super.lookupEntryWithContext(name)(from)
}
override def lookupWithContext(name : Name)(from : Symbol) = {
if (from != NoSymbol && depends != null) {
depends.createDepend(from,name)
}
super.lookupWithContext(name)(from)
}
}
abstract class Scope(initElems: ScopeEntry) extends Iterable[Symbol] {
class Scope(initElems: ScopeEntry) extends Iterable[Symbol] {
var elems: ScopeEntry = initElems
@ -167,17 +86,10 @@ trait Scopes {
/** Returns a new scope with the same content as this one. */
def cloneScope: Scope = {
val clone = newScope
val clone = new Scope()
this.toList foreach (clone enter _)
clone
}
/* clear the contents of this scope */
def clear = {
elems = null
elemsCache = null
hashtable = null
}
/** is the scope empty? */
override def isEmpty: Boolean = elems eq null
@ -314,11 +226,6 @@ trait Scopes {
def next: Symbol = { val r = e.sym; e = lookupNextEntry(e); r }
}
/** Can lookup symbols and trace who the client is.
*/
def lookupEntryWithContext(name : Name)(from : Symbol) : ScopeEntry = lookupEntry(name)
def lookupWithContext(name : Name)(from : Symbol) : Symbol = lookup(name)
/** lookup a symbol entry matching given name.
* @note from Martin: I believe this is a hotspot or will be one
* in future versions of the type system. I have reverted the previous
@ -385,8 +292,6 @@ trait Scopes {
/** Return the nesting level of this scope, i.e. the number of times this scope
* was nested in another */
def nestingLevel = nestinglevel
def invalidate(name : Name) = {}
}
/** The empty scope (immutable).
@ -399,22 +304,6 @@ trait Scopes {
/** The error scope.
*/
class ErrorScope(owner: Symbol) extends Scope(null: ScopeEntry) {
/* The following method was intended to be here,
* but it was written (in two different iterations!) so that
* it was actually a no-op. That's why I am leaving it comment-out
* for now.
override def lookupEntry(name: Name): ScopeEntry = {
def errorSym =
if (name.isTermName) owner newErrorValue name
else owner newErrorClass name
super.lookupEntry(name) match {
case null => enter(errorSym); lookupEntry(name)
case e => e
}
}
*/
}
class ErrorScope(owner: Symbol) extends Scope(null: ScopeEntry)
}

View File

@ -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.{Position, NoPosition}
import scala.tools.nsc.util.{Position, NoPosition, ClassPath, ClassRep, JavaClassPath, MsilClassPath}
import classfile.ClassfileParser
import Flags._
@ -27,38 +27,42 @@ abstract class SymbolLoaders {
val global: Global
import global._
/** A lazy type that completes itself by calling parameter doComplete.
/**
* A lazy type that completes itself by calling parameter doComplete.
* Any linked modules/classes or module classes are also initialized.
*
* @param doComplete The type completion procedure to be run.
* It takes symbol to compkete as parameter and returns
* name of file loaded for completion as a result.
* Can throw an IOException on error.
*/
abstract class SymbolLoader extends LazyType {
/** Load source or class file for `root', return */
protected def doComplete(root: Symbol): Unit
/** The kind of file that's processed by this loader */
protected def kindString: String
protected def sourcefile: Option[AbstractFile] = None
/**
* Description of the resource (ClassPath, AbstractFile, MSILType)
* being processed by this loader
*/
protected def description: String
private var ok = false
def sourceFile: AbstractFile = null
protected def sourceString: String
private def setSource(sym: Symbol) {
sourcefile map (sf => sym match {
case cls: ClassSymbol => cls.sourceFile = sf
case mod: ModuleSymbol => mod.moduleClass.sourceFile = sf
case _ => ()
})
}
override def complete(root: Symbol) : Unit = {
try {
val start = currentTime
val currentphase = phase
doComplete(root)
phase = currentphase
def source = kindString + " " + sourceString
informTime("loaded " + source, start)
//if (root.rawInfo == this && root.linkedSym.rawInfo == this)
// throw new TypeError(source + " does not define " + root)
informTime("loaded " + description, start)
ok = true
setSource(root)
setSource(root.linkedSym) // module -> class, class -> module
} catch {
case ex: IOException =>
ok = false
@ -84,115 +88,84 @@ abstract class SymbolLoaders {
}
}
/** Load contents of a package
/**
* Load contents of a package
*/
class PackageLoader(val directory: global.classPath0.Context) extends SymbolLoader {
abstract class PackageLoader[T](classpath: ClassPath[T]) extends SymbolLoader {
protected def description = "package loader "+ classpath.name
// XXX: for IDE.
protected def sourceString = directory.toString()
protected def kindString: String = "directory path"
protected def newPackageLoader(dir: global.classPath0.Context): PackageLoader =
new PackageLoader(dir)
protected def checkSource(name: String, source: AbstractFile): Boolean = source ne null
var root: Symbol = _
def enterPackage(name: String, completer: SymbolLoader) {
def enterPackage(root: Symbol, name: String, completer: SymbolLoader) {
val preExisting = root.info.decls.lookup(newTermName(name))
if (preExisting != NoSymbol)
throw new TypeError(
root+" contains object and package with same name: "+name+"\none of them needs to be removed from classpath")
val pkg = root.newPackage(NoPosition, newTermName(name))
pkg.moduleClass.setInfo(completer)
pkg.setInfo(pkg.moduleClass.tpe)
root.info.decls.enter(pkg)
}
// @return - the symbol of the class
def enterClassAndModule(name: String, completer: SymbolLoader): Symbol = {
def enterClassAndModule(root: Symbol, name: String, completer: SymbolLoader) {
val owner = if (root.isRoot) definitions.EmptyPackageClass else root
val className = newTermName(name)
assert(owner.info.decls.lookup(name) == NoSymbol, owner.fullNameString + "." + name)
var clazz = owner.newClass(NoPosition, name.toTypeName)
var module = owner.newModule(NoPosition, name)
val clazz = owner.newClass(NoPosition, name.toTypeName)
val module = owner.newModule(NoPosition, name)
clazz setInfo completer
module setInfo completer
module.moduleClass setInfo moduleClassLoader
clazz = (owner.info.decls enter clazz).asInstanceOf[ClassSymbol]
module = (owner.info.decls enter module).asInstanceOf[ModuleSymbol]
owner.info.decls enter clazz
owner.info.decls enter module
assert(clazz.linkedModuleOfClass == module, module)
assert(module.linkedClassOfModule == clazz, clazz)
clazz
}
def checkAdd(name0 : String) = {
var name = name0
while ((name indexOf '$') != -1) {
name = name.substring(0, name indexOf '$')
}
}
lazy val scope = newPackageScope(computeDepends(this))
/**
* Tells wether a class with both a binary and a source representation
* (found in classpath and in sourcepath) should be re-compiled. Behaves
* similar to javac, i.e. if the source file is newer than the classfile,
* a re-compile is triggered.
*/
protected def needCompile(bin: T, src: AbstractFile): Boolean
/**
* Tells wether a class should be loaded and entered into the package
* scope. On .NET, this method returns `false' for all synthetic classes
* (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 newClassLoader(bin: T): SymbolLoader
protected def newPackageLoader(pkg: ClassPath[T]): SymbolLoader
protected def doComplete(root: Symbol) {
assert(root.isPackageClass, root)
this.root = root
root.setInfo(new PackageClassInfoType(scope, root, this))
refresh()
}
def refresh() {
/** Is the given name a valid input file base name? */
def isValid(name: String): Boolean =
name.length() > 0 && (!name.endsWith("$class") || settings.XO.value)
root.setInfo(new PackageClassInfoType(new Scope(), root))
val classes = new HashMap[String, global.classPath0.Context]
val packages = new HashMap[String, global.classPath0.Context]
def recordClass(file: AbstractFile, extension: String, classOK: global.classPath0.Context => Boolean) {
if (!file.isDirectory && file.name.endsWith(extension)) {
val name = file.name.substring(0, file.name.length - extension.length)
if (isValid(name) && !classes.isDefinedAt(name)) {
val clazz = directory.find(name, false)
if ((clazz ne null) && classOK(clazz)) classes(name) = clazz
}
val sourcepaths = classpath.sourcepaths
for (classRep <- classpath.classes if doLoad(classRep)) {
if (classRep.binary.isDefined && classRep.source.isDefined) {
val (bin, src) = (classRep.binary.get, classRep.source.get)
val loader = if (needCompile(bin, src)) new SourcefileLoader(src)
else newClassLoader(bin)
enterClassAndModule(root, classRep.name, loader)
} else if (classRep.binary.isDefined) {
enterClassAndModule(root, classRep.name, newClassLoader(classRep.binary.get))
} else if (classRep.source.isDefined) {
enterClassAndModule(root, classRep.name, new SourcefileLoader(classRep.source.get))
}
}
for (dir <- directory.entries) if ((dir.location ne null) && dir.location.isDirectory) {
for (file <- dir.location) {
if (file.isDirectory && directory.validPackage(file.name) && !packages.isDefinedAt(file.name))
packages(file.name) = directory.find(file.name, true);
else if (!global.forMSIL)
recordClass(file, ".class", source => true)
for (pkg <- classpath.packages) {
enterPackage(root, pkg.name, newPackageLoader(pkg))
}
}
for (dir <- directory.entries) if (dir.source ne null) {
for (file <- dir.source.location) {
if (file.isDirectory && directory.validPackage(file.name) && !packages.isDefinedAt(file.name))
packages(file.name) = directory.find(file.name, true)
else if (dir.source.compile)
recordClass(file, ".scala", source => checkSource(file.name, source.sourceFile))
}
}
// do classes first
for ((name, file) <- classes.iterator) {
val loader = if (!file.isSourceFile) {
new ClassfileLoader(file.classFile, file.sourceFile, file.sourcePath)
} else {
assert(file.sourceFile ne null)
new SourcefileLoader(file.sourceFile)
}
enterClassAndModule(name, loader)
}
// packages second
for ((name, file) <- packages.iterator)
enterPackage(name, newPackageLoader(file))
// if there's a $member object, enter its members as well.
val pkgModule = root.info.decl(nme.PACKAGEkw)
if (pkgModule.isModule && !pkgModule.rawInfo.isInstanceOf[SourcefileLoader])
if (pkgModule.isModule && !(pkgModule.rawInfo.isInstanceOf[SourcefileLoader] &&
classpath.name == "scala"))
openPackageModule(pkgModule)
}
}
@ -210,120 +183,88 @@ abstract class SymbolLoaders {
}
}
class NamespaceLoader(directory: global.classPath0.Context) extends PackageLoader(directory) {
class JavaPackageLoader(classpath: ClassPath[AbstractFile]) extends PackageLoader(classpath) {
protected def needCompile(bin: AbstractFile, src: AbstractFile) =
(src.lastModified >= bin.lastModified)
override protected def kindString: String = "namespace " + namespace
protected def doLoad(cls: ClassRep[AbstractFile]) = true
override protected def sourceString = ""
protected def newClassLoader(bin: AbstractFile) =
new ClassfileLoader(bin)
override def newPackageLoader(dir: global.classPath0.Context): PackageLoader =
new NamespaceLoader(dir)
val types = new HashMap[String, MSILType]()
val namespaces = new HashSet[String]()
def namespace: String = if (root.isRoot) "" else root.fullNameString
// TODO: Add check whether the source is newer than the assembly
override protected def checkSource(name: String, source: AbstractFile): Boolean = {
val result = (source ne null) && !types.contains(name)
if (!result && settings.debug.value)
Console.println("Skipping source file " + source)
result
protected def newPackageLoader(pkg: ClassPath[AbstractFile]) =
new JavaPackageLoader(pkg)
}
override protected def doComplete(root: Symbol) {
clrTypes.collectMembers(root, types, namespaces)
super.doComplete(root)
for (namespace <- namespaces.iterator) {
val oldPkg = root.info.decls lookup newTermName(namespace)
if (oldPkg == NoSymbol)
enterPackage(namespace, new NamespaceLoader(new classPath0.Context(List())))
//else System.out.println("PackageLoader: package already in scope: " + oldPkg.fullNameString)
}
// import the CLR types contained in the package (namespace)
for ((name, typ) <- types.iterator) {
assert(namespace == typ.Namespace, typ.FullName)
class NamespaceLoader(classpath: ClassPath[MSILType]) extends PackageLoader(classpath) {
protected def needCompile(bin: MSILType, src: AbstractFile) =
(!src.name.endsWith(".java"))
protected def doLoad(cls: ClassRep[MSILType]) = {
if (cls.binary.isDefined) {
val typ = cls.binary.get
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]
if (a.getConstructor() == clrTypes.SYMTAB_CONSTR)
enterClassAndModule(name, new MSILTypeLoader(typ))
}
else
enterClassAndModule(name, new MSILTypeLoader(typ))
// symtab_constr takes a byte array argument (the pickle), i.e. typ has a pickle.
// otherwise, symtab_default_constr was used, which marks typ as scala-synthetic.
a.getConstructor() == clrTypes.SYMTAB_CONSTR
} else true // always load non-scala types
} else true // always load source
}
val pkgModule = root.info.decl(nme.PACKAGEkw)
if (pkgModule.isModule && !pkgModule.rawInfo.isInstanceOf[SourcefileLoader])
openPackageModule(pkgModule)
}
} // NamespaceLoader
protected def newClassLoader(bin: MSILType) =
new MSILTypeLoader(bin)
protected def newPackageLoader(pkg: ClassPath[MSILType]) =
new NamespaceLoader(pkg)
class MSILTypeLoader(typ: MSILType) extends SymbolLoader {
private object typeParser extends clr.TypeParser {
val global: SymbolLoaders.this.global.type = SymbolLoaders.this.global
}
protected def doComplete(root: Symbol) {
typeParser.parse(typ, root.asInstanceOf[typeParser.global.loaders.clrTypes.global.Symbol]) // don't check this
}
protected def kindString: String = typ.FullName
protected def sourceString = typ.Assembly.FullName
}
// IDE hook.
protected def completeClassfile(root : Symbol, loader : ClassfileLoader)(f : => Unit) : Unit = f
// incremental builder hook
protected def computeDepends(loader : PackageLoader) : PackageScopeDependMap = {
null
}
class ClassfileLoader(val classFile: AbstractFile, override val sourceFile: AbstractFile, sourcePath0: AbstractFile) extends SymbolLoader {
class ClassfileLoader(val classfile: AbstractFile) extends SymbolLoader {
/**
* @FIXME: iulian,
* there should not be a new ClassfileParser for every loaded classfile, this object
* should be outside the class ClassfileLoader! This was changed by Sean in r5494.
*
* However, when pulling it out, loading "java.lang.Object" breaks with:
* "illegal class file dependency between java.lang.Object and java.lang.Class"
*/
private object classfileParser extends ClassfileParser {
val global: SymbolLoaders.this.global.type = SymbolLoaders.this.global
override def sourcePath = sourcePath0 /* could be null */
}
protected def doComplete(root: Symbol) {
completeClassfile(root, this) {
classfileParser.parse(classFile, root)
}
root match {
case clazz: ClassSymbol =>
if ((sourceFile ne null) && (clazz.sourceFile eq null))
clazz.sourceFile = sourceFile
case module: ModuleSymbol if module.moduleClass.isInstanceOf[ClassSymbol] =>
val clazz = module.moduleClass.asInstanceOf[ClassSymbol]
if ((sourceFile ne null) && (clazz.sourceFile eq null))
clazz.sourceFile = sourceFile
case _ =>
}
if (root.sourceFile ne null)
prepareReset(root, this)
}
protected def kindString: String = "class file"
protected def sourceString = classFile.toString()
}
class SourcefileLoader(override val sourceFile: AbstractFile) extends SymbolLoader {
protected def doComplete(root: Symbol): Unit = global.currentRun.compileLate(sourceFile)
protected def kindString: String = "source file"
protected def sourceString = sourceFile.toString()
protected def description = "class file "+ classfile.toString
protected def doComplete(root: Symbol) {
classfileParser.parse(classfile, root)
}
}
class MSILTypeLoader(typ: MSILType) extends SymbolLoader {
protected def description = "MSILType "+ typ.FullName + ", assembly "+ typ.Assembly.FullName
protected def doComplete(root: Symbol) { typeParser.parse(typ, root) }
}
class SourcefileLoader(val srcfile: AbstractFile) extends SymbolLoader {
protected def description = "source file "+ srcfile.toString
override protected def sourcefile = Some(srcfile)
protected def doComplete(root: Symbol): Unit = global.currentRun.compileLate(srcfile)
}
object moduleClassLoader extends SymbolLoader {
protected def description = "module class loader"
protected def doComplete(root: Symbol) { root.sourceModule.initialize }
protected def kindString: String = ""
protected def sourceString = ""
}
private object typeParser extends clr.TypeParser {
val global: SymbolLoaders.this.global.type = SymbolLoaders.this.global
}
object clrTypes extends clr.CLRTypes {
val global: SymbolLoaders.this.global.type = SymbolLoaders.this.global
if (global.forMSIL) init()
}
}

View File

@ -42,12 +42,6 @@ abstract class SymbolTable extends Names
}
def notifyImport(what : Name, container : Type, from : Name, to : Name) : Unit = {}
def sanitize(tree : Tree) : Tree = tree
def attachSource(symbol : ClassSymbol, file : io.AbstractFile) : Unit = {
assert(symbol != null)
}
def prepareReset(symbol : Symbol, tpe : LazyType) : Unit = {
assert(symbol != null)
}
/** A period is an ordinal number for a phase in a run.
* Phases in later runs have higher periods than phases in earlier runs.

View File

@ -1822,7 +1822,6 @@ trait Symbols {
if (owner.isPackageClass) source else super.sourceFile
override def sourceFile_=(f: AbstractFile) {
//System.err.println("set source file of " + this + ": " + f);
attachSource(this, f)
source = f
}
override def isFromClassFile = {

View File

@ -756,7 +756,7 @@ trait Types {
while (!bcs.isEmpty) {
val decls = bcs.head.info.decls
var entry =
if (name == nme.ANYNAME) decls.elems else decls.lookupEntryWithContext(name)(from)
if (name == nme.ANYNAME) decls.elems else decls.lookupEntry(name)
while (entry ne null) {
val sym = entry.sym
if (sym.getFlag(requiredFlags) == requiredFlags) {
@ -779,10 +779,10 @@ trait Types {
if (self eq null) self = this.narrow;
(self.memberType(member) matches self.memberType(sym))
})) {
members = newThrowAwayScope(List(member, sym))
members = new Scope(List(member, sym))
}
} else {
var prevEntry = members.lookupEntryWithContext(sym.name)(from)
var prevEntry = members.lookupEntry(sym.name)
while ((prevEntry ne null) &&
!(prevEntry.sym == sym ||
prevEntry.sym.owner != sym.owner &&
@ -1422,10 +1422,8 @@ trait Types {
override def kind = "ClassInfoType"
}
class PackageClassInfoType(decls: Scope, clazz: Symbol, val lazyLoader : LazyType)
extends ClassInfoType(List(), decls, clazz) {
def reset = clazz.setInfo(lazyLoader)
}
class PackageClassInfoType(decls: Scope, clazz: Symbol)
extends ClassInfoType(List(), decls, clazz)
/** A class representing a constant type.
*
@ -2230,8 +2228,7 @@ A type's typeSymbol should never be inspected directly.
/** The canonical creator for this-types */
def mkThisType(sym: Symbol): Type = {
class UniqueThisType extends ThisType(sym) with UniqueType
if (phase.erasedTypes) sym.tpe else unique(new UniqueThisType)
if (phase.erasedTypes) sym.tpe else unique(new ThisType(sym) with UniqueType)
}
/** The canonical creator for single-types */
@ -2244,9 +2241,7 @@ A type's typeSymbol should never be inspected directly.
var sym1 = rebind(pre, sym)
val pre1 = removeSuper(pre, sym1)
if (pre1 ne pre) sym1 = rebind(pre1, sym1)
class UniqueSingleType extends SingleType(pre1, sym1) with UniqueType
unique(new UniqueSingleType)
unique(new SingleType(pre1, sym1) with UniqueType)
}
}
@ -2254,14 +2249,12 @@ A type's typeSymbol should never be inspected directly.
def mkSuperType(thistp: Type, supertp: Type): Type =
if (phase.erasedTypes) supertp
else {
class UniqueSuperType extends SuperType(thistp, supertp) with UniqueType
unique(new UniqueSuperType)
unique(new SuperType(thistp, supertp) with UniqueType)
}
/** The canonical creator for type bounds */
def mkTypeBounds(lo: Type, hi: Type): TypeBounds = {
class UniqueTypeBounds extends TypeBounds(lo, hi) with UniqueType
unique(new UniqueTypeBounds)
unique(new TypeBounds(lo, hi) with UniqueType)
}
def refinementOfClass(clazz: Symbol, parents: List[Type], decls: Scope) = {
@ -2280,7 +2273,7 @@ A type's typeSymbol should never be inspected directly.
else {
// having $anonfun as owner causes the pickler to break upon unpickling; see ticket #2323
val nonAnonOwner = (owner.ownerChain dropWhile (_.isAnonymousFunction)).headOption getOrElse NoSymbol
val clazz = recycle(nonAnonOwner.newRefinementClass(NoPosition))
val clazz = nonAnonOwner.newRefinementClass(NoPosition)
val result = refinementOfClass(clazz, parents, decls)
clazz.setInfo(result)
result
@ -2294,7 +2287,7 @@ A type's typeSymbol should never be inspected directly.
* @return ...
*/
def refinedType(parents: List[Type], owner: Symbol): Type =
refinedType(parents, owner, newTempScope, owner.pos)
refinedType(parents, owner, new Scope, owner.pos)
def copyRefinedType(original: RefinedType, parents: List[Type], decls: Scope) =
if ((parents eq original.parents) && (decls eq original.decls)) original
@ -4578,7 +4571,7 @@ A type's typeSymbol should never be inspected directly.
else {
def lubBounds(bnds: List[TypeBounds]): TypeBounds =
mkTypeBounds(glb(bnds map (_.lo), decr(depth)), lub(bnds map (_.hi), decr(depth)))
recycle(lubRefined.typeSymbol.newAbstractType(proto.pos, proto.name))
lubRefined.typeSymbol.newAbstractType(proto.pos, proto.name)
.setInfo(lubBounds(symtypes map (_.bounds)))
}
}

View File

@ -14,7 +14,7 @@ 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.{Position, NoPosition}
import scala.tools.nsc.util.{Position, NoPosition, ClassRep}
import scala.annotation.switch
/** This abstract class implements a class file parser.
@ -23,8 +23,6 @@ import scala.annotation.switch
* @version 1.0
*/
abstract class ClassfileParser {
def sourcePath : AbstractFile = null
val global: Global
import global._
@ -416,7 +414,7 @@ abstract class ClassfileParser {
}
addEnclosingTParams(clazz)
parseInnerClasses()
parseInnerClasses() // also sets the isScala / isScalaRaw / hasMeta flags, see r15956
val superType = if (isAnnotation) { in.nextChar; definitions.AnnotationClass.tpe }
else pool.getSuperClass(in.nextChar).tpe
val ifaceCount = in.nextChar
@ -424,8 +422,8 @@ abstract class ClassfileParser {
if (isAnnotation) ifaces = definitions.ClassfileAnnotationClass.tpe :: ifaces
val parents = superType :: ifaces
// get the class file parser to reuse scopes.
instanceDefs = newClassScope(clazz)
staticDefs = newClassScope(statics)
instanceDefs = new Scope
staticDefs = new Scope
val classInfo = ClassInfoType(parents, instanceDefs, clazz)
val staticInfo = ClassInfoType(List(), staticDefs, statics)
@ -778,19 +776,6 @@ abstract class ClassfileParser {
val meta = pool.getName(in.nextChar).toString().trim()
metaParser.parse(meta, sym, symtype)
this.hasMeta = true
case nme.SourceFileATTR =>
assert(attrLen == 2)
val source = pool.getName(in.nextChar)
if (sourcePath ne null) {
val sourceFile0 = sourcePath.lookupPath(source.toString(), false)
if ((sourceFile0 ne null) && (clazz.sourceFile eq null)) {
clazz.sourceFile = sourceFile0
}
// XXX: removing only in IDE test. Also needs to be tested in the build compiler.
if (staticModule.moduleClass != NoSymbol) {
staticModule.moduleClass.sourceFile = clazz.sourceFile
}
}
// Attribute on methods of java annotation classes when that method has a default
case nme.AnnotationDefaultATTR =>
sym.addAnnotation(AnnotationInfo(definitions.AnnotationDefaultAttr.tpe, List(), List(), NoPosition))
@ -926,10 +911,11 @@ abstract class ClassfileParser {
for (entry <- innerClasses.valuesIterator) {
// create a new class member for immediate inner classes
if (entry.outerName == externalName) {
val file = global.classPath.lookupPath(
entry.externalName.replace('.', java.io.File.separatorChar).toString, false)
assert(file ne null, entry.externalName)
enterClassAndModule(entry, new global.loaders.ClassfileLoader(file, null, null), entry.jflags)
val file = global.classPath.findClass(entry.externalName.toString) match {
case Some(ClassRep(Some(binary: AbstractFile), _)) => binary
case _ => throw new AssertionError(entry.externalName)
}
enterClassAndModule(entry, new global.loaders.ClassfileLoader(file), entry.jflags)
}
}
}

View File

@ -14,7 +14,7 @@ import scala.collection.mutable._
import scala.tools.nsc._
import scala.tools.nsc.backend.icode._
import scala.tools.nsc.io._
import scala.tools.nsc.util.{Position,NoPosition}
import scala.tools.nsc.util.{Position, NoPosition, ClassRep}
import ClassfileConstants._
import Flags._
@ -49,19 +49,20 @@ abstract class ICodeReader extends ClassfileParser {
isScalaModule = cls.isModule && !cls.hasFlag(JAVA)
log("Reading class: " + cls + " isScalaModule?: " + isScalaModule)
val name = cls.fullNameString(java.io.File.separatorChar) + (if (sym.hasFlag(MODULE)) "$" else "")
val entry = classPath.root.find(name, false)
if (entry ne null) {
classFile = entry.classFile
val name = cls.fullNameString('.') + (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
assert(classFile ne null, "No classfile for " + cls)
// for (s <- cls.info.members)
// Console.println("" + s + ": " + s.tpe)
parse(classFile, sym)
} else
case _ =>
log("Could not find: " + cls)
}
(staticCode, instanceCode)
}

View File

@ -51,15 +51,6 @@ abstract class Pickler extends SubComponent {
add(sym, pickle)
add(sym.linkedSym, pickle)
pickle.finish
// pickleHash is used to track changes in a signature (-> IDE)
val doPickleHash = global.doPickleHash
if (doPickleHash) {
var i = 0
while (i < pickle.writeIndex) {
unit.pickleHash += pickle.bytes(i).toLong // toLong needed to work around bug
i += 1
}
}
case _ =>
}
}

View File

@ -89,16 +89,10 @@ abstract class UnPickler {
}
/** The `decls' scope associated with given symbol */
private def symScope(sym: Symbol, isTemp : Boolean) = symScopes.get(sym) match {
case None =>
val s = if (isTemp) newTempScope
else if (sym.isClass || sym.isModuleClass || sym.isModule) newClassScope(sym);
else newScope
symScopes(sym) = s; s
private def symScope(sym: Symbol) = symScopes.get(sym) match {
case None => val s = new Scope; symScopes(sym) = s; s
case Some(s) => s
}
private def symScope(sym : Symbol) : Scope = symScope(sym, false)
/** Does entry represent an (internal) symbol */
private def isSymbolEntry(i: Int): Boolean = {
@ -302,7 +296,7 @@ abstract class UnPickler {
val dcls = symScope(clazz)
new RefinedType(ps, dcls) { override def symbol = clazz }
*/
new RefinedType(until(end, readTypeRef), symScope(clazz, true)) {
new RefinedType(until(end, readTypeRef), symScope(clazz)) {
override def typeSymbol = clazz
}
case CLASSINFOtpe =>
@ -816,10 +810,8 @@ abstract class UnPickler {
private class LazyTypeRef(i: Int) extends LazyType {
private val definedAtRunId = currentRunId
private val p = phase
// In IDE, captures class files dependencies so they can be reloaded when their dependencies change.
private val ideHook = unpickleIDEHook
override def complete(sym: Symbol) : Unit = {
val tp = ideHook(at(i, readType))
val tp = at(i, readType)
if (p != phase) atPhase(p) (sym setInfo tp)
else sym setInfo tp
if (currentRunId != definedAtRunId) sym.setInfo(adaptToNewRunMap(tp))

View File

@ -63,20 +63,11 @@ abstract class CLRTypes {
val fields: Map[Symbol, FieldInfo] = new HashMap
val sym2type: Map[Type,Symbol] = new HashMap
private var alltypes: Array[Type] = _
def init() = try { // initialize
/*
val assems = new StringTokenizer(global.settings.assemrefs.value, File.pathSeparator)
while (assems.hasMoreTokens()) {
assemrefs += new File(assems.nextToken())
}
*/
val mscorlib = findAssembly("mscorlib.dll")
Type.initMSCORLIB(mscorlib)
findAssembly("scalaruntime.dll")
findAllAssemblies()
// 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")
@ -104,38 +95,20 @@ abstract class CLRTypes {
SYMTAB_CONSTR = SCALA_SYMTAB_ATTR.GetConstructor(bytearray)
SYMTAB_DEFAULT_CONSTR = SCALA_SYMTAB_ATTR.GetConstructor(Type.EmptyTypes)
//assert(SCALA_SYMTAB_ATTR != null)
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)
//assert(DELEGATE_COMBINE != null)
//assert(DELEGATE_REMOVE != null)
var alltypes: Array[Type] = Type.EmptyTypes
for (assem <- assemblies) {
val atypes = assem.GetTypes().filter((typ: Type) => typ.DeclaringType == null)
alltypes = Array.concat(alltypes, atypes)
}
Sorting.stableSort(alltypes, (t1: Type, t2: Type) => (t1.FullName compareTo t2.FullName) < 0)
this.alltypes = alltypes
}
catch {
case e: RuntimeException =>
Console.println(e.getMessage)
// no bloody exits! exit(1)
throw e
}
//##########################################################################
// type mapping and lookup
// private class MyHashMap[A, B <: AnyRef] extends HashMap[A, B] {
// override def default(key: A): B = null;
// }
def getType(name: String): Type = Type.GetType(name)
def getTypeSafe(name: String): Type = {
@ -147,107 +120,4 @@ abstract class CLRTypes {
def mkArrayType(elemType: Type): Type = getType(elemType.FullName + "[]")
def isDelegateType(t: Type): Boolean = { t.BaseType() == DELEGATE }
//##########################################################################
// assembly loading methods
// a list of all loaded assemblies
private var assemblies: ListBuffer[Assembly] = new ListBuffer()
// a set of all directories and assembly files
//private var assemrefs: Set[File] = new HashSet()
//def assembly(file : File) = assemrefs += file
/** Load the assembly with the given name
*/
private def findAssembly(name: String): Assembly = {
// see if the assembly is referenced directly
for (file <- global.assemrefs.iterator if file.getName() == name) {
val assem = Assembly.LoadFrom(file.getPath())
if (assem != null) {
global.assemrefs -= file
assemblies += assem
return assem
}
}
// look in directories specified with the '-r' option
for (dir <- global.assemrefs.iterator if dir.isDirectory()) {
val file = new File(dir, name)
if (file.exists()) {
val assem = Assembly.LoadFrom(file.getPath())
if (assem != null) {
assemblies += assem
return assem
}
}
}
// try in the current directory
val file = new File(".", name)
if (file.exists()) {
val assem = Assembly.LoadFrom(file.getPath())
if (assem != null) {
assemblies += assem
return assem
}
}
throw new RuntimeException(
"cannot find assembly " + name + "; use the -Xassem-path option to specify its location")
}
/** Load the rest of the assemblies specified with the '-r' option
*/
private def findAllAssemblies() {
for (file <- global.assemrefs.iterator) {
if (file.isFile()) {
//System.out.println("Loading assembly " + file)
val assem = Assembly.LoadFrom(file.getPath())
if (assem != null) {
assemblies += assem
}
}
}
global.assemrefs.clear
}
//##########################################################################
// collect the members contained in a given namespace
/** Find the position of the first type whose name starts with
* the given prefix; return the length of the types array if no match
* is found so the result canbe used to terminate loop conditions
*/
private def findFirst(prefix: String): Int = {
var m = 0
var n = alltypes.length - 1
while (m < n) {
val l = (m + n) / 2
val res = alltypes(l).FullName.compareTo(prefix)
if (res < 0) m = l + 1
else n = l
}
if (alltypes(m).FullName.startsWith(prefix)) m else alltypes.length
}
/** Collects the members contained in the given Scala package (namespace)
*/
def collectMembers(pakage: Symbol, typesMap: Map[String,Type], namespacesSet: Set[String]) = {
val namespace = if (pakage.isRoot) "" else pakage.fullNameString + "."
val nl = namespace.length()
var i = findFirst(namespace)
while (i < alltypes.length && alltypes(i).FullName.startsWith(namespace)) {
val typ = alltypes(i)
if (typ.FullName != "java.lang.Object" && typ.FullName != "java.lang.String") {
val k = typ.FullName.indexOf(".", nl)
if (k < 0) {
typesMap.update(typ.Name, typ)
} else {
namespacesSet += (typ.Namespace.substring(nl, k))
}
}
i += 1
}
}
//##########################################################################
} // CLRTypes

View File

@ -22,8 +22,9 @@ import classfile.UnPickler
abstract class TypeParser {
val global: Global
import global.loaders.clrTypes
import clrTypes.global._
import global._
import loaders.clrTypes
//##########################################################################
@ -76,8 +77,7 @@ abstract class TypeParser {
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.asInstanceOf[unpickler.global.Symbol],
staticModule.asInstanceOf[unpickler.global.Symbol], typ.FullName);
unpickler.unpickle(symtab, 0, clazz, staticModule, typ.FullName);
val mClass = clrTypes.getType(typ.FullName + "$");
if (mClass != null) {
clrTypes.types(statics) = mClass;
@ -93,8 +93,8 @@ abstract class TypeParser {
else if (typ.IsInterface()) definitions.ObjectClass.tpe
else definitions.AnyClass.tpe; // this is System.Object
val parents = superType :: ifaces.map(getCLRType).toList
instanceDefs = newClassScope(clazz)
staticDefs = newClassScope(staticModule)
instanceDefs = new Scope
staticDefs = new Scope
val classInfo = ClassInfoType(parents, instanceDefs, clazz)
val staticInfo = ClassInfoType(List(), staticDefs, statics)
@ -112,7 +112,7 @@ abstract class TypeParser {
|| ntype.IsNestedFamANDAssem)
|| ntype.IsInterface)
{
val loader = new global.loaders.MSILTypeLoader(ntype)
val loader = new loaders.MSILTypeLoader(ntype)
val nclazz = statics.newClass(NoPosition, ntype.Name.toTypeName)
val nmodule = statics.newModule(NoPosition, ntype.Name)
nclazz.setInfo(loader)

View File

@ -240,8 +240,8 @@ trait Contexts { self: Analyzer =>
make(unit, tree, owner, scope, imports)
}
def makeNewScope(tree: Tree, owner: Symbol)(implicit kind : ScopeKind): Context =
make(tree, owner, scopeFor(scope, tree, kind))
def makeNewScope(tree: Tree, owner: Symbol): Context =
make(tree, owner, new Scope(scope))
// IDE stuff: distinguish between scopes created for typing and scopes created for naming.
def make(tree: Tree, owner: Symbol): Context =
@ -268,7 +268,7 @@ trait Contexts { self: Analyzer =>
//todo: find out why we need next line
while (baseContext.tree.isInstanceOf[Template])
baseContext = baseContext.outer
val argContext = baseContext.makeNewScope(tree, owner)(Constructor0ScopeKind)
val argContext = baseContext.makeNewScope(tree, owner)
argContext.reportGeneralErrors = this.reportGeneralErrors
argContext.reportAmbiguousErrors = this.reportAmbiguousErrors
def enterElems(c: Context) {

View File

@ -107,7 +107,7 @@ trait Namers { self: Analyzer =>
private var innerNamerCache: Namer = null
protected def makeConstructorScope(classContext : Context) : Context = {
val outerContext = classContext.outer.outer
outerContext.makeNewScope(outerContext.tree, outerContext.owner)(Constructor1ScopeKind)
outerContext.makeNewScope(outerContext.tree, outerContext.owner)
}
def namerOf(sym: Symbol): Namer = {
@ -116,7 +116,7 @@ trait Namers { self: Analyzer =>
if (innerNamerCache eq null)
innerNamerCache =
if (!isTemplateContext(context)) this
else newNamer(context.make(context.tree, context.owner, scopeFor(context.tree, InnerScopeKind)))
else newNamer(context.make(context.tree, context.owner, new Scope))
innerNamerCache
}
@ -168,7 +168,7 @@ trait Namers { self: Analyzer =>
def enterInScope(sym: Symbol, scope: Scope): Symbol = {
// allow for overloaded methods
if (!(sym.isSourceMethod && sym.owner.isClass && !sym.owner.isPackageClass)) {
var prev = scope.lookupEntryWithContext(sym.name)(context.owner);
var prev = scope.lookupEntry(sym.name)
if ((prev ne null) && prev.owner == scope && conflict(sym, prev.sym)) {
doubleDefError(sym.pos, prev.sym)
sym setInfo ErrorType
@ -185,10 +185,10 @@ trait Namers { self: Analyzer =>
case Select(qual: RefTree, name) =>
enterPackageSymbol(pos, qual, pkgOwner).moduleClass
}
var pkg = owner.info.decls.lookupWithContext(pid.name)(owner)
var pkg = owner.info.decls.lookup(pid.name)
if (!pkg.isPackage || owner != pkg.owner) {
pkg = owner.newPackage(pos, pid.name)
pkg.moduleClass.setInfo(new PackageClassInfoType(newScope, pkg.moduleClass, null))
pkg.moduleClass.setInfo(new PackageClassInfoType(new Scope, pkg.moduleClass))
pkg.setInfo(pkg.moduleClass.tpe)
enterInScope(pkg, owner.info.decls)
}
@ -196,7 +196,7 @@ trait Namers { self: Analyzer =>
}
def enterClassSymbol(tree : ClassDef): Symbol = {
var c: Symbol = context.scope.lookupWithContext(tree.name)(context.owner);
var c: Symbol = context.scope.lookup(tree.name)
if (c.isType && c.owner.isPackageClass && context.scope == c.owner.info.decls && !currentRun.compiles(c)) {
updatePosFlags(c, tree.pos, tree.mods.flags)
setPrivateWithin(tree, c, tree.mods)
@ -226,7 +226,7 @@ trait Namers { self: Analyzer =>
* or a class definition */
def enterModuleSymbol(tree : ModuleDef): Symbol = {
// .pos, mods.flags | MODULE | FINAL, name
var m: Symbol = context.scope.lookupWithContext(tree.name)(context.owner)
var m: Symbol = context.scope.lookup(tree.name)
val moduleFlags = tree.mods.flags | MODULE | FINAL
if (m.isModule && !m.isPackage && inCurrentScope(m) &&
(!currentRun.compiles(m) || (m hasFlag SYNTHETIC))) {
@ -286,7 +286,7 @@ trait Namers { self: Analyzer =>
* @return the companion object symbol.
*/
def ensureCompanionObject(tree: ClassDef, creator: => Tree): Symbol = {
val m: Symbol = context.scope.lookupWithContext(tree.name.toTermName)(context.owner).filter(! _.isSourceMethod)
val m: Symbol = context.scope.lookup(tree.name.toTermName).filter(! _.isSourceMethod)
if (m.isModule && inCurrentScope(m) && currentRun.compiles(m)) m
else enterSyntheticSym(creator)
}
@ -302,7 +302,7 @@ trait Namers { self: Analyzer =>
//@M e.g., in [A[x <: B], B], A and B are entered first as both are in scope in the definition of x
//@M x is only in scope in `A[x <: B]'
if(!sym.isAbstractType) //@M TODO: change to isTypeMember ?
newNamer(context.makeNewScope(tree, sym)(FinishWithScopeKind)).enterSyms(tparams)
newNamer(context.makeNewScope(tree, sym)).enterSyms(tparams)
ltype = new PolyTypeCompleter(tparams, ltype, tree, sym, context) //@M
if (sym.isTerm) skolemize(tparams)
@ -638,11 +638,11 @@ trait Namers { self: Analyzer =>
val parentTyper =
if (earlyTypes.isEmpty) typer
else {
val earlyContext = context.outer.makeNewScope(context.tree, context.outer.owner.newLocalDummy(templ.pos))(InnerScopeKind)
val earlyContext = context.outer.makeNewScope(context.tree, context.outer.owner.newLocalDummy(templ.pos))
newNamer(earlyContext).enterSyms(earlyTypes)
newTyper(earlyContext).typedStats(earlyTypes, context.owner)
val parentContext = context.makeNewScope(context.tree, context.owner)(InnerScopeKind)
val parentContext = context.makeNewScope(context.tree, context.owner)
for (etdef <- earlyTypes) parentContext.scope enter etdef.symbol
newTyper(parentContext)
}
@ -669,7 +669,7 @@ trait Namers { self: Analyzer =>
*/
var parents = typer.parentTypes(templ) map checkParent
enterSelf(templ.self)
val decls = newClassScope(clazz)
val decls = new Scope
// for (etdef <- earlyTypes) decls enter etdef.symbol
val templateNamer = newNamer(context.make(templ, clazz, decls))
.enterSyms(templ.body)
@ -790,7 +790,7 @@ trait Namers { self: Analyzer =>
case Ident(name) if (vparams contains tree.symbol) =>
val dtpe = debruijnFor(tree.symbol)
val dsym =
newLocalDummy(context.owner, tree.symbol.pos)
context.owner.newLocalDummy(tree.symbol.pos)
.newValue(tree.symbol.pos, name)
dsym.setFlag(PARAM)
@ -1125,7 +1125,6 @@ trait Namers { self: Analyzer =>
annotated.deSkolemize.setAnnotations(ainfos)
case _ =>
}
implicit val scopeKind = TypeSigScopeKind
val result =
try {
tree match {
@ -1169,12 +1168,12 @@ trait Namers { self: Analyzer =>
if (!tree.symbol.hasFlag(SYNTHETIC) &&
!((expr1.symbol ne null) && expr1.symbol.isInterpreterWrapper) &&
base.member(from) != NoSymbol) {
val e = context.scope.lookupEntryWithContext(to)(context.owner)
val e = context.scope.lookupEntry(to)
def warnRedundant(sym: Symbol) =
context.unit.warning(pos, "imported `"+to+
"' is permanently hidden by definition of "+sym+
sym.locationString)
if ((e ne null) && e.owner == context.scope) {
if ((e ne null) && e.owner == context.scope && e.sym.exists) {
warnRedundant(e.sym); return false
} else if (context eq context.enclClass) {
val defSym = context.prefix.member(to) filter (
@ -1307,7 +1306,7 @@ trait Namers { self: Analyzer =>
override val tree = restp.tree
override def complete(sym: Symbol) {
if(ownerSym.isAbstractType) //@M an abstract type's type parameters are entered -- TODO: change to isTypeMember ?
newNamer(ctx.makeNewScope(owner, ownerSym)(PolyTypeCompleterScopeKind)).enterSyms(tparams) //@M
newNamer(ctx.makeNewScope(owner, ownerSym)).enterSyms(tparams) //@M
restp.complete(sym)
}
}

View File

@ -114,7 +114,7 @@ trait NamesDefaults { self: Analyzer =>
*/
def baseFunBlock(baseFun: Tree): Tree = {
val isConstr = baseFun.symbol.isConstructor
val blockTyper = newTyper(context.makeNewScope(tree, context.owner)(BlockScopeKind(context.depth)))
val blockTyper = newTyper(context.makeNewScope(tree, context.owner))
// baseFun1: extract the function from a potential TypeApply
// funTargs: type arguments on baseFun, used to reconstruct TypeApply in blockWith(Out)Qualifier

View File

@ -601,7 +601,7 @@ abstract class RefChecks extends InfoTransform {
case ClassDef(_, _, _, _) | DefDef(_, _, _, _, _, _) | ModuleDef(_, _, _) | ValDef(_, _, _, _) =>
assert(stat.symbol != NoSymbol, stat);//debug
if (stat.symbol.isLocal) {
currentLevel.scope.enter(newScopeEntry(stat.symbol, currentLevel.scope));
currentLevel.scope.enter(stat.symbol)
symIndex(stat.symbol) = index;
}
case _ =>

View File

@ -454,7 +454,7 @@ trait Typers { self: Analyzer =>
o = o.owner
if (o == sym.owner) addHidden(sym)
} else if (sym.owner.isTerm && !sym.isTypeParameterOrSkolem) {
var e = scope.lookupEntryWithContext(sym.name)(context.owner)
var e = scope.lookupEntry(sym.name)
var found = false
while (!found && (e ne null) && e.owner == scope) {
if (e.sym == sym) {
@ -525,7 +525,7 @@ trait Typers { self: Analyzer =>
*/
def labelTyper(ldef: LabelDef): Typer =
if (ldef.symbol == NoSymbol) { // labeldef is part of template
val typer1 = newTyper(context.makeNewScope(ldef, context.owner)(LabelScopeKind))
val typer1 = newTyper(context.makeNewScope(ldef, context.owner))
typer1.enterLabelDef(ldef)
typer1
} else this
@ -1111,7 +1111,7 @@ trait Typers { self: Analyzer =>
val outercontext = context.outer
assert(clazz != NoSymbol)
val cscope = outercontext.makeNewScope(constr, outercontext.owner)(ParentTypesScopeKind(clazz))
val cscope = outercontext.makeNewScope(constr, outercontext.owner)
val cbody2 = newTyper(cscope) // called both during completion AND typing.
.typePrimaryConstrBody(clazz,
cbody1, supertparams, clazz.unsafeTypeParams, vparamss map (_.map(_.duplicate)))
@ -1250,7 +1250,7 @@ trait Typers { self: Analyzer =>
assert(clazz != NoSymbol)
reenterTypeParams(cdef.tparams)
val tparams1 = cdef.tparams mapConserve (typedTypeDef)
val impl1 = newTyper(context.make(cdef.impl, clazz, scopeFor(cdef.impl, TypedDefScopeKind)))
val impl1 = newTyper(context.make(cdef.impl, clazz, new Scope))
.typedTemplate(cdef.impl, parentTypes(cdef.impl))
val impl2 = addSyntheticMethods(impl1, clazz, context)
if ((clazz != ClassfileAnnotationClass) &&
@ -1279,7 +1279,7 @@ trait Typers { self: Analyzer =>
val clazz = mdef.symbol.moduleClass
val typedMods = removeAnnotations(mdef.mods)
assert(clazz != NoSymbol)
val impl1 = newTyper(context.make(mdef.impl, clazz, scopeFor(mdef.impl, TypedDefScopeKind)))
val impl1 = newTyper(context.make(mdef.impl, clazz, new Scope))
.typedTemplate(mdef.impl, parentTypes(mdef.impl))
val impl2 = addSyntheticMethods(impl1, clazz, context)
@ -1416,7 +1416,7 @@ trait Typers { self: Analyzer =>
def typedTemplate(templ: Template, parents1: List[Tree]): Template = {
val clazz = context.owner
if (templ.symbol == NoSymbol)
templ setSymbol newLocalDummy(clazz, templ.pos)
templ setSymbol clazz.newLocalDummy(templ.pos)
val self1 = templ.self match {
case vd @ ValDef(mods, name, tpt, EmptyTree) =>
val tpt1 = checkNoEscaping.privates(clazz.thisSym, typedType(tpt))
@ -1585,7 +1585,7 @@ trait Typers { self: Analyzer =>
var cx = context
while (cx != NoContext) {
val pre = cx.enclClass.prefix
val defEntry = cx.scope.lookupEntryWithContext(name)(context.owner)
val defEntry = cx.scope.lookupEntry(name)
if ((defEntry ne null) && defEntry.sym.exists)
return Some(defEntry.sym)
@ -1796,7 +1796,7 @@ trait Typers { self: Analyzer =>
def typedCases(tree: Tree, cases: List[CaseDef], pattp0: Type, pt: Type): List[CaseDef] = {
var pattp = pattp0
cases mapConserve (cdef =>
newTyper(context.makeNewScope(cdef, context.owner)(TypedCasesScopeKind))
newTyper(context.makeNewScope(cdef, context.owner))
.typedCase(cdef, pattp, pt))
/* not yet!
cdef.pat match {
@ -2310,7 +2310,7 @@ trait Typers { self: Analyzer =>
(ErrorType, List())
}
val (unappFormal, freeVars) = freshArgType(unappType)
val context1 = context.makeNewScope(context.tree, context.owner)(FreshArgScopeKind)
val context1 = context.makeNewScope(context.tree, context.owner)
freeVars foreach(sym => context1.scope.enter(sym))
val typer1 = newTyper(context1)
arg.tpe = typer1.infer.inferTypedPattern(tree.pos, unappFormal, arg.tpe)
@ -2488,7 +2488,7 @@ trait Typers { self: Analyzer =>
else typedFun.tpe.params.iterator)
val nvPairs = args map {
case arg @ AssignOrNamedArg(Ident(name), rhs) =>
val sym = if (isJava) annScope.lookupWithContext(name)(context.owner)
val sym = if (isJava) annScope.lookup(name)
else typedFun.tpe.params.find(p => p.name == name).getOrElse(NoSymbol)
if (sym == NoSymbol) {
error(arg.pos, "unknown annotation argument name: " + name)
@ -2607,7 +2607,7 @@ trait Typers { self: Analyzer =>
val name = if (sym.isType) sym.name else newTypeName(sym.name+".type")
val bound = sym.existentialBound
val sowner = if (isRawParameter(sym)) context.owner else sym.owner
val quantified: Symbol = recycle(sowner.newAbstractType(sym.pos, name))
val quantified: Symbol = sowner.newAbstractType(sym.pos, name)
trackSetInfo(quantified setFlag EXISTENTIAL)(bound.cloneInfo(quantified))
}
val typeParamTypes = typeParams map (_.tpe) // don't trackSetInfo here, since type already set!
@ -2778,7 +2778,7 @@ trait Typers { self: Analyzer =>
* (Note: -Yself-in-annots must be on to see the problem)
**/
val sym =
newLocalDummy(context.owner, ann.pos)
context.owner.newLocalDummy(ann.pos)
.newValue(ann.pos, nme.self)
sym.setInfo(arg1.tpe.withoutAnnotations)
sym
@ -2833,7 +2833,7 @@ trait Typers { self: Analyzer =>
val rawInfo = vble.rawInfo
vble = if (vble.name == nme.WILDCARD.toTypeName) context.scope.enter(vble)
else namer.enterInScope(vble)
trackSetInfo(vble)(rawInfo) // vble could have been recycled, detect changes in type
trackSetInfo(vble)(rawInfo)
tree setSymbol vble setType vble.tpe
} else {
if (vble == NoSymbol)
@ -3384,7 +3384,7 @@ trait Typers { self: Analyzer =>
while (defSym == NoSymbol && cx != NoContext) {
pre = cx.enclClass.prefix
defEntry = cx.scope.lookupEntryWithContext(name)(context.owner)
defEntry = cx.scope.lookupEntry(name)
if ((defEntry ne null) && qualifies(defEntry.sym)) {
defSym = defEntry.sym
}
@ -3481,7 +3481,7 @@ trait Typers { self: Analyzer =>
val parents1 = templ.parents mapConserve (typedType(_, mode))
if (parents1 exists (_.tpe.isError)) tree setType ErrorType
else {
val decls = scopeFor(tree, CompoundTreeScopeKind)
val decls = new Scope
//Console.println("Owner: " + context.enclClass.owner + " " + context.enclClass.owner.id)
val self = refinedType(parents1 map (_.tpe), context.enclClass.owner, decls, templ.pos)
newTyper(context.make(templ, self.typeSymbol, decls)).typedRefinement(templ.body)
@ -3535,7 +3535,6 @@ trait Typers { self: Analyzer =>
}
// begin typed1
implicit val scopeKind = TypedScopeKind
val sym: Symbol = tree.symbol
if ((sym ne null) && (sym ne NoSymbol)) sym.initialize
//if (settings.debug.value && tree.isDef) log("typing definition of "+sym);//DEBUG
@ -3577,7 +3576,7 @@ trait Typers { self: Analyzer =>
typedAnnotated(constr, typed(arg, mode, pt))
case tree @ Block(_, _) =>
newTyper(context.makeNewScope(tree, context.owner)(BlockScopeKind(context.depth)))
newTyper(context.makeNewScope(tree, context.owner))
.typedBlock(tree, mode, pt)
case Alternative(alts) =>
@ -3603,8 +3602,8 @@ trait Typers { self: Analyzer =>
case tree @ Function(_, _) =>
if (tree.symbol == NoSymbol)
tree.symbol = recycle(context.owner.newValue(tree.pos, nme.ANON_FUN_NAME)
.setFlag(SYNTHETIC).setInfo(NoType))
tree.symbol = context.owner.newValue(tree.pos, nme.ANON_FUN_NAME)
.setFlag(SYNTHETIC).setInfo(NoType)
newTyper(context.makeNewScope(tree, tree.symbol)).typedFunction(tree, mode, pt)
case Assign(lhs, rhs) =>

View File

@ -11,19 +11,24 @@ package util
import java.io.File
import java.net.URL
import java.util.StringTokenizer
import scala.util.Sorting
import scala.collection.mutable.ArrayBuffer
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.
* 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]
* </p>
*
* @author Stepan Koltsov
*/
object ClassPath {
/** Expand single path entry */
private def expandStar(pattern: String): List[String] = {
private def expandS(pattern: String): List[String] = {
def nameMatchesStar(name: String) = name.toLowerCase().endsWith(".jar")
/** Get all jars in directory */
@ -41,299 +46,390 @@ object ClassPath {
}
/** Split path using platform-dependent path separator */
def splitPath(path: String): List[String] =
private def splitPath(path: String): List[String] =
path split File.pathSeparator toList
/** Expand path with expanding stars */
def expandPath(path: String): List[String] = splitPath(path).flatMap(expandStar(_))
def expandPath(path: String, expandStar: Boolean): List[String] =
if (expandStar) expandPath(path)
/** Expand path and possibly expanding stars */
def expandPath(path: String, expandStar: Boolean = true): List[String] =
if (expandStar) splitPath(path).flatMap(expandS(_))
else splitPath(path)
}
/** <p>
* Richer classpath abstraction than files.
* </p>
* <p>
* Roughly based on Eclipse's classpath abstractions.
* </p>
*
* @author Sean McDirmid
*/
class ClassPath(onlyPresentation: Boolean) {
def this() = this(false)
class Source(val location: AbstractFile, val compile: Boolean) {
// assert(location != null, "cannot find source location")
// assert(location.getFile() != null, "cannot find source location " + " " + location + " " + location.getClass())
override def toString(): String = "" + location + " " + compile
}
abstract class Entry(val location: AbstractFile) {
// assert(location != null, "cannot find classpath location")
// assert(location.getFile() != null, "cannot find classpath location " + " " + location + " " + location.getClass())
def source: Source
override def toString() =
(if (location == null) "<none>" else location.toString) +
(if (source == null) "" else " source=" + source)
}
class Output(location0: AbstractFile, val sourceFile: AbstractFile) extends Entry(location0) {
def source = if (sourceFile ne null) new Source(sourceFile, true) else null
}
class Library(location0: AbstractFile) extends Entry(location0) {
def doc: AbstractFile = null
def sourceFile: AbstractFile = null
def source = if (sourceFile eq null) null else new Source(sourceFile, false)
}
class Context(val entries: List[Entry]) {
def find(name: String, isDir: Boolean): Context = if (isPackage) {
def find0(entries: List[Entry]): Context = {
if (entries.isEmpty) new Context(Nil)
else {
val ret = find0(entries.tail)
val head = entries.head;
val name0 = name + (if (!isDir) ".class" else "")
val clazz = if (head.location eq null) null
else head.location.lookupPath(name0, isDir)
val source0 =
if (head.source eq null) null
else if ((clazz eq null) || isDir) {
val source1 = head.source.location.lookupPath(
name + (if (isDir) "" else ".scala"), isDir)
if ((source1 eq null) && !isDir && (clazz ne null)) head.source.location
else source1
}
else head.source.location
if ((clazz eq null) && (source0 eq null)) ret
else {
val entry = new Entry(clazz) {
override def source =
if (source0 eq null) null
else new Source(source0, head.source.compile)
}
try {
//Console.err.println("this=" + this + "\nclazz=" + clazz + "\nsource0=" + source0 + "\n")
if (!isDir) new Context(entry :: Nil)
else new Context(entry :: ret.entries)
} catch {
case e: Error =>
throw e
}
}
}
}
val ret = find0(entries)
if (ret.entries.isEmpty) {
//Console.err.println("BAD_FILE: " + name + " in " + this)
null
} else ret
} else null
def isPackage: Boolean =
if (entries.isEmpty) false
else if (entries.head.location ne null) entries.head.location.isDirectory
else entries.head.source.location.isDirectory
def name =
if (entries.isEmpty) "<none>"
else {
val head = entries.head
val name = if (head.location ne null) head.location.name
else head.source.location.name
if (isPackage) name
else name.substring(0, name.length() - (".class").length())
}
override def toString(): String = toString(entries)
def toString(entry: Entry): String =
((if (entry.location eq null) "<none>"
else entry.location.toString()) +
(if (entry.source eq null) ""
else " with_source=" + entry.source.location.toString()))
def toString(entries0: List[Entry]): String =
if (entries0.isEmpty) ""
else toString(entries0.head) + ":::" + toString(entries0.tail)
def isSourceFile = {
def head = entries.head
def clazz = head.location
def source = if (head.source eq null) null else head.source.location
def isPredef = source.name.equals("Predef.scala") ||
source.path.startsWith("scala/runtime")
if (entries.isEmpty || entries.isEmpty || (source eq null)) false
else if (!onlyPresentation && !head.source.compile) false
else if (source.isDirectory) false
else if (clazz eq null) true
else if (onlyPresentation && !isPredef) true
else if (source.lastModified > clazz.lastModified) true
else false
}
def sourceFile = if ((entries.head.source ne null) && !entries.head.source.location.isDirectory)
entries.head.source.location else null
def classFile = if (!isSourceFile) entries.head.location else null
def sourcePath =
if (!isSourceFile && !entries.isEmpty && (entries.head.source ne null)) {
val ret = entries.head.source.location
if ((ret ne null) && !ret.isDirectory) {
Console.err.println("source path " + ret + " is not a directory")
null
} else ret
}
else null
def validPackage(name: String): Boolean =
def validPackage(name: String) =
!(name.equals("META-INF") || name.startsWith("."))
def validSourceFile(name: String) =
(name.endsWith(".scala") || name.endsWith(".java"))
var XO = false
def validClassFile(name: String) =
if (name.endsWith(".class")) {
val className = name.substring(0, name.length - 6)
(!className.endsWith("$class") || XO)
} else 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((typ: MSILType) => typ.DeclaringType == null)
Sorting.stableSort(res, (t1: MSILType, t2: MSILType) => (t1.FullName compareTo t2.FullName) < 0)
}
class Build {
val entries = new ArrayBuffer[Entry]
def root = new Context(entries.toList)
def this(classpath: String) {
this()
addFilesInPath(classpath)
res
}
def this(source: String, output: String) {
this()
addDirsInPath(source, output)
}
def this(classpath: String, source: String, output: String,
boot: String, extdirs: String, codebase: String) {
this()
addFilesInPath(boot)
addArchivesInExtDirPath(extdirs)
addDirsInPath(source, output)
addFilesInPath(classpath)
addURLsInPath(codebase)
}
/**
* Lookup the given path in this classpath. Returns null if not found.
* Does not work with absolute paths (starting with '/').
*
* @param path Path to look up (if isDir is false, '.class' is appended!).
* @param isDir Whether to look for a directory or a file
* @return The abstract file or null if path was not found
* A represents classes which can be loaded with a ClassfileLoader/MSILTypeLoader
* and / or a SourcefileLoader.
*/
def lookupPath(path: String, isDir: Boolean): AbstractFile = {
val ctx = root.find(path, isDir)
if (ctx eq null) null
else if (ctx.entries.isEmpty) null
else if (ctx.entries.head eq null) null
else ctx.entries.head.location
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.substring(0, f.name.length - 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.substring(0, nme.length - 6)
else if (nme.endsWith(".java"))
nme.substring(0, nme.length - 5)
else
throw new FatalError("Unexpected source file ending: "+ nme)
}
}
}
/**
* @param classes where the class files come from and are written to
* @param sources where the source files come from
* Represents a package which contains classes and other packages
*/
def output(classes : String, sources : String) = {
assert(classes ne null)
assert(sources ne null)
val location = AbstractFile.getDirectory(classes)
val sources0 = AbstractFile.getDirectory(sources)
class Output0 extends Output(location, sources0)
entries += new Output0()
}
abstract class ClassPath[T] {
/**
* @param classes where the class files come from
* @param sources optional source file attachment, otherwise null
* The short name of the package (without prefix)
*/
def library(classes: String, sources: String) {
assert(classes ne null)
val location = AbstractFile.getDirectory(classes)
var sourceFile0 =
if (sources ne null) AbstractFile.getDirectory(sources)
else null
if (sourceFile0 ne null) {
val file00 = sourceFile0.lookupPath("src", true)
if ((file00 ne null) && file00.isDirectory) {
sourceFile0 = file00
def name: String
def classes: List[ClassRep[T]]
def packages: List[ClassPath[T]]
def sourcepaths: List[AbstractFile]
/**
* 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]] = {
val i = name.indexOf('.')
if (i < 0) {
classes.find(c => c.name == name)
} else {
val pkg = name.substring(0, i)
val rest = name.substring(i + 1, name.length)
packages.find(p => p.name == pkg).flatMap(_.findClass(rest))
}
}
}
class Library0 extends Library(location) {
override def sourceFile = sourceFile0
/**
* A Classpath containing source files
*/
class SourcePath[T](dir: AbstractFile) extends ClassPath[T] {
def name = dir.name
def classes = {
val cls = new ListBuffer[ClassRep[T]]
for (f <- dir.iterator) {
if (!f.isDirectory && ClassPath.validSourceFile(f.name))
cls += ClassRep[T](None, Some(f))
}
entries += new Library0()
cls.toList
}
private def addFilesInPath(path: String) {
for (fileName <- ClassPath.expandPath(path)) {
def packages = {
val pkg = new ListBuffer[SourcePath[T]]
for (f <- dir.iterator) {
if (f.isDirectory && ClassPath.validPackage(f.name))
pkg += new SourcePath[T](f)
}
pkg.toList
}
def sourcepaths: List[AbstractFile] = List(dir)
override def toString() = "sourcepath: "+ dir.toString()
}
/**
* A directory (or a .jar file) containing classfiles and packages
*/
class DirectoryClassPath(dir: AbstractFile) extends ClassPath[AbstractFile] {
def name = dir.name
def classes = {
val cls = new ListBuffer[ClassRep[AbstractFile]]
for (f <- dir.iterator) {
if (!f.isDirectory && ClassPath.validClassFile(f.name))
cls += ClassRep(Some(f), None)
}
cls.toList
}
def packages = {
val pkg = new ListBuffer[DirectoryClassPath]
for (f <- dir.iterator) {
if (f.isDirectory && ClassPath.validPackage(f.name))
pkg += new DirectoryClassPath(f)
}
pkg.toList
}
def sourcepaths: List[AbstractFile] = Nil
override def toString() = "directory classpath: "+ dir.toString()
}
/**
* A assembly file (dll / exe) containing classes and namespaces
*/
class AssemblyClassPath(types: Array[MSILType], namespace: String) extends ClassPath[MSILType] {
def name = {
val i = namespace.lastIndexOf('.')
if (i < 0) namespace
else namespace.substring(i + 1, namespace.length)
}
def this(assemFile: AbstractFile) {
this(ClassPath.collectTypes(assemFile), "")
}
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
}
def 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
}
def 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)
}
def sourcepaths: List[AbstractFile] = Nil
override def toString() = "assembly classpath "+ namespace
}
/**
* A classpath unifying multiple class- and sourcepath entries.
*/
abstract class MergedClassPath[T] extends ClassPath[T] {
protected val entries: List[ClassPath[T]]
def name = entries.head.name
def classes: List[ClassRep[T]] = {
val cls = new ListBuffer[ClassRep[T]]
for (e <- entries; c <- e.classes) {
val name = c.name
val idx = cls.indexWhere(cl => cl.name == name)
if (idx >= 0) {
val existing = cls(idx)
if (existing.binary.isEmpty && c.binary.isDefined)
cls(idx) = existing.copy(binary = c.binary)
if (existing.source.isEmpty && c.source.isDefined)
cls(idx) = existing.copy(source = c.source)
} else {
cls += c
}
}
cls.toList
}
def packages: List[ClassPath[T]] = {
val pkg = new ListBuffer[ClassPath[T]]
for (e <- entries; p <- e.packages) {
val name = p.name
val idx = pkg.indexWhere(pk => pk.name == name)
if (idx >= 0) {
pkg(idx) = addPackage(pkg(idx), p)
} else {
pkg += p
}
}
pkg.toList
}
def sourcepaths: List[AbstractFile] = entries.flatMap(_.sourcepaths)
private def addPackage(to: ClassPath[T], pkg: ClassPath[T]) = to match {
case cp: MergedClassPath[T] =>
newMergedClassPath(cp.entries ::: List(pkg))
case _ =>
newMergedClassPath(List(to, pkg))
}
private def newMergedClassPath(entrs: List[ClassPath[T]]): MergedClassPath[T] =
new MergedClassPath[T] {
protected val entries = entrs
}
override def toString() = "merged classpath "+ entries.mkString("(", "\n", ")")
}
/**
* The classpath when compiling with target:jvm. Binary files (classfiles) are represented
* as AbstractFile. nsc.io.ZipArchive is used to view zip/jar archives as directories.
*/
class JavaClassPath(boot: String, ext: String, user: String, source: String, Xcodebase: String)
extends MergedClassPath[AbstractFile] {
protected val entries: List[ClassPath[AbstractFile]] = assembleEntries()
private def assembleEntries(): List[ClassPath[AbstractFile]] = {
import ClassPath._
val etr = new ListBuffer[ClassPath[AbstractFile]]
def addFilesInPath(path: String, expand: Boolean,
ctr: AbstractFile => ClassPath[AbstractFile] = x => new DirectoryClassPath(x)) {
for (fileName <- expandPath(path, expandStar = expand)) {
val file = AbstractFile.getDirectory(fileName)
if (file ne null) entries += (new Library(file))
if (file ne null) etr += ctr(file)
}
}
private def addArchivesInExtDirPath(path: String) {
for (fileName <- ClassPath.expandPath(path)) {
val file = AbstractFile.getDirectory(fileName)
if (file ne null) {
for (file0 <- file) {
val name = file0.name
if (name.endsWith(".jar") || name.endsWith(".zip") || file0.isDirectory) {
val archive = AbstractFile.getDirectory(new File(file.file, name))
if (archive ne null) entries += (new Library(archive))
}
// 1. Boot classpath
addFilesInPath(boot, false)
// 2. Ext classpath
for (fileName <- expandPath(ext, expandStar = false)) {
val dir = AbstractFile.getDirectory(fileName)
if (dir ne null) {
for (file <- dir) {
val name = file.name.toLowerCase
if (name.endsWith(".jar") || name.endsWith(".zip") || file.isDirectory) {
val archive = AbstractFile.getDirectory(new File(dir.file, name))
if (archive ne null) etr += new DirectoryClassPath(archive)
}
}
}
}
private def addDirsInPath(source: String, output: String) {
val clazzes = AbstractFile.getDirectory(output)
if (clazzes eq null)
throw new FatalError("Output location \"" + output + "\" not found")
val strtok = new StringTokenizer(source, File.pathSeparator)
if (!strtok.hasMoreTokens()) {
val output0 = (new Output(clazzes, null))
entries += output0
}
else while (strtok.hasMoreTokens()) {
val sources = AbstractFile.getDirectory(strtok.nextToken())
val output0 = (new Output(clazzes, sources))
entries += output0
}
}
// 3. User classpath
addFilesInPath(user, true)
private val urlSeparator = " "
private def addURLsInPath(codebase: String) {
val strtok = new StringTokenizer(codebase, urlSeparator)
while (strtok.hasMoreTokens()) {
try {
val url = new URL(strtok.nextToken())
// 4. Codebase entries (URLs)
{
val urlSeparator = " "
val urlStrtok = new StringTokenizer(Xcodebase, urlSeparator)
while (urlStrtok.hasMoreTokens()) try {
val url = new URL(urlStrtok.nextToken())
val archive = AbstractFile.getURL(url)
if (archive ne null) entries += (new Library(archive))
if (archive ne null) etr += new DirectoryClassPath(archive)
}
catch {
case e =>
Console.println("error in addURLsInPath: " + e.getMessage)//debug
Console.println("error adding classpath form URL: " + e.getMessage)//debug
throw e
}
}
// 5. Source path
if (source != "")
addFilesInPath(source, false, x => new SourcePath[AbstractFile](x))
etr.toList
}
}
override def toString() =
entries.toList.mkString("", File.pathSeparator, "")
} // class Build
/**
* The classpath when compiling with target:msil. Binary files are represented as
* MSILType values.
*/
class MsilClassPath(ext: String, user: String, source: String) 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)
}
}
}
}
// 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)
}
}
}
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)
}
etr.toList
}
}

View File

@ -36,13 +36,12 @@ trait XMLLoader[T <: Node]
*/
def loadXML(source: InputSource, parser: SAXParser): T = {
val newAdapter = adapter
import newAdapter._
scopeStack push TopScope
newAdapter.scopeStack push TopScope
parser.parse(source, newAdapter)
scopeStack.pop
newAdapter.scopeStack.pop
rootElem.asInstanceOf[T]
newAdapter.rootElem.asInstanceOf[T]
}
/** Loads XML from the given file, file descriptor, or filename. */

View File

@ -57,11 +57,10 @@ class ReflectiveRunner extends RunnerUtils {
val newClasspath = paths mkString pathSeparator
syspropset("java.class.path", newClasspath)
syspropset("env.classpath", newClasspath)
syspropset("scala.home", "")
if (fileManager.debug)
for (prop <- List("java.class.path", "env.classpath", "sun.boot.class.path", "java.ext.dirs"))
for (prop <- List("java.class.path", "sun.boot.class.path", "java.ext.dirs"))
println(prop + ": " + sysprop(prop))
try {

View File

@ -11,8 +11,9 @@ package scala.tools.scalap
import java.io.{File, PrintStream, OutputStreamWriter, ByteArrayOutputStream}
import scala.tools.nsc.util.ClassPath
import scalax.rules.scalasig._
import tools.nsc.io.AbstractFile
import tools.nsc.util.{ClassPath, JavaClassPath}
/**The main object used to execute scalap on the command-line.
*
@ -61,7 +62,7 @@ object Main {
out.flush()
}
def isPackageObjectFile(s: String) = s != null && (s.endsWith(File.separator + "package") || s == "package")
def isPackageObjectFile(s: String) = s != null && (s.endsWith(".package") || s == "package")
def parseScalaSignature(scalaSig: ScalaSig, isPackageObject: Boolean) = {
val baos = new ByteArrayOutputStream
@ -112,19 +113,20 @@ object Main {
* @param path...
* @param classname...
*/
def process(args: Arguments, path: ClassPath#Build)(classname: String): Unit = {
def process(args: Arguments, path: ClassPath[AbstractFile])(classname: String): Unit = {
// find the classfile
val filename = Names.encode(
val encName = Names.encode(
if (classname == "scala.AnyRef") "java.lang.Object"
else classname).replace('.', File.separatorChar)
val cfile = path.lookupPath(filename, /*isDir*/ false)
if (cfile != null) {
else classname)
val cls = path.findClass(encName)
if (cls.isDefined && cls.get.binary.isDefined) {
val cfile = cls.get.binary.get
if (verbose) {
Console.println(Console.BOLD + "FILENAME" + Console.RESET + " = " + cfile.path)
}
val bytes = cfile.toByteArray
if (isScalaFile(bytes)) {
decompileScala(bytes, isPackageObjectFile(filename))
decompileScala(bytes, isPackageObjectFile(encName))
} else {
// construct a reader for the classfile content
val reader = new ByteArrayReader(cfile.toByteArray)
@ -261,13 +263,12 @@ object Main {
verbose = arguments contains "-verbose"
printPrivates = arguments contains "-private"
// construct a custom class path
val classPath0 = new ClassPath(false)
val path = arguments.getArgument("-classpath") match {
case None => arguments.getArgument("-cp") match {
case None => new classPath0.Build()
case Some(path) => new classPath0.Build(path)
case None => EmptyClasspath
case Some(path) => new JavaClassPath("", "", path, "", "")
}
case Some(path) => new classPath0.Build(path)
case Some(path) => new JavaClassPath("", "", path, "", "")
}
// print the classpath if output is verbose
if (verbose) {
@ -277,4 +278,15 @@ object Main {
arguments.getOthers.foreach(process(arguments, path))
}
}
object EmptyClasspath extends ClassPath[AbstractFile] {
import tools.nsc.util.ClassRep
/**
* The short name of the package (without prefix)
*/
def name: String = ""
def classes: List[ClassRep[AbstractFile]] = Nil
def packages: List[ClassPath[AbstractFile]] = Nil
def sourcepaths: List[AbstractFile] = Nil
}
}

View File

@ -175,10 +175,13 @@ def f(e: Exp) = e match {{ // non-exhaustive warning here
val output = new PrintWriter(
new Skip1Writer(new OutputStreamWriter(Console.out)))
val repl = new InterpreterLoop(input, output)
repl.main(new Settings)
val settings = new Settings
// when running that compiler, give it a scala-library to the classpath
settings.classpath.value = System.getProperty("java.class.path")
repl.main(settings)
println()
val interp = new Interpreter(new Settings)
val interp = new Interpreter(settings)
interp.interpret("def plusOne(x: Int) = x + 1")
interp.interpret("plusOne(5)")
interp.reset()

View File

@ -90,6 +90,8 @@ object Test {
settings.Xexperimental.value = true
settings.selfInAnnots.value = true
settings.deprecation.value = true
// when running that compiler, give it a scala-library to the classpath
settings.classpath.value = System.getProperty("java.class.path")
val interp = new Interpreter(settings)

View File

@ -113,6 +113,8 @@ object Foo2 {
var reporter: ConsoleReporter = _
def process(args: Array[String]) {
val docSettings = new scala.tools.nsc.doc.Settings(error)
// when running that compiler, give it a scala-library to the classpath
docSettings.classpath.value = System.getProperty("java.class.path")
reporter = new ConsoleReporter(docSettings)
val command = new CompilerCommand(args.toList, docSettings, error, false)
try {

View File

@ -332,7 +332,7 @@ object LispAny extends Lisp {
val result = eval1(x, env);
if (trace) {
indent -= 1;
for (val x <- range(1, indent)) Console.print(" ");
for (x <- range(1, indent)) Console.print(" ");
Console.println("<=== " + result);
}
curexp = prevexp;

View File

@ -20,6 +20,8 @@ object Test {
val tool = new Interpreter(new Settings())
val global = tool.compiler
// when running that compiler, give it a scala-library to the classpath
global.settings.classpath.value = System.getProperty("java.class.path")
import global._
import definitions._

View File

@ -31,6 +31,9 @@ object Test {
val tool = new Interpreter(new Settings())
val global = tool.compiler
// when running that compiler, give it a scala-library to the classpath
global.settings.classpath.value = System.getProperty("java.class.path")
import global._
import definitions._