http://chaton.practical-scheme.net/gauche/a/2009/05/22
- はやみず
Gaucheって __FILE__ 的なものってあるんでしょうか。探してみたけどみつからなかった、、、- shiro
それは昔ちょっと要望が出たことがあるんですが、Cプリプロセッサとセマンティクスが違うのでうまくいかないんです。
ソースコード上の位置はextended pairに記録されているのでそれを取ることはできます。
で、自分自身のソース名と行番号を取れるマクロ (例えば (__FILE__)) も書ける。 ところが、この__FILE__の使用を隠すためにもう一段マクロをかますと
例えば(define-macro (MALLOC x) `(debug-malloc ,x (__FILE__) (__LINE__)))Cプリプロセッサ的にはMALLOCを実際に使った場所の__FILE__, __LINE__を取れることを期待するわけですが「ソース上の」__FILE__, __LINE__の位置はMALLOCマクロの定義された位置であって、MALLOCマクロがどこで使われるかとは関係ないわけなので、役に立たなかったと。
もしGaucheで書くのなら、「マクロに渡されたフォームのソースコード情報を抜き出して使う」ようなマクロにする必要がありますね。
- shiro
gosh> (define-macro (with-srcinfo form) `(,(car form) ,@(cdr form) (debug-source-info ',form))) #<undef> gosh> (define (test lis srcinfo) (print lis "@" srcinfo)) test gosh> (begin (with-srcinfo (test '(1 2 3))) (with-srcinfo (test '(4 5 6))) (with-srcinfo (test '(7 8 9)))) (1 2 3)@((stdin) 31) (4 5 6)@((stdin) 32) (7 8 9)@((stdin) 33) #<undef>こんな方向でなんとかできるかもしれない。
http://chaton.practical-scheme.net/gauche/a/2013/04/23
- yamasushi
__FILE__、__LINE__みたいな特殊変数ってあるのでしたっけ?
デバッグするときに、どこだっけ?ということが多々あるので、#?= __FILE__ __LINE__ みたいな感じでマークをつけておきたいのです。
- shiro
ああ、それは前に話題にしたことがあったけどどこだったかな>__FILE__。
今でも、#?=の後の式が単純な変数や定数でなければその場所が表示されますよね。処理系の中ではファイルと行数の情報は取れているんです。そこで、例えば(source-pos)のようなマクロ呼び出しでソースファイル名と行数に置き換えられるようなマクロを書くことは出来ます。ただ、Cプリプロセッサのように使えないんです。
というのは、Gaucheが取れる情報は「そのフォームがソース上に実際に出現した場所」です。したがって「(source-pos)を含む式に展開される便利マクロfoo」を書いて、fooを使った場所で簡単にその場所がわかるようにしよう、と思っても、表示されるのはfooが展開された場所ではなく、fooが定義された場所になっちゃうんです。Cプリプロセッサでは、__FILE__や__LINE__は変数名のまま展開されて、展開が全て終わった後に、展開後の場所の情報に置き換えられますよね。
Cプリプロセッサは行指向なので展開後にもファイル名や行数がわかるんですが、Gaucheの場合、マクロ展開をする時点では既にソースファイルからは離れてしまっているので、「場所」という概念が無くなっちゃってます。
- shiro
まあ、「マクロ呼び出しが出現した場所のソース情報」を何らかの形でマクロ展開器からアクセスできるようにしてやればいいのかもしれない。マクロ展開器を含めた改造が必要になりますが。
- yamasushi
ということは、#?=で単純な値の時にファイル名がでないのは、その情報がとれないから、ということですか?
()で囲むと出るのはなぜだろうなあと、いつも不思議に思っていました。- shiro
そうです。純粋に実装上の都合で、ソース情報はリストの先頭のペアにだけ保存されるようになっています。
GaucheSource:lib/gauche/vm/debugger.scm
(define (debug-source-info obj) (and-let* ([ (pair? obj) ] [info ((with-module gauche.internal pair-attribute-get) obj 'source-info #f)] [ (pair? info) ] [ (pair? (cdr info)) ]) info))