Skip to content

Commit 49e0d87

Browse files
committed
Add a sum-type-descriptor for reflection. Optimize sum-type predicate.
1 parent 3657d92 commit 49e0d87

File tree

2 files changed

+30
-11
lines changed

2 files changed

+30
-11
lines changed

src/active/clojure/sum_type.cljc

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
#?(:clj [active.clojure.record :as record]
44
:cljs [active.clojure.cljs.record :as record :include-macros true])
55
[active.clojure.record-helper :as record-helper]
6+
[active.clojure.record-runtime :as record-runtime]
67
#?(:clj [active.clojure.lens :as lens]
78
:cljs [active.clojure.lens :as lens :include-macros true])))
89

@@ -40,6 +41,21 @@
4041
(str (:name ((resolve 'cljs.analyzer.api/resolve) env t)))
4142
(str (:ns (meta (resolve t))) "/" (:name (meta (resolve t)))))))
4243

44+
(record/define-record-type ^:no-doc SumTypeDescriptor
45+
(make-sum-type-descriptor name sub-types)
46+
sum-type-descriptor?
47+
[name sum-type-descriptor-name
48+
sub-types sum-type-descriptor-sub-types])
49+
50+
(defn ^:no-doc value-of-sum-type? [v sum-type]
51+
(boolean (some (fn [t]
52+
(cond
53+
(sum-type-descriptor? t) (value-of-sum-type? v t)
54+
(record-runtime/record-type-descriptor? t) (record-runtime/record-of-type? v t)
55+
:else
56+
(do (assert false t) false) ;; should not happen?
57+
))
58+
(sum-type-descriptor-sub-types sum-type))))
4359

4460

4561
;; a clause is one of the following:
@@ -131,7 +147,7 @@
131147

132148

133149
(let [sym-fn (fn [a] (str *ns* "/" a))
134-
resolved-type-symbols (mapv #(resolve-qualified-str % &env) type-symbols)
150+
resolved-type-symbols (mapv (comp symbol #(resolve-qualified-str % &env)) type-symbols)
135151
sum-type-meta {:predicate (sym-fn predicate)
136152
:t sum-type-identifier
137153

@@ -143,21 +159,20 @@
143159
(dissoc :end-line)
144160
(dissoc :end-column)
145161
(dissoc :name) ; this leads to a crash in clj
146-
(dissoc :column)) type-symbols)}]
162+
(dissoc :column)) type-symbols)}
163+
arg (gensym "arg")]
147164

148165
(throw-when-illegal-types! type-symbols &env)
149166

150167

151168
`(do
152-
153-
(let [rss# ~resolved-type-symbols] ;; we only do resolution once
154-
155-
(defn ~predicate [arg#]
156-
(boolean (some true?
157-
(map (fn [pred#] (pred# arg#))
158-
~(mapv #(symbol (get-predicate (symbol %) &env)) resolved-type-symbols)))))
159-
160-
(def ~(add-meta type-name sum-type-meta) ~sum-type-meta))))))
169+
(defn ~predicate [~arg]
170+
;; we could use [[value-of-sum-type?]], but this is an optimized compiled version:
171+
(or ~@(map (fn [p] (list p arg))
172+
(mapv #(symbol (get-predicate % &env)) resolved-type-symbols))))
173+
174+
(def ~(add-meta type-name sum-type-meta)
175+
(make-sum-type-descriptor '~type-name (vector ~@resolved-type-symbols)))))))
161176

162177

163178

test/active/clojure/sum_type_test.cljc

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,7 +170,11 @@
170170

171171
(st/define-sum-type forms&colors forms&colors? [data/circle data/square rgb-color])
172172

173+
(deftest sum-type-descriptor-test
174+
(is (st/sum-type-descriptor? forms&colors))
173175

176+
(is (st/value-of-sum-type? (data/make-square 0 0) forms&colors))
177+
(is (st/value-of-sum-type? (make-red 0) forms&colors)))
174178

175179

176180
(deftest from-other-ns

0 commit comments

Comments
 (0)