 ;; CLAUSES
 
 (defrecord Recall [memory pattern]) ;; memory is one of :known :pretended :remembered :forgotten :known&pretended
-(defrecord Filter [expr])
-(defrecord Let [name expr])
-(defrecord Set [name vars clauses])
+(defrecord Compute [pattern])
 (defrecord Output [memory pattern]) ;; memory is one of :pretended :remembered :forgotten
-(defrecord OutputMany [memory expr]) ;; memory is one of :pretended :remembered :forgotten
-
-(defn clause->flow-plan [flow-plan shape clause]
-  (condp = (type clause)
-    ;; TODO !!! keep going here
-    ))
+(defrecord OutputMany [memory vars expr]) ;; memory is one of :pretended :remembered :forgotten
+
+;; horrible non-relational things
+(deffact Let "Let [name] be the result of [vars] [expr]")
+(deffact When "When [vars] [expr]")
+
+;; if clause can be calculated somehow then return a new [plan node shape] pair that calculates it
+;; TODO make this extensible
+(defn compute? [plan node shape {:keys pattern}]
+  (condp = (.-shape pattern)
+    Let (when (every? (set shape) (:vars pattern))
+          (let [let-fun (expr->fun shape (:expr pattern))
+                filter-map-fun (fn [fact]
+                                 (let [new-value (.apply let-fun (.-values fact))
+                                       new-values (aclone (.-values fact))]
+                                   (apush new-values new-value)
+                                   (Fact. nil new-values)))
+                [plan node] (add-flow plan (->FilterMap [node] filter-map-fun))]
+            [plan node (conj shape (:name pattern))]))
+    When (when (every? (set shape) (:vars pattern))
+           (let [when-fun (expr->fun shape (:expr pattern))
+                 filter-map-fun (fn [fact]
+                                  (when (.apply when-fun (.-values fact))
+                                    fact))
+                 [plan node] (add-flow plan (->FilterMap [node] filter-map-fun))]
+             [plan node shape]))))
 
 ;; RULES
 
 (defrecord Rule [clauses])
+
+;; turn all Recalls into nodes
+;; try to apply computes
+;; loop
+  ;; join two nodes
+  ;; try to apply computes
+;; filter down vars?
+
+;; Correctness: Each clause must appear at least once in the plan
+;; Heuristic: Each Recall clause is used at most once in the plan
+;; Heuristic: Each Filter/Let clause is used at most once per path in the pln
 
 (defn rule->flow-plan [flow-plan rule]
   (loop [flow-plan flow-plan

(defrecord FilterMap [nodes fun])
(defrecord Index [nodes key-ixes])
(defrecord Lookup [nodes index-node key-ixes val-ixes])

;; FLOW PLAN


      (recur new-flow-plan new-shape (filter #(not= clause %) clauses))
      (do (assert (empty? clauses) (str "Cannot join " (pr-str shape) " with " (pr-str clauses)))
        flow-plan))))
