- 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
Root causes:
- core-binding used tuples instead of arrays for call forms.
Evaluator treats tuples as literal vectors, so calls failed.
Fixed with @[...] and proper (push-thread-bindings frame) forms.
- try handler: finally only ran on error, not success.
Fixed to run finally on both paths.
- ns accessors: all-ns, remove-ns, create-ns, the-ns, ns-interns,
ns-aliases, ns-imports-fn added to types.janet
- ns form: :require/:refer, :use, :refer-clojure/:exclude, :import
- eval-require: :refer support
- All 317 tests pass, 0 failures
Root cause: compile-and-eval for def created Janet global but never
interned the var in Jolt's namespace. Bare symbols fell through to
interpreter which couldn't find them.
Fixes:
- eval-string: bare symbols and tuples now go through compile path
- compile-and-eval: def/defn/defn- forms intern result in Jolt namespace
- New tests: defn/def integration (4 assertions)
All 317 tests pass.
47 new compile-mode tests: collections, math, predicates, comparison,
seq operations (map/filter/reduce/take/drop), special forms (let/if/loop/
try/quote), macros (defn/when/and/or/fn/if-let), complex nesting.
Bugs fixed:
- emit-vector-expr: use (tuple ...) instead of bare tuple
(Janet eval treats bare tuples as function calls)
- make-symbol: / at position 0 → unqualified symbol
(was parsing as {:ns "" :name ""})
- core-renames: add missing fn? entry
- throw: emit (error val) in Janet
- try/catch/finally: map to Janet (try body ([err] handler))
- loop*/recur: emit closure-based loop (do (var f nil) (set f (fn [args] body)) (f init-vals))
- recur rewrites to loop function call at emit time
- All 317 tests pass + 5 new Phase 5 tests
- 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
Add binding-get helper that walks Janet table prototype chain.
resolve-sym now uses two-stage lookup: direct get first,
then prototype walk as fallback. This fixes access to outer
let bindings from inner let forms without breaking fn parameter
resolution (which uses direct table keys).
All 9 test suites pass including macro-test.
- 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.
Add edamame.core + clojure.tools.reader.reader-types shim to core.janet.
init-edamame-shim! takes parse-string and read-form as args to avoid
circular module dependencies. Creates shim namespaces after SCI loads.
SCI eval-string is found and callable — next step is loading the 4
internal namespaces (interpreter, parser, analyzer, opts) whose source
files aren't loaded by the ns :require handler.