From 32499638cef3c49ff686b19b5708d6b08712c526 Mon Sep 17 00:00:00 2001 From: Your Name Date: Sun, 16 Mar 2025 18:03:26 +0530 Subject: Refactor into cli and cljcc-compiler folders Pass all tests. Fix babashka tasks and build setup. Repl is behaving in unexpected ways, otherwise working as expected. --- cljcc-compiler/src/cljcc/util.clj | 124 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) create mode 100644 cljcc-compiler/src/cljcc/util.clj (limited to 'cljcc-compiler/src/cljcc/util.clj') diff --git a/cljcc-compiler/src/cljcc/util.clj b/cljcc-compiler/src/cljcc/util.clj new file mode 100644 index 0000000..dee99ad --- /dev/null +++ b/cljcc-compiler/src/cljcc/util.clj @@ -0,0 +1,124 @@ +(ns cljcc.util + (:require + [clojure.string :as str] + [cljcc.core.exception :as exc])) + +(def ^:private counter "Global integer counter for generating unique identifier names." (atom 0)) + +(defn create-identifier! + "Returns a unique identifier. Used for generating unique identifier. + + Removes : from keywords. + Replaces all - with _ for generating valid assembly names." + ([] + (create-identifier! "tmp")) + ([identifier] + (let [n @counter + _ (swap! counter inc)] + (-> identifier + (str "." n) + (str/replace #":" "") + (str/replace #"-" "_"))))) + +(defn reset-counter! [] + (reset! counter 0)) + +(defn letter? [^Character ch] + (or (= \_ ch) + (Character/isLetter ch))) + +(defn letter-digit? [^Character ch] + (or (= \_ ch) + (Character/isLetterOrDigit ch))) + +(defn letter-digit-period? [^Character ch] + (or (= \_ ch) + (= \. ch) + (= \+ ch) + (= \- ch) + (Character/isLetterOrDigit ch))) + +(defn digit? [^Character ch] + (Character/isDigit ch)) + +(defn newline? [ch] + (= \newline ch)) + +(defn whitespace? [^Character ch] + (Character/isWhitespace ch)) + +(defn matches-regex [re s] + (not (nil? (re-matches re s)))) + +(def unsigned-long-re-without-wordbreak #"[0-9]+([lL][uU]|[uU][lL])") +(def signed-long-re-without-wordbreak #"[0-9]+[lL]") +(def unsigned-int-re-without-wordbreak #"[0-9]+[uU]") +(def signed-int-re-without-wordbreak #"[0-9]+") +(def floating-point-constant-without-wordbreak #"([0-9]*\.[0-9]+|[0-9]+\.?)[Ee][+-]?[0-9]+|[0-9]*\.[0-9]+|[0-9]+\.") + +(def unsigned-long-re #"([0-9]+([lL][uU]|[uU][lL]))[^\w.]") +(def signed-long-re #"([0-9]+[lL])[^\w.]") +(def unsigned-int-re #"([0-9]+[uU])[^\w.]") +(def signed-int-re #"([0-9]+)[^\w.]") +(def floating-point-constant #"(([0-9]*\.[0-9]+|[0-9]+\.?)[Ee][+-]?[0-9]+|[0-9]*\.[0-9]+|[0-9]+\.)[^\w.]") + +(defn- re-find-indexed [re s] + (let [matcher (re-matcher re s)] + (when (.find matcher) + [(.group matcher 1) + (.start matcher 1) + (.end matcher 1)]))) + +(defn match-regex + "Returns matched string and remaining string tuple, otherwise returns nil. + + The first match by re-finds must be the starting subsequence, otherwise false." + [re s] + (when-let [[matched start-index _] (re-find-indexed re s)] + (when (and (= 0 start-index) (str/starts-with? s matched)) + [matched (str/replace-first s matched "")]))) + +(defn read-number + "Returns tuple of matched number and remaining string, otherwise nil." + [s line col] + (if-let [x (or + (match-regex floating-point-constant s) + (match-regex signed-int-re s) + (match-regex signed-long-re s) + (match-regex unsigned-int-re s) + (match-regex unsigned-long-re s))] + x + (exc/lex-error {:line line + :col col}))) + +(defn round-away-from-zero [num div] + (let [div (abs div)] + (cond + (= (mod num div) 0) num + (< num 0) (- num (- div (mod num div))) + :else (+ num (- div (mod num div)))))) + +(defn in-int-range? + "Verifies whether -2^31 <= x <= 2^31." + [v] + (and (>= v Integer/MIN_VALUE) + (<= v Integer/MAX_VALUE))) + +(defn get-type-size [t] + (condp = t + {:type :int} 5 + {:type :uint} 5 + {:type :long} 10 + {:type :ulong} 10 + (exc/analyzer-error "Invalid type passed to get-type-size." {:type t}))) + +(defn type-double? [t] + (= {:type :double} t)) + +(defn type-signed? [t] + (condp = t + {:type :int} true + {:type :long} true + {:type :uint} false + {:type :ulong} false + (exc/analyzer-error "Invalid type passed to type-signed?." {:type t}))) -- cgit v1.2.3