<< Previous exercise (5.10) | Index | Next exercise (5.12) >>
I took a different path than everyone else... I ended up creating a stack-table similar to the register table.
;; Allocate a stack (define (allocate-stack name) (if (assoc name stack-table) (error "Multiply defined stacks: " name) (set! stack-table (cons (list name (make-stack)) stack-table))) 'stack-allocated) ;; Then when initializing machine in (make-machine ...) (for-each (lambda (reg-name) ;; New stack for each register ((machine 'allocate-stack) reg-name)) register-names) ;; Initializing all stacks becomes this: (the-ops (list (list 'initialize-stack (lambda () (for-each (lambda (stack) (stack 'initialize)) (map cadr stack-table))))))
;; c. alt.1 (define (make-save inst machine stack pc) (let ((reg (get-register machine (stack-inst-reg-name inst)))) (lambda () (push stack (cons reg (get-contents reg))) ;** (advance-pc pc)))) (define (pop stack reg) (let loop ((items '()) (top (stack 'pop))) (if (eq? (car top) reg) (begin (for-each (lambda (e) (push stack e)) (reverse items)) top) (loop (cons top items) (stack 'pop))))) (define (make-restore inst machine stack pc) (let ((reg (get-register machine (stack-inst-reg-name inst)))) (lambda () (set-contents! reg (pop stack reg)) ;** (advance-pc pc)))) ;;; c. alt.2 (define (make-machine register-names ops controller-text) (let ((machine (make-new-machine))) (for-each (lambda (register-name) ((machine 'allocate-register) register-name) ((machine 'allocate-stack) register-name)) ;++ register-names) ((machine 'install-operations) ops) ((machine 'install-instruction-sequence) (assemble controller-text machine)) machine)) (define (make-new-machine) (let ((pc (make-register 'pc)) (flag (make-register 'flag)) ;; (stack (make-stack)) (the-instruction-sequence '())) (let ((the-ops '()) (register-table (list (list 'pc pc) (list 'flag flag))) (stack-table '())) (define (allocate-register name) (if (assoc name register-table) (error "Multiply defined register: " name) (set! register-table (cons (list name (make-register name)) register-table))) 'register-allocated) (define (allocate-stack name) ;++ (if (assoc name stack-table) (error "Multiply defined register: " name) (set! stack-table (cons (list name (make-stack)) stack-table))) 'stack-allocated) (define (lookup-register name) (let ((val (assoc name register-table))) (if val (cadr val) (error "Unknown register:" name)))) (define (lookup-stack name) ;** (let ((val (assoc name stack-table))) (if val (cadr val) (error "Unknown stack:" name)))) (define (execute) (let ((insts (get-contents pc))) (if (null? insts) 'done (begin ((instruction-execution-proc (car insts))) (execute))))) (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 'allocate-stack) allocate-stack) ;** ((eq? message 'get-register) lookup-register) ((eq? message 'get-stack) lookup-stack) ;** ((eq? message 'install-operations) (lambda (ops) (set! the-ops (append the-ops ops)))) ((eq? message 'stack) stack) ((eq? message 'operations) the-ops) (else (error "Unknown request -- MACHINE" message)))) dispatch))) (define (update-insts! insts labels machine) (let ((pc (get-register machine 'pc)) (flag (get-register machine 'flag)) ;; (stack (machine 'stack)) (ops (machine 'operations))) (for-each (lambda (inst) (set-instruction-execution-proc! inst (make-execution-procedure (instruction-text inst) labels machine pc flag ops))) ;** insts))) (define (make-execution-procedure inst labels machine pc flag ops) (cond ((eq? (car inst) 'assign) (make-assign inst machine labels ops pc)) ((eq? (car inst) 'test) (make-test inst machine labels ops flag pc)) ((eq? (car inst) 'branch) (make-branch inst machine labels flag pc)) ((eq? (car inst) 'goto) (make-goto inst machine labels pc)) ((eq? (car inst) 'save) (make-save inst machine pc)) ;** ((eq? (car inst) 'restore) (make-restore inst machine pc)) ;** ((eq? (car inst) 'perform) (make-perform inst machine labels ops pc)) (else (error "Unknown instruction type -- ASSEMBLE" inst)))) (define (get-stack machine reg-name) ((machine 'get-stack) reg-name)) (define (make-save inst machine pc) (let* ((reg-name (stack-inst-reg-name inst)) (reg (get-register machine reg-name)) (stack (get-stack machine reg-name))) (lambda () (push stack (get-contents reg)) (advance-pc pc)))) (define (make-restore inst machine stack pc) (let* ((reg-name (stack-inst-reg-name inst)) (reg (get-register machine reg-name)) (stack (get-stack machine reg-name))) (lambda () (set-contents! reg (pop stack)) (advance-pc pc))))
verdammelt