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">

と怒られた。一つ限定らしい。困った。