Skip to content

Change/treecopying #164

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 44 commits into from
Oct 11, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
2020938
Code to handle overloaded unapply/unapplySeq methods
odersky Aug 3, 2014
168e4f1
Added version settings -migration, -source
odersky Aug 3, 2014
e25232d
Annotation decorators for symbols
odersky Aug 3, 2014
85044e4
Type#foreachPart
odersky Aug 3, 2014
9748c9b
Changed first phase normalization and improvements to TreeTransform
odersky Aug 3, 2014
f87153b
Detect cycles and protected legal ones with LazyRefs
odersky Aug 7, 2014
058729c
LazyRefs break cycles for unpickled types
odersky Aug 8, 2014
19b6a04
Re-enabled checkbounds tests
odersky Aug 8, 2014
9ec3a4f
prepareStats should span all statement transforms
odersky Aug 9, 2014
978a714
Initial version of RefChecks
odersky Aug 9, 2014
80ee8b1
Made Phase a trait
odersky Aug 9, 2014
bb1972b
Fixed fully qualified name of migration annotation
odersky Aug 9, 2014
9024f25
ParamAccessors are assumed to have definition
odersky Aug 9, 2014
57c6c85
Disentangle phases from treetransforms
odersky Aug 9, 2014
96cd350
Module vals are lazy
odersky Aug 9, 2014
80b866f
In refined printer, show only source modifier flags.
odersky Aug 9, 2014
bbf777a
Narrow assertion for Scope#enter
odersky Aug 9, 2014
c2cdd3a
More targeted eta-lifting
odersky Aug 10, 2014
f606a47
Add Product{1,2} supertrait to case classes
odersky Aug 10, 2014
d388e94
Fix Object's scope after ersure
odersky Aug 11, 2014
b89c4af
Add CaseAccessor flag for case accessors
odersky Aug 11, 2014
c7f817f
Added some more methods as infix tree operations:
odersky Aug 11, 2014
98d2583
New methods in Definitions
odersky Aug 11, 2014
ab63413
Sperate matchingDecl and mathingMember.
odersky Aug 11, 2014
ce53589
Add SyntheticMethods miniphase
odersky Aug 11, 2014
974f706
Avoid printing expanded names
odersky Aug 11, 2014
a3cc938
Use _1 intstead of get for accessing unary case class parameters
odersky Aug 11, 2014
81745e2
Fix a problem due to different type inference
odersky Aug 12, 2014
843f976
Two fixes in desugar
odersky Aug 12, 2014
472d711
Add matchesLoosely
odersky Aug 12, 2014
ab8ee53
mergeDenot should prefer concerete over deferred.
odersky Aug 12, 2014
deaa0d8
Package denotations are never transformed
odersky Aug 13, 2014
ece7656
Erasure should copy denotations only if they are changed.
odersky Aug 13, 2014
3558e07
Change access boundary of protected[this]
odersky Aug 13, 2014
34f73de
Fix and enable RefChecks
odersky Aug 13, 2014
a878d19
Changes to tree copying
odersky Jul 6, 2014
891aeba
Switched to new cpy scheme.
odersky Aug 13, 2014
0b41954
Restrict treee copiers with default arguments to trees with more than…
odersky Aug 13, 2014
3ce9d15
Drop commented out code.
odersky Aug 13, 2014
01f2475
Make typed tree copiers selectively retype nodes.
odersky Aug 15, 2014
9326a00
Delete propagateType and RetypingTreeMap
odersky Aug 15, 2014
53ab5f0
Add hook for phase when a TreeTransform is run.
odersky Aug 15, 2014
c54cd3e
Extend retyping to more copy methods.
odersky Aug 15, 2014
7d414eb
Roll Uncurry into Erasure
odersky Aug 16, 2014
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 6 additions & 8 deletions src/dotty/tools/dotc/Compiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import Contexts._
import Periods._
import Symbols._
import Scopes._
import typer.{FrontEnd, Typer, Mode, ImportInfo}
import typer.{FrontEnd, Typer, Mode, ImportInfo, RefChecks}
import reporting.ConsoleReporter
import dotty.tools.dotc.core.Phases.Phase
import dotty.tools.dotc.transform._
Expand All @@ -19,22 +19,20 @@ class Compiler {
def phases: List[List[Phase]] =
List(
List(new FrontEnd),
List(new Companions),
List(new FirstTransform, new SyntheticMethods),
List(new SuperAccessors),
// pickling and refchecks goes here
List(new ElimRepeated, new ElimLocals),
// pickling goes here
List(new RefChecks, new ElimRepeated, new ElimLocals),
List(new ExtensionMethods),
List(new TailRec),
List(new PatternMatcher,
new LazyValTranformContext().transformer,
// new LazyValTranformContext().transformer, // disabled, awaiting fixes
new Splitter),
List(new Nullarify,
new TypeTestsCasts,
new InterceptedMethods,
new Literalize),
List(new Erasure),
List(new UncurryTreeTransform
/* , new Constructors */)
List(new Erasure)
)

var runId = 1
Expand Down
4 changes: 2 additions & 2 deletions src/dotty/tools/dotc/ElimLocals.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,11 @@ import DenotTransformers.SymTransformer
import Phases.Phase
import Contexts.Context
import SymDenotations.SymDenotation
import TreeTransforms.TreeTransform
import TreeTransforms.MiniPhaseTransform
import Flags.Local

/** Widens all private[this] and protected[this] qualifiers to just private/protected */
class ElimLocals extends TreeTransform with SymTransformer { thisTransformer =>
class ElimLocals extends MiniPhaseTransform with SymTransformer { thisTransformer =>
override def name = "elimlocals"

def transformSym(ref: SymDenotation)(implicit ctx: Context) =
Expand Down
100 changes: 51 additions & 49 deletions src/dotty/tools/dotc/ast/Desugar.scala
Original file line number Diff line number Diff line change
Expand Up @@ -72,13 +72,13 @@ object desugar {

/** A type definition copied from `tdef` with a rhs typetree derived from it */
def derivedTypeParam(tdef: TypeDef) =
cpy.TypeDef(tdef, tdef.mods, tdef.name,
new DerivedFromParamTree() withPos tdef.rhs.pos watching tdef, tdef.tparams) // todo: copy type params
cpy.TypeDef(tdef)(
rhs = new DerivedFromParamTree() withPos tdef.rhs.pos watching tdef)

/** A value definition copied from `vdef` with a tpt typetree derived from it */
def derivedTermParam(vdef: ValDef) =
cpy.ValDef(vdef, vdef.mods, vdef.name,
new DerivedFromParamTree() withPos vdef.tpt.pos watching vdef, vdef.rhs)
cpy.ValDef(vdef)(
tpt = new DerivedFromParamTree() withPos vdef.tpt.pos watching vdef)

// ----- Desugar methods -------------------------------------------------

Expand All @@ -98,7 +98,7 @@ object desugar {
// I don't see a problem with that but if there is one we can avoid it by making a copy here.
val setterParam = makeSyntheticParameter(tpt = (new SetterParamTree).watching(vdef))
val setterRhs = if (vdef.rhs.isEmpty) EmptyTree else unitLiteral
val setter = cpy.DefDef(vdef,
val setter = cpy.DefDef(vdef)(
mods | Accessor, name.setterName, Nil, (setterParam :: Nil) :: Nil,
TypeTree(defn.UnitType), setterRhs) // rhs gets filled in later, when field is generated and getter has parameters
Thicket(vdef, setter)
Expand All @@ -124,14 +124,14 @@ object desugar {
val DefDef(mods, name, tparams, vparamss, tpt, rhs) = meth
val epbuf = new ListBuffer[ValDef]
val tparams1 = tparams mapConserve {
case tparam @ TypeDef(mods, name, ContextBounds(tbounds, cxbounds)) =>
case tparam @ TypeDef(_, _, ContextBounds(tbounds, cxbounds)) =>
for (cxbound <- cxbounds) {
val paramFlags: FlagSet = if (isPrimaryConstructor) PrivateLocalParamAccessor else Param
val epname = (nme.EVIDENCE_PARAM_PREFIX.toString + epbuf.length).toTermName
epbuf +=
ValDef(Modifiers(paramFlags | Implicit), epname, cxbound, EmptyTree)
}
cpy.TypeDef(tparam, mods, name, tbounds, tparam.tparams)
cpy.TypeDef(tparam)(rhs = tbounds)
case tparam =>
tparam
}
Expand All @@ -146,7 +146,7 @@ object desugar {
case _ =>
vparamss :+ evidenceParams
}
cpy.DefDef(meth, mods, name, tparams1, vparamss1, tpt, rhs)
cpy.DefDef(meth)(tparams = tparams1, vparamss = vparamss1)
}

/** The longest prefix of parameter lists in vparamss whose total length does not exceed `n` */
Expand All @@ -159,7 +159,7 @@ object desugar {
}

def normalizedVparamss = vparamss map (_ map (vparam =>
cpy.ValDef(vparam, vparam.mods, vparam.name, vparam.tpt, EmptyTree)))
cpy.ValDef(vparam)(rhs = EmptyTree)))

def defaultGetters(vparamss: List[List[ValDef]], n: Int): List[DefDef] = vparamss match {
case (vparam :: vparams) :: vparamss1 =>
Expand All @@ -182,9 +182,9 @@ object desugar {
val defGetters = defaultGetters(vparamss, 0)
if (defGetters.isEmpty) meth1
else {
val mods1 = meth1.mods | DefaultParameterized
val meth2 = cpy.DefDef(meth1, meth1.mods | DefaultParameterized,
meth1.name, meth1.tparams, normalizedVparamss, meth1.tpt, meth1.rhs)
val meth2 = cpy.DefDef(meth1)(
mods = meth1.mods | DefaultParameterized,
vparamss = normalizedVparamss)
Thicket(meth2 :: defGetters)
}
}
Expand All @@ -196,25 +196,26 @@ object desugar {
* class C { type v C$T; type v T = C$T }
*/
def typeDef(tdef: TypeDef)(implicit ctx: Context): Tree = {
val TypeDef(mods, name, rhs) = tdef
if (mods is PrivateLocalParam) {
val tparam = cpy.TypeDef(tdef,
mods &~ PrivateLocal | ExpandedName, name.expandedName(ctx.owner), rhs, tdef.tparams)
val alias = cpy.TypeDef(tdef,
Modifiers(PrivateLocalParamAccessor | Synthetic | mods.flags & VarianceFlags),
name, refOfDef(tparam))
if (tdef.mods is PrivateLocalParam) {
val tparam = cpy.TypeDef(tdef)(
mods = tdef.mods &~ PrivateLocal | ExpandedName,
name = tdef.name.expandedName(ctx.owner))
val alias = cpy.TypeDef(tdef)(
mods = Modifiers(PrivateLocalParamAccessor | Synthetic | tdef.mods.flags & VarianceFlags),
rhs = refOfDef(tparam),
tparams = Nil)
Thicket(tparam, alias)
}
else cpy.TypeDef(tdef, mods, name, rhs, tdef.tparams)
else tdef
}

private val synthetic = Modifiers(Synthetic)

private def toDefParam(tparam: TypeDef) =
cpy.TypeDef(tparam, Modifiers(Param), tparam.name, tparam.rhs, tparam.tparams)
cpy.TypeDef(tparam)(mods = Modifiers(Param))

private def toDefParam(vparam: ValDef) =
cpy.ValDef(vparam, Modifiers(Param | vparam.mods.flags & Implicit), vparam.name, vparam.tpt, vparam.rhs)
cpy.ValDef(vparam)(mods = Modifiers(Param | vparam.mods.flags & Implicit))

/** The expansion of a class definition. See inline comments for what is involved */
def classDef(cdef: TypeDef)(implicit ctx: Context): Tree = {
Expand All @@ -239,13 +240,12 @@ object desugar {
ListOfNil
}
else constr1.vparamss.nestedMap(toDefParam)
val constr = cpy.DefDef(constr1,
constr1.mods, constr1.name, constrTparams, constrVparamss, constr1.tpt, constr1.rhs)
val constr = cpy.DefDef(constr1)(tparams = constrTparams, vparamss = constrVparamss)

// Add constructor type parameters to auxiliary constructors
val normalizedBody = body map {
case ddef: DefDef if ddef.name.isConstructorName =>
cpy.DefDef(ddef, ddef.mods, ddef.name, constrTparams, ddef.vparamss, ddef.tpt, ddef.rhs)
cpy.DefDef(ddef)(tparams = constrTparams)
case stat =>
stat
}
Expand Down Expand Up @@ -288,20 +288,18 @@ object desugar {
DefDef(synthetic, name, Nil, Nil, TypeTree(), rhs)
val isDefinedMeth = syntheticProperty(nme.isDefined, Literal(Constant(true)))
val productArityMeth = syntheticProperty(nme.productArity, Literal(Constant(arity)))
def selectorName(n: Int) =
if (arity == 1) nme.get else nme.selectorName(n)
val caseParams = constrVparamss.head.toArray
val productElemMeths = for (i <- 0 until arity) yield
syntheticProperty(selectorName(i), Select(This(EmptyTypeName), caseParams(i).name))
syntheticProperty(nme.selectorName(i), Select(This(EmptyTypeName), caseParams(i).name))
val copyMeths =
if (mods is Abstract) Nil
else {
def copyDefault(vparam: ValDef) =
makeAnnotated(defn.UncheckedVarianceAnnot, refOfDef(vparam))
val copyFirstParams = derivedVparamss.head.map(vparam =>
cpy.ValDef(vparam, vparam.mods, vparam.name, vparam.tpt, copyDefault(vparam)))
cpy.ValDef(vparam)(rhs = copyDefault(vparam)))
val copyRestParamss = derivedVparamss.tail.nestedMap(vparam =>
cpy.ValDef(vparam, vparam.mods, vparam.name, vparam.tpt, EmptyTree))
cpy.ValDef(vparam)(rhs = EmptyTree))
DefDef(synthetic, nme.copy, derivedTparams, copyFirstParams :: copyRestParamss, TypeTree(), creatorExpr) :: Nil
}
copyMeths ::: isDefinedMeth :: productArityMeth :: productElemMeths.toList
Expand All @@ -312,12 +310,12 @@ object desugar {
def productConstr(n: Int) = {
val tycon = ref(defn.ProductNClass(n).typeRef)
val targs = constrVparamss.head map (_.tpt)
AppliedTypeTree(tycon, targs)
if (targs.isEmpty) tycon else AppliedTypeTree(tycon, targs)
}

// Case classes get a ProductN parent
var parents1 = parents
if ((mods is Case) && 2 <= arity && arity <= Definitions.MaxTupleArity)
if ((mods is Case) && arity <= Definitions.MaxTupleArity)
parents1 = parents1 :+ productConstr(arity)

// The thicket which is the desugared version of the companion object
Expand All @@ -326,7 +324,8 @@ object desugar {
moduleDef(
ModuleDef(
Modifiers(Synthetic), name.toTermName,
Template(emptyConstructor, parentTpt :: Nil, EmptyValDef, defs))).toList
Template(emptyConstructor, parentTpt :: Nil, EmptyValDef, defs)))
.withPos(cdef.pos).toList

// The companion object defifinitions, if a companion is needed, Nil otherwise.
// companion definitions include:
Expand All @@ -340,7 +339,8 @@ object desugar {
val companions =
if (mods is Case) {
val parent =
if (constrTparams.nonEmpty) anyRef // todo: also use anyRef if constructor has a dependent method type (or rule that out)!
if (constrTparams.nonEmpty || constrVparamss.length > 1) anyRef
// todo: also use anyRef if constructor has a dependent method type (or rule that out)!
else (constrVparamss :\ classTypeRef) ((vparams, restpe) => Function(vparams map (_.tpt), restpe))
val applyMeths =
if (mods is Abstract) Nil
Expand Down Expand Up @@ -379,21 +379,23 @@ object desugar {
val self1 = {
val selfType = if (self.tpt.isEmpty) classTypeRef else self.tpt
if (self.isEmpty) self
else cpy.ValDef(self, self.mods | SelfName, self.name, selfType, self.rhs)
else cpy.ValDef(self)(mods = self.mods | SelfName, tpt = selfType)
}

val cdef1 = {
val originalTparams = constr1.tparams.toIterator
val originalVparams = constr1.vparamss.toIterator.flatten
val tparamAccessors = derivedTparams map { tdef =>
cpy.TypeDef(tdef, originalTparams.next.mods, tdef.name, tdef.rhs, tdef.tparams)
cpy.TypeDef(tdef)(mods = originalTparams.next.mods)
}
val caseAccessor = if (mods is Case) CaseAccessor else EmptyFlags
val vparamAccessors = derivedVparamss.flatten map { vdef =>
cpy.ValDef(vdef, originalVparams.next.mods, vdef.name, vdef.tpt, vdef.rhs)
cpy.ValDef(vdef)(mods = originalVparams.next.mods | caseAccessor)
}
cpy.TypeDef(cdef, mods, name,
cpy.Template(impl, constr, parents1, self1,
tparamAccessors ::: vparamAccessors ::: normalizedBody ::: caseClassMeths))
cpy.TypeDef(cdef)(
rhs = cpy.Template(impl)(constr, parents1, self1,
tparamAccessors ::: vparamAccessors ::: normalizedBody ::: caseClassMeths),
tparams = Nil)
}

// install the watch on classTycon
Expand All @@ -414,18 +416,18 @@ object desugar {
* <module> final class name$ extends parents { self: name.type => body }
*/
def moduleDef(mdef: ModuleDef)(implicit ctx: Context): Tree = {
val ModuleDef(mods, name, tmpl @ Template(constr, parents, self, body)) = mdef
val ModuleDef(mods, name, tmpl) = mdef
if (mods is Package)
PackageDef(Ident(name), cpy.ModuleDef(mdef, mods &~ Package, nme.PACKAGE, tmpl) :: Nil)
PackageDef(Ident(name), cpy.ModuleDef(mdef)(mods &~ Package, nme.PACKAGE, tmpl) :: Nil)
else {
val clsName = name.moduleClassName
val clsRef = Ident(clsName)
val modul = ValDef(mods | ModuleCreationFlags, name, clsRef, New(clsRef, Nil)) withPos mdef.pos
val ValDef(selfMods, selfName, selfTpt, selfRhs) = self
if (!selfTpt.isEmpty) ctx.error("object definition may not have a self type", self.pos)
val ValDef(selfMods, selfName, selfTpt, selfRhs) = tmpl.self
if (!selfTpt.isEmpty) ctx.error("object definition may not have a self type", tmpl.self.pos)
val clsSelf = ValDef(selfMods, selfName, SingletonTypeTree(Ident(name)), selfRhs)
.withPos(self.pos orElse tmpl.pos.startPos)
val clsTmpl = cpy.Template(tmpl, constr, parents, clsSelf, body)
.withPos(tmpl.self.pos orElse tmpl.pos.startPos)
val clsTmpl = cpy.Template(tmpl)(self = clsSelf, body = tmpl.body)
val cls = TypeDef(mods.toTypeFlags & AccessFlags | ModuleClassCreationFlags, clsName, clsTmpl)
Thicket(modul, classDef(cls))
}
Expand Down Expand Up @@ -502,7 +504,7 @@ object desugar {
*/
def block(tree: Block)(implicit ctx: Context): Block = tree.expr match {
case EmptyTree =>
cpy.Block(tree, tree.stats,
cpy.Block(tree)(tree.stats,
unitLiteral withPos (if (tree.stats.isEmpty) tree.pos else tree.pos.endPos))
case _ =>
tree
Expand All @@ -515,7 +517,7 @@ object desugar {
val TypeBoundsTree(lo, hi) = tree
val lo1 = if (lo.isEmpty) untpd.TypeTree(defn.NothingType) else lo
val hi1 = if (hi.isEmpty) untpd.TypeTree(defn.AnyType) else hi
cpy.TypeBoundsTree(tree, lo1, hi1)
cpy.TypeBoundsTree(tree)(lo1, hi1)
}

/** Make closure corresponding to function.
Expand Down Expand Up @@ -562,7 +564,7 @@ object desugar {
*/
def makeBinop(left: Tree, op: Name, right: Tree): Tree = {
def assignToNamedArg(arg: Tree) = arg match {
case Assign(Ident(name), rhs) => cpy.NamedArg(arg, name, rhs)
case Assign(Ident(name), rhs) => cpy.NamedArg(arg)(name, rhs)
case _ => arg
}
if (isLeftAssoc(op)) {
Expand Down
14 changes: 11 additions & 3 deletions src/dotty/tools/dotc/ast/TreeInfo.scala
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,19 @@ trait TreeInfo[T >: Untyped <: Type] { self: Trees.Instance[T] =>
/** The number of arguments in an application */
def numArgs(tree: Tree): Int = unsplice(tree) match {
case Apply(fn, args) => numArgs(fn) + args.length
case TypeApply(fn, args) => numArgs(fn)
case Block(stats, expr) => numArgs(expr)
case TypeApply(fn, _) => numArgs(fn)
case Block(_, expr) => numArgs(expr)
case _ => 0
}

/** The (last) list of arguments of an application */
def arguments(tree: Tree): List[Tree] = unsplice(tree) match {
case Apply(_, args) => args
case TypeApply(fn, _) => arguments(fn)
case Block(_, expr) => arguments(expr)
case _ => Nil
}

/** Is tree a self constructor call this(...)? I.e. a call to a constructor of the
* same object?
*/
Expand Down Expand Up @@ -253,7 +261,7 @@ trait TreeInfo[T >: Untyped <: Type] { self: Trees.Instance[T] =>
* is an abstract typoe declaration
*/
def lacksDefinition(mdef: MemberDef) = mdef match {
case mdef: ValOrDefDef => mdef.rhs.isEmpty && !mdef.name.isConstructorName
case mdef: ValOrDefDef => mdef.rhs.isEmpty && !mdef.name.isConstructorName && !mdef.mods.is(ParamAccessor)
case mdef: TypeDef => mdef.rhs.isEmpty || mdef.rhs.isInstanceOf[TypeBoundsTree]
case _ => false
}
Expand Down
Loading