Scm_VMCallCC (19)

今日、体調不良にて昨晩のエントリのフォローのみ。

微妙な部分

以下なインストラクションな並びのナニ

gosh> (disasm (lambda () (list 1 2 (call/cc (lambda (c) (set1 cont c) 3)) 4)))
main_code (name=#f, code=0x80f9db0, size=12, const=2, stack=12):
args: #f
     0 CONSTI-PUSH(1)
     1 CONSTI-PUSH(2)
     2 PRE-CALL(1) 8
     4 CLOSURE #<lambda 0>      ; (lambda (c) (set1 cont c) 3)
     6 PUSH-GREF-CALL(1) #<identifier user#call/cc>; (call/cc (lambda (c) (set1 cont c) 3))
     8 PUSH
     9 CONSTI(4)
    10 LIST(4)                  ; (list 1 2 (call/cc (lambda (c) (set1 con ...
    11 RET
internal_closure_0 (name=#f, code=0x80f8ca0, size=8, const=2 stack=11):
args: #f
     0 PRE-CALL(2) 6
     2 GREF-PUSH #<identifier user#cont>; cont
     4 LREF0-PUSH-GREF-CALL(2) #<identifier user#set1>; (set1 cont c)
     6 CONSTI(3)
     7 RET
#<undef>
gosh>

上記、PRE-CALL な時点の継続は 8 ッス、って出てますな。よく考えたら上記 2, 4, 6 って (call/cc (lambda (c) ... 3)) のための一連の命令なのか。
しかも R5RS の継続の項を踏まえると例えば 6 のインストラクションは val0 に何らかの値 (上記のケースだと 3 か) をセットする事になるのか。デフォルト 1 つであれば val0 で何とかなりますな。
上記のケイスだと引数列の中で call/cc してるから push なんですが、他のケースだとどうなるのか、は別途確認してみたいな、と。

あらら?

なんかもの凄いカン違いしてそうな。昨晩エントリで

(cont -1)

したナニでは cont には subr が束縛されてて呼び出されるのは throw_continuation 手続きで、最終的には以下の命令がナニで throw_cont_body 手続きの戻りが戻されて val0 に格納される、はず。

        return throw_cont_body(handlers_to_call, ep, args);

で、throw_cont_body 手続きの中のソレが昨晩箇条書きにしたソレ。以下に再度書きます。

  • PC に PC_TO_RETURN がセット
    • RET です
    • ので RETURN_OP にて POP_CONT されます。
  • CONT には ep の cont 属性がセット
    • 上記の通り pop されます
  • handlers も復帰

で、ひとつの値を受け取る継続シバリで書きますが、最終的に引数の値が戻される形になっています。

                    VAL0 = SCM_SUBR(VAL0)->func(ARGP, argc,
                                                SCM_SUBR(VAL0)->data);
                    /* the subr may substituted pc, so we need to check
                       if we can pop the continuation immediately. */
                    if (TAIL_POS()) RETURN_OP();
                    NEXT;

それを val0 にセットして、末尾式なら継続を pop して NEXT している。Scm_VMCallCC (15) にあるマンガも参考にしつつ、と思ったら pc に入っている、な記述がいきなり違うし。
しかも Scm_VMCallCC 手続きで継続とか環境が heap に保管されるあたりを完全にスルーしています。これも別途確認しつつ記録残します。

どうも

冷静に記録を見返してみるともの凄い蛇行っぷりでぶっちゃけ微妙。