みずぴー日記

月に行こうという目標があったから、アポロは月に行けた。飛行機を改良した結果、月に行けたわけではない。

compiler-libsによるOCamlコンパイラの改造、もしくはきょんくん結婚祝いLTについて

4月の頭に@さんと@さんの結婚を祝うLT大会 というよく意味が分からないイベントに参加してきました。時間がたってしまいましたが、せっかくなので資料(と補足説明)を公開します。

発表資料

発表テーマ: ハートマーク演算子の追加

LTのテーマは指定されていませんでしたが、さすがに関係ない話をするのは気がとがめたので「♥︎(ハートマーク)を中置演算子として利用できるようにOCamlを改造する」というテーマにしました。ハートマークとか結婚っぽいですよね。

要するに、こんな感じのコードが書けるようにする改造するのが目的です。

f:id:mzp:20140502232450p:plain

これは、(たしか)3年くらい前に@yoyaさんから聞いた「東京のPHPコミュニティには結婚祝にPHPの拡張モジュールを贈る習慣があるんですよ」という話が元ネタなんですが、検索してもソースを見つけれませんでした。

compiler-libsによるコンパイラの改造

今回の改造にはOCaml 4.00で付属するようになったcompiler-libsを利用しました。これはOCamlコンパイラを構成する各モジュールがライブラリとして提供されているもので、お手軽にコンパイラを改造することができます。

詳しい使い方やサンプルはcompiler-libs-hackで解説されています。

従来はOCamlコンパイラソースコードを直接いじってビルドするしか改造版のコンパイラを作る方法はありませんでした。 これが、compiler-libsのおかげで、改造版モジュールと、compiler-libsの提供するモジュールをリンクするだけで改造コンパイラが作れるようになりました。

今回の場合は、パーサ部分をハートマークを認識できるように改造し、それ以外は標準コンパイラのモジュールを使っています。

f:id:mzp:20140502232651p:plain

何人かに聞かれましたが、これはコンパイラに拡張ポイントが用意されているわけではないので、改造する箇所自体は、従来のOCamlコンパイラのコードを直接いじる方法と大差ありません。ただ、ビルドの時間が短縮される上に、配布が圧倒的に楽になりました。

改造メモ

  • コンパイラパイプラインはcompile.mlで定義されている。
  • .mlのパースは Parsing.implementation でやる。
    • ファイルの読み込み等は高階関数であるPparse.fileがやってくれる。
  • レキサーコンパイラパイプラインには登場せず、パースの一部として処理される
  • レキサーの定義はlexer.mllにある。ocamllexが使われている。
  • LexerのINFIXOP4としてハートマークの追加した。
    • INFIXOP4なので(**)と同じ優先度、結合方向を持つ。