From c7a2fc0f8d85b5d3233ac1125df1b3d95db2b35a Mon Sep 17 00:00:00 2001 From: Shagun Agrawal Date: Fri, 30 Aug 2024 23:54:55 +0530 Subject: Add compound statements Adding compound statements Variable values changed based on scope --- src/cljcc/analyzer.clj | 67 +++++++++++++++++++++++++++++++++----------------- 1 file changed, 45 insertions(+), 22 deletions(-) (limited to 'src/cljcc/analyzer.clj') diff --git a/src/cljcc/analyzer.clj b/src/cljcc/analyzer.clj index 5970be4..b8b0141 100644 --- a/src/cljcc/analyzer.clj +++ b/src/cljcc/analyzer.clj @@ -8,11 +8,13 @@ ([] (unique-identifier "analyzer")) ([identifier] (u/create-identifier! identifier))) +(declare resolve-block) + (defn- resolve-exp [e mp] (condp = (:exp-type e) :constant-exp e :variable-exp (if (contains? mp (:identifier e)) - (p/variable-exp-node (get mp (:identifier e))) + (p/variable-exp-node (:name (get mp (:identifier e)))) (throw (ex-info "Undeclared variable seen." {:variable e}))) :assignment-exp (let [left (:left e) right (:right e) @@ -33,11 +35,12 @@ (throw (ex-info "Analyzer error. Invalid expression type" {:exp e})))) (defn- resolve-declaration [d mp] - (if (contains? mp (:identifier d)) + (if (and (contains? mp (:identifier d)) (:from-current-block (get mp (:identifier d)))) (throw (ex-info "Analyzer error. Duplicate variable declaration." {:declaration d})) (let [ident (:identifier d) unique-name (unique-identifier ident) - updated-mp (assoc mp ident unique-name) + updated-mp (assoc mp ident {:name unique-name + :from-current-block true}) init (when (:initial d) (resolve-exp (:initial d) updated-mp))] (if init {:declaration (p/declaration-node unique-name init) @@ -55,6 +58,11 @@ (resolve-statement (:else-statement s) mp)) (p/if-statement-node (resolve-exp (:condition s) mp) (resolve-statement (:then-statement s) mp))) + :compound (let [updated-mp (zipmap (keys mp) + (map (fn [m] + (update m :from-current-block (fn [_] false))) + (vals mp)))] + (p/compound-statement-node (:block (resolve-block (:block s) updated-mp)))) :empty (p/empty-statement-node) (throw (ex-info "Analyzer error. Invalid statement." {:statement s})))) @@ -62,22 +70,39 @@ (let [type (:type item)] (cond (= type :declaration) (let [v (resolve-declaration item mp)] - {:item (:declaration v) + {:block-item (:declaration v) :variable-map (:variable-map v)}) - (= type :statement) {:item (resolve-statement item mp) + (= type :statement) {:block-item (resolve-statement item mp) :variable-map mp} :else (throw (ex-info "Analyzer Error. Invalid statement/declaration." {item item}))))) +(defn- resolve-block + ([block] + (resolve-block block {})) + ([block var-mp] + (reduce (fn [acc block-item] + (let [v (resolve-block-item block-item (:variable-map acc))] + {:block (conj (:block acc) (:block-item v)) + :variable-map (:variable-map v)})) + {:block [] + :variable-map var-mp} + block))) + (defn- validate-function [f] - (let [updated-body (reduce - (fn [acc item] - (let [v (resolve-block-item item (:variable-map acc))] - {:body (conj (:body acc) (:item v)) - :variable-map (:variable-map v)})) - {:body [] - :variable-map {}} - (:body f))] - (assoc f :body (:body updated-body)))) + (let [updated-body (resolve-block (:body f))] + (assoc f :body (:block updated-body)))) + +(comment + + (resolve-block + [{:type :declaration + :identifier "a", + :initial {:type :exp, :exp-type :constant-exp, :value 1}} + {:type :statement, + :statement-type :return, + :value {:type :exp, :exp-type :constant-exp, :value 0}}]) + + ()) (defn validate [ast] (map validate-function ast)) @@ -94,19 +119,17 @@ (pp/pprint (validate-from-src "int main (void) { -; -return 0; +int a = 3; +{ + int a = a = 4; +} +return a; }")) (pp/pprint (validate-from-src "int main (void) { -int x; -int a = -1; -int b = 2; - -int c = b = 4 + 4; -return 12 / 12321312 + 12312 % 4; +int x = 1 + x; }")) ()) -- cgit v1.2.3