psyntax 最新版への道 1
目的
psyntax rev 10 に上げることで
- いくつかのバグ修正になる
- Repl を提供する枠組みをゲット
などを目指す。
方針
- ログは全て残す
- Mosh で展開する
- psyntax の構造を理解する
やってみよう!
まずは展開を試みる。
% cd rev10 % ~/mosh/mosh -b psyntax/ironscheme-buildscript.ss Condition components: 1. &error 2. &who: expander 3. &message: "cannot export unbound identifier" 4. &irritants: (compile-core-expr)
このエラーは誰が出しているか?
→mosh に組み込み済の psyntax の expander 。
このエラーの意味するところは?
→export で指定した識別子が定義されていないという意味。以下のような例。
(library (hage) (export hage-val) (import) )
compile-core-expr を export しているのは internal.ss 。
でも export していると同時に define しているから合法に見える。
試しに export から消してみたら次のエラーがでたのでここっぽい。
分かった。
#;(define need-quote-hack? (let ((x (cons 1 2))) (not (eq? (eval-core `',x) (eval-core `',x)))))
という行がうまくコメントアウトされていないのが原因っぽい。この行より下にある compile-core-expr が有効になっていなかった。
internal.ss から該当する行を消した。
さてもう一度実行してみよう。あれ?反応が返ってこないぞ。
さてこれは「ただ遅いだけ」なのか「無限ループ的な何か」なのかを見きわめないと。
ironscheme-buildscript.ss にいくつか print 的なものを入れてどこまで行ったか見ていこう。
あれ。全く表示されない。ということは ironscheme-buildscript を mosh 組み込みの psyntax が展開しているのに時間がかかっているのかな。
この仮説が正しいのであれば、ironscheme-buildscript.ss のコードをコメントアウトなど絵簡略化すればこの現象が防げることになる。
やってみよう。→正しかった。
(psyntax library-manager) の import で時間がかかっている。
library-manager.ss を見てみよう。export をコメントアウトする。
その後 define を軒並みコメントアウトしたらすぐにレスポンスが返ることが分かった。
あとはコメントを元に戻していき差分を見よう。
分かった。
(fprintf (current-error-port) "WARNING: library ~s has an inconsistent dependency \ on library ~s; file ~s will be recompiled from \ source.\n" name dname filename)
これの read にほぼ確定。文字列を \ でつなげるのは合法なのだっけ?どうみても合法だな。
というわけで scanner.re と reader.cpp を変更して対応した。
さて library-manager.ss を元に戻します。
fprintf が unbound identifier だ。
出来るだけ元のコードに手を入れたくないので以下のようなライブラリを作って対処。
(library (mosh psyntax) (export fprintf) (import (rnrs) (mosh string)) (define fprintf format) )
さて全て元に戻してみると
1. &error 2. &who: expander 3. &message: "unbound identifier" 4. &irritants: ((make-library id name ver imp-lib* vis-lib* inv-lib* exp-subst exp-env visit-proc invoke-proc visit-code invoke-code visible? source-file-name))
ふむ。確かに make-library が library-manager.ss から呼び出されているが、定義が見当たらない。
ironscheme.boot.pp にあるっぽい。これはどうするか。
あれ?。Record っぽいな。library-manager.ssに定義あるな。
(define-record library (id name version imp* vis* inv* subst env visit-state
ただ make-library がおかしいのはまちがいない。
library-manager.ss の先頭の近くに以下のように書いてみたが同じエラーになった。
(define a (make-library 3))
ちょっと psyntax を離れて実験。
moge.scm
(library (moge) (export define-record2) (import (rnrs)) (define-syntax define-record2 (lambda (x) (define (syn->str s) (symbol->string (syntax->datum s))) (define (gen-getter id) (lambda (fld) (datum->syntax id (string->symbol (string-append (syn->str id) "-" (syn->str fld)))))) (define (gen-setter id) (lambda (fld) (datum->syntax id (string->symbol (string-append "set-" (syn->str id) "-" (syn->str fld) "!"))))) (syntax-case x () [(_ name (field* ...) printer) (quasisyntax (begin (define-record name (field* ...)) ; (define rp (make-record-printer 'name printer)))] ))] [(_ name (field* ...)) (with-syntax ([(getter* ...) (map (gen-getter (syntax name)) (syntax (field* ...)))] [(setter* ...) (map (gen-setter (syntax name)) (syntax (field* ...)))]) (quasisyntax (define-record-type (name make-moge moge?) (sealed #t) ; for better performance (opaque #t) ; for security (nongenerative) ; for sanity (fields (mutable field* getter* setter*) ...))))]))))
muge.scm
(import (rnrs) (moge)) (define-record2 moge (a)) ;; (define-record-type moge ;; (sealed #t) ;; (opaque #t) ;; (nongenerative) ;; (fields (mutable a moge-a set-a!))) (make-moge 0)
これを mosh -b, mosh psyntax.pp, gosh gosh.r6rs の3通りの psyntax.pp の使い方で動かしてみたがやはりだめだった。
つまり現在の psyntax はこのタイミングでのマクロ展開の結果を参照できていないというバグがありそうな気がする。
Ikarus で同じコードを動かして、OK なら先に進もう(手動展開)。