summaryrefslogtreecommitdiff
path: root/src/compiler/scala/tools/nsc/interpreter/package.scala
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 /src/compiler/scala/tools/nsc/interpreter/package.scala
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.
Diffstat (limited to 'src/compiler/scala/tools/nsc/interpreter/package.scala')
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/package.scala137
1 files changed, 137 insertions, 0 deletions
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)
+ }
+ }
+ }
}