現時点でのmake-new-machine.
今回追加するのは,exercise5.16のもの.
(define (make-new-machine) (let ((pc (make-register 'pc)) (flag (make-register 'flag)) (stack (make-stack)) (the-instruction-sequence '()) (instruction-count 0) ;; exercise 5.15 (trace #f)) ;; exercise 5.16 (let ((the-operations (list (list 'initialize-stack (lambda () (stack 'initialize))) (list 'print-stack-statistics (lambda () (stack 'print-statistics))))) (register-table (list (list 'pc pc) (list 'flag flag)))) (define (allocate-register name) (if (assoc name register-table) (error "Multiply define register: " name) (set! register-table (cons (list name (make-register name)) register-table))) 'register-allocated) (define (lookup-register name) (let ((val (assoc name register-table))) (if val (cadr val) (error "Unknown register: " name)))) (define (execute) (let ((instructions (get-contents pc))) (if (null? instructions) 'done (begin (if trace (print "instruction: "(caar instructions))) ;; exercise 5.16 ((instruction-execution-proc (car instructions))) (instruction-count-up) ;; exercise 5.15 (execute))))) (define (print-stack-statistics) ;; exercise 5.14 (stack 'print-statistics)) (define (instruction-count-up) ;; exercise 5.15 (set! instruction-count (+ instruction-count 1))) (define (print-inst-count) ;; exercise 5.15 (print "instruction-count: "instruction-count) (set! instruction-count 0)) (define (trace-on) ;; exercise 5.16 (set! trace #t)) (define (trace-off) ;; exercise 5.16 (set! trace #f)) (define (dispatch message) (cond [(eq? message 'start) (set-contents! pc the-instruction-sequence) (execute)] [(eq? message 'install-instruction-sequence) (lambda (seq) (set! the-instruction-sequence seq))] [(eq? message 'allocate-register) allocate-register] [(eq? message 'get-register) lookup-register] [(eq? message 'install-operations) (lambda (operations) (set! the-operations (append the-operations operations)))] [(eq? message 'stack) stack] [(eq? message 'print-stack) (print-stack-statistics)] ;; exercise 5.14 [(eq? message 'inst-count-init) (instruction-count-init)] ;; exercise 5.15 [(eq? message 'print-inst-count) (print-inst-count)] ;; exercise 5.15 [(eq? message 'trace-on) (trace-on)] ;; exercise 5.16 [(eq? message 'trace-off) (trace-off)] ;; exercise 5.16 [(eq? message 'operations) the-operations] [else (error "Unknown request -- MACHINE" message)])) dispatch))) (define (trace-on machine) ;; exercise 5.16 (machine 'trace-on)) (define (trace-off machine) ;; exercise 5.16 (machine 'trace-off))
実行
exptで試した.
(define expt-machine (make-machine '(counter product n b) (list (list '= =) (list '* *) (list '- -)) '((assign counter (reg n)) (assign product (const 1)) expt-iter (test (op =) (reg counter) (const 0)) (branch (label expt-done)) (assign product (op *) (reg b) (reg product)) (assign counter (op -) (reg counter) (const 1)) (goto (label expt-iter)) expt-done))) (set-register-contents! expt-machine 'b 3) (set-register-contents! expt-machine 'n 4) (trace-on expt-machine) (start expt-machine)
結果
gosh> instruction: (assign counter (reg n)) instruction: (assign product (const 1)) instruction: (test (op =) (reg counter) (const 0)) instruction: (branch (label expt-done)) instruction: (assign product (op *) (reg b) (reg product)) instruction: (assign counter (op -) (reg counter) (const 1)) instruction: (goto (label expt-iter)) instruction: (test (op =) (reg counter) (const 0)) instruction: (branch (label expt-done)) instruction: (assign product (op *) (reg b) (reg product)) instruction: (assign counter (op -) (reg counter) (const 1)) instruction: (goto (label expt-iter)) instruction: (test (op =) (reg counter) (const 0)) instruction: (branch (label expt-done)) instruction: (assign product (op *) (reg b) (reg product)) instruction: (assign counter (op -) (reg counter) (const 1)) instruction: (goto (label expt-iter)) instruction: (test (op =) (reg counter) (const 0)) instruction: (branch (label expt-done)) instruction: (assign product (op *) (reg b) (reg product)) instruction: (assign counter (op -) (reg counter) (const 1)) instruction: (goto (label expt-iter)) instruction: (test (op =) (reg counter) (const 0)) instruction: (branch (label expt-done)) done