fix: all 317 SCI forms load, zero failures

- Reorder load sequence: types→unrestrict→vars→lang→utils→namespaces→core
- Add if-let/when-let/if-some/when-some/let macros and register in core-macro-names
- Add stubs: resolve, update, copy-core-var, copy-var, macrofy, new-var, avoid-method-too-large
- Add dynamic vars: *1, *2, *3, *e, *assert with nil-sentinel
- Fix core-update: use put instead of Janet's update (struct-incompatible)
- Change *clojure-version* from struct to table (mutable for update)
- Fix core-avoid-method-too-large: return @{} not nil
- Fix init-core! nil-sentinel unwrapping
- Fix let* destructuring for {:keys [...]} and sequential patterns
- Fix fn*/defmacro: capture defining ns for symbol resolution in closures
This commit is contained in:
Yogthos 2026-06-02 00:07:40 -04:00
parent 93f0e42716
commit b948c4fdbb
9 changed files with 377 additions and 108 deletions

View file

@ -1,4 +1,5 @@
# jolt-bootstrap
# jolt-bootstrap
TDD workflow for bootstrapping a Clojure interpreter on Janet
@ -81,8 +82,19 @@ Used in `def`, `ns`, `deftype`, `defmethod` to handle metadata-wrapped names.
### deftype →TypeName constructor
`deftype` interns both `TypeName` and `->TypeName` (Clojure arrow constructor convention).
### bind-put helper and :jolt/nil sentinel
Janet's `(put table key nil)` silently drops the key, even on mutable `@{}` tables.
`bind-put` stores nil as `:jolt/nil` sentinel; `resolve-sym` unwraps `:jolt/nil` back to `nil`.
Must be used for ALL binding `put` calls: `fn*`, `let*`, `loop*`, macro bodies, `deftype` reify.
### resolve-sym sentinels
- `:jolt/not-found` — returned when a symbol is truly absent (distinct from nil binding)
- `:jolt/nil` → unwrapped to actual `nil` — nil values in bindings stored as sentinel due to Janet `put` nil-drop
- Auto-refer fallback: unqualified symbols not found in current ns fall back to `clojure.core`
## Pitfalls
- Janet `let` can't bind to nil; use `(var x nil)` then `(set x val)`
- Janet `(put table key nil)` silently drops the key — use `bind-put` helper for all binding tables
- `(get table)` with 1 arg = compile error, use `(table :key)` shorthand
- `(put fn :key val)` fails on functions; stash metadata on vars instead
- `deftype` field names must be keywords (not strings) for `(inst :field)` access