-
Notifications
You must be signed in to change notification settings - Fork 0
/
specs.clj
101 lines (76 loc) · 2.9 KB
/
specs.clj
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
(ns defrag.specs
(:require [clojure.spec.alpha :as s]))
;;; This ns coppied from clojure.core.specs.alpha 0.2.44, with slight modifications
;;;; destructure
(s/def ::local-name (s/and simple-symbol? #(not= '& %)))
(s/def ::binding-form
(s/or :local-symbol ::local-name
:seq-destructure ::seq-binding-form
:map-destructure ::map-binding-form))
;; sequential destructuring
(s/def ::seq-binding-form
(s/and vector?
(s/conformer identity vec)
(s/cat :elems (s/* ::binding-form)
:rest (s/? (s/cat :amp #{'&} :form ::binding-form))
:as (s/? (s/cat :as #{:as} :sym ::local-name)))))
;; map destructuring
(s/def ::keys (s/coll-of ident? :kind vector?))
(s/def ::syms (s/coll-of symbol? :kind vector?))
(s/def ::strs (s/coll-of simple-symbol? :kind vector?))
(s/def ::or (s/map-of simple-symbol? any?))
(s/def ::as ::local-name)
(s/def ::map-special-binding
(s/keys :opt-un [::as ::or ::keys ::syms ::strs]))
(s/def ::map-binding (s/tuple ::binding-form any?))
(s/def ::ns-keys
(s/tuple
(s/and qualified-keyword? #(-> % name #{"keys" "syms"}))
(s/coll-of simple-symbol? :kind vector?)))
(s/def ::map-bindings
(s/every (s/or :map-binding ::map-binding
:qualified-keys-or-syms ::ns-keys
:special-binding (s/tuple #{:as :or :keys :syms :strs} any?)) :kind map?))
(s/def ::map-binding-form (s/merge ::map-bindings ::map-special-binding))
;; bindings
(defn even-number-of-forms?
"Returns true if there are an even number of forms in a binding vector"
[forms]
(even? (count forms)))
(s/def ::binding (s/cat :form ::binding-form :init-expr any?))
(s/def ::bindings (s/and vector? even-number-of-forms? (s/* ::binding)))
;; defn, defn-, fn
(defn arg-list-unformer [a]
(vec
(if (and (coll? (last a)) (= '& (first (last a))))
(concat (drop-last a) (last a))
a)))
(s/def ::param-list
(s/and
vector?
(s/conformer identity arg-list-unformer)
(s/cat :args (s/* ::binding-form)
:varargs (s/? (s/cat :amp #{'&} :form ::binding-form)))))
(s/def ::params+body
(s/cat :params ::param-list
:body (s/alt :prepost+body (s/cat :prepost map?
:body (s/+ any?))
:body (s/* any?))))
(s/def ::defn-args
(s/cat :fn-name simple-symbol?
:docstring (s/? string?)
:meta (s/? map?)
:fn-tail (s/alt :arity-1 ::params+body
:arity-n (s/cat :bodies (s/+ (s/spec ::params+body))
:attr-map (s/? map?)))))
;; (s/fdef clojure.core/defn
;; :args ::defn-args
;; :ret any?)
;; (s/fdef clojure.core/defn-
;; :args ::defn-args
;; :ret any?)
;; (s/fdef clojure.core/fn
;; :args (s/cat :fn-name (s/? simple-symbol?)
;; :fn-tail (s/alt :arity-1 ::params+body
;; :arity-n (s/+ (s/spec ::params+body))))
;; :ret any?)