aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2015-02-19 14:57:51 +0100
committerDmitry Petrashko <dmitry.petrashko@gmail.com>2015-03-18 11:14:08 +0100
commit82f1ac6c326fc0a60b04b05e46c3e5e837249e64 (patch)
treebbbdb6dfafa3df664bffea3eac49fb9faff3c0bc /src/dotty/tools
parent30f08b095192435b080afe4b1734b8ce48039f84 (diff)
downloaddotty-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')
-rw-r--r--src/dotty/tools/dotc/core/pickling/TastyBuffer.scala2
-rw-r--r--src/dotty/tools/dotc/core/pickling/TastyPrinter.scala6
-rw-r--r--src/dotty/tools/dotc/core/pickling/TastyReader.scala70
-rw-r--r--src/dotty/tools/dotc/core/pickling/TastyUnpickler.scala10
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)
}
}