<< Previous exercise (5.23) | Index | Next exercise (5.25) >>
This is a longer version.
ev-cond (save continue) ; save final destination (assign exp (op cond-clauses) (reg exp)) ; drop cond label ev-cond-have-clause? (test (op have-clause?) (reg exp)) ; any clauses? (branch (label ev-cond-check-clause)) ; --> check clause (goto (label ev-cond-no-clauses)) ; --> no clauses ev-cond-check-clause (assign unev (op clauses-first) (reg exp)) ; get first clause (test (op cond-else-clause?) (reg unev)) ; else clause? (branch (label ev-cond-else)) ; --> else (save exp) ; save clauses list (save unev) ; save clause (save env) ; save env (assign exp (op cond-predicate) (reg unev)) ; get predicate (assign continue (label ev-cond-after-predicate)) (goto (label eval-dispatch)) ; --> eval predicate ev-cond-after-predicate (restore env) ; restore env (restore unev) ; restore clause (restore exp) ; restore clauses list (test (op true?) (reg val)) ; is predicate true? (branch (label ev-cond-actions)) ; --> actions (assign exp (op clauses-rest) (reg exp)) ; drop first clause (goto (label ev-cond-have-clause?)) ; --> try-again ev-cond-else (assign val (op clauses-rest) (reg exp)) ; get clauses after else (test (op have-clause?) (reg val)) ; any clauses after else? (branch (label ev-cond-error-else-not-last)) ; --> prepare error ev-cond-actions (assign unev (op cond-actions) (reg unev)) ; store actions for ev-seq (goto (label ev-sequence)) ; --> ev-sequence ev-cond-no-clauses (restore continue) ; restore continue (assign exp (const false)) ; name of false variable (goto (label ev-variable)) ; --> lookup false value ev-cond-error-else-not-last (restore (reg continue)) ; restore continue (assign val (const else-not-last-clause--COND)) (goto (label signal-error)) ; --> raise error No Match: if there's no match I believe #f should be returned, because: 1) that is what's returned by the metacirular evaluator, 2) that is what eceval returns for an if without an alternate clause. Else Last Error: to match the behaviour of the metacircular evaluator, checks if the else clause is the last clause. Sample ====== (define (on-dice? n) (cond ((< n 1) false) (else (< n 7)))) Returns first clause: --------------------- (cond ((on-dice? 1) "Hello from First Clause") ((on-dice? 2) "Hello from Second Clause") (else "Hello from Else Clause")) Output: eceval DONE - val: Hello from First Clause Returns other clause: --------------------- (cond ((on-dice? 9) "Hello from First Clause") ((on-dice? 2) "Hello from Second Clause") (else "Hello from Else Clause")) Output: eceval DONE - val: Hello from Second Clause Returns else clause: -------------------- (cond ((on-dice? 0) "Hello from First Clause") ((on-dice? 7) "Hello from Second Clause") (else "Hello from Else Clause")))) Output: eceval DONE - val: Hello from Else Clause Returns false if no match: -------------------------- (cond ((on-dice? 0) "Hello from First Clause") ((on-dice? 7) "Hello from Second Clause")) Output: eceval DONE - val: #f Error if else is not last clause -------------------------------- (cond ((on-dice? 0) "Hello from First Clause") (else "Hello from Else Clause") ((on-dice? 2) "Hello from Third Clause")) Output: ERROR: ELSE-clause-isnt-last--COND
;;; Exercise 5.24 ev-cond (save continue) ;; extract the clauses (assign unev (op cond-clauses) (reg exp)) ;; set default value for cond (assgin val (const '<void>)) ev-cond-loop ;; test for empty clauses (test (op empty-clauses?) (reg unev)) (branch (label ev-cond-return)) ;; extract the first (assign exp (op first-clause) (reg unev)) (test (op cond-else-clause?) (reg exp)) (branch (label ev-cond-actions)) ;; save the first (save exp) ;; save the clauses (save unev) (save env) (assign exp (op cond-predicate) (reg exp)) (assign continue (label ev-predicate-decide)) (goto (label eval-dispatch)) ev-predicate-decide (restore env) (restore unev) (restore exp) (test (op true?) (reg val)) (branch (label ev-cond-actions)) (assign unev (op rest-clauses) (reg unev)) (goto (label ev-cond-loop)) ev-cond-actions (assign unev (op cond-actions) (reg exp)) ;; (save continue) ignored, since we have saved it before. (goto (label ev-sequence)) ev-cond-return (restore continue) (goto (reg continue))
Rptx
This is a shorter version.