aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/util/Positions.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-04-30 17:44:06 +0200
committerMartin Odersky <odersky@gmail.com>2013-04-30 17:44:06 +0200
commit68021907ec042d2e0404e47303c2723bde375f16 (patch)
tree99b8fbea8b5dcf1e8460a98f488c6b86b9468478 /src/dotty/tools/dotc/util/Positions.scala
parentfc8fc177d2dfd270e57996099deef2e4a3a975ed (diff)
downloaddotty-68021907ec042d2e0404e47303c2723bde375f16.tar.gz
dotty-68021907ec042d2e0404e47303c2723bde375f16.tar.bz2
dotty-68021907ec042d2e0404e47303c2723bde375f16.zip
Re-vamping of positions, and split into synthetic and source-derived.
Diffstat (limited to 'src/dotty/tools/dotc/util/Positions.scala')
-rw-r--r--src/dotty/tools/dotc/util/Positions.scala100
1 files changed, 72 insertions, 28 deletions
diff --git a/src/dotty/tools/dotc/util/Positions.scala b/src/dotty/tools/dotc/util/Positions.scala
index 056af00d1..274ba80cb 100644
--- a/src/dotty/tools/dotc/util/Positions.scala
+++ b/src/dotty/tools/dotc/util/Positions.scala
@@ -10,65 +10,106 @@ package util
*/
object Positions {
+ private val SyntheticPointDelta = 1 << (64 - StartEndBits * 2) - 1
private val StartEndBits = 26
private val StartEndMask: Long = (1L << StartEndBits) - 1
- private val PointOffsetLimit = 1L << (64 - StartEndBits * 2)
+ /** A position indicates a range between a start offset and an end offset.
+ * Positions can be synthetic or source-derived. A source-derived position
+ * has in addition a pointlies somewhere between start and end. The point
+ * is roughly where the ^ would go if an error was diagnosed at that position.
+ * All quantities are encoded opaquely in a Long.
+ */
class Position(val coords: Long) extends AnyVal {
+
+ /** The start of this position. */
def start: Int = (coords & StartEndMask).toInt
- def point: Int = start + (coords >>> (StartEndBits * 2)).toInt
+
+ /** The point of this position, returns start for synthetic positions */
+ def point: Int = {
+ val poff = pointDelta
+ if (poff == SyntheticPointDelta) start else start + poff
+ }
+
+ /** The end of this position */
def end: Int = ((coords >>> StartEndBits) & StartEndMask).toInt
- /** The union of two positions. Tries to keep the point offset of
- * the first positon if within range. Otherwise, pointoffset will be 0.
+ /** The difference between point and start in this position */
+ def pointDelta = (coords >>> (StartEndBits * 2)).toInt
+
+ /** The union of two positions. This is the least range that encloses
+ * both positions. It is always a synthetic position.
*/
def union(that: Position) =
if (!this.exists) that
else if (!that.exists) this
- else {
- val start = this.start min that.start
- val end = this.end max that.end
- var pointOffset = this.point - start
- if (pointOffset >= PointOffsetLimit) pointOffset = 0
- Position(start, end, pointOffset)
- }
+ else Position(this.start min that.start, this.end max that.end)
+
+ /** Does the range of this position contain the one of that position? */
+ def contains(that: Position): Boolean =
+ if (exists) (start <= that.start && end >= that.end)
+ else !that.exists
+ /** Is this position different from NoPosition? */
def exists = this != NoPosition
+ /** Is this position synthetic? */
+ def isSynthetic = pointDelta == SyntheticPointDelta
+
+ /** Is this position source-derived? */
+ def isSourceDerived = !isSynthetic
+
+ /** A position where all components are shifted by a given `offset`
+ * relative to this position.
+ */
def shift(offset: Int) =
- if (exists) Position(start + offset, end + offset, point - start)
+ if (exists) Position(start + offset, end + offset, pointDelta)
else this
+ /** The zero-extent position with start and end at the point of this position */
def focus = Position(point)
+
+ /** The zero-extent position with start and end at the start of this position */
def startPos = Position(start)
+
+ /** The zero-extent position with start and end at the end of this position */
def endPos = Position(end)
+ /** A copy of this position with a different start */
def withStart(start: Int) = Position(start, this.end, this.point - start)
+
+ /** A copy of this position with a different end */
def withEnd(end: Int) = Position(this.start, end, this.point - this.start)
- def withPoint(point: Int) = Position(this.start, this.end, point - this.start)
- def transparent: Position = this /* for now */
+
+ /** A copy of this position with a different point */
+ def withPoint(point: Int) =
+ Position(this.start, this.end, point - this.start)
+
+ /** A synthetic copy of this position */
+ def toSynthetic = Position(start, end)
}
- def Position(start: Int, end: Int, pointOffset: Int = 0): Position =
+ private def fromOffsets(start: Int, end: Int, pointDelta: Int) =
new Position(
(start & StartEndMask).toLong |
((end & StartEndMask).toLong << StartEndBits) |
- (pointOffset.toLong << (StartEndBits * 2)))
+ (pointDelta.toLong << (StartEndBits * 2)))
- def Position(point: Int): Position = Position(point, point, 0)
+ /** A synthetic position with given start and end */
+ def Position(start: Int, end: Int): Position =
+ fromOffsets(start, end, SyntheticPointDelta)
- val NoPosition = new Position(-1L)
+ /** A source-derived position with given start, end, and point delta */
+ def Position(start: Int, end: Int, pointDelta: Int): Position =
+ fromOffsets(start, end, if (pointDelta >= SyntheticPointDelta) 0 else pointDelta)
- case class PositionPrefix(val coords: Long) extends AnyVal {
- def start: Int = (coords & StartEndMask).toInt
- def point: Int = start + (coords >>> StartEndBits).toInt
- def toPosition(end: Int) = Position(start, end, point - start max 0)
- }
+ /** A synthetic zero-extent position that starts and ends at given `start`. */
+ def Position(start: Int): Position = Position(start, start, 0)
- def PositionPrefix(start: Int, pointOffset: Int = 0): PositionPrefix =
- new PositionPrefix(
- (start & StartEndMask).toLong | pointOffset.toLong << StartEndBits)
+ /** A sentinal for a non-existing position */
+ val NoPosition = Position(1, 0)
+ /** A source position is comprised of a position in a source file */
case class SourcePosition(source: SourceFile, pos: Position) {
def point: Int = pos.point
def start: Int = pos.start
@@ -76,10 +117,11 @@ object Positions {
def exists = pos.exists
}
+ /** A sentinel for a non-existing source position */
val NoSourcePosition = SourcePosition(NoSource, NoPosition)
/** The coordinate of a symbol. This is either an index or
- * a point position.
+ * a zero-range position.
*/
class Coord(val encoding: Int) extends AnyVal {
def isIndex = encoding > 0
@@ -94,8 +136,10 @@ object Positions {
}
}
+ /** An index coordinate */
def indexCoord(n: Int) = new Coord(n + 1)
- def positionCoord(n: Int) = new Coord(-(n + 1))
+ def positionCoord(pos: Position) = new Coord(-(pos.point + 1))
+ /** A sentinel for a missing coordinate */
val NoCoord = new Coord(0)
} \ No newline at end of file