scala.tools.nsc.interpreter.package.scala Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of scala-compiler Show documentation
Show all versions of scala-compiler Show documentation
Compiler for the SubScript extension of the Scala Programming Language
The newest version!
/* NSC -- new Scala compiler
* Copyright 2005-2013 LAMP/EPFL
* @author Paul Phillips
*/
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}
import scala.util.control.Exception.catching
import scala.util.Try
/** The main REPL related classes and values are as follows.
* In addition to standard compiler classes Global and Settings, there are:
*
* History: an interface for session history.
* Completion: an interface for tab completion.
* ILoop (formerly InterpreterLoop): The umbrella class for a session.
* IMain (formerly Interpreter): Handles the evolving state of the session
* and handles submitting code to the compiler and handling the output.
* InteractiveReader: how ILoop obtains input.
* History: an interface for session history.
* Completion: an interface for tab completion.
* Power: a repository for more advanced/experimental features.
*
* ILoop contains { in: InteractiveReader, intp: IMain, settings: Settings, power: Power }
* InteractiveReader contains { history: History, completion: Completion }
* IMain contains { global: Global }
*/
package object interpreter extends ReplConfig with ReplStrings {
type JFile = java.io.File
type JClass = java.lang.Class[_]
type JList[T] = java.util.List[T]
type JCollection[T] = java.util.Collection[T]
type JPrintWriter = java.io.PrintWriter
type InputStream = java.io.InputStream
type OutputStream = java.io.OutputStream
val IR = Results
implicit def postfixOps = scala.language.postfixOps // make all postfix ops in this package compile without warning
private[interpreter] implicit def javaCharSeqCollectionToScala(xs: JCollection[_ <: CharSequence]): List[String] = {
import scala.collection.JavaConverters._
xs.asScala.toList map ("" + _)
}
private[nsc] implicit def enrichClass[T](clazz: Class[T]) = new RichClass[T](clazz)
private[nsc] implicit def enrichAnyRefWithTap[T](x: T) = new TapMaker(x)
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._
protected def echo(msg: String) = {
Console.out println msg
Console.out.flush()
}
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("")
}
""
}
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.info)
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
* -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)
}
}
}
/* debug assist
private[nsc] implicit class `smart stringifier`(val sc: StringContext) extends AnyVal {
import StringContext._, runtime.ScalaRunTime.stringOf
def ss(args: Any*): String = sc.standardInterpolator(treatEscapes, args map stringOf)
} debug assist */
private[nsc] implicit class `try lastly`[A](val t: Try[A]) extends AnyVal {
private def effect[X](last: =>Unit)(a: X): Try[A] = { last; t }
def lastly(last: =>Unit): Try[A] = t transform (effect(last) _, effect(last) _)
}
}