

アラン・ケイが Smalltalk（Squeak）を卒業して次を目指すための秘密兵器と目される“黄金の箱”あるいは「イアンのやつ」 と呼ばれている Pepsi & Coke 。地球の重力（暫定ダイナブック＝ Smalltalk ）に魂を縛られた「オールドタイプ」な私には明らかに新たな「脅威」(^_^;)なわけですが、こいつがどの程度動くものなのか、はたして本当に Smalltalk（や LISP）を凌駕する「ニュータイプ」なのかも興味があるところなので、ちょっとだけいじってみました。

とは申しましても、「オールドタイプ」である以前に、私は言語処理系内部や仕組みことがよくわからないので（ぉぃぉぃ…）、サンプルに見つけて面白そうだなーと感じた Python や JavaScript もどきのコードを比較的高速に走らせるってのをチョしてみただけです（実質はたらいまわし大会？ｗ）。けっきょく“コイツ”がかろうじて“動くぞ…”ってことは分かったのですが、どの程度「ニュータイプ」であるかどうかについては、まだ実感できていません（それって、LISP のマクロや Smalltalk で SmaCC 使うのとどう違うの？…状態）。なので、もっとちゃんと知りたい人は、id:squeaker さんや id:propella さん、id:nqthm さんもこの「イアンのやつ」がらみの記事をエントリーされているので、とっかかりにはそちらのほうからどうぞ。







念のため、Pepsi & Coke のメーリングリストにおける Ian Piumarta 氏（名字の発音がワカンネ〜）の投稿によれば、

Id …… オブジェクトモデル。

idst …… Id なオブジェクトをハンドリングするための Smalltalk ライクな文法の言語。

idc …… idst のコンパイラ。idst 自身で記述されている。

Pepsi …… idc の別名。

Jolt …… idst で記述された AST（abstract syntax tree、抽象構文木）コンパイラ。コード生成や動的パースの実験用。

Coke …… Jolt 上に構築された、idst のメッセージ式（Smalltalk)と AST のＳ式（LISP）を混在させられるスクリプト言語処理系。言語処理系の“すべて”をコントロール可能!?

とのことですが、私にはさっぱり…。ｗ 例によってよく分からない例えをすれば、SELF のようにシンプルなオブジェクトモデルをベースに、CLOS MOP（あるいは Smalltalk）がごとく自己記述された、しかしそれらとは違って、エンドユーザーがアドホックにオブジェクトモデルの拡張、言語の文法やセマンティックスを改変することが可能であるような“開かれた”オブジェクトシステムによって構成される処理系を実現した…といったかんじでしょうか。







▼Coke のインストール Coke のビルドには idc が必要です。idc については、各種環境用のバイナリ配布も行なわれているようですが、私はソースを make しました。 idst-5.7-20061002.tar.gz を入手して展開 idst-5.7 に移動して make; sudo make install 。環境別設定について、くわしくは INSTALL を参照のこと。 examples/jolt に移動して make 。

▼Coke の起動と終了 example/jolt から移動していなければ、./main で対話環境が起動します。プロンプトは「.」（ドット）です。 $ ./main Welcome to Jolt 0.1 [VPU 4.0.1 ppc darwin 2004-05-03 14:46:24] .(+ 3 4) => 7

