aboutsummaryrefslogtreecommitdiff
path: root/cli/src
diff options
context:
space:
mode:
authorYour Name <agrawalshagun07@gmail.com>2025-03-16 02:00:40 +0530
committerYour Name <agrawalshagun07@gmail.com>2025-03-16 02:00:40 +0530
commit0321df3708cfa4d1440faf3f407611df85484b4b (patch)
tree8c23154afaf1afd78363eb0fa639edd5d8a32821 /cli/src
parente458b2fadee1eaf0a6cf4ed4881da6f3f25acc21 (diff)
Refactor files to cljcc-compiler and cli tool.
Diffstat (limited to 'cli/src')
-rw-r--r--cli/src/cli/cli.clj51
-rw-r--r--cli/src/cli/core/log.clj28
-rw-r--r--cli/src/cli/core/shell.clj31
-rw-r--r--cli/src/cli/driver.clj3
-rw-r--r--cli/src/cli/log.clj28
5 files changed, 141 insertions, 0 deletions
diff --git a/cli/src/cli/cli.clj b/cli/src/cli/cli.clj
new file mode 100644
index 0000000..f7aba04
--- /dev/null
+++ b/cli/src/cli/cli.clj
@@ -0,0 +1,51 @@
+(ns cli.cli
+ (:require
+ [clojure.tools.cli :refer [parse-opts]]
+ [clojure.string :as string]
+ [cljcc.util :refer [exit]]
+ [cli.driver :as driver])
+ (:gen-class))
+
+(set! *warn-on-reflection* true)
+
+(defn usage [options-summary]
+ (->>
+ ["Usage: ./cljcc path/to/file.c [options]"
+ ""
+ "Options:"
+ options-summary]
+ (string/join \newline)))
+
+(def cli-options
+ [[nil "--lex" "Runs lexer. Does not emit any files."]
+ [nil "--parse" "Runs parser. Does not emit any files."]
+ [nil "--validate" "Runs semantic analyzer. Does not emit any files."]
+ [nil "--tacky" "Runs tacky generation. Does not emit any files."]
+ [nil "--codegen" "Runs compiler. Does not emit any files."]
+ ["-c" nil "Generate object file."
+ :id :generate-object-file]
+ ["-h" "--help"]])
+
+(defn validate-args [args]
+ (let [{:keys [options arguments summary]} (parse-opts args cli-options)]
+ (cond
+ (:help options) {:exit-message (usage summary) :ok? true}
+ (= 1 (count arguments)) {:file-path (first arguments)
+ :options options}
+ :else {:exit-message (usage summary)})))
+
+(defn -main
+ "Main entrypoint for cljcc compiler."
+ [& args]
+ (let [{:keys [file-path exit-message ok? options]} (validate-args args)
+ libs (filterv (fn [v] (and
+ (string? v)
+ (re-matches #"-l.+" v)))
+ args)]
+ (if exit-message
+ (exit (if ok? 0 1) exit-message)
+ (try
+ (driver/run file-path (assoc options :libs libs))
+ (exit 0 "Successfully executed.")
+ (catch Exception e
+ (exit 1 (ex-message e) e))))))
diff --git a/cli/src/cli/core/log.clj b/cli/src/cli/core/log.clj
new file mode 100644
index 0000000..1b279fc
--- /dev/null
+++ b/cli/src/cli/core/log.clj
@@ -0,0 +1,28 @@
+(ns cli.core.log
+ (:require [clojure.string :as str]))
+
+(def ^:private log-colors
+ {:debug "\u001b[36m" ; Cyan
+ :info "\u001b[32m" ; Green
+ :warn "\u001b[33m" ; Yellow
+ :error "\u001b[31m" ; Red
+ :reset "\u001b[0m"}) ; Reset color
+
+(def reset-color (get log-colors :reset))
+
+(defn- log-message [level message]
+ (let [color (get log-colors level)
+ formatted-message (str color "[" (str/upper-case (name level)) "] " message reset-color)]
+ (println formatted-message)))
+
+(defn debug [msg]
+ (log-message :debug msg))
+
+(defn info [msg]
+ (log-message :info msg))
+
+(defn warn [msg]
+ (log-message :warn msg))
+
+(defn error [msg]
+ (log-message :error msg))
diff --git a/cli/src/cli/core/shell.clj b/cli/src/cli/core/shell.clj
new file mode 100644
index 0000000..c17dbaa
--- /dev/null
+++ b/cli/src/cli/core/shell.clj
@@ -0,0 +1,31 @@
+(ns cli.core.shell
+ (:require [cli.core.log :as log]
+ [clojure.java.shell :refer [sh]]))
+
+(defn get-os []
+ (let [os-name (.toLowerCase (System/getProperty "os.name"))]
+ (cond
+ (.contains os-name "mac") :mac
+ (.contains os-name "linux") :linux
+ :else :unsupported)))
+
+(defn mac-aarch64? []
+ (and (= :mac (get-os)) (= (System/getProperty "os.arch") "aarch64")))
+
+(defn handle-sh
+ "Preprends arch -x86_64 if running under Mac M chips."
+ [command & args]
+ (let [args (filterv (comp not empty?) args)]
+ (if (mac-aarch64?)
+ (apply sh "arch" "-x86_64" command args)
+ (apply sh command args))))
+
+(defn exit
+ ([status msg]
+ (if (= status 0)
+ (log/info msg)
+ (log/error msg))
+ (System/exit status))
+ ([status msg e]
+ (log/error (ex-data e))
+ (exit status msg)))
diff --git a/cli/src/cli/driver.clj b/cli/src/cli/driver.clj
new file mode 100644
index 0000000..41a916f
--- /dev/null
+++ b/cli/src/cli/driver.clj
@@ -0,0 +1,3 @@
+(ns cli.driver)
+
+(defn run [& args])
diff --git a/cli/src/cli/log.clj b/cli/src/cli/log.clj
new file mode 100644
index 0000000..3f207d7
--- /dev/null
+++ b/cli/src/cli/log.clj
@@ -0,0 +1,28 @@
+(ns cli.log
+ (:require [clojure.string :as str]))
+
+(def ^:private log-colors
+ {:debug "\u001b[36m" ; Cyan
+ :info "\u001b[32m" ; Green
+ :warn "\u001b[33m" ; Yellow
+ :error "\u001b[31m" ; Red
+ :reset "\u001b[0m"}) ; Reset color
+
+(def reset-color (get log-colors :reset))
+
+(defn- log-message [level message]
+ (let [color (get log-colors level)
+ formatted-message (str color "[" (str/upper-case (name level)) "] " message reset-color)]
+ (println formatted-message)))
+
+(defn debug [msg]
+ (log-message :debug msg))
+
+(defn info [msg]
+ (log-message :info msg))
+
+(defn warn [msg]
+ (log-message :warn msg))
+
+(defn error [msg]
+ (log-message :error msg))