package dotty.tools
package dotc
package core
import Periods._
import Transformers._
import Names._, Scopes._
import Flags._
import java.lang.AssertionError
import Decorators._
import Symbols._
import Contexts._
import SymDenotations._
import Types._, Annotations._
import Denotations.{ Denotation, SingleDenotation, MultiDenotation }
import collection.mutable
import io.AbstractFile
trait Symbols { this: Context =>
def newLazySymbol[N <: Name](owner: Symbol, name: N, initFlags: FlagSet, completer: SymCompleter) =
new Symbol(new LazySymDenotation(_, owner, name, initFlags, completer)) {
type ThisName = N
}
def newLazyClassSymbol(owner: Symbol, name: TypeName, initFlags: FlagSet, completer: ClassCompleter, assocFile: AbstractFile = null) =
new ClassSymbol(new LazyClassDenotation(_, owner, name, initFlags, completer, assocFile)(this))
def newLazyModuleSymbols(owner: Symbol,
name: TermName,
flags: FlagSet,
completer: ClassCompleter,
assocFile: AbstractFile = null)
= {
val module = newLazySymbol(
owner, name, flags | ModuleCreationFlags, new ModuleCompleter(condensed))
val modcls = newLazyClassSymbol(
owner, name.toTypeName, flags | ModuleClassCreationFlags, completer, assocFile)
module.denot.asInstanceOf[LazySymDenotation].info =
TypeRef(owner.thisType(ctx), modcls)
modcls.denot.asInstanceOf[LazyClassDenotation].selfType =
TermRef(owner.thisType, module)
(module, modcls)
}
def newLazyPackageSymbols(owner: Symbol, name: TermName, completer: ClassCompleter) =
newLazyModuleSymbols(owner, name, PackageCreationFlags, completer)
def newSymbol[N <: Name](owner: Symbol, name: N, flags: FlagSet, info: Type, privateWithin: Symbol = NoSymbol) =
new Symbol(new CompleteSymDenotation(_, owner, name, flags, privateWithin, info)) {
type ThisName = N
}
def newClassSymbol(
owner: Symbol,
name: TypeName,
flags: FlagSet,
parents: List[TypeRef],
privateWithin: Symbol = NoSymbol,
optSelfType: Type = NoType,
decls: Scope = newScope,
assocFile: AbstractFile = null)
=
new ClassSymbol(new CompleteClassDenotation(
_, owner, name, flags, privateWithin, parents, optSelfType, decls, assocFile)(this))
def newModuleSymbols(
owner: Symbol,
name: TermName,
flags: FlagSet,
classFlags: FlagSet,
parents: List[TypeRef],
privateWithin: Symbol = NoSymbol,
decls: Scope = newScope,
assocFile: AbstractFile = null)(implicit ctx: Context)
= {
val module = newLazySymbol(owner, name, flags | ModuleCreationFlags, new ModuleCompleter(condensed))
val modcls = newClassSymbol(
owner, name.toTypeName, classFlags | ModuleClassCreationFlags, parents, privateWithin,
optSelfType = TermRef(owner.thisType, module),
decls, assocFile)
module.denot.asInstanceOf[LazySymDenotation].info =
TypeRef(owner.thisType, modcls)
(module, modcls)
}
def newPackageSymbols(
owner: Symbol,
name: TermName,
decls: Scope = newScope)(implicit ctx: Context) =
newModuleSymbols(
owner, name, PackageCreationFlags, PackageCreationFlags, Nil, NoSymbol, decls)
def newStubSymbol(owner: Symbol, name: Name)(implicit ctx: Context): Symbol = {
def stub[Denot <: SymDenotation] = new StubCompleter[Denot](ctx.condensed)
name match {
case name: TermName => ctx.newLazySymbol(owner, name, EmptyFlags, stub)
case name: TypeName => ctx.newLazyClassSymbol(owner, name, EmptyFlags, stub)
}
}
}
object Symbols {
/** A Symbol represents a Scala definition/declaration or a package.
*/
class Symbol(denotf: Symbol => SymDenotation) extends DotClass {
type ThisName <: Name
/** Is symbol different from NoSymbol? */
def exists = true
/** This symbol, if it exists, otherwise the result of evaluating `that` */
def orElse(that: => Symbol) = if (exists) this else that
def filter(p: Symbol => Boolean): Symbol = if (p(this)) this else NoSymbol
/** The last denotation of this symbol */
private[this] var lastDenot: SymDenotation = denotf(this)
/** The current denotation of this symbol */
final def denot(implicit ctx: Context): SymDenotation = {
var denot = lastDenot
if (!(denot.validFor contains ctx.period)) denot = denot.current.asInstanceOf[SymDenotation]
denot
}
private[this] var _id: Int = _
/** The unique id of this symbol */
def id(implicit ctx: Context) = {
if (_id == 0) _id = ctx.nextId
_id
}
/** Subclass tests and casts */
final def isTerm: Boolean = isInstanceOf[TermSymbol]
final def isType: Boolean = isInstanceOf[TypeSymbol]
final def isClass: Boolean = isInstanceOf[ClassSymbol]
final def asTerm: TermSymbol = asInstanceOf[TermSymbol]
final def asType: TypeSymbol = asInstanceOf[TypeSymbol]
final def asClass: ClassSymbol = asInstanceOf[ClassSymbol]
/** A unique, densely packed integer tag for each class symbol, -1
* for all other symbols. To save memory, this method
* should be called only if class is a super class of some other class.
*/
def superId: Int = -1
final def entered(implicit ctx: Context): this.type = {
owner.info.decls.enter(this)
this
}
/** Is symbol a primitive value class? */
def isPrimitiveValueClass(implicit ctx: Context) = defn.ScalaValueClasses contains this
/** Is symbol a phantom class for which no runtime representation exists? */
def isPhantomClass(implicit ctx: Context) = defn.PhantomClasses contains this
// --------- Forwarders for sym methods --------------------------
/** Special case tests for flags that are known a-priori and do not need loading
* flags.
*/
def isModule(implicit ctx: Context) = denot.isModule
def isModuleObj(implicit ctx: Context) = denot.isModuleVal
def isModuleClass(implicit ctx: Context) = denot.isModuleClass
def isPackage(implicit ctx: Context) = denot.isPackage
def isPackageObj(implicit ctx: Context) = denot.isPackageVal
def isPackageClass(implicit ctx: Context) = denot.isPackageClass
/** The current owner of this symbol */
final def owner(implicit ctx: Context): Symbol = denot.owner
/** The current name of this symbol */
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
/** The current flag set of this symbol */
final def flags(implicit ctx: Context): FlagSet = denot.flags
/** The current privateWithin boundary of this symbol, NoSymbol if no boundary is given. */
final def privateWithin(implicit ctx: Context): Symbol = denot.privateWithin
/** The current annotations of this symbol */
final def annotations(implicit ctx: Context): List[Annotation] = denot.annotations
/** The name with which this symbol was created */
def originalName(implicit ctx: Context) = denot.originalName
/** Set given flags(s) of this symbol */
def setFlag(flags: FlagSet)(implicit ctx: Context): Unit = denot.setFlag(flags)
/** Unset given flag(s) of this symbol */
def resetFlag(flags: FlagSet)(implicit ctx: Context): Unit = denot.resetFlag(flags)
/** Does this symbol have an annotation matching the given class symbol? */
final def hasAnnotation(cls: Symbol)(implicit ctx: Context): Boolean = denot.hasAnnotation(cls)
/** Add given annotation to this symbol */
final def addAnnotation(annot: Annotation)(implicit ctx: Context): Unit = denot.addAnnotation(annot)
/** Record that this symbol is an alias of given `alias` symbol */
final def setAlias(alias: Symbol)(implicit ctx: Context): Unit = denot.setAlias(alias)
/** The chain of owners of this symbol, starting with the symbol itself */
final def ownersIterator(implicit ctx: Context): Iterator[Symbol] = denot.ownersIterator
/** Same as `ownersIterator contains sym` but more efficient. */
final def hasTransOwner(sym: Symbol)(implicit ctx: Context): Boolean = denot.hasTransOwner(sym)
/** The owner, skipping package objects. */
def effectiveOwner(implicit ctx: Context) = denot.effectiveOwner
/** If this is a package object or its implementing class, its owner: otherwise this.
*/
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
*/
def topLevelClass(implicit ctx: Context): Symbol = denot.topLevelClass
/** 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)
final def fullName(implicit ctx: Context): Name = fullName('.')
/** The source or class file from which this symbol was generated, null if not applicable. */
final def associatedFile(implicit ctx: Context): AbstractFile = denot.associatedFile
/** The class file from which this symbol was generated, null if not applicable. */
final def binaryFile(implicit ctx: Context): AbstractFile = denot.binaryFile
/** The source or class file from which this symbol was generated, null if not applicable. */
final def sourceFile(implicit ctx: Context): AbstractFile = denot.sourceFile
/** Is this symbol defined in the same compilation unit as that symbol? */
final def isCoDefinedWith(that: Symbol)(implicit ctx: Context): Boolean = denot.isCoDefinedWith(that)
/** The class with the same (type-) name as this module or module class,
* which is the defined in the same compilation unit.
* NoSymbol if this class does not exist.
*/
final def companionClass(implicit ctx: Context): Symbol = denot.companionClass
/** The module object with the same (term-) name as this class or module class,
* which is the defined in the same compilation unit.
* NoSymbol if this class does not exist.
*/
final def companionModule(implicit ctx: Context): Symbol = denot.companionModule
/** If this is a class, the module class of its companion object.
* If this is a module class, its companion class.
* NoSymbol otherwise.
*/
final def linkedClass(implicit ctx: Context): Symbol = denot.linkedClass
/** Is this symbol a subclass of the given class? */
final def isSubClass(cls: Symbol)(implicit ctx: Context): Boolean = denot.isSubClass(cls)
/** Is this class symbol a subclass of `cls`,
* and is this class symbol also different from Null or Nothing?
*/
final def isNonBottomSubClass(cls: Symbol)(implicit ctx: Context): Boolean = denot.isNonBottomSubClass(cls)
/** Is this symbol a subclass of `base` or a companion object of such a subclass? */
final def isSubClassOrCompanion(base: Symbol)(implicit ctx: Context): Boolean = denot.isSubClassOrCompanion(base)
/** The class that encloses the owner of the current context
* and that is a subclass of this class.
*/
final def enclosingSubClass(implicit ctx: Context) = denot.enclosingSubClass
///** Is this symbol a proper subclass of the given class? */
//def isProperSubClass(cls: ClassSymbol)(implicit ctx: Context): Boolean = (this ne cls) && this.isSubClass(cls)
/** The non-private symbol whose type matches the type of this symbol
* in in given class.
*
* @param inClass The class containing the symbol's definition
* @param site The base type from which member types are computed
*/
final def matchingSymbol(inClass: Symbol, site: Type)(implicit ctx: Context): Symbol = denot.matchingSymbol(inClass, site)
/** The symbol, in class `inClass`, that is overridden by this symbol. */
final def overriddenSymbol(inClass: ClassSymbol)(implicit ctx: Context): Symbol = denot.overriddenSymbol(inClass)
/** All symbols overriden by this symbol. */
final def allOverriddenSymbols(implicit ctx: Context): Iterator[Symbol] = denot.allOverriddenSymbols
/** The class or term symbol up to which this symbol is accessible,
* or RootClass if it is public. As java protected statics are
* otherwise completely inaccessible in scala, they are treated
* as public.
* @param base
*/
final def accessBoundary(base: Symbol)(implicit ctx: Context): Symbol = denot.accessBoundary(base)
/** Is this symbol contained in `boundary`? */
final def isContainedIn(boundary: Symbol)(implicit ctx: Context): Boolean = denot.isContainedIn(boundary)
/** Is this symbol accessible whenever `that` symbol is accessible?
* Does not take into account status of protected members.
*/
final def isAsAccessibleAs(that: Symbol)(implicit ctx: Context): Boolean = denot.isAsAccessibleAs(that)
/** Is this symbol a non-value class? */
final def isNonValueClass(implicit ctx: Context): Boolean = denot.isNonValueClass
/** Is this symbol accessible as a member of tree with type `pre`?
* @param pre The type of the tree from which the selection is made
* @param superAccess Access is via super
*/
final def isAccessibleFrom(pre: Type, superAccess: Boolean = false)(implicit ctx: Context): Boolean = denot.isAccessibleFrom(pre, superAccess)
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)
def showKind(implicit tcx: Context): String = ???
def showName(implicit ctx: Context): String = ???
/** The type parameters of a class symbol, Nil for all other symbols */
def typeParams(implicit ctx: Context): List[TypeSymbol] = denot.typeParams
/** The type This(cls), where cls is this class symbol */
def thisType(implicit ctx: Context): Type = denot.thisType
/** 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
/** Can a term with this symbol be a stable value? */
def isStable(implicit ctx: Context): Boolean = denot.isStable
/** Is this symbol static (i.e. with no outer instance)? */
def isStatic(implicit ctx: Context): Boolean = denot.isStatic
/** Does this symbol denote a class that defines static symbols? */
final def isStaticOwner(implicit ctx: Context): Boolean = denot.isStaticOwner
// def isOverridable: Boolean = !!! need to enforce that classes cannot be redefined
// def isSkolem: Boolean = ???
// def isAbstractType: Boolean = ???
// def newAbstractType(name: TypeName, info: TypeBounds): TypeSymbol = ???
// def newAbstractTerm(name: TermName, tpe: Type): TypeSymbol = ???
//def isMethod(implicit ctx: Context): Boolean = denot.isMethod
/** The type representing the type constructor for this type symbol */
def typeConstructor(implicit ctx: Context): TypeRef = denot.typeConstructor
/** The variance of this type parameter as an Int, with
* +1 = Covariant, -1 = Contravariant, 0 = Nonvariant
*/
def variance(implicit ctx: Context): Int = denot.variance
}
type TermSymbol = Symbol { type ThisName = TermName }
type TypeSymbol = Symbol { type ThisName = TypeName }
class ClassSymbol(denotf: ClassSymbol => ClassDenotation) extends Symbol(s => denotf(s.asClass)) {
type ThisName = TypeName
private var superIdHint: Int = -1
final def classDenot(implicit ctx: Context): ClassDenotation =
denot.asInstanceOf[ClassDenotation]
def selfType(implicit ctx: Context): Type = classDenot.selfType
/** The base classes of this class in linearization order,
* with the class itself as first element.x
*/
def baseClasses(implicit ctx: Context): List[ClassSymbol] = classDenot.baseClasses
/** The parent types of this class */
def parents(implicit ctx: Context): List[TypeRef] = classDenot.parents
/** The symbols defined directly in this class */
def decls(implicit ctx: Context): Scope = classDenot.decls
// override def typeTemplate(implicit ctx: Context): Type = classDenot.typeTemplate
def superId(implicit ctx: Context): Int = {
val hint = superIdHint
if (hint >= 0 && hint <= ctx.lastSuperId && (ctx.classOfId(hint) eq this)) hint
else {
val id = ctx.superIdOfClass get this match {
case Some(id) =>
id
case None =>
val id = ctx.nextSuperId
ctx.superIdOfClass(this) = id
ctx.classOfId(id) = this
id
}
superIdHint = id
id
}
}
}
class ErrorSymbol(val underlying: Symbol, msg: => String)(implicit ctx: Context) extends Symbol(sym => underlying.denot) {
type ThisName = underlying.ThisName
}
object NoSymbol extends Symbol(sym => NoDenotation) {
override def exists = false
}
implicit class Copier[N <: Name](sym: Symbol { type ThisName = N })(implicit ctx: Context) {
/** Copy a symbol, overriding selective fields */
def copy(
owner: Symbol = sym.owner,
name: N = sym.name,
flags: FlagSet = sym.flags,
privateWithin: Symbol = sym.privateWithin,
info: Type = sym.info): Symbol =
if (sym.isClass) {
assert(info eq sym.info)
val pw = privateWithin
new ClassCopier(sym.asClass).copy(owner, name.asTypeName, flags, privateWithin = pw)
} else
ctx.newSymbol(owner, name, flags, info, privateWithin)
}
implicit class ClassCopier(cls: ClassSymbol)(implicit ctx: Context) {
/** Copy a class symbol, overriding selective fields */
def copy(
owner: Symbol = cls.owner,
name: TypeName = cls.name.asTypeName,
flags: FlagSet = cls.flags,
parents: List[TypeRef] = cls.classDenot.parents,
privateWithin: Symbol = cls.privateWithin,
selfType: Type = cls.selfType,
decls: Scope = cls.decls,
associatedFile: AbstractFile = cls.associatedFile) =
ctx.newClassSymbol(owner, name, flags, parents, privateWithin, selfType, decls, associatedFile)
}
implicit def defn(implicit ctx: Context): Definitions = ctx.definitions
implicit def toFlagSet(sym: Symbol)(implicit ctx: Context): FlagSet = sym.flags
}