An options map for the resolvers, and sid beside the clip it is in

Finishing the last commit, which traded a simpler definition for noisier call
sites: deleting the arity ladders left `(symbol/resolver sym st pal/index-of
nil nil)` at twenty-odd places, and two trailing nils tell a reader nothing
except to go and count positions.

The ladder was a symptom. The disease is five positional parameters, and the
split that matters is which of them are OPTIONAL:

  store, palette    positional, because neither is optional. A dense channel
                    cannot be read without the store it names — that is the
                    crash two commits ago — and every op carries a colour.
  pose-tracks       one call site, in `clip/resolver`'s own recursion
  source/picture-fps  two call sites

So the last three become one `opts` map, and the common call loses a nil. The
point is not the nil: it is that the sixth option, whenever it arrives, is a
key at one call site rather than a nil at fifty.

`clip/resolver` also had `sid` FOURTH, behind two arguments that say nothing
about which symbol is being resolved. It is second now, beside the clip it is
in: `(clip/resolver c :main store pal/index-of nil)`.

62 call sites rewritten by parsing the forms rather than by regex, because
`clip/resolver`'s arguments move past each other and a regex cannot see that.
An earlier attempt at this dropped `palette` on the floor and still compiled
at 62 sites — it only surfaced as an arity error, so if that had been a
same-arity mistake the tests would have been the last line of defence.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Your Name 2026-09-30 12:21:12 -04:00
parent ee66680a0c
commit 624242b407
20 changed files with 84 additions and 81 deletions

View file

