Skip to content

Commit 5e516aa

Browse files
committed
Data readers for tagged literals split into code and data related handlers
1 parent 7f529d1 commit 5e516aa

File tree

9 files changed

+156
-60
lines changed

9 files changed

+156
-60
lines changed

resources/io/randomseed/bankster/bankster_data_readers.clj

-3
This file was deleted.

src/data_readers.clj

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
{currency io.randomseed.bankster.currency/lit,
2-
money io.randomseed.bankster.money/lit,
3-
money/crypto io.randomseed.bankster.money/lit-crypto}
1+
{currency io.randomseed.bankster.currency/code-literal,
2+
money io.randomseed.bankster.money/code-literal,
3+
money/crypto io.randomseed.bankster.money/code-literal-crypto}

src/data_readers.cljc

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
{currency io.randomseed.bankster.currency/lit,
2-
money io.randomseed.bankster.money/lit,
3-
money/crypto io.randomseed.bankster.money/lit-crypto}
1+
{currency io.randomseed.bankster.currency/code-literal,
2+
money io.randomseed.bankster.money/code-literal,
3+
money/crypto io.randomseed.bankster.money/code-literal-crypto}

src/data_readers_edn.clj

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{currency io.randomseed.bankster.currency/data-literal,
2+
money io.randomseed.bankster.money/data-literal,
3+
money/crypto io.randomseed.bankster.money/data-literal-crypto}

src/io/randomseed/bankster/currency.clj

