diff options
author | Martin Odersky <odersky@gmail.com> | 2013-02-18 15:29:38 +0100 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2013-02-18 15:29:38 +0100 |
commit | 5c9433161e116704730693254fdaf161c69cbcb5 (patch) | |
tree | 6c9adc3d7e3b91ee07f7335aac0479df68d67af2 /src/dotty/tools/dotc/core/Positions.scala | |
parent | 2b4a19e80a643dfdf8eea5fa40811f76edb27be3 (diff) | |
download | dotty-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.scala | 58 |
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 |