Reformat all util-appmacro

This commit is contained in:
jvican 2017-05-23 23:53:04 +02:00
parent ed38fcd695
commit d2f019a47a
No known key found for this signature in database
GPG Key ID: 42DAFA0F112E8050
8 changed files with 337 additions and 297 deletions

View File

@ -251,8 +251,8 @@ lazy val commandProj = (project in file("main-command"))
// The core macro project defines the main logic of the DSL, abstracted // The core macro project defines the main logic of the DSL, abstracted
// away from several sbt implementators (tasks, settings, et cetera). // away from several sbt implementators (tasks, settings, et cetera).
lazy val coreMacrosProj = (project in file("core-macros")). lazy val coreMacrosProj = (project in file("core-macros"))
settings( .settings(
commonSettings, commonSettings,
name := "Core Macros", name := "Core Macros",
libraryDependencies += "org.scala-lang" % "scala-compiler" % scalaVersion.value libraryDependencies += "org.scala-lang" % "scala-compiler" % scalaVersion.value

View File

@ -22,8 +22,8 @@ object ContextUtil {
* Given `myImplicitConversion(someValue).extensionMethod`, where `extensionMethod` is a macro that uses this * Given `myImplicitConversion(someValue).extensionMethod`, where `extensionMethod` is a macro that uses this
* method, the result of this method is `f(<Tree of someValue>)`. * method, the result of this method is `f(<Tree of someValue>)`.
*/ */
def selectMacroImpl[T: c.WeakTypeTag](c: blackbox.Context)(f: (c.Expr[Any], c.Position) => c.Expr[T]): c.Expr[T] = def selectMacroImpl[T: c.WeakTypeTag](c: blackbox.Context)(
{ f: (c.Expr[Any], c.Position) => c.Expr[T]): c.Expr[T] = {
import c.universe._ import c.universe._
c.macroApplication match { c.macroApplication match {
case s @ Select(Apply(_, t :: Nil), tp) => f(c.Expr[Any](t), s.pos) case s @ Select(Apply(_, t :: Nil), tp) => f(c.Expr[Any](t), s.pos)
@ -31,7 +31,8 @@ object ContextUtil {
} }
} }
def unexpectedTree[C <: blackbox.Context](tree: C#Tree): Nothing = sys.error("Unexpected macro application tree (" + tree.getClass + "): " + tree) def unexpectedTree[C <: blackbox.Context](tree: C#Tree): Nothing =
sys.error("Unexpected macro application tree (" + tree.getClass + "): " + tree)
} }
/** /**
@ -68,8 +69,7 @@ final class ContextUtil[C <: blackbox.Context](val ctx: C) {
* Constructs a new, synthetic, local ValDef Type `tpe`, a unique name, * Constructs a new, synthetic, local ValDef Type `tpe`, a unique name,
* Position `pos`, an empty implementation (no rhs), and owned by `owner`. * Position `pos`, an empty implementation (no rhs), and owned by `owner`.
*/ */
def freshValDef(tpe: Type, pos: Position, owner: Symbol): ValDef = def freshValDef(tpe: Type, pos: Position, owner: Symbol): ValDef = {
{
val SYNTHETIC = (1 << 21).toLong.asInstanceOf[FlagSet] val SYNTHETIC = (1 << 21).toLong.asInstanceOf[FlagSet]
val sym = owner.newTermSymbol(freshTermName("q"), pos, SYNTHETIC) val sym = owner.newTermSymbol(freshTermName("q"), pos, SYNTHETIC)
setInfo(sym, tpe) setInfo(sym, tpe)
@ -84,14 +84,15 @@ final class ContextUtil[C <: blackbox.Context](val ctx: C) {
* Collects all definitions in the tree for use in checkReferences. * Collects all definitions in the tree for use in checkReferences.
* This excludes definitions in wrapped expressions because checkReferences won't allow nested dereferencing anyway. * This excludes definitions in wrapped expressions because checkReferences won't allow nested dereferencing anyway.
*/ */
def collectDefs(tree: Tree, isWrapper: (String, Type, Tree) => Boolean): collection.Set[Symbol] = def collectDefs(tree: Tree, isWrapper: (String, Type, Tree) => Boolean): collection.Set[Symbol] = {
{
val defs = new collection.mutable.HashSet[Symbol] val defs = new collection.mutable.HashSet[Symbol]
// adds the symbols for all non-Ident subtrees to `defs`. // adds the symbols for all non-Ident subtrees to `defs`.
val process = new Traverser { val process = new Traverser {
override def traverse(t: Tree) = t match { override def traverse(t: Tree) = t match {
case _: Ident => () case _: Ident => ()
case ApplyTree(TypeApply(Select(_, nme), tpe :: Nil), qual :: Nil) if isWrapper(nme.decodedName.toString, tpe.tpe, qual) => () case ApplyTree(TypeApply(Select(_, nme), tpe :: Nil), qual :: Nil)
if isWrapper(nme.decodedName.toString, tpe.tpe, qual) =>
()
case tree => case tree =>
if (tree.symbol ne null) defs += tree.symbol; if (tree.symbol ne null) defs += tree.symbol;
super.traverse(tree) super.traverse(tree)
@ -112,10 +113,13 @@ final class ContextUtil[C <: blackbox.Context](val ctx: C) {
* A function that checks the provided tree for illegal references to M instances defined in the * 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. * expression passed to the macro and for illegal dereferencing of M instances.
*/ */
def checkReferences(defs: collection.Set[Symbol], isWrapper: (String, Type, Tree) => Boolean): Tree => Unit = { def checkReferences(defs: collection.Set[Symbol],
isWrapper: (String, Type, Tree) => Boolean): Tree => Unit = {
case s @ ApplyTree(TypeApply(Select(_, nme), tpe :: Nil), qual :: Nil) => case s @ ApplyTree(TypeApply(Select(_, nme), tpe :: Nil), qual :: Nil) =>
if (isWrapper(nme.decodedName.toString, tpe.tpe, qual)) ctx.error(s.pos, DynamicDependencyError) if (isWrapper(nme.decodedName.toString, tpe.tpe, qual))
case id @ Ident(name) if illegalReference(defs, id.symbol) => ctx.error(id.pos, DynamicReferenceError + ": " + name) ctx.error(s.pos, DynamicDependencyError)
case id @ Ident(name) if illegalReference(defs, id.symbol) =>
ctx.error(id.pos, DynamicReferenceError + ": " + name)
case _ => () case _ => ()
} }
@ -142,34 +146,41 @@ final class ContextUtil[C <: blackbox.Context](val ctx: C) {
/** Creates a new, synthetic type variable with the specified `owner`. */ /** Creates a new, synthetic type variable with the specified `owner`. */
def newTypeVariable(owner: Symbol, prefix: String = "T0"): TypeSymbol = def newTypeVariable(owner: Symbol, prefix: String = "T0"): TypeSymbol =
owner.asInstanceOf[global.Symbol].newSyntheticTypeParam(prefix, 0L).asInstanceOf[ctx.universe.TypeSymbol] owner
.asInstanceOf[global.Symbol]
.newSyntheticTypeParam(prefix, 0L)
.asInstanceOf[ctx.universe.TypeSymbol]
/** The type representing the type constructor `[X] X` */ /** The type representing the type constructor `[X] X` */
lazy val idTC: Type = lazy val idTC: Type = {
{
val tvar = newTypeVariable(NoSymbol) val tvar = newTypeVariable(NoSymbol)
internal.polyType(tvar :: Nil, refVar(tvar)) internal.polyType(tvar :: Nil, refVar(tvar))
} }
/** A Type that references the given type variable. */ /** A Type that references the given type variable. */
def refVar(variable: TypeSymbol): Type = variable.toTypeConstructor def refVar(variable: TypeSymbol): Type = variable.toTypeConstructor
/** Constructs a new, synthetic type variable that is a type constructor. For example, in type Y[L[x]], L is such a type variable. */ /** 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): TypeSymbol = def newTCVariable(owner: Symbol): TypeSymbol = {
{
val tc = newTypeVariable(owner) val tc = newTypeVariable(owner)
val arg = newTypeVariable(tc, "x"); val arg = newTypeVariable(tc, "x");
tc.setInfo(internal.polyType(arg :: Nil, emptyTypeBounds)) tc.setInfo(internal.polyType(arg :: Nil, emptyTypeBounds))
tc tc
} }
/** >: Nothing <: Any */ /** >: Nothing <: Any */
def emptyTypeBounds: TypeBounds = internal.typeBounds(definitions.NothingClass.toType, definitions.AnyClass.toType) def emptyTypeBounds: TypeBounds =
internal.typeBounds(definitions.NothingClass.toType, definitions.AnyClass.toType)
/** Creates a new anonymous function symbol with Position `pos`. */ /** Creates a new anonymous function symbol with Position `pos`. */
def functionSymbol(pos: Position): Symbol = def functionSymbol(pos: Position): Symbol =
callsiteTyper.context.owner.newAnonymousFunctionValue(pos.asInstanceOf[global.Position]).asInstanceOf[ctx.universe.Symbol] callsiteTyper.context.owner
.newAnonymousFunctionValue(pos.asInstanceOf[global.Position])
.asInstanceOf[ctx.universe.Symbol]
def functionType(args: List[Type], result: Type): Type = def functionType(args: List[Type], result: Type): Type = {
{ val tpe = global.definitions
val tpe = global.definitions.functionType(args.asInstanceOf[List[global.Type]], result.asInstanceOf[global.Type]) .functionType(args.asInstanceOf[List[global.Type]], result.asInstanceOf[global.Type])
tpe.asInstanceOf[Type] tpe.asInstanceOf[Type]
} }
@ -178,8 +189,7 @@ final class ContextUtil[C <: blackbox.Context](val ctx: C) {
treeCopy.Ident(replaced, vd.name).setSymbol(vd.symbol) treeCopy.Ident(replaced, vd.name).setSymbol(vd.symbol)
/** Creates a Function tree using `functionSym` as the Symbol and changing `initialOwner` to `functionSym` in `body`.*/ /** Creates a Function tree using `functionSym` as the Symbol and changing `initialOwner` to `functionSym` in `body`.*/
def createFunction(params: List[ValDef], body: Tree, functionSym: Symbol): Tree = def createFunction(params: List[ValDef], body: Tree, functionSym: Symbol): Tree = {
{
changeOwner(body, initialOwner, functionSym) changeOwner(body, initialOwner, functionSym)
val f = Function(params, body) val f = Function(params, body)
setSymbol(f, functionSym) setSymbol(f, functionSym)
@ -187,10 +197,14 @@ final class ContextUtil[C <: blackbox.Context](val ctx: C) {
} }
def changeOwner(tree: Tree, prev: Symbol, next: Symbol): Unit = def changeOwner(tree: Tree, prev: Symbol, next: Symbol): Unit =
new ChangeOwnerAndModuleClassTraverser(prev.asInstanceOf[global.Symbol], next.asInstanceOf[global.Symbol]).traverse(tree.asInstanceOf[global.Tree]) new ChangeOwnerAndModuleClassTraverser(
prev.asInstanceOf[global.Symbol],
next.asInstanceOf[global.Symbol]).traverse(tree.asInstanceOf[global.Tree])
// Workaround copied from scala/async:can be removed once https://github.com/scala/scala/pull/3179 is merged. // Workaround copied from scala/async:can be removed once https://github.com/scala/scala/pull/3179 is merged.
private[this] class ChangeOwnerAndModuleClassTraverser(oldowner: global.Symbol, newowner: global.Symbol) extends global.ChangeOwnerTraverser(oldowner, newowner) { private[this] class ChangeOwnerAndModuleClassTraverser(oldowner: global.Symbol,
newowner: global.Symbol)
extends global.ChangeOwnerTraverser(oldowner, newowner) {
override def traverse(tree: global.Tree): Unit = { override def traverse(tree: global.Tree): Unit = {
tree match { tree match {
case _: global.DefTree => change(tree.symbol.moduleClass) case _: global.DefTree => change(tree.symbol.moduleClass)
@ -221,8 +235,8 @@ final class ContextUtil[C <: blackbox.Context](val ctx: C) {
* `object Demo { type M[x] = List[x] }`, the call `extractTC(Demo, "M")` will return a type representing * `object Demo { type M[x] = List[x] }`, the call `extractTC(Demo, "M")` will return a type representing
* the type constructor `[x] List[x]`. * the type constructor `[x] List[x]`.
*/ */
def extractTC(tcp: AnyRef with Singleton, name: String)(implicit it: ctx.TypeTag[tcp.type]): ctx.Type = def extractTC(tcp: AnyRef with Singleton, name: String)(
{ implicit it: ctx.TypeTag[tcp.type]): ctx.Type = {
val itTpe = it.tpe.asInstanceOf[global.Type] val itTpe = it.tpe.asInstanceOf[global.Type]
val m = itTpe.nonPrivateMember(global.newTypeName(name)) val m = itTpe.nonPrivateMember(global.newTypeName(name))
val tc = itTpe.memberInfo(m).asInstanceOf[ctx.universe.Type] val tc = itTpe.memberInfo(m).asInstanceOf[ctx.universe.Type]
@ -236,8 +250,8 @@ final class ContextUtil[C <: blackbox.Context](val ctx: C) {
* Typically, `f` is a `Select` or `Ident`. * Typically, `f` is a `Select` or `Ident`.
* The wrapper is replaced with the result of `subWrapper(<Type of T>, <Tree of v>, <wrapper Tree>)` * The wrapper is replaced with the result of `subWrapper(<Type of T>, <Tree of v>, <wrapper Tree>)`
*/ */
def transformWrappers(t: Tree, subWrapper: (String, Type, Tree, Tree) => Converted[ctx.type]): Tree = def transformWrappers(t: Tree,
{ subWrapper: (String, Type, Tree, Tree) => Converted[ctx.type]): Tree = {
// the main tree transformer that replaces calls to InputWrapper.wrap(x) with // the main tree transformer that replaces calls to InputWrapper.wrap(x) with
// plain Idents that reference the actual input value // plain Idents that reference the actual input value
object appTransformer extends Transformer { object appTransformer extends Transformer {

View File

@ -19,7 +19,9 @@ sealed trait Converted[C <: blackbox.Context with Singleton] {
} }
object Converted { object Converted {
def NotApplicable[C <: blackbox.Context with Singleton] = new NotApplicable[C] def NotApplicable[C <: blackbox.Context with Singleton] = new NotApplicable[C]
final case class Failure[C <: blackbox.Context with Singleton](position: C#Position, message: String) extends Converted[C] { final case class Failure[C <: blackbox.Context with Singleton](position: C#Position,
message: String)
extends Converted[C] {
def isSuccess = false def isSuccess = false
def transform(f: C#Tree => C#Tree): Converted[C] = new Failure(position, message) def transform(f: C#Tree => C#Tree): Converted[C] = new Failure(position, message)
} }
@ -27,11 +29,14 @@ object Converted {
def isSuccess = false def isSuccess = false
def transform(f: C#Tree => C#Tree): Converted[C] = this def transform(f: C#Tree => C#Tree): Converted[C] = this
} }
final case class Success[C <: blackbox.Context with Singleton](tree: C#Tree, finalTransform: C#Tree => C#Tree) extends Converted[C] { final case class Success[C <: blackbox.Context with Singleton](tree: C#Tree,
finalTransform: C#Tree => C#Tree)
extends Converted[C] {
def isSuccess = true def isSuccess = true
def transform(f: C#Tree => C#Tree): Converted[C] = Success(f(tree), finalTransform) def transform(f: C#Tree => C#Tree): Converted[C] = Success(f(tree), finalTransform)
} }
object Success { object Success {
def apply[C <: blackbox.Context with Singleton](tree: C#Tree): Success[C] = Success(tree, idFun) def apply[C <: blackbox.Context with Singleton](tree: C#Tree): Success[C] =
Success(tree, idFun)
} }
} }

View File

@ -31,7 +31,9 @@ object Instance {
final val MapName = "map" final val MapName = "map"
final val InstanceTCName = "M" final val InstanceTCName = "M"
final class Input[U <: Universe with Singleton](val tpe: U#Type, val expr: U#Tree, val local: U#ValDef) final class Input[U <: Universe with Singleton](val tpe: U#Type,
val expr: U#Tree,
val local: U#ValDef)
trait Transform[C <: blackbox.Context with Singleton, N[_]] { trait Transform[C <: blackbox.Context with Singleton, N[_]] {
def apply(in: C#Tree): C#Tree def apply(in: C#Tree): C#Tree
} }
@ -75,11 +77,15 @@ object Instance {
* If this is for multi-input flatMap (app followed by flatMap), * If this is for multi-input flatMap (app followed by flatMap),
* this should be the argument wrapped in Right. * this should be the argument wrapped in Right.
*/ */
def contImpl[T, N[_]](c: blackbox.Context, i: Instance with Singleton, convert: Convert, builder: TupleBuilder)(t: Either[c.Expr[T], c.Expr[i.M[T]]], inner: Transform[c.type, N])( def contImpl[T, N[_]](
implicit c: blackbox.Context,
tt: c.WeakTypeTag[T], nt: c.WeakTypeTag[N[T]], it: c.TypeTag[i.type] i: Instance with Singleton,
): c.Expr[i.M[N[T]]] = convert: Convert,
{ builder: TupleBuilder)(t: Either[c.Expr[T], c.Expr[i.M[T]]], inner: Transform[c.type, N])(
implicit tt: c.WeakTypeTag[T],
nt: c.WeakTypeTag[N[T]],
it: c.TypeTag[i.type]
): c.Expr[i.M[N[T]]] = {
import c.universe.{ Apply => ApplyTree, _ } import c.universe.{ Apply => ApplyTree, _ }
val util = ContextUtil[c.type](c) val util = ContextUtil[c.type](c)
@ -119,8 +125,7 @@ object Instance {
} }
// no inputs, so construct M[T] via Instance.pure or pure+flatten // no inputs, so construct M[T] via Instance.pure or pure+flatten
def pure(body: Tree): Tree = def pure(body: Tree): Tree = {
{
val typeApplied = TypeApply(util.select(instance, PureName), TypeTree(treeType) :: Nil) val typeApplied = TypeApply(util.select(instance, PureName), TypeTree(treeType) :: Nil)
val f = util.createFunction(Nil, body, functionSym) val f = util.createFunction(Nil, body, functionSym)
val p = ApplyTree(typeApplied, f :: Nil) val p = ApplyTree(typeApplied, f :: Nil)
@ -128,33 +133,34 @@ object Instance {
} }
// m should have type M[M[T]] // m should have type M[M[T]]
// the returned Tree will have type M[T] // the returned Tree will have type M[T]
def flatten(m: Tree): Tree = def flatten(m: Tree): Tree = {
{
val typedFlatten = TypeApply(util.select(instance, FlattenName), TypeTree(tt.tpe) :: Nil) val typedFlatten = TypeApply(util.select(instance, FlattenName), TypeTree(tt.tpe) :: Nil)
ApplyTree(typedFlatten, m :: Nil) ApplyTree(typedFlatten, m :: Nil)
} }
// calls Instance.map or flatmap directly, skipping the intermediate Instance.app that is unnecessary for a single input // calls Instance.map or flatmap directly, skipping the intermediate Instance.app that is unnecessary for a single input
def single(body: Tree, input: In): Tree = def single(body: Tree, input: In): Tree = {
{
val variable = input.local val variable = input.local
val param = treeCopy.ValDef(variable, util.parameterModifiers, variable.name, variable.tpt, EmptyTree) val param =
val typeApplied = TypeApply(util.select(instance, MapName), variable.tpt :: TypeTree(treeType) :: Nil) treeCopy.ValDef(variable, util.parameterModifiers, variable.name, variable.tpt, EmptyTree)
val typeApplied =
TypeApply(util.select(instance, MapName), variable.tpt :: TypeTree(treeType) :: Nil)
val f = util.createFunction(param :: Nil, body, functionSym) val f = util.createFunction(param :: Nil, body, functionSym)
val mapped = ApplyTree(typeApplied, input.expr :: f :: Nil) val mapped = ApplyTree(typeApplied, input.expr :: f :: Nil)
if (t.isLeft) mapped else flatten(mapped) if (t.isLeft) mapped else flatten(mapped)
} }
// calls Instance.app to get the values for all inputs and then calls Instance.map or flatMap to evaluate the body // calls Instance.app to get the values for all inputs and then calls Instance.map or flatMap to evaluate the body
def arbArity(body: Tree, inputs: List[In]): Tree = def arbArity(body: Tree, inputs: List[In]): Tree = {
{
val result = builder.make(c)(mTC, inputs) val result = builder.make(c)(mTC, inputs)
val param = util.freshMethodParameter(appliedType(result.representationC, util.idTC :: Nil)) val param = util.freshMethodParameter(appliedType(result.representationC, util.idTC :: Nil))
val bindings = result.extract(param) val bindings = result.extract(param)
val f = util.createFunction(param :: Nil, Block(bindings, body), functionSym) val f = util.createFunction(param :: Nil, Block(bindings, body), functionSym)
val ttt = TypeTree(treeType) val ttt = TypeTree(treeType)
val typedApp = TypeApply(util.select(instance, ApplyName), TypeTree(result.representationC) :: ttt :: Nil) val typedApp =
val app = ApplyTree(ApplyTree(typedApp, result.input :: f :: Nil), result.alistInstance :: Nil) TypeApply(util.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) if (t.isLeft) app else flatten(app)
} }
@ -163,15 +169,13 @@ object Instance {
// the call is addType(Type A, Tree qual) // the call is addType(Type A, Tree qual)
// The result is a Tree representing a reference to // The result is a Tree representing a reference to
// the bound value of the input. // the bound value of the input.
def addType(tpe: Type, qual: Tree, selection: Tree): Tree = def addType(tpe: Type, qual: Tree, selection: Tree): Tree = {
{
qual.foreach(checkQual) qual.foreach(checkQual)
val vd = util.freshValDef(tpe, qual.pos, functionSym) val vd = util.freshValDef(tpe, qual.pos, functionSym)
inputs ::= new Input(tpe, qual, vd) inputs ::= new Input(tpe, qual, vd)
util.refVal(selection, vd) util.refVal(selection, vd)
} }
def sub(name: String, tpe: Type, qual: Tree, replace: Tree): Converted[c.type] = def sub(name: String, tpe: Type, qual: Tree, replace: Tree): Converted[c.type] = {
{
val tag = c.WeakTypeTag[T](tpe) val tag = c.WeakTypeTag[T](tpe)
convert[T](c)(name, qual)(tag) transform { tree => convert[T](c)(name, qual)(tag) transform { tree =>
addType(tpe, tree, replace) addType(tpe, tree, replace)
@ -187,7 +191,8 @@ object Instance {
import Types._ import Types._
implicit def applicativeInstance[A[_]](implicit ap: Applicative[A]): Instance { type M[x] = A[x] } = new Instance { implicit def applicativeInstance[A[_]](
implicit ap: Applicative[A]): Instance { type M[x] = A[x] } = new Instance {
type M[x] = A[x] type M[x] = A[x]
def app[K[L[x]], Z](in: K[A], f: K[Id] => Z)(implicit a: AList[K]) = a.apply[A, Z](in, f) def app[K[L[x]], Z](in: K[A], f: K[Id] => Z)(implicit a: AList[K]) = a.apply[A, Z](in, f)
def map[S, T](in: A[S], f: S => T) = ap.map(f, in) def map[S, T](in: A[S], f: S => T) = ap.map(f, in)
@ -195,14 +200,14 @@ object Instance {
} }
type AI[A[_]] = Instance { type M[x] = A[x] } type AI[A[_]] = Instance { type M[x] = A[x] }
def compose[A[_], B[_]](implicit a: AI[A], b: AI[B]): Instance { type M[x] = A[B[x]] } = new Composed[A, B](a, b) def compose[A[_], B[_]](implicit a: AI[A], b: AI[B]): Instance { type M[x] = A[B[x]] } =
new Composed[A, B](a, b)
// made a public, named, unsealed class because of trouble with macros and inference when the Instance is not an object // made a public, named, unsealed class because of trouble with macros and inference when the Instance is not an object
class Composed[A[_], B[_]](a: AI[A], b: AI[B]) extends Instance { class Composed[A[_], B[_]](a: AI[A], b: AI[B]) extends Instance {
type M[x] = A[B[x]] type M[x] = A[B[x]]
def pure[S](s: () => S): A[B[S]] = a.pure(() => b.pure(s)) def pure[S](s: () => S): A[B[S]] = a.pure(() => b.pure(s))
def map[S, T](in: M[S], f: S => T): M[T] = a.map(in, (bv: B[S]) => b.map(bv, f)) def map[S, T](in: M[S], f: S => T): M[T] = a.map(in, (bv: B[S]) => b.map(bv, f))
def app[K[L[x]], Z](in: K[M], f: K[Id] => Z)(implicit alist: AList[K]): A[B[Z]] = def app[K[L[x]], Z](in: K[M], f: K[Id] => Z)(implicit alist: AList[K]): A[B[Z]] = {
{
val g: K[B] => B[Z] = in => b.app[K, Z](in, f) val g: K[B] => B[Z] = in => b.app[K, Z](in, f)
type Split[L[x]] = K[(L B)#l] type Split[L[x]] = K[(L B)#l]
a.app[Split, B[Z]](in, g)(AList.asplit(alist)) a.app[Split, B[Z]](in, g)(AList.asplit(alist))

View File

@ -6,7 +6,9 @@ import macros._
/** A `TupleBuilder` that uses a KList as the tuple representation.*/ /** A `TupleBuilder` that uses a KList as the tuple representation.*/
object KListBuilder extends TupleBuilder { object KListBuilder extends TupleBuilder {
def make(c: blackbox.Context)(mt: c.Type, inputs: Inputs[c.universe.type]): BuilderResult[c.type] = new BuilderResult[c.type] { def make(c: blackbox.Context)(mt: c.Type,
inputs: Inputs[c.universe.type]): BuilderResult[c.type] =
new BuilderResult[c.type] {
val ctx: c.type = c val ctx: c.type = c
val util = ContextUtil[c.type](c) val util = ContextUtil[c.type](c)
import c.universe.{ Apply => ApplyTree, _ } import c.universe.{ Apply => ApplyTree, _ }
@ -38,10 +40,15 @@ object KListBuilder extends TupleBuilder {
case Nil => revBindings.reverse case Nil => revBindings.reverse
} }
private[this] def makeKList(revInputs: Inputs[c.universe.type], klist: Tree, klistType: Type): Tree = private[this] def makeKList(revInputs: Inputs[c.universe.type],
klist: Tree,
klistType: Type): Tree =
revInputs match { revInputs match {
case in :: tail => case in :: tail =>
val next = ApplyTree(TypeApply(Ident(kcons), TypeTree(in.tpe) :: TypeTree(klistType) :: TypeTree(mTC) :: Nil), in.expr :: klist :: Nil) val next = ApplyTree(
TypeApply(Ident(kcons),
TypeTree(in.tpe) :: TypeTree(klistType) :: TypeTree(mTC) :: Nil),
in.expr :: klist :: Nil)
makeKList(tail, next, appliedType(kconsTC, in.tpe :: klistType :: mTC :: Nil)) makeKList(tail, next, appliedType(kconsTC, in.tpe :: klistType :: mTC :: Nil))
case Nil => klist case Nil => klist
} }
@ -58,7 +65,8 @@ object KListBuilder extends TupleBuilder {
val representationC = internal.polyType(tcVariable :: Nil, klistType) val representationC = internal.polyType(tcVariable :: Nil, klistType)
val input = klist val input = klist
val alistInstance: ctx.universe.Tree = TypeApply(select(Ident(alist), "klist"), TypeTree(representationC) :: Nil) val alistInstance: ctx.universe.Tree =
TypeApply(select(Ident(alist), "klist"), TypeTree(representationC) :: Nil)
def extract(param: ValDef) = bindKList(param, Nil, inputs.map(_.local)) def extract(param: ValDef) = bindKList(param, Nil, inputs.map(_.local))
} }
} }

View File

@ -9,8 +9,8 @@ import macros._
* and `KList` for larger numbers of inputs. This builder cannot handle fewer than 2 inputs. * and `KList` for larger numbers of inputs. This builder cannot handle fewer than 2 inputs.
*/ */
object MixedBuilder extends TupleBuilder { object MixedBuilder extends TupleBuilder {
def make(c: blackbox.Context)(mt: c.Type, inputs: Inputs[c.universe.type]): BuilderResult[c.type] = def make(c: blackbox.Context)(mt: c.Type,
{ inputs: Inputs[c.universe.type]): BuilderResult[c.type] = {
val delegate = if (inputs.size > TupleNBuilder.MaxInputs) KListBuilder else TupleNBuilder val delegate = if (inputs.size > TupleNBuilder.MaxInputs) KListBuilder else TupleNBuilder
delegate.make(c)(mt, inputs) delegate.make(c)(mt, inputs)
} }

View File

@ -23,11 +23,13 @@ import macros._
* The returned list of ValDefs should be the ValDefs from `inputs`, but with non-empty right-hand sides. * The returned list of ValDefs should be the ValDefs from `inputs`, but with non-empty right-hand sides.
*/ */
trait TupleBuilder { trait TupleBuilder {
/** A convenience alias for a list of inputs (associated with a Universe of type U). */ /** A convenience alias for a list of inputs (associated with a Universe of type U). */
type Inputs[U <: Universe with Singleton] = List[Instance.Input[U]] type Inputs[U <: Universe with Singleton] = List[Instance.Input[U]]
/** Constructs a one-time use Builder for Context `c` and type constructor `tcType`. */ /** Constructs a one-time use Builder for Context `c` and type constructor `tcType`. */
def make(c: blackbox.Context)(tcType: c.Type, inputs: Inputs[c.universe.type]): BuilderResult[c.type] def make(c: blackbox.Context)(tcType: c.Type,
inputs: Inputs[c.universe.type]): BuilderResult[c.type]
} }
trait BuilderResult[C <: blackbox.Context with Singleton] { trait BuilderResult[C <: blackbox.Context with Singleton] {
@ -52,4 +54,3 @@ trait BuilderResult[C <: blackbox.Context with Singleton] {
* non-empty right hand sides. Each `ValDef` may refer to `param` and previous `ValDef`s in the list.*/ * non-empty right hand sides. Each `ValDef` may refer to `param` and previous `ValDef`s in the list.*/
def extract(param: ValDef): List[ValDef] def extract(param: ValDef): List[ValDef]
} }

View File

@ -10,11 +10,14 @@ import macros._
* It is limited to tuples of size 2 to `MaxInputs`. * It is limited to tuples of size 2 to `MaxInputs`.
*/ */
object TupleNBuilder extends TupleBuilder { object TupleNBuilder extends TupleBuilder {
/** The largest number of inputs that this builder can handle. */ /** The largest number of inputs that this builder can handle. */
final val MaxInputs = 11 final val MaxInputs = 11
final val TupleMethodName = "tuple" final val TupleMethodName = "tuple"
def make(c: blackbox.Context)(mt: c.Type, inputs: Inputs[c.universe.type]): BuilderResult[c.type] = new BuilderResult[c.type] { def make(c: blackbox.Context)(mt: c.Type,
inputs: Inputs[c.universe.type]): BuilderResult[c.type] =
new BuilderResult[c.type] {
val util = ContextUtil[c.type](c) val util = ContextUtil[c.type](c)
import c.universe._ import c.universe._
import util._ import util._
@ -24,7 +27,8 @@ object TupleNBuilder extends TupleBuilder {
val ctx: c.type = c val ctx: c.type = c
val representationC: PolyType = { val representationC: PolyType = {
val tcVariable: Symbol = newTCVariable(util.initialOwner) val tcVariable: Symbol = newTCVariable(util.initialOwner)
val tupleTypeArgs = inputs.map(in => internal.typeRef(NoPrefix, tcVariable, in.tpe :: Nil).asInstanceOf[global.Type]) val tupleTypeArgs = inputs.map(in =>
internal.typeRef(NoPrefix, tcVariable, in.tpe :: Nil).asInstanceOf[global.Type])
val tuple = global.definitions.tupleType(tupleTypeArgs) val tuple = global.definitions.tupleType(tupleTypeArgs)
internal.polyType(tcVariable :: Nil, tuple.asInstanceOf[Type]) internal.polyType(tcVariable :: Nil, tuple.asInstanceOf[Type])
} }
@ -36,7 +40,10 @@ object TupleNBuilder extends TupleBuilder {
} }
def extract(param: ValDef): List[ValDef] = bindTuple(param, Nil, inputs.map(_.local), 1) def extract(param: ValDef): List[ValDef] = bindTuple(param, Nil, inputs.map(_.local), 1)
def bindTuple(param: ValDef, revBindings: List[ValDef], params: List[ValDef], i: Int): List[ValDef] = def bindTuple(param: ValDef,
revBindings: List[ValDef],
params: List[ValDef],
i: Int): List[ValDef] =
params match { params match {
case (x @ ValDef(mods, name, tpt, _)) :: xs => case (x @ ValDef(mods, name, tpt, _)) :: xs =>
val rhs = select(Ident(param.name), "_" + i.toString) val rhs = select(Ident(param.name), "_" + i.toString)