mutable deftype fields: (set! field val) in a method
deftype fields tagged ^:unsynchronized-mutable / ^:volatile-mutable can now be reassigned in place from a method, as on the JVM. A jrec stores fields as cons cells, so a new jolt-set-field! mutates the pair with set-cdr!. The deftype macro rewrites (set! mutable-field v) in a method body to (set! (.-field inst) v), and the analyzer compiles a (set! (.-field obj) v) target to jolt-set-field! — so both the rewritten symbol form and an explicit interop (set! (.-root this) v) go through one path. Field reads remain a snapshot at method entry, which is correct for the universal read-then-set pattern (a repeated set! of the same field in one call would read the entry value). Closes the set!-of-local SCI failures: SCI load 202 -> 205/218.
This commit is contained in:
parent
b9ab750983
commit
424ce75cf6
9 changed files with 416 additions and 371 deletions
|
|
@ -307,6 +307,21 @@
|
|||
(:volatile-mutable mt)))
|
||||
true false)))
|
||||
fields)
|
||||
;; mutable field symbols (^:unsynchronized-mutable / ^:volatile-mutable):
|
||||
;; (set! field v) in a method body lowers to (set! (.-field inst) v), the
|
||||
;; in-place field write the analyzer compiles to jolt-set-field! (jolt-c3q).
|
||||
mutable-syms (map first (filter second (map vector fields field-muts)))
|
||||
mutable? (fn [s] (boolean (some (fn [m] (= m s)) mutable-syms)))
|
||||
rewrite-set (fn rw [inst form]
|
||||
(cond
|
||||
(and (seq? form) (seq form) (symbol? (first form))
|
||||
(= "set!" (name (first form)))
|
||||
(symbol? (second form)) (mutable? (second form)))
|
||||
(list 'set! (list (symbol (str ".-" (name (second form)))) inst)
|
||||
(rw inst (nth form 2)))
|
||||
(seq? form) (map (fn [x] (rw inst x)) form)
|
||||
(vector? form) (mapv (fn [x] (rw inst x)) form)
|
||||
:else form))
|
||||
;; inline impls register for dispatch but are NOT extenders of the
|
||||
;; protocol (the JVM compiles them into the class) — register-inline-method,
|
||||
;; not extend-type.
|
||||
|
|
@ -315,9 +330,10 @@
|
|||
~@(map (fn [spec]
|
||||
(let [argv (nth spec 1)
|
||||
inst (first argv)
|
||||
binds (vec (mapcat (fn [f] [f `(get ~inst ~(keyword (name f)))]) fields))]
|
||||
binds (vec (mapcat (fn [f] [f `(get ~inst ~(keyword (name f)))]) fields))
|
||||
mbody (map (fn [bf] (rewrite-set inst bf)) (drop 2 spec))]
|
||||
`(register-inline-method ~(name tname) ~(name proto) ~(name (first spec))
|
||||
(fn ~argv (let [~@binds] ~@(drop 2 spec))))))
|
||||
(fn ~argv (let [~@binds] ~@mbody)))))
|
||||
specs)))]
|
||||
`(do
|
||||
(def ~tname (make-deftype-ctor (quote ~tname) [~@field-kws] [~@field-tags] [~@field-muts]))
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue