diff --git a/clj/src/cljd/core.cljd b/clj/src/cljd/core.cljd index 51867f0a..36f6485e 100644 --- a/clj/src/cljd/core.cljd +++ b/clj/src/cljd/core.cljd @@ -1659,6 +1659,10 @@ (-rseq [coll] "Returns a seq of the items in coll in reversed order.")) +(defn ^bool reversible? + "Returns true if coll satisfies? IReversible" + [coll] (satisfies? IReversible coll)) + (defn rseq "Returns, in constant time, a seq of the items in rev (which can be a vector or sorted-map), in reverse order. If rev is empty returns nil" @@ -1679,6 +1683,10 @@ "Like -sorted-seq bur returns a sequence in descending order. from and to MUST NOT be swapped, they are interpreted as per -sorted-seq.")) +(defn ^bool sorted? + "Returns true if coll satisfies ISorted" + [coll] (satisfies? ISorted coll)) + (defn subseq "sc must be a sorted collection, test(s) one of <, <=, > or >=. Returns a seq of those entries with keys ek for @@ -1967,6 +1975,13 @@ [x] (boolean (and (symbol? x) (namespace x) true))) +(defn ^bool special-symbol? + "Returns true if x names a special form" + [x] + (contains? '#{. & set! dart/is? dart/await dart/async-barrier dart/run-zoned dart/assert dart/type-like + throw new ns try catch finally case* quote do var let* loop* recur if fn* letfn def + reify* deftype* defprotocol* defmethod* defmulti* extend-type-protocol*} x)) + (defn symbol "Returns a Symbol with the given namespace and name. Arity-1 works on strings, keywords, and vars." @@ -9458,6 +9473,19 @@ specified. (double/tryParse s) (throw (ArgumentError (parsing-err s))))) +(def ^:private uuid-regex + #"^[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]-[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]-[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]-[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]-[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]$") + +(defn parse-uuid + "Parse a string representing a UUID and return a UUID instance, + or nil if parse fails. + + Grammar: https://docs.oracle.com/javase/8/docs/api/java/util/UUID.html#toString--" + [s] + (if (string? s) + (when (re-matches uuid-regex s) (uuid s)) + (throw (ArgumentError. (parsing-err s))))) + (defn ^bool? parse-boolean {:doc "Parse strings \"true\" or \"false\" and return a boolean, or nil if invalid" :added "1.11"} diff --git a/clj/src/cljd/reader.cljd b/clj/src/cljd/reader.cljd index 2de38314..bc7e19d4 100644 --- a/clj/src/cljd/reader.cljd +++ b/clj/src/cljd/reader.cljd @@ -585,15 +585,9 @@ (defn unquote-splicing? [form] (and (seq? form) (= 'cljd.core/unquote-splicing (first form)))) -;; TODO: should not be in reader.cljd -(defn special-form? [form] - (contains? '#{. set! dart/is? dart/await dart/async-barrier dart/run-zoned dart/assert dart/type-like - throw new ns try case* quote do var let* loop* recur if fn* letfn def reify* deftype* - defprotocol* defmethod* defmulti* extend-type-protocol*} form)) - (defn- syntax-quote [form] (cond - (special-form? form) (list 'quote form) + (special-symbol? form) (list 'quote form) (symbol? form) (let [nsform (namespace form) nameform (name form)] diff --git a/clj/test/cljd/test_clojure/parse.cljd b/clj/test/cljd/test_clojure/parse.cljd index c857bdb6..4bcb1266 100644 --- a/clj/test/cljd/test_clojure/parse.cljd +++ b/clj/test/cljd/test_clojure/parse.cljd @@ -1,6 +1,6 @@ (ns cljd.test-clojure.parse (:require - [clojure.test :refer [deftest is are]])) + [clojure.test :refer [deftest is are testing]])) (def max-int-32 0x7fffffff) ;; 2147483647 (def max-int-64 0x7fffffffffffffff) ;; 9223372036854775807 @@ -88,6 +88,38 @@ (is true res))) +(deftest test-parse-uuid + (are [x] (uuid? (parse-uuid x)) + "e2c6efed-dabf-4f55-90bd-58f2c22863be" + "1f43838a-80fc-4a8a-be89-306a343ac867") + + (testing "lower and upper case" + (let [uuid-lower (parse-uuid "cb048ac2-5e0b-439e-a59f-dfdf11651be0") + uuid-upper (parse-uuid "CB048AC2-5E0B-439E-A59F-DFDF11651BE0")] + (is (= uuid-lower uuid-upper)) + (is (uuid? uuid-lower)) + (is (uuid? uuid-upper)))) + + (testing "invalid format" + (are [x] (nil? (parse-uuid x)) + "" + "0" + "abc123" + "000000000-0000-0000-0000-000000000000" ;; extra leading + "00000000-0000-0000-0000-0000000000000")) ;; extra trailing + + (testing "bad input" + (are [x] (thrown? ArgumentError (parse-uuid x)) + nil + 0 + 0.0 + :foo + 'foo + [] + '() + {} + #{}))) + (deftest test-parse-boolean (is (identical? true (parse-boolean "true"))) (is (identical? false (parse-boolean "false"))) diff --git a/clj/test/cljd/test_clojure/predicates.cljd b/clj/test/cljd/test_clojure/predicates.cljd index fd5d48d3..84282326 100644 --- a/clj/test/cljd/test_clojure/predicates.cljd +++ b/clj/test/cljd/test_clojure/predicates.cljd @@ -143,29 +143,28 @@ (def pred-val-table (let [now (DateTime/now) - ;; uuid (java.util.UUID/randomUUID) + uuid (random-uuid) ;; barray (byte-array 0) iarray (int-array 0) uri (Uri/parse "http://clojure.org")] - [ - [identity int? pos-int? neg-int? nat-int? double? boolean? indexed? seqable? ident? #_uuid? #_decimal? inst? uri? #_bytes?] - [0 true false false true false false false false false #_false #_false false false #_false] - [1 true true false true false false false false false #_false #_false false false #_false] - [-1 true false true false false false false false false #_false #_false false false #_false] - [1.0 false false false false true false false false false #_false #_false false false #_false] - [true false false false false false true false false false #_false #_false false false #_false] - [[] false false false false false false true true false #_false #_false false false #_false] - [nil false false false false false false true true false #_false #_false false false #_false] - [{} false false false false false false false true false #_false #_false false false #_false] - [:foo false false false false false false false false true #_false #_false false false #_false] - ['foo false false false false false false false false true #_false #_false false false #_false] - #_[0.0M false false false false false false false false false #_false #_true false false #_false] - #_[0N false false false false false false false false false #_false #_false false false #_false] - #_[uuid false false false false false false false false false #_true #_false false false #_false] - [uri false false false false false false false false false #_false #_false false true #_false] - [now false false false false false false false false false #_false #_false true false #_false] - [iarray false false false false false false true true false #_false #_false false false #_false] - #_[barray false false false false false false false true false #_false #_false false false #_true]])) + [[identity int? pos-int? neg-int? nat-int? double? boolean? indexed? seqable? reversible? ident? uuid? #_decimal? inst? uri? #_bytes?] + [0 true false false true false false false false false false false #_false false false #_false] + [1 true true false true false false false false false false false #_false false false #_false] + [-1 true false true false false false false false false false false #_false false false #_false] + [1.0 false false false false true false false false false false false #_false false false #_false] + [true false false false false false true false false false false false #_false false false #_false] + [[] false false false false false false true true true false false #_false false false #_false] + [nil false false false false false false true true false false false #_false false false #_false] + [{} false false false false false false false true false false false #_false false false #_false] + [:foo false false false false false false false false false true false #_false false false #_false] + ['foo false false false false false false false false false true false #_false false false #_false] + #_[0.0M false false false false false false false false false false false #_true false false #_false] + #_[0N false false false false false false false false false false false #_false false false #_false] + [uuid false false false false false false false false false false true #_false false false #_false] + [uri false false false false false false false false false false false #_false false true #_false] + [now false false false false false false false false false false false #_false true false #_false] + [iarray false false false false false false true true false false false #_false false false #_false] + #_[barray false false false false false false false true false false false #_false false false #_true]])) (deftest test-preds (let [[preds & rows] pred-val-table] @@ -175,6 +174,24 @@ (is (= ((nth preds i) v) (nth row i)) (pr-str (list (get-fn-name (nth preds i)) v)))))))) +(deftest test-sorted? + (are [x] (not (sorted? x)) + nil + 0 + -1.0 + true + :abc + "" + [] + #{} + {} + [1 2 3]) + (are [x] (sorted? x) + (sorted-map) + (sorted-map-by compare :foo :bar) + (sorted-set) + (sorted-set-by compare :foo :bar))) + ;; Special double predicates (deftest test-double-preds @@ -201,3 +218,22 @@ (is (thrown? Error (infinite? nil-value))) (is (thrown? Error (infinite? kw-value)))) ) + +(deftest test-special-symbol? + (are [x] (not (special-symbol? x)) + nil + true + false + "foo" + 0 + 0.0 + :foo + 'foo/bar + 'defn + 'require + 'letfn* + 'ns/ns) + (are [x] (special-symbol? x) + '. '& 'set! 'if 'def 'throw 'new 'ns 'try 'catch 'finally 'do 'var 'letfn 'quote 'recur + 'dart/is? 'dart/await 'dart/async-barrier 'dart/run-zoned 'dart/assert 'dart/type-like + 'case* 'let* 'loop* 'fn* 'reify* 'deftype* 'defprotocol* 'defmethod* 'defmulti* 'extend-type-protocol*)) \ No newline at end of file