diff options
author | Martin Odersky <odersky@gmail.com> | 2015-04-29 10:36:16 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2015-05-02 19:23:08 +0200 |
commit | 60ab9f8f525d319aa5b6d5052018c6781da036eb (patch) | |
tree | fbc5096a1f7193a4970226a7ad6f03fbf7670a4b /src/dotty/tools/dotc/core/tasty/TastyUnpickler.scala | |
parent | ac46a0e4489bba4f76863cc1491bf2b8441ed1cb (diff) | |
download | dotty-60ab9f8f525d319aa5b6d5052018c6781da036eb.tar.gz dotty-60ab9f8f525d319aa5b6d5052018c6781da036eb.tar.bz2 dotty-60ab9f8f525d319aa5b6d5052018c6781da036eb.zip |
Pickling modularization reorg
The pickling package got rather large and confusing with three
separate tasks that each had their own conventions: read JVM classfiles,
read Scala2 pickle info, read Tasty. The classes for each task are now in
separate packages.
Diffstat (limited to 'src/dotty/tools/dotc/core/tasty/TastyUnpickler.scala')
-rw-r--r-- | src/dotty/tools/dotc/core/tasty/TastyUnpickler.scala | 95 |
1 files changed, 95 insertions, 0 deletions
diff --git a/src/dotty/tools/dotc/core/tasty/TastyUnpickler.scala b/src/dotty/tools/dotc/core/tasty/TastyUnpickler.scala new file mode 100644 index 000000000..8a1f58acd --- /dev/null +++ b/src/dotty/tools/dotc/core/tasty/TastyUnpickler.scala @@ -0,0 +1,95 @@ +package dotty.tools.dotc +package core +package tasty + +import scala.collection.mutable +import TastyFormat._ +import Names.{Name, termName} +import java.util.UUID + +object TastyUnpickler { + class UnpickleException(msg: String) extends Exception(msg) + + abstract class SectionUnpickler[R](val name: String) { + def unpickle(reader: TastyReader, tastyName: TastyName.Table): R + } +} + +import TastyUnpickler._ + +class TastyUnpickler(reader: TastyReader) { + import reader._ + + def this(bytes: Array[Byte]) = this(new TastyReader(bytes)) + + private val sectionReader = new mutable.HashMap[String, TastyReader] + val tastyName = new TastyName.Table + + def check(cond: Boolean, msg: => String) = + if (!cond) throw new UnpickleException(msg) + + def readString(): String = { + val TastyName.Simple(name) = tastyName(readNameRef()) + name.toString + } + + def readName(): TastyName = { + import TastyName._ + val tag = readByte() + val length = readNat() + val start = currentAddr + val end = start + length + val result = tag match { + case UTF8 => + goto(end) + Simple(termName(bytes, start.index, length)) + case QUALIFIED => + Qualified(readNameRef(), readNameRef()) + case SIGNED => + val original = readNameRef() + val result = readNameRef() + val params = until(end)(readNameRef()) + Signed(original, params, result) + case EXPANDED => + Expanded(readNameRef(), readNameRef()) + case OBJECTCLASS => + ModuleClass(readNameRef()) + case SUPERACCESSOR => + SuperAccessor(readNameRef()) + case DEFAULTGETTER => + DefaultGetter(readNameRef(), readNat()) + case SHADOWED => + Shadowed(readNameRef()) + } + assert(currentAddr == end, s"bad name $result $start $currentAddr $end") + result + } + + private def readHeader(): UUID = { + for (i <- 0 until header.length) + check(readByte() == header(i), "not a TASTy file") + val major = readNat() + val minor = readNat() + check(major == MajorVersion && minor <= MinorVersion, + s"""TASTy signature has wrong version. + | expected: $MajorVersion.$MinorVersion + | found : $major.$minor""".stripMargin) + new UUID(readUncompressedLong(), readUncompressedLong()) + } + + val uuid = readHeader() + + locally { + until(readEnd()) { tastyName.add(readName()) } + while (!isAtEnd) { + val secName = readString() + val secEnd = readEnd() + sectionReader(secName) = new TastyReader(bytes, currentAddr.index, secEnd.index, currentAddr.index) + goto(secEnd) + } + } + + def unpickle[R](sec: SectionUnpickler[R]): Option[R] = + for (reader <- sectionReader.get(sec.name)) yield + sec.unpickle(reader, tastyName) +} |