S式で書くOCaml

~ S式は神が作った、その他の文法は人間が勝手に作った ~

更新履歴:


S式でOCamlを書けたらLispマクロでメタプログラミングできたりして良さそうだな
という所が出発点でありゴールです。
(一応S式でOCamlを書こうという試みは過去にもあったようですが、マクロまで踏み込んではいなかったようです)

実行にはOCaml処理系と、Scheme処理系Gaucheが必要です。
OCaml website
Gauche website

以下が変換スクリプト本体、マクロサンプル集です。
s_exp_ocaml.scm (変換スクリプト)
common.scm (共通ライブラリ、これ自体がマクロのサンプルも兼ねてます)
src.scm (単純な例)
使い方は単純で変換スクリプト「s_exp_ocaml.scm」に引数としてソースのファイルを与えると
標準出力に変換されたOCamlのコードを出力します。
(変換スクリプトの実行にはGaucheが必要です)
gosh s_exp_ocaml.scm src.scm > result.ml
ocamlc result.ml



もっともらしい概要のようなもの

基本的にLisp(Scheme)を目指しているわけではなく、 単純にOCamlのコードをS式に落とし込むことを中間目標とします。
これによりLispマクロを導入するにあたって最大の障壁である文法の問題を解決します。
そしてOCamlの機能を基礎として、最終目標はそこからの拡張を目指します。
(OCamlに無い機能は言語コアには組み込まず、原則としてマクロで拡張する方針です)

以下が組み込みとして持つOCamlの機能、特徴(の一部)
この辺はOCamlの機能に丸投げです、OCamlは素晴らしい。

以下が組み込みとして持つOCamlに無い機能


以下が組み込みではなくマクロで拡張された機能、マクロのサンプルも兼ねています
(以下のマクロは全てcommon.scmで定義されている)


各種機能に関する情報等


REPLを起動してみる

REPLはS式OCamlの入力を受け付け、OCamlコードに変換するフロントエンドと
変換されたOCamlコードを受け取って結果を返すバックエンドのocaml toplevelで
構成されます。

以下のコマンドで起動します
#rlwrap gosh s_exp_ocaml.scm
rlwrapは必須ではありませんが、あった方が便利です。
***   S-expression OCaml version 0.20130406
***   OCaml version 4.00.1

#
REPLが起動したら、入力待ちの状態になります。
式を入力してみましょう。
#   (* 4 -5)
((4) * (-5));;

- : int = -20
「(* 4 -5)」と入力したところ、「((4) * (-5));;」へと変換され、
バックエンドのOCamlインタプリタに渡されます。
そして「- : int = -20」というのがOCamlが評価した結果となります。

リストは「'(exp1 exp2 ...)」或いは「(list exp1 exp2 ...)」です。
(詳細は「基本的なデータ、文法等」)
# '(1 2 3 4 5)
([(1);(2);(3);(4);(5)]);;

- : int list = [1; 2; 3; 4; 5]
「Ctrl + D」か、或いは「(exit 0)」でREPLを終了します。
もう少しREPLについて補足


図形描画を行うサンプル

結果はGDを利用してファイルに出力されます(png形式)
GDインターフェースにはgd4oを利用しています。
同じディレクトリに「gd.cma」「dllocamlgd.so」がある場合は以下のようにコンパイル、及び実行を行います。
gosh s_exp_ocaml.scm draw3.scm > result.ml
ocamlc -dllpath . gd.cma result.ml
./a.out

draw1.scm コード
draw1.scm 実行結果
単純な四角形を出力するだけです

draw2.scm コード
draw2.scm 実行結果
シェルピンスキーのギャスケットを出力します

draw3.scm コード
draw3.scm 実行結果
波紋のような図形を出力します

draw4.scm コード
draw4.scm 実行結果
ドット絵を出力します