3imp 読んでみる (14)

なんも考えずに

	       [apply ()
		      (if (primitive? a)
			  (VM (apply (cadr a) r) '(return) e r s)
			  (record (body e vars) a
				  (VM a body (extend e vars r) '() s)))]

	       [apply ()
		      (if (primitive? a)
			  (VM (apply (cadr a) r) x e r s)
			  (record (body e vars) a
				  (VM a body (extend e vars r) '() s)))]

ってやってみると以下の試験にパスしない。

(test-section "primitive")
(test* "(VM '() (compile '(if (= 1 1) 0 1) '(halt)) (init-env) '() '())"
       0
       (VM '() (compile '(if (= 1 1) 0 1) '(halt)) (init-env) '() '()))

意味不明。戻ってきているのは以下のエラー

#<error "improper list not allowed: #t">

improper list は行儀の悪いリスト、との事。具体的に何が原因でドコでエラーが発生するのか、まで追っかけきれていません。

原因解析

コンパイルの戻りは以下 (整形してます

gosh> (compile '(if (= 1 1) 0 1) '(halt))
(frame (test (constant 0 #0=(halt)) 
	     (constant 1 #0#)) 
       (constant 1 
		 (argument (constant 1 
				     (argument (refer = (apply)))))))
gosh> 

VM な手続きをトレイスしてみる事に。

  • 最初は x に上記の compile の戻りがセットされて VM 手続き起動
  • frame な処理
    • test で始まるリストが s に ((test (constant ry)) () () ()) な形
    • constant 1 で始まるリストが x に
    • VM 手続き呼び出し
  • constant な処理
    • 1 と 1 を順に current rib に cons
  • refer
    • = を current environment から解決 (primitive #) が a に
    • (apply) が x に
  • apply
    • a は primitive 認定なんで a に (apply (cadr a) r) を置いて VM 呼び出し

x は変わってないからエラーのケースだと a に #t とかが入ってて primitive ではない認定された挙句に

			  (record (body e vars) a
				  (VM a body (extend e vars r) '() s))

で死亡、がおおよそのストーリーですか。
よく考えたら x は (return) 限定で良さげな気がしてきた。いや

(compile (+ 1 1) '(halt))

の場合どうか、というと

(constant 1 (argument (constant 1 (argument (refer + (apply))))))

になるか、と思ったらアタマに frame が付く

(frame (halt)
       (constant 1 (argument (constant 1 (argument (refer + (apply)))))))

これなら return キメ打ちでも問題ないのかな。