SICP 読み (279) 5.4 積極制御評価器
うーん。allcode にあるソレを使えば一発起動なんですが、以前作ったモノと色々な意味で関わりがでてきてるみたいなので、なるべく自分で対処した方が良さげ。
しかし具体的にどう読むものか、と思っていたんですが scheme な手続き (4 章のやつ) と対比させてみたらどうか、と。例えば
ev-self-eval (assign val (reg exp)) (goto (reg continue)) ev-variable (assign val (op lookup-variable-value) (reg exp) (reg env)) (goto (reg continue)) ev-quoted (assign val (op text-of-quotation) (reg exp)) (goto (reg continue)) ev-lambda (assign unev (op lambda-parameters) (reg exp)) (assign exp (op lambda-body) (reg exp)) (assign val (op make-procedure) (reg unev) (reg exp) (reg env)) (goto (reg continue))
のあたりのナニは 4.1.1 の eval によれば以下
(define (eval exp env) (cond ((self-evaluating? exp) exp) ((variable? exp) (lookup-variable-value exp env)) ((quoted? exp) (text-of-quotation exp)) ;; snip ((lambda? exp) (make-procedure (lambda-parameters exp) (lambda-body exp) env)) ;; snip (else (error "Unknown expression type -- EVAL" exp))))
むむむ。成程、と言うしかない感じッス。(駄目
あるいは application? なナニは以下ですが
((application? exp) (apply (eval (operator exp) env) (list-of-values (operands exp) env)))
以下は (operator exp) を eval してる部分ですか。
ev-application (save continue) (save env) (assign unev (op operands) (reg exp)) (save unev) (assign exp (op operator) (reg exp)) (assign continue (label ev-appl-did-operator)) (goto (label eval-dispatch))
(reg continue) に jmp してる箇所をまだ見てないんですが、unev なレジスタに入れらているソレを見るに上記の list-of-values なソレは
ev-appl-did-operator (restore unev) ; the operands (restore env) (assign argl (op empty-arglist)) (assign proc (reg val)) ; the operator (test (op no-operands?) (reg unev)) (branch (label apply-dispatch)) (save proc) ev-appl-operand-loop (save argl) (assign exp (op first-operand) (reg unev)) (test (op last-operand?) (reg unev)) (branch (label ev-appl-last-arg)) (save env) (save unev) (assign continue (label ev-appl-accumulate-arg)) (goto (label eval-dispatch))
な部分かな。ちなみに list-of-values 手続きは以下
上記の ev-appl-did-operator が出口っぽい。apply-dispatch に branch しています。あるいは引数リストの先頭要素を eval してるのが上記になるのか。
(define (list-of-values exps env) (if (no-operands? exps) '() (cons (eval (first-operand exps) env) (list-of-values (rest-operands exps) env))))
むむ。ev-appl-accumulate-arg も関係ありですか。でもどこで (goto (reg continue)) してるか、と思ったら既出だよ (ev-self-eval、ev-variable、ev-quoted、ev-lambda)。primitive-apply でも goto しています。
ev-appl-accumulate-arg (restore unev) (restore env) (restore argl) (assign argl (op adjoin-arg) (reg val) (reg argl)) (assign unev (op rest-operands) (reg unev)) (goto (label ev-appl-operand-loop)) ev-appl-last-arg (assign continue (label ev-appl-accum-last-arg)) (goto (label eval-dispatch)) ev-appl-accum-last-arg (restore argl) (assign argl (op adjoin-arg) (reg val) (reg argl)) (restore proc) (goto (label apply-dispatch))
で、上記で eval した結果を argl に adjoin して unev から取り除いている模様。ラストの引数だったら後処理の入口を continue にセットして eval ですか。後処理な ev-appl-accum-last-arg は argl 設定して proc を pop して apply してる模様。apply のためには proc と argl が必要という事でしょうか。
上記の ev-appl-accum-last-arg と ev-appl-did-operator の関係が微妙。ええと、ev-appl-did-operator は operator の eval が終わった時点で、と考えて良いのかなぁ。これ前提で did-operator を見てみると no-operands だった時に branch してるのか。成程。これはしかしスタックの状態遷移を手動で見るべきな気もしますが別途とゆー事で。
次はその先の apply な模様ですが、とりあえず別途なエントリで。あと、元気があればスタックの様子をナニしてみるかもしれませんが可能性は低いッス。(を