Lambda→CEK dispatch: enable IO suspension through sx_call

Lambda calls in sx_call now go through the CEK machine instead of
returning a Thunk for the tree-walker trampoline. This lets perform/
IO suspension work everywhere — including hyperscript wait/bounce.

Key changes:
- sx_runtime: Lambda case calls _cek_eval_lambda_ref (forward ref)
- sx_vm: initializes ref with cek_step_loop + stub VM for suspension
- sx_apply_cek: VmSuspended → __vm_suspended marker dict (not exception)
- continue_with_call callable path: handles __vm_suspended with
  vm-resume-frame, matching the existing JIT Lambda pattern
- sx_render: let VmSuspended propagate through try_catch
- Remove invalid io-contract test (perform now suspends, not errors)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-08 16:19:30 +00:00
parent 23749773f2
commit 33e8788781
9 changed files with 2122 additions and 1829 deletions

View File

@@ -4248,14 +4248,19 @@
(not (component? f))
(not (island? f)))
(let
((result (apply-cek f args)))
(if
((result (sx-apply-cek f args)))
(cond
(eval-error? result)
(make-cek-value
(get result "message")
env
(kont-push (make-raise-eval-frame env false) kont))
(make-cek-value result env kont)))
(and (dict? result) (get result "__vm_suspended"))
(make-cek-suspended
(get result "request")
env
(kont-push (make-vm-resume-frame (get result "resume") env) kont))
:else (make-cek-value result env kont)))
(lambda? f)
(let
((params (lambda-params f))

View File

@@ -84,18 +84,4 @@
(try-catch
(fn () (io "totally-unknown-op-xyz"))
(fn (err) (set! caught true)))
(assert caught)))
(deftest
"io suspends for registered operations"
(defio
"test-io-contract"
:category :data
:params ()
:returns "string"
:doc "Contract test.")
(let
((caught-msg ""))
(try-catch
(fn () (io "test-io-contract"))
(fn (err) (set! caught-msg err)))
(assert (not (string-contains? caught-msg "unknown operation"))))))
(assert caught))))