ステップ実行eval開発中(6)
隠し束縛を安全に隠す方法を思い付いた。
- (gensym)を使って、文字列からは変換不可能なシンボルを生成する
- 対象モジュール内で、このシンボルに対して、隠したい内容(今回はspecial formの実体)を束縛する
- このシンボル内の束縛にアクセスする為には、元のシンボルを保持していないと不可能!
- Gaucheのmodule-table手続き等の、モジュール操作関連の手続きを提供している場合は取り出せてしまうが、その場合はそもそもモジュールを逸脱した操作が既に提供されてしまってる気がする。
- これでは一見、マクロ展開時にも、このシンボルの解釈ができずに駄目なように思えるが、define-macroを使って、gensymシンボルを含むようにした場合は想定通りに機能した!
- これが機能する(かも知れない)という事に気付くのに時間がかかった。そして機能した。
具体的には、以下のような感じになる。
(define m (make-module #f)) ; 対象モジュールを生成 (eval '(extend) m) ; 予め、束縛を完全に消しておく (define (bind-in-m symbol expr) ; m内で、symbolに対してexprを束縛する手続き (eval `(define-in-module ,m ,symbol (quote ,expr)) (current-module))) (define if-symbol (gensym)) ; ifを隠すシンボル (bind-in-m if-symbol if) ; ifを隠し束縛に隠す (global-variable-ref m if-symbol) ; => #<syntax if> が得られる事を確認 (global-variable-ref m (string->symbol (symbol->string if-symbol))) ;; => 文字列から得られるシンボルはエラーになる事を確認 ;; 隠し束縛のifを呼び出すマクロを書いてみる (define-macro (_if . args) ;; 実際には、ここに色々と余計な処理を追加する筈 `(,if-symbol ,@args)) ;; さっきのマクロをm内にインポートする (bind-in-m '__if _if) ;; m内で、__ifを動かしてみる (eval '(__if #f (not-reached) 123) m) ; => 123 (eval '(__if #t 456 (not-reached)) m) ; => 456 ;; 最後に、mの束縛一覧を確認してみる (module-parents m) (module-precedence-list m) (use util.list) (hash-table->alist (module-table m))
完璧だ!……多分。
不安があるとすれば、未来のバージョンのGaucheでも確実に動く、という保証は無さそうな点ぐらいだ。
しかし、gauche.gongに向けての実装には、これで充分だろう。
-
-
- -
-
gauche.nightの前売りチケットはもう少しで売り切れらしい。
しかし、自分自身が3/8に現地に行けるかどうかは、まだ謎のまま。
なんとかして現地参加したいが、こればっかりは別イベントの方のスケジュール判明を待つのみだ。