unpickler.scala

来自「JAVA 语言的函数式编程扩展」· SCALA 代码 · 共 790 行 · 第 1/2 页

SCALA
790
字号
/* NSC -- new Scala compiler * Copyright 2005-2008 LAMP/EPFL * @author  Martin Odersky */// $Id: UnPickler.scala 13813 2008-01-27 13:11:26Z mcdirmid $package scala.tools.nsc.symtab.classfileimport java.io.IOExceptionimport java.lang.{Float, Double}import scala.tools.nsc.util.{Position, NoPosition}import scala.tools.util.UTF8Codecimport Flags._import PickleFormat._import collection.mutable.{HashMap, ListBuffer}/** This abstract class implements .. * *  @author Martin Odersky *  @version 1.0 */abstract class UnPickler {  val global: Global  import global._  /** Unpickle symbol table information descending from a class and/or module root   *  from an array of bytes.   *  @param bytes      bytearray from which we unpickle   *  @param offset     offset from which unpickling starts   *  @param classroot  the top-level class which is unpickled, or NoSymbol if unapplicable   *  @param moduleroot the top-level module which is unpickled, or NoSymbol if unapplicable   *  @param filename   filename associated with bytearray, only used for error messages   */  def unpickle(bytes: Array[Byte], offset: Int, classRoot: Symbol, moduleRoot: Symbol, filename: String) {    try {      new UnPickle(bytes, offset, classRoot, moduleRoot)    } catch {      case ex: IOException =>        throw ex      case ex: Throwable =>        if (settings.debug.value) ex.printStackTrace()        throw new RuntimeException("error reading Scala signature of "+filename+": "+ex.getMessage())    }  }  private class UnPickle(bytes: Array[Byte], offset: Int, classRoot: Symbol, moduleRoot: Symbol) extends PickleBuffer(bytes, offset, -1) {    if (settings.debug.value) global.log("unpickle " + classRoot + " and " + moduleRoot)    checkVersion()    /** A map from entry numbers to array offsets */    private val index = createIndex        /** A map from entry numbers to symbols, types, or annotations */    private val entries = new Array[AnyRef](index.length)        /** A map from symbols to their associated `decls' scopes */    private val symScopes = new HashMap[Symbol, Scope]    for (i <- 0 until index.length) {      if (isSymbolEntry(i)) { at(i, readSymbol); {} }      else if (isAnnotationEntry(i)) { at(i, readAnnotation); {} }    }    if (settings.debug.value) global.log("unpickled " + classRoot + ":" + classRoot.rawInfo + ", " + moduleRoot + ":" + moduleRoot.rawInfo);//debug    private def checkVersion() {      val major = readNat()      val minor = readNat()      if (major != MajorVersion || minor > MinorVersion)        throw new IOException("Scala signature " + classRoot.name +                               " has wrong version\n expected: " +                               MajorVersion + "." + MinorVersion +                               "\n found: " + major + "." + minor)    }    /** The `decls' scope associated with given symbol */    private def symScope(sym: Symbol, isTemp : Boolean) = symScopes.get(sym) match {      case None =>         val s = if (isTemp) newTempScope                else if (sym.isClass || sym.isModuleClass || sym.isModule) newClassScope(sym);                else newScope              symScopes(sym) = s; s      case Some(s) => s    }    private def symScope(sym : Symbol) : Scope = symScope(sym, false)    /** Does entry represent an (internal) symbol */    private def isSymbolEntry(i: Int): Boolean = {      val tag = bytes(index(i)) % PosOffset      (firstSymTag <= tag && tag <= lastSymTag &&       (tag != CLASSsym || !isRefinementSymbolEntry(i)))    }    /** Does entry represent an (internal or external) symbol */    private def isSymbolRef(i: Int): Boolean = {      val tag = bytes(index(i)) % PosOffset      (firstSymTag <= tag && tag <= lastExtSymTag)    }    /** Does entry represent a name? */    private def isNameEntry(i: Int): Boolean = {      val tag = bytes(index(i))      tag == TERMname || tag == TYPEname    }    /** Does entry represent a symbol attribute? */    private def isAnnotationEntry(i: Int): Boolean = {      val tag = bytes(index(i))      tag == ATTRIBUTE || tag == CHILDREN    }    /** Does entry represent a refinement symbol?      *  pre: Entry is a class symbol     */    private def isRefinementSymbolEntry(i: Int): Boolean = {      val savedIndex = readIndex      readIndex = index(i)      val tag = readByte()      if (tag % PosOffset != CLASSsym) assert(false)      readNat(); // read length      if (tag > PosOffset) readNat(); // read position      val result = readNameRef() == nme.REFINE_CLASS_NAME.toTypeName      readIndex = savedIndex      result    }    /** If entry at <code>i</code> is undefined, define it by performing     *  operation <code>op</code> with <code>readIndex at start of i'th     *  entry. Restore <code>readIndex</code> afterwards.     */    private def at[T <: AnyRef](i: Int, op: () => T): T = {      var r = entries(i)      if (r eq null) {        val savedIndex = readIndex        readIndex = index(i)        r = op()        assert(entries(i) eq null, entries(i))        entries(i) = r        readIndex = savedIndex      }      r.asInstanceOf[T]    }    /** Read a name */    private def readName(): Name = {      val tag = readByte()      val len = readNat()      tag match {        case TERMname => newTermName(bytes, readIndex, len)        case TYPEname => newTypeName(bytes, readIndex, len)        case _ => errorBadSignature("bad name tag: " + tag)      }    }    /** Read a symbol */    private def readSymbol(): Symbol = {      val tag = readByte()      val end = readNat() + readIndex      var sym: Symbol = NoSymbol      tag match {        case EXTref | EXTMODCLASSref =>          val name = readNameRef()          val owner = if (readIndex == end) definitions.RootClass else readSymbolRef()          sym = if (name.toTermName == nme.ROOT) definitions.RootClass                else if (name == nme.ROOTPKG) definitions.RootPackage                else if (tag == EXTref) owner.info.decl(name)                else owner.info.decl(name).moduleClass          if (sym == NoSymbol) {            errorBadSignature(              "reference " + (if (name.isTypeName) "type " else "value ") +              name.decode + " of " + owner + " refers to nonexisting symbol.")          }        case NONEsym =>          sym = NoSymbol        case _ =>          val unusedPos : Int = {            if (tag > PosOffset) readNat            else -1          }          val name = readNameRef()          val owner = readSymbolRef()          val flags = readNat()          var privateWithin: Symbol = NoSymbol          var inforef = readNat()          if (isSymbolRef(inforef)) {            privateWithin = at(inforef, readSymbol)            inforef = readNat()          }          (tag % PosOffset) match {            case TYPEsym =>              sym = owner.newAbstractType(NoPosition, name)            case ALIASsym =>              sym = owner.newAliasType(NoPosition, name)            case CLASSsym =>              sym =                 if (name == classRoot.name && owner == classRoot.owner)                  (if ((flags & MODULE) != 0) moduleRoot.moduleClass                   else classRoot)                else                   if ((flags & MODULE) != 0) owner.newModuleClass(NoPosition, name)                  else owner.newClass(NoPosition, name)              if (readIndex != end) sym.typeOfThis = new LazyTypeRef(readNat())            case MODULEsym =>              val clazz = at(inforef, readType).typeSymbol              sym =                 if (name == moduleRoot.name && owner == moduleRoot.owner) moduleRoot                else {                  assert(clazz.isInstanceOf[ModuleClassSymbol], clazz)                  val mclazz = clazz.asInstanceOf[ModuleClassSymbol]                  val m = owner.newModule(NoPosition, name, mclazz)                  mclazz.setSourceModule(m)                  m                }            case VALsym =>              sym = if (name == moduleRoot.name && owner == moduleRoot.owner) moduleRoot.resetFlag(MODULE)                    else owner.newValue(NoPosition, name)            case _ =>              errorBadSignature("bad symbol tag: " + tag)          }          sym.setFlag(flags.toLong & PickledFlags)          sym.privateWithin = privateWithin          if (readIndex != end) assert(sym hasFlag (SUPERACCESSOR | PARAMACCESSOR))          if (sym hasFlag SUPERACCESSOR) assert(readIndex != end)          sym.setInfo(            if (readIndex != end) new LazyTypeRefAndAlias(inforef, readNat())            else new LazyTypeRef(inforef))          if (sym.owner.isClass && sym != classRoot && sym != moduleRoot &&               !sym.isModuleClass && !sym.isRefinementClass && !sym.isTypeParameter)            symScope(sym.owner) enter sym      }      sym    }    /** Read a type */    private def readType(): Type = {      val tag = readByte()      val end = readNat() + readIndex      tag match {        case NOtpe =>          NoType        case NOPREFIXtpe =>          NoPrefix        case THIStpe =>          mkThisType(readSymbolRef())        case SINGLEtpe =>          singleType(readTypeRef(), readSymbolRef())        case CONSTANTtpe =>          mkConstantType(readConstantRef())        case TYPEREFtpe =>          rawTypeRef(readTypeRef(), readSymbolRef(), until(end, readTypeRef))        case TYPEBOUNDStpe =>          mkTypeBounds(readTypeRef(), readTypeRef())        case REFINEDtpe =>          val clazz = readSymbolRef()/*          val ps = until(end, readTypeRef)          val dcls = symScope(clazz)          new RefinedType(ps, dcls) { override def symbol = clazz }*/         new RefinedType(until(end, readTypeRef), symScope(clazz, true)) {           override def typeSymbol = clazz          }        case CLASSINFOtpe =>          val clazz = readSymbolRef()          ClassInfoType(until(end, readTypeRef), symScope(clazz), clazz)        case METHODtpe =>          val restpe = readTypeRef()          MethodType(until(end, readTypeRef), restpe)        case IMPLICITMETHODtpe =>          val restpe = readTypeRef()          ImplicitMethodType(until(end, readTypeRef), restpe)        case POLYtpe =>          val restpe = readTypeRef()          PolyType(until(end, readSymbolRef), restpe)        case EXISTENTIALtpe =>          val restpe = readTypeRef()          ExistentialType(until(end, readSymbolRef), restpe)        case ANNOTATEDtpe | ANNOTATEDWSELFtpe =>          val tp = readTypeRef()	  val selfsym = if (tag == ANNOTATEDWSELFtpe) readSymbolRef()                        else NoSymbol          val attribs = until(end, readTreeAttribRef)          if (settings.selfInAnnots.value || (selfsym eq NoSymbol))            AnnotatedType(attribs, tp, selfsym)          else            tp // drop annotations with a self symbol unless               // -Yself-in-annots is on        case DEBRUIJNINDEXtpe =>          DeBruijnIndex(readNat(), readNat())        case _ =>          errorBadSignature("bad type tag: " + tag)      }    }    /** Read a constant */    private def readConstant(): Constant = {      val tag = readByte()      val len = readNat()      tag match {        case LITERALunit    => Constant(())        case LITERALboolean => Constant(if (readLong(len) == 0) false else true)        case LITERALbyte    => Constant(readLong(len).asInstanceOf[Byte])        case LITERALshort   => Constant(readLong(len).asInstanceOf[Short])        case LITERALchar    => Constant(readLong(len).asInstanceOf[Char])        case LITERALint     => Constant(readLong(len).asInstanceOf[Int])        case LITERALlong    => Constant(readLong(len))        case LITERALfloat   => Constant(Float.intBitsToFloat(readLong(len).asInstanceOf[Int]))        case LITERALdouble  => Constant(Double.longBitsToDouble(readLong(len)))        case LITERALstring  => Constant(readNameRef().toString())        case LITERALnull    => Constant(null)        case LITERALclass   => Constant(readTypeRef())        case _              => errorBadSignature("bad constant tag: " + tag)      }    }    /** Read an annotation argument.  It can use either Constant's or     *  Tree's for its arguments.  If a reflect tree is seen, it     *  prints a warning and returns an empty tree.     */    private def readAnnotationArg(): AnnotationArgument = {      if (peekByte() == REFLTREE) {        reflectAnnotationWarning()	new AnnotationArgument(EmptyTree)      } else if (peekByte() == TREE) {	val tree = readTree()	new AnnotationArgument(tree)      } else {        val const = readConstant()        new AnnotationArgument(const)              }    }    /** Read an annotation abstract syntax tree. */    private def readAnnotationTree(): Annotation = {      val tag = readByte()      val end = readNat() + readIndex      val tpe = readTypeRef()      val constr = readTreeRef()      val elements = until(end, readTreeRef)      Annotation(constr, elements).setType(tpe)    }    /** Read an attribute and as a side effect store it into     *  the symbol it requests. */    private def readAnnotation(): AnyRef = {      val tag = readByte()      val end = readNat() + readIndex      val target = readSymbolRef()      if (tag == ATTRIBUTE) {        val attrType = readTypeRef()        val args = new ListBuffer[AnnotationArgument]        val assocs = new ListBuffer[(Name, AnnotationArgument)]        while (readIndex != end) {          val argref = readNat()          if (isNameEntry(argref))            assocs += (at(argref, readName), readAnnotationArgRef)          else            args += at(argref, readAnnotationArg)        }        val attr = AnnotationInfo(attrType, args.toList, assocs.toList)        target.attributes = attr :: target.attributes      } else if (tag == CHILDREN) {        while (readIndex != end) target addChild readSymbolRef()      }      null    }    /** Read an annotation and return it. */    private def readTreeAttrib(): AnnotationInfo = {      val tag = readByte()      if(tag != ANNOTINFO)        errorBadSignature("tree-based annotation expected (" + tag + ")")      val end = readNat() + readIndex      val atp = readTypeRef()      val numargs = readNat()      val args = times(numargs, readAnnotationArgRef)      val assocs =        until(end, {() =>          val name = readNameRef()          val tree = readAnnotationArgRef()          (name,tree)})      AnnotationInfo(atp, args, assocs)    }    /* Read an abstract syntax tree */    private def readTree(): Tree = {      val outerTag = readByte()      if (outerTag != TREE)	errorBadSignature("tree expected (" + outerTag + ")")      val end = readNat() + readIndex      val tag = readByte()

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?