diff --git a/src/ludus/prelude.clj b/src/ludus/prelude.clj index f980f6e..85ccd80 100644 --- a/src/ludus/prelude.clj +++ b/src/ludus/prelude.clj @@ -1,6 +1,7 @@ (ns ludus.prelude (:require - [ludus.data :as data])) + [ludus.data :as data] + [ludus.show])) (def eq {:name "eq" ::data/type ::data/clj @@ -44,6 +45,17 @@ (println (apply str args)) :ok)}) +(declare show) + +(defn- show-vector [v] + (if (= (first v) ::data/tuple) + (str "(" (apply str (into [] (comp (map (:body show)) (interpose ", ")) (next v))) ")") + (str "[" (apply str (into [] (comp (map (:body show)) (interpose ", ")) v)) "]"))) + +(def show {:name "show" + ::data/type ::data/clj + :body ludus.show/show}) + (def prelude {"eq" eq "add" add "panic!" panic! @@ -53,4 +65,5 @@ "div" div "inc" inc- "dec" dec- - "not" not}) \ No newline at end of file + "not" not + "show" show}) \ No newline at end of file diff --git a/src/ludus/show.clj b/src/ludus/show.clj new file mode 100644 index 0000000..506d91c --- /dev/null +++ b/src/ludus/show.clj @@ -0,0 +1,54 @@ +(ns ludus.show + (:require + [ludus.data :as data] + [clojure.pprint :as pp])) + +(declare show show-linear show-keyed) + +(defn- show-vector [v] + (if (= (first v) ::data/tuple) + (str "(" (apply str (into [] show-linear (next v))) ")") + (str "[" (apply str (into [] show-linear v)) "]"))) + +;; TODO: +(defn- show-map [v] + (cond + (or (= (::data/type v) ::data/fn) + (= (::data/type v) ::data/clj)) + (str "fn " (:name v)) + + (= (::data/type v) ::data/ns) + (str "ns " (::data/name v) " {" + (apply str (into [] show-keyed (dissoc v ::data/struct ::data/type ::data/name))) + "}") + + (::data/struct v) + (str "@{" (apply str (into [] show-keyed (dissoc v ::data/struct))) "}") + + :else + (str "#{" (apply str (into [] show-keyed v)) "}") + + )) + +(defn- show-set [v] + (str "${" (apply str (into [] show-linear v)) "}")) + +(defn show [v] + (cond + (string? v) (str "\"" v "\"") + (number? v) (str v) + (keyword? v) (str v) + (boolean? v) (str v) + (nil? v) "nil" + (vector? v) (show-vector v) + (set? v) (show-set v) + (map? v) (show-map v) + :else (with-out-str (pp/pprint v)))) + +(def show-linear (comp (map show) (interpose ", "))) + +(def show-keyed (comp + (map #(str (show (first %)) " " (show (second %)))) + (interpose ", "))) + +(show {::data/type ::data/fn :name "foo"})