Bytecode compiler: desugar let-match, fix SPA navigation

The bytecode compiler now handles let-match (both variants):
- Variant 1: (let-match name expr {:k v} body...) — named binding + destructure
- Variant 2: (let-match {:k v} expr body...) — pattern-only destructure

Desugars to sequential let + get calls — no new opcodes needed.

This was the last blocker for SPA navigation. The bytecoded orchestration
and router modules used let-match which compiled to CALL_PRIM "let-match"
(undefined at runtime). Now desugared at compile time.

Also synced dist/sx/ sources with web/ and recompiled all 26 .sxbc modules.

2650/2650 tests pass.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-04 21:31:17 +00:00
parent c0665ba58e
commit 9b060ef8c5
7 changed files with 1208 additions and 1130 deletions

View File

@@ -41,6 +41,7 @@
compile-or
compile-begin
compile-let
desugar-let-match
compile-letrec
compile-lambda
compile-define
@@ -250,6 +251,8 @@
(compile-let em args scope tail?)
(= name "let*")
(compile-let em args scope tail?)
(= name "let-match")
(compile-let em (desugar-let-match args) scope tail?)
(= name "begin")
(compile-begin em args scope tail?)
(= name "do")
@@ -446,6 +449,47 @@
(compile-expr em (first exprs) scope false)
(emit-op em 5)
(compile-begin em (rest exprs) scope tail?))))))
(define
desugar-let-match
(fn
(args)
(let
((first-arg (first args)))
(if (dict? first-arg)
;; Variant 2: (let-match {:k v} expr body...)
(let
((pattern first-arg)
(expr (nth args 1))
(body (slice args 2))
(src-sym (make-symbol "__lm_tmp"))
(bindings (list)))
(append! bindings (list src-sym expr))
(for-each
(fn (k)
(append! bindings
(list (get pattern k)
(list (make-symbol "get") src-sym (str k)))))
(keys pattern))
(cons bindings body))
;; Variant 1: (let-match name expr {:k v} body...)
(let
((name-sym first-arg)
(expr (nth args 1))
(pattern (nth args 2))
(body (slice args 3))
(src-sym (if (= (str name-sym) "_")
(make-symbol "__lm_tmp")
name-sym))
(bindings (list)))
(append! bindings (list src-sym expr))
(when (dict? pattern)
(for-each
(fn (k)
(append! bindings
(list (get pattern k)
(list (make-symbol "get") src-sym (str k)))))
(keys pattern)))
(cons bindings body))))))
(define
compile-let
(fn