core: move binding macro to overlay
Phase 3 batch 6 (jolt-1j0). binding installs an array-map var->value thread frame and restores it on exit via try/finally. Dynamic rebinding is seen by called fns. This completes the cleanly-portable safe macros (19 total). conformance 228/228 x3, full suite green.
This commit is contained in:
parent
394bbe07c3
commit
3dafa60e65
3 changed files with 14 additions and 28 deletions
|
|
@ -107,6 +107,15 @@
|
|||
[] fnspecs)]
|
||||
`(let* [~@binds] ~@body)))
|
||||
|
||||
;; Dynamic binding: install a thread-binding frame of var->value (array-map keeps
|
||||
;; var-get happy, unlike a phm), restore on exit.
|
||||
(defmacro binding [bindings & body]
|
||||
(let [pairs (reduce (fn [acc p] (conj (conj acc `(var ~(first p))) (second p)))
|
||||
[] (partition 2 bindings))]
|
||||
`(let* [frame# (array-map ~@pairs)]
|
||||
(push-thread-bindings frame#)
|
||||
(try (do ~@body) (finally (pop-thread-bindings))))))
|
||||
|
||||
;; condp: clauses are test-expr result-expr, or test-expr :>> result-fn (calls
|
||||
;; result-fn on the truthy (pred test-expr value)); a lone trailing expr is the
|
||||
;; default. The recursive emit builds a nested if chain.
|
||||
|
|
|
|||
|
|
@ -2264,31 +2264,6 @@
|
|||
|
||||
(defn core-intern [ns-name sym-name val] val)
|
||||
|
||||
(defn core-binding
|
||||
"Macro: (binding [var val ...] body...)
|
||||
Uses array-map (plain struct) to store binding frame
|
||||
to avoid PHM get() incompatibility with var-get."
|
||||
[bindings & body]
|
||||
(def frame-pairs @[])
|
||||
(var i 0)
|
||||
(let [n (length bindings)]
|
||||
(while (< i n)
|
||||
(array/push frame-pairs
|
||||
@[{:jolt/type :symbol :ns nil :name "var"} (in bindings i)])
|
||||
(array/push frame-pairs (in bindings (+ i 1)))
|
||||
(+= i 2)))
|
||||
(def hm-form (array/insert frame-pairs 0
|
||||
{:jolt/type :symbol :ns nil :name "array-map"}))
|
||||
@[{:jolt/type :symbol :ns nil :name "let*"}
|
||||
[{:jolt/type :symbol :ns nil :name "frame"} hm-form]
|
||||
@[{:jolt/type :symbol :ns nil :name "push-thread-bindings"}
|
||||
{:jolt/type :symbol :ns nil :name "frame"}]
|
||||
@[{:jolt/type :symbol :ns nil :name "try"}
|
||||
@[{:jolt/type :symbol :ns nil :name "do"} ;body]
|
||||
@[{:jolt/type :symbol :ns nil :name "finally"}
|
||||
@[{:jolt/type :symbol :ns nil :name "pop-thread-bindings"}]]]])
|
||||
|
||||
|
||||
(defn- defn->def
|
||||
"Shared expansion for defn/defn-: (name doc-string? attr-map? params body...)
|
||||
or (name doc-string? attr-map? ([params] body)... attr-map?) -> (def name (fn* ...))."
|
||||
|
|
@ -3695,7 +3670,6 @@
|
|||
"alter-meta!" core-alter-meta!
|
||||
"reset-meta!" core-reset-meta!
|
||||
"intern" core-intern
|
||||
"binding" core-binding
|
||||
"push-thread-bindings" core-push-thread-bindings
|
||||
"pop-thread-bindings" core-pop-thread-bindings
|
||||
# Dynamic vars — stubs for SCI bootstrap
|
||||
|
|
@ -3710,7 +3684,7 @@
|
|||
(defn core-macro-names
|
||||
"Set of core binding names that are macros."
|
||||
[]
|
||||
@{"and" true "or" true "cond" true "case" true "for" true "when" true "when-not" true "when-let" true "defn" true "defn-" true "declare" true "fn" true "let" true "loop" true "defrecord" true "defprotocol" true "extend-type" true "extend-protocol" true "extend" true "reify" true "proxy" true "definterface" true "binding" true "lazy-seq" true "lazy-cat" true "cond->" true "->" true "->>" true "doseq" true})
|
||||
@{"and" true "or" true "cond" true "case" true "for" true "when" true "when-not" true "when-let" true "defn" true "defn-" true "declare" true "fn" true "let" true "loop" true "defrecord" true "defprotocol" true "extend-type" true "extend-protocol" true "extend" true "reify" true "proxy" true "definterface" true "lazy-seq" true "lazy-cat" true "cond->" true "->" true "->>" true "doseq" true})
|
||||
|
||||
(def init-core!
|
||||
(fn [& args]
|
||||
|
|
|
|||
|
|
@ -68,4 +68,7 @@
|
|||
["condp match" ":two" "(condp = 2 1 :one 2 :two 3 :three)"]
|
||||
["condp default" ":else" "(condp = 9 1 :one 2 :two :else)"]
|
||||
["condp :>> form" "\"got 2\"" "(condp some [1 2 3] #{0 9} :>> (fn [x] (str \"got \" x)) #{2 6} :>> (fn [x] (str \"got \" x)))"]
|
||||
["condp no match" ":threw" "(try (condp = 9 1 :one) (catch :default e :threw))"])
|
||||
["condp no match" ":threw" "(try (condp = 9 1 :one) (catch :default e :threw))"]
|
||||
["binding rebinds" "99" "(do (def ^:dynamic *bx* 10) (binding [*bx* 99] *bx*))"]
|
||||
["binding restores" "10" "(do (def ^:dynamic *by* 10) (binding [*by* 99] *by*) *by*)"]
|
||||
["binding seen by fn" "7" "(do (def ^:dynamic *bz* 0) (defn rdz [] *bz*) (binding [*bz* 7] (rdz)))"])
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue