Mosh に psyntaxを移植しよう その2
前回までのあらすじ。
- psyntax 移植しようぜ。
- "invalid syntax of top-level program" って怒られる
psyntax にデバッグの print を入れる
pre-built しなおす。
(cd tools/psyntax-r6rs/ && rm -f psyntax.pp && cp pre-built/psyntax-petite.pp psyntax.pp && gosh gosh.r6rs.ss psyntax-buildscript.ss && gosh gosh.r6rs.ss psyntax-buildscript.ss && mv psyntax.pp pre-built/psyntax-mosh.pp)
エラーがでている箇所
(define (parse-top-level-program e*) (syntax-match e* () (((import imp* ...) b* ...) (eq? import 'import) (values imp* b*)) (_ (error "invalid syntax of top-level program"))))
gosh ./tools/psyntax-r6rs/pre-built/gosh.pp ./tools/psyntax-r6rs/examples/my-library.ss r6rs psyntax ready ((library (my-library) (export print-hello) (import (rnrs)) (define (print-hello) (display Hello World gosh: "error": invalid syntax of top-level program
あれ。Gauche でも怒られる。
落ちつけ
まずは Gauche で README にある通りに
(cd tools/psyntax-r6rs/ && cp pre-built/psyntax-gosh.pp psyntax.pp && gosh ./gosh.r6rs.ss ./test.scm) r6rs psyntax ready Hello World
動いたな。
Mosh と Gauche の結果と比較できるように Makefile を用意した。
Mosh と Gauche は同じ psyntax.pp を共有しているので psyntax.pp の問題ではない。
となると大枠の実行のフローを把握して二分法でしぼるのが良さそう。
フロー
二分法
top-level-expander の結果は同じか?→ Mosh はそこまで到達していない。
- top-level-expander
- parse-top-level-program
- ここで発生
- library-body-expander
- parse-top-level-program
parse-top-level-program への入力は同一か?→同一
となると
(syntax-match e* () (((import imp* ...) b* ...)
ここだな。
psyntax.pp ではどうやって展開されているかな?
(set! g$15$13215 (lambda (g$15$13919) (g$15$13207 g$15$13919 null?)))
こいつの返す値がおかしい。
(g$15$13902 g$15$13901)
の結果が違う。
今日書いた null? の実装が間違ってた。
Object scheme::nullPEx(Object args) { if (args.first().isPair()) { return Object::makeBool(args.first().isNil()); } else { return Object::False; } }
args.first().isPair() じゃなくて args.isPair() だな。。
大抵の null? 呼び出しは NULL_P インストラクションになるので気付くのが遅れた。
さて先に進もう
unbound variable dynamic-wind on top level
うぅこれは厳しい。
dynamic-wind
使われているのは
(with-syntax (((lhs* ...) (generate-temporaries (syntax (olhs* ...)))) ((rhs* ...) (generate-temporaries (syntax (olhs* ...))))) (syntax (let ((lhs* olhs*) ... (rhs* orhs*) ...) (let ((swap (lambda () (let ((t (lhs*))) (lhs* rhs*) (set! rhs* t)) ...))) (dynamic-wind swap (lambda () b b* ...) swap)))))))))
ここか。
とりあえず。
(define (dynamic-wind before thunk after) (before) (thunk) (after))
でお茶を濁す。(ごめんなさいごめんなさい)。
さて次
unbound variable symbol? on top level ./psyntax.pp:20: (<proc> g$49$13931)
ありゃ。SYMBOL_P インストラクションはあるが (apply symbol? ...) しているのかな。
追加した。
SEGV
うーん。助けて gdb !。
#0 scheme::VM::run (this=0x841fe40, code=0x843c094, returnPoint=0x0, returnTable=false) at scheme.h:260 #1 0x0806018c in scheme::VM::evaluate (this=0x841fe40, code=0x8396a40, codeSize=9) at VM.cpp:201 #2 0x080602b5 in scheme::VM::applyClosure (this=0x841fe40, closure=@0xbff595c0, args=@0xbff595bc) at VM.cpp:268 #3 0x08069f20 in scheme::applyEx (args=@0xa04ee10) at freeproc.cpp:1461
applyEx に渡っている closure が何者か?
- lambda?
- C++ の関数?
あたりから調べよう。