package sbt package appmacro import Types.Id import scala.tools.nsc.Global import scala.reflect._ import macros._ /** * A `TupleBuilder` abstracts the work of constructing a tuple data structure such as a `TupleN` or `KList` * and extracting values from it. The `Instance` macro implementation will (roughly) traverse the tree of its argument * and ultimately obtain a list of expressions with type `M[T]` for different types `T`. * The macro constructs an `Input` value for each of these expressions that contains the `Type` for `T`, * the `Tree` for the expression, and a `ValDef` that will hold the value for the input. * * `TupleBuilder.apply` is provided with the list of `Input`s and is expected to provide three values in the returned BuilderResult. * First, it returns the constructed tuple data structure Tree in `input`. * Next, it provides the type constructor `representationC` that, when applied to M, gives the type of tuple data structure. * For example, a builder that constructs a `Tuple3` for inputs `M[Int]`, `M[Boolean]`, and `M[String]` * would provide a Type representing `[L[x]] (L[Int], L[Boolean], L[String])`. The `input` method * would return a value whose type is that type constructor applied to M, or `(M[Int], M[Boolean], M[String])`. * * Finally, the `extract` method provides a list of vals that extract information from the applied input. * The type of the applied input is the type constructor applied to `Id` (`[X] X`). * The returned list of ValDefs should be the ValDefs from `inputs`, but with non-empty right-hand sides. */ trait TupleBuilder { /** 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]] /** Constructs a one-time use Builder for Context `c` and type constructor `tcType`. */ def make(c: Context)(tcType: c.Type, inputs: Inputs[c.universe.type]): BuilderResult[c.type] } trait BuilderResult[C <: Context with Singleton] { val ctx: C import ctx.universe._ /** Represents the higher-order type constructor `[L[x]] ...` where `...` is the * type of the data structure containing the added expressions, * except that it is abstracted over the type constructor applied to each heterogeneous part of the type . */ def representationC: PolyType /** The instance of AList for the input. For a `representationC` of `[L[x]]`, this `Tree` should have a `Type` of `AList[L]`*/ def alistInstance: Tree /** Returns the completed value containing all expressions added to the builder. */ def input: Tree /* The list of definitions that extract values from a value of type `$representationC[Id]`. * The returned value should be identical to the `ValDef`s provided to the `TupleBuilder.make` method but with * non-empty right hand sides. Each `ValDef` may refer to `param` and previous `ValDef`s in the list.*/ def extract(param: ValDef): List[ValDef] }