aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/tasty/PositionPickler.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2015-04-29 10:36:16 +0200
committerMartin Odersky <odersky@gmail.com>2015-05-02 19:23:08 +0200
commit60ab9f8f525d319aa5b6d5052018c6781da036eb (patch)
treefbc5096a1f7193a4970226a7ad6f03fbf7670a4b /src/dotty/tools/dotc/core/tasty/PositionPickler.scala
parentac46a0e4489bba4f76863cc1491bf2b8441ed1cb (diff)
downloaddotty-60ab9f8f525d319aa5b6d5052018c6781da036eb.tar.gz
dotty-60ab9f8f525d319aa5b6d5052018c6781da036eb.tar.bz2
dotty-60ab9f8f525d319aa5b6d5052018c6781da036eb.zip
Pickling modularization reorg
The pickling package got rather large and confusing with three separate tasks that each had their own conventions: read JVM classfiles, read Scala2 pickle info, read Tasty. The classes for each task are now in separate packages.
Diffstat (limited to 'src/dotty/tools/dotc/core/tasty/PositionPickler.scala')
-rw-r--r--src/dotty/tools/dotc/core/tasty/PositionPickler.scala75
1 files changed, 75 insertions, 0 deletions
diff --git a/src/dotty/tools/dotc/core/tasty/PositionPickler.scala b/src/dotty/tools/dotc/core/tasty/PositionPickler.scala
new file mode 100644
index 000000000..b0550b70a
--- /dev/null
+++ b/src/dotty/tools/dotc/core/tasty/PositionPickler.scala
@@ -0,0 +1,75 @@
+package dotty.tools
+package dotc
+package core
+package tasty
+
+import ast.tpd._
+import ast.Trees.WithLazyField
+import TastyFormat._
+import core._
+import Contexts._, Symbols._, Types._, Names._, Constants._, Decorators._, Annotations._
+import collection.mutable
+import TastyBuffer._
+import util.Positions._
+
+object PositionPickler {
+
+ trait DeferredPosition {
+ var parentPos: Position = NoPosition
+ }
+
+ def traverse(x: Any, parentPos: Position, op: (Tree, Position) => Unit)(implicit ctx: Context): Unit =
+ if (parentPos.exists)
+ x match {
+ case x: Tree @unchecked =>
+ op(x, parentPos)
+ x match {
+ case x: MemberDef @unchecked => traverse(x.symbol.annotations, x.pos, op)
+ case _ =>
+ }
+ traverse(x.productIterator, x.pos, op)
+ case x: DeferredPosition =>
+ x.parentPos = parentPos
+ case xs: TraversableOnce[_] =>
+ xs.foreach(traverse(_, parentPos, op))
+ case _ =>
+ }
+}
+import PositionPickler._
+
+class PositionPickler(pickler: TastyPickler, addrOfTree: Tree => Option[Addr]) {
+ val buf = new TastyBuffer(5000)
+ pickler.newSection("Positions", buf)
+ import buf._
+
+ def picklePositions(roots: List[Tree], totalRange: Position)(implicit ctx: Context) = {
+ var lastIndex = 0
+ def record(tree: Tree, parentPos: Position): Unit =
+ if (tree.pos.exists) {
+ def msg = s"failure to pickle $tree at ${tree.pos}, parent = $parentPos"
+ val endPos = tree.pos.end min parentPos.end
+ // end positions can be larger than their parents
+ // e.g. in the case of synthetic empty ranges, which are placed at the next token after
+ // the current construct.
+ val endDelta = endPos - parentPos.end
+ val startPos =
+ if (endDelta == 0) tree.pos.start max parentPos.start else tree.pos.start min endPos
+ // Since end positions are corrected above, start positions have to follow suit.
+ val startDelta = startPos - parentPos.start
+ if (startDelta != 0 || endDelta != 0)
+ for (addr <- addrOfTree(tree)) {
+ buf.writeInt(addr.index - lastIndex)
+ lastIndex = addr.index
+ if (startDelta != 0) buf.writeInt(startDelta)
+ if (endDelta != 0) {
+ assert(endDelta < 0, msg)
+ buf.writeInt(endDelta)
+ } else
+ assert(startDelta >= 0, msg)
+ }
+ }
+
+ buf.writeNat(totalRange.end)
+ traverse(roots, totalRange, record)
+ }
+}