SICP 読み (300) 5.4 積極制御評価器
体調悪い。どこでどうすりゃ良いのか、は何となくイメージできてるんですが、具体的にどうすれば、な部分で思考が止まる。疲れてるのかな。
問題 5.30 の a.
エラーです、という意味の **error** な文字列を特別な条件コードって事にする。なので、ch5-eceval-support.scm の extend-environment と lookup-variable-value と set-variable-value! はそれぞれ以下の形に変更。
あ、駄目だ。extend-environment は違うソレだな。面倒臭いから以下に。
(define (extend-environment vars vals base-env) (if (= (length vars) (length vals)) (cons (make-frame vars vals) base-env) (if (< (length vars) (length vals)) 'too-many-arguments 'too-few-arguments (define (lookup-variable-value var env) (define (env-loop env) (define (scan vars vals) (cond ((null? vars) (env-loop (enclosing-environment env))) ((eq? var (car vars)) (car vals)) (else (scan (cdr vars) (cdr vals))))) (if (eq? env the-empty-environment) 'unbound-variable (let ((frame (first-frame env))) (scan (frame-variables frame) (frame-values frame))))) (env-loop env)) (define (set-variable-value! var val env) (define (env-loop env) (define (scan vars vals) (cond ((null? vars) (env-loop (enclosing-environment env))) ((eq? var (car vars)) (set-car! vals val)) (else (scan (cdr vars) (cdr vals))))) (if (eq? env the-empty-environment) 'unbound-variable (let ((frame (first-frame env))) (scan (frame-variables frame) (frame-values frame))))) (env-loop env))
で、ch5-eceval.scm の ev-variable が以下
ev-variable (assign val (op lookup-variable-value) (reg exp) (reg env)) (test (op eq?) (reg val) (const unbound-variable)) (branche (label unbound-variable-error)) (goto (reg continue))
compound-apply は以下
compound-apply (assign unev (op procedure-parameters) (reg proc)) (assign env (op procedure-environment) (reg proc)) (assign env (op extend-environment) (reg unev) (reg argl) (reg env)) (test (op eq?) (reg env) (const too-many-arguments)) (branch (label too-many-arguments-error)) (test (op eq?) (reg env) (const too-few-arguments)) (branch (label too-few-arguments-error)) (assign unev (op procedure-body) (reg proc)) (goto (label ev-sequence))
あとは ev-assignment-1
ev-assignment-1 (restore continue) (restore env) (restore unev) (perform (op set-variable-value!) (reg unev) (reg val) (reg env)) (test (op eq?) (reg val) (const unbound-variable)) (branch (label unbound-variable-error)) (assign val (const ok)) (goto (reg continue))
で、エラー処理を追加
unbound-variable-error (assign val (const unbound-variable)) (goto (label signal-error)) too-many-arguments-error (assign val (const too-many-arguments)) (goto (label signal-error)) too-few-arguments-error (assign val (const too-few-arguments)) (goto (label signal-error))
微妙杉。ちょっとここ、スルー気味でヤッツケてラストに進んだ方が精神的に楽かも。(何
問題 5.30 の b.
こちら方面にも修正は盛り込む必要あり。
primitive-apply (assign val (op apply-primitive-procedure) (reg proc) (reg argl)) (restore continue) (goto (reg continue))
val がエラーな条件コードだったら云々、になるのかなぁ。こんな感じにできれば幸せ??
primitive-apply (assign val (op apply-primitive-procedure) (reg proc) (reg argl)) (test (op eq?) (reg val) (const pair-required)) (branch (label signal-error)) (restore continue) (goto (reg continue))
あるいは ch5-eceval-support.scm の
(define (apply-primitive-procedure proc args) (apply-in-underlying-scheme (primitive-implementation proc) args))
で args は proc の要件を満たした引数になってるかどうかを確認した上で云々、なのか
(define (apply-primitive-procedure proc args) (let ((ret (check-args (primitive-implementation proc) args))) (if (null? ret) (apply-in-underlying-scheme (primitive-implementation proc) args) (car ret))))
むぎゃー。微妙。駄目だ絶不調。しかも check-args って手続き受け取っても名前が分からねぇ。わはははは。(死亡
案 1
primitive なソレを (primitive 手続きの名前 手続き本体) な形で持つ。
(define (primitive-procedure-objects) (map (lambda (proc) (list 'primitive (car proc) (cadr proc))) primitive-procedures)) (define (primitive-implementation proc) (caddr proc))
そーすれば名前 (cadr にある) を元に引数をチェック可能。