summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2009-05-27 16:19:05 +0000
committerMartin Odersky <odersky@gmail.com>2009-05-27 16:19:05 +0000
commit2039b7fec7b902e3cef0a9c31a94ea96c2e469c8 (patch)
treecfa00f45f4f0fe0a502aab23e50088783851fa1f /src
parentb22342e78a3134d186f82dac5e1c7be01ece7c17 (diff)
downloadscala-2039b7fec7b902e3cef0a9c31a94ea96c2e469c8.tar.gz
scala-2039b7fec7b902e3cef0a9c31a94ea96c2e469c8.tar.bz2
scala-2039b7fec7b902e3cef0a9c31a94ea96c2e469c8.zip
Fixed problem that spurious caused exhaustivene...
Fixed problem that spurious caused exhaustiveness warning for RefChecks. Enriched positions and worked on the interactive compiler.
Diffstat (limited to 'src')
-rw-r--r--src/compiler/scala/tools/nsc/ast/NodePrinters.scala2
-rw-r--r--src/compiler/scala/tools/nsc/ast/TreePrinters.scala2
-rw-r--r--src/compiler/scala/tools/nsc/ast/Trees.scala12
-rwxr-xr-xsrc/compiler/scala/tools/nsc/ast/parser/Parsers.scala21
-rwxr-xr-xsrc/compiler/scala/tools/nsc/interactive/Global.scala41
-rw-r--r--src/compiler/scala/tools/nsc/interactive/REPL.scala70
-rw-r--r--src/compiler/scala/tools/nsc/symtab/Definitions.scala4
-rw-r--r--src/compiler/scala/tools/nsc/symtab/StdNames.scala1
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Typers.scala30
-rw-r--r--src/compiler/scala/tools/nsc/util/Position.scala3
-rw-r--r--src/compiler/scala/tools/nsc/util/trace.scala4
11 files changed, 145 insertions, 45 deletions
diff --git a/src/compiler/scala/tools/nsc/ast/NodePrinters.scala b/src/compiler/scala/tools/nsc/ast/NodePrinters.scala
index 57e60f9fba..4292cb24a0 100644
--- a/src/compiler/scala/tools/nsc/ast/NodePrinters.scala
+++ b/src/compiler/scala/tools/nsc/ast/NodePrinters.scala
@@ -341,8 +341,6 @@ abstract class NodePrinters {
}
printcln(")")
} else printcln(p.productPrefix)
- case _ =>
- printcln("***" + tree.getClass)
}
}
}
diff --git a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
index 4deccddde6..9e9b801d25 100644
--- a/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
+++ b/src/compiler/scala/tools/nsc/ast/TreePrinters.scala
@@ -389,7 +389,7 @@ abstract class TreePrinters {
}
def print(tree: Tree) {
- if (settings.Xprintpos.value) print("[" + tree.pos + "]")
+ if (settings.Xprintpos.value) print(tree.pos.show)
printRaw(
if (tree.isDef && tree.symbol != NoSymbol && tree.symbol.isInitialized) {
tree match {
diff --git a/src/compiler/scala/tools/nsc/ast/Trees.scala b/src/compiler/scala/tools/nsc/ast/Trees.scala
index 5e930bb4fc..12c5c9c46d 100644
--- a/src/compiler/scala/tools/nsc/ast/Trees.scala
+++ b/src/compiler/scala/tools/nsc/ast/Trees.scala
@@ -96,7 +96,7 @@ trait Trees {
// @M helper method for asserts that check consistency in kinding
//def kindingIrrelevant(tp: Type) = (tp eq null) || phase.name == "erasure" || phase.erasedTypes
- abstract class Tree {
+ abstract class Tree extends Product {
{
import util.Statistics
if (Statistics.enabled) nodeCount += 1
@@ -159,6 +159,10 @@ trait Trees {
/** Is there part of this tree which satisfies predicate `p'? */
def exists(p: Tree => Boolean): Boolean = !find(p).isEmpty
+ /** The direct children of this tree */
+ def children(): Iterator[Tree] =
+ productElements filter (_.isInstanceOf[Tree]) map (_.asInstanceOf[Tree])
+
override def toString(): String = {
val buffer = new StringWriter()
val printer = treePrinters.create(new PrintWriter(buffer))
@@ -190,10 +194,7 @@ trait Trees {
i += 1
}
}
- this match {
- case p : Product => g(p)
- case _ =>
- }
+ g(this)
hc
}
def equalsStructure(that : Tree) = equalsStructure0(that){case (t0,t1) => false}
@@ -1788,6 +1789,7 @@ trait Trees {
override def end: Int = original.pos.end
override def underlying = original.pos.underlying
override def focus = original.pos.focus
+ override def show = "["+underlying.show+"]"
}
}
diff --git a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
index 0aa4907fc6..4254be02d5 100755
--- a/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
+++ b/src/compiler/scala/tools/nsc/ast/parser/Parsers.scala
@@ -114,6 +114,7 @@ self =>
def freshName(pos: Position, prefix: String): Name
def o2p(offset: Int): Position
def r2p(start: Int, mid: Int, end: Int): Position
+ def t2p(tree: Tree): Position = SyntheticPosition(tree)
//private implicit def p2i(pos: Position) = pos.offset.get
/** whether a non-continuable syntax error has been seen */
@@ -370,7 +371,7 @@ self =>
*/
def joinComment(trees: => List[Tree]): List[Tree] = {
val buf = in.flushDoc
- if ((buf ne null) && buf.length > 0) trees map (t => DocDef(buf, t) setPos t.pos)
+ if ((buf ne null) && buf.length > 0) trees map (t => DocDef(buf, t) setPos t.pos) // !!! take true comment position
else trees
}
@@ -403,13 +404,13 @@ self =>
tree match {
case Ident(name) =>
removeAsPlaceholder(name)
- ValDef(Modifiers(Flags.PARAM), name, TypeTree(), EmptyTree)
+ ValDef(Modifiers(Flags.PARAM), name, TypeTree() setPos o2p(tree.pos.end), EmptyTree)
case Typed(tree @ Ident(name), tpe) if (tpe.isType) => // get the ident!
removeAsPlaceholder(name)
ValDef(Modifiers(Flags.PARAM), name, tpe, EmptyTree)
case _ =>
syntaxError(tree.pos, "not a legal formal parameter", false)
- ValDef(Modifiers(Flags.PARAM), nme.ERROR, errorTypeTree, EmptyTree)
+ ValDef(Modifiers(Flags.PARAM), nme.ERROR, errorTypeTree setPos o2p(tree.pos.end), EmptyTree)
}
}
@@ -812,7 +813,7 @@ self =>
def wildcardType(start: Int) = {
val pname = freshName(o2p(start), "_$").toTypeName
val t = atPos(start) { Ident(pname) }
- val param = atPos(start) { makeSyntheticTypeParam(pname, typeBounds()) }
+ val param = atPos(t2p(t)) { makeSyntheticTypeParam(pname, typeBounds()) }
placeholderTypes = param :: placeholderTypes
t
}
@@ -1130,12 +1131,12 @@ self =>
path(true, false)
case USCORE =>
val start = in.offset
- atPos(in.skipToken()) {
- val pname = freshName(o2p(start), "x$")
- val param = atPos(start){ makeSyntheticParam(pname) }
- placeholderParams = param :: placeholderParams
- Ident(pname)
- }
+ val pname = freshName(o2p(start), "x$")
+ val id = atPos(start) (Ident(pname))
+ in.nextToken()
+ val param = atPos(t2p(id)){ makeSyntheticParam(pname) }
+ placeholderParams = param :: placeholderParams
+ id
case LPAREN =>
atPos(in.skipToken()) {
val ts = if (in.token == RPAREN) List() else exprs()
diff --git a/src/compiler/scala/tools/nsc/interactive/Global.scala b/src/compiler/scala/tools/nsc/interactive/Global.scala
index 0ad7c1b5aa..44001b4b64 100755
--- a/src/compiler/scala/tools/nsc/interactive/Global.scala
+++ b/src/compiler/scala/tools/nsc/interactive/Global.scala
@@ -28,8 +28,8 @@ self =>
/** The currently active typer run */
private var currentTyperRun: TyperRun = _
- /** Is a background compiler currently running? */
- private var compiling = false
+ /** Is a background compiler run needed? */
+ private var outOfDate = false
/** Is a reload/ background compiler currently running? */
private var acting = false
@@ -84,7 +84,7 @@ self =>
def pollForWork() {
scheduler.pollException() match {
case Some(ex: CancelActionReq) => if (acting) throw ex
- case Some(ex: FreshRunReq) => if (compiling) throw ex
+ case Some(ex: FreshRunReq) => if (outOfDate) throw ex
case Some(ex: Throwable) => throw ex
case _ =>
}
@@ -115,16 +115,13 @@ self =>
while (true) {
scheduler.waitForMoreWork()
pollForWork()
- var continue = true
- while (continue) {
+ while (outOfDate) {
try {
- compiling = true
backgroundCompile()
- continue = false
} catch {
case ex: FreshRunReq =>
} finally {
- compiling = false
+ outOfDate = false
}
}
}
@@ -190,6 +187,7 @@ self =>
val unit = new RichCompilationUnit(source)
unitOfFile(source.file) = unit
currentTyperRun.compileLate(unit)
+ validatePositions(unit.body)
unit.status = JustParsed
}
moveToFront(sources)
@@ -199,7 +197,8 @@ self =>
result set Right(ex)
throw ex
}
- if (compiling) throw new FreshRunReq
+ if (outOfDate) throw new FreshRunReq
+ else outOfDate = true
}
/** Set sync var `result` to a fully attributed tree located at position `pos` */
@@ -218,6 +217,29 @@ self =>
// ---------------- Helper classes ---------------------------
+
+ def validatePositions(tree: Tree) {
+ def check(condition: Boolean, msg: => String) {
+ if (!condition) {
+ println("**** bad positions:")
+ println(msg)
+ println("================= in =================")
+ println(tree)
+ }
+ }
+ def validate(tree: Tree, encltree: Tree, lefttree: Tree) {
+ if (encltree.pos.isSynthetic) check(tree.pos.isSynthetic, "synthetic "+encltree+" contains nonsynthetic" + tree)
+ check(encltree.pos includes tree.pos, encltree+" does not include "+tree)
+ if (lefttree != EmptyTree) check(lefttree.pos precedes tree.pos, lefttree+" does not not precede "+tree)
+ var newleft: Tree = EmptyTree
+ for (ct <- tree.children) {
+ validate(ct, tree, newleft)
+ newleft = ct
+ }
+ }
+ validate(tree, tree, EmptyTree)
+ }
+
/** A transformer that replaces tree `from` with tree `to` in a given tree */
class TreeReplacer(from: Tree, to: Tree) extends Transformer {
override def transform(t: Tree): Tree = {
@@ -262,6 +284,7 @@ self =>
*/
def typedTreeAt(pos: Position): Tree = {
val tree = locateTree(pos)
+// println("at pos "+pos+" was found: "+tree)
if (tree.tpe ne null) tree
else {
val unit = unitOf(pos)
diff --git a/src/compiler/scala/tools/nsc/interactive/REPL.scala b/src/compiler/scala/tools/nsc/interactive/REPL.scala
index 58477dd693..e773f9f281 100644
--- a/src/compiler/scala/tools/nsc/interactive/REPL.scala
+++ b/src/compiler/scala/tools/nsc/interactive/REPL.scala
@@ -9,12 +9,66 @@ import scala.tools.nsc.io._
/** Interface of interactive compiler to a client such as an IDE
*/
-object REPL extends EvalLoop {
+object REPL {
- val settings = new Settings()
- val comp = new Global(settings, new ConsoleReporter(settings))
+ val versionMsg = "Scala compiler " +
+ Properties.versionString + " -- " +
+ Properties.copyrightString
- def prompt = "> "
+ val prompt = "> "
+
+ var reporter: ConsoleReporter = _
+
+ def error(msg: String) {
+ reporter.error(/*new Position */FakePos("scalac"),
+ msg + "\n scalac -help gives more information")
+ }
+
+ def process(args: Array[String]) {
+ val settings = new Settings(error)
+ reporter = new ConsoleReporter(settings)
+ val command = new CompilerCommand(args.toList, settings, error, false)
+ if (command.settings.version.value)
+ reporter.info(null, versionMsg, true)
+ else {
+ try {
+ object compiler extends Global(command.settings, reporter)
+ if (reporter.hasErrors) {
+ reporter.flush()
+ return
+ }
+ if (command.shouldStopWithInfo) {
+ reporter.info(null, command.getInfoMessage(compiler), true)
+ } else {
+ run(compiler)
+ }
+ } catch {
+ case ex @ FatalError(msg) =>
+ if (true || command.settings.debug.value) // !!!
+ ex.printStackTrace();
+ reporter.error(null, "fatal error: " + msg)
+ }
+ }
+ }
+
+ def main(args: Array[String]) {
+ process(args)
+ exit(if (reporter.hasErrors) 1 else 0)
+ }
+
+ def loop(action: (String) => Unit) {
+ Console.print(prompt)
+ try {
+ val line = Console.readLine
+ if (line.length() > 0) {
+ action(line)
+ }
+ loop(action)
+ }
+ catch {
+ case _: java.io.EOFException => //nop
+ }
+ }
/** Commands:
*
@@ -23,12 +77,10 @@ object REPL extends EvalLoop {
*
*
*/
- def run() {
+ def run(comp: Global) {
val reloadResult = new SyncVar[Either[Unit, Throwable]]
val typeatResult = new SyncVar[Either[comp.Tree, Throwable]]
loop { line =>
- println("["+line+"]")
- println((line split " ").toList)
(line split " ").toList match {
case "reload" :: args =>
comp.askReload(args map toSourceFile, reloadResult)
@@ -55,8 +107,4 @@ object REPL extends EvalLoop {
case Right(exc/*: Throwable ??*/) => exc.printStackTrace; println("ERROR: "+exc)
}
}
-
- def main(args: Array[String]) {
- run()
- }
}
diff --git a/src/compiler/scala/tools/nsc/symtab/Definitions.scala b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
index ca8ad48224..03783d054c 100644
--- a/src/compiler/scala/tools/nsc/symtab/Definitions.scala
+++ b/src/compiler/scala/tools/nsc/symtab/Definitions.scala
@@ -37,6 +37,9 @@ trait Definitions {
lazy val ScalaPackage: Symbol = getModule("scala")
lazy val ScalaPackageClass: Symbol = ScalaPackage.tpe.typeSymbol
+ lazy val ScalaCollectionImmutablePackage: Symbol = getModule("scala.collection.immutable")
+ lazy val ScalaCollectionImmutablePackageClass: Symbol = ScalaCollectionImmutablePackage.tpe.typeSymbol
+
var AnyClass: Symbol = _
var AnyValClass: Symbol = _
var AnyRefClass: Symbol = _
@@ -111,6 +114,7 @@ trait Definitions {
def Iterable_hasNext = getMember(IterableClass, nme.hasNext)
lazy val IteratorClass: Symbol = getClass2("scala.Iterator", "scala.collection.Iterator")
lazy val SeqClass: Symbol = getClass2("scala.Seq", "scala.collection.Sequence")
+ lazy val SeqModule: Symbol = getModule2("scala.Seq", "scala.collection.Sequence")
lazy val TraversableClass: Symbol = getClass("scala.collection.Traversable")
lazy val RandomAccessSeqMutableClass: Symbol = getMember(
getModule2("scala.RandomAccessSeq", "scala.collection.Vector"), nme.Mutable)
diff --git a/src/compiler/scala/tools/nsc/symtab/StdNames.scala b/src/compiler/scala/tools/nsc/symtab/StdNames.scala
index bb04630985..f19a8e5138 100644
--- a/src/compiler/scala/tools/nsc/symtab/StdNames.scala
+++ b/src/compiler/scala/tools/nsc/symtab/StdNames.scala
@@ -234,6 +234,7 @@ trait StdNames {
val Function = newTermName("Function")
val Function1 = newTermName("Function1")
val Int = newTermName("Int")
+ val List = newTermName("List")
val Long = newTermName("Long")
val Nil = newTermName("Nil")
val Object = newTermName("Object")
diff --git a/src/compiler/scala/tools/nsc/typechecker/Typers.scala b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
index 89e2028ded..68ae453793 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Typers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Typers.scala
@@ -560,10 +560,25 @@ trait Typers { self: Analyzer =>
/** 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.
+ * (exception for some symbols in scala package which are dealiased immediately)
+ * Call checkAccessible, which sets tree's attributes.
+ * @return modified tree and new prefix type
*/
- private def makeAccessible(tree: Tree, sym: Symbol, pre: Type, site: Tree): Tree =
+ private def makeAccessible(tree: Tree, sym: Symbol, pre: Type, site: Tree): (Tree, Type) =
if (isInPackageObject(sym, pre.typeSymbol)) {
+ if (pre.typeSymbol == ScalaPackageClass && sym.isTerm) {
+ // short cut some aliases. It seems that without that pattern matching
+ // fails to notice exhaustiveness and to generate good code when
+ // List extractors are mixed with :: patterns. See Test5 in lists.scala.
+ def dealias(sym: Symbol) =
+ (atPos(tree.pos) { gen.mkAttributedRef(sym) }, sym.owner.thisType)
+ sym.name match {
+ case nme.List => return dealias(ListModule)
+ case nme.Seq => return dealias(SeqModule)
+ case nme.Nil => return dealias(NilModule)
+ case _ =>
+ }
+ }
val qual = typedQualifier {
tree match {
case Ident(_) => Ident(nme.PACKAGEkw)
@@ -578,10 +593,9 @@ trait Typers { self: Analyzer =>
case SelectFromTypeTree(_, name) => SelectFromTypeTree(qual, name)
}
}
- val tree2 = checkAccessible(tree1, sym, qual.tpe, qual)
- tree2
+ (checkAccessible(tree1, sym, qual.tpe, qual), qual.tpe)
} else {
- checkAccessible(tree, sym, pre, site)
+ (checkAccessible(tree, sym, pre, site), pre)
}
private def isInPackageObject(sym: Symbol, pkg: Symbol) =
@@ -2943,7 +2957,8 @@ trait Typers { self: Analyzer =>
case SelectFromTypeTree(_, _) => copy.SelectFromTypeTree(tree, qual, name)
}
//if (name.toString == "Elem") println("typedSelect "+qual+":"+qual.tpe+" "+sym+"/"+tree1+":"+tree1.tpe)
- val result = stabilize(makeAccessible(tree1, sym, qual.tpe, qual), qual.tpe, mode, pt)
+ val (tree2, pre2) = makeAccessible(tree1, sym, qual.tpe, qual)
+ val result = stabilize(tree2, pre2, mode, pt)
def isPotentialNullDeference() = {
phase.id <= currentRun.typerPhase.id &&
!sym.isConstructor &&
@@ -3103,7 +3118,8 @@ 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(makeAccessible(tree1, defSym, pre, qual), pre, mode, pt)
+ val (tree2, pre2) = makeAccessible(tree1, defSym, pre, qual)
+ stabilize(tree2, pre2, mode, pt)
}
}
diff --git a/src/compiler/scala/tools/nsc/util/Position.scala b/src/compiler/scala/tools/nsc/util/Position.scala
index bd60035a5a..48343fd948 100644
--- a/src/compiler/scala/tools/nsc/util/Position.scala
+++ b/src/compiler/scala/tools/nsc/util/Position.scala
@@ -98,6 +98,7 @@ trait Position {
})
}
+ def show: String = "["+toString+"]"
}
case object NoPosition extends Position
@@ -114,6 +115,7 @@ case class OffsetPosition(source0: SourceFile, offset0: Int) extends Position {
case that => false
}
override def hashCode = offset0 * 37 + source0.file.hashCode
+ override def show = "["+point+"]"
}
/** new for position ranges */
@@ -125,6 +127,7 @@ extends OffsetPosition(source0, point) {
override def endOrElse(d: Int) = end
override def focus = OffsetPosition(source0, point)
override def toString = "RangePosition("+source0+", "+start+", "+point+", "+end+")"
+ override def show = "["+start+":"+end+"]"
}
diff --git a/src/compiler/scala/tools/nsc/util/trace.scala b/src/compiler/scala/tools/nsc/util/trace.scala
index a24a18ec45..dc78756ec6 100644
--- a/src/compiler/scala/tools/nsc/util/trace.scala
+++ b/src/compiler/scala/tools/nsc/util/trace.scala
@@ -5,4 +5,8 @@ object trace {
println(msg+value)
value
}
+ def withFun[T, U](msg: String)(value: T)(fun: T => U): T = {
+ println(msg+fun(value))
+ value
+ }
}