3imp 読んでみる (16)
とっとと残った試験をヤッツケて lexical address なソレ方面に去ろうとも思ったのですが、3.4.1 説なソレを再度確認。
- (halt)
VM 終了。accumulator の値を戻す - (refer var x)
var の値を current environment から見つけて accumulator に置く。引数 x を next expression に置く - (constant obj x)
obj を accumulator に置いて x を next expression に置く - (close vars body x)
vars と body から closure を生成。生成した closure は accumulator に置く。x を next expression に置く - (test then else)
accumulator が #f でなければ next expression に then を置き、#f の場合は else を置く - (assign var x)
current environment にある var に accumulator の値を置き、next expression に x を置く - (conti x)
一旦スルー - (nuate s var)
これもスルー - (frame x ret)
current environment、current rib、next expression としての ret より新たな frame を生成。この frame は current stack に追加される。current rib は空になり、x を next expression に置く (生成された call frame は return する時に使われる) - (argument x)
accumulator の値を current rib に追加。x を next expression に置く - (apply)
accumulator にある closure を current rib で apply する。
むむ。原典の英語が微妙。基本的にはこうなるはず (primitive は除外
(apply (lambda (body e vars) (VM a body (extend e vars r) '() s)) a)
ちなみに apply が呼ばれた時点の a には (body e vars) という closure なリストがセットされているのが前提になっている模様。closure の中の環境は closure が生成された時点での環境になる。これに仮引数なリストと current rib の値で環境を extend とゆーのでビンゴだろうか。これを踏まえて再度原典の説明を見ると「正確にはこのインストラクションは closure の変数 (引数??) リストと current rib で closure の環境を拡張し、新たな環境にこの環境を置いて current rib に空リストを置いて next expression に closure の body を置く」で良いのかな。コードもそうなっている模様。
- (return)
手続きを見るに current stack から next expression と current environment と current rib と current stack (前の) を復帰して VM 呼び出し、になっている模様。原典によると「先頭 frame を current stack から除去し云々(上記と同じ)」とある。
継続関連は試験してから再度整理予定とゆーコトで。
テスツ
まず set! を、という事で以下な試験をでっち上げたら
(test-section "set!") (test* "(evaluate '((lambda (x) (set! x 1) x) 2))" 1 (evaluate '((lambda (x) (set! x 1) x) 2)))
通らなひ (以下、整形済み
discrepancies found. Errors are: test (evaluate '((lambda (x) (set! x 1) x) 2)): expects 1 => got #<error "wrong number of arguments for #<closure (compile compile)> (required 2, got 3)">
何処だ、と言いつつソースをニラむ
[lambda (vars body) (list 'close vars (compile body '(return)) next)]
lambda の手続き部分は一括りのリストになってないと NG な模様。なので
(test-section "set!") (test* "(evaluate '((lambda (x) ((set! x 1) x)) 2))" 1 (evaluate '((lambda (x) ((set! x 1) x)) 2)))
にしたら今度は
discrepancies found. Errors are: test (evaluate '((lambda (x) ((set! x 1) x)) 2)): expects 1 => got #<error "improper list not allowed: 1">
と怒られた。一つ限定らしい。困った。