Chapter 5, Computing with Register Machines

Exercise 5.18


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
(define (make-register name)
  (let ((contents '*unassigned*)
		(trace-on false))
    (define (dispatch message)
      (cond ((eq? message 'get) contents)
            ((eq? message 'set)
             (lambda (value)
			   (if trace-on
				   (begin
					 (newline)
					 (display "Changing reg-")
					 (display name)
					 (display " old-val: ")
					 (display contents)
					 (display " new-val: ")
					 (display value)))
			   (set! contents value)))
			((eq? message 'trace-on) (set! trace-on true))
			((eq? message 'trace-off) (set! trace-on false))
            (else
             (error "Unknown request -- REGISTER" message))))
    dispatch))

;;;CHANGES IN DISPATCH PROCEDURE IN make-new-machine
;;note the to support variable number of arguments we need to separate first-register
;; and other registers (lambda (first-reg . reg-names))
(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 (ops) (set! the-ops (append the-ops ops))))
        ((eq? message 'stack) stack)
        ((eq? message 'operations) the-ops)
        ((eq? message 'reset-instruction-count) (reset-instruction-count))
        ((eq? message 'trace-on) (set! trace-on true))
        ((eq? message 'trace-off) (set! trace-on false))
        ((eq? message 'registers-trace-on)
		 (lambda (first-reg . reg-names)
		   (for-each (lambda(reg-name)
					   ((lookup-register reg-name) 'trace-on))
					 (cons first-reg reg-names))))
        ((eq? message 'registers-trace-off)
		 (lambda (first-reg . reg-names)
		   (for-each (lambda(reg-name)
					   ((lookup-register reg-name) 'trace-off))
					 (cons first-reg reg-names))))
        (else (error "Unknown request -- MACHINE" message))))

Output:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
1 ]=> 
(define gcd-machine
  (make-machine
   '(a b t)
   (list (list 'rem remainder) (list '= =))
   '(test-b
	 dummy-label
       (test (op =) (reg b) (const 0))
       (branch (label gcd-done))
       (assign t (op rem) (reg a) (reg b))
       (assign a (reg b))
       (assign b (reg t))
       (goto (label test-b))
       gcd-done)))

((gcd-machine 'registers-trace-on) 'a 'b)
(set-register-contents! gcd-machine 'a 50)
(set-register-contents! gcd-machine 'b 375)
(start gcd-machine)

;Value 18: (register simulator loaded)

1 ]=> 
;Value: gcd-machine

1 ]=> 
;Unspecified return value

1 ]=> 
Changing reg-a old-val: *unassigned* new-val: 50
;Value: done

1 ]=> 
Changing reg-b old-val: *unassigned* new-val: 375
;Value: done

1 ]=> 
Changing reg-a old-val: 50 new-val: 375
Changing reg-b old-val: 375 new-val: 50
Changing reg-a old-val: 375 new-val: 50
Changing reg-b old-val: 50 new-val: 25
Changing reg-a old-val: 50 new-val: 25
Changing reg-b old-val: 25 new-val: 0
;Value: done

1 ]=>