summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2009-01-13 18:50:50 +0000
committerMartin Odersky <odersky@gmail.com>2009-01-13 18:50:50 +0000
commit323e895672ba0f9426be33de485bb7a6190af74c (patch)
tree97da75af4762b055dcd095ce84d2232af119ff12
parent55795630fd0b7a4dd3e25dff1b9618e6f73adf23 (diff)
downloadscala-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.
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/Parsers.scala11
-rw-r--r--src/compiler/scala/tools/nsc/ast/parser/TreeBuilder.scala6
-rw-r--r--src/compiler/scala/tools/nsc/symtab/SymbolLoaders.scala70
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Infer.scala6
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala13
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala45
-rwxr-xr-xsrc/library/scalax/collection/generic/IterableTemplate.scala2
-rwxr-xr-xsrc/library/scalax/collection/generic/SequenceTemplate.scala2
-rwxr-xr-xsrc/library/scalax/collection/generic/SequenceView.scala2
-rwxr-xr-xsrc/library/scalax/collection/generic/covartest/IterableTemplate.scala2
-rwxr-xr-xsrc/library/scalax/collection/generic/covartest/SequenceTemplate.scala2
-rwxr-xr-xsrc/library/scalax/collection/generic/covartest/SequenceView.scala2
-rwxr-xr-xsrc/library/scalax/util/control/Break.scala15
-rwxr-xr-xsrc/library/scalax/util/control/Breaks.scala25
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)
+ }
+ }
+}