Exercise 5.48. The compile-and-go interface implemented in this section is awkward, since the compiler can be called only once (when the evaluator machine is started). Augment the compiler-interpreter interface by providing a compile-and-run primitive that can be called from within the explicit-control evaluator as follows: ;;; EC-Eval input: (compile-and-run '(define (factorial n) (if (= n 1) 1 (* (factorial (- n 1)) n)))) ;;; EC-Eval value: ok ;;; EC-Eval input: (factorial 5) ;;; EC-Eval value: 120 ———————————————————————————————————————————————————————————————————————— $ scheme --load 5.48-load-eceval-compiler.scm 1 ]=> (load "ch5-compiler.scm") 1 ]=> (start-eceval) ;;; EC-Eval input: (compile-and-run '(define (fac n) (if (= n 1) 1 (* (fac (- n 1)) n)))) ;;; EC-Eval value: ok ;;; EC-Eval input: (fac 5) ;;; EC-Eval value: 120 --- ch5-eceval-compiler.scm 2001-06-21 12:54:36.000000000 -0600 +++ 5.48-eceval-compiler.scm 2010-06-27 17:56:23.000000000 -0600 @@ -56,6 +56,13 @@ (set-register-contents! eceval 'val instructions) (set-register-contents! eceval 'flag true) (start eceval))) + +(define (compile-and-keep-going expression) + (let ((instructions + (assemble (statements + (compile expression 'val 'return)) + eceval))) + (set-register-contents! eceval 'val instructions))) ;;**NB. To [not] monitor stack operations, comment in/[out] the line after ;; print-result in the machine controller below @@ -128,6 +135,9 @@ (list 'compiled-procedure? compiled-procedure?) (list 'compiled-procedure-entry compiled-procedure-entry) (list 'compiled-procedure-env compiled-procedure-env) + (list 'compile-and-run? compile-and-run?) + (list 'compile-and-keep-going compile-and-keep-going) ; defined above + (list 'compile-and-run-expression compile-and-run-expression) )) (define eceval @@ -148,8 +158,19 @@ (op prompt-for-input) (const ";;; EC-Eval input:")) (assign exp (op read)) (assign env (op get-global-environment)) + (test (op compile-and-run?) (reg exp)) + (branch (label compile-and-run)) (assign continue (label print-result)) (goto (label eval-dispatch)) +compile-and-run + (assign exp (op compile-and-run-expression) (reg exp)) + (assign continue (label compile-and-run-2)) + (goto (label eval-dispatch)) +compile-and-run-2 + (perform (op compile-and-keep-going) (reg val)) + (assign env (op get-global-environment)) + (assign continue (label print-result)) + (goto (reg val)) print-result ;;**following instruction optional -- if use it, need monitored stack (perform (op print-stack-statistics)) --- ch5-eceval-support.scm 2010-04-22 11:09:43.000000000 -0600 +++ 5.48-eceval-support.scm 2010-06-27 17:42:42.000000000 -0600 @@ -185,3 +185,5 @@ (define (compiled-procedure-entry c-proc) (cadr c-proc)) (define (compiled-procedure-env c-proc) (caddr c-proc)) +(define (compile-and-run? exp) (tagged-list? exp 'compile-and-run)) +(define (compile-and-run-expression exp) (cadr exp))