 (defn knowledge []
   (Knowledge. {} 0))
 
+;; FLOWS
+
+(deftype Join [input-types input-args output-kinds output-names output-fields]
+  Object
+  (run [this kn]
+       (let [input-iters (amap input-types i _
+                               (.apply (aget js/aurora.join (aget input-types i)) nil (aget input-args i)))
+             join-iter (join/join-iterator input-iters)
+             facts (btree/iterator->keys join-iter)]
+         (dotimes [i (alength output-kinds)]
+           (.add-facts kn (aget output-kinds i) (aget output-names i) (aget output-fields i) facts)))))
+
+(deftype Chain [flows]
+  Object
+  (run [this kn]
+       (dotimes [i (alength flows)]
+         (.run (aget flows i) kn))))
+
+(deftype Fixpoint [flow]
+  Object
+  (run [this kn]
+       (loop [old-version (.-version kn)]
+         (.run flow kn)
+         (let [new-version (.-version kn)]
+           (when (not (== old-version new-version))
+             (recur new-version))))))
 
 (comment
 

(ns aurora.language
  (:require [aurora.btree :as btree])
  (:require-macros [aurora.macros :refer [apush set!!]]))

(defn keymap [from-fields to-fields]
  (let [keymap (make-array (alength to-fields))]


  (.get-or-create-index kn "know" "heights" #js ["height" "name"])

  (.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"]])

  (def edge-flow
    (Join. #js ["magic_iterator"] #js [#js [(.get-or-create-index kn "know" "edge" #js ["x" "y"]) #js [0 1]]]
           #js ["know"] #js ["connected"] #js [#js ["x" "y"]]))

  (def connected-flow
    (Join. #js ["magic_iterator" "magic_iterator"] #js [#js [(.get-or-create-index kn "know" "edge" #js ["x" "y"]) #js [0 1 nil]]
                                                        #js [(.get-or-create-index kn "know" "connected" #js ["x" "y"]) #js [nil 0 1]]]
           #js ["know"] #js ["connected"] #js [#js ["x" nil "y"]]))

  (def transitive-flow
    (Chain. #js [edge-flow (Fixpoint. connected-flow)]))

  (.run transitive-flow kn)

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