低レベルマクロとターゲット環境の非対称性

Schemeの低レベルマクロは、一般のSchemeプログラムでソースコードを組み立てることができる。コレ自体は納得の機能性で、Scheme(や、他のLisp語族)の強みでも有るけど、クロス環境では地味に問題になる。Schemeは他のLisp方言に比べるとクロス開発を熱心に考察している方だと思うけど、このへんの対応はなかなか難しい。
目的を簡潔に設定すると:
今のnmoshのVMコンパイラは、ライブラリキャッシュに2種類のプログラムを格納している。

  1. 実際の手続きコード
  2. マクロ処理コード

この内、後者のマクロ処理コードを生成しないで済む方法を考えたい。クロス開発環境では、

  1. 実際の手続きコード(ターゲットVM用)
  2. マクロ処理コード(ホストVM用)

のようにマクロ処理コードと手続きコードで対象アーキテクチャが異なる。

ターゲット環境の非対称性

(ホストとターゲットの区別を導入する。ホストはWin32やPOSIXのような開発環境やVMコンパイラが動作する環境で、ターゲットは実際のプログラムが動作する環境となる。)
例えば、多くのR6RSプログラムは(rnrs)としてR6RSの語彙を纏めてimportしているが、R6RSのフルセットはマイコンに乗らない(unicodeサポートだけでかなりのROMを要求する)。このため、Sufficientなサブセットを用意する必要がある。このため、ホストとターゲットで独立した実装を用意する必要がある。
nmoshはexplicit phasingを採用しているので、原理的にはマクロ展開フェーズにホストSchemeをimportし、実行フェーズにターゲットSchemeをimportすることで一応分割を実現できる。
しかし、explicit phasingは(標準化された)良い記法が無い - これはあくまでマクロ展開のフェーズを分割する手法なので、meta level 0以前と以降を一括して指示できるScheme実装は世間に存在しない(AFAIK)。

低レベルマクロを使用する動機

比較して、syntax-rulesにはこの問題は無い - syntax-rulesは、SchemeシンボルをScheme手続きによって挿入する方法を用意していないので、ユーザが提供する手続きによってマクロの挙動を変える方法もない。
ユーザがマクロ中でScheme手続きを実行したくなるのにはいくつかの理由がある。

  • パタン言語よりも簡潔に書ける。多くのケースで、syntax-rulesで記述できるマクロでも、低レベルマクロの方が簡単という理由で低レベルマクロが採用されるケースがある。(syntax-rulesは実際にはかなりのことができる cf. OlegのScheme to syntax-rulesコンパイラ: http://okmij.org/ftp/Scheme/macros.html#syntax-rules-compiler )
  • 本質的に必要である。例えばincludeマクロのように、実装のためにScheme手続きを使用しないとどうしようもないクラスが存在する。
    • identifierやデータを生成したい。syntax-rulesは、ソース中に現れないシンボルを挿入できない。

このうち、本質的に必要である動機の一つである、identifierの生成に関して"Non-hygenicマクロプリミティブ"の形で組み込みライブラリとして提供すれば低レベルマクロを使わなければならなくなるシチュエーションを減らせるのではないかと考える。

Non-hygenicマクロプリミティブ

冷静に考えると、そもそもC言語すらマクロ中でidentifierを生成できるので、それと同等のプリミティブを用意するのが好ましい気がする。

  • シンボルの連結。例えば、nmoshの(shoten)ライブラリでは、一旦文字列に戻してからシンボルを生成している。https://github.com/okuoku/mosh/blob/308a610b2cb2cad3d7ebdb25da4647ad1b14b0d5/lib/shorten.ss#L78
  • シンボルの生成。いわゆる(gensym)で、Chezのように高速化のhackを行うこともある。これはsyntax-rulesで書けるが、専用のマクロ(か、clause)を用意する必要がある。
    • symbol→stringやstring→symbolも必要かもしれない。
  • 処理系やソース位置のクエリ。Cで言うところの"__FILE__"等。nmosh以外の処理系でサポートしているものは有るんだろうか。。
  • シンボルのパースと分割。prefixを取り除くなど。不要かも。
  • quote、quasiquote、unquoteのoverride。quote中で生成シンボルを使用したい場合のために、専用のquoteが必要になる。

ソース位置クエリがここに有るのは、この仕組で対応しないと"マクロが定義された位置"がとれてしまうため。