aboutsummaryrefslogtreecommitdiff
path: root/src/cljcc/analyzer.clj
diff options
context:
space:
mode:
Diffstat (limited to 'src/cljcc/analyzer.clj')
-rw-r--r--src/cljcc/analyzer.clj67
1 files changed, 45 insertions, 22 deletions
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;
}"))
())