2016/02/02

SICP 問題 5.24

condを派生式ではなく構文として実装する.

;; unevがcondの本体を保存.expはevalされる.
 ev-cond
   (assing unev (op cond-clauses) (reg exp)) ;((p1 e1) (p2 e2) ...)の形にする.
   (save continue)                      ;cond後の継続をsave
   (save env)                           ;現在の環境をsave
   (save unev)                           ;ev-cond-loopで復元できるようにsave
   (goto (label ev-cond-test))

 ev-cond-test
   (restore exp)                        ;unevの内容がexpにコピーされる.
   (restore env)
   (restore continue)
   (test (op null?) (reg exp))
   (branch (label ev-cond-null))
   (assign exp (op car) (reg unev))      ;(p1 e1)の形に.
   (test (op cond-else-clause?) (reg exp)        ;(else e1)なら
   (branch (label ev-cond-else))        ;ev-cond-elseへ
   (save continue)
   (save env)
   (save unev)
   (assign continue (label ev-cond-loop)) ;eval-dispatchの後ev-cond-loopに戻れるように代入
   (assign exp (op cond-predicate) (reg exp))
   (goto (label eval-dispatch))

 ev-cond-loop
   (test (op true?) (reg val))
   (branch (label ev-cond-value))
   (restore unev)
   (restore env)                        ;環境を元に戻す
   (assign unev (op cdr) (reg unev))      ;残りのclausesへ
   (save env)
   (save unev)
   (goto (label ev-cond-test))


 ev-cond-else
   (assign exp (op cond-actions) (reg exp))
   (assign exp (op sequence->exp) (reg exp))
   (goto (label eval-dispatch))

 ev-cond-value
   ;; expはpredicateを評価した値になってる.
   (restore exp)                        ;unevが持っていたcond本体をexpがrestore
   (restore env)
   (restore continue)
   ;;((p1 e1 e1' ...) (p2 e2 e2' ...) ...)という形なのでcarを取る.
   (assign exp (op car) (reg exp))
   (assign exp (op cond-actions) (reg exp))  ;(e1 e1' ...)にする.
   (assign exp (op sequence->exp) (reg exp))
   (goto (label eval-dispatch))

 ev-cond-null
     (assign val (const cond-null-error))
     (goto (label signal-error))

test

gosh> (start eceval)


;;; EC-Eval input:
(define (append x y)
  (cond ((null? x) y)
        (else (cons (car x)
                    (append (cdr x) y)))))

;;; EC-Eval value:
ok

;;; EC-Eval input:
(append '(a b c) '(d e f))

;;; EC-Eval value:
(a b c d e f)

;;; EC-Eval input:
(define (append x y)
  (cond ))

;;; EC-Eval value:
ok

;;; EC-Eval input:
(append '(a b c) '(d e f))
cond-null-error

© 2022 wat-aro