                                              {}
                                              optimized-with-path)
                            pathmap (:graph (graph/get set-graph [request]))]
-                  ((:set handler) pathmap ctx))))]
+                  ((:set handler) pathmap env))))]
       (let [pathsets (core/collapse paths)]
-        (execute route-tree :set runner pathsets)))))
+        (execute route-tree
+                 (init-context :set pathsets env)
+                 runner)))))
 
 (defn set
   ([router pathmaps]
    (set router pathmaps {}))
-  ([router pathmaps ctx]
-   (last (sets router pathmaps ctx))))
-
-(defn calls [{:keys [route-tree]} call-path args queries ctx]
+  ([router pathmaps env]
+   (last (sets router pathmaps env))))
+
+(defn calls [{:keys [route-tree]} call-path args queries env]
   (letfn [(runner [{:keys [method handler request]} matched-path _]
             (case method
-              :get ((:get handler) matched-path ctx)
-              :call (let [results ((:call handler) matched-path args ctx)
+              :get ((:get handler) matched-path env)
+              :call (let [results ((:call handler) matched-path args env)
                           ;; expand pathmaps so we can search for refs
                           results (into [] (mapcat (fn [result]
                                                      (if (core/pathmap? result)

                                          (seq this-paths) (conj (additional-paths this-paths))
                                          (seq ref-paths) (conj (additional-paths ref-paths)))]
                      results)))]
    (execute route-tree :call runner [call-path])))

(defn call
  ([router path args queries]
   (call router path args queries {}))
  ([router path args queries ctx]
   (last (calls router path args queries ctx))))

;; TODO: this name sucks
(defn handle
  ([router request]
   (handle router request {}))
  ([router {:keys [method] :as request} ctx]
   (case method
     :get (let [{:keys [pathsets]} request]
            (get router pathsets ctx))
     :set (let [{:keys [pathmaps]} request]
            (set router pathmaps ctx))
     :call (let [{:keys [path args queries]} request]
             (call router path args queries ctx)))))

(defrecord Router [route-tree])


(defn set-method [method]
  (SetMethod. method))

(defn merge-results
  [context results]
  (letfn [(optimize-pathsets [{:keys [pathsets graph] :as context}]
            (assoc context :pathsets (->> pathsets
                                          (core/optimize graph)
                                          core/collapse
                                          (into []))))]
    (let [context (reduce (fn [context [match value]]
                            (update-context value context match))
                          context
                          results)
          context (optimize-pathsets context)]
      context)))

(defn init-context
  [method pathsets env]
  {:method method
   :pathsets pathsets
   :env env
   :graph {}
   :request pathsets
   :matched []
   :optimized []
   :missing []})

(defn execute
  [route-tree context runner]
  (letfn [(context-result [context]
            (dissoc context :method :pathsets :env))
          (match-and-run [{:keys [method] :as context} pathset]
            (let [matches (match route-tree method pathset)
                  results (run context pathset matches runner)]
              results))
          (execute* [{:keys [pathsets] :as context}]
            (lazy-seq
              (if (seq pathsets)
                (let [results (mapcat (partial match-and-run context) pathsets)
