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

動いたな。
MoshGauche の結果と比較できるように Makefile を用意した。


MoshGauche は同じ psyntax.pp を共有しているので psyntax.pp の問題ではない。
となると大枠の実行のフローを把握して二分法でしぼるのが良さそう。

フロー

  1. (load-r6rs-top-level (car args))
  2. (eval-r6rs-top-level x*)
  3. (top-level-expander)
  4. (for-each invoke-library lib*)
  5. (eval-core (expanded->core invoke-code))

二分法

top-level-expander の結果は同じか?→ Mosh はそこまで到達していない。

  • top-level-expander
    • parse-top-level-program
      • ここで発生
    • library-body-expander

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++ の関数?

あたりから調べよう。