aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/dotty/tools/dotc/ast/CheckTrees.scala3
-rw-r--r--src/dotty/tools/dotc/ast/PluggableTransformers.scala2
-rw-r--r--src/dotty/tools/dotc/ast/TreeInfo.scala2
-rw-r--r--src/dotty/tools/dotc/ast/TypedTrees.scala536
-rw-r--r--src/dotty/tools/dotc/ast/UntypedTrees.scala847
-rw-r--r--src/dotty/tools/dotc/core/Annotations.scala2
-rw-r--r--src/dotty/tools/dotc/core/Contexts.scala2
-rw-r--r--src/dotty/tools/dotc/core/Symbols.scala3
-rw-r--r--src/dotty/tools/dotc/core/Types.scala2
-rw-r--r--src/dotty/tools/dotc/core/pickling/ClassfileParser.scala2
-rw-r--r--src/dotty/tools/dotc/core/pickling/UnPickler.scala2
-rw-r--r--src/dotty/tools/dotc/parsing/MarkupParsers.scala2
-rw-r--r--src/dotty/tools/dotc/parsing/Parsers.scala2
-rw-r--r--src/dotty/tools/dotc/parsing/ScriptParsers.scala2
-rw-r--r--src/dotty/tools/dotc/parsing/SymbolicXMLBuilder.scala2
-rw-r--r--src/dotty/tools/dotc/parsing/TreeBuilder.scala.unused2
-rw-r--r--src/dotty/tools/dotc/printing/PlainPrinter.scala2
-rw-r--r--src/dotty/tools/dotc/printing/RefinedPrinter.scala2
-rw-r--r--test/test/ParserTest.scala2
-rw-r--r--test/test/parsePackage.scala2
-rw-r--r--test/test/showTree.scala2
21 files changed, 709 insertions, 714 deletions
diff --git a/src/dotty/tools/dotc/ast/CheckTrees.scala b/src/dotty/tools/dotc/ast/CheckTrees.scala
index f62eb1921..c10a2dacb 100644
--- a/src/dotty/tools/dotc/ast/CheckTrees.scala
+++ b/src/dotty/tools/dotc/ast/CheckTrees.scala
@@ -5,10 +5,11 @@ package ast
import core._
import util.Positions._, Types._, Contexts._, Constants._, Names._, Flags._
import SymDenotations._, Symbols._, StdNames._, Annotations._, Trees._
-import TypedTrees.{tpd, TreeOps, localSyms}
object CheckTrees {
+ import tpd.{TreeMapper, localSyms, TreeOps}
+
def check(p: Boolean, msg: => String = "")(implicit ctx: Context): Unit = assert(p, msg)
def checkTypeArg(arg: tpd.Tree, bounds: TypeBounds)(implicit ctx: Context): Unit = {
diff --git a/src/dotty/tools/dotc/ast/PluggableTransformers.scala b/src/dotty/tools/dotc/ast/PluggableTransformers.scala
index 8c64feb21..84bbf833c 100644
--- a/src/dotty/tools/dotc/ast/PluggableTransformers.scala
+++ b/src/dotty/tools/dotc/ast/PluggableTransformers.scala
@@ -84,7 +84,7 @@ object PluggableTransformers {
}
}
-import PluggableTransformers._, Types._, Trees._, Contexts._, TypedTrees.tpd
+import PluggableTransformers._, Types._, Trees._, Contexts._
class ExampleTransformer extends PluggableTransformer[Type] {
diff --git a/src/dotty/tools/dotc/ast/TreeInfo.scala b/src/dotty/tools/dotc/ast/TreeInfo.scala
index eeab6ceb0..75e82ecca 100644
--- a/src/dotty/tools/dotc/ast/TreeInfo.scala
+++ b/src/dotty/tools/dotc/ast/TreeInfo.scala
@@ -3,7 +3,7 @@ package dotc
package ast
import core._
-import Flags._, Trees._, UntypedTrees._, TypedTrees._, Types._, Contexts._
+import Flags._, Trees._, Types._, Contexts._
import Names._, StdNames._, NameOps._, Decorators._, Symbols._
import util.HashSet
diff --git a/src/dotty/tools/dotc/ast/TypedTrees.scala b/src/dotty/tools/dotc/ast/TypedTrees.scala
index b6583baf0..958927148 100644
--- a/src/dotty/tools/dotc/ast/TypedTrees.scala
+++ b/src/dotty/tools/dotc/ast/TypedTrees.scala
@@ -7,320 +7,317 @@ import util.Positions._, Types._, Contexts._, Constants._, Names._, Flags._
import SymDenotations._, Symbols._, StdNames._, Annotations._, Trees._
import CheckTrees._
-object TypedTrees {
+object tpd extends Trees.Instance[Type] {
- object tpd extends Trees.Instance[Type] {
+ def Modifiers(sym: Symbol)(implicit ctx: Context): Modifiers = Trees.Modifiers[Type](
+ sym.flags & ModifierFlags,
+ if (sym.privateWithin.exists) sym.privateWithin.asType.name else tpnme.EMPTY,
+ sym.annotations map (_.tree))
- def Modifiers(sym: Symbol)(implicit ctx: Context): Modifiers = Trees.Modifiers[Type](
- sym.flags & ModifierFlags,
- if (sym.privateWithin.exists) sym.privateWithin.asType.name else tpnme.EMPTY,
- sym.annotations map (_.tree))
+ def Ident(tp: NamedType)(implicit ctx: Context): Ident =
+ Trees.Ident(tp.name).withType(tp).checked
- def Ident(tp: NamedType)(implicit ctx: Context): Ident =
- Trees.Ident(tp.name).withType(tp).checked
+ def Select(pre: Tree, tp: NamedType)(implicit ctx: Context): Select =
+ Trees.Select(pre, tp.name).withType(tp).checked
- def Select(pre: Tree, tp: NamedType)(implicit ctx: Context): Select =
- Trees.Select(pre, tp.name).withType(tp).checked
+ def This(cls: ClassSymbol)(implicit ctx: Context): This =
+ Trees.This(cls.name).withType(cls.thisType).checked
- def This(cls: ClassSymbol)(implicit ctx: Context): This =
- Trees.This(cls.name).withType(cls.thisType).checked
-
- def Super(qual: Tree, mix: TypeName)(implicit ctx: Context): Super = {
- val owntype =
- if (mix.isEmpty) ctx.glb(qual.tpe.parents)
- else {
- val mixParents = qual.tpe.parents filter (_.name == mix)
- check(mixParents.length == 1)
- mixParents.head
- }
- Trees.Super(qual, mix).withType(SuperType(qual.tpe, owntype)).checked
- }
-
- def Apply(fn: Tree, args: List[Tree])(implicit ctx: Context): Apply = {
- val owntype = fn.tpe.widen match {
- case fntpe @ MethodType(pnames, ptypes) =>
- check(sameLength(ptypes, args), s"${fn.show}: ${fntpe.show} to ${args.map(_.show).mkString(", ")}")
- fntpe.instantiate(args map (_.tpe))
- case _ =>
- check(false)
- ErrorType
+ def Super(qual: Tree, mix: TypeName)(implicit ctx: Context): Super = {
+ val owntype =
+ if (mix.isEmpty) ctx.glb(qual.tpe.parents)
+ else {
+ val mixParents = qual.tpe.parents filter (_.name == mix)
+ check(mixParents.length == 1)
+ mixParents.head
}
- Trees.Apply(fn, args).withType(owntype).checked
+ Trees.Super(qual, mix).withType(SuperType(qual.tpe, owntype)).checked
+ }
+
+ def Apply(fn: Tree, args: List[Tree])(implicit ctx: Context): Apply = {
+ val owntype = fn.tpe.widen match {
+ case fntpe @ MethodType(pnames, ptypes) =>
+ check(sameLength(ptypes, args), s"${fn.show}: ${fntpe.show} to ${args.map(_.show).mkString(", ")}")
+ fntpe.instantiate(args map (_.tpe))
+ case _ =>
+ check(false)
+ ErrorType
}
+ Trees.Apply(fn, args).withType(owntype).checked
+ }
- def TypeApply(fn: Tree, args: List[Tree])(implicit ctx: Context): TypeApply = {
- val owntype = fn.tpe.widen match {
- case fntpe @ PolyType(pnames) =>
- check(sameLength(pnames, args))
- fntpe.instantiate(args map (_.tpe))
- case _ =>
- check(false)
- ErrorType
- }
- Trees.TypeApply(fn, args).withType(owntype).checked
+ def TypeApply(fn: Tree, args: List[Tree])(implicit ctx: Context): TypeApply = {
+ val owntype = fn.tpe.widen match {
+ case fntpe @ PolyType(pnames) =>
+ check(sameLength(pnames, args))
+ fntpe.instantiate(args map (_.tpe))
+ case _ =>
+ check(false)
+ ErrorType
}
+ Trees.TypeApply(fn, args).withType(owntype).checked
+ }
- def Literal(const: Constant)(implicit ctx: Context): Literal =
- Trees.Literal(const).withType(const.tpe).checked
+ def Literal(const: Constant)(implicit ctx: Context): Literal =
+ Trees.Literal(const).withType(const.tpe).checked
- def New(tp: Type)(implicit ctx: Context): New =
- Trees.New(TypeTree(tp)).withType(tp).checked
+ def New(tp: Type)(implicit ctx: Context): New =
+ Trees.New(TypeTree(tp)).withType(tp).checked
- def Pair(left: Tree, right: Tree)(implicit ctx: Context): Pair =
- Trees.Pair(left, right).withType(defn.PairType.appliedTo(left.tpe, right.tpe)).checked
+ def Pair(left: Tree, right: Tree)(implicit ctx: Context): Pair =
+ Trees.Pair(left, right).withType(defn.PairType.appliedTo(left.tpe, right.tpe)).checked
- def Typed(expr: Tree, tpt: Tree)(implicit ctx: Context): Typed =
- Trees.Typed(expr, tpt).withType(tpt.tpe).checked
+ def Typed(expr: Tree, tpt: Tree)(implicit ctx: Context): Typed =
+ Trees.Typed(expr, tpt).withType(tpt.tpe).checked
- def NamedArg(name: TermName, arg: Tree)(implicit ctx: Context) =
- Trees.NamedArg(name, arg).withType(arg.tpe).checked
+ def NamedArg(name: TermName, arg: Tree)(implicit ctx: Context) =
+ Trees.NamedArg(name, arg).withType(arg.tpe).checked
- def Assign(lhs: Tree, rhs: Tree)(implicit ctx: Context): Assign =
- Trees.Assign(lhs, rhs).withType(defn.UnitType).checked
+ def Assign(lhs: Tree, rhs: Tree)(implicit ctx: Context): Assign =
+ Trees.Assign(lhs, rhs).withType(defn.UnitType).checked
- def Block(stats: List[Tree], expr: Tree)(implicit ctx: Context): Block = {
- lazy val locals = localSyms(stats).toSet
- val blk = Trees.Block(stats, expr)
- def widen(tp: Type): Type = tp match {
- case tp: TermRef if locals contains tp.symbol =>
- widen(tp.info)
- case _ => tp
- }
- blk.withType(widen(expr.tpe))
+ def Block(stats: List[Tree], expr: Tree)(implicit ctx: Context): Block = {
+ lazy val locals = localSyms(stats).toSet
+ val blk = Trees.Block(stats, expr)
+ def widen(tp: Type): Type = tp match {
+ case tp: TermRef if locals contains tp.symbol =>
+ widen(tp.info)
+ case _ => tp
}
+ blk.withType(widen(expr.tpe))
+ }
- def If(cond: Tree, thenp: Tree, elsep: Tree)(implicit ctx: Context): If =
- Trees.If(cond, thenp, elsep).withType(thenp.tpe | elsep.tpe).checked
-
- def Match(selector: Tree, cases: List[CaseDef])(implicit ctx: Context): Match =
- Trees.Match(selector, cases).withType(ctx.lub(cases map (_.body.tpe))).checked
+ def If(cond: Tree, thenp: Tree, elsep: Tree)(implicit ctx: Context): If =
+ Trees.If(cond, thenp, elsep).withType(thenp.tpe | elsep.tpe).checked
- def CaseDef(pat: Tree, guard: Tree, body: Tree)(implicit ctx: Context): CaseDef =
- Trees.CaseDef(pat, guard, body).withType(body.tpe).checked
+ def Match(selector: Tree, cases: List[CaseDef])(implicit ctx: Context): Match =
+ Trees.Match(selector, cases).withType(ctx.lub(cases map (_.body.tpe))).checked
- def Return(expr: Tree, from: Ident)(implicit ctx: Context): Return =
- Trees.Return(expr, from).withType(defn.NothingType).checked
+ def CaseDef(pat: Tree, guard: Tree, body: Tree)(implicit ctx: Context): CaseDef =
+ Trees.CaseDef(pat, guard, body).withType(body.tpe).checked
- def Try(block: Tree, handler: Tree, finalizer: Tree)(implicit ctx: Context): Try =
- Trees.Try(block, handler, finalizer).withType(block.tpe | handler.tpe).checked
+ def Return(expr: Tree, from: Ident)(implicit ctx: Context): Return =
+ Trees.Return(expr, from).withType(defn.NothingType).checked
- def Throw(expr: Tree)(implicit ctx: Context): Throw =
- Trees.Throw(expr).withType(defn.NothingType).checked
+ def Try(block: Tree, handler: Tree, finalizer: Tree)(implicit ctx: Context): Try =
+ Trees.Try(block, handler, finalizer).withType(block.tpe | handler.tpe).checked
- def SeqLiteral(elemtpt: Tree, elems: List[Tree])(implicit ctx: Context): SeqLiteral =
- Trees.SeqLiteral(elemtpt, elems).withType(defn.RepeatedParamType.appliedTo(elemtpt.tpe)).checked
+ def Throw(expr: Tree)(implicit ctx: Context): Throw =
+ Trees.Throw(expr).withType(defn.NothingType).checked
- def SeqLiteral(elems: List[Tree])(implicit ctx: Context): SeqLiteral =
- SeqLiteral(TypeTree(ctx.lub(elems map (_.tpe))), elems)
+ def SeqLiteral(elemtpt: Tree, elems: List[Tree])(implicit ctx: Context): SeqLiteral =
+ Trees.SeqLiteral(elemtpt, elems).withType(defn.RepeatedParamType.appliedTo(elemtpt.tpe)).checked
- def TypeTree(tp: Type, original: Tree = EmptyTree)(implicit ctx: Context): TypeTree =
- Trees.TypeTree(original).withType(tp).checked
+ def SeqLiteral(elems: List[Tree])(implicit ctx: Context): SeqLiteral =
+ SeqLiteral(TypeTree(ctx.lub(elems map (_.tpe))), elems)
- def SingletonTypeTree(ref: Tree)(implicit ctx: Context): SingletonTypeTree =
- Trees.SingletonTypeTree(ref).withType(ref.tpe).checked
+ def TypeTree(tp: Type, original: Tree = EmptyTree)(implicit ctx: Context): TypeTree =
+ Trees.TypeTree(original).withType(tp).checked
- def SelectFromTypeTree(qualifier: Tree, tp: NamedType)(implicit ctx: Context): SelectFromTypeTree =
- Trees.SelectFromTypeTree(qualifier, tp.name).withType(tp).checked
+ def SingletonTypeTree(ref: Tree)(implicit ctx: Context): SingletonTypeTree =
+ Trees.SingletonTypeTree(ref).withType(ref.tpe).checked
- def AndTypeTree(left: Tree, right: Tree)(implicit ctx: Context): AndTypeTree =
- Trees.AndTypeTree(left, right).withType(left.tpe & right.tpe).checked
+ def SelectFromTypeTree(qualifier: Tree, tp: NamedType)(implicit ctx: Context): SelectFromTypeTree =
+ Trees.SelectFromTypeTree(qualifier, tp.name).withType(tp).checked
- def OrTypeTree(left: Tree, right: Tree)(implicit ctx: Context): OrTypeTree =
- Trees.OrTypeTree(left, right).withType(left.tpe | right.tpe).checked
+ def AndTypeTree(left: Tree, right: Tree)(implicit ctx: Context): AndTypeTree =
+ Trees.AndTypeTree(left, right).withType(left.tpe & right.tpe).checked
- def RefinedTypeTree(tpt: Tree, refinements: List[DefTree])(implicit ctx: Context): RefinedTypeTree = {
- def refineType(tp: Type, refinement: Symbol): Type =
- RefinedType(tp, refinement.name, refinement.info)
- Trees.RefinedTypeTree(tpt, refinements)
- .withType((tpt.tpe /: (refinements map (_.symbol)))(refineType)).checked
- }
+ def OrTypeTree(left: Tree, right: Tree)(implicit ctx: Context): OrTypeTree =
+ Trees.OrTypeTree(left, right).withType(left.tpe | right.tpe).checked
- def refineType(tp: Type, refinement: Symbol)(implicit ctx: Context): Type =
+ def RefinedTypeTree(tpt: Tree, refinements: List[DefTree])(implicit ctx: Context): RefinedTypeTree = {
+ def refineType(tp: Type, refinement: Symbol): Type =
RefinedType(tp, refinement.name, refinement.info)
+ Trees.RefinedTypeTree(tpt, refinements)
+ .withType((tpt.tpe /: (refinements map (_.symbol)))(refineType)).checked
+ }
- def AppliedTypeTree(tpt: Tree, args: List[Tree])(implicit ctx: Context): AppliedTypeTree =
- Trees.AppliedTypeTree(tpt, args).withType(tpt.tpe.appliedTo(args map (_.tpe))).checked
-
- def TypeBoundsTree(lo: Tree, hi: Tree)(implicit ctx: Context): TypeBoundsTree =
- Trees.TypeBoundsTree(lo, hi).withType(TypeBounds(lo.tpe, hi.tpe)).checked
+ def refineType(tp: Type, refinement: Symbol)(implicit ctx: Context): Type =
+ RefinedType(tp, refinement.name, refinement.info)
- def Bind(sym: TermSymbol, body: Tree)(implicit ctx: Context): Bind =
- Trees.Bind(sym.name, body).withType(refType(sym)).checked
+ def AppliedTypeTree(tpt: Tree, args: List[Tree])(implicit ctx: Context): AppliedTypeTree =
+ Trees.AppliedTypeTree(tpt, args).withType(tpt.tpe.appliedTo(args map (_.tpe))).checked
- def Alternative(trees: List[Tree])(implicit ctx: Context): Alternative =
- Trees.Alternative(trees).withType(ctx.lub(trees map (_.tpe))).checked
+ def TypeBoundsTree(lo: Tree, hi: Tree)(implicit ctx: Context): TypeBoundsTree =
+ Trees.TypeBoundsTree(lo, hi).withType(TypeBounds(lo.tpe, hi.tpe)).checked
- def UnApply(fun: Tree, args: List[Tree])(implicit ctx: Context): UnApply = {
- val owntype = fun.tpe.widen match {
- case MethodType(_, paramType :: Nil) => paramType
- case _ => check(false); ErrorType
- }
- Trees.UnApply(fun, args).withType(owntype).checked
- }
+ def Bind(sym: TermSymbol, body: Tree)(implicit ctx: Context): Bind =
+ Trees.Bind(sym.name, body).withType(refType(sym)).checked
- def ValDef(sym: TermSymbol, rhs: Tree = EmptyTree)(implicit ctx: Context): ValDef =
- Trees.ValDef(Modifiers(sym), sym.name, TypeTree(sym.info), rhs).withType(refType(sym)).checked
+ def Alternative(trees: List[Tree])(implicit ctx: Context): Alternative =
+ Trees.Alternative(trees).withType(ctx.lub(trees map (_.tpe))).checked
- def DefDef(sym: TermSymbol, rhs: Tree = EmptyTree)(implicit ctx: Context): DefDef = {
+ def UnApply(fun: Tree, args: List[Tree])(implicit ctx: Context): UnApply = {
+ val owntype = fun.tpe.widen match {
+ case MethodType(_, paramType :: Nil) => paramType
+ case _ => check(false); ErrorType
+ }
+ Trees.UnApply(fun, args).withType(owntype).checked
+ }
- val (tparams, mtp) = sym.info match {
- case tp: PolyType =>
- val tparams = ctx.newTypeParams(sym, tp.paramNames, EmptyFlags, tp.instantiateBounds)
- (tparams, tp.instantiate(tparams map (_.typeConstructor)))
- case tp => (Nil, tp)
- }
+ def ValDef(sym: TermSymbol, rhs: Tree = EmptyTree)(implicit ctx: Context): ValDef =
+ Trees.ValDef(Modifiers(sym), sym.name, TypeTree(sym.info), rhs).withType(refType(sym)).checked
- def valueParamss(tp: Type): (List[List[TermSymbol]], Type) = tp match {
- case tp @ MethodType(paramNames, paramTypes) =>
- def valueParam(name: TermName, info: Type): TermSymbol =
- ctx.newSymbol(sym, name, TermParam, info)
- val params = (paramNames, paramTypes).zipped.map(valueParam)
- val (paramss, rtp) = valueParamss(tp.instantiate(params map (_.typeConstructor)))
- (params :: paramss, rtp)
- case tp => (Nil, tp)
- }
- val (vparamss, rtp) = valueParamss(mtp)
+ def DefDef(sym: TermSymbol, rhs: Tree = EmptyTree)(implicit ctx: Context): DefDef = {
- Trees.DefDef(
- Modifiers(sym), sym.name, tparams map TypeDef,
- vparamss map (_ map (ValDef(_))), TypeTree(rtp), rhs)
- .withType(refType(sym)).checked
+ val (tparams, mtp) = sym.info match {
+ case tp: PolyType =>
+ val tparams = ctx.newTypeParams(sym, tp.paramNames, EmptyFlags, tp.instantiateBounds)
+ (tparams, tp.instantiate(tparams map (_.typeConstructor)))
+ case tp => (Nil, tp)
}
- def TypeDef(sym: TypeSymbol)(implicit ctx: Context): TypeDef =
- Trees.TypeDef(Modifiers(sym), sym.name, Nil, TypeTree(sym.info)) // !!! fill in typeParams
- .withType(refType(sym)).checked
-
- def ClassDef(cls: ClassSymbol, typeParams: List[TypeSymbol], constr: DefDef, body: List[Tree])(implicit ctx: Context): ClassDef = {
- val parents = cls.info.parents map (TypeTree(_))
- val selfType =
- if (cls.classInfo.optSelfType.exists) ValDef(ctx.newSelfSym(cls))
- else EmptyValDef
- def isOwnTypeParamAccessor(stat: Tree) =
- (stat.symbol is TypeParam) && stat.symbol.owner == cls
- val (tparamAccessors, rest) = body partition isOwnTypeParamAccessor
- val tparams =
- (typeParams map TypeDef) ++
- (tparamAccessors collect {
- case td: TypeDef if !(typeParams contains td.symbol) => td
- })
- val findLocalDummy = new FindLocalDummyAccumulator(cls)
- val localDummy = ((NoSymbol: Symbol) /: body)(findLocalDummy)
- .orElse(ctx.newLocalDummy(cls))
- val impl = Trees.Template(constr, parents, selfType, rest)
- .withType(refType(localDummy)).checked
- Trees.ClassDef(Modifiers(cls), cls.name, tparams, impl)
- .withType(refType(cls)).checked
+ def valueParamss(tp: Type): (List[List[TermSymbol]], Type) = tp match {
+ case tp @ MethodType(paramNames, paramTypes) =>
+ def valueParam(name: TermName, info: Type): TermSymbol =
+ ctx.newSymbol(sym, name, TermParam, info)
+ val params = (paramNames, paramTypes).zipped.map(valueParam)
+ val (paramss, rtp) = valueParamss(tp.instantiate(params map (_.typeConstructor)))
+ (params :: paramss, rtp)
+ case tp => (Nil, tp)
}
+ val (vparamss, rtp) = valueParamss(mtp)
- def Import(expr: Tree, selectors: List[Trees.UntypedTree])(implicit ctx: Context): Import =
- Trees.Import(expr, selectors).withType(refType(ctx.newImportSymbol(SharedTree(expr)))).checked
-
- def PackageDef(pid: RefTree, stats: List[Tree])(implicit ctx: Context): PackageDef =
- Trees.PackageDef(pid, stats).withType(refType(pid.symbol)).checked
-
- def Annotated(annot: Tree, arg: Tree)(implicit ctx: Context): Annotated =
- Trees.Annotated(annot, arg).withType(AnnotatedType(Annotation(annot), arg.tpe)).checked
-
- val EmptyTree: Tree = Trees.EmptyTree[Type]
-
- val EmptyValDef: ValDef = Trees.EmptyValDef[Type]
-
- def SharedTree(tree: Tree): SharedTree =
- Trees.SharedTree(tree).withType(tree.tpe)
-
- def refType(sym: Symbol)(implicit ctx: Context): NamedType = NamedType.withSym(sym.owner.thisType, sym)
-
- // ------ Creating typed equivalents of trees that exist only in untyped form -------
-
- /** A tree representing the same reference as the given type */
- def ref(tp: NamedType)(implicit ctx: Context): NameTree =
- if (tp.symbol.isStatic) Ident(tp)
- else tp.prefix match {
- case pre: TermRef => Select(ref(pre), tp)
- case pre => SelectFromTypeTree(TypeTree(pre), tp)
- } // no checks necessary
-
- def ref(sym: Symbol)(implicit ctx: Context): tpd.NameTree =
- ref(NamedType(sym.owner.thisType, sym.name).withDenot(sym))
-
- /** new C(args) */
- def New(tp: Type, args: List[Tree])(implicit ctx: Context): Apply =
- Apply(
- Select(
- New(tp),
- TermRef.withSym(tp.normalizedPrefix, tp.typeSymbol.primaryConstructor.asTerm)),
- args)
-
- /** An object def
- *
- * object obs extends parents { decls }
- *
- * gets expanded to
- *
- * <module> lazy val obj = {
- * class obj$ extends parents { this: obj.type => decls }
- * new obj$
- * }
- *
- * What's interesting here is that the block is well typed
- * (because class obj$ is hoistable), but the type of the `obj` val is
- * not expressible. What needs to happen in general when
- * inferring the type of a val from its RHS, is: if the type contains
- * a class that has the val itself as owner, then that class
- * is remapped to have the val's owner as owner. Remapping could be
- * done by cloning the class with the new owner and substituting
- * everywhere in the tree. We know that remapping is safe
- * because the only way a local class can appear in the RHS of a val is
- * by being hoisted outside of a block, and the necessary checks are
- * done at this point already.
- *
- * On the other hand, for method result type inference, if the type of
- * the RHS of a method contains a class owned by the method, this would be
- * an error.
- */
- def ModuleDef(sym: TermSymbol, body: List[Tree])(implicit ctx: Context): tpd.TempTrees = {
- val modcls = sym.moduleClass.asClass
- val constr = DefDef(modcls.primaryConstructor.asTerm, EmptyTree)
- val clsdef = ClassDef(modcls, Nil, constr, body)
- val valdef = ValDef(sym, New(modcls.typeConstructor))
- TempTrees(valdef :: clsdef :: Nil)
- }
+ Trees.DefDef(
+ Modifiers(sym), sym.name, tparams map TypeDef,
+ vparamss map (_ map (ValDef(_))), TypeTree(rtp), rhs)
+ .withType(refType(sym)).checked
+ }
- /** A function def
- *
- * vparams => expr
- *
- * gets expanded to
- *
- * { def $anonfun(vparams) = expr; $anonfun: pt }
- *
- * where pt is the target type of the expression (FunctionN) unless
- * otherwise specified.
- */
- def Function(meth: TermSymbol, body: Tree, target: Type = NoType)(implicit ctx: Context): Block = {
- val funtpe =
- if (target.exists) target
- else meth.info match {
- case mt @ MethodType(_, formals) =>
- assert(!mt.isDependent)
- defn.FunctionType(formals, mt.resultType)
- }
- Block(
- DefDef(meth, body) :: Nil,
- Typed(Ident(TermRef.withSym(NoPrefix, meth)), TypeTree(funtpe)))
- }
+ def TypeDef(sym: TypeSymbol)(implicit ctx: Context): TypeDef =
+ Trees.TypeDef(Modifiers(sym), sym.name, Nil, TypeTree(sym.info)) // !!! fill in typeParams
+ .withType(refType(sym)).checked
+
+ def ClassDef(cls: ClassSymbol, typeParams: List[TypeSymbol], constr: DefDef, body: List[Tree])(implicit ctx: Context): ClassDef = {
+ val parents = cls.info.parents map (TypeTree(_))
+ val selfType =
+ if (cls.classInfo.optSelfType.exists) ValDef(ctx.newSelfSym(cls))
+ else EmptyValDef
+ def isOwnTypeParamAccessor(stat: Tree) =
+ (stat.symbol is TypeParam) && stat.symbol.owner == cls
+ val (tparamAccessors, rest) = body partition isOwnTypeParamAccessor
+ val tparams =
+ (typeParams map TypeDef) ++
+ (tparamAccessors collect {
+ case td: TypeDef if !(typeParams contains td.symbol) => td
+ })
+ val findLocalDummy = new FindLocalDummyAccumulator(cls)
+ val localDummy = ((NoSymbol: Symbol) /: body)(findLocalDummy)
+ .orElse(ctx.newLocalDummy(cls))
+ val impl = Trees.Template(constr, parents, selfType, rest)
+ .withType(refType(localDummy)).checked
+ Trees.ClassDef(Modifiers(cls), cls.name, tparams, impl)
+ .withType(refType(cls)).checked
+ }
- private class FindLocalDummyAccumulator(cls: ClassSymbol)(implicit ctx: Context) extends TreeAccumulator[Symbol] {
- def apply(sym: Symbol, tree: Tree) =
- if (sym.exists) sym
- else if (tree.isDef) {
- val owner = tree.symbol.owner
- if (owner.isLocalDummy && owner.owner == cls) owner
- else if (owner == cls) foldOver(sym, tree)
- else sym
- } else foldOver(sym, tree)
- }
+ def Import(expr: Tree, selectors: List[Trees.UntypedTree])(implicit ctx: Context): Import =
+ Trees.Import(expr, selectors).withType(refType(ctx.newImportSymbol(SharedTree(expr)))).checked
+
+ def PackageDef(pid: RefTree, stats: List[Tree])(implicit ctx: Context): PackageDef =
+ Trees.PackageDef(pid, stats).withType(refType(pid.symbol)).checked
+
+ def Annotated(annot: Tree, arg: Tree)(implicit ctx: Context): Annotated =
+ Trees.Annotated(annot, arg).withType(AnnotatedType(Annotation(annot), arg.tpe)).checked
+
+ val EmptyTree: Tree = Trees.EmptyTree[Type]
+
+ val EmptyValDef: ValDef = Trees.EmptyValDef[Type]
+
+ def SharedTree(tree: Tree): SharedTree =
+ Trees.SharedTree(tree).withType(tree.tpe)
+
+ def refType(sym: Symbol)(implicit ctx: Context): NamedType = NamedType.withSym(sym.owner.thisType, sym)
+
+ // ------ Creating typed equivalents of trees that exist only in untyped form -------
+
+ /** A tree representing the same reference as the given type */
+ def ref(tp: NamedType)(implicit ctx: Context): NameTree =
+ if (tp.symbol.isStatic) Ident(tp)
+ else tp.prefix match {
+ case pre: TermRef => Select(ref(pre), tp)
+ case pre => SelectFromTypeTree(TypeTree(pre), tp)
+ } // no checks necessary
+
+ def ref(sym: Symbol)(implicit ctx: Context): tpd.NameTree =
+ ref(NamedType(sym.owner.thisType, sym.name).withDenot(sym))
+
+ /** new C(args) */
+ def New(tp: Type, args: List[Tree])(implicit ctx: Context): Apply =
+ Apply(
+ Select(
+ New(tp),
+ TermRef.withSym(tp.normalizedPrefix, tp.typeSymbol.primaryConstructor.asTerm)),
+ args)
+
+ /** An object def
+ *
+ * object obs extends parents { decls }
+ *
+ * gets expanded to
+ *
+ * <module> lazy val obj = {
+ * class obj$ extends parents { this: obj.type => decls }
+ * new obj$
+ * }
+ *
+ * What's interesting here is that the block is well typed
+ * (because class obj$ is hoistable), but the type of the `obj` val is
+ * not expressible. What needs to happen in general when
+ * inferring the type of a val from its RHS, is: if the type contains
+ * a class that has the val itself as owner, then that class
+ * is remapped to have the val's owner as owner. Remapping could be
+ * done by cloning the class with the new owner and substituting
+ * everywhere in the tree. We know that remapping is safe
+ * because the only way a local class can appear in the RHS of a val is
+ * by being hoisted outside of a block, and the necessary checks are
+ * done at this point already.
+ *
+ * On the other hand, for method result type inference, if the type of
+ * the RHS of a method contains a class owned by the method, this would be
+ * an error.
+ */
+ def ModuleDef(sym: TermSymbol, body: List[Tree])(implicit ctx: Context): tpd.TempTrees = {
+ val modcls = sym.moduleClass.asClass
+ val constr = DefDef(modcls.primaryConstructor.asTerm, EmptyTree)
+ val clsdef = ClassDef(modcls, Nil, constr, body)
+ val valdef = ValDef(sym, New(modcls.typeConstructor))
+ TempTrees(valdef :: clsdef :: Nil)
+ }
+
+ /** A function def
+ *
+ * vparams => expr
+ *
+ * gets expanded to
+ *
+ * { def $anonfun(vparams) = expr; $anonfun: pt }
+ *
+ * where pt is the target type of the expression (FunctionN) unless
+ * otherwise specified.
+ */
+ def Function(meth: TermSymbol, body: Tree, target: Type = NoType)(implicit ctx: Context): Block = {
+ val funtpe =
+ if (target.exists) target
+ else meth.info match {
+ case mt @ MethodType(_, formals) =>
+ assert(!mt.isDependent)
+ defn.FunctionType(formals, mt.resultType)
+ }
+ Block(
+ DefDef(meth, body) :: Nil,
+ Typed(Ident(TermRef.withSym(NoPrefix, meth)), TypeTree(funtpe)))
+ }
+
+ private class FindLocalDummyAccumulator(cls: ClassSymbol)(implicit ctx: Context) extends TreeAccumulator[Symbol] {
+ def apply(sym: Symbol, tree: Tree) =
+ if (sym.exists) sym
+ else if (tree.isDef) {
+ val owner = tree.symbol.owner
+ if (owner.isLocalDummy && owner.owner == cls) owner
+ else if (owner == cls) foldOver(sym, tree)
+ else sym
+ } else foldOver(sym, tree)
}
implicit class TreeOps[ThisTree <: tpd.Tree](val tree: ThisTree) extends AnyVal {
@@ -357,7 +354,7 @@ object TypedTrees {
new TreeMapper(ownerMap = (sym => if (sym == from) to else sym)).apply(tree)
}
- class TreeMapper(val typeMap: TypeMap = IdentityTypeMap, val ownerMap: Symbol => Symbol = identity)(implicit ctx: Context) extends TreeTransformer[Type] {
+ class TreeMapper(val typeMap: TypeMap = IdentityTypeMap, val ownerMap: Symbol => Symbol = identity)(implicit ctx: Context) extends TreeTransformer {
override def transform(tree: tpd.Tree): tpd.Tree = {
val tree1 =
if (tree.isEmpty) tree
@@ -381,7 +378,7 @@ object TypedTrees {
val mapped = ctx.mapSymbols(locals, typeMap, ownerMap)
if (locals eq mapped) super.transform(trees)
else withSubstitution(locals, mapped).transform(trees)
- }
+ }
def apply[ThisTree <: tpd.Tree](tree: ThisTree): ThisTree = transform(tree).asInstanceOf[ThisTree]
@@ -403,3 +400,4 @@ object TypedTrees {
def localSyms(stats: List[tpd.Tree])(implicit ctx: Context): List[Symbol] =
for (stat <- stats if (stat.isDef)) yield stat.symbol
}
+
diff --git a/src/dotty/tools/dotc/ast/UntypedTrees.scala b/src/dotty/tools/dotc/ast/UntypedTrees.scala
index c7f468134..16a1efa03 100644
--- a/src/dotty/tools/dotc/ast/UntypedTrees.scala
+++ b/src/dotty/tools/dotc/ast/UntypedTrees.scala
@@ -4,484 +4,481 @@ package ast
import core._
import util.Positions._, Types._, Contexts._, Constants._, Names._, NameOps._, Flags._
-import SymDenotations._, Symbols._, StdNames._, Annotations._, Trees._, TypedTrees._
+import SymDenotations._, Symbols._, StdNames._, Annotations._, Trees._
import TreeInfo._
import Decorators._
import language.higherKinds
import collection.mutable.ListBuffer
-object UntypedTrees {
+object untpd extends Trees.Instance[Untyped] {
- 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: TypedTree) extends UntypedTree
- /** A typed subtree of an untyped tree needs to be wrapped in a TypedSlice */
- case class TypedSplice(tree: TypedTree) extends UntypedTree
+ /** mods object name impl */
+ 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
+ }
- /** mods object name impl */
- 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
- }
+ /** (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 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
+ case class ForDo(enums: List[Tree], body: Tree) extends TermTree
+ case class GenFrom(pat: Tree, expr: Tree) extends Tree
+ case class GenAlias(pat: Tree, expr: Tree) extends Tree
+ case class ContextBounds(bounds: TypeBoundsTree, cxBounds: List[Tree]) extends TypTree
+ case class PatDef(mods: Modifiers, pats: List[Tree], tpt: Tree, rhs: Tree) extends Tree
- /** (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 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
- case class ForDo(enums: List[Tree], body: Tree) extends TermTree
- case class GenFrom(pat: Tree, expr: Tree) extends Tree
- case class GenAlias(pat: Tree, expr: Tree) extends Tree
- 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())
- val unitLiteral = Literal(Constant())
+ private type VarInfo = (NameTree, Tree)
- private type VarInfo = (NameTree, Tree)
+ def ref(tp: NamedType)(implicit ctx: Context): Tree =
+ TypedSplice(tpd.ref(tp))
- def ref(tp: NamedType)(implicit ctx: Context): Tree =
- TypedSplice(tpd.ref(tp))
+ def scalaUnit(implicit ctx: Context) = ref(defn.UnitClass.typeConstructor)
- def scalaUnit(implicit ctx: Context) = ref(defn.UnitClass.typeConstructor)
+ def makeConstructor(mods: Modifiers, vparamss: List[List[ValDef]], rhs: Tree = EmptyTree())(implicit ctx: Context): DefDef =
+ DefDef(mods, nme.CONSTRUCTOR, Nil, vparamss, TypeTree(), rhs)
- def makeConstructor(mods: Modifiers, vparamss: List[List[ValDef]], rhs: Tree = EmptyTree())(implicit ctx: Context): DefDef =
- DefDef(mods, nme.CONSTRUCTOR, Nil, vparamss, TypeTree(), rhs)
+ def makeSelfDef(name: TermName, tpt: Tree)(implicit ctx: Context) =
+ ValDef(Modifiers(Private), name, tpt, EmptyTree())
- def makeSelfDef(name: TermName, tpt: Tree)(implicit ctx: Context) =
- ValDef(Modifiers(Private), name, tpt, EmptyTree())
+ def makeTupleOrParens(ts: List[Tree])(implicit ctx: Context) = ts match {
+ case t :: Nil => Parens(t)
+ case _ => Tuple(ts)
+ }
- def makeTupleOrParens(ts: List[Tree])(implicit ctx: Context) = ts match {
- case t :: Nil => Parens(t)
- case _ => Tuple(ts)
- }
+ def makeTuple(ts: List[Tree])(implicit ctx: Context) = ts match {
+ case t :: Nil => t
+ case _ => Tuple(ts)
+ }
- def makeTuple(ts: List[Tree])(implicit ctx: Context) = ts match {
- case t :: Nil => t
- 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())
- /** new C(args) */
- def makeNew(tpt: Tree, args: List[Tree])(implicit ctx: Context): Apply =
- Apply(Select(Trees.New(tpt), nme.CONSTRUCTOR), args)
+ def desugar(tree: Tree, mode: Mode.Value)(implicit ctx: Context): Tree = {
- def makeSyntheticParameter(pname: TermName)(implicit ctx: Context): ValDef =
- ValDef(Modifiers(SyntheticTermParam), pname, TypeTree(), EmptyTree())
+ def labelDefAndCall(lname: TermName, rhs: Tree, call: Tree) = {
+ val ldef = DefDef(Modifiers(Label), lname, Nil, ListOfNil, TypeTree(), rhs)
+ Block(ldef, call)
+ }
- def desugar(tree: Tree, mode: Mode.Value)(implicit ctx: Context): Tree = {
+ def derivedValDef(mods: Modifiers, named: NameTree, tpt: Tree, rhs: Tree) =
+ ValDef(mods, named.name.asTermName, tpt, rhs).withPos(named.pos)
- def labelDefAndCall(lname: TermName, rhs: Tree, call: Tree) = {
- val ldef = DefDef(Modifiers(Label), lname, Nil, ListOfNil, TypeTree(), rhs)
- Block(ldef, call)
+ /** Translate infix operation expression left op right
+ */
+ def makeBinop(left: Tree, op: Name, right: Tree): Tree = {
+ def assignToNamedArg(arg: Tree) = arg match {
+ case Assign(Ident(name), rhs) => arg.derivedNamedArg(name, rhs)
+ case _ => arg
+ }
+ if (isLeftAssoc(op)) {
+ val args: List[Tree] = right match {
+ case Parens(arg) => assignToNamedArg(arg) :: Nil
+ case Tuple(args) => args mapConserve assignToNamedArg
+ case _ => right :: Nil
+ }
+ Apply(Select(left, op.encode), args)
+ } else {
+ val x = ctx.freshName().toTermName
+ Block(
+ ValDef(Modifiers(Synthetic), x, TypeTree(), left),
+ Apply(Select(right, op.encode), Ident(x)))
}
+ }
- def derivedValDef(mods: Modifiers, named: NameTree, tpt: Tree, rhs: Tree) =
- ValDef(mods, named.name.asTermName, tpt, rhs).withPos(named.pos)
+ /** 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.
+ * The creation performs the following rewrite rules:
+ *
+ * 1.
+ *
+ * for (P <- G) E ==> G.foreach (P => E)
+ *
+ * Here and in the following (P => E) is interpreted as the function (P => E)
+ * if P is a variable pattern and as the partial function { case P => E } otherwise.
+ *
+ * 2.
+ *
+ * for (P <- G) yield E ==> G.map (P => E)
+ *
+ * 3.
+ *
+ * for (P_1 <- G_1; P_2 <- G_2; ...) ...
+ * ==>
+ * G_1.flatMap (P_1 => for (P_2 <- G_2; ...) ...)
+ *
+ * 4.
+ *
+ * for (P <- G; E; ...) ...
+ * =>
+ * for (P <- G.filter (P => E); ...) ...
+ *
+ * 5. For any N:
+ *
+ * for (P_1 <- G; P_2 = E_2; val P_N = E_N; ...)
+ * ==>
+ * for (TupleN(P_1, P_2, ... P_N) <-
+ * for (x_1 @ P_1 <- G) yield {
+ * val x_2 @ P_2 = E_2
+ * ...
+ * val x_N & P_N = E_N
+ * TupleN(x_1, ..., x_N)
+ * } ...)
+ *
+ * If any of the P_i are variable patterns, the corresponding `x_i @ P_i' is not generated
+ * and the variable constituting P_i is used instead of x_i
+ *
+ * @param mapName The name to be used for maps (either map or foreach)
+ * @param flatMapName The name to be used for flatMaps (either flatMap or foreach)
+ * @param enums The enumerators in the for expression
+ * @param body The body of the for expression
+ */
+ def makeFor(mapName: TermName, flatMapName: TermName, enums: List[Tree], body: Tree): Tree = {
- /** Translate infix operation expression left op right
+ /** Make a function value pat => body.
+ * If pat is a var pattern id: T then this gives (id: T) => body
+ * Otherwise this gives { case pat => body }
*/
- def makeBinop(left: Tree, op: Name, right: Tree): Tree = {
- def assignToNamedArg(arg: Tree) = arg match {
- case Assign(Ident(name), rhs) => arg.derivedNamedArg(name, rhs)
- case _ => arg
- }
- if (isLeftAssoc(op)) {
- val args: List[Tree] = right match {
- case Parens(arg) => assignToNamedArg(arg) :: Nil
- case Tuple(args) => args mapConserve assignToNamedArg
- case _ => right :: Nil
- }
- Apply(Select(left, op.encode), args)
- } else {
- val x = ctx.freshName().toTermName
- Block(
- ValDef(Modifiers(Synthetic), x, TypeTree(), left),
- Apply(Select(right, op.encode), Ident(x)))
- }
+ def makeLambda(pat: Tree, body: Tree): Tree = pat match {
+ case VarPattern(named, tpt) =>
+ Function(derivedValDef(Modifiers(Param), named, tpt, EmptyTree()) :: Nil, body)
+ case _ =>
+ Match(EmptyTree(), CaseDef(pat, EmptyTree(), body) :: Nil)
}
- /** 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.
- * The creation performs the following rewrite rules:
- *
- * 1.
- *
- * for (P <- G) E ==> G.foreach (P => E)
- *
- * Here and in the following (P => E) is interpreted as the function (P => E)
- * if P is a variable pattern and as the partial function { case P => E } otherwise.
- *
- * 2.
- *
- * for (P <- G) yield E ==> G.map (P => E)
- *
- * 3.
- *
- * for (P_1 <- G_1; P_2 <- G_2; ...) ...
- * ==>
- * G_1.flatMap (P_1 => for (P_2 <- G_2; ...) ...)
- *
- * 4.
- *
- * for (P <- G; E; ...) ...
- * =>
- * for (P <- G.filter (P => E); ...) ...
- *
- * 5. For any N:
- *
- * for (P_1 <- G; P_2 = E_2; val P_N = E_N; ...)
- * ==>
- * for (TupleN(P_1, P_2, ... P_N) <-
- * for (x_1 @ P_1 <- G) yield {
- * val x_2 @ P_2 = E_2
- * ...
- * val x_N & P_N = E_N
- * TupleN(x_1, ..., x_N)
- * } ...)
- *
- * If any of the P_i are variable patterns, the corresponding `x_i @ P_i' is not generated
- * and the variable constituting P_i is used instead of x_i
- *
- * @param mapName The name to be used for maps (either map or foreach)
- * @param flatMapName The name to be used for flatMaps (either flatMap or foreach)
- * @param enums The enumerators in the for expression
- * @param body The body of the for expression
+ /** If `pat` is not yet a `Bind` wrap it in one with a fresh name
*/
- def makeFor(mapName: TermName, flatMapName: TermName, enums: List[Tree], body: Tree): Tree = {
-
- /** Make a function value pat => body.
- * If pat is a var pattern id: T then this gives (id: T) => body
- * Otherwise this gives { case pat => body }
- */
- def makeLambda(pat: Tree, body: Tree): Tree = pat match {
- case VarPattern(named, tpt) =>
- Function(derivedValDef(Modifiers(Param), named, tpt, EmptyTree()) :: Nil, body)
- case _ =>
- Match(EmptyTree(), CaseDef(pat, EmptyTree(), body) :: Nil)
- }
-
- /** If `pat` is not yet a `Bind` wrap it in one with a fresh name
- */
- def makeBind(pat: Tree): Tree = pat match {
- case Bind(_, _) => pat
- case _ => Bind(ctx.freshName().toTermName, pat)
- }
-
- /** Is pattern `pat` irrefutable when matched against `rhs`?
- * We only can do a simple syntactic check here; a more refined check
- * is done later prompted by the presence of a "withFilterIfRefutable" call.
- */
- def isIrrefutable(pat: Tree, rhs: Tree): Boolean = {
- def matchesTuple(pats: List[Tree], rhs: Tree): Boolean = rhs match {
- case Tuple(trees) => (pats corresponds trees)(isIrrefutable)
- case Parens(rhs1) => matchesTuple(pats, rhs1)
- case Block(_, rhs1) => matchesTuple(pats, rhs1)
- case If(_, thenp, elsep) => matchesTuple(pats, thenp) && matchesTuple(pats, elsep)
- case Match(_, cases) => cases forall (matchesTuple(pats, _))
- case CaseDef(_, _, rhs1) => matchesTuple(pats, rhs)
- case Throw(_) => true
- case _ => false
- }
- pat match {
- case Bind(_, pat1) => isIrrefutable(pat1, rhs)
- case Parens(pat1) => isIrrefutable(pat1, rhs)
- case Tuple(pats) => matchesTuple(pats, rhs)
- case _ => isVarPattern(pat)
- }
- }
-
- /** Make a pattern filter:
- * rhs.withFilterIfRefutable { case pat => true case _ => false }
- */
- def makePatFilter(rhs: Tree, pat: Tree): Tree = {
- val cases = List(
- CaseDef(pat, EmptyTree(), Literal(Constant(true))),
- CaseDef(Ident(nme.WILDCARD), EmptyTree(), Literal(Constant(false))))
- Apply(Select(rhs, nme.withFilterIfRefutable), Match(EmptyTree(), cases))
- }
+ def makeBind(pat: Tree): Tree = pat match {
+ case Bind(_, _) => pat
+ case _ => Bind(ctx.freshName().toTermName, pat)
+ }
- /** rhs.name with a pattern filter on rhs unless `pat` is irrefutable when
- * matched against `rhs`.
- */
- def rhsSelect(rhs: Tree, name: TermName, pat: Tree) = {
- val rhs1 = if (isIrrefutable(pat, rhs)) rhs else makePatFilter(rhs, pat)
- Select(rhs1, name)
+ /** Is pattern `pat` irrefutable when matched against `rhs`?
+ * We only can do a simple syntactic check here; a more refined check
+ * is done later prompted by the presence of a "withFilterIfRefutable" call.
+ */
+ def isIrrefutable(pat: Tree, rhs: Tree): Boolean = {
+ def matchesTuple(pats: List[Tree], rhs: Tree): Boolean = rhs match {
+ case Tuple(trees) => (pats corresponds trees)(isIrrefutable)
+ case Parens(rhs1) => matchesTuple(pats, rhs1)
+ case Block(_, rhs1) => matchesTuple(pats, rhs1)
+ case If(_, thenp, elsep) => matchesTuple(pats, thenp) && matchesTuple(pats, elsep)
+ case Match(_, cases) => cases forall (matchesTuple(pats, _))
+ case CaseDef(_, _, rhs1) => matchesTuple(pats, rhs)
+ case Throw(_) => true
+ case _ => false
}
-
- enums match {
- case (enum @ GenFrom(pat, rhs)) :: Nil =>
- Apply(rhsSelect(rhs, mapName, pat), makeLambda(pat, body))
- case GenFrom(pat, rhs) :: (rest @ (GenFrom(_, _) :: _)) =>
- val cont = makeFor(mapName, flatMapName, rest, body)
- Apply(rhsSelect(rhs, flatMapName, pat), makeLambda(pat, cont))
- case (enum @ GenFrom(pat, rhs)) :: (rest @ GenAlias(_, _) :: _) =>
- val (valeqs, rest1) = rest.span(_.isInstanceOf[GenAlias])
- val pats = valeqs map { case GenAlias(pat, _) => pat }
- val rhss = valeqs map { case GenAlias(_, rhs) => rhs }
- val defpat1 = makeBind(pat)
- val defpats = pats map makeBind
- val pdefs = (defpats, rhss).zipped map (makePatDef(Modifiers(), _, _))
- val ids = (defpat1 :: defpats) map { case Bind(name, _) => Ident(name) }
- val rhs1 = makeFor(nme.map, nme.flatMap, GenFrom(defpat1, rhs) :: Nil, Block(pdefs, makeTuple(ids)))
- val allpats = pat :: pats
- val vfrom1 = GenFrom(makeTuple(allpats), rhs1)
- makeFor(mapName, flatMapName, vfrom1 :: rest1, body)
- case (enum @ GenFrom(pat, rhs)) :: test :: rest =>
- val filtered = Apply(rhsSelect(rhs, nme.withFilter, pat), makeLambda(pat, test))
- makeFor(mapName, flatMapName, GenFrom(pat, filtered) :: rest, body)
- case _ =>
- EmptyTree() //may happen for erroneous input
+ pat match {
+ case Bind(_, pat1) => isIrrefutable(pat1, rhs)
+ case Parens(pat1) => isIrrefutable(pat1, rhs)
+ case Tuple(pats) => matchesTuple(pats, rhs)
+ case _ => isVarPattern(pat)
}
}
- def makeAnnotated(cls: Symbol, tree: Tree) =
- Annotated(TypedSplice(tpd.New(cls.typeConstructor)), tree)
-
- /** Returns list of all pattern variables, possibly with their types,
- * without duplicates
- */
- def getVariables(tree: Tree): List[VarInfo] =
- getVars(new ListBuffer[VarInfo], tree).toList
-
- /** In case there is exactly one variable x_1 in pattern
- * val/var p = e ==> val/var x_1 = (e: @unchecked) match (case p => (x_1))
- *
- * in case there are zero or more than one variables in pattern
- * val/var p = e ==> private synthetic val t$ = (e: @unchecked) match (case p => (x_1, ..., x_N))
- * val/var x_1 = t$._1
- * ...
- * val/var x_N = t$._N
- * If the original pattern variable carries a type annotation, so does the corresponding
- * ValDef.
+ /** Make a pattern filter:
+ * rhs.withFilterIfRefutable { case pat => true case _ => false }
*/
- def makePatDef(mods: Modifiers, pat: Tree, rhs: Tree): Tree = pat match {
- case VarPattern(named, tpt) =>
- derivedValDef(mods, named, tpt, rhs)
- case _ =>
- val rhsUnchecked = makeAnnotated(defn.UncheckedAnnot, rhs)
- val vars = getVariables(pat)
- val ids = for ((named, _) <- vars) yield Ident(named.name)
- val caseDef = CaseDef(pat, EmptyTree(), makeTuple(ids))
- val matchExpr = Match(rhsUnchecked, caseDef :: Nil)
- vars match {
- case (named, tpt) :: Nil =>
- derivedValDef(mods, named, tpt, matchExpr)
- case _ =>
- val tmpName = ctx.freshName().toTermName
- val patMods = Modifiers(PrivateLocal | Synthetic | (mods.flags & Lazy))
- val firstDef = ValDef(patMods, tmpName, TypeTree(), matchExpr)
- def selector(n: Int) = Select(Ident(tmpName), ("_" + n).toTermName)
- val restDefs =
- for (((named, tpt), n) <- vars.zipWithIndex)
- yield derivedValDef(mods, named, tpt, selector(n))
- TempTrees(firstDef :: restDefs)
- }
+ def makePatFilter(rhs: Tree, pat: Tree): Tree = {
+ val cases = List(
+ CaseDef(pat, EmptyTree(), Literal(Constant(true))),
+ CaseDef(Ident(nme.WILDCARD), EmptyTree(), Literal(Constant(false))))
+ Apply(Select(rhs, nme.withFilterIfRefutable), Match(EmptyTree(), cases))
}
- def isPatternVar(id: Ident) =
- mode == Mode.Pattern && isVarPattern(id) && id.name != nme.WILDCARD
-
- // begin desugar
- tree match { // todo: move general tree desugaring to typer, and keep only untyped trees here?
- case id @ Ident(_) if isPatternVar(id) =>
- Bind(id.name, Ident(nme.WILDCARD))
- case Typed(id @ Ident(_), tpt) if isPatternVar(id) =>
- Bind(id.name, Typed(Ident(nme.WILDCARD), tpt)).withPos(id.pos)
- case New(templ: Template) =>
- desugarAnonClass(templ)
- case Assign(Apply(fn, args), rhs) =>
- Apply(Select(fn, nme.update), args :+ rhs)
- case If(cond, thenp, EmptyTree()) =>
- If(cond, thenp, unitLiteral)
- case _: DefDef | _: ClassDef =>
- desugarContextBounds(tree)
- case ModuleDef(mods, name, tmpl @ Template(constr, parents, self, body)) =>
- // <module> val name: name$ = New(name$)
- // <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 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)
- TempTrees(List(modul, cls))
- case SymbolLit(str) =>
- makeNew(ref(defn.SymbolClass.typeConstructor), Literal(Constant(str)) :: Nil)
- case InterpolatedString(id, strs, elems) =>
- Apply(Select(Apply(Ident(nme.StringContext), strs), id), elems)
- case Function(args, body) =>
- if (mode == Mode.Type) // FunctionN[args: _*, body]
- 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),
- Ident(nme.ANON_FUN))
- }
- 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
- makeBinop(l, op, r)
- case Mode.Pattern => // op'(l, r)
- Apply(Ident(op.encode), l :: r :: Nil)
- case Mode.Type => // op'[l, r]
- AppliedTypeTree(Ident(op.encode), l :: r :: Nil)
- }
- case PostfixOp(t, op) =>
- if (mode == Mode.Type && op == nme.raw.STAR)
- AppliedTypeTree(ref(defn.RepeatedParamType), t)
- else {
- assert(mode == Mode.Expr)
- if (op == nme.WILDCARD) tree // desugar later by eta expansion
- else Select(t, op.encode)
- }
- case PrefixOp(op, t) =>
- if (mode == Mode.Type && op == nme.ARROWkw)
- AppliedTypeTree(ref(defn.ByNameParamClass.typeConstructor), t)
- else
- Select(t, nme.UNARY_PREFIX ++ op.encode)
- case Parens(t) =>
- t
- case Tuple(ts) =>
- def PairTypeTree(l: Tree, r: Tree) =
- AppliedTypeTree(ref(defn.PairClass.typeConstructor), l :: r :: Nil)
- if (mode == Mode.Type) ts.reduceRight(PairTypeTree)
- else if (ts.isEmpty) unitLiteral
- else ts.reduceRight(Pair(_, _))
- case WhileDo(cond, body) =>
- // { <label> def while$(): Unit = if (cond) { body; while$() } ; while$() }
- val call = Apply(Ident(nme.WHILE_PREFIX), Nil)
- val rhs = If(cond, Block(body, call), unitLiteral)
- labelDefAndCall(nme.WHILE_PREFIX, rhs, call)
- case DoWhile(body, cond) =>
- // { label def doWhile$(): Unit = { body; if (cond) doWhile$() } ; doWhile$() }
- val call = Apply(Ident(nme.DO_WHILE_PREFIX), Nil)
- val rhs = Block(body, If(cond, call, unitLiteral))
- labelDefAndCall(nme.DO_WHILE_PREFIX, rhs, call)
- case ForDo(enums, body) =>
- makeFor(nme.foreach, nme.foreach, enums, body) orElse tree
- case ForYield(enums, body) =>
- 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))
- combine(pats1 map (makePatDef(mods, _, rhs)))
- case _ =>
- tree
- }
- }.withPos(tree.pos)
-
- def desugarContextBounds(tparams: List[TypeDef], vparamss: List[List[ValDef]], ofClass: Boolean): (List[TypeDef], List[List[ValDef]]) = {
- val epbuf = new ListBuffer[ValDef]
- def makeEvidenceParam(cxBound: Tree): ValDef = ???
- val tparams1 = tparams map {
- case tparam @ TypeDef(mods, name, ttparams, ContextBounds(tbounds, cxbounds)) =>
- for (cxbound <- cxbounds) {
- val accessMods = if (ofClass) PrivateOrLocal else EmptyFlags
- val epname = (nme.EVIDENCE_PARAM_PREFIX.toString + epbuf.length).toTermName
- epbuf +=
- ValDef(Modifiers(Implicit | Param | accessMods), epname, cxbound, EmptyTree())
- }
- tparam.derivedTypeDef(mods, name, ttparams, tbounds)
- case tparam =>
- tparam
+ /** rhs.name with a pattern filter on rhs unless `pat` is irrefutable when
+ * matched against `rhs`.
+ */
+ def rhsSelect(rhs: Tree, name: TermName, pat: Tree) = {
+ val rhs1 = if (isIrrefutable(pat, rhs)) rhs else makePatFilter(rhs, pat)
+ Select(rhs1, name)
}
- val evidenceParams = epbuf.toList
- val vparamss1 = vparamss.reverse match {
- case (vparams @ (vparam :: _)) :: rvparamss if vparam.mods is Implicit =>
- ((vparams ++ evidenceParams) :: rvparamss).reverse
+
+ enums match {
+ case (enum @ GenFrom(pat, rhs)) :: Nil =>
+ Apply(rhsSelect(rhs, mapName, pat), makeLambda(pat, body))
+ case GenFrom(pat, rhs) :: (rest @ (GenFrom(_, _) :: _)) =>
+ val cont = makeFor(mapName, flatMapName, rest, body)
+ Apply(rhsSelect(rhs, flatMapName, pat), makeLambda(pat, cont))
+ case (enum @ GenFrom(pat, rhs)) :: (rest @ GenAlias(_, _) :: _) =>
+ val (valeqs, rest1) = rest.span(_.isInstanceOf[GenAlias])
+ val pats = valeqs map { case GenAlias(pat, _) => pat }
+ val rhss = valeqs map { case GenAlias(_, rhs) => rhs }
+ val defpat1 = makeBind(pat)
+ val defpats = pats map makeBind
+ val pdefs = (defpats, rhss).zipped map (makePatDef(Modifiers(), _, _))
+ val ids = (defpat1 :: defpats) map { case Bind(name, _) => Ident(name) }
+ val rhs1 = makeFor(nme.map, nme.flatMap, GenFrom(defpat1, rhs) :: Nil, Block(pdefs, makeTuple(ids)))
+ val allpats = pat :: pats
+ val vfrom1 = GenFrom(makeTuple(allpats), rhs1)
+ makeFor(mapName, flatMapName, vfrom1 :: rest1, body)
+ case (enum @ GenFrom(pat, rhs)) :: test :: rest =>
+ val filtered = Apply(rhsSelect(rhs, nme.withFilter, pat), makeLambda(pat, test))
+ makeFor(mapName, flatMapName, GenFrom(pat, filtered) :: rest, body)
case _ =>
- vparamss :+ evidenceParams
+ EmptyTree() //may happen for erroneous input
}
- (tparams1, vparamss1)
- }
-
- def desugarContextBounds(tree: Tree): Tree = tree match {
- case DefDef(mods, name, tparams, vparamss, tpt, rhs) =>
- val (tparams1, vparamss1) =
- desugarContextBounds(tparams, vparamss, ofClass = false)
- tree.derivedDefDef(mods, name, tparams1, vparamss, tpt, rhs)
- case ClassDef(
- mods, name, tparams, templ @ Template(constr, parents, self, body)) =>
- val (tparams1, vparamss1) =
- desugarContextBounds(tparams, constr.vparamss, ofClass = true)
- val constr1 = constr.derivedDefDef(
- constr.mods, constr.name, constr.tparams, vparamss1, constr.tpt, constr.rhs)
- val templ1 = templ.derivedTemplate(constr1, parents, self, body)
- tree.derivedClassDef(mods, name, tparams1, templ1)
- case _ => tree
}
- def desugarAnonClass(templ: Template): Tree = {
- val x = tpnme.ANON_CLASS
- val clsDef = ClassDef(Modifiers(Final), x, Nil, templ)
- Block(clsDef, New(Ident(x), Nil))
- }
-
- object Mode extends Enumeration {
- val Type, Expr, Pattern = Value
- }
+ def makeAnnotated(cls: Symbol, tree: Tree) =
+ Annotated(TypedSplice(tpd.New(cls.typeConstructor)), tree)
- /** If tree is a variable pattern, return its name and type, otherwise return None.
+ /** Returns list of all pattern variables, possibly with their types,
+ * without duplicates
*/
- private object VarPattern {
- def unapply(tree: Tree): Option[VarInfo] = tree match {
- case id: Ident => Some(id, TypeTree())
- case Typed(id: Ident, tpt) => Some((id, tpt))
- case _ => None
- }
- }
+ def getVariables(tree: Tree): List[VarInfo] =
+ getVars(new ListBuffer[VarInfo], tree).toList
- /** Traverse pattern and collect all variable names with their types in buffer.
- * Works for expanded as well as unexpanded patterns
+ /** In case there is exactly one variable x_1 in pattern
+ * val/var p = e ==> val/var x_1 = (e: @unchecked) match (case p => (x_1))
*
+ * in case there are zero or more than one variables in pattern
+ * val/var p = e ==> private synthetic val t$ = (e: @unchecked) match (case p => (x_1, ..., x_N))
+ * val/var x_1 = t$._1
+ * ...
+ * val/var x_N = t$._N
+ * If the original pattern variable carries a type annotation, so does the corresponding
+ * ValDef.
*/
- private object getVars extends TreeAccumulator[ListBuffer[VarInfo]] {
- override def apply(buf: ListBuffer[VarInfo], tree: Tree): ListBuffer[VarInfo] = {
- def seenName(name: Name) = buf exists (_._1.name == name)
- def add(named: NameTree, t: Tree): ListBuffer[VarInfo] =
- if (seenName(named.name)) buf else buf += ((named, t))
- tree match {
- case Bind(nme.WILDCARD, _) =>
- foldOver(buf, tree)
- case tree @ Bind(_, Typed(tree1, tpt)) if !mayBeTypePat(tpt) =>
- apply(add(tree, tpt), tree1)
- case tree @ Bind(_, tree1) =>
- apply(add(tree, TypeTree()), tree1)
- case Typed(id: Ident, t) if isVarPattern(id) =>
- add(id, t)
- case id: Ident if isVarPattern(id) =>
- add(id, TypeTree())
+ def makePatDef(mods: Modifiers, pat: Tree, rhs: Tree): Tree = pat match {
+ case VarPattern(named, tpt) =>
+ derivedValDef(mods, named, tpt, rhs)
+ case _ =>
+ val rhsUnchecked = makeAnnotated(defn.UncheckedAnnot, rhs)
+ val vars = getVariables(pat)
+ val ids = for ((named, _) <- vars) yield Ident(named.name)
+ val caseDef = CaseDef(pat, EmptyTree(), makeTuple(ids))
+ val matchExpr = Match(rhsUnchecked, caseDef :: Nil)
+ vars match {
+ case (named, tpt) :: Nil =>
+ derivedValDef(mods, named, tpt, matchExpr)
case _ =>
- foldOver(buf, tree)
+ val tmpName = ctx.freshName().toTermName
+ val patMods = Modifiers(PrivateLocal | Synthetic | (mods.flags & Lazy))
+ val firstDef = ValDef(patMods, tmpName, TypeTree(), matchExpr)
+ def selector(n: Int) = Select(Ident(tmpName), ("_" + n).toTermName)
+ val restDefs =
+ for (((named, tpt), n) <- vars.zipWithIndex)
+ yield derivedValDef(mods, named, tpt, selector(n))
+ TempTrees(firstDef :: restDefs)
}
- }
}
- implicit class UntypedTreeDecorator(val self: Tree) extends AnyVal {
- def locateEnclosing(base: List[Tree], pos: Position): List[Tree] = {
- def encloses(elem: Any) = elem match {
- case t: Tree => t.envelope contains pos
- case _ => false
+ def isPatternVar(id: Ident) =
+ mode == Mode.Pattern && isVarPattern(id) && id.name != nme.WILDCARD
+
+ // begin desugar
+ tree match { // todo: move general tree desugaring to typer, and keep only untyped trees here?
+ case id @ Ident(_) if isPatternVar(id) =>
+ Bind(id.name, Ident(nme.WILDCARD))
+ case Typed(id @ Ident(_), tpt) if isPatternVar(id) =>
+ Bind(id.name, Typed(Ident(nme.WILDCARD), tpt)).withPos(id.pos)
+ case New(templ: Template) =>
+ desugarAnonClass(templ)
+ case Assign(Apply(fn, args), rhs) =>
+ Apply(Select(fn, nme.update), args :+ rhs)
+ case If(cond, thenp, EmptyTree()) =>
+ If(cond, thenp, unitLiteral)
+ case _: DefDef | _: ClassDef =>
+ desugarContextBounds(tree)
+ case ModuleDef(mods, name, tmpl @ Template(constr, parents, self, body)) =>
+ // <module> val name: name$ = New(name$)
+ // <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 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)
+ TempTrees(List(modul, cls))
+ case SymbolLit(str) =>
+ makeNew(ref(defn.SymbolClass.typeConstructor), Literal(Constant(str)) :: Nil)
+ case InterpolatedString(id, strs, elems) =>
+ Apply(Select(Apply(Ident(nme.StringContext), strs), id), elems)
+ case Function(args, body) =>
+ if (mode == Mode.Type) // FunctionN[args: _*, body]
+ 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),
+ Ident(nme.ANON_FUN))
}
- base.productIterator find encloses match {
- case Some(tree: Tree) => locateEnclosing(tree :: base, pos)
- case none => base
+ 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
+ makeBinop(l, op, r)
+ case Mode.Pattern => // op'(l, r)
+ Apply(Ident(op.encode), l :: r :: Nil)
+ case Mode.Type => // op'[l, r]
+ AppliedTypeTree(Ident(op.encode), l :: r :: Nil)
}
+ case PostfixOp(t, op) =>
+ if (mode == Mode.Type && op == nme.raw.STAR)
+ AppliedTypeTree(ref(defn.RepeatedParamType), t)
+ else {
+ assert(mode == Mode.Expr)
+ if (op == nme.WILDCARD) tree // desugar later by eta expansion
+ else Select(t, op.encode)
+ }
+ case PrefixOp(op, t) =>
+ if (mode == Mode.Type && op == nme.ARROWkw)
+ AppliedTypeTree(ref(defn.ByNameParamClass.typeConstructor), t)
+ else
+ Select(t, nme.UNARY_PREFIX ++ op.encode)
+ case Parens(t) =>
+ t
+ case Tuple(ts) =>
+ def PairTypeTree(l: Tree, r: Tree) =
+ AppliedTypeTree(ref(defn.PairClass.typeConstructor), l :: r :: Nil)
+ if (mode == Mode.Type) ts.reduceRight(PairTypeTree)
+ else if (ts.isEmpty) unitLiteral
+ else ts.reduceRight(Pair(_, _))
+ case WhileDo(cond, body) =>
+ // { <label> def while$(): Unit = if (cond) { body; while$() } ; while$() }
+ val call = Apply(Ident(nme.WHILE_PREFIX), Nil)
+ val rhs = If(cond, Block(body, call), unitLiteral)
+ labelDefAndCall(nme.WHILE_PREFIX, rhs, call)
+ case DoWhile(body, cond) =>
+ // { label def doWhile$(): Unit = { body; if (cond) doWhile$() } ; doWhile$() }
+ val call = Apply(Ident(nme.DO_WHILE_PREFIX), Nil)
+ val rhs = Block(body, If(cond, call, unitLiteral))
+ labelDefAndCall(nme.DO_WHILE_PREFIX, rhs, call)
+ case ForDo(enums, body) =>
+ makeFor(nme.foreach, nme.foreach, enums, body) orElse tree
+ case ForYield(enums, body) =>
+ 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))
+ combine(pats1 map (makePatDef(mods, _, rhs)))
+ case _ =>
+ tree
+ }
+ }.withPos(tree.pos)
+
+ def desugarContextBounds(tparams: List[TypeDef], vparamss: List[List[ValDef]], ofClass: Boolean): (List[TypeDef], List[List[ValDef]]) = {
+ val epbuf = new ListBuffer[ValDef]
+ def makeEvidenceParam(cxBound: Tree): ValDef = ???
+ val tparams1 = tparams map {
+ case tparam @ TypeDef(mods, name, ttparams, ContextBounds(tbounds, cxbounds)) =>
+ for (cxbound <- cxbounds) {
+ val accessMods = if (ofClass) PrivateOrLocal else EmptyFlags
+ val epname = (nme.EVIDENCE_PARAM_PREFIX.toString + epbuf.length).toTermName
+ epbuf +=
+ ValDef(Modifiers(Implicit | Param | accessMods), epname, cxbound, EmptyTree())
+ }
+ tparam.derivedTypeDef(mods, name, ttparams, tbounds)
+ case tparam =>
+ tparam
+ }
+ val evidenceParams = epbuf.toList
+ val vparamss1 = vparamss.reverse match {
+ case (vparams @ (vparam :: _)) :: rvparamss if vparam.mods is Implicit =>
+ ((vparams ++ evidenceParams) :: rvparamss).reverse
+ case _ =>
+ vparamss :+ evidenceParams
+ }
+ (tparams1, vparamss1)
+ }
+
+ def desugarContextBounds(tree: Tree): Tree = tree match {
+ case DefDef(mods, name, tparams, vparamss, tpt, rhs) =>
+ val (tparams1, vparamss1) =
+ desugarContextBounds(tparams, vparamss, ofClass = false)
+ tree.derivedDefDef(mods, name, tparams1, vparamss, tpt, rhs)
+ case ClassDef(
+ mods, name, tparams, templ @ Template(constr, parents, self, body)) =>
+ val (tparams1, vparamss1) =
+ desugarContextBounds(tparams, constr.vparamss, ofClass = true)
+ val constr1 = constr.derivedDefDef(
+ constr.mods, constr.name, constr.tparams, vparamss1, constr.tpt, constr.rhs)
+ val templ1 = templ.derivedTemplate(constr1, parents, self, body)
+ tree.derivedClassDef(mods, name, tparams1, templ1)
+ case _ => tree
+ }
+
+ def desugarAnonClass(templ: Template): Tree = {
+ val x = tpnme.ANON_CLASS
+ val clsDef = ClassDef(Modifiers(Final), x, Nil, templ)
+ Block(clsDef, New(Ident(x), Nil))
+ }
+
+ object Mode extends Enumeration {
+ val Type, Expr, Pattern = Value
+ }
+
+ /** If tree is a variable pattern, return its name and type, otherwise return None.
+ */
+ private object VarPattern {
+ def unapply(tree: Tree): Option[VarInfo] = tree match {
+ case id: Ident => Some(id, TypeTree())
+ case Typed(id: Ident, tpt) => Some((id, tpt))
+ case _ => None
+ }
+ }
+
+ /** Traverse pattern and collect all variable names with their types in buffer.
+ * Works for expanded as well as unexpanded patterns
+ *
+ */
+ private object getVars extends TreeAccumulator[ListBuffer[VarInfo]] {
+ override def apply(buf: ListBuffer[VarInfo], tree: Tree): ListBuffer[VarInfo] = {
+ def seenName(name: Name) = buf exists (_._1.name == name)
+ def add(named: NameTree, t: Tree): ListBuffer[VarInfo] =
+ if (seenName(named.name)) buf else buf += ((named, t))
+ tree match {
+ case Bind(nme.WILDCARD, _) =>
+ foldOver(buf, tree)
+ case tree @ Bind(_, Typed(tree1, tpt)) if !mayBeTypePat(tpt) =>
+ apply(add(tree, tpt), tree1)
+ case tree @ Bind(_, tree1) =>
+ apply(add(tree, TypeTree()), tree1)
+ case Typed(id: Ident, t) if isVarPattern(id) =>
+ add(id, t)
+ case id: Ident if isVarPattern(id) =>
+ add(id, TypeTree())
+ case _ =>
+ foldOver(buf, tree)
+ }
+ }
+ }
+
+ implicit class UntypedTreeDecorator(val self: Tree) extends AnyVal {
+ def locateEnclosing(base: List[Tree], pos: Position): List[Tree] = {
+ def encloses(elem: Any) = elem match {
+ case t: Tree => t.envelope contains pos
+ case _ => false
+ }
+ base.productIterator find encloses match {
+ case Some(tree: Tree) => locateEnclosing(tree :: base, pos)
+ case none => base
}
}
}
-} \ No newline at end of file
+}
diff --git a/src/dotty/tools/dotc/core/Annotations.scala b/src/dotty/tools/dotc/core/Annotations.scala
index 07ed37f06..bef8499b0 100644
--- a/src/dotty/tools/dotc/core/Annotations.scala
+++ b/src/dotty/tools/dotc/core/Annotations.scala
@@ -1,7 +1,7 @@
package dotty.tools.dotc
package core
-import Symbols._, Types._, util.Positions._, Contexts._, Constants._, ast.TypedTrees.tpd._
+import Symbols._, Types._, util.Positions._, Contexts._, Constants._, ast.tpd._
object Annotations {
diff --git a/src/dotty/tools/dotc/core/Contexts.scala b/src/dotty/tools/dotc/core/Contexts.scala
index 8fcdc2cbd..af8bd6e91 100644
--- a/src/dotty/tools/dotc/core/Contexts.scala
+++ b/src/dotty/tools/dotc/core/Contexts.scala
@@ -9,7 +9,7 @@ import Phases._
import Types._
import Symbols._
import TypeComparers._, NameOps._, SymDenotations._, util.Positions._
-import ast.TypedTrees.tpd._, util.FreshNameCreator
+import ast.tpd._, util.FreshNameCreator
import config.Settings._
import config.ScalaSettings
import reporting._
diff --git a/src/dotty/tools/dotc/core/Symbols.scala b/src/dotty/tools/dotc/core/Symbols.scala
index 8c5474740..0d6f87cda 100644
--- a/src/dotty/tools/dotc/core/Symbols.scala
+++ b/src/dotty/tools/dotc/core/Symbols.scala
@@ -13,8 +13,7 @@ import Contexts._
import SymDenotations._, printing.Texts._
import printing.Printer
import Types._, Annotations._, util.Positions._, StdNames._, NameOps._
-import ast.TypedTrees.TreeMapper
-import ast.TypedTrees.tpd.SharedTree
+import ast.tpd.{TreeMapper, SharedTree}
import Denotations.{ Denotation, SingleDenotation, MultiDenotation }
import collection.mutable
import io.AbstractFile
diff --git a/src/dotty/tools/dotc/core/Types.scala b/src/dotty/tools/dotc/core/Types.scala
index 135437671..1b21567a0 100644
--- a/src/dotty/tools/dotc/core/Types.scala
+++ b/src/dotty/tools/dotc/core/Types.scala
@@ -15,7 +15,7 @@ import SymDenotations._
import Decorators._
import Denotations._
import Periods._
-import ast.TypedTrees.tpd._, ast.TypedTrees.TreeMapper, printing.Texts._
+import ast.tpd._, printing.Texts._
import transform.Erasure
import printing.Printer
import scala.util.hashing.{ MurmurHash3 => hashing }
diff --git a/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala b/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala
index 9586b9436..8a790d760 100644
--- a/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala
+++ b/src/dotty/tools/dotc/core/pickling/ClassfileParser.scala
@@ -5,7 +5,7 @@ package pickling
import Contexts._, Symbols._, Types._, Names._, StdNames._, NameOps._, Scopes._, Decorators._
import SymDenotations._, UnPickler._, Constants._, Annotations._, util.Positions._
-import ast.TypedTrees.tpd._
+import ast.tpd._
import java.io.{ File, IOException }
import java.lang.Integer.toHexString
import scala.collection.{ mutable, immutable }
diff --git a/src/dotty/tools/dotc/core/pickling/UnPickler.scala b/src/dotty/tools/dotc/core/pickling/UnPickler.scala
index 42899ef44..51816b971 100644
--- a/src/dotty/tools/dotc/core/pickling/UnPickler.scala
+++ b/src/dotty/tools/dotc/core/pickling/UnPickler.scala
@@ -10,7 +10,7 @@ import java.lang.Double.longBitsToDouble
import Contexts._, Symbols._, Types._, Scopes._, SymDenotations._, Names._, NameOps._
import StdNames._, Denotations._, NameOps._, Flags._, Constants._, Annotations._
import util.Positions._
-import ast.Trees, ast.TypedTrees.tpd._, ast.TypedTrees.TreeOps
+import ast.Trees, ast.tpd._
import printing.Texts._
import printing.Printer
import io.AbstractFile
diff --git a/src/dotty/tools/dotc/parsing/MarkupParsers.scala b/src/dotty/tools/dotc/parsing/MarkupParsers.scala
index 04694a61c..f74ebb509 100644
--- a/src/dotty/tools/dotc/parsing/MarkupParsers.scala
+++ b/src/dotty/tools/dotc/parsing/MarkupParsers.scala
@@ -35,7 +35,7 @@ import Constants._
*/
object MarkupParsers {
- import ast.UntypedTrees.untpd._
+ import ast.untpd._
case object MissingEndTagControl extends ControlThrowable {
override def getMessage = "start tag was here: "
diff --git a/src/dotty/tools/dotc/parsing/Parsers.scala b/src/dotty/tools/dotc/parsing/Parsers.scala
index f31a93c24..0599c4490 100644
--- a/src/dotty/tools/dotc/parsing/Parsers.scala
+++ b/src/dotty/tools/dotc/parsing/Parsers.scala
@@ -25,7 +25,7 @@ import annotation.switch
object Parsers {
- import ast.UntypedTrees.untpd._
+ import ast.untpd._
case class OpInfo(operand: Tree, operator: Name, offset: Offset)
diff --git a/src/dotty/tools/dotc/parsing/ScriptParsers.scala b/src/dotty/tools/dotc/parsing/ScriptParsers.scala
index 2aab98eaa..bd66c252d 100644
--- a/src/dotty/tools/dotc/parsing/ScriptParsers.scala
+++ b/src/dotty/tools/dotc/parsing/ScriptParsers.scala
@@ -57,7 +57,7 @@ import Parsers._
*/
object ScriptParsers {
- import ast.UntypedTrees.untpd._
+ import ast.untpd._
class ScriptParser(source: SourceFile)(implicit ctx: Context) extends Parser(source) {
diff --git a/src/dotty/tools/dotc/parsing/SymbolicXMLBuilder.scala b/src/dotty/tools/dotc/parsing/SymbolicXMLBuilder.scala
index a712a437c..669efcbef 100644
--- a/src/dotty/tools/dotc/parsing/SymbolicXMLBuilder.scala
+++ b/src/dotty/tools/dotc/parsing/SymbolicXMLBuilder.scala
@@ -7,7 +7,7 @@ import scala.xml.{ EntityRef, Text }
import scala.xml.XML.{ xmlns }
import core._
import Flags.Mutable
-import Names._, NameOps._, StdNames._, Decorators._, ast.Trees._, ast.TypedTrees._, ast.UntypedTrees._, Constants._
+import Names._, NameOps._, StdNames._, Decorators._, ast.Trees._, ast.{tpd, untpd}, Constants._
import Symbols._, Contexts._
import util.Positions._
import Parsers.Parser
diff --git a/src/dotty/tools/dotc/parsing/TreeBuilder.scala.unused b/src/dotty/tools/dotc/parsing/TreeBuilder.scala.unused
index c903cc55b..12377ca94 100644
--- a/src/dotty/tools/dotc/parsing/TreeBuilder.scala.unused
+++ b/src/dotty/tools/dotc/parsing/TreeBuilder.scala.unused
@@ -10,7 +10,7 @@ import TreeInfo._
/** Methods for building trees, used in the parser. All the trees
* returned by this class must be untyped.
- * Note: currently unused, should be refactored into UntypedTrees.
+ * Note: currently unused
*/
class TreeBuilder(implicit ctx: Context) {
diff --git a/src/dotty/tools/dotc/printing/PlainPrinter.scala b/src/dotty/tools/dotc/printing/PlainPrinter.scala
index a133d25da..0ada9eac5 100644
--- a/src/dotty/tools/dotc/printing/PlainPrinter.scala
+++ b/src/dotty/tools/dotc/printing/PlainPrinter.scala
@@ -5,7 +5,7 @@ import core._
import Texts._, Types._, Flags._, Names._, Symbols._, NameOps._, Constants._
import Contexts.Context, Scopes.Scope, Denotations.Denotation, Annotations.Annotation
import StdNames.nme
-import ast.Trees._, ast.UntypedTrees.untpd
+import ast.Trees._, ast.untpd
import java.lang.Integer.toOctalString
import scala.annotation.switch
diff --git a/src/dotty/tools/dotc/printing/RefinedPrinter.scala b/src/dotty/tools/dotc/printing/RefinedPrinter.scala
index c24d3a800..bcf58e4e5 100644
--- a/src/dotty/tools/dotc/printing/RefinedPrinter.scala
+++ b/src/dotty/tools/dotc/printing/RefinedPrinter.scala
@@ -6,7 +6,7 @@ import Texts._, Types._, Flags._, Names._, Symbols._, NameOps._, Constants._
import Contexts.Context, Scopes.Scope, Denotations.Denotation, Annotations.Annotation
import StdNames.nme
import ast.Trees._
-import ast.UntypedTrees.untpd
+import ast.untpd
import scala.annotation.switch
class RefinedPrinter(_ctx: Context) extends PlainPrinter(_ctx) {
diff --git a/test/test/ParserTest.scala b/test/test/ParserTest.scala
index dc2a79576..49a1ff7b6 100644
--- a/test/test/ParserTest.scala
+++ b/test/test/ParserTest.scala
@@ -5,7 +5,7 @@ import dotty.tools.dotc.util._
import dotty.tools.dotc.core._
import dotty.tools.dotc.parsing._
import Tokens._, Parsers._
-import dotty.tools.dotc.ast.UntypedTrees.untpd._
+import dotty.tools.dotc.ast.untpd._
import org.junit.Test
import scala.collection.mutable.ListBuffer
diff --git a/test/test/parsePackage.scala b/test/test/parsePackage.scala
index 49846fdd2..c9f0a0651 100644
--- a/test/test/parsePackage.scala
+++ b/test/test/parsePackage.scala
@@ -6,7 +6,7 @@ import Trees._
object parsePackage extends ParserTest {
- import ast.UntypedTrees.untpd._
+ import ast.untpd._
var nodes = 0
diff --git a/test/test/showTree.scala b/test/test/showTree.scala
index 5a9452c09..b9b68ed19 100644
--- a/test/test/showTree.scala
+++ b/test/test/showTree.scala
@@ -1,5 +1,5 @@
package test
-import dotty.tools.dotc.ast.UntypedTrees.untpd._
+import dotty.tools.dotc.ast.untpd._
object showTree extends ParserTest {