aboutsummaryrefslogtreecommitdiff
path: root/src/dotty/tools/dotc/ast/TypedTrees.scala
diff options
context:
space:
mode:
authorMartin Odersky <odersky@gmail.com>2013-05-22 18:56:31 +0200
committerMartin Odersky <odersky@gmail.com>2013-05-22 18:56:57 +0200
commit965a62d4a165da7e5a53c9afdba3175e10fe714b (patch)
tree9698567b21c4a6006aa5c1e3bdd7ba788706539b /src/dotty/tools/dotc/ast/TypedTrees.scala
parentfd079d2f3335db7b54b0f78a4d884d9948a7beea (diff)
downloaddotty-965a62d4a165da7e5a53c9afdba3175e10fe714b.tar.gz
dotty-965a62d4a165da7e5a53c9afdba3175e10fe714b.tar.bz2
dotty-965a62d4a165da7e5a53c9afdba3175e10fe714b.zip
Made tpd/untpd toplevel objects.
Moved all other elements of TypedTrees and UntypedTrees into tpd and untpd.
Diffstat (limited to 'src/dotty/tools/dotc/ast/TypedTrees.scala')
-rw-r--r--src/dotty/tools/dotc/ast/TypedTrees.scala536
1 files changed, 267 insertions, 269 deletions
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
}
+