summaryrefslogtreecommitdiff
path: root/src/compiler/scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2011-08-29 17:15:56 +0000
committerMartin Odersky <odersky@gmail.com>2011-08-29 17:15:56 +0000
commit6d717dc9865cc5a957f0d634acc6fc2dc2665301 (patch)
tree09f684f4d6ee37e64405cb246267b6e9559b0159 /src/compiler/scala
parent65bf9178c4c3d92cb9e498d09587e45c14eba594 (diff)
downloadscala-6d717dc9865cc5a957f0d634acc6fc2dc2665301.tar.gz
scala-6d717dc9865cc5a957f0d634acc6fc2dc2665301.tar.bz2
scala-6d717dc9865cc5a957f0d634acc6fc2dc2665301.zip
Added package object support to reflection fram...
Added package object support to reflection framework. Removed debug output and made some speed improvements.
Diffstat (limited to 'src/compiler/scala')
-rw-r--r--src/compiler/scala/reflect/internal/SymbolTable.scala38
-rw-r--r--src/compiler/scala/reflect/internal/Types.scala1
-rw-r--r--src/compiler/scala/reflect/runtime/JavaToScala.scala10
-rw-r--r--src/compiler/scala/reflect/runtime/Loaders.scala76
-rw-r--r--src/compiler/scala/reflect/runtime/Mirror.scala3
-rw-r--r--src/compiler/scala/reflect/runtime/SymbolTable.scala7
-rw-r--r--src/compiler/scala/tools/nsc/symtab/BrowsingLoaders.scala2
-rw-r--r--src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala32
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Analyzer.scala2
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala5
10 files changed, 91 insertions, 85 deletions
diff --git a/src/compiler/scala/reflect/internal/SymbolTable.scala b/src/compiler/scala/reflect/internal/SymbolTable.scala
index 0ddfc2df50..3ab2408cf7 100644
--- a/src/compiler/scala/reflect/internal/SymbolTable.scala
+++ b/src/compiler/scala/reflect/internal/SymbolTable.scala
@@ -123,6 +123,44 @@ abstract class SymbolTable extends api.Universe
}
}
+ def openPackageModule(container: Symbol, dest: Symbol) {
+ // unlink existing symbols in the package
+ for (member <- container.info.decls.iterator) {
+ if (!member.isPrivate && !member.isConstructor) {
+ // todo: handle overlapping definitions in some way: mark as errors
+ // or treat as abstractions. For now the symbol in the package module takes precedence.
+ for (existing <- dest.info.decl(member.name).alternatives)
+ dest.info.decls.unlink(existing)
+ }
+ }
+ // enter non-private decls the class
+ for (member <- container.info.decls.iterator) {
+ if (!member.isPrivate && !member.isConstructor) {
+ dest.info.decls.enter(member)
+ }
+ }
+ // enter decls of parent classes
+ for (pt <- container.info.parents; p = pt.typeSymbol) {
+ if (p != definitions.ObjectClass && p != definitions.ScalaObjectClass) {
+ openPackageModule(p, dest)
+ }
+ }
+ }
+
+ /** if there's a `package` member object in `pkgClass`, enter its members into it. */
+ def openPackageModule(pkgClass: Symbol) {
+
+ val pkgModule = pkgClass.info.decl(nme.PACKAGEkw)
+ def fromSource = pkgModule.rawInfo match {
+ case ltp: LazyType => ltp.fromSource
+ case _ => false
+ }
+ if (pkgModule.isModule && !fromSource) {
+ // println("open "+pkgModule)//DEBUG
+ openPackageModule(pkgModule, pkgClass)
+ }
+ }
+
object perRunCaches {
import java.lang.ref.WeakReference
import scala.runtime.ScalaRunTime.stringOf
diff --git a/src/compiler/scala/reflect/internal/Types.scala b/src/compiler/scala/reflect/internal/Types.scala
index 349fa2bb68..5049b6bd90 100644
--- a/src/compiler/scala/reflect/internal/Types.scala
+++ b/src/compiler/scala/reflect/internal/Types.scala
@@ -2758,6 +2758,7 @@ A type's typeSymbol should never be inspected directly.
/** A class representing an as-yet unevaluated type.
*/
abstract class LazyType extends Type {
+ def fromSource = false
override def isComplete: Boolean = false
override def complete(sym: Symbol)
override def safeToString = "<?>"
diff --git a/src/compiler/scala/reflect/runtime/JavaToScala.scala b/src/compiler/scala/reflect/runtime/JavaToScala.scala
index 35e95b4799..e598e7751d 100644
--- a/src/compiler/scala/reflect/runtime/JavaToScala.scala
+++ b/src/compiler/scala/reflect/runtime/JavaToScala.scala
@@ -51,13 +51,12 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable =>
else "error while loading " + clazz.name + ", " + msg)
}
try {
- println("unpickling " + clazz + " " + module) //debug
+ info("unpickling " + clazz + " " + module) //debug
markAbsent(NoType)
val ssig = jclazz.getAnnotation(classOf[scala.reflect.ScalaSignature])
if (ssig != null) {
val bytes = ssig.bytes.getBytes
val len = ByteCodecs.decode(bytes)
- println("short sig:" + len)
unpickler.unpickle(bytes take len, 0, clazz, module, jclazz.getName)
} else {
val slsig = jclazz.getAnnotation(classOf[scala.reflect.ScalaLongSignature])
@@ -70,10 +69,9 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable =>
bs.copyToArray(bytes, len, l)
len += l
}
- println("long sig") //debug
unpickler.unpickle(bytes, 0, clazz, module, jclazz.getName)
} else { // class does not have a Scala signature; it's a Java class
- println("no sig found for " + jclazz) //debug
+ info("no sig found for " + jclazz) //debug
initClassModule(clazz, module, new FromJavaClassCompleter(clazz, module, jclazz))
}
}
@@ -127,7 +125,7 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable =>
*/
private class FromJavaClassCompleter(clazz: Symbol, module: Symbol, jclazz: jClass[_]) extends LazyType {
override def complete(sym: Symbol) = {
- println("completing from Java " + sym + "/" + clazz.fullName)//debug
+ info("completing from Java " + sym + "/" + clazz.fullName)//debug
assert(sym == clazz || sym == module || sym == module.moduleClass, sym)
val flags = toScalaFlags(jclazz.getModifiers, isClass = true)
clazz setFlag (flags | JAVA)
@@ -288,7 +286,7 @@ trait JavaToScala extends ConversionUtil { self: SymbolTable =>
var pkg = owner.info decl name
if (pkg == NoSymbol) {
pkg = owner.newPackage(NoPosition, name)
- pkg.moduleClass setInfo newPackageType(pkg.moduleClass)
+ pkg.moduleClass setInfo new LazyPackageType
pkg setInfo typeRef(pkg.owner.thisType, pkg.moduleClass, Nil)
owner.info.decls enter pkg
} else if (!pkg.isPackage)
diff --git a/src/compiler/scala/reflect/runtime/Loaders.scala b/src/compiler/scala/reflect/runtime/Loaders.scala
index f3097e2b6e..070221fc00 100644
--- a/src/compiler/scala/reflect/runtime/Loaders.scala
+++ b/src/compiler/scala/reflect/runtime/Loaders.scala
@@ -2,15 +2,15 @@ package scala.reflect
package runtime
import internal.Flags
-
import java.lang.{Class => jClass, Package => jPackage}
+import collection.mutable
trait Loaders { self: SymbolTable =>
/** The lazy type for root.
*/
override val rootLoader = new LazyType {
- override def complete(sym: Symbol) = sym setInfo newPackageType(definitions.RootClass)
+ override def complete(sym: Symbol) = sym setInfo new LazyPackageType
}
/** The standard completer for top-level classes
@@ -21,34 +21,33 @@ trait Loaders { self: SymbolTable =>
* is found, a package is created instead.
*/
class TopClassCompleter(clazz: Symbol, module: Symbol) extends LazyType {
- def makePackage() {
- println("wrong guess; making package "+clazz)
- val ptpe = newPackageType(module.moduleClass)
- for (sym <- List(clazz, module, module.moduleClass)) {
- sym setFlag Flags.PACKAGE
- sym setInfo ptpe
- }
- }
+// def makePackage() {
+// println("wrong guess; making package "+clazz)
+// val ptpe = newPackageType(module.moduleClass)
+// for (sym <- List(clazz, module, module.moduleClass)) {
+// sym setFlag Flags.PACKAGE
+// sym setInfo ptpe
+// }
+// }
override def complete(sym: Symbol) = {
- println("completing "+sym+"/"+clazz.fullName+
- (if (sym == clazz) 1 else if (sym == module) 2 else if (sym == module.moduleClass) 3 else 4)) //debug
+ info("completing "+sym+"/"+clazz.fullName)
assert(sym == clazz || sym == module || sym == module.moduleClass)
- try {
- unpickleClass(clazz, module, jClass.forName(clazz.fullName))
- } catch {
- case ex: ClassNotFoundException => makePackage()
- case ex: NoClassDefFoundError => makePackage()
+// try {
+ unpickleClass(clazz, module, jClass.forName(clazz.fullName))
+// } catch {
+// case ex: ClassNotFoundException => makePackage()
+// case ex: NoClassDefFoundError => makePackage()
// Note: We catch NoClassDefFoundError because there are situations
// where a package and a class have the same name except for capitalization.
// It seems in this case the class is loaded even if capitalization differs
// but then a NoClassDefFound error is issued with a ("wrong name: ...")
// reason. (I guess this is a concession to Windows).
// The present behavior is a bit too forgiving, in that it masks
- // all class loade errors, not just wrong name errors. We should try
+ // all class load errors, not just wrong name errors. We should try
// to be more discriminating. To get on the right track simply delete
// the clause above and load a collection class such as collection.Iterable.
// You'll see an error that class `parallel` has the wrong name.
- }
+// }
}
}
@@ -74,43 +73,34 @@ trait Loaders { self: SymbolTable =>
module.moduleClass.setInfo(completer)
}
- /** The type for packages.
- * Since we cannot search the file system for classes in directories to populate
- * a package, we do the following instead: For every member that is looked up in
- * the package, create a class and companion object optimistically, giving it
- * a TopClassCompleter type. When any of the two symbols is forced via info,
- * the TopClassCompleter will sort things out.
+ /** The type completer for packages.
*/
- def newPackageType(pkgClass: Symbol) = new ClassInfoType(List(), new PackageScope(pkgClass), pkgClass) {
- /*
- override def decl(name: Name): Symbol =
- (decls lookup name) orElse {
- assert(this eq pkg.info, this+" "+pkg.info)
- assert(decls eq pkg.info.decls)
- //println("creating "+name+" in "+pkg) //debug
- val (clazz, module) = createClassModule(pkg, name.toTypeName, new TopClassCompleter(_, _))
- if (name.isTypeName) clazz else module
- }
- override def member(name: Name): Symbol = decl(name)
- override def findMember(name: Name, excludedFlags: Long, requiredFlags: Long, stableOnly: Boolean) =
- member(name).filter (m => m.hasAllFlags(requiredFlags) && !m.hasFlag(excludedFlags))
-*/
- override def safeToString = pkgClass.toString
+ class LazyPackageType extends LazyType {
+ override def complete(sym: Symbol) {
+ assert(sym.isPackageClass)
+ sym setInfo new ClassInfoType(List(), new PackageScope(sym), sym)
+ // override def safeToString = pkgClass.toString
+ openPackageModule(sym)
+ }
}
class PackageScope(pkgClass: Symbol) extends Scope {
+ private var negatives = mutable.Set[Name]()
override def lookupEntry(name: Name): ScopeEntry = {
val e = super.lookupEntry(name)
if (e != null)
e
+ else if (negatives contains name)
+ null
else try {
jClass.forName(pkgClass.fullName + "." + name)
val (clazz, module) = createClassModule(pkgClass, name.toTypeName, new TopClassCompleter(_, _))
- println("created "+module+"/"+module.moduleClass+" in "+pkgClass+", scope = "+(this map (_.name)))
+ info("created "+module+"/"+module.moduleClass+" in "+pkgClass+", scope = "+(this map (_.name)))
lookupEntry(name)
} catch {
- case ex: ClassNotFoundException =>
- println("not found : "+pkgClass.fullName + "." + name)
+ case (_: ClassNotFoundException) | (_: NoClassDefFoundError) =>
+ info("*** not found : "+pkgClass.fullName + "." + name)
+ negatives += name
null
}
}
diff --git a/src/compiler/scala/reflect/runtime/Mirror.scala b/src/compiler/scala/reflect/runtime/Mirror.scala
index eea45d787a..0591de5f78 100644
--- a/src/compiler/scala/reflect/runtime/Mirror.scala
+++ b/src/compiler/scala/reflect/runtime/Mirror.scala
@@ -72,7 +72,7 @@ object Mirror extends Mirror
/** test code; should go to tests once things settle down a bit
*
- */
+
object Test extends Mirror with App {
val sym = classToScala(classOf[scala.collection.Iterable[_]])
println(sym)
@@ -81,3 +81,4 @@ object Test extends Mirror with App {
val ms = sym.info.members.toList map (_.initialize)
println("members = "+(ms map (_.defString) mkString ("\n ")))
}
+*/ \ No newline at end of file
diff --git a/src/compiler/scala/reflect/runtime/SymbolTable.scala b/src/compiler/scala/reflect/runtime/SymbolTable.scala
index eb4026f7ef..419fed14bb 100644
--- a/src/compiler/scala/reflect/runtime/SymbolTable.scala
+++ b/src/compiler/scala/reflect/runtime/SymbolTable.scala
@@ -15,7 +15,7 @@ trait SymbolTable extends internal.SymbolTable with JavaToScala with ScalaToJava
if (name.isTermName && owner.hasPackageFlag)
makeScalaPackage(if (owner.isRoot) name.toString else owner.fullName+"."+name).sourceModule
else {
- println(name+"/"+name.isTermName+"/"+owner+"/"+owner.hasPackageFlag+"/"+owner.info.decls.getClass)
+ info("*** missing: "+name+"/"+name.isTermName+"/"+owner+"/"+owner.hasPackageFlag+"/"+owner.info.decls.getClass)
super.missingHook(owner, name)
}
@@ -23,4 +23,9 @@ trait SymbolTable extends internal.SymbolTable with JavaToScala with ScalaToJava
override def validateClassInfo(tp: ClassInfoType) {
assert(!tp.typeSymbol.isPackageClass || tp.decls.isInstanceOf[PackageScope])
}
+
+ protected var verbose = false
+
+ def info(msg: => String) =
+ if (verbose) println("[reflect-compiler] "+msg)
}
diff --git a/src/compiler/scala/tools/nsc/symtab/BrowsingLoaders.scala b/src/compiler/scala/tools/nsc/symtab/BrowsingLoaders.scala
index 390342cc06..59342a36ef 100644
--- a/src/compiler/scala/tools/nsc/symtab/BrowsingLoaders.scala
+++ b/src/compiler/scala/tools/nsc/symtab/BrowsingLoaders.scala
@@ -84,7 +84,7 @@ abstract class BrowsingLoaders extends SymbolLoaders {
entered += 1
if (name == nme.PACKAGEkw) {
println("open package module: "+module)
- loaders.openPackageModule(module)()
+ openPackageModule(module, root)
}
} else println("prefixes differ: "+packagePrefix+","+root.fullName)
case _ =>
diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
index c8c6a71038..45114a1dc0 100644
--- a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
+++ b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala
@@ -231,36 +231,7 @@ abstract class SymbolLoaders {
enterPackage(root, pkg.name, newPackageLoader(pkg))
}
- // 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]) {
- // println("open "+pkgModule)//DEBUG
- openPackageModule(pkgModule)()
- }
- }
- }
-
- def openPackageModule(module: Symbol)(packageClass: Symbol = module.owner): Unit = {
- // unlink existing symbols in the package
- for (member <- module.info.decls.iterator) {
- if (!member.isPrivate && !member.isConstructor) {
- // todo: handle overlapping definitions in some way: mark as errors
- // or treat as abstractions. For now the symbol in the package module takes precedence.
- for (existing <- packageClass.info.decl(member.name).alternatives)
- packageClass.info.decls.unlink(existing)
- }
- }
- // enter non-private decls the class
- for (member <- module.info.decls.iterator) {
- if (!member.isPrivate && !member.isConstructor) {
- packageClass.info.decls.enter(member)
- }
- }
- // enter decls of parent classes
- for (pt <- module.info.parents; p = pt.typeSymbol) {
- if (p != definitions.ObjectClass && p != definitions.ScalaObjectClass) {
- openPackageModule(p)(packageClass)
- }
+ openPackageModule(root)
}
}
@@ -328,6 +299,7 @@ abstract class SymbolLoaders {
class SourcefileLoader(val srcfile: AbstractFile) extends SymbolLoader {
protected def description = "source file "+ srcfile.toString
+ override def fromSource = true
override def sourcefile = Some(srcfile)
protected def doComplete(root: Symbol): Unit = global.currentRun.compileLate(srcfile)
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala b/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala
index 1635a9a534..e3786c154f 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Analyzer.scala
@@ -55,7 +55,7 @@ trait Analyzer extends AnyRef
override def traverse(tree: Tree): Unit = tree match {
case ModuleDef(_, _, _) =>
if (tree.symbol.name == nme.PACKAGEkw) {
- loaders.openPackageModule(tree.symbol)()
+ openPackageModule(tree.symbol, tree.symbol.owner)
}
case ClassDef(_, _, _, _) => () // make it fast
case _ => super.traverse(tree)
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index a94205e07a..7d68abccf0 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -191,8 +191,9 @@ trait Namers { self: Analyzer =>
var pkg = owner.info.decls.lookup(pid.name)
if (!pkg.isPackage || owner != pkg.owner) {
pkg = owner.newPackage(pos, pid.name.toTermName)
- pkg.moduleClass.setInfo(new PackageClassInfoType(new Scope, pkg.moduleClass))
- pkg.setInfo(pkg.moduleClass.tpe)
+ val pkgClass = pkg.moduleClass
+ pkgClass.setInfo(new PackageClassInfoType(newPackageScope(pkgClass), pkgClass))
+ pkg.setInfo(pkgClass.tpe)
enterInScope(pkg, owner.info.decls)
}
pkg