diff options
Diffstat (limited to 'src/dotty/tools/dotc/core')
-rw-r--r-- | src/dotty/tools/dotc/core/Definitions.scala | 5 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/SymbolLoaders.scala | 5 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/pickling/ClassfileParser.scala | 74 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/pickling/DottyUnpickler.scala | 17 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/pickling/PickleFormat.scala | 2 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/pickling/Scala2Unpickler.scala (renamed from src/dotty/tools/dotc/core/pickling/UnPickler.scala) | 8 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/pickling/TastyPickler.scala | 16 | ||||
-rw-r--r-- | src/dotty/tools/dotc/core/pickling/TreeUnpickler.scala | 13 |
8 files changed, 89 insertions, 51 deletions
diff --git a/src/dotty/tools/dotc/core/Definitions.scala b/src/dotty/tools/dotc/core/Definitions.scala index 7de254008..3c36b1a1e 100644 --- a/src/dotty/tools/dotc/core/Definitions.scala +++ b/src/dotty/tools/dotc/core/Definitions.scala @@ -4,7 +4,7 @@ package core import Types._, Contexts._, Symbols._, Denotations._, SymDenotations._, StdNames._, Names._ import Flags._, Scopes._, Decorators._, NameOps._, util.Positions._ -import pickling.UnPickler.ensureConstructor +import pickling.Scala2Unpickler.ensureConstructor import scala.annotation.{ switch, meta } import scala.collection.{ mutable, immutable } import PartialFunction._ @@ -99,7 +99,8 @@ class Definitions { lazy val RootPackage: TermSymbol = ctx.newSymbol( NoSymbol, nme.ROOTPKG, PackageCreationFlags, TypeRef(NoPrefix, RootClass)) - lazy val EmptyPackageVal = ctx.newCompletePackageSymbol(RootClass, nme.EMPTY_PACKAGE).entered + lazy val EmptyPackageVal = ctx.newPackageSymbol( + RootClass, nme.EMPTY_PACKAGE, (emptypkg, emptycls) => ctx.rootLoader(emptypkg)).entered lazy val EmptyPackageClass = EmptyPackageVal.moduleClass.asClass /** A package in which we can place all methods that are interpreted specially by the compiler */ diff --git a/src/dotty/tools/dotc/core/SymbolLoaders.scala b/src/dotty/tools/dotc/core/SymbolLoaders.scala index 0e8c9a41d..296c4ad1e 100644 --- a/src/dotty/tools/dotc/core/SymbolLoaders.scala +++ b/src/dotty/tools/dotc/core/SymbolLoaders.scala @@ -251,7 +251,10 @@ class ClassfileLoader(val classfile: AbstractFile) extends SymbolLoader { else (rootDenot, linkedDenot) } - def doComplete(root: SymDenotation)(implicit ctx: Context): Unit = { + override def doComplete(root: SymDenotation)(implicit ctx: Context): Unit = + load(root) + + def load(root: SymDenotation)(implicit ctx: Context): Option[ClassfileParser.Embedded] = { val (classRoot, moduleRoot) = rootDenots(root.asClass) new ClassfileParser(classfile, classRoot, moduleRoot)(ctx).run() } diff --git a/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala b/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala index 21c9aa84d..918a97476 100644 --- a/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala +++ b/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala @@ -4,7 +4,7 @@ package core package pickling import Contexts._, Symbols._, Types._, Names._, StdNames._, NameOps._, Scopes._, Decorators._ -import SymDenotations._, UnPickler._, Constants._, Annotations._, util.Positions._ +import SymDenotations._, Scala2Unpickler._, Constants._, Annotations._, util.Positions._ import ast.tpd._ import java.io.{ File, IOException } import java.lang.Integer.toHexString @@ -15,12 +15,18 @@ import typer.Checking.checkNonCyclic import io.AbstractFile import scala.util.control.NonFatal +object ClassfileParser { + /** Marker trait for unpicklers that can be embedded in classfiles. */ + trait Embedded +} + class ClassfileParser( classfile: AbstractFile, classRoot: ClassDenotation, moduleRoot: ClassDenotation)(ictx: Context) { import ClassfileConstants._ + import ClassfileParser._ protected val in = new AbstractFileReader(classfile) @@ -41,7 +47,7 @@ class ClassfileParser( private def mismatchError(c: Symbol) = throw new IOException(s"class file '${in.file}' has location not matching its contents: contains $c") - def run()(implicit ctx: Context): Unit = try { + def run()(implicit ctx: Context): Option[Embedded] = try { ctx.debuglog("[class] >> " + classRoot.fullName) parseHeader this.pool = new ConstantPool @@ -80,7 +86,7 @@ class ClassfileParser( var sawPrivateConstructor = false - def parseClass()(implicit ctx: Context): Unit = { + def parseClass()(implicit ctx: Context): Option[Embedded] = { val jflags = in.nextChar val isAnnotation = hasAnnotation(jflags) val sflags = FlagTranslation.classFlags(jflags) @@ -94,8 +100,6 @@ class ClassfileParser( addEnclosingTParams() - if (unpickleOrParseInnerClasses()) return - /** Parse parents for Java classes. For Scala, return AnyRef, since the real type will be unpickled. * Updates the read pointer of 'in'. */ def parseParents: List[Type] = { @@ -114,33 +118,36 @@ class ClassfileParser( superType :: ifaces } - var classInfo: Type = TempClassInfoType(parseParents, instanceScope, classRoot.symbol) + val result = unpickleOrParseInnerClasses() + if (!result.isDefined) { + var classInfo: Type = TempClassInfoType(parseParents, instanceScope, classRoot.symbol) // might be reassigned by later parseAttributes - val staticInfo = TempClassInfoType(List(), staticScope, moduleRoot.symbol) + val staticInfo = TempClassInfoType(List(), staticScope, moduleRoot.symbol) - enterOwnInnerClasses + enterOwnInnerClasses - classRoot.setFlag(sflags) - moduleRoot.setFlag(Flags.JavaDefined | Flags.ModuleClassCreationFlags) - setPrivateWithin(classRoot, jflags) - setPrivateWithin(moduleRoot, jflags) - setPrivateWithin(moduleRoot.sourceModule, jflags) + classRoot.setFlag(sflags) + moduleRoot.setFlag(Flags.JavaDefined | Flags.ModuleClassCreationFlags) + setPrivateWithin(classRoot, jflags) + setPrivateWithin(moduleRoot, jflags) + setPrivateWithin(moduleRoot.sourceModule, jflags) - for (i <- 0 until in.nextChar) parseMember(method = false) - for (i <- 0 until in.nextChar) parseMember(method = true) - classInfo = parseAttributes(classRoot.symbol, classInfo) - if (isAnnotation) addAnnotationConstructor(classInfo) + for (i <- 0 until in.nextChar) parseMember(method = false) + for (i <- 0 until in.nextChar) parseMember(method = true) + classInfo = parseAttributes(classRoot.symbol, classInfo) + if (isAnnotation) addAnnotationConstructor(classInfo) - val companionClassMethod = ctx.synthesizeCompanionMethod(nme.COMPANION_CLASS_METHOD, classRoot, moduleRoot) - if (companionClassMethod.exists) companionClassMethod.entered - val companionModuleMethod = ctx.synthesizeCompanionMethod(nme.COMPANION_MODULE_METHOD, moduleRoot, classRoot) - if (companionModuleMethod.exists) companionModuleMethod.entered + val companionClassMethod = ctx.synthesizeCompanionMethod(nme.COMPANION_CLASS_METHOD, classRoot, moduleRoot) + if (companionClassMethod.exists) companionClassMethod.entered + val companionModuleMethod = ctx.synthesizeCompanionMethod(nme.COMPANION_MODULE_METHOD, moduleRoot, classRoot) + if (companionModuleMethod.exists) companionModuleMethod.entered - setClassInfo(classRoot, classInfo) - setClassInfo(moduleRoot, staticInfo) + setClassInfo(classRoot, classInfo) + setClassInfo(moduleRoot, staticInfo) + } + result } - /** Add type parameters of enclosing classes */ def addEnclosingTParams()(implicit ctx: Context): Unit = { var sym = classRoot.owner @@ -644,7 +651,7 @@ class ClassfileParser( * Restores the old `bp`. * @return true iff classfile is from Scala, so no Java info needs to be read. */ - def unpickleOrParseInnerClasses()(implicit ctx: Context): Boolean = { + def unpickleOrParseInnerClasses()(implicit ctx: Context): Option[Embedded] = { val oldbp = in.bp try { skipSuperclasses() @@ -664,15 +671,16 @@ class ClassfileParser( i < attrs } - def unpickleScala(bytes: Array[Byte]): Boolean = { - new UnPickler(bytes, classRoot, moduleRoot)(ctx).run() - true + def unpickleScala(bytes: Array[Byte]): Some[Embedded] = { + val unpickler = new Scala2Unpickler(bytes, classRoot, moduleRoot)(ctx) + unpickler.run() + Some(unpickler) } - def unpickleTASTY(bytes: Array[Byte]): Boolean = { - new DottyUnpickler(bytes) - .enter(roots = Set(classRoot, moduleRoot, moduleRoot.sourceModule)) - true + def unpickleTASTY(bytes: Array[Byte]): Some[Embedded] = { + val unpickler = new DottyUnpickler(bytes) + unpickler.enter(roots = Set(classRoot, moduleRoot, moduleRoot.sourceModule)) + Some(unpickler) } def parseScalaSigBytes: Array[Byte] = { @@ -739,7 +747,7 @@ class ClassfileParser( } } } - false + None } finally in.bp = oldbp } diff --git a/src/dotty/tools/dotc/core/pickling/DottyUnpickler.scala b/src/dotty/tools/dotc/core/pickling/DottyUnpickler.scala index 64be68975..2d8f571ec 100644 --- a/src/dotty/tools/dotc/core/pickling/DottyUnpickler.scala +++ b/src/dotty/tools/dotc/core/pickling/DottyUnpickler.scala @@ -7,6 +7,7 @@ import Contexts._, SymDenotations._ import dotty.tools.dotc.ast.tpd import TastyUnpickler._, TastyBuffer._ import util.Positions._ +import util.{SourceFile, NoSource} import PositionUnpickler._ object DottyUnpickler { @@ -18,7 +19,7 @@ object DottyUnpickler { /** A class for unpickling Tasty trees and symbols. * @param bytes the bytearray containing the Tasty file from which we unpickle */ -class DottyUnpickler(bytes: Array[Byte]) { +class DottyUnpickler(bytes: Array[Byte]) extends ClassfileParser.Embedded { import tpd._ private val unpickler = new TastyUnpickler(bytes) @@ -30,14 +31,20 @@ class DottyUnpickler(bytes: Array[Byte]) { def enter(roots: Set[SymDenotation])(implicit ctx: Context): Unit = treeUnpickler.enterTopLevel(roots) - /** The unpickled trees + /** The unpickled trees, and the source file they come from * @param readPositions if true, trees get decorated with position information. */ - def body(readPositions: Boolean = false)(implicit ctx: Context): List[Tree] = { + def body(readPositions: Boolean = false)(implicit ctx: Context): (List[Tree], SourceFile) = { + val source = unpickler.unpickle(new SourceFileUnpickler).getOrElse(NoSource) if (readPositions) - for ((totalRange, positions) <- unpickler.unpickle(new PositionsSectionUnpickler())) + for ((totalRange, positions) <- unpickler.unpickle(new PositionsSectionUnpickler)) treeUnpickler.usePositions(totalRange, positions) - treeUnpickler.unpickle() + (treeUnpickler.unpickle(), source) + } + + private class SourceFileUnpickler extends SectionUnpickler[SourceFile]("Sourcefile") { + def unpickle(reader: TastyReader, tastyName: TastyName.Table) = + new SourceFile(tastyName(reader.readNameRef()).toString, Seq()) } private class TreeSectionUnpickler extends SectionUnpickler[TreeUnpickler]("ASTs") { diff --git a/src/dotty/tools/dotc/core/pickling/PickleFormat.scala b/src/dotty/tools/dotc/core/pickling/PickleFormat.scala index d12a879ba..4f3841212 100644 --- a/src/dotty/tools/dotc/core/pickling/PickleFormat.scala +++ b/src/dotty/tools/dotc/core/pickling/PickleFormat.scala @@ -185,6 +185,8 @@ Note: Tree tags are grouped into 5 categories that determine what follows, and t Category 4 (tags 112-127): tag Nat AST Category 5 (tags 128-255): tag Length <payload> +Standard Section: "Sourcefile" sourcefile_NameRef + Standard Section: "Positions" sourceLength_Nat Assoc* Assoc = addr_Delta offset_Delta offset_Delta? diff --git a/src/dotty/tools/dotc/core/pickling/UnPickler.scala b/src/dotty/tools/dotc/core/pickling/Scala2Unpickler.scala index 3c3ec4a70..5fbb4b57f 100644 --- a/src/dotty/tools/dotc/core/pickling/UnPickler.scala +++ b/src/dotty/tools/dotc/core/pickling/Scala2Unpickler.scala @@ -24,7 +24,7 @@ import scala.collection.{ mutable, immutable } import scala.collection.mutable.ListBuffer import scala.annotation.switch -object UnPickler { +object Scala2Unpickler { /** Exception thrown if classfile is corrupted */ class BadSignature(msg: String) extends RuntimeException(msg) @@ -147,8 +147,8 @@ object UnPickler { * @param moduleroot the top-level module class which is unpickled, or NoSymbol if inapplicable * @param filename filename associated with bytearray, only used for error messages */ -class UnPickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClassRoot: ClassDenotation)(ictx: Context) - extends PickleBuffer(bytes, 0, -1) { +class Scala2Unpickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClassRoot: ClassDenotation)(ictx: Context) + extends PickleBuffer(bytes, 0, -1) with ClassfileParser.Embedded { def showPickled() = { atReadPos(0, () => { @@ -159,7 +159,7 @@ class UnPickler(bytes: Array[Byte], classRoot: ClassDenotation, moduleClassRoot: // print("unpickling "); showPickled() // !!! DEBUG - import UnPickler._ + import Scala2Unpickler._ val moduleRoot = moduleClassRoot.sourceModule(ictx).denot(ictx) assert(moduleRoot.isTerm) diff --git a/src/dotty/tools/dotc/core/pickling/TastyPickler.scala b/src/dotty/tools/dotc/core/pickling/TastyPickler.scala index 6bd6f1c44..74cc72b8c 100644 --- a/src/dotty/tools/dotc/core/pickling/TastyPickler.scala +++ b/src/dotty/tools/dotc/core/pickling/TastyPickler.scala @@ -7,6 +7,8 @@ import PickleFormat._ import collection.mutable import TastyBuffer._ import java.util.UUID +import core.Symbols.Symbol +import ast.tpd class TastyPickler { @@ -51,4 +53,18 @@ class TastyPickler { assert(all.length == totalSize && all.bytes.length == totalSize, s"totalSize = $totalSize, all.length = ${all.length}, all.bytes.length = ${all.bytes.length}") all.bytes } + + /** + * Addresses in TASTY file of trees, stored by pickling. + * Note that trees are checked for reference equality, + * so one can reliably use this function only directly after `pickler` + */ + var addrOfTree: tpd.Tree => Option[Addr] = (_ => None) + + /** + * Addresses in TASTY file of symbols, stored by pickling. + * Note that trees are checked for reference equality, + * so one can reliably use this function only dirrectly after `pickler` + */ + var addrOfSym: Symbol => Option[Addr] = (_ => None) } diff --git a/src/dotty/tools/dotc/core/pickling/TreeUnpickler.scala b/src/dotty/tools/dotc/core/pickling/TreeUnpickler.scala index ba3023ed1..7b143dfad 100644 --- a/src/dotty/tools/dotc/core/pickling/TreeUnpickler.scala +++ b/src/dotty/tools/dotc/core/pickling/TreeUnpickler.scala @@ -338,7 +338,7 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) { name.isTermName && !name.isConstructorName && !givenFlags.is(ParamOrAccessor) || isAbstractType var flags = givenFlags - if (lacksDefinition) flags |= Deferred + if (lacksDefinition && tag != PARAM) flags |= Deferred if (tag == DEFDEF) flags |= Method if (givenFlags is Module) flags = flags | (if (tag == VALDEF) ModuleCreationFlags else ModuleClassCreationFlags) @@ -860,11 +860,12 @@ class TreeUnpickler(reader: TastyReader, tastyName: TastyName.Table) { } } - private def setNormalized(tree: Tree, parentPos: Position): Unit = { - assert(tree.pos.exists) - val absPos = Position(parentPos.start + offsetToInt(tree.pos.start), parentPos.end - tree.pos.end) - tree.setPosUnchecked(absPos) - } + private def setNormalized(tree: Tree, parentPos: Position): Unit = + tree.setPosUnchecked( + if (tree.pos.exists) + Position(parentPos.start + offsetToInt(tree.pos.start), parentPos.end - tree.pos.end) + else + parentPos) def normalizePos(x: Any, parentPos: Position)(implicit ctx: Context): Unit = traverse(x, parentPos, setNormalized) |