5.24 Exercise 5.24
Interpreting cond expressions as first-order constructs, rather than simplifying them into if expressions, requires slightly more work. The most important piece of it is to keep track of which branches have yet to be evaluated. As usual, we can use the unev register to maintain a reference to a list of cond branches that we haven’t checked yet.
We can use cond-clauses as a machine primitive to get a reference to the clauses. Of course, we’ll also have to allow else expressions, and verify that they only appear as the final alternative in the expression. I’ve chosen not to implement support for the alternate form at this time, largely because I never use it.
First, we need some new procedures for extracting parts of cond expressions:
(define (cond-first-predicate exp) (cond-predicate (first-exp exp))) (define (cond-first-actions exp) (cond-actions (first-exp exp))) (define (cond-else-predicate? exp) (eq? exp 'else))
Naturally, these will need to be added to the list of operations supported by the machine. I’ve also added null?, which we’ve managed to get away with not having until now.
For simplicity’s sake, we can implement the cond expression without tail recursion on the alternatives for now. That assembly looks like the following:
ev-begin-cond (assign unev (op cond-clauses) (reg exp)) (save continue) ev-cond (test (op null?) (reg unev)) (branch (label ev-cond-finished)) (assign exp (op cond-first-predicate) (reg unev)) (test (op cond-else-predicate?) (reg exp)) (branch (label ev-cond-else-test)) (save env) (save unev) (assign continue (label ev-cond-test-predicate)) (goto (label eval-dispatch)) ev-cond-test-predicate (restore unev) (restore env) (test (op true?) (reg val)) (branch (label ev-cond-body)) (assign unev (op rest-exps) (reg unev)) (goto (label ev-cond)) ev-cond-body (assign unev (op cond-first-actions) (reg unev)) (assign continue (label ev-cond-finished)) (goto (label ev-sequence)) ev-cond-else-test (test (op last-exp?) (reg unev)) (branch (label ev-cond-else)) (goto (label invalid-cond-else-form)) ev-cond-else (assign unev (op cond-first-actions) (reg unev)) (assign continue (label ev-cond-finished)) (goto (label ev-sequence)) ev-cond-finished (restore continue) (goto (reg continue)) invalid-cond-else-form (assign val (const invalid-cond-else-form-error)) (goto (label signal-error))