-
Notifications
You must be signed in to change notification settings - Fork 0
/
compiler.lisp
64 lines (60 loc) · 2.26 KB
/
compiler.lisp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
(in-package :lcc)
;; IR Intermediate Representation
(defun create-globals (ir &optional (globals (make-hash-table :test 'eql)))
(maphash #'(lambda (name spec)
(case (construct spec)
('|@VARIABLE| (setf (gethash name globals) spec))
('|@FUNCTION| (setf (gethash name globals) spec))
('|@TYPEDEF| (setf (gethash name globals) spec))
('|@ENUM|
(unless (anonymous spec) (setf (gethash name globals) spec))
(maphash #'(lambda (k v) (setf (gethash k globals) v)) (inners spec)))
('|@STRUCT|
(setf (gethash name globals) spec)
(maphash #'(lambda (k v)
(when (eql (construct v) '|@DECLARES|) (setf (gethash k globals) v)))
(inners spec)))
('|@UNION|
(setf (gethash name globals) spec)
(maphash #'(lambda (k v)
(when (eql (construct v) '|@DECLARES|) (setf (gethash k globals) v)))
(inners spec)))
('|@GUARD| (create-globals spec globals))
(otherwise nil)))
(inners ir))
globals)
;; AST Abstract Syntax Tree
(defun compile-ast (targets)
(uiop:chdir "lcc")
(uiop:with-current-directory ("lcc")
(dolist (target targets)
(let ((name (car target))
(ir nil)
(globals nil))
(cond ((key-eq name '|target|)
(setq ir (specify-target target))
(setq globals (create-globals ir))
(compile-target ir globals))
((key-eq name '|class|)
(setq ir (specify-class target))
(setq globals (create-globals ir))
(format t "lcc: globals in ~A~%" (cadr target))
(print-specifiers globals)
(compile-class ir globals))
(t (error (format nil "target or class is missing for ~A" name)))))))
(uiop:chdir ".."))
(defun compile-lcc-file (file-name)
(ensure-directories-exist "lcc/meta")
(let ((rt (copy-readtable nil)))
(multiple-value-bind (function non-terminating-p)
(get-macro-character #\| rt)
(set-macro-character #\| nil nil)
(compile-ast (read-file file-name))
(set-macro-character #\| function non-terminating-p))))
(set-macro-character
#\" #'(lambda (stream char)
(declare (ignore char))
(with-output-to-string (out)
(do ((char (read-char stream nil nil) (read-char stream nil nil)))
((char= char #\") nil)
(write char :stream out :escape nil)))))