moving some code around, adding call to play card

--- cartagena-web/src/cartagena_web/main.cljs
+++ cartagena-web/src/cartagena_web/main.cljs
@@ -244,12 +244,39 @@
   [game-state]
   (first (filter #(= (:current-player game-state) (:name %)) (:players game-state))))

+(defn on-error [{:keys [status status-text]}]
+  (.log js/console (str "ERROR [" status "] " status-text)))
+
+(defn on-new-game [response]
+  (println "on-new-game" response)
+  (reset! app-state response))
+
+(defn new-game! []
+  (ajax/POST "http://localhost:3000/new-game"
+             {:params {:players [{:name "tanya" :color :orange} {:name "rusty" :color :black}]}
+              :handler on-new-game
+              :error-handler on-error}))
+
+(defn on-play-card [response]
+  (println "on-play-card" response))
+
+(defn play-card! [player card from-space board discard-pile]
+  (ajax/POST "http://localhost:3000/play-card"
+             {:params {:player player
+                       :icon card
+                       :from-space from-space
+                       :board board
+                       :discard-pile discard-pile}
+              :handler on-play-card
+              :error-handler on-error}))
+
 (defn pirate-click [color from-space-index]
-  (if-let [selected-card (:selected-card @app-state)]
-    (when (= color (:color (active-player @app-state)))
-      (do
-        (println "moving" color "from" from-space-index "to" selected-card "; call the server and get the new game state back")
-        (reset! app-state (dissoc @app-state :selected-card)))
+  (when (= color (:color (active-player @app-state)))
+    (if-let [selected-card (:selected-card @app-state)]
+      (let [player (active-player @app-state)
+            board (:board @app-state)
+            from-space (get board from-space-index)]
+        (play-card! player selected-card from-space board (:discard-pile @app-state)))
       (println "moving" color "from" from-space-index "backward; call the server and get the new game state back"))))

 (defn jail []
@@ -324,18 +351,6 @@
     (println "card-click" card)
     (reset! app-state (assoc @app-state :selected-card card))))

-(defn on-error [{:keys [status status-text]}]
-  (.log js/console (str "ERROR [" status "] " status-text)))
-
-(defn on-new-game [response]
-  (println "on-new-game" response)
-  (reset! app-state response))
-
-(defn new-game! []
-  (ajax/POST "http://localhost:3000/new-game"
-             {:params {:players [{:name "tanya" :color :orange} {:name "rusty" :color :black}]}
-              :handler on-new-game
-              :error-handler on-error}))

 (defn main-view []
   [:center


Add heartbeat timeout

Add heartbeat timeout

--- src/zoo_event/events.clj
+++ src/zoo_event/events.clj
@@ -1,7 +1,7 @@
 (ns zoo-event.events
   (:require [clj-kafka.core :refer [with-resource]]
             [cheshire.core :refer [parse-string generate-string]]
-            [clojure.core.async :refer [go <! <!! map< sub chan close! go-loop >!]]
+            [clojure.core.async :refer [go <! <!! map< sub chan close! go-loop >! timeout alts!]]
             [zoo-event.web.resp :refer :all]
             [korma.core :refer :all]
             [clojure.string :as str]
@@ -44,15 +44,19 @@
 (def process-event ^{:private true}
   (comp #(str % "\n") generate-string filter-user-data :event))

+(defn- message-or-heartbeat
+  [stream]
+  (or (alts! (<! stream) (timeout 30000) "Heartbeat")))
+
 (defn- streaming-response
   [msgs type project req]
   (let [inchan (sub msgs (str type "/" project) (chan))
         stream (map< process-event inchan)]
     (with-channel req channel
       (send! channel (resp-ok "Stream Start\n" stream-mime) false)
-      (let [writer (go-loop [msg (<! stream)]
+      (let [writer (go-loop [msg (message-or-heartbeat stream)]
                             (send! channel (resp-ok msg stream-mime) false)
-                            (recur (<! stream)))]
+                            (recur (message-or-heartbeat stream)))]
         (on-close channel (fn [status]
                             (close! writer)
                             (close! stream)


BUGFIX: fixed wrong call in stroke-weight.

--- rosado/processing/processing.clj
+++ rosado/processing/processing.clj
@@ -679,7 +679,7 @@

 (defn stroke-join [jn] (.strokeJoin *applet* (int jn)))

-(defn stroke-weight [weight] (.strokeJoin *applet* (float weight)))
+(defn stroke-weight [weight] (.strokeWeight *applet* (float weight)))

 ;; $$subset


Changed load-resources to load according to newest Clojure svn version

--- rosado/processing/processing.clj
+++ rosado/processing/processing.clj
@@ -11,7 +11,7 @@

 (clojure/ns rosado.processing
 			(:import (processing.core PApplet PImage PGraphics PFont))
-			(:load-resources "constants.clj"))
+			(:load "constants.clj"))

 ;; used by functions in this lib. Use binding to set it
 ;; to an instance of processing.core.PApplet


better isolation of join fn-ality

better isolation of join fn-ality

--- dada2-core/src/test/clojure/org/dada2/test_join_model.clj
+++ dada2-core/src/test/clojure/org/dada2/test_join_model.clj
@@ -97,22 +97,25 @@
 ;;--------------------------------------------------------------------------------
 ;; this layer encapsulates access to both lhs and rhs at the same time...

-(defn- derive-joins [rhs-indeces lhs-fk-keys lhs join-fn]
+(defn- lhs-join [rhs-indeces lhs-fk-keys lhs join-fn]
   (map
    (fn [args] (apply join-fn lhs args))
    (permute [[]] (rhses-get rhs-indeces lhs-fk-keys lhs))))

+(defn- rhs-join [rhs-indeces lhs-fk-keys join-fn lhs-indeces i fk]
+  (mapcat (fn [lhs] (lhs-join rhs-indeces lhs-fk-keys lhs join-fn)) (lhses-get lhs-indeces i fk)))
+
 ;;--------------------------------------------------------------------------------

 (defn- lhs-upsert [[old-lhs-index rhs-indeces old-joins] lhs-pk-key lhs-fk-keys lhs join-fn join-pk joined-model]
   (let [new-lhs-indeces (lhs-assoc old-lhs-index lhs-pk-key lhs-fk-keys lhs)
-	joins (derive-joins rhs-indeces lhs-fk-keys lhs join-fn)
+	joins (lhs-join rhs-indeces lhs-fk-keys lhs join-fn)
 	new-joins (reduce (fn [old-joins join] (assoc old-joins (join-pk join) join)) old-joins joins)]
     [[new-lhs-indeces rhs-indeces new-joins] (fn [_] (on-upserts joined-model joins))]))

 (defn- lhs-delete [[old-lhs-indeces rhs-indeces old-joins] lhs-pk-key lhs-fk-keys lhs join-fn join-pk joined-model]
   (let [new-lhs-indeces (lhs-dissoc old-lhs-indeces lhs-pk-key lhs-fk-keys lhs)
-	joins (derive-joins rhs-indeces lhs-fk-keys lhs join-fn)
+	joins (lhs-join rhs-indeces lhs-fk-keys lhs join-fn)
 	new-joins (reduce (fn [old-joins join] (dissoc old-joins (join-pk join))) old-joins joins)]
     [[new-lhs-indeces rhs-indeces new-joins] (fn [_] (on-deletes joined-model joins))]))

@@ -135,8 +138,7 @@
 (defn- rhs-upsert [[lhs-indeces old-rhs-indeces old-joins] i rhs-pk-key rhs-fk-key lhs-fk-keys rhs join-fn join-pk joined-model]
   (let [fk (rhs-fk-key rhs)
 	new-rhs-indeces (rhs-assoc old-rhs-indeces i rhs-pk-key fk rhs)
-	lhses (lhses-get lhs-indeces i fk)
-	joins (mapcat (fn [lhs] (derive-joins new-rhs-indeces lhs-fk-keys lhs join-fn)) lhses)
+	joins (rhs-join new-rhs-indeces lhs-fk-keys join-fn lhs-indeces i fk)
 	new-joins (reduce (fn [old-joins join] (assoc old-joins (join-pk join) join)) old-joins joins)
 	]
     [[lhs-indeces new-rhs-indeces new-joins] (fn [_] (on-upserts joined-model joins))]
@@ -146,11 +148,9 @@
 (defn- rhs-delete [[lhs-indeces old-rhs-indeces old-joins]
 		   i rhs-pk-key rhs-fk-key lhs-fk-keys rhs join-fn join-pk joined-model]
   (let [fk (rhs-fk-key rhs)
-	lhses (lhses-get lhs-indeces i fk)
-	;;old-joins2 (mapcat (fn [lhs] (derive-joins old-rhs-indeces lhs-fk-keys lhs join-fn)) lhses)
 	old-joins2 (vals old-joins)
 	new-rhs-indeces (rhs-dissoc old-rhs-indeces i rhs-pk-key fk rhs)
-	new-joins2 (mapcat (fn [lhs] (derive-joins new-rhs-indeces lhs-fk-keys lhs join-fn)) lhses)
+	new-joins2 (rhs-join new-rhs-indeces lhs-fk-keys join-fn lhs-indeces i fk)
 	joins (remove (fn [i] (contains? (apply hash-set new-joins2) i)) old-joins2)
 	new-joins (reduce (fn [old-joins join] (dissoc old-joins (join-pk join))) old-joins joins)
 	]


converted more tests

converted more tests

--- test/cljs/cljs/core_test.cljs
+++ test/cljs/cljs/core_test.cljs
@@ -676,6 +676,12 @@
     ;; vary-meta
     (is (= {:a 1} (meta (vary-meta [] assoc :a 1))))
     (is (= {:a 1 :b 2} (meta (vary-meta (with-meta [] {:b 2}) assoc :a 1))))
+    ;; comparator
+    (is (= [1 1 2 2 3 5] (seq (.sort (to-array [2 3 1 5 2 1]) (comparator <)))))
+    (is (= [5 3 2 2 1 1] (seq (.sort (to-array [2 3 1 5 2 1]) (comparator >)))))
+    (is (= (hash 'foo) (hash (symbol "foo"))))
+    (is (= (hash 'foo/bar) (hash (symbol "foo" "bar"))))
+    (is (= (lazy-cat [1] [2] [3]) '(1 2 3)))
     ))

 (deftest test-booleans
@@ -1123,6 +1129,9 @@
 (defmethod my-map? ::map [_] true)
 (defmethod my-map? :default [_] false)

+(defmulti foo2' identity)
+(defmethod foo2' 0 [x] x)
+
 (deftest test-multimethods-2
   (let [r (rect 4 13)
         c (circle 12)]
@@ -1136,13 +1145,11 @@
       ;; CLJS-863
       (is (= :foo (foo2)))
       ;; remove method tests
-      ;; TODO: these side-effects return fn values
-      ;; will interact badly with cljs.test need to fix - David
-      ;; (is (= 2 (count (methods bar))))
-      ;; (remove-method bar [::rect ::shape])
-      ;; (is (= 1 (count (methods bar))))
-      ;; (remove-all-methods bar)
-      ;; (is (zero? (count (methods bar))))
+      (is (= 2 (count (methods bar))))
+      (remove-method bar [::rect ::shape])
+      (is (= 1 (count (methods bar))))
+      (remove-all-methods bar)
+      (is (zero? (count (methods bar))))
       (is (= [:three '(2)] (apply apply-multi-test [0 1 2])))
       (is (try
             (no-dispatch-value {:test :test})
@@ -1154,6 +1161,8 @@
       (is (every? true?
             (for [not-m [[] 1 "asdf" :foo]]
               (not (my-map? not-m)))))
+      ;; multimethod hashing
+      (is (= foo2' (ffirst {foo2' 1})))
 )))

 (deftest test-range
@@ -1178,6 +1187,16 @@
     (is (= (count (range 0 0 0)) 0))
     (is (= (take 3 (range 1 0 0)) (list 1 1 1)))
     (is (= (take 3 (range 3 1 0)) (list 3 3 3)))
+    ))
+
+(deftest test-rseq
+  (testing "Testing RSeq"
+    (is (= '(3 2 1) (reverse (seq (array 1 2 3)))))
+    (is (= '(3 2 1) (reverse [1 2 3])))
+    (is (= '(4 3 2 1) (cons 4 (reverse [1 2 3]))))
+    (is (= 6 (reduce + (reverse [1 2 3]))))
+    (is (= '(4 3 2) (map inc (reverse [1 2 3]))))
+    (is (= '(4 2) (filter even? (reverse [1 2 3 4]))))
     ))

 (deftest test-sorted-map
@@ -1590,6 +1609,179 @@
     (is (=  1 (compare (subvec [1 2 4] 1) (subvec [1 2 3] 1)))))
   )

+(deftest test-dot
+  (let [s "abc"]
+   (testing "Testing dot operations"
+     (is (= 3 (.-length s)))
+     (is (= 3 (. s -length)))
+     (is (= 3 (. (str 138) -length)))
+     (is (= 3 (. "abc" -length)))
+     (is (= "bc" (.substring s 1)))
+     (is (= "bc" (.substring "abc" 1)))
+     (is (= "bc" ((memfn substring start) s 1)))
+     (is (= "bc" (. s substring 1)))
+     (is (= "bc" (. s (substring 1))))
+     (is (= "bc" (. s (substring 1 3))))
+     (is (= "bc" (.substring s 1 3)))
+     (is (= "ABC" (. s (toUpperCase))))
+     (is (= "ABC" (. "abc" (toUpperCase))))
+     (is (= "ABC" ((memfn toUpperCase) s)))
+     (is (= "BC" (. (. s (toUpperCase)) substring 1)))
+     (is (= 2 (.-length (. (. s (toUpperCase)) substring 1))))
+     )))
+
+(defrecord Person [firstname lastname])
+(defrecord A [])
+(defrecord C [a b c])
+(defrecord A' [x])
+(defrecord B' [x])
+
+(deftest test-records
+  (let [fred (Person. "Fred" "Mertz")
+        fred-too (Person. "Fred" "Mertz")
+        ethel (with-meta (assoc (Person. "Ethel" "Mertz") :husband :fred)
+                {:married true})
+        ethel-too (with-meta (assoc (Person. "Ethel" "Mertz")  :husband :fred)
+                    {:married true})
+        letters (C. "a" "b" "c")
+        more-letters (assoc letters :d "d" :e "e" :f "f")]
+    (testing "Testing records"
+      (is (= (:firstname fred) "Fred"))
+      (is (= fred fred-too))
+      (is (false? (= fred nil)))
+      (is (false? (= nil fred)))
+      (is (= (meta ethel) {:married true}))
+      (is (= ethel ethel-too))
+      (is (= (map->Person {:firstname "Fred" :lastname "Mertz"}) fred))
+      (is (= (->Person "Fred" "Mertz") fred))
+      (is (= (count fred) 2))
+      (is (= (count ethel) 3))
+      (is (= (conj fred {:wife :ethel :friend :ricky})
+                (map->Person {:firstname "Fred" :lastname "Mertz" :wife :ethel :friend :ricky})))
+      (is (= (conj fred {:lastname "Flintstone"})
+                (map->Person {:firstname "Fred" :lastname "Flintstone"})))
+      (is (= (assoc fred :lastname "Flintstone")
+                (map->Person {:firstname "Fred" :lastname "Flintstone"})))
+      (is (= (assoc fred :wife :ethel)
+                (map->Person {:firstname "Fred" :lastname "Mertz" :wife :ethel})))
+      (is (= (dissoc ethel :husband)
+                (map->Person {:firstname "Ethel" :lastname "Mertz"})))
+      (is (= {:foo 'bar} (meta (with-meta (A.) {:foo 'bar}))))
+      (is (= 'bar (:foo (assoc (A.) :foo 'bar))))
+      (is (= (set (keys letters)) #{:a :b :c}))
+      (is (= (set (keys more-letters)) #{:a :b :c :d :e :f}))
+      (is (= (set (keys (dissoc more-letters :d))) #{:a :b :c :e :f}))
+      (is (= (set (keys (dissoc more-letters :d :e))) #{:a :b :c :f}))
+      (is (= (set (keys (dissoc more-letters :d :e :f))) #{:a :b :c}))
+      (is (not= (A'. nil) (B'. nil))))))
+
+(deftype FnLike []
+  IFn
+  (-invoke [_] :a)
+  (-invoke [_ a] :b)
+  (-invoke [_ a b] :c))
+
+(deftype FnLikeB [a]
+  IFn
+  (-invoke [_] a))
+
+(deftest test-ifn
+  (testing "Testing IFn implementations"
+    (is (= :a ((FnLike.))))
+    (is (= :b ((FnLike.) 1)))
+    (is (= :c ((FnLike.) 1 2)))
+    (is (= [:b :b :b] (map (FnLike.) [0 0 0])))
+    (is (= 1 ((FnLikeB. 1))))
+    ))
+
+(deftest test-case
+  (testing "Test case expr"
+    (let [x 1]
+      (is (= (case x 1 :one) :one)))
+    (let [x 1]
+      (is (= (case x 2 :two :default) :default)))
+    (let [x 1]
+      (is (= (try
+                   (case x 3 :three)
+                   (catch js/Error e
+                     :fail))
+                :fail)))
+    (let [x 1]
+      (is (= (case x
+                   (1 2 3) :ok
+                   :fail)
+                :ok)))
+    (let [x [:a :b]]
+      (is (= (case x
+                   [:a :b] :ok)
+                :ok)))
+    (let [a 'a]
+      (is (= (case a
+                   nil nil
+                   & :amp
+                   :none)
+                :none)))
+    (let [a '&]
+      (is (= (case a
+                   nil nil
+                   & :amp
+                   :none)
+                :amp)))
+    (let [foo 'a]
+      (testing "multiple match"
+        (is (= (case foo
+                 (a b c) :sym
+                 :none)
+              :sym))
+        (is (= (case foo
+                 (b c d) :sym
+                 :none)
+              :none))))
+    ))
+
+(defprotocol IHasFirst
+  (-get-first [this]))
+
+(defprotocol IFindsFirst
+  (-find-first [this other]))
+
+(deftype First [xs]
+  ISeqable
+  (-seq [this] (seq xs))
+  IIndexed
+  (-nth [this i] (nth xs i))
+  (-nth [this i not-found] (nth xs i not-found))
+  IFn
+  (-invoke [[x]] x)
+  (-invoke [this x] this)
+  Object
+  (toString [[x]] (str x))
+  IHasFirst
+  (-get-first [[x]] x)
+  IFindsFirst
+  (-find-first [_ [x]] x))
+
+(deftype DestructuringWithLocals [a]
+  IFindsFirst
+  (-find-first [_ [x y]]
+    [x y a]))
+
+(deftest test-protocol-method-destructuring
+  (testing "Testing protocol method destructuring"
+    (let [fv (First. [1 2 3])
+          fs (First. "asdf")]
+      (testing "basic operations"
+        (is (= (fv) 1))
+        (is (= (fs) \a))
+        (is (= (str fs) \a))
+        (is (= (-get-first fv) 1))
+        (is (= (-get-first fs) \a))
+        (is (= (-find-first fv [1]) 1))
+        (is (identical? (fv 1) fv))))
+    (let [t (DestructuringWithLocals. 1)]
+      (testing "with locals"
+        (is (= [2 3 1] (-find-first t [2 3])))))))
+
 ;; =============================================================================
 ;; Tickets

@@ -1606,6 +1798,493 @@
   (testing "Testing CLJS-513"
     (let [sentinel (js-obj)]
       (is (identical? sentinel (try ([] 0) (catch js/Error _ sentinel)))))))
+
+(defprotocol IFoo (foo [this]))
+
+(deftest test-reify-meta
+  (is (= (meta (with-meta (reify IFoo (foo [this] :foo)) {:foo :bar}))
+            {:foo :bar})))
+
+;; hashing bug in many JS runtimes CLJ-118
+(deftest test-clj-118
+  (let [g #{(conj #{:2} :alt)}
+        h #{#{:2 :alt}}]
+    (is (= g h)))
+  (is (= (hash {:a 1 :b 2})
+            (hash {:b 2 :a 1})))
+  (is (= (hash (hash-map :a 1 :b 2))
+            (hash (hash-map :b 2 :a 1))))
+  (is (= (hash {:start 133 :end 134})
+            (hash (apply hash-map [:start 133 :end 134]))))
+  (is (= (hash :a)
+            (hash (keyword "a")))))
+
+(defprotocol IBar (-bar [this x]))
+
+(defn baz [f]
+  (reify
+    IBar
+    (-bar [_ x]
+      (f x))))
+
+(deftest test-405
+  (is (= 2 (-bar (baz inc) 1))))
+
+(let [x "original"]
+  (defn original-closure-stmt [] x))
+
+(deftest test-401-411
+  (let [x "overwritten"]
+    (is (= "original" (original-closure-stmt))))
+  (is (= "original" (let [x "original"
+                               oce (fn [] x)
+                               x "overwritten"]
+                           (oce)))))
+
+(deftest test-letfn-shadowing
+  (letfn [(x [] "original")
+          (y [] (x))]
+    (let [x (fn [] "overwritten")]
+      (is (= "original" (y))))))
+
+(deftest test-459
+  (is (= (reduce-kv conj [] (sorted-map :foo 1 :bar 2))
+        [:bar 2 :foo 1])))
+
+(deftest test-kv-reduce
+  (letfn [(kvr-test [data expect]
+            (and
+              (= :reduced
+                (reduce-kv
+                  (fn [_ _ _] (reduced :reduced))
+                  [] data))
+              (= (sort expect)
+                (sort
+                  (reduce-kv
+                    (fn [r k v] (-> r (conj [k v])))
+                    [] data)))))]
+    (testing "Testing IKVReduce"
+      (is (every? true?
+            (for [[data expect] [[(obj-map :k0 :v0 :k1 :v1) [[:k0 :v0] [:k1 :v1]]]
+                                 [(hash-map :k0 :v0 :k1 :v1) [[:k0 :v0] [:k1 :v1]]]
+                                 [(array-map :k0 :v0 :k1 :v1) [[:k0 :v0] [:k1 :v1]]]
+                                 [[:v0 :v1] [[0 :v0] [1 :v1]]]]]
+              (kvr-test data expect))))
+      (is (= {:init :val} (reduce-kv assoc {:init :val} nil))))))
+
+(deftest test-data-conveying-exceptions
+  (is (= {:foo 1}
+             (try (throw (ex-info "asdf" {:foo 1}))
+                  (catch ExceptionInfo e
+                    (ex-data e)))))
+  (is (instance? js/Error (ex-info "asdf" {:foo 1})))
+  (is (not (instance? cljs.core.ExceptionInfo (js/Error.)))))
+
+(deftest test-435
+  (is (= (assoc {} 154618822656 1 261993005056 1)
+            {154618822656 1 261993005056 1})))
+
+(deftest test-458
+  (is (= (get-in {:a {:b 1}} [:a :b :c] :nothing-there)
+        :nothing-there)))
+
+(deftest test-464
+  (is (nil? (get-in {:foo {:bar 2}} [:foo :bar :baz]))))
+
+(deftest test-symbol-meta
+  (is (= (meta (with-meta 'foo {:tag 'int})) {:tag 'int})))
+
+(deftest test-467
+  (is (= (reduce-kv + 0 (apply hash-map (range 1000)))
+        (reduce + (range 1000)))))
+
+(deftest test-477
+  (is (= [js/undefined 1 2] ((fn [& more] more) js/undefined 1 2)))
+  (is (= [js/undefined 4 5] ((fn [a b & more] more) 1 2 js/undefined 4 5))))
+
+(deftest test-493
+  (is (nil? (get 42 :anything)))
+  (is (= (get 42 :anything :not-found) :not-found))
+  (is (nil? (first (map get [42] [:anything]))))
+  (is (= (first (map get [42] [:anything] [:not-found])) :not-found)))
+
+(deftest test-481
+  (let [fs (atom [])]
+    (doseq [x (range 4)
+            :let [y (inc x)
+                  f (fn [] y)]]
+      (swap! fs conj f))
+    (is (= (map #(%) @fs) '(1 2 3 4)))))
+
+(def exists?-test-val 'foo)
+
+(deftest test-495
+  (testing "Testing CLJS-495, exists?"
+    (is (false? (exists? js/jQuery)))
+    (is (exists? exists?-test-val))))
+
+(deftest test-496
+  (is (= (char 65) \A))
+  (is (= (char \A) \A)))
+
+(deftype PositionalFactoryTest [x])
+
+(deftest test-515
+  (is (== 1 (.-x (->PositionalFactoryTest 1)))))
+
+(deftest test-518
+  (is (nil? (:test "test"))))
+
+;; r1798 core fn protocol regression
+(extend-type object
+  ISeqable
+  (-seq [coll]
+    (map #(vector % (aget coll %)) (js-keys coll)))
+
+  ILookup
+  (-lookup
+    ([coll k]
+     (-lookup coll k nil))
+    ([coll k not-found]
+     (if-let [v (aget coll k)]
+       v
+       not-found))))
+
+(deftest test-extend-to-object
+  (is (= (seq (js-obj "foo" 1 "bar" 2)) '(["foo" 1] ["bar" 2])))
+  (is (= (get (js-obj "foo" 1) "foo") 1))
+  (is (= (get (js-obj "foo" 1) "bar" ::not-found) ::not-found))
+  (is (= (reduce (fn [s [k v]] (+ s v)) 0 (js-obj "foo" 1 "bar" 2)) 3)))
+
+(deftest test-541
+  (letfn [(f! [x] (print \f) x)
+          (g! [x] (print \g) x)]
+    (is (= "ffgfg"
+          (with-out-str
+            (instance? Symbol (f! 'foo))
+            (max (f! 5) (g! 10))
+            (min (f! 5) (g! 10)))))))
+
+(deftest test-582
+  (is (= #{1 2} (set [1 2 2])))
+  (is (= #{1 2} (hash-set 1 2 2)))
+  (is (= #{1 2} (apply hash-set [1 2 2]))))
+
+(deftest test-585
+  (is (= (last (map identity (into [] (range 32)))) 31))
+  (is (= (into #{} (range 32))
+            (set (map identity (into [] (range 32)))))))
+
+(def foo580)
+(def foo580 {:a (fn []) :b (fn [] (foo580 :a))})
+
+(deftest test-580
+  (is (nil? (((:b foo580))))))
+
+(deftest test-587
+  (is (== (first (filter #(== % 9999) (range))) 9999)))
+
+(deftest test-604
+  (is (= () (concat nil [])))
+  (is (= () (concat [] []))))
+
+(deftest test-600
+  (is (= "foobar" (apply str (concat "foo" "bar")))))
+
+(deftest test-608
+  (is (= '("") (re-seq #"\s*" ""))))
+
+(deftype KeywordTest []
+  ILookup
+  (-lookup [o k] :nothing)
+  (-lookup [o k not-found] not-found))
+
+(deftest tset-638
+  (is (= (:a (KeywordTest.)) :nothing)))
+
+(deftest test-648
+  (let [a (reify IHash (-hash [_] 42))
+        b (reify IHash (-hash [_] 42))
+        s (set (range 128))]
+    (testing "Testing CLJS-648 (CLJ-1285)"
+      (is (= (-> (conj s a b) transient (disj! a) persistent! (conj a))
+             (-> (conj s a b) transient (disj! a) persistent! (conj a)))))))
+
+(deftest test-660
+  (testing "Testing CLJS-660, namespace handling"
+    (is (= (-> 'a.b keyword ((juxt namespace name))) [nil "a.b"]))
+    (is (= (-> 'a.b/c keyword ((juxt namespace name))) ["a.b" "c"]))
+    (is (= (-> "a.b" keyword ((juxt namespace name))) [nil "a.b"]))
+    (is (= (-> "a.b/c" keyword ((juxt namespace name))) ["a.b" "c"]))))
+
+(deftest test-663
+  (testing "Testing CLJS-663, invalid keywords"
+    (is (= (keyword 123) nil))
+    (is (= (keyword (js/Date.)) nil))))
+
+(deftest test-647
+  (let [keys #(vec (js-keys %))
+        z "x"]
+    (testing "Testing CLJS-647, js-keys"
+      (assert (= ["x"]
+                (keys (js-obj "x" "y"))
+                (keys (js-obj (identity "x") "y"))
+                (keys (js-obj z "y")))))))
+
+
+(def some-x 1)
+(def some-y 1)
+
+(deftest test-583
+  (is (= (count #{some-x some-y}) 1)))
+
+(deftest test-584
+  (is (= (count {some-x :foo some-y :bar}) 1)))
+
+(deftest test-717
+  (testing "Testing CLJS-717, JS literals"
+    (is (array? #js [1 2 3]))
+    (is (= (alength #js [1 2 3]) 3))
+    (is (= (seq #js [1 2 3]) (seq [1 2 3])))
+    (is (= (set (js-keys #js {:foo "bar" :baz "woz"})) #{"foo" "baz"}))
+    (is (= (aget #js {:foo "bar"} "foo") "bar"))
+    (is (= (aget #js {"foo" "bar"} "foo") "bar"))
+    (is (array? (aget #js {"foo" #js [1 2 3]} "foo")))
+    (is (= (seq (aget #js {"foo" #js [1 2 3]} "foo")) '(1 2 3)))))
+
+(deftest test-725
+  (testing "Testing CLJS-725, drop"
+    (is (= (apply vector (drop-while (partial = 1) [1 2 3])) [2 3]))
+    (is (= (apply list (drop-while (partial = 1) [1 2 3])) '(2 3)))
+    (is (= (set (drop 1 #js [1 2 3])) #{2 3}))))
+
+(deftest test-724
+  (is (nil? (first (rest (rest (rest (range 3))))))))
+
+(deftest test-730
+  (testing "Testing CLJS-730, object? predicate"
+    (is (true? (object? #js {})))
+    (is (false? (object? nil)))))
+
+(deftest test-count-hash-set
+  (is
+    (== (count (hash-set [1 4] [2 4] [3 4] [0 3] [1 3] [2 3] [3 3]
+                 [0 2] [1 2] [2 2] [3 2] [4 2] [0 1] [1 1]
+                 [2 1] [3 1] [1 0] [2 0] [3 0]))
+      (count (list [1 4] [2 4] [3 4] [0 3] [1 3] [2 3] [3 3]
+               [0 2] [1 2] [2 2] [3 2] [4 2] [0 1] [1 1]
+               [2 1] [3 1] [1 0] [2 0] [3 0])))))
+
+(defprotocol IWoz
+  (-woz [this]))
+
+(def noz [])
+
+(deftest test-414
+  (testing "Testing CLJS-414, specify"
+    (is (= (specify noz IWoz (-woz [_] :boz)) noz))
+    (is (not (identical? (specify noz IWoz (-woz [_] :boz)) noz)))
+    (is (= (-woz (specify noz IWoz (-woz [this] this))) noz))
+    (is (= (-woz (specify noz IWoz (-woz [_] :boz))) :boz))))
+
+(deftest test-734
+  (testing "Testing CLJS-734, transient operations"
+    (is (= (-> (transient []) (conj! 1 2) persistent!) [1 2]))
+    (is (= (-> (transient #{1 2 3}) (disj! 1 2) persistent!) #{3}))
+    (is (= (-> (transient {}) (assoc! :a 1 :b 2) persistent!) {:a 1 :b 2}))
+    (is (= (-> (transient {:a 1 :b 2 :c 3}) (dissoc! :a :b) persistent!) {:c 3}))))
+
+(deftest test-767
+  (testing "Testing CLJS-767, invalid assoc"
+    (is (every? true?
+          (for [n [nil "-1" "" "0" "1" false true (js-obj)]]
+            (and
+              (= :fail (try (assoc [1 2] n 4)
+                            (catch js/Error e :fail)))
+              (= :fail (try (assoc (subvec [1 2 3] 2) n 4)
+                            (catch js/Error e :fail)))
+              (= :fail (try (assoc (range 1 3) n 4)
+                            (catch js/Error e :fail)))))))))
+
+(deftest test-768
+  (testing "Testing CLJS-768, invalid assoc!"
+    (is (every? true?
+          (for [n [nil "-1" "" "0" "1" false true (js-obj)]]
+            (= :fail (try (assoc! (transient [1 2]) n 4)
+                          (catch js/Error e :fail))))))))
+
+(defn cljs-739 [arr names]
+  (let [name (first names)]
+    (if name
+      (recur (conj arr (fn [] (println name)))
+        (rest names))
+      arr)))
+
+(deftest test-739
+  (testing "Testing CLJS-739, with-out-str"
+    (set! *print-newline* true)
+    (is (= (with-out-str (doseq [fn (cljs-739 [] [:a :b :c :d])] (fn)))
+          ":a\n:b\n:c\n:d\n"))
+    (set! *print-newline* false)))
+
+(deftest test-728
+  (testing "Testing CLJS-728, lookup with default"
+    (is (every? true?
+          (for [n [nil "-1" "" "0" "1" false true (js-obj)]]
+            (and
+              (nil? (get [1 2] n))
+              (= :fail (try (nth [1 2] n) (catch js/Error e :fail)))
+              (= 4 (get [1 2] n 4))
+              (= :fail (try (nth [1 2] n 4) (catch js/Error e :fail)))
+
+              (nil? (get (subvec [1 2] 1) n))
+              (= :fail (try (nth (subvec [1 2] 1) n) (catch js/Error e :fail)))
+              (= 4 (get (subvec [1 2] 1) n 4))
+              (= :fail (try (nth (subvec [1 2] 1) n 4) (catch js/Error e :fail)))
+
+              (nil? (get (transient [1 2]) n))
+              (= :fail (try (nth (transient [1 2]) n) (catch js/Error e :fail)))
+              (= 4 (get (transient [1 2]) n 4))
+              (= :fail (try (nth (transient [1 2]) n 4) (catch js/Error e :fail)))
+
+              (nil? (get (range 1 3) n))
+              (= :fail (try (nth (range 1 3) n) (catch js/Error e :fail)))
+              (= 4 (get (range 1 3) n 4))
+              (= :fail (try (nth (range 1 3) n 4) (catch js/Error e :fail))))))))
+  )
+
+(deftest test-778
+  (testing "Testing CLJS-778, -rest, -next RSeq"
+    (is (= (-rest (rseq [0])) ()))
+    (is (nil? (-next (rseq [0]))))
+    (is (= (set (rseq [0])) #{0}))))
+
+(def cljs-780 (atom {:foo (with-meta [] {:bar '(1 2 3)})}))
+
+(deftest test-780
+  (let [_ (swap! cljs-780 update-in [:foo] vary-meta update-in [:bar] vec)
+        x (-> @cljs-780 :foo meta :bar)]
+    (testing "Testing CLJS-780, update-in + vary-meta"
+      (is (vector? x))
+      (is (= x [1 2 3])))) )
+
+(deftest test-782
+  (testing "Testing CLJS-782, UUID toString"
+    (is (= (.toString #uuid "550e8400-e29b-41d4-a716-446655440000")
+          "550e8400-e29b-41d4-a716-446655440000"))))
+
+(deftest test-784
+  (testing "Testing CLJS-784, conj on maps"
+    (is (every? true?
+          (for [m [(array-map) (hash-map) (sorted-map)]]
+            (and (= :ok
+                      (try
+                        (conj m "foo")
+                        (catch js/Error _
+                          :ok)))
+                  (= {:foo 1} (conj m [:foo 1]))
+                  (= {:foo 1} (conj m {:foo 1}))
+                  (= {:foo 1} (conj m (list [:foo 1])))))))
+    (is (every? true?
+          (for [mt [array-map hash-map sorted-map]]
+            (= {:foo 1 :bar 2 :baz 3}
+              (conj (mt :foo 1)
+                ((fn make-seq [from-seq]
+                   ;; this tests specifically for user defined seq's, that implement the bare minimum, i.e. no INext
+                   (when (seq from-seq)
+                     (reify
+                       ISeqable
+                       (-seq [this] this)
+                       ISeq
+                       (-first [this] (first from-seq))
+                       (-rest [this] (make-seq (rest from-seq))))))
+                 [[:bar 2] [:baz 3]])))))))
+  )
+
+(deftest test-case-keyword
+  (is (= (let [x "a"] (case x :a 1 "a")) "a")))
+
+(deftest test-801
+  (testing "Testing CLJS-801, str"
+    (is (= "0atrue:key/wordsymb/olfalse[1 2 3 4]1234.56789"
+          (str 0 "a" true nil :key/word 'symb/ol false [1 2 3 4] 1234.5678 0x09)))))
+
+(defn case-recur [value]
+  (case value
+    :a (recur :b)
+    :b 0))
+
+(deftest test-812
+  (testing "Testing CLJS-812, case with recur"
+    (is (= (case-recur :a) 0))))
+
+(deftest test-816
+  (testing "Testing CLJS-816, rename-keys"
+    (is (= (set/rename-keys {:a "one" :b "two"} {:a :z}) {:z "one" :b "two"}))
+    (is (= (set/rename-keys {:a "one" :b "two"} {:a :z :c :y}) {:z "one" :b "two"}))
+    (is (= (set/rename-keys {:a "one" :b "two" :c "three"} {:a :b :b :a})
+          {:a "two" :b "one" :c "three"}))) )
+
+(deftest test-881
+  (testing "Testing CLJS-881, duplicate keys in array maps"
+    (is (= [:foo] (keys (apply array-map [:foo 1 :foo 2]))))))
+
+(deftest test-810
+  (let [not-strings [true false nil 1 (fn [])]]
+    (testing "Testing CLJS-810, exception on bad input to regex fns"
+      (is (every? #(= :failed (try (re-find #"." %)
+                                   (catch js/TypeError _ :failed))) not-strings))
+      (is (every? #(= :failed (try (re-matches #"." %)
+                                   (catch js/TypeError _ :failed))) not-strings))
+      (is (every? #(= :failed (try (re-find #"nomatch" %)
+                                   (catch js/TypeError _ :failed))) not-strings))
+      (is (every? #(= :failed (try (re-matches #"nomatch" %)
+                                   (catch js/TypeError _ :failed))) not-strings)))))
+
+(deftest test-849
+  (let [xs [44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24]]
+    (testing "Testing CLJS-849, transient contains?"
+      (is (loop [m (transient (zipmap xs (repeat 1)))
+                 xs xs]
+            (if-let [x (first xs)]
+              (if (contains? m x)
+                (recur (dissoc! m x) (next xs))
+                false)
+              true))))))
+
+(deftest test-large-array-map
+  (let [m (array-map 0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 10 11 11 12 12 13 13 14 14 15 15)]
+    (testing "Testing large array maps"
+      (is (instance? cljs.core/PersistentArrayMap m))
+      (is (= (seq m) [[0 0] [1 1] [2 2] [3 3] [4 4] [5 5] [6 6] [7 7] [8 8] [9 9] [10 10] [11 11] [12 12] [13 13] [14 14] [15 15]])))))
+
+(def test-map
+  {:a 1
+   :b 2
+   #inst "2013-12-19T05:00:00.000-00:00" 3
+   :d 4
+   :e 5
+   #inst "2013-12-06T05:00:00.000-00:00" 6
+   :g 7
+   :h 8
+   :i 9
+   :j 10})
+
+(deftest test-716
+  (testing "Testing CLJS-716, date as keys in maps"
+    (is (= (test-map #inst "2013-12-19T05:00:00.000-00:00") 3))
+    (is (= (test-map #inst "2013-12-06T05:00:00.000-00:00") 6))))
+
+(deftest test-853
+  (testing "Testing CLJS-853, function metadata"
+    (is (= {:foo true} (meta ^:foo (fn []))))))
+
+(deftest test-807
+  (testing "Testing CLJS-807, big int, float, big dec literals"
+    (is (= -1 -1N))
+    (is (= 9.007199254740996E15 9007199254740995N))
+    (is (= 1.5 1.5M))
+    (is (= 4.9E-324 5E-324M))))

 (defn test-stuff []
   (let [v1 (vec (range 15 48))
@@ -1848,688 +2527,12 @@
                              s))))
             (assert (= s (set (remove #(zero? (mod % 3)) (range 100))))))))))

-  ;; defrecord
-  (defrecord Person [firstname lastname])
-  (def fred (Person. "Fred" "Mertz"))
-  (assert (= (:firstname fred) "Fred"))
-  (def fred-too (Person. "Fred" "Mertz"))
-  (assert (= fred fred-too))
-  (assert (false? (= fred nil)))
-  (assert (false? (= nil fred)))
-
-  ;; invalid tests, cannot set meta and extmap directly - David
-  (def ethel (with-meta (assoc (Person. "Ethel" "Mertz") :husband :fred)
-               {:married true}))
-  (assert (= (meta ethel) {:married true}))
-  (def ethel-too (with-meta (assoc (Person. "Ethel" "Mertz")  :husband :fred)
-                   {:married true}))
-  (assert (= ethel ethel-too))
-
-  (assert (= (map->Person {:firstname "Fred" :lastname "Mertz"}) fred))
-  (assert (= (->Person "Fred" "Mertz") fred))
-
-  (assert (= (count fred) 2))
-  (assert (= (count ethel) 3))
-
-  (defrecord A [])
-  (assert (= {:foo 'bar} (meta (with-meta (A.) {:foo 'bar}))))
-  (assert (= 'bar (:foo (assoc (A.) :foo 'bar))))
-
-  (defrecord C [a b c])
-  (def letters (C. "a" "b" "c"))
-  (assert (= (set (keys letters)) #{:a :b :c}))
-  (def more-letters (assoc letters :d "d" :e "e" :f "f"))
-  (assert (= (set (keys more-letters)) #{:a :b :c :d :e :f}))
-  (assert (= (set (keys (dissoc more-letters :d))) #{:a :b :c :e :f}))
-  (assert (= (set (keys (dissoc more-letters :d :e))) #{:a :b :c :f}))
-  (assert (= (set (keys (dissoc more-letters :d :e :f))) #{:a :b :c}))
-
   ;; ObjMap
-  (let [ks (map (partial str "foo") (range 500))
-        m  (apply obj-map (interleave ks (range 500)))]
-    (assert (instance? cljs.core.ObjMap m))
-    (assert (= 500 (count m)))
-    (assert (= 123 (m "foo123"))))
-
-  ;; comparator
-  (assert (= [1 1 2 2 3 5] (seq (.sort (to-array [2 3 1 5 2 1]) (comparator <)))))
-  (assert (= [5 3 2 2 1 1] (seq (.sort (to-array [2 3 1 5 2 1]) (comparator >)))))
-
-  ;; dot
-  (let [s "abc"]
-    (assert (= 3 (.-length s)))
-    (assert (= 3 (. s -length)))
-    (assert (= 3 (. (str 138) -length)))
-    (assert (= 3 (. "abc" -length)))
-    (assert (= "bc" (.substring s 1)))
-    (assert (= "bc" (.substring "abc" 1)))
-    (assert (= "bc" ((memfn substring start) s 1)))
-    (assert (= "bc" (. s substring 1)))
-    (assert (= "bc" (. s (substring 1))))
-    (assert (= "bc" (. s (substring 1 3))))
-    (assert (= "bc" (.substring s 1 3)))
-    (assert (= "ABC" (. s (toUpperCase))))
-    (assert (= "ABC" (. "abc" (toUpperCase))))
-    (assert (= "ABC" ((memfn toUpperCase) s)))
-    (assert (= "BC" (. (. s (toUpperCase)) substring 1)))
-    (assert (= 2 (.-length (. (. s (toUpperCase)) substring 1)))))
-
-  (assert (= (conj fred {:wife :ethel :friend :ricky})
-             (map->Person {:firstname "Fred" :lastname "Mertz" :wife :ethel :friend :ricky})))
-  (assert (= (conj fred {:lastname "Flintstone"})
-             (map->Person {:firstname "Fred" :lastname "Flintstone"})))
-  (assert (= (assoc fred :lastname "Flintstone")
-             (map->Person {:firstname "Fred" :lastname "Flintstone"})))
-  (assert (= (assoc fred :wife :ethel)
-             (map->Person {:firstname "Fred" :lastname "Mertz" :wife :ethel})))
-  (assert (= (dissoc ethel :husband)
-             (map->Person {:firstname "Ethel" :lastname "Mertz"})))
-
-  (defrecord A [x])
-  (defrecord B [x])
-  (assert (not= (A. nil) (B. nil)))
-
-  (defprotocol IFoo (foo [this]))
-  (assert (= (meta (with-meta (reify IFoo (foo [this] :foo)) {:foo :bar}))
-             {:foo :bar}))
-
-  (defmulti foo2 identity)
-  (defmethod foo2 0 [x] x)
-  (assert (= foo2 (ffirst {foo2 1})))
-
-  (defprotocol IMutate
-    (mutate [this]))
-
-  (deftype Mutate [^:mutable a]
-    IMutate
-    (mutate [_]
-      (set! a 'foo)))
-
-  ;; IFn
-  (deftype FnLike []
-    IFn
-    (-invoke [_] :a)
-    (-invoke [_ a] :b)
-    (-invoke [_ a b] :c))
-
-  (assert (= :a ((FnLike.))))
-  (assert (= :b ((FnLike.) 1)))
-  (assert (= :c ((FnLike.) 1 2)))
-
-  (assert (= [:b :b :b] (map (FnLike.) [0 0 0])))
-
-  (deftype FnLikeB [a]
-    IFn
-    (-invoke [_] a))
-
-  (assert (= 1 ((FnLikeB. 1))))
-
-  ;; hashing bug in many JS runtimes CLJ-118
-  (let [g #{(conj #{:2} :alt)}
-        h #{#{:2 :alt}}]
-    (assert (= g h)))
-  (assert (= (hash {:a 1 :b 2})
-             (hash {:b 2 :a 1})))
-  (assert (= (hash (hash-map :a 1 :b 2))
-             (hash (hash-map :b 2 :a 1))))
-  (assert (= (hash {:start 133 :end 134})
-             (hash (apply hash-map [:start 133 :end 134]))))
-  (assert (= (hash :a)
-             (hash (keyword "a"))))
-
-  (defprotocol IHasFirst
-    (-get-first [this]))
-
-  (defprotocol IFindsFirst
-    (-find-first [this other]))
-
-  (deftype First [xs]
-    ISeqable
-    (-seq [this] (seq xs))
-    IIndexed
-    (-nth [this i] (nth xs i))
-    (-nth [this i not-found] (nth xs i not-found))
-    IFn
-    (-invoke [[x]] x)
-    (-invoke [this x] this)
-    Object
-    (toString [[x]] (str x))
-    IHasFirst
-    (-get-first [[x]] x)
-    IFindsFirst
-    (-find-first [_ [x]] x))
-
-  (let [fv (First. [1 2 3])
-        fs (First. "asdf")]
-    (assert (= (fv) 1))
-    (assert (= (fs) \a))
-    (assert (= (str fs) \a))
-    (assert (= (-get-first fv) 1))
-    (assert (= (-get-first fs) \a))
-    (assert (= (-find-first fv [1]) 1))
-    (assert (identical? (fv 1) fv)))
-
-  (deftype DestructuringWithLocals [a]
-    IFindsFirst
-    (-find-first [_ [x y]]
-      [x y a]))
-
-  (let [t (DestructuringWithLocals. 1)]
-    (assert (= [2 3 1] (-find-first t [2 3]))))
-
-  (let [x 1]
-    (assert (= (case x 1 :one) :one)))
-  (let [x 1]
-    (assert (= (case x 2 :two :default) :default)))
-  (let [x 1]
-    (assert (= (try
-                 (case x 3 :three)
-                 (catch js/Error e
-                     :fail))
-               :fail)))
-  (let [x 1]
-    (assert (= (case x
-                 (1 2 3) :ok
-                 :fail)
-               :ok)))
-
-  (let [x [:a :b]]
-    (assert (= (case x
-                 [:a :b] :ok)
-               :ok)))
-
-  (let [a 'a]
-    (assert (= (case a
-                 nil nil
-                 & :amp
-                 :none)
-               :none)))
-
-  (let [a '&]
-    (assert (= (case a
-                 nil nil
-                 & :amp
-                 :none)
-               :amp)))
-
-  (let [foo 'a]
-    (assert (= (case foo
-                 (a b c) :sym
-                 :none)
-               :sym))
-    (assert (= (case foo
-                 (b c d) :sym
-                 :none)
-               :none)))
-
-  ;; RSeq
-
-  (assert (= '(3 2 1) (reverse (seq (array 1 2 3)))))
-  (assert (= '(3 2 1) (reverse [1 2 3])))
-  (assert (= '(4 3 2 1) (cons 4 (reverse [1 2 3]))))
-  (assert (= 6 (reduce + (reverse [1 2 3]))))
-  (assert (= '(4 3 2) (map inc (reverse [1 2 3]))))
-  (assert (= '(4 2) (filter even? (reverse [1 2 3 4]))))
-
-  ;; CLJS-405
-
-  (defprotocol IBar (-bar [this x]))
-
-  (defn baz [f]
-    (reify
-      IBar
-      (-bar [_ x]
-        (f x))))
-
-  (assert (= 2 (-bar (baz inc) 1)))
-
-  ;; CLJS-401 / CLJS-411
-
-  (let [x "original"]
-    (defn original-closure-stmt [] x))
-
-  (let [x "overwritten"]
-    (assert (= "original" (original-closure-stmt))))
-
-  (assert (= "original" (let [x "original"
-                              oce (fn [] x)
-                              x "overwritten"]
-                          (oce))))
-
-
-  (letfn [(x [] "original")
-          (y [] (x))]
-    (let [x (fn [] "overwritten")]
-      (assert (= "original" (y)))))
-
-  ;; CLJS-459: reduce-kv visit order
-  (assert (= (reduce-kv conj [] (sorted-map :foo 1 :bar 2))
-             [:bar 2 :foo 1]))
-
-  ;; Test builtin implementations of IKVReduce
-  (letfn [(kvr-test [data expect]
-            (assert
-              (= :reduced
-                (reduce-kv
-                  (fn [_ _ _] (reduced :reduced))
-                  [] data)))
-            (assert
-              (= (sort expect)
-                 (sort
-                   (reduce-kv
-                     (fn [r k v] (-> r (conj [k v])))
-                     [] data)))))]
-    (kvr-test (obj-map :k0 :v0 :k1 :v1) [[:k0 :v0] [:k1 :v1]])
-    (kvr-test (hash-map :k0 :v0 :k1 :v1) [[:k0 :v0] [:k1 :v1]])
-    (kvr-test (array-map :k0 :v0 :k1 :v1) [[:k0 :v0] [:k1 :v1]])
-    (kvr-test [:v0 :v1] [[0 :v0] [1 :v1]]))
-  (assert (= {:init :val} (reduce-kv assoc {:init :val} nil)))
-
-  ;; data conveying exception
-  (assert (= {:foo 1}
-             (try (throw (ex-info "asdf" {:foo 1}))
-                  (catch ExceptionInfo e
-                    (ex-data e)))))
-  (assert (instance? js/Error (ex-info "asdf" {:foo 1})))
-  (assert (not (instance? cljs.core.ExceptionInfo (js/Error.))))
-
-  ;; CLJS-435
-
-  (assert (= (assoc {} 154618822656 1 261993005056 1)
-             {154618822656 1 261993005056 1}))
-
-  ;; CLJS-458
-
-  (assert (= (get-in {:a {:b 1}} [:a :b :c] :nothing-there)
-             :nothing-there))
-
-  ;; CLJS-464
-
-  (assert (nil? (get-in {:foo {:bar 2}} [:foo :bar :baz])))
-
-  ;; symbol metadata
-
-  (assert (= (meta (with-meta 'foo {:tag 'int})) {:tag 'int}))
-
-  ;; CLJS-467
-
-  (assert (= (reduce-kv + 0 (apply hash-map (range 1000)))
-             (reduce + (range 1000))))
-
-  ;; CLJS-477
-
-  (assert (= [js/undefined 1 2] ((fn [& more] more) js/undefined 1 2)))
-  (assert (= [js/undefined 4 5] ((fn [a b & more] more) 1 2 js/undefined 4 5)))
-
-  ;; CLJS-493
-
-  (assert (nil? (get 42 :anything)))
-  (assert (= (get 42 :anything :not-found) :not-found))
-  (assert (nil? (first (map get [42] [:anything]))))
-  (assert (= (first (map get [42] [:anything] [:not-found])) :not-found))
-
-  ;; CLJS-481
-
-  (let [fs (atom [])]
-    (doseq [x (range 4)
-            :let [y (inc x)
-                  f (fn [] y)]]
-      (swap! fs conj f))
-    (assert (= (map #(%) @fs) '(1 2 3 4))))
-
-  ;; CLJS-495
-  (assert (false? (exists? js/jQuery)))
-  (def exists?-test-val 'foo)
-  (assert (exists? exists?-test-val))
-
-  ;; CLJS-496
-  (assert (= (char 65) \A))
-  (assert (= (char \A) \A))
-
-  ;; compile time run symbol hash codes
-
-  (assert (= (hash 'foo) (hash (symbol "foo"))))
-  (assert (= (hash 'foo/bar) (hash (symbol "foo" "bar"))))
-
-  (assert (= (lazy-cat [1] [2] [3]) '(1 2 3)))
-
-  ;; r1798 core fn protocol regression
-  (extend-type object
-    ISeqable
-    (-seq [coll]
-      (map #(vector % (aget coll %)) (js-keys coll)))
-
-    ILookup
-    (-lookup
-      ([coll k]
-        (-lookup coll k nil))
-      ([coll k not-found]
-        (if-let [v (aget coll k)]
-          v
-          not-found))))
-
-  (assert (= (seq (js-obj "foo" 1 "bar" 2)) '(["foo" 1] ["bar" 2])))
-  (assert (= (get (js-obj "foo" 1) "foo") 1))
-  (assert (= (get (js-obj "foo" 1) "bar" ::not-found) ::not-found))
-  (assert (= (reduce (fn [s [k v]] (+ s v)) 0 (js-obj "foo" 1 "bar" 2)) 3))
-
-  ;; CLJS-515
-  (deftype PositionalFactoryTest [x])
-
-  (assert (== 1 (.-x (->PositionalFactoryTest 1))))
-
-  ;; CLJS-518
-  (assert (nil? (:test "test")))
-
-  ;; CLJS-541
-  (letfn [(f! [x] (print \f) x)
-          (g! [x] (print \g) x)]
-    (assert (= "ffgfg"
-               (with-out-str
-                 (instance? Symbol (f! 'foo))
-                 (max (f! 5) (g! 10))
-                 (min (f! 5) (g! 10))))))
-
-  ;; CLJS-582
-  (assert (= #{1 2} (set [1 2 2])))
-  (assert (= #{1 2} (hash-set 1 2 2)))
-  (assert (= #{1 2} (apply hash-set [1 2 2])))
-
-  ;; CLJS-585
-  (assert (= (last (map identity (into [] (range 32)))) 31))
-  (assert (= (into #{} (range 32))
-             (set (map identity (into [] (range 32))))))
-
-  ;; CLJS-580
-  (def foo580)
-  (def foo580 {:a (fn []) :b (fn [] (foo580 :a))})
-  (assert (nil? (((:b foo580)))))
-
-  ;; CLJS-587
-  (assert (== (first (filter #(== % 9999) (range))) 9999))
-
-  ;; LazySeq regressions
-
-  ;; CLJS-604
-  (assert (= () (concat nil [])))
-  (assert (= () (concat [] [])))
-
-  ;; CLJS-600
-  (assert (= "foobar" (apply str (concat "foo" "bar"))))
-
-  ;; CLJS-608
-  (assert (= '("") (re-seq #"\s*" "")))
-
-  ;; CLJS-638
-
-  (deftype KeywordTest []
-    ILookup
-    (-lookup [o k] :nothing)
-    (-lookup [o k not-found] not-found))
-
-  (assert (= (:a (KeywordTest.)) :nothing))
-
-  ;; CLJS-648 (CLJ-1285)
-  (let [a (reify IHash (-hash [_] 42))
-        b (reify IHash (-hash [_] 42))
-        s (set (range 128))]
-    (assert (= (-> (conj s a b) transient (disj! a) persistent! (conj a))
-               (-> (conj s a b) transient (disj! a) persistent! (conj a)))))
-
-  ;; CLJS-660
-
-  (assert (= (-> 'a.b keyword ((juxt namespace name))) [nil "a.b"]))
-  (assert (= (-> 'a.b/c keyword ((juxt namespace name))) ["a.b" "c"]))
-  (assert (= (-> "a.b" keyword ((juxt namespace name))) [nil "a.b"]))
-  (assert (= (-> "a.b/c" keyword ((juxt namespace name))) ["a.b" "c"]))
-
-  ;; CLJS-663
-
-  (assert (= (keyword 123) nil))
-  (assert (= (keyword (js/Date.)) nil))
-
-  ;; CLJS-647
-  (let [keys #(vec (js-keys %))
-        z "x"]
-    (assert (= ["x"]
-               (keys (js-obj "x" "y"))
-               (keys (js-obj (identity "x") "y"))
-               (keys (js-obj z "y")))))
-
-  ;; CLJS-583
-
-  (def some-x 1)
-  (def some-y 1)
-
-  (assert (= (count #{some-x some-y}) 1))
-
-  ;; CLJS-584
-
-  (assert (= (count {some-x :foo some-y :bar}) 1))
-
-  ;; CLJS-717
-
-  (assert (array? #js [1 2 3]))
-  (assert (= (alength #js [1 2 3]) 3))
-  (assert (= (seq #js [1 2 3]) (seq [1 2 3])))
-  (assert (= (set (js-keys #js {:foo "bar" :baz "woz"})) #{"foo" "baz"}))
-  (assert (= (aget #js {:foo "bar"} "foo") "bar"))
-  (assert (= (aget #js {"foo" "bar"} "foo") "bar"))
-  (assert (array? (aget #js {"foo" #js [1 2 3]} "foo")))
-  (assert (= (seq (aget #js {"foo" #js [1 2 3]} "foo")) '(1 2 3)))
-
-  ;; CLJS-725
-
-  (assert (= (apply vector (drop-while (partial = 1) [1 2 3])) [2 3]))
-  (assert (= (apply list (drop-while (partial = 1) [1 2 3])) '(2 3)))
-  (assert (= (set (drop 1 #js [1 2 3])) #{2 3}))
-
-  ;; CLJS-724
-
-  (assert (nil? (first (rest (rest (rest (range 3)))))))
-
-  ;; CLJS-730
-
-  (assert (true? (object? #js {})))
-  (assert (false? (object? nil)))
-
-  (assert
-    (== (count (hash-set [1 4] [2 4] [3 4] [0 3] [1 3] [2 3] [3 3]
-                         [0 2] [1 2] [2 2] [3 2] [4 2] [0 1] [1 1]
-                         [2 1] [3 1] [1 0] [2 0] [3 0]))
-        (count (list [1 4] [2 4] [3 4] [0 3] [1 3] [2 3] [3 3]
-                     [0 2] [1 2] [2 2] [3 2] [4 2] [0 1] [1 1]
-                     [2 1] [3 1] [1 0] [2 0] [3 0]))))
-
-  (defprotocol IWoz
-    (-woz [this]))
-
-  (def noz [])
-
-  ;; CLJS-414
-
-  (assert (= (specify noz IWoz (-woz [_] :boz)) noz))
-  (assert (not (identical? (specify noz IWoz (-woz [_] :boz)) noz)))
-  (assert (= (-woz (specify noz IWoz (-woz [this] this))) noz))
-  (assert (= (-woz (specify noz IWoz (-woz [_] :boz))) :boz))
-
-  ;; CLJS-734
-
-  (assert (= (-> (transient []) (conj! 1 2) persistent!) [1 2]))
-  (assert (= (-> (transient #{1 2 3}) (disj! 1 2) persistent!) #{3}))
-  (assert (= (-> (transient {}) (assoc! :a 1 :b 2) persistent!) {:a 1 :b 2}))
-  (assert (= (-> (transient {:a 1 :b 2 :c 3}) (dissoc! :a :b) persistent!) {:c 3}))
-
-  ;; CLJS-767
-
-  (doseq [n [nil "-1" "" "0" "1" false true (js-obj)]]
-    (assert (= :fail (try (assoc [1 2] n 4)
-                       (catch js/Error e :fail))))
-    (assert (= :fail (try (assoc (subvec [1 2 3] 2) n 4)
-                       (catch js/Error e :fail))))
-    (assert (= :fail (try (assoc (range 1 3) n 4)
-                       (catch js/Error e :fail)))))
-
-  ;; CLJS-768
-
-  (doseq [n [nil "-1" "" "0" "1" false true (js-obj)]]
-    (assert (= :fail (try (assoc! (transient [1 2]) n 4)
-                       (catch js/Error e :fail)))))
-
-  ;; CLJS-739
-
-  (defn cljs-739 [arr names]
-    (let [name (first names)]
-      (if name
-        (recur (conj arr (fn [] (println name)))
-          (rest names))
-        arr)))
-
-  (set! *print-newline* true)
-  (assert (= (with-out-str (doseq [fn (cljs-739 [] [:a :b :c :d])] (fn)))
-             ":a\n:b\n:c\n:d\n"))
-  (set! *print-newline* false)
-
-  ;; CLJS-728
-
-  (doseq [n [nil "-1" "" "0" "1" false true (js-obj)]]
-    (assert (nil? (get [1 2] n)))
-    (assert (= :fail (try (nth [1 2] n) (catch js/Error e :fail))))
-    (assert (= 4 (get [1 2] n 4)))
-    (assert (= :fail (try (nth [1 2] n 4) (catch js/Error e :fail))))
-
-    (assert (nil? (get (subvec [1 2] 1) n)))
-    (assert (= :fail (try (nth (subvec [1 2] 1) n) (catch js/Error e :fail))))
-    (assert (= 4 (get (subvec [1 2] 1) n 4)))
-    (assert (= :fail (try (nth (subvec [1 2] 1) n 4) (catch js/Error e :fail))))
-
-    (assert (nil? (get (transient [1 2]) n)))
-    (assert (= :fail (try (nth (transient [1 2]) n) (catch js/Error e :fail))))
-    (assert (= 4 (get (transient [1 2]) n 4)))
-    (assert (= :fail (try (nth (transient [1 2]) n 4) (catch js/Error e :fail))))
-
-    (assert (nil? (get (range 1 3) n)))
-    (assert (= :fail (try (nth (range 1 3) n) (catch js/Error e :fail))))
-    (assert (= 4 (get (range 1 3) n 4)))
-    (assert (= :fail (try (nth (range 1 3) n 4) (catch js/Error e :fail)))))
-
-  ;; CLJS-778
-  (assert (= (-rest (rseq [0])) ()))
-  (assert (nil? (-next (rseq [0]))))
-  (assert (= (set (rseq [0])) #{0}))
-
-  ;; CLJS-780
-  (def cljs-780 (atom {:foo (with-meta [] {:bar '(1 2 3)})}))
-  (swap! cljs-780 update-in [:foo] vary-meta update-in [:bar] vec)
-  (let [x (-> @cljs-780 :foo meta :bar)]
-    (assert (vector? x))
-    (assert (= x [1 2 3])))
-
-  ;; CLJS-782
-  (assert (= (.toString #uuid "550e8400-e29b-41d4-a716-446655440000")
-             "550e8400-e29b-41d4-a716-446655440000"))
-
-  ;; CLJS-784
-  (doseq [m [(array-map) (hash-map) (sorted-map)]]
-    (assert (= :ok
-               (try
-                 (conj m "foo")
-                 (catch js/Error _
-                   :ok))))
-    (assert (= {:foo 1} (conj m [:foo 1])))
-    (assert (= {:foo 1} (conj m {:foo 1})))
-    (assert (= {:foo 1} (conj m (list [:foo 1])))))
-
-  (doseq [mt [array-map hash-map sorted-map]]
-    (assert (= {:foo 1 :bar 2 :baz 3}
-               (conj (mt :foo 1)
-                     ((fn make-seq [from-seq]
-                        ;; this tests specifically for user defined seq's, that implement the bare minimum, i.e. no INext
-                        (when (seq from-seq)
-                          (reify
-                            ISeqable
-                            (-seq [this] this)
-                            ISeq
-                            (-first [this] (first from-seq))
-                            (-rest [this] (make-seq (rest from-seq))))))
-                      [[:bar 2] [:baz 3]])))))
-
-  ;; case keyword
-  (assert (= (let [x "a"] (case x :a 1 "a")) "a"))
-
-  ;; CLJS-801
-  (assert (= "0atrue:key/wordsymb/olfalse[1 2 3 4]1234.56789"
-             (str 0 "a" true nil :key/word 'symb/ol false [1 2 3 4] 1234.5678 0x09)))
-
-  ;; CLJS-812
-  (defn case-recur [value]
-    (case value
-      :a (recur :b)
-      :b 0))
-
-  (assert (= (case-recur :a) 0))
-
-  ;; CLJS-816
-  (assert (= (set/rename-keys {:a "one" :b "two"} {:a :z}) {:z "one" :b "two"}))
-  (assert (= (set/rename-keys {:a "one" :b "two"} {:a :z :c :y}) {:z "one" :b "two"}))
-  (assert (= (set/rename-keys {:a "one" :b "two" :c "three"} {:a :b :b :a})
-             {:a "two" :b "one" :c "three"}))
-
-  ;; CLJS-881
-  (assert (= [:foo] (keys (apply array-map [:foo 1 :foo 2]))))
-
-
-  ;; CLJS-810
-  (let [not-strings [true false nil 1 (fn [])]]
-    (assert (every? #(= :failed (try (re-find #"." %)
-                                     (catch js/TypeError _ :failed))) not-strings))
-    (assert (every? #(= :failed (try (re-matches #"." %)
-                                     (catch js/TypeError _ :failed))) not-strings))
-    (assert (every? #(= :failed (try (re-find #"nomatch" %)
-                                     (catch js/TypeError _ :failed))) not-strings))
-    (assert (every? #(= :failed (try (re-matches #"nomatch" %)
-                                     (catch js/TypeError _ :failed))) not-strings)))
-
-  ;; CLJS-849
-  (let [xs [44 43 42 41 40 39 38 37 36 35 34 33 32 31 30 29 28 27 26 25 24]]
-    (loop [m  (transient (zipmap xs (repeat 1)))
-           xs xs]
-      (if-let [x (first xs)]
-        (if (contains? m x)
-          (recur (dissoc! m x) (next xs))
-          (throw (ex-info "CLJS-849 regression!"
-                   {:m (persistent! m) :xs xs}))))))
-
-  ;; CLJS-
-  (let [m (array-map 0 0 1 1 2 2 3 3 4 4 5 5 6 6 7 7 8 8 9 9 10 10 11 11 12 12 13 13 14 14 15 15)]
-    (assert (instance? cljs.core/PersistentArrayMap m))
-    (assert (= (seq m) [[0 0] [1 1] [2 2] [3 3] [4 4] [5 5] [6 6] [7 7] [8 8] [9 9] [10 10] [11 11] [12 12] [13 13] [14 14] [15 15]])))
-
-  ;; CLJS-716
-  (def test-map
-    {:a 1
-     :b 2
-     #inst "2013-12-19T05:00:00.000-00:00" 3
-     :d 4
-     :e 5
-     #inst "2013-12-06T05:00:00.000-00:00" 6
-     :g 7
-     :h 8
-     :i 9
-     :j 10})
-
-  (assert (= (test-map #inst "2013-12-19T05:00:00.000-00:00") 3))
-  (assert (= (test-map #inst "2013-12-06T05:00:00.000-00:00") 6))
-
-  ;; CLJS-853
-
-  (assert (= {:foo true} (meta ^:foo (fn []))))
-
-  ;; CLJS-807
-  (assert (= -1 -1N))
-  (assert (= 9.007199254740996E15 9007199254740995N))
-  (assert (= 1.5 1.5M))
-  (assert (= 4.9E-324 5E-324M))
+  ;; (let [ks (map (partial str "foo") (range 500))
+  ;;       m  (apply obj-map (interleave ks (range 500)))]
+  ;;   (assert (instance? cljs.core.ObjMap m))
+  ;;   (assert (= 500 (count m)))
+  ;;   (assert (= 123 (m "foo123"))))

   ;; vars


Refactor and use less trivial code

Refactor and use less trivial code

--- src/org/playasophy/wonderdome/handler.clj
+++ src/org/playasophy/wonderdome/handler.clj
@@ -114,18 +114,24 @@
 (defn konami-code
   "Detects a custom key sequence and activates a secret mode."
   [handler & {:keys [buttons mode]
-              :or {buttons [:B :A :start] mode :strobe}}]
-;              :or {buttons [:up :up :down :down :left :right :left :right :b :a :start]}}]
+              :or {buttons [:A :B :X :Y :L :R :start] mode :strobe}}]
   (let [matched-prefix-len (atom 0)]
     (fn [state event]
-      (if (= (:type event) :button/press)
-        (if (= (:button event) (get buttons @matched-prefix-len))
+      (let [button (:button event)
+            _ (if-not (nil? button) (println "got button: " button))]
+        (cond
+          (not (= (:type event) :button/press))
+          (handler state event)
+
+          (= (:button event) (get buttons @matched-prefix-len))
           (do
             (swap! matched-prefix-len inc)
             (if (= @matched-prefix-len (count buttons))
               (assoc state :mode/current mode)
               (handler state event)))
+
+          :else
           (do
             (reset! matched-prefix-len (if (= (first buttons) (:button event)) 1 0))
             (handler state event)))
-        (handler state event)))))
+        ))))


[Feature] Added regex groups and successfully destructed the incorrect filename

--- folder-monitor/src/folder_monitor/core.clj
+++ folder-monitor/src/folder_monitor/core.clj
@@ -2,16 +2,30 @@
   (:gen-class)
   (:require [clojure-watch.core :refer [start-watch]]))

-(def sookasa-regex #".*\.ext\(.*conflicted copy \d{4}-\d{2}-\d{2}\)\.sookasa")
+; regex for identifying misnamed sookasa files
+; also includes capturing groups so that filenames can be rearranged programatically
+(def sookasa-regex #"([^.]*)(\..*)(\(.*conflicted copy \d{4}-\d{2}-\d{2}\))\.sookasa")

 (defn rename-file
   "Renames incorrectly named files to their proper form"
   [event filename]
   ; print the event and filename to the console - change this to a log file
   (println event filename)
+
+  ; destructuring to break apart regex groups
+  ; full-filename is the full filename
+  ; short-filename is the name of the file without the conflict parens and extensions
+  ; extension is the files extension (other than .sookasa)
+  ; conflict-string is the (users conflicted copy...) string
+  (let [[full-filename short-filename extension conflict-string]
+         (re-matches sookasa-regex filename)]
+    (println short-filename)
+    (println extension)
+    (println conflict-string)))
+
   ; see if the modified files name matches the incorrect pattern
-  (println
-    (re-matches sookasa-regex filename)))
+  ; (println
+  ;   (re-matches sookasa-regex filename)))

 (defn -main
   "I don't do a whole lot ... yet."


Add debug logging to bot event sending

Add debug logging to bot event sending

--- src/braid/server/bots.clj
+++ src/braid/server/bots.clj
@@ -22,6 +22,7 @@
 (defn send-event-notification
   [bot info]
   (when-let [url (:event-webhook-url bot)]
+    (timbre/debugf "Sending event notification %s to %s" info bot)
     (let [body (->transit info)
           hmac (crypto/hmac-bytes (bot :token) body)]
       (timbre/debugf "sending bot event notification")


Allow to set color to "none" to disable drag

--- src/chessground/ctrl.cljs
+++ src/chessground/ctrl.cljs
@@ -113,7 +113,7 @@
        (show/piece-interactions root new-state chans))]))

 (defn set-color [state color]
-  (if (common/seq-contains? (conj chess/colors "both") color)
+  (if (common/seq-contains? (conj chess/colors "both" "none") color)
     (let [new-state (assoc-in state [:movable :color] color)]
       [new-state
        (fn [root chans]


allow test-for-explanations to take 3 args

--- src/structural_typing/assist/testutil.clj
+++ src/structural_typing/assist/testutil.clj
@@ -38,8 +38,8 @@
       plain
       (format "`%s` mismatches `%s`" plain lifted))))

-(defn check-for-explanations [type candidate]
-  (let [[retval output] (val-and-output (type/checked type candidate))]
+(defn check-for-explanations [& args]
+  (let [[retval output] (val-and-output (apply type/checked args))]
     (if (nil? retval)
       (str-split output #"\n") ; too lazy to handle windows.
       ["Actual return result was not `nil`"])))


use timbre in cljs too, set default level to :info

--- src/chat/client/sync.cljs
+++ src/chat/client/sync.cljs
@@ -1,11 +1,11 @@
 (ns chat.client.sync
   (:require [taoensso.sente  :as sente :refer [cb-success?]]
+            [taoensso.timbre :as timbre :refer-macros [debugf]]
             [goog.string :as gstring]
             [chat.client.store :as store]
             [goog.string.format]))

-(defn debugf [s & args]
-  #_(js/console.log (apply gstring/format s args)))
+(timbre/set-level! :info)

 (defn make-socket! []
   (let [domain (aget js/window "api_domain")


Revert "Revert "Bind cheshire.generate/*date-format* to ISO-8601 date format""

This reverts commit 69a3f2bad66bb9da93d9881266312cd18be4b1a9.

--- src/cheshire/generate.clj
+++ src/cheshire/generate.clj
@@ -8,7 +8,7 @@
            (clojure.lang IPersistentCollection Keyword Ratio Symbol)))

 ;; date format rebound for custom encoding
-(def ^{:dynamic true :private true} *date-format*)
+(def ^{:dynamic true :private true} *date-format* "yyyy-MM-dd'T'HH:mm:ssZ")

 (defmacro tag
   ([obj]


Use inlined functions for map/array encoding rather than functions

--- src/cheshire/generate.clj
+++ src/cheshire/generate.clj
@@ -1,6 +1,6 @@
 (ns cheshire.generate
   (:import (org.codehaus.jackson JsonGenerator)
-           (java.util List Date SimpleTimeZone UUID)
+           (java.util Date Map List Set SimpleTimeZone UUID)
            (java.sql Timestamp)
            (java.text SimpleDateFormat)
            (java.math BigInteger)
@@ -38,63 +38,62 @@
          Ratio (.writeNumber ~jg (double ~obj))
          (fail ~obj)))))

+(declare generate)
+
+(definline generate-map [^JsonGenerator jg obj ^String date-format]
+  `(do
+     (.writeStartObject ~jg)
+     (doseq [[k# v#] ~obj]
+       (.writeFieldName ~jg (if (keyword? k#)
+                              (name k#)
+                              (str k#)))
+       (generate ~jg v# ~date-format))
+     (.writeEndObject ~jg)))
+
+(definline generate-array [^JsonGenerator jg obj ^String date-format]
+  `(do
+     (.writeStartArray ~jg)
+     (doseq [item# ~obj]
+       (generate ~jg item# ~date-format))
+     (.writeEndArray ~jg)))
+
 (defn generate [^JsonGenerator jg obj ^String date-format]
-  (let [generate-map (fn [^JsonGenerator jg m ^String date-format]
-                       (do
-                         (.writeStartObject jg)
-                         (doseq [[k v] m
-                                 :let [field-name (if (keyword? k)
-                                                    (name k)
-                                                    (str k))]]
-                           (.writeFieldName jg field-name)
-                           (generate jg v date-format))
-                         (.writeEndObject jg)))
-        generate-array (fn [^JsonGenerator jg a ^String date-format]
-                         (do
-                           (.writeStartArray jg)
-                           (dotimes [i (count obj)]
-                             (generate jg (.get ^List obj i) date-format))
-                           (.writeEndArray jg)))]
-    (condp instance? obj
-      IPersistentCollection (condp instance? obj
-                              clojure.lang.IPersistentMap
-                              (generate-map jg obj date-format)
-                              clojure.lang.IPersistentVector
-                              (generate-array jg obj date-format)
-                              clojure.lang.IPersistentSet
-                              (generate jg (seq obj) date-format)
-                              clojure.lang.ISeq
-                              (do
-                                (.writeStartArray jg)
-                                (doseq [item obj]
-                                  (generate jg item date-format))
-                                (.writeEndArray jg)))
-      java.util.Map (generate-map jg obj date-format)
-      java.util.List (generate-array jg obj date-format)
-      java.util.Set (generate jg (seq obj) date-format)
-      Number (number-dispatch ^JsonGenerator jg obj)
-      String (write-string ^JsonGenerator jg ^String obj)
-      Keyword (write-string ^JsonGenerator jg
-                            (if-let [ns (namespace obj)]
-                              (str ns "/" (name obj))
-                              (name obj)))
-      UUID (write-string ^JsonGenerator jg (.toString ^UUID obj))
-      Symbol (write-string ^JsonGenerator jg (if-let [sym (resolve obj)]
-                                               (str (:ns (meta sym))
-                                                    "/"
-                                                    (:name (meta sym)))
-                                               (.toString ^Symbol obj)))
-      Boolean (.writeBoolean ^JsonGenerator jg ^Boolean obj)
-      Date (let [sdf (doto (SimpleDateFormat. date-format)
-                       (.setTimeZone (SimpleTimeZone. 0 "UTC")))]
-             (write-string ^JsonGenerator jg (.format sdf obj)))
-      Timestamp (let [date (Date. (.getTime ^Timestamp obj))
-                      sdf (doto (SimpleDateFormat. date-format)
-                            (.setTimeZone (SimpleTimeZone. 0 "UTC")))]
-                  (write-string ^JsonGenerator jg (.format sdf obj)))
-      (if (nil? obj)
-        (.writeNull ^JsonGenerator jg)
-        ;; it must be a primative then
-        (try
-          (.writeNumber ^JsonGenerator jg obj)
-          (catch Exception e (fail obj)))))))
+  (condp instance? obj
+    IPersistentCollection (condp instance? obj
+                            clojure.lang.IPersistentMap
+                            (generate-map jg obj date-format)
+                            clojure.lang.IPersistentVector
+                            (generate-array jg obj date-format)
+                            clojure.lang.IPersistentSet
+                            (generate jg (seq obj) date-format)
+                            clojure.lang.ISeq
+                            (generate-array jg obj date-format))
+    Map (generate-map jg obj date-format)
+    List (generate-array jg obj date-format)
+    Set (generate jg (seq obj) date-format)
+    Number (number-dispatch ^JsonGenerator jg obj)
+    String (write-string ^JsonGenerator jg ^String obj)
+    Keyword (write-string ^JsonGenerator jg
+                          (if-let [ns (namespace obj)]
+                            (str ns "/" (name obj))
+                            (name obj)))
+    UUID (write-string ^JsonGenerator jg (.toString ^UUID obj))
+    Symbol (write-string ^JsonGenerator jg (if-let [sym (resolve obj)]
+                                             (str (:ns (meta sym))
+                                                  "/"
+                                                  (:name (meta sym)))
+                                             (.toString ^Symbol obj)))
+    Boolean (.writeBoolean ^JsonGenerator jg ^Boolean obj)
+    Date (let [sdf (doto (SimpleDateFormat. date-format)
+                     (.setTimeZone (SimpleTimeZone. 0 "UTC")))]
+           (write-string ^JsonGenerator jg (.format sdf obj)))
+    Timestamp (let [date (Date. (.getTime ^Timestamp obj))
+                    sdf (doto (SimpleDateFormat. date-format)
+                          (.setTimeZone (SimpleTimeZone. 0 "UTC")))]
+                (write-string ^JsonGenerator jg (.format sdf obj)))
+    (if (nil? obj)
+      (.writeNull ^JsonGenerator jg)
+      ;; it must be a primative then
+      (try
+        (.writeNumber ^JsonGenerator jg obj)
+        (catch Exception e (fail obj))))))


combine go loop forms to go-loop

combine go loop forms to go-loop

--- src/client/game/core.cljs
+++ src/client/game/core.cljs
@@ -218,38 +218,36 @@
   "Kicks off the drawing routine."
   []
   (let [redraw-chan (make-redraw-chan)]
-    (go
-      (loop [board nil theme nil]
-        (let [[_ c] (alts! [quit-chan redraw-chan])]
-          (if (= c redraw-chan)
-            (let [new-board (drawable-board)
-                  new-theme (:theme @state)
-                  next-piece (:next-piece @state)]
-              (when (or (not= board new-board)
-                        (not= theme new-theme))
-
-                (history/draw-history! (:history @state))
-                (draw-board! "mainGameCanvas" new-board cell-size new-theme rows-cutoff)
-                (draw-board! "nextPieceCanvas" (next-piece-board next-piece) cell-size new-theme)
-                (if (:recording @vcr)
-                  (record-frame!)))
-              (recur new-board new-theme))))))))
+    (go-loop [board nil theme nil]
+      (let [[_ c] (alts! [quit-chan redraw-chan])]
+        (if (= c redraw-chan)
+          (let [new-board (drawable-board)
+                new-theme (:theme @state)
+                next-piece (:next-piece @state)]
+            (when (or (not= board new-board)
+                      (not= theme new-theme))
+
+              (history/draw-history! (:history @state))
+              (draw-board! "mainGameCanvas" new-board cell-size new-theme rows-cutoff)
+              (draw-board! "nextPieceCanvas" (next-piece-board next-piece) cell-size new-theme)
+              (if (:recording @vcr)
+                (record-frame!)))
+            (recur new-board new-theme)))))))

 (defn go-go-emit-updates!
   []
-  (go
-    (loop [prev-data nil]
-
-      ; emit update to the server if relevant attributes have changed
-      (let [data (select-keys @state [:piece :position :board :theme])]
-        (when (not= prev-data data)
-          (socket/emit "update-player" {:theme (:theme @state) :board (drawable-board)}))
-
-        ; quit or schedule another update
-        (let [quit quit-chan
-              [_ ch] (alts! [quit (timeout 16)])]
-          (when-not (= ch quit)
-            (recur data)))))))
+  (go-loop [prev-data nil]
+
+    ; emit update to the server if relevant attributes have changed
+    (let [data (select-keys @state [:piece :position :board :theme])]
+      (when (not= prev-data data)
+        (socket/emit "update-player" {:theme (:theme @state) :board (drawable-board)}))
+
+      ; quit or schedule another update
+      (let [quit quit-chan
+            [_ ch] (alts! [quit (timeout 16)])]
+        (when-not (= ch quit)
+          (recur data))))))

 ;;------------------------------------------------------------


Added support for dot form where target is a function/macro call

--- src/clj/cljs/compiler.clj
+++ src/clj/cljs/compiler.clj
@@ -876,7 +876,9 @@

 (defn- build-method-call
   [target meth args]
-  {:dot-action ::call :target target :method (munge meth) :args args})
+  (if (symbol? meth)
+    {:dot-action ::call :target target :method (munge meth) :args args}
+    {:dot-action ::call :target target :method (munge (first meth)) :args args}))

 ;; (.m o 1 2)
 ;; (. o m 1 2)
@@ -896,9 +898,19 @@
   [[target [meth & args] _]]
   (build-method-call target meth args))

+;; (. (. ...))
+(defmethod build-dot-form [::list ::list ()]
+  [[target meth _]]
+  (build-method-call target meth ()))
+
+;; (.m (f _) 1 2)
+(defmethod build-dot-form [::list ::symbol ::list]
+  [[target meth args]]
+  (build-method-call target meth args))
+
 (defmethod build-dot-form :default
   [dot-form]
-  (throw (Error. (str "Unknown dot form of " dot-form))))
+  (throw (Error. (str "Unknown dot form of " dot-form " with cassification " (vec (map classify-sub dot-form))))))

 (defmethod parse '.
   [_ env [_ target & [field & member+]] _]


take in 'system for helmsman-definition

take in 'system for helmsman-definition

--- src/clj/traveler/core.clj
+++ src/clj/traveler/core.clj
@@ -37,22 +37,23 @@

 (defn helmsman-definition
   "Main helmsman definition"
-  [db-conn]
-  [^{:id :traveler/resources}
-   [:resources "/"]
-   ^{:name "Traveler"
-     :id :traveler/root
-     :main-menu true}
-   [:any "/" (:dashboard liberator-resources)]
-   ^{:name "Dashboard" :id :traveler/dashboard}
-   [:any "/dashboard" (:dashboard liberator-resources)]
-   ^{:name "Manage Users" :id :traveler/users}
-   [:any "/users" (:users liberator-resources)]
-   ^{:name "Manage User" :id :traveler/user}
-   [:any "/user/:id-sk" (:user liberator-resources)]
-   ^{:name "View System" :id :traveler/system}
-   [:any "/system" (:system liberator-resources)]
-   (into [:context "/api"] (api-routes db-conn))
-   ;;middleware
-   [wrap-params]
-   ])
+  [system]
+  (let [db-conn (:db-conn system)]
+    [^{:id :traveler/resources}
+     [:resources "/"]
+     ^{:name "Traveler"
+       :id :traveler/root
+       :main-menu true}
+     [:any "/" (:dashboard liberator-resources)]
+     ^{:name "Dashboard" :id :traveler/dashboard}
+     [:any "/dashboard" (:dashboard liberator-resources)]
+     ^{:name "Manage Users" :id :traveler/users}
+     [:any "/users" (:users liberator-resources)]
+     ^{:name "Manage User" :id :traveler/user}
+     [:any "/user/:id-sk" (:user liberator-resources)]
+     ^{:name "View System" :id :traveler/system}
+     [:any "/system" (:system liberator-resources)]
+     (into [:context "/api"] (api-routes db-conn))
+     ;;middleware
+     [wrap-params]
+     ]))


Reorganize dictionary a bit

Reorganize dictionary a bit

--- src/clj/zetawar/data.cljs
+++ src/clj/zetawar/data.cljs
@@ -7,11 +7,13 @@
     :cancel-button "Cancel"
     :close-button "Close"

-    ;; Game actions and labels
-    :credits-label "Credits"
+    ;; Game links
     :copy-game-url-link "Copy Link"
     :new-game-link "New Game"
     :end-turn-link "End Turn?"
+
+    ;; Game labels
+    :credits-label "Credits"
     :round-label "Round"

     ;; Faction configuration


Docstring fix

Docstring fix

--- src/cljc/zetawar/doc.cljc
+++ src/cljc/zetawar/doc.cljc
@@ -12,7 +12,7 @@
   k)

 (defn registry
-  "Returns the registry map, prefer 'get-docstring' to lookup a docstring by
+  "Returns the registry map, prefer 'get-doc' to lookup a docstring by
   name."
   []
   @registry-ref)


Using (str tag) instead of (name tag) when reading tagged literals

In order to support proper edn tagged elements (which must contain a prefix
component) we must use the full symbol (not just it's name) when looking up
and assoc'ing the the tag in *tag-table*

--- src/cljs/cljs/reader.cljs
+++ src/cljs/cljs/reader.cljs
@@ -530,22 +530,22 @@
 (defn maybe-read-tagged-type
   [rdr initch]
   (let [tag  (read-symbol rdr initch)]
-    (if-let [pfn (get @*tag-table* (name tag))]
+    (if-let [pfn (get @*tag-table* (str tag))]
       (pfn (read rdr true nil false))
       (reader-error rdr
-                    "Could not find tag parser for " (name tag)
+                    "Could not find tag parser for " (str tag)
                     " in " (pr-str (keys @*tag-table*))))))

 (defn register-tag-parser!
   [tag f]
-  (let [tag (name tag)
+  (let [tag (str tag)
         old-parser (get @*tag-table* tag)]
     (swap! *tag-table* assoc tag f)
     old-parser))

 (defn deregister-tag-parser!
   [tag]
-  (let [tag (name tag)
+  (let [tag (str tag)
         old-parser (get @*tag-table* tag)]
     (swap! *tag-table* dissoc tag)
     old-parser))


Update data reader to ignore #inst and #uuid

--- src/cljs/cljs/reader.cljs
+++ src/cljs/cljs/reader.cljs
@@ -333,7 +333,9 @@
    "<" (throwing-reader "Unreadable form")
    "\"" read-regex
    "!" read-comment
-   "_" read-discard})
+   "_" read-discard
+   "i" read-discard
+   "u" read-discard})

 (defn read
   "Reads the first object from a PushbackReader. Returns the object read.


much idiom

much idiom

--- src/cljs/fatlip/core.cljs
+++ src/cljs/fatlip/core.cljs
@@ -515,7 +515,7 @@
     (if (empty? nodes)
       crossings
       (let [node (first nodes)
-            dest-set (into #{} (map :dest (get succs node)))
+            dest-set (set (map :dest (get succs node)))
             dests (filter #(contains? dest-set %) minus-qs)
             c (count-sub-crossings-single-node node dests characters)]
         (recur (rest nodes) (+ crossings c))))))
@@ -756,7 +756,7 @@
   aligned blocks"
   [cm-graph]
   (let [{:keys [layers succs preds marked crossings characters]} cm-graph
-        cm-layers (into [] (map OrderedLayer->FlatLayer layers))
+        cm-layers (vec (map OrderedLayer->FlatLayer layers))
         [aboves belows] (apply map merge (map neighborify cm-layers))
         [top-idxs bot-idxs] (apply map merge (map indexify cm-layers))]
     (map->FlatGraph {:layers cm-layers
@@ -792,7 +792,7 @@
                     (range (inc dest-layer) src-layer))
                (map (partial Edge->Segment pred)
                     (range (dec dest-layer) src-layer -1)))]
-    (conj (into [] segs) src)))
+    (conj (vec segs) src)))

 (defn blockify-layer
@@ -906,12 +906,12 @@
            succs {}
            preds {}]
       (if (empty? bs)
-        (let [block-set (into #{} (vals blocks))
+        (let [block-set (set (vals blocks))
               simple-succs (->> (map (fn [[src edges]]
-                                       [src (into #{} (map :dest edges))])
+                                       [src (set (map :dest edges))])
                                      succs)
                                 (into {}))
-              all-succs (into #{} (reduce set/union (vals simple-succs)))
+              all-succs (reduce set/union (vals simple-succs))
               long-block (first (filter #(> (count %) 1) block-set))
               layer-id-compare (if (< (-> long-block first :layer-id)
                                       (-> long-block second :layer-id))
@@ -969,7 +969,7 @@
   classes. This means there can be multiple edges per class pair."
   [block-graph]
   (let [block-classes (classify block-graph)
-        classes (into #{} (vals block-classes))
+        classes (set (vals block-classes))
         edge->set #(update-in %1 [(get block-classes (:src %2))]
                               (fnil conj #{}) %2)]
     (loop [cs classes
@@ -978,10 +978,9 @@
       (if (empty? cs)
         (let [simple-succs (->> (map (fn [[src edges]]
                                        [src
-                                        (into #{}
-                                              (map #(get-in
-                                                     block-classes [(:dest %)])
-                                                   edges))])
+                                        (set (map #(get-in
+                                                    block-classes [(:dest %)])
+                                                  edges))])
                                      succs)
                                 (into {}))
               all-succs (reduce set/union (vals simple-succs))
@@ -990,10 +989,10 @@
           (map->ClassGraph {:classes topo-classes :succs succs
                             :preds preds :sources sources}))
         (let [class (first cs)
-              class-set (into #{} class)
+              class-set (set class)
               block-succs (->> (mapcat #(-> block-graph :succs (get %)) class)
                                (remove #(contains? class-set (:dest %)))
-                               (into #{}))
+                               set)
               block-preds (map rev block-succs)
               ss (reduce edge->set succs block-succs)
               ps (reduce edge->set preds block-preds)]


begin x-y-positions

begin x-y-positions

--- src/cljs/signet/core.cljs
+++ src/cljs/signet/core.cljs
@@ -57,6 +57,26 @@
       (select frame)
       (select "svg")
       remove))
+
+
+(defn compute-positions
+  "Compute positions using widht, height, circle size and improved commit graph"
+  [w h cs icg]
+  (let [eos (- w cs)]
+      (loop [x-order (:x-order icg)
+             x-positions {}]
+        (if (empty? x-order)
+          (assoc icg :x-positions x-positions)
+          (recur (rest x-order)
+                 (let [branch (first x-order)
+                       nodes (get-in icg [:nodes branch])
+                       n (count nodes)
+
+                       start (or (first (get-in icg [:branch-links branch])) 0)
+                       end (or (first (get-in icg [:merge-links branch])) eos)
+                       dx (/ (- end start) (if (= 0 start)
+                                             (if (= ))
+                                             (dec n) n))]))))))

 (defn compute-pos [w h cs]


input callback is working

input callback is working

--- src/clojure/yaw/world.clj
+++ src/clojure/yaw/world.clj
@@ -47,11 +47,11 @@
 (defn register-input-callback!
   "Register the input callback for low-level keyboard management."
   [world callback]
-  (let [cb (reify yaw.engine.InputCallback
+  (let [cb (reify InputCallback
              (sendKey [this key scancode action mode]
-               (println "key event! key=" key " scancode=" scancode "action=" action "mode=" mode)
+               ;; (println "key event! key=" key " scancode=" scancode "action=" action "mode=" mode)
                (callback key scancode action mode)))]
-    (println "[input callback] cb=" cb "world=" world)
+    ;; (println "[input callback] cb=" cb "world=" world)
     (.registerInputCallback world cb)))


avoids using apply max in favor of reduce max (#1084)

--- waiter/src/waiter/service_description.clj
+++ waiter/src/waiter/service_description.clj
@@ -1169,7 +1169,7 @@
       :token->token-data
       (pc/map-vals (fn [{:strs [last-update-time]}] (or last-update-time 0)))
       vals
-      (apply max))
+      (reduce max))
     0))

 (defn service-id->service-description


Added missing :else clause to cond

Added missing :else clause to cond

--- ccw.core/src/clj/ccw/debug/serverrepl.clj
+++ ccw.core/src/clj/ccw/debug/serverrepl.clj
@@ -371,13 +371,13 @@
           idxy (distance-fn y s)]
       (cond
         (and idxx idxy)
-        (if (= idxx idxy)
-          (if-same-distances-comparator x y)
-          (- idxx idxy))
+          (if (= idxx idxy)
+            (if-same-distances-comparator x y)
+            (- idxx idxy))
         (and idxx (not idxy)) -1
         (and idxy (not idxx)) 1
-        if-nil-distances-comparator
-        (if-nil-distances-comparator x y)))))
+        :else
+        ((or if-nil-distances-comparator if-same-distances-comparator) x y)))))

 ;; TODO instead of this monolithic piece of code
 ;; see if we can instead compose comparators


Complete destructuring koans test

Complete destructuring koans test

--- clojure/koans/src/koans/14_destructuring.clj
+++ clojure/koans/src/koans/14_destructuring.clj
@@ -5,37 +5,53 @@

 (meditations
   "Destructuring is an arbiter: it breaks up arguments"
-  (= __ ((fn [[a b]] (str b a))
+  (= ":bar:foo" ((fn [[a b]] (str b a))
          [:foo :bar]))

   "Whether in function definitions"
   (= (str "First comes love, "
           "then comes marriage, "
           "then comes Clojure with the baby carriage")
-     ((fn [[a b c]] __)
-      ["love" "marriage" "Clojure"]))
+     ((fn [[a b c]] (str "First comes " a ", "
+          "then comes " b ", "
+          "then comes " c " with the baby carriage"))
+      ["love" "marriage" "Clojure"])
+  )

   "Or in let expressions"
   (= "Rich Hickey aka The Clojurer aka Go Time aka Macro Killah"
      (let [[first-name last-name & aliases]
            (list "Rich" "Hickey" "The Clojurer" "Go Time" "Macro Killah")]
-       __))
+       (str first-name " " last-name (apply str (map #(str " aka " %) aliases)))
+     )
+  )

   "You can regain the full argument if you like arguing"
   (= {:original-parts ["Steven" "Hawking"] :named-parts {:first "Steven" :last "Hawking"}}
      (let [[first-name last-name :as full-name] ["Steven" "Hawking"]]
-       __))
+       {:original-parts full-name
+         :named-parts {:first first-name :last last-name}
+       }
+     )
+  )

   "Break up maps by key"
   (= "123 Test Lane, Testerville, TX"
      (let [{street-address :street-address, city :city, state :state} test-address]
-       __))
+       (str street-address ", " city ", " state))
+  )

   "Or more succinctly"
   (= "123 Test Lane, Testerville, TX"
-     (let [{:keys [street-address __ __]} test-address]
-       __))
+     (let [{:keys [street-address city state]} test-address]
+       (str street-address ", " city ", " state))
+  )

   "All together now!"
   (= "Test Testerson, 123 Test Lane, Testerville, TX"
-     (___ ["Test" "Testerson"] test-address)))
+    ((fn [[first-name last-name] {:keys [street-address city state]}]
+      (str first-name " " last-name ", " street-address ", " city ", " state)
+    )
+    ["Test" "Testerson"] test-address)
+  )
+)


CLJS-1086: Keyword constants should have stable names

--- src/clj/cljs/analyzer.clj
+++ src/clj/cljs/analyzer.clj
@@ -205,7 +205,7 @@
                  :else
                  (throw
                    (Exception. (str "constant type " (type value) " not supported"))))]
-    (symbol (str prefix (swap! constant-counter inc)))))
+    (symbol (str prefix (string/replace (munge value) "." "$")))))

 (defn- register-constant!
   ([val] (register-constant! nil val))


refactor ns parsing

refactor ns parsing

--- src/clj/cljs/analyzer.clj
+++ src/clj/cljs/analyzer.clj
@@ -969,6 +969,109 @@
                (nil? (.findInternedVar ^clojure.lang.Namespace (find-ns lib) sym)))
       (warning :undeclared-ns env {:type :macro :lib lib :sym sym}))))

+(defn parse-ns-error-msg [spec msg]
+  (str msg "; offending spec: " (pr-str spec)))
+
+(defn basic-validate-ns-spec [env macros? spec]
+  (when-not (or (symbol? spec) (vector? spec))
+    (throw
+      (error env
+        (parse-ns-error-msg spec
+          "Only [lib.ns & options] and lib.ns specs supported in :require / :require-macros"))))
+  (when (vector? spec)
+    (when-not (symbol? (first spec))
+      (throw
+        (error env
+          (parse-ns-error-msg spec
+            "Library name must be specified as a symbol in :require / :require-macros"))))
+    (when-not (odd? (count spec))
+      (throw
+        (error env
+          (parse-ns-error-msg spec
+            "Only :as alias and :refer (names) options supported in :require"))))
+    (when-not (every? #{:as :refer} (map first (partition 2 (next spec))))
+      (throw
+        (error env
+          (parse-ns-error-msg spec
+            "Only :as and :refer options supported in :require / :require-macros"))))
+    (when-not (let [fs (frequencies (next spec))]
+                (and (<= (fs :as 0) 1)
+                     (<= (fs :refer 0) 1)))
+      (throw
+        (error env
+          (parse-ns-error-msg spec
+            "Each of :as and :refer options may only be specified once in :require / :require-macros"))))))
+
+(defn parse-ns-excludes [env args]
+  (reduce
+    (fn [s [k exclude xs]]
+      (if (= k :refer-clojure)
+        (do
+          (when-not (= exclude :exclude)
+            (throw (error env "Only [:refer-clojure :exclude (names)] form supported")))
+          (when (seq s)
+            (throw (error env "Only one :refer-clojure form is allowed per namespace definition")))
+          (into s xs))
+        s))
+    #{} args))
+
+(defn use->require [env [lib kw referred :as spec]]
+  (when-not (and (symbol? lib) (= :only kw) (sequential? referred) (every? symbol? referred))
+    (throw
+      (error env
+        (parse-ns-error-msg spec
+          "Only [lib.ns :only (names)] specs supported in :use / :use-macros"))))
+  [lib :refer referred])
+
+(defn parse-require-spec [env macros? deps aliases spec]
+  (if (symbol? spec)
+    (recur env macros? deps aliases [spec])
+    (do
+      (basic-validate-ns-spec env macros? spec)
+      (let [[lib & opts] spec
+            {alias :as referred :refer :or {alias lib}} (apply hash-map opts)
+            [rk uk] (if macros? [:require-macros :use-macros] [:require :use])]
+        (when-not (or (symbol? alias) (nil? alias))
+          (throw
+            (error env
+              (parse-ns-error-msg spec
+                ":as must be followed by a symbol in :require / :require-macros"))))
+        (when alias
+          (let [alias-type (if macros? :macros :fns)]
+            (when (contains? (alias-type @aliases) alias)
+              (throw (error env (parse-ns-error-msg spec ":as alias must be unique"))))
+            (swap! aliases
+              update-in [alias-type]
+              conj alias)))
+        (when-not (or (and (sequential? referred)
+                           (every? symbol? referred))
+                      (nil? referred))
+          (throw
+            (error env
+              (parse-ns-error-msg spec
+                ":refer must be followed by a sequence of symbols in :require / :require-macros"))))
+        (when-not macros?
+          (swap! deps conj lib))
+        (merge
+          (when alias
+            {rk (merge {alias lib} {lib lib})})
+          (when referred {uk (apply hash-map (interleave referred (repeat lib)))}))))))
+
+(defn parse-import-spec [env deps spec]
+  (when-not (or (and (sequential? spec)
+                     (every? symbol? spec))
+                (and (symbol? spec) (nil? (namespace spec))))
+    (throw (error env (parse-ns-error-msg spec "Only lib.ns.Ctor or [lib.ns Ctor*] spec supported in :import"))))
+  (let [import-map (if (sequential? spec)
+                     (->> (rest spec)
+                       (map #(vector % (symbol (str (first spec) "." %))))
+                       (into {}))
+                     {(symbol (last (string/split (str spec) #"\."))) spec})]
+    (doseq [[_ spec] import-map]
+      (swap! deps conj spec))
+    {:import  import-map
+     :require import-map}))
+
 (defmethod parse 'ns
   [_ env [_ name & args :as form] _]
   (when-not (symbol? name)
@@ -977,81 +1080,17 @@
         args      (if docstring (next args) args)
         metadata  (if (map? (first args)) (first args))
         args      (if metadata (next args) args)
-        excludes
-        (reduce (fn [s [k exclude xs]]
-                  (if (= k :refer-clojure)
-                    (do
-                      (when-not (= exclude :exclude)
-                        (throw (error env "Only [:refer-clojure :exclude (names)] form supported")))
-                      (when (seq s)
-                        (throw (error env "Only one :refer-clojure form is allowed per namespace definition")))
-                      (into s xs))
-                    s))
-                #{} args)
-        deps (atom #{})
-        aliases (atom {:fns #{} :macros #{}})
+        excludes  (parse-ns-excludes env args)
+        deps      (atom #{})
+        aliases   (atom {:fns #{} :macros #{}})
+        spec-parsers {:require        (partial parse-require-spec env false deps aliases)
+                      :require-macros (partial parse-require-spec env true deps aliases)
+                      :use            (comp (partial parse-require-spec env false deps aliases)
+                                            (partial use->require env))
+                      :use-macros     (comp (partial parse-require-spec env true deps aliases)
+                                            (partial use->require env))
+                      :import         (partial parse-import-spec env deps)}
         valid-forms (atom #{:use :use-macros :require :require-macros :import})
-        error-msg (fn [spec msg] (str msg "; offending spec: " (pr-str spec)))
-        parse-require-spec (fn parse-require-spec [macros? spec]
-                             (when-not (or (symbol? spec) (vector? spec))
-                               (throw (error env (error-msg spec "Only [lib.ns & options] and lib.ns specs supported in :require / :require-macros"))))
-                             (when (vector? spec)
-                               (when-not (symbol? (first spec))
-                                 (throw (error env (error-msg spec "Library name must be specified as a symbol in :require / :require-macros"))))
-                               (when-not (odd? (count spec))
-                                 (throw (error env (error-msg spec "Only :as alias and :refer (names) options supported in :require"))))
-                               (when-not (every? #{:as :refer} (map first (partition 2 (next spec))))
-                                 (throw (error env (error-msg spec "Only :as and :refer options supported in :require / :require-macros"))))
-                               (when-not (let [fs (frequencies (next spec))]
-                                           (and (<= (fs :as 0) 1)
-                                                (<= (fs :refer 0) 1)))
-                                 (throw (error env (error-msg spec "Each of :as and :refer options may only be specified once in :require / :require-macros")))))
-                             (if (symbol? spec)
-                               (recur macros? [spec])
-                               (let [[lib & opts] spec
-                                     {alias :as referred :refer :or {alias lib}} (apply hash-map opts)
-                                     [rk uk] (if macros? [:require-macros :use-macros] [:require :use])]
-                                 (when-not (or (symbol? alias) (nil? alias))
-                                   (throw (error env (error-msg spec ":as must be followed by a symbol in :require / :require-macros"))))
-                                 (when alias
-                                   (let [alias-type (if macros? :macros :fns)]
-                                     (when (contains? (alias-type @aliases) alias)
-                                       (throw (error env (error-msg spec ":as alias must be unique"))))
-                                     (swap! aliases
-                                            update-in [alias-type]
-                                            conj alias)))
-                                 (when-not (or (and (sequential? referred) (every? symbol? referred))
-                                               (nil? referred))
-                                   (throw (error env (error-msg spec ":refer must be followed by a sequence of symbols in :require / :require-macros"))))
-                                 (when-not macros?
-                                   (swap! deps conj lib))
-                                 (merge
-                                   (when alias
-                                     {rk (merge {alias lib} {lib lib})})
-                                   (when referred {uk (apply hash-map (interleave referred (repeat lib)))})))))
-        use->require (fn use->require [[lib kw referred :as spec]]
-                       (when-not (and (symbol? lib) (= :only kw) (sequential? referred) (every? symbol? referred))
-                         (throw (error env (error-msg spec "Only [lib.ns :only (names)] specs supported in :use / :use-macros"))))
-                       [lib :refer referred])
-        parse-import-spec (fn parse-import-spec [spec]
-                            (when-not (or (and (sequential? spec)
-                                               (every? symbol? spec))
-                                          (and (symbol? spec) (nil? (namespace spec))))
-                              (throw (error env (error-msg spec "Only lib.ns.Ctor or [lib.ns Ctor*] spec supported in :import"))))
-                            (let [import-map (if (sequential? spec)
-                                               (->> (rest spec)
-                                                 (map #(vector % (symbol (str (first spec) "." %))))
-                                                 (into {}))
-                                               {(symbol (last (string/split (str spec) #"\."))) spec})]
-                              (doseq [[_ spec] import-map]
-                                (swap! deps conj spec))
-                              {:import  import-map
-                               :require import-map}))
-        spec-parsers {:require        (partial parse-require-spec false)
-                      :require-macros (partial parse-require-spec true)
-                      :use            (comp (partial parse-require-spec false) use->require)
-                      :use-macros     (comp (partial parse-require-spec true) use->require)
-                      :import         parse-import-spec}
         {uses :use requires :require use-macros :use-macros require-macros :require-macros imports :import :as params}
         (reduce (fn [m [k & libs]]
                   (when-not (#{:use :use-macros :require :require-macros :import} k)
@@ -1072,14 +1111,14 @@
     (when (seq use-macros)
       (check-use-macros use-macros env))
     (swap! env/*compiler* update-in [::namespaces name] assoc
-           :name name
-           :doc docstring
-           :excludes excludes
-           :uses uses
-           :requires requires
-           :use-macros use-macros
-           :require-macros require-macros
-           :imports imports)
+      :name name
+      :doc docstring
+      :excludes excludes
+      :uses uses
+      :requires requires
+      :use-macros use-macros
+      :require-macros require-macros
+      :imports imports)
     {:env env :op :ns :form form :name name :doc docstring :uses uses :requires requires :imports imports
      :use-macros use-macros :require-macros require-macros :excludes excludes}))


* src/cljs/cljs/reader.cljs: optimize CLJS-108 patch

--- src/cljs/cljs/reader.cljs
+++ src/cljs/cljs/reader.cljs
@@ -297,7 +297,7 @@
             (identical? (aget name (dec (.-length name))) ":")
             (coercive-not (== (.indexOf token "::" 1) -1)))
       (reader-error reader "Invalid token: " token)
-      (if (and ns (> (.-length ns) 0))
+      (if (and (coercive-not= ns nil) (> (.-length ns) 0))
         (keyword (.substring ns 0 (.indexOf ns "/")) name)
         (keyword token)))))


smarten up the ordering loop

smarten up the ordering loop

--- src/cljs/fatlip/core.cljs
+++ src/cljs/fatlip/core.cljs
@@ -496,20 +496,20 @@
   'An Efficient Implementation of Sugiyama’s Algorithm for Layered Graph Drawing',
   a paper by Markus Eiglsperger, Martin Sieberhaller, and Michael Kaufmann (ESK)"
   [sparse-graph]
-  ;; seed the first layer with initial compact representation and alternating layer
-  (let [nodes (-> sparse-graph :layers first :nodes)
-        alternating (cons (first segment-containers)
-                          (interleave nodes segment-containers))]
-    (loop [seeded-graph (update-in sparse-graph [:layers 0] assoc :alternating alternating)
-           counter 0]
-      (if (= counter 20)
-        seeded-graph
-        (let [ordered-graph (order-graph-once seeded-graph)
-              last-alternating (-> ordered-graph :layers peek :alternating)
-              sd-graph (-> sparse-graph
-                           (#(if (odd? counter)
-                               (reverse-graph %)
-                               %))
-                           (update-in [:layers 0] assoc :alternating last-alternating))]
-          (println counter (:crossings ordered-graph) last-alternating)
-          (recur sd-graph (inc counter)))))))
+  ;; seed the first layer with initial alternating layer
+  (loop [alternating (cons (first segment-containers)
+                           (interleave (-> sparse-graph :layers first :nodes)
+                                       segment-containers))
+         orderings []]
+    (let [c (count orderings)]
+      (if (= c 20)
+        orderings
+        (let [reverse? (odd? c)
+              ordered-graph (-> (if reverse?
+                                  (reverse-graph sparse-graph)
+                                  sparse-graph)
+                                (update-in [:layers 0] assoc :alternating alternating)
+                                order-graph-once)]
+          (println c (:crossings ordered-graph) (-> ordered-graph :layers peek :alternating))
+          (recur (-> ordered-graph :layers peek :alternating)
+                 (conj orderings (if reverse? (reverse-graph ordered-graph) ordered-graph))))))))