Pivot from a jolt reimplementation to running the upstream library verbatim.
Vendors the real clojure/tools/logging.clj; jolt provides the backend and the
host primitives it needs. Language features (broadly useful for real Clojure
libs), all covered in 3-mode conformance + spec suites:
- defmacro: multi-arity dispatch (jolt-q8l) and a docstring + attr-map + params
head (jolt-qnr) — the 4-arity log macro and every level macro need these.
- syntax-quote resolves an alias-qualified symbol to its target ns (jolt-9av),
so a macro template (impl/get-logger) resolves at the use site.
- the ns macro unwraps ^{:map} metadata on the ns name (jolt-8w2 workaround,
matching def/defn/defmacro).
- a namespace object self-evaluates, so ~*ns* can be spliced into a template.
Host shims (ported from / modeled on clojure where applicable):
- clojure.string/trim-newline (ported, CharSequence interop -> count/subs)
- agent/send-off/send (minimal synchronous stubs; jolt has no thread pool/STM)
- clojure.lang.LockingTransaction/isRunning -> false
- a minimal clojure.pprint (pprint/with-pprint-dispatch/code-dispatch, for spy)
- clojure.tools.logging.impl: a jolt stderr LoggerFactory backend (the library's
designed pluggable extension point)
docs/libraries.md lists tools.logging; grammar.ebnf metadata note clarified.
Conformance 355/355 x3 modes; full jpm test gate green.
48 lines
3 KiB
Text
48 lines
3 KiB
Text
# Specification: stateful reference types (atoms, volatiles, delays, promises).
|
|
(use ../support/harness)
|
|
|
|
(defspec "state / atoms"
|
|
["deref @" "0" "(let [a (atom 0)] @a)"]
|
|
["deref fn" "0" "(deref (atom 0))"]
|
|
["reset!" "5" "(let [a (atom 0)] (reset! a 5) @a)"]
|
|
["reset! returns new" "5" "(let [a (atom 0)] (reset! a 5))"]
|
|
["swap!" "1" "(let [a (atom 0)] (swap! a inc) @a)"]
|
|
["swap! with args" "10" "(let [a (atom 1)] (swap! a + 2 3 4) @a)"]
|
|
["swap! returns new" "1" "(let [a (atom 0)] (swap! a inc))"]
|
|
["swap-vals!" "[0 1]" "(let [a (atom 0)] (swap-vals! a inc))"]
|
|
["reset-vals!" "[0 9]" "(let [a (atom 0)] (reset-vals! a 9))"]
|
|
["compare-and-set! ok" "true" "(let [a (atom 0)] (compare-and-set! a 0 1))"]
|
|
["compare-and-set! no" "false" "(let [a (atom 0)] (compare-and-set! a 9 1))"]
|
|
["atom?" "true" "(do (require (quote [clojure.core])) (instance? clojure.lang.Atom (atom 0)))"]
|
|
["atom? predicate" "true" "(atom? (atom 0))"]
|
|
["atom? on non-atom" "false" "(atom? 5)"])
|
|
|
|
(defspec "state / watches & validators"
|
|
["add-watch fires" "1" "(let [a (atom 0) seen (atom 0)] (add-watch a :k (fn [k r o n] (reset! seen 1))) (reset! a 5) @seen)"]
|
|
["remove-watch" "0" "(let [a (atom 0) seen (atom 0)] (add-watch a :k (fn [k r o n] (swap! seen inc))) (remove-watch a :k) (reset! a 5) @seen)"]
|
|
["set-validator! ok" "5" "(let [a (atom 0)] (set-validator! a number?) (reset! a 5) @a)"]
|
|
["set-validator! rejects" :throws "(let [a (atom 0)] (set-validator! a pos?) (reset! a -1))"]
|
|
["get-validator" "true" "(let [a (atom 0)] (set-validator! a number?) (fn? (get-validator a)))"])
|
|
|
|
(defspec "state / volatiles & delays"
|
|
["volatile! deref" "0" "(let [v (volatile! 0)] @v)"]
|
|
["vreset!" "5" "(let [v (volatile! 0)] (vreset! v 5) @v)"]
|
|
["vswap!" "1" "(let [v (volatile! 0)] (vswap! v inc) @v)"]
|
|
["delay not forced" "0" "(let [c (atom 0) d (delay (swap! c inc))] @c)"]
|
|
["delay force once" "1" "(let [c (atom 0) d (delay (swap! c inc))] (force d) (force d) @c)"]
|
|
["delay value" "5" "(let [d (delay 5)] @d)"]
|
|
["realized? before" "false" "(let [d (delay 5)] (realized? d))"]
|
|
["realized? after" "true" "(let [d (delay 5)] (force d) (realized? d))"])
|
|
|
|
(defspec "state / promises"
|
|
["promise deliver" "5" "(let [p (promise)] (deliver p 5) @p)"]
|
|
["promise undelivered" "nil" "(let [p (promise)] @p)"])
|
|
|
|
# Minimal synchronous agent shim (jolt has no thread pool/STM) — enough for
|
|
# libraries that hold an agent without depending on async dispatch.
|
|
(defspec "state / agents (synchronous shim)"
|
|
["agent deref" "0" "(deref (agent 0))"]
|
|
["agent with opts" "0" "(deref (agent 0 :error-mode :continue))"]
|
|
["send-off applies" "5" "(let [a (agent 0)] (send-off a + 5) (deref a))"]
|
|
["send applies" "7" "(let [a (agent 1)] (send a + 6) (deref a))"]
|
|
["agent-error nil" "nil" "(agent-error (agent 0))"])
|