R6RS Macros and R6RS librariesを今度こそ移植する の6
最後は東の横綱exceptionsが残るのみとなった。
キャッシュディレクトリの自動生成
(define (ca-serialize fn l) (unless (file-exists? (nmosh-cache-dir)) (create-directory (nmosh-cache-dir))) (ca-writeobj fn (compile-w/o-halt l)))
現在のmoshは起動時に生成しているが、書き込み時に毎回チェックするようにタイミングを変更した。インタプリタの実行中に削除されるケースも考えられるため。
キャッシュの無効化
今の所2つのケースでキャッシュが無効化される可能性が有る。
- 元のファイルよりキャッシュが古い
- すでにロードされるライブラリの中に、互換性の無いものを含んでいる
(define (ca-load fn recompile? name) (define (reload) (PCK 'CACHE: 'RECOMPILE!!!) (set! nm:parachute #f) (ca-load fn #t name)) (let ((cfn (ca-filename->cachename fn))) (cond ((file-exists? cfn) (cond ((and (not recompile?) (file-newer? cfn fn)) (PCK (list 'CACHE: 'loading.. cfn)) ; try loading (if (eq? 'nm:failure (call/cc (lambda (k) ; FIXME: i assume a call/cc is much faster than an I/O (set! nm:parachute k) (eval-compiled! (ca-readobj cfn))))) (reload) (set! nm:parachute #f)) (PCK 'CACHE: 'done))
後者のケースのために、継続をつかって大域脱出を行っている。この継続の評価は、シリアライズされるライブラリに挿入される、ライブラリエントリポイントで必要に応じて行われる。これらはmosh-utils5.scmではなくexpander.scmに書かれている :
(define (expand-file-to-cache filename target name) (define (fappend a b) (define (itr cur rest) (if (pair? rest) (itr (cons (car rest) cur) (cdr rest)) cur)) (itr b (reverse a))) (define KODE `((nm:register-source ,filename (quote ,name) (quote ,(nm:dump-library-table name))))) (with-toplevel-parameters (lambda () (ca-serialize target (cons 'begin (fappend KODE (expand-toplevel-sequence (normalize (read-file filename)))))))))
展開されるコードをbeginでつつみ、register-source手続きの呼び出しを加えている。この呼び出し中に、ライブラリがコンパイルされた際のロードされていたライブラリのバージョン全てを含めている。
すでにロードしたライブラリのバージョンチェック(今回追加した)と、ライブラリをロードしたあと必要なライブラリをロードするためのテスト(これは本来備わっている)を両方持つのはムダなので、起動の高速化のためには修正されるべきだろう。