From f16b12c3a58bdd692089c23288a45a80f14332ab Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Mon, 23 Feb 2015 13:53:22 +0100 Subject: First version of position pickler. --- src/dotty/tools/dotc/core/pickling/Edge.scala | 22 ++++++++++ .../tools/dotc/core/pickling/PositionBuffer.scala | 33 ++++++++++++++ .../tools/dotc/core/pickling/PositionPickler.scala | 51 ++++++++++++++++++++++ .../tools/dotc/core/pickling/TastyPrinter.scala | 23 ++++++++++ src/dotty/tools/dotc/transform/Pickler.scala | 2 + 5 files changed, 131 insertions(+) create mode 100644 src/dotty/tools/dotc/core/pickling/Edge.scala create mode 100644 src/dotty/tools/dotc/core/pickling/PositionBuffer.scala create mode 100644 src/dotty/tools/dotc/core/pickling/PositionPickler.scala (limited to 'src/dotty') diff --git a/src/dotty/tools/dotc/core/pickling/Edge.scala b/src/dotty/tools/dotc/core/pickling/Edge.scala new file mode 100644 index 000000000..543f85831 --- /dev/null +++ b/src/dotty/tools/dotc/core/pickling/Edge.scala @@ -0,0 +1,22 @@ +package dotty.tools.dotc +package core.pickling + +import util.Positions._ +import ast.tpd._ +import core.Contexts._ + +abstract class Edge { + def offset(pos: Position): Int + def seq(op1: () => Unit, op2: () => Unit): Unit +} + +object Edge { + object left extends Edge { + def offset(pos: Position): Int = pos.start + def seq(op1: () => Unit, op2: () => Unit) = { op1(); op2() } + } + object right extends Edge { + def offset(pos: Position): Int = pos.end + def seq(op1: () => Unit, op2: () => Unit) = { op2(); op1() } + } +} \ No newline at end of file diff --git a/src/dotty/tools/dotc/core/pickling/PositionBuffer.scala b/src/dotty/tools/dotc/core/pickling/PositionBuffer.scala new file mode 100644 index 000000000..f564e364d --- /dev/null +++ b/src/dotty/tools/dotc/core/pickling/PositionBuffer.scala @@ -0,0 +1,33 @@ +package dotty.tools +package dotc +package core +package pickling + +import TastyBuffer.Addr + +class PositionBuffer extends TastyBuffer(100000) { thisBuffer => + + class PositionRecorder(val edge: Edge) extends TastyBuffer(thisBuffer.bytes.size / 2) { + private var lastOffset: Int = -1 + private var lastIndex: Int = 0 + def record(addr: Addr, offset: Int): Unit = + if (offset != lastOffset) { + if (lastOffset < 0) lastOffset = 0 + writeInt(offset - lastOffset) + writeInt(addr.index - lastIndex) + lastOffset = offset + lastIndex = addr.index + } + } + + val startPos = new PositionRecorder(Edge.left) + val endPos = new PositionRecorder(Edge.right) + + /** Final assembly: copy startPos and endPos into own bytes */ + override def assemble(): Unit = { + writeNat(startPos.length) + writeBytes(startPos.bytes, startPos.length) + writeNat(endPos.length) + writeBytes(endPos.bytes, endPos.length) + } +} \ No newline at end of file diff --git a/src/dotty/tools/dotc/core/pickling/PositionPickler.scala b/src/dotty/tools/dotc/core/pickling/PositionPickler.scala new file mode 100644 index 000000000..0cf519b23 --- /dev/null +++ b/src/dotty/tools/dotc/core/pickling/PositionPickler.scala @@ -0,0 +1,51 @@ +package dotty.tools +package dotc +package core +package pickling + +import ast.tpd._ +import PickleFormat._ +import core._ +import Contexts._, Symbols._, Types._, Names._, Constants._, Decorators._, Annotations._ +import collection.mutable +import TastyBuffer._ + +class PositionPickler(pickler: TastyPickler, addrOfTree: Tree => Option[Addr]) { + val buf = new PositionBuffer + pickler.newSection("Positions", buf) + import buf._ + + val noOp = () => () + + def traverseAll(root: Tree, recorder: PositionRecorder)(implicit ctx: Context) = { + import recorder.edge.{seq, offset} + + def elemsTraversal(xs: TraversableOnce[Any]): () => Unit = + (noOp /: xs) ((op, x) => () => seq(op, elemTraversal(x))) + + def elemTraversal(x: Any): () => Unit = () => x match { + case x: Tree @ unchecked => + if (x.pos.exists) + for (addr <- addrOfTree(x)) + recorder.record(addr, offset(x.pos)) + + val annotTraversal = x match { + case x: MemberDef => elemsTraversal(x.symbol.annotations) + case _ => noOp + } + val childrenTraversal = elemsTraversal(x.productIterator) + seq(annotTraversal, childrenTraversal) + case xs: List[_] => + elemsTraversal(xs)() + case _ => + () + } + + elemTraversal(root)() + } + + def picklePositions(root: Tree)(implicit ctx: Context) = { + traverseAll(root, startPos) + traverseAll(root, endPos) + } +} \ No newline at end of file diff --git a/src/dotty/tools/dotc/core/pickling/TastyPrinter.scala b/src/dotty/tools/dotc/core/pickling/TastyPrinter.scala index 8056e600d..cf531ecac 100644 --- a/src/dotty/tools/dotc/core/pickling/TastyPrinter.scala +++ b/src/dotty/tools/dotc/core/pickling/TastyPrinter.scala @@ -34,6 +34,7 @@ class TastyPrinter(bytes: Array[Byte])(implicit ctx: Context) { printNames() println("Trees:") unpickle(new TreeUnpickler) + unpickle(new PositionUnpickler) } class TreeUnpickler extends SectionUnpickler[Unit]("ASTs") { @@ -101,4 +102,26 @@ class TastyPrinter(bytes: Array[Byte])(implicit ctx: Context) { } } } + + class PositionUnpickler extends SectionUnpickler[Unit]("Positions") { + def unpickle(reader: TastyReader, tastyName: TastyName.Table): Unit = { + import reader._ + + def unpickleOffsets(edge: Edge): Unit = { + var lastOffset = 0 + var lastAddr = 0 + val length = readNat() + println(s"$length offset bytes") + val end = currentAddr + length + until(end) { + lastOffset += readInt() + lastAddr += readInt() + println(s"$lastOffset: $lastAddr") + } + } + + unpickleOffsets(Edge.left) + unpickleOffsets(Edge.right) + } + } } \ No newline at end of file diff --git a/src/dotty/tools/dotc/transform/Pickler.scala b/src/dotty/tools/dotc/transform/Pickler.scala index f080aa7ad..aa133eeb4 100644 --- a/src/dotty/tools/dotc/transform/Pickler.scala +++ b/src/dotty/tools/dotc/transform/Pickler.scala @@ -20,6 +20,8 @@ class Pickler extends MiniPhaseTransform { thisTransform => val treePkl = new TreePickler(pickler) treePkl.pickle(tree) + new PositionPickler(pickler, treePkl.buf.addrOfTree).picklePositions(tree) + val bytes = pickler.assembleParts() def rawBytes = // not needed right now, but useful to print raw format. bytes.iterator.grouped(10).toList.zipWithIndex.map { -- cgit v1.2.3