Objective Caml を使って300行で書いたインタプリタについての記事を研究用ブログにのせました。
現在、カテゴリ「research」の投稿記事を表示中です。
今月の PTTは早稲田大学で開催されるそうです。タイトルを見たときは「数値計算か。。。」と参加しないつもりだったのですが、発表概要によれば数値計算に制約プログラミングを応用したということなので行ってみる気になりました。参加自由+無料です。
制約プログラミングについてはどなたも聞いたこともないと思います。(こんなおかしなことを言い出した背景は、ぎょんさんのコメントへの返事をご参照下さい)ぼくらが日頃親しむプログラムは、命令を次々に発するスタイルですけれども、制約プログラミングはパラメター空間に対して制約を与えておくことで、プログラム実行が不適切な道を歩まないように宣言します。敢て例えるなら、鞭をあてる命令型に対して真綿で首を締める制約型となりますでそうか。まるで考え方の異なるプログラミングパラダイムです。応用例としては、図形描画システム、ウィンドウシステム、制御システム、さまざまな人工知能システムなどがあります。
AppleScript を知ってますよね?Mac OS に昔からあるスクリプト言語で、複数のアプリケーションにまたがるスクリプトが書けます。残念ながら、ぼくには AppleScript リテラシが書けています。もしかして、JavaScript で同様なことができるのではないんだろうか?Mac OS X ユーザを何年も続けて今ごろになって探し始めたらヒットしました。JavaScript OSA です。設定にちょっとしたコツがあったので紹介します。
Google Chrome を二回しか起動したことがない私が言うのは全くおこがましいことなんですけれども、それを承知で書いています。
昨日の今ホットなJavaScriptエンジン全部インストールしましょうのムードを引き摺りつつ、ひょっとして Firefox や Chrome の JavaScript エンジンも SquirrelFish のようにどこかに落ちているんじゃないだろうかと思って探しています。Chrome の場合は、ウェブブラウザ本体とリンクされていることが分りました。*1
で、VM の捜索活動をしているうちに Google Chrome のインスペクタのソースが見つかったという話です。大部分は JavaScript が書かれていて、それが見つかったというだけなのでたいした話ではないんですけど。。。
とりあえず、あなたが Google Chrome をインストールした Mac を使っているのなら、適当なディレクトリを作成して、その中で以下のスクリプトを実行してみて下さい。
#!/bin/sh
/usr/bin/split -p '^/\* .*js \*/' '/Applications/Google Chrome.app/Contents/Versions/4.0.249.49/Google Chrome Framework.framework/Resources/inspector/devtools.js'
for f in x??
do
fname=`/usr/bin/head -1 $f | /usr/bin/sed -e 's/[/* ]//g'`
echo "$fname"
/bin/cp $f $fname
/bin/rm $f
done
echo '' > 0_Manifest.txt
echo >> 0_Manifest.txt
wc -l *.js | sort -n >> 0_Manifest.txt
echo >> 0_Manifest.txt
ls *.js >> 0_Manifest.txt
スクリプトを実行すると以下のようにどっさりとファイルが作成されます。
0_Convert.sh Resource.js 0_Manifest.txt ResourceCategory.js AbstractTimelinePanel.js ResourceView.js BottomUpProfileDataGridTree.js ResourcesPanel.js Breakpoint.js ScopeChainSidebarPane.js BreakpointsSidebarPane.js Script.js CallStackSidebarPane.js ScriptView.js Callback.js ScriptsPanel.js ChangesView.js SidebarPane.js Color.js SidebarTreeElement.js ...
これは、Google Chrome の inspector/devtools.js という cat されたファイルを分割して元に戻しただけです。Google の腕こきの JavaScript ハッカーが書いたコードですから、読めば JavaScript の腕があがるのは間違いなし!
もとの devtools.js は 3万6千行もあってゲンナリするんですけれども、こうして分割すると元気が出ますよね。
Safari に組込まれているJavaScriptエンジンの SquirrelFish ですが、今朝、一時間ほどもかけてビルドしたんですけれども、Mac OS X の標準ライブラリのなかを探ったら見つかりました。以下の場所にあります。
/System/Library/Frameworks/JavaScriptCore.framework/Resources/jsc
使い方は jsc -h でわかります。
「な〜んだ」な一日になりました。まあ、よい経験になったと見るか。*2
JavaScript エンジンを揃えたので、ついでにまとめページを作っておきます。ことだけどもね。
- V8
- Rhino: Mozilla のサイトへのリンク
- SpiderMonkey: MacPorts で sudo port install spidermonkey しただけ
- TraceMonkey
- SquirrelFish
(2/9 21:56 追記)実は Mac OS X に標準インストールされていることを知りました。二番目のコメントを読んで下さい。
ようやくSquirrelFishのビルドもできました。こちらは WebKit 全体のダウンロードとビルドを行ってしまったためにやたらに時間がかかってしまったのだけれども、SquirrelFish だけならもっと短時間でできた気がします。
道具が揃っていれば以下をやるだけです。
svn checkout http://svn.webkit.org/repository/webkit/trunk WebKit WebKitTools/Scripts/build-jsc --debug
普通ならば WebKit/JavaScriptCore/build/Debug/jsc とかにできるのではないかと思います。*1
あと、jsc の隣りにできる JavaScriptCore.framework は ~/Library/Frameworks/ にでもいれるんでしょうか。よくわかってませんけれど、ひとまずそうしておきました。
ちなみに SquirrelFish は基本的にはこっちのタイプでした。
$ js prog1.js prog2.js ...
でも – の後に引数を与えることもできるようです。
$ js prog1.js prog2.js -- arg1 arg2 ...
現在、WebKit をビルド中です。この作業が完了すれば以下の5つのJavaScriptエンジンが手にはいったことになります。
- Google V8
- Mozilla Rhino
- Mozilla SpiderMonkey
- Mozilla TraceMonkey
- WebKit SquirrelFish
このうち、スクリプティングに対応しているのは SpiderMonkey と TraceMonkey で、これらは以下のように起動できます。
$ js program.js arg1 arg2 ...
一方、残りの V8 と Rhino はコマンド行引数を受け取らずに、複数のファイルが書けるようになっています。
$ js prog1.js prog2.js ...
これらをターゲットにテストケースを書こうと思っていたのだけれども、幸いどの処理系も -e オプションをサポートしているので、以下でいこうかと思っています。
$ js -e 'load("prog1,js", "prog2.js", ...);'
それとも、こっちの方が簡単か。
$ js -e 'load("prog1.js;prog2.js;...".split(";"));'
今朝、見つけたブログ記事(http://ptspts.blogspot.com/2009/10/how-to-compile-tracemonkey-for-linux.html)にしたがって、無事に TraceMonkey のビルドできたのでご報告します。
$ sudo port install autoconf213 mercurial $ hg clone http://hg.mozilla.org/tracemonkey/ $ cd tracemonkey/js/src $ autoconf213 $ ./configure $ make
shell/js が TraceMonkey です。
一箇所、はまったのは autoconf のバージョンです。Mac OS X の開発者パッケージに含まれるのは古すぎるようです。autoconf213 を使って下さい。実行すると undefined macros: などと言われてドキッとしましたが、そのまま configure & make でできちゃいました。あれはなんだったんだろう。
すみません。大嘘を書きました。このプログラムを通さないのは、Spidermonkey だけでした。Rhino と Firefox は大丈夫です。ということで、タイトルからRhino と Firefox を削除しました。ごめんなさい。
以下の短い JavaScript のプログラムを見て下さい。
(function () {
var Array = [];
return function () { return Object; };
})();
何も面白いことをしないプログラムです。真面目に確認していないけれども、たぶん Safari, Chrome では問題ないけれども、Mozilla 系列だと全滅します。真面目に確認したところ、Spidermonkey のみでエラーが再現しました。*1
たとえば、Spidermonkey でこれを実行すると以下のわけのわからないエラーを出力します。
TypeError: Array is not a constructor
で、以下のように変更するとこのエラーは消えます。
- Array という名前の変数を別な無難なもの、たとえば array に変更する。
- 3行目の関数の本体から組込みのオブジェクト名を除去する。たとえば、return Object のかわりに return Array とするのは大丈夫です。以下がエラーが消える例です。
(function () {
var Array = [];
})();
(function () { return Object; })();
ブロックのなかで組込みのオブジェクトと同名の変数を宣言し、そのブロックで別の組込みのオブジェクトを参照しているとエラーになるような気がします。
ちなみに ECMA では、組込みオブジェクトの名前は予約語ではないようです。
あまり詳しくないので自信を持って言えないのだけど、バグだよね?バグ?よく知られた話なんですか?
