Fix core-signals bytecode: letrec for self-ref, explicit get for dict destructuring

Two issues prevented core-signals.sx from working as bytecode:

1. computed/effect used (let) for self-referencing bindings (recompute,
   run-effect). Changed to (letrec) so the VM pre-allocates slots before
   compiling the lambda bodies — required for self-reference in bytecode.

2. deref used dict destructuring (let {:notify n :deps d} ctx ...) which
   the transpiled OCaml compiler doesn't support. Rewrote to explicit
   (get ctx "notify") / (get ctx "deps") calls.

Also fixed compile-let dict destructuring opcodes (OP_CONST=1 not 2,
OP_CALL_PRIM=52 not 10) for future use when compiler is retranspiled.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-11 12:38:07 +00:00
parent ef8f8b7c03
commit fc9c90b7b1
6 changed files with 16 additions and 22 deletions

View File

@@ -614,13 +614,10 @@
(str k))))
(emit-op em 16)
(emit-byte em temp-slot)
(let
((key-idx (pool-add (get em "pool") key-str)))
(emit-op em 2)
(emit-u16 em key-idx))
(emit-const em key-str)
(let
((get-idx (pool-add (get em "pool") "get")))
(emit-op em 10)
(emit-op em 52)
(emit-u16 em get-idx)
(emit-byte em 2))
(let

View File

@@ -614,13 +614,10 @@
(str k))))
(emit-op em 16)
(emit-byte em temp-slot)
(let
((key-idx (pool-add (get em "pool") key-str)))
(emit-op em 2)
(emit-u16 em key-idx))
(emit-const em key-str)
(let
((get-idx (pool-add (get em "pool") "get")))
(emit-op em 10)
(emit-op em 52)
(emit-u16 em get-idx)
(emit-byte em 2))
(let

File diff suppressed because one or more lines are too long

View File

@@ -83,8 +83,8 @@
(when
ctx
(let
{:notify notify-fn :deps dep-list}
ctx
((notify-fn (get ctx "notify"))
(dep-list (get ctx "deps")))
(when
(not (contains? dep-list s))
(append! dep-list s)
@@ -124,7 +124,7 @@
((compute-fn :as lambda))
(let
((s (make-signal nil)) (deps (list)) (compute-ctx nil))
(let
(letrec
((recompute (fn () (for-each (fn ((dep :as signal)) (signal-remove-sub! dep recompute)) (signal-deps s)) (signal-set-deps! s (list)) (let ((ctx (dict "deps" (list) "notify" recompute))) (scope-push! "sx-reactive" ctx) (let ((new-val (cek-call compute-fn nil))) (scope-pop! "sx-reactive") (signal-set-deps! s (get ctx "deps")) (let ((old (signal-value s))) (signal-set-value! s new-val) (when (not (identical? old new-val)) (notify-subscribers s))))))))
(recompute)
(register-in-scope (fn () (dispose-computed s)))
@@ -136,7 +136,7 @@
((effect-fn :as lambda))
(let
((deps (list)) (disposed false) (cleanup-fn nil))
(let
(letrec
((run-effect (fn () (when (not disposed) (when cleanup-fn (cek-call cleanup-fn nil)) (for-each (fn ((dep :as signal)) (signal-remove-sub! dep run-effect)) deps) (set! deps (list)) (let ((ctx (dict "deps" (list) "notify" run-effect))) (scope-push! "sx-reactive" ctx) (let ((result (cek-call effect-fn nil))) (scope-pop! "sx-reactive") (set! deps (get ctx "deps")) (when (callable? result) (set! cleanup-fn result))))))))
(run-effect)
(let

File diff suppressed because one or more lines are too long

View File

@@ -83,8 +83,8 @@
(when
ctx
(let
{:notify notify-fn :deps dep-list}
ctx
((notify-fn (get ctx "notify"))
(dep-list (get ctx "deps")))
(when
(not (contains? dep-list s))
(append! dep-list s)
@@ -124,7 +124,7 @@
((compute-fn :as lambda))
(let
((s (make-signal nil)) (deps (list)) (compute-ctx nil))
(let
(letrec
((recompute (fn () (for-each (fn ((dep :as signal)) (signal-remove-sub! dep recompute)) (signal-deps s)) (signal-set-deps! s (list)) (let ((ctx (dict "deps" (list) "notify" recompute))) (scope-push! "sx-reactive" ctx) (let ((new-val (cek-call compute-fn nil))) (scope-pop! "sx-reactive") (signal-set-deps! s (get ctx "deps")) (let ((old (signal-value s))) (signal-set-value! s new-val) (when (not (identical? old new-val)) (notify-subscribers s))))))))
(recompute)
(register-in-scope (fn () (dispose-computed s)))
@@ -136,7 +136,7 @@
((effect-fn :as lambda))
(let
((deps (list)) (disposed false) (cleanup-fn nil))
(let
(letrec
((run-effect (fn () (when (not disposed) (when cleanup-fn (cek-call cleanup-fn nil)) (for-each (fn ((dep :as signal)) (signal-remove-sub! dep run-effect)) deps) (set! deps (list)) (let ((ctx (dict "deps" (list) "notify" run-effect))) (scope-push! "sx-reactive" ctx) (let ((result (cek-call effect-fn nil))) (scope-pop! "sx-reactive") (set! deps (get ctx "deps")) (when (callable? result) (set! cleanup-fn result))))))))
(run-effect)
(let