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:
Yogthos 2026-06-10 17:52:30 -04:00
parent daab2ab4cc
commit d06b3fe636
8 changed files with 414 additions and 151 deletions

View file

@ -42,9 +42,15 @@ jolt = interned | resolvable
# --- 3. what the tests exercise --------------------------------------------
tested = set()
sym = re.compile(r'\(([a-zA-Z*+!?<>=_-][a-zA-Z0-9*+!?<>=_./-]*)')
test_text = ''
# A var counts as tested when its name appears as a WHOLE TOKEN anywhere in
# the test sources (assertions live inside strings, so call-position-only
# matching missed *1, +', ., .., /, and bare transducer refs like cat).
SYMCHARS = r"\w*+!?<>=_.'/-"
def token_re(name):
return re.compile('(?<![' + re.escape(SYMCHARS) + '])' + re.escape(name) + '(?![' + re.escape(SYMCHARS) + '])')
for f in glob.glob('test/spec/*.janet') + ['test/integration/conformance-test.janet']:
tested |= set(sym.findall(open(f).read()))
test_text += open(f).read()
# --- classification ---------------------------------------------------------
SPECIAL = {'catch','finally','do','def','defmacro','fn','if','let','loop','quote',
@ -72,7 +78,7 @@ JVM = {'class','class?','cast','bases','supers','compile','add-classpath',
def classify(n):
if n in jolt:
return 'implemented+tested' if n in tested else 'implemented-untested'
return 'implemented+tested' if token_re(n).search(test_text) else 'implemented-untested'
if re.match(r'^\*.*\*$', n): return 'dynamic-var'
if n in SPECIAL: return 'special-form'
if n in AGENTS: return 'agents-taps'