diff options
author | Martin Odersky <odersky@gmail.com> | 2015-02-19 14:57:51 +0100 |
---|---|---|
committer | Dmitry Petrashko <dmitry.petrashko@gmail.com> | 2015-03-18 11:14:08 +0100 |
commit | 82f1ac6c326fc0a60b04b05e46c3e5e837249e64 (patch) | |
tree | bbbdb6dfafa3df664bffea3eac49fb9faff3c0bc /src/dotty/tools | |
parent | 30f08b095192435b080afe4b1734b8ce48039f84 (diff) | |
download | dotty-82f1ac6c326fc0a60b04b05e46c3e5e837249e64.tar.gz dotty-82f1ac6c326fc0a60b04b05e46c3e5e837249e64.tar.bz2 dotty-82f1ac6c326fc0a60b04b05e46c3e5e837249e64.zip |
Polishings on TastyReader
In particular: Allow for Addr(0) to point to
the middle of the `bytes` array. Needed so that
we can read trees without copying the bytes representing
trees into a fresh array.
Diffstat (limited to 'src/dotty/tools')
4 files changed, 62 insertions, 26 deletions
diff --git a/src/dotty/tools/dotc/core/pickling/TastyBuffer.scala b/src/dotty/tools/dotc/core/pickling/TastyBuffer.scala index ba033461e..1c0f6e24f 100644 --- a/src/dotty/tools/dotc/core/pickling/TastyBuffer.scala +++ b/src/dotty/tools/dotc/core/pickling/TastyBuffer.scala @@ -21,7 +21,7 @@ object TastyBuffer { /** The maximal number of address bytes. * Since addresses are written as base-128 natural numbers, - * the value of 4 gives a maximal array size of 512M. + * the value of 4 gives a maximal array size of 256M. */ final val AddrWidth = 4 } diff --git a/src/dotty/tools/dotc/core/pickling/TastyPrinter.scala b/src/dotty/tools/dotc/core/pickling/TastyPrinter.scala index a4d1554f8..7f77d821b 100644 --- a/src/dotty/tools/dotc/core/pickling/TastyPrinter.scala +++ b/src/dotty/tools/dotc/core/pickling/TastyPrinter.scala @@ -40,9 +40,9 @@ class TastyPrinter(bytes: Array[Byte])(implicit ctx: Context) { import PickleFormat._ def unpickle(reader: TastyReader, tastyName: TastyName.Table): Text = { import reader._ - val sb = new StringBuilder(s"${reader.end.index - reader.from.index} bytes of AST:") + val sb = new StringBuilder(s"${startAddr.index - endAddr.index} bytes of AST:") var indent = 0 - def newLine() = print(f"\n ${currentAddr.index - from.index}%5d:" + " " * indent) + def newLine() = print(f"\n ${currentAddr.index - startAddr.index}%5d:" + " " * indent) def printNat() = print(" " + readNat()) def printName() = { val idx = readNat() @@ -96,7 +96,7 @@ class TastyPrinter(bytes: Array[Byte])(implicit ctx: Context) { indent -= 2 } println(s"base = $currentAddr") - while (!atEnd) { + while (!isAtEnd) { printTree() newLine() } diff --git a/src/dotty/tools/dotc/core/pickling/TastyReader.scala b/src/dotty/tools/dotc/core/pickling/TastyReader.scala index 659eb8977..4e1acf9a9 100644 --- a/src/dotty/tools/dotc/core/pickling/TastyReader.scala +++ b/src/dotty/tools/dotc/core/pickling/TastyReader.scala @@ -8,18 +8,40 @@ import TastyBuffer._ import TastyName.NameRef import collection.mutable -/** A byte array bufferfer that can be filled with bytes or natural numbers in TASTY format, +/** A byte array buffer that can be filled with bytes or natural numbers in TASTY format, * and that supports reading and patching addresses represented as natural numbers. + * + * @param bytes The array containing data + * @param from The position from which to read + * @param end The position one greater than the last byte to be read + * @param base The index referenced by the logical zero address Addr(0) */ -class TastyReader(val bytes: Array[Byte], val from: Addr, val end: Addr) { +class TastyReader(val bytes: Array[Byte], start: Int, end: Int, val base: Int = 0) { - def this(bytes: Array[Byte]) = this(bytes, Addr(0), Addr(bytes.length)) + def this(bytes: Array[Byte]) = this(bytes, 0, bytes.length) - private var bp: Int = from.index + private var bp: Int = start - def currentAddr: Addr = Addr(bp) + def addr(idx: Int) = Addr(idx - base) + def index(addr: Addr) = addr.index + base + + /** The address of the first byte to read, respectively byte that was read */ + def startAddr: Addr = addr(start) + + /** The address of the next byte to read */ + def currentAddr: Addr = addr(bp) + + /** the address one greater than the last brte to read */ + def endAddr: Addr = addr(end) - def atEnd: Boolean = bp == end.index + /** Have all bytes been read? */ + def isAtEnd: Boolean = bp == end + + /** A new reader over the same array with the same address base, but with + * specified start and end positions + */ + def subReader(start: Addr, end: Addr): TastyReader = + new TastyReader(bytes, index(start), index(end), base) /** Read a byte of data. */ def readByte(): Int = { @@ -28,6 +50,9 @@ class TastyReader(val bytes: Array[Byte], val from: Addr, val end: Addr) { result } + /** Returns the next byte of data to read without advancing the read position */ + def nextByte: Int = bytes(bp) + /** Read the next `n` bytes of `data`. */ def readBytes(n: Int): Array[Byte] = { val result = new Array[Byte](n) @@ -54,25 +79,34 @@ class TastyReader(val bytes: Array[Byte], val from: Addr, val end: Addr) { } while ((b & 0x80) == 0) x } - - /** Read `nbytes` bytes in big endian format into a Long */ - def readRaw(nbytes: Int): Unit = { - def recur(x: Long, n: Int): Long = - if (n == 0) x else recur((x << 8) | (readByte & 0xff), n - 1) - recur(0, nbytes) - } - + + /** Read a natural number and return as a NameRef */ def readNameRef() = NameRef(readNat()) + /** Read a natural number and return as an address */ + def readAddr() = Addr(readNat()) + + /** Read a length number and return the absolute end address implied by it, + * given as <address following length field> + <length-value-read>. + */ def readEnd(): Addr = Addr(readNat() + bp) + /** Set read position to the one pointed to by `addr` */ def skipTo(addr: Addr): Unit = - bp = addr.index - + bp = index(addr) + + /** Perform `op` until `end` address is reached and collect results in a list. */ def until[T](end: Addr)(op: => T): List[T] = { val buf = new mutable.ListBuffer[T] - while (bp < end.index) buf += op - assert(bp == end.index) + while (bp < index(end)) buf += op + assert(bp == index(end)) + buf.toList + } + + /** Perform `op` while cindition `cond` holds and collect results in a list. */ + def collectWhile[T](cond: => Boolean)(op: => T): List[T] = { + val buf = new mutable.ListBuffer[T] + while (cond) buf += op buf.toList } } diff --git a/src/dotty/tools/dotc/core/pickling/TastyUnpickler.scala b/src/dotty/tools/dotc/core/pickling/TastyUnpickler.scala index 422ce292a..f2d075446 100644 --- a/src/dotty/tools/dotc/core/pickling/TastyUnpickler.scala +++ b/src/dotty/tools/dotc/core/pickling/TastyUnpickler.scala @@ -67,15 +67,17 @@ class TastyUnpickler(reader: TastyReader) { check(magic.map(_.toChar).mkString == header, "not a TASTy file") val major = readNat() val minor = readNat() - check(major == MajorVersion && (major != 0 || minor == MinorVersion), + def versionMsg = s"""TASTy signature has wrong version. | expected: $MajorVersion.$MinorVersion - | found : $major.$minor""".stripMargin) + | found : $major.$minor""".stripMargin + check(major == MajorVersion, versionMsg) + if (MajorVersion == 0) check(minor == MinorVersion, versionMsg) until(readEnd()) { tastyName.add(readName()) } - while (!atEnd) { + while (!isAtEnd) { val secName = readString() val secEnd = readEnd() - sectionReader(secName) = new TastyReader(bytes, currentAddr, secEnd) + sectionReader(secName) = new TastyReader(bytes, currentAddr.index, secEnd.index, currentAddr.index) skipTo(secEnd) } } |