-
Notifications
You must be signed in to change notification settings - Fork 19
/
macro_specs.cljc
176 lines (147 loc) · 4.32 KB
/
macro_specs.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
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
(ns debux.common.macro-specs
"clojure.core macro specs which are minified, simplified and modified."
(:require [clojure.spec.alpha :as s]))
(declare skip o-skip a-skip)
; skip => full skip
; o-skip => outermost skip
; a-skip => all args skip
;;; def
(defn name-unformer [name]
`(skip ~name))
(s/def ::name
(s/and
simple-symbol?
(s/conformer identity name-unformer)))
(s/def ::def-args
(s/cat :name ::name
:docstring (s/? string?)
:body (s/* any?) ))
;;; defn, defn-, fn
(defn arg-list-unformer [arg]
`(skip ~(vec arg)))
(s/def ::arg-list
(s/and
vector?
(s/conformer identity arg-list-unformer)
(s/cat :args (s/* any?))))
(s/def ::args+body
(s/cat :args ::arg-list
:body (s/alt :prepost+body (s/cat :prepost map?
:body (s/+ any?))
:body (s/* any?))))
(s/def ::defn-args
(s/cat :name ::name
:docstring (s/? string?)
:meta (s/? map?)
:bs (s/alt :arity-1 ::args+body
:arity-n (s/cat :bodies (s/+ (s/spec ::args+body))
:attr (s/? map?)))))
(s/def ::fn-args
(s/cat :name (s/? ::name)
:bs (s/alt :arity-1 ::args+body
:arity-n (s/cat :bodies (s/+ (s/spec ::args+body))))))
(comment
(def f1
'(defn add1
"add1 docstring"
{:added "1.0"}
[x y]
(+ x y)))
; => #'debux.common.macro-specs/f1
(s/conform ::defn-args (next f1))
; => {:name add1,
; :docstring "add1 docstring",
; :meta {:added "1.0"},
; :bs [:arity-1 {:args {:args [x y]},
; :body [:body [(+ x y)]]}]}
(def f1-1
'(defn add1
"add1 docstring"
{:added "1.0"}
[x y]
{:pre [(and (pos? x) (pos? y))]
:post [(pos? %)]}
(+ x y)))
(s/conform ::defn-args (next f1-1))
; => {:name add1,
; :docstring "add1 docstring",
; :meta {:added "1.0"},
; :bs
; [:arity-1
; {:args {:args [x y]},
; :body
; [:prepost+body
; {:prepost {:pre [(and (pos? x) (pos? y))], :post [(pos? %)]},
; :body [(+ x y)]}]}]}
(s/explain ::defn-args (next f1))
(def f2
'(defn add2
"add2 docstring"
{:added "1.0"}
([] 0)
([x] x)
([x y] (+ x y))
([x y & zs] (apply + x y zs))))
(s/conform ::defn-args (next f2))
; => {:name add2,
; :docstring "add2 docstring",
; :meta {:added "1.0"},
; :bs
; [:arity-n
; {:bodies
; [{:args {}, :body [:body [0]]}
; {:args {:args [x]}, :body [:body [x]]}
; {:args {:args [x y]}, :body [:body [(+ x y)]]}
; {:args {:args [x y & zs]}, :body [:body [(apply + x y zs)]]}]}]}
(def f2-2
'(defn add2
"add2 docstring"
{:added "1.0"}
([] 0)
([x] {:pre [(pos? x)]} x)
([x y] {:pre [(pos? x)]} (+ x y))
([x y & zs] {:pre [(pos? x)]} (apply + x y zs))))
(s/conform ::defn-args (next f2-2))
; => {:name add2,
; :docstring "add2 docstring",
; :meta {:added "1.0"},
; :bs
; [:arity-n
; {:bodies
; [{:args {}, :body [:body [0]]}
; {:args {:args [x]},
; :body [:prepost+body {:prepost {:pre [(pos? x)]},
; :body [x]}]}
; {:args {:args [x y]},
; :body [:prepost+body {:prepost {:pre [(pos? x)]}, :body [(+ x y)]}]}
; {:args {:args [x y & zs]},
; :body [:prepost+body {:prepost {:pre [(pos? x)]}, :body [(apply + x y zs)]}]}]}]}
(s/explain ::defn-args (next f2))
(def f3
'(fn add1
[x y]
(+ x y)))
(def f4
'(fn add2
([] 0)
([x] x)
([x y] (+ x y))
([x y & zs] (apply + x y zs))))
(def f5 '#(+ % %2))
(s/conform ::fn-args (next f3))
; => {:name add1,
; :bs [:arity-1 {:args {:args [x y]},
; :body [:body [(+ x y)]]}]}
(s/explain ::fn-args (next f3))
(s/conform ::fn-args (next f4))
; => {:name add2,
; :bs [:arity-n {:bodies [{:args {}, :body [:body [0]]}
; {:args {:args [x]}, :body [:body [x]]}
; {:args {:args [x y]}, :body [:body [(+ x y)]]}
; {:args {:args [x y & zs]}, :body [:body [(apply + x y zs)]]}]}]}
(s/explain ::fn-args (next f4))
(s/conform ::fn-args (next f5))
; => {:bs [:arity-1 {:args {:args [p1__30164# p2__30165#]},
; :body [:body [(+ p1__30164# p2__
(s/explain ::fn-args (next f5))
) ; end of comment