blob: e25c87f72ee51e9f00de16e2efe9752b7d9d65ec (
plain)
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
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
|
(ns cljcc.tacky
(:require
[clojure.pprint :as pp]
[instaparse.core :as insta]
[cljcc.parser :as p]))
(def counter "Global integer counter for generating unique identifier names." (atom 0))
(defn create-identifier
"Returns a unique identifier. Used for generating tacky variable names."
([]
(create-identifier "tmp"))
([identifier]
(let [n @counter
_ (swap! counter #(+ % 1))]
(str identifier "." n))))
(defn variable
([]
{:type :variable
:value (create-identifier)})
([^String identifier]
{:type :variable
:value (create-identifier identifier)}))
(defn constant [^String v]
{:type :constant
:value (Long. v)})
(defn unop-operator [^String unop]
(condp = unop
"~" :complement
"-" :negate))
(defn unary-instruction [unop src dst]
{:type :unary
:unary-operator unop
:dst dst
:src src})
(defn return-instruction [val]
{:type :return
:val val})
(defn exp-instructions [exp]
(when-let [expr (second exp)]
(condp = (first expr)
:constant {:val (constant (second expr))}
:unop-exp (let [inner (exp-instructions (nth expr 2))
dst (variable)
src (:val inner)
unop (unop-operator (second (second expr)))
inst (unary-instruction unop src dst)]
{:val dst
:instructions (conj (:instructions inner) inst)}))))
(defn ret-instructions [exp]
(let [e (exp-instructions exp)
val (:val e)
instructions (:instructions e)]
(conj instructions (return-instruction val))))
(defn statement-transform [_ret-keyword exp]
(reverse (ret-instructions exp)))
(defn tacky-generate [ast]
(insta/transform {:statement statement-transform} ast))
(comment
(reset! counter 0)
(pp/pprint (tacky-generate (p/parse "int main(void) {return -~-8;}")))
(pp/pprint
(exp-instructions [:exp [:constant "2"]]))
(pp/pprint
(exp-instructions [:exp [:constant "2"]]))
(pp/pprint
(exp-instructions [:exp [:unop-exp [:unop "-"] [:exp [:constant "2"]]]]))
(def ex-exp
[:exp
[:unop-exp
[:unop "-"]
[:exp
[:unop-exp
[:unop "~"]
[:exp [:unop-exp [:unop "-"] [:exp [:constant "8"]]]]]]]])
(def ex-ret
[:statement "return"
[:exp
[:unop-exp
[:unop "-"]
[:exp
[:unop-exp
[:unop "~"]
[:exp [:unop-exp [:unop "-"] [:exp [:constant "8"]]]]]]]]])
(pp/pprint
(exp-instructions ex-exp))
(pp/pprint
(ret-instructions ex-ret))
(def exprg
"int main(void) {
return -(~(-8));
}")
(pp/pprint (parse "int main(void) {return 2;}"))
(pp/pprint (parse exprg))
,)
|