summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2012-10-29 07:41:41 -0700
committerPaul Phillips <paulp@improving.org>2012-11-09 16:47:52 -0700
commit31ed2e8da246da07a3318c34cdfae2ca02740524 (patch)
treec66bda59fdb521c405eaf8247f2fc0cc2d1498d2
parentf56f9a3c4b7b9903c732658f052be1172dfd9baa (diff)
downloadscala-31ed2e8da246da07a3318c34cdfae2ca02740524.tar.gz
scala-31ed2e8da246da07a3318c34cdfae2ca02740524.tar.bz2
scala-31ed2e8da246da07a3318c34cdfae2ca02740524.zip
Moved IMain ops requiring stability into implicit class.
A long-standing annoyance of having IMain stored in a var is that you can't call a method on it which returns a dependent type and then pass that to any other method. I realized I could get around this by creating an implicit class around the var; in the class, it is a val, so the method can be written there, and we implicitly convert from the var on demand.
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/ILoop.scala111
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/package.scala137
-rw-r--r--test/files/run/repl-colon-type.check2
3 files changed, 140 insertions, 110 deletions
diff --git a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala
index d99a1c18f9..cde8d81611 100644
--- a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala
@@ -66,54 +66,6 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
echoAndRefresh(msg)
}
- /** Having inherited the difficult "var-ness" of the repl instance,
- * I'm trying to work around it by moving operations into a class from
- * which it will appear a stable prefix.
- */
- private def onIntp[T](f: IMain => T): T = f(intp)
-
- class IMainOps[T <: IMain](val intp: T) {
- import intp._
- import global._
-
- def printAfterTyper(msg: => String) =
- intp.reporter printUntruncatedMessage exitingTyper(msg)
-
- /** Strip NullaryMethodType artifacts. */
- private def replInfo(sym: Symbol) = {
- sym.info match {
- case NullaryMethodType(restpe) if sym.isAccessor => restpe
- case info => info
- }
- }
- def echoTypeStructure(sym: Symbol) =
- printAfterTyper("" + deconstruct.show(replInfo(sym)))
-
- def echoTypeSignature(sym: Symbol, verbose: Boolean) = {
- if (verbose) ILoop.this.echo("// Type signature")
- printAfterTyper("" + replInfo(sym))
-
- if (verbose) {
- ILoop.this.echo("\n// Internal Type structure")
- echoTypeStructure(sym)
- }
- }
- }
- implicit def stabilizeIMain(intp: IMain) = new IMainOps[intp.type](intp)
-
- /** TODO -
- * -n normalize
- * -l label with case class parameter names
- * -c complete - leave nothing out
- */
- private def typeCommandInternal(expr: String, verbose: Boolean): Result = {
- onIntp { intp =>
- val sym = intp.symbolOfLine(expr)
- if (sym.exists) intp.echoTypeSignature(sym, verbose)
- else ""
- }
- }
-
override def echoCommandMessage(msg: String) {
intp.reporter printUntruncatedMessage msg
}
@@ -269,7 +221,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
historyCommand,
cmd("h?", "<string>", "search the history", searchHistory),
cmd("imports", "[name name ...]", "show import history, identifying sources of names", importsCommand),
- cmd("implicits", "[-v]", "show the implicits in scope", implicitsCommand),
+ cmd("implicits", "[-v]", "show the implicits in scope", intp.implicitsCommand),
cmd("javap", "<path|class>", "disassemble a file or class name", javapCommand),
cmd("load", "<path>", "load and interpret a Scala file", loadCommand),
nullary("paste", "enter paste mode: all input up to ctrl-D compiled together", pasteCommand),
@@ -312,63 +264,6 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
}
}
- private def implicitsCommand(line: String): Result = onIntp { intp =>
- import intp._
- import global._
-
- def p(x: Any) = intp.reporter.printMessage("" + x)
-
- // If an argument is given, only show a source with that
- // in its name somewhere.
- val args = line split "\\s+"
- val filtered = intp.implicitSymbolsBySource filter {
- case (source, syms) =>
- (args contains "-v") || {
- if (line == "") (source.fullName.toString != "scala.Predef")
- else (args exists (source.name.toString contains _))
- }
- }
-
- if (filtered.isEmpty)
- return "No implicits have been imported other than those in Predef."
-
- filtered foreach {
- case (source, syms) =>
- p("/* " + syms.size + " implicit members imported from " + source.fullName + " */")
-
- // This groups the members by where the symbol is defined
- val byOwner = syms groupBy (_.owner)
- val sortedOwners = byOwner.toList sortBy { case (owner, _) => exitingTyper(source.info.baseClasses indexOf owner) }
-
- sortedOwners foreach {
- case (owner, members) =>
- // Within each owner, we cluster results based on the final result type
- // if there are more than a couple, and sort each cluster based on name.
- // This is really just trying to make the 100 or so implicits imported
- // by default into something readable.
- val memberGroups: List[List[Symbol]] = {
- val groups = members groupBy (_.tpe.finalResultType) toList
- val (big, small) = groups partition (_._2.size > 3)
- val xss = (
- (big sortBy (_._1.toString) map (_._2)) :+
- (small flatMap (_._2))
- )
-
- xss map (xs => xs sortBy (_.name.toString))
- }
-
- val ownerMessage = if (owner == source) " defined in " else " inherited from "
- p(" /* " + members.size + ownerMessage + owner.fullName + " */")
-
- memberGroups foreach { group =>
- group foreach (s => p(" " + intp.symbolDefString(s)))
- p("")
- }
- }
- p("")
- }
- }
-
private def findToolsJar() = {
val jdkPath = Directory(jdkHome)
val jar = jdkPath / "lib" / "tools.jar" toFile;
@@ -408,8 +303,8 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
private def typeCommand(line0: String): Result = {
line0.trim match {
case "" => ":type [-v] <expression>"
- case s if s startsWith "-v " => typeCommandInternal(s stripPrefix "-v " trim, true)
- case s => typeCommandInternal(s, false)
+ case s if s startsWith "-v " => intp.typeCommandInternal(s stripPrefix "-v " trim, true)
+ case s => intp.typeCommandInternal(s, false)
}
}
diff --git a/src/compiler/scala/tools/nsc/interpreter/package.scala b/src/compiler/scala/tools/nsc/interpreter/package.scala
index e3440c9f8b..6a2d69db2c 100644
--- a/src/compiler/scala/tools/nsc/interpreter/package.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/package.scala
@@ -6,6 +6,10 @@
package scala.tools.nsc
import scala.language.implicitConversions
+import scala.reflect.{ classTag, ClassTag }
+import scala.reflect.runtime.{ universe => ru }
+import scala.reflect.{ClassTag, classTag}
+import scala.reflect.api.{Mirror, TypeCreator, Universe => ApiUniverse}
/** The main REPL related classes and values are as follows.
* In addition to standard compiler classes Global and Settings, there are:
@@ -46,4 +50,137 @@ package object interpreter extends ReplConfig with ReplStrings {
private[nsc] implicit def enrichAnyRefWithTap[T](x: T) = new TapMaker(x)
private[nsc] def tracing[T](msg: String)(x: T): T = x.tapTrace(msg)
private[nsc] def debugging[T](msg: String)(x: T) = x.tapDebug(msg)
+
+ private val ourClassloader = getClass.getClassLoader
+
+ def staticTypeTag[T: ClassTag]: ru.TypeTag[T] = ru.TypeTag[T](
+ ru.runtimeMirror(ourClassloader),
+ new TypeCreator {
+ def apply[U <: ApiUniverse with Singleton](m: Mirror[U]): U # Type =
+ m.staticClass(classTag[T].runtimeClass.getName).toTypeConstructor.asInstanceOf[U # Type]
+ })
+
+ /** This class serves to trick the compiler into treating a var
+ * (intp, in ILoop) as a stable identifier.
+ */
+ implicit class IMainOps(val intp: IMain) {
+ import intp._
+ import global.{ reporter => _, _ }
+ import definitions._
+
+ lazy val tagOfStdReplVals = staticTypeTag[scala.tools.nsc.interpreter.StdReplVals]
+
+ protected def echo(msg: String) = {
+ Console.out println msg
+ Console.out.flush()
+ }
+
+ def wrapCommand(line: String): String = {
+ def failMsg = "Argument to :wrap must be the name of a method with signature [T](=> T): T"
+
+ words(line) match {
+ case Nil =>
+ intp.executionWrapper match {
+ case "" => "No execution wrapper is set."
+ case s => "Current execution wrapper: " + s
+ }
+ case "clear" :: Nil =>
+ intp.executionWrapper match {
+ case "" => "No execution wrapper is set."
+ case s => intp.clearExecutionWrapper() ; "Cleared execution wrapper."
+ }
+ case wrapper :: Nil =>
+ intp.typeOfExpression(wrapper) match {
+ case PolyType(List(targ), MethodType(List(arg), restpe)) =>
+ setExecutionWrapper(originalPath(wrapper))
+ "Set wrapper to '" + wrapper + "'"
+ case tp =>
+ failMsg + "\nFound: <unknown>"
+ }
+ case _ => failMsg
+ }
+ }
+
+ def implicitsCommand(line: String): String = {
+ def p(x: Any) = intp.reporter.printMessage("" + x)
+
+ // If an argument is given, only show a source with that
+ // in its name somewhere.
+ val args = line split "\\s+"
+ val filtered = intp.implicitSymbolsBySource filter {
+ case (source, syms) =>
+ (args contains "-v") || {
+ if (line == "") (source.fullName.toString != "scala.Predef")
+ else (args exists (source.name.toString contains _))
+ }
+ }
+
+ if (filtered.isEmpty)
+ return "No implicits have been imported other than those in Predef."
+
+ filtered foreach {
+ case (source, syms) =>
+ p("/* " + syms.size + " implicit members imported from " + source.fullName + " */")
+
+ // This groups the members by where the symbol is defined
+ val byOwner = syms groupBy (_.owner)
+ val sortedOwners = byOwner.toList sortBy { case (owner, _) => exitingTyper(source.info.baseClasses indexOf owner) }
+
+ sortedOwners foreach {
+ case (owner, members) =>
+ // Within each owner, we cluster results based on the final result type
+ // if there are more than a couple, and sort each cluster based on name.
+ // This is really just trying to make the 100 or so implicits imported
+ // by default into something readable.
+ val memberGroups: List[List[Symbol]] = {
+ val groups = members groupBy (_.tpe.finalResultType) toList
+ val (big, small) = groups partition (_._2.size > 3)
+ val xss = (
+ (big sortBy (_._1.toString) map (_._2)) :+
+ (small flatMap (_._2))
+ )
+
+ xss map (xs => xs sortBy (_.name.toString))
+ }
+
+ val ownerMessage = if (owner == source) " defined in " else " inherited from "
+ p(" /* " + members.size + ownerMessage + owner.fullName + " */")
+
+ memberGroups foreach { group =>
+ group foreach (s => p(" " + intp.symbolDefString(s)))
+ p("")
+ }
+ }
+ p("")
+ }
+ ""
+ }
+
+ /** TODO -
+ * -n normalize
+ * -l label with case class parameter names
+ * -c complete - leave nothing out
+ */
+ def typeCommandInternal(expr: String, verbose: Boolean): Unit =
+ symbolOfLine(expr) andAlso (echoTypeSignature(_, verbose))
+
+ def printAfterTyper(msg: => String) =
+ reporter printUntruncatedMessage exitingTyper(msg)
+
+ private def replInfo(sym: Symbol) =
+ if (sym.isAccessor) dropNullaryMethod(sym.info) else sym.info
+
+ def echoTypeStructure(sym: Symbol) =
+ printAfterTyper("" + deconstruct.show(replInfo(sym)))
+
+ def echoTypeSignature(sym: Symbol, verbose: Boolean) = {
+ if (verbose) echo("// Type signature")
+ printAfterTyper("" + replInfo(sym))
+
+ if (verbose) {
+ echo("\n// Internal Type structure")
+ echoTypeStructure(sym)
+ }
+ }
+ }
}
diff --git a/test/files/run/repl-colon-type.check b/test/files/run/repl-colon-type.check
index 2e8ce8c801..7716221f54 100644
--- a/test/files/run/repl-colon-type.check
+++ b/test/files/run/repl-colon-type.check
@@ -14,7 +14,6 @@ scala> :type List[1, 2, 3]
List[1, 2, 3]
^
-
scala> :type List(1, 2, 3)
List[Int]
@@ -55,7 +54,6 @@ scala> :type protected lazy val f = 5
lazy val $result = f
^
-
scala> :type def f = 5
=> Int