symbols.scala
来自「JAVA 语言的函数式编程扩展」· SCALA 代码 · 共 1,613 行 · 第 1/4 页
SCALA
1,613 行
def hasTransOwner(sym: Symbol) = { var o = this while ((o ne sym) && (o ne NoSymbol)) o = o.owner o eq sym } def name: Name = rawname final def name_=(name: Name) { if (name != rawname) { if (owner.isClass) { var ifs = owner.infos while (ifs != null) { ifs.info.decls.rehash(this, name) ifs = ifs.prev } } rawname = name } } /** If this symbol has an expanded name, its original name, otherwise its name itself. * @see expandName */ def originalName = nme.originalName(name) final def flags: Long = { val fs = rawflags & phase.flagMask (fs | ((fs & LateFlags) >>> LateShift)) & ~(fs >>> AntiShift) } final def flags_=(fs: Long) = rawflags = fs final def setFlag(mask: Long): this.type = { rawflags = rawflags | mask; this } final def resetFlag(mask: Long): this.type = { rawflags = rawflags & ~mask; this } final def getFlag(mask: Long): Long = flags & mask final def hasFlag(mask: Long): Boolean = (flags & mask) != 0 final def resetFlags { rawflags = rawflags & TopLevelCreationFlags } /** The class or term up to which this symbol is accessible, * or RootClass if it is public */ def accessBoundary(base: Symbol): Symbol = { if (hasFlag(PRIVATE) || owner.isTerm) owner else if (privateWithin != NoSymbol && !phase.erasedTypes) privateWithin else if (hasFlag(PROTECTED)) base else RootClass } def isLessAccessibleThan(other: Symbol): Boolean = { val tb = this.accessBoundary(owner) val ob1 = other.accessBoundary(owner) val ob2 = ob1.linkedClassOfClass var o = tb while (o != NoSymbol && o != ob1 && o != ob2) { o = o.owner } o != NoSymbol && o != tb }// Info and Type ------------------------------------------------------------------- private[Symbols] var infos: TypeHistory = null /** Get type. The type of a symbol is: * for a type symbol, the type corresponding to the symbol itself * for a term symbol, its usual type */ def tpe: Type = info /** Get type info associated with symbol at current phase, after * ensuring that symbol is initialized (i.e. type is completed). */ def info: Type = try { var cnt = 0 while (validTo == NoPeriod) { //if (settings.debug.value) System.out.println("completing " + this);//DEBUG assert(infos ne null, this.name) assert(infos.prev eq null, this.name) val tp = infos.info //if (settings.debug.value) System.out.println("completing " + this.rawname + tp.getClass());//debug if ((rawflags & LOCKED) != 0) { setInfo(ErrorType) throw CyclicReference(this, tp) } rawflags = rawflags | LOCKED val current = phase try { phase = phaseOf(infos.validFrom) tp.complete(this) // if (settings.debug.value && runId(validTo) == currentRunId) System.out.println("completed " + this/* + ":" + info*/);//DEBUG rawflags = rawflags & ~LOCKED } finally { phase = current } cnt += 1 // allow for two completions: // one: sourceCompleter to LazyType, two: LazyType to completed type if (cnt == 3) throw new Error("no progress in completing " + this + ":" + tp) } val result = rawInfo result } catch { case ex: CyclicReference => if (settings.debug.value) println("... trying to complete "+this) throw ex } /** Set initial info. */ def setInfo(info: Type): this.type = { assert(info ne null) infos = TypeHistory(currentPeriod, info, null) if (info.isComplete) { rawflags = rawflags & ~LOCKED validTo = currentPeriod } else { rawflags = rawflags & ~LOCKED validTo = NoPeriod } this } /** Set new info valid from start of this phase. */ final def updateInfo(info: Type): Symbol = { assert(phaseId(infos.validFrom) <= phase.id) if (phaseId(infos.validFrom) == phase.id) infos = infos.prev infos = TypeHistory(currentPeriod, info, infos) this } def hasRawInfo: Boolean = infos ne null /** Return info without checking for initialization or completing */ def rawInfo: Type = { var infos = this.infos assert(infos != null, name) val curPeriod = currentPeriod val curPid = phaseId(curPeriod) if (!inIDE && validTo != NoPeriod) { // IDE doesn't adapt. // skip any infos that concern later phases while (curPid < phaseId(infos.validFrom) && infos.prev != null) infos = infos.prev if (validTo < curPeriod) { // adapt any infos that come from previous runs val current = phase try { infos = adaptInfos(infos) //assert(runId(validTo) == currentRunId, name) //assert(runId(infos.validFrom) == currentRunId, name) if (validTo < curPeriod) { var itr = infoTransformers.nextFrom(phaseId(validTo)) infoTransformers = itr; // caching optimization while (itr.pid != NoPhase.id && itr.pid < current.id) { phase = phaseWithId(itr.pid) val info1 = itr.transform(this, infos.info) if (info1 ne infos.info) { infos = TypeHistory(currentPeriod + 1, info1, infos) this.infos = infos } validTo = currentPeriod + 1 // to enable reads from same symbol during info-transform itr = itr.next } validTo = if (itr.pid == NoPhase.id) curPeriod else period(currentRunId, itr.pid) } } finally { phase = current } } } infos.info } private def adaptInfos(infos: TypeHistory): TypeHistory = if (infos == null || runId(infos.validFrom) == currentRunId) { infos } else { val prev1 = adaptInfos(infos.prev) if (prev1 ne infos.prev) prev1 else { def adaptToNewRun(info: Type): Type = if (isPackageClass) info else adaptToNewRunMap(info) val pid = phaseId(infos.validFrom) validTo = period(currentRunId, pid) phase = phaseWithId(pid) val info1 = adaptToNewRun(infos.info) if (info1 eq infos.info) { infos.validFrom = validTo infos } else { this.infos = TypeHistory(validTo, info1, prev1) this.infos } } } /** Initialize the symbol */ final def initialize: this.type = { if (!isInitialized) info this } /** Was symbol's type updated during given phase? */ final def isUpdatedAt(pid: Phase#Id): Boolean = { var infos = this.infos while ((infos ne null) && phaseId(infos.validFrom) != pid + 1) infos = infos.prev infos ne null } /** The type constructor of a symbol is: * For a type symbol, the type corresponding to the symbol itself, * excluding parameters. * Not applicable for term symbols. */ def typeConstructor: Type = throw new Error("typeConstructor inapplicable for " + this) def tpeHK = if (isType) typeConstructor else tpe // @M! used in memberType /** The type parameters of this symbol, without ensuring type completion. * assumption: if a type starts out as monomorphic, it will not acquire * type parameters later. */ def unsafeTypeParams: List[Symbol] = if (isMonomorphicType) List() else rawInfo.typeParams /** The type parameters of this symbol. * assumption: if a type starts out as monomorphic, it will not acquire * type parameters later. */ def typeParams: List[Symbol] = if (isMonomorphicType) List() else { rawInfo.load(this); rawInfo.typeParams } def getAttributes(clazz: Symbol): List[AnnotationInfo] = attributes.filter(_.atp.typeSymbol.isNonBottomSubClass(clazz)) /** The least proper supertype of a class; includes all parent types * and refinement where needed */ def classBound: Type = { val tp = refinedType(info.parents, owner) val thistp = tp.typeSymbol.thisType val oldsymbuf = new ListBuffer[Symbol] val newsymbuf = new ListBuffer[Symbol] for (sym <- info.decls.toList) { // todo: what about public references to private symbols? if (sym.isPublic && !sym.isConstructor) { oldsymbuf += sym newsymbuf += ( if (sym.isClass) tp.typeSymbol.newAbstractType(sym.pos, sym.name).setInfo(sym.existentialBound) else sym.cloneSymbol(tp.typeSymbol)) } } val oldsyms = oldsymbuf.toList val newsyms = newsymbuf.toList for (sym <- newsyms) { addMember(thistp, tp, sym.setInfo(sym.info.substThis(this, thistp).substSym(oldsyms, newsyms))) } tp } /** If we quantify existentially over this symbol, * the bound of the type variable that stands for it * pre: symbol is a term, a class, or an abstract type (no alias type allowed) */ def existentialBound: Type = if (this.isClass) polyType(this.typeParams, mkTypeBounds(AllClass.tpe, this.classBound)) else if (this.isAbstractType) this.info else if (this.isTerm) mkTypeBounds(AllClass.tpe, intersectionType(List(this.tpe, SingletonClass.tpe))) else throw new Error("unexpected alias type: "+this) /** Reset symbol to initial state */ def reset(completer: Type) { resetFlags infos = null validTo = NoPeriod //limit = NoPhase.id setInfo(completer) }// Comparisons ---------------------------------------------------------------- /** A total ordering between symbols that refines the class * inheritance graph (i.e. subclass.isLess(superclass) always holds). * the ordering is given by: (isType, -|closure| for type symbols, id) */ final def isLess(that: Symbol): Boolean = { def closureLength(sym: Symbol) = if (sym.isAbstractType) 1 + sym.info.bounds.hi.closure.length else sym.info.closure.length if (this.isType) (that.isType && { val diff = closureLength(this) - closureLength(that) diff > 0 || diff == 0 && this.id < that.id }) else that.isType || this.id < that.id } /** A partial ordering between symbols. * (this isNestedIn that) holds iff this symbol is defined within * a class or method defining that symbol */ final def isNestedIn(that: Symbol): Boolean = owner == that || owner != NoSymbol && (owner isNestedIn that) /** Is this class symbol a subclass of that symbol? */ final def isNonBottomSubClass(that: Symbol): Boolean = this == that || this.isError || that.isError || info.closurePos(that) >= 0 final def isSubClass(that: Symbol): Boolean = { isNonBottomSubClass(that) || this == AllClass || this == AllRefClass && (that == AnyClass || that != AllClass && (that isSubClass AnyRefClass)) }// Overloaded Alternatives --------------------------------------------------------- def alternatives: List[Symbol] = if (hasFlag(OVERLOADED)) info.asInstanceOf[OverloadedType].alternatives else List(this) def filter(cond: Symbol => Boolean): Symbol = if (hasFlag(OVERLOADED)) { //assert(info.isInstanceOf[OverloadedType], "" + this + ":" + info);//DEBUG val alts = alternatives val alts1 = alts filter cond if (alts1 eq alts) this else if (alts1.isEmpty) NoSymbol else if (alts1.tail.isEmpty) alts1.head else owner.newOverloaded(info.prefix, alts1) } else if (cond(this)) this else NoSymbol def suchThat(cond: Symbol => Boolean): Symbol = { val result = filter(cond) // @S: seems like NoSymbol has the overloaded flag???? if (inIDE && (this eq result) && result != NoSymbol && (result hasFlag OVERLOADED)) { return result } if (!inIDE) assert(!(result hasFlag OVERLOADED), result.alternatives) result }// Cloneing ------------------------------------------------------------------- /** A clone of this symbol */ final def cloneSymbol: Symbol = cloneSymbol(owner) /** A clone of this symbol, but with given owner */ final def cloneSymbol(owner: Symbol): Symbol = cloneSymbolImpl(owner).setInfo(info.cloneInfo(this)) .setFlag(this.rawflags).setAttributes(this.attributes) /** Internal method to clone a symbol's implementation without flags or type */ def cloneSymbolImpl(owner: Symbol): Symbol// Access to related symbols -------------------------------------------------- /** The next enclosing class */ def enclClass: Symbol = if (isClass) this else owner.enclClass /** The next enclosing method */ def enclMethod: Symbol = if (isSourceMethod) this else owner.enclMethod /** The primary constructor of a class */ def primaryConstructor: Symbol = { var c = info.decl( if (isTrait || isImplClass) nme.MIXIN_CONSTRUCTOR else nme.CONSTRUCTOR) c = if (c hasFlag OVERLOADED) c.alternatives.head else c //assert(c != NoSymbol) c } /** The self symbol of a class with explicit self type, or else the * symbol itself. */ def thisSym: Symbol = this /** The type of `this' in a class, or else the type of the symbol itself. */ def typeOfThis = thisSym.tpe /** Sets the type of `this' in a class */ def typeOfThis_=(tp: Type): Unit = throw new Error("typeOfThis cannot be set for " + this) /** If symbol is a class, the type <code>this.type</code> in this class, * otherwise <code>NoPrefix</code>.
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?