diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/dotty/tools/dotc/ast/Trees.scala | 19 | ||||
-rw-r--r-- | src/dotty/tools/dotc/ast/TypedTrees.scala | 5 | ||||
-rw-r--r-- | src/dotty/tools/dotc/ast/UntypedTrees.scala | 223 |
3 files changed, 207 insertions, 40 deletions
diff --git a/src/dotty/tools/dotc/ast/Trees.scala b/src/dotty/tools/dotc/ast/Trees.scala index 153e14495..fc95b4ea0 100644 --- a/src/dotty/tools/dotc/ast/Trees.scala +++ b/src/dotty/tools/dotc/ast/Trees.scala @@ -97,13 +97,20 @@ object Trees { privateWithin: TypeName = tpnme.EMPTY, annotations: List[Tree[T]] = Nil) extends Positioned with Cloneable { - def | (fs: FlagSet): Modifiers[T] = copy(flags = flags | fs) - def & (fs: FlagSet): Modifiers[T] = copy(flags = flags & fs) - def &~(fs: FlagSet): Modifiers[T] = copy(flags = flags &~ fs) - def is(fs: FlagSet): Boolean = flags is fs def is(fc: FlagConjunction): Boolean = flags is fc + def | (fs: FlagSet): Modifiers[T] = withFlags(flags | fs) + def & (fs: FlagSet): Modifiers[T] = withFlags(flags & fs) + def &~(fs: FlagSet): Modifiers[T] = withFlags(flags &~ fs) + + def toTypeFlags: Modifiers[T] = withFlags(flags.toTypeFlags) + def toTermFlags: Modifiers[T] = withFlags(flags.toTermFlags) + + private def withFlags(flags: FlagSet) = + if (this.flags == flags) this + else copy(flags = flags) + def withAnnotations(annots: List[Tree[T]]) = if (annots.isEmpty) this else copy(annotations = annotations ++ annots) @@ -677,10 +684,6 @@ object Trees { type DefTree = Trees.DefTree[T] type ModDefTree = Trees.ModDefTree[T] - type TreeCopier = Trees.TreeCopier[T] - type TreeAccumulator[U] = Trees.TreeAccumulator[U, T] - type TreeTransformer = Trees.TreeTransformer[T] - type Ident = Trees.Ident[T] type Select = Trees.Select[T] type This = Trees.This[T] diff --git a/src/dotty/tools/dotc/ast/TypedTrees.scala b/src/dotty/tools/dotc/ast/TypedTrees.scala index 93b83bdb0..860611b97 100644 --- a/src/dotty/tools/dotc/ast/TypedTrees.scala +++ b/src/dotty/tools/dotc/ast/TypedTrees.scala @@ -398,5 +398,10 @@ object tpd extends Trees.Instance[Type] { def localSyms(stats: List[tpd.Tree])(implicit ctx: Context): List[Symbol] = for (stat <- stats if (stat.isDef)) yield stat.symbol + + type TreeAccumulator[U] = Trees.TreeAccumulator[U, Type] + type TreeCopier = Trees.TreeCopier[Type] + type TreeTransformer = Trees.TreeTransformer[Type] + } diff --git a/src/dotty/tools/dotc/ast/UntypedTrees.scala b/src/dotty/tools/dotc/ast/UntypedTrees.scala index 82c99a781..ba67a0546 100644 --- a/src/dotty/tools/dotc/ast/UntypedTrees.scala +++ b/src/dotty/tools/dotc/ast/UntypedTrees.scala @@ -12,7 +12,7 @@ import collection.mutable.ListBuffer object untpd extends Trees.Instance[Untyped] { - // ----- Tree cases that exist in untyped form only ------------------ +// ----- 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: tpd.Tree) extends Tree @@ -21,25 +21,17 @@ object untpd extends Trees.Instance[Untyped] { case class ModuleDef(mods: Modifiers, name: TermName, impl: Template) extends NameTree with ModDefTree { type ThisTree[T >: Untyped] <: Trees.NameTree[T] with Trees.ModDefTree[T] with ModuleDef - def derivedModuleDef(mods: Modifiers, name: TermName, impl: Template) = - if ((mods eq this.mods) && (name eq this.name) && (impl eq this.impl)) this - else ModuleDef(mods, name, impl).copyAttr(this) - def withName(name: Name) = derivedModuleDef(mods, name.toTermName, impl) + def withName(name: Name) = this.derivedModuleDef(mods, name.toTermName, impl) } - /** (vparams) => body */ case class SymbolLit(str: String) extends Tree case class InterpolatedString(id: TermName, strings: List[Literal], elems: List[Tree]) extends Tree case class Function(args: List[Tree], body: Tree) extends Tree case class InfixOp(left: Tree, op: Name, right: Tree) extends Tree - case class PostfixOp(tree: Tree, op: Name) extends Tree - case class PrefixOp(op: Name, tree: Tree) extends Tree - case class Parens(tree: Tree) extends Tree { - def derivedParens(tree: Tree) = if (this.tree eq tree) this else Parens(tree).copyAttr(this) - } - case class Tuple(trees: List[Tree]) extends Tree { - def derivedTuple(trees: List[Tree]) = if (this.trees eq trees) this else Tuple(trees).copyAttr(this) - } + case class PostfixOp(od: Tree, op: Name) extends Tree + case class PrefixOp(op: Name, od: Tree) extends Tree + case class Parens(t: Tree) extends Tree + case class Tuple(trees: List[Tree]) extends Tree case class WhileDo(cond: Tree, body: Tree) extends TermTree case class DoWhile(body: Tree, cond: Tree) extends TermTree case class ForYield(enums: List[Tree], expr: Tree) extends TermTree @@ -49,10 +41,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 - val unitLiteral = Literal(Constant()) +// ------ Untyped tree values and creation methods --------------------- private type VarInfo = (NameTree, Tree) + val unitLiteral = Literal(Constant()) + def ref(tp: NamedType)(implicit ctx: Context): Tree = TypedSplice(tpd.ref(tp)) @@ -74,15 +68,13 @@ object untpd extends Trees.Instance[Untyped] { case _ => Tuple(ts) } - /** new C(args) */ - def makeNew(tpt: Tree, args: List[Tree])(implicit ctx: Context): Apply = - Apply(Select(Trees.New(tpt), nme.CONSTRUCTOR), args) - - def makeSyntheticParameter(pname: TermName)(implicit ctx: Context): ValDef = - ValDef(Modifiers(SyntheticTermParam), pname, TypeTree(), EmptyTree()) +// ------ Untyped tree desugaring ------------------------------------------ def desugar(tree: Tree, mode: Mode.Value)(implicit ctx: Context): Tree = { + def makeSyntheticParameter(): ValDef = + ValDef(Modifiers(SyntheticTermParam), ctx.freshName().toTermName, TypeTree(), EmptyTree()) + def labelDefAndCall(lname: TermName, rhs: Tree, call: Tree) = { val ldef = DefDef(Modifiers(Label), lname, Nil, ListOfNil, TypeTree(), rhs) Block(ldef, call) @@ -113,6 +105,18 @@ object untpd extends Trees.Instance[Untyped] { } } + /** Make closure corresponding to function params => body */ + def makeClosure(params: List[ValDef], body: Tree) = + Block( + DefDef(Modifiers(Synthetic), nme.ANON_FUN, Nil, params :: Nil, EmptyTree(), body), + Closure(Nil, Ident(nme.ANON_FUN))) + + /** Make closure corresponding to partial function { cases } */ + def makeCaseClosure(cases: List[CaseDef]) = { + val param = makeSyntheticParameter() + makeClosure(param :: Nil, Match(Ident(param.name), cases)) + } + /** Create tree for for-comprehension <for (enums) do body> or * <for (enums) yield body> where mapName and flatMapName are chosen * corresponding to whether this is a for-do or a for-yield. @@ -169,9 +173,9 @@ object untpd extends Trees.Instance[Untyped] { */ def makeLambda(pat: Tree, body: Tree): Tree = pat match { case VarPattern(named, tpt) => - Function(derivedValDef(Modifiers(Param), named, tpt, EmptyTree()) :: Nil, body) + makeClosure(derivedValDef(Modifiers(Param), named, tpt, EmptyTree()) :: Nil, body) case _ => - Match(EmptyTree(), CaseDef(pat, EmptyTree(), body) :: Nil) + makeCaseClosure(CaseDef(pat, EmptyTree(), body) :: Nil) } /** If `pat` is not yet a `Bind` wrap it in one with a fresh name @@ -307,6 +311,8 @@ object untpd extends Trees.Instance[Untyped] { Apply(Select(fn, nme.update), args :+ rhs) case If(cond, thenp, EmptyTree()) => If(cond, thenp, unitLiteral) + case Match(EmptyTree(), cases) => + makeCaseClosure(cases) case _: DefDef | _: ClassDef => desugarContextBounds(tree) case ModuleDef(mods, name, tmpl @ Template(constr, parents, self, body)) => @@ -314,13 +320,13 @@ object untpd extends Trees.Instance[Untyped] { // <module> final class name$ extends parents { self: name.type => body } val clsName = name.moduleClassName val clsRef = Ident(clsName) - val modul = ValDef(mods | ModuleCreationFlags, name, clsRef, clsRef) + val modul = ValDef(mods | ModuleCreationFlags, name, clsRef, New(clsRef, Nil)) 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 & AccessFlags | ModuleClassCreationFlags, clsName, Nil, clsTmpl) + val cls = ClassDef(mods.toTypeFlags & AccessFlags | ModuleClassCreationFlags, clsName, Nil, clsTmpl) TempTrees(List(modul, cls)) case SymbolLit(str) => - makeNew(ref(defn.SymbolClass.typeConstructor), Literal(Constant(str)) :: Nil) + New(ref(defn.SymbolClass.typeConstructor), (Literal(Constant(str)) :: Nil) :: Nil) case InterpolatedString(id, strs, elems) => Apply(Select(Apply(Ident(nme.StringContext), strs), id), elems) case Function(args, body) => @@ -328,12 +334,8 @@ object untpd extends Trees.Instance[Untyped] { AppliedTypeTree( ref(defn.FunctionClass(args.length).typeConstructor), args :+ body) - else { // { def $anonfun(args) = body; $anonfun } - val params = args.asInstanceOf[List[ValDef]] - Block( - DefDef(Modifiers(Synthetic), nme.ANON_FUN, Nil, params :: Nil, EmptyTree(), body), - Closure(Nil, Ident(nme.ANON_FUN))) - } + else + makeClosure(args.asInstanceOf[List[ValDef]], body) case InfixOp(l, op, r) => mode match { case Mode.Expr => // l.op(r), or val x = r; l.op(x), plus handle named args specially @@ -481,6 +483,8 @@ object untpd extends Trees.Instance[Untyped] { } } +// ------- A decorator for producing a path to a location -------------- + implicit class UntypedTreeDecorator(val self: Tree) extends AnyVal { def locateEnclosing(base: List[Tree], pos: Position): List[Tree] = { def encloses(elem: Any) = elem match { @@ -493,4 +497,159 @@ object untpd extends Trees.Instance[Untyped] { } } } + +// --------- Copier/Transformer/Accumulator classes for untyped trees ----- + + 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 _ => ModuleDef(mods, name, impl).copyAttr(tree) + } + def derivedSymbolLit(str: String) = tree match { + case tree: SymbolLit if (str == tree.str) => tree + case _ => SymbolLit(str).copyAttr(tree) + } + def derivedInterpolatedString(id: TermName, strings: List[Literal], elems: List[Tree]) = tree match { + case tree: InterpolatedString if (id eq tree.id) && (strings eq tree.strings) && (elems eq tree.elems) => tree + case _ => InterpolatedString(id, strings, elems).copyAttr(tree) + } + def derivedFunction(args: List[Tree], body: Tree) = tree match { + case tree: Function if (args eq tree.args) && (body eq tree.body) => tree + case _ => Function(args, body).copyAttr(tree) + } + def derivedInfixOp(left: Tree, op: Name, right: Tree) = tree match { + case tree: InfixOp if (left eq tree.left) && (op eq tree.op) && (right eq tree.right) => tree + case _ => InfixOp(left, op, right).copyAttr(tree) + } + def derivedPostfixOp(od: Tree, op: Name) = tree match { + case tree: PostfixOp if (od eq tree.od) && (op eq tree.op) => tree + case _ => PostfixOp(od, op).copyAttr(tree) + } + def derivedPrefixOp(op: Name, od: Tree) = tree match { + case tree: PrefixOp if (op eq tree.op) && (od eq tree.od) => tree + case _ => PrefixOp(op, od).copyAttr(tree) + } + def derivedParens(t: Tree) = tree match { + case tree: Parens if (t eq tree.t) => tree + case _ => Parens(t).copyAttr(tree) + } + def derivedTuple(trees: List[Tree]) = tree match { + case tree: Tuple if (trees eq tree.trees) => tree + case _ => Tuple(trees).copyAttr(tree) + } + def derivedWhileDo(cond: Tree, body: Tree) = tree match { + case tree: WhileDo if (cond eq tree.cond) && (body eq tree.body) => tree + case _ => WhileDo(cond, body).copyAttr(tree) + } + def derivedDoWhile(body: Tree, cond: Tree) = tree match { + case tree: DoWhile if (body eq tree.body) && (cond eq tree.cond) => tree + case _ => DoWhile(body, cond).copyAttr(tree) + } + def derivedForYield(enums: List[Tree], expr: Tree) = tree match { + case tree: ForYield if (enums eq tree.enums) && (expr eq tree.expr) => tree + case _ => ForYield(enums, expr).copyAttr(tree) + } + def derivedForDo(enums: List[Tree], body: Tree) = tree match { + case tree: ForDo if (enums eq tree.enums) && (body eq tree.body) => tree + case _ => ForDo(enums, body).copyAttr(tree) + } + def derivedGenFrom(pat: Tree, expr: Tree) = tree match { + case tree: GenFrom if (pat eq tree.pat) && (expr eq tree.expr) => tree + case _ => GenFrom(pat, expr).copyAttr(tree) + } + def derivedGenAlias(pat: Tree, expr: Tree) = tree match { + case tree: GenAlias if (pat eq tree.pat) && (expr eq tree.expr) => tree + case _ => GenAlias(pat, expr).copyAttr(tree) + } + def derivedContextBounds(bounds: TypeBoundsTree, cxBounds: List[Tree]) = tree match { + case tree: ContextBounds if (bounds eq tree.bounds) && (cxBounds eq tree.cxBounds) => tree + case _ => ContextBounds(bounds, cxBounds).copyAttr(tree) + } + def derivedPatDef(mods: Modifiers, pats: List[Tree], tpt: Tree, rhs: Tree) = tree match { + case tree: PatDef if (mods eq tree.mods) && (pats eq tree.pats) && (tpt eq tree.tpt) && (rhs eq tree.rhs) => tree + case _ => PatDef(mods, pats, tpt, rhs).copyAttr(tree) + } + } + + abstract class TreeTransformer extends Trees.TreeTransformer[Untyped] { + override def transform(tree: Tree): Tree = tree match { + case ModuleDef(mods, name, impl) => + tree.derivedModuleDef(mods, name, transformSub(impl)) + case SymbolLit(str) => + tree.derivedSymbolLit(str) + case InterpolatedString(id, strings, elems) => + tree.derivedInterpolatedString(id, transformSub(strings), transform(elems)) + case Function(args, body) => + tree.derivedFunction(transform(args), transform(body)) + case InfixOp(left, op, right) => + tree.derivedInfixOp(transform(left), op, transform(right)) + case PostfixOp(od, op) => + tree.derivedPostfixOp(transform(od), op) + case PrefixOp(op, od) => + tree.derivedPrefixOp(op, transform(od)) + case Parens(t) => + tree.derivedParens(transform(t)) + case Tuple(trees) => + tree.derivedTuple(transform(trees)) + case WhileDo(cond, body) => + tree.derivedWhileDo(transform(cond), transform(body)) + case DoWhile(body, cond) => + tree.derivedDoWhile(transform(body), transform(cond)) + case ForYield(enums, expr) => + tree.derivedForYield(transform(enums), transform(expr)) + case ForDo(enums, body) => + tree.derivedForDo(transform(enums), transform(body)) + case GenFrom(pat, expr) => + tree.derivedGenFrom(transform(pat), transform(expr)) + case GenAlias(pat, expr) => + tree.derivedGenAlias(transform(pat), transform(expr)) + case ContextBounds(bounds, cxBounds) => + tree.derivedContextBounds(transformSub(bounds), transform(cxBounds)) + case PatDef(mods, pats, tpt, rhs) => + tree.derivedPatDef(mods, transform(pats), transform(tpt), transform(rhs)) + case _ => + super.transform(tree) + } + } + + abstract class TreeAccumulator[X] extends Trees.TreeAccumulator[X, Untyped] { + override def foldOver(x: X, tree: Tree): X = tree match { + case ModuleDef(mods, name, impl) => + this(x, impl) + case SymbolLit(str) => + x + case InterpolatedString(id, strings, elems) => + this(this(x, strings), elems) + case Function(args, body) => + this(this(x, args), body) + case InfixOp(left, op, right) => + this(this(x, left), right) + case PostfixOp(od, op) => + this(x, od) + case PrefixOp(op, od) => + this(x, od) + case Parens(t) => + this(x, t) + case Tuple(trees) => + this(x, trees) + case WhileDo(cond, body) => + this(this(x, cond), body) + case DoWhile(body, cond) => + this(this(x, body), cond) + case ForYield(enums, expr) => + this(this(x, enums), expr) + case ForDo(enums, body) => + this(this(x, enums), body) + case GenFrom(pat, expr) => + this(this(x, pat), expr) + case GenAlias(pat, expr) => + this(this(x, pat), expr) + case ContextBounds(bounds, cxBounds) => + this(this(x, bounds), cxBounds) + case PatDef(mods, pats, tpt, rhs) => + this(this(this(x, pats), tpt), rhs) + case _ => + super.foldOver(x, tree) + } + } } |