spec: rows for every untested var (131 -> 0); the probes found five real bugs
test/spec/untested-vars-spec.janet adds 143 rows asserting jolt's documented behavior for the whole implemented-untested category — primed arithmetic, the array/aset/coercion stubs, unchecked-*, the chunk family, JVM-shape stubs (class/bean/proxy/memfn as resolve-only or :throws), ns/REPL machinery, and the misc seqs. tools/spec_coverage.py now checks each var as a whole TOKEN in the test sources (call-position-only matching missed *1, +', ., .., /, and bare transducer refs like cat). Writing rows from probed truth surfaced five real bugs, all fixed: - comp with a jolt-IFn stage silently returned nil ((comp seq :content)) — raw Janet keyword application is not jolt invoke. comp is the canonical overlay defn now (fixed-arity composed fn, so the hot 1-arg path is two direct calls); the seed keeps a private td-comp only for the transducer machinery. hof bench +9% vs native, the price of correct IFn dispatch. - extend (the fn) was a nil-expanding stub MACRO shadowing any definition; it's a real fn over register-method now, and extends? (a constant-false stub) is real over extenders - (.. x f g) hit the 'ClassName.' constructor branch (a name ending in a dot) and died; .. is the canonical threading macro now - aclone errored on pvecs; ns-interns/ns-imports returned live host tables that count/seq reject (now structs) Thread/sleep + Thread/yield land as Thread statics beside Math/: sleep parks the WORKER's own event loop (each future thread has one), which makes timed deref provably fire — futures-spec gains the timeout-fires, sleep-in-body, and timed-out-future-still-completes rows. The futures impl itself already ran on real OS threads (ev/spawn-thread + marshalled results); jolt-ejx was stale. Dashboard: implemented+tested 433 -> 564 of 694; implemented-untested and missing-portable are both EMPTY. Gate: jpm exit 0, all tests passed.
This commit is contained in:
parent
daab2ab4cc
commit
d06b3fe636
8 changed files with 414 additions and 151 deletions
|
|
@ -821,3 +821,20 @@
|
|||
;; The raw Inst protocol method; jolt insts have one representation, so it is
|
||||
;; inst-ms itself.
|
||||
(defn inst-ms* [i] (inst-ms i))
|
||||
|
||||
;; Canonical comp — here rather than the seed so each stage is invoked with
|
||||
;; jolt call semantics: (comp seq :content) works because the keyword stage
|
||||
;; goes through IFn dispatch (raw Janet keyword application does not).
|
||||
(defn comp
|
||||
([] identity)
|
||||
([f] f)
|
||||
([f g]
|
||||
;; fixed arities first (Clojure's own shape): the 1-arg path — every
|
||||
;; map/filter stage — is two direct calls, no rest-seq, no apply.
|
||||
(fn
|
||||
([] (f (g)))
|
||||
([x] (f (g x)))
|
||||
([x y] (f (g x y)))
|
||||
([x y z] (f (g x y z)))
|
||||
([x y z & args] (f (apply g x y z args)))))
|
||||
([f g & fs] (reduce comp (comp f g) fs)))
|
||||
|
|
|
|||
|
|
@ -295,6 +295,43 @@
|
|||
(protocol-dispatch ~(name pname) ~(name (first sig)) this# rest#))))
|
||||
sigs))))
|
||||
|
||||
;; Member threading: (.. x f g) => (. (. x f) g); a parenthesized member
|
||||
;; carries args. Canonical Clojure shape, single-arity defmacro.
|
||||
(defmacro .. [x form & more]
|
||||
(let [step (if (seq? form)
|
||||
`(. ~x ~(first form) ~@(rest form))
|
||||
`(. ~x ~form))]
|
||||
(if (seq more)
|
||||
`(.. ~step ~@more)
|
||||
step)))
|
||||
|
||||
;; True when atype's methods were registered for this protocol (via extend /
|
||||
;; extend-type). Tags are canonical host names or ns-qualified record names,
|
||||
;; so a bare record name also matches its "ns.Name" tag.
|
||||
(defn extends? [protocol atype]
|
||||
(let [want (name atype)
|
||||
dotted (str "." want)
|
||||
dlen (count dotted)]
|
||||
(boolean (some (fn [t]
|
||||
(let [tn (name t)]
|
||||
(or (= tn want)
|
||||
(and (> (count tn) dlen)
|
||||
(= (subs tn (- (count tn) dlen)) dotted)))))
|
||||
(extenders protocol)))))
|
||||
|
||||
;; extend, the FUNCTION (extend-type's runtime sibling): protocol + method-map
|
||||
;; pairs, methods registered under the type's (canonicalized) name — so
|
||||
;; (extend 'String P {:m (fn [x] ...)}) dispatches exactly like extend-type.
|
||||
(defn extend [atype & proto+mmaps]
|
||||
(loop [s (seq proto+mmaps)]
|
||||
(when s
|
||||
(let [proto (first s)
|
||||
mmap (second s)
|
||||
pname (name (get proto :name))]
|
||||
(doseq [[k f] mmap]
|
||||
(register-method (name atype) pname (name k) f)))
|
||||
(recur (nnext s)))))
|
||||
|
||||
(defmacro extend-type [tsym psym & impls]
|
||||
;; register-method is a fn (clojure.core); pass type/protocol/method NAMES as
|
||||
;; strings (not the symbols) so the call compiles as a plain invoke.
|
||||
|
|
@ -308,7 +345,7 @@
|
|||
(group-by-head type-impls))))
|
||||
|
||||
;; extend (the fn form) is not supported — stub to nil, as before.
|
||||
(defmacro extend [& args] nil)
|
||||
;; extend is a real FUNCTION now — defined above extend-type.
|
||||
;; JVM proxies are unsupported.
|
||||
(defmacro proxy [& args] nil)
|
||||
;; definterface is JVM-only; bind the name to an empty marker.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue