ogatatsu
8/27/2011 - 11:58 AM

Rhinoを利用したcoffeescriptコンパイラ

Rhinoを利用したcoffeescriptコンパイラ


import java.io._
import java.net._
import org.mozilla.javascript._

class CoffeeScript private(reader: Reader) {
  
  private val _compile = {
    val cx = Context.enter()
    //generated bytecode for method exceeds 64K limit.回避
    cx.setOptimizationLevel(-1)
    val global = cx.initStandardObjects()
    cx.evaluateReader(global, reader, "coffee-script.js", 1, null)
    val f = cx.compileFunction(global, "function(source, bare) { return CoffeeScript.compile(source, {bare: bare}) }", "_compile", 1, null)
    (source: String, bare: java.lang.Boolean) => f.call(cx, global, null, Array[AnyRef](source, bare)).asInstanceOf[String]
  }
  
  def compile(source: String, bare: Boolean = false): Either[String, String] = {
    try {
      Right(_compile(source, bare))
    } catch {
      case ex: JavaScriptException => Left(ex.getValue().toString())
    }
  }
}


object CoffeeScript {
  
  def using[A, B <: {def close(): Unit}](closeable: B)(f: B => A): A =
    try { f(closeable) } finally { closeable.close() }
  
  def fromFile(file: String): Either[Exception,CoffeeScript] = {
    try {
      using(new FileReader(file)) { reader =>
        Right(new CoffeeScript(reader))
      }
    }
    catch {
      case ex: Exception => Left(ex)
    }
  }
  
  def fromWeb(): Either[Exception,CoffeeScript] = {
    try {
      val url = new URL("""http://jashkenas.github.com/coffee-script/extras/coffee-script.js""")
      using(new InputStreamReader(url.openStream())) { reader =>
        Right(new CoffeeScript(reader))
      }
    }
    catch {
      case ex: Exception => Left(ex)
    }
  }
}