-
Notifications
You must be signed in to change notification settings - Fork 5
/
dstr.cljc
149 lines (130 loc) · 4.88 KB
/
dstr.cljc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
(ns ont-app.vocabulary.dstr
{:doc "Defines DatatypeStr type to inform #voc/dstr custom reader tag"
:author "Eric D. Scott"
}
(:require
[clojure.spec.alpha :as spec]
#?(:cljs [cljs.compiler])))
;;;;;;;;
;; spec
;;;;;;;;;
(declare datatypestring-re)
(spec/def :dstr/valid-string (fn [s] (re-matches datatypestring-re s)))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; DATATYPE STR
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(deftype DatatypeStr [s datatype]
Object
(hashCode [this] (hash (str (.s this) "^^" (.datatype this))))
(toString [_] s)
#?(:clj
(equals [this that]
(and (instance? DatatypeStr that)
(= (.s this) (.s that))
(= (.datatype this) (.datatype that))))))
;; for clj...
#?(:clj
(defmethod print-method DatatypeStr
[^DatatypeStr literal ^java.io.Writer w]
(.write w (pr-str (tagged-literal 'voc/dstr (str literal "^^" (.datatype literal)))))))
#?(:clj
(defmethod print-dup DatatypeStr [o ^java.io.Writer w]
(print-method o w)))
;; for cljs ...
#?(:cljs
(extend-protocol IPrintWithWriter
DatatypeStr
(-pr-writer [this writer _]
(write-all writer "#voc/dstr \"" (.toString this) "^^" (.-datatype this) "\""))))
#?(:cljs
(extend-protocol IEquiv
DatatypeStr
(-equiv [this that]
(and (instance? DatatypeStr that)
(= (str (.-s this)) (str (.-s ^DatatypeStr that)))
(= (str (.-datatype this)) (str (.-datatype ^DatatypeStr that)))))))
#?(:cljs
(defmethod cljs.compiler/emit-constant* ont_app.vocabulary.dstr.DatatypeStr
;; Emits a string of js instantiating a DatatypeStr
[^DatatypeStr x]
(apply cljs.compiler/emits [(str "new DatatypeStr (\""
(#?(:clj .s :cljs .-s) x)
"\" , \""
(#?(:clj .datatype :cljs .-datatype) x)
"\")")])))
(defn datatype
"returns the datatype tag associated with `datatypeStr`"
[^DatatypeStr datatypeStr]
(#?(:clj .datatype
:cljs .-datatype) datatypeStr))
(def ^:private datatypestring-re
"A regex matching and destructuring DatatypeStr format.
- Match := [_ `value` `datatype`]"
#?(:clj (re-pattern (str "(?s)" ;; match all including newline
"(" ;; start group 1
".+" ;; at least one of anything
")" ;; end group 1
"\\^\\^" ;; ^^
"(" ;; start group 2
".+" ;; at least one of anything
")" ;; end group 2
"$"
))
:cljs (re-pattern (str "^" ;; start
"(" ;; start group 1
"(?:" ;; start non-capturing group
"." ;; single char
"|" ;; or
"\\s" ;; space
")" ;; end non-capturing group
"*" ;; 0 or more of the non-capturing group
")" ;; end group 1
"\\^\\^" ;; ^^
"(" ;; start group 2
".+" ;; at least one char
")" ;; end group 2
))
))
;; END READER MACROS
(defn parse
"Returns [`datum` `datatype`] for `s`, or nil
- Where
-`s` is a string :~ `datum`^^`datatype`
- `datum` is a string
- `datatype` is is a string
"
[form]
(when-let [[_ datum datatype] (re-matches datatypestring-re form)]
[datum datatype]))
(defn read-DatatypeStr
"Returns an instance of DatatypeStr parsed from `form`
- Where:
- `form` :- `datum`^^`datatype`"
^DatatypeStr [form]
(if-let [[datum datatype] (parse form)]
(DatatypeStr. datum datatype)
;; else no parse
(throw (ex-info "Bad DatatypeString format"
{:type ::BadDatatypestringFormat
:regex datatypestring-re
:form form}))))
(defn read-DatatypeStr-cljs
"Returns a macro expression for read-DatatypeStr suitable for insertion and interpretation in cljs source."
^DatatypeStr [form]
`(read-DatatypeStr ~form))
(def default-tags
"A map := {(type `obj`) `tag`, ...}
- Where
-`obj` is a clojure value
-`tag` is a qname for the resource tagging the datatype of `obj`
- NOTE: this informs the `voc/tag` method's 1-arg version
"
(atom {(type 0) "xsd:long"
(type 0.0) "xsd:double"
(type true) "xsd:Boolean"
(type #inst "2000") "xsd:dateTime"
(type "") "xsd:string"
(type (short 0)) "xsd:short"
(type (byte 0)) "xsd:byte"
(type (float 0)) "xsd:float"
}))