多相型をサポートしました ー OCamlをC言語に変換するプログラム ー

OCamlC言語に変換するプログラム(今のところ、uCamlって名前にしてます)に機能追加しました。多相型のサポートです。

https://github.com/masateruk/micro-caml

これにより、以下のようなOCamlのプログラムをCのプログラムに変換できます。

let rec id x = x in
let n = if (id true) then (id 1) else (id 0) in
  print_int n

多相型のサポートによる恩恵は、上記プログラムにある id という関数です。これは引数 x をそのまま返すなんてことない関数ですが、注目してほしいのはその型です。型を調べるためにOCamlのインタプリンタに入力してみましょう。

$ ocaml
        Objective Caml version 3.12.0

# let rec id x = x;;
val id : 'a -> 'a = <fun>

val id : 'a -> 'a = と出ました。これは、id はある a という型を引数にとり、その型 a を結果として返す関数型である、ということを示しています。ここで a は型変数と呼ばれるもので、どんな型もとることができます。たとえば、int 型の引数を適応する場合は int -> int という型になり、bool型の引数を適応する場合は bool -> bool という型になります。インタプリンタで試してみましょう。

# id 0;;
- : int = 0
# id true;;
- : bool = true

こういった関数をC言語で実現するのは簡単ではありません。たいてい型の制約をさけるために void* を利用しますが、これだと引数を関数に適応する場合にキャストする必要があります。キャストした場合はコンパイラの型検査の恩恵をあずかることができません。たとえば、int 型の引数を適応した結果をbool 型の変数に代入するようなコードがあってもキャストしている場合はコンパイラはエラーを報告してくれません。しかし、OCaml(だけでなく一般的な関数型言語)ならば、こういった型エラーをコンパイル時に報告してくれます。uCamlでもOCamlと同様の型検査を行います。型検査を通ったものがC言語に変換されるため、生成されたC言語のプログラムには型エラーはありません。

一番上にあげたプログラムは以下の手順で C へ変換、コンパイル、実行できます。

$ ./ucaml id.ml -o id.c
$ gcc -Wall id.c -o id -I/usr/local/include -I. -lgc -L/usr/local/lib
$ ./id
1

ひとつだけ注意点があります。今回は、メモリ管理の部分をさぼって Boehm GC (http://www.hpl.hp.com/personal/Hans_Boehm/gc/) を使うようにしました。よって、生成した C のプログラムをビルドおよび実行するときには Boehm GC が必要になります。個人的には自分でメモリ管理するよりもこういった GC を利用した方がいいと思っているのですが、一応 Boehm GC に依存しないものも出力できるようにするつもりです。