First attempt at macro assembly
Saturday, January 24th, 2009Now that I’ve got an interpreter that I’m satisfied with, I’m going back to the problem of compilation and assembly.
I moved the “assembler” up one level, so that it is interpreted by my high level interpreter, rather than the base interpreter. I had to copy a few of the support routines from the lower level.
Then I made an attempt at a macro facility for the assembler. It didn’t come together quite right. After I stepped back and thought about it, I realized that I had created code generators, rather than macros. That was because the “macros” wrote directly to the output file, rather than sending back data for another translation.
Here are the primary procedures:
(translate
(lambda (x)
(cond
((symbol? x)
(write-sym x)
(write-octet (integer->octet 58))
(write-newline))
((find-codegen (first x)) ((second (find-codegen (first x))) x))
(#t
(write-sym (car x))
(cond
((null? (cdr x)) (quote ()))
(#t
(write-octet (integer->octet 32))
(write-operand (car (cdr x)))
(cond
((null? (cdr (cdr x))) (quote ()))
(#t
(write-octet (integer->octet 44))
(write-operand (car (cdr (cdr x))))))))
(write-newline)))))
(find-codegen
(lambda (x)
(assq x codegenlist)))
(write-operand-list-tail
(lambda (x)
(cond
((null? x) (quote ()))
(#t
(write-octet (integer->octet 44))
(write-operand (car x))
(write-operand-list-tail (cdr x))))))
(write-newline
(lambda ()
(write-octet (integer->octet 13))
(write-octet (integer->octet 10))))
By giving the code generator the entire form, it is possible to share code generators for several assembly instructions. The following shows how the code generators can be written and shared:
;;;
;;; Define code generators
;;;
(set! label-op-opd
(lambda (form)
(write-sym (second form))
(write-octet (integer->octet 32)) ; the space character
(write-sym (first form))
(write-octet (integer->octet 32)) ; the space character
(write-operand (third form))
(write-newline)))
(set! op-opd*
(lambda (form)
(write-sym (car form))
(write-octet (integer->octet 32)) ; the space character
(write-operand (car(cdr form)))
(write-operand-list-tail (cdr(cdr form)))
(write-newline)))
;;;
;;; Bind names to code generators
;;;
(set! codegenlist
(list
(list 'equ label-op-opd)
(list 'label label-op-opd)
(list 'db op-opd*)
(list 'dd op-opd*)))
;;;
;;; Run translator
;;;
(open-output (cdr 'SchCode.inc))
(for-each translate code)
(close-output)