diff options
author | Paul Phillips <paulp@improving.org> | 2011-02-03 22:26:35 +0000 |
---|---|---|
committer | Paul Phillips <paulp@improving.org> | 2011-02-03 22:26:35 +0000 |
commit | 1038b708f23374439310f3a700a2e1170e2b61a0 (patch) | |
tree | 8179368c54ca2c1ad63ac1d05f9266d278ead0b4 /src/compiler/scala/tools/nsc/interpreter/ILoop.scala | |
parent | c332e580a3fec48dc193b518666f93c589163045 (diff) | |
download | scala-1038b708f23374439310f3a700a2e1170e2b61a0.tar.gz scala-1038b708f23374439310f3a700a2e1170e2b61a0.tar.bz2 scala-1038b708f23374439310f3a700a2e1170e2b61a0.zip |
A couple long-threatened repl features.
1) :implicits command.
scala> :implicits
No implicits have been imported other than those in Predef.
scala> import BigDecimal._
import BigDecimal._
scala> class Bippy[T] { implicit def makeMeABippy[U <: T] : Bippy[U] = new Bippy[U] }
defined class Bippy
scala> val bippy = new Bippy[String]
bippy: Bippy[String] = Bippy@4f0bd71c
scala> import bippy._
import bippy._
scala> :implicits
/* 3 implicit members imported from scala.math.BigDecimal */
/* 3 defined in scala.math.BigDecimal */
implicit def double2bigDecimal(d: Double): scala.math.BigDecimal
implicit def int2bigDecimal(i: Int): scala.math.BigDecimal
implicit def long2bigDecimal(l: Long): scala.math.BigDecimal
/* 1 implicit members imported from Bippy */
/* 1 defined in Bippy */
implicit def makeMeABippy[U <: T]: Bippy[U]
2) This one I will probably have to optionize, but: automatic rebinding
to a more specific type, signalled via tab-completion failures. More
easily demonstrated than explained.
scala> val x: AnyRef = "abc" // does not apply to var/def
x: AnyRef = abc
scala> x.<tab>
asInstanceOf isInstanceOf toString
scala> x.<tab>
Rebinding stable value x from AnyRef to java.lang.String
+ asInstanceOf charAt codePointAt codePointBefore codePointCount
compareTo compareToIgnoreCase concat contains contentEquals endsWith
equalsIgnoreCase getBytes getChars indexOf intern isEmpty isInstanceOf
lastIndexOf length matches offsetByCodePoints regionMatches replace
replaceAll replaceFirst split startsWith subSequence substring
toCharArray toLowerCase toString toUpperCase trim
scala> x
res0: java.lang.String = abc
Who's up for some reviewing? I'm taking volunteers! No review.
Diffstat (limited to 'src/compiler/scala/tools/nsc/interpreter/ILoop.scala')
-rw-r--r-- | src/compiler/scala/tools/nsc/interpreter/ILoop.scala | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala index a075fe5bb0..c7739b8a8a 100644 --- a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala +++ b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala @@ -196,6 +196,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: PrintWriter) NoArgs("help", "print this help message", printHelp), VarArgs("history", "show the history (optional arg: lines to show)", printHistory), LineArg("h?", "search the history", searchHistory), + LineArg("implicits", "show the implicits in scope (-v to include Predef)", implicitsCommand), LineArg("javap", "disassemble a file or class name", javapCommand), LineArg("keybindings", "show how ctrl-[A-Z] and other keys are bound", keybindingsCommand), OneArg("load", "load and interpret a Scala file", load), @@ -216,6 +217,79 @@ class ILoop(in0: Option[BufferedReader], protected val out: PrintWriter) LineArg("wrap", "code to wrap around all executions", wrapCommand) ) } + + private val typeTransforms = List( + "scala.collection.immutable." -> "immutable.", + "scala.collection.mutable." -> "mutable.", + "scala.collection.generic." -> "generic.", + "java.lang." -> "jl.", + "scala.runtime." -> "runtime." + ) + + private def implicitsCommand(line: String): Result = { + val intp = ILoop.this.intp + import intp._ + import global.Symbol + + def p(x: Any) = intp.reporter.printMessage("" + x) + def toDefString(sym: Symbol) = { + TypeStrings.quieter( + intp.afterTyper(sym.defString), + sym.owner.name + ".this.", + sym.owner.fullName + "." + ) + } + + // 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, _) => intp.afterTyper(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(" " + toDefString(s))) + p("") + } + } + p("") + } + } private def javapCommand(line: String): Result = { if (line == "") return ":javap <filename or classname>" |