;;;; An aggregate whose value reads the place it is assigned to sees the old ;;;; value of that place, in every field. ;;;; ;;;; (set p (P {.a (.b p) .b (.a p)})) swaps the two fields. It does only if ;;;; the whole right-hand side is read before any of it is stored. A backend ;;;; that builds the struct straight into [p] writes [.a] first, and the read ;;;; of [(.a p)] for [.b] then sees the new value: the answer comes back 2 2 ;;;; rather than 2 1. ;;;; ;;;; Each row is a different destination: a global, a field of a global, a ;;;; local, a field of a local, a place behind a pointer, a variable read ;;;; through a pointer that points at it, and a local rebound inside a loop ;;;; whose previous turn the new value reads. The last row reads a different ;;;; variable, which is the case still built in place. (defstruct P [a i32 b i32]) (defstruct Q [tag i32 inner P]) (defonce g P (P {.a 1 .b 2})) (defonce gq Q (Q {.tag 0 .inner (P {.a 1 .b 2})})) (defn show [p P] () (print (.a p)) (print " ") (print (.b p)) (print "\n")) (defn main [] () ;; A global. (set g (P {.a (.b g) .b (.a g)})) (show g) ;; A field of a global. (set (.inner gq) (P {.a (.b (.inner gq)) .b (.a (.inner gq))})) (show (.inner gq)) (let [p (P {.a 1 .b 2}) q (Q {.tag 0 .inner (P {.a 1 .b 2})}) r (P {.a 1 .b 2}) s (P {.a 1 .b 2}) t (P {.a 1 .b 2}) other (P {.a 3 .b 4})] ;; A local. (set p (P {.a (.b p) .b (.a p)})) (show p) ;; A field of a local. (set (.inner q) (P {.a (.b (.inner q)) .b (.a (.inner q))})) (show (.inner q)) ;; A place behind a pointer, reading the variable it points at. (let [pr (addr r)] (set (deref pr) (P {.a (.b r) .b (.a r)})) (show r)) ;; A variable, reading itself through a pointer. (let [ps (addr s)] (set s (P {.a (.b (deref ps)) .b (.a (deref ps))})) (show s)) ;; A local rebound in a loop, reading its own previous turn. (let [pt (addr t) i 0] (while (< i 2) (let [u (P {.a (.b (deref pt)) .b (.a (deref pt))})] (show u) (set pt (addr u))) (set i (+ i 1)))) ;; No self-read. (set p (P {.a (.b other) .b (.a other)})) (show p)))