summaryrefslogblamecommitdiff
path: root/shared.sc
blob: 20e3b54849b6d127c55282ef8ec1184ce7bfd61b (plain) (tree)

























































                                                                                                                   






                                                                                                                   
                                                               









                                  
                                   






                                                      

















                                                                                                                       
     
                                    





                    
                                        

                            
 


                                                                   
                                                                                           
 
/**
  * Utility code that is shared between our SBT build and our Mill build. SBT
  * calls this by shelling out to Ammonite in a subprocess, while Mill loads it
  * via import $file
  */

import ammonite.ops.{write, Path, mkdir, RelPath, up}

def argNames(n: Int) = {
  val uppercases = (0 until n).map("T" + _)
  val lowercases = uppercases.map(_.toLowerCase)
  val typeArgs   = uppercases.mkString(", ")
  val zipArgs    = lowercases.mkString(", ")
  (lowercases, uppercases, typeArgs, zipArgs)
}
def generateApplyer(dir: Path) = {
  def generate(n: Int) = {
    val (lowercases, uppercases, typeArgs, zipArgs) = argNames(n)
    val parameters = lowercases.zip(uppercases).map { case (lower, upper) => s"$lower: TT[$upper]" }.mkString(", ")

    val body   = s"mapCtx(zip($zipArgs)) { case (($zipArgs), z) => cb($zipArgs, z) }"
    val zipmap = s"def zipMap[$typeArgs, Res]($parameters)(cb: ($typeArgs, Ctx) => Z[Res]) = $body"
    val zip    = s"def zip[$typeArgs]($parameters): TT[($typeArgs)]"

    if (n < 22) List(zipmap, zip).mkString("\n") else zip
  }
  write(
    dir / "ApplicativeGenerated.scala",
    s"""package mill.define
      |import scala.language.higherKinds
      |trait ApplyerGenerated[TT[_], Z[_], Ctx] {
      |  def mapCtx[A, B](a: TT[A])(f: (A, Ctx) => Z[B]): TT[B]
      |  ${(2 to 22).map(generate).mkString("\n")}
      |}""".stripMargin
  )
}

def generateTarget(dir: Path) = {
  def generate(n: Int) = {
    val (lowercases, uppercases, typeArgs, zipArgs) = argNames(n)
    val parameters = lowercases.zip(uppercases).map { case (lower, upper) => s"$lower: TT[$upper]" }.mkString(", ")
    val body       = uppercases.zipWithIndex.map { case (t, i) => s"args[$t]($i)" }.mkString(", ")

    s"def zip[$typeArgs]($parameters) = makeT[($typeArgs)](Seq($zipArgs), (args: mill.util.Ctx) => ($body))"
  }

  write(
    dir / "TaskGenerated.scala",
    s"""package mill.define
       |import scala.language.higherKinds
       |trait TargetGenerated {
       |  type TT[+X]
       |  def makeT[X](inputs: Seq[TT[_]], evaluate: mill.util.Ctx => mill.eval.Result[X]): TT[X]
       |  ${(3 to 22).map(generate).mkString("\n")}
       |}""".stripMargin
  )
}

def generateEval(dir: Path) = {
  def generate(n: Int) = {
    val (lowercases, uppercases, typeArgs, zipArgs) = argNames(n)
    val parameters = lowercases.zip(uppercases).map { case (lower, upper) => s"$lower: TT[$upper]" }.mkString(", ")
    val extract    = uppercases.zipWithIndex.map { case (t, i) =>  s"result($i).asInstanceOf[$t]" }.mkString(", ")

    s"""def eval[$typeArgs]($parameters):($typeArgs) = {
       |  val result = evaluator.evaluate(Agg($zipArgs)).values
       |  (${extract})
       |}
     """.stripMargin
  }

  write(
    dir / "EvalGenerated.scala",
    s"""package mill.main
       |import mill.eval.Evaluator
       |import mill.define.Task
       |import mill.util.Strict.Agg
       |class EvalGenerated(evaluator: Evaluator[_]) {
       |  type TT[+X] = Task[X]
       |  ${(1 to 22).map(generate).mkString("\n")}
       |}""".stripMargin
  )
}

def generateApplicativeTest(dir: Path) = {
  def generate(n: Int): String = {
    val (lowercases, uppercases, typeArgs, zipArgs) = argNames(n)
    val parameters = lowercases.zip(uppercases).map { case (lower, upper) => s"$lower: Option[$upper]" }.mkString(", ")
    val forArgs = lowercases.map(i => s"$i <- $i").mkString("; ")
    s"def zip[$typeArgs]($parameters) = { for ($forArgs) yield ($zipArgs) }"
  }

  write(
    dir / "ApplicativeTestsGenerated.scala",
    s"""package mill.define
       |trait OptGenerated {
       |  ${(2 to 22).map(generate).mkString("\n")}
       |}
    """.stripMargin
  )
}

@main
def generateCoreSources(p: Path) = {
  generateApplyer(p)
  generateTarget(p)
  generateEval(p)
}

@main
def generateCoreTestSources(p: Path) = {
  generateApplicativeTest(p)
}


@main
def downloadTestRepo(label: String, commit: String, dest: Path) = {
  mill.modules.Util.unpackZip(dest, s"https://github.com/$label/archive/$commit.zip")(dest)
}