core: the last seven missing-portable vars — coverage gap closed (jolt-brh)

The dashboard's missing-portable category is now EMPTY (was 35 when the issue
was filed; this session's io/leaf work had already landed most of them).
The final seven:

- extenders — ctx-capturing clojure.core fn over the protocol type-registry:
  the type-tags implementing a protocol, as symbols; nil when none
- find-keyword — keyword: jolt keywords have no intern table, so it always
  finds (babashka makes the same call)
- inst-ms* — the raw Inst method; one inst representation, so = inst-ms
- read+string — over the 50-io readers, which now expose :buf and :fill-fn;
  returns [form exact-text-consumed], EOF throws or yields [eof-value ""]
  with the 3-arity, works for string AND stdin readers
- with-local-vars — fresh free-standing var cells (__local-var seam) bound as
  locals; var-get/var-set work on any cell
- with-open — canonical recursive expansion closing through the __close seam:
  a map-like value's :close fn or a host file (no .close interop here);
  nested closes run inner-first, finally runs on throw
- with-precision — body evaluates with precision/:rounding accepted and
  ignored (doubles, no BigDecimal context) — documented divergence

30 new spec rows (test/spec/missing-vars-spec.janet); coverage.md
regenerated: implemented+tested 426 -> 433, missing-portable 7 -> 0.
Gate: jpm exit 0, all tests passed.
This commit is contained in:
Yogthos 2026-06-10 17:22:28 -04:00
parent 3051f4264a
commit 6445f461bb
7 changed files with 167 additions and 26 deletions

View file

@ -2256,6 +2256,17 @@
(defn core-copy-var [sym & args] nil)
(defn core-macrofy [sym fn & more] fn)
(defn core-new-var [sym & args] nil)
# A free-standing var cell (not interned anywhere): with-local-vars binds
# these as locals; var-get/var-set work on any cell.
(defn core-local-var [&opt val]
@{:jolt/type :jolt/var :name "local" :ns nil :root val :gen 0})
# with-open's close seam: a map-like value closes via its :close fn, a host
# file via file/close. No .close interop on the Janet host.
(defn core-close-resource [x]
(cond
(and (or (table? x) (struct? x)) (function? (get x :close))) ((get x :close))
(= :core/file (type x)) (file/close x)
(error (string "with-open: don't know how to close " (type x)))))
# sci stub: pass the registry map through (it was @{} — a raw host table that
# strict map-conj rightly rejects; identity also keeps sci's registry intact).
(defn core-avoid-method-too-large [& args] (if (> (length args) 0) (in args 0) {}))
@ -2949,6 +2960,8 @@
"copy-var" core-copy-var
"macrofy" core-macrofy
"new-var" core-new-var
"__local-var" core-local-var
"__close" core-close-resource
"avoid-method-too-large" core-avoid-method-too-large
"inst?" core-inst?
"inst-ms" core-inst-ms

View file

@ -951,6 +951,17 @@
(ns-intern core "protocol-dispatch"
(fn [proto-name method-name obj rest-args]
(protocol-dispatch-impl ctx proto-name method-name obj rest-args)))
(ns-intern core "extenders"
(fn [proto]
# All type-tags whose registry entry implements this protocol, as symbols
# (closest analog to Clojure's class list); nil when none.
(let [pname (get (get proto :name) :name)
registry (get (ctx :env) :type-registry)
out @[]]
(each tag (keys registry)
(when (get (get registry tag) pname)
(array/push out {:jolt/type :symbol :ns nil :name tag})))
(if (empty? out) nil (tuple ;out)))))
(ns-intern core "register-method"
(fn [type-name proto-name method-name f]
(register-method-impl ctx type-name proto-name method-name f)))