diff options
author | Martin Odersky <odersky@gmail.com> | 2013-03-13 14:11:44 +0100 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2013-03-13 14:11:44 +0100 |
commit | 3c7a8eada3630989b07bd3022797fd42a3b8cfcc (patch) | |
tree | 0036fee8aa025e3eea8502ea08f413f6baec3a56 /src/dotty/tools/dotc/util/ShowPickled.scala | |
parent | d1794c15f5a5743763adeb8f8e248f9ca5f53869 (diff) | |
download | dotty-3c7a8eada3630989b07bd3022797fd42a3b8cfcc.tar.gz dotty-3c7a8eada3630989b07bd3022797fd42a3b8cfcc.tar.bz2 dotty-3c7a8eada3630989b07bd3022797fd42a3b8cfcc.zip |
Various fixes to get past Definitions#init.
Diffstat (limited to 'src/dotty/tools/dotc/util/ShowPickled.scala')
-rw-r--r-- | src/dotty/tools/dotc/util/ShowPickled.scala | 294 |
1 files changed, 294 insertions, 0 deletions
diff --git a/src/dotty/tools/dotc/util/ShowPickled.scala b/src/dotty/tools/dotc/util/ShowPickled.scala new file mode 100644 index 000000000..ab2801127 --- /dev/null +++ b/src/dotty/tools/dotc/util/ShowPickled.scala @@ -0,0 +1,294 @@ +package dotty.tools.dotc +package util + +import java.io.{File, FileInputStream, PrintStream} +import java.lang.Long.toHexString +import java.lang.Float.intBitsToFloat +import java.lang.Double.longBitsToDouble +import scala.reflect.internal.Flags +import scala.reflect.internal.pickling.PickleFormat +import core.pickling.PickleBuffer +import core.Names._ + +object ShowPickled { + 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 sys.error("%s is no name" format tagName) + def nameIndex = + if (hasName) readNat(bytes, 0) + else sys.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" + case NONEsym => "NONEsym" + case TYPEsym => "TYPEsym" + case ALIASsym => "ALIASsym" + case CLASSsym => "CLASSsym" + case MODULEsym => "MODULEsym" + case VALsym => "VALsym" + case EXTref => "EXTref" + case EXTMODCLASSref => "EXTMODCLASSref" + case NOtpe => "NOtpe" + case NOPREFIXtpe => "NOPREFIXtpe" + case THIStpe => "THIStpe" + case SINGLEtpe => "SINGLEtpe" + case CONSTANTtpe => "CONSTANTtpe" + case TYPEREFtpe => "TYPEREFtpe" + case TYPEBOUNDStpe => "TYPEBOUNDStpe" + case REFINEDtpe => "REFINEDtpe" + case CLASSINFOtpe => "CLASSINFOtpe" + case METHODtpe => "METHODtpe" + case POLYtpe => "POLYtpe" + case IMPLICITMETHODtpe => "METHODtpe" // IMPLICITMETHODtpe no longer used. + case SUPERtpe => "SUPERtpe" + case LITERALunit => "LITERALunit" + case LITERALboolean => "LITERALboolean" + case LITERALbyte => "LITERALbyte" + case LITERALshort => "LITERALshort" + case LITERALchar => "LITERALchar" + case LITERALint => "LITERALint" + case LITERALlong => "LITERALlong" + case LITERALfloat => "LITERALfloat" + case LITERALdouble => "LITERALdouble" + case LITERALstring => "LITERALstring" + case LITERALnull => "LITERALnull" + case LITERALclass => "LITERALclass" + case LITERALenum => "LITERALenum" + case SYMANNOT => "SYMANNOT" + case CHILDREN => "CHILDREN" + case ANNOTATEDtpe => "ANNOTATEDtpe" + case ANNOTINFO => "ANNOTINFO" + case ANNOTARGARRAY => "ANNOTARGARRAY" + // case DEBRUIJNINDEXtpe => "DEBRUIJNINDEXtpe" + case EXISTENTIALtpe => "EXISTENTIALtpe" + case TREE => "TREE" + case MODIFIERS => "MODIFIERS" + + 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 = System.out) { + out.println("Version " + buf.readNat() + "." + buf.readNat()) + val index = buf.createIndex + val entryList = makeEntryList(buf, index) + buf.readIndex = 0 + + def p(s: String) = out print s + + def printNameRef() { + val idx = buf.readNat() + val name = entryList nameAt idx + val toPrint = " %s(%s)".format(idx, name) + + out print toPrint + } + + def printNat() = p(" " + buf.readNat()) + def printReadNat(x: Int) = p(" " + x) + + def printSymbolRef() = printNat() + def printTypeRef() = printNat() + def printConstantRef() = printNat() + def printAnnotInfoRef() = printNat() + def printConstAnnotArgRef() = printNat() + def printAnnotArgRef() = printNat() + + def printSymInfo(end: Int) { + printNameRef() + printSymbolRef() + val pflags = buf.readLongNat() + def printFlags(privateWithin: Option[Int]) = { + val accessBoundary = ( + for (idx <- privateWithin) yield { + val s = entryList nameAt idx + 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 + * interpreted are for the most part going to tell you the wrong thing. + * It's not so easy to duplicate the logic applied in the UnPickler. + */ + def printEntry(i: Int) { + buf.readIndex = index(i) + p(i + "," + buf.readIndex + ": ") + val tag = buf.readByte() + out.print(tag2string(tag)) + val len = buf.readNat() + val end = len + buf.readIndex + p(" " + len + ":") + tag match { + case TERMname => + out.print(" ") + out.print(termName(buf.bytes, buf.readIndex, len).toString) + buf.readIndex = end + case TYPEname => + out.print(" ") + out.print(typeName(buf.bytes, buf.readIndex, len)) + buf.readIndex = end + case TYPEsym | ALIASsym | CLASSsym | MODULEsym | VALsym => + printSymInfo(end) + if (tag == CLASSsym && (buf.readIndex < end)) printTypeRef() + case EXTref | EXTMODCLASSref => + printNameRef() + if (buf.readIndex < end) { printSymbolRef() } + case THIStpe => + printSymbolRef() + case SINGLEtpe => + printTypeRef(); printSymbolRef() + case CONSTANTtpe => + printTypeRef(); printConstantRef() + case TYPEREFtpe => + printTypeRef(); printSymbolRef(); buf.until(end, printTypeRef) + case TYPEBOUNDStpe => + printTypeRef(); printTypeRef() + case REFINEDtpe => + printSymbolRef(); buf.until(end, printTypeRef) + case CLASSINFOtpe => + printSymbolRef(); buf.until(end, printTypeRef) + case METHODtpe | IMPLICITMETHODtpe => + printTypeRef(); buf.until(end, printTypeRef) + case POLYtpe => + printTypeRef(); buf.until(end, printSymbolRef) + case LITERALboolean => + out.print(if (buf.readLong(len) == 0L) " false" else " true") + case LITERALbyte => + out.print(" " + buf.readLong(len).toByte) + case LITERALshort => + out.print(" " + buf.readLong(len).toShort) + case LITERALchar => + out.print(" " + buf.readLong(len).toChar) + case LITERALint => + out.print(" " + buf.readLong(len).toInt) + case LITERALlong => + out.print(" " + buf.readLong(len)) + case LITERALfloat => + out.print(" " + intBitsToFloat(buf.readLong(len).toInt)) + case LITERALdouble => + out.print(" " + longBitsToDouble(buf.readLong(len))) + case LITERALstring => + printNameRef() + case LITERALenum => + printSymbolRef() + case LITERALnull => + out.print(" <null>") + case LITERALclass => + printTypeRef() + case CHILDREN => + printSymbolRef(); buf.until(end, printSymbolRef) + case SYMANNOT => + printSymbolRef(); printTypeRef(); buf.until(end, printAnnotArgRef) + case ANNOTATEDtpe => + printTypeRef(); buf.until(end, printAnnotInfoRef); + case ANNOTINFO => + printTypeRef(); buf.until(end, printAnnotArgRef) + case ANNOTARGARRAY => + buf.until(end, printConstAnnotArgRef) + case EXISTENTIALtpe => + printTypeRef(); buf.until(end, printSymbolRef) + + case _ => + } + out.println() + if (buf.readIndex != end) { + out.println("BAD ENTRY END: computed = %d, actual = %d, bytes = %s".format( + end, buf.readIndex, buf.bytes.slice(index(i), (end max buf.readIndex)).mkString(", ") + )) + } + } + + for (i <- 0 until index.length) printEntry(i) + } + +/* + * + def fromFile(path: String) = fromBytes(io.File(path).toByteArray) + def fromName(name: String) = fromBytes(scalaSigBytesForPath(name) getOrElse Array()) + def fromBytes(data: => Array[Byte]): Option[PickleBuffer] = + try Some(new PickleBuffer(data, 0, data.length)) + catch { case _: Exception => None } + + def show(what: String, pickle: PickleBuffer) = { + Console.println(what) + val saved = pickle.readIndex + pickle.readIndex = 0 + printFile(pickle, Console.out) + pickle.readIndex = saved + } + + def main(args: Array[String]) { + args foreach { arg => + (fromFile(arg) orElse fromName(arg)) match { + case Some(pb) => show(arg + ":", pb) + case _ => Console.println("Cannot read " + arg) + } + } + }*/ +} |