2010-m1s1-compilation/implementation/compilation.lisp
2010-11-03 00:04:35 +01:00

123 lines
3.2 KiB
Common Lisp

(load "../util")
(load "lisp2lic")
(defvar asm-fixnum-size 8)
(defvar asm-max-fixnum (expt 2 asm-fixnum-size))
(defun type-number (type)
(position type '(fixnum bignum symbol string cons)))
(defvar label-ctr 0)
;; My-compile
(defvar result-data nil)
(defvar result-asm nil)
(defun data (&rest args)
(push (apply #'format nil args) result-data))
(defun asm (&rest args)
(push (apply #'format nil args) result-asm))
(defmacro my-compile (expr)
`(progn (setq result-data nil)
(setq result-asm nil)
(my-compile1 (lisp2cli ',expr))
(format nil
"section .data~%~
~{~%~a~}~%~
~%section .text~%~
~{~%~a~}"
(reverse result-data)
(reverse result-asm)
)))
(defvar compile-rules-conditions '())
(defvar compile-rules-functions '())
(defun my-compile1 (expr)
(some (lambda (condition rule)
(if (funcall (cdr condition) expr)
(funcall (cdr rule) expr)))
compile-rules-conditions
compile-rules-functions))
(defmacro defcompile-rule (name condition &rest body)
`(progn (aset ',name (lambda (expr) ,condition) compile-rules-conditions)
(aset ',name (lambda (expr) ,@body) compile-rules-functions)))
;;; Règles de compilation
(defcompile-rule fixnum (match (? numberp (< x asm-max-fixnum)) expr)
(data "fixnum-constant-~a:" (incf label-ctr))
(data "db ~a" (type-number 'fixnum))
(data "db ~a" expr)
(format nil "fixnum-constant-~a" label-ctr))
(defcompile-rule bignum (match (? numberp (>= expr asm-max-fixnum)) expr)
(data "bignum-constant-~a:" (incf label-ctr))
(data "db ~a" (type-number 'bignum))
(let ((lst (split-bytes expr asm-fixnum-size)))
(data "~{~&db ~a~}" (cons (length lst) lst)))
(format nil "bignum-constant-~a" label-ctr))
(defcompile-rule string (match (? stringp) expr)
(data "string-constant-~a:" (incf label-ctr))
(data "db ~a" (type-number 'string))
(data "db ~a" (length expr))
(data "~{~&db ~a~}" (map 'list #'char-code expr))
(format nil "string-constant-~a" label-ctr))
(defcompile-rule symbol (match (? symbolp) expr)
(let ((name (my-compile1 (string expr))))
(data "symbol-~a:" (incf label-ctr))
(data "db ~a" (type-number 'symbol))
(data "db @~a" name)
(format nil "symbol-~a" label-ctr)))
(defcompile-rule cons (match (quote (_ . _)) expr)
(print "")
(print expr)
(print (list 'quote (caadr expr)))
(print (list 'quote (cdadr expr)))
(let ((left (my-compile1 (list 'quote (caadr expr))))
(right (my-compile1 (list 'quote (cdadr expr)))))
; (let ((left "foo")
; (right "bar"))
(data "cons-~a:" (incf label-ctr))
(data "db ~a" (type-number 'cons))
(data "db @~a" left)
(data "db @~a" right)
(format nil "cons-~a" label-ctr)))
;;; Exemples
(my-compile '(1 2 3))
(my-compile 3)
;; section .data
;; fixnum-constant-1
;; db 0
;; db 3
(my-compile (+ 2 3))
;; =>
;; section .data
;; :global-1
;; db 1
;; db 2
;; section .data
;; :global-2
;; db 1
;; db 3
;; section .text
;; :fn-main
;; load @global-1 r0
;; push r0
;; load @global-2
;; push r0
;; jsr @fn-+
;; retn
;; section .text
;; :fn-+
;; pop r1
;; pop r0
;; add r1 r0
;; retn