diff options
author | Martin Odersky <odersky@gmail.com> | 2011-08-29 17:15:56 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2011-08-29 17:15:56 +0000 |
commit | 6d717dc9865cc5a957f0d634acc6fc2dc2665301 (patch) | |
tree | 09f684f4d6ee37e64405cb246267b6e9559b0159 /src | |
parent | 65bf9178c4c3d92cb9e498d09587e45c14eba594 (diff) | |
download | scala-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')
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 |