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]
}