aboutsummaryrefslogtreecommitdiff
path: root/src/cljcc/tacky.clj
diff options
context:
space:
mode:
Diffstat (limited to 'src/cljcc/tacky.clj')
-rw-r--r--src/cljcc/tacky.clj110
1 files changed, 84 insertions, 26 deletions
diff --git a/src/cljcc/tacky.clj b/src/cljcc/tacky.clj
index 4772766..d87a909 100644
--- a/src/cljcc/tacky.clj
+++ b/src/cljcc/tacky.clj
@@ -23,45 +23,93 @@
{:type :variable
:value (create-identifier identifier)}))
-(defn constant [^String v]
+(defn constant-instruction [^String v]
{:type :constant
:value (Long. v)})
-(defn unop-operator [^String unop]
+(defn- unary-operator [^String unop]
(condp = unop
"~" :complement
"-" :negate))
-(defn unary-instruction [unop src dst]
+(defn- binary-operator [binop]
+ (condp = binop
+ :add-exp :add
+ :sub-exp :sub
+ :mul-exp :mul
+ :div-exp :div
+ :mod-exp :mod))
+
+(defn- unary-instruction [unary-operator src dst]
{:type :unary
- :unary-operator unop
+ :unary-operator unary-operator
:dst dst
:src src})
+(defn- binary-instruction [binary-operator src1 src2 dst]
+ {:type :binary
+ :binary-operator binary-operator
+ :src1 src1
+ :src2 src2
+ :dst dst})
+
(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]
+(def binary-exprs
+ #{:add-exp
+ :sub-exp
+ :mul-exp
+ :mod-exp
+ :div-exp})
+
+(defn- binary-expr? [v]
+ (contains? binary-exprs v))
+
+(declare expression-handler)
+
+(defn- constant-expr-handler [e]
+ {:val (constant-instruction (second e))})
+
+(defn- unary-expr-handler [e]
+ (let [inner (expression-handler (nth e 2))
+ dst (variable)
+ src (:val inner)
+ unary-operator (unary-operator (second (second e)))
+ instruction (unary-instruction unary-operator src dst)]
+ {:val dst
+ :instructions (flatten [(:instructions inner) instruction])}))
+
+(defn- binary-expr-handler [e]
+ (let [e1 (expression-handler (nth e 1))
+ e2 (expression-handler (nth e 2))
+ src1 (:val e1)
+ src2 (:val e2)
+ dst (variable)
+ binary-operator (binary-operator (first e))
+ instruction (binary-instruction binary-operator src1 src2 dst)]
+ {:val dst
+ :instructions (flatten [(:instructions e1) (:instructions e2) instruction])}))
+
+(defn- expression-handler [e]
+ (when-let [exp-type (first e)]
+ (cond
+ (= exp-type :constant-exp) (constant-expr-handler e)
+ (= exp-type :unary-exp) (unary-expr-handler e)
+ (binary-expr? exp-type) (binary-expr-handler e))))
+
+(defn- exp-instructions [exp]
+ (expression-handler (second exp)))
+
+(defn- ret-instructions [exp]
(let [e (exp-instructions exp)
val (:val e)
instructions (:instructions e)]
- (conj instructions (return-instruction val))))
+ (conj (vec instructions) (return-instruction val))))
-(defn statement-transform [_ret-keyword exp]
- {:instructions (reverse (ret-instructions exp))})
+(defn- statement-transform [_ret-keyword exp]
+ {:instructions (remove nil? (ret-instructions exp))})
(defn tacky-generate [ast]
(reset! counter 0)
@@ -71,7 +119,19 @@
(reset! counter 0)
- (pp/pprint (tacky-generate (p/parse "int main(void) {return -~-8;}")))
+ (pp/pprint
+ (tacky-generate
+ (p/parse "int main(void) {return 1 * 2 - 3 * (4 + 5);}")))
+
+ (pp/pprint
+ (p/parse "int main(void) {return 1 * 2 - 3 * (4 + 5);}"))
+
+ (pp/pprint
+ (p/parse "int main(void) {return 1 + 2 + -3 + -(4 + 5);}"))
+
+ (pp/pprint
+ (tacky-generate
+ (p/parse "int main(void) {return 1 + 2 + -3 + -(4 + 5);}")))
(pp/pprint
(exp-instructions [:exp [:constant "2"]]))
@@ -104,14 +164,12 @@
(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
+ (ret-instructions ex-ret))
- (pp/pprint (parse exprg)))
+ ())