Fix server import suspension, dist sync, JIT errors
- cek_run patched to handle import suspensions via _import_hook. define-library (import ...) now resolves cleanly on the server. IO suspension errors: 190 → 0. JIT failures: ~50 → 0. - _import_hook wired in sx_server.ml to load .sx files on demand. - compile-modules.js syncs source .sx files to dist/sx/ before compiling — eliminates stale bytecode from out-of-date copies. - WASM binary rebuilt with all fixes. - 2658/2658 tests pass (8 new — previously failing import tests). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -783,6 +783,18 @@ let () =
|
|||||||
if not (Sx_primitives.is_primitive name) then
|
if not (Sx_primitives.is_primitive name) then
|
||||||
Hashtbl.replace _shared_vm_globals name v)
|
Hashtbl.replace _shared_vm_globals name v)
|
||||||
|
|
||||||
|
(* Import hook — resolves (import ...) suspensions inside eval_expr/cek_run.
|
||||||
|
Loads the .sx file for the library, registers it, and returns true. *)
|
||||||
|
let () =
|
||||||
|
Sx_types._import_hook := Some (fun lib_spec ->
|
||||||
|
let key = Sx_ref.library_name_key lib_spec in
|
||||||
|
if Sx_types.sx_truthy (Sx_ref.library_loaded_p key) then true
|
||||||
|
else match resolve_library_path lib_spec with
|
||||||
|
| Some path ->
|
||||||
|
(try load_library_file path; true
|
||||||
|
with _ -> false)
|
||||||
|
| None -> false)
|
||||||
|
|
||||||
let make_server_env () =
|
let make_server_env () =
|
||||||
let env = make_env () in
|
let env = make_env () in
|
||||||
Sx_render.setup_render_env env;
|
Sx_render.setup_render_env env;
|
||||||
|
|||||||
@@ -16,12 +16,53 @@ const { execSync, spawnSync } = require('child_process');
|
|||||||
|
|
||||||
const distDir = process.argv[2] || path.join(__dirname, 'dist');
|
const distDir = process.argv[2] || path.join(__dirname, 'dist');
|
||||||
const sxDir = path.join(distDir, 'sx');
|
const sxDir = path.join(distDir, 'sx');
|
||||||
|
const projectRoot = path.resolve(__dirname, '..', '..', '..');
|
||||||
|
|
||||||
if (!fs.existsSync(sxDir)) {
|
if (!fs.existsSync(sxDir)) {
|
||||||
console.error('sx dir not found:', sxDir);
|
console.error('sx dir not found:', sxDir);
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Sync source .sx files to dist/sx/ before compiling.
|
||||||
|
// Source locations: spec/ for core, lib/ for compiler/vm, web/ and web/lib/ for web stack.
|
||||||
|
const SOURCE_MAP = {
|
||||||
|
// spec/
|
||||||
|
'render.sx': 'spec/render.sx',
|
||||||
|
'core-signals.sx': 'spec/signals.sx',
|
||||||
|
// lib/
|
||||||
|
'bytecode.sx': 'lib/bytecode.sx', 'compiler.sx': 'lib/compiler.sx',
|
||||||
|
'vm.sx': 'lib/vm.sx', 'freeze.sx': 'lib/freeze.sx',
|
||||||
|
'highlight.sx': 'lib/highlight.sx',
|
||||||
|
// web/lib/
|
||||||
|
'dom.sx': 'web/lib/dom.sx', 'browser.sx': 'web/lib/browser.sx',
|
||||||
|
// web/
|
||||||
|
'signals.sx': 'web/signals.sx', 'deps.sx': 'web/deps.sx',
|
||||||
|
'router.sx': 'web/router.sx', 'page-helpers.sx': 'web/page-helpers.sx',
|
||||||
|
'adapter-html.sx': 'web/adapter-html.sx', 'adapter-sx.sx': 'web/adapter-sx.sx',
|
||||||
|
'adapter-dom.sx': 'web/adapter-dom.sx',
|
||||||
|
'boot-helpers.sx': 'web/lib/boot-helpers.sx',
|
||||||
|
'hypersx.sx': 'web/hypersx.sx',
|
||||||
|
'harness.sx': 'spec/harness.sx', 'harness-reactive.sx': 'web/harness-reactive.sx',
|
||||||
|
'harness-web.sx': 'web/harness-web.sx',
|
||||||
|
'engine.sx': 'web/engine.sx', 'orchestration.sx': 'web/orchestration.sx',
|
||||||
|
'boot.sx': 'web/boot.sx',
|
||||||
|
'tw-layout.sx': 'web/tw-layout.sx', 'tw-type.sx': 'web/tw-type.sx', 'tw.sx': 'web/tw.sx',
|
||||||
|
};
|
||||||
|
let synced = 0;
|
||||||
|
for (const [dist, src] of Object.entries(SOURCE_MAP)) {
|
||||||
|
const srcPath = path.join(projectRoot, src);
|
||||||
|
const dstPath = path.join(sxDir, dist);
|
||||||
|
if (fs.existsSync(srcPath)) {
|
||||||
|
const srcContent = fs.readFileSync(srcPath);
|
||||||
|
const dstExists = fs.existsSync(dstPath);
|
||||||
|
if (!dstExists || !fs.readFileSync(dstPath).equals(srcContent)) {
|
||||||
|
fs.writeFileSync(dstPath, srcContent);
|
||||||
|
synced++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (synced > 0) console.log('Synced ' + synced + ' source files to dist/sx/');
|
||||||
|
|
||||||
// Find the native OCaml binary
|
// Find the native OCaml binary
|
||||||
const binPaths = [
|
const binPaths = [
|
||||||
path.join(__dirname, '..', '_build', 'default', 'bin', 'sx_server.exe'),
|
path.join(__dirname, '..', '_build', 'default', 'bin', 'sx_server.exe'),
|
||||||
|
|||||||
@@ -488,7 +488,21 @@ and cek_step_loop state =
|
|||||||
|
|
||||||
(* cek-run *)
|
(* cek-run *)
|
||||||
and cek_run state =
|
and cek_run state =
|
||||||
(let final = (cek_step_loop (state)) in (if sx_truthy ((cek_suspended_p (final))) then (raise (Eval_error (value_to_str (String "IO suspension in non-IO context")))) else (cek_value (final))))
|
(let rec run s =
|
||||||
|
let final = cek_step_loop s in
|
||||||
|
if sx_truthy (cek_suspended_p final) then begin
|
||||||
|
let request = cek_io_request final in
|
||||||
|
let op = match request with Dict d -> (match Hashtbl.find_opt d "op" with Some (String s) -> s | _ -> "") | _ -> "" in
|
||||||
|
if op = "import" then
|
||||||
|
let lib_spec = match request with Dict d -> (match Hashtbl.find_opt d "library" with Some v -> v | _ -> Nil) | _ -> Nil in
|
||||||
|
let key = library_name_key lib_spec in
|
||||||
|
let resolved = sx_truthy (library_loaded_p key) ||
|
||||||
|
(match !_import_hook with Some hook -> hook lib_spec | None -> false) in
|
||||||
|
if resolved then run (cek_resume final Nil)
|
||||||
|
else raise (Eval_error "IO suspension in non-IO context")
|
||||||
|
else raise (Eval_error "IO suspension in non-IO context")
|
||||||
|
end else cek_value final
|
||||||
|
in run state)
|
||||||
|
|
||||||
(* cek-resume *)
|
(* cek-resume *)
|
||||||
and cek_resume suspended_state result' =
|
and cek_resume suspended_state result' =
|
||||||
@@ -810,6 +824,22 @@ let () = Sx_primitives._sx_trampoline_fn := !trampoline_fn
|
|||||||
let cek_run_iterative state =
|
let cek_run_iterative state =
|
||||||
let s = ref state in
|
let s = ref state in
|
||||||
(try
|
(try
|
||||||
|
while not (match cek_terminal_p !s with Bool true -> true | _ -> false)
|
||||||
|
&& not (match cek_suspended_p !s with Bool true -> true | _ -> false) do
|
||||||
|
s := cek_step !s
|
||||||
|
done;
|
||||||
|
(match cek_suspended_p !s with
|
||||||
|
| Bool true ->
|
||||||
|
let request = cek_io_request !s in
|
||||||
|
let op = match request with Dict d -> (match Hashtbl.find_opt d "op" with Some (String s) -> s | _ -> "") | _ -> "" in
|
||||||
|
if op = "import" then begin
|
||||||
|
let lib_spec = match request with Dict d -> (match Hashtbl.find_opt d "library" with Some v -> v | _ -> Nil) | _ -> Nil in
|
||||||
|
let key = library_name_key lib_spec in
|
||||||
|
let resolved = sx_truthy (library_loaded_p key) ||
|
||||||
|
(match !_import_hook with Some hook -> hook lib_spec | None -> false) in
|
||||||
|
if resolved then begin
|
||||||
|
s := cek_resume !s Nil;
|
||||||
|
(* Continue the step loop after resolving the import *)
|
||||||
while not (match cek_terminal_p !s with Bool true -> true | _ -> false)
|
while not (match cek_terminal_p !s with Bool true -> true | _ -> false)
|
||||||
&& not (match cek_suspended_p !s with Bool true -> true | _ -> false) do
|
&& not (match cek_suspended_p !s with Bool true -> true | _ -> false) do
|
||||||
s := cek_step !s
|
s := cek_step !s
|
||||||
@@ -817,6 +847,9 @@ let cek_run_iterative state =
|
|||||||
(match cek_suspended_p !s with
|
(match cek_suspended_p !s with
|
||||||
| Bool true -> raise (Eval_error "IO suspension in non-IO context")
|
| Bool true -> raise (Eval_error "IO suspension in non-IO context")
|
||||||
| _ -> cek_value !s)
|
| _ -> cek_value !s)
|
||||||
|
end else raise (Eval_error "IO suspension in non-IO context")
|
||||||
|
end else raise (Eval_error "IO suspension in non-IO context")
|
||||||
|
| _ -> cek_value !s)
|
||||||
with Eval_error msg ->
|
with Eval_error msg ->
|
||||||
_last_error_kont_ref := cek_kont !s;
|
_last_error_kont_ref := cek_kont !s;
|
||||||
raise (Eval_error msg))
|
raise (Eval_error msg))
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
|
||||||
|
|
||||||
(define-library (sx signals)
|
(define-library
|
||||||
|
(sx signals)
|
||||||
(export
|
(export
|
||||||
make-signal
|
make-signal
|
||||||
signal?
|
signal?
|
||||||
@@ -26,48 +27,50 @@
|
|||||||
with-island-scope
|
with-island-scope
|
||||||
register-in-scope)
|
register-in-scope)
|
||||||
(begin
|
(begin
|
||||||
|
(define
|
||||||
(define
|
|
||||||
make-signal
|
make-signal
|
||||||
(fn
|
(fn
|
||||||
(value)
|
(value)
|
||||||
(dict "__signal" true "value" value "subscribers" (list) "deps" (list))))
|
(dict
|
||||||
|
"__signal"
|
||||||
(define signal? (fn (x) (and (dict? x) (has-key? x "__signal"))))
|
true
|
||||||
|
"value"
|
||||||
(define signal-value (fn (s) (get s "value")))
|
value
|
||||||
|
"subscribers"
|
||||||
(define signal-set-value! (fn (s v) (dict-set! s "value" v)))
|
(list)
|
||||||
|
"deps"
|
||||||
(define signal-subscribers (fn (s) (get s "subscribers")))
|
(list))))
|
||||||
|
(define signal? (fn (x) (and (dict? x) (has-key? x "__signal"))))
|
||||||
(define
|
(define signal-value (fn (s) (get s "value")))
|
||||||
|
(define signal-set-value! (fn (s v) (dict-set! s "value" v)))
|
||||||
|
(define signal-subscribers (fn (s) (get s "subscribers")))
|
||||||
|
(define
|
||||||
signal-add-sub!
|
signal-add-sub!
|
||||||
(fn
|
(fn
|
||||||
(s f)
|
(s f)
|
||||||
(when
|
(when
|
||||||
(not (contains? (get s "subscribers") f))
|
(not (contains? (get s "subscribers") f))
|
||||||
(dict-set! s "subscribers" (append (get s "subscribers") (list f))))))
|
(dict-set!
|
||||||
|
s
|
||||||
(define
|
"subscribers"
|
||||||
|
(append (get s "subscribers") (list f))))))
|
||||||
|
(define
|
||||||
signal-remove-sub!
|
signal-remove-sub!
|
||||||
(fn
|
(fn
|
||||||
(s f)
|
(s f)
|
||||||
(dict-set!
|
(dict-set!
|
||||||
s
|
s
|
||||||
"subscribers"
|
"subscribers"
|
||||||
(filter (fn (sub) (not (identical? sub f))) (get s "subscribers")))))
|
(filter
|
||||||
|
(fn (sub) (not (identical? sub f)))
|
||||||
(define signal-deps (fn (s) (get s "deps")))
|
(get s "subscribers")))))
|
||||||
|
(define signal-deps (fn (s) (get s "deps")))
|
||||||
(define signal-set-deps! (fn (s deps) (dict-set! s "deps" deps)))
|
(define signal-set-deps! (fn (s deps) (dict-set! s "deps" deps)))
|
||||||
|
(define
|
||||||
(define
|
|
||||||
signal
|
signal
|
||||||
:effects ()
|
:effects ()
|
||||||
(fn ((initial-value :as any)) (make-signal initial-value)))
|
(fn ((initial-value :as any)) (make-signal initial-value)))
|
||||||
|
(define
|
||||||
(define
|
|
||||||
deref
|
deref
|
||||||
:effects ()
|
:effects ()
|
||||||
(fn
|
(fn
|
||||||
@@ -80,14 +83,14 @@
|
|||||||
(when
|
(when
|
||||||
ctx
|
ctx
|
||||||
(let
|
(let
|
||||||
((dep-list (get ctx "deps")) (notify-fn (get ctx "notify")))
|
{:notify notify-fn :deps dep-list}
|
||||||
|
ctx
|
||||||
(when
|
(when
|
||||||
(not (contains? dep-list s))
|
(not (contains? dep-list s))
|
||||||
(append! dep-list s)
|
(append! dep-list s)
|
||||||
(signal-add-sub! s notify-fn))))
|
(signal-add-sub! s notify-fn))))
|
||||||
(signal-value s)))))
|
(signal-value s)))))
|
||||||
|
(define
|
||||||
(define
|
|
||||||
reset!
|
reset!
|
||||||
:effects (mutation)
|
:effects (mutation)
|
||||||
(fn
|
(fn
|
||||||
@@ -100,8 +103,7 @@
|
|||||||
(not (identical? old value))
|
(not (identical? old value))
|
||||||
(signal-set-value! s value)
|
(signal-set-value! s value)
|
||||||
(notify-subscribers s))))))
|
(notify-subscribers s))))))
|
||||||
|
(define
|
||||||
(define
|
|
||||||
swap!
|
swap!
|
||||||
:effects (mutation)
|
:effects (mutation)
|
||||||
(fn
|
(fn
|
||||||
@@ -115,8 +117,7 @@
|
|||||||
(not (identical? old new-val))
|
(not (identical? old new-val))
|
||||||
(signal-set-value! s new-val)
|
(signal-set-value! s new-val)
|
||||||
(notify-subscribers s))))))
|
(notify-subscribers s))))))
|
||||||
|
(define
|
||||||
(define
|
|
||||||
computed
|
computed
|
||||||
:effects (mutation)
|
:effects (mutation)
|
||||||
(fn
|
(fn
|
||||||
@@ -128,8 +129,7 @@
|
|||||||
(recompute)
|
(recompute)
|
||||||
(register-in-scope (fn () (dispose-computed s)))
|
(register-in-scope (fn () (dispose-computed s)))
|
||||||
s))))
|
s))))
|
||||||
|
(define
|
||||||
(define
|
|
||||||
effect
|
effect
|
||||||
:effects (mutation)
|
:effects (mutation)
|
||||||
(fn
|
(fn
|
||||||
@@ -143,12 +143,9 @@
|
|||||||
((dispose-fn (fn () (set! disposed true) (when cleanup-fn (cek-call cleanup-fn nil)) (for-each (fn ((dep :as signal)) (signal-remove-sub! dep run-effect)) deps) (set! deps (list)))))
|
((dispose-fn (fn () (set! disposed true) (when cleanup-fn (cek-call cleanup-fn nil)) (for-each (fn ((dep :as signal)) (signal-remove-sub! dep run-effect)) deps) (set! deps (list)))))
|
||||||
(register-in-scope dispose-fn)
|
(register-in-scope dispose-fn)
|
||||||
dispose-fn)))))
|
dispose-fn)))))
|
||||||
|
(define *batch-depth* 0)
|
||||||
(define *batch-depth* 0)
|
(define *batch-queue* (list))
|
||||||
|
(define
|
||||||
(define *batch-queue* (list))
|
|
||||||
|
|
||||||
(define
|
|
||||||
batch
|
batch
|
||||||
:effects (mutation)
|
:effects (mutation)
|
||||||
(fn
|
(fn
|
||||||
@@ -176,8 +173,7 @@
|
|||||||
(signal-subscribers s)))
|
(signal-subscribers s)))
|
||||||
queue)
|
queue)
|
||||||
(for-each (fn ((sub :as lambda)) (sub)) pending))))))
|
(for-each (fn ((sub :as lambda)) (sub)) pending))))))
|
||||||
|
(define
|
||||||
(define
|
|
||||||
notify-subscribers
|
notify-subscribers
|
||||||
:effects (mutation)
|
:effects (mutation)
|
||||||
(fn
|
(fn
|
||||||
@@ -186,15 +182,13 @@
|
|||||||
(> *batch-depth* 0)
|
(> *batch-depth* 0)
|
||||||
(when (not (contains? *batch-queue* s)) (append! *batch-queue* s))
|
(when (not (contains? *batch-queue* s)) (append! *batch-queue* s))
|
||||||
(flush-subscribers s))))
|
(flush-subscribers s))))
|
||||||
|
(define
|
||||||
(define
|
|
||||||
flush-subscribers
|
flush-subscribers
|
||||||
:effects (mutation)
|
:effects (mutation)
|
||||||
(fn
|
(fn
|
||||||
((s :as dict))
|
((s :as dict))
|
||||||
(for-each (fn (sub) (cek-call sub nil)) (signal-subscribers s))))
|
(for-each (fn (sub) (cek-call sub nil)) (signal-subscribers s))))
|
||||||
|
(define
|
||||||
(define
|
|
||||||
dispose-computed
|
dispose-computed
|
||||||
:effects (mutation)
|
:effects (mutation)
|
||||||
(fn
|
(fn
|
||||||
@@ -205,26 +199,21 @@
|
|||||||
(fn ((dep :as signal)) (signal-remove-sub! dep nil))
|
(fn ((dep :as signal)) (signal-remove-sub! dep nil))
|
||||||
(signal-deps s))
|
(signal-deps s))
|
||||||
(signal-set-deps! s (list)))))
|
(signal-set-deps! s (list)))))
|
||||||
|
(define
|
||||||
(define
|
|
||||||
with-island-scope
|
with-island-scope
|
||||||
:effects (mutation)
|
:effects (mutation)
|
||||||
(fn
|
(fn
|
||||||
((scope-fn :as lambda) (body-fn :as lambda))
|
((scope-fn :as lambda) (body-fn :as lambda))
|
||||||
(scope-push! "sx-island-scope" scope-fn)
|
(scope-push! "sx-island-scope" scope-fn)
|
||||||
(let ((result (body-fn))) (scope-pop! "sx-island-scope") result)))
|
(let ((result (body-fn))) (scope-pop! "sx-island-scope") result)))
|
||||||
|
(define
|
||||||
(define
|
|
||||||
register-in-scope
|
register-in-scope
|
||||||
:effects (mutation)
|
:effects (mutation)
|
||||||
(fn
|
(fn
|
||||||
((disposable :as lambda))
|
((disposable :as lambda))
|
||||||
(let
|
(let
|
||||||
((collector (scope-peek "sx-island-scope")))
|
((collector (scope-peek "sx-island-scope")))
|
||||||
(when collector (cek-call collector (list disposable))))))
|
(when collector (cek-call collector (list disposable)))))))) ;; end define-library
|
||||||
|
|
||||||
|
|
||||||
)) ;; end define-library
|
|
||||||
|
|
||||||
;; Re-export to global namespace for backward compatibility
|
;; Re-export to global namespace for backward compatibility
|
||||||
(import (sx signals))
|
(import (sx signals))
|
||||||
|
|||||||
@@ -40,7 +40,7 @@
|
|||||||
(when
|
(when
|
||||||
(starts-with? name "~")
|
(starts-with? name "~")
|
||||||
(when (not (contains? refs name)) (append! refs name)))))
|
(when (not (contains? refs name)) (append! refs name)))))
|
||||||
("list" (for-each (fn (item) (scan-refs-walk item refs)) node))
|
("list" (for-each (fn (child) (scan-refs-walk child refs)) node))
|
||||||
("dict"
|
("dict"
|
||||||
(for-each
|
(for-each
|
||||||
(fn (key) (scan-refs-walk (dict-get node key) refs))
|
(fn (key) (scan-refs-walk (dict-get node key) refs))
|
||||||
@@ -56,27 +56,16 @@
|
|||||||
(append! seen n)
|
(append! seen n)
|
||||||
(let
|
(let
|
||||||
((val (env-get env n)))
|
((val (env-get env n)))
|
||||||
(match
|
(cond
|
||||||
(type-of val)
|
(or (= (type-of val) "component") (= (type-of val) "island"))
|
||||||
("component"
|
|
||||||
(for-each
|
(for-each
|
||||||
(fn
|
(fn ((ref :as string)) (transitive-deps-walk ref seen env))
|
||||||
((ref :as string))
|
(scan-refs (component-body val)))
|
||||||
(transitive-deps-walk ref seen env))
|
(= (type-of val) "macro")
|
||||||
(scan-refs (component-body val))))
|
|
||||||
("island"
|
|
||||||
(for-each
|
(for-each
|
||||||
(fn
|
(fn ((ref :as string)) (transitive-deps-walk ref seen env))
|
||||||
((ref :as string))
|
(scan-refs (macro-body val)))
|
||||||
(transitive-deps-walk ref seen env))
|
:else nil)))))
|
||||||
(scan-refs (component-body val))))
|
|
||||||
("macro"
|
|
||||||
(for-each
|
|
||||||
(fn
|
|
||||||
((ref :as string))
|
|
||||||
(transitive-deps-walk ref seen env))
|
|
||||||
(scan-refs (macro-body val))))
|
|
||||||
(_ nil))))))
|
|
||||||
(define
|
(define
|
||||||
transitive-deps
|
transitive-deps
|
||||||
:effects ()
|
:effects ()
|
||||||
@@ -216,9 +205,8 @@
|
|||||||
(append! seen n)
|
(append! seen n)
|
||||||
(let
|
(let
|
||||||
((val (env-get env n)))
|
((val (env-get env n)))
|
||||||
(match
|
(cond
|
||||||
(type-of val)
|
(= (type-of val) "component")
|
||||||
("component"
|
|
||||||
(do
|
(do
|
||||||
(for-each
|
(for-each
|
||||||
(fn
|
(fn
|
||||||
@@ -231,8 +219,8 @@
|
|||||||
(fn
|
(fn
|
||||||
((dep :as string))
|
((dep :as string))
|
||||||
(transitive-io-refs-walk dep seen all-refs env io-names))
|
(transitive-io-refs-walk dep seen all-refs env io-names))
|
||||||
(scan-refs (component-body val)))))
|
(scan-refs (component-body val))))
|
||||||
("macro"
|
(= (type-of val) "macro")
|
||||||
(do
|
(do
|
||||||
(for-each
|
(for-each
|
||||||
(fn
|
(fn
|
||||||
@@ -245,8 +233,8 @@
|
|||||||
(fn
|
(fn
|
||||||
((dep :as string))
|
((dep :as string))
|
||||||
(transitive-io-refs-walk dep seen all-refs env io-names))
|
(transitive-io-refs-walk dep seen all-refs env io-names))
|
||||||
(scan-refs (macro-body val)))))
|
(scan-refs (macro-body val))))
|
||||||
(_ nil))))))
|
:else nil)))))
|
||||||
(define
|
(define
|
||||||
transitive-io-refs
|
transitive-io-refs
|
||||||
:effects ()
|
:effects ()
|
||||||
@@ -318,15 +306,16 @@
|
|||||||
(if
|
(if
|
||||||
(not (= (type-of val) "component"))
|
(not (= (type-of val) "component"))
|
||||||
"server"
|
"server"
|
||||||
(match
|
(let
|
||||||
(component-affinity val)
|
((affinity (component-affinity val)))
|
||||||
("server" "server")
|
(cond
|
||||||
("client" "client")
|
(= affinity "server")
|
||||||
(_
|
"server"
|
||||||
(if
|
(= affinity "client")
|
||||||
|
"client"
|
||||||
(not (component-pure? name env io-names))
|
(not (component-pure? name env io-names))
|
||||||
"server"
|
"server"
|
||||||
"client"))))))))
|
:else "client")))))))
|
||||||
(define
|
(define
|
||||||
page-render-plan
|
page-render-plan
|
||||||
:effects ()
|
:effects ()
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -21,7 +21,8 @@
|
|||||||
|
|
||||||
;; Registry of freeze scopes: name → list of {name signal} entries
|
;; Registry of freeze scopes: name → list of {name signal} entries
|
||||||
|
|
||||||
(define-library (sx freeze)
|
(define-library
|
||||||
|
(sx freeze)
|
||||||
(export
|
(export
|
||||||
freeze-registry
|
freeze-registry
|
||||||
freeze-signal
|
freeze-signal
|
||||||
@@ -33,82 +34,96 @@
|
|||||||
freeze-to-sx
|
freeze-to-sx
|
||||||
thaw-from-sx)
|
thaw-from-sx)
|
||||||
(begin
|
(begin
|
||||||
|
(define freeze-registry (dict))
|
||||||
(define freeze-registry (dict))
|
(define
|
||||||
|
freeze-signal
|
||||||
;; Register a signal in the current freeze scope
|
:effects (mutation)
|
||||||
(define freeze-signal :effects [mutation]
|
(fn
|
||||||
(fn (name sig)
|
(name sig)
|
||||||
(let ((scope-name (context "sx-freeze-scope" nil)))
|
(let
|
||||||
(when scope-name
|
((scope-name (context "sx-freeze-scope" nil)))
|
||||||
(let ((entries (or (get freeze-registry scope-name) (list))))
|
(when
|
||||||
|
scope-name
|
||||||
|
(let
|
||||||
|
((entries (or (get freeze-registry scope-name) (list))))
|
||||||
(append! entries (dict "name" name "signal" sig))
|
(append! entries (dict "name" name "signal" sig))
|
||||||
(dict-set! freeze-registry scope-name entries))))))
|
(dict-set! freeze-registry scope-name entries))))))
|
||||||
|
(define
|
||||||
;; Freeze scope delimiter — collects signals registered within body
|
freeze-scope
|
||||||
(define freeze-scope :effects [mutation]
|
:effects (mutation)
|
||||||
(fn (name body-fn)
|
(fn
|
||||||
|
(name body-fn)
|
||||||
(scope-push! "sx-freeze-scope" name)
|
(scope-push! "sx-freeze-scope" name)
|
||||||
;; Initialize empty entry list for this scope
|
|
||||||
(dict-set! freeze-registry name (list))
|
(dict-set! freeze-registry name (list))
|
||||||
(cek-call body-fn nil)
|
(cek-call body-fn nil)
|
||||||
(scope-pop! "sx-freeze-scope")
|
(scope-pop! "sx-freeze-scope")
|
||||||
nil))
|
nil))
|
||||||
|
(define
|
||||||
;; Freeze a named scope → SX dict of signal values
|
cek-freeze-scope
|
||||||
(define cek-freeze-scope :effects []
|
:effects ()
|
||||||
(fn (name)
|
(fn
|
||||||
(let ((entries (or (get freeze-registry name) (list)))
|
(name)
|
||||||
|
(let
|
||||||
|
((entries (or (get freeze-registry name) (list)))
|
||||||
(signals-dict (dict)))
|
(signals-dict (dict)))
|
||||||
(for-each (fn (entry)
|
(for-each
|
||||||
(dict-set! signals-dict
|
(fn
|
||||||
|
(entry)
|
||||||
|
(dict-set!
|
||||||
|
signals-dict
|
||||||
(get entry "name")
|
(get entry "name")
|
||||||
(signal-value (get entry "signal"))))
|
(signal-value (get entry "signal"))))
|
||||||
entries)
|
entries)
|
||||||
(dict "name" name "signals" signals-dict))))
|
(dict "name" name "signals" signals-dict))))
|
||||||
|
(define
|
||||||
;; Freeze all scopes
|
cek-freeze-all
|
||||||
(define cek-freeze-all :effects []
|
:effects ()
|
||||||
(fn ()
|
(fn
|
||||||
(map (fn (name) (cek-freeze-scope name))
|
()
|
||||||
(keys freeze-registry))))
|
(map (fn (name) (cek-freeze-scope name)) (keys freeze-registry))))
|
||||||
|
(define
|
||||||
;; Thaw a named scope — restore signal values from frozen data
|
cek-thaw-scope
|
||||||
(define cek-thaw-scope :effects [mutation]
|
:effects (mutation)
|
||||||
(fn (name frozen)
|
(fn
|
||||||
(let ((entries (or (get freeze-registry name) (list)))
|
(name frozen)
|
||||||
|
(let
|
||||||
|
((entries (or (get freeze-registry name) (list)))
|
||||||
(values (get frozen "signals")))
|
(values (get frozen "signals")))
|
||||||
(when values
|
(when
|
||||||
(for-each (fn (entry)
|
values
|
||||||
(let ((sig-name (get entry "name"))
|
(for-each
|
||||||
|
(fn
|
||||||
|
(entry)
|
||||||
|
(let
|
||||||
|
((sig-name (get entry "name"))
|
||||||
(sig (get entry "signal"))
|
(sig (get entry "signal"))
|
||||||
(val (get values sig-name)))
|
(val (get values sig-name)))
|
||||||
(when (not (nil? val))
|
(when (not (nil? val)) (reset! sig val))))
|
||||||
(reset! sig val))))
|
|
||||||
entries)))))
|
entries)))))
|
||||||
|
(define
|
||||||
;; Thaw all scopes from a list of frozen scope dicts
|
cek-thaw-all
|
||||||
(define cek-thaw-all :effects [mutation]
|
:effects (mutation)
|
||||||
(fn (frozen-list)
|
(fn
|
||||||
(for-each (fn (frozen)
|
(frozen-list)
|
||||||
(cek-thaw-scope (get frozen "name") frozen))
|
(for-each
|
||||||
|
(fn (frozen) (cek-thaw-scope (get frozen "name") frozen))
|
||||||
frozen-list)))
|
frozen-list)))
|
||||||
|
(define
|
||||||
;; Serialize a frozen scope to SX text
|
freeze-to-sx
|
||||||
(define freeze-to-sx :effects []
|
:effects ()
|
||||||
(fn (name)
|
(fn (name) (sx-serialize (cek-freeze-scope name))))
|
||||||
(sx-serialize (cek-freeze-scope name))))
|
(define
|
||||||
|
thaw-from-sx
|
||||||
;; Restore from SX text
|
:effects (mutation)
|
||||||
(define thaw-from-sx :effects [mutation]
|
(fn
|
||||||
(fn (sx-text)
|
(sx-text)
|
||||||
(let ((parsed (sx-parse sx-text)))
|
(let
|
||||||
(when (not (empty? parsed))
|
((parsed (sx-parse sx-text)))
|
||||||
(let ((frozen (first parsed)))
|
(when
|
||||||
(cek-thaw-scope (get frozen "name") frozen))))))
|
(not (empty? parsed))
|
||||||
|
(let
|
||||||
|
((frozen (first parsed)))
|
||||||
)) ;; end define-library
|
(cek-thaw-scope (get frozen "name") frozen)))))))) ;; end define-library
|
||||||
|
|
||||||
;; Re-export to global namespace for backward compatibility
|
;; Re-export to global namespace for backward compatibility
|
||||||
(import (sx freeze))
|
(import (sx freeze))
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
(sxbc 1 "320fb4826d09fed3"
|
(sxbc 1 "050ab6181dc93341"
|
||||||
(code
|
(code
|
||||||
:constants ("freeze-registry" "dict" "freeze-signal" {:upvalue-count 0 :arity 2 :constants ("context" "sx-freeze-scope" "get" "freeze-registry" "list" "append!" "dict" "name" "signal" "dict-set!") :bytecode (1 1 0 2 52 0 0 2 17 2 16 2 33 55 0 20 3 0 16 2 52 2 0 2 6 34 5 0 5 52 4 0 0 17 3 16 3 1 7 0 16 0 1 8 0 16 1 52 6 0 4 52 5 0 2 5 20 3 0 16 2 16 3 52 9 0 3 32 1 0 2 50)} "freeze-scope" {:upvalue-count 0 :arity 2 :constants ("scope-push!" "sx-freeze-scope" "dict-set!" "freeze-registry" "list" "cek-call" "scope-pop!") :bytecode (1 1 0 16 0 52 0 0 2 5 20 3 0 16 0 52 4 0 0 52 2 0 3 5 16 1 2 52 5 0 2 5 1 1 0 52 6 0 1 5 2 50)} "cek-freeze-scope" {:upvalue-count 0 :arity 1 :constants ("get" "freeze-registry" "list" "dict" "for-each" {:upvalue-count 1 :arity 1 :constants ("dict-set!" "get" "name" "signal-value" "signal") :bytecode (18 0 16 0 1 2 0 52 1 0 2 20 3 0 16 0 1 4 0 52 1 0 2 48 1 52 0 0 3 50)} "name" "signals") :bytecode (20 1 0 16 0 52 0 0 2 6 34 5 0 5 52 2 0 0 17 1 52 3 0 0 17 2 51 5 0 1 2 16 1 52 4 0 2 5 1 6 0 16 0 1 7 0 16 2 52 3 0 4 50)} "cek-freeze-all" {:upvalue-count 0 :arity 0 :constants ("map" {:upvalue-count 0 :arity 1 :constants ("cek-freeze-scope") :bytecode (20 0 0 16 0 49 1 50)} "keys" "freeze-registry") :bytecode (51 1 0 20 3 0 52 2 0 1 52 0 0 2 50)} "cek-thaw-scope" {:upvalue-count 0 :arity 2 :constants ("get" "freeze-registry" "list" "signals" "for-each" {:upvalue-count 1 :arity 1 :constants ("get" "name" "signal" "not" "nil?" "reset!") :bytecode (16 0 1 1 0 52 0 0 2 17 1 16 0 1 2 0 52 0 0 2 17 2 18 0 16 1 52 0 0 2 17 3 16 3 52 4 0 1 52 3 0 1 33 12 0 20 5 0 16 2 16 3 49 2 32 1 0 2 50)}) :bytecode (20 1 0 16 0 52 0 0 2 6 34 5 0 5 52 2 0 0 17 2 16 1 1 3 0 52 0 0 2 17 3 16 3 33 14 0 51 5 0 1 3 16 2 52 4 0 2 32 1 0 2 50)} "cek-thaw-all" {:upvalue-count 0 :arity 1 :constants ("for-each" {:upvalue-count 0 :arity 1 :constants ("cek-thaw-scope" "get" "name") :bytecode (20 0 0 16 0 1 2 0 52 1 0 2 16 0 49 2 50)}) :bytecode (51 1 0 16 0 52 0 0 2 50)} "freeze-to-sx" {:upvalue-count 0 :arity 1 :constants ("sx-serialize" "cek-freeze-scope") :bytecode (20 1 0 16 0 48 1 52 0 0 1 50)} "thaw-from-sx" {:upvalue-count 0 :arity 1 :constants ("sx-parse" "not" "empty?" "first" "cek-thaw-scope" "get" "name") :bytecode (20 0 0 16 0 48 1 17 1 16 1 52 2 0 1 52 1 0 1 33 27 0 16 1 52 3 0 1 17 2 20 4 0 16 2 1 6 0 52 5 0 2 16 2 49 2 32 1 0 2 50)} {:library (sx freeze) :op "import"}) :bytecode (52 1 0 0 128 0 0 5 51 3 0 128 2 0 5 51 5 0 128 4 0 5 51 7 0 128 6 0 5 51 9 0 128 8 0 5 51 11 0 128 10 0 5 51 13 0 128 12 0 5 51 15 0 128 14 0 5 51 17 0 128 16 0 5 1 18 0 112 50)))
|
:constants ("freeze-registry" "dict" "freeze-signal" {:upvalue-count 0 :arity 2 :constants ("context" "sx-freeze-scope" "get" "freeze-registry" "list" "append!" "dict" "name" "signal" "dict-set!") :bytecode (1 1 0 2 52 0 0 2 17 2 16 2 33 55 0 20 3 0 16 2 52 2 0 2 6 34 5 0 5 52 4 0 0 17 3 16 3 1 7 0 16 0 1 8 0 16 1 52 6 0 4 52 5 0 2 5 20 3 0 16 2 16 3 52 9 0 3 32 1 0 2 50)} "freeze-scope" {:upvalue-count 0 :arity 2 :constants ("scope-push!" "sx-freeze-scope" "dict-set!" "freeze-registry" "list" "cek-call" "scope-pop!") :bytecode (1 1 0 16 0 52 0 0 2 5 20 3 0 16 0 52 4 0 0 52 2 0 3 5 16 1 2 52 5 0 2 5 1 1 0 52 6 0 1 5 2 50)} "cek-freeze-scope" {:upvalue-count 0 :arity 1 :constants ("get" "freeze-registry" "list" "dict" "for-each" {:upvalue-count 1 :arity 1 :constants ("dict-set!" "get" "name" "signal-value" "signal") :bytecode (18 0 16 0 1 2 0 52 1 0 2 20 3 0 16 0 1 4 0 52 1 0 2 48 1 52 0 0 3 50)} "name" "signals") :bytecode (20 1 0 16 0 52 0 0 2 6 34 5 0 5 52 2 0 0 17 1 52 3 0 0 17 2 51 5 0 1 2 16 1 52 4 0 2 5 1 6 0 16 0 1 7 0 16 2 52 3 0 4 50)} "cek-freeze-all" {:upvalue-count 0 :arity 0 :constants ("map" {:upvalue-count 0 :arity 1 :constants ("cek-freeze-scope") :bytecode (20 0 0 16 0 49 1 50)} "keys" "freeze-registry") :bytecode (51 1 0 20 3 0 52 2 0 1 52 0 0 2 50)} "cek-thaw-scope" {:upvalue-count 0 :arity 2 :constants ("get" "freeze-registry" "list" "signals" "for-each" {:upvalue-count 1 :arity 1 :constants ("get" "name" "signal" "not" "nil?" "reset!") :bytecode (16 0 1 1 0 52 0 0 2 17 1 16 0 1 2 0 52 0 0 2 17 2 18 0 16 1 52 0 0 2 17 3 16 3 52 4 0 1 52 3 0 1 33 12 0 20 5 0 16 2 16 3 49 2 32 1 0 2 50)}) :bytecode (20 1 0 16 0 52 0 0 2 6 34 5 0 5 52 2 0 0 17 2 16 1 1 3 0 52 0 0 2 17 3 16 3 33 14 0 51 5 0 1 3 16 2 52 4 0 2 32 1 0 2 50)} "cek-thaw-all" {:upvalue-count 0 :arity 1 :constants ("for-each" {:upvalue-count 0 :arity 1 :constants ("cek-thaw-scope" "get" "name") :bytecode (20 0 0 16 0 1 2 0 52 1 0 2 16 0 49 2 50)}) :bytecode (51 1 0 16 0 52 0 0 2 50)} "freeze-to-sx" {:upvalue-count 0 :arity 1 :constants ("sx-serialize" "cek-freeze-scope") :bytecode (20 1 0 16 0 48 1 52 0 0 1 50)} "thaw-from-sx" {:upvalue-count 0 :arity 1 :constants ("sx-parse" "not" "empty?" "first" "cek-thaw-scope" "get" "name") :bytecode (20 0 0 16 0 48 1 17 1 16 1 52 2 0 1 52 1 0 1 33 27 0 16 1 52 3 0 1 17 2 20 4 0 16 2 1 6 0 52 5 0 2 16 2 49 2 32 1 0 2 50)} {:library (sx freeze) :op "import"}) :bytecode (52 1 0 0 128 0 0 5 51 3 0 128 2 0 5 51 5 0 128 4 0 5 51 7 0 128 6 0 5 51 9 0 128 8 0 5 51 11 0 128 10 0 5 51 13 0 128 12 0 5 51 15 0 128 14 0 5 51 17 0 128 16 0 5 1 18 0 112 50)))
|
||||||
|
|||||||
@@ -79,35 +79,35 @@
|
|||||||
(fn
|
(fn
|
||||||
(vm value)
|
(vm value)
|
||||||
(let
|
(let
|
||||||
((sp (get vm "sp")) (stack (get vm "stack")))
|
((sp (vm-sp vm)) (stack (vm-stack vm)))
|
||||||
(when
|
(when
|
||||||
(>= sp (vm-stack-length stack))
|
(>= sp (vm-stack-length stack))
|
||||||
(let
|
(let
|
||||||
((new-stack (make-vm-stack (* sp 2))))
|
((new-stack (vm-stack-grow stack sp)))
|
||||||
(vm-stack-copy! stack new-stack sp)
|
(vm-stack-copy! stack new-stack sp)
|
||||||
(dict-set! vm "stack" new-stack)
|
(vm-set-stack! vm new-stack)
|
||||||
(set! stack new-stack)))
|
(set! stack new-stack)))
|
||||||
(vm-stack-set! stack sp value)
|
(vm-stack-set! stack sp value)
|
||||||
(dict-set! vm "sp" (+ sp 1)))))
|
(vm-set-sp! vm (+ sp 1)))))
|
||||||
(define
|
(define
|
||||||
vm-pop
|
vm-pop
|
||||||
(fn
|
(fn
|
||||||
(vm)
|
(vm)
|
||||||
(let
|
(let
|
||||||
((sp (- (get vm "sp") 1)))
|
((sp (- (vm-sp vm) 1)))
|
||||||
(dict-set! vm "sp" sp)
|
(vm-set-sp! vm sp)
|
||||||
(vm-stack-get (get vm "stack") sp))))
|
(vm-stack-get (vm-stack vm) sp))))
|
||||||
(define
|
(define
|
||||||
vm-peek
|
vm-peek
|
||||||
(fn (vm) (vm-stack-get (get vm "stack") (- (get vm "sp") 1))))
|
(fn (vm) (vm-stack-get (vm-stack vm) (- (vm-sp vm) 1))))
|
||||||
(define
|
(define
|
||||||
frame-read-u8
|
frame-read-u8
|
||||||
(fn
|
(fn
|
||||||
(frame)
|
(frame)
|
||||||
(let
|
(let
|
||||||
((ip (get frame "ip"))
|
((ip (frame-ip frame))
|
||||||
(bc (get (get (get frame "closure") "vm-code") "vc-bytecode")))
|
(bc (-> frame frame-closure closure-code code-bytecode)))
|
||||||
(let ((v (nth bc ip))) (dict-set! frame "ip" (+ ip 1)) v))))
|
(let ((v (nth bc ip))) (frame-set-ip! frame (+ ip 1)) v))))
|
||||||
(define
|
(define
|
||||||
frame-read-u16
|
frame-read-u16
|
||||||
(fn
|
(fn
|
||||||
@@ -206,31 +206,28 @@
|
|||||||
(if
|
(if
|
||||||
(has-key? cells key)
|
(has-key? cells key)
|
||||||
(uv-get (get cells key))
|
(uv-get (get cells key))
|
||||||
(vm-stack-get (get vm "stack") (+ (get frame "base") slot))))))
|
(vm-stack-get (vm-stack vm) (+ (frame-base frame) slot))))))
|
||||||
(define
|
(define
|
||||||
frame-local-set
|
frame-local-set
|
||||||
(fn
|
(fn
|
||||||
(vm frame slot value)
|
(vm frame slot value)
|
||||||
"Write a local variable — to shared cell if captured, else to stack."
|
"Write a local variable — to shared cell or stack."
|
||||||
(let
|
(let
|
||||||
((cells (get frame "local-cells")) (key (str slot)))
|
((cells (get frame "local-cells")) (key (str slot)))
|
||||||
(if
|
(if
|
||||||
(has-key? cells key)
|
(has-key? cells key)
|
||||||
(uv-set! (get cells key) value)
|
(uv-set! (get cells key) value)
|
||||||
(vm-stack-set!
|
(vm-stack-set! (vm-stack vm) (+ (frame-base frame) slot) value)))))
|
||||||
(get vm "stack")
|
|
||||||
(+ (get frame "base") slot)
|
|
||||||
value)))))
|
|
||||||
(define
|
(define
|
||||||
frame-upvalue-get
|
frame-upvalue-get
|
||||||
(fn
|
(fn
|
||||||
(frame idx)
|
(frame idx)
|
||||||
(uv-get (nth (get (get frame "closure") "vm-upvalues") idx))))
|
(uv-get (nth (-> frame frame-closure closure-upvalues) idx))))
|
||||||
(define
|
(define
|
||||||
frame-upvalue-set
|
frame-upvalue-set
|
||||||
(fn
|
(fn
|
||||||
(frame idx value)
|
(frame idx value)
|
||||||
(uv-set! (nth (get (get frame "closure") "vm-upvalues") idx) value)))
|
(uv-set! (nth (-> frame frame-closure closure-upvalues) idx) value)))
|
||||||
(define frame-ip (fn (frame) (get frame "ip")))
|
(define frame-ip (fn (frame) (get frame "ip")))
|
||||||
(define frame-set-ip! (fn (frame val) (dict-set! frame "ip" val)))
|
(define frame-set-ip! (fn (frame val) (dict-set! frame "ip" val)))
|
||||||
(define frame-base (fn (frame) (get frame "base")))
|
(define frame-base (fn (frame) (get frame "base")))
|
||||||
@@ -302,12 +299,12 @@
|
|||||||
(vm frame name)
|
(vm frame name)
|
||||||
"Look up a global: globals table → closure env → primitives → HO wrappers"
|
"Look up a global: globals table → closure env → primitives → HO wrappers"
|
||||||
(let
|
(let
|
||||||
((globals (get vm "globals")))
|
((globals (vm-globals-ref vm)))
|
||||||
(if
|
(if
|
||||||
(has-key? globals name)
|
(has-key? globals name)
|
||||||
(get globals name)
|
(get globals name)
|
||||||
(let
|
(let
|
||||||
((closure-env (get (get frame "closure") "closure-env")))
|
((closure-env (-> frame frame-closure closure-env)))
|
||||||
(if
|
(if
|
||||||
(nil? closure-env)
|
(nil? closure-env)
|
||||||
(cek-try
|
(cek-try
|
||||||
@@ -325,41 +322,42 @@
|
|||||||
vm-resolve-ho-form
|
vm-resolve-ho-form
|
||||||
(fn
|
(fn
|
||||||
(vm name)
|
(vm name)
|
||||||
(cond
|
(match
|
||||||
(= name "for-each")
|
name
|
||||||
|
("for-each"
|
||||||
(fn
|
(fn
|
||||||
(f coll)
|
(f coll)
|
||||||
(for-each (fn (x) (vm-call-external vm f (list x))) coll))
|
(for-each (fn (x) (vm-call-external vm f (list x))) coll)))
|
||||||
(= name "map")
|
("map"
|
||||||
(fn
|
(fn
|
||||||
(f coll)
|
(f coll)
|
||||||
(map (fn (x) (vm-call-external vm f (list x))) coll))
|
(map (fn (x) (vm-call-external vm f (list x))) coll)))
|
||||||
(= name "map-indexed")
|
("map-indexed"
|
||||||
(fn
|
(fn
|
||||||
(f coll)
|
(f coll)
|
||||||
(map-indexed
|
(map-indexed
|
||||||
(fn (i x) (vm-call-external vm f (list i x)))
|
(fn (i x) (vm-call-external vm f (list i x)))
|
||||||
coll))
|
coll)))
|
||||||
(= name "filter")
|
("filter"
|
||||||
(fn
|
(fn
|
||||||
(f coll)
|
(f coll)
|
||||||
(filter (fn (x) (vm-call-external vm f (list x))) coll))
|
(filter (fn (x) (vm-call-external vm f (list x))) coll)))
|
||||||
(= name "reduce")
|
("reduce"
|
||||||
(fn
|
(fn
|
||||||
(f init coll)
|
(f init coll)
|
||||||
(reduce
|
(reduce
|
||||||
(fn (acc x) (vm-call-external vm f (list acc x)))
|
(fn (acc x) (vm-call-external vm f (list acc x)))
|
||||||
init
|
init
|
||||||
coll))
|
coll)))
|
||||||
(= name "some")
|
("some"
|
||||||
(fn
|
(fn
|
||||||
(f coll)
|
(f coll)
|
||||||
(some (fn (x) (vm-call-external vm f (list x))) coll))
|
(some (fn (x) (vm-call-external vm f (list x))) coll)))
|
||||||
(= name "every?")
|
("every?"
|
||||||
(fn
|
(fn
|
||||||
(f coll)
|
(f coll)
|
||||||
(every? (fn (x) (vm-call-external vm f (list x))) coll))
|
(every? (fn (x) (vm-call-external vm f (list x))) coll)))
|
||||||
:else (error (str "VM undefined: " name)))))
|
(_ (error (str "VM undefined: " name))))))
|
||||||
(define
|
(define
|
||||||
vm-call-external
|
vm-call-external
|
||||||
(fn
|
(fn
|
||||||
@@ -372,14 +370,14 @@
|
|||||||
vm-global-set
|
vm-global-set
|
||||||
(fn
|
(fn
|
||||||
(vm frame name value)
|
(vm frame name value)
|
||||||
"Set a global: write to closure env if name exists there, else globals."
|
"Set a global: write to closure env if found, else globals table."
|
||||||
(let
|
(let
|
||||||
((closure-env (get (get frame "closure") "vm-closure-env"))
|
((closure-env (get (frame-closure frame) "vm-closure-env"))
|
||||||
(written false))
|
(written false))
|
||||||
(when
|
(when
|
||||||
(not (nil? closure-env))
|
(not (nil? closure-env))
|
||||||
(set! written (env-walk-set! closure-env name value)))
|
(set! written (env-walk-set! closure-env name value)))
|
||||||
(when (not written) (dict-set! (get vm "globals") name value)))))
|
(when (not written) (dict-set! (vm-globals-ref vm) name value)))))
|
||||||
(define
|
(define
|
||||||
env-walk
|
env-walk
|
||||||
(fn
|
(fn
|
||||||
@@ -414,20 +412,15 @@
|
|||||||
(let
|
(let
|
||||||
((code (code-from-value code-val))
|
((code (code-from-value code-val))
|
||||||
(uv-count
|
(uv-count
|
||||||
(if
|
(if (dict? code-val) (or (get code-val "upvalue-count") 0) 0)))
|
||||||
(dict? code-val)
|
|
||||||
(let
|
(let
|
||||||
((n (get code-val "upvalue-count")))
|
((upvalues (let ((result (list)) (i 0)) (define capture-loop (fn () (when (< i uv-count) (let ((is-local (frame-read-u8 frame)) (index (frame-read-u8 frame))) (let ((cell (if (= is-local 1) (let ((cells (get frame "local-cells")) (key (str index))) (if (has-key? cells key) (get cells key) (let ((c (make-upvalue-cell (vm-stack-get (vm-stack vm) (+ (frame-base frame) index))))) (dict-set! cells key c) c))) (nth (-> frame frame-closure closure-upvalues) index)))) (append! result cell) (set! i (+ i 1)) (capture-loop)))))) (capture-loop) result)))
|
||||||
(if (nil? n) 0 n))
|
(make-vm-closure code upvalues nil (vm-globals-ref vm) nil)))))
|
||||||
0)))
|
|
||||||
(let
|
|
||||||
((upvalues (let ((result (list)) (i 0)) (define capture-loop (fn () (when (< i uv-count) (let ((is-local (frame-read-u8 frame)) (index (frame-read-u8 frame))) (let ((cell (if (= is-local 1) (let ((cells (get frame "local-cells")) (key (str index))) (if (has-key? cells key) (get cells key) (let ((c (make-upvalue-cell (vm-stack-get (get vm "stack") (+ (get frame "base") index))))) (dict-set! cells key c) c))) (nth (get (get frame "closure") "vm-upvalues") index)))) (append! result cell) (set! i (+ i 1)) (capture-loop)))))) (capture-loop) result)))
|
|
||||||
(make-vm-closure code upvalues nil (get vm "globals") nil)))))
|
|
||||||
(define
|
(define
|
||||||
vm-run
|
vm-run
|
||||||
(fn
|
(fn
|
||||||
(vm)
|
(vm)
|
||||||
"Execute bytecode until all frames are consumed."
|
"Execute bytecode until all frames are done or IO suspension."
|
||||||
(define
|
(define
|
||||||
loop
|
loop
|
||||||
(fn
|
(fn
|
||||||
@@ -438,9 +431,9 @@
|
|||||||
((frame (first (vm-frames vm)))
|
((frame (first (vm-frames vm)))
|
||||||
(rest-frames (rest (vm-frames vm))))
|
(rest-frames (rest (vm-frames vm))))
|
||||||
(let
|
(let
|
||||||
((bc (code-bytecode (closure-code (frame-closure frame))))
|
((bc (-> frame frame-closure closure-code code-bytecode))
|
||||||
(consts
|
(consts
|
||||||
(code-constants (closure-code (frame-closure frame)))))
|
(-> frame frame-closure closure-code code-constants)))
|
||||||
(if
|
(if
|
||||||
(>= (frame-ip frame) (len bc))
|
(>= (frame-ip frame) (len bc))
|
||||||
(vm-set-frames! vm (list))
|
(vm-set-frames! vm (list))
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -1792,7 +1792,7 @@
|
|||||||
blake2_js_for_wasm_create: blake2_js_for_wasm_create};
|
blake2_js_for_wasm_create: blake2_js_for_wasm_create};
|
||||||
}
|
}
|
||||||
(globalThis))
|
(globalThis))
|
||||||
({"link":[["runtime-0db9b496",0],["prelude-d7e4b000",0],["stdlib-23ce0836",[]],["sx-d4b9c764",[2]],["jsoo_runtime-f96b44a8",[2]],["js_of_ocaml-651f6707",[2,4]],["dune__exe__Sx_browser-ba5b5565",[2,3,5]],["std_exit-10fb8830",[2]],["start-f5d3f095",0]],"generated":(b=>{var
|
({"link":[["runtime-0db9b496",0],["prelude-d7e4b000",0],["stdlib-23ce0836",[]],["sx-90abc6ab",[2]],["jsoo_runtime-f96b44a8",[2]],["js_of_ocaml-651f6707",[2,4]],["dune__exe__Sx_browser-216e88df",[2,3,5]],["std_exit-10fb8830",[2]],["start-f5d3f095",0]],"generated":(b=>{var
|
||||||
c=b,a=b?.module?.export||b;return{"env":{"caml_ba_kind_of_typed_array":()=>{throw new
|
c=b,a=b?.module?.export||b;return{"env":{"caml_ba_kind_of_typed_array":()=>{throw new
|
||||||
Error("caml_ba_kind_of_typed_array not implemented")},"caml_exn_with_js_backtrace":()=>{throw new
|
Error("caml_ba_kind_of_typed_array not implemented")},"caml_exn_with_js_backtrace":()=>{throw new
|
||||||
Error("caml_exn_with_js_backtrace not implemented")},"caml_int64_create_lo_mi_hi":()=>{throw new
|
Error("caml_exn_with_js_backtrace not implemented")},"caml_int64_create_lo_mi_hi":()=>{throw new
|
||||||
|
|||||||
Reference in New Issue
Block a user