@ -24,7 +24,7 @@
(/ dt n))))
(deftest bench
(let [res (symbol/resolver (clip/symbol @swarm/clip :main) @swarm/store pal/index-of nil nil)
(let [res (symbol/resolver (clip/symbol @swarm/clip :main) @swarm/store pal/index-of nil)
ras (raster/make 320 200)
dest (js/Uint8ClampedArray. (* 320 200 4))
n 120]

View file

@ -34,7 +34,7 @@
(defn- drawn [c path]
(partition 2 (take 6 (array-seq (:pts (first (filter #(= path (:node %))
((clip/resolver c nil pal/index-of :main nil) 16))))))))
((clip/resolver c :main nil pal/index-of nil) 16))))))))
(defn- near? [a b] (every? #(< (js/Math.abs %) 1e-9) (map - (flatten a) (flatten b))))

View file

@ -36,7 +36,7 @@
:channels {[:xform :pos] (ch/framed [120 50])}}}})
(assoc-in [:symbols :sym/test]
(assoc (get-in source [:symbols :main]) :id :sym/test)))
resolve (clip/resolver document nil pal/index-of :main nil)
resolve (clip/resolver document :main nil pal/index-of nil)
at (fn [f] (mapv (juxt :node :cx) (resolve f)))]
(is (empty? (clip/problems document)))
(is (= [[[:left :mark] 110]] (at 1)))
@ -75,9 +75,9 @@
:parent :root :z "a2"
:playback {:tracks {:mouth {0 0, 8 8}}}}}}
:sym/poses symbol}}
resolve (clip/resolver document {"sizes" {:data values}} pal/index-of :main nil)
low-resolve (clip/resolver document {"sizes" {:data values}}
pal/index-of :main {:picture-fps 8})
store {"sizes" {:data values}}
resolve (clip/resolver document :main store pal/index-of nil)
low-resolve (clip/resolver document :main store pal/index-of {:picture-fps 8})
at (fn [f] (into {} (map (fn [op] [(:node op) op])) (resolve f)))
low-at (fn [f] (into {} (map (fn [op] [(:node op) op])) (low-resolve f)))]
(is (empty? (clip/problems document)))
@ -98,14 +98,12 @@
"an explicit cut occurs at its exact local frame, even off the picture grid")
(is (= 8 (:cx (get (low-at 8) [:first :eye])))
"authored position ignores the picture grid")
(let [sym (get-in document [:symbols :sym/poses])
opts {:source-fps 30 :picture-fps 8}]
(let [sym (get-in document [:symbols :sym/poses])
opts {:source-fps 30 :picture-fps 8 :pose-tracks {:mouth {0 0, 8 20}}}]
(is (= (mapv #(select-keys % [:node :cx :size])
(symbol/eval-frame sym 8 {"sizes" {:data values}}
pal/index-of {:mouth {0 0, 8 20}} opts))
(symbol/eval-frame sym 8 store pal/index-of opts))
(mapv #(select-keys % [:node :cx :size])
((symbol/resolver sym {"sizes" {:data values}}
pal/index-of {:mouth {0 0, 8 20}} opts) 8)))
((symbol/resolver sym store pal/index-of opts) 8)))
"pure evaluation and playback apply the same pose choice"))))
(deftest stage-pose-edits-preserve-earlier-motion-and-survive-save

View file

@ -40,7 +40,7 @@
{:keys [sid frame pts]} (nest/drawn-inside c nil :main [u] 16 drawn)
c (paint/new-shape c sid :shape frame pts :brow)
[op] (filter #(= [u :shape] (:node %))
((clip/resolver c nil pal/index-of :main nil) 16))]
((clip/resolver c :main nil pal/index-of nil) 16))]
(is (= :box sid))
(is (= 6 frame) "frame 16 of main is frame 6 of an instance placed at 10")
(is (every? #(< (js/Math.abs %) 1e-9)
@ -64,7 +64,7 @@
(turn :mid v [5 -3] 0.3 1.5)
(paint/new-shape :box :shape 4 [0 0 10 0 5 10] :brow))
draw #(take 6 (array-seq (:pts (first (filter (fn [op] (= [u v :shape] (:node op)))
((clip/resolver % nil pal/index-of :main nil) 16))))))
((clip/resolver % :main nil pal/index-of nil) 16))))))
{:keys [frame matrix time]} (nest/inside c nil :main [u v :shape] 16)
out (js/Float64Array. 2)
seen (mapcat (fn [[x y]] (vec (array-seq (node/apply-pt! out 0 matrix x y))))
@ -105,7 +105,7 @@
"What `sid` draws at each of `fs`, without the node paths a move changes:
per frame, the sorted marks with their points rounded to a thousandth."
[c sid fs]
(let [resolve (clip/resolver c nil pal/index-of sid nil)
(let [resolve (clip/resolver c sid nil pal/index-of nil)
round #(/ (js/Math.round (* 1000 %)) 1000)]
(mapv (fn [f]
(sort-by str (map (fn [op]
@ -251,7 +251,7 @@
(is (= [0 8] (:span heard))
"own frames 0-8: it starts on inner's 2 and inner ends on 10")
(is (= [7 15] (node/placed-span heard)) "inner starts on 5 of outer")
(is (empty? ((clip/resolver c nil pal/index-of :inner nil) 3))
(is (empty? ((clip/resolver c :inner nil pal/index-of nil) 3))
"and it draws nothing")
(is (= c (clip/place-sound c :inner {:sound "tone"} "tone.mp3" 40 1 10 (random-uuid)))
"nor lands past the end of its symbol")

View file

@ -31,5 +31,5 @@
(is (empty? (channel/problems mixed)))
;; The demo's root is exposed on 2s. Paint at frame 3 must still appear at 3.
(is (some #(= :paint-test (:node %))
(symbol/eval-frame (get-in c2 [:symbols :main]) 3 nil pal/index-of nil nil)))
(symbol/eval-frame (get-in c2 [:symbols :main]) 3 nil pal/index-of nil)))
(is (= mixed-clip (leaf/clip :c1 (leaf/leaves :c1 mixed-clip))))))

View file

@ -148,7 +148,7 @@
;; frame rather than hidden, and its partner is not.
(let [back (wired :c1 @gappy)
drawn (into #{} (map :node)
((symbol/resolver (face-symbol (:clip back)) (:store back) pal/index-of nil nil) 12))]
((symbol/resolver (face-symbol (:clip back)) (:store back) pal/index-of nil) 12))]
(is (not (contains? drawn :eye-r)))
(is (contains? drawn :eye-l))
(is (contains? drawn :mouth))))

View file

@ -27,7 +27,7 @@
{:nodes (into {} (map (juxt :id identity)) nodes)})
(defn- ids-at [scene f]
(mapv :node (symbol/eval-frame scene f nil pal/index-of nil nil)))
(mapv :node (symbol/eval-frame scene f nil pal/index-of nil)))
(def ^:private pts-of ops/points)
@ -70,9 +70,9 @@
(is (identical? (get-in s [:nodes :b]) (get-in s' [:nodes :b]))
"and so is the new one")
(is (= [[0 0] [10 0] [10 10]]
(pts-of (first (filter #(= :c (:node %)) (symbol/eval-frame s 0 nil pal/index-of nil nil))))))
(pts-of (first (filter #(= :c (:node %)) (symbol/eval-frame s 0 nil pal/index-of nil))))))
(is (= [[100 0] [110 0] [110 10]]
(pts-of (first (filter #(= :c (:node %)) (symbol/eval-frame s' 0 nil pal/index-of nil nil))))))))
(pts-of (first (filter #(= :c (:node %)) (symbol/eval-frame s' 0 nil pal/index-of nil))))))))
;; ---- draw order ----
@ -129,7 +129,7 @@
:channels {[:xform :pos] (ch/framed [100 50])
[:xform :scale] (ch/framed [2 2])}}
(poly :p :g "a1" [0 0 10 0 10 10 0 10] :skin-base))
op (first (symbol/eval-frame s 0 nil pal/index-of nil nil))]
op (first (symbol/eval-frame s 0 nil pal/index-of nil))]
(is (= [[100 50] [120 50] [120 70] [100 70]] (pts-of op)))))
(deftest a-keyed-group-position-moves-its-children-and-holds-between-keys
@ -139,7 +139,7 @@
:channels {[:xform :pos]
(ch/keyed {0 [0 0], 4 [10 0], 8 [10 10], 12 [0 10]} :hold)}}
(poly :p :g "a1" [0 0 2 0 2 2] :skin-base))
at #(first (pts-of (first (symbol/eval-frame s % nil pal/index-of nil nil))))]
at #(first (pts-of (first (symbol/eval-frame s % nil pal/index-of nil))))]
(is (= [0 0] (at 0)))
(is (= [0 0] (at 3)) "held")
(is (= [10 0] (at 4)))
@ -156,7 +156,7 @@
{:id :g :kind :group :parent :root :z "a1"
:channels {[:xform :pos] (ch/keyed (into {} (map (juxt identity #(vector % 0))) (range 12)) :hold)}}
(poly :p :g "a1" [0 0 1 0 1 1] :skin-base))
x-at #(first (first (pts-of (first (symbol/eval-frame s % nil pal/index-of nil nil)))))]
x-at #(first (first (pts-of (first (symbol/eval-frame s % nil pal/index-of nil)))))]
(is (= [0 0 0 3 3 3 6 6 6 9 9 9] (mapv x-at (range 12)))))
(testing "and a node may set its own grid, which the model permits deliberately"
@ -164,7 +164,7 @@
{:id :g :kind :group :parent :root :z "a1" :time {:mode :map :expose 4}
:channels {[:xform :pos] (ch/keyed (into {} (map (juxt identity #(vector % 0))) (range 12)) :hold)}}
(poly :p :g "a1" [0 0 1 0 1 1] :skin-base))
x-at #(first (first (pts-of (first (symbol/eval-frame s % nil pal/index-of nil nil)))))]
x-at #(first (first (pts-of (first (symbol/eval-frame s % nil pal/index-of nil)))))]
(is (= [0 0 0 0 4 4 4 4 8 8 8 8] (mapv x-at (range 12)))))))
(deftest offset-is-per-node-which-is-the-entire-point-of-mouth-lead
@ -178,7 +178,7 @@
{:id :mouth :kind :group :parent :root :z "a2" :time {:mode :map :offset 2}
:channels {[:xform :pos] (ch/keyed keys :hold)}}
(poly :mouth-p :mouth "a1" [0 0 1 0 1 1] :mouth-dark))
x-of (fn [f id] (->> (symbol/eval-frame s f nil pal/index-of nil nil)
x-of (fn [f id] (->> (symbol/eval-frame s f nil pal/index-of nil)
(filter #(= id (:node %))) first pts-of first first))]
(is (= [0 1 2 3] (mapv #(x-of % :plate-p) (range 4))))
(is (= [2 3 4 5] (mapv #(x-of % :mouth-p) (range 4))) "the mouth reads ahead")))
@ -221,11 +221,11 @@
:dense {:store "pts" :offset 0 :stride 6 :frames 2}}
[:style :color] (ch/framed :mouth-dark)}}
(poly :teeth :m "a2" [0 0 1 0 1 1] :teeth))]
(is (= [:child] (mapv :node (symbol/eval-frame absent-pos 0 store pal/index-of nil nil))))
(is (= [] (mapv :node (symbol/eval-frame absent-pos 1 store pal/index-of nil nil)))
(is (= [:child] (mapv :node (symbol/eval-frame absent-pos 0 store pal/index-of nil))))
(is (= [] (mapv :node (symbol/eval-frame absent-pos 1 store pal/index-of nil)))
"an absent transform gives the children nowhere to be")
(is (= [:m :teeth] (mapv :node (symbol/eval-frame absent-pts 0 store pal/index-of nil nil))))
(is (= [:teeth] (mapv :node (symbol/eval-frame absent-pts 1 store pal/index-of nil nil)))
(is (= [:m :teeth] (mapv :node (symbol/eval-frame absent-pts 0 store pal/index-of nil))))
(is (= [:teeth] (mapv :node (symbol/eval-frame absent-pts 1 store pal/index-of nil)))
"an absent outline removes only itself")))
;; ---- stencils ----
@ -239,7 +239,7 @@
{:id :iris :kind :disc :parent :root :stencil :sclera :z "a2"
:channels {[:geom :radius] (ch/framed 4)
[:style :color] (ch/framed :iris)}})
ops (symbol/eval-frame s 0 nil pal/index-of nil nil)]
ops (symbol/eval-frame s 0 nil pal/index-of nil)]
(is (= [:sclera :iris] (mapv :node ops)))
(is (= (:eye-white pal/index-of) (:stencil (second ops))))))
@ -266,7 +266,7 @@
:channels {[:geom :radius] (ch/framed 3) [:style :color] (ch/framed :iris)}}
{:id :r :kind :rect :parent :g :z "a2"
:channels {[:geom :size] (ch/framed 1.7) [:style :color] (ch/framed :pupil)}})
[d r] (symbol/eval-frame s 0 nil pal/index-of nil nil)]
[d r] (symbol/eval-frame s 0 nil pal/index-of nil)]
(is (= [50 60 6] [(:cx d) (:cy d) (:r d)]))
(is (= 3.4 (:size r)))))
@ -291,7 +291,7 @@
(deftest the-resolver-reuses-one-buffer-per-node
;; At 30fps per-frame allocation is the only thing that will make this stutter,
;; and fixed topology is what makes the buffer size knowable at all.
(let [res (symbol/resolver demo/main nil pal/index-of nil nil)
(let [res (symbol/resolver demo/main nil pal/index-of nil)
buf-of (fn [f id] (->> (res f) (filter #(= id (:node %))) first :pts))]
(is (identical? (buf-of 0 :card) (buf-of 30 :card)))))
@ -308,15 +308,15 @@
;; The mistake this split makes easy: both are maps with an :id, and the wrong
;; one resolves to no ops rather than to an error.
(is (thrown-with-msg? ExceptionInfo #"not a symbol"
(symbol/resolver demo/clip nil pal/index-of nil nil)))
(symbol/resolver demo/clip nil pal/index-of nil)))
(is (thrown-with-msg? ExceptionInfo #"not a symbol"
(symbol/eval-frame demo/clip 0 nil pal/index-of nil nil)))))
(symbol/eval-frame demo/clip 0 nil pal/index-of nil)))))
(deftest the-hand-written-clip-renders-and-moves
;; port-plan step 2's done condition, as an assertion rather than a look: the
;; scene rasterises, it writes only palette indices, and the pixels are not the
;; same on every frame.
(let [res (symbol/resolver demo/main nil pal/index-of nil nil)
(let [res (symbol/resolver demo/main nil pal/index-of nil)
render (fn [f]
(let [r (raster/make (:width demo/clip) (:height demo/clip))]
(raster/clear! r (:bg pal/index-of))
@ -334,7 +334,7 @@
;; Exposure 2 on the clip root, inherited, so odd frames are identical to the
;; even frame before them. If this fails, exposure is being applied somewhere
;; other than the frame the channels are sampled at.
(let [res (symbol/resolver demo/main nil pal/index-of nil nil)
(let [res (symbol/resolver demo/main nil pal/index-of nil)
render (fn [f]
(let [r (raster/make (:width demo/clip) (:height demo/clip))]
(raster/clear! r (:bg pal/index-of))
@ -351,7 +351,7 @@
(deftest the-hand-written-clip-keeps-the-iris-and-pupil-inside-the-card
;; The stencil chain, on real pixels: the iris is clipped by the card and the
;; pupil by the iris, and neither is expressed anywhere as a chain.
(let [res (symbol/resolver demo/main nil pal/index-of nil nil)]
(let [res (symbol/resolver demo/main nil pal/index-of nil)]
(doseq [f (range 0 demo/frames 4)]
(let [before (raster/make (:width demo/clip) (:height demo/clip))
after (raster/make (:width demo/clip) (:height demo/clip))
@ -384,9 +384,9 @@
(poly :p :root "a1" [0 0 10 0 10 10] :skin-base))
day {:skin-base 1}
night {:skin-base 17}]
(is (= 1 (:color (first (symbol/eval-frame s 0 nil day nil nil)))))
(is (= 17 (:color (first (symbol/eval-frame s 0 nil night nil nil)))))
(is (= 17 (:color (first ((symbol/resolver s nil night nil nil) 0))))
(is (= 1 (:color (first (symbol/eval-frame s 0 nil day nil)))))
(is (= 17 (:color (first (symbol/eval-frame s 0 nil night nil)))))
(is (= 17 (:color (first ((symbol/resolver s nil night nil) 0))))
"and the playback path agrees")))
(deftest a-tone-the-ramp-does-not-define-is-loudly-wrong
@ -394,7 +394,7 @@
;; authored data and should be impossible to miss.
(let [s (sc {:id :root :kind :group :z "a1"}
(poly :p :root "a1" [0 0 10 0 10 10] :skin-base))]
(is (= 255 (:color (first (symbol/eval-frame s 0 nil {} nil nil)))))))
(is (= 255 (:color (first (symbol/eval-frame s 0 nil {} nil)))))))
(deftest partitioning-the-index-space-stops-two-palettes-colliding-on-a-stencil
;; A stencil is a colour key, so two nodes sharing a tone share a stencil —
@ -407,6 +407,6 @@
[:style :color] (ch/framed :iris)}})
;; :night's tones sit above :day's in one concatenated space
night {:eye-white 14 :iris 15}
ops (symbol/eval-frame s 0 nil night nil nil)]
ops (symbol/eval-frame s 0 nil night nil)]
(is (= 14 (:stencil (second ops)))
"the stencil resolves to the index the stencil node actually drew in")))

View file

@ -52,7 +52,7 @@
(defn- photo-at
"The photo matrix of face-1 alone at frame `f`, the still being 1000px tall."
[c f]
(let [r (symbol/resolver (clip/symbol c :face-1) @store pal/index-of nil nil)
(let [r (symbol/resolver (clip/symbol c :face-1) @store pal/index-of nil)
h (head c)]
(r f)
(vec (array-seq (trace/photo-matrix (symbol/world-of r :head) h @store
@ -111,7 +111,7 @@
;; The same answer as `nest/placement`, which walks and resolves the path all
;; over again — the resolver has it already, from drawing the frame.
(let [c (wrapped)
r (clip/resolver c @store pal/index-of :wrap nil)
r (clip/resolver c :wrap @store pal/index-of nil)
path [:m :face-1 :head]]
(doseq [f [0 17 60]]
(r f)

View file

@ -59,7 +59,7 @@
(is (not (ch/nothing? (sample :eye-l f))))
(is (not (ch/nothing? (sample :mouth f)))))
(let [drawn (into #{} (map :node)
((symbol/resolver (clip/symbol clip :face-1) store pal/index-of nil nil) 11))]
((symbol/resolver (clip/symbol clip :face-1) store pal/index-of nil) 11))]
(is (not (contains? drawn :eye-r)))
(is (not (contains? drawn :iris-r)))
(is (contains? drawn :eye-l))

View file

@ -56,7 +56,7 @@
(defn- ops-at
"Ops for one frame of a TIMELINE."
[sym f]
((symbol/resolver sym @store pal/index-of nil nil) f))
((symbol/resolver sym @store pal/index-of nil) f))
(defn- render
"One frame of a CLIP into a byte buffer. The stage's size comes off the clip and
@ -64,7 +64,7 @@
[c f]
(let [r (raster/make (:width c) (:height c))]
(raster/clear! r (get pal/index-of :bg))
(raster/draw-ops! r ((clip/resolver c @store pal/index-of :main nil) f))
(raster/draw-ops! r ((clip/resolver c :main @store pal/index-of nil) f))
(vec (array-seq (:buf r)))))
(defn- drawn
@ -195,7 +195,7 @@
;; checking arithmetic against itself; this checks `node/local!`, `node/world!`
;; and `emit` as well.
(let [c (freeze/head-mode {} @frozen)
res (clip/resolver c @store pal/index-of :main nil)
res (clip/resolver c :main @store pal/index-of nil)
k (first (:value (chan :face [:xform :scale])))
anc (:value (chan :face [:xform :anchor]))
pos (:value (chan :face [:xform :pos]))
@ -249,14 +249,11 @@
"the trace survives the document round trip")))
(deftest trace-keys-hold-the-whole-measured-transform
(let [free (symbol/resolver (face-symbol (freeze/head-mode {} @frozen))
@store pal/index-of nil nil)
(let [free (symbol/resolver (face-symbol (freeze/head-mode {} @frozen)) @store pal/index-of nil)
held (symbol/resolver (face-symbol
(freeze/head-mode {:trace {:origin :keys :frames [12 88]}} @frozen))
@store pal/index-of nil nil)
(freeze/head-mode {:trace {:origin :keys :frames [12 88]}} @frozen)) @store pal/index-of nil)
start (symbol/resolver (face-symbol
(freeze/head-mode {:trace {:origin :start :frames [12 88]}} @frozen))
@store pal/index-of nil nil)
(freeze/head-mode {:trace {:origin :start :frames [12 88]}} @frozen)) @store pal/index-of nil)
world (fn [resolver frame]
(resolver frame)
(vec (array-seq (symbol/world-of resolver :head))))]
@ -511,7 +508,7 @@
(is (not (ch/nothing? (at :eye-r 60))))
(is (not (ch/nothing? (at :eye-l 50))))
(is (not (ch/nothing? (at :mouth 50))))
(let [drawn-nodes (into #{} (map :node) ((symbol/resolver sym (:store c) pal/index-of nil nil) 50))]
(let [drawn-nodes (into #{} (map :node) ((symbol/resolver sym (:store c) pal/index-of nil) 50))]
(is (not (contains? drawn-nodes :eye-r)))
(is (contains? drawn-nodes :eye-l))
(is (contains? drawn-nodes :mouth)))
@ -586,7 +583,7 @@
;; Hoisted: the resolver caches its order and reuses its buffers, so the
;; node ids come out before the next frame is asked for.
nodes-at (fn [c]
(let [r (symbol/resolver (face-symbol (:clip c)) (:store c) pal/index-of nil nil)]
(let [r (symbol/resolver (face-symbol (:clip c)) (:store c) pal/index-of nil)]
(fn [f] (into #{} (map :node) (r f)))))
ref-at (nodes-at ref)
occ-at (nodes-at occ)
@ -623,7 +620,7 @@
c (freeze/clip (assoc take/params :name "gappy")
{:face-1 (assoc @take/measured :detected det)})
sym (face-symbol (:clip c))
res (symbol/resolver sym (:store c) pal/index-of nil nil)]
res (symbol/resolver sym (:store c) pal/index-of nil)]
(doseq [f [39 40 50 59 60]]
(let [ops (res f)]
(if (contains? gap f)
@ -682,7 +679,7 @@
shot (fn [f]
(let [r (raster/make W H)
mouth (filter #(= [:face-1 :mouth] (:node %))
((clip/resolver locked @store pal/index-of :main nil) f))]
((clip/resolver locked :main @store pal/index-of nil) f))]
(raster/clear! r (get pal/index-of :bg))
(raster/draw-ops! r mouth)
(vec (array-seq (:buf r)))))

View file

@ -35,7 +35,7 @@
(defn channel [entry subject node path]
(get-in entry [:clip :symbols subject :nodes node :channels path]))
(defn snapshot [c store f] (ops/snapshot ((clip/resolver c store pal/index-of :main nil) f)))
(defn snapshot [c store f] (ops/snapshot ((clip/resolver c :main store pal/index-of nil) f)))
(defn by-node [c store f] (into {} (map (juxt :node identity)) (snapshot c store f)))
(deftest subjects-share-local-names-without-sharing-blocks
@ -178,8 +178,8 @@
(merge (dissoc (:nodes (clip/symbol clip :main)) :face-1)
(assoc-in (get-in clip [:symbols :face-1 :nodes])
[:head :parent] :face)))
nested (clip/resolver clip store pal/index-of :main nil)
reference (clip/resolver flat store pal/index-of :main nil)]
nested (clip/resolver clip :main store pal/index-of nil)
reference (clip/resolver flat :main store pal/index-of nil)]
(doseq [f [0 1 7 20 39]]
(let [a (ops/snapshot (nested f)) b (ops/snapshot (reference f))]
(is (= (mapv (comp second :node) a) (mapv :node b)))

View file

@ -52,11 +52,11 @@
"(fn [f] -> snapshot) through `eval-frame`, the specification."
([sym store] (specified sym store pal/index-of))
([sym store palette]
(fn [f] (snapshot (symbol/eval-frame sym f store palette nil nil)))))
(fn [f] (snapshot (symbol/eval-frame sym f store palette nil)))))
(defn resolved
"(fn [f] -> snapshot) through `resolver`, the playback path."
([sym store] (resolved sym store pal/index-of))
([sym store palette]
(let [res (symbol/resolver sym store palette nil nil)]
(let [res (symbol/resolver sym store palette nil)]
(fn [f] (snapshot (res f))))))