Let's start Scheme

2012-11-30

続 マクロ戦争再び

すこぶる体調が悪いが頭はそれなりに稼動するので案をベッドの上で考えていたりした。

現状の問題としては、同一の環境でリネームされた識別子(本来はシンボル)が同名にならないというものだ。これは本質的に2つの問題を含んでいることを示唆している。
  1. 識別子を用いてシンボルの同一性を取ろうとしていること
    1. α変換が不完全である
  2. 識別子が本来の意味を越えて使用されているため、複雑なものが複雑怪奇にグレードアップしている
    1. 識別子=構文オブジェクト=パターン変数=リネームされたシンボルになっている
では、どうすればいいかということを考えていた。とりあえず1と2の問題の一部を解決するアイデアが以下である。
  • 使用されている環境に応じて適切にシンボルのリネームを行う
王道である。実際これくらいしか思いつかなかったともいう。問題になるのは、どの環境をもって同一の環境というかという点である。Sagittariusではマクロ展開時に3つの環境を参照することができる。
  1. コンパイル時の環境
  2. マクロ束縛時の環境
  3. マクロ展開時の環境
自分の中でもなんでこんなに環境が必要なのか実は整理できていないのが問題なのだが、それぞれ全て違う。細かいこと(細かくないが)はとりあえず置いておいて、とりあえず以下のプログラムを考える;
(import (rnrs))
(let ((bv #t)) ;; ※1
  (define-syntax foo
    (lambda (x)
      (syntax-case x ()
        ((_)
         (with-syntax ((set (let ((type #'bytevector-u8-set!))
                              #`(#,type bv 0 1))))
           #'(let ((bv (make-bytevector 1)))
               set
               bv))))))
  
  (let ((bv #f))
    (display (foo))))
まぁ、前回とほぼ同じコードである。違いは、マクロ束縛時環境が何かを捉えている点である。ここで問題になるのは、全てのbvが同一のシンボルになる必要がある点である。そうすると、コンパイル時環境を使うのはまずいことになる。letで束縛されたtypeが入ってくるからだ。そうすると、二つ目のbvと環境が異なるため、生成されるシンボルが異なる。
この状態では、マクロ束縛時と展開時の環境が多少違う。このパターンを考えるとマクロ束縛時の環境を使ってリネームするのが正しい気がする。ただし、リネームされたシンボルは※1と同名になる必要がある。これは、with-syntax>で生成されたものがそれを参照している必要があるからだ。また、最終的に返される構文で束縛されるbvも同様である。それによってシャドウイングされて結果正しい値を返す。
もし、このスクリプトでマクロ展開時の環境を使うと、(まぁ、結果的には問題ないのだが)、二つ目のbvにリネームされることになるのでうれしくない。

なんとなくどうすればいいのか見えてきた。結果として以下のように修正すれば、いいのではないだろうか?
  1. コンパイラ側のリネームを(uninterned)シンボルを使うように修正
  2. マクロ展開器ではマクロ束縛時の環境を元にシンボルを(uninterned)シンボルにリネーム
方針は固まったので、後は実装か・・・
いろいそうだうだ書いたが結局まったく別の方法で解決することにした。それは、VMにもう一個マクロ用のフィールドを持たせて、リネームしたシンボルを記憶させておくというもの。

なぜそうしたかを忘れないようにメモ。
  • 上記の方法ではuninternedシンボルの比較方法がない
    • そもそも、internされてないシンボルはeq?での比較ができない
  • かといって、全てのシンボルをinternしたくない
    • シンボルテーブルの肥大化は避けたいところ(省メモリの一環)
  • この問題とその他いくつかのマクロ周りの問題は、小手先ではなくマクロ展開器を割りと根本から見直す必要がある
    • 大掛かりに直すとなると時間がかなりかかるので、現状は避けたい
    • それに、方針を固めないとまた暗礁に乗り上げるだけだ
(いつになるかは分からないが)そのうち根本から治すべき問題で、現状小手先で何とかなるのならあまりリソースを割きたくなかったというのが本音。(大分辟易しているともいう)。 

No comments:

Post a Comment