aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/core
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
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')
-rw-r--r--src/dotty/tools/dotc/core/Definitions.scala2
-rw-r--r--src/dotty/tools/dotc/core/Positions.scala58
-rw-r--r--src/dotty/tools/dotc/core/Symbols.scala52
-rw-r--r--src/dotty/tools/dotc/core/Trees.scala176
-rw-r--r--src/dotty/tools/dotc/core/TypedTreeGen.scala12
-rw-r--r--src/dotty/tools/dotc/core/pickling/ClassfileParser.scala6
-rw-r--r--src/dotty/tools/dotc/core/pickling/UnPickler.scala13
7 files changed, 213 insertions, 106 deletions
diff --git a/src/dotty/tools/dotc/core/Definitions.scala b/src/dotty/tools/dotc/core/Definitions.scala
index 461f574c5..e805f59d6 100644
--- a/src/dotty/tools/dotc/core/Definitions.scala
+++ b/src/dotty/tools/dotc/core/Definitions.scala
@@ -41,7 +41,7 @@ class Definitions(implicit ctx: Context) {
val parentRefs: List[TypeRef] = ctx.normalizeToRefs(parents, cls, paramDecls)
CompleteClassDenotation(cls, ScalaPackageClass, name, flags, parentRefs, decls = paramDecls)(ctx)
}
- new ClassSymbol(NoOffset, classDenot)
+ new ClassSymbol(NoCoord, classDenot)
}
private def mkArityArray(name: String, arity: Int, countFrom: Int): Array[ClassSymbol] = {
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
diff --git a/src/dotty/tools/dotc/core/Symbols.scala b/src/dotty/tools/dotc/core/Symbols.scala
index 815e1bbaa..cd644df4e 100644
--- a/src/dotty/tools/dotc/core/Symbols.scala
+++ b/src/dotty/tools/dotc/core/Symbols.scala
@@ -19,25 +19,25 @@ import io.AbstractFile
/** Creation methods for symbols */
trait Symbols { this: Context =>
- def newLazySymbol[N <: Name](owner: Symbol, name: N, initFlags: FlagSet, completer: SymCompleter, off: Offset = NoOffset) =
- new Symbol(off, new LazySymDenotation(_, owner, name, initFlags, completer)) {
+ def newLazySymbol[N <: Name](owner: Symbol, name: N, initFlags: FlagSet, completer: SymCompleter, coord: Coord = NoCoord) =
+ new Symbol(coord, new LazySymDenotation(_, owner, name, initFlags, completer)) {
type ThisName = N
}
- def newLazyClassSymbol(owner: Symbol, name: TypeName, initFlags: FlagSet, completer: ClassCompleter, assocFile: AbstractFile = null, off: Offset = NoOffset) =
- new ClassSymbol(off, new LazyClassDenotation(_, owner, name, initFlags, completer, assocFile)(this))
+ def newLazyClassSymbol(owner: Symbol, name: TypeName, initFlags: FlagSet, completer: ClassCompleter, assocFile: AbstractFile = null, coord: Coord = NoCoord) =
+ new ClassSymbol(coord, new LazyClassDenotation(_, owner, name, initFlags, completer, assocFile)(this))
def newLazyModuleSymbols(owner: Symbol,
name: TermName,
flags: FlagSet,
completer: ClassCompleter,
assocFile: AbstractFile = null,
- off: Offset = NoOffset): (TermSymbol, ClassSymbol)
+ coord: Coord = NoCoord): (TermSymbol, ClassSymbol)
= {
val module = newLazySymbol(
- owner, name, flags | ModuleCreationFlags, new ModuleCompleter(condensed), off)
+ owner, name, flags | ModuleCreationFlags, new ModuleCompleter(condensed), coord)
val modcls = newLazyClassSymbol(
- owner, name.toTypeName, flags | ModuleClassCreationFlags, completer, assocFile, off)
+ owner, name.toTypeName, flags | ModuleClassCreationFlags, completer, assocFile, coord)
module.denot.asInstanceOf[LazySymDenotation].info =
TypeRef(owner.thisType(ctx), modcls)
modcls.denot.asInstanceOf[LazyClassDenotation].selfType =
@@ -48,8 +48,8 @@ trait Symbols { this: Context =>
def newLazyPackageSymbols(owner: Symbol, name: TermName, completer: ClassCompleter) =
newLazyModuleSymbols(owner, name, PackageCreationFlags, completer)
- def newSymbol[N <: Name](owner: Symbol, name: N, flags: FlagSet, info: Type, privateWithin: Symbol = NoSymbol, off: Offset = NoOffset) =
- new Symbol(off, CompleteSymDenotation(_, owner, name, flags, info, privateWithin)) {
+ def newSymbol[N <: Name](owner: Symbol, name: N, flags: FlagSet, info: Type, privateWithin: Symbol = NoSymbol, coord: Coord = NoCoord) =
+ new Symbol(coord, CompleteSymDenotation(_, owner, name, flags, info, privateWithin)) {
type ThisName = N
}
@@ -62,9 +62,9 @@ trait Symbols { this: Context =>
optSelfType: Type = NoType,
decls: Scope = newScope,
assocFile: AbstractFile = null,
- off: Offset = NoOffset)
+ coord: Coord = NoCoord)
=
- new ClassSymbol(off, new CompleteClassDenotation(
+ new ClassSymbol(coord, new CompleteClassDenotation(
_, owner, name, flags, parents, privateWithin, optSelfType, decls, assocFile)(this))
def newModuleSymbols(
@@ -76,15 +76,15 @@ trait Symbols { this: Context =>
privateWithin: Symbol = NoSymbol,
decls: Scope = newScope,
assocFile: AbstractFile = null,
- off: Offset = NoOffset): (TermSymbol, ClassSymbol)
+ coord: Coord = NoCoord): (TermSymbol, ClassSymbol)
= {
val module = newLazySymbol(
owner, name, flags | ModuleCreationFlags,
- new ModuleCompleter(condensed), off)
+ new ModuleCompleter(condensed), coord)
val modcls = newClassSymbol(
owner, name.toTypeName, classFlags | ModuleClassCreationFlags, parents, privateWithin,
optSelfType = TermRef(owner.thisType, module),
- decls, assocFile, off)
+ decls, assocFile, coord)
module.denot.asInstanceOf[LazySymDenotation].info =
TypeRef(owner.thisType, modcls)
(module, modcls)
@@ -105,11 +105,11 @@ trait Symbols { this: Context =>
}
}
- def newLocalDummy(cls: Symbol, off: Offset = NoOffset) =
+ def newLocalDummy(cls: Symbol, coord: Coord = NoCoord) =
newSymbol(cls, nme.localDummyName(cls), EmptyFlags, NoType)
- def newImportSymbol(expr: TypedTree, off: Offset = NoOffset) =
- newSymbol(NoSymbol, nme.IMPORT, EmptyFlags, ImportType(expr), off = off)
+ def newImportSymbol(expr: TypedTree, coord: Coord = NoCoord) =
+ newSymbol(NoSymbol, nme.IMPORT, EmptyFlags, ImportType(expr), coord = coord)
def requiredPackage(path: PreName): TermSymbol =
base.staticRef(path.toTermName).requiredSymbol(_.isPackage).asTerm
@@ -125,7 +125,7 @@ object Symbols {
/** A Symbol represents a Scala definition/declaration or a package.
*/
- class Symbol(val offset: Offset, denotf: Symbol => SymDenotation) extends DotClass {
+ class Symbol(val coord: Coord, denotf: Symbol => SymDenotation) extends DotClass {
type ThisName <: Name
@@ -197,7 +197,7 @@ object Symbols {
type TermSymbol = Symbol { type ThisName = TermName }
type TypeSymbol = Symbol { type ThisName = TypeName }
- class ClassSymbol(off: Offset, denotf: ClassSymbol => ClassDenotation) extends Symbol(off, s => denotf(s.asClass)) {
+ class ClassSymbol(coord: Coord, denotf: ClassSymbol => ClassDenotation) extends Symbol(coord, s => denotf(s.asClass)) {
type ThisName = TypeName
@@ -227,11 +227,11 @@ object Symbols {
}
}
- class ErrorSymbol(val underlying: Symbol, msg: => String)(implicit ctx: Context) extends Symbol(NoOffset, sym => underlying.denot) {
+ class ErrorSymbol(val underlying: Symbol, msg: => String)(implicit ctx: Context) extends Symbol(NoCoord, sym => underlying.denot) {
type ThisName = underlying.ThisName
}
- object NoSymbol extends Symbol(NoOffset, sym => NoDenotation) {
+ object NoSymbol extends Symbol(NoCoord, sym => NoDenotation) {
override def exists = false
}
@@ -243,12 +243,12 @@ object Symbols {
flags: FlagSet = sym.flags,
privateWithin: Symbol = sym.privateWithin,
info: Type = sym.info,
- off: Offset = sym.offset): Symbol =
+ coord: Coord = sym.coord): Symbol =
if (sym.isClass) {
assert(info eq sym.info)
- new ClassCopier(sym.asClass).copy(owner, name.asTypeName, flags, privateWithin = privateWithin, off = off)
+ new ClassCopier(sym.asClass).copy(owner, name.asTypeName, flags, privateWithin = privateWithin, coord = coord)
} else
- ctx.newSymbol(owner, name, flags, info, privateWithin, sym.offset)
+ ctx.newSymbol(owner, name, flags, info, privateWithin, sym.coord)
}
implicit class ClassCopier(cls: ClassSymbol)(implicit ctx: Context) {
@@ -262,8 +262,8 @@ object Symbols {
selfType: Type = cls.selfType,
decls: Scope = cls.decls,
associatedFile: AbstractFile = cls.associatedFile,
- off: Offset = cls.offset) =
- ctx.newClassSymbol(owner, name, flags, parents, privateWithin, selfType, decls, associatedFile, off)
+ coord: Coord = cls.coord) =
+ ctx.newClassSymbol(owner, name, flags, parents, privateWithin, selfType, decls, associatedFile, coord)
}
implicit def defn(implicit ctx: Context): Definitions = ctx.definitions
diff --git a/src/dotty/tools/dotc/core/Trees.scala b/src/dotty/tools/dotc/core/Trees.scala
index 25226c660..1245119f2 100644
--- a/src/dotty/tools/dotc/core/Trees.scala
+++ b/src/dotty/tools/dotc/core/Trees.scala
@@ -2,6 +2,7 @@ package dotty.tools.dotc.core
import Types._, Names._, Flags._, Positions._, Contexts._, Constants._, SymDenotations._, Symbols._
import Denotations._, StdNames._
+import annotation.tailrec
object Trees {
@@ -30,17 +31,29 @@ object Trees {
* nodes.
*/
abstract class Tree[T] extends DotClass {
+
+ /** The tree's position. Except
+ * for Shared nodes, it is always ensured that a tree's position
+ * contains the positions of all its subtrees.
+ */
def pos: Position
+ /** The typeconstructor at the root of the tree */
type ThisTree[T] <: Tree[T]
protected var _tpe: T = _
+ /** The type of the tree. In case of an untyped tree,
+ * an UnAssignedTypeException is thrown.
+ */
def tpe: T = {
if (_tpe == null) throw new UnAssignedTypeException(this)
_tpe
}
+ /** Return a typed tree that's isomorphic to this tree, but has given
+ * type.
+ */
def withType(tpe: Type): ThisTree[Type] = {
val tree =
(if (_tpe == null ||
@@ -50,12 +63,22 @@ object Trees {
tree.asInstanceOf[ThisTree[Type]]
}
+ /** The denotation referred to by this tree, NoDenotation where not applicable */
def denot(implicit ctx: Context): Denotation = NoDenotation
+
+ /** The symbol defined by ot referred to by this tree, NoSymbol where not applicable */
def symbol(implicit ctx: Context): Symbol = NoSymbol
+ /** Does this tree represent a type? */
def isType: Boolean = false
+
+ /** Does this tree represent a term? */
def isTerm: Boolean = false
+
+ /** Does this tree represent a definition or declaration? */
def isDef: Boolean = false
+
+ /** Is this tree either the empty tree or the empty ValDef? */
def isEmpty: Boolean = false
}
@@ -68,16 +91,16 @@ object Trees {
// ------ Categories of trees -----------------------------------
- /** Tree is definitely a type. Note that some trees
- * have isType = true without being TypTrees (e.g. Ident, AnnotatedTree)
+ /** Instances of this class are trees for which isType is definitely true.
+ * Note that some trees have isType = true without being TypTrees (e.g. Ident, AnnotatedTree)
*/
trait TypTree[T] extends Tree[T] {
type ThisTree[T] <: TypTree[T]
override def isType = true
}
- /** Tree is definitely a term. Note that some trees
- * have isType = true without being TypTrees (e.g. Ident, AnnotatedTree)
+ /** Instances of this class are trees for which isTerm is definitely true.
+ * Note that some trees have isTerm = true without being TermTrees (e.g. Ident, AnnotatedTree)
*/
trait TermTree[T] extends Tree[T] {
type ThisTree[T] <: TermTree[T]
@@ -97,7 +120,7 @@ object Trees {
}
}
- /** Tree's symbol/isType/isTerm properties come from a subtree identifier
+ /** Tree's symbol/isType/isTerm properties come from a subtree identified
* by `forwardTo`.
*/
abstract class ProxyTree[T] extends Tree[T] {
@@ -123,6 +146,7 @@ object Trees {
override def isTerm = name.isTermName
}
+ /** Tree represents a definition */
abstract class DefTree[T] extends NameTree[T] {
type ThisTree[T] <: DefTree[T]
override def isDef = true
@@ -131,28 +155,32 @@ object Trees {
// ----------- Tree case classes ------------------------------------
/** name */
- case class Ident[T] (name: Name)(implicit val pos: Position)
+ case class Ident[T] (name: Name)(implicit cpos: Position)
extends RefTree[T] {
type ThisTree[T] = Ident[T]
+ val pos = cpos
def qualifier: Tree[T] = EmptyTree[T]
}
/** qualifier.name */
- case class Select[T](qualifier: Tree[T], name: Name)(implicit val pos: Position)
+ case class Select[T](qualifier: Tree[T], name: Name)(implicit cpos: Position)
extends RefTree[T] {
type ThisTree[T] = Select[T]
+ val pos = cpos union qualifier.pos
}
/** qual.this */
- case class This[T](qual: TypeName)(implicit val pos: Position)
+ case class This[T](qual: TypeName)(implicit cpos: Position)
extends SymTree[T] with TermTree[T] {
type ThisTree[T] = This[T]
+ val pos = cpos
}
/** C.super[mix], where qual = C.this */
- case class Super[T](qual: Tree[T], mix: TypeName)(implicit val pos: Position)
+ case class Super[T](qual: Tree[T], mix: TypeName)(implicit cpos: Position)
extends ProxyTree[T] with TermTree[T] {
type ThisTree[T] = Super[T]
+ val pos = cpos union qual.pos
def forwardTo = qual
}
@@ -164,82 +192,95 @@ object Trees {
}
/** fun(args) */
- case class Apply[T](fun: Tree[T], args: List[Tree[T]])(implicit val pos: Position)
+ case class Apply[T](fun: Tree[T], args: List[Tree[T]])(implicit cpos: Position)
extends GenericApply[T] {
type ThisTree[T] = Apply[T]
+ val pos = unionPos(cpos union fun.pos, args)
}
/** fun[args] */
- case class TypeApply[T](fun: Tree[T], args: List[Tree[T]])(implicit val pos: Position)
+ case class TypeApply[T](fun: Tree[T], args: List[Tree[T]])(implicit cpos: Position)
extends GenericApply[T] {
type ThisTree[T] = TypeApply[T]
+ val pos = unionPos(cpos union fun.pos, args)
}
/** const */
- case class Literal[T](const: Constant)(implicit val pos: Position)
+ case class Literal[T](const: Constant)(implicit cpos: Position)
extends TermTree[T] {
type ThisTree[T] = Literal[T]
+ val pos = cpos
}
/** new tpt, but no constructor call */
- case class New[T](tpt: Tree[T])(implicit val pos: Position)
+ case class New[T](tpt: Tree[T])(implicit cpos: Position)
extends TermTree[T] {
type ThisTree[T] = New[T]
+ val pos = cpos union tpt.pos
}
/** (left, right) */
- case class Pair[T](left: Tree[T], right: Tree[T])(implicit val pos: Position)
+ case class Pair[T](left: Tree[T], right: Tree[T])(implicit cpos: Position)
extends TermTree[T] {
type ThisTree[T] = Pair[T]
+ val pos = cpos union left.pos union right.pos
}
/** expr : tpt */
- case class Typed[T](expr: Tree[T], tpt: Tree[T])(implicit val pos: Position)
+ case class Typed[T](expr: Tree[T], tpt: Tree[T])(implicit cpos: Position)
extends ProxyTree[T] with TermTree[T] {
type ThisTree[T] = Typed[T]
+ val pos = cpos union expr.pos union tpt.pos
def forwardTo = expr
}
/** name = arg, in a parameter list */
- case class NamedArg[T](name: Name, arg: Tree[T])(implicit val pos: Position)
+ case class NamedArg[T](name: Name, arg: Tree[T])(implicit cpos: Position)
extends TermTree[T] {
type ThisTree[T] = NamedArg[T]
+ val pos = cpos union arg.pos
}
/** name = arg, outside a parameter list */
- case class Assign[T](lhs: Tree[T], rhs: Tree[T])(implicit val pos: Position)
+ case class Assign[T](lhs: Tree[T], rhs: Tree[T])(implicit cpos: Position)
extends TermTree[T] {
type ThisTree[T] = Assign[T]
+ val pos = cpos union lhs.pos union rhs.pos
}
/** (vparams) => body */
- case class Function[T](vparams: List[ValDef[T]], body: Tree[T])(implicit val pos: Position)
+ case class Function[T](vparams: List[ValDef[T]], body: Tree[T])(implicit cpos: Position)
extends SymTree[T] with TermTree[T] {
type ThisTree[T] = Function[T]
+ val pos = unionPos(cpos union body.pos, vparams)
}
/** { stats; expr } */
- case class Block[T](stats: List[Tree[T]], expr: Tree[T])(implicit val pos: Position)
+ case class Block[T](stats: List[Tree[T]], expr: Tree[T])(implicit cpos: Position)
extends TermTree[T] {
type ThisTree[T] = Block[T]
+ val pos = unionPos(cpos union expr.pos, stats)
}
/** if cond then thenp else elsep */
- case class If[T](cond: Tree[T], thenp: Tree[T], elsep: Tree[T])(implicit val pos: Position)
+ case class If[T](cond: Tree[T], thenp: Tree[T], elsep: Tree[T])(implicit cpos: Position)
extends TermTree[T] {
type ThisTree[T] = If[T]
+ val pos = cpos union cond.pos union thenp.pos union elsep.pos
}
/** selector match { cases } */
- case class Match[T](selector: Tree[T], cases: List[CaseDef[T]])(implicit val pos: Position)
+ case class Match[T](selector: Tree[T], cases: List[CaseDef[T]])(implicit cpos: Position)
extends TermTree[T] {
type ThisTree[T] = Match[T]
+ val pos = unionPos(cpos union selector.pos, cases)
}
/** case pat if guard => body */
- case class CaseDef[T](pat: Tree[T], guard: Tree[T], body: Tree[T])(implicit val pos: Position)
+ case class CaseDef[T](pat: Tree[T], guard: Tree[T], body: Tree[T])(implicit cpos: Position)
extends Tree[T] {
type ThisTree[T] = CaseDef[T]
+ val pos = cpos union pat.pos union guard.pos union body.pos
}
/** return expr
@@ -247,107 +288,124 @@ object Trees {
* After program transformations this is not necessarily the enclosing method, because
* closures can intervene.
*/
- case class Return[T](expr: Tree[T], from: Ident[T])(implicit val pos: Position)
+ case class Return[T](expr: Tree[T], from: Ident[T])(implicit cpos: Position)
extends TermTree[T] {
type ThisTree[T] = Return[T]
+ val pos = cpos union expr.pos // from is synthetic, does not influence pos
}
/** try block catch { catches } */
- case class Try[T](block: Tree[T], catches: List[CaseDef[T]], finalizer: Tree[T])(implicit val pos: Position)
+ case class Try[T](block: Tree[T], catches: List[CaseDef[T]], finalizer: Tree[T])(implicit cpos: Position)
extends TermTree[T] {
type ThisTree[T] = Try[T]
+ val pos = unionPos(cpos union block.pos union finalizer.pos, catches)
}
/** throw expr */
- case class Throw[T](expr: Tree[T])(implicit val pos: Position)
+ case class Throw[T](expr: Tree[T])(implicit cpos: Position)
extends TermTree[T] {
type ThisTree[T] = Throw[T]
+ val pos = cpos union expr.pos
}
/** Array[elemtpt](elems) */
- case class ArrayValue[T](elemtpt: Tree[T], elems: List[Tree[T]])(implicit val pos: Position)
+ case class ArrayValue[T](elemtpt: Tree[T], elems: List[Tree[T]])(implicit cpos: Position)
extends TermTree[T] {
type ThisTree[T] = ArrayValue[T]
+ val pos = unionPos(cpos union elemtpt.pos, elems)
}
/** A type tree that represents an existing or inferred type */
- case class TypeTree[T](original: Tree[T] = EmptyTree[T])(implicit val pos: Position)
+ case class TypeTree[T](original: Tree[T] = EmptyTree[T])(implicit cpos: Position)
extends SymTree[T] with TypTree[T] {
type ThisTree[T] = TypeTree[T]
+ val pos = cpos union original.pos
}
/** ref.type */
- case class SingletonTypeTree[T](ref: Tree[T])(implicit val pos: Position)
+ case class SingletonTypeTree[T](ref: Tree[T])(implicit cpos: Position)
extends SymTree[T] with TypTree[T] {
type ThisTree[T] = SingletonTypeTree[T]
+ val pos = cpos union ref.pos
}
/** qualifier # name */
- case class SelectFromTypeTree[T](qualifier: Tree[T], name: TypeName)(implicit val pos: Position)
+ case class SelectFromTypeTree[T](qualifier: Tree[T], name: TypeName)(implicit cpos: Position)
extends RefTree[T] with TypTree[T] {
type ThisTree[T] = SelectFromTypeTree[T]
+ val pos = cpos union qualifier.pos
}
/** left & right */
- case class AndTypeTree[T](left: Tree[T], right: Tree[T])(implicit val pos: Position)
+ case class AndTypeTree[T](left: Tree[T], right: Tree[T])(implicit cpos: Position)
extends TypTree[T] {
type ThisTree[T] = AndTypeTree[T]
+ val pos = cpos union left.pos union right.pos
}
/** left | right */
- case class OrTypeTree[T](left: Tree[T], right: Tree[T])(implicit val pos: Position)
+ case class OrTypeTree[T](left: Tree[T], right: Tree[T])(implicit cpos: Position)
extends TypTree[T] {
type ThisTree[T] = OrTypeTree[T]
+ val pos = cpos union left.pos union right.pos
}
/** tpt { refinements } */
- case class RefineTypeTree[T](tpt: Tree[T], refinements: List[DefTree[T]])(implicit val pos: Position)
+ case class RefineTypeTree[T](tpt: Tree[T], refinements: List[DefTree[T]])(implicit cpos: Position)
extends ProxyTree[T] with TypTree[T] {
type ThisTree[T] = RefineTypeTree[T]
+ val pos = unionPos(cpos union tpt.pos, refinements)
def forwardTo = tpt
}
/** tpt[args] */
- case class AppliedTypeTree[T](tpt: Tree[T], args: List[Tree[T]])(implicit val pos: Position)
+ case class AppliedTypeTree[T](tpt: Tree[T], args: List[Tree[T]])(implicit cpos: Position)
extends ProxyTree[T] with TypTree[T] {
type ThisTree[T] = AppliedTypeTree[T]
+ val pos = unionPos(cpos union tpt.pos, args)
def forwardTo = tpt
}
/** >: lo <: hi */
- case class TypeBoundsTree[T](lo: Tree[T], hi: Tree[T])(implicit val pos: Position)
+ case class TypeBoundsTree[T](lo: Tree[T], hi: Tree[T])(implicit cpos: Position)
extends Tree[T] {
type ThisTree[T] = TypeBoundsTree[T]
+ val pos = cpos union lo.pos union hi.pos
}
/** name @ body */
- case class Bind[T](name: Name, body: Tree[T])(implicit val pos: Position)
+ case class Bind[T](name: Name, body: Tree[T])(implicit cpos: Position)
extends DefTree[T] {
type ThisTree[T] = Bind[T]
+ val pos = cpos union body.pos
}
/** tree_1 | ... | tree_n */
- case class Alternative[T](trees: List[Tree[T]])(implicit val pos: Position)
+ case class Alternative[T](trees: List[Tree[T]])(implicit cpos: Position)
extends Tree[T] {
type ThisTree[T] = Alternative[T]
+ val pos = unionPos(cpos, trees)
}
/** fun(args) in a pattern, if fun is an extractor */
- case class UnApply[T](fun: Tree[T], args: List[Tree[T]])(implicit val pos: Position)
+ case class UnApply[T](fun: Tree[T], args: List[Tree[T]])(implicit cpos: Position)
extends Tree[T] {
type ThisTree[T] = UnApply[T]
+ val pos = unionPos(cpos union fun.pos, args)
}
/** mods val name: tpt = rhs */
- case class ValDef[T](mods: Modifiers[T], name: Name, tpt: Tree[T], rhs: Tree[T])(implicit val pos: Position)
+ case class ValDef[T](mods: Modifiers[T], name: Name, tpt: Tree[T], rhs: Tree[T])(implicit cpos: Position)
extends DefTree[T] {
type ThisTree[T] = ValDef[T]
+ val pos = cpos union tpt.pos union rhs.pos
}
/** mods def name[tparams](vparams_1)...(vparams_n): tpt = rhs */
- case class DefDef[T](mods: Modifiers[T], name: Name, tparams: List[TypeDef[T]], vparamss: List[List[ValDef[T]]], tpt: Tree[T], rhs: Tree[T])(implicit val pos: Position)
+ case class DefDef[T](mods: Modifiers[T], name: Name, tparams: List[TypeDef[T]], vparamss: List[List[ValDef[T]]], tpt: Tree[T], rhs: Tree[T])(implicit cpos: Position)
extends DefTree[T] {
type ThisTree[T] = DefDef[T]
+ val pos = (unionPos(cpos union tpt.pos union rhs.pos, tparams) /: vparamss)(unionPos)
}
class ImplicitDefDef[T](mods: Modifiers[T], name: Name, tparams: List[TypeDef[T]], vparamss: List[List[ValDef[T]]], tpt: Tree[T], rhs: Tree[T])
@@ -358,43 +416,49 @@ object Trees {
/** mods type name = rhs or
* mods type name >: lo <: hi, if rhs = TypeBoundsTree(lo, hi) */
- case class TypeDef[T](mods: Modifiers[T], name: Name, rhs: Tree[T])(implicit val pos: Position)
+ case class TypeDef[T](mods: Modifiers[T], name: Name, rhs: Tree[T])(implicit cpos: Position)
extends DefTree[T] {
type ThisTree[T] = TypeDef[T]
+ val pos = cpos union rhs.pos
}
/** extends parents { self => body } */
- case class Template[T](parents: List[Tree[T]], self: ValDef[T], body: List[Tree[T]])(implicit val pos: Position)
+ case class Template[T](parents: List[Tree[T]], self: ValDef[T], body: List[Tree[T]])(implicit cpos: Position)
extends SymTree[T] {
type ThisTree[T] = Template[T]
+ val pos = unionPos(unionPos(cpos union self.pos, parents), body)
}
/** mods class name[tparams] impl */
- case class ClassDef[T](mods: Modifiers[T], name: TypeName, tparams: List[TypeDef[T]], impl: Template[T])(implicit val pos: Position)
+ case class ClassDef[T](mods: Modifiers[T], name: TypeName, tparams: List[TypeDef[T]], impl: Template[T])(implicit cpos: Position)
extends DefTree[T] {
type ThisTree[T] = ClassDef[T]
+ val pos = unionPos(cpos union impl.pos, tparams)
}
/** import expr.selectors
* where a selector is either an untyped `Ident`, `name` or
* an untyped `Pair` `name => rename`
*/
- case class Import[T](expr: Tree[T], selectors: List[UntypedTree])(implicit val pos: Position)
+ case class Import[T](expr: Tree[T], selectors: List[UntypedTree])(implicit cpos: Position)
extends SymTree[T] {
type ThisTree[T] = Import[T]
+ val pos = unionPos(cpos union expr.pos, selectors)
}
/** package pid { stats } */
- case class PackageDef[T](pid: RefTree[T], stats: List[Tree[T]])(implicit val pos: Position)
+ case class PackageDef[T](pid: RefTree[T], stats: List[Tree[T]])(implicit cpos: Position)
extends DefTree[T] {
type ThisTree[T] = PackageDef[T]
+ val pos = unionPos(cpos union pid.pos, stats)
override def name = pid.name
}
/** arg @annot */
- case class Annotated[T](annot: Tree[T], arg: Tree[T])(implicit val pos: Position)
+ case class Annotated[T](annot: Tree[T], arg: Tree[T])(implicit cpos: Position)
extends ProxyTree[T] {
type ThisTree[T] = Annotated[T]
+ val pos = cpos union annot.pos union arg.pos
def forwardTo = arg
}
@@ -426,20 +490,34 @@ object Trees {
def apply[T]: EmptyValDef[T] = theEmptyValDef.asInstanceOf
}
-// ----- Tree cases that exist in untyped form only ------------------
+ /** A tree that can be shared without its position polluting containing trees */
+ case class Shared[T](tree: Tree[T]) extends Tree[T] {
+ type ThisTree[T] = Shared[T]
+ val pos = NoPosition
+ }
+
+ // ----- Tree cases that exist in untyped form only ------------------
/** A typed subtree of an untyped tree needs to be wrapped in a TypedSlice */
- case class TypedSplice(tree: TypedTree) extends UntypedTree {
- def pos = tree.pos
+ class TypedSplice(tree: TypedTree) extends UntypedTree {
+ val pos = tree.pos
}
/** mods object name impl */
- case class ModuleDef(mods: Modifiers[Nothing], name: TermName, impl: Template[Nothing])(implicit val pos: Position)
+ case class ModuleDef(mods: Modifiers[Nothing], name: TermName, impl: Template[Nothing])(implicit cpos: Position)
extends DefTree[Nothing] {
+ val pos = cpos union impl.pos
}
abstract class TreeAccumulator[T, U] extends ((T, Tree[U]) => T) {
def apply(x: T, tree: Tree[U]): T
def foldOver(x: T, tree: Tree[U]): T = ???
}
+
+// ----- Helper functions ---------------------------------------------
+
+ @tailrec final def unionPos(base: Position, trees: List[Tree[_]]): Position = trees match {
+ case t :: ts => unionPos(base union t.pos, ts)
+ case nil => base
+ }
} \ No newline at end of file
diff --git a/src/dotty/tools/dotc/core/TypedTreeGen.scala b/src/dotty/tools/dotc/core/TypedTreeGen.scala
index b081a6ba7..7672f1f77 100644
--- a/src/dotty/tools/dotc/core/TypedTreeGen.scala
+++ b/src/dotty/tools/dotc/core/TypedTreeGen.scala
@@ -9,6 +9,8 @@ object TypedTrees {
class TypeTreeGen {
implicit def pos(implicit ctx: Context): Position = ctx.position
+ def defPos(sym: Symbol)(implicit ctx: Context) = ctx.position union sym.coord.toPosition
+
def Modifiers(sym: Symbol)(implicit ctx: Context): Modifiers[Type] = Trees.Modifiers[Type](
sym.flags & ModifierFlags,
if (sym.privateWithin.exists) sym.privateWithin.asType.name else tpnme.EMPTY,
@@ -118,7 +120,7 @@ object TypedTrees {
Trees.TypeBoundsTree(lo, hi).withType(TypeBounds(lo.tpe, hi.tpe))
def Bind(sym: Symbol, body: TypedTree)(implicit ctx: Context): Bind[Type] =
- Trees.Bind(sym.name, body).withType(sym.info)
+ Trees.Bind(sym.name, body)(defPos(sym)).withType(sym.info)
def Alternative(trees: List[TypedTree])(implicit ctx: Context): Alternative[Type] =
Trees.Alternative(trees).withType(ctx.lub(trees map (_.tpe)))
@@ -131,7 +133,7 @@ object TypedTrees {
def refType(sym: Symbol)(implicit ctx: Context) = NamedType(sym.owner.thisType, sym)
def ValDef(sym: TermSymbol, rhs: TypedTree = EmptyTree)(implicit ctx: Context): ValDef[Type] =
- Trees.ValDef(Modifiers(sym), sym.name, TypeTree(sym.info), rhs)
+ Trees.ValDef(Modifiers(sym), sym.name, TypeTree(sym.info), rhs)(defPos(sym))
.withType(refType(sym))
def DefDef(sym: TermSymbol, rhs: TypedTree = EmptyTree)(implicit ctx: Context): DefDef[Type] = {
@@ -165,12 +167,12 @@ object TypedTrees {
Trees.DefDef(
Modifiers(sym), sym.name, tparams map TypeDef,
- vparamss map (_ map (ValDef(_))), TypeTree(rtp), rhs)
+ vparamss map (_ map (ValDef(_))), TypeTree(rtp), rhs)(defPos(sym))
.withType(refType(sym))
}
def TypeDef(sym: TypeSymbol)(implicit ctx: Context): TypeDef[Type] =
- Trees.TypeDef(Modifiers(sym), sym.name, TypeTree(sym.info))
+ Trees.TypeDef(Modifiers(sym), sym.name, TypeTree(sym.info))(defPos(sym))
.withType(refType(sym))
def ClassDef(cls: ClassSymbol, typeParams: List[TypeSymbol], body: List[TypedTree])(implicit ctx: Context): ClassDef[Type] = {
@@ -191,7 +193,7 @@ object TypedTrees {
.orElse(ctx.newLocalDummy(cls))
val impl = Trees.Template(parents, selfType, rest)
.withType(refType(localDummy))
- Trees.ClassDef(Modifiers(cls), cls.name, tparams, impl)
+ Trees.ClassDef(Modifiers(cls), cls.name, tparams, impl)(defPos(cls))
.withType(refType(cls))
}
diff --git a/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala b/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala
index 9ba2c46e5..9955d8b56 100644
--- a/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala
+++ b/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala
@@ -148,7 +148,7 @@ class ClassfileParser(
}
def parseMember(method: Boolean): Unit = {
- val start = new Offset(in.bp)
+ val start = indexCoord(in.bp)
val jflags = in.nextChar
val sflags =
if (method) FlagTranslation.methodFlags(jflags)
@@ -162,7 +162,7 @@ class ClassfileParser(
def complete(denot: LazySymDenotation) = {
val oldbp = in.bp
try {
- in.bp = denot.symbol.offset.value
+ in.bp = denot.symbol.coord.toIndex
val sym = denot.symbol
val jflags = in.nextChar
val isEnum = (jflags & JAVA_ACC_ENUM) != 0
@@ -335,7 +335,7 @@ class ClassfileParser(
while (sig(index) != '>') {
val tpname = subName(':'.==).toTypeName
val s = cctx.newLazySymbol(
- owner, tpname, Flags.TypeParam, new TypeParamCompleter(index), new Offset(index))
+ owner, tpname, Flags.TypeParam, new TypeParamCompleter(index), indexCoord(index))
tparams = tparams + (tpname -> s)
sig2typeBounds(tparams, skiptvs = true)
newTParams += s
diff --git a/src/dotty/tools/dotc/core/pickling/UnPickler.scala b/src/dotty/tools/dotc/core/pickling/UnPickler.scala
index 3d8be89b9..e3d08b304 100644
--- a/src/dotty/tools/dotc/core/pickling/UnPickler.scala
+++ b/src/dotty/tools/dotc/core/pickling/UnPickler.scala
@@ -68,7 +68,6 @@ object UnPickler {
/** Unpickle symbol table information descending from a class and/or module root
* from an array of bytes.
* @param bytes bytearray from which we unpickle
- * @param offset offset from which unpickling starts
* @param classroot the top-level class which is unpickled, or NoSymbol if inapplicable
* @param moduleroot the top-level module class which is unpickled, or NoSymbol if inapplicable
* @param filename filename associated with bytearray, only used for error messages
@@ -274,7 +273,7 @@ class UnPickler(bytes: Array[Byte], classRoot: LazyClassDenotation, moduleRoot:
/** Read a symbol, with possible disambiguation */
protected def readDisambiguatedSymbol(p: Symbol => Boolean)(): Symbol = {
- val start = new Offset(readIndex)
+ val start = indexCoord(readIndex)
val tag = readByte()
val end = readNat() + readIndex
def atEnd = readIndex == end
@@ -349,7 +348,7 @@ class UnPickler(bytes: Array[Byte], classRoot: LazyClassDenotation, moduleRoot:
def isModuleRoot = (name.toTermName == moduleRoot.name.toTermName) && (owner == moduleRoot.owner)
def completeRoot(denot: LazyClassDenotation): Symbol = {
- atReadPos(start.value, () => completeLocal(denot))
+ atReadPos(start.toIndex, () => completeLocal(denot))
denot.symbol
}
@@ -370,16 +369,16 @@ class UnPickler(bytes: Array[Byte], classRoot: LazyClassDenotation, moduleRoot:
name1 = name1.expandedName(owner)
flags1 |= TypeParamFlags
}
- cctx.newLazySymbol(owner, name1, flags1, symUnpickler, off = start)
+ cctx.newLazySymbol(owner, name1, flags1, symUnpickler, coord = start)
case CLASSsym =>
if (isClassRoot) completeRoot(classRoot)
else if (isModuleRoot) completeRoot(moduleRoot)
- else cctx.newLazyClassSymbol(owner, name.asTypeName, flags, classUnpickler, off = start)
+ else cctx.newLazyClassSymbol(owner, name.asTypeName, flags, classUnpickler, coord = start)
case MODULEsym | VALsym =>
if (isModuleRoot) {
moduleRoot.flags = flags
moduleRoot.symbol
- } else cctx.newLazySymbol(owner, name.asTermName, flags, symUnpickler, off = start)
+ } else cctx.newLazySymbol(owner, name.asTermName, flags, symUnpickler, coord = start)
case _ =>
errorBadSignature("bad symbol tag: " + tag)
})
@@ -420,7 +419,7 @@ class UnPickler(bytes: Array[Byte], classRoot: LazyClassDenotation, moduleRoot:
assignClassFields(denot, tp, selfType)
}
}
- atReadPos(denot.symbol.offset.value, parseToCompletion)
+ atReadPos(denot.symbol.coord.toIndex, parseToCompletion)
}
private object symUnpickler extends SymCompleter {