Objective-C のように [ ] で括ってメッセージ式（Smalltalk 式）を書くことができますが。いろいろと便利な関数を使ったりオブジェクトを参照するのには起動時に boot.k を読み込んでおくほうがよいようです（boot.k の中味を読むと、何が追加されるのか分かります）。boot.k の他にも読み込ませたい（評価したいコードを含む）ファイルがあれば、そのファイル名も続けて書きます。なお、ファイル群（boot.k だけの場合も含む）を評価したあと終了せずに対話環境にとどまりたい場合には最後に「-」を付ける必要があります。 $ ./main boot.k - Welcome to Jolt 0.1 [VPU 4.0.1 ppc darwin 2004-05-03 14:46:24] ; loading: 'boot.k ; loading: 'quasiquote.k ; loading: 'syntax.k ; loading: 'object.k .(printf "Hello, World!

") Hello, World! => 14 .[StdOut nextPutAll: '"Hello, World!

"] Hello, World! => 29

終了は boot.k を読み込んでいれば、(exit) が使えますが、そうでなければ ctrl-D で。









▼Coke で Python もどき exampes/jolt/python に test.py というフィボナッチ数列を使ったサンプルがあります。make; make run か、いったん make したあとは、「../main boot.k monty.k meta-repl.k monty.mk test.py」で起動可能です。 $ make run ../main boot.k monty.k meta-repl.k monty.mk test.py ; loading: 'boot.k ; loading: 'quasiquote.k ; loading: 'match.k ; loading: 'sugar.k ; loading: 'syntax.k ; loading: 'object.k ; loading: 'meta.k ; loading: 'meta-coke.k ; loading: 'meta-meta.k ; loading: 'CheckpointStream.k Parsing and compiling Monty compiler... done. Entering Monty read-eval-print loop. nfibs( 0 ) = 1 took 0 ms nfibs( 1 ) = 1 took 0 ms nfibs( 2 ) = 3 took 0 ms nfibs( 3 ) = 5 took 0 ms <snip> nfibs( 25 ) = 242785 took 109 ms nfibs( 26 ) = 392835 took 170 ms nfibs( 27 ) = 635621 took 280 ms nfibs( 28 ) = 1028457 took 449 ms nfibs( 29 ) = 1664079 took 730 ms nfibs( 30 ) = 2692537 took 1169 ms

test.py は Python でも実行できます。 $ python test.py nfibs( 0 ) = 1 took 0 ms nfibs( 1 ) = 1 took 0 ms nfibs( 2 ) = 3 took 0 ms nfibs( 3 ) = 5 took 0 ms nfibs( 4 ) = 9 took 0 ms nfibs( 5 ) = 15 took 0 ms <snip> nfibs( 25 ) = 242785 took 364 ms nfibs( 26 ) = 392835 took 615 ms nfibs( 27 ) = 635621 took 973 ms nfibs( 28 ) = 1028457 took 1511 ms nfibs( 29 ) = 1664079 took 2470 ms nfibs( 30 ) = 2692537 took 4467 ms

test.py の代わりに - で対話環境にとどまれば（プロンプトは「:」）、任意の Python コードをインタラクティブに評価できます。っても、関数定義とその実行以外、肝心なことはクラス定義も配列もぜんぜんダメみたいです（いちおうそれぞれに対応する文法の定義っぽいのは monty.mk に書いてあるらしいのですが…）。 $ ../main boot.k monty.k meta-repl.k monty.mk - Welcome to Jolt 0.1 [VPU 4.0.1 ppc darwin 2004-05-03 14:46:24] ; loading: 'boot.k ; loading: 'quasiquote.k ; loading: 'match.k ; loading: 'sugar.k ; loading: 'syntax.k ; loading: 'object.k ; loading: 'meta.k ; loading: 'meta-coke.k ; loading: 'meta-meta.k ; loading: 'CheckpointStream.k Parsing and compiling Monty compiler... done. Entering Monty read-eval-print loop. :class Foo: : pass : syntax error: () Abort trap Entering Monty read-eval-print loop. :[1,2,3] undefined: MontyList Abort trap

ここいらへんの不都合をふまえて、Coke でも Python でも動く、たらい回し関数（Tak y）を taky.py として書いてみました。 from time import time def taky (x, y, z): if x<=y: return y else : return taky(taky(x- 1 , y, z), taky(y- 1 , z, x), taky(z- 1 , x, y)) x = 12 ; y = 6 ; z = 0 ; t1 = time() ans = taky(x, y, z) t2 = time() print "tarai(" , x, "," , y, "," , z, ") =" , ans, "took" , int ((t2 - t1) * 1000 ), "ms"

結果はこんな感じ。 $ python taky.py tarai( 12 , 6 , 0 ) = 12 took 17886 ms $ ../main boot.k monty.k meta-repl.k monty.mk taky.py ; loading: 'boot.k ; loading: 'quasiquote.k ; loading: 'match.k ; loading: 'sugar.k ; loading: 'syntax.k ; loading: 'object.k ; loading: 'meta.k ; loading: 'meta-coke.k ; loading: 'meta-meta.k ; loading: 'CheckpointStream.k Parsing and compiling Monty compiler... done. Entering Monty read-eval-print loop. tarai( 12 , 6 , 0 ) = 12 took 7359 ms

▼ Coke で JavaScript もどき examples/jolt/javascript に移動してから make run すれば、Python もどきと同様のフィボナッチ数列を用いたベンチが走ります。 $ cd ../javascript $ make run ../main boot.k meta-repl.k js.mk test.js ; loading: 'boot.k ; loading: 'quasiquote.k ; loading: 'syntax.k ; loading: 'object.k ; loading: 'meta.k ; loading: 'meta-coke.k ; loading: 'meta-meta.k ; loading: 'CheckpointStream.k Parsing and compiling JavaScript compiler... done. Entering JavaScript read-eval-print loop. nfibs(0) = 1 took 0 ms nfibs(1) = 1 took 0 ms nfibs(2) = 3 took 0 ms nfibs(3) = 5 took 0 ms nfibs(4) = 9 took 0 ms nfibs(5) = 15 took 0 ms <snip> nfibs(25) = 242785 took 110 ms nfibs(26) = 392835 took 170 ms nfibs(27) = 635621 took 280 ms nfibs(28) = 1028457 took 440 ms nfibs(29) = 1664079 took 730 ms

前後をタグで括った test.html を WWW ブラウザで開けば、ちゃんとした JavaScript での結果も得られます。 nfibs(0) = 1 took 0 ms nfibs(1) = 1 took 0 ms nfibs(2) = 3 took 0 ms nfibs(3) = 5 took 0 ms nfibs(4) = 9 took 0 ms nfibs(5) = 15 took 0 ms <snip> nfibs(25) = 242785 took 380 ms nfibs(26) = 392835 took 633 ms nfibs(27) = 635621 took 1048 ms nfibs(28) = 1028457 took 1643 ms nfibs(29) = 1664079 took 2681 ms

Python と同じく、たらいまわし関数も定義してみました。Coke の JavaScript もどきでは、Date.getTime() が使えないので、一部、妙なことをやっていますがあしからず。 function taky(x, y, z) { if (x <= y) return y; else return taky(taky(x-1, y, z), taky(y-1, z, x), taky(z-1, x, y)); } var x = 12, y = 6, z = 0; var d = new Date (), t0 = d.getSeconds() * 1000 + d.getMilliseconds(); var ans = taky(x, y, z); var d = new Date (), t1 = d.getSeconds() * 1000 + d.getMilliseconds(); var delta = (60000 + t1 - t0); if (delta > 60000) { delta = delta - 60000; } document .write( "tarai( " + x + " , " + y + " , " + z + " ) = " + ans + " took " + delta + " ms

" ); $ ../main boot.k meta-repl.k js.mk taky.js ; loading: 'boot.k ; loading: 'quasiquote.k ; loading: 'syntax.k ; loading: 'object.k ; loading: 'meta.k ; loading: 'meta-coke.k ; loading: 'meta-meta.k ; loading: 'CheckpointStream.k Parsing and compiling JavaScript compiler... done. Entering JavaScript read-eval-print loop. tarai( 12 , 6 , 0 ) = 12 took 7100 ms

これは手元の環境では遅すぎて WWW ブラウザではダメなので、document.write を print に書き換えたものを SpiderMonkey (JavaScript-C) に喰わせた結果を次に。 $ js -v JavaScript-C 1.5 2004-09-24 $ js taky.print.js tarai( 12 , 6 , 0 ) = 12 took 41970 ms