Jun Inoue
jun.l****@gmail*****
2006年 4月 9日 (日) 08:08:30 JST
YamaKen <yamak****@bp*****> writes: > ところで本体のmacro.cがcommitされてないですよ。 太田さんに言われて commit しました。orz >> 自分では expand-macro で展開を確認しながら scm_format を埋めて debug >> してるんですが、sscm では出力が unwrap-syntax されてしまうので scope >> 周りの debug が不便です。原因はguard_body() で返り値に delay() を被せ >> てるからですが、どう直すべきかわかりません。というか guard 周りの code >> はどうもよくわからない & わかるまで粘る気になるような外見でないので、 >> 書いた人に見てほしいんですが… > ヤマケンさん > > unwrap-syntaxをググってみても恥ずかしながらどういう出力が欲しい > のかわからないんで、現状と理想の出力を例示してもらえますか? コー > ドいじりはこっちで引き受けます。 端的に言えば sscm> (define-syntax macro (syntax-rules () ((_) sym))) という前提で、現状 sscm> (expand-macro macro) sym となってるのが #<farsym 0 sym> になってほしいということです。 unwrap-syntax の semantics については、例えば sscm> (write ;; guard bug 回避 (expand-macro macro)) #<farsym 0 sym> ;; sym ではない (#<undef> が返ってくる) で、macro の展開が返してきた sym という symbol は、単純に sym と書いて 得られるものと eq? ではありません: sscm> (eq? 'sym (expand-macro macro)) () ; SIOD compat なので これが "timestamp" と言ってるやつで、R5RS でいう renamed identifier を 表現する object に元の symbol を包んでいます。 この timestamp は symbol lookup のための情報であって、実際に "datum と しての sym" を返されたときには eq? にならないと困ります。 sscm> (eq? 'sym (let-syntax ((macro (syntax-rules () ((_) 'sym)))) ;; quote してる (macro))) ;; expand-macro 無し #t これをするのが unwrap-syntax で、与えられた object 内で識別子を探して 片っ端から timestamp を剥していきます。いまのところ quote, quasiquote, case, match が引数の全部乃至一部を unwrap-syntax しています。guard で は delay() 内の quote が余分に unwrap しています (unwrap しないものと 差し替えて確認)。 ;; 最初の例で wrap された識別子が直接見えたのは expand-macro という反 ;; 則技を使ったから。本来 wrapped id は scheme level からは見れません。 > こんな不自然なコードになっているのはSRFI-34の参照実装を機械的にC > にベタ移植しているからで、なぜそうしているかと言うと、Scheme処理 > 系の満たすべき仕様に精通しているとは言えない私がSRFI-34実装の正 > しさを保証するには既存のauthoritativeなコードを主観の入り込む余 > 地のない形で移植するしか手がないからです。 > > このポリシーによって実装の正しさを保証する限り、許されるコード変 > 更は機械的?に等価な変換だけとなります。意味的に等価、という仕様 > の解釈が入る書き換えは行ってはいけない。したがって、元のコードで > lambdaを使っているところはCのコードでもlambdaを使う必要がありま > す。 > > R5RSやSRFIのドキュメントを拝借する際に文言をいじるべきではない、 > というのも同様の思想です。 SRFI 文書の参考実装を忠実に C に転写するのは構いませんが、それが参考実 装の code (である list 構造) を C data で表現するという意味であれば C 路線を捨てて core 以外 scheme で書いた方が確実で効率的です。(SRFI も殆 どコピペで済むし、read の overhead が嫌ならScheme→C converter を scheme で書けば良い。多分 50 行以内で済むでしょう。) それより、 > Scheme処理系の満たすべき仕様に精通しているとは言えない私がSRFI-34実 > 装の正しさを保証するには という部分が非常に気になります。言葉の齟齬がある気がしますが、もしこれ が、ヤマケンさんが自分でよくわかってないものをよくわからない code を拝 借して形にしようとしている、という意味であれば危険極まりないと思います。 他人 (∋過去の自分) の実装に正しさを求めるなら、その実装の働きを理解し ないと正しくコピペすることもできません。 実際、guard は verbatim に転写できていません。参考実装が define-syntax を使っている関係から中途半端に C に手が出ているために、解釈が紛れ込ん でいます (「何の」かは難しいところですが)。その証拠に expand-macro を 使えば sigscheme の実装と SRFI-34 の参考実装を scheme level で見分けら れます。 (define-syntax macro (syntax-rules () ((_) (let ((sym 0)) sym)))) ;; srfi-34 の実装をコピペ (省略) (write (guard (err (else #f)) (expand-macro macro))) (use srfi-34) したときと結果が違います。他の実装で試したいなら STklos では s/expand-macro/macro-expand/, Gauche では %macroexpand。Guile と scheme48 はよくわかりませんでした。 >> scm_s_srfi34_guard(catch, body) >> { >> push_handler (make_handler (catch)); >> ret = scm_s_begin (body); >> pop_handler (); >> return ret; >> } >> ではダメなんでしょうか。(dynamic-wind の側で PROCEDUREP() か CONSP() >> かければ make_handler() も要らないような) > > 現状のlongjmpな継続実装ならそれで動きそうな気もしますが、前述の > ように仕様上の穴が無い事を保証できないのと、将来的にうひひな手段 > でフルスペックの継続を導入したいと考えているのでこれを正式コード > にはしたくないです。 うーむ。サッパリ思いつかない。