Rewrite <resolve-lookup-refs to work for lookup refs.

Note that `go` (and `go-pair`) don't descend into `for` comprehensions
and other situations in which a fn is created. This commit rewrites to
use nested `loop`s, and also improves use of `<av`.
This commit is contained in:
Richard Newman 2016-08-12 16:29:44 -07:00
parent 86b5a8ea8a
commit 2529378725

View file

@ -209,23 +209,48 @@
(->> (update-txInstant db*))))) (->> (update-txInstant db*)))))
(defn- lookup-ref? [x] (defn- lookup-ref? [x]
"Return true if `x` is like [:attr value]." "Return `x` if `x` is like [:attr value], false otherwise."
(and (sequential? x) (and (sequential? x)
(= (count x) 2) (= (count x) 2)
(or (keyword? (first x)) (or (keyword? (first x))
(integer? (first x))))) (integer? (first x)))
x))
(defn <resolve-lookup-refs [db report] (defn <resolve-lookup-refs [db report]
{:pre [(db/db? db) (report? report)]} {:pre [(db/db? db) (report? report)]}
(let [entities (:entities report)]
;; TODO: meta.
(go-pair (go-pair
(->> (if (empty? entities)
(vec (for [[op & entity] (:entities report)] report
(into [op] (for [field entity] (assoc-in
(if (lookup-ref? field) report [:entities]
(first (<? (apply db/<av db field))) ;; We can't use `for` because go-pair doesn't traverse function boundaries.
field))))) ;; Apologies for the tortured nested loop.
(assoc-in report [:entities])))) ;; TODO: meta. (loop [[op & entity] (first entities)
next (rest entities)
acc []]
(if (nil? op)
acc
(recur (first next)
(rest next)
(conj acc
(loop [field (first entity)
rem (rest entity)
acc [op]]
(if (nil? field)
acc
(recur (first rem)
(rest rem)
(conj acc
(if-let [[a v] (lookup-ref? field)]
(or
;; The lookup might fail! If so, throw.
(:e (<? (db/<av db a v)))
(raise "No entity found with attr " a " and val " v "."
{:a a :v v}))
field))))))))))))))
(declare <resolve-id-literals) (declare <resolve-id-literals)