aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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 {