Skip to content

Instantly share code, notes, and snippets.

@xuwei-k
Created February 21, 2014 05:41
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save xuwei-k/9129407 to your computer and use it in GitHub Desktop.
Save xuwei-k/9129407 to your computer and use it in GitHub Desktop.
package scalaz.applybuilder
import java.io.File
import sbt._
object Generator {
def main(args: Array[String]){
val dir = args.headOption.flatMap(a => util.Try(new File(a)).toOption).getOrElse(sys.error("invalid argument" + args.mkString(" ")))
IO.delete(dir)
IO.write(dir / "ApplyBuilder.scala", generate(args(1).toInt))
}
def generate(max: Int): String = {
val (methods, classes) = (2 to max).map{ n =>
val % = "%" * (n - 1)
val F = "F"
val f = "f"
val M = "M"
val Fn = (1 to n).map(F + _)
val tparam = Fn.mkString(", ")
val param = (1 to n).map(i => f + i + ": => " + F + i).mkString(", ")
val implicits = (1 to n).map(i => F + i + ": Unapply[Apply, " + F + i + "]").mkString(", ")
val classTparam = (Fn.map(_ + ".M") ++ Fn.map(_ + ".A")).mkString(", ")
val constructorParam = (1 to n).map(i => F + i + "(" + f + i + ")").mkString(", ")
val evidence = (2 to n).map(i => "_" + i + ": " + F + i + "[_" + i + "] =:= F1[_" + i + "]").mkString(",\n ")
val m = s"""
def ${%}[${tparam}](${param})(implicit ${implicits}) =
new Apply${n}[${classTparam}](${constructorParam}, F1.TC)
"""
val applyN = {
if(n <= 12)
s"""F.apply${n}(f1, ${(2 to n).map(i => "_" + i + "(f" + i + ")").mkString(", ")})(f)"""
else {
val a = math.ceil(n / 12.0).toInt
val c = math.ceil(n / a.toDouble).toInt
val d = n - ((a - 1) * c)
def e(start: Int, end: Int) = s"""F.apply${c}(${(start to end).map(i => "_" + i + "(f" + i + ")").mkString(", ")})(Tuple${c}.apply)"""
val t = (1 to a).map("t" + _)
s"""F.apply${a}(
F.apply${d}(f1, ${(2 to d).map(i => "_" + i + "(f" + i + ")").mkString(", ")})(Tuple${d}.apply),
${(2 to a).map(x => e((x - 2) * c + d + 1, (x - 1) * c + d)).mkString(", ")}
)((${t.mkString(", ")}) =>
${((1 to d).map("t1._" + _) ++ t.zipWithIndex.tail.flatMap{case (x, i) => (1 to c).map("t" + (i + 1) + "._" + _)}).mkString("f(",", ",")")}
)"""
}
}
val tupled =
if(n <= 22){ // TODO
s"""
def tupled(implicit
${evidence}
): F1[(${(1 to n).map("_" + _).mkString(", ")})] = run(Tuple${n}.apply)
"""
} else ""
val c = s"""
private[scalaz] final class Apply${n}[${Fn.map(_ + "[_]").mkString(", ")}, ${(1 to n).map("_" + _).mkString(", ")}](
${(1 to n).map(i => f + i + ": => " + F + i + "[_" + i + "]").mkString(", ")}, F: Apply[F1]
){
$tupled
def run[Z](f: (${(1 to n).map("_" + _).mkString(", ")}) => Z)(implicit
${evidence}
): F1[Z] = ${applyN}
}
"""
(m, c)
}.unzip
s"""
package scalaz
object ApplyBuilder {
${methods.mkString("\n")}
}
${classes.mkString("\n")}
"""
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment