aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core/Positions.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-02-18 15:29:38 +0100
committerMartin Odersky <odersky@gmail.com>2013-02-18 15:29:38 +0100
commit5c9433161e116704730693254fdaf161c69cbcb5 (patch)
tree6c9adc3d7e3b91ee07f7335aac0479df68d67af2 /src/dotty/tools/dotc/core/Positions.scala
parent2b4a19e80a643dfdf8eea5fa40811f76edb27be3 (diff)
downloaddotty-5c9433161e116704730693254fdaf161c69cbcb5.tar.gz
dotty-5c9433161e116704730693254fdaf161c69cbcb5.tar.bz2
dotty-5c9433161e116704730693254fdaf161c69cbcb5.zip
Improved position handling.
1. All positions are range position. 2. Improved position API 3. renamed Offset to Coord, and made sure indices cannot be confused with positions. 4. Trees now automatically get positions that enclose their subtree's positions. 5. typed DefTrees contain positions that also enclose their symbol's position. To make this work well, a symbol's coord should point to the introducing keyword (e.g. def, val, class).
Diffstat (limited to 'src/dotty/tools/dotc/core/Positions.scala')
-rw-r--r--src/dotty/tools/dotc/core/Positions.scala58
1 files changed, 43 insertions, 15 deletions
diff --git a/src/dotty/tools/dotc/core/Positions.scala b/src/dotty/tools/dotc/core/Positions.scala
index 3a7d51b33..1d455e6f2 100644
--- a/src/dotty/tools/dotc/core/Positions.scala
+++ b/src/dotty/tools/dotc/core/Positions.scala
@@ -1,27 +1,55 @@
package dotty.tools.dotc.core
+/** Position format in little endian:
+ * Start: unsigned 26 Bits (works for source files up to 64M)
+ * End: unsigned 26 Bits
+ * Point: unsigned 12 Bits relative to start
+ * NoPosition encoded as -1L (this is a normally invalid position
+ * because point would lie beyond end.
+ */
object Positions {
- /** The bit position of the end part of a range position */
- private val Shift = 32
+ private val StartEndBits = 26
+ private val StartEndMask = (1 << StartEndBits) - 1
class Position(val coords: Long) extends AnyVal {
- def isRange = coords < 0
- def point: Int = if (isRange) start else coords.toInt
- def start: Int = coords.abs.toInt
- def end: Int = (if (isRange) coords.abs >>> Shift else coords).toInt
+ def point: Int = start + (coords >>> (StartEndBits * 2)).toInt
+ def start: Int = (coords & StartEndMask).toInt
+ def end: Int = ((coords >>> StartEndBits) & StartEndMask).toInt
+ def union(that: Position) =
+ if (this == NoPosition) that
+ else if (that == NoPosition) this
+ else Position(this.start min that.start, this.end max that.end)
}
- class Offset(val value: Int) extends AnyVal {
- def toPosition = new Position(value.toLong & 0xffff)
- }
-
- def rangePos(start: Int, end: Int) =
- new Position(-(start + (end.toLong << Shift)))
+ def Position(start: Int, end: Int, pointOffset: Int = 0): Position =
+ new Position(
+ (start & StartEndMask).toLong |
+ ((end & StartEndMask).toLong << StartEndBits) |
+ (pointOffset.toLong << (StartEndBits * 2)))
- def offsetPos(point: Int) =
- new Position(point.toLong)
+ def Position(point: Int): Position = Position(point, point, 0)
val NoPosition = new Position(-1L)
- val NoOffset = new Offset(-1)
+
+ /** The coordinate of a symbol. This is either an index or
+ * a point position.
+ */
+ class Coord(val encoding: Int) extends AnyVal {
+ def isIndex = encoding > 0
+ def isPosition = encoding <= 0
+ def toIndex: Int = {
+ assert(isIndex)
+ encoding - 1
+ }
+ def toPosition = {
+ assert(isPosition)
+ if (this == NoCoord) NoPosition else Position(1 - encoding)
+ }
+ }
+
+ def indexCoord(n: Int) = new Coord(n + 1)
+ def positionCoord(n: Int) = new Coord(-(n + 1))
+
+ val NoCoord = new Coord(0)
} \ No newline at end of file