[Scheme] Scheme による scheme macro の実装

いくつかの procedure を実装して syntax.pp という file を load すると、sc-expand という procedure が定義されて、こいつに適当な parameter を渡すと展開済みの list が返ってるんだと。
Compiler 型の architecture だとこういうのもいいのかもなぁ。

REF_CAR()

((ScmRef)&((SCM_CAST_UINT(SCM_GET_DIRECT_CAR(cons)) & ~SCM_GCBIT_MASK)))

これは (cons にひっついてる type tag を適当に払う以外は) 次のと等価なんだと思いますが:

((ScmRef) &((cons)->X & ~SCM_GCBIT_MASK))

そらエラりますがな。正しくはこうです。

((ScmRef)&((cons)->X))

Bit mask の入る余地はありません。ただし、これで取得した参照を使って代入する際に (cons)->X & SCM_GCBIT_MASK を保存してやる必要があります。それが SCM_SET() の役目です。

追記: ヤマケンさんの方が早かったな。でも SET() は GC bit の保護 code が要りますよー。

R5RS macro

いや、どうにでもなるといえばなるんですが…
例えば "far symbol" 型を作れば syntax-rules の定義環境での参照解決を表現できます。

(let ((a 0))    ; frame_1
  (let ((b 1))         ; frame_2
    (let-syntax ((macro (syntax-rules () ((_) a))))
      (macro))))

この code で syntax-rules が走ったとき、ScmExp_syntax_rules() は ((_) a) という list を traverse して symbol a を見つけ、それを scm_new_far_symbol (env, (1 << N) | 0) に置き換えます。ここで引数二つ目の 1 というのは 1 つ外の frame の意味で、0 は frame_1 内での offset、N はバッティング回避のためのずらしです。
Macro の外の普通の変数参照もこれに肖れそうな気がしますが、参照見つけて解決せ次第破壊的代入〜とかすると gloc や eval との絡みが危なそう。あんまり深く考えてみてないけど。とりあえず compaction 待ちですかね。
;; というのを口実に先延ばしにしてるわけですが