(* Filed on: {phylum}<desrivieres>nlisp>aardvark *) (* Aardvark - #1 compiler for 2-LISP. *) (* Last modified: Nov. 8th, 1983 by Jim des Rivieres. *) (* Mode: InTeRlIsP *) (globalvars *return-opcode* *const-opcode* *var-opcode* *pcheck-opcode* *call-opcode* *tail-call-opcode* *call-objectified-opcode* *tail-call-objectified-opcode* *lambda-opcode* *if-opcode* *primitive-opcode* *gset-opcode* *rcons-opcode* *halt-opcode*) (defun initialise-aardvark () (setq *return-opcode* 0) (setq *const-opcode* 1) (setq *var-opcode* 2) (setq *pcheck-opcode* 3) (setq *call-opcode* 4) (setq *tail-call-opcode* 5) (setq *call-objectified-opcode* 6) (setq *tail-call-objectified-opcode* 7) (setq *lambda-opcode* 8) (setq *if-opcode* 9) (setq *primitive-opcode* 10) (setq *gset-opcode* 11) (setq *rcons-opcode* 12) (setq *halt-opcode* 13)) (defun a-prettycode (code) (for x in code collect (cons (a-opcode (car x)) (if (equal (car x) *if-opcode*) then (cons (a-prettycode (cadr x)) (cons (a-prettycode (caddr x)) (cdddr x))) else if (equal (car x) *lambda-opcode*) then (cons (cadr x) (cons (a-prettycode (caddr x)) (cdddr x))) else (cdr x))))) (defun a-opcode (n) (select n (*return-opcode* 'return) (*const-opcode* 'const) (*var-opcode* 'var) (*pcheck-opcode* 'pcheck) (*call-opcode* 'call) (*tail-call-opcode* 'tail-call) (*call-objectified-opcode* 'call-objectified) (*tail-call-objectified-opcode* 'tail-call-objectified) (*lambda-opcode* 'lambda) (*if-opcode* 'if) (*primitive-opcode* 'primitive) (*gset-opcode* 'gset) (*rcons-opcode* 'rcons) (*halt-opcode* 'halt) (list '**bad-opcode** n))) (defun ac (x) (a-prettycode (aardvark (import x) global-env))) (defun aardvark (exp env) (a-compile exp env ())) (defun a-compile (exp env code) (cond ((atom? exp) (a-compile-variable exp env code)) ((rail? exp) (a-compile-rail exp env code)) ((pair? exp) (a-compile-pair exp env code)) (t (a-compile-constant exp env code)) )) (defun a-terminate (code) (if (null code) then (list (list *return-opcode*)) else code)) (defun a-compile-constant (exp env code) (cons (list *const-opcode* exp) (a-terminate code))) (defun a-compile-variable (exp env code) (cons (list *var-opcode* exp) (a-terminate code))) (defun a-binding (var env) (if (null env) then (let ((val (gethash var global-env-hash-array))) (if (eq val 'nil.surrogate) then nil else if (null val) then 'not.found else val)) else (if (member var (car env)) then 'local.variable else (a-binding var (cdr env))))) (defun a-compile-pair (exp env code) (let ((proc (pcar exp))) (if (and (not (atom? proc)) (not (closure? proc))) then (a-compile-application exp env code) else (let ((expectation (if (atom? proc) then (a-binding proc env) else proc))) (cond ((lambda? expectation) (a-compile-lambda exp env code)) ((if? expectation) (a-compile-if exp env code)) ((gset? expectation) (a-compile-gset exp env code)) ((let? expectation) (a-compile-let exp env code)) (t (a-compile-application exp env code))))))) (defun a-compile-application (exp env code) (let ((proc (pcar exp)) (args (pcdr exp))) (a-compile proc env (cons (list *pcheck-opcode*) (if (rail? args) then (a-compile-tail args env (if (not (null code)) then (cons (list *call-opcode* (rlength args)) code) else (list (list *tail-call-opcode* (rlength args))))) else (a-compile args env (if (not (null code)) then (cons (list *call-objectified-opcode*) code) else (list (list *tail-call-objectified-opcode*))))))))) (defun a-compile-tail (exp env code) (if (empty? exp) then code else (a-compile (first exp) env (a-compile-tail (rest exp) env code)))) (defun a-compile-rail (exp env code) (a-compile-tail exp env (cons (list *rcons-opcode* (rlength exp)) (a-terminate code)))) (defun a-compile-lambda (exp env code) (let ((args (pcdr exp))) (if (or (not (rail? args)) (not (equal (rlength args) 2))) then (a-compilation-error "Mangled LAMBDA" exp)) (let ((pattern-info (a-analyze-pattern (first args))) (body (second args))) (let ((compiled-body (a-compile body (cons (cadr pattern-info) env) (list)))) (cons (list *lambda-opcode* pattern-info compiled-body) (a-terminate code)))))) (defun a-analyze-pattern (pat) (cond ((atom? pat) (list -1 (extract-atom pat))) ((rail? pat) (let ((var-list (rail-to-list pat))) (if (every var-list 'atom?) then (cons (length var-list) (reverse var-list)) else (a-compilation-error "Mangled LAMBDA pattern" pat)))) (t (a-compilation-error "Mangled LAMBDA pattern" pat)))) (defun a-compile-if (exp env code) (let ((args (pcdr exp))) (if (or (not (rail? args)) (not (equal (rlength args) 3))) then (a-compilation-error "Mangled IF" exp)) (let ((premise (first args)) (consequent (second args)) (alternate (third args))) (a-compile premise env (list (list *if-opcode* (a-compile consequent env code) (a-compile alternate env code))))))) (defun a-compile-gset (exp env code) (let ((args (pcdr exp))) (if (or (not (rail? args)) (not (equal (rlength args) 2)) (not (atom? (first args)))) then (a-compilation-error "Mangled GSET" exp)) (let ((variable (first args)) (rhs (second args))) (a-compile rhs env (cons (list *gset-opcode* variable) (a-terminate code)))))) (defun a-compile-let (exp env code) (let ((args (pcdr exp))) (if (or (not (rail? args)) (not (equal (rlength args) 2)) (not (rail? (first args)))) then (a-compilation-error "Mangled LET" exp)) (let ((body (second args)) (binding-pairs (for x in (rail-to-list (first args)) collect (if (or (not (rail? x)) (not (equal (rlength x) 2)) (not (atom? (first x)))) then (a-compilation-error "Mangled LET" exp)) (list (first x) (second x))) )) (a-compile (pcons (pcons lambda-closure (prep (list-to-rail (mapcar binding-pairs 'car)) (prep body (rcons0)))) (list-to-rail (mapcar binding-pairs 'cadr))) env code)))) STOP