■
[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 待ちですかね。
;; というのを口実に先延ばしにしてるわけですが