Scm_VMCallCC (13)

save_env の退避なあたりを復習。

とりあえず

マンガを描くんですがどんなのが良いやら。

 i -> j

みたいなカンジで環境なリストがあるとします。矢印は up なリンクです。
i はこんなカンジ?

     +--------+
size |   2    |
info |        |
 up  |   j    | <- i
     |   x    |
     |   y    |
     +--------+

で、j が以下なカンジ?

     +--------+
size |   1    |
info |        |
 up  |  NULL  | <- j
     |   z    |
     +--------+

env_begin に i がセットされたとして、まずここで領域確保。

        d = SCM_NEW2(ScmObj*, ENV_SIZE(esize) * sizeof(ScmObj));

(* 4 (+ 2 3)) な領域が確保。次でコピィなんですが

        for (i=ENV_SIZE(esize), s = (ScmObj*)e - esize; i>0; i--) {
            *d++ = *s++;
        }

i は 5 から開始、s が最初に指すのは領域の一番てっぺん。
で、てっぺんから順に下に降りていきつつ i が指す環境フレームから heap に値がコピーされていくはず。ん? 本当かなぁ。違いますね。底からコピーか。先の処理を見るに最後は d がてっぺんを指してる状態でないと微妙。
あ、ちなみに i も j もスタックの中にあるのが前提です。
とりあえず以降の処理は箇条書きで追ってみます。

  • saved に d から 3 なポインタ値をを引いた値を設定
    • heap 側の up 属性のアドレスが saved にセット
  • prev が NULL でなければ prev->up に先でセットされた saved の値がセット
    • prev は heap 側のアドレスがセットされてるはずなので、これは新たに確保した領域のポインタを繋いでリストにしてる、と言えるはず
    • この時点では prev は NULL なのでスルー
  • head が NULL なら head に saved をセット
    • 戻す先頭ポインタを退避する処理
    • head は i' のポインタがセットされるはず
  • next に e->up の値をセット
    • ええと、e はコピー元なので、コピー元のリストの次の要素を退避、か
    • 上記の構造で言えば j のポインタ値が next にセット
  • saved のポインタ値を prev と e->up に設定
    • prev は直前のステップで処理された heap の要素のアドレス
    • コピー元の次の要素が上記で確保された heap のナニになる
    • prev と e->up (i の up 属性) には i' がナニ
    • この段階でのリストの状態が以下?
i  -> i'

# j へのリンクは next が保持
  • 属性セット
    • e->size が -1 に、e->info に #f がセット
    • i が指す要素は無効 (forwarded) に
  • e に次の要素 (j) のポインタをセット

だんだん面倒になってきつつありますが次の要素です

  • 領域確保して中身をコピィ
  • saved に d から 3 なポインタ値を引いた値を設定
    • ここでは j' のソレになるはず
  • prev が NULL でなければ
    • prev は i' で、i' の次が j' になる形で up 属性設定
  • head が NULL なら (ry
    • ここはスルー
  • next に e->up の値をセット
    • e->up の値は NULL
  • saved のポインタ値を prev と e->up に設定
    • j' が prev と e->up (j の up 属性) にセットされるはず
    • この時点でリストは以下な形
i  -> i'
         -> j'
      j
  • e に next の値をセット
    • NULL が設定されて、IN_STACK_P ではなくなるので繰り返しから脱出

一応

save_env はマトモに理解できてるはず。ただ、上記なリストにさらに環境が積まれたケースでどうなるか、は今のトコ不明。
ただ、get_env 手続きでは継続フレームを順に手繰っていきながら、退避された環境を指す継続の環境な属性を heap を指すように修正しているのが分かる。
おそらくは save_cont でも継続フレームを退避しつつ、環境についても上記と同様の処理をしているものに違いない。

save_cont 手続きを確認しますが、一旦ここでエントリ投入。

つづき

  • save_cont も同じような仕掛けと見た。
  • 環境云々で言うと_ローカル環境をポップした時の_云々がツッコミ不足?
  • 積みかけの引数フレームの処理
    • _作りかけの引数フレームのみが必要に応じてスタックエリアにコピーされる_とある

ここがある程度整理できたら Scm_VMCallCC 手続きがなんとかイメージできるはず。と言いつつ、とりあえずソースは見てますが限界近し。