OCamlをC言語に変換するプログラムをつくりました

MinCamlをベースにしてOCamlC言語に変換するプログラムをつくりました。

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

何でそんなものをつくったかと言うと、わたしは組み込みプログラムの開発を仕事にしているのですが、

  • 自分はOCamlで開発したい(C言語の型検査は心もとない。OCamlの強力な型検査に守られてコードを書きたい)
  • しかし、OCamlで書くと誰も引き継げないため、使わせてもらえない。

ということで、自分が書くときはOCamlで書いて、納品するときにCに変換すればいいんじゃないかと思った次第です。OCamlを書ける人がいるんだったらOCamlのコードを引き継いでもらえばいいけど、Cしかわかりませんな人には変換後のCのコードを渡すという作戦です。もちろん、変換後のCのコードを直接変更しちゃうとOCamlのコードは役に立たなくなるんですけど、それはしょうがないとします。

サポートしている構文要素はMinCamlよりもさらに少なく、基本型はInt型のみ。破壊的代入もありません。しかしクロージャはサポートしたので、以下のようなプログラム

let rec plus x =
  let rec add y = x + y in
    add in
  print_int ((plus 1) 2)

は次のようなCのプログラムに変換します。

#include <stdio.h>
#include <stdbool.h>

int _add_11_(int y_12_, int x_6_)
{
  return x_6_ + y_12_;
}

typedef struct {
  int (*f)(int, int);
  int fv1;
} c_13_t;

c_13_t make_c_13_t(int (*f)(int, int), int fv1)
{
  c_13_t tmp_r14;

  tmp_r14.f = f;
  tmp_r14.fv1 = fv1;
  return tmp_r14;
}

c_13_t plus_5_(int x_6_)
{
  c_13_t add_11_;

  add_11_ = make_c_13_t(_add_11_, x_6_);
  return add_11_;
}

int apply_c_13_t(c_13_t tmp_r15, int tmp_i16)
{
  return tmp_r15.f(tmp_i16, tmp_r15.fv1);
}

int main()
{
  int tmp_i1_10_;
  c_13_t tmp_f2_8_;
  int tmp_i3_9_;
  int tmp_i4_7_;

  tmp_i1_10_ = 1;
  tmp_f2_8_ = plus_5_(tmp_i1_10_);
  tmp_i3_9_ = 2;
  tmp_i4_7_ = apply_c_13_t(tmp_f2_8_, tmp_i3_9_);
  printf("%d", tmp_i4_7_);
  return 0;
}

テンポラリーな変数が多いのは、おそらくK正規化のためだと思います。変換先の言語がCなので、K正規化を適当にサボればもう少し読みやすいコードが出力できるようになるかと思います。

まだまだ機能が足りないのですぐに実用できるレベルではありませんが、入出力やリソース管理を除いたロジックを取り出して、その部分をささっとつくっちゃうようなことができないかと期待してます。

今後、他の言語要素もサポートしたいのですが、単純にOCamlの言語要素をサポートするのではなくモデリングやプロトタイプ時に役に立つような機能をたそうかなと考えているところです。
ねらいは、OCamlモデリング(プロトタイプや検証など)してからC言語を生成です。