home *** CD-ROM | disk | FTP | other *** search
- ;;;; compiler.jl -- Simple compiler for Lisp files/forms
- ;;; Copyright (C) 1993, 1994 John Harper <jsh@ukc.ac.uk>
-
- ;;; This file is part of Jade.
-
- ;;; Jade is free software; you can redistribute it and/or modify it
- ;;; under the terms of the GNU General Public License as published by
- ;;; the Free Software Foundation; either version 2, or (at your option)
- ;;; any later version.
-
- ;;; Jade is distributed in the hope that it will be useful, but
- ;;; WITHOUT ANY WARRANTY; without even the implied warranty of
- ;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ;;; GNU General Public License for more details.
-
- ;;; You should have received a copy of the GNU General Public License
- ;;; along with Jade; see the file COPYING. If not, write to
- ;;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
-
- ;;;
- ;;; The opcode of instructions which take an argument is:
- ;;; bits:
- ;;; 0->2 argument/type, 0->5 = literal, 6 = next byte, 7 = next 2 bytes.
- ;;; 3->7 opcode.
- ;;;
- ;;; If an instruction needs extra bytes only the bottom 7 bits of each are
- ;;; used, the top bit is always set. (This is so no \0 bytes end up in the
- ;;; string.)
- ;;;
- ;;; When two extra bytes are used the high 7 bits are stored first, then the
- ;;; low seven bits.
- ;;;
-
- (provide 'compiler)
-
- ;; Options
- (defvar comp-eval-constants-p t
- "When t any references to variables which are marked as being constant (ie,
- by `defconst' or `set-constant-variable') are evaluated at compile time.")
-
- (defvar comp-write-docs-p nil
- "When t all doc-strings are appended to the doc file and replaced with
- their position in that file.")
-
- ;; Opcodes
- (defconst op-call 0x08) ; call (stk[n] stk[n-1] ... stk[0])
- ;pops n values, replacing the
- ;function with the result.
- (defconst op-push 0x10) ; pushes constant # n
- (defconst op-vrefc 0x18) ; pushes val of symbol n (in c-v)
- (defconst op-vsetc 0x20) ; sets symbol n (in c-v) to stk[0],
- ;then pops the stack.
- (defconst op-list 0x28) ; makes top n items into a list
- (defconst op-bind 0x30) ; bind constant n to stk[0], pops stk
-
- (defconst op-last-with-args 0x37)
-
- (defconst op-vref 0x40) ; replace symbol with it's value
- (defconst op-vset 0x41) ; set (sym)stk[0]=stk[1], pops both
- (defconst op-fref 0x42) ; similar to vref/vset, but for
- (defconst op-fset 0x43) ;function value.
- (defconst op-init-bind 0x44) ; initialise a new set of bindings
- (defconst op-unbind 0x45) ; unbind all bindings in the top set
- (defconst op-dup 0x46) ; duplicate top of stack
- (defconst op-swap 0x47) ; swap top two values on stack
- (defconst op-pop 0x48) ; pops the stack
-
- (defconst op-nil 0x49) ; pushes nil
- (defconst op-t 0x4a) ; pushes t
- (defconst op-cons 0x4b)
- (defconst op-car 0x4c)
- (defconst op-cdr 0x4d)
- (defconst op-rplaca 0x4e)
- (defconst op-rplacd 0x4f)
- (defconst op-nth 0x50)
- (defconst op-nthcdr 0x51)
- (defconst op-aset 0x52)
- (defconst op-aref 0x53)
- (defconst op-length 0x54)
- (defconst op-eval 0x55)
- (defconst op-plus-2 0x56) ; The `-2' on the end means that it
- (defconst op-negate 0x57) ;only works on 2 arguments.
- (defconst op-minus-2 0x58)
- (defconst op-product-2 0x59)
- (defconst op-divide-2 0x5a)
- (defconst op-mod-2 0x5b)
- (defconst op-bit-not 0x5c)
- (defconst op-not 0x5d)
- (defconst op-bit-or-2 0x5e)
- (defconst op-bit-and-2 0x5f)
- (defconst op-equal 0x60)
- (defconst op-eq 0x61)
- (defconst op-num-eq 0x62)
- (defconst op-num-noteq 0x63)
- (defconst op-gtthan 0x64)
- (defconst op-gethan 0x65)
- (defconst op-ltthan 0x66)
- (defconst op-lethan 0x67)
- (defconst op-inc 0x68)
- (defconst op-dec 0x69)
- (defconst op-lsh 0x6a)
- (defconst op-zerop 0x6b)
- (defconst op-null 0x6c)
- (defconst op-atom 0x6d)
- (defconst op-consp 0x6e)
- (defconst op-listp 0x6f)
- (defconst op-numberp 0x70)
- (defconst op-stringp 0x71)
- (defconst op-vectorp 0x72)
- (defconst op-catch-kludge 0x73)
- (defconst op-throw 0x74)
- (defconst op-unwind-pro 0x75)
- (defconst op-un-unwind-pro 0x76)
- (defconst op-fboundp 0x77)
- (defconst op-boundp 0x78)
- (defconst op-symbolp 0x79)
- (defconst op-get 0x7a)
- (defconst op-put 0x7b)
- (defconst op-error-pro 0x7c)
- (defconst op-signal 0x7d)
-
- (defconst op-set-current-buffer 0xb0)
- (defconst op-swap-buffer 0xb1) ; switch to buffer stk[0], stk[0]
- ;becomes old buffer.
- (defconst op-current-buffer 0xb2)
- (defconst op-bufferp 0xb3)
- (defconst op-mark-p 0xb4)
- (defconst op-windowp 0xb5)
- (defconst op-swap-window 0xb6)
-
- (defconst op-last-before-jmps 0xfa)
-
- ;; All jmps take two-byte arguments
- (defconst op-jmp 0xfb) ; jmp to x
- (defconst op-jmp-nil 0xfc) ; pop the stack, if nil, jmp x
- (defconst op-jmp-t 0xfd) ; pop the stack, if t, jmp x
- (defconst op-jmp-nil-else-pop 0xfe) ; if stk[0] nil, jmp x, else pop
- (defconst op-jmp-t-else-pop 0xff) ; if stk[0] t, jmp x, else pop
-
- (defconst comp-max-1-byte-arg 5) ; max arg held in 1-byte instruction
- (defconst comp-max-2-byte-arg 0x7f) ; max arg held in 2-byte instruction
- (defconst comp-max-3-byte-arg 0x3fff) ; max arg help in 3-byte instruction
-
- (defvar comp-constant-alist nil) ; list of (VALUE . INDEX)
- (defvar comp-constant-index 0) ; next free constant index number
- (defvar comp-current-stack 0) ; current stack requirement
- (defvar comp-max-stack 0) ; highest possible stack
- (defvar comp-output nil) ; list of (BYTE . INDEX)
- (defvar comp-output-pc 0) ; INDEX of next byte
- (defvar comp-macro-env nil) ; alist of (NAME . MACRO-DEF)
-
- (defun compile-file (file-name)
- "(compile-file FILE-NAME)
- Compiles the file of jade-lisp code FILE-NAME into a new file called
- `(concat FILE-NAME ?c)' (ie, `foo.jl' => `foo.jlc')."
- (let*
- (src-file dst-file form comp-macro-env)
- (when (and (setq src-file (open file-name "r"))
- (setq dst-file (open (concat file-name ?c) "w")))
- (error-protect
- (unwind-protect
- (progn
- (title-now (concat "Compiling file " file-name "..."))
- (while (not (file-eof-p src-file))
- (when (setq form (comp-compile-file-form (read src-file)))
- (print form dst-file)
- (write dst-file ?\n))))
- (close dst-file)
- (close src-file))
- (error
- ;; Be sure to remove any partially written dst-file. Also, signal
- ;; the error again so that the user sees it.
- (let
- ((fname (concat file-name ?c)))
- (when (file-exists-p fname)
- (delete-file fname)))
- (funcall 'signal (car error-info) (cdr error-info))))
- t)))
-
- (defun compile-directory (dir-name &optional force-p)
- "(compile-directory DIRECTORY-NAME [FORCE-P])
- Compiles all jade-lisp files in the directory DIRECTORY-NAME whose object
- files are either older than their source file or don't exist. If FORCE-P
- is non-nil every lisp file is recompiled."
- (let
- ((dir (directory-files dir-name)))
- (while (consp dir)
- (when (regexp-match "\\.jl$" (car dir))
- (let*
- ((file (file-concat dir-name (car dir)))
- (cfile (concat file ?c)))
- (when (file-newer-than-file-p file cfile)
- (compile-file file))))
- (setq dir (cdr dir)))
- t))
-
- (defun compile-lisp-lib (&optional force-p)
- "(compile-lisp-lib [FORCE-P])
- Recompile all out of date files in the lisp library directory. If FORCE-P
- is non-nil it's as though all files were out of date.
- This makes sure that all doc strings are written to their special file."
- (let
- ((comp-write-docs-p t))
- (compile-directory lisp-lib-dir force-p)))
-
- (put 'compile-error 'error-message "Compilation mishap")
- (defun comp-error (&rest data)
- (signal 'compile-error data))
-
- (defun comp-compile-file-form (form)
- (if (not (consp form))
- form
- (let
- ((fun (car form)))
- (cond
- ((eq fun 'defun)
- (let
- ((tmp (assq (nth 1 form) comp-macro-env)))
- (when tmp
- (rplaca tmp nil)
- (rplacd tmp nil)))
- (cons 'defun
- (cons (nth 1 form)
- (cdr (comp-compile-lambda (cons 'lambda (nthcdr 2 form)))))))
- ((eq fun 'defmacro)
- (let
- ((code (comp-compile-lambda (cons 'lambda (nthcdr 2 form))))
- (tmp (assq (nth 1 form) comp-macro-env)))
- (if tmp
- (rplacd tmp code)
- (setq comp-macro-env (cons (cons (nth 1 form) code) comp-macro-env)))
- (cons 'defmacro (cons (nth 1 form) (cdr code)))))
- ((or (eq fun 'defconst) (eq fun 'defvar))
- (let
- ((doc (nth 3 form)))
- (when (and comp-write-docs-p (stringp doc))
- (rplaca (nthcdr 3 form) (add-doc-string doc))))
- form)
- ((eq fun 'require)
- (eval form)
- form)
- (t
- form)))))
-
- (defun compile-top-level-form (form)
- (let*
- (comp-constant-alist
- (comp-constant-index 0)
- (comp-current-stack 0)
- (comp-max-stack 0)
- comp-output
- (comp-output-pc 0))
- (comp-compile-form form)
- ;; Don't bother with rts, '\0' at end of string does the same.
- ;; (comp-write-op op-rts)
- (when comp-output
- (list 'lisp-code (comp-make-code-string) (comp-make-const-vec)
- comp-max-stack))))
-
- (defun comp-make-code-string ()
- (let
- ((code-string (make-string comp-output-pc ?*))
- (data comp-output))
- (while (consp data)
- (aset code-string (cdr (car data)) (car (car data)))
- (setq data (cdr data)))
- code-string))
-
- (defun comp-make-const-vec ()
- (let
- ((vec (make-vector comp-constant-index))
- (consts comp-constant-alist))
- (while (consp consts)
- (aset vec (cdr (car consts)) (car (car consts)))
- (setq consts (cdr consts)))
- vec))
-
- (defun comp-inc-stack ()
- (when (> (setq comp-current-stack (1+ comp-current-stack)) comp-max-stack)
- (setq comp-max-stack comp-current-stack)))
-
- (defmacro comp-dec-stack (&optional n)
- (list 'setq 'comp-current-stack
- (if n
- (list '- 'comp-current-stack n)
- (list '1- 'comp-current-stack))))
-
- (defun comp-compile-form (form)
- (cond
- ((eq form nil)
- (comp-write-op op-nil)
- (comp-inc-stack))
- ((eq form t)
- (comp-write-op op-t)
- (comp-inc-stack))
- ((symbolp form)
- (if (and comp-eval-constants-p (const-variable-p form))
- (comp-write-op op-push (comp-add-constant (symbol-value form)))
- (comp-write-op op-vrefc (comp-add-constant form)))
- (comp-inc-stack))
- ((consp form)
- (let
- (fun)
- (if (and (symbolp (car form)) (setq fun (get (car form) 'compile-fun)))
- (funcall fun form)
- (setq form (macroexpand form comp-macro-env))
- (if (and (symbolp (car form))
- (setq fun (get (car form) 'compile-fun)))
- (funcall fun form)
- (setq fun (car form))
- (cond
- ((symbolp fun)
- (comp-compile-constant fun))
- ((and (consp fun) (eq (car fun) 'lambda))
- (comp-compile-constant (comp-compile-lambda fun)))
- (t
- (comp-error "Bad function name" fun)))
- (setq form (cdr form))
- (let
- ((i 0))
- (while (consp form)
- (comp-compile-form (car form))
- (setq
- i (1+ i)
- form (cdr form)))
- (comp-write-op op-call i)
- (comp-dec-stack i))))))
- (t
- (comp-compile-constant form))))
-
- (defun comp-compile-constant (form)
- (comp-write-op op-push (comp-add-constant form))
- (comp-inc-stack))
-
- (defun comp-add-constant (const)
- (unless (cdr (assoc const comp-constant-alist))
- (setq
- comp-constant-alist (cons (cons const comp-constant-index) comp-constant-alist)
- comp-constant-index (1+ comp-constant-index))
- (1- comp-constant-index)))
-
- (defun comp-compile-body (body)
- (if (null body)
- (progn
- (comp-write-op op-nil)
- (comp-inc-stack))
- (while (consp body)
- (comp-compile-form (car body))
- (when (cdr body)
- (comp-write-op op-pop)
- (comp-dec-stack))
- (setq body (cdr body)))))
-
- (defun comp-compile-lambda (list)
- ;; from LIST, `(lambda (args) [docstring] body...)' returns a new list of,
- ;; `(lambda (args) [docstring] (lisp-code ...))'
- (let
- ((body (nthcdr 2 list))
- new-head)
- (cond
- ((stringp (car body))
- (setq
- body (cdr body)
- new-head (list 'lambda (nth 1 list)
- (if comp-write-docs-p
- (add-doc-string (nth 2 list))
- (nth 2 list)))))
- (t
- (setq new-head (list 'lambda (nth 1 list)))))
- (nconc new-head (cons (compile-top-level-form (cons 'progn body)) nil))))
-
- (defmacro comp-make-label ()
- ;; a label is, (PC-OF-LABEL . (LIST-OF-PC-REFERENCES))
- '(cons nil nil))
-
- (defun comp-compile-jmp (opcode label)
- (comp-byte-out opcode)
- (cond
- ((numberp (car label))
- ;; we know the final offset of this label so use it
- (comp-byte-out (bit-or 0x80 (lsh (car label) -7)))
- (comp-byte-out (bit-or 0x80 (bit-and (car label) 0x7f))))
- (t
- ;; offset unknown, show we need it patched in later
- (rplacd label (cons comp-output-pc (cdr label)))
- (setq comp-output-pc (+ comp-output-pc 2)))))
-
- (defun comp-set-label (label)
- (when (> comp-output-pc comp-max-3-byte-arg)
- (comp-error "Jump destination overflow!"))
- (rplaca label comp-output-pc)
- (setq label (cdr label))
- (while (consp label)
- (setq comp-output
- (cons
- (cons
- (bit-or 0x80 (lsh comp-output-pc -7))
- (car label))
- (cons
- (cons
- (bit-or 0x80 (bit-and comp-output-pc 0x7f))
- (1+ (car label)))
- comp-output)))
- (setq label (cdr label))))
-
- (defun comp-write-op (opcode &optional arg)
- (cond
- ((null arg)
- (comp-byte-out opcode))
- ((<= arg comp-max-1-byte-arg)
- (comp-byte-out (+ opcode arg)))
- ((<= arg comp-max-2-byte-arg)
- ;; 2-byte instruction
- (comp-byte-out (+ opcode 6))
- (comp-byte-out (bit-or 0x80 arg)))
- ((<= arg comp-max-3-byte-arg)
- ;; 3-byte instruction
- (comp-byte-out (+ opcode 7))
- (comp-byte-out (bit-or 0x80 (lsh arg -7)))
- (comp-byte-out (bit-or 0x80 (bit-and arg 0x7f))))
- (t
- (comp-error "Opcode overflow!"))))
-
- (defun comp-byte-out (byte)
- (setq
- comp-output (cons (cons byte comp-output-pc) comp-output)
- comp-output-pc (1+ comp-output-pc)))
-
- ;;;
- ;;; functions which compile non-standard functions (ie special-forms)
- ;;;
-
- (put 'if 'compile-fun 'comp-compile-if)
- (defun comp-compile-if (form)
- (comp-compile-form (nth 1 form))
- (if (= (length form) 3)
- (let*
- ((end-label (comp-make-label)))
- (comp-compile-jmp op-jmp-nil-else-pop end-label)
- (comp-dec-stack)
- (comp-compile-form (nth 2 form))
- (comp-set-label end-label))
- (let*
- ((end-label (comp-make-label))
- (else-label (comp-make-label)))
- (comp-compile-jmp op-jmp-nil else-label)
- (comp-dec-stack)
- (comp-compile-form (nth 2 form))
- (comp-compile-jmp op-jmp end-label)
- (comp-set-label else-label)
- (comp-dec-stack)
- (comp-compile-body (nthcdr 3 form))
- (comp-set-label end-label))))
-
- (put 'when 'compile-fun 'comp-compile-when)
- (defun comp-compile-when (form)
- (comp-compile-form (nth 1 form))
- (let
- ((end-label (comp-make-label)))
- (comp-compile-jmp op-jmp-nil-else-pop end-label)
- (comp-dec-stack)
- (comp-compile-body (nthcdr 2 form))
- (comp-set-label end-label)))
-
- (put 'unless 'compile-fun 'comp-compile-unless)
- (defun comp-compile-unless (form)
- (comp-compile-form (nth 1 form))
- (let
- ((end-label (comp-make-label)))
- (comp-compile-jmp op-jmp-t-else-pop end-label)
- (comp-dec-stack)
- (comp-compile-body (nthcdr 2 form))
- (comp-set-label end-label)))
-
- (put 'quote 'compile-fun 'comp-compile-quote)
- (defun comp-compile-quote (form)
- (comp-compile-constant (car (cdr form))))
-
- (put 'function 'compile-fun 'comp-compile-function)
- (defun comp-compile-function (form)
- (setq form (car (cdr form)))
- (if (symbolp form)
- (comp-compile-constant form)
- (comp-compile-constant (comp-compile-lambda form))))
-
- (put 'while 'compile-fun 'comp-compile-while)
- (defun comp-compile-while (form)
- (let*
- ((tst-label (comp-make-label))
- (end-label (comp-make-label)))
- (comp-set-label tst-label)
- (comp-compile-form (nth 1 form))
- (comp-compile-jmp op-jmp-nil-else-pop end-label)
- (comp-dec-stack)
- (comp-compile-body (nthcdr 2 form))
- (comp-write-op op-pop)
- (comp-dec-stack)
- (comp-compile-jmp op-jmp tst-label)
- (comp-set-label end-label)
- (comp-inc-stack)))
-
- (put 'progn 'compile-fun 'comp-compile-progn)
- (defun comp-compile-progn (form)
- (comp-compile-body (cdr form)))
-
- (put 'prog1 'compile-fun 'comp-compile-prog1)
- (defun comp-compile-prog1 (form)
- (comp-compile-form (nth 1 form))
- (comp-compile-body (nthcdr 2 form))
- (comp-write-op op-pop)
- (comp-dec-stack))
-
- (put 'prog2 'compile-fun 'comp-compile-prog2)
- (defun comp-compile-prog2 (form)
- (comp-compile-form (nth 1 form))
- (comp-write-op op-pop)
- (comp-dec-stack)
- (comp-compile-form (nth 2 form))
- (comp-compile-body (nthcdr 3 form))
- (comp-write-op op-pop)
- (comp-dec-stack))
-
- (put 'setq 'compile-fun 'comp-compile-setq)
- (defun comp-compile-setq (form)
- (setq form (cdr form))
- (while (and (consp form) (consp (cdr form)))
- (comp-compile-form (car (cdr form)))
- (unless (consp (nthcdr 2 form))
- (comp-write-op op-dup)
- (comp-inc-stack))
- (comp-write-op op-vsetc (comp-add-constant (car form)))
- (comp-dec-stack)
- (setq form (nthcdr 2 form))))
-
- (put 'set 'compile-fun 'comp-compile-set)
- (defun comp-compile-set (form)
- (comp-compile-form (nth 2 form))
- (comp-write-op op-dup)
- (comp-inc-stack)
- (comp-compile-form (nth 1 form))
- (comp-write-op op-vset)
- (comp-dec-stack 2))
-
- (put 'fset 'compile-fun 'comp-compile-fset)
- (defun comp-compile-fset (form)
- (comp-compile-form (nth 2 form))
- (comp-write-op op-dup)
- (comp-inc-stack)
- (comp-compile-form (nth 1 form))
- (comp-write-op op-fset)
- (comp-dec-stack 2))
-
- (put 'let* 'compile-fun 'comp-compile-let*)
- (defun comp-compile-let* (form)
- (let
- ((list (car (cdr form))))
- (comp-write-op op-init-bind)
- (while (consp list)
- (cond
- ((consp (car list))
- (let
- ((tmp (car list)))
- (comp-compile-body (cdr tmp))
- (comp-write-op op-bind (comp-add-constant (car tmp)))))
- (t
- (comp-write-op op-nil)
- (comp-inc-stack)
- (comp-write-op op-bind (comp-add-constant (car list)))))
- (comp-dec-stack)
- (setq list (cdr list)))
- (comp-compile-body (nthcdr 2 form))
- (comp-write-op op-unbind)))
-
- (put 'let 'compile-fun 'comp-compile-let)
- (defun comp-compile-let (form)
- (let
- ((list (car (cdr form)))
- (sym-stk nil))
- (comp-write-op op-init-bind)
- (while (consp list)
- (cond
- ((consp (car list))
- (setq sym-stk (cons (car (car list)) sym-stk))
- (comp-compile-body (cdr (car list))))
- (t
- (setq sym-stk (cons (car list) sym-stk))
- (comp-write-op op-nil)
- (comp-inc-stack)))
- (setq list (cdr list)))
- (while (consp sym-stk)
- (comp-write-op op-bind (comp-add-constant (car sym-stk)))
- (comp-dec-stack)
- (setq sym-stk (cdr sym-stk)))
- (comp-compile-body (nthcdr 2 form))
- (comp-write-op op-unbind)))
-
- (put 'defun 'compile-fun 'comp-compile-defun)
- (defun comp-compile-defun (form)
- (comp-compile-constant (nth 1 form))
- (comp-write-op op-dup)
- (comp-inc-stack)
- (comp-compile-constant (comp-compile-lambda (cons 'lambda (nthcdr 2 form))))
- (comp-write-op op-swap)
- (comp-write-op op-fset)
- (comp-dec-stack 2))
-
- (put 'defmacro 'compile-fun 'comp-compile-defmacro)
- (defun comp-compile-defmacro (form)
- (comp-compile-constant (nth 1 form))
- (comp-write-op op-dup)
- (comp-inc-stack)
- (comp-compile-constant (cons 'macro (comp-compile-lambda (cons 'lambda (nthcdr 2 form)))))
- (comp-write-op op-swap)
- (comp-write-op op-fset)
- (comp-dec-stack 2))
-
- (put 'cond 'compile-fun 'comp-compile-cond)
- (defun comp-compile-cond (form)
- (let
- ((end-label (comp-make-label)))
- (setq form (cdr form))
- (while (consp form)
- (let
- ((subl (car form))
- (next-label (comp-make-label)))
- (comp-compile-form (car subl))
- (comp-dec-stack)
- (cond
- ((consp (cdr subl))
- (comp-compile-jmp op-jmp-nil next-label)
- (comp-compile-body (cdr subl))
- (comp-dec-stack)
- (comp-compile-jmp op-jmp end-label)
- (comp-set-label next-label))
- (t
- (comp-compile-jmp op-jmp-t-else-pop end-label)))
- (setq form (cdr form))))
- (comp-write-op op-nil)
- (comp-inc-stack)
- (comp-set-label end-label)))
-
- (put 'or 'compile-fun 'comp-compile-or)
- (defun comp-compile-or (form)
- (let
- ((end-label (comp-make-label)))
- (setq form (cdr form))
- (while (consp form)
- (comp-compile-form (car form))
- (comp-dec-stack)
- (when (cdr form)
- (comp-compile-jmp op-jmp-t-else-pop end-label))
- (setq form (cdr form)))
- (comp-inc-stack)
- (comp-set-label end-label)))
-
- (put 'and 'compile-fun 'comp-compile-and)
- (defun comp-compile-and (form)
- (let
- ((end-label (comp-make-label)))
- (setq form (cdr form))
- (while (consp form)
- (comp-compile-form (car form))
- (comp-dec-stack)
- (when (cdr form)
- (comp-compile-jmp op-jmp-nil-else-pop end-label))
- (setq form (cdr form)))
- (comp-inc-stack)
- (comp-set-label end-label)))
-
- (put 'catch 'compile-fun 'comp-compile-catch)
- (defun comp-compile-catch (form)
- (comp-compile-constant (compile-top-level-form (cons 'progn (nthcdr 2 form))))
- (comp-compile-constant (nth 1 form))
- (comp-write-op op-catch-kludge)
- (comp-dec-stack))
-
- (put 'unwind-protect 'compile-fun 'comp-compile-unwind-pro)
- (defun comp-compile-unwind-pro (form)
- (comp-compile-constant (compile-top-level-form (cons 'progn (nthcdr 2 form))))
- (comp-write-op op-unwind-pro)
- (comp-dec-stack)
- (comp-compile-form (nth 1 form))
- (comp-write-op op-un-unwind-pro))
-
- (put 'error-protect 'compile-fun 'comp-compile-error-protect)
- (defun comp-compile-error-protect (form)
- (let
- ((i 0))
- (setq form (cdr form))
- (unless (consp form)
- (comp-error "No FORM to `error-protect'" form))
- (comp-compile-constant (compile-top-level-form (car form)))
- (setq form (cdr form))
- (while (consp form)
- (let
- ((handler (car form)))
- (unless (consp handler)
- (comp-error "Badly formed handler to `error-protect'" form))
- (comp-compile-constant (list (car handler) (compile-top-level-form (cons 'progn (cdr handler)))))
- (setq
- form (cdr form)
- i (1+ i))))
- (comp-compile-constant (1+ i))
- (comp-write-op op-error-pro)
- (comp-dec-stack i)))
-
- (put 'list 'compile-fun 'comp-compile-list)
- (defun comp-compile-list (form)
- (let
- ((count 0))
- (setq form (cdr form))
- (while (consp form)
- (comp-compile-form (car form))
- (setq
- count (1+ count)
- form (cdr form)))
- (comp-write-op op-list count)
- (comp-dec-stack (1- count))))
-
- (put 'with-buffer 'compile-fun 'comp-compile-with-buffer)
- (defun comp-compile-with-buffer (form)
- (comp-compile-form (nth 1 form))
- (comp-write-op op-swap-buffer)
- (comp-compile-body (nthcdr 2 form))
- (comp-write-op op-swap)
- (comp-write-op op-swap-buffer)
- (comp-write-op op-pop)
- (comp-dec-stack))
-
- (put 'with-window 'compile-fun 'comp-compile-with-window)
- (defun comp-compile-with-window (form)
- (comp-compile-form (nth 1 form))
- (comp-write-op op-swap-window)
- (comp-compile-body (nthcdr 2 form))
- (comp-write-op op-swap)
- (comp-write-op op-swap-window)
- (comp-write-op op-pop)
- (comp-dec-stack))
-
- (put '- 'compile-fun 'comp-compile-minus)
- (put '- 'compile-opcode op-minus-2)
- (defun comp-compile-minus (form)
- (if (/= (length form) 2)
- (comp-compile-binary-op form)
- (comp-compile-form (car (cdr form)))
- (comp-write-op op-negate)))
-
- (defun comp-compile-0-args (form)
- (comp-write-op (get (car form) 'compile-opcode) 0)
- (comp-inc-stack))
-
- (defun comp-compile-1-args (form)
- (comp-compile-form (nth 1 form))
- (comp-write-op (get (car form) 'compile-opcode) 0))
-
- (defun comp-compile-2-args (form)
- (comp-compile-form (nth 1 form))
- (comp-compile-form (nth 2 form))
- (comp-write-op (get (car form) 'compile-opcode) 0)
- (comp-dec-stack))
-
- (defun comp-compile-3-args (form)
- (comp-compile-form (nth 1 form))
- (comp-compile-form (nth 2 form))
- (comp-compile-form (nth 3 form))
- (comp-write-op (get (car form) 'compile-opcode) 0)
- (comp-dec-stack 2))
-
- (defun comp-compile-binary-op (form)
- (let
- ((opcode (get (car form) 'compile-opcode)))
- (setq form (cdr form))
- (unless (>= (length form) 2)
- (comp-error "Too few args to binary operator" form))
- (comp-compile-form (car form))
- (setq form (cdr form))
- (while (consp form)
- (comp-compile-form (car form))
- (comp-write-op opcode)
- (comp-dec-stack)
- (setq form (cdr form)))))
-
- (put 'cons 'compile-fun 'comp-compile-2-args)
- (put 'cons 'compile-opcode op-cons)
- (put 'car 'compile-fun 'comp-compile-1-args)
- (put 'car 'compile-opcode op-car)
- (put 'cdr 'compile-fun 'comp-compile-1-args)
- (put 'cdr 'compile-opcode op-cdr)
- (put 'rplaca 'compile-fun 'comp-compile-2-args)
- (put 'rplaca 'compile-opcode op-rplaca)
- (put 'rplacd 'compile-fun 'comp-compile-2-args)
- (put 'rplacd 'compile-opcode op-rplacd)
- (put 'nth 'compile-fun 'comp-compile-2-args)
- (put 'nth 'compile-opcode op-nth)
- (put 'nthcdr 'compile-fun 'comp-compile-2-args)
- (put 'nthcdr 'compile-opcode op-nthcdr)
- (put 'aset 'compile-fun 'comp-compile-3-args)
- (put 'aset 'compile-opcode op-aset)
- (put 'aref 'compile-fun 'comp-compile-2-args)
- (put 'aref 'compile-opcode op-aref)
- (put 'length 'compile-fun 'comp-compile-1-args)
- (put 'length 'compile-opcode op-length)
- (put 'eval 'compile-fun 'comp-compile-1-args)
- (put 'eval 'compile-opcode op-eval)
- (put '+ 'compile-fun 'comp-compile-binary-op)
- (put '+ 'compile-opcode op-plus-2)
- (put '* 'compile-fun 'comp-compile-binary-op)
- (put '* 'compile-opcode op-product-2)
- (put '/ 'compile-fun 'comp-compile-binary-op)
- (put '/ 'compile-opcode op-divide-2)
- (put 'mod 'compile-fun 'comp-compile-binary-op)
- (put 'mod 'compile-opcode op-mod-2)
- (put 'bit-not 'compile-fun 'comp-compile-1-args)
- (put 'bit-not 'compile-opcode op-bit-not)
- (put 'not 'compile-fun 'comp-compile-1-args)
- (put 'not 'compile-opcode op-not)
- (put 'bit-or 'compile-fun 'comp-compile-binary-op)
- (put 'bit-or 'compile-opcode op-bit-or-2)
- (put 'bit-and 'compile-fun 'comp-compile-binary-op)
- (put 'bit-and 'compile-opcode op-bit-and-2)
- (put 'equal 'compile-fun 'comp-compile-2-args)
- (put 'equal 'compile-opcode op-equal)
- (put 'eq 'compile-fun 'comp-compile-2-args)
- (put 'eq 'compile-opcode op-eq)
- (put '= 'compile-fun 'comp-compile-2-args)
- (put '= 'compile-opcode op-num-eq)
- (put '/= 'compile-fun 'comp-compile-2-args)
- (put '/= 'compile-opcode op-num-noteq)
- (put '> 'compile-fun 'comp-compile-2-args)
- (put '> 'compile-opcode op-gtthan)
- (put '< 'compile-fun 'comp-compile-2-args)
- (put '< 'compile-opcode op-ltthan)
- (put '>= 'compile-fun 'comp-compile-2-args)
- (put '>= 'compile-opcode op-gethan)
- (put '<= 'compile-fun 'comp-compile-2-args)
- (put '<= 'compile-opcode op-lethan)
- (put '1+ 'compile-fun 'comp-compile-1-args)
- (put '1+ 'compile-opcode op-inc)
- (put '1- 'compile-fun 'comp-compile-1-args)
- (put '1- 'compile-opcode op-dec)
- (put 'lsh 'compile-fun 'comp-compile-2-args)
- (put 'lsh 'compile-opcode op-lsh)
- (put 'zerop 'compile-fun 'comp-compile-1-args)
- (put 'zerop 'compile-opcode op-zerop)
- (put 'null 'compile-fun 'comp-compile-1-args)
- (put 'null 'compile-opcode op-null)
- (put 'atom 'compile-fun 'comp-compile-1-args)
- (put 'atom 'compile-opcode op-atom)
- (put 'consp 'compile-fun 'comp-compile-1-args)
- (put 'consp 'compile-opcode op-consp)
- (put 'listp 'compile-fun 'comp-compile-1-args)
- (put 'listp 'compile-opcode op-listp)
- (put 'numberp 'compile-fun 'comp-compile-1-args)
- (put 'numberp 'compile-opcode op-numberp)
- (put 'stringp 'compile-fun 'comp-compile-1-args)
- (put 'stringp 'compile-opcode op-stringp)
- (put 'vectorp 'compile-fun 'comp-compile-1-args)
- (put 'vectorp 'compile-opcode op-vectorp)
- (put 'throw 'compile-fun 'comp-compile-2-args)
- (put 'throw 'compile-opcode op-throw)
- (put 'fboundp 'compile-fun 'comp-compile-1-args)
- (put 'fboundp 'compile-opcode op-fboundp)
- (put 'boundp 'compile-fun 'comp-compile-1-args)
- (put 'boundp 'compile-opcode op-boundp)
- (put 'symbolp 'compile-fun 'comp-compile-1-args)
- (put 'symbolp 'compile-opcode op-symbolp)
- (put 'get 'compile-fun 'comp-compile-2-args)
- (put 'get 'compile-opcode op-get)
- (put 'put 'compile-fun 'comp-compile-3-args)
- (put 'put 'compile-opcode op-put)
- (put 'signal 'compile-fun 'comp-compile-2-args)
- (put 'signal 'compile-opcode op-signal)
-
- (put 'set-current-buffer 'compile-fun 'comp-compile-2-args)
- (put 'set-current-buffer 'compile-opcode op-set-current-buffer)
- (put 'current-buffer 'compile-fun 'comp-compile-1-args)
- (put 'current-buffer 'compile-opcode op-current-buffer)
- (put 'bufferp 'compile-fun 'comp-compile-1-args)
- (put 'bufferp 'compile-opcode op-bufferp)
- (put 'mark-p 'compile-fun 'comp-compile-1-args)
- (put 'mark-p 'compile-opcode op-mark-p)
- (put 'windowp 'compile-fun 'comp-compile-1-args)
- (put 'windowp 'compile-opcode op-windowp)
-