From a3f6a1df1bd623ee913e41f739b3f13ac9638d14 Mon Sep 17 00:00:00 2001 From: Martin Odersky Date: Thu, 13 Jun 2013 21:30:54 +0200 Subject: Dropping type parameters from typed TypeDefs. Typed TypeDefs no longer carry tparams. Untyped ones still do, but there is a special PolyTypeDef node for them in untpd. Also, fixed flatten and DeSugarTest to deal with new tree desugarings which are not idempotent (e.g. desugar.classDef, or desugar.valDef). --- src/dotty/tools/dotc/ast/CheckTrees.scala | 2 +- src/dotty/tools/dotc/ast/Desugar.scala | 23 ++++---- src/dotty/tools/dotc/ast/TreeInfo.scala | 8 +-- src/dotty/tools/dotc/ast/Trees.scala | 59 +++++++++++-------- src/dotty/tools/dotc/ast/TypedTrees.scala | 2 +- src/dotty/tools/dotc/ast/UntypedTrees.scala | 16 +++++- src/dotty/tools/dotc/parsing/Parsers.scala | 8 +-- src/dotty/tools/dotc/printing/RefinedPrinter.scala | 10 ++-- src/dotty/tools/dotc/typer/Typer.scala | 5 +- test/test/DeSugarTest.scala | 12 ++-- test/test/showTree.scala | 66 +++------------------- 11 files changed, 92 insertions(+), 119 deletions(-) diff --git a/src/dotty/tools/dotc/ast/CheckTrees.scala b/src/dotty/tools/dotc/ast/CheckTrees.scala index ae7fc5fc1..71bceebf1 100644 --- a/src/dotty/tools/dotc/ast/CheckTrees.scala +++ b/src/dotty/tools/dotc/ast/CheckTrees.scala @@ -222,7 +222,7 @@ object CheckTrees { check(rhs.isValue) check(rhs.tpe <:< tpt.tpe) } - case TypeDef(mods, name, _, tpt) => + case TypeDef(mods, name, tpt) => check(tpt.tpe.isInstanceOf[TypeBounds]) case Template(constr, parents, selfType, body) => case ClassDef(mods, names, impl) => diff --git a/src/dotty/tools/dotc/ast/Desugar.scala b/src/dotty/tools/dotc/ast/Desugar.scala index cb6e00ebf..390b846f6 100644 --- a/src/dotty/tools/dotc/ast/Desugar.scala +++ b/src/dotty/tools/dotc/ast/Desugar.scala @@ -40,16 +40,15 @@ object desugar { def defDef(meth: DefDef, isPrimaryConstructor: Boolean = false): DefDef = { val DefDef(mods, name, tparams, vparamss, tpt, rhs) = meth val epbuf = new ListBuffer[ValDef] - def makeEvidenceParam(cxBound: Tree): ValDef = ??? val tparams1 = tparams mapConserve { - case tparam @ TypeDef(mods, name, ttparams, ContextBounds(tbounds, cxbounds)) => + case tparam @ TypeDef(mods, name, 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) } - tparam.derivedTypeDef(mods, name, ttparams, tbounds) + tparam.derivedTypeDef(mods, name, tbounds, tparam.tparams) case tparam => tparam } @@ -68,13 +67,13 @@ object desugar { } def typeDef(tdef: TypeDef)(implicit ctx: Context): Tree = { - val TypeDef(mods, name, tparams, rhs) = tdef + val TypeDef(mods, name, rhs) = tdef if (mods is PrivateLocalParamAccessor) { val tparam = tdef.derivedTypeDef( - tdef.mods &~ PrivateLocal | ExpandedName, tdef.name.expandedName(ctx.owner), tdef.tparams, tdef.rhs) + tdef.mods &~ PrivateLocal | ExpandedName, tdef.name.expandedName(ctx.owner), tdef.rhs, tdef.tparams) val alias = tdef.derivedTypeDef( - Modifiers(PrivateLocal | Synthetic), tdef.name, Nil, refOfDef(tparam)) - Thicket(tparam :: alias :: Nil) + Modifiers(PrivateLocal | Synthetic), tdef.name, refOfDef(tparam)) + Thicket(tparam, alias) } else tdef } @@ -88,7 +87,7 @@ object desugar { val constr1 = defDef(constr0, isPrimaryConstructor = true) val tparams = constr1.tparams.map(tparam => tparam.derivedTypeDef( - Modifiers(Param), tparam.name, tparam.tparams, tparam.rhs)) + Modifiers(Param), tparam.name, tparam.rhs, tparam.tparams)) // ensure parameter list is non-empty val vparamss = @@ -167,7 +166,7 @@ object desugar { val cdef1 = cdef.derivedClassDef(mods, name, impl.derivedTemplate(constr, parents, self, constr1.tparams ::: constr1.vparamss.flatten ::: body ::: caseClassMeths)) - Thicket(cdef1 :: caseCompanions ::: implicitWrappers) + Thicket.make(cdef1 :: caseCompanions ::: implicitWrappers) } /** Expand to: @@ -182,7 +181,7 @@ object desugar { val clsSelf = self.derivedValDef(self.mods, self.name, SingletonTypeTree(Ident(name)), self.rhs) val clsTmpl = tmpl.derivedTemplate(constr, parents, clsSelf, body) val cls = ClassDef(mods.toTypeFlags & AccessFlags | ModuleClassCreationFlags, clsName, clsTmpl) - Thicket(cls :: valDef(modul).toList) + Thicket(cls, valDef(modul)) } def memberDef(tree: Tree)(implicit ctx: Context): Tree = tree match { @@ -412,7 +411,7 @@ object desugar { val restDefs = for (((named, tpt), n) <- vars.zipWithIndex) yield derivedValDef(mods, named, tpt, selector(n)) - Thicket(firstDef :: restDefs) + Thicket.make(firstDef :: restDefs) } } @@ -494,7 +493,7 @@ object desugar { makeFor(nme.map, nme.flatMap, enums, body) orElse tree case PatDef(mods, pats, tpt, rhs) => val pats1 = if (tpt.isEmpty) pats else pats map (Typed(_, tpt)) - Thicket(pats1 map (makePatDef(mods, _, rhs))) + Thicket.make(pats1 map (makePatDef(mods, _, rhs))) case _ => tree } diff --git a/src/dotty/tools/dotc/ast/TreeInfo.scala b/src/dotty/tools/dotc/ast/TreeInfo.scala index cfb175e0b..11d50fc1b 100644 --- a/src/dotty/tools/dotc/ast/TreeInfo.scala +++ b/src/dotty/tools/dotc/ast/TreeInfo.scala @@ -17,7 +17,7 @@ abstract class TreeInfo { def isDeclarationOrTypeDef(tree: Tree[_ >: Untyped]): Boolean = tree match { case DefDef(_, _, _, _, _, EmptyTree) | ValDef(_, _, _, EmptyTree) - | TypeDef(_, _, _, _) => true + | TypeDef(_, _, _) => true case _ => false } @@ -26,7 +26,7 @@ abstract class TreeInfo { def isInterfaceMember(tree: Tree[_ >: Untyped]): Boolean = tree match { case EmptyTree => true case Import(_, _) => true - case TypeDef(_, _, _, _) => true + case TypeDef(_, _, _) => true case DefDef(mods, _, _, _, _, __) => mods.flags is Deferred case ValDef(mods, _, _, _) => mods is Deferred case _ => false @@ -38,7 +38,7 @@ abstract class TreeInfo { def isIdempotentDef(tree: Tree[Type])(implicit ctx: Context): Boolean = tree match { case EmptyTree | ClassDef(_, _, _) - | TypeDef(_, _, _, _) + | TypeDef(_, _, _) | Import(_, _) | DefDef(_, _, _, _, _, _) => true @@ -232,7 +232,7 @@ abstract class TreeInfo { } def isEarlyTypeDef(tree: Tree[_ >: Untyped]) = tree match { - case TypeDef(mods, _, _, _) => mods is Scala2PreSuper + case TypeDef(mods, _, _) => mods is Scala2PreSuper case _ => false } diff --git a/src/dotty/tools/dotc/ast/Trees.scala b/src/dotty/tools/dotc/ast/Trees.scala index ded027e42..7e0ac3bdc 100644 --- a/src/dotty/tools/dotc/ast/Trees.scala +++ b/src/dotty/tools/dotc/ast/Trees.scala @@ -571,10 +571,11 @@ object Trees { /** mods type name = rhs or * mods type name >: lo <: hi, if rhs = TypeBoundsTree(lo, hi) */ - case class TypeDef[T >: Untyped](mods: Modifiers[T], name: TypeName, tparams: List[TypeDef[T]], rhs: Tree[T]) + case class TypeDef[T >: Untyped](mods: Modifiers[T], name: TypeName, rhs: Tree[T]) extends MemberDef[T] { type ThisTree[T >: Untyped] = TypeDef[T] - def withName(name: Name) = this.derivedTypeDef(mods, name.toTypeName, tparams, rhs) + def withName(name: Name) = this.derivedTypeDef(mods, name.toTypeName, rhs, tparams) + def tparams: List[untpd.TypeDef] = Nil } /** extends parents { self => body } */ @@ -657,8 +658,8 @@ object Trees { object Thicket { def apply[T >: Untyped](): Thicket[T] = emptyTree() - def apply[T >: Untyped](x1: Tree[T], x2: Tree[T]): Thicket[T] = Thicket(List(x1, x2)) - def apply[T >: Untyped](x1: Tree[T], x2: Tree[T], x3: Tree[T]): Thicket[T] = Thicket(List(x1, x2, x3)) + def apply[T >: Untyped](x1: Tree[T], x2: Tree[T]): Thicket[T] = Thicket(x1 :: x2 :: Nil) + def apply[T >: Untyped](x1: Tree[T], x2: Tree[T], x3: Tree[T]): Thicket[T] = Thicket(x1 :: x2 :: x3 :: Nil) def make[T >: Untyped](xs: List[Tree[T]]): Tree[T] = flatten(xs) match { case x :: Nil => x case _ => apply(xs) @@ -876,9 +877,13 @@ object Trees { case tree: DefDef[_] if (mods == tree.mods) && (name == tree.name) && (tparams eq tree.tparams) && (vparamss eq tree.vparamss) && (tpt eq tree.tpt) && (rhs eq tree.rhs) => tree case _ => DefDef(mods, name, tparams, vparamss, tpt, rhs).copyAttr(tree) } - def derivedTypeDef(mods: Modifiers[T], name: TypeName, tparams: List[TypeDef[T]], rhs: Tree[T]): TypeDef[T] = tree match { - case tree: TypeDef[_] if (mods == tree.mods) && (name == tree.name) && (tparams eq tree.tparams) && (rhs eq tree.rhs) => tree - case _ => TypeDef(mods, name, tparams, rhs).copyAttr(tree) + def derivedTypeDef(mods: Modifiers[T], name: TypeName, rhs: Tree[T], tparams: List[untpd.TypeDef] = Nil): TypeDef[T] = tree match { + case tree: TypeDef[_] if (mods == tree.mods) && (name == tree.name) && (rhs eq tree.rhs) && (tparams eq tree.tparams) => tree + case _ => + if (tparams.nonEmpty) + (untpd.typeDef _).asInstanceOf[(Modifiers[T], TypeName, List[untpd.TypeDef], Tree[T]) => TypeDef[T]]( + mods, name, tparams, rhs).copyAttr(tree) + else TypeDef(mods, name, rhs).copyAttr(tree) } def derivedTemplate(constr: DefDef[T], parents: List[Tree[T]], self: ValDef[T], body: List[Tree[T]]): Template[T] = tree match { case tree: Template[_] if (constr eq tree.constr) && (parents eq tree.parents) && (self eq tree.self) && (body eq tree.body) => tree @@ -982,8 +987,8 @@ object Trees { finishValDef(tree.derivedValDef(mods, name, transform(tpt, c), transform(rhs, c)), tree, c, plugins) case DefDef(mods, name, tparams, vparamss, tpt, rhs) => finishDefDef(tree.derivedDefDef(mods, name, transformSub(tparams, c), vparamss mapConserve (transformSub(_, c)), transform(tpt, c), transform(rhs, c)), tree, c, plugins) - case TypeDef(mods, name, tparams, rhs) => - finishTypeDef(tree.derivedTypeDef(mods, name, transformSub(tparams, c), transform(rhs, c)), tree, c, plugins) + case tree @ TypeDef(mods, name, rhs) => + finishTypeDef(tree.derivedTypeDef(mods, name, transform(rhs, c), tree.tparams), tree, c, plugins) case Template(constr, parents, self, body) => finishTemplate(tree.derivedTemplate(transformSub(constr, c), transform(parents, c), transformSub(self, c), transform(body, c)), tree, c, plugins) case ClassDef(mods, name, impl) => @@ -1064,17 +1069,26 @@ object Trees { def flatten[T >: Untyped](trees: List[Tree[T]]): List[Tree[T]] = { var buf: ListBuffer[Tree[T]] = null + def add(tree: Tree[T]) = { + assert(!tree.isInstanceOf[Thicket[_]]) + buf += tree + } var xs = trees while (xs.nonEmpty) { xs.head match { case Thicket(elems) => - if (buf == null) buf = new ListBuffer - var ys = trees - while (ys ne xs) { - buf += ys.head - ys = ys.tail + if (buf == null) { + buf = new ListBuffer + var ys = trees + while (ys ne xs) { + buf += ys.head + ys = ys.tail + } + } + for (elem <- elems) { + assert(!elem.isInstanceOf[Thicket[_]]) + buf += elem } - buf ++= elems case tree => if (buf != null) buf += tree } @@ -1155,8 +1169,8 @@ object Trees { tree.derivedValDef(mods, name, transform(tpt), transform(rhs)) case DefDef(mods, name, tparams, vparamss, tpt, rhs) => tree.derivedDefDef(mods, name, transformSub(tparams), vparamss mapConserve (transformSub(_)), transform(tpt), transform(rhs)) - case TypeDef(mods, name, tparams, rhs) => - tree.derivedTypeDef(mods, name, transformSub(tparams), transform(rhs)) + case tree @ TypeDef(mods, name, rhs) => + tree.derivedTypeDef(mods, name, transform(rhs), tree.tparams) case Template(constr, parents, self, body) => tree.derivedTemplate(transformSub(constr), transform(parents), transformSub(self), transformStats(body)) case ClassDef(mods, name, impl) => @@ -1168,9 +1182,8 @@ object Trees { case Annotated(annot, arg) => tree.derivedAnnotated(transform(annot), transform(arg)) case Thicket(trees) => - val ts1 = trees.toList - val ts2 = transform(ts1) - if (ts1 eq ts2) tree else Thicket(ts2) + val trees1 = transform(trees) + if (trees1 eq trees) tree else Thicket(trees1) case tree @ SharedTree(shared) => sharedMemo get tree match { case Some(tree1) => tree1 @@ -1183,7 +1196,7 @@ object Trees { def transformStats(trees: List[Tree[T]]): List[Tree[T]] = transform(trees) def transform(trees: List[Tree[T]]): List[Tree[T]] = - flatten(trees) mapConserve (transform(_)) + flatten(trees mapConserve (transform(_))) def transformSub(tree: Tree[T]): tree.ThisTree[T] = transform(tree).asInstanceOf[tree.ThisTree[T]] def transformSub[TT <: Tree[T]](trees: List[TT]): List[TT] = @@ -1263,8 +1276,8 @@ object Trees { this(this(x, tpt), rhs) case DefDef(mods, name, tparams, vparamss, tpt, rhs) => this(this((this(x, tparams) /: vparamss)(apply), tpt), rhs) - case TypeDef(mods, name, tparams, rhs) => - this(this(x, tparams), rhs) + case TypeDef(mods, name, rhs) => + this(x, rhs) case Template(constr, parents, self, body) => this(this(this(this(x, constr), parents), self), body) case ClassDef(mods, name, impl) => diff --git a/src/dotty/tools/dotc/ast/TypedTrees.scala b/src/dotty/tools/dotc/ast/TypedTrees.scala index e52c7d538..2f1da6133 100644 --- a/src/dotty/tools/dotc/ast/TypedTrees.scala +++ b/src/dotty/tools/dotc/ast/TypedTrees.scala @@ -210,7 +210,7 @@ object tpd extends Trees.Instance[Type] { } def TypeDef(sym: TypeSymbol)(implicit ctx: Context): TypeDef = - Trees.TypeDef(Modifiers(sym), sym.name, Nil, TypeTree(sym.info)) // !!! fill in typeParams + Trees.TypeDef(Modifiers(sym), sym.name, TypeTree(sym.info)) .withType(refType(sym)).checked def ClassDef(cls: ClassSymbol, typeParams: List[TypeSymbol], constr: DefDef, body: List[Tree])(implicit ctx: Context): ClassDef = { diff --git a/src/dotty/tools/dotc/ast/UntypedTrees.scala b/src/dotty/tools/dotc/ast/UntypedTrees.scala index 4af05acfb..dacf13510 100644 --- a/src/dotty/tools/dotc/ast/UntypedTrees.scala +++ b/src/dotty/tools/dotc/ast/UntypedTrees.scala @@ -43,6 +43,12 @@ object untpd extends Trees.Instance[Untyped] { case class ContextBounds(bounds: TypeBoundsTree, cxBounds: List[Tree]) extends TypTree case class PatDef(mods: Modifiers, pats: List[Tree], tpt: Tree, rhs: Tree) extends Tree + class PolyTypeDef(mods: Modifiers, name: TypeName, override val tparams: List[TypeDef], rhs: Tree) + extends TypeDef(mods, name, rhs) + + def typeDef(mods: Modifiers, name: TypeName, tparams: List[TypeDef], rhs: Tree): TypeDef = + if (tparams.isEmpty) TypeDef(mods, name, rhs) else new PolyTypeDef(mods, name, tparams, rhs) + // ------ Untyped tree values and creation methods --------------------- val unitLiteral = Literal(Constant()) @@ -98,9 +104,13 @@ object untpd extends Trees.Instance[Untyped] { implicit class UntypedTreeCopier(val tree: Tree) extends AnyVal { def derivedModuleDef(mods: Modifiers, name: TermName, impl: Template) = tree match { - case tree: ModuleDef if (mods eq tree.mods) && (name eq tree.name) && (impl eq tree.impl) =>tree + case tree: ModuleDef if (mods eq tree.mods) && (name eq tree.name) && (impl eq tree.impl) => tree case _ => ModuleDef(mods, name, impl).copyAttr(tree) } + def derivedPolyTypeDef(mods: Modifiers, name: TypeName, tparams: List[TypeDef], rhs: Tree) = tree match { + case tree: PolyTypeDef if (mods eq tree.mods) && (name eq tree.name) && (tparams eq tree.tparams) && (rhs eq tree.rhs) => tree + case _ => new PolyTypeDef(mods, name, tparams, rhs).copyAttr(tree) + } def derivedSymbolLit(str: String) = tree match { case tree: SymbolLit if (str == tree.str) => tree case _ => SymbolLit(str).copyAttr(tree) @@ -203,6 +213,8 @@ object untpd extends Trees.Instance[Untyped] { tree.derivedContextBounds(transformSub(bounds), transform(cxBounds)) case PatDef(mods, pats, tpt, rhs) => tree.derivedPatDef(mods, transform(pats), transform(tpt), transform(rhs)) + case tree: PolyTypeDef => + tree.derivedPolyTypeDef(tree.mods, tree.name, transformSub(tree.tparams), transform(tree.rhs)) case _ => super.transform(tree) } @@ -244,6 +256,8 @@ object untpd extends Trees.Instance[Untyped] { this(this(x, bounds), cxBounds) case PatDef(mods, pats, tpt, rhs) => this(this(this(x, pats), tpt), rhs) + case tree: PolyTypeDef => + this(this(x, tree.tparams), tree.rhs) case _ => super.foldOver(x, tree) } diff --git a/src/dotty/tools/dotc/parsing/Parsers.scala b/src/dotty/tools/dotc/parsing/Parsers.scala index 13e5494cb..4ac74c86e 100644 --- a/src/dotty/tools/dotc/parsing/Parsers.scala +++ b/src/dotty/tools/dotc/parsing/Parsers.scala @@ -1427,7 +1427,7 @@ object Parsers { val bounds = if (isConcreteOwner) typeParamBounds(name) else typeBounds() - TypeDef(mods, name, hkparams, bounds) + typeDef(mods, name, hkparams, bounds) } } commaSeparated(typeParam) @@ -1463,7 +1463,7 @@ object Parsers { in.nextToken() addFlag(mods, Mutable) } else { - if ((mods.flags &~ ParamAccessor).isEmpty) syntaxError("`val' or `var' expected") + if (!(mods.flags &~ ParamAccessor).isEmpty) syntaxError("`val' or `var' expected") if (firstClauseOfCaseClass) mods else mods | PrivateLocal } } @@ -1708,9 +1708,9 @@ object Parsers { in.token match { case EQUALS => in.nextToken() - TypeDef(mods, name, tparams, typ()) + typeDef(mods, name, tparams, typ()) case SUPERTYPE | SUBTYPE | SEMI | NEWLINE | NEWLINES | COMMA | RBRACE | EOF => - TypeDef(mods, name, tparams, typeBounds()) + typeDef(mods, name, tparams, typeBounds()) case _ => syntaxErrorOrIncomplete("`=', `>:', or `<:' expected") EmptyTree diff --git a/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/src/dotty/tools/dotc/printing/RefinedPrinter.scala index 23482b773..9df2c053f 100644 --- a/src/dotty/tools/dotc/printing/RefinedPrinter.scala +++ b/src/dotty/tools/dotc/printing/RefinedPrinter.scala @@ -19,7 +19,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { private var currentOwner: Tree[_ >: Untyped] = emptyTree() def atOwner(owner: Tree[_ >: Untyped])(op: => Text): Text = { - val saved = owner + val saved = currentOwner currentOwner = owner try op finally { currentOwner = saved } @@ -96,7 +96,7 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { def optAscription(tpt: Tree[T]) = optText(tpt)(": " ~ _) - def tparamsText(params: List[Tree[T]]): Text = + def tparamsText[T >: Untyped](params: List[Tree[T]]): Text = "[" ~ toText(params, ", ") ~ "]" provided params.nonEmpty def addVparamssText(txt: Text, vparamss: List[List[ValDef[T]]]): Text = @@ -214,13 +214,13 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { val first = modText(mods, "def") ~~ toText(name) ~ tparamsText(tparams) addVparamssText(first, vparamss) ~ optAscription(tpt) ~ optText(rhs)(" = " ~ _) } - case TypeDef(mods, name, tparams, rhs) => + case tree @ TypeDef(mods, name, rhs) => atOwner(tree) { val rhsText = rhs match { case TypeBoundsTree(_, _) => toText(rhs) case _ => optText(rhs)(" = " ~ _) } - modText(mods, "type") ~~ toText(name) ~ tparamsText(tparams) ~ rhsText + modText(mods, "type") ~~ toText(name) ~ tparamsText(tree.tparams) ~ rhsText } case Template(DefDef(mods, _, tparams, vparamss, _, _), parents, self, stats) => val tparamsTxt = tparamsText(tparams) @@ -331,6 +331,8 @@ class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) { case PatDef(mods, pats, tpt, rhs) => modText(mods, "val") ~~ toText(pats, ", ") ~ optAscription(tpt) ~ optText(rhs)(" = " ~ _) + case Thicket(trees) => + "Thicket {" ~~ toTextGlobal(trees, "\n") ~~ "}" case _ => tree.fallbackToText(this) } diff --git a/src/dotty/tools/dotc/typer/Typer.scala b/src/dotty/tools/dotc/typer/Typer.scala index 295d0a1b2..1b3c2f22b 100644 --- a/src/dotty/tools/dotc/typer/Typer.scala +++ b/src/dotty/tools/dotc/typer/Typer.scala @@ -42,11 +42,10 @@ class Typer extends Namer { } def typedTypeDef(tdef: untpd.TypeDef, sym: Symbol)(implicit ctx: Context): TypeDef = { - val Trees.TypeDef(mods, name, tparams, rhs) = tdef + val Trees.TypeDef(mods, name, rhs) = tdef val mods1 = typedModifiers(mods) - val tparams1 = tparams mapconserve (typed(_).asInstanceOf[TypeDef]) val rhs1 = typedType(rhs) - tdef.withType(sym.symRef).derivedTypeDef(mods1, name, tparams1, rhs1) + tdef.withType(sym.symRef).derivedTypeDef(mods1, name, rhs1) } def typedClassDef(cdef: untpd.ClassDef, cls: ClassSymbol)(implicit ctx: Context) = { diff --git a/test/test/DeSugarTest.scala b/test/test/DeSugarTest.scala index ef0c34ec3..0a3a261fb 100644 --- a/test/test/DeSugarTest.scala +++ b/test/test/DeSugarTest.scala @@ -33,11 +33,7 @@ class DeSugarTest extends ParserTest { override def transform(tree: Tree): Tree = { val tree1 = desugar(tree, curMode) - if (tree1 ne tree) { - //println(s"repeat desugar ${tree1.getClass}") - transform(tree1) - } - else tree1 match { + tree1 match { case TypedSplice(t) => tree1 case PostfixOp(od, op) => @@ -62,12 +58,14 @@ class DeSugarTest extends ParserTest { tree1.derivedValDef(mods, name, transform(tpt, Type), transform(rhs)) case DefDef(mods, name, tparams, vparamss, tpt, rhs) => tree1.derivedDefDef(mods, name, transformSub(tparams), vparamss mapConserve (transformSub(_)), transform(tpt, Type), transform(rhs)) - case TypeDef(mods, name, tparams, rhs) => - tree1.derivedTypeDef(mods, name, transformSub(tparams), transform(rhs, Type)) + case tree1 @ TypeDef(mods, name, rhs) => + tree1.derivedTypeDef(mods, name, transform(rhs, Type), transformSub(tree1.tparams)) case Template(constr, parents, self, body) => tree1.derivedTemplate(transformSub(constr), transform(parents), transformSub(self), transform(body, Expr)) case ClassDef(mods, name, impl) => tree1.derivedClassDef(mods, name, transformSub(impl)) + case Thicket(trees) => + Thicket(flatten(trees mapConserve super.transform)) case tree1 => super.transform(tree1) } diff --git a/test/test/showTree.scala b/test/test/showTree.scala index 5d2710715..957131cf7 100644 --- a/test/test/showTree.scala +++ b/test/test/showTree.scala @@ -4,72 +4,20 @@ import ast.Trees._ import ast.desugar import ast.desugar._ -object showTree extends ParserTest { +object showTree extends DeSugarTest { import dotty.tools.dotc.ast.untpd._ import Mode._ - object DeSugar extends TreeTransformer { - var curMode: Mode.Value = Mode.Expr - def withMode[T](mode: Mode.Value)(op: => T) = { - val saved = curMode - curMode = mode - try op - finally curMode = saved - } - - def transform(tree: Tree, mode: Mode.Value): Tree = withMode(mode) { transform(tree) } - def transform(trees: List[Tree], mode: Mode.Value): List[Tree] = withMode(mode) { transform(trees) } - - override def transform(tree: Tree): Tree = { - val tree1 = desugar(tree, curMode) - if (tree1 ne tree) { - //println(s"repeat desugar ${tree1.getClass}") - transform(tree1) - } - else tree1 match { - case TypedSplice(t) => - tree1 - case PostfixOp(od, op) => - PostfixOp(transform(od), op) - case Select(qual, name) => - tree1.derivedSelect(transform(qual, Expr), name) - case Apply(fn, args) => - tree1.derivedApply(transform(fn, Expr), transform(args)) - case TypeApply(fn, args) => - tree1.derivedTypeApply(transform(fn, Expr), transform(args, Type)) - case New(tpt) => - tree1.derivedNew(transform(tpt, Type)) - case Typed(expr, tpt) => - tree1.derivedTyped(transform(expr), transform(tpt, Type)) - case CaseDef(pat, guard, body) => - tree1.derivedCaseDef(transform(pat, Pattern), transform(guard), transform(body)) - case SeqLiteral(elempt, elems) => - tree1.derivedSeqLiteral(transform(elempt, Type), transform(elems)) - case UnApply(fun, args) => - tree1.derivedUnApply(transform(fun, Expr), transform(args)) - case ValDef(mods, name, tpt, rhs) => - tree1.derivedValDef(mods, name, transform(tpt, Type), transform(rhs)) - case DefDef(mods, name, tparams, vparamss, tpt, rhs) => - tree1.derivedDefDef(mods, name, transformSub(tparams), vparamss mapConserve (transformSub(_)), transform(tpt, Type), transform(rhs)) - case TypeDef(mods, name, tparams, rhs) => - tree1.derivedTypeDef(mods, name, transformSub(tparams), transform(rhs, Type)) - case Template(constr, parents, self, body) => - tree1.derivedTemplate(transformSub(constr), transform(parents), transformSub(self), transform(body, Expr)) - case ClassDef(mods, name, impl) => - tree1.derivedClassDef(mods, name, transformSub(impl)) - case tree1 => - super.transform(tree1) - } - } + def test(arg: String) = { + val tree: Tree = parse(arg) + println("result = "+tree.show) + println("desugared = "+DeSugar.transform(tree).show) } def main(args: Array[String]): Unit = { - for (arg <- args) { - val tree: Tree = parse(arg) - println("result = "+tree.show) - println("desugared = "+DeSugar.transform(tree).show) - } + test("src/dotty/tools/dotc/core/Types.scala") + for (arg <- args) test(arg) } } \ No newline at end of file -- cgit v1.2.3