+17-7
Original file line numberDiff line numberDiff line change
@@ -493,10 +493,10 @@
493493
registry/with or with-registry)."
494494
{:added "1.0.0"}
495495
([currency]
496-
(let [cur# (parse-currency-code currency)]
496+
(let [cur# (parse-currency-code currency &env)]
497497
`(unit ~cur#)))
498498
([currency registry]
499-
(let [cur# (parse-currency-code currency)]
499+
(let [cur# (parse-currency-code currency &env)]
500500
`(unit ~cur# ~registry))))
501501

502502
;;
@@ -1544,15 +1544,25 @@
15441544
~@body))
15451545

15461546
;;
1547-
;; Tagged literal handler.
1547+
;; Tagged literals.
15481548
;;
15491549

1550-
(defn lit
1551-
"Tagged literal handler."
1552-
{:added "1.0.0"}
1550+
(defn code-literal
1551+
"Tagged literal handler for Clojure code. Emits compound forms that are going to be
1552+
evaluated."
1553+
{:added "1.2.4"}
1554+
[arg]
1555+
(if (or (nil? arg) (and (map? arg) (< (count arg) 1)))
1556+
'(quote nil)
1557+
`(of ~arg)))
1558+
1559+
(defn data-literal
1560+
"Tagged literal handler for EDN data files. Emits Currency objects or nil values."
1561+
{:added "1.2.4"}
15531562
[arg]
15541563
(if (or (nil? arg) (and (map? arg) (< (count arg) 1)))
1555-
'(quote nil) (unit arg)))
1564+
'(quote nil)
1565+
(of arg)))
15561566

15571567
;;
15581568
;; Formatting.

src/io/randomseed/bankster/money.clj

+80-14
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
pos? neg? zero?])
1111

1212
(:require [clojure.string]
13+
[clojure.edn]
1314
[trptr.java-wrapper.locale :as l]
1415
[io.randomseed.bankster :refer :all]
1516
[io.randomseed.bankster.scale :as scale]
@@ -2015,18 +2016,49 @@
20152016
;; Tagged literals.
20162017
;;
20172018

2018-
(defn lit
2019-
"Tagged literal handler."
2020-
{:added "1.0.0" :no-doc true}
2021-
([arg]
2022-
(let [[c amount r] (if (sequential? arg) arg [arg nil nil])]
2023-
(if (or (nil? c) (and (sequential? c) (nil? (seq c))))
2024-
'(quote nil)
2025-
(if (nil? amount)
2026-
(of-gen parse c)
2027-
(if (nil? r)
2028-
(of-gen parse c amount)
2029-
(of-gen parse c amount r)))))))
2019+
(defn lit-parse
2020+
"Internal pre-parser for tagged literals. Takes a parsing function and arguments
2021+
in decomposed form."
2022+
{:added "1.2.4" :private true}
2023+
([a]
2024+
(of-gen parse a))
2025+
([a b]
2026+
(if (nil? b)
2027+
(of-gen parse a)
2028+
(of-gen parse a b)))
2029+
([a b r]
2030+
(if (nil? r)
2031+
(if (nil? b)
2032+
(lit-parse a)
2033+
(lit-parse a b))
2034+
(of-gen parse a b r))))
2035+
2036+
(defn code-literal
2037+
"Tagged literal handler for Money objects expressed as tagged literals in Clojure
2038+
code. Returns compound forms (parsing function invocations that can be influenced
2039+
by the runtime environment, e.g. dynamic variables like scale/*rounding-mode*)."
2040+
{:added "1.2.4"}
2041+
[arg]
2042+
(if (nil? arg)
2043+
(lit-parse nil)
2044+
(if (sequential? arg)
2045+
(apply lit-parse (take 3 arg))
2046+
(if (map? arg)
2047+
(lit-parse (:currency arg)
2048+
(:amount arg)
2049+
(or (:rounding-mode arg)
2050+
(:rounding arg)))
2051+
(lit-parse arg)))))
2052+
2053+
(defn data-literal
2054+
"Data reader for Money objects expressed as tagged literals in EDN data
2055+
files."
2056+
{:added "1.2.4" :tag io.randomseed.bankster.Money}
2057+
[arg]
2058+
(let [r (code-literal arg)]
2059+
(if (seq? r)
2060+
(apply (first r) (rest r))
2061+
r)))
20302062

20312063
(defn defliteral
20322064
"For the given currency identifier or a currency object it creates a tagged literal
@@ -2050,16 +2082,50 @@
20502082
(set! clojure.core/*data-readers*
20512083
(assoc clojure.core/*data-readers* snam varn)))))))
20522084

2053-
(defn ns-lit
2085+
(defn ns-data-literal
20542086
{:private true :added "1.0.0"}
20552087
[kw arg]
20562088
(let [[a b r] (if (sequential? arg) arg [arg nil nil])
20572089
[c am] (if (and (some? b) (number? a)) [b a] [a b])
20582090
c (if (number? c) c (keyword kw (str (symbol c))))]
2059-
(lit [c am r])))
2091+
(data-literal [c am r])))
2092+
2093+
(defn ns-code-literal
2094+
{:private true :added "1.0.0"}
2095+
[kw arg]
2096+
(let [[a b r] (if (sequential? arg) arg [arg nil nil])
2097+
[c am] (if (and (some? b) (number? a)) [b a] [a b])
2098+
c (if (number? c) c (keyword kw (str (symbol c))))]
2099+
(code-literal [c am r])))
20602100

20612101
(load "money/reader_handlers")
20622102

2103+
;;
2104+
;; Data readers maps.
2105+
;;
2106+
2107+
(def ^{:tag clojure.lang.IPersistentMap :added "1.2.4"}
2108+
data-readers
2109+
"Data readers map for currency and money (intended to be used when reading EDN data
2110+
files containing tagged literals: #currency and #money). Handlers assigned to
2111+
literals are always emitting constant forms. Please note that tagged literal
2112+
handlers for Clojure code are using different readers (defined as code-readers)."
2113+
(when-some [r (fs/get-resource "data_readers_edn.clj")]
2114+
(when-some [d (clojure.edn/read-string (slurp r))]
2115+
(when (map? d)
2116+
(into {} (for [[k v] d] [k (resolve v)]))))))
2117+
2118+
(def ^{:tag clojure.lang.IPersistentMap :added "1.2.4"}
2119+
code-readers
2120+
"Data readers map for currency and money (intended to be used when evaluating Clojure
2121+
code with tagged literals: #currency and #money). Handlers assigned to literals may
2122+
emit compound forms, like function call forms (as Clojure code). To operate on EDN
2123+
data files, see data-readers."
2124+
(when-some [r (fs/get-resource "data_readers.clj")]
2125+
(when-some [d (clojure.edn/read-string (slurp r))]
2126+
(when (map? d)
2127+
(into {} (for [[k v] d] [k (resolve v)]))))))
2128+
20632129
;;
20642130
;; Formatting.
20652131
;;
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
11
(in-ns 'io.randomseed.bankster.money)
22

3-
(defn lit-crypto {:no-doc true} [arg] (ns-lit "crypto" arg))
3+
(defn code-literal-crypto {:no-doc true} [arg] (ns-code-literal "crypto" arg))
4+
5+
(defn data-literal-crypto {:no-doc true} [arg] (ns-data-literal "crypto" arg))

src/io/randomseed/bankster/util/importer.clj

+43-28
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,13 @@
4646

4747
(def ^{:const true :tag String :added "1.0.0"}
4848
default-reader-filenames
49-
"Default data reader filenames."
49+
"Default data reader filenames (Clojure code)."
5050
["data_readers.clj" "data_readers.cljc"])
5151

52-
(def ^{:const true :tag String :added "1.2.3"}
53-
default-reader-filename-res
54-
"Data reader filename in resources subdirectory."
55-
"bankster_data_readers.clj")
52+
(def ^{:const true :tag String :added "1.2.4"}
53+
default-data-reader-filename
54+
"Default data reader filename (pure data)."
55+
"data_readers_edn.clj")
5656

5757
(def ^{:const true :tag String :added "1.0.0"}
5858
default-handlers-pathname
@@ -248,16 +248,23 @@
248248
(let [nsp (symbol (str "'" handlers-namespace))]
249249
(list 'in-ns nsp))))
250250

251-
(defn handler-gen
252-
"Generates handler functions for tagged literals for each namespaced currency."
253-
{:no-doc true :added "1.0.0"}
254-
[names]
251+
(defn handler-gen-for-prefix
252+
{:private true :added "1.0.0"}
253+
[prefix names]
255254
(map
256-
(fn [n] (list 'defn (symbol (str "lit-" n))
257-
'{:no-doc true}
258-
'[arg] (list 'ns-lit (str n) 'arg)))
255+
(fn [n]
256+
(list 'defn (symbol (str prefix "-" n))
257+
'{:no-doc true}
258+
'[arg] (list (symbol (str "ns-" prefix)) (str n) 'arg)))
259259
names))
260260

261+
(defn handler-gen
262+
"Generates handler functions for tagged literals for each namespaced currency. Each
263+
function will have a prefixed name."
264+
[names]
265+
(concat (handler-gen-for-prefix "code-literal" names)
266+
(handler-gen-for-prefix "data-literal" names)))
267+
261268
(defn readers-export
262269
"Creates clojure source code files with reader functions for tagged literals handling
263270
on a basis of registry information and data reader map files referring to the
@@ -290,56 +297,64 @@
290297
([]
291298
(readers-export (registry/state)
292299
default-reader-filenames
293-
default-reader-filename-res
300+
default-data-reader-filename
294301
default-handlers-pathname
295302
default-handlers-namespace))
296303
([^Registry registry]
297304
(readers-export registry
298305
default-reader-filenames
299-
default-reader-filename-res
306+
default-data-reader-filename
300307
default-handlers-pathname
301308
default-handlers-namespace))
302309
([^Registry registry filenames]
303310
(readers-export registry
304311
filenames
305-
default-reader-filename-res
312+
default-data-reader-filename
306313
default-handlers-pathname
307314
default-handlers-namespace))
308-
([^Registry registry filenames res-filename]
315+
([^Registry registry filenames data-filename]
309316
(readers-export registry
310317
filenames
311-
res-filename
318+
data-filename
312319
default-handlers-pathname
313320
default-handlers-namespace))
314-
([^Registry registry filenames res-filename handlers-pathname handlers-namespace]
321+
([^Registry registry filenames data-filename handlers-pathname handlers-namespace]
315322
(when-some [nsses (->> (.cur-id->cur ^Registry registry)
316323
(map (comp namespace first))
317324
(filter identity)
318325
set seq)]
319-
(let [m (->> nsses
320-
(map #(vector (symbol "money" %) (symbol handlers-namespace (str "lit-" %))))
321-
(into {'money 'io.randomseed.bankster.money/lit
322-
'currency 'io.randomseed.bankster.currency/lit}))]
326+
(let [m (->> nsses
327+
(map #(vector (symbol "money" %) (symbol handlers-namespace (str "code-literal-" %))))
328+
(into {'money 'io.randomseed.bankster.money/code-literal
329+
'currency 'io.randomseed.bankster.currency/code-literal}))
330+
dm (->> nsses
331+
(map #(vector (symbol "money" %) (symbol handlers-namespace (str "data-literal-" %))))
332+
(into {'money 'io.randomseed.bankster.money/data-literal
333+
'currency 'io.randomseed.bankster.currency/data-literal}))]
323334
(when-some [fdir (io/resource (first filenames))]
324335
(when-some [pdir (.getParent (io/file fdir))]
325336
(when-some [hfile (io/file pdir handlers-pathname)]
326337
(println)
327-
(println "------------------- readers map:")
338+
(println "------------- data readers map (for handling Clojure code):")
328339
(println)
329340
(puget/cprint m)
330341
(println)
342+
(println "------------- data readers map (for handling EDN data):")
343+
(println)
344+
(puget/cprint dm)
345+
(println)
331346
(doseq [f filenames]
332347
(let [fname (io/file pdir f)]
333348
(println "Exporting to:" (str fname))
334349
(spit fname (puget/pprint-str m))))
335-
(when-some [rdir (fs/resource-pathname default-resource-name
336-
default-resource-must-exist-file)]
337-
(let [fname (io/file (.getParent ^java.io.File (io/file rdir)) res-filename)]
350+
(when (some? (seq data-filename))
351+
(when-some [fname (io/file pdir data-filename)]
338352
(println "Exporting to:" (str fname))
339-
(spit fname (puget/pprint-str m))))
353+
(spit fname (puget/pprint-str dm))))
354+
(println)
340355
(println "Generating handlers code to:" (str hfile))
341356
(some->> nsses
342-
handler-gen
357+
(handler-gen)
343358
(cons (handler-preamble handlers-namespace))
344359
(map puget/pprint-str)
345360
(str/join (str \newline \newline))

test/io/randomseed/bankster/currency_test.clj

+4-1
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,10 @@
7777
#currency {:id :EUR :numeric 1000 :scale 2 :kind :FIAT} => {:id :EUR :domain nil :kind :FIAT :numeric 1000 :scale 2 :weight 0}
7878
#currency {:id :EUR :kind :FIAT} => {:id :EUR :domain nil :kind :FIAT :numeric -1 :scale -1 :weight 0}
7979
#currency {:id :EUR :numeric 1000 :kind :FIAT} => {:id :EUR :domain nil :kind :FIAT :numeric 1000 :scale -1 :weight 0}
80-
#currency {:id :EUR :scale 2 :kind :FIAT :domain :ISO-4217} => {:id :EUR :domain :ISO-4217 :kind :FIAT :numeric -1 :scale 2 :weight 0}))
80+
#currency {:id :EUR :scale 2 :kind :FIAT :domain :ISO-4217} => {:id :EUR :domain :ISO-4217 :kind :FIAT :numeric -1 :scale 2 :weight 0})
81+
(fact "when it can use different registries"
82+
(let [r (c/update (registry/get) #currency{:id PLN :scale 10})]
83+
(c/with-registry r #currency PLN)) => {:id :PLN :scale 10 :numeric -1 :weight 0 :kind nil :domain nil}))
8184

8285
(facts "about currency registering"
8386
(fact "when it returns nil for nil or empty map"

0 commit comments

Comments
 (0)