     (alength (time (iterator->keys j)))
   )
 
-  (let [tree1 (tree 10)
-        _ (.assoc! tree1 #js ["a" "b"] 0)
-        _ (.assoc! tree1 #js ["b" "c"] 0)
-        _ (.assoc! tree1 #js ["c" "d"] 0)
-        _ (.assoc! tree1 #js ["d" "b"] 0)
-        tree2 (tree 10)
-        _ (.assoc! tree2 #js ["b" "a"] 0)
-        _ (.assoc! tree2 #js ["c" "b"] 0)
-        _ (.assoc! tree2 #js ["d" "c"] 0)
-        _ (.assoc! tree2 #js ["b" "d"] 0)
-        join-itr (join #js [(iterator tree1) (iterator tree2)] 3 #js [#js [true false true]
-                                                                      #js [false true true]])
-        ]
-     (map vec (iterator->keys join-itr))
-    )
+
+
+
 
  )
+
+(enable-console-print!)
+
+(let [tree1 (tree 10)
+      _ (.assoc! tree1 #js ["a" "b"] 0)
+      _ (.assoc! tree1 #js ["b" "c"] 0)
+      _ (.assoc! tree1 #js ["c" "d"] 0)
+      _ (.assoc! tree1 #js ["d" "b"] 0)
+      tree2 (tree 10)
+      _ (.assoc! tree2 #js ["b" "a"] 0)
+      _ (.assoc! tree2 #js ["c" "b"] 0)
+      _ (.assoc! tree2 #js ["d" "c"] 0)
+      _ (.assoc! tree2 #js ["b" "d"] 0)
+      s (solver #js [(contains (iterator tree1) #js [0 2])
+                     (contains (iterator tree2) #js [1 2])]
+                3)
+      ]
+  [(.next s) (.next s) (.next s)]
+  )
+

  (split [this]
         ;; split by value of next unset var
         (loop [i 0]
           (if (< i (alength upper))
             (if (identical? (aget lower i) (aget upper i))
               (recur (+ i 1))
               (do
                 (apush pushed|split false)
                 (apush split-uppers (aclone upper))
                 (aset upper i (aget lower i))
                 (apush split-lowers (aclone upper)) ;; the lower for right-hand branch is the next key after the upper for the left-hand branch
                 true))
             false)))

(def failed 2)

;; lower and upper are inclusive
(deftype Contains [iterator ^:mutable lower ^:mutable upper ixes pushed|split pushed-nodes pushed-ixes split-lowers split-uppers]
  Object
  (reset [this]
         (.reset iterator)
         (dotimes [i (alength lower)]
           (aset lower i least)
           (aset upper i greatest))
         (let [key (.seek-gte iterator lower)]
           (aset lower 0 (aget key 0)))
         (aclear pushed-nodes)
         (aclear pushed-ixes)
         (aclear split-lowers)
         (aclear split-uppers))
  (propagate [this los his]
             (check (key-lte los his) (pr-str los his))
             (check (key-lte lower upper) (pr-str lower upper))
             (debug :before-propagate lower upper los his)
             (let [this-changed? false]
               (loop [i 0]
                 (when (< i (alength ixes))
                   (let [ix (aget ixes i)
                         old-lo (aget lower i)
                         old-hi (aget upper i)
                         new-lo (aget los ix)
                         new-hi (aget his ix)]
                     (when (val-lt old-lo new-lo)
                       (aset lower i new-lo)
                       (set!! this-changed? true))
                     (when (val-lt new-hi old-hi)
                       (aset upper i new-hi)
                       (set!! this-changed? true))
                     (when (identical? new-lo new-hi)
                       (recur (+ i 1))))))
               ;; TODO only seek on change, including split as change
               (let [key (.seek-gte iterator lower)
                     that-changed? false]
                 (debug :propagate-with key)
                 (if (or (nil? key)
                         (key-lt upper key))
                   failed
                   (loop [i 0]
                     (let [ix (aget ixes i)
                           old-lo (aget los ix)
                           old-hi (aget his ix)
                           new-lo (aget key i)
                           new-hi (aget upper i)]
                       (if (val-lt old-hi new-lo)
                         failed
                         (do
                           (aset lower i new-lo)
                           (when (val-lt old-lo new-lo)
                             (aset los ix new-lo)
                             (set!! that-changed? true))
                           (when (val-lt new-hi old-hi)
                             (aset his ix new-hi)
                             (set!! that-changed? true))
                           (if (and (< (+ i 1) (alength ixes)) (identical? new-lo new-hi))
                             (recur (+ i 1))
                             (do
                               (debug :after-propagate lower upper los his)
                               (check (key-lte los his) (pr-str los his))
                               (check (key-lte lower upper) (pr-str lower upper))
                               (if (true? that-changed?)
                                 changed
                                 unchanged)))))))))))
  (push [this]
        (apush pushed|split true)
        (apush pushed-nodes (.-node iterator))
