|
| 1 | +; Copyright (c) Rich Hickey. All rights reserved. |
| 2 | +; The use and distribution terms for this software are covered by the |
| 3 | +; Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php) |
| 4 | +; which can be found in the file epl-v10.html at the root of this distribution. |
| 5 | +; By using this software in any fashion, you are agreeing to be bound by |
| 6 | +; the terms of this license. |
| 7 | +; You must not remove this notice, or any other, from this software. |
| 8 | + |
| 9 | +(ns cljs.core.specs.alpha |
| 10 | + (:require [clojure.spec.alpha :as s] |
| 11 | + #?(:clj [cljs.core :as core] |
| 12 | + :cljs [cljs.core$macros :as core]))) |
| 13 | + |
| 14 | +;;;; destructure |
| 15 | + |
| 16 | +(s/def ::local-name (s/and simple-symbol? #(not= '& %))) |
| 17 | + |
| 18 | +(s/def ::binding-form |
| 19 | + (s/or :sym ::local-name |
| 20 | + :seq ::seq-binding-form |
| 21 | + :map ::map-binding-form)) |
| 22 | + |
| 23 | +;; sequential destructuring |
| 24 | + |
| 25 | +(s/def ::seq-binding-form |
| 26 | + (s/and vector? |
| 27 | + (s/cat :elems (s/* ::binding-form) |
| 28 | + :rest (s/? (s/cat :amp #{'&} :form ::binding-form)) |
| 29 | + :as (s/? (s/cat :as #{:as} :sym ::local-name))))) |
| 30 | + |
| 31 | +;; map destructuring |
| 32 | + |
| 33 | +(s/def ::keys (s/coll-of ident? :kind vector?)) |
| 34 | +(s/def ::syms (s/coll-of symbol? :kind vector?)) |
| 35 | +(s/def ::strs (s/coll-of simple-symbol? :kind vector?)) |
| 36 | +(s/def ::or (s/map-of simple-symbol? any?)) |
| 37 | +(s/def ::as ::local-name) |
| 38 | + |
| 39 | +(s/def ::map-special-binding |
| 40 | + (s/keys :opt-un [::as ::or ::keys ::syms ::strs])) |
| 41 | + |
| 42 | +(s/def ::map-binding (s/tuple ::binding-form any?)) |
| 43 | + |
| 44 | +(s/def ::ns-keys |
| 45 | + (s/tuple |
| 46 | + (s/and qualified-keyword? #(-> % name #{"keys" "syms"})) |
| 47 | + (s/coll-of simple-symbol? :kind vector?))) |
| 48 | + |
| 49 | +(s/def ::map-bindings |
| 50 | + (s/every (s/or :mb ::map-binding |
| 51 | + :nsk ::ns-keys |
| 52 | + :msb (s/tuple #{:as :or :keys :syms :strs} any?)) :into {})) |
| 53 | + |
| 54 | +(s/def ::map-binding-form (s/merge ::map-bindings ::map-special-binding)) |
| 55 | + |
| 56 | +;; bindings |
| 57 | + |
| 58 | +(s/def ::binding (s/cat :binding ::binding-form :init-expr any?)) |
| 59 | +(s/def ::bindings (s/and vector? (s/* ::binding))) |
| 60 | + |
| 61 | +;; let, if-let, when-let |
| 62 | + |
| 63 | +(s/fdef core/let |
| 64 | + :args (s/cat :bindings ::bindings |
| 65 | + :body (s/* any?))) |
| 66 | + |
| 67 | +(s/fdef core/if-let |
| 68 | + :args (s/cat :bindings (s/and vector? ::binding) |
| 69 | + :then any? |
| 70 | + :else (s/? any?))) |
| 71 | + |
| 72 | +(s/fdef core/when-let |
| 73 | + :args (s/cat :bindings (s/and vector? ::binding) |
| 74 | + :body (s/* any?))) |
| 75 | + |
| 76 | +;; defn, defn-, fn |
| 77 | + |
| 78 | +(s/def ::arg-list |
| 79 | + (s/and |
| 80 | + vector? |
| 81 | + (s/cat :args (s/* ::binding-form) |
| 82 | + :varargs (s/? (s/cat :amp #{'&} :form ::binding-form))))) |
| 83 | + |
| 84 | +(s/def ::args+body |
| 85 | + (s/cat :args ::arg-list |
| 86 | + :body (s/alt :prepost+body (s/cat :prepost map? |
| 87 | + :body (s/+ any?)) |
| 88 | + :body (s/* any?)))) |
| 89 | + |
| 90 | +(s/def ::defn-args |
| 91 | + (s/cat :name simple-symbol? |
| 92 | + :docstring (s/? string?) |
| 93 | + :meta (s/? map?) |
| 94 | + :bs (s/alt :arity-1 ::args+body |
| 95 | + :arity-n (s/cat :bodies (s/+ (s/spec ::args+body)) |
| 96 | + :attr (s/? map?))))) |
| 97 | + |
| 98 | +(s/fdef core/defn |
| 99 | + :args ::defn-args |
| 100 | + :ret any?) |
| 101 | + |
| 102 | +(s/fdef core/defn- |
| 103 | + :args ::defn-args |
| 104 | + :ret any?) |
| 105 | + |
| 106 | +(s/fdef core/fn |
| 107 | + :args (s/cat :name (s/? simple-symbol?) |
| 108 | + :bs (s/alt :arity-1 ::args+body |
| 109 | + :arity-n (s/+ (s/spec ::args+body)))) |
| 110 | + :ret any?) |
| 111 | + |
| 112 | +;;;; ns |
| 113 | + |
| 114 | +(s/def ::exclude (s/coll-of simple-symbol?)) |
| 115 | +(s/def ::only (s/coll-of simple-symbol?)) |
| 116 | +(s/def ::rename (s/map-of simple-symbol? simple-symbol?)) |
| 117 | +(s/def ::filters (s/keys* :opt-un [::exclude ::only ::rename])) |
| 118 | + |
| 119 | +(s/def ::ns-refer-clojure |
| 120 | + (s/spec (s/cat :clause #{:refer-clojure} |
| 121 | + :filters ::filters))) |
| 122 | + |
| 123 | +(s/def ::refer (s/coll-of simple-symbol?)) |
| 124 | +(s/def ::refer-macros (s/coll-of simple-symbol?)) |
| 125 | +(s/def ::include-macros #{true}) |
| 126 | + |
| 127 | +(s/def ::lib (s/or :sym simple-symbol? |
| 128 | + :str string?)) |
| 129 | + |
| 130 | +(s/def ::libspec |
| 131 | + (s/alt :lib ::lib |
| 132 | + :lib+opts (s/spec (s/cat :lib ::lib |
| 133 | + :options (s/keys* :opt-un [::as ::refer ::refer-macros ::include-macros]))))) |
| 134 | + |
| 135 | +(s/def ::macros-libspec |
| 136 | + (s/alt :lib simple-symbol? |
| 137 | + :lib+opts (s/spec (s/cat :lib simple-symbol? |
| 138 | + :options (s/keys* :opt-un [::as ::refer]))))) |
| 139 | + |
| 140 | +(s/def ::ns-require |
| 141 | + (s/spec (s/cat :clause #{:require} |
| 142 | + :body (s/+ (s/alt :libspec ::libspec |
| 143 | + :flag #{:reload :reload-all :verbose}))))) |
| 144 | + |
| 145 | +(s/def ::ns-require-macros |
| 146 | + (s/spec (s/cat :clause #{:require-macros} |
| 147 | + :body (s/+ (s/alt :libspec ::macros-libspec |
| 148 | + :flag #{:reload :reload-all :verbose}))))) |
| 149 | + |
| 150 | +(s/def ::package-list |
| 151 | + (s/spec |
| 152 | + (s/cat :package simple-symbol? |
| 153 | + :classes (s/* simple-symbol?)))) |
| 154 | + |
| 155 | +(s/def ::import-list |
| 156 | + (s/* (s/alt :class simple-symbol? |
| 157 | + :package-list ::package-list))) |
| 158 | + |
| 159 | +(s/def ::ns-import |
| 160 | + (s/spec |
| 161 | + (s/cat :clause #{:import} |
| 162 | + :classes ::import-list))) |
| 163 | + |
| 164 | +;; same as ::libspec, but also supports the ::filters options in the libspec |
| 165 | +(s/def ::use-libspec |
| 166 | + (s/alt :lib ::lib |
| 167 | + :lib+opts (s/spec (s/cat :lib ::lib |
| 168 | + :options (s/keys* :req-un [::only] :opt-un [::rename]))))) |
| 169 | + |
| 170 | +(s/def ::ns-use |
| 171 | + (s/spec (s/cat :clause #{:use} |
| 172 | + :libs (s/+ (s/alt :libspec ::use-libspec |
| 173 | + :flag #{:reload :reload-all :verbose}))))) |
| 174 | + |
| 175 | +;; same as ::libspec-macros, but also supports the ::filters options in the libspec |
| 176 | +(s/def ::use-macros-libspec |
| 177 | + (s/alt :lib simple-symbol? |
| 178 | + :lib+opts (s/spec (s/cat :lib simple-symbol? |
| 179 | + :options (s/keys* :req-un [::only] :opt-un [::rename]))))) |
| 180 | + |
| 181 | +(s/def ::ns-use-macros |
| 182 | + (s/spec (s/cat :clause #{:use-macros} |
| 183 | + :libs (s/+ (s/alt :libspec ::use-macros-libspec |
| 184 | + :flag #{:reload :reload-all :verbose}))))) |
| 185 | + |
| 186 | + |
| 187 | +(s/def ::ns-clauses |
| 188 | + (s/* (s/alt :refer-clojure ::ns-refer-clojure |
| 189 | + :require ::ns-require |
| 190 | + :require-macros ::ns-require-macros |
| 191 | + :import ::ns-import |
| 192 | + :use ::ns-use |
| 193 | + :use-macros ::ns-use-macros))) |
| 194 | + |
| 195 | +(s/def ::ns-form |
| 196 | + (s/cat :name simple-symbol? |
| 197 | + :docstring (s/? string?) |
| 198 | + :attr-map (s/? map?) |
| 199 | + :clauses ::ns-clauses)) |
| 200 | + |
| 201 | +#_(s/fdef clojure.core/ns |
| 202 | + :args ::ns-form) |
| 203 | + |
| 204 | +(defmacro ^:private quotable |
| 205 | + "Returns a spec that accepts both the spec and a (quote ...) form of the spec" |
| 206 | + [spec] |
| 207 | + `(s/or :spec ~spec :quoted-spec (s/cat :quote #{'quote} :spec ~spec))) |
| 208 | + |
| 209 | +(s/def ::quotable-import-list |
| 210 | + (s/* (s/alt :class (quotable simple-symbol?) |
| 211 | + :package-list (quotable ::package-list)))) |
| 212 | + |
| 213 | +(s/fdef core/import |
| 214 | + :args ::quotable-import-list) |
| 215 | + |
| 216 | +(s/fdef core/require |
| 217 | + :args (s/+ (s/spec (s/cat :quote #{'quote} |
| 218 | + :spec (s/alt :libspec ::libspec |
| 219 | + :flag #{:reload :reload-all :verbose}))))) |
| 220 | + |
| 221 | +(s/fdef core/require-macros |
| 222 | + :args (s/+ (s/spec (s/cat :quote #{'quote} |
| 223 | + :spec (s/alt :libspec ::macros-libspec |
| 224 | + :flag #{:reload :reload-all :verbose}))))) |
| 225 | + |
| 226 | +(s/fdef core/use |
| 227 | + :args (s/+ (s/spec (s/cat :quote #{'quote} |
| 228 | + :spec (s/alt :libspec ::use-libspec |
| 229 | + :flag #{:reload :reload-all :verbose}))))) |
| 230 | + |
| 231 | +(s/fdef core/use-macros |
| 232 | + :args (s/+ (s/spec (s/cat :quote #{'quote} |
| 233 | + :spec (s/alt :libspec ::use-macros-libspec |
| 234 | + :flag #{:reload :reload-all :verbose}))))) |
0 commit comments