Phase 11: Fix pre-existing failures — 316/317 passing

- types.janet: ns? now accepts both structs and tables
  (defensive for namespace-like tables created via @{...})
- core.janet: wire comment macro into core-bindings
  (was in core-macro-names but missing from core-bindings)
- sci/lang_stubs.clj: minimal SCI type stubs for bootstrap
  (IBox, HasName, IVar, DynVar protocols, SciUnbound/Var/Namespace deftypes)
- test-load-sci.janet: load stubs before SCI source files,
  removed broken preprocessor

Before: 315 ok, 2 fail (SciVar + array/buffer)
After:  316 ok, 1 fail (only deftype in lang.cljc remains)

The remaining failure is lang.cljc's SciVar deftype with #?@ inserts
for JVM/CLJS-specific protocol implementations — a known limitation
for Phase 15 (SCI bootstrap).
This commit is contained in:
Yogthos 2026-06-03 12:30:11 -04:00
parent 1c1100e2f0
commit 09b4e3e1bd
10 changed files with 179 additions and 69 deletions

View file

@ -1,5 +1,5 @@
Janet's `case` for multi-arity dispatch: `(defn f [& args] (case (length args) 1 ... 2 ...))`. Used in core-derive, core-isa?, core-ancestors, core-descendants because Janet doesn't support Clojure-style `([arg1] body1) ([arg1 arg2] body2)` multi-arity defn syntax.
Janet's `break` does NOT return a value from a loop — `(break val)` in a `while` loop just exits, discarding val. To return from a loop, set a variable before break: `(do (set result val) (break))`. Hit us in phm-bucket-assoc where `(break nb)` silently returned nil instead of the new bucket. Fixed by capturing index before break and building the result array after the loop.
§
Janet's boolean function doesn't exist — use (if x true false). Janet's defn doesn't support Clojure-style multi-arity syntax ([args] body) — use [& args] with case (length args) dispatch. fn? exists as Janet builtin (not Jolt core fn) — use (or (function? x) (cfunction? x)) in tests.
Clojure .clj source files loaded via eval-form cannot have docstrings. If a defn form has 5 elements (defn, name, docstring, params, body), the evaluator's defn macro handler gets 4 args instead of 3, breaking with "macro arity mismatch". All .clj files in src/jolt/clojure/ must use 4-element defn forms: (defn name [params] body). Docstrings on defn are a Clojure feature not supported by Jolt's defn macro.
§
Janet's `cond` treats the last position as a test clause, NOT a catch-all body. A bare expression like `(push-str buf val)` in the last position runs as a test (always truthy, but executed for side effects between other cond clauses). Use `true (push-str buf val)` to make it a proper catch-all body. Hit us in buffer-based write-value — raw tuple addresses leaked into output because `(push-str buf (string v))` ran as a test clause between other branches.
PHM internal key leak: Core functions iterating over PHM maps with keys/pairs get internal metadata keys (:jolt/deftype, :cnt, :buckets, :_meta). Always check for set?/phm? first and use type-aware helpers (phm-to-struct, phs-seq, phm-keys, phm-entries) before generic iteration. Hit us in core-merge, core-reduce, core-every?, core-filter which all needed set?/phm? checks added.