aboutsummaryrefslogblamecommitdiff
path: root/stage2/plugins/Frege.scala
blob: da5e54f2323fd7f55177833191d7be73672c131a (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12











                                               
                                                       






                                                                                                                        
 
                                           
                                                      
                                                         




                                                                                                                       
                                                                           
                     
                                                                               









                                                                                  
                        
                   

                             
                                     
                     
                                                                                                             


                           
                                                                                         




                                                                                  
                           

                        
                                  
                             
                                                                  


                                      
 



                                                                          
                              
          


                                                
                                        

                                          
                                                                                                 


                                   


                                                                






                                                                                    
                                      
                       
                                                                     
















                                                                       
                                                                                                 
  
                                       












                                                                                                                       


                            
       


     
package cbt
import java.io.File
import java.net.URL
import java.nio.file.Files
import java.nio.file.attribute.FileTime

trait Frege extends BaseBuild{
  def fregeVersion: String = "3.24.100.1"
  def classifier: Option[String] = Some("jdk8")
  def fregeTarget: String = "1.8"
  def enableMakeMode = true
  def enableOptimisation = true
  def fregeDependencies: Seq[Dependency] = dependencies
  def inline = true

  private def fregeOptions: Seq[String] = {
    val opts : Seq[(String, Boolean)] = Seq(("-make", enableMakeMode), ("-O", enableOptimisation), ("-inline", inline) )
    opts.filter(_._2).map(_._1)
  }
  override def scalaTarget: File = target ++ s"/frege-$fregeVersion"

  private lazy val fregeLib = new FregeLib(
    context.cbtLastModified, context.paths.mavenCache,
    fregeVersion = fregeVersion, classifier = classifier,
    fregeDependencies = fregeDependencies, fregeTarget = fregeTarget
  )

  override def sourceFileFilter(file: File): Boolean = file.toString.endsWith(".fr") || file.toString.endsWith(".java")

  override def compile: Option[Long] = taskCache[Frege]("compile").memoize{
    fregeLib.compile(
      sourceFiles, compileTarget, compileStatusFile, dependencies, fregeOptions
    )
  }

  override def dependencies = Resolver(mavenCentral).bind(
    MavenDependency("org.frege-lang","frege",fregeVersion, Classifier(classifier))
  )

}

class FregeLib(
  cbtLastModified: Long,
  mavenCache: File,
  fregeVersion: String,
  classifier: Option[String],
  fregeDependencies: Seq[Dependency],
  fregeTarget: String
)(implicit transientCache: java.util.Map[AnyRef,AnyRef], classLoaderCache: ClassLoaderCache, logger: Logger){
  val lib = new Lib(logger)
  import lib._

  private def Resolver(urls: URL*) = MavenResolver(cbtLastModified, mavenCache, urls: _*)
  private lazy val fregeDependency = Resolver(mavenCentral).bindOne(
    MavenDependency("org.frege-lang","frege",fregeVersion, Classifier(classifier))
  )

  def compile(
    sourceFiles: Seq[File],
    compileTarget: File,
    statusFile: File,
    dependencies: Seq[Dependency],
    fregeOptions: Seq[String]
  )(implicit classLoaderCache: ClassLoaderCache): Option[Long] = {
    val d = Dependencies(dependencies)
    val classpath = d.classpath
    val cp = classpath.string

    def lastModified = (
      cbtLastModified +: d.lastModified +: sourceFiles.map(_.lastModified)
    ).max

    if( sourceFiles.isEmpty ){
      None
    } else {
      val start = System.currentTimeMillis
      val lastCompiled = statusFile.lastModified
      if( lastModified > lastCompiled ){

        val _class = "frege.compiler.Main"
        val fp = (fregeDependency.classpath.strings ++ fregeDependencies.map(_.classpath.string))
        val dualArgs =
          Seq(
            "-target", fregeTarget,
            "-d", compileTarget.toString
          ) ++ (
            if(fp.isEmpty) Nil else Seq("-fp", fp.mkString(":"))
          )
        val singleArgs = fregeOptions
        val code = 
          try{
            System.err.println("Compiling with Frege to " ++ compileTarget.toString)
            compileTarget.mkdirs
            redirectOutToErr{
              fregeDependency.runMain(
                _class,
                dualArgs ++ singleArgs ++ sourceFiles.map(_.toString)
              )
            }
          } catch {
            case e: Exception =>
            System.err.println(red("Frege crashed. To reproduce run:"))
            System.out.println(s"""
java -cp \\
${fregeDependency.classpath.strings.mkString(":\\\n")} \\
\\
${_class} \\
\\
${dualArgs.grouped(2).map(_.mkString(" ")).mkString(" \\\n")} \\
\\
${singleArgs.mkString(" \\\n")} \\
\\
-bootclasspath \\
${fregeDependency.classpath.strings.mkString(":\\\n")} \\
${if(classpath.strings.isEmpty) "" else ("  -fp \\\n" ++ classpath.strings.mkString(":\\\n"))} \\
\\
${sourceFiles.sorted.mkString(" \\\n")}
"""
            )
            ExitCode.Failure
          }

        if(code == ExitCode.Success){
          // write version and when last compilation started so we can trigger
          // recompile if cbt version changed or newer source files are seen
          write(statusFile, "")//cbtVersion.getBytes)
          Files.setLastModifiedTime(statusFile.toPath, FileTime.fromMillis(start) )
        } else {
          System.exit(code.integer) // FIXME: let's find a better solution for error handling. Maybe a monad after all.
        }
        Some( start )
      } else {
        Some( lastCompiled )
      }
    }
  }
}