CoffeeScriptのスクリプトを直接実行したい場合、CoffeeScriptのコンパイラを動かしているJavaScript処理系で実行することが大半だ。
現状ではデフォルトのNode.js、Webブラウザ*1、PhantomJS*2、Windows Script Host*3で実行できることは分かっている。しかしRhinoで(それもRhino単体で)実行する為の仕組みは見当たらないようだ。
そこで、思い立って気合と諦めで作ってみた。
RCSI - Rhino CoffeeScript Interpreter
コード的に大したことはしていない、気合一発ネタに近い代物である。機能は非常に限定されている(面倒なので諦めた、ともいう)。
具体的には、CoffeeScriptのスクリプトファイルないし引数に指定したスクリプトの文字列をRhinoで実行する機能しかない。コンパイルしたいならNode.jsで十分だ(なので実装していない)。REPLぐらいは入れたかったけど、面倒なので止めた(花粉症が完治して毎年の悩みから解放されたら、考えなくもない)。
RCSIとは何か?
CoffeeScriptのコードをRhinoで直接実行するインタプリタ。CoffeeScriptのコンパイラではない。
長所
- Mozilla JavaScriptの独自拡張機能が使える。
- Javaの機能も使える。
- 末尾再帰を最適化する。
短所
- 遅い。
- エラーのハンドリングがまずい。
- REPL未実装。
インストール
必要なもの:
- Java Runtime Environment
- js.jar(Rhinoに付属)
- extras/coffee-script.js(CoffeeScriptに付属のブラウザ用?)
使い方
「rcsi -h」のメッセージを参照。
以下、実行例。
C:\tmp>rcsi -e "print i for i in [1..3]" 1 2 3 C:\tmp>rcsi -e "print i for i in arguments" foo bar baz foo bar baz C:\tmp>cat > zzzz.coffee for i in arguments print i C:\tmp>rcsi zzzz.coffee A B C A B C C:\soft\shell>_
ライセンス
zlibライセンス。
Tips
スクリプトはトップレベル直下の無名関数として実行される(はず)。
スクリプト内で他のCoffeeScriptのファイルをインクルードしたい場合に備えて、readCoffeeScriptという関数を用意している。この関数はCoffeeScriptで書かれたスクリプトファイルを読みこみ、コンパイルされたコード(JavaScript)の文字列を返す。
eval readCoffeeScript 'foo.coffee' eval readCoffeeScript 'bar.coffee', charCode
上記のような使い方になるが、実は結構危険である。というのも、CoffeeScriptが生成するコードには自動的に追加された一時変数が含まれているが、この変数の名前が衝突する可能性がある。外部モジュールのロード的な使い方をしたいので、readCoffeeScriptで読み込むコードを無名関数で包み込むようなことはしていないのだ(スクリプト本体をトップレベル直下の無名関数として実行している点に留意すべし)。
本当は「loadCoffeeScript」のような名前のrequireやloadのような関数を追加したかったのだけど、関数の中からその1つ外の関数の内部変数を追加するなんて無理だと思うので、断念した。
動作確認済み環境
TODO
- REPLよりも前に、もうちょっとマシなコマンドオプション解析を実装したい。現状は無茶苦茶適当すぎる。
*1:CoffeeScriptの処理系に付属するextras/coffee-script.jsを使用する。
*2:PhantomJS 1.9.0のソースを見る限り、プログラム内部にリソースとしてextras/coffee-script.jsを抱えていて、Webブラウザのコンテクストでそれを使用しているようだ。ちなみに内部に抱えているCoffeeScriptの処理系のバージョンは1.3.3のようだ。