 (ns spec-tools.core
-  (:refer-clojure :exclude [type string? integer? int? double? keyword? boolean? uuid? inst?])
+  (:refer-clojure :exclude [type any? some?
+                            number? integer? int? pos-int? neg-int? nat-int? float? double?
+                            boolean? string? ident? simple-ident? qualified-ident?
+                            keyword? simple-keyword? qualified-keyword? symbol? simple-symbol? qualified-symbol?
+                            uuid? uri? bigdec? inst? seqable? indexed? map? vector? list? seq? char? set?
+                            nil? false? true? zero? rational? coll? empty? associative? sequential? ratio? bytes?])
   #?(:cljs (:require-macros [spec-tools.core :refer [type]]))
   (:require
     [clojure.spec :as s]

  (gen* [_ _ _ _] (if gfn
                    (gfn)
                    (gen/gen-for-pred pred)))
  (with-gen* [_ gfn] (->Type form pred gfn info))
  (describe* [_] `(spec-tools.core/type ~form ~info))
  IFn
  #?(:clj  (invoke [_ x] (pred x))
     :cljs (-invoke [_ x] (pred x)))

     (.write w (str "#Type"
                    (merge
                      {:pred (:form t)}
                      (extra-type-map t))))))

(defmacro type
  ([pred]
   `(map->Type {:form '~(or (->> pred #?(:clj resolve, :cljs (resolve &env)) ->sym) pred), :pred ~pred}))
  ([pred info]
   `(map->Type (merge ~info {:form '~(or (->> pred #?(:clj resolve, :cljs (resolve &env)) ->sym) pred), :pred ~pred}))))

(defn with-info [^Type t info]
  (assoc t :info info))

(defn info [^Type t]
  (:info t))
