From 5de5a81e8a652d2a01e793ca4e39bc0fd5974f58 Mon Sep 17 00:00:00 2001 From: Shagun Agrawal Date: Fri, 30 Aug 2024 21:30:02 +0530 Subject: Implement if and conditional expressions in Tacky IR --- src/cljcc/parser.clj | 5 +---- src/cljcc/tacky.clj | 61 ++++++++++++++++++++++++++++++++++++++-------------- 2 files changed, 46 insertions(+), 20 deletions(-) (limited to 'src/cljcc') diff --git a/src/cljcc/parser.clj b/src/cljcc/parser.clj index 0aec1dc..6525c24 100644 --- a/src/cljcc/parser.clj +++ b/src/cljcc/parser.clj @@ -113,10 +113,7 @@ (defn if-statement-node ([cond then] - {:type :statement - :statement-type :if - :condition cond - :then-statement then}) + (if-statement-node cond then nil)) ([cond then else] {:type :statement :statement-type :if diff --git a/src/cljcc/tacky.clj b/src/cljcc/tacky.clj index 6046045..8bb9c6d 100644 --- a/src/cljcc/tacky.clj +++ b/src/cljcc/tacky.clj @@ -34,22 +34,6 @@ :logical-not :logical-not (throw (ex-info "Tacky Error. Invalid unary operator." {op op})))) -(defn- assignment-operator - "Converts parser assignment operator to tacky representation." - [op] - (condp = op - :assignemnt :assignemnt - :assignment-plus :assignment-add - :assignment-multiply :assignment-mul - :assignment-minus :assignment-minus - :assignment-divide :assignment-div - :assignment-mod :assignment-mod - :assignment-bitwise-and :assignemnt-bit-and - :assignment-bitwise-or :assignemnt-bit-or - :assignment-bitwise-xor :assignemnt-bit-xor - :assignment-bitwise-left-shift :assignment-bit-left-shift - :assignment-bitwise-right-shift :assignment-bit-right-shift)) - (defn- assignment-operator->binary-operator "Converts parser assignment operator to binary operator keyword." [op] @@ -211,6 +195,26 @@ :instructions (flatten [(:instructions rhs) (copy-instruction (:val rhs) var)])})))) +(defn- conditional-exp-handler [e] + (let [ce (expression-handler (:left e)) + cv (:val ce) + then-e (expression-handler (:middle e)) + else-e (expression-handler (:right e)) + end-label (label "conditional_end") + else-label (label "conditional_else") + res (variable "conditional_result")] + {:val res + :instructions (flatten + [(:instructions ce) + (jump-if-zero-instruction cv else-label) + (:instructions then-e) + (copy-instruction (:val then-e) res) + (jump-instruction end-label) + (label-instruction else-label) + (:instructions else-e) + (copy-instruction (:val else-e) res) + (label-instruction end-label)])})) + (defn- expression-handler [e] (when-let [exp-type (:exp-type e)] (cond @@ -223,11 +227,35 @@ (binary-expr-handler e))) (= exp-type :variable-exp) {:val (parsed-var->tacky-var e)} (= exp-type :assignment-exp) (assignment-exp-handler e) + (= exp-type :conditional-exp) (conditional-exp-handler e) :else (throw (ex-info "Tacky error. Invalid expression." {e e}))))) (defn- exp-instructions [exp] (expression-handler exp)) +(declare statement->tacky-instruction) + +(defn if-statement-handler [s] + (let [cond-exp (exp-instructions (:condition s)) + cond-value (:val cond-exp) + cond-instructions (:instructions cond-exp) + then-instructions (statement->tacky-instruction (:then-statement s)) + end-label (label "if_end") + else-label (label "if_else") + else? (:else-statement s)] + (if else? + [cond-instructions + (jump-if-zero-instruction cond-value else-label) + then-instructions + (jump-instruction end-label) + (label-instruction else-label) + (statement->tacky-instruction (:else-statement s)) + (label-instruction end-label)] + [cond-instructions + (jump-if-zero-instruction cond-value end-label) + then-instructions + (label-instruction end-label)]))) + (defn- statement->tacky-instruction [s] (condp = (:statement-type s) :return (let [e (exp-instructions (:value s)) @@ -235,6 +263,7 @@ instructions (:instructions e)] (conj (vec instructions) (return-instruction val))) :expression [(:instructions (exp-instructions (:value s)))] + :if (if-statement-handler s) :empty [] (throw (ex-info "Tacky error. Invalid statement." {:statement s})))) -- cgit v1.2.3