diff options
Diffstat (limited to 'src/dotty/tools/dotc/core')
-rw-r--r-- | src/dotty/tools/dotc/core/Chars.scala | 91 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Contexts.scala | 35 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Decorators.scala | 13 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Definitions.scala | 6 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Denotations.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/NameOps.scala | 275 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Names.scala | 367 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Printers.scala | 76 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/StdNames.scala | 728 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/SymDenotations.scala | 33 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Symbols.scala | 33 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/Types.scala | 2 |
12 files changed, 1469 insertions, 192 deletions
diff --git a/src/dotty/tools/dotc/core/Chars.scala b/src/dotty/tools/dotc/core/Chars.scala new file mode 100644 index 000000000..6b796aa31 --- /dev/null +++ b/src/dotty/tools/dotc/core/Chars.scala @@ -0,0 +1,91 @@ +/* NSC -- new Scala compiler + * Copyright 2006-2012 LAMP/EPFL + * @author Martin Odersky + */ +package dotty.tools.dotc +package core + +import scala.annotation.{ tailrec, switch } +import java.lang.{ Character => JCharacter } +import scala.language.postfixOps + +/** Contains constants and classifier methods for characters */ +object Chars { + + final val LF = '\u000A' + final val FF = '\u000C' + final val CR = '\u000D' + final val SU = '\u001A' + + /** Convert a character digit to an Int according to given base, + * -1 if no success + */ + def digit2int(ch: Char, base: Int): Int = { + val num = ( + if (ch <= '9') ch - '0' + else if ('a' <= ch && ch <= 'z') ch - 'a' + 10 + else if ('A' <= ch && ch <= 'Z') ch - 'A' + 10 + else -1 + ) + if (0 <= num && num < base) num else -1 + } + /** Buffer for creating '\ u XXXX' strings. */ + private[this] val char2uescapeArray = Array[Char]('\\', 'u', 0, 0, 0, 0) + + /** Convert a character to a backslash-u escape */ + def char2uescape(c: Char): String = { + @inline def hexChar(ch: Int): Char = + ( if (ch < 10) '0' else 'A' - 10 ) + ch toChar + + char2uescapeArray(2) = hexChar((c >> 12) ) + char2uescapeArray(3) = hexChar((c >> 8) % 16) + char2uescapeArray(4) = hexChar((c >> 4) % 16) + char2uescapeArray(5) = hexChar((c ) % 16) + + new String(char2uescapeArray) + } + + /** Is character a line break? */ + def isLineBreakChar(c: Char) = (c: @switch) match { + case LF|FF|CR|SU => true + case _ => false + } + + /** Is character a whitespace character (but not a new line)? */ + def isWhitespace(c: Char) = + c == ' ' || c == '\t' || c == CR + + /** Can character form part of a doc comment variable $xxx? */ + def isVarPart(c: Char) = + '0' <= c && c <= '9' || 'A' <= c && c <= 'Z' || 'a' <= c && c <= 'z' + + /** Can character start an alphanumeric Scala identifier? */ + def isIdentifierStart(c: Char): Boolean = + (c == '_') || (c == '$') || Character.isUnicodeIdentifierStart(c) + + /** Can character form part of an alphanumeric Scala identifier? */ + def isIdentifierPart(c: Char) = + (c == '$') || Character.isUnicodeIdentifierPart(c) + + /** Is character a math or other symbol in Unicode? */ + def isSpecial(c: Char) = { + val chtp = Character.getType(c) + chtp == Character.MATH_SYMBOL.toInt || chtp == Character.OTHER_SYMBOL.toInt + } + + private final val otherLetters = Set[Char]('\u0024', '\u005F') // '$' and '_' + private final val letterGroups = { + import JCharacter._ + Set[Byte](LOWERCASE_LETTER, UPPERCASE_LETTER, OTHER_LETTER, TITLECASE_LETTER, LETTER_NUMBER) + } + def isScalaLetter(ch: Char) = letterGroups(JCharacter.getType(ch).toByte) || otherLetters(ch) + + /** Can character form part of a Scala operator name? */ + def isOperatorPart(c : Char) : Boolean = (c: @switch) match { + case '~' | '!' | '@' | '#' | '%' | + '^' | '*' | '+' | '-' | '<' | + '>' | '?' | ':' | '=' | '&' | + '|' | '/' | '\\' => true + case c => isSpecial(c) + } +} diff --git a/src/dotty/tools/dotc/core/Contexts.scala b/src/dotty/tools/dotc/core/Contexts.scala index 6bfc6233b..c66d4a07e 100644 --- a/src/dotty/tools/dotc/core/Contexts.scala +++ b/src/dotty/tools/dotc/core/Contexts.scala @@ -7,13 +7,17 @@ import Names._ import Phases._ import Types._ import Symbols._ -import TypeComparers._, Printers._ +import TypeComparers._, Printers._, NameOps._ import collection.mutable import collection.immutable.BitSet object Contexts { - abstract class Context extends Periods with Substituters with TypeOps with Cloneable { + abstract class Context extends Periods + with Substituters + with TypeOps + with Printers + with Cloneable { implicit val ctx: Context = this def base: ContextBase @@ -40,28 +44,18 @@ object Contexts { _typeComparer } - private[this] var _printer: Printer = _ - protected def printer_=(printer: Printer) = _printer = printer - def printer: Printer = _printer + private[this] var _printer: Context => Printer = _ + protected def printer_=(printer: Context => Printer) = _printer = printer + def printer: Context => Printer = _printer private[this] var _owner: Symbol = _ protected def owner_=(owner: Symbol) = _owner = owner def owner: Symbol = _owner - private[this] var _diagnostics: Option[StringBuilder] = _ - protected def diagnostics_=(diagnostics: Option[StringBuilder]) = _diagnostics = diagnostics - def diagnostics: Option[StringBuilder] = _diagnostics - - def diagnose(str: => String) = - for (sb <- diagnostics) { - sb.setLength(0) - sb.append(str) - } - - def phase: Phase = ??? // phase(period.phaseId) def enclClass: Context = ??? def erasedTypes: Boolean = ??? + def debug: Boolean = ??? // def settings: Settings = ??? def warning(msg: String) = ??? @@ -77,7 +71,7 @@ object Contexts { def withPeriod(period: Period): this.type = { this.period = period; this } def withPhase(pid: PhaseId): this.type = withPeriod(Period(runId, pid)) def withConstraints(constraints: Constraints): this.type = { this.constraints = constraints; this } - def withPrinter(printer: Printer): this.type = { this.printer = printer; this } + def withPrinter(printer: Context => Printer): this.type = { this.printer = printer; this } def withOwner(owner: Symbol): this.type = { this.owner = owner; this } def withDiagnostics(diagnostics: Option[StringBuilder]): this.type = { this.diagnostics = diagnostics; this } } @@ -86,7 +80,7 @@ object Contexts { underlying = NoContext period = Nowhere constraints = Map() - printer = new StdPrinter + printer = new StdPrinter()(_) owner = NoSymbol } @@ -95,12 +89,11 @@ object Contexts { } class ContextBase extends Transformers.TransformerBase - with Printers.PrinterBase { + with Printers.PrinterBase + with NameOps.NameOpsBase { val initialCtx: Context = new InitialContext(this) - val names: NameTable = new NameTable - lazy val definitions = new Definitions()(initialCtx) // Symbols state diff --git a/src/dotty/tools/dotc/core/Decorators.scala b/src/dotty/tools/dotc/core/Decorators.scala index d0ce3efe0..e3679266a 100644 --- a/src/dotty/tools/dotc/core/Decorators.scala +++ b/src/dotty/tools/dotc/core/Decorators.scala @@ -8,14 +8,11 @@ import Contexts._, Names._ object Decorators { - implicit class toTypeNameDecorator(val s: String) extends AnyVal { - def toTypeName(implicit context: Context): TypeName = - context.names.newTypeName(s) - } - - implicit class toTermNameDecorator(val s: String) extends AnyVal { - def toTermName(implicit context: Context): TermName = - context.names.newTermName(s) + implicit class StringDecorator(val s: String) extends AnyVal { + def toTypeName: TypeName = typeName(s) + def toTermName: TermName = termName(s) + def toEncodedTypeName = encodedTypeName(s) + def toEncodedTermName = encodedTermName(s) } implicit class SymbolIteratorDecorator(val it: Iterator[Symbol]) extends AnyVal { diff --git a/src/dotty/tools/dotc/core/Definitions.scala b/src/dotty/tools/dotc/core/Definitions.scala index 9bf1e88c3..7e83e48bb 100644 --- a/src/dotty/tools/dotc/core/Definitions.scala +++ b/src/dotty/tools/dotc/core/Definitions.scala @@ -21,6 +21,12 @@ class Definitions(implicit ctx: Context) { lazy val ArrayClass: ClassSymbol = ??? lazy val uncheckedStableClass: ClassSymbol = ??? + /** Modules whose members are in the default namespace */ + lazy val UnqualifiedModules: Set[Symbol] = ??? // List(PredefModule, ScalaPackage, JavaLangPackage) + + /** `UnqualifiedModules` and their module classes */ + lazy val UnqualifiedOwners = UnqualifiedModules ++ UnqualifiedModules.map(_.moduleClass) + def init() = if (!isInitialized) { // force initialization of every symbol that is synthesized or hijacked by the compiler diff --git a/src/dotty/tools/dotc/core/Denotations.scala b/src/dotty/tools/dotc/core/Denotations.scala index e3c73fdb3..f7935d675 100644 --- a/src/dotty/tools/dotc/core/Denotations.scala +++ b/src/dotty/tools/dotc/core/Denotations.scala @@ -354,7 +354,7 @@ object Denotations { current } - //final def asSymDenotation = asInstanceOf[SymDenotation] + final def asSymDenotation = asInstanceOf[SymDenotation] // ------ DenotationSet ops ---------------------------------------------- diff --git a/src/dotty/tools/dotc/core/NameOps.scala b/src/dotty/tools/dotc/core/NameOps.scala new file mode 100644 index 000000000..2bbfa1360 --- /dev/null +++ b/src/dotty/tools/dotc/core/NameOps.scala @@ -0,0 +1,275 @@ +package dotty.tools.dotc +package core + +import java.security.MessageDigest +import Chars.isOperatorPart +import scala.annotation.switch +import scala.io.Codec +import Names._, StdNames._, Contexts._, Symbols._ +import Decorators.StringDecorator + +object NameOps { + + trait NameOpsBase { this: ContextBase => + + final object compactify extends (String => String) { + val md5 = MessageDigest.getInstance("MD5") + + /** COMPACTIFY + * + * The hashed name has the form (prefix + marker + md5 + marker + suffix), where + * - prefix/suffix.length = MaxNameLength / 4 + * - md5.length = 32 + * + * We obtain the formula: + * + * FileNameLength = 2*(MaxNameLength / 4) + 2.marker.length + 32 + 6 + * + * (+6 for ".class"). MaxNameLength can therefore be computed as follows: + */ + val marker = "$$$$" + val limit: Int = ??? // !!! settings.maxClassfileName.value + val MaxNameLength = (limit - 6) min 2 * (limit - 6 - 2 * marker.length - 32) + + def toMD5(s: String, edge: Int): String = { + val prefix = s take edge + val suffix = s takeRight edge + + val cs = s.toArray + val bytes = Codec toUTF8 cs + md5 update bytes + val md5chars = (md5.digest() map (b => (b & 0xFF).toHexString)).mkString + + prefix + marker + md5chars + marker + suffix + } + def apply(s: String): String = + if (s.length <= MaxNameLength) s else toMD5(s, MaxNameLength / 4) + } + } + + private val Boxed = Map[TypeName, TypeName]( + tpnme.Boolean -> jtpnme.BoxedBoolean, + tpnme.Byte -> jtpnme.BoxedByte, + tpnme.Char -> jtpnme.BoxedCharacter, + tpnme.Short -> jtpnme.BoxedShort, + tpnme.Int -> jtpnme.BoxedInteger, + tpnme.Long -> jtpnme.BoxedLong, + tpnme.Float -> jtpnme.BoxedFloat, + tpnme.Double -> jtpnme.BoxedDouble) + + implicit class NameDecorator(val name: Name) extends AnyVal { + import nme._ + + def isConstructorName = name == CONSTRUCTOR || name == MIXIN_CONSTRUCTOR + def isExceptionResultName = name startsWith EXCEPTION_RESULT_PREFIX + def isImplClassName = name endsWith IMPL_CLASS_SUFFIX + def isLocalDummyName = name startsWith LOCALDUMMY_PREFIX + def isLoopHeaderLabel = (name startsWith WHILE_PREFIX) || (name startsWith DO_WHILE_PREFIX) + def isProtectedAccessorName = name startsWith PROTECTED_PREFIX + def isSuperAccessorName = name startsWith SUPER_PREFIX + def isReplWrapperName = name containsSlice INTERPRETER_IMPORT_WRAPPER + def isSetterName = name endsWith SETTER_SUFFIX + def isTraitSetterName = isSetterName && (name containsSlice TRAIT_SETTER_SEPARATOR) + def isSingletonName = name endsWith SINGLETON_SUFFIX + def isModuleName = name endsWith MODULE_SUFFIX + + def isModuleVarName(name: Name): Boolean = + name.stripAnonNumberSuffix endsWith MODULE_VAR_SUFFIX + + def isLocalName = name.isInstanceOf[LocalName] + + /** Is name a variable name? */ + def isVariableName: Boolean = { + val first = name.head + (((first.isLower && first.isLetter) || first == '_') + && (name != false_) + && (name != true_) + && (name != null_)) + } + + def isOpAssignmentName: Boolean = name match { + case raw.NE | raw.LE | raw.GE | EMPTY => + false + case _ => + name.last == '=' && name.head != '=' && isOperatorPart(name.head) + } + + /** If the name ends with $nn where nn are + * all digits, strip the $ and the digits. + * Otherwise return the argument. + */ + def stripAnonNumberSuffix: Name = { + var pos = name.length + while (pos > 0 && name(pos - 1).isDigit) + pos -= 1 + + if (pos <= 0 || pos == name.length || name(pos - 1) != '$') name + else name take (pos - 1) + } + + def stripModuleSuffix: Name = + if (isModuleName) name dropRight MODULE_SUFFIX.length else name + + /** Translate a name into a list of simple TypeNames and TermNames. + * In all segments before the last, type/term is determined by whether + * the following separator char is '.' or '#'. The last segment + * is of the same type as the original name. + * + * Examples: + * + * package foo { + * object Lorax { object Wog ; class Wog } + * class Lorax { object Zax ; class Zax } + * } + * + * f("foo.Lorax".toTermName) == List("foo": Term, "Lorax": Term) // object Lorax + * f("foo.Lorax".toTypeName) == List("foo": Term, "Lorax": Type) // class Lorax + * f("Lorax.Wog".toTermName) == List("Lorax": Term, "Wog": Term) // object Wog + * f("Lorax.Wog".toTypeName) == List("Lorax": Term, "Wog": Type) // class Wog + * f("Lorax#Zax".toTermName) == List("Lorax": Type, "Zax": Term) // object Zax + * f("Lorax#Zax".toTypeName) == List("Lorax": Type, "Zax": Type) // class Zax + * + * Note that in actual scala syntax you cannot refer to object Zax without an + * instance of Lorax, so Lorax#Zax could only mean the type. One might think + * that Lorax#Zax.type would work, but this is not accepted by the parser. + * For the purposes of referencing that object, the syntax is allowed. + */ + def segments: List[Name] = { + def mkName(name: Name, follow: Char): Name = + if (follow == '.') name.toTermName else name.toTypeName + + name.indexWhere(ch => ch == '.' || ch == '#') match { + case -1 => + if (name.isEmpty) scala.Nil else name :: scala.Nil + case idx => + mkName(name take idx, name(idx)) :: (name drop (idx + 1)).segments + } + } + + /** If name length exceeds allowable limit, replace part of it by hash */ + def compactified(implicit ctx: Context): TermName = termName(ctx.compactify(name.toString)) + } + + implicit class TypeNameDecorator(val name: TypeName) extends AnyVal { + def isUnboxedName = Boxed contains name + def boxedName: TypeName = Boxed(name) + } + + implicit class TermNameDecorator(val name: TermName) extends AnyVal { + import nme._ + + /** The expanded name of `name` relative to this class `base` with given `separator` + */ + def expandedName(base: Symbol, separator: Name = EXPAND_SEPARATOR)(implicit ctx: Context): TermName = + (base.fullName('$') ++ separator ++ name).toTermName + + /** The expanded setter name of `name` relative to this class `base` + */ + def expandedSetterName(base: Symbol)(implicit ctx: Context): TermName = + expandedName(base, separator = TRAIT_SETTER_SEPARATOR) + + def getterName: TermName = name match { + case name: LocalName => name.toGlobalName + case name => name + } + + def getterToSetter: TermName = name ++ SETTER_SUFFIX + + def setterToGetter: TermName = { + val p = name.indexOfSlice(TRAIT_SETTER_SEPARATOR) + if (p >= 0) + (name drop (p + TRAIT_SETTER_SEPARATOR.length)).asTermName.setterToGetter + else + name.take(name.length - SETTER_SUFFIX.length).asTermName + } + + /** Nominally, name$default$N, encoded for <init> */ + def defaultGetterName(pos: Int): TermName = { + val prefix = if (name.isConstructorName) DEFAULT_GETTER_INIT else name + prefix ++ DEFAULT_GETTER ++ pos.toString + } + + /** Nominally, name from name$default$N, CONSTRUCTOR for <init> */ + def defaultGetterToMethod: TermName = { + val p = name.indexOfSlice(DEFAULT_GETTER) + if (p >= 0) { + val q = name.take(p).asTermName + // i.e., if (q.decoded == CONSTRUCTOR.toString) CONSTRUCTOR else q + if (q == DEFAULT_GETTER_INIT) CONSTRUCTOR else q + } else name + } + + /** The name of a super-accessor */ + def superAccessorName: TermName = + SUPER_PREFIX ++ name + + /** The name of an accessor for protected symbols. */ + def protectedAccessorName: TermName = + PROTECTED_PREFIX ++ name + + /** The name of a setter for protected symbols. Used for inherited Java fields. */ + def protectedSetterName(name: Name): TermName = + PROTECTED_SET_PREFIX ++ name + + def moduleVarName: TermName = + name ++ MODULE_VAR_SUFFIX + + /** The name unary_x for a prefix operator x */ + def toUnaryName: TermName = name match { + case raw.MINUS => UNARY_- + case raw.PLUS => UNARY_+ + case raw.TILDE => UNARY_~ + case raw.BANG => UNARY_! + case _ => name + } + + /** The name of a method which stands in for a primitive operation + * during structural type dispatch. + */ + def primitiveInfixMethodName: TermName = name match { + case OR => takeOr + case XOR => takeXor + case AND => takeAnd + case EQ => testEqual + case NE => testNotEqual + case ADD => add + case SUB => subtract + case MUL => multiply + case DIV => divide + case MOD => takeModulo + case LSL => shiftSignedLeft + case LSR => shiftLogicalRight + case ASR => shiftSignedRight + case LT => testLessThan + case LE => testLessOrEqualThan + case GE => testGreaterOrEqualThan + case GT => testGreaterThan + case ZOR => takeConditionalOr + case ZAND => takeConditionalAnd + case _ => NO_NAME + } + + /** Postfix/prefix, really. + */ + def primitivePostfixMethodName: TermName = name match { + case UNARY_! => takeNot + case UNARY_+ => positive + case UNARY_- => negate + case UNARY_~ => complement + case `toByte` => toByte + case `toShort` => toShort + case `toChar` => toCharacter + case `toInt` => toInteger + case `toLong` => toLong + case `toFloat` => toFloat + case `toDouble` => toDouble + case _ => NO_NAME + } + + def primitiveMethodName: TermName = + primitiveInfixMethodName match { + case NO_NAME => primitivePostfixMethodName + case name => name + } + } +}
\ No newline at end of file diff --git a/src/dotty/tools/dotc/core/Names.scala b/src/dotty/tools/dotc/core/Names.scala index 30d80a938..abf902a1c 100644 --- a/src/dotty/tools/dotc/core/Names.scala +++ b/src/dotty/tools/dotc/core/Names.scala @@ -3,29 +3,35 @@ package core import scala.io.Codec import util.NameTransformer -import Periods._ import Decorators._ +import collection.IndexedSeqOptimized +import collection.generic.CanBuildFrom +import collection.mutable.{ Builder, StringBuilder } +import collection.immutable.WrappedString +import collection.generic.CanBuildFrom +//import annotation.volatile object Names { /** A name is essentially a string, with three differences * 1. Names belong in one of two universes: they are type names or term names. * The same string can correspond both to a type name and to a term name. - * 2. In each universe, names are hash-consed per basis. Two names - * representing the same string in the same basis are always reference identical. + * 2. NAmes are hash-consed. Two names + * representing the same string in the same universe are always reference identical. * 3. Names are intended to be encoded strings. @see dotc.util.NameTransformer. * The encoding will be applied when converting a string to a name. */ - abstract class Name extends DotClass { + abstract class Name extends DotClass + with Seq[Char] + with IndexedSeqOptimized[Char, Name] { - /** The basis in which this name is stored */ - val basis: NameTable + type ThisName <: Name /** The start index in the character array */ val start: Int /** The length of the names */ - val length: Int + override val length: Int /** Is this name a type name? */ def isTypeName: Boolean @@ -45,31 +51,15 @@ object Names { /** This name downcasted to a term name */ def asTermName: TermName - /** This name in the given basis */ - def in(basis: NameTable) = - if (this.basis eq basis) this - else newName(basis, this.basis.chrs, start, length) + /** This name converted to a local field name */ + def toLocalName: LocalName /** Create a new name of same kind as this one, in the given * basis, with `len` characters taken from `cs` starting at `offset`. */ - protected def newName(basis: NameTable, cs: Array[Char], offset: Int, len: Int): Name + def fromChars(cs: Array[Char], offset: Int, len: Int): ThisName - /** A dummy equals method to catch all comparisons of names - * to other entities (e.g. strings). - * One always should use the ==(Name) method instead. - */ - final override def equals(that: Any): Boolean = unsupported("equals") - - /** The only authorized == method on names */ - def == (that: Name): Boolean = ( - (this eq that) - || - (this.basis ne that.basis) && - (this == (that in this.basis)) - ) - - override def toString = new String(basis.chrs, start, length) + override def toString = new String(chrs, start, length) /** Write to UTF8 representation of this name to given character array. * Start copying to index `to`. Return index of next free byte in array. @@ -77,147 +67,270 @@ object Names { * (i.e. maximally 3*length bytes). */ final def copyUTF8(bs: Array[Byte], offset: Int): Int = { - val bytes = Codec.toUTF8(basis.chrs, start, length) + val bytes = Codec.toUTF8(chrs, start, length) scala.compat.Platform.arraycopy(bytes, 0, bs, offset, bytes.length) offset + bytes.length } /** Convert to string replacing operator symbols by corresponding \$op_name. */ def decode: String = NameTransformer.decode(toString) + + def ++ (other: Name): ThisName = ++ (other.toString) + + def ++ (other: String): ThisName = { + val s = toString + other + fromChars(s.toCharArray, 0, s.length) + } + + // ----- Collections integration ------------------------------------- + + override protected[this] def thisCollection: WrappedString = new WrappedString(repr.toString) + override protected[this] def toCollection(repr: Name): WrappedString = new WrappedString(repr.toString) + + override protected[this] def newBuilder: Builder[Char, Name] = unsupported("newBuilder") + + override def apply(index: Int): Char = chrs(start + index) + + override def slice(from: Int, until: Int): ThisName = + fromChars(chrs, start + from, start + until) + + override def seq = toCollection(this) } - class TermName(val basis: NameTable, val start: Int, val length: Int, val next: TermName) extends Name { + class TermName(val start: Int, val length: Int, private[Names] var next: TermName) extends Name { + type ThisName = TermName def isTypeName = false def isTermName = true - lazy val toTypeName: TypeName = new TypeName(basis, start, length, this) + + @volatile private[this] var _typeName: TypeName = null + + def toTypeName: TypeName = { + if (_typeName == null) + synchronized { + if (_typeName == null) + _typeName = new TypeName(start, length, this) + } + _typeName + } def toTermName = this - def asTypeName = throw new ClassCastException(this+" is not a type name") + def asTypeName = throw new ClassCastException(this + " is not a type name") def asTermName = this - protected def newName(basis: NameTable, cs: Array[Char], offset: Int, len: Int): Name = - basis.newTermName(cs, offset, len) + def toLocalName: LocalName = toTypeName.toLocalName + + override protected[this] def newBuilder: Builder[Char, Name] = termNameBuilder + + def fromChars(cs: Array[Char], offset: Int, len: Int): TermName = termName(cs, offset, len) } - class TypeName(val basis: NameTable, val start: Int, val length: Int, val toTermName: TermName) extends Name { + class TypeName(val start: Int, val length: Int, initialTermName: TermName) extends Name { + type ThisName = TypeName def isTypeName = true def isTermName = false def toTypeName = this def asTypeName = this - def asTermName = throw new ClassCastException(this+" is not a term name") + def asTermName = throw new ClassCastException(this + " is not a term name") + + private[this] var _termName = initialTermName + + def toTermName: TermName = _termName match { + case tn: LocalName => + synchronized { tn.toGlobalName } + case tn => + tn + } + + def toLocalName: LocalName = _termName match { + case tn: LocalName => + tn + case _ => + synchronized { + val lname = new LocalName(start, length, _termName) + _termName = lname + lname + } + } - protected def newName(basis: NameTable, cs: Array[Char], offset: Int, len: Int): Name = - basis.newTypeName(cs, offset, len) + override protected[this] def newBuilder: Builder[Char, Name] = typeNameBuilder + + def fromChars(cs: Array[Char], offset: Int, len: Int): TypeName = typeName(cs, offset, len) } - class NameTable { + /* A local name representing a field that has otherwise the same name as + * a normal term name. Used to avoid name clashes between fields and methods. + * Local names are linked to their corresponding trem anmes and type names. + * + * The encoding is as follows. + * + * If there are only a term name and type name: + * + * TermName + * | ^ + * _typeName | | _termName + * v | + * TypeName + * + * If there is also a local name: + * + * TermName + * | ^ + * | +--------------+ _termNme + * | | + * _typeName | LocalName + * | ^ + * | +--------------+ _termName + * v | + * TypeName + */ + class LocalName(start: Int, length: Int, _next: TermName) extends TermName(start, length, _next) { + def toGlobalName: TermName = next + } - private final val HASH_SIZE = 0x8000 - private final val HASH_MASK = 0x7FFF - private final val NAME_SIZE = 0x20000 - final val nameDebug = false + // Nametable - /** Memory to store all names sequentially. */ - private[Names] var chrs: Array[Char] = new Array[Char](NAME_SIZE) - private var nc = 0 + private final val InitialHashSize = 0x8000 + private final val InitialNameSize = 0x20000 + private final val fillFactor = 0.7 - /** Hashtable for finding term names quickly. */ - private val table = new Array[Names.TermName](HASH_SIZE) + /** Memory to store all names sequentially. */ + private var chrs: Array[Char] = new Array[Char](InitialNameSize) - /** The hashcode of a name. */ - private def hashValue(cs: Array[Char], offset: Int, len: Int): Int = - if (len > 0) - (len * (41 * 41 * 41) + - cs(offset) * (41 * 41) + - cs(offset + len - 1) * 41 + - cs(offset + (len >> 1))) - else 0 + /** The number of characters filled. */ + private var nc = 0 - /** - * Is (the ASCII representation of) name at given index equal to - * cs[offset..offset+len-1]? - */ - private def equals(index: Int, cs: Array[Char], offset: Int, len: Int): Boolean = { - var i = 0 - while ((i < len) && (chrs(index + i) == cs(offset + i))) - i += 1; - i == len + /** Hashtable for finding term names quickly. */ + private var table = new Array[TermName](InitialHashSize) + + /** The number of defined names. */ + private var size = 1 + + /** Make sure the capacity of the character array is at least `n` */ + private def ensureCapacity(n: Int) = + if (n > chrs.length) { + val newchrs = new Array[Char](chrs.length * 2) + chrs.copyToArray(newchrs) + chrs = newchrs } - /** Enter characters into chrs array. */ - private def enterChars(cs: Array[Char], offset: Int, len: Int) { - var i = 0 - while (i < len) { - if (nc + i == chrs.length) { - val newchrs = new Array[Char](chrs.length * 2) - scala.compat.Platform.arraycopy(chrs, 0, newchrs, 0, chrs.length) - chrs = newchrs - } - chrs(nc + i) = cs(offset + i) - i += 1 - } - if (len == 0) nc += 1 - else nc = nc + len + /** Make sure the hash table is large enough for the given load factor */ + private def incTableSize() = { + size += 1 + if (size.toDouble / table.size > fillFactor) { + val oldTable = table + table = new Array[TermName](table.size * 2) + for (i <- 0 until oldTable.size) rehash(oldTable(i)) } + } - /** - * Create a term name from the characters in cs[offset..offset+len-1]. - * Assume they are already encoded. - */ - def newTermName(cs: Array[Char], offset: Int, len: Int): TermName = /* sync if parallel */ { - val h = hashValue(cs, offset, len) & HASH_MASK + /** Rehash chain of names */ + private def rehash(name: TermName): Unit = + if (name != null) { + rehash(name.next) + val h = hashValue(chrs, name.start, name.length) & (table.size - 1) + name.next = table(h) + table(h) = name + } + + /** The hash of a name made of from characters cs[offset..offset+len-1]. */ + private def hashValue(cs: Array[Char], offset: Int, len: Int): Int = + if (len > 0) + (len * (41 * 41 * 41) + + cs(offset) * (41 * 41) + + cs(offset + len - 1) * 41 + + cs(offset + (len >> 1))) + else 0 + + /** Is (the ASCII representation of) name at given index equal to + * cs[offset..offset+len-1]? + */ + private def equals(index: Int, cs: Array[Char], offset: Int, len: Int): Boolean = { + var i = 0 + while ((i < len) && (chrs(index + i) == cs(offset + i))) + i += 1; + i == len + } + + /** Enter characters into chrs array. */ + private def enterChars(cs: Array[Char], offset: Int, len: Int) { + ensureCapacity(nc + len) + var i = 0 + while (i < len) { + chrs(nc + i) = cs(offset + i) + i += 1 + } + nc += len + } + + /** Create a term name from the characters in cs[offset..offset+len-1]. + * Assume they are already encoded. + */ + def termName(cs: Array[Char], offset: Int, len: Int): TermName = { + val h = hashValue(cs, offset, len) & (table.size - 1) + synchronized { val next = table(h) var name = next - while ((name ne null) && (name.length != len || !equals(name.start, cs, offset, len))) + while (name ne null) { + if (name.length == len && equals(name.start, cs, offset, len)) + return name name = name.next - - if (name eq null) /* needs sync if parallel */ { - name = new TermName(this, nc, len, next) - enterChars(cs, offset, len) - table(h) = name - name } - + name = new TermName(nc, len, next) + enterChars(cs, offset, len) + table(h) = name + incTableSize() name } + } - /** - * Create a type name from the characters in cs[offset..offset+len-1]. - * Assume they are already encoded. - */ - def newTypeName(cs: Array[Char], offset: Int, len: Int): TypeName = - newTermName(cs, offset, len).toTypeName + /** Create a type name from the characters in cs[offset..offset+len-1]. + * Assume they are already encoded. + */ + def typeName(cs: Array[Char], offset: Int, len: Int): TypeName = + termName(cs, offset, len).toTypeName - /** - * Create a term name from the UTF8 encoded bytes in bs[offset..offset+len-1]. - * Assume they are already encoded. - */ - def newTermName(bs: Array[Byte], offset: Int, len: Int): TermName = { - val chars = Codec.fromUTF8(bs, offset, len) - newTermName(chars, 0, chars.length) - } + /** Create a term name from the UTF8 encoded bytes in bs[offset..offset+len-1]. + * Assume they are already encoded. + */ + def termName(bs: Array[Byte], offset: Int, len: Int): TermName = { + val chars = Codec.fromUTF8(bs, offset, len) + termName(chars, 0, chars.length) + } - /** - * Create a type name from the UTF8 encoded bytes in bs[offset..offset+len-1]. - * Assume they are already encoded. - */ - def newTypeName(bs: Array[Byte], offset: Int, len: Int): TypeName = - newTermName(bs, offset, len).toTypeName + /** Create a type name from the UTF8 encoded bytes in bs[offset..offset+len-1]. + * Assume they are already encoded. + */ + def typeName(bs: Array[Byte], offset: Int, len: Int): TypeName = + termName(bs, offset, len).toTypeName - /** Create a term name from a string, encode if necessary*/ - def newTermName(s: String): TermName = { - val es = NameTransformer.encode(s) - newTermName(es.toCharArray, 0, es.length) - } + /** Create a term name from a string, wihtout encoding operators */ + def termName(s: String): TermName = termName(s.toCharArray, 0, s.length) - /** Create a type name from a string, encode if necessary */ - def newTypeName(s: String): TypeName = { - val es = NameTransformer.encode(s) - newTypeName(es.toCharArray, 0, es.length) - } - } + /** Create a term name from a string, encode if necessary*/ + def encodedTermName(s: String): TermName = termName(NameTransformer.encode(s)) + + /** Create a type name from a string, wihtout encoding operators */ + def typeName(s: String): TypeName = typeName(s.toCharArray, 0, s.length) + + /** Create a type name from a string, encode if necessary*/ + def encodedTypeName(s: String): TypeName = typeName(NameTransformer.encode(s)) + + /** The term name represented by the empoty string */ + val EmptyTermName = new TermName(-1, 0, null) - object BootNameTable extends NameTable + table(0) = EmptyTermName - val EmptyTypeName = BootNameTable.newTypeName("") - val EmptyTermName = BootNameTable.newTermName("") -}
\ No newline at end of file + /** The type name represented by the empoty string */ + val EmptyTypeName = EmptyTermName.toTypeName + + val termNameBuilder: Builder[Char, TermName] = + StringBuilder.newBuilder.mapResult(termName) + + val typeNameBuilder: Builder[Char, TypeName] = + StringBuilder.newBuilder.mapResult(typeName) + + implicit val nameCanBuildFrom: CanBuildFrom[Name, Char, Name] = new CanBuildFrom[Name, Char, Name] { + def apply(from: Name): Builder[Char, Name] = + StringBuilder.newBuilder.mapResult(s => from.fromChars(s.toCharArray, 0, s.length)) + def apply(): Builder[Char, Name] = termNameBuilder + } +} diff --git a/src/dotty/tools/dotc/core/Printers.scala b/src/dotty/tools/dotc/core/Printers.scala index d7476c433..354790e97 100644 --- a/src/dotty/tools/dotc/core/Printers.scala +++ b/src/dotty/tools/dotc/core/Printers.scala @@ -3,9 +3,16 @@ package core import Types._, Symbols._, Contexts._, Scopes._ -trait Printers { +trait Printers { this: Context => + + def show(tp: Type): String = printer(this).show(tp) + def show(sym: Symbol): String = printer(this).show(sym) + def showLocated(sym: Symbol): String = printer(this).showLocated(sym) + def showDef(sym: Symbol): String = printer(this).showDef(sym) + def show(sc: Scope): String = printer(this).show(sc) + + private var _diagnostics: Option[StringBuilder] = _ - private[this] var _diagnostics: Option[StringBuilder] = _ protected def diagnostics_=(diagnostics: Option[StringBuilder]) = _diagnostics = diagnostics def diagnostics: Option[StringBuilder] = _diagnostics @@ -20,27 +27,20 @@ trait Printers { object Printers { trait PrinterBase { self: ContextBase => - private[core] var showRecursions = 0 - } abstract class Printer { - def show(tp: Type)(implicit ctx: Context): String - def show(sym: Symbol)(implicit ctx: Context): String - def showLocated(sym: Symbol)(implicit ctx: Context): String - def showDef(sym: Symbol)(implicit ctx: Context): String - def show(sc: Scope)(implicit ctx: Context): String - } - - object StdPrinter { - final val maxShowRecursions = 50 + def show(tp: Type): String + def show(sym: Symbol): String + def showLocated(sym: Symbol): String + def showDef(sym: Symbol): String + def show(sc: Scope): String } - class StdPrinter extends Printer { - import StdPrinter._ + class StdPrinter(implicit ctx: Context) extends Printer { - def controlled(op: => String)(implicit ctx: Context): String = + def controlled(op: => String): String = if (ctx.showRecursions < maxShowRecursions) try { ctx.showRecursions += 1 @@ -49,14 +49,14 @@ object Printers { ctx.showRecursions -= 1 } else { - if (???/*ctx.settings.debug.value*/) { + if (ctx.debug) { ctx.warning("Exceeded recursion depth attempting to print type.") (new Throwable).printStackTrace } "..." } - def show(tp: Type)(implicit ctx: Context): String = controlled { + def show(tp: Type): String = controlled { tp match { case TermRef(pre, name) => ??? // showPrefix(pre) + show(name) @@ -65,15 +65,45 @@ object Printers { } } - def show(sym: Symbol)(implicit ctx: Context): String = controlled { + + protected def objectPrefix = "object " + protected def packagePrefix = "package " + + protected def trimPrefix(str: String) = + str.stripPrefix(objectPrefix).stripPrefix(packagePrefix) + + protected def isOmittablePrefix(sym: Symbol) = + (defn.UnqualifiedOwners contains sym) || isEmptyPrefix(sym) + + protected def isEmptyPrefix(sym: Symbol) = + sym.isEffectiveRoot || sym.isAnonymousClass || ??? // nme.isReplWrapperName(sym.name) + + + def showPrefix(tp: Type): String = controlled { + tp match { + case ThisType(cls) => + if (ctx.debug) showName(cls) + ".this." + else if (cls.isAnonymousClass) "this." + else ??? + case NoPrefix => + "" + case _ => + trimPrefix(show(tp)) + "#" + + } + } + + def show(sym: Symbol): String = controlled { + ??? } - def showLocated(sym: Symbol)(implicit ctx: Context): String = ??? - def showDef(sym: Symbol)(implicit ctx: Context): String = ??? - def show(sc: Scope)(implicit ctx: Context): String = + def showName(sym: Symbol): String = ??? + def showLocated(sym: Symbol): String = ??? + def showDef(sym: Symbol): String = ??? + def show(sc: Scope): String = sc.toList.map(_.showDef).mkString("Scope{\n ", ";\n ", "\n}") } - + final val maxShowRecursions = 50 }
\ No newline at end of file diff --git a/src/dotty/tools/dotc/core/StdNames.scala b/src/dotty/tools/dotc/core/StdNames.scala new file mode 100644 index 000000000..0866caaeb --- /dev/null +++ b/src/dotty/tools/dotc/core/StdNames.scala @@ -0,0 +1,728 @@ +package dotty.tools.dotc +package core + +import scala.language.implicitConversions +import scala.collection.{mutable, immutable} +import scala.annotation.switch +import Names._ +import Symbols._ +import Contexts._ +import Decorators.StringDecorator +import util.NameTransformer + +object StdNames { + +/** Base strings from which synthetic names are derived. */ + + abstract class DefinedNames[N <: Name] { + protected implicit def fromString(s: String): N + + private val kws = mutable.Set[N]() + protected def kw(name: N) = { kws += name; name } + + final val keywords: collection.Set[N] = kws + } + + abstract class ScalaNames[N <: Name] extends DefinedNames[N] { + private def encode(s: String): N = fromString(NameTransformer.encode(s)) + +// Keywords, need to come first ----------------------- + + final val ABSTRACTkw: N = kw("abstract") + final val CASEkw: N = kw("case") + final val CLASSkw: N = kw("class") + final val CATCHkw: N = kw("catch") + final val DEFkw: N = kw("def") + final val DOkw: N = kw("do") + final val ELSEkw: N = kw("else") + final val EXTENDSkw: N = kw("extends") + final val FALSEkw: N = kw("false") + final val FINALkw: N = kw("final") + final val FINALLYkw: N = kw("finally") + final val FORkw: N = kw("for") + final val FORSOMEkw: N = kw("forSome") + final val IFkw: N = kw("if") + final val IMPLICITkw: N = kw("implicit") + final val IMPORTkw: N = kw("import") + final val LAZYkw: N = kw("lazy") + final val MACROkw: N = kw("macro") + final val MATCHkw: N = kw("match") + final val NEWkw: N = kw("new") + final val NULLkw: N = kw("null") + final val OBJECTkw: N = kw("object") + final val OVERRIDEkw: N = kw("override") + final val PACKAGEkw: N = kw("package") + final val PRIVATEkw: N = kw("private") + final val PROTECTEDkw: N = kw("protected") + final val RETURNkw: N = kw("return") + final val SEALEDkw: N = kw("sealed") + final val SUPERkw: N = kw("super") + final val THENkw: N = kw("then") + final val THISkw: N = kw("this") + final val THROWkw: N = kw("throw") + final val TRAITkw: N = kw("trait") + final val TRUEkw: N = kw("true") + final val TRYkw: N = kw("try") + final val TYPEkw: N = kw("type") + final val VALkw: N = kw("val") + final val VARkw: N = kw("var") + final val WITHkw: N = kw("with") + final val WHILEkw: N = kw("while") + final val YIELDkw: N = kw("yield") + final val DOTkw: N = kw(".") + final val USCOREkw: N = kw("_") + final val COLONkw: N = kw(":") + final val EQUALSkw: N = kw("=") + final val ARROWkw: N = kw("=>") + final val LARROWkw: N = kw("<-") + final val SUBTYPEkw: N = kw("<:") + final val VIEWBOUNDkw: N = kw("<%") + final val SUPERTYPEkw: N = kw(">:") + final val HASHkw: N = kw("#") + final val ATkw: N = kw("@") + + val ANON_CLASS_NAME: N = "$anon" + val ANON_FUN_NAME: N = "$anonfun" + val BITMAP_PREFIX: N = "bitmap$" + val BITMAP_NORMAL: N = BITMAP_PREFIX // initialization bitmap for public/protected lazy vals + val BITMAP_TRANSIENT: N = BITMAP_PREFIX + "trans$" // initialization bitmap for transient lazy vals + val BITMAP_CHECKINIT: N = BITMAP_PREFIX + "init$" // initialization bitmap for checkinit values + val BITMAP_CHECKINIT_TRANSIENT: N = BITMAP_PREFIX + "inittrans$" // initialization bitmap for transient checkinit values + val DEFAULT_GETTER: N = "$default$" + val DEFAULT_GETTER_INIT: N = encode("<init>") + val DO_WHILE_PREFIX: N = "doWhile$" + val EMPTY: N = "" + val EMPTY_PACKAGE: N = "<empty>" + val EVIDENCE_PARAM_PREFIX: N = "evidence$" + val EXCEPTION_RESULT_PREFIX: N = "exceptionResult" + val EXPAND_SEPARATOR: N = "$$" + val IMPL_CLASS_SUFFIX: N = "$class" + val IMPORT: N = "<import>" + val INTERPRETER_IMPORT_WRAPPER: N = "$iw" + val INTERPRETER_LINE_PREFIX: N = "line" + val INTERPRETER_VAR_PREFIX: N = "res" + val INTERPRETER_WRAPPER_SUFFIX: N = "$object" + val LOCALDUMMY_PREFIX: N = "<local " // owner of local blocks + val MODULE_SUFFIX: N = NameTransformer.MODULE_SUFFIX_STRING + val MODULE_VAR_SUFFIX: N = "$module" + val NAME_JOIN: N = NameTransformer.NAME_JOIN_STRING + val PACKAGE: N = "package" + val PROTECTED_PREFIX: N = "protected$" + val PROTECTED_SET_PREFIX: N = PROTECTED_PREFIX + "set" + val ROOT: N = "<root>" + val SINGLETON_SUFFIX: N = ".type" + val SPECIALIZED_SUFFIX: N = "$sp" + val SUPER_PREFIX: N = "super$" + val TRAIT_SETTER_SEPARATOR: N = "$_setter_$" + val WHILE_PREFIX: N = "while$" + + // value types (and AnyRef) are all used as terms as well + // as (at least) arguments to the @specialize annotation. + final val Boolean: N = "Boolean" + final val Byte: N = "Byte" + final val Char: N = "Char" + final val Double: N = "Double" + final val Float: N = "Float" + final val Int: N = "Int" + final val Long: N = "Long" + final val Short: N = "Short" + final val Unit: N = "Unit" + + final val ScalaValueNames: scala.List[N] = + scala.List(Byte, Char, Short, Int, Long, Float, Double, Boolean, Unit) + + // some types whose companions we utilize + final val AnyRef: N = "AnyRef" + final val Array: N = "Array" + final val List: N = "List" + final val Seq: N = "Seq" + final val Symbol: N = "Symbol" + final val ClassTag: N = "ClassTag" + final val WeakTypeTag: N = "WeakTypeTag" + final val TypeTag : N = "TypeTag" + final val Expr: N = "Expr" + final val String: N = "String" + final val Annotation: N = "Annotation" + + // fictions we use as both types and terms + final val ERROR: N = "<error>" + final val NO_NAME: N = "<none>" // formerly NOSYMBOL + final val WILDCARD: N = "_" + +// ----- Type names ----------------------------------------- + + final val BYNAME_PARAM_CLASS: N = "<byname>" + final val EQUALS_PATTERN: N = "<equals>" + final val JAVA_REPEATED_PARAM_CLASS: N = "<repeated...>" + final val LOCAL_CHILD: N = "<local child>" + final val REPEATED_PARAM_CLASS: N = "<repeated>" + final val WILDCARD_STAR: N = "_*" + final val REIFY_TREECREATOR_PREFIX: N = "$treecreator" + final val REIFY_TYPECREATOR_PREFIX: N = "$typecreator" + + final val Any: N = "Any" + final val AnyVal: N = "AnyVal" + final val ExprApi: N = "ExprApi" + final val Mirror: N = "Mirror" + final val Nothing: N = "Nothing" + final val Null: N = "Null" + final val Object: N = "Object" + final val PartialFunction: N = "PartialFunction" + final val PrefixType: N = "PrefixType" + final val Product: N = "Product" + final val Serializable: N = "Serializable" + final val Singleton: N = "Singleton" + final val Throwable: N = "Throwable" + + final val ClassfileAnnotation: N = "ClassfileAnnotation" + final val ClassManifest: N = "ClassManifest" + final val Enum: N = "Enum" + final val Group: N = "Group" + final val Tree: N = "Tree" + final val Type : N = "Type" + final val TypeTree: N = "TypeTree" + + // Annotation simple names, used in Namer + final val BeanPropertyAnnot: N = "BeanProperty" + final val BooleanBeanPropertyAnnot: N = "BooleanBeanProperty" + final val bridgeAnnot: N = "bridge" + + // Classfile Attributes + final val AnnotationDefaultATTR: N = "AnnotationDefault" + final val BridgeATTR: N = "Bridge" + final val ClassfileAnnotationATTR: N = "RuntimeInvisibleAnnotations" // RetentionPolicy.CLASS. Currently not used (Apr 2009). + final val CodeATTR: N = "Code" + final val ConstantValueATTR: N = "ConstantValue" + final val DeprecatedATTR: N = "Deprecated" + final val ExceptionsATTR: N = "Exceptions" + final val InnerClassesATTR: N = "InnerClasses" + final val LineNumberTableATTR: N = "LineNumberTable" + final val LocalVariableTableATTR: N = "LocalVariableTable" + final val RuntimeAnnotationATTR: N = "RuntimeVisibleAnnotations" // RetentionPolicy.RUNTIME + final val RuntimeParamAnnotationATTR: N = "RuntimeVisibleParameterAnnotations" // RetentionPolicy.RUNTIME (annotations on parameters) + final val ScalaATTR: N = "Scala" + final val ScalaSignatureATTR: N = "ScalaSig" + final val SignatureATTR: N = "Signature" + final val SourceFileATTR: N = "SourceFile" + final val SyntheticATTR: N = "Synthetic" + +// ----- Term names ----------------------------------------- + + // Compiler-internal + val ANYname: N = "<anyname>" + val CONSTRUCTOR: N = "<init>" + val EQEQ_LOCAL_VAR: N = "eqEqTemp$" + val FAKE_LOCAL_THIS: N = "this$" + val INITIALIZER: N = CONSTRUCTOR // Is this buying us something? + val LAZY_LOCAL: N = "$lzy" + val LAZY_SLOW_SUFFIX: N = "$lzycompute" + val LOCAL_SUFFIX: N = " " + val UNIVERSE_BUILD_PREFIX: N = "$u.build." + val UNIVERSE_BUILD: N = "$u.build" + val UNIVERSE_PREFIX: N = "$u." + val UNIVERSE_SHORT: N = "$u" + val MIRROR_PREFIX: N = "$m." + val MIRROR_SHORT: N = "$m" + val MIRROR_UNTYPED: N = "$m$untyped" + val REIFY_FREE_PREFIX: N = "free$" + val REIFY_FREE_THIS_SUFFIX: N = "$this" + val REIFY_FREE_VALUE_SUFFIX: N = "$value" + val REIFY_SYMDEF_PREFIX: N = "symdef$" + val MIXIN_CONSTRUCTOR: N = "$init$" + val MODULE_INSTANCE_FIELD: N = NameTransformer.MODULE_INSTANCE_NAME // "MODULE$" + val OUTER: N = "$outer" + val OUTER_LOCAL: N = "$outer " + val OUTER_SYNTH: N = "<outer>" // emitted by virtual pattern matcher, replaced by outer accessor in explicitouter + val ROOTPKG: N = "_root_" + val SELECTOR_DUMMY: N = "<unapply-selector>" + val SELF: N = "$this" + val SETTER_SUFFIX: N = encode("_=") + val SPECIALIZED_INSTANCE: N = "specInstance$" + val STAR: N = "*" + val THIS: N = "_$this" + + final val Nil: N = "Nil" + final val Predef: N = "Predef" + final val ScalaRunTime: N = "ScalaRunTime" + final val Some: N = "Some" + + val x_0 : N = "x$0" + val x_1 : N = "x$1" + val x_2 : N = "x$2" + val x_3 : N = "x$3" + val x_4 : N = "x$4" + val x_5 : N = "x$5" + val x_6 : N = "x$6" + val x_7 : N = "x$7" + val x_8 : N = "x$8" + val x_9 : N = "x$9" + + val ??? = encode("???") + + val wrapRefArray: N = "wrapRefArray" + val wrapByteArray: N = "wrapByteArray" + val wrapShortArray: N = "wrapShortArray" + val wrapCharArray: N = "wrapCharArray" + val wrapIntArray: N = "wrapIntArray" + val wrapLongArray: N = "wrapLongArray" + val wrapFloatArray: N = "wrapFloatArray" + val wrapDoubleArray: N = "wrapDoubleArray" + val wrapBooleanArray: N = "wrapBooleanArray" + val wrapUnitArray: N = "wrapUnitArray" + val genericWrapArray: N = "genericWrapArray" + + // Compiler utilized names + + val AnnotatedType: N = "AnnotatedType" + val AppliedTypeTree: N = "AppliedTypeTree" + val Apply: N = "Apply" + val ArrayAnnotArg: N = "ArrayAnnotArg" + val Constant: N = "Constant" + val ConstantType: N = "ConstantType" + val EmptyPackage: N = "EmptyPackage" + val EmptyPackageClass: N = "EmptyPackageClass" + val ExistentialTypeTree: N = "ExistentialTypeTree" + val Flag : N = "Flag" + val Ident: N = "Ident" + val Import: N = "Import" + val Literal: N = "Literal" + val LiteralAnnotArg: N = "LiteralAnnotArg" + val Modifiers: N = "Modifiers" + val NestedAnnotArg: N = "NestedAnnotArg" + val NoFlags: N = "NoFlags" + val NoPrefix: N = "NoPrefix" + val NoSymbol: N = "NoSymbol" + val NoType: N = "NoType" + val RootPackage: N = "RootPackage" + val RootClass: N = "RootClass" + val Select: N = "Select" + val StringContext: N = "StringContext" + val This: N = "This" + val ThisType: N = "ThisType" + val Tuple2: N = "Tuple2" + val TYPE_ : N = "TYPE" + val TypeApply: N = "TypeApply" + val TypeRef: N = "TypeRef" + val UNIT : N = "UNIT" + val add_ : N = "add" + val annotation: N = "annotation" + val anyValClass: N = "anyValClass" + val append: N = "append" + val apply: N = "apply" + val applyDynamic: N = "applyDynamic" + val applyDynamicNamed: N = "applyDynamicNamed" + val applyOrElse: N = "applyOrElse" + val args : N = "args" + val argv : N = "argv" + val arrayClass: N = "arrayClass" + val arrayElementClass: N = "arrayElementClass" + val arrayValue: N = "arrayValue" + val array_apply : N = "array_apply" + val array_clone : N = "array_clone" + val array_length : N = "array_length" + val array_update : N = "array_update" + val arraycopy: N = "arraycopy" + val asTerm: N = "asTerm" + val asModule: N = "asModule" + val asMethod: N = "asMethod" + val asType: N = "asType" + val asClass: N = "asClass" + val asInstanceOf_ : N = "asInstanceOf" + val asInstanceOf_Ob : N = "$asInstanceOf" + val assert_ : N = "assert" + val assume_ : N = "assume" + val box: N = "box" + val build : N = "build" + val bytes: N = "bytes" + val canEqual_ : N = "canEqual" + val checkInitialized: N = "checkInitialized" + val ClassManifestFactory: N = "ClassManifestFactory" + val classOf: N = "classOf" + val clone_ : N = "clone" + val conforms: N = "conforms" + val copy: N = "copy" + val currentMirror: N = "currentMirror" + val definitions: N = "definitions" + val delayedInit: N = "delayedInit" + val delayedInitArg: N = "delayedInit$body" + val drop: N = "drop" + val elem: N = "elem" + val emptyValDef: N = "emptyValDef" + val ensureAccessible : N = "ensureAccessible" + val eq: N = "eq" + val equalsNumChar : N = "equalsNumChar" + val equalsNumNum : N = "equalsNumNum" + val equalsNumObject : N = "equalsNumObject" + val equals_ : N = "equals" + val error: N = "error" + val eval: N = "eval" + val ex: N = "ex" + val experimental: N = "experimental" + val f: N = "f" + val false_ : N = "false" + val filter: N = "filter" + val finalize_ : N = "finalize" + val find_ : N = "find" + val flagsFromBits : N = "flagsFromBits" + val flatMap: N = "flatMap" + val foreach: N = "foreach" + val genericArrayOps: N = "genericArrayOps" + val get: N = "get" + val getOrElse: N = "getOrElse" + val hasNext: N = "hasNext" + val hashCode_ : N = "hashCode" + val hash_ : N = "hash" + val head: N = "head" + val identity: N = "identity" + val implicitly: N = "implicitly" + val in: N = "in" + val info: N = "info" + val inlinedEquals: N = "inlinedEquals" + val isArray: N = "isArray" + val isDefinedAt: N = "isDefinedAt" + val isEmpty: N = "isEmpty" + val isInstanceOf_ : N = "isInstanceOf" + val isInstanceOf_Ob : N = "$isInstanceOf" + val java: N = "java" + val key: N = "key" + val lang: N = "lang" + val length: N = "length" + val lengthCompare: N = "lengthCompare" + val liftedTree: N = "liftedTree" + val `macro` : N = "macro" + val macroThis : N = "_this" + val macroContext : N = "c" + val main: N = "main" + val manifest: N = "manifest" + val ManifestFactory: N = "ManifestFactory" + val manifestToTypeTag: N = "manifestToTypeTag" + val map: N = "map" + val materializeClassTag: N = "materializeClassTag" + val materializeWeakTypeTag: N = "materializeWeakTypeTag" + val materializeTypeTag: N = "materializeTypeTag" + val mirror : N = "mirror" + val moduleClass : N = "moduleClass" + val name: N = "name" + val ne: N = "ne" + val newArray: N = "newArray" + val newFreeTerm: N = "newFreeTerm" + val newFreeType: N = "newFreeType" + val newNestedSymbol: N = "newNestedSymbol" + val newScopeWith: N = "newScopeWith" + val next: N = "next" + val nmeNewTermName: N = "newTermName" + val nmeNewTypeName: N = "newTypeName" + val normalize: N = "normalize" + val notifyAll_ : N = "notifyAll" + val notify_ : N = "notify" + val null_ : N = "null" + val ofDim: N = "ofDim" + val origin: N = "origin" + val prefix : N = "prefix" + val productArity: N = "productArity" + val productElement: N = "productElement" + val productIterator: N = "productIterator" + val productPrefix: N = "productPrefix" + val readResolve: N = "readResolve" + val reflect : N = "reflect" + val reify : N = "reify" + val rootMirror : N = "rootMirror" + val runOrElse: N = "runOrElse" + val runtime: N = "runtime" + val runtimeClass: N = "runtimeClass" + val runtimeMirror: N = "runtimeMirror" + val sameElements: N = "sameElements" + val scala_ : N = "scala" + val selectDynamic: N = "selectDynamic" + val selectOverloadedMethod: N = "selectOverloadedMethod" + val selectTerm: N = "selectTerm" + val selectType: N = "selectType" + val self: N = "self" + val setAccessible: N = "setAccessible" + val setAnnotations: N = "setAnnotations" + val setSymbol: N = "setSymbol" + val setType: N = "setType" + val setTypeSignature: N = "setTypeSignature" + val splice: N = "splice" + val staticClass : N = "staticClass" + val staticModule : N = "staticModule" + val staticPackage : N = "staticPackage" + val synchronized_ : N = "synchronized" + val tail: N = "tail" + val `then` : N = "then" + val this_ : N = "this" + val thisPrefix : N = "thisPrefix" + val throw_ : N = "throw" + val toArray: N = "toArray" + val toList: N = "toList" + val toObjectArray : N = "toObjectArray" + val toSeq: N = "toSeq" + val toString_ : N = "toString" + val toTypeConstructor: N = "toTypeConstructor" + val tpe : N = "tpe" + val tree : N = "tree" + val true_ : N = "true" + val typedProductIterator: N = "typedProductIterator" + val typeTagToManifest: N = "typeTagToManifest" + val unapply: N = "unapply" + val unapplySeq: N = "unapplySeq" + val unbox: N = "unbox" + val universe: N = "universe" + val update: N = "update" + val updateDynamic: N = "updateDynamic" + val value: N = "value" + val valueOf : N = "valueOf" + val values : N = "values" + val view_ : N = "view" + val wait_ : N = "wait" + val withFilter: N = "withFilter" + val wrap: N = "wrap" + val zip: N = "zip" + + val synthSwitch: N = "$synthSwitch" + + // unencoded operators + object raw { + final val AMP : N = "&" + final val BANG : N = "!" + final val BAR : N = "|" + final val DOLLAR: N = "$" + final val GE: N = ">=" + final val LE: N = "<=" + final val MINUS: N = "-" + final val NE: N = "!=" + final val PLUS : N = "+" + final val SLASH: N = "/" + final val STAR : N = "*" + final val TILDE: N = "~" + + final val isUnary: Set[Name] = Set(MINUS, PLUS, TILDE, BANG) + } + + // value-conversion methods + val toByte: N = "toByte" + val toShort: N = "toShort" + val toChar: N = "toChar" + val toInt: N = "toInt" + val toLong: N = "toLong" + val toFloat: N = "toFloat" + val toDouble: N = "toDouble" + + // primitive operation methods for structural types mostly + // overlap with the above, but not for these two. + val toCharacter: N = "toCharacter" + val toInteger: N = "toInteger" + + def newLazyValSlowComputeName(lzyValName: N) = lzyValName ++ LAZY_SLOW_SUFFIX + + // ASCII names for operators + val ADD = encode("+") + val AND = encode("&") + val ASR = encode(">>") + val DIV = encode("/") + val EQ = encode("==") + val EQL = encode("=") + val GE = encode(">=") + val GT = encode(">") + val HASHHASH = encode("##") + val LE = encode("<=") + val LSL = encode("<<") + val LSR = encode(">>>") + val LT = encode("<") + val MINUS = encode("-") + val MOD = encode("%") + val MUL = encode("*") + val NE = encode("!=") + val OR = encode("|") + val PLUS = ADD // technically redundant, but ADD looks funny with MINUS + val SUB = MINUS // ... as does SUB with PLUS + val XOR = encode("^") + val ZAND = encode("&&") + val ZOR = encode("||") + + // unary operators + val UNARY_~ = encode("unary_~") + val UNARY_+ = encode("unary_+") + val UNARY_- = encode("unary_-") + val UNARY_! = encode("unary_!") + + // Grouped here so Cleanup knows what tests to perform. + val CommonOpNames = Set[Name](OR, XOR, AND, EQ, NE) + val ConversionNames = Set[Name](toByte, toChar, toDouble, toFloat, toInt, toLong, toShort) + val BooleanOpNames = Set[Name](ZOR, ZAND, UNARY_!) ++ CommonOpNames + val NumberOpNames = ( + Set[Name](ADD, SUB, MUL, DIV, MOD, LSL, LSR, ASR, LT, LE, GE, GT) + ++ Set(UNARY_+, UNARY_-, UNARY_!) + ++ ConversionNames + ++ CommonOpNames + ) + + val add: N = "add" + val complement: N = "complement" + val divide: N = "divide" + val multiply: N = "multiply" + val negate: N = "negate" + val positive: N = "positive" + val shiftLogicalRight: N = "shiftLogicalRight" + val shiftSignedLeft: N = "shiftSignedLeft" + val shiftSignedRight: N = "shiftSignedRight" + val subtract: N = "subtract" + val takeAnd: N = "takeAnd" + val takeConditionalAnd: N = "takeConditionalAnd" + val takeConditionalOr: N = "takeConditionalOr" + val takeModulo: N = "takeModulo" + val takeNot: N = "takeNot" + val takeOr: N = "takeOr" + val takeXor: N = "takeXor" + val testEqual: N = "testEqual" + val testGreaterOrEqualThan: N = "testGreaterOrEqualThan" + val testGreaterThan: N = "testGreaterThan" + val testLessOrEqualThan: N = "testLessOrEqualThan" + val testLessThan: N = "testLessThan" + val testNotEqual: N = "testNotEqual" + + val isBoxedNumberOrBoolean: N = "isBoxedNumberOrBoolean" + val isBoxedNumber: N = "isBoxedNumber" + + val reflPolyCacheName: N = "reflPoly$Cache" + val reflClassCacheName: N = "reflClass$Cache" + val reflParamsCacheName: N = "reflParams$Cache" + val reflMethodCacheName: N = "reflMethod$Cache" + val reflMethodName: N = "reflMethod$Method" + + private val reflectionCacheNames = Set[N]( + reflPolyCacheName, + reflClassCacheName, + reflParamsCacheName, + reflMethodCacheName, + reflMethodName + ) + + def isReflectionCacheName(name: Name) = reflectionCacheNames exists (name startsWith _) + } + + class ScalaTermNames extends ScalaNames[TermName] { + protected def fromString(s: String) = termName(s) + + @switch def syntheticParamName(i: Int): TermName = i match { + case 0 => x_0 + case 1 => x_1 + case 2 => x_2 + case 3 => x_3 + case 4 => x_4 + case 5 => x_5 + case 6 => x_6 + case 7 => x_7 + case 8 => x_8 + case 9 => x_9 + case _ => termName("x$" + i) + } + + def localDummyName(clazz: Symbol)(implicit ctx: Context): TermName = + LOCALDUMMY_PREFIX ++ clazz.name ++ ">" + + def newBitmapName(bitmapPrefix: TermName, n: Int): TermName = bitmapPrefix ++ n.toString + + } + + class ScalaTypeNames extends ScalaNames[TypeName] { + protected def fromString(s: String) = typeName(s) + } + + abstract class JavaNames[N <: Name] extends DefinedNames[N] { + final val ABSTRACTkw: N = kw("abstract") + final val ASSERTkw: N = kw("assert") + final val BOOLEANkw: N = kw("boolean") + final val BREAKkw: N = kw("break") + final val BYTEkw: N = kw("byte") + final val CASEkw: N = kw("case") + final val CATCHkw: N = kw("catch") + final val CHARkw: N = kw("char") + final val CLASSkw: N = kw("class") + final val CONSTkw: N = kw("const") + final val CONTINUEkw: N = kw("continue") + final val DEFAULTkw: N = kw("default") + final val DOkw: N = kw("do") + final val DOUBLEkw: N = kw("double") + final val ELSEkw: N = kw("else") + final val ENUMkw: N = kw("enum") + final val EXTENDSkw: N = kw("extends") + final val FINALkw: N = kw("final") + final val FINALLYkw: N = kw("finally") + final val FLOATkw: N = kw("float") + final val FORkw: N = kw("for") + final val IFkw: N = kw("if") + final val GOTOkw: N = kw("goto") + final val IMPLEMENTSkw: N = kw("implements") + final val IMPORTkw: N = kw("import") + final val INSTANCEOFkw: N = kw("instanceof") + final val INTkw: N = kw("int") + final val INTERFACEkw: N = kw("interface") + final val LONGkw: N = kw("long") + final val NATIVEkw: N = kw("native") + final val NEWkw: N = kw("new") + final val PACKAGEkw: N = kw("package") + final val PRIVATEkw: N = kw("private") + final val PROTECTEDkw: N = kw("protected") + final val PUBLICkw: N = kw("public") + final val RETURNkw: N = kw("return") + final val SHORTkw: N = kw("short") + final val STATICkw: N = kw("static") + final val STRICTFPkw: N = kw("strictfp") + final val SUPERkw: N = kw("super") + final val SWITCHkw: N = kw("switch") + final val SYNCHRONIZEDkw: N = kw("synchronized") + final val THISkw: N = kw("this") + final val THROWkw: N = kw("throw") + final val THROWSkw: N = kw("throws") + final val TRANSIENTkw: N = kw("transient") + final val TRYkw: N = kw("try") + final val VOIDkw: N = kw("void") + final val VOLATILEkw: N = kw("volatile") + final val WHILEkw: N = kw("while") + + final val BoxedBoolean: N = "java.lang.Boolean" + final val BoxedByte: N = "java.lang.Byte" + final val BoxedCharacter: N = "java.lang.Character" + final val BoxedDouble: N = "java.lang.Double" + final val BoxedFloat: N = "java.lang.Float" + final val BoxedInteger: N = "java.lang.Integer" + final val BoxedLong: N = "java.lang.Long" + final val BoxedNumber: N = "java.lang.Number" + final val BoxedShort: N = "java.lang.Short" + final val Class: N = "java.lang.Class" + final val IOOBException: N = "java.lang.IndexOutOfBoundsException" + final val InvTargetException: N = "java.lang.reflect.InvocationTargetException" + final val MethodAsObject: N = "java.lang.reflect.Method" + final val NPException: N = "java.lang.NullPointerException" + final val Object: N = "java.lang.Object" + final val String: N = "java.lang.String" + final val Throwable: N = "java.lang.Throwable" + + final val ForName: N = "forName" + final val GetCause: N = "getCause" + final val GetClass: N = "getClass" + final val GetClassLoader: N = "getClassLoader" + final val GetComponentType: N = "getComponentType" + final val GetMethod: N = "getMethod" + final val Invoke: N = "invoke" + final val JavaLang: N = "java.lang" + + final val BeanProperty: N = "scala.beans.BeanProperty" + final val BooleanBeanProperty: N = "scala.beans.BooleanBeanProperty" + final val JavaSerializable: N = "java.io.Serializable" + } + + class JavaTermNames extends JavaNames[TermName] { + protected def fromString(s: String): TermName = termName(s) + } + class JavaTypeNames extends JavaNames[TypeName] { + protected def fromString(s: String): TypeName = typeName(s) + } + + val nme = new ScalaTermNames + val tpnme = new ScalaTypeNames + val jnme = new JavaTermNames + val jtpnme = new JavaTypeNames + +} diff --git a/src/dotty/tools/dotc/core/SymDenotations.scala b/src/dotty/tools/dotc/core/SymDenotations.scala index 0748cf42d..f10097359 100644 --- a/src/dotty/tools/dotc/core/SymDenotations.scala +++ b/src/dotty/tools/dotc/core/SymDenotations.scala @@ -2,7 +2,7 @@ package dotty.tools.dotc package core import Periods._, Contexts._, Symbols._, Denotations._, Names._, Annotations._ -import Types._, Flags._, Decorators._, Transformers._ +import Types._, Flags._, Decorators._, Transformers._, StdNames._ import Scopes.Scope import collection.mutable import collection.immutable.BitSet @@ -123,6 +123,9 @@ object SymDenotations { final def effectiveOwner(implicit ctx: Context) = owner.skipPackageObject + def enclosingClass(implicit ctx: Context): Symbol = + if (isClass) symbol else owner.enclosingClass + final def topLevelClass(implicit ctx: Context): Symbol = if (!(owner.isPackageClass)) owner.topLevelClass else if (isClass) symbol @@ -131,6 +134,10 @@ object SymDenotations { final def enclosingPackage(implicit ctx: Context): Symbol = if (isPackageClass) symbol else owner.enclosingPackage + def fullName(separator: Char)(implicit ctx: Context): Name = + if (this == NoSymbol || owner == NoSymbol || owner.isEffectiveRoot) name + else (effectiveOwner.enclosingClass.fullName(separator) :+ separator) ++ name + def associatedFile(implicit ctx: Context): AbstractFile = topLevelClass.associatedFile final def binaryFile(implicit ctx: Context): AbstractFile = binaryFileOnly(associatedFile) final def sourceFile(implicit ctx: Context): AbstractFile = sourceFileOnly(associatedFile) @@ -288,7 +295,13 @@ object SymDenotations { else if (this is Contravariant) -1 else 0 - def isRoot: Boolean = !owner.exists // !!! && name == tpnme.Root + def isRoot: Boolean = name.toTermName == nme.ROOT && !owner.exists + + def isEmptyPackage(implicit ctx: Context): Boolean = name.toTermName == nme.EMPTY_PACKAGE && owner.isRoot + + def isEffectiveRoot(implicit ctx: Context) = isRoot || isEmptyPackage + + def isAnonymousClass(implicit ctx: Context): Boolean = ??? // initial.asSymDenotation.name startsWith tpnme.AnonClass def copy( sym: Symbol, @@ -604,10 +617,22 @@ object SymDenotations { val ownNames = decls.iterator map (_.name) val candidates = inheritedNames ++ ownNames val names = candidates filter (keepOnly(thisType, _)) - memberNamesCache += (keepOnly -> names) + memberNamesCache = memberNamesCache.updated(keepOnly, names) names } + private[this] var fullNameCache: Map[Char, Name] = Map() + + override final def fullName(separator: Char)(implicit ctx: Context): Name = + fullNameCache get separator match { + case Some(fn) => + fn + case _ => + val fn = super.fullName(separator) + fullNameCache = fullNameCache.updated(separator, fn) + fn + } + def copyClass( sym: ClassSymbol, owner: Symbol = this.owner, @@ -654,7 +679,7 @@ object SymDenotations { object NoDenotation extends SymDenotation(Flags.Empty) with isComplete { override def symbol: Symbol = NoSymbol override def owner: Symbol = throw new AssertionError("NoDenotation.owner") - override def name: Name = BootNameTable.newTermName("<none>") + override def name: Name = "<none>".toTermName override def info: Type = NoType } diff --git a/src/dotty/tools/dotc/core/Symbols.scala b/src/dotty/tools/dotc/core/Symbols.scala index 127e36f4d..77b834102 100644 --- a/src/dotty/tools/dotc/core/Symbols.scala +++ b/src/dotty/tools/dotc/core/Symbols.scala @@ -22,7 +22,7 @@ object Symbols { */ abstract class Symbol(denotf: Symbol => SymDenotation) extends DotClass { - type Name <: Names.Name + type ThisName <: Name /** Is symbol different from NoSymbol? */ def exists = true @@ -73,7 +73,7 @@ object Symbols { final def owner(implicit ctx: Context): Symbol = denot.owner /** The current name of this symbol */ - final def name(implicit ctx: Context): Name = denot.name.asInstanceOf[Name] + final def name(implicit ctx: Context): ThisName = denot.name.asInstanceOf[ThisName] /** The current type info of this symbol */ final def info(implicit ctx: Context): Type = denot.info @@ -103,6 +103,9 @@ object Symbols { */ def skipPackageObject(implicit ctx: Context): Symbol = if (this is PackageObject) owner else this + /** The class containing this symbol */ + def enclosingClass(implicit ctx: Context): Symbol = denot.enclosingClass + /** The top-level class containing this symbol, except for a toplevel module * its module class */ @@ -111,6 +114,13 @@ object Symbols { /** The package containing this symbol */ def enclosingPackage(implicit ctx: Context): Symbol = denot.enclosingPackage + /** 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. + * Drops package objects. + */ + final def fullName(separator: Char)(implicit ctx: Context): Name = denot.fullName(separator) + /** The source or class file from which this symbol was generated, null if not applicable. */ final def associatedFile(implicit ctx: Context): AbstractFile = denot.associatedFile @@ -199,9 +209,9 @@ object Symbols { */ final def isAccessibleFrom(pre: Type, superAccess: Boolean = false)(implicit ctx: Context): Boolean = denot.isAccessibleFrom(pre, superAccess) - def show(implicit ctx: Context): String = ctx.printer.show(this) - def showLocated(implicit ctx: Context): String = ctx.printer.showLocated(this) - def showDef(implicit ctx: Context): String = ctx.printer.showDef(this) + def show(implicit ctx: Context): String = ctx.show(this) + def showLocated(implicit ctx: Context): String = ctx.showLocated(this) + def showDef(implicit ctx: Context): String = ctx.showDef(this) /** The type parameters of a class symbol, Nil for all other symbols */ def typeParams(implicit ctx: Context): List[TypeSymbol] = denot.typeParams @@ -212,6 +222,15 @@ object Symbols { /** Is this symbol the root class or its companion object? */ def isRoot(implicit ctx: Context): Boolean = denot.isRoot + /** Is this symbol the empty package class or its companion object? */ + def isEmptyPackage(implicit ctx: Context): Boolean = denot.isEmptyPackage + + /** Is this symbol an anonymous class? */ + def isAnonymousClass(implicit ctx: Context): Boolean = denot.isAnonymousClass + + /** Is this symbol the root class, empty package class, or one of their companion objects? */ + def isEffectiveRoot(implicit ctx: Context): Boolean = denot.isEffectiveRoot + /** If this is a module symbol, the class defining its template, otherwise NoSymbol. */ def moduleClass(implicit ctx: Context): Symbol = denot.moduleClass @@ -244,14 +263,14 @@ object Symbols { } class TermSymbol(denotf: Symbol => SymDenotation) extends Symbol(denotf) { - type Name = TermName + type ThisName = TermName override def isTerm = true override def copy(implicit ctx: Context): TermSymbol = copy(owner) override def copy(owner: Symbol)(implicit ctx: Context): TermSymbol = new TermSymbol(denot.copy(_, owner)) } class TypeSymbol(denotf: Symbol => SymDenotation) extends Symbol(denotf) { - type Name = TypeName + type ThisName = TypeName override def isType = true override def copy(implicit ctx: Context): TypeSymbol = copy(owner) override def copy(owner: Symbol)(implicit ctx: Context): TypeSymbol = new TypeSymbol(denot.copy(_, owner)) diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala index dfa09a4c5..28f254172 100644 --- a/src/dotty/tools/dotc/core/Types.scala +++ b/src/dotty/tools/dotc/core/Types.scala @@ -431,7 +431,7 @@ object Types { def |(that: Type)(implicit ctx: Context): Type = ctx.lub(this, that) - def show(implicit ctx: Context): String = ctx.printer.show(this) + def show(implicit ctx: Context): String = ctx.show(this) // ----- hashing ------------------------------------------------------ |