diff options
author | Martin Odersky <odersky@gmail.com> | 2009-01-13 18:50:50 +0000 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2009-01-13 18:50:50 +0000 |
commit | 323e895672ba0f9426be33de485bb7a6190af74c (patch) | |
tree | 97da75af4762b055dcd095ce84d2232af119ff12 /src | |
parent | 55795630fd0b7a4dd3e25dff1b9618e6f73adf23 (diff) | |
download | scala-323e895672ba0f9426be33de485bb7a6190af74c.tar.gz scala-323e895672ba0f9426be33de485bb7a6190af74c.tar.bz2 scala-323e895672ba0f9426be33de485bb7a6190af74c.zip |
renamed util.control.Break to Breaks and added ...
renamed util.control.Break to Breaks and added support for continue.
Fully implemented package objects.
Diffstat (limited to 'src')
14 files changed, 132 insertions, 71 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala index 6a41a36005..ba00802af7 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala @@ -2360,8 +2360,11 @@ trait Parsers extends NewScanners with MarkupParsers { while (inToken != RBRACE && inToken != EOF) { if (inToken == PACKAGE) { val pkgPos = accept(PACKAGE) - stats += (if (inToken == OBJECT) objectDef(Modifiers(Flags.PACKAGE)) - else packaging(pkgPos)) + stats += { + if (inToken == OBJECT) + atPos(pkgPos) { makePackageObject(objectDef(NoMods)) } + else packaging(pkgPos) + } } else if (inToken == IMPORT) { stats ++= importClause() // XXX: IDE hook this all. @@ -2516,9 +2519,9 @@ trait Parsers extends NewScanners with MarkupParsers { // @S: just eat them (doesn't really change the grammar) while (inToken == SEMI) inNextToken if (inToken == PACKAGE) { - inNextToken + pos = inSkipToken if (in.token == OBJECT) { - ts += objectDef(Modifiers(Flags.PACKAGE)) + ts += makePackageObject(objectDef(NoMods)) if (inToken != EOF) { acceptStatSep() ts ++= topStatSeq() diff --git a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala index 4a4d05ebf5..c52e514119 100644 --- a/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala +++ b/src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala @@ -453,5 +453,11 @@ abstract class TreeBuilder { makePackaging(qual, List(PackageDef(name, stats).setPos(pkg.pos))) } + /** Create a tree representing a package object */ + def makePackageObject(objDef: ModuleDef): PackageDef = objDef match { + case ModuleDef(mods, name, impl) => + makePackaging(Ident(name), List(ModuleDef(mods, nme.PACKAGEkw, impl))) + } + case class Parens(args: List[Tree]) extends Tree } diff --git a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala index d64849c767..74a63b4e0c 100644 --- a/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala +++ b/src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala @@ -118,13 +118,16 @@ abstract class SymbolLoaders { protected def newPackageLoader(dir: global.classPath0.Context): PackageLoader = new PackageLoader(dir) - protected def checkSource(name: String, source: AbstractFile): Boolean = true + protected def checkSource(name: String, source: AbstractFile): Boolean = source ne null var root: Symbol = _ def enterPackage(name: String, completer: SymbolLoader) { - if (inIDE && root.info.decls.lookup(newTermName(name)) != NoSymbol) { - return // refresh + val preExisting = root.info.decls.lookup(newTermName(name)) + if (preExisting != NoSymbol) { + if (inIDE) return + else 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) @@ -158,44 +161,41 @@ abstract class SymbolLoaders { assert(root.isPackageClass, root) this.root = root root.setInfo(new PackageClassInfoType(scope, root, this)) - refresh + refresh() } - def 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*/true || - (name.indexOf("$anon") == -1)); + name.length() > 0 && !name.endsWith("$class") + (/*settings.XO.value*/true || name.indexOf("$anon") == -1) 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 + } + } + } + for (dir <- directory.entries) if ((dir.location ne null) && (!inIDE || 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 && !file.isDirectory && file.name.endsWith(".class")) { - val name = file.name.substring(0, file.name.length() - (".class").length()); - if (isValid(name) && !classes.isDefinedAt(name)) { - val clazz = directory.find(name, false) - if (clazz ne null) classes(name) = clazz - } - } + else if (!global.forMSIL) + recordClass(file, ".class", source => true) } } 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 && !file.isDirectory && file.name.endsWith(".scala")) { - val name = file.name.substring(0, file.name.length() - (".scala").length()) - if (isValid(name) && !classes.isDefinedAt(name)) { - val source = directory.find(name, false) - if ((source ne null) && (source.sourceFile ne null)) - if (checkSource(name, source.sourceFile)) - classes(name) = source - else if (settings.debug.value) - Console.println("Skipping source file " + source.sourceFile) - } - } + else if (dir.source.compile) + recordClass(file, ".scala", source => checkSource(name, source.sourceFile)) } } @@ -209,8 +209,20 @@ abstract class SymbolLoaders { } enterClassAndModule(name, loader) } + + // packages second for ((name, file) <- packages.elements) enterPackage(name, newPackageLoader(file)) + + // if there's a $member object, enter its members as well. + val membersModule = root.info.decl(nme.PACKAGEkw) + if (membersModule.isModule) { + for (member <- membersModule.info.decls.elements) { + // todo: handle overlapping definitions in some way: mark as errors + // or treat as abstractions. + root.info.decls.enter(member) + } + } } } @@ -230,8 +242,12 @@ abstract class SymbolLoaders { 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 = - !types.contains(name) + 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 + } override protected def doComplete(root: Symbol) { clrTypes.collectMembers(root, types, namespaces) diff --git a/src/compiler/scala/tools/nsc/typechecker/Infer.scala b/src/compiler/scala/tools/nsc/typechecker/Infer.scala index a8062a8163..7009adb35d 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Infer.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Infer.scala @@ -327,12 +327,6 @@ trait Infer { /** Check that <code>sym</code> is defined and accessible as a member of * tree <code>site</code> with type <code>pre</code> in current context. - * - * @param tree ... - * @param sym ... - * @param pre ... - * @param site ... - * @return ... */ def checkAccessible(tree: Tree, sym: Symbol, pre: Type, site: Tree): Tree = if (sym.isError) { diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala index adab0faebf..f3fe615e80 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala @@ -181,13 +181,13 @@ trait Namers { self: Analyzer => } def enterPackageSymbol(pos: Position, name: Name): Symbol = { - val cscope = if (context.owner == EmptyPackageClass) RootClass.info.decls - else context.scope + val (cscope, cowner) = + if (context.owner == EmptyPackageClass) (RootClass.info.decls, RootClass) + else (context.scope, context.owner) val p: Symbol = cscope.lookupWithContext(name)(context.owner) if (p.isPackage && cscope == p.owner.info.decls) { p } else { - val cowner = if (context.owner == EmptyPackageClass) RootClass else context.owner val pkg = cowner.newPackage(pos, name) // IDE: newScope should be ok because packages are never destroyed. if (inIDE) assert(!pkg.moduleClass.hasRawInfo || !pkg.moduleClass.rawInfo.isComplete) @@ -286,7 +286,7 @@ trait Namers { self: Analyzer => def deSkolemize: TypeMap = new DeSkolemizeMap(applicableTypeParams(context.owner)) // should be special path for IDE but maybe not.... - def enterSym(tree: Tree): Context = { + def enterSym(tree: Tree): Context = try { def finishWith(tparams: List[TypeDef]) { val sym = tree.symbol @@ -399,6 +399,11 @@ trait Namers { self: Analyzer => } } this.context + } catch { + case ex: TypeError => + //Console.println("caught " + ex + " in enterSym")//DEBUG + typer.reportTypeError(tree.pos, ex) + this.context } def enterSyntheticSym(tree: Tree): Symbol = { diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala index 2c399b60d9..5a9ac741f6 100644 --- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala +++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala @@ -524,13 +524,40 @@ trait Typers { self: Analyzer => (mode & QUALmode) != 0 && !tree.symbol.isConstant || pt.typeSymbol.isAbstractType && pt.bounds.lo.isStable && !(tree.tpe <:< pt))) - /** <p> - * Post-process an identifier or selection node, performing the following: - * </p> - * <ol> - * <!--(1)--><li>Check that non-function pattern expressions are stable</li> - * <!--(2)--><li>Check that packages and static modules are not used as values</li> - * <!--(3)--><li>Turn tree type into stable type if possible and required by context.</li> + /** Make symbol accessible. This means: + * If symbol refers to package object, insert `.package` as second to last selector. + * Call checkAccessible, which sets symbol's attributes. + */ + private def makeAccessible(tree: Tree, sym: Symbol, pre: Type, site: Tree): Tree = + if (isInPackageObject(sym, pre.typeSymbol)) { + val qual = typedQualifier { + tree match { + case Ident(_) => Ident(nme.PACKAGEkw) + case Select(qual, _) => Select(qual, nme.PACKAGEkw) + case SelectFromTypeTree(qual, _) => Select(qual, nme.PACKAGEkw) + } + } + val tree1 = tree match { + case Ident(name) => Select(qual, name) + case Select(_, name) => Select(qual, name) + case SelectFromTypeTree(_, name) => SelectFromTypeTree(qual, name) + } + val tree2 = checkAccessible(tree1, sym, qual.tpe, qual) + tree2 + } else { + checkAccessible(tree, sym, pre, site) + } + + private def isInPackageObject(sym: Symbol, pkg: Symbol) = + pkg.isPackageClass && + sym.owner.isModuleClass && + sym.owner.name.toTermName == nme.PACKAGEkw && + sym.owner.owner == pkg + + /** Post-process an identifier or selection node, performing the following: + * 1. Check that non-function pattern expressions are stable + * 2. Check that packages and static modules are not used as values + * 3. Turn tree type into stable type if possible and required by context. * </ol> */ private def stabilize(tree: Tree, pre: Type, mode: Int, pt: Type): Tree = { @@ -2842,7 +2869,7 @@ trait Typers { self: Analyzer => case Select(_, _) => copy.Select(tree, qual, name) case SelectFromTypeTree(_, _) => copy.SelectFromTypeTree(tree, qual, name) } - val result = stabilize(checkAccessible(tree1, sym, qual.tpe, qual), qual.tpe, mode, pt) + val result = stabilize(makeAccessible(tree1, sym, qual.tpe, qual), qual.tpe, mode, pt) if (phase.id <= currentRun.typerPhase.id && settings.Xchecknull.value && !sym.isConstructor && @@ -3014,7 +3041,7 @@ trait Typers { self: Analyzer => val tree1 = if (qual == EmptyTree) tree else atPos(tree.pos)(Select(qual, name)) // atPos necessary because qualifier might come from startContext - stabilize(checkAccessible(tree1, defSym, pre, qual), pre, mode, pt) + stabilize(makeAccessible(tree1, defSym, pre, qual), pre, mode, pt) } } diff --git a/src/library/scalax/collection/generic/IterableTemplate.scala b/src/library/scalax/collection/generic/IterableTemplate.scala index c48c8dfdf5..c2f1fadd9c 100755 --- a/src/library/scalax/collection/generic/IterableTemplate.scala +++ b/src/library/scalax/collection/generic/IterableTemplate.scala @@ -13,7 +13,7 @@ package scalax.collection.generic import scalax.collection.mutable.{Buffer, ArrayBuffer, ListBuffer} import scalax.collection.immutable.{List, Nil, ::, Stream} -import util.control.Break._ +import util.control.Breaks._ import Iterable._ /** Collection classes mixing in this class provide a method diff --git a/src/library/scalax/collection/generic/SequenceTemplate.scala b/src/library/scalax/collection/generic/SequenceTemplate.scala index 6cbe3e0fd6..27bba86ba0 100755 --- a/src/library/scalax/collection/generic/SequenceTemplate.scala +++ b/src/library/scalax/collection/generic/SequenceTemplate.scala @@ -11,7 +11,7 @@ package scalax.collection.generic -import util.control.Break._ +import util.control.Breaks._ import scalax.collection.immutable.{List, Nil, ::} import Sequence._ diff --git a/src/library/scalax/collection/generic/SequenceView.scala b/src/library/scalax/collection/generic/SequenceView.scala index 4cbf00b48d..72e863d4f2 100755 --- a/src/library/scalax/collection/generic/SequenceView.scala +++ b/src/library/scalax/collection/generic/SequenceView.scala @@ -11,7 +11,7 @@ package scalax.collection.generic -import util.control.Break._ +import util.control.Breaks._ import annotation.unchecked.uncheckedVariance import Sequence._ diff --git a/src/library/scalax/collection/generic/covartest/IterableTemplate.scala b/src/library/scalax/collection/generic/covartest/IterableTemplate.scala index bb5cc5e22d..27772b2ece 100755 --- a/src/library/scalax/collection/generic/covartest/IterableTemplate.scala +++ b/src/library/scalax/collection/generic/covartest/IterableTemplate.scala @@ -13,7 +13,7 @@ package scalax.collection.generic.covartest import scalax.collection.mutable.{Buffer, ArrayBuffer, ListBuffer} import scalax.collection.immutable.{List, Nil, ::, Stream} -import util.control.Break._ +import util.control.Breaks._ import Iterable._ /** Collection classes mixing in this class provide a method diff --git a/src/library/scalax/collection/generic/covartest/SequenceTemplate.scala b/src/library/scalax/collection/generic/covartest/SequenceTemplate.scala index c0f9dcf69f..eab7904af8 100755 --- a/src/library/scalax/collection/generic/covartest/SequenceTemplate.scala +++ b/src/library/scalax/collection/generic/covartest/SequenceTemplate.scala @@ -11,7 +11,7 @@ package scalax.collection.generic.covartest -import util.control.Break._ +import util.control.Breaks._ import scalax.collection.immutable.{List, Nil, ::} import Sequence._ diff --git a/src/library/scalax/collection/generic/covartest/SequenceView.scala b/src/library/scalax/collection/generic/covartest/SequenceView.scala index feb3c059ee..bae43636ae 100755 --- a/src/library/scalax/collection/generic/covartest/SequenceView.scala +++ b/src/library/scalax/collection/generic/covartest/SequenceView.scala @@ -11,7 +11,7 @@ package scalax.collection.generic.covartest -import util.control.Break._ +import util.control.Breaks._ import annotation.unchecked.uncheckedVariance import Sequence._ diff --git a/src/library/scalax/util/control/Break.scala b/src/library/scalax/util/control/Break.scala deleted file mode 100755 index 173188d2e9..0000000000 --- a/src/library/scalax/util/control/Break.scala +++ /dev/null @@ -1,15 +0,0 @@ -package scalax.util.control - -object Break { - private class BreakException extends RuntimeException - private val breakException = new BreakException - def break { throw breakException } - def breakable(op: => Unit) { - try { - op - } catch { - case ex: BreakException => - } - } -} - diff --git a/src/library/scalax/util/control/Breaks.scala b/src/library/scalax/util/control/Breaks.scala new file mode 100755 index 0000000000..d5ca883b77 --- /dev/null +++ b/src/library/scalax/util/control/Breaks.scala @@ -0,0 +1,25 @@ +package scalax.util.control + +object Breaks { + private class BreakException extends RuntimeException + private val breakException = new BreakException + private class ContinueException extends RuntimeException + private val continueException = new BreakException + def break { throw breakException } + def breakable(op: => Unit) { + try { + op + } catch { + case ex: BreakException => + } + } + def continue { throw continueException } + def continuable(op: => Unit) { + try { + op + } catch { + case ex: ContinueException => + continuable(op) + } + } +} |