Skip to content

Instantly share code, notes, and snippets.

@xuwei-k
Created January 21, 2012 10:25
Show Gist options
  • Save xuwei-k/1652284 to your computer and use it in GitHub Desktop.
Save xuwei-k/1652284 to your computer and use it in GitHub Desktop.
generate specs2 DataTables using treehugger
import sbt._
import Keys._
object build extends Build{
val root = Project(
"Specs2DataTableGen",
file("."),
settings = Defaults.defaultSettings ++ Seq(
scalaVersion := "2.9.1"
)
) dependsOn ( treehugger )
lazy val treehugger = uri("git://github.com/eed3si9n/treehugger.git")
}
import treehugger._
import treehuggerDSL._
import definitions._
object Main{
val StringListType = appliedType(ListClass.toType, List(StringClass.toType))
def tableHeader(n: Int) = {
val tableHeader = RootClass.newClass("TableHeader".toTypeName)
val tableHeaderMethods = List(("|", false), ("|>", true)).map {
case (m, f) => tableHeader.newMethod(m) -> f
}
val titles = REF("titles")
CLASSDEF(tableHeader).withFlags(Flags.CASE).withParams(VAL(titles.name, StringListType)) := BLOCK(
{
{
val title = REF("title")
DEF("|").withParams(VAL(title.name, StringClass)) := {
REF("copy") APPLY (titles := titles INFIX(":+", title))
}
} :: {
{
for {
t <- 1 to n
(m, f) <- tableHeaderMethods
} yield {
val tp = (1 to t).map {
k => TYPE(m.newTypeParameter(("T" + k).toString.toTypeName)): TypeDef // ?
}
val types = (1 to t).map {
k => m.newTypeParameter(("T" + k).toString.toTypeName).toType
}
val row = REF("row")
val c = RootClass.newClass(("Table" + t).toTypeName)
DEF(m.name).withTypeParams(tp: _*).withParams(
VAL(row.name, appliedType(definitions.getClass("DataRow" + t).typeConstructor, types.toList))
) := {
if (f)
NEW(c, titles, ListClass.APPLY(row), REF("execute") := TRUE)
else
NEW(c, titles, ListClass.APPLY(row))
}
}
}.toList
}
}: _*
)
}
val tableSym = RootClass.newClass(("Table").toTypeName)
val DecoratedResult = RootClass.newClass(("DecoratedResult").toTypeName)
val dataTable = RootClass.newClass("DataTable".toTypeName)
val collect = tableSym.newMethod("collect")
val Success = RootClass.newClass("Success".toTypeName)
val rows = REF("rows")
val table = {
val allSuccess = tableSym.newMethod("allSuccess")
val resultLine = tableSym.newMethod("resultLine")
CLASSDEF(tableSym).withFlags(Flags.ABSTRACT) := BLOCK(
DEF(collect.name, UnitClass).withFlags(Flags.PROTECTED).withTypeParams(
TYPE(tableSym.newTypeParameter(("R").toTypeName)): TypeDef
) := BLOCK(REF(""))
,
DEF(allSuccess.name).withFlags(Flags.PRIVATE) := REF("")
,
DEF(resultLine.name).withFlags(Flags.PRIVATE) := REF("")
)
}
val ResultType = RootClass.newClass("Result".toTypeName)
def tableClasses(n: Int) = {
(1 to n).map { i =>
val tableN = RootClass.newClass(("Table" + i).toTypeName)
val m1 = tableN.newMethod("|")
val m2 = tableN.newMethod("|>")
val m3 = tableN.newMethod("executeRow")
val tp = (1 to i).map {
k => tableN.newTypeParameter(("T" + k).toTypeName)
}
val tt = tp.map { t => TYPE(t): TypeDef }
val titles = REF("titles")
val execute = REF("execute")
val outer = REF("outer")
val f = REF("f")
val r = m1.newTypeParameter("R".toTypeName)
CLASSDEF(tableN).withFlags(Flags.CASE).withTypeParams(tt: _*).withParams(
VAL(titles.name, StringListType).withFlags(Flags.OVERRIDE),
VAL(execute.name, BooleanClass).withFlags(Flags.OVERRIDE) := TRUE
).withParents(tableSym.toType.APPLY(titles, execute)) := BLOCK(
{
val row = REF("row")
DEF(m1.name, tableN).withTypeParams {
(1 to i).map {
j =>
(
TYPE(m1.newTypeParameter(("S" + j).toTypeName)) := TypeBounds.lower(tp(j - 1).toType)
): TypeDef
}: _*
}.withParams(
VAL(row.name, IntClass)
) := {
tableN.APPLY(titles, outer DOT "rows" INFIX(":+", row), execute)
}
}, {
DEF(m1.name).withTypeParams(TYPE(r)).withParams(// TODO view bound `<% Result`
VAL(f.name, functionType(tp.map {
_.toType
}.toList, r.toType))
) := m3.APPLY(f, execute)
}, {
DEF(m2.name).withTypeParams(TYPE(r)).withParams(// TODO view bound `<% Result`
VAL(f.name, functionType(tp.map {
_.toType
}.toList, r.toType))
) := m3.APPLY(f, TRUE)
}, {
val exec = REF("exec")
DEF(
m3.name, appliedType(DecoratedResult.typeConstructor, List(dataTable.toType))
).withTypeParams(TYPE(r)).withParams(// TODO view bound `<% Result`
VAL(f.name, functionType(tp.map {
_.toType
}.toList, r.toType)),
VAL(exec.name, BooleanClass)
) := BLOCK(
IF(exec) THEN {
collect.APPLY(
rows INFIX("map", functionApply(i).APPLY()) // TODO anon function
)
} ELSE {
DecoratedResult.APPLY(dataTable.APPLY(titles, SeqClass.APPLY()), Success.APPLY(LIT("ok")))
}
)
}
)
}.toList
}
def main(args:Array[String]){
val n = 10
println {
treesToString {
tableHeader(n) :: tableClasses(n)
}
}
}
}
case class TableHeader(titles: List[String]) {
def |(title: String) =
copy(titles = titles :+ title)
def |[T1](row: DataRow1[T1]) =
new <notype>(titles, List(row))
def |>[T1](row: DataRow1[T1]) =
new <notype>(titles, List(row), execute = true)
def |[T1, T2](row: DataRow2[T1,T2]) =
new <notype>(titles, List(row))
def |>[T1, T2](row: DataRow2[T1,T2]) =
new <notype>(titles, List(row), execute = true)
def |[T1, T2, T3](row: DataRow3[T1,T2,T3]) =
new <notype>(titles, List(row))
def |>[T1, T2, T3](row: DataRow3[T1,T2,T3]) =
new <notype>(titles, List(row), execute = true)
def |[T1, T2, T3, T4](row: DataRow4[T1,T2,T3,T4]) =
new <notype>(titles, List(row))
def |>[T1, T2, T3, T4](row: DataRow4[T1,T2,T3,T4]) =
new <notype>(titles, List(row), execute = true)
def |[T1, T2, T3, T4, T5](row: DataRow5[T1,T2,T3,T4,T5]) =
new <notype>(titles, List(row))
def |>[T1, T2, T3, T4, T5](row: DataRow5[T1,T2,T3,T4,T5]) =
new <notype>(titles, List(row), execute = true)
def |[T1, T2, T3, T4, T5, T6](row: DataRow6[T1,T2,T3,T4,T5,T6]) =
new <notype>(titles, List(row))
def |>[T1, T2, T3, T4, T5, T6](row: DataRow6[T1,T2,T3,T4,T5,T6]) =
new <notype>(titles, List(row), execute = true)
def |[T1, T2, T3, T4, T5, T6, T7](row: DataRow7[T1,T2,T3,T4,T5,T6,T7]) =
new <notype>(titles, List(row))
def |>[T1, T2, T3, T4, T5, T6, T7](row: DataRow7[T1,T2,T3,T4,T5,T6,T7]) =
new <notype>(titles, List(row), execute = true)
def |[T1, T2, T3, T4, T5, T6, T7, T8](row: DataRow8[T1,T2,T3,T4,T5,T6,T7,T8]) =
new <notype>(titles, List(row))
def |>[T1, T2, T3, T4, T5, T6, T7, T8](row: DataRow8[T1,T2,T3,T4,T5,T6,T7,T8]) =
new <notype>(titles, List(row), execute = true)
def |[T1, T2, T3, T4, T5, T6, T7, T8, T9](row: DataRow9[T1,T2,T3,T4,T5,T6,T7,T8,T9]) =
new <notype>(titles, List(row))
def |>[T1, T2, T3, T4, T5, T6, T7, T8, T9](row: DataRow9[T1,T2,T3,T4,T5,T6,T7,T8,T9]) =
new <notype>(titles, List(row), execute = true)
def |[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10](row: DataRow10[T1,T2,T3,T4,T5,T6,T7,T8,T9,T10]) =
new <notype>(titles, List(row))
def |>[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10](row: DataRow10[T1,T2,T3,T4,T5,T6,T7,T8,T9,T10]) =
new <notype>(titles, List(row), execute = true)
}
case class Table1[T1](titles: List[String], execute: Boolean = true) extends Table(titles, execute) {
def |[S1 >: T1](row: Int): Table1 =
Table1(titles, outer.rows :+ row, execute)
def |[R](f: T1 => R) =
executeRow(f, execute)
def |>[R](f: T1 => R) =
executeRow(f, true)
def executeRow[R](f: T1 => R, exec: Boolean): DecoratedResult[DataTable] = {
if (exec) collect(rows map apply())
else DecoratedResult(DataTable(titles, Seq()), Success("ok"))
}
}
case class Table2[T1, T2](titles: List[String], execute: Boolean = true) extends Table(titles, execute) {
def |[S1 >: T1, S2 >: T2](row: Int): Table2 =
Table2(titles, outer.rows :+ row, execute)
def |[R](f: (T1, T2) => R) =
executeRow(f, execute)
def |>[R](f: (T1, T2) => R) =
executeRow(f, true)
def executeRow[R](f: (T1, T2) => R, exec: Boolean): DecoratedResult[DataTable] = {
if (exec) collect(rows map apply())
else DecoratedResult(DataTable(titles, Seq()), Success("ok"))
}
}
case class Table3[T1, T2, T3](titles: List[String], execute: Boolean = true) extends Table(titles, execute) {
def |[S1 >: T1, S2 >: T2, S3 >: T3](row: Int): Table3 =
Table3(titles, outer.rows :+ row, execute)
def |[R](f: (T1, T2, T3) => R) =
executeRow(f, execute)
def |>[R](f: (T1, T2, T3) => R) =
executeRow(f, true)
def executeRow[R](f: (T1, T2, T3) => R, exec: Boolean): DecoratedResult[DataTable] = {
if (exec) collect(rows map apply())
else DecoratedResult(DataTable(titles, Seq()), Success("ok"))
}
}
case class Table4[T1, T2, T3, T4](titles: List[String], execute: Boolean = true) extends Table(titles, execute) {
def |[S1 >: T1, S2 >: T2, S3 >: T3, S4 >: T4](row: Int): Table4 =
Table4(titles, outer.rows :+ row, execute)
def |[R](f: (T1, T2, T3, T4) => R) =
executeRow(f, execute)
def |>[R](f: (T1, T2, T3, T4) => R) =
executeRow(f, true)
def executeRow[R](f: (T1, T2, T3, T4) => R, exec: Boolean): DecoratedResult[DataTable] = {
if (exec) collect(rows map apply())
else DecoratedResult(DataTable(titles, Seq()), Success("ok"))
}
}
case class Table5[T1, T2, T3, T4, T5](titles: List[String], execute: Boolean = true) extends Table(titles, execute) {
def |[S1 >: T1, S2 >: T2, S3 >: T3, S4 >: T4, S5 >: T5](row: Int): Table5 =
Table5(titles, outer.rows :+ row, execute)
def |[R](f: (T1, T2, T3, T4, T5) => R) =
executeRow(f, execute)
def |>[R](f: (T1, T2, T3, T4, T5) => R) =
executeRow(f, true)
def executeRow[R](f: (T1, T2, T3, T4, T5) => R, exec: Boolean): DecoratedResult[DataTable] = {
if (exec) collect(rows map apply())
else DecoratedResult(DataTable(titles, Seq()), Success("ok"))
}
}
case class Table6[T1, T2, T3, T4, T5, T6](titles: List[String], execute: Boolean = true) extends Table(titles, execute) {
def |[S1 >: T1, S2 >: T2, S3 >: T3, S4 >: T4, S5 >: T5, S6 >: T6](row: Int): Table6 =
Table6(titles, outer.rows :+ row, execute)
def |[R](f: (T1, T2, T3, T4, T5, T6) => R) =
executeRow(f, execute)
def |>[R](f: (T1, T2, T3, T4, T5, T6) => R) =
executeRow(f, true)
def executeRow[R](f: (T1, T2, T3, T4, T5, T6) => R, exec: Boolean): DecoratedResult[DataTable] = {
if (exec) collect(rows map apply())
else DecoratedResult(DataTable(titles, Seq()), Success("ok"))
}
}
case class Table7[T1, T2, T3, T4, T5, T6, T7](titles: List[String], execute: Boolean = true) extends Table(titles, execute) {
def |[S1 >: T1, S2 >: T2, S3 >: T3, S4 >: T4, S5 >: T5, S6 >: T6, S7 >: T7](row: Int): Table7 =
Table7(titles, outer.rows :+ row, execute)
def |[R](f: (T1, T2, T3, T4, T5, T6, T7) => R) =
executeRow(f, execute)
def |>[R](f: (T1, T2, T3, T4, T5, T6, T7) => R) =
executeRow(f, true)
def executeRow[R](f: (T1, T2, T3, T4, T5, T6, T7) => R, exec: Boolean): DecoratedResult[DataTable] = {
if (exec) collect(rows map apply())
else DecoratedResult(DataTable(titles, Seq()), Success("ok"))
}
}
case class Table8[T1, T2, T3, T4, T5, T6, T7, T8](titles: List[String], execute: Boolean = true) extends Table(titles, execute) {
def |[S1 >: T1, S2 >: T2, S3 >: T3, S4 >: T4, S5 >: T5, S6 >: T6, S7 >: T7, S8 >: T8](row: Int): Table8 =
Table8(titles, outer.rows :+ row, execute)
def |[R](f: (T1, T2, T3, T4, T5, T6, T7, T8) => R) =
executeRow(f, execute)
def |>[R](f: (T1, T2, T3, T4, T5, T6, T7, T8) => R) =
executeRow(f, true)
def executeRow[R](f: (T1, T2, T3, T4, T5, T6, T7, T8) => R, exec: Boolean): DecoratedResult[DataTable] = {
if (exec) collect(rows map apply())
else DecoratedResult(DataTable(titles, Seq()), Success("ok"))
}
}
case class Table9[T1, T2, T3, T4, T5, T6, T7, T8, T9](titles: List[String], execute: Boolean = true) extends Table(titles, execute) {
def |[S1 >: T1, S2 >: T2, S3 >: T3, S4 >: T4, S5 >: T5, S6 >: T6, S7 >: T7, S8 >: T8, S9 >: T9](row: Int): Table9 =
Table9(titles, outer.rows :+ row, execute)
def |[R](f: (T1, T2, T3, T4, T5, T6, T7, T8, T9) => R) =
executeRow(f, execute)
def |>[R](f: (T1, T2, T3, T4, T5, T6, T7, T8, T9) => R) =
executeRow(f, true)
def executeRow[R](f: (T1, T2, T3, T4, T5, T6, T7, T8, T9) => R, exec: Boolean): DecoratedResult[DataTable] = {
if (exec) collect(rows map apply())
else DecoratedResult(DataTable(titles, Seq()), Success("ok"))
}
}
case class Table10[T1, T2, T3, T4, T5, T6, T7, T8, T9, T10](titles: List[String], execute: Boolean = true) extends Table(titles, execute) {
def |[S1 >: T1, S2 >: T2, S3 >: T3, S4 >: T4, S5 >: T5, S6 >: T6, S7 >: T7, S8 >: T8, S9 >: T9, S10 >: T10](row: Int): Table10 =
Table10(titles, outer.rows :+ row, execute)
def |[R](f: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) => R) =
executeRow(f, execute)
def |>[R](f: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) => R) =
executeRow(f, true)
def executeRow[R](f: (T1, T2, T3, T4, T5, T6, T7, T8, T9, T10) => R, exec: Boolean): DecoratedResult[DataTable] = {
if (exec) collect(rows map apply())
else DecoratedResult(DataTable(titles, Seq()), Success("ok"))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment