大島さんの記事 http://d.hatena.ne.jp/squeaker/20061031#p2 を読みながら、pepsi & coke の勉強をしています。

環境の準備 idst-5.7 に付属する jolt を使って勉強します。必要なファイルは http://piumarta.com/pepsi/ にあります。ここでは、ソースとバイナリ両方使います。ソースだけ落としてコンパイルしても勿論大丈夫です。まずバイナリを / 以下にコピーします。windows の場合は cygwin が必要です。ソースで使うのは example/jolt ディレクトリだけなので、それを適当な場所にコピーして make しておきます。以後このディレクトリで作業を行います。なお、linux で使うためには以下を実行する必要があります。 $ execstack -s main

シェルを起動して coke 式を評価 coke の実装である jolt のシェルを起動して式を入力すると答えが返ります。基本的な計算のテストをします。ここではカーソルキー等、一般的な readline のキー操作が使えます。終了するには ctrl + D です。 $ ./main.exe boot.k - .(+ 3 4) => 7 .(+ 3 (* 2 3)) => 9 coke では lisp のような形式 (関数名 引数 ...) でリストを評価します。引数を全て評価してから関数が呼ばれます。すると => の後に答えが表示されます。大島さんのテキストでは、ここから [] を使ったメッセージ送信について解説がありますが、難しいのでもう少し () だけを使った実験をします。関数定義の define を実験してみます。scheme とよく似ています。 .(define plus (lambda (a b) (+ a b))) => 10797800 .(plus 3 4) => 7 .(define fib (lambda (n) . (if (== n 0) 1 . (if (== n 1) 1 . (+ (fib (- n 1)) (fib (- n 2))))))) => 10823464 .(fib 10) => 89 関数定義の時にも数字が出てきて鬱陶しいですが、これは関数のアドレスです。アドレスで直接呼び出しても同じです。 .(define minus (lambda (a b) (- a b))) => 10857176 .(10857176 100 10) => 90 という事は結局 coke のプログラムは整数を括弧で包んだ物と言えます。

C の関数を呼ぶ boot.k を見ると、printf が定義されています。 .(printf "hello world

") hello world => 12 .(printf "3 + 4 = %i

" (+ 3 4)) 3 + 4 = 7 => 10 (_dlsym _RTLD_DEFAULT 関数名) で任意の C の関数を coke の関数に出来るようです。芸が無いですが、putc を定義してみます。 .(define puts (_dlsym _RTLD_DEFAULT "puts")) => -519487552 .(puts "hage") hage => 10

メッセージ送信 book.k では、C の関数以外に pepsi の StdOut オブジェクトもインポートしています。pepsi とは、coke の為に用意された別の言語です。ややこしいですが、coke のソースは pepsi で書かれています。インポートされた StdOut オブジェクトを使うには send 関数を使います。send 関数を使うと、(send メッセージ オブジェクト 引数 ...) の形で pepsi オブジェクトにメッセージを送信出来ます。??? なんだこれは??? boot.k を見ると、StdOut がオブジェクトとして定義されているのでこれを使ってみます。test.k がにサンプルがあります。 .(send 'nextPutAll: StdOut '"hello world

") hello world => 25 ' をつける奴とつけない奴に注意が必要です。StdOut 以外には ' を付ける必要があります。 を使うとこの send 式をもう少し読みやすく表現する事が出来ます。 式では、要素の順番が変わってメッセージの ' を省略します。引数の ' は省略出来ないので注意が必要です。 .[StdOut nextPutAll: '"hello world

"] hello world => 25 ここで ' についてもうちょっと調べます。なにも付けない 3 は機械語の世界の 3 ですが、' を付けると pepsi オブジェクトになります。pepsi オブジェクトの整数の内部表現は、Squeak VM に習って 数字 * 2 + 1 になっているので coke シェルは 7 と答えます。 .3 => 3 .(quote 3) => 7 .'3 => 7 .[StdOut nextPutAll: ['3 printString]] 3 => 3 StdOut も printf と同じく define 文で定義された物ですが、C の関数ではなく pepsi のオブジェクトです。両者の定義方法を比較してみます。 (define printf (_dlsym _RTLD_DEFAULT "printf")) C の関数

(define StdOut (import "StdOut")) pepsi のオブジェクト



coke (jolt) と pepsi (idc) と C 言語の関係 ややこしいですが、依存関係は次のようになっています。 pepsi 処理系 (idc) は Smalltalk に似た言語で、pepsi 自体によって書かれています。

pepsi (idc) をコンパイルするには C 言語を一旦経由するため、C コンパイラが必要です。

coke (jolt) は scheme に似た言語で、pepsi によって書かれています。coke はインタプリタなので C コンパイラは不要ですが、C プログラム並みに早く動作します。

大島さんに聞いた話では、coke によって pepsi を実装しなおすのがとりあえず目標だそうです。