diff options
author | Martin Odersky <odersky@gmail.com> | 2013-04-17 09:48:22 +0200 |
---|---|---|
committer | Martin Odersky <odersky@gmail.com> | 2013-04-17 10:16:22 +0200 |
commit | ca8dc7ada663e44aafe470944dd17256dbde151c (patch) | |
tree | d15939e204042e358e0c83064250f1f18c1c4f25 /src/dotty/tools/dotc/util/Positions.scala | |
parent | e32fedb6844eab11a27e365a570b2033a0f6f78d (diff) | |
download | dotty-ca8dc7ada663e44aafe470944dd17256dbde151c.tar.gz dotty-ca8dc7ada663e44aafe470944dd17256dbde151c.tar.bz2 dotty-ca8dc7ada663e44aafe470944dd17256dbde151c.zip |
Scanners added.
Moving Positions, Chars to new packages.
Added Source positions.
Added untyped trees module.
Factored out behavior between typed and untyped trees.
Diffstat (limited to 'src/dotty/tools/dotc/util/Positions.scala')
-rw-r--r-- | src/dotty/tools/dotc/util/Positions.scala | 88 |
1 files changed, 88 insertions, 0 deletions
diff --git a/src/dotty/tools/dotc/util/Positions.scala b/src/dotty/tools/dotc/util/Positions.scala new file mode 100644 index 000000000..31eb2ff0d --- /dev/null +++ b/src/dotty/tools/dotc/util/Positions.scala @@ -0,0 +1,88 @@ +package dotty.tools.dotc +package util + +/** 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 { + + private val StartEndBits = 26 + private val StartEndMask = (1 << StartEndBits) - 1 + private val PointOffsetLimit = 1L << (64 - StartEndBits * 2) + + class Position(val coords: Long) extends AnyVal { + def point: Int = start + (coords >>> (StartEndBits * 2)).toInt + def start: Int = (coords & StartEndMask).toInt + 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. + */ + 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) + } + + def exists = this != NoPosition + + def shift(offset: Int) = + if (exists) Position(start + offset, end + offset, point - start) + else this + + def focus = Position(point) + + def withStart(start: Int) = Position(start, this.end, this.point - start) + 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 Position(start: Int, end: Int, pointOffset: Int = 0): Position = + new Position( + (start & StartEndMask).toLong | + ((end & StartEndMask).toLong << StartEndBits) | + (pointOffset.toLong << (StartEndBits * 2))) + + def Position(point: Int): Position = Position(point, point, 0) + + val NoPosition = new Position(-1L) + + case class SourcePosition(source: SourceFile, pos: Position) { + def point: Int = pos.point + def start: Int = pos.start + def end: Int = pos.end + def exists = pos.exists + } + + val NoSourcePosition = SourcePosition(NoSource, NoPosition) + + /** 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 |