scala.tools.nsc.interpreter.Naming.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 Scala Programming Language
/* NSC -- new Scala compiler
* Copyright 2005-2013 LAMP/EPFL
* @author Paul Phillips
*/
package scala.tools.nsc
package interpreter
/** This is for name logic which is independent of the compiler (notice there's no Global.)
* That includes at least generating, metaquoting, mangling, and unmangling.
*/
trait Naming {
def unmangle(str: String): String = {
val ESC = '\u001b'
val cleaned = removeIWPackages(removeLineWrapper(str))
// Looking to exclude binary data which hoses the terminal, but
// let through the subset of it we need, like whitespace and also
// for ansi codes.
val binaryChars = cleaned count (ch => ch < 32 && !ch.isWhitespace && ch != ESC)
// Lots of binary chars - translate all supposed whitespace into spaces
if (binaryChars > 5)
cleaned map (ch => if (ch.isWhitespace) ' ' else if (ch < 32) '?' else ch)
// Not lots - preserve whitespace and ESC
else
cleaned map (ch => if (ch.isWhitespace || ch == ESC) ch else if (ch < 32) '?' else ch)
}
// The two name forms this is catching are the two sides of this assignment:
//
// $line3.$read.$iw.$iw.Bippy =
// $line3.$read$$iw$$iw$Bippy@4a6a00ca
private def noMeta(s: String) = "\\Q" + s + "\\E"
private lazy val lineRegex = {
val sn = sessionNames
val members = List(sn.read, sn.eval, sn.print) map noMeta mkString ("(?:", "|", ")")
debugging("lineRegex")(noMeta(sn.line) + """\d+[./]""" + members + """[$.]""")
}
private def removeLineWrapper(s: String) = s.replaceAll(lineRegex, "")
private def removeIWPackages(s: String) = s.replaceAll("""\$iw[$.]""", "")
trait SessionNames {
// All values are configurable by passing e.g. -Dscala.repl.name.read=XXX
final def propOr(name: String): String = propOr(name, "$" + name)
final def propOr(name: String, default: String): String =
sys.props.getOrElse("scala.repl.name." + name, default)
// Prefixes used in repl machinery. Default to $line, $read, etc.
def line = propOr("line")
def read = propOr("read")
def eval = propOr("eval")
def print = propOr("print")
def result = propOr("result")
// The prefix for unnamed results: by default res0, res1, etc.
def res = propOr("res", "res") // INTERPRETER_VAR_PREFIX
// Internal ones
def ires = propOr("ires")
}
lazy val sessionNames: SessionNames = new SessionNames { }
/** Generates names pre0, pre1, etc. via calls to apply method */
class NameCreator(pre: String) {
private var x = -1
var mostRecent: String = ""
def apply(): String = {
x += 1
mostRecent = pre + x
mostRecent
}
def reset(): Unit = x = -1
def didGenerate(name: String) =
(name startsWith pre) && ((name drop pre.length) forall (_.isDigit))
}
private lazy val userVar = new NameCreator(sessionNames.res) // var name, like res0
private lazy val internalVar = new NameCreator(sessionNames.ires) // internal var name, like $ires0
def isLineName(name: String) = (name startsWith sessionNames.line) && (name stripPrefix sessionNames.line forall (_.isDigit))
def isUserVarName(name: String) = userVar didGenerate name
def isInternalVarName(name: String) = internalVar didGenerate name
val freshLineId = {
var x = 0
() => { x += 1 ; x }
}
def freshUserVarName() = userVar()
def freshInternalVarName() = internalVar()
def resetAllCreators() {
userVar.reset()
internalVar.reset()
}
def mostRecentVar = userVar.mostRecent
}