diff --git a/util/appmacro/ContextUtil.scala b/util/appmacro/ContextUtil.scala index 31f61c356..8be859494 100644 --- a/util/appmacro/ContextUtil.scala +++ b/util/appmacro/ContextUtil.scala @@ -14,7 +14,7 @@ object ContextUtil { /** Utility methods for macros. Several methods assume that the context's universe is a full compiler (`scala.tools.nsc.Global`). * This is not thread safe due to the underlying Context and related data structures not being thread safe. * Use `ContextUtil[c.type](c)` to construct. */ -final class ContextUtil[C <: Context with Singleton](val ctx: C) +final class ContextUtil[C <: Context](val ctx: C) { import ctx.universe.{Apply=>ApplyTree,_} @@ -31,13 +31,11 @@ final class ContextUtil[C <: Context with Singleton](val ctx: C) * (The current implementation uses Context.fresh, which increments*/ def freshTermName(prefix: String) = newTermName(ctx.fresh("$" + prefix)) - def typeTree(tpe: Type) = TypeTree().setType(tpe) - /** Constructs a new, local ValDef with the given Type, a unique name, * the same position as `sym`, and an empty implementation (no rhs). */ def freshValDef(tpe: Type, sym: Symbol): ValDef = { - val vd = localValDef(typeTree(tpe), EmptyTree) + val vd = localValDef(TypeTree(tpe), EmptyTree) vd setPos getPos(sym) vd } @@ -54,10 +52,10 @@ final class ContextUtil[C <: Context with Singleton](val ctx: C) } /** Creates a new, synthetic type variable with the specified `owner`. */ - def newTypeVariable(owner: Symbol): Symbol = + def newTypeVariable(owner: Symbol, prefix: String = "T0"): TypeSymbol = { val global: Global = ctx.universe.asInstanceOf[Global] - owner.asInstanceOf[global.Symbol].newSyntheticTypeParam().asInstanceOf[ctx.universe.Symbol] + owner.asInstanceOf[global.Symbol].newSyntheticTypeParam(prefix, 0L).asInstanceOf[ctx.universe.TypeSymbol] } /** The type representing the type constructor `[X] X` */ val idTC: Type = @@ -65,28 +63,27 @@ final class ContextUtil[C <: Context with Singleton](val ctx: C) val tvar = newTypeVariable(NoSymbol) polyType(tvar :: Nil, refVar(tvar)) } + /** A Type that references the given type variable. */ + def refVar(variable: TypeSymbol): Type = variable.asTypeConstructor /** Constructs a new, synthetic type variable that is a type constructor. For example, in type Y[L[x]], L is such a type variable. */ - def newTCVariable(owner: Symbol): Symbol = + def newTCVariable(owner: Symbol): TypeSymbol = { - val global: Global = ctx.universe.asInstanceOf[Global] - val tc = owner.asInstanceOf[global.Symbol].newSyntheticTypeParam() - val arg = tc.newSyntheticTypeParam("x", 0L) - tc.setInfo(global.PolyType(arg :: Nil, global.TypeBounds.empty)).asInstanceOf[ctx.universe.Symbol] + val tc = newTypeVariable(owner) + val arg = newTypeVariable(tc, "x") + tc.setTypeSignature(PolyType(arg :: Nil, emptyTypeBounds)) + tc } + def emptyTypeBounds: TypeBounds = TypeBounds(definitions.NothingClass.asType, definitions.AnyClass.asType) + /** Returns the Symbol that references the statically accessible singleton `i`. */ def singleton[T <: AnyRef with Singleton](i: T)(implicit it: ctx.TypeTag[i.type]): Symbol = it.tpe match { case SingleType(_, sym) if !sym.isFreeTerm && sym.isStatic => sym case x => error("Instance must be static (was " + x + ").") } - /** Constructs a Type that references the given type variable. */ - def refVar(variable: Symbol): Type = typeRef(NoPrefix, variable, Nil) /** Returns the symbol for the non-private method named `name` for the class/module `obj`. */ - def method(obj: Symbol, name: String): Symbol = { - val global: Global = ctx.universe.asInstanceOf[Global] - obj.asInstanceOf[global.Symbol].info.nonPrivateMember(global.newTermName(name)).asInstanceOf[ctx.universe.Symbol] - } + def method(obj: Symbol, name: String): Symbol = obj.typeSignature.nonPrivateMember(newTermName(name)) /** Returns a Type representing the type constructor tcp.. For example, given * `object Demo { type M[x] = List[x] }`, the call `extractTC(Demo, "M")` will return a type representing diff --git a/util/appmacro/Instance.scala b/util/appmacro/Instance.scala index 05a80b4e8..6dec0eabc 100644 --- a/util/appmacro/Instance.scala +++ b/util/appmacro/Instance.scala @@ -84,10 +84,6 @@ object Instance implicit tt: c.TypeTag[T], mt: c.TypeTag[i.M[T]], it: c.TypeTag[i.type]): c.Expr[i.M[T]] = { import c.universe.{Apply=>ApplyTree,_} - - import scala.tools.nsc.Global - // Used to access compiler methods not yet exposed via the reflection/macro APIs - val global: Global = c.universe.asInstanceOf[Global] val util = ContextUtil[c.type](c) val mTC: Type = util.extractTC(i, InstanceTCName) @@ -113,19 +109,9 @@ object Instance // constructs a ValDef with a parameter modifier, a unique name, with the provided Type and with an empty rhs def freshMethodParameter(tpe: Type): ValDef = - ValDef(parameterModifiers, freshTermName("p"), typeTree(tpe), EmptyTree) + ValDef(parameterModifiers, freshTermName("p"), TypeTree(tpe), EmptyTree) def freshTermName(prefix: String) = newTermName(c.fresh("$" + prefix)) - def typeTree(tpe: Type) = TypeTree().setType(tpe) - - // constructs a function that applies f to each subtree of the input tree - def visitor(f: Tree => Unit): Tree => Unit = - { - val v: Transformer = new Transformer { - override def transform(tree: Tree): Tree = { f(tree); super.transform(tree) } - } - (tree: Tree) => v.transform(tree) - } /* Local definitions in the macro. This is used to ensure * references are to M instances defined outside of the macro call.*/ @@ -137,13 +123,13 @@ object Instance // a function that checks the provided tree for illegal references to M instances defined in the // expression passed to the macro and for illegal dereferencing of M instances. - val checkQual = visitor { + val checkQual: Tree => Unit = { case s @ ApplyTree(fun, qual :: Nil) => if(isWrapper(fun)) c.error(s.pos, DynamicDependencyError) case id @ Ident(name) if illegalReference(id.symbol) => c.error(id.pos, DynamicReferenceError) case _ => () } // adds the symbols for all non-Ident subtrees to `defs`. - val defSearch = visitor { + val defSearch: Tree => Unit = { case _: Ident => () case tree => if(tree.symbol ne null) defs += tree.symbol; } @@ -160,7 +146,7 @@ object Instance // no inputs, so construct M[T] via Instance.pure or pure+flatten def pure(body: Tree): Tree = { - val typeApplied = TypeApply(Select(instance, PureName), typeTree(treeType) :: Nil) + val typeApplied = TypeApply(Select(instance, PureName), TypeTree(treeType) :: Nil) val p = ApplyTree(typeApplied, Function(Nil, body) :: Nil) if(t.isLeft) p else flatten(p) } @@ -168,7 +154,7 @@ object Instance // the returned Tree will have type M[T] def flatten(m: Tree): Tree = { - val typedFlatten = TypeApply(Select(instance, FlattenName), typeTree(tt.tpe) :: Nil) + val typedFlatten = TypeApply(Select(instance, FlattenName), TypeTree(tt.tpe) :: Nil) ApplyTree(typedFlatten, m :: Nil) } @@ -177,7 +163,7 @@ object Instance { val variable = input.local val param = ValDef(parameterModifiers, variable.name, variable.tpt, EmptyTree) - val typeApplied = TypeApply(Select(instance, MapName), variable.tpt :: typeTree(treeType) :: Nil) + val typeApplied = TypeApply(Select(instance, MapName), variable.tpt :: TypeTree(treeType) :: Nil) val mapped = ApplyTree(typeApplied, input.expr :: Function(param :: Nil, body) :: Nil) if(t.isLeft) mapped else flatten(mapped) } @@ -189,8 +175,8 @@ object Instance val param = freshMethodParameter( appliedType(result.representationC, util.idTC :: Nil) ) val bindings = result.extract(param) val f = Function(param :: Nil, Block(bindings, body)) - val ttt = typeTree(treeType) - val typedApp = TypeApply(Select(instance, ApplyName), typeTree(result.representationC) :: ttt :: Nil) + val ttt = TypeTree(treeType) + val typedApp = TypeApply(Select(instance, ApplyName), TypeTree(result.representationC) :: ttt :: Nil) val app = ApplyTree(ApplyTree(typedApp, result.input :: f :: Nil), result.alistInstance :: Nil) if(t.isLeft) app else flatten(app) } @@ -202,7 +188,7 @@ object Instance // the bound value of the input def addType(tpe: Type, qual: Tree): Tree = { - checkQual(qual) + qual.foreach(checkQual) val vd = util.freshValDef(tpe, qual.symbol) inputs ::= new Input(tpe, qual, vd) Ident(vd.name) @@ -223,7 +209,7 @@ object Instance } // collects all definitions in the tree. used for finding illegal references - defSearch(tree) + tree.foreach(defSearch) // applies the transformation // resetting attributes: a) must be local b) must be done diff --git a/util/appmacro/KListBuilder.scala b/util/appmacro/KListBuilder.scala index 5b658ea69..b57a39449 100644 --- a/util/appmacro/KListBuilder.scala +++ b/util/appmacro/KListBuilder.scala @@ -24,7 +24,7 @@ object KListBuilder extends TupleBuilder val kconsTC: Type = kconsTpe.typeConstructor /** This is the L in the type function [L[x]] ... */ - val tcVariable: Symbol = newTCVariable(NoSymbol) + val tcVariable: TypeSymbol = newTCVariable(NoSymbol) /** Instantiates KCons[h, t <: KList[L], L], where L is the type constructor variable */ def kconsType(h: Type, t: Type): Type = @@ -52,7 +52,7 @@ object KListBuilder extends TupleBuilder val representationC = PolyType(tcVariable :: Nil, klistType) val resultType = appliedType(representationC, idTC :: Nil) val input = klist - val alistInstance = TypeApply(Select(Ident(alist), "klist"), typeTree(representationC) :: Nil) + val alistInstance = TypeApply(Select(Ident(alist), "klist"), TypeTree(representationC) :: Nil) def extract(param: ValDef) = bindKList(param, Nil, inputs.map(_.local)) } } \ No newline at end of file diff --git a/util/appmacro/TupleNBuilder.scala b/util/appmacro/TupleNBuilder.scala index ddf312f1b..4f034adae 100644 --- a/util/appmacro/TupleNBuilder.scala +++ b/util/appmacro/TupleNBuilder.scala @@ -35,7 +35,7 @@ object TupleNBuilder extends TupleBuilder val input: Tree = mkTuple(inputs.map(_.expr)) val alistInstance: Tree = { val select = Select(Ident(alist), TupleMethodName + inputs.size.toString) - TypeApply(select, inputs.map(in => typeTree(in.tpe))) + TypeApply(select, inputs.map(in => TypeTree(in.tpe))) } def extract(param: ValDef): List[ValDef] = bindTuple(param, Nil, inputs.map(_.local), 1)