1 (make-machine <regs> <ops> <controller>)
3 (set-register-contents! <machine> <reg> <value>)
4 (get-register-contents <machine> <reg>)
6 (define (make-register name)
7 (let ((contents '*unassigned*))
8 (define (dispatch message)
9 (cond ((eq? message 'get) contents)
11 (lambda (val) (set! contents val)))
13 (error "Unknown request -- REGISTER"
17 (define (get-contents reg)
19 (define (set-contents! reg val)
29 (set! number-pushes (+ number-pushes 1))
30 (set! current-depth (+ current-depth 1))
31 (set! max-depth (max max-depth current-depth)))
34 (error "Empty stack -- POP")
37 (set! current-depth (- current-depth 1))
41 (set! number-pushes 0)
42 (set! current-depth 0)
44 (define (print-statistics)
45 `(total-pushes = ,number-pushes
46 max-depth = ,max-depth))
47 (define (dispatch message)
48 (cond ((eq? message 'push) push)
49 ((eq? message 'pop) (pop))
50 ((eq? message 'initialize) (initialize))
51 ((eq? message 'print-statistics) (print-statistics))
53 (error "Unknown request -- STACK"
56 (define (push stack val)
61 (define (make-machine regs ops controller)
62 (let ((machine (make-new-machine)))
65 ((machine 'allocate-register) reg))
67 ((machine 'install-operations) ops)
68 ((machine 'install-instruction-sequence)
69 (assemble controller machine))
72 (define (make-new-machine)
73 (let* ((pc (make-register 'pc))
74 (flag (make-register 'flag))
76 (the-instruction-sequence '())
82 ,(lambda () (stack 'initialize)))
84 ,(lambda () (stack 'print-statistics))))))
86 (let ((insts (get-contents pc)))
89 (begin ((instruction-proc (car insts)))
91 (define (allocate-register name)
92 (let ((val (assoc name register-table)))
94 (error "Multiply defined register: " name)
96 (cons (list name (make-register name))
98 (define (lookup-register name)
99 (let ((val (assoc name register-table)))
102 (error "Undefined register: " name))))
103 (define (dispatch message)
104 (cond ((eq? message 'start)
105 (set-contents! pc the-instruction-sequence)
107 ((eq? message 'allocate-register) allocate-register)
108 ((eq? message 'get-register) lookup-register)
109 ((eq? message 'install-operations)
110 (lambda (ops) (set! the-ops (append the-ops ops))))
111 ((eq? message 'install-instruction-sequence)
112 (lambda (seq) (set! the-instruction-sequence seq)))
113 ((eq? message 'stack) stack)
114 ((eq? message 'operations) the-ops)))
117 (define (make-instruction text)
119 (define (instruction-proc inst)
121 (define (instruction-text inst)
123 (define (set-instruction-proc! inst proc)
124 (set-cdr! inst proc))
126 (define (start machine)
128 (define (get-register machine reg-name)
129 ((machine 'get-register) reg-name))
130 (define (set-register-contents! machine reg val)
131 (set-contents! (get-register machine reg) val)
133 (define (get-register-contents machine reg)
134 (get-contents (get-register machine reg)))
136 (define (assemble controller-text machine)
139 (lambda (insts labels)
140 (update-insts! insts labels machine)
142 (define (extract-labels text receive)
147 (lambda (insts labels)
148 (let ((next-inst (car text)))
149 (if (symbol? next-inst)
152 (cons (make-label-entry next-inst insts) labels))
154 (cons (make-instruction next-inst) insts)
157 (define (extract-labels text)
160 (let* ((result (extract-labels (cdr text)))
162 (labels (cdr result))
163 (next-inst (car text)))
164 (if (symbol? next-inst)
166 (cons (make-label-entry next-inst insts)
168 (cons (cons (make-instruction next-inst) insts)
170 (define (assemble controller machine)
171 (let* ((result (extract-labels controller))
173 (labels (cdr result)))
174 (update-insts! insts labels machine)
177 (define (update-insts! insts labels machine)
178 (let* ((pc (get-register machine 'pc))
179 (flag (get-register machine 'flag))
180 (stack (machine 'stack))
181 (ops (machine 'operations)))
184 (set-instruction-proc!
186 (make-execution-procedure
187 (instruction-text inst) labels machine
191 (define (make-execution-procedure text labels machine
193 (cond ((eq? (car text) 'assign)
195 text machine labels ops pc))
196 ((eq? (car text) 'test)
198 text machine labels ops pc))
199 ((eq? (car text) 'branch)
201 text machine labels flag pc))
202 ((eq? (car text) 'goto)
204 text machine labels pc))
205 ((eq? (car text) 'perform)
207 text machine labels ops pc))
208 ((eq? (car text) 'save)
210 text machine stack pc))
211 ((eq? (car text) 'restore)
213 text machine stack pc))
215 (error "Unknown instruction type -- ASSEMBLE"
217 (define (make-assign inst machine labels ops pc)
218 (let* ((reg (get-register machine (assign-reg-name inst)))
219 (value-exp (assign-reg-value inst))
221 (if (operation-exp? value-exp)
223 value-exp machine labels ops)
225 (car value-exp) machine labels))))
227 (set-contents! reg (value-proc))
229 (define (assign-reg-name inst)
231 (define (assign-reg-value inst)
233 (define (advance-pc pc)
234 (set-contents! pc (cdr (get-contents pc))))
235 (define (make-test inst machine labels ops pc)
236 (let* ((test (test-cond inst)))
237 (if (operation-exp? test)
238 (let ((test-proc (make-operation-exp
239 test machine labels ops)))
241 (set-contents! flag (test-proc))
243 (error "Bad TEST instruction -- ASSEMBLE"
245 (define (test-cond exp)
247 (define (make-branch text machine labels flag pc)
248 (let ((dest (branch-dest text)))
249 (if (label-exp? dest)
250 (let ((insts (lookup-label labels (label-exp-label dest))))
252 (if (get-contents flag)
253 (set-contents! pc insts)
255 (error "Bad BRANCH instruction -- ASSEMBLE"
257 (define (branch-dest exp)
259 (define (make-goto text machine labels pc)
260 (let ((dest (goto-dest text)))
261 (cond ((register-exp? dest)
262 (let ((reg (get-register machine (register-exp-name dest))))
264 (set-contents! pc (get-contents reg)))))
266 (let ((insts (lookup-label labels (label-exp-label dest))))
268 (set-contents! pc insts))))
270 (error "Bad GOTO instruction -- ASSEMBLE"
272 (define (goto-dest exp)
274 (define (make-perform text machine labels ops pc)
275 (let ((action (perform-action text)))
276 (if (operation-exp? action)
277 (let ((action-proc (make-operation-exp
278 action machine labels ops)))
282 (error "Bad PERFORM instruction -- ASSEMBLE"
284 (define (perform-action exp)
286 (define (make-save text machine stack pc)
287 (let ((reg (get-register machine (stack-inst-reg text))))
289 (push stack (get-contents reg))
291 (define (stack-inst-reg exp)
293 (define (make-restore text machine stack pc)
294 (let ((reg (get-register machine (stack-inst-reg text))))
296 (set-contents! reg (pop stack))
299 (define (make-primitive-exp exp machine labels)
300 (cond ((register-exp? exp)
301 (let ((reg (get-register machine (register-exp-name exp))))
303 (get-contents reg))))
305 (let ((val (const-exp-value exp)))
308 (let ((insts (lookup-label labels (label-exp-label exp))))
311 "Unknown expression type -- ASSEMBLE"
313 (define (register-exp? exp)
314 (tagged-list? exp 'reg))
315 (define (register-exp-name exp)
317 (define (const-exp? exp)
318 (tagged-list? exp 'const))
319 (define (const-exp-value exp)
321 (define (label-exp? exp)
322 (tagged-list? exp 'label))
323 (define (label-exp-label exp)
325 (define (make-operation-exp exp machine labels ops)
326 (let* ((proc (lookup-prim (operation-exp-op exp) ops))
331 (operation-exp-operands exp))))
333 (apply proc (map (lambda (p) (p)) aprocs)))))
334 (define (operation-exp? exp)
335 (and (pair? exp) (tagged-list? (car exp) 'op))))
336 (define (operation-exp-op exp)
338 (define (operation-exp-operands exp)
340 (define (lookup-prim symbol ops)
341 (let ((val (assoc symbol ops)))
344 (error "Undefined operation -- ASSEMBLE"
346 (define (make-label-entry label insts)
348 (define (lookup-label labels label-name)
349 (let ((val (assoc label-name labels)))
352 (error "Undefined label -- ASSEMBLE"