diff options
author | Paul Phillips <paulp@improving.org> | 2012-10-29 07:41:41 -0700 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2012-11-09 16:47:52 -0700 |
commit | 31ed2e8da246da07a3318c34cdfae2ca02740524 (patch) | |
tree | c66bda59fdb521c405eaf8247f2fc0cc2d1498d2 /src/compiler/scala/tools/nsc/interpreter/package.scala | |
parent | f56f9a3c4b7b9903c732658f052be1172dfd9baa (diff) | |
download | scala-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.scala | 137 |
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) + } + } + } } |