aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/ast
diff options
context:
space:
mode:
authorGuillaume Martres <smarter@ubuntu.com>2016-11-04 00:48:36 +0100
committerGitHub <noreply@github.com>2016-11-04 00:48:36 +0100
commit6ba6ea542d7915a48b426fea1f75f9cb8c2db424 (patch)
treef728f6c54fe8c2e57ae136ef08d6fb20eaca534b /src/dotty/tools/dotc/ast
parent98a92c6f4ec743edb9465071dcfd43f17dbf054b (diff)
parentd694f15a028cf14ea0cf210d3113c7b1d6af54e7 (diff)
downloaddotty-6ba6ea542d7915a48b426fea1f75f9cb8c2db424.tar.gz
dotty-6ba6ea542d7915a48b426fea1f75f9cb8c2db424.tar.bz2
dotty-6ba6ea542d7915a48b426fea1f75f9cb8c2db424.zip
Merge pull request #1587 from dotty-staging/change-tasty-pos
Fix Tasty positions
Diffstat (limited to 'src/dotty/tools/dotc/ast')
-rw-r--r--src/dotty/tools/dotc/ast/Positioned.scala6
-rw-r--r--src/dotty/tools/dotc/ast/TreeInfo.scala69
-rw-r--r--src/dotty/tools/dotc/ast/Trees.scala39
-rw-r--r--src/dotty/tools/dotc/ast/tpd.scala7
-rw-r--r--src/dotty/tools/dotc/ast/untpd.scala5
5 files changed, 88 insertions, 38 deletions
diff --git a/src/dotty/tools/dotc/ast/Positioned.scala b/src/dotty/tools/dotc/ast/Positioned.scala
index 8d364d439..bb6817603 100644
--- a/src/dotty/tools/dotc/ast/Positioned.scala
+++ b/src/dotty/tools/dotc/ast/Positioned.scala
@@ -24,7 +24,7 @@ abstract class Positioned extends DotClass with Product {
* positions in children.
*/
protected def setPos(pos: Position): Unit = {
- curPos = pos
+ setPosUnchecked(pos)
if (pos.exists) setChildPositions(pos.toSynthetic)
}
@@ -107,7 +107,7 @@ abstract class Positioned extends DotClass with Product {
/** The initial, synthetic position. This is usually the union of all positioned children's positions.
*/
- protected def initialPos: Position = {
+ def initialPos: Position = {
var n = productArity
var pos = NoPosition
while (n > 0) {
@@ -139,7 +139,7 @@ abstract class Positioned extends DotClass with Product {
(this.pos contains that.pos) && {
var n = productArity
var found = false
- while (n > 0 && !found) {
+ while (!found && n > 0) {
n -= 1
found = isParent(productElement(n))
}
diff --git a/src/dotty/tools/dotc/ast/TreeInfo.scala b/src/dotty/tools/dotc/ast/TreeInfo.scala
index 7911840c6..8b2915174 100644
--- a/src/dotty/tools/dotc/ast/TreeInfo.scala
+++ b/src/dotty/tools/dotc/ast/TreeInfo.scala
@@ -6,6 +6,7 @@ import core._
import Flags._, Trees._, Types._, Contexts._
import Names._, StdNames._, NameOps._, Decorators._, Symbols._
import util.HashSet
+import typer.ConstFold
trait TreeInfo[T >: Untyped <: Type] { self: Trees.Instance[T] =>
import TreeInfo._
@@ -289,13 +290,14 @@ trait UntypedTreeInfo extends TreeInfo[Untyped] { self: Trees.Instance[Untyped]
trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
import TreeInfo._
+ import tpd._
/** The purity level of this statement.
* @return pure if statement has no side effects
* idempotent if running the statement a second time has no side effects
* impure otherwise
*/
- private def statPurity(tree: tpd.Tree)(implicit ctx: Context): PurityLevel = unsplice(tree) match {
+ private def statPurity(tree: Tree)(implicit ctx: Context): PurityLevel = unsplice(tree) match {
case EmptyTree
| TypeDef(_, _)
| Import(_, _)
@@ -319,7 +321,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
* takes a different code path than all to follow; but they are idempotent
* because running the expression a second time gives the cached result.
*/
- private def exprPurity(tree: tpd.Tree)(implicit ctx: Context): PurityLevel = unsplice(tree) match {
+ private def exprPurity(tree: Tree)(implicit ctx: Context): PurityLevel = unsplice(tree) match {
case EmptyTree
| This(_)
| Super(_, _)
@@ -358,8 +360,8 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
private def minOf(l0: PurityLevel, ls: List[PurityLevel]) = (l0 /: ls)(_ min _)
- def isPureExpr(tree: tpd.Tree)(implicit ctx: Context) = exprPurity(tree) == Pure
- def isIdempotentExpr(tree: tpd.Tree)(implicit ctx: Context) = exprPurity(tree) >= Idempotent
+ def isPureExpr(tree: Tree)(implicit ctx: Context) = exprPurity(tree) == Pure
+ def isIdempotentExpr(tree: Tree)(implicit ctx: Context) = exprPurity(tree) >= Idempotent
/** The purity level of this reference.
* @return
@@ -369,17 +371,62 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
* @DarkDimius: need to make sure that lazy accessor methods have Lazy and Stable
* flags set.
*/
- private def refPurity(tree: tpd.Tree)(implicit ctx: Context): PurityLevel =
+ private def refPurity(tree: Tree)(implicit ctx: Context): PurityLevel =
if (!tree.tpe.widen.isParameterless) Pure
else if (!tree.symbol.isStable) Impure
else if (tree.symbol.is(Lazy)) Idempotent // TODO add Module flag, sinxce Module vals or not Lazy from the start.
else Pure
- def isPureRef(tree: tpd.Tree)(implicit ctx: Context) =
+ def isPureRef(tree: Tree)(implicit ctx: Context) =
refPurity(tree) == Pure
- def isIdempotentRef(tree: tpd.Tree)(implicit ctx: Context) =
+ def isIdempotentRef(tree: Tree)(implicit ctx: Context) =
refPurity(tree) >= Idempotent
+ /** If `tree` is a constant expression, its value as a Literal,
+ * or `tree` itself otherwise.
+ *
+ * Note: Demanding idempotency instead of purity in literalize is strictly speaking too loose.
+ * Example
+ *
+ * object O { final val x = 42; println("43") }
+ * O.x
+ *
+ * Strictly speaking we can't replace `O.x` with `42`. But this would make
+ * most expressions non-constant. Maybe we can change the spec to accept this
+ * kind of eliding behavior. Or else enforce true purity in the compiler.
+ * The choice will be affected by what we will do with `inline` and with
+ * Singleton type bounds (see SIP 23). Presumably
+ *
+ * object O1 { val x: Singleton = 42; println("43") }
+ * object O2 { inline val x = 42; println("43") }
+ *
+ * should behave differently.
+ *
+ * O1.x should have the same effect as { println("43"); 42 }
+ *
+ * whereas
+ *
+ * O2.x = 42
+ *
+ * Revisit this issue once we have implemented `inline`. Then we can demand
+ * purity of the prefix unless the selection goes to an inline val.
+ *
+ * Note: This method should be applied to all term tree nodes that are not literals,
+ * that can be idempotent, and that can have constant types. So far, only nodes
+ * of the following classes qualify:
+ *
+ * Ident
+ * Select
+ * TypeApply
+ */
+ def constToLiteral(tree: Tree)(implicit ctx: Context): Tree = {
+ val tree1 = ConstFold(tree)
+ tree1.tpe.widenTermRefExpr match {
+ case ConstantType(value) if isIdempotentExpr(tree1) => Literal(value)
+ case _ => tree1
+ }
+ }
+
/** Is symbol potentially a getter of a mutable variable?
*/
def mayBeVarGetter(sym: Symbol)(implicit ctx: Context): Boolean = {
@@ -394,7 +441,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
/** Is tree a reference to a mutable variable, or to a potential getter
* that has a setter in the same class?
*/
- def isVariableOrGetter(tree: tpd.Tree)(implicit ctx: Context) = {
+ def isVariableOrGetter(tree: Tree)(implicit ctx: Context) = {
def sym = tree.symbol
def isVar = sym is Mutable
def isGetter =
@@ -419,8 +466,8 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
}
/** Strips layers of `.asInstanceOf[T]` / `_.$asInstanceOf[T]()` from an expression */
- def stripCast(tree: tpd.Tree)(implicit ctx: Context): tpd.Tree = {
- def isCast(sel: tpd.Tree) = sel.symbol == defn.Any_asInstanceOf
+ def stripCast(tree: Tree)(implicit ctx: Context): Tree = {
+ def isCast(sel: Tree) = sel.symbol == defn.Any_asInstanceOf
unsplice(tree) match {
case TypeApply(sel @ Select(inner, _), _) if isCast(sel) =>
stripCast(inner)
@@ -456,7 +503,7 @@ trait TypedTreeInfo extends TreeInfo[Type] { self: Trees.Instance[Type] =>
}
/** If tree is a closure, its body, otherwise tree itself */
- def closureBody(tree: tpd.Tree)(implicit ctx: Context): tpd.Tree = tree match {
+ def closureBody(tree: Tree)(implicit ctx: Context): Tree = tree match {
case Block((meth @ DefDef(nme.ANON_FUN, _, _, _, _)) :: Nil, Closure(_, _, _)) => meth.rhs
case _ => tree
}
diff --git a/src/dotty/tools/dotc/ast/Trees.scala b/src/dotty/tools/dotc/ast/Trees.scala
index 2c02e7d1e..9108a4d22 100644
--- a/src/dotty/tools/dotc/ast/Trees.scala
+++ b/src/dotty/tools/dotc/ast/Trees.scala
@@ -60,15 +60,19 @@ object Trees {
with Cloneable {
if (Stats.enabled) ntrees += 1
+
+ private def nxId = {
+ nextId += 1
+ //assert(nextId != 199, this)
+ nextId
+ }
/** A unique identifier for this tree. Used for debugging, and potentially
* tracking presentation compiler interactions
*/
- val uniqueId = {
- nextId += 1
- //assert(nextId != 214, this)
- nextId
- }
+ private var myUniqueId: Int = nxId
+
+ def uniqueId = myUniqueId
/** The type constructor at the root of the tree */
type ThisTree[T >: Untyped] <: Tree[T]
@@ -188,6 +192,12 @@ object Trees {
override def hashCode(): Int = uniqueId // for debugging; was: System.identityHashCode(this)
override def equals(that: Any) = this eq that.asInstanceOf[AnyRef]
+
+ override def clone: Tree[T] = {
+ val tree = super.clone.asInstanceOf[Tree[T]]
+ tree.myUniqueId = nxId
+ tree
+ }
}
class UnAssignedTypeException[T >: Untyped](tree: Tree[T]) extends RuntimeException {
@@ -502,7 +512,9 @@ object Trees {
/** A tree representing inlined code.
*
- * @param call The original call that was inlined
+ * @param call Info about the original call that was inlined
+ * Until PostTyper, this is the full call, afterwards only
+ * a reference to the toplevel class from which the call was inlined.
* @param bindings Bindings for proxies to be used in the inlined code
* @param expansion The inlined tree, minus bindings.
*
@@ -520,13 +532,12 @@ object Trees {
}
/** A type tree that represents an existing or inferred type */
- case class TypeTree[-T >: Untyped] private[ast] (original: Tree[T])
+ case class TypeTree[-T >: Untyped] ()
extends DenotingTree[T] with TypTree[T] {
type ThisTree[-T >: Untyped] = TypeTree[T]
- override def initialPos = NoPosition
- override def isEmpty = !hasType && original.isEmpty
+ override def isEmpty = !hasType
override def toString =
- s"TypeTree${if (hasType) s"[$typeOpt]" else s"($original)"}"
+ s"TypeTree${if (hasType) s"[$typeOpt]" else ""}"
}
/** ref.type */
@@ -960,10 +971,6 @@ object Trees {
case tree: Inlined if (call eq tree.call) && (bindings eq tree.bindings) && (expansion eq tree.expansion) => tree
case _ => finalize(tree, untpd.Inlined(call, bindings, expansion))
}
- def TypeTree(tree: Tree)(original: Tree): TypeTree = tree match {
- case tree: TypeTree if original eq tree.original => tree
- case _ => finalize(tree, untpd.TypeTree(original))
- }
def SingletonTypeTree(tree: Tree)(ref: Tree): SingletonTypeTree = tree match {
case tree: SingletonTypeTree if ref eq tree.ref => tree
case _ => finalize(tree, untpd.SingletonTypeTree(ref))
@@ -1106,7 +1113,7 @@ object Trees {
cpy.SeqLiteral(tree)(transform(elems), transform(elemtpt))
case Inlined(call, bindings, expansion) =>
cpy.Inlined(tree)(call, transformSub(bindings), transform(expansion))
- case TypeTree(original) =>
+ case TypeTree() =>
tree
case SingletonTypeTree(ref) =>
cpy.SingletonTypeTree(tree)(transform(ref))
@@ -1210,7 +1217,7 @@ object Trees {
this(this(x, elems), elemtpt)
case Inlined(call, bindings, expansion) =>
this(this(x, bindings), expansion)
- case TypeTree(original) =>
+ case TypeTree() =>
x
case SingletonTypeTree(ref) =>
this(x, ref)
diff --git a/src/dotty/tools/dotc/ast/tpd.scala b/src/dotty/tools/dotc/ast/tpd.scala
index d8db3306c..273fc8d0a 100644
--- a/src/dotty/tools/dotc/ast/tpd.scala
+++ b/src/dotty/tools/dotc/ast/tpd.scala
@@ -121,11 +121,8 @@ object tpd extends Trees.Instance[Type] with TypedTreeInfo {
def Inlined(call: Tree, bindings: List[MemberDef], expansion: Tree)(implicit ctx: Context): Inlined =
ta.assignType(untpd.Inlined(call, bindings, expansion), bindings, expansion)
- def TypeTree(original: Tree)(implicit ctx: Context): TypeTree =
- TypeTree(original.tpe, original)
-
- def TypeTree(tp: Type, original: Tree = EmptyTree)(implicit ctx: Context): TypeTree =
- untpd.TypeTree(original).withType(tp)
+ def TypeTree(tp: Type)(implicit ctx: Context): TypeTree =
+ untpd.TypeTree().withType(tp)
def SingletonTypeTree(ref: Tree)(implicit ctx: Context): SingletonTypeTree =
ta.assignType(untpd.SingletonTypeTree(ref), ref)
diff --git a/src/dotty/tools/dotc/ast/untpd.scala b/src/dotty/tools/dotc/ast/untpd.scala
index 6513dfdc3..ac3beaff4 100644
--- a/src/dotty/tools/dotc/ast/untpd.scala
+++ b/src/dotty/tools/dotc/ast/untpd.scala
@@ -186,7 +186,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
/** A type tree that gets its type from some other tree's symbol. Enters the
* type tree in the References attachment of the `from` tree as a side effect.
*/
- abstract class DerivedTypeTree extends TypeTree(EmptyTree) {
+ abstract class DerivedTypeTree extends TypeTree {
private var myWatched: Tree = EmptyTree
@@ -247,8 +247,7 @@ object untpd extends Trees.Instance[Untyped] with UntypedTreeInfo {
def SeqLiteral(elems: List[Tree], elemtpt: Tree): SeqLiteral = new SeqLiteral(elems, elemtpt)
def JavaSeqLiteral(elems: List[Tree], elemtpt: Tree): JavaSeqLiteral = new JavaSeqLiteral(elems, elemtpt)
def Inlined(call: tpd.Tree, bindings: List[MemberDef], expansion: Tree): Inlined = new Inlined(call, bindings, expansion)
- def TypeTree(original: Tree): TypeTree = new TypeTree(original)
- def TypeTree() = new TypeTree(EmptyTree)
+ def TypeTree() = new TypeTree()
def SingletonTypeTree(ref: Tree): SingletonTypeTree = new SingletonTypeTree(ref)
def AndTypeTree(left: Tree, right: Tree): AndTypeTree = new AndTypeTree(left, right)
def OrTypeTree(left: Tree, right: Tree): OrTypeTree = new OrTypeTree(left, right)