diff options
author | Dmitry Petrashko <dmitry.petrashko@gmail.com> | 2015-12-20 12:05:33 +0100 |
---|---|---|
committer | Dmitry Petrashko <dmitry.petrashko@gmail.com> | 2015-12-20 15:39:06 +0100 |
commit | f10cfa2a2079cacae2931bb0b0b6336fd6c6d4b1 (patch) | |
tree | 16290ce4db07f07227fbf53a15db08189bf0cc95 /src | |
parent | 5903fe35fada0f081334e933e6a5a182047d5d5f (diff) | |
download | dotty-f10cfa2a2079cacae2931bb0b0b6336fd6c6d4b1.tar.gz dotty-f10cfa2a2079cacae2931bb0b0b6336fd6c6d4b1.tar.bz2 dotty-f10cfa2a2079cacae2931bb0b0b6336fd6c6d4b1.zip |
Linker specific: TreePicker: export functions for reuse
Linker needs to save some trees.
Instead of reimplementing I would rather reuse already existing methods.
Diffstat (limited to 'src')
-rw-r--r-- | src/dotty/tools/dotc/core/tasty/TreePickler.scala | 543 |
1 files changed, 271 insertions, 272 deletions
diff --git a/src/dotty/tools/dotc/core/tasty/TreePickler.scala b/src/dotty/tools/dotc/core/tasty/TreePickler.scala index d11d6f4b7..5c0d4bd67 100644 --- a/src/dotty/tools/dotc/core/tasty/TreePickler.scala +++ b/src/dotty/tools/dotc/core/tasty/TreePickler.scala @@ -80,225 +80,251 @@ class TreePickler(pickler: TastyPickler) { case None => false } - def pickle(trees: List[Tree])(implicit ctx: Context) = { - - def qualifiedName(sym: Symbol): TastyName = - if (sym.isRoot || sym.owner.isRoot) TastyName.Simple(sym.name.toTermName) - else TastyName.Qualified(nameIndex(qualifiedName(sym.owner)), nameIndex(sym.name)) + def pickleConstant(c: Constant)(implicit ctx: Context): Unit = c.tag match { + case UnitTag => + writeByte(UNITconst) + case BooleanTag => + writeByte(if (c.booleanValue) TRUEconst else FALSEconst) + case ByteTag => + writeByte(BYTEconst) + writeInt(c.byteValue) + case ShortTag => + writeByte(SHORTconst) + writeInt(c.shortValue) + case CharTag => + writeByte(CHARconst) + writeNat(c.charValue) + case IntTag => + writeByte(INTconst) + writeInt(c.intValue) + case LongTag => + writeByte(LONGconst) + writeLongInt(c.longValue) + case FloatTag => + writeByte(FLOATconst) + writeInt(java.lang.Float.floatToRawIntBits(c.floatValue)) + case DoubleTag => + writeByte(DOUBLEconst) + writeLongInt(java.lang.Double.doubleToRawLongBits(c.doubleValue)) + case StringTag => + writeByte(STRINGconst) + writeNat(nameIndex(c.stringValue).index) + case NullTag => + writeByte(NULLconst) + case ClazzTag => + writeByte(CLASSconst) + pickleType(c.typeValue) + case EnumTag => + writeByte(ENUMconst) + pickleType(c.symbolValue.termRef) + } - def pickleConstant(c: Constant): Unit = c.tag match { - case UnitTag => - writeByte(UNITconst) - case BooleanTag => - writeByte(if (c.booleanValue) TRUEconst else FALSEconst) - case ByteTag => - writeByte(BYTEconst) - writeInt(c.byteValue) - case ShortTag => - writeByte(SHORTconst) - writeInt(c.shortValue) - case CharTag => - writeByte(CHARconst) - writeNat(c.charValue) - case IntTag => - writeByte(INTconst) - writeInt(c.intValue) - case LongTag => - writeByte(LONGconst) - writeLongInt(c.longValue) - case FloatTag => - writeByte(FLOATconst) - writeInt(java.lang.Float.floatToRawIntBits(c.floatValue)) - case DoubleTag => - writeByte(DOUBLEconst) - writeLongInt(java.lang.Double.doubleToRawLongBits(c.doubleValue)) - case StringTag => - writeByte(STRINGconst) - writeNat(nameIndex(c.stringValue).index) - case NullTag => - writeByte(NULLconst) - case ClazzTag => - writeByte(CLASSconst) - pickleType(c.typeValue) - case EnumTag => - writeByte(ENUMconst) - pickleType(c.symbolValue.termRef) + def pickleType(tpe0: Type, richTypes: Boolean = false)(implicit ctx: Context): Unit = try { + val tpe = tpe0.stripTypeVar + val prev = pickledTypes.get(tpe) + if (prev == null) { + pickledTypes.put(tpe, currentAddr) + pickleNewType(tpe, richTypes) } - - def pickleType(tpe0: Type, richTypes: Boolean = false): Unit = try { - val tpe = tpe0.stripTypeVar - val prev = pickledTypes.get(tpe) - if (prev == null) { - pickledTypes.put(tpe, currentAddr) - pickleNewType(tpe, richTypes) - } - else { - writeByte(SHARED) - writeRef(prev.asInstanceOf[Addr]) - } - } catch { - case ex: AssertionError => - println(i"error when pickling type $tpe0") - throw ex + else { + writeByte(SHARED) + writeRef(prev.asInstanceOf[Addr]) } + } catch { + case ex: AssertionError => + println(i"error when pickling type $tpe0") + throw ex + } - def pickleNewType(tpe: Type, richTypes: Boolean): Unit = try { tpe match { - case AppliedType(tycon, args) => - writeByte(APPLIEDtype) - withLength { pickleType(tycon); args.foreach(pickleType(_)) } - case ConstantType(value) => - pickleConstant(value) - case tpe: TypeRef if tpe.info.isAlias && tpe.symbol.is(Flags.AliasPreferred) => - pickleType(tpe.info.bounds.hi) - case tpe: WithFixedSym => - val sym = tpe.symbol - def pickleRef() = - if (tpe.prefix == NoPrefix) { - writeByte(if (tpe.isType) TYPEREFdirect else TERMREFdirect) - pickleSymRef(sym) - } - else { - assert(tpe.symbol.isClass) - assert(tpe.symbol.is(Flags.Scala2x), tpe.symbol.showLocated) - writeByte(TYPEREF) // should be changed to a new entry that keeps track of prefix, symbol & owner - pickleName(tpe.name) - pickleType(tpe.prefix) - } - if (sym.is(Flags.Package)) { - writeByte(if (tpe.isType) TYPEREFpkg else TERMREFpkg) - pickleName(qualifiedName(sym)) - } - else if (sym is Flags.BindDefinedType) { - registerDef(sym) - writeByte(BIND) - withLength { - pickleName(sym.name) - pickleType(sym.info) - pickleRef() - } - } - else pickleRef() - case tpe: TermRefWithSignature => - if (tpe.symbol.is(Flags.Package)) picklePackageRef(tpe.symbol) - else { - writeByte(TERMREF) - pickleNameAndSig(tpe.name, tpe.signature); pickleType(tpe.prefix) - } - case tpe: NamedType => - if (isLocallyDefined(tpe.symbol)) { - writeByte(if (tpe.isType) TYPEREFsymbol else TERMREFsymbol) - pickleSymRef(tpe.symbol); pickleType(tpe.prefix) - } else { - writeByte(if (tpe.isType) TYPEREF else TERMREF) - pickleName(tpe.name); pickleType(tpe.prefix) + private def pickleNewType(tpe: Type, richTypes: Boolean)(implicit ctx: Context): Unit = try { tpe match { + case AppliedType(tycon, args) => + writeByte(APPLIEDtype) + withLength { pickleType(tycon); args.foreach(pickleType(_)) } + case ConstantType(value) => + pickleConstant(value) + case tpe: TypeRef if tpe.info.isAlias && tpe.symbol.is(Flags.AliasPreferred) => + pickleType(tpe.info.bounds.hi) + case tpe: WithFixedSym => + val sym = tpe.symbol + def pickleRef() = + if (tpe.prefix == NoPrefix) { + writeByte(if (tpe.isType) TYPEREFdirect else TERMREFdirect) + pickleSymRef(sym) } - case tpe: ThisType => - if (tpe.cls.is(Flags.Package) && !tpe.cls.isEffectiveRoot) - picklePackageRef(tpe.cls) else { - writeByte(THIS) - pickleType(tpe.tref) + assert(tpe.symbol.isClass) + assert(tpe.symbol.is(Flags.Scala2x), tpe.symbol.showLocated) + writeByte(TYPEREF) // should be changed to a new entry that keeps track of prefix, symbol & owner + pickleName(tpe.name) + pickleType(tpe.prefix) } - case tpe: SuperType => - writeByte(SUPERtype) - withLength { pickleType(tpe.thistpe); pickleType(tpe.supertpe)} - case tpe: RefinedThis => - writeByte(REFINEDthis) - val binderAddr = pickledTypes.get(tpe.binder) - assert(binderAddr != null, tpe.binder) - writeRef(binderAddr.asInstanceOf[Addr]) - case tpe: SkolemType => - pickleType(tpe.info) - case tpe: RefinedType => - writeByte(REFINEDtype) + if (sym.is(Flags.Package)) { + writeByte(if (tpe.isType) TYPEREFpkg else TERMREFpkg) + pickleName(qualifiedName(sym)) + } + else if (sym is Flags.BindDefinedType) { + registerDef(sym) + writeByte(BIND) withLength { - pickleType(tpe.parent) - pickleName(tpe.refinedName) - pickleType(tpe.refinedInfo, richTypes = true) + pickleName(sym.name) + pickleType(sym.info) + pickleRef() } - case tpe: TypeAlias => - writeByte(TYPEALIAS) - withLength { - pickleType(tpe.alias, richTypes) - tpe.variance match { - case 1 => writeByte(COVARIANT) - case -1 => writeByte(CONTRAVARIANT) - case 0 => - } + } + else pickleRef() + case tpe: TermRefWithSignature => + if (tpe.symbol.is(Flags.Package)) picklePackageRef(tpe.symbol) + else { + writeByte(TERMREF) + pickleNameAndSig(tpe.name, tpe.signature); pickleType(tpe.prefix) + } + case tpe: NamedType => + if (isLocallyDefined(tpe.symbol)) { + writeByte(if (tpe.isType) TYPEREFsymbol else TERMREFsymbol) + pickleSymRef(tpe.symbol); pickleType(tpe.prefix) + } else { + writeByte(if (tpe.isType) TYPEREF else TERMREF) + pickleName(tpe.name); pickleType(tpe.prefix) + } + case tpe: ThisType => + if (tpe.cls.is(Flags.Package) && !tpe.cls.isEffectiveRoot) + picklePackageRef(tpe.cls) + else { + writeByte(THIS) + pickleType(tpe.tref) + } + case tpe: SuperType => + writeByte(SUPERtype) + withLength { pickleType(tpe.thistpe); pickleType(tpe.supertpe)} + case tpe: RefinedThis => + writeByte(REFINEDthis) + val binderAddr = pickledTypes.get(tpe.binder) + assert(binderAddr != null, tpe.binder) + writeRef(binderAddr.asInstanceOf[Addr]) + case tpe: SkolemType => + pickleType(tpe.info) + case tpe: RefinedType => + writeByte(REFINEDtype) + withLength { + pickleType(tpe.parent) + pickleName(tpe.refinedName) + pickleType(tpe.refinedInfo, richTypes = true) + } + case tpe: TypeAlias => + writeByte(TYPEALIAS) + withLength { + pickleType(tpe.alias, richTypes) + tpe.variance match { + case 1 => writeByte(COVARIANT) + case -1 => writeByte(CONTRAVARIANT) + case 0 => } - case tpe: TypeBounds => - writeByte(TYPEBOUNDS) - withLength { pickleType(tpe.lo, richTypes); pickleType(tpe.hi, richTypes) } - case tpe: AnnotatedType => - writeByte(ANNOTATED) - withLength { pickleType(tpe.tpe, richTypes); pickleTree(tpe.annot.tree) } - case tpe: AndOrType => - writeByte(if (tpe.isAnd) ANDtype else ORtype) - withLength { pickleType(tpe.tp1, richTypes); pickleType(tpe.tp2, richTypes) } - case tpe: ExprType => - writeByte(BYNAMEtype) - pickleType(tpe.underlying) - case tpe: MethodType if richTypes => - writeByte(METHODtype) - pickleMethodic(tpe.resultType, tpe.paramNames, tpe.paramTypes) - case tpe: PolyType if richTypes => - writeByte(POLYtype) - pickleMethodic(tpe.resultType, tpe.paramNames, tpe.paramBounds) - case tpe: PolyParam => - if (!pickleParamType(tpe)) - // TODO figure out why this case arises in e.g. pickling AbstractFileReader. - ctx.typerState.constraint.entry(tpe) match { - case TypeBounds(lo, hi) if lo eq hi => pickleNewType(lo, richTypes) - case _ => assert(false, s"orphan poly parameter: $tpe") - } - case tpe: MethodParam => - assert(pickleParamType(tpe), s"orphan method parameter: $tpe") - case tpe: LazyRef => - pickleType(tpe.ref) - }} catch { - case ex: AssertionError => - println(i"error while pickling type $tpe") - throw ex + } + case tpe: TypeBounds => + writeByte(TYPEBOUNDS) + withLength { pickleType(tpe.lo, richTypes); pickleType(tpe.hi, richTypes) } + case tpe: AnnotatedType => + writeByte(ANNOTATED) + withLength { pickleType(tpe.tpe, richTypes); pickleTree(tpe.annot.tree) } + case tpe: AndOrType => + writeByte(if (tpe.isAnd) ANDtype else ORtype) + withLength { pickleType(tpe.tp1, richTypes); pickleType(tpe.tp2, richTypes) } + case tpe: ExprType => + writeByte(BYNAMEtype) + pickleType(tpe.underlying) + case tpe: MethodType if richTypes => + writeByte(METHODtype) + pickleMethodic(tpe.resultType, tpe.paramNames, tpe.paramTypes) + case tpe: PolyType if richTypes => + writeByte(POLYtype) + pickleMethodic(tpe.resultType, tpe.paramNames, tpe.paramBounds) + case tpe: PolyParam => + if (!pickleParamType(tpe)) + // TODO figure out why this case arises in e.g. pickling AbstractFileReader. + ctx.typerState.constraint.entry(tpe) match { + case TypeBounds(lo, hi) if lo eq hi => pickleNewType(lo, richTypes) + case _ => assert(false, s"orphan poly parameter: $tpe") + } + case tpe: MethodParam => + assert(pickleParamType(tpe), s"orphan method parameter: $tpe") + case tpe: LazyRef => + pickleType(tpe.ref) + }} catch { + case ex: AssertionError => + println(i"error while pickling type $tpe") + throw ex + } + + def picklePackageRef(pkg: Symbol)(implicit ctx: Context): Unit = { + writeByte(TERMREFpkg) + pickleName(qualifiedName(pkg)) + } + + def pickleMethodic(result: Type, names: List[Name], types: List[Type])(implicit ctx: Context) = + withLength { + pickleType(result, richTypes = true) + (names, types).zipped.foreach { (name, tpe) => + pickleName(name); pickleType(tpe) + } } - def picklePackageRef(pkg: Symbol): Unit = { - writeByte(TERMREFpkg) - pickleName(qualifiedName(pkg)) + def pickleParamType(tpe: ParamType)(implicit ctx: Context): Boolean = { + val binder = pickledTypes.get(tpe.binder) + val pickled = binder != null + if (pickled) { + writeByte(PARAMtype) + withLength { writeRef(binder.asInstanceOf[Addr]); writeNat(tpe.paramNum) } } + pickled + } - def pickleMethodic(result: Type, names: List[Name], types: List[Type]) = - withLength { - pickleType(result, richTypes = true) - (names, types).zipped.foreach { (name, tpe) => - pickleName(name); pickleType(tpe) - } - } + def pickleTpt(tpt: Tree)(implicit ctx: Context): Unit = pickleType(tpt.tpe) // TODO correlate with original when generating positions - def pickleParamType(tpe: ParamType): Boolean = { - val binder = pickledTypes.get(tpe.binder) - val pickled = binder != null - if (pickled) { - writeByte(PARAMtype) - withLength { writeRef(binder.asInstanceOf[Addr]); writeNat(tpe.paramNum) } + def pickleTreeUnlessEmpty(tree: Tree)(implicit ctx: Context): Unit = + if (!tree.isEmpty) pickleTree(tree) + + def pickleDef(tag: Int, sym: Symbol, tpt: Tree, rhs: Tree = EmptyTree, pickleParams: => Unit = ())(implicit ctx: Context) = { + assert(symRefs(sym) == NoAddr) + registerDef(sym) + writeByte(tag) + withLength { + pickleName(sym) + pickleParams + tpt match { + case tpt: TypeTree => pickleTpt(tpt) + case _ => pickleTree(tpt) } - pickled + pickleTreeUnlessEmpty(rhs) + pickleModifiers(sym) } + } + + def pickleParam(tree: Tree)(implicit ctx: Context): Unit = tree match { + case tree: ValDef => pickleDef(PARAM, tree.symbol, tree.tpt) + case tree: DefDef => pickleDef(PARAM, tree.symbol, tree.tpt, tree.rhs) + case tree: TypeDef => pickleDef(TYPEPARAM, tree.symbol, tree.rhs) + } - def pickleTpt(tpt: Tree): Unit = pickleType(tpt.tpe) // TODO correlate with original when generating positions + def pickleParams(trees: List[Tree])(implicit ctx: Context): Unit = { + trees.foreach(preRegister) + trees.foreach(pickleParam) + } - def pickleTreeUnlessEmpty(tree: Tree): Unit = - if (!tree.isEmpty) pickleTree(tree) + def pickleStats(stats: List[Tree])(implicit ctx: Context) = { + stats.foreach(preRegister) + stats.foreach(stat => if (!stat.isEmpty) pickleTree(stat)) + } - def pickleTree(tree: Tree): Unit = try { - pickledTrees.put(tree, currentAddr) - tree match { + def pickleTree(tree: Tree)(implicit ctx: Context): Unit = try { + pickledTrees.put(tree, currentAddr) + tree match { case Ident(name) => tree.tpe match { case tp: TermRef => pickleType(tp) case _ => - writeByte(IDENT) - pickleName(name) - pickleType(tree.tpe) + writeByte(IDENT) + pickleName(name) + pickleType(tree.tpe) } case This(_) => pickleType(tree.tpe) @@ -459,89 +485,62 @@ class TreePickler(pickler: TastyPickler) { writeByte(PACKAGE) withLength { pickleType(pid.tpe); pickleStats(stats) } }} - catch { - case ex: AssertionError => - println(i"error when pickling tree $tree") - throw ex - } - - def pickleDef(tag: Int, sym: Symbol, tpt: Tree, rhs: Tree = EmptyTree, pickleParams: => Unit = ()) = { - assert(symRefs(sym) == NoAddr) - registerDef(sym) - writeByte(tag) - withLength { - pickleName(sym) - pickleParams - tpt match { - case tpt: TypeTree => pickleTpt(tpt) - case _ => pickleTree(tpt) - } - pickleTreeUnlessEmpty(rhs) - pickleModifiers(sym) - } - } - - def pickleParam(tree: Tree): Unit = tree match { - case tree: ValDef => pickleDef(PARAM, tree.symbol, tree.tpt) - case tree: DefDef => pickleDef(PARAM, tree.symbol, tree.tpt, tree.rhs) - case tree: TypeDef => pickleDef(TYPEPARAM, tree.symbol, tree.rhs) - } + catch { + case ex: AssertionError => + println(i"error when pickling tree $tree") + throw ex + } - def pickleParams(trees: List[Tree]): Unit = { - trees.foreach(preRegister) - trees.foreach(pickleParam) - } + def qualifiedName(sym: Symbol)(implicit ctx: Context): TastyName = + if (sym.isRoot || sym.owner.isRoot) TastyName.Simple(sym.name.toTermName) + else TastyName.Qualified(nameIndex(qualifiedName(sym.owner)), nameIndex(sym.name)) - def pickleStats(stats: List[Tree]) = { - stats.foreach(preRegister) - stats.foreach(stat => if (!stat.isEmpty) pickleTree(stat)) + def pickleModifiers(sym: Symbol)(implicit ctx: Context): Unit = { + import Flags._ + val flags = sym.flags + val privateWithin = sym.privateWithin + if (privateWithin.exists) { + writeByte(if (flags is Protected) PROTECTEDqualified else PRIVATEqualified) + pickleType(privateWithin.typeRef) } - - def pickleModifiers(sym: Symbol): Unit = { - import Flags._ - val flags = sym.flags - val privateWithin = sym.privateWithin - if (privateWithin.exists) { - writeByte(if (flags is Protected) PROTECTEDqualified else PRIVATEqualified) - pickleType(privateWithin.typeRef) - } - if (flags is Private) writeByte(PRIVATE) - if (flags is Protected) if (!privateWithin.exists) writeByte(PROTECTED) - if ((flags is Final) && !(sym is Module)) writeByte(FINAL) - if (flags is Case) writeByte(CASE) - if (flags is Override) writeByte(OVERRIDE) - if (flags is Inline) writeByte(INLINE) - if (flags is JavaStatic) writeByte(STATIC) - if (flags is Module) writeByte(OBJECT) - if (flags is Local) writeByte(LOCAL) - if (flags is Synthetic) writeByte(SYNTHETIC) - if (flags is Artifact) writeByte(ARTIFACT) - if (flags is Scala2x) writeByte(SCALA2X) - if (flags is InSuperCall) writeByte(INSUPERCALL) - if (sym.isTerm) { - if (flags is Implicit) writeByte(IMPLICIT) - if ((flags is Lazy) && !(sym is Module)) writeByte(LAZY) - if (flags is AbsOverride) { writeByte(ABSTRACT); writeByte(OVERRIDE) } - if (flags is Mutable) writeByte(MUTABLE) - if (flags is Accessor) writeByte(FIELDaccessor) - if (flags is CaseAccessor) writeByte(CASEaccessor) - if (flags is DefaultParameterized) writeByte(DEFAULTparameterized) - if (flags is Stable) writeByte(STABLE) - } else { - if (flags is Sealed) writeByte(SEALED) - if (flags is Abstract) writeByte(ABSTRACT) - if (flags is Trait) writeByte(TRAIT) - if (flags is Covariant) writeByte(COVARIANT) - if (flags is Contravariant) writeByte(CONTRAVARIANT) - } - sym.annotations.foreach(pickleAnnotation) + if (flags is Private) writeByte(PRIVATE) + if (flags is Protected) if (!privateWithin.exists) writeByte(PROTECTED) + if ((flags is Final) && !(sym is Module)) writeByte(FINAL) + if (flags is Case) writeByte(CASE) + if (flags is Override) writeByte(OVERRIDE) + if (flags is Inline) writeByte(INLINE) + if (flags is JavaStatic) writeByte(STATIC) + if (flags is Module) writeByte(OBJECT) + if (flags is Local) writeByte(LOCAL) + if (flags is Synthetic) writeByte(SYNTHETIC) + if (flags is Artifact) writeByte(ARTIFACT) + if (flags is Scala2x) writeByte(SCALA2X) + if (flags is InSuperCall) writeByte(INSUPERCALL) + if (sym.isTerm) { + if (flags is Implicit) writeByte(IMPLICIT) + if ((flags is Lazy) && !(sym is Module)) writeByte(LAZY) + if (flags is AbsOverride) { writeByte(ABSTRACT); writeByte(OVERRIDE) } + if (flags is Mutable) writeByte(MUTABLE) + if (flags is Accessor) writeByte(FIELDaccessor) + if (flags is CaseAccessor) writeByte(CASEaccessor) + if (flags is DefaultParameterized) writeByte(DEFAULTparameterized) + if (flags is Stable) writeByte(STABLE) + } else { + if (flags is Sealed) writeByte(SEALED) + if (flags is Abstract) writeByte(ABSTRACT) + if (flags is Trait) writeByte(TRAIT) + if (flags is Covariant) writeByte(COVARIANT) + if (flags is Contravariant) writeByte(CONTRAVARIANT) } + sym.annotations.foreach(pickleAnnotation) + } - def pickleAnnotation(ann: Annotation) = { - writeByte(ANNOTATION) - withLength { pickleType(ann.symbol.typeRef); pickleTree(ann.tree) } - } + def pickleAnnotation(ann: Annotation)(implicit ctx: Context) = { + writeByte(ANNOTATION) + withLength { pickleType(ann.symbol.typeRef); pickleTree(ann.tree) } + } + def pickle(trees: List[Tree])(implicit ctx: Context) = { def updateMapWithDeltas[T](mp: collection.mutable.Map[T, Addr]) = for (key <- mp.keysIterator.toBuffer[T]) mp(key) = adjusted(mp(key)) |