summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2009-05-26 18:18:11 +0000
committerMartin Odersky <odersky@gmail.com>2009-05-26 18:18:11 +0000
commit5b2dec1e9ea1a41112d87a37a16811b71bdaf273 (patch)
tree6ebecdda4ca6b49d12d106e59d11cf9d0574041c /src
parent103c97f7deef02d81d6d87c21f751899c63683b1 (diff)
downloadscala-5b2dec1e9ea1a41112d87a37a16811b71bdaf273.tar.gz
scala-5b2dec1e9ea1a41112d87a37a16811b71bdaf273.tar.bz2
scala-5b2dec1e9ea1a41112d87a37a16811b71bdaf273.zip
new test repl for interactive mode; bug fixes
Diffstat (limited to 'src')
-rwxr-xr-xsrc/compiler/scala/tools/nsc/interactive/ContextTrees.scala46
-rwxr-xr-xsrc/compiler/scala/tools/nsc/interactive/Global.scala11
-rw-r--r--src/compiler/scala/tools/nsc/interactive/REPL.scala86
-rw-r--r--src/compiler/scala/tools/nsc/reporters/AbstractReporter.scala7
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Implicits.scala30
-rw-r--r--src/compiler/scala/tools/nsc/util/Position.scala4
6 files changed, 98 insertions, 86 deletions
diff --git a/src/compiler/scala/tools/nsc/interactive/ContextTrees.scala b/src/compiler/scala/tools/nsc/interactive/ContextTrees.scala
index 8f8470ae2d..8e8d280b4b 100755
--- a/src/compiler/scala/tools/nsc/interactive/ContextTrees.scala
+++ b/src/compiler/scala/tools/nsc/interactive/ContextTrees.scala
@@ -50,23 +50,37 @@ trait ContextTrees { self: Global =>
else if (cpos precedes contexts(0).pos)
new ContextTree(context) +: contexts
else {
+ def insertAt(idx: Int): Boolean = {
+ val oldpos = contexts(idx).pos
+ if (oldpos sameRange cpos) {
+ contexts(idx) = new ContextTree(context, contexts(idx).children)
+ true
+ } else if (oldpos includes cpos) {
+ addContext(contexts(idx).children, context)
+ true
+ } else if (cpos includes oldpos) {
+ val start = contexts.indexWhere(cpos includes _.pos)
+ val last = contexts.lastIndexWhere(cpos includes _.pos)
+ contexts(start) = new ContextTree(context, contexts.slice(start, last + 1))
+ contexts.remove(start + 1, last - start)
+ true
+ } else false
+ }
def loop(lo: Int, hi: Int) {
- assert(lo <= hi)
- val mid = (lo + hi) / 2
- val midpos = contexts(mid).pos
- if (cpos precedes midpos)
- loop(lo, mid - 1)
- else if (midpos precedes cpos)
- loop(mid + 1, hi)
- else if (midpos sameRange cpos)
- contexts(mid) = new ContextTree(context, contexts(mid).children)
- else if ((midpos includes cpos) && !(cpos includes midpos))
- addContext(contexts(mid).children, context)
- else if (cpos includes midpos)
- contexts(mid) = new ContextTree(context, ArrayBuffer(contexts(mid)))
- else {
- inform("internal error? skewed positions: "+midpos+"/"+cpos)
- contexts(mid) = new ContextTree(context)
+ if (hi - lo > 1) {
+ val mid = (lo + hi) / 2
+ val midpos = contexts(mid).pos
+ if (cpos precedes midpos)
+ loop(lo, mid)
+ else if (midpos precedes cpos)
+ loop(mid, hi)
+ } else if (!insertAt(lo) && !insertAt(hi)) {
+ val lopos = contexts(lo).pos
+ val hipos = contexts(hi).pos
+ if ((lopos precedes cpos) && (cpos precedes hipos))
+ contexts.insert(hi, new ContextTree(context))
+ else
+ inform("internal error? skewed positions: "+lopos+" !< "+cpos+" !< "+hipos)
}
}
loop(0, hi)
diff --git a/src/compiler/scala/tools/nsc/interactive/Global.scala b/src/compiler/scala/tools/nsc/interactive/Global.scala
index 16af234d48..3d0d14293d 100755
--- a/src/compiler/scala/tools/nsc/interactive/Global.scala
+++ b/src/compiler/scala/tools/nsc/interactive/Global.scala
@@ -55,7 +55,7 @@ self =>
def integrateNew() {
context.unit.body = new TreeReplacer(old, result) transform context.unit.body
}
- if (context.unit.targetPos includes result.pos) {
+ if ((context.unit != null) && (context.unit.targetPos includes result.pos)) {
integrateNew()
throw new TyperResult(result)
}
@@ -233,11 +233,12 @@ self =>
override def traverse(t: Tree) {
if (t.hasSymbol) t.symbol = NoSymbol
t match {
- case EmptyTree => ;
+ case EmptyTree =>
+ ;
+ case _ =>
+ t.tpe = null
+ super.traverse(t)
}
-
- t.tpe = null
- super.traverse(t)
}
}
diff --git a/src/compiler/scala/tools/nsc/interactive/REPL.scala b/src/compiler/scala/tools/nsc/interactive/REPL.scala
index cd83ddf082..11def170b5 100644
--- a/src/compiler/scala/tools/nsc/interactive/REPL.scala
+++ b/src/compiler/scala/tools/nsc/interactive/REPL.scala
@@ -1,15 +1,20 @@
package scala.tools.nsc.interactive
import scala.concurrent.SyncVar
-import scala.tools.nsc.io.AbstractFile
-import scala.tools.nsc.util.{SourceFile, Position, WorkScheduler}
+import scala.tools.nsc.util._
import scala.tools.nsc.symtab._
import scala.tools.nsc.ast._
+import scala.tools.nsc.reporters._
+import scala.tools.nsc.io._
/** Interface of interactive compiler to a client such as an IDE
*/
-object REPL /* extends EvalLoop */ {
-}
+object REPL extends EvalLoop {
+
+ val settings = new Settings()
+ val comp = new Global(settings, new ConsoleReporter(settings))
+
+ def prompt = "> "
/** Commands:
*
@@ -17,56 +22,39 @@ object REPL /* extends EvalLoop */ {
* typeat file line col
*
*
+ */
def run() {
+ val reloadResult = new SyncVar[Either[Unit, Throwable]]
+ val typeatResult = new SyncVar[Either[comp.Tree, Throwable]]
loop { line =>
-
-
+ (line split " ").toList match {
+ case "reload" :: args =>
+ comp.askReload(args map toSourceFile, reloadResult)
+ show(reloadResult)
+ case List("typeat", file, line, col1, col2) =>
+ val source = toSourceFile(file)
+ val linestart = source.lineToOffset(line.toInt)
+ val pos = comp.rangePos(source, linestart + col1.toInt, linestart + col1.toInt, linestart + col2.toInt)
+ comp.askTypeAt(pos, typeatResult)
+ show(typeatResult)
+ case List("quit") =>
+ System.exit(1)
+ case _ =>
+ println("unrecongized command")
+ }
}
+ }
- def process(args: Array[String]) {
- val settings = new Settings(error)
- reporter = new ConsoleReporter(settings)
- val command = new CompilerCommand(List.fromArray(args), settings, error, false)
- if (command.settings.version.value)
- reporter.info(null, versionMsg, true)
- else {
- if (command.settings.target.value == "msil") {
- val libpath = System.getProperty("msil.libpath")
- if (libpath != null)
- command.settings.assemrefs.value =
- command.settings.assemrefs.value + File.pathSeparator + libpath
- }
- try {
- object compiler extends Global(command.settings, reporter)
- if (reporter.hasErrors) {
- reporter.flush()
- return
- }
+ def toSourceFile(name: String) = new BatchSourceFile(new PlainFile(new java.io.File(name)))
- if (command.shouldStopWithInfo) {
- reporter.info(null, command.getInfoMessage(compiler), true)
- } else {
- if (command.settings.resident.value)
- resident(compiler)
- else if (command.files.isEmpty) {
- reporter.info(null, command.usageMsg, true)
- reporter.info(null, compiler.pluginOptionsHelp, true)
- } else {
- val run = new compiler.Run()
- run compile command.files
- reporter.printSummary()
- }
- }
- } catch {
- case ex @ FatalError(msg) =>
- if (true || command.settings.debug.value) // !!!
- ex.printStackTrace();
- reporter.error(null, "fatal error: " + msg)
- }
+ def show[T](svar: SyncVar[Either[T, Throwable]]) {
+ svar.get match {
+ case Left(result) => println("==> "+result)
+ case Right(exc/*: Throwable ??*/) => exc.printStackTrace; println("ERROR: "+exc)
}
}
- val comp = new Global
-
- def
- */
+ def main(args: Array[String]) {
+ run()
+ }
+}
diff --git a/src/compiler/scala/tools/nsc/reporters/AbstractReporter.scala b/src/compiler/scala/tools/nsc/reporters/AbstractReporter.scala
index d6f94e8626..5aedf09a28 100644
--- a/src/compiler/scala/tools/nsc/reporters/AbstractReporter.scala
+++ b/src/compiler/scala/tools/nsc/reporters/AbstractReporter.scala
@@ -44,6 +44,7 @@ abstract class AbstractReporter extends Reporter {
}
/** Logs a position and returns <code>true</code> if it was already logged.
+ * @note Two positions are considered identical for logging if they have the same point.
*
* @param pos ...
* @return <code>true</code> if <code>pos</code> was already logged.
@@ -51,9 +52,9 @@ abstract class AbstractReporter extends Reporter {
private def testAndLog(pos: Position, severity: Severity): Boolean = {
if (pos eq null) return false
if (pos.offset.isEmpty) return false
- if ((positions contains pos) && positions(pos) >= severity) return true
- positions += (pos -> severity)
+ val fpos = pos.focus
+ if ((positions contains fpos) && positions(fpos) >= severity) return true
+ positions += (fpos -> severity)
false
}
-
}
diff --git a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
index 667827dfa4..43f6d54be0 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Implicits.scala
@@ -28,7 +28,7 @@ self: Analyzer =>
import definitions._
import posAssigner.atPos
- final val traceImplicits = false
+ final val traceImplicits = true
var implicitTime = 0L
var inscopeSucceed = 0L
@@ -55,6 +55,7 @@ self: Analyzer =>
* @return A search result
*/
def inferImplicit(tree: Tree, pt0: Type, reportAmbiguous: Boolean, context: Context): SearchResult = {
+ println("infer impl "+pt0)
if (traceImplicits && !tree.isEmpty && !context.undetparams.isEmpty)
println("typing implicit with undetermined type params: "+context.undetparams+"\n"+tree)
val search = new ImplicitSearch(tree, pt0, context.makeImplicit(reportAmbiguous))
@@ -302,7 +303,7 @@ self: Analyzer =>
*/
val wildPt = approximate(pt)
- //if (traceImplicits) println("typed impl for "+wildPt+"? "+info.name+":"+info.tpe+"/"+undetParams)
+ if (traceImplicits) println("typed impl for "+wildPt+"? "+info.name+":"+info.tpe+"/"+undetParams)
if (isPlausiblyCompatible(info.tpe, wildPt) &&
isCompatible(depoly(info.tpe), wildPt) &&
isStable(info.pre)) {
@@ -311,7 +312,7 @@ self: Analyzer =>
if (info.pre == NoPrefix) Ident(info.name)
else Select(gen.mkAttributedQualifier(info.pre), info.name)
}
- //if (traceImplicits) println("typed impl?? "+info.name+":"+info.tpe+" ==> "+itree+" with "+wildPt)
+ if (traceImplicits) println("typed impl?? "+info.name+":"+info.tpe+" ==> "+itree+" with "+wildPt)
def fail(reason: String): SearchResult = {
if (settings.XlogImplicits.value)
inform(itree+" is not a valid implicit value for "+pt0+" because:\n"+reason)
@@ -653,18 +654,21 @@ self: Analyzer =>
//val timer1 = System.nanoTime()
//if (result == SearchFailure) inscopeFail += timer1 - start else inscopeSucceed += timer1 - start
if (result == SearchFailure) {
- implicitsCache get pt match {
- case Some(r) =>
- hits += 1
- result = r
- case None =>
- misses += 1
- result = searchImplicit(implicitsOfExpectedType, false)
-// println("new fact: search implicit of "+pt+" = "+result)
+ if (pt.isInstanceOf[UniqueType])
+ implicitsCache get pt match {
+ case Some(r) =>
+ hits += 1
+ result = r
+ case None =>
+ misses += 1
+ result = searchImplicit(implicitsOfExpectedType, false)
+// println("new fact: search implicit of "+pt+" = "+result)
// if (implicitsCache.size >= sizeLimit)
// implicitsCache -= implicitsCache.values.next
- implicitsCache(pt) = result
- }
+ implicitsCache(pt) = result
+ }
+ else
+ result = searchImplicit(implicitsOfExpectedType, false)
}
//val timer2 = System.nanoTime()
//if (result == SearchFailure) oftypeFail += timer2 - timer1 else oftypeSucceed += timer2 - timer1
diff --git a/src/compiler/scala/tools/nsc/util/Position.scala b/src/compiler/scala/tools/nsc/util/Position.scala
index a62974c426..1ebc2df19e 100644
--- a/src/compiler/scala/tools/nsc/util/Position.scala
+++ b/src/compiler/scala/tools/nsc/util/Position.scala
@@ -27,10 +27,13 @@ trait Position {
def endOrElse(d: Int) = offset.getOrElse(d)
def underlying = this
+ def focus = this
def includes(pos: Position) =
isDefined && pos.isDefined && start <= pos.start && pos.end <= end
+ /** Does this position precede that position?
+ */
def precedes(pos: Position) =
isDefined && pos.isDefined && end <= pos.start
@@ -114,6 +117,7 @@ extends OffsetPosition(source0, point) {
override def startOrElse(d: Int) = start
override def pointOrElse(d: Int) = point
override def endOrElse(d: Int) = end
+ override def focus = OffsetPosition(source0, point)
}