- 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).
Root cause: fn* multi-arity detection checks (array? (in form 1))
— defprotocol used @[...] for args, triggering multi-arity path
that treated the body form as a second arity pair.
Fixes applied:
- defprotocol: change fn* args from @[...] to [...] (tuple)
so single-arity fn* path is used with [this & rest-args]
- defprotocol: remove quote wrappers from protocol-dispatch call
(protocol-name and method-name passed directly as symbols)
- extend-type/extend-protocol: remove quote wrappers from
register-method call (symbols passed directly, not via quote)
- protocol-dispatch: use (in form ...) directly for proto/method
symbols (no eval-form needed after quote removal)
- satisfy?: extract name string from protocol value's :name field
(which is a symbol struct, not a plain string)
- make-reified: remove spurious (apply fn []) call
- core-reify: fix (keyword struct) → extract :name string first
- core-extend-protocol: handle single method spec vs multi
5 test sections (35-39) covering:
defprotocol, extend-type, extend-protocol,
satisfies?, reify — all pass
315 ok, 2 fail (pre-existing, unchanged)
- phm.janet: LazySeq (realize-once with caching, ls-first/ls-rest/ls-seq/ls-count)
PersistentHashSet (backed by PHM, phs-conj/phs-disj/phs-contains?/phs-count/...)
make-lazy-seq creates lazy thunk wrapper with :jolt/lazy-seq type tag
make-phs creates hash set with :jolt/set type tag
- evaluator.janet: :jolt/set handler in eval-form, disj/set? special forms,
special-symbol? entries, phm import for compile-time visibility
- core.janet: lazy-seq/iterate macros, set?/disj core fns, make-phs wired
into hash-set, core-bindings entries for set?/disj/lazy-seq/make-lazy-seq/iterate
Set support in core-conj/core-contains?/core-count/core-empty?/core-seq/core-get
LazySeq support in core-first/core-rest/core-count/core-seq
- 9 tests (32-33): lazy-seq basic ops, realize-once caching
PersistentHashSet construction, conj, disj, count, set? predicate
- 315 ok, 2 fail (pre-existing, unchanged)
- types.janet: find-var (ctx-based var resolution), alter-meta!, reset-meta!
- evaluator.janet: 10 new special-form dispatch arms for var ops
- core.janet: 6 new Clojure-level wrappers in core-bindings
- core-meta: add var-aware branch (was struct-only)
- core-binding macro: use array-map instead of hash-map (PHM incompatibility)
- 8 new tests (17: var system, 18: var metadata) — all pass
- 317 total tests, 0 failures
Compile-time implementation of syntax-quote proved too complex for the
current emission pipeline (qualified symbol handling across both
string and data-structure paths). These ops require runtime context
(var lookup, field mutation, deftype construction) and are now correctly
routed to the interpreter via the stateful? check in eval-string.
Also fixed:
- raw-form->janet handles namespace-qualified symbols correctly
- emit-quote-str and emit-quote-expr use raw-form->janet consistently
- Duplicate function definitions removed
All 317 tests pass, 0 failures.
- loader.janet: load-ns with compile? dispatch, compiled-cache, compiled?, clear-compiled-cache
- compiler.janet: compile-ast (Janet data structures for direct eval), compile-and-eval
- api.janet: compile-string, compile-file, eval-string dispatches to compile-and-eval when :compile? is true
- types.janet: :compile? flag and :compiled-cache table in context env
- Stateful forms (def, defmacro, ns, deftype, defmulti, defmethod) fall back to interpreter
- All 317 tests pass + 16 new Phase 3 tests
Root cause of HAMT failure: Janet uses 64-bit doubles, bit operations
require 32-bit signed ints. Hash values from Janet exceed this range.
Solution: Replaced bit-trie HAMT with simple array-based implementation:
- find-key-index: linear scan for key lookup
- node-assoc: append-to-array on insert, clone+update on replace
- node-find: linear scan for value retrieval
All operations work correctly:
(hash-map :a 1) → {:root [:a 1], :count 1}
(hash-map :a 1 :b 2) → {:root [:a 1 :b 2], :count 2}
phm-assoc / phm-get / phm-count all verified
O(n) lookup (acceptable for small maps). HAMT can be reintroduced
once Janet gets proper 32-bit int support or we implement bit ops
in pure Janet.
- Add SCI as git submodule at vendor/sci (replaces absolute path)
- Fix defrecord macro: emit array-map at expansion time, no interleave dep
- Remove stale test files (test-ctor, test-parser, edamame_shim)
- All 317 SCI forms load with 0 failures, 9 test suites green
Replace SCI's internal interpreter/parser/analyzer pipeline with
Jolt-native eval-string that delegates to Jolt's reader and evaluator.
All 317 SCI source forms load, 9 namespaces populated, 46 total ns.
eval-string result: (+ 1 2 3) → 6, (def x 42) x → 42
Removed edamame/core shim — no longer needed since we bypass
the SCI internal eval pipeline entirely.