Begin C code generation.

This commit is contained in:
2024-08-08 17:13:29 +03:00
parent b215590395
commit 1056b74b11
3 changed files with 168 additions and 74 deletions

View File

@@ -164,38 +164,81 @@
(parse-tokens tokens)))
;;; COMPILER
(defun write-program (program out &key (mem-cap 640000))
;;(defgeneric write-program (target program stream))
(defmethod write-program ((target (eql :nasm)) program out
&key (mem-cap 640000))
(format out "~a~%" "segment .text")
(gen-dump out)
(format out "~{~a~%~}" '("global _start"
"_start:"))
(let ((strs nil))
(iter (for op in-sequence program)
(let ((gen-val (gen-code op out)))
(let ((gen-val (write-op target out (car op) (cdr op))))
(when (and (consp gen-val) (eq :string (car gen-val)))
(push (cdr gen-val) strs))))
(gen-code '(:exit 0) out)
(unless (null strs)
(format out "segment .data~%")
(dolist (str strs)
(format out "str_~a: db ~{0x~x~^,~}~%"
(first str)
(map 'list #'char-code (second str))))))
(write-op target out :exit '(0))
(unless (null strs)
(format out "segment .data~%")
(dolist (str strs)
(format out "str_~a: db ~{0x~x~^,~}~%"
(first str)
(map 'list #'char-code (second str))))))
(format out "~a~%" "segment .bss")
(format out "~a ~a~%" "bel: resb" mem-cap))
(defun generate-program (program &key (path "output.asm") (compile nil)
(mem-cap 640000) (silence nil))
(with-open-file (out path :direction :output
:if-exists :supersede)
(write-program program out :mem-cap mem-cap))
(defmethod write-program ((target (eql :c)) program out &key (mem-cap 640000))
(declare (ignore mem-cap))
(format out
"#include <stdio.h>
struct Stack {
int content[100];
int i;
};
typedef struct Stack Stack;
void push(Stack* stack, int val){
stack->content[stack->i] = val;
stack->i += 1;
}
int pop(Stack* stack){
stack->i -= 1;
return stack->content[stack->i];
}
Stack stack;
int rax, rbx;
int main(void){
stack.i = 0;
")
(iter (for op in-sequence program)
(write-op target out (car op) (cdr op)))
(format out " return 0;~%}~%"))
(defun generate-program (program
&key (path "output.asm") (compile nil)
(mem-cap 640000) (silence nil) (target :nasm))
(with-open-file (out path :direction :output :if-exists :supersede)
(write-program target program out :mem-cap mem-cap))
(when compile
(run `("nasm" "-felf64" ,path) :output t :silence silence)
(let ((name (first (uiop:split-string path :separator '(#\.)))))
(run `("ld" "-o" ,name ,(concatenate 'string name ".o"))
:output t :silence silence))))
(compile-program target path silence)))
(defgeneric compile-program (target path silence))
(setf (documentation #'compile-program 'function)
(format nil "Produces the executable from source code, targets are ~a"
*targets*))
(defmethod compile-program ((target (eql :nasm)) path silence)
(run `("nasm" "-felf64" ,path) :output t :silence silence)
(let ((name (first (uiop:split-string path :separator '(#\.)))))
(run `("ld" "-o" ,name ,(concatenate 'string name ".o"))
:output t :silence silence)))
(defmethod compile-program ((target (eql :c)) path silence)
(run `("gcc" ,path) :output t :silence silence))
(defun compile-program (path)
(generate-program (make-program path) :compile t))