               (children-zips-by-generation kids)))
     nil))
 
+
+;; === tags
+
+(defn get-tags
+  [node pred-map]
+  (vec (for [[kw pred] pred-map
+             :when (pred node)]
+         kw)))
+
+(defn get-tag-map
+  [tree pred-map]
+  (reduce (fn [tag-map node]
+            (assoc tag-map
+                   (:id node)
+                   (get-tags node pred-map)))
+          {}
+          (tree-seq map? :children tree)))
+
+(defn mk-get-tag-fn
+  [tag-map]
+  (fn [tree]
+    (-> tree
+        :id
+        tag-map)))
+
+;; === zippers
+
+(defn tree->zipper
+  [tree]
+  (z/zipper map?
+            #(-> % :children not-empty)
+            #(assoc % :children %2)
+            tree))
+
+(defn traverse-assoc-zipper
+  [zipr]
+  (if (z/end? zipr)
+    (-> zipr z/root)
+    (recur (-> zipr
+               (z/edit assoc :zipper zipr)
+               z/next))))
+
+(defn traverse-tree-assoc-zipper
+  [tree]
+  (-> tree
+      tree->zipper
+      traverse-assoc-zipper))
+
+;; move this to trace or utils?
+(defn traverse-tree
+  [tree f]
+  (assoc (f tree)
+         :children (mapv #(traverse-tree % f)
+                         (:children tree))))
+
+(defn traverse-tree-dissoc-zipper
+  [tree]
+  (traverse-tree tree #(dissoc % :zipper)))
+
+;; === query
+
+(defn query-tree
+  [qry-fn tree]
+  (if-not (nil? tree)
+    (let [e' (update-in tree [:children]
+                        (partial mapcat
+                                 (partial query-tree
+                                          qry-fn)))]
+      (if (qry-fn tree)
+        [e']
+        (:children e')))
+    []))
+
+(defn query-dos
+  [tree pred-map pred-final-fn] ;; pred-final-fn takes a node (w/ :zipper) and fn to retrieve tags from a node
+  (let [tag-map (get-tag-map tree pred-map)
+        get-tag-fn (mk-get-tag-fn tag-map)
+        pred-final-fn' #(pred-final-fn % get-tag-fn)]
+    (->> tree
+         tree->zipper
+         traverse-assoc-zipper
+         (query-tree pred-final-fn'))))
+
+(defn query-uno
+  [tree pred-fn]
+  (query-tree pred-fn tree))
+
+(defn query
+  ([tree pred-fn] (query-uno tree pred-fn))
+  ([tree pred-map pred-final-fn] (query-dos tree pred-map pred-final-fn)))
+
+;; === macro interface
+
+
+(defn get-some*
+  [f v]
+  (cond
+    (fn? f)
+    (f v)
+
+    (set? f)
+    (f v)
+
+    :default
+    (get v f)))
+
+(defn get-some
+  [coll v]
+  (loop [coll coll
+         v v]
+    (if ((some-fn empty? nil?) coll)
+      v
+      (let [[f & r] coll]
+        (when-let [v' (get-some* f v)]
+          (recur r v'))))))
+
+(defn eq* [pred v]
+  (cond (fn? pred)
+        (pred v)
+
+        (set? pred)
+        (pred v)
+
+        (instance? java.util.regex.Pattern pred)
+        (->> v
+             str
+             (re-matches pred))
+
+        :default (= pred v)))
+
+(defn mk-query-fn
+  [query-coll]
+  (let [path (drop-last query-coll)
+        pred (last query-coll)]
+    (fn [v]
+      (try
+        (->> v
+             (get-some path)
+             (eq* pred))
+        (catch Exception ex
+          nil)))))
+
+(defn some-mk-query-fn
+  [queries]
+  (->> queries
+       (map mk-query-fn)
+       (apply some-fn)))
+
+(defn every-pred-2
+  [& preds]
+  (fn [node tag-fn]
+    (loop [[f & r] preds]
+      (and (f node tag-fn)
+           (if (not-empty r)
+             (recur r)
+             true)))))
+
+
 (defn mk-lazy-descendant-tag-seq
   [node tag-fn dist]
-  (def n' node)
-  (def tag-fn' tag-fn)
-  (def d' dist)
   (let [generations-seq (->> node
                              :zipper
                              children-zips-by-generation)

         (mapcat tag-fn))))


(defn mk-lazy-sibling-tag-seq [])
(defn mk-lazy-ancestor-tag-seq [])

(defn mk-relative-final-qry-fn
  [opts tag-set & [dist]]

  (->> z
       (iter-while-identity z/up)
       rest))

(defn children-zips [zipr]
  (some->> zipr
