             (.reset (aget iterators i))))
         (.maintain this))))
 
-(defn join [trees num-vars tree->vars]
+(defn join [iterators num-vars iterator->vars]
   (assert (> num-vars 0))
-  (dotimes [i (alength trees)]
-    (let [tree-vars (aget tree->vars i)]
-      (assert (== (alength tree-vars) (.key-len (aget trees i))))
-      (dotimes [j (alength tree-vars)]
-        (assert (< (aget tree-vars j) num-vars)))))
-  (let [iterators (amap trees i _ (iterator (aget trees i)))
-        var->trees #js []
-        var->tree->present? #js []
+  (dotimes [i (alength iterators)]
+    (let [iterator-vars (aget iterator->vars i)]
+      (assert (== (alength iterator-vars) (.key-len (aget iterators i))))
+      (dotimes [j (alength iterator-vars)]
+        (assert (< (aget iterator-vars j) num-vars)))))
+  (let [var->iterators #js []
+        var->iterator->present? #js []
         var->intersection #js []]
     (dotimes [i num-vars]
-      (.push var->trees #js [])
-      (let [tree->present? #js []]
-        (.push var->tree->present? tree->present?)
-        (dotimes [j (alength trees)]
-          (.push tree->present? false))))
-    (dotimes [tree (alength trees)]
-      (let [tree-vars (aget trees tree)]
-        (dotimes [j (alength tree-vars)]
-          (let [var (aget tree-vars j)]
-            (.push (aget var->trees var) tree)
-            (aset var->tree->present? var tree true)))))
+      (.push var->iterators #js [])
+      (let [iterator->present? #js []]
+        (.push var->iterator->present? iterator->present?)
+        (dotimes [j (alength iterators)]
+          (.push iterator->present? false))))
+    (dotimes [iterator (alength iterators)]
+      (let [iterator-vars (aget iterators iterator)]
+        (dotimes [j (alength iterator-vars)]
+          (let [var (aget iterator-vars j)]
+            (.push (aget var->iterators var) iterator)
+            (aset var->iterator->present? var iterator true)))))
     (dotimes [i num-vars]
-      (.push var->intersection i (intersection (aget var->trees i))))
-    (let [join (Join. 0 iterators var->intersection var->tree->present? false)]
+      (assert (> (alength (aget var->iterators i)) 0))
+      (.push var->intersection i (intersection (aget var->iterators i))))
+    (let [join (Join. 0 iterators var->intersection var->iterator->present? false num-vars)]
       (.maintain join)
       join)))
+
+;; tree view of a trie
+(deftype Treeterator [iterator key ^:mutable key-ix ^:mutable end? key-len]
+  Object
+  (key [this]
+       (when (false? end?)
+         (aclone key)))
+  (val [this]
+       (when (false? end?)
+         (.val iterator)))
+  (walk-up [this]
+           (loop []
+             (when (false? end?)
+               (if (.-end? iterator)
+                 (if (<= key-ix 0)
+                   (set! end? true)
+                   (do
+                     (set! key-ix (- key-ix 1))
+                     (.up iterator)
+                     (recur)))))))
+  (walk-down [this]
+             (loop []
+               (when (and (false? end?) (< key-ix (- (alength key) 1)))
+                 (do
+                   (set! key-ix (+ key-ix 1))
+                   (.down iterator)
+                   (aset key key-ix (.key iterator))))))
+  (next [this]
+        (.walk-up this)
+        (when (false? end?)
+          (.next iterator)
+          (if (false? (.-end? iterator))
+            (aset key key-ix (.key iterator))
+            (set! end? true)))
+        (.walk-down this))
+  (seek [this key]
+        (assert false "TODO")))
+
+(defn treeterator [iterator]
+  (let [treeterator (Treeterator. iterator (least-key (.-key-len iterator)) 0 (.-key-len iterator))]
+    (.walk-down treeterator)
+    treeterator))
+
+(defn iter-seq [iterator]
+  (let [results #js []]
+    (while (false? (.-end? iterator))
+      (.push results (.key iterator))
+      (.next iterator))
+    results))
 
 ;; TESTS
 

  (loop [node (.-root tree)]
    (if (nil? (.-children node))
      (if (> (alength (.-keys node)) 0)
        (Iterator. (.-max-keys tree) node 0 #js [] #js [] false)
        (Iterator. (.-max-keys tree) node 0 #js [] #js [] true))
      (recur (aget (.-children node) 0)))))

(deftype Trieterator [iterator seek-key ^:mutable pinned-key ^:mutable pinned-key-ix ^:mutable moving-key-ix ^:mutable end?]
  Object
  (key [this]
       (aget (.key iterator) moving-key-ix))

  (reset [this]
         (.reset iterator)))

(defn trieterator [iterator]
  (Trieterator. iterator (least-key (.-key-len iterator)) nil -1 0 (.-end? it) (.-key-len iterator)))

;; works on trees
(deftype Intersection [iterators ^:mutable end? key-len]
  Object
  (key [this]
       (when (false? end?)
