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