っで、GaucheのCiSEを眺めていたらすごく抽象化されていて美しいコードだなぁと。たぶんそのまま移植できるんだろうけど、それやったら面白くない上に結局理解してないから自分で拡張できない。ということでコードの分析。
基本的にほしい機能の部分としては、gauche.cgen.cise、gauche.cgen.stubの2つ。っでこれらが大きく依存しているのが、gauche.cgen.unit(以下ユニット)、gauche.cgen.literal(以下リテラル)。ツール的になのかフックなのかはまだ見てないけどgauche.cgen.typeがstubファイル内での<object>形式の記述をCに変換している。
ユニットではCのプリプロセッサと生のコードを扱う。生のコードがどう書かれるのかは知らない。それぞれを扱うクラスがあって、それぞれをどう出力するかの総称関数がある。
リテラルはSchemeのリテラルをCに変換するモジュール。リストとか文字列の変換。リテラルクラスが上記のユニットを継承して定義される。
CiSE内では基本的な変換部分しか定義されず、その他のモジュールでGauche固有の定義が入る。ただ、そうは言ってもCiSE内で定義されている構文にはScmObjとか入ってくる(let*とかfor-eachとか)
また、CiSEは環境を保持していて、トップレベル、ステートメント、式の3つがある。たとえばdefine-cfnはトップレベルでしか定義できないし、beginは全部いけるんだけどそれぞれ出力されるCのコードが違う。
とりあえずここまで踏まえて、まずどこまでやるかを考える。
- 特に純粋なCファイルを出力する必要はない
- 現状のStubファイルとVMインストラクションの手直しはがっつりやってもOK
- SchemeファイルをCにする必要はない(gauche.cgen.precompモジュール相当はいらない)
- ノード毎のクラスは取り入れたい
- 環境+render部分を移植(だめじゃん)
- 純粋なCiSE部分、Sagittarius固有定義というようにする
+--------------+ +-------------+ | CiSE | ----- | Unit | +--------------+ +-------------+ | | +--------------+ +-------------+ | Syntax | | Literal | +--------------+ +-------------+ | | +--------------+ | | Stub | -------------+ +--------------+CiSEではSagittariusに依存しない構文までサポート。letでは総称関数を作ってデフォルト型の定義を下位のライブラリで行うようにする。デフォルトの振る舞いはエラーでいい気がする。
SyntaxではSagittariusに依存する構文を入れる(for-eachとか)。
Stubは単なるエントリーポイントになるか、それとももう少し何か入れるかは考えてない。