summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2011-07-23 20:50:24 +0000
committerPaul Phillips <paulp@improving.org>2011-07-23 20:50:24 +0000
commit5c61410fe5b8fd636bde6484f04a2d1160ed7eb4 (patch)
tree7d6d8068b148e0282bc5156d3e8fde1f9ac4fb7f
parentf9f164d3c71aee897e7885e4c991866bd1c0c339 (diff)
downloadscala-5c61410fe5b8fd636bde6484f04a2d1160ed7eb4.tar.gz
scala-5c61410fe5b8fd636bde6484f04a2d1160ed7eb4.tar.bz2
scala-5c61410fe5b8fd636bde6484f04a2d1160ed7eb4.zip
Start of an attempt to abstract above some hard...
Start of an attempt to abstract above some hardcoded name mangling decisions so they can be modified, something we need to do to fix long-standing problems with inner classes. It's not easy. This commit doesn't actually change much, it's primarily setup. No review.
-rw-r--r--src/compiler/scala/reflect/internal/Definitions.scala4
-rw-r--r--src/compiler/scala/reflect/internal/NameManglers.scala15
-rw-r--r--src/compiler/scala/reflect/internal/StdNames.scala6
-rw-r--r--src/compiler/scala/reflect/internal/Symbols.scala15
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala17
-rw-r--r--src/compiler/scala/tools/nsc/backend/jvm/GenJVMUtil.scala4
-rw-r--r--src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala12
-rw-r--r--src/compiler/scala/tools/nsc/dependencies/Changes.scala2
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/ByteCode.scala3
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/ILoop.scala7
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/IMain.scala10
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/Power.scala4
-rw-r--r--src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala7
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala8
-rw-r--r--src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala9
-rw-r--r--src/compiler/scala/tools/nsc/transform/Constructors.scala2
-rw-r--r--src/compiler/scala/tools/nsc/transform/Erasure.scala7
-rw-r--r--src/compiler/scala/tools/nsc/transform/Flatten.scala63
-rw-r--r--src/compiler/scala/tools/nsc/transform/LambdaLift.scala4
-rw-r--r--src/compiler/scala/tools/nsc/typechecker/Namers.scala4
-rw-r--r--src/compiler/scala/tools/nsc/util/Origins.scala4
-rw-r--r--src/library/scala/Enumeration.scala9
-rwxr-xr-xsrc/library/scala/reflect/NameTransformer.scala6
23 files changed, 138 insertions, 84 deletions
diff --git a/src/compiler/scala/reflect/internal/Definitions.scala b/src/compiler/scala/reflect/internal/Definitions.scala
index e1a3e732b0..00d2c232a0 100644
--- a/src/compiler/scala/reflect/internal/Definitions.scala
+++ b/src/compiler/scala/reflect/internal/Definitions.scala
@@ -765,8 +765,8 @@ trait Definitions extends reflect.api.StandardDefinitions {
}
def flatNameString(sym: Symbol, separator: Char): String =
if (sym == NoSymbol) "" // be more resistant to error conditions, e.g. neg/t3222.scala
- else if (sym.owner.isPackageClass) sym.fullName('.') + (if (sym.isModuleClass) "$" else "")
- else flatNameString(sym.owner, separator) + "$" + sym.simpleName;
+ else if (sym.owner.isPackageClass) sym.javaClassName
+ else flatNameString(sym.owner, separator) + nme.NAME_JOIN_STRING + sym.simpleName
def signature1(etp: Type): String = {
if (etp.typeSymbol == ArrayClass) "[" + signature1(erasure(etp.normalize.typeArgs.head))
else if (isValueClass(etp.typeSymbol)) abbrvTag(etp.typeSymbol).toString()
diff --git a/src/compiler/scala/reflect/internal/NameManglers.scala b/src/compiler/scala/reflect/internal/NameManglers.scala
index 571b2ba248..c09397e2c2 100644
--- a/src/compiler/scala/reflect/internal/NameManglers.scala
+++ b/src/compiler/scala/reflect/internal/NameManglers.scala
@@ -20,7 +20,10 @@ trait NameManglers {
trait NameManglingCommon {
self: CommonNames =>
- def flattenedName(segments: Name*): NameType = compactedString(segments mkString "$")
+ val MODULE_SUFFIX_STRING = NameTransformer.MODULE_SUFFIX_STRING
+ val NAME_JOIN_STRING = NameTransformer.NAME_JOIN_STRING
+
+ def flattenedName(segments: Name*): NameType = compactedString(segments mkString NAME_JOIN_STRING)
/**
* COMPACTIFY
@@ -66,12 +69,12 @@ trait NameManglers {
self: nme.type =>
val IMPL_CLASS_SUFFIX = "$class"
- val SINGLETON_SUFFIX = ".type"
val LOCALDUMMY_PREFIX = "<local " // owner of local blocks
val PROTECTED_PREFIX = "protected$"
val PROTECTED_SET_PREFIX = PROTECTED_PREFIX + "set"
val SELECTOR_DUMMY = "<unapply-selector>"
val SETTER_SUFFIX = encode("_=")
+ val SINGLETON_SUFFIX = ".type"
val SUPER_PREFIX_STRING = "super$"
val TRAIT_SETTER_SEPARATOR_STRING = "$_setter_$"
@@ -87,6 +90,7 @@ trait NameManglers {
def isSetterName(name: Name) = name endsWith SETTER_SUFFIX
def isTraitSetterName(name: Name) = isSetterName(name) && (name containsName TRAIT_SETTER_SEPARATOR_STRING)
def isSingletonName(name: Name) = name endsWith SINGLETON_SUFFIX
+ def isModuleName(name: Name) = name endsWith MODULE_SUFFIX_STRING
def isOpAssignmentName(name: Name) = name match {
case raw.NE | raw.LE | raw.GE | EMPTY => false
@@ -155,6 +159,13 @@ trait NameManglers {
else name
}
+ def stripModuleSuffix(name: Name): Name = (
+ if (isModuleName(name)) name stripEnd MODULE_SUFFIX_STRING else name
+ )
+
+ /** Note that for performance reasons, stripEnd does not verify that the
+ * suffix is actually the suffix specified.
+ */
def dropSingletonName(name: Name): TypeName = name stripEnd SINGLETON_SUFFIX toTypeName
def singletonName(name: Name): TypeName = name append SINGLETON_SUFFIX toTypeName
def implClassName(name: Name): TypeName = name append IMPL_CLASS_SUFFIX toTypeName
diff --git a/src/compiler/scala/reflect/internal/StdNames.scala b/src/compiler/scala/reflect/internal/StdNames.scala
index 43fe89ed63..4947334c1e 100644
--- a/src/compiler/scala/reflect/internal/StdNames.scala
+++ b/src/compiler/scala/reflect/internal/StdNames.scala
@@ -92,7 +92,7 @@ trait StdNames extends /*reflect.generic.StdNames with*/ NameManglers { self: Sy
val ANON_FUN_NAME: NameType = "$anonfun"
val EMPTY_PACKAGE_NAME: NameType = "<empty>"
val IMPORT: NameType = "<import>"
- val MODULE_SUFFIX: NameType = "$module"
+ val MODULE_VAR_SUFFIX: NameType = "$module"
val ROOT: NameType = "<root>"
// value types are all used as terms as well
@@ -172,7 +172,7 @@ trait StdNames extends /*reflect.generic.StdNames with*/ NameManglers { self: Sy
val FAKE_LOCAL_THIS: NameType = "this$"
val INITIALIZER: NameType = CONSTRUCTOR // Is this buying us something?
val MIXIN_CONSTRUCTOR: NameType = "$init$"
- val MODULE_INSTANCE_FIELD: NameType = "MODULE$"
+ val MODULE_INSTANCE_FIELD: NameType = NameTransformer.MODULE_INSTANCE_NAME // "MODULE$"
val OUTER: NameType = "$outer"
val OUTER_LOCAL: NameType = "$outer " // note the space
val SELF: NameType = "$this"
@@ -374,7 +374,7 @@ trait StdNames extends /*reflect.generic.StdNames with*/ NameManglers { self: Sy
def expandedName(name: TermName, base: Symbol, separator: String = EXPAND_SEPARATOR_STRING): TermName =
newTermName(base.fullName('$') + separator + name)
- def moduleVarName(name: TermName): TermName = newTermName("" + name + MODULE_SUFFIX)
+ def moduleVarName(name: TermName): TermName = newTermName("" + name + MODULE_VAR_SUFFIX)
val EXPAND_SEPARATOR_STRING = "$$"
val LOCAL_SUFFIX_STRING = " "
diff --git a/src/compiler/scala/reflect/internal/Symbols.scala b/src/compiler/scala/reflect/internal/Symbols.scala
index f9afd164f5..91f052af6c 100644
--- a/src/compiler/scala/reflect/internal/Symbols.scala
+++ b/src/compiler/scala/reflect/internal/Symbols.scala
@@ -620,6 +620,8 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
}
def ownerChain: List[Symbol] = this :: owner.ownerChain
+ def originalOwnerChain: List[Symbol] = this :: originalOwner.getOrElse(this, rawowner).originalOwnerChain
+
def enclClassChain: List[Symbol] = {
if (this eq NoSymbol) Nil
else if (isClass && !isPackageClass) this :: owner.enclClassChain
@@ -665,7 +667,7 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
*/
def originalName = nme.originalName(name)
- /** The name of the symbol before decoding, e.g. `\$eq\$eq` instead of `==`.
+ /** The name of the symbol before decoding, e.g. `\$eq\$eq` instead of `==`.
*/
def encodedName: String = name.toString
@@ -673,6 +675,17 @@ trait Symbols extends api.Symbols { self: SymbolTable =>
*/
def decodedName: String = stripLocalSuffix(NameTransformer.decode(encodedName))
+ def moduleSuffix: String = (
+ if (hasModuleFlag && !isMethod && !isImplClass && !isJavaDefined) nme.MODULE_SUFFIX_STRING
+ else ""
+ )
+
+ /** These should be moved somewhere like JavaPlatform.
+ */
+ def javaSimpleName = stripLocalSuffix("" + simpleName) + moduleSuffix
+ def javaBinaryName = fullName('/') + moduleSuffix
+ def javaClassName = fullName('.') + moduleSuffix
+
/** The encoded full path name of this symbol, where outer names and inner names
* are separated by `separator` characters.
* Never translates expansions of operators back to operator symbol.
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
index a53fbef200..7c382c5f93 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVM.scala
@@ -95,12 +95,6 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
}
}
- /** Return the suffix of a class name */
- def moduleSuffix(sym: Symbol) =
- if (sym.hasModuleFlag && !sym.isMethod &&
- !sym.isImplClass && !sym.isJavaDefined) "$"
- else ""
-
var pickledBytes = 0 // statistics
/**
@@ -161,8 +155,13 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
val emitVars = debugLevel >= 3
override def javaName(sym: Symbol): String = {
- if (sym.isClass && !sym.rawowner.isPackageClass && !sym.isModuleClass)
+ val isInner = sym.isClass && !sym.rawowner.isPackageClass && !sym.isModuleClass
+ // TODO: something atPhase(currentRun.flattenPhase.prev) which accounts for
+ // being nested in parameterized classes (if we're going to selectively flatten.)
+ if (isInner) {
+ log("Inner class: " + sym.fullLocationString)
innerClassBuffer += sym
+ }
super.javaName(sym)
}
@@ -199,7 +198,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
*/
def scalaSignatureAddingMarker(jclass: JClass, sym: Symbol): Option[AnnotationInfo] =
currentRun.symData get sym match {
- case Some(pickle) if !jclass.getName().endsWith("$") =>
+ case Some(pickle) if !nme.isModuleName(jclass.getName()) =>
val scalaAttr =
fjbgContext.JOtherAttribute(jclass, jclass, tpnme.ScalaSignatureATTR.toString,
versionPickle.bytes, versionPickle.writeIndex)
@@ -673,7 +672,7 @@ abstract class GenJVM extends SubComponent with GenJVMUtil with GenAndroid with
null
else {
val outerName = javaName(innerSym.rawowner)
- if (isTopLevelModule(innerSym.rawowner)) outerName stripSuffix "$"
+ if (isTopLevelModule(innerSym.rawowner)) "" + nme.stripModuleSuffix(outerName)
else outerName
}
}
diff --git a/src/compiler/scala/tools/nsc/backend/jvm/GenJVMUtil.scala b/src/compiler/scala/tools/nsc/backend/jvm/GenJVMUtil.scala
index 9697477543..acaf1f6cc2 100644
--- a/src/compiler/scala/tools/nsc/backend/jvm/GenJVMUtil.scala
+++ b/src/compiler/scala/tools/nsc/backend/jvm/GenJVMUtil.scala
@@ -87,9 +87,9 @@ trait GenJVMUtil {
def javaName(sym: Symbol): String =
javaNameCache.getOrElseUpdate(sym, {
if (sym.isClass || (sym.isModule && !sym.isMethod))
- sym.fullName('/') + moduleSuffix(sym)
+ sym.javaBinaryName
else
- sym.simpleName.toString.trim() + moduleSuffix(sym)
+ sym.javaSimpleName
})
def javaType(t: TypeKind): JType = (t: @unchecked) match {
diff --git a/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala b/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala
index ae2082ec8b..f2f5ecb2fe 100644
--- a/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala
+++ b/src/compiler/scala/tools/nsc/backend/msil/GenMSIL.scala
@@ -1618,9 +1618,7 @@ abstract class GenMSIL extends SubComponent {
* not exist in the classpath: the type checker will be very confused.
*/
def msilName(sym: Symbol): String = {
- val suffix: String = if (sym.hasModuleFlag && !sym.isMethod &&
- !sym.isImplClass &&
- !sym.isJavaDefined) "$" else ""
+ val suffix = sym.moduleSuffix
// Flags.JAVA: "symbol was not defined by a scala-class" (java, or .net-class)
if (sym == definitions.NothingClass)
@@ -2035,7 +2033,7 @@ abstract class GenMSIL extends SubComponent {
}
def nestingAwareFullClassname(csym: Symbol) : String = {
- val suffix = moduleSuffix(csym)
+ val suffix = csym.moduleSuffix
val res = if (csym.isNestedClass)
nestingAwareFullClassname(csym.owner) + "+" + csym.encodedName
else
@@ -2043,12 +2041,6 @@ abstract class GenMSIL extends SubComponent {
res + suffix
}
- /** cut&pasted from GenJVM */
- def moduleSuffix(sym: Symbol) =
- if (sym.hasFlag(Flags.MODULE) && !sym.isMethod &&
- !sym.isImplClass && !sym.hasFlag(Flags.JAVA)) "$"
- else "";
-
/** Adds a static initializer which creates an instance of the module
* class (calls the primary constructor). A special primary constructor
* will be generated (notInitializedModules) which stores the new instance
diff --git a/src/compiler/scala/tools/nsc/dependencies/Changes.scala b/src/compiler/scala/tools/nsc/dependencies/Changes.scala
index baab0271e1..4c7263ef69 100644
--- a/src/compiler/scala/tools/nsc/dependencies/Changes.scala
+++ b/src/compiler/scala/tools/nsc/dependencies/Changes.scala
@@ -52,7 +52,7 @@ abstract class Changes {
private val changedTypeParams = new mutable.HashSet[String]
private def sameParameterSymbolNames(sym1: Symbol, sym2: Symbol): Boolean =
- sameSymbol(sym1, sym2, true) || sym2.encodedName.startsWith(sym1.encodedName + "$") // see #3140
+ sameSymbol(sym1, sym2, true) || sym2.encodedName.startsWith(sym1.encodedName + nme.NAME_JOIN_STRING) // see #3140
private def sameSymbol(sym1: Symbol, sym2: Symbol, simple: Boolean = false): Boolean =
if (simple) sym1.encodedName == sym2.encodedName else sym1.fullName == sym2.fullName
private def sameFlags(sym1: Symbol, sym2: Symbol): Boolean =
diff --git a/src/compiler/scala/tools/nsc/interpreter/ByteCode.scala b/src/compiler/scala/tools/nsc/interpreter/ByteCode.scala
index 1b2f6443ae..ece80af272 100644
--- a/src/compiler/scala/tools/nsc/interpreter/ByteCode.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/ByteCode.scala
@@ -10,6 +10,7 @@ import java.lang.reflect
import java.util.concurrent.ConcurrentHashMap
import util.ScalaClassLoader
import ScalaClassLoader.getSystemLoader
+import scala.reflect.NameTransformer._
object ByteCode {
/** Until I figure out why I can't get scalap onto the classpath such
@@ -17,7 +18,7 @@ object ByteCode {
*/
private lazy val DECODER: Option[AnyRef] =
for (clazz <- getSystemLoader.tryToLoadClass[AnyRef]("scala.tools.scalap.Decode$")) yield
- clazz.getField("MODULE$").get()
+ clazz.getField(MODULE_INSTANCE_NAME).get()
private def decoderMethod(name: String, args: JClass*): Option[reflect.Method] = {
for (decoder <- DECODER ; m <- Option(decoder.getClass.getMethod(name, args: _*))) yield m
diff --git a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala
index 8e7f73296f..8ae4f9779a 100644
--- a/src/compiler/scala/tools/nsc/interpreter/ILoop.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/ILoop.scala
@@ -18,6 +18,7 @@ import scala.concurrent.ops
import util.{ ClassPath, Exceptional, stringFromWriter, stringFromStream }
import interpreter._
import io.{ File, Sources }
+import scala.reflect.NameTransformer._
/** The Scala interactive shell. It provides a read-eval-print loop
* around the Interpreter class.
@@ -359,10 +360,10 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
if (rest.nonEmpty) {
intp optFlatName hd match {
case Some(flat) =>
- val clazz = flat :: rest mkString "$"
+ val clazz = flat :: rest mkString NAME_JOIN_STRING
val bytes = super.tryClass(clazz)
if (bytes.nonEmpty) bytes
- else super.tryClass(clazz + "$")
+ else super.tryClass(clazz + MODULE_SUFFIX_STRING)
case _ => super.tryClass(path)
}
}
@@ -371,7 +372,7 @@ class ILoop(in0: Option[BufferedReader], protected val out: JPrintWriter)
// we have to drop the $ to find object Foo, then tack it back onto
// the end of the flattened name.
def className = intp flatName path
- def moduleName = (intp flatName path.stripSuffix("$")) + "$"
+ def moduleName = (intp flatName path.stripSuffix(MODULE_SUFFIX_STRING)) + MODULE_SUFFIX_STRING
val bytes = super.tryClass(className)
if (bytes.nonEmpty) bytes
diff --git a/src/compiler/scala/tools/nsc/interpreter/IMain.scala b/src/compiler/scala/tools/nsc/interpreter/IMain.scala
index 9edf7f44f3..b84bf178a0 100644
--- a/src/compiler/scala/tools/nsc/interpreter/IMain.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/IMain.scala
@@ -209,7 +209,11 @@ class IMain(val settings: Settings, protected val out: JPrintWriter) extends Imp
def quietRun[T](code: String) = beQuietDuring(interpret(code))
private def logAndDiscard[T](label: String, alt: => T): PartialFunction[Throwable, T] = {
- case t => repldbg(label + ": " + t) ; alt
+ case t =>
+ repldbg(label + ": " + unwrap(t))
+ repltrace(util.stackTraceString(unwrap(t)))
+
+ alt
}
/** whether to bind the lastException variable */
@@ -311,7 +315,7 @@ class IMain(val settings: Settings, protected val out: JPrintWriter) extends Imp
* }}}
*/
def generatedName(simpleName: String): Option[String] = {
- if (simpleName endsWith "$") optFlatName(simpleName.init) map (_ + "$")
+ if (simpleName endsWith nme.MODULE_SUFFIX_STRING) optFlatName(simpleName.init) map (_ + nme.MODULE_SUFFIX_STRING)
else optFlatName(simpleName)
}
def flatName(id: String) = optFlatName(id) getOrElse id
@@ -795,7 +799,7 @@ class IMain(val settings: Settings, protected val out: JPrintWriter) extends Imp
* $line5.$iw$$iw$$iw$Bippy // fullFlatName
*/
def fullFlatName(name: String) =
- lineRep.readPath + accessPath.replace('.', '$') + "$" + name
+ lineRep.readPath + accessPath.replace('.', '$') + nme.NAME_JOIN_STRING + name
/** The unmangled symbol name, but supplemented with line info. */
def disambiguated(name: Name): String = name + " (in " + lineRep + ")"
diff --git a/src/compiler/scala/tools/nsc/interpreter/Power.scala b/src/compiler/scala/tools/nsc/interpreter/Power.scala
index 95b42ebf69..cfef2c5e87 100644
--- a/src/compiler/scala/tools/nsc/interpreter/Power.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/Power.scala
@@ -188,7 +188,7 @@ abstract class Power(
getCompilerClass("scala." + x).tpe
case _ =>
val name = m.erasure.getName
- if (name endsWith "$") getCompilerModule(name dropRight 1).tpe
+ if (name endsWith nme.MODULE_SUFFIX_STRING) getCompilerModule(name dropRight 1).tpe
else {
val sym = getCompilerClass(name)
val args = m.typeArguments
@@ -361,7 +361,7 @@ abstract class Power(
object Implicits extends Implicits2 { }
trait ReplUtilities {
- def module[T: Manifest] = getCompilerModule(manifest[T].erasure.getName stripSuffix "$")
+ def module[T: Manifest] = getCompilerModule(manifest[T].erasure.getName stripSuffix nme.MODULE_SUFFIX_STRING)
def clazz[T: Manifest] = getCompilerClass(manifest[T].erasure.getName)
def info[T: Manifest] = InternalInfo[T]
def ?[T: Manifest] = InternalInfo[T]
diff --git a/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala b/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala
index fc286b4868..aa926adecc 100644
--- a/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala
+++ b/src/compiler/scala/tools/nsc/interpreter/TypeStrings.scala
@@ -9,6 +9,7 @@ package interpreter
import java.lang.{ reflect => r }
import r.TypeVariable
import scala.reflect.NameTransformer
+import NameTransformer._
/** Logic for turning a type into a String. The goal is to be
* able to take some arbitrary object 'x' and obtain the most precise
@@ -36,17 +37,17 @@ trait TypeStrings {
} toMap
def scalaName(s: String): String = {
- if (s endsWith "$") s.init + ".type"
+ if (s endsWith MODULE_SUFFIX_STRING) s.init + ".type"
else if (s == "void") "scala.Unit"
else if (primitives(s)) "scala." + s.capitalize
- else primitiveMap.getOrElse(s, NameTransformer decode s)
+ else primitiveMap.getOrElse(s, NameTransformer.decode(s))
}
// Trying to put humpty dumpty back together again.
def scalaName(clazz: JClass): String = {
val name = clazz.getName
val isAnon = clazz.isScalaAnonymous
val enclClass = clazz.getEnclosingClass
- def enclPre = enclClass.getName + "$"
+ def enclPre = enclClass.getName + MODULE_SUFFIX_STRING
def enclMatch = name startsWith enclPre
scalaName(
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
index 9d3421ae27..1970a580a6 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ClassfileParser.scala
@@ -187,8 +187,8 @@ abstract class ClassfileParser {
val start = starts(index)
if (in.buf(start).toInt != CONSTANT_CLASS) errorBadTag(start)
val name = getExternalName(in.getChar(start + 1))
- if (name endsWith '$')
- c = definitions.getModule(name stripEnd "$")
+ if (nme.isModuleName(name))
+ c = definitions.getModule(nme.stripModuleSuffix(name))
else
c = classNameToSymbol(name)
@@ -1226,9 +1226,7 @@ abstract class ClassfileParser {
innerClasses.get(externalName) match {
case Some(entry) =>
- val outerName =
- if (entry.outerName.endsWith("$")) entry.outerName.subName(0, entry.outerName.length - 1)
- else entry.outerName
+ val outerName = nme.stripModuleSuffix(entry.outerName)
val sym = classSymbol(outerName)
val s =
// if loading during initialization of `definitions` typerPhase is not yet set.
diff --git a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
index 1d8588209e..b9e8abe53f 100644
--- a/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
+++ b/src/compiler/scala/tools/nsc/symtab/classfile/ICodeReader.scala
@@ -37,15 +37,14 @@ abstract class ICodeReader extends ClassfileParser {
*/
def readClass(cls: Symbol): (IClass, IClass) = {
var classFile: io.AbstractFile = null;
- var sym = cls
- sym.info // ensure accurate type information
+ cls.info // ensure accurate type information
isScalaModule = cls.isModule && !cls.isJavaDefined
log("Reading class: " + cls + " isScalaModule?: " + isScalaModule)
- val name = cls.fullName('.') + (if (sym.hasFlag(MODULE)) "$" else "")
+ val name = cls.javaClassName
classPath.findSourceFile(name) match {
- case Some(classFile) => parse(classFile, sym)
+ case Some(classFile) => parse(classFile, cls)
case _ => throw new MissingRequirementError("Could not find bytecode for " + cls)
}
@@ -192,7 +191,7 @@ abstract class ICodeReader extends ClassfileParser {
log("forcing " + iface.owner + " at phase: " + phase + " impl: " + iface.implClass)
iface.owner.info // force the mixin type-transformer
definitions.getClass(name)
- } else if (name.endsWith("$")) {
+ } else if (name.endsWith(nme.MODULE_SUFFIX_STRING)) {
val sym = forceMangledName(name.subName(0, name.length -1).decode, true)
// println("classNameToSymbol: " + name + " sym: " + sym)
if (name.toString == "scala.collection.immutable.Stream$$hash$colon$colon$")
diff --git a/src/compiler/scala/tools/nsc/transform/Constructors.scala b/src/compiler/scala/tools/nsc/transform/Constructors.scala
index a333c7458d..eb700f1610 100644
--- a/src/compiler/scala/tools/nsc/transform/Constructors.scala
+++ b/src/compiler/scala/tools/nsc/transform/Constructors.scala
@@ -62,7 +62,7 @@ abstract class Constructors extends Transform with ast.TreeDSL {
// The constructor parameter with given name. This means the parameter
// has given name, or starts with given name, and continues with a `$` afterwards.
def parameterNamed(name: Name): Symbol = {
- def matchesName(param: Symbol) = param.name == name || param.name.startsWith(name + "$")
+ def matchesName(param: Symbol) = param.name == name || param.name.startsWith(name + nme.NAME_JOIN_STRING)
(constrParams filter matchesName) match {
case Nil => assert(false, name + " not in " + constrParams) ; null
diff --git a/src/compiler/scala/tools/nsc/transform/Erasure.scala b/src/compiler/scala/tools/nsc/transform/Erasure.scala
index fbb5a8dcde..c2013e77f9 100644
--- a/src/compiler/scala/tools/nsc/transform/Erasure.scala
+++ b/src/compiler/scala/tools/nsc/transform/Erasure.scala
@@ -214,10 +214,7 @@ abstract class Erasure extends AddInterfaces
// Anything which could conceivably be a module (i.e. isn't known to be
// a type parameter or similar) must go through here or the signature is
// likely to end up with Foo<T>.Empty where it needs Foo<T>.Empty$.
- def nameInSig(sym: Symbol) = "" + sym.name + global.genJVM.moduleSuffix(sym)
- def fullNameInSig(sym: Symbol) = "L" + (
- atPhase(currentRun.icodePhase)(sym.fullName('/') + global.genJVM.moduleSuffix(sym))
- )
+ def fullNameInSig(sym: Symbol) = "L" + atPhase(currentRun.icodePhase)(sym.javaBinaryName)
def jsig(tp0: Type, existentiallyBound: List[Symbol] = Nil, toplevel: Boolean = false, primitiveOK: Boolean = true): String = {
val tp = tp0.dealias
@@ -266,7 +263,7 @@ abstract class Erasure extends AddInterfaces
(
if (needsJavaSig(preRebound)) {
val s = jsig(preRebound, existentiallyBound)
- if (s.charAt(0) == 'L') s.substring(0, s.length - 1) + "." + nameInSig(sym)
+ if (s.charAt(0) == 'L') s.substring(0, s.length - 1) + "." + sym.javaSimpleName
else fullNameInSig(sym)
}
else fullNameInSig(sym)
diff --git a/src/compiler/scala/tools/nsc/transform/Flatten.scala b/src/compiler/scala/tools/nsc/transform/Flatten.scala
index 28dfabb035..53016dd748 100644
--- a/src/compiler/scala/tools/nsc/transform/Flatten.scala
+++ b/src/compiler/scala/tools/nsc/transform/Flatten.scala
@@ -18,43 +18,69 @@ abstract class Flatten extends InfoTransform {
/** the following two members override abstract members in Transform */
val phaseName: String = "flatten"
+ /** Updates the owning scope with the given symbol; returns the old symbol.
+ */
+ private def replaceSymbolInCurrentScope(sym: Symbol): Symbol = {
+ atPhase(phase.next) {
+ val scope = sym.owner.info.decls
+ val old = scope lookup sym.name
+ if (old ne NoSymbol)
+ scope unlink old
+
+ scope enter sym
+ old
+ }
+ }
+
private def liftClass(sym: Symbol) {
- if (!(sym hasFlag LIFTED)) {
+ if (!sym.isLifted) {
sym setFlag LIFTED
- atPhase(phase.next) {
- if (settings.debug.value) log("re-enter " + sym + " in " + sym.owner)
- assert(sym.owner.isPackageClass, sym) //debug
- val scope = sym.owner.info.decls
- val old = scope lookup sym.name
- if (old != NoSymbol) scope unlink old
- scope enter sym
- }
+ debuglog("re-enter " + sym.fullLocationString)
+ val old = replaceSymbolInCurrentScope(sym)
+ if (old ne NoSymbol)
+ debuglog("lifted " + sym.fullLocationString + ", unlinked " + old)
+ }
+ }
+ private def liftSymbol(sym: Symbol) {
+ liftClass(sym)
+ if (sym.needsImplClass)
+ liftClass(erasure implClass sym)
+ }
+ // This is a short-term measure partially working around objects being
+ // lifted out of parameterized classes, leaving them referencing
+ // invisible type parameters.
+ private def isFlattenablePrefix(pre: Type) = {
+ val clazz = pre.typeSymbol
+ clazz.isClass && !clazz.isPackageClass && {
+ // Cannot flatten here: class A[T] { object B }
+ atPhase(currentRun.erasurePhase.prev)(clazz.typeParams.isEmpty)
}
}
private val flattened = new TypeMap {
def apply(tp: Type): Type = tp match {
- case TypeRef(pre, sym, args) if (pre.typeSymbol.isClass && !pre.typeSymbol.isPackageClass) =>
- assert(args.isEmpty)
- assert(sym.toplevelClass != NoSymbol, sym.ownerChain)
- typeRef(sym.toplevelClass.owner.thisType, sym, args)
+ case TypeRef(pre, sym, args) if isFlattenablePrefix(pre) =>
+ assert(args.isEmpty && sym.toplevelClass != NoSymbol, sym.ownerChain)
+ typeRef(sym.toplevelClass.owner.thisType, sym, Nil)
case ClassInfoType(parents, decls, clazz) =>
var parents1 = parents
val decls1 = new Scope
if (clazz.isPackageClass) {
atPhase(phase.next)(decls foreach (decls1 enter _))
- } else {
+ }
+ else {
val oldowner = clazz.owner
atPhase(phase.next)(oldowner.info)
parents1 = parents mapConserve (this)
+
for (sym <- decls) {
if (sym.isTerm && !sym.isStaticModule) {
decls1 enter sym
- if (sym.isModule) sym.moduleClass setFlag LIFTED
- } else if (sym.isClass) {
- liftClass(sym)
- if (sym.needsImplClass) liftClass(erasure.implClass(sym))
+ if (sym.isModule)
+ sym.moduleClass setFlag LIFTED
}
+ else if (sym.isClass)
+ liftSymbol(sym)
}
}
ClassInfoType(parents1, decls1, clazz)
@@ -74,7 +100,6 @@ abstract class Flatten extends InfoTransform {
protected def newTransformer(unit: CompilationUnit): Transformer = new Flattener
class Flattener extends Transformer {
-
/** Buffers for lifted out classes */
private val liftedDefs = new mutable.HashMap[Symbol, ListBuffer[Tree]]
diff --git a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala
index 7c3ace7637..533caff078 100644
--- a/src/compiler/scala/tools/nsc/transform/LambdaLift.scala
+++ b/src/compiler/scala/tools/nsc/transform/LambdaLift.scala
@@ -195,9 +195,9 @@ abstract class LambdaLift extends InfoTransform {
for (sym <- renamable) {
val originalName = sym.name
- val base = sym.name + "$" + (
+ val base = sym.name + nme.NAME_JOIN_STRING + (
if (sym.isAnonymousFunction && sym.owner.isMethod)
- sym.owner.name + "$"
+ sym.owner.name + nme.NAME_JOIN_STRING
else ""
)
sym.name =
diff --git a/src/compiler/scala/tools/nsc/typechecker/Namers.scala b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
index 9e9c42cf90..6bbb94bf29 100644
--- a/src/compiler/scala/tools/nsc/typechecker/Namers.scala
+++ b/src/compiler/scala/tools/nsc/typechecker/Namers.scala
@@ -1259,8 +1259,8 @@ trait Namers { self: Analyzer =>
def notMember() = context.error(tree.pos, from.decode + " is not a member of " + expr)
// for Java code importing Scala objects
- if (from endsWith nme.raw.DOLLAR)
- isValidSelector(from stripEnd "$")(notMember())
+ if (nme.isModuleName(from))
+ isValidSelector(nme.stripModuleSuffix(from))(notMember())
else
notMember()
}
diff --git a/src/compiler/scala/tools/nsc/util/Origins.scala b/src/compiler/scala/tools/nsc/util/Origins.scala
index 847a9b6dad..f8ba34ae3c 100644
--- a/src/compiler/scala/tools/nsc/util/Origins.scala
+++ b/src/compiler/scala/tools/nsc/util/Origins.scala
@@ -6,6 +6,8 @@
package scala.tools.nsc
package util
+import scala.reflect.NameTransformer._
+
/** A debugging class for logging from whence a method is being called.
* Say you wanted to discover who was calling phase_= in SymbolTable.
* You could do this:
@@ -98,7 +100,7 @@ object Origins {
class OneLine(clazz: Class[_]) extends Origins {
type Rep = StackTraceElement
- val originClass = clazz.getName stripSuffix "$"
+ val originClass = clazz.getName stripSuffix MODULE_SUFFIX_STRING
def newRep(xs: StackSlice): Rep = xs(0)
def repString(rep: Rep) = " " + rep
}
diff --git a/src/library/scala/Enumeration.scala b/src/library/scala/Enumeration.scala
index 563b2d70c4..22bb98ba46 100644
--- a/src/library/scala/Enumeration.scala
+++ b/src/library/scala/Enumeration.scala
@@ -10,6 +10,8 @@ package scala
import scala.collection.{ mutable, immutable, generic, SetLike }
import java.lang.reflect.{ Modifier, Method => JMethod, Field => JField }
+import scala.reflect.NameTransformer._
+import java.util.regex.Pattern
/** Defines a finite set of values specific to the enumeration. Typically
* these values enumerate all possible forms something can take and provide
@@ -59,11 +61,14 @@ abstract class Enumeration(initial: Int, names: String*) extends Serializable {
/* Note that `readResolve` cannot be private, since otherwise
the JVM does not invoke it when deserializing subclasses. */
- protected def readResolve(): AnyRef = thisenum.getClass.getField("MODULE$").get()
+ protected def readResolve(): AnyRef = thisenum.getClass.getField(MODULE_INSTANCE_NAME).get()
/** The name of this enumeration.
*/
- override def toString = (getClass.getName stripSuffix "$" split '.' last) split '$' last
+ override def toString = (
+ (getClass.getName stripSuffix MODULE_SUFFIX_STRING split '.' last)
+ split Pattern.quote(NAME_JOIN_STRING) last
+ )
/** The mapping from the integer used to identify values to the actual
* values. */
diff --git a/src/library/scala/reflect/NameTransformer.scala b/src/library/scala/reflect/NameTransformer.scala
index 6c12c8db33..38fbbc98f2 100755
--- a/src/library/scala/reflect/NameTransformer.scala
+++ b/src/library/scala/reflect/NameTransformer.scala
@@ -12,6 +12,12 @@ package scala.reflect
* @author Martin Odersky
*/
object NameTransformer {
+ // XXX Short term: providing a way to alter these without having to recompile
+ // the compiler before recompiling the compiler.
+ val MODULE_SUFFIX_STRING = sys.props.getOrElse("SCALA_MODULE_SUFFIX_STRING", "$")
+ val NAME_JOIN_STRING = sys.props.getOrElse("SCALA_NAME_JOIN_STRING", "$")
+ val MODULE_INSTANCE_NAME = "MODULE$"
+
private val nops = 128
private val ncodes = 26 * 26