        (.replace (js/uuid) (js/RegExp. "-" "gi") "_")
        (str "id-" (swap! next inc)))))
 
-
 ;; NOTE can't handle missing keys yet - requires a schema
 (defn compile [kn]
-  (let [clauses (btree/iterator->keys (btree/iterator (.get-or-create-index kn "know" "clauses" ["rule-id" "when|pretend|remember|forget" "clause-id" "name"])))
-        fields (btree/iterator->keys (btree/iterator (.get-or-create-index kn "know" "clause-fields" ["clause-id" "constant|variable" "key" "val"])))
+  (let [clauses (btree/iterator->keys (btree/iterator (.get-or-create-index kn "know" "clauses" #js ["rule-id" "when|pretend|remember|forget" "clause-id" "name"])))
+        fields (btree/iterator->keys (btree/iterator (.get-or-create-index kn "know" "clause-fields" #js ["clause-id" "constant|variable" "key" "val"])))
         rule-id->clauses (atom (into {} (for [[k vs] (group-by #(nth % 0) clauses)] [k (set (map vec vs))])))
         clause-id->fields (atom (into {} (for [[k vs] (group-by #(nth % 0) fields)] [k (set (map vec vs))])))]
 

      (let [vars (atom #{})]

        ;; collect vars
        (doseq [[_ _ clause-id _] clauses
                (get @clause-id->fields clause-id)]
          (let [fields (get @clause-id->fields clause-id)]
            (doseq [[_ field-type key val] fields]
              (when (= field-type "variable")
                (swap! vars conj val)))))

        ;; make ruleset
        (let [var->ix (zipmap @vars (range))
              num-vars (count @vars)
              iters (for [[_ clause-type clause-id name] clauses
                          :when (= clause-type "when")]
                      (let [fields (get @clause-id->fields clause-id)]

                                              key)
                                index (.get-or-create-index kn "know" name clause-keys)]
                            (join/magic-iterator index (into-array var-map))))))
              join-iter (join/join-iterator (into-array iterators))

              ;; make output specs
              output-kinds (into-array
                            (for [[_ clause-type clause-id name] clauses
                                  :when (not= clause-type "when")]
                              clause-type))
              output-names (into-array
                            (for [[_ clause-type clause-id name] clauses
                                  :when (not= clause-type "when")]
                              name))
              output-fields (into-array
                             (for [[_ clause-type clause-id name] clauses
                                   :when (not= clause-type "when")]
                               (let [clause-fields (get @clause-id->fields clause-id)
                                     output-fields (make-array num-vars)]
                                 (doseq [[_ field-type key val] fields]
                                   (assert (= field-type "variable"))
                                   (aset output-fields (var->ix val) key)))))]

          (Flow. join-iter output-kinds output-names output-fields))))))

(def kn (knowledge))

(.get-or-create-index kn "know" "edge" #js ["x" "y"])

(.get-or-create-index kn "know" "connected" #js ["x" "y"])

(.add-facts kn "know" "edge" #js ["x" "y"] #js [#js ["a" "b"] #js ["b" "c"] #js ["c" "d"] #js ["d" "b"]])

(.get-or-create-index kn "know" "clauses" #js ["rule-id" "when|pretend|remember|forget" "clause-id" "name"])

(.get-or-create-index kn "know" "clause-fields" #js ["clause-id" "constant|variable" "key" "val"])

(.add-facts kn "know" "clauses" #js ["rule-id" "when|pretend|remember|forget" "clause-id" "name"] #js [#js ["edge->connected" "when" "get-edges" "edge"]
                                                                                                       #js ["edge->connected" "pretend" "output-connected" "edge"]])

(.add-facts kn "know" "clause-fields" #js ["clause-id" "constant|variable" "key" "val"] #js [#js ["get-edges" "variable" "x" "xx"]
                                                                                             #js ["get-edges" "variable" "y" "yy"]
                                                                                             #js ["output-connected" "variable" "x" "xx"]
                                                                                             #js ["output-connected" "variable" "y" "yy"]])

(compile kn)

(comment

