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 手続きがなんとかイメージできるはず。と言いつつ、とりあえずソースは見てますが限界近し。