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 + -
显示快捷键?