     (f/add-edge! g src v f/signal-forward nil)
     v))
 
+(defn qvar?
+  "Returns true, if x is a qvar (a symbol prefixed with '?')"
+  [x] (and (symbol? x) (= \? (.charAt ^String (name x) 0))))
+
+(defn bind-translator
+  [vs? vp? vo? s p o]
+  (if vs?
+    (if vp?
+      (if vo?
+        (fn [r] {s (r 0) p (r 1) o (r 2)})
+        (fn [r] {s (r 0) p (r 1)}))
+      (if vo?
+        (fn [r] {s (r 0) o (r 2)})
+        (fn [r] {s (r 0)})))
+    (if vp?
+      (if vo?
+        (fn [r] {p (r 1) o (r 2)})
+        (fn [r] {p (r 1)}))
+      (if vo?
+        (fn [r] {o (r 2)})
+        (fn [_] {})))))
+
+(defn pattern-translator
+  [vs? vp? vo? [s p o]]
+  (if (qvar? vs? s)
+    (if (qvar? vp? p)
+      (if (qvar? vo? o)
+        (fn [p] [nil nil nil])
+        (fn [p] [nil nil (p 2)]))
+      (if (qvar? vo? o)
+        (fn [p] [nil (p 1) nil])
+        (fn [p] (assoc p 0 nil))))
+    (if (qvar? vp? p)
+      (if (qvar? vo? o)
+        (fn [p] [(p 0) nil nil])
+        (fn [p] (assoc p 1 nil)))
+      (if (qvar? vo? o)
+        (fn [p] (assoc p 2 nil))
+        identity))))
+
+(defn triple-verifier
+  [ts tp to vars varp varo]
+  (cond
+    (and vars varp varo) (cond
+                           (= ts tp to) (fn [r] (= (r 0) (r 1) (r 2)))
+                           (= ts tp) (fn [r] (and (= (r 0) (r 1)) (not= (r 0) (r 2))))
+                           (= ts to) (fn [r] (and (= (r 0) (r 2)) (not= (r 0) (r 1))))
+                           (= tp to) (fn [r] (and (= (r 1) (r 2)) (not= (r 0) (r 1))))
+                           :else (constantly true))
+    (and vars varp)      (if (= ts tp)
+                           (fn [r] (= (r 0) (r 1)))
+                           (fn [r] (not= (r 0) (r 1))))
+    (and vars varo)      (if (= ts to)
+                           (fn [r] (= (r 0) (r 2)))
+                           (fn [r] (not= (r 0) (r 2))))
+    (and varp varo)      (if (= tp to)
+                           (fn [r] (= (r 1) (r 2)))
+                           (fn [r] (not= (r 1) (r 2))))
+    :else                (constantly true)))
+
+(defn param-query
+  [g id [s p o]]
+  (let [vs?        (qvar? s), vp? (qvar? p), vo? (qvar? o)
+        vmap       (bind-translator vs? vp? vo? s p o)
+        verify     (triple-verifier s p o vs? vp? vo?)
+        collect-fn (f/simple-collect
+                    (fn [_ incoming]
+                      (delay
+                       (when-let [res (peek incoming)]
+                         (into #{}
+                               (comp (map #(if (verify %) (vmap %)))
+                                     (filter identity))
+                               @res)))))
+        q-pattern  [(if vs? nil s) (if vp? nil p) (if vo? nil o)]
+        q-spec     (add-query! g id q-pattern)
+        r-vertex   (f/add-vertex! g {:val (delay nil) ::f/collect-fn collect-fn})]
+    (f/add-edge! g (:result q-spec) r-vertex f/signal-forward nil)
+    (assoc q-spec :qvar-result r-vertex)))
+
+(defn add-join-query
+  [g pat-a pat-b]
+  (let [qa  (param-query g (keyword (gensym)) pat-a)
+        qb  (param-query g (keyword (gensym)) pat-b)
+        jfn (fn [vertex]
+              (let [state (:state vertex)
+                    a @(get-in @state [::f/signal-map (:id (:qvar-result qa))])
+                    b @(get-in @state [::f/signal-map (:id (:qvar-result qb))])]
+                (info :join-sets a b)
+                (swap! state assoc :val (set/join a b))))
+        jv  (f/add-vertex!
+             g {:val (delay nil)
+                ::f/collect-fn jfn
+                ::f/score-collect-fn #(if (== (count (::f/signal-map @(:state %))) 2) 1 0)})]
+    (f/add-edge! g (:qvar-result qa) jv f/signal-forward nil)
+    (f/add-edge! g (:qvar-result qb) jv f/signal-forward nil)
+    {:a qa :b qb :join jv}))
+
 (defn start
   []
   (let [g (triple-graph (f/compute-graph))
         toxi (:result (add-query! g :toxi ['toxi nil nil]))
         types (:result (add-query! g :types [nil 'type nil]))
         projects (:result (add-query! g :projects [nil 'type 'project]))
+        knows (:result (add-query! g :projects [nil 'knows nil]))
         all (:result (add-query! g :all [nil nil nil]))
         num-projects (add-counter! g projects)
         num-types (add-counter! g types)
         inf1 (add-rule! g :knows [nil 'knows nil] (fn [[s p o]] [[s 'type 'person] [o 'type 'person] [o 'knows s]]))
-
+        pq (:qvar-result (param-query g :pq '[?s knows ?o]))
+        jq (:join (add-join-query g '[?p author ?prj] '[?prj type project]))
         ctx (f/async-context {:graph g :processor f/eager-vertex-processor :timeout nil})]
     (f/execute! ctx)
     (mapv

     :all all
     :toxi toxi
     :types types
     :projects projects
     :num-projects num-projects
     :num-types num-types}))

       ;;(info :coll-select val incoming)
       val))))

(defn score-collect-min-signal-vals
  [num]
  (fn [vertex]
    (if (> num (count (vals (peek (::f/uncollected @(:state vertex)))))) 0 1)))

(defn score-collect-min-signals
  [num]
  (fn [vertex]
    (if (> num (count (::f/uncollected @(:state vertex)))) 0 1)))

(defn aggregate-select
  [g]
