summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Phillips <paulp@improving.org>2010-03-01 19:47:48 +0000
committerPaul Phillips <paulp@improving.org>2010-03-01 19:47:48 +0000
commitdae85e321aaf121d83e2b3824e47ab7c525ed2cd (patch)
treeb95f73d67290f988fea78aa24bc6fbafa9a9ad55
parent9690b45b3be8a73228faa40d79adac1616c5ae38 (diff)
downloadscala-dae85e321aaf121d83e2b3824e47ab7c525ed2cd.tar.gz
scala-dae85e321aaf121d83e2b3824e47ab7c525ed2cd.tar.bz2
scala-dae85e321aaf121d83e2b3824e47ab7c525ed2cd.zip
Whipped ShowPickled until it would print out pr...
Whipped ShowPickled until it would print out private[scope] from the signature, and infrastructure created along the way. Only now at this late hour do I realize that this work would be a lot better aimed at creating a fake Universe and then adapting UnPickler.Scan so you can reuse the real logic. My advice to the next guy: do that instead. No review.
-rw-r--r--src/compiler/scala/tools/nsc/util/ShowPickled.scala100
-rwxr-xr-xsrc/library/scala/reflect/generic/PickleBuffer.scala23
2 files changed, 108 insertions, 15 deletions
diff --git a/src/compiler/scala/tools/nsc/util/ShowPickled.scala b/src/compiler/scala/tools/nsc/util/ShowPickled.scala
index bc33f2156b..260c048b8a 100644
--- a/src/compiler/scala/tools/nsc/util/ShowPickled.scala
+++ b/src/compiler/scala/tools/nsc/util/ShowPickled.scala
@@ -17,9 +17,42 @@ import scala.reflect.generic.{ PickleBuffer, PickleFormat }
import interpreter.ByteCode.scalaSigBytesForPath
object ShowPickled extends Names {
-
import PickleFormat._
+ case class PickleBufferEntry(num: Int, startIndex: Int, tag: Int, bytes: Array[Byte]) {
+ def isName = tag == TERMname || tag == TYPEname
+ def hasName = tag match {
+ case TYPEsym | ALIASsym | CLASSsym | MODULEsym | VALsym | EXTref | EXTMODCLASSref => true
+ case _ => false
+ }
+ def readName =
+ if (isName) new String(bytes, "UTF-8")
+ else error("%s is no name" format tagName)
+ def nameIndex =
+ if (hasName) readNat(bytes, 0)
+ else error("%s has no name" format tagName)
+
+ def tagName = tag2string(tag)
+ override def toString = "%d,%d: %s".format(num, startIndex, tagName)
+ }
+
+ case class PickleBufferEntryList(entries: IndexedSeq[PickleBufferEntry]) {
+ def nameAt(idx: Int) = {
+ val entry = entries(idx)
+ if (entry.isName) entry.readName
+ else if (entry.hasName) entries(entry.nameIndex).readName
+ else "?"
+ }
+ }
+
+ def makeEntryList(buf: PickleBuffer, index: Array[Int]) = {
+ val entries = buf.toIndexedSeq.zipWithIndex map {
+ case ((tag, data), num) => PickleBufferEntry(num, index(num), tag, data)
+ }
+
+ PickleBufferEntryList(entries)
+ }
+
def tag2string(tag: Int): String = tag match {
case TERMname => "TERMname"
case TYPEname => "TYPEname"
@@ -70,30 +103,42 @@ object ShowPickled extends Names {
case _ => "***BAD TAG***(" + tag + ")"
}
+ /** Extremely regrettably, essentially copied from PickleBuffer.
+ */
+ def readNat(data: Array[Byte], index: Int): Int = {
+ var idx = index
+ var result = 0L
+ var b = 0L
+ do {
+ b = data(idx)
+ idx += 1
+ result = (result << 7) + (b & 0x7f)
+ } while((b & 0x80) != 0L)
+
+ result.toInt
+ }
+
def printFile(buf: PickleBuffer, out: PrintStream): Unit = printFile(buf, out, false)
def printFile(buf: PickleBuffer, out: PrintStream, bare: Boolean) {
out.println("Version " + buf.readNat() + "." + buf.readNat())
val index = buf.createIndex
+ val entryList = makeEntryList(buf, index)
+ buf.readIndex = 0
/** A print wrapper which discards everything if bare is true.
*/
def p(s: String) = if (!bare) out print s
def printNameRef() {
- val x = buf.readNat()
- val savedIndex = buf.readIndex
- buf.readIndex = index(x)
- val tag = buf.readByte()
- val len = buf.readNat()
- val name = newTermName(buf.bytes, buf.readIndex, len)
+ val idx = buf.readNat()
+ val name = entryList nameAt idx
+ val toPrint = if (bare) " " + name else " %s(%s)".format(idx, name)
- val toPrint = if (bare) " " + name else " %s(%s)".format(x, name)
out print toPrint
-
- buf.readIndex = savedIndex
}
def printNat() = p(" " + buf.readNat())
+ def printReadNat(x: Int) = p(" " + x)
def printSymbolRef() = printNat()
def printTypeRef() = printNat()
@@ -102,13 +147,38 @@ object ShowPickled extends Names {
def printConstAnnotArgRef() = printNat()
def printAnnotArgRef() = printNat()
- def printSymInfo() {
+ def printSymInfo(end: Int) {
printNameRef()
printSymbolRef()
val pflags = buf.readLongNat()
- out.print(" " + toHexString(pflags) +
- "[" + Flags.flagsToString(Flags.pickledToRawFlags(pflags)) + "] ")
- printTypeRef()
+ def printFlags(privateWithin: Option[Int]) = {
+ val accessBoundary = (
+ for (idx <- privateWithin) yield {
+ val s = entryList nameAt idx
+ if (bare) s else idx + "(" + s + ")"
+ }
+ )
+ val flagString = {
+ val arg1 = Flags.pickledToRawFlags(pflags)
+ accessBoundary match {
+ case Some(pw) => Flags.flagsToString(arg1, pw)
+ case _ => Flags.flagsToString(arg1)
+ }
+ }
+
+ out.print(" %s[%s]".format(toHexString(pflags), flagString))
+ }
+
+ /** Might be info or privateWithin */
+ val x = buf.readNat()
+ if (buf.readIndex == end) {
+ printFlags(None)
+ printReadNat(x)
+ }
+ else {
+ printFlags(Some(x))
+ printTypeRef()
+ }
}
/** Note: the entries which require some semantic analysis to be correctly
@@ -133,7 +203,7 @@ object ShowPickled extends Names {
out.print(newTypeName(buf.bytes, buf.readIndex, len))
buf.readIndex = end
case TYPEsym | ALIASsym | CLASSsym | MODULEsym | VALsym =>
- printSymInfo()
+ printSymInfo(end)
if (tag == CLASSsym && (buf.readIndex < end)) printTypeRef()
case EXTref | EXTMODCLASSref =>
printNameRef()
diff --git a/src/library/scala/reflect/generic/PickleBuffer.scala b/src/library/scala/reflect/generic/PickleBuffer.scala
index 584b94578e..2fab02bcfe 100755
--- a/src/library/scala/reflect/generic/PickleBuffer.scala
+++ b/src/library/scala/reflect/generic/PickleBuffer.scala
@@ -128,6 +128,29 @@ class PickleBuffer(data: Array[Byte], from: Int, to: Int) {
x << leading >> leading
}
+ /** Returns the buffer as a sequence of (Int, Array[Byte]) representing
+ * (tag, data) of the individual entries. Saves and restores buffer state.
+ */
+
+ def toIndexedSeq: IndexedSeq[(Int, Array[Byte])] = {
+ val saved = readIndex
+ readIndex = 0
+ readNat() ; readNat() // discarding version
+ val result = new Array[(Int, Array[Byte])](readNat())
+
+ result.indices foreach { index =>
+ val tag = readNat()
+ val len = readNat()
+ val bytes = data.slice(readIndex, len + readIndex)
+ readIndex += len
+
+ result(index) = tag -> bytes
+ }
+
+ readIndex = saved
+ result.toIndexedSeq
+ }
+
/** Perform operation <code>op</code> until the condition
* <code>readIndex == end</code> is satisfied.
* Concatenate results into a list.