aboutsummaryrefslogtreecommitdiff
path: root/src/cljcc/tacky.clj
diff options
context:
space:
mode:
authorShagun Agrawal <agrawalshagun07@gmail.com>2024-08-10 11:27:28 +0530
committerShagun Agrawal <agrawalshagun07@gmail.com>2024-08-10 11:27:28 +0530
commita0811a84e381d64069834d5c0097669d66f4b627 (patch)
treeaee0924cfbd8b4e79bf1d441c46eb7e023325695 /src/cljcc/tacky.clj
parentb82a214687d0b0f95f98dbd5ba7fefd82012fb85 (diff)
Add parsing and tacky generation for binary operators
Fix grammar to handle left associativity Update parser for binary operators Update tacky generation for binary operators
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)))
+ ())