diff options
author | Eugene Yokota <eed3si9n@gmail.com> | 2013-04-20 21:12:39 -0400 |
---|---|---|
committer | Eugene Yokota <eed3si9n@gmail.com> | 2013-04-20 21:12:39 -0400 |
commit | 1d1492f7217f8f75f62febf1f68131931b31bfe2 (patch) | |
tree | 35866756a2359379dd6e0834e5fa258ea3c39779 /src/repl | |
parent | 68c6ba7e59befa88b2f383dd7eca71a9329a8b6d (diff) | |
download | scala-1d1492f7217f8f75f62febf1f68131931b31bfe2.tar.gz scala-1d1492f7217f8f75f62febf1f68131931b31bfe2.tar.bz2 scala-1d1492f7217f8f75f62febf1f68131931b31bfe2.zip |
Add :kind command to REPL
:kind command diplays the kind of types and type constructors in Scala
syntax notation.
scala> :kind (Int, Int) => Int
scala.Function2's kind is F[-A1,-A2,+A3]
Diffstat (limited to 'src/repl')
-rw-r--r-- | src/repl/scala/tools/nsc/interpreter/ExprTyper.scala | 15 | ||||
-rw-r--r-- | src/repl/scala/tools/nsc/interpreter/ILoop.scala | 13 | ||||
-rw-r--r-- | src/repl/scala/tools/nsc/interpreter/package.scala | 42 |
3 files changed, 67 insertions, 3 deletions
diff --git a/src/repl/scala/tools/nsc/interpreter/ExprTyper.scala b/src/repl/scala/tools/nsc/interpreter/ExprTyper.scala index 55182a4f95..9353215e1e 100644 --- a/src/repl/scala/tools/nsc/interpreter/ExprTyper.scala +++ b/src/repl/scala/tools/nsc/interpreter/ExprTyper.scala @@ -95,4 +95,19 @@ trait ExprTyper { } finally typeOfExpressionDepth -= 1 } + + // This only works for proper types. + def typeOfTypeString(typeString: String): Type = { + def asProperType(): Option[Type] = { + val name = freshInternalVarName() + val line = "def %s: %s = ???" format (name, typeString) + interpretSynthetic(line) match { + case IR.Success => + val sym0 = symbolOfTerm(name) + Some(sym0.asMethod.returnType) + case _ => None + } + } + beSilentDuring(asProperType()) getOrElse NoType + } } diff --git a/src/repl/scala/tools/nsc/interpreter/ILoop.scala b/src/repl/scala/tools/nsc/interpreter/ILoop.scala index df28e428ce..8da5742d1e 100644 --- a/src/repl/scala/tools/nsc/interpreter/ILoop.scala +++ b/src/repl/scala/tools/nsc/interpreter/ILoop.scala @@ -221,6 +221,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) shCommand, nullary("silent", "disable/enable automatic printing of results", verbosity), cmd("type", "[-v] <expr>", "display the type of an expression without evaluating it", typeCommand), + cmd("kind", "[-v] <expr>", "display the kind of expression's type", kindCommand), nullary("warnings", "show the suppressed warnings from the most recent line which had any", warningsCommand) ) @@ -286,9 +287,15 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter) // Still todo: modules. private def typeCommand(line0: String): Result = { line0.trim match { - case "" => ":type [-v] <expression>" - case s if s startsWith "-v " => intp.typeCommandInternal(s stripPrefix "-v " trim, verbose = true) - case s => intp.typeCommandInternal(s, verbose = false) + case "" => ":type [-v] <expression>" + case s => intp.typeCommandInternal(s stripPrefix "-v " trim, verbose = s startsWith "-v ") + } + } + + private def kindCommand(expr: String): Result = { + expr.trim match { + case "" => ":kind [-v] <expression>" + case s => intp.kindCommandInternal(s stripPrefix "-v " trim, verbose = s startsWith "-v ") } } diff --git a/src/repl/scala/tools/nsc/interpreter/package.scala b/src/repl/scala/tools/nsc/interpreter/package.scala index 52a085080b..f82c38f5e7 100644 --- a/src/repl/scala/tools/nsc/interpreter/package.scala +++ b/src/repl/scala/tools/nsc/interpreter/package.scala @@ -10,6 +10,7 @@ import scala.reflect.{ classTag, ClassTag } import scala.reflect.runtime.{ universe => ru } import scala.reflect.{ClassTag, classTag} import scala.reflect.api.{Mirror, TypeCreator, Universe => ApiUniverse} +import scala.util.control.Exception.catching /** The main REPL related classes and values are as follows. * In addition to standard compiler classes Global and Settings, there are: @@ -127,6 +128,47 @@ package object interpreter extends ReplConfig with ReplStrings { "" } + def kindCommandInternal(expr: String, verbose: Boolean): Unit = { + val catcher = catching(classOf[MissingRequirementError], + classOf[ScalaReflectionException]) + def typeFromTypeString: Option[ClassSymbol] = catcher opt { + exprTyper.typeOfTypeString(expr).typeSymbol.asClass + } + def typeFromNameTreatedAsTerm: Option[ClassSymbol] = catcher opt { + val moduleClass = exprTyper.typeOfExpression(expr).typeSymbol + moduleClass.linkedClassOfClass.asClass + } + def typeFromFullName: Option[ClassSymbol] = catcher opt { + intp.global.rootMirror.staticClass(expr) + } + def typeOfTerm: Option[TypeSymbol] = replInfo(symbolOfLine(expr)).typeSymbol match { + case sym: TypeSymbol => Some(sym) + case _ => None + } + (typeFromTypeString orElse typeFromNameTreatedAsTerm orElse typeFromFullName orElse typeOfTerm) foreach { sym => + val (kind, tpe) = exitingTyper { + val tpe = sym.tpeHK + (intp.global.inferKind(NoPrefix)(tpe, sym.owner), tpe) + } + echoKind(tpe, kind, verbose) + } + } + + def echoKind(tpe: Type, kind: Kind, verbose: Boolean) { + def typeString(tpe: Type): String = { + tpe match { + case TypeRef(_, sym, _) => typeString(sym.typeSignature) + case RefinedType(_, _) => tpe.toString + case _ => tpe.typeSymbol.fullName + } + } + printAfterTyper(typeString(tpe) + "'s kind is " + kind.scalaNotation) + if (verbose) { + echo(kind.starNotation) + echo(kind.description) + } + } + /** TODO - * -n normalize * -l label with case class parameter names |