JIT allowlist + integration tests + --test mode + clean up debug logging
JIT allowlist (sx_server.ml): - Replace try-every-lambda strategy with StringSet allowlist. Only functions in the list get JIT compiled (compiler, parser, pure transforms). Render functions that need dynamic scope skip JIT entirely — no retry overhead, no silent fallbacks. - Add (jit-allow name) command for dynamic expansion from Python bridge. - JIT failures log once with "[jit] DISABLED fn — reason" then go silent. Standalone --test mode (sx_server.ml): - New --test flag loads full env (spec + adapters + compiler + signals), supports --eval and --load flags. Quick kernel testing without Docker. Example: dune exec bin/sx_server.exe -- --test --eval '(len HTML_TAGS)' Integration tests (integration_tests.ml): - New binary exercising the full rendering pipeline: loads spec + adapters into a server-like env, renders HTML via both native and SX adapter paths. - 26 tests: HTML tags, special forms (when/if/let), letrec with side effects, component rendering, eval-expr with HTML tag functions. - Would have caught the "Undefined symbol: div/lake/init" issues from the previous commit immediately without Docker. VM cleanup (sx_vm.ml): - Remove temporary debug logging (insn counter, call_closure counter, VmClosure depth tracking) added during debugging. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -1440,11 +1440,12 @@
|
||||
(make-cek-value (sf-lambda args env) env kont)))
|
||||
|
||||
;; scope: evaluate name, then push ScopeFrame
|
||||
;; scope/provide/context/emit!/emitted — ALL use hashtable stacks.
|
||||
;; One world: the aser and CEK share the same scope mechanism.
|
||||
;; No continuation frame walking — scope-push!/pop!/peek are the primitives.
|
||||
;; scope/provide/context/emit!/emitted — CEK frame-based.
|
||||
;; provide/scope push proper CEK frames onto the continuation so that
|
||||
;; shift/reset can capture and restore them correctly.
|
||||
;; context/emit!/emitted walk the kont to find the relevant frame.
|
||||
|
||||
;; scope: push scope, evaluate body, pop scope.
|
||||
;; scope: push ScopeAccFrame, evaluate body expressions via continuation.
|
||||
;; (scope name body...) or (scope name :value v body...)
|
||||
(define step-sf-scope
|
||||
(fn (args env kont)
|
||||
@@ -1458,48 +1459,50 @@
|
||||
(do (set! val (trampoline (eval-expr (nth rest-args 1) env)))
|
||||
(set! body (slice rest-args 2)))
|
||||
(set! body rest-args))
|
||||
(scope-push! name val)
|
||||
(let ((result nil))
|
||||
(for-each (fn (expr) (set! result (trampoline (eval-expr expr env)))) body)
|
||||
(scope-pop! name)
|
||||
(make-cek-value result env kont)))))
|
||||
(if (empty? body)
|
||||
(make-cek-value nil env kont)
|
||||
(make-cek-state
|
||||
(first body) env
|
||||
(kont-push (make-scope-acc-frame name val (rest body) env) kont))))))
|
||||
|
||||
;; provide: sugar for scope with value.
|
||||
;; provide: push ProvideFrame, evaluate body expressions via continuation.
|
||||
(define step-sf-provide
|
||||
(fn (args env kont)
|
||||
(let ((name (trampoline (eval-expr (first args) env)))
|
||||
(val (trampoline (eval-expr (nth args 1) env)))
|
||||
(body (slice args 2)))
|
||||
(scope-push! name val)
|
||||
(let ((result nil))
|
||||
(for-each (fn (expr) (set! result (trampoline (eval-expr expr env)))) body)
|
||||
(scope-pop! name)
|
||||
(make-cek-value result env kont)))))
|
||||
(if (empty? body)
|
||||
(make-cek-value nil env kont)
|
||||
(make-cek-state
|
||||
(first body) env
|
||||
(kont-push (make-provide-frame name val (rest body) env) kont))))))
|
||||
|
||||
;; context: read from scope stack.
|
||||
;; context: walk kont for nearest ProvideFrame with matching name.
|
||||
(define step-sf-context
|
||||
(fn (args env kont)
|
||||
(let ((name (trampoline (eval-expr (first args) env)))
|
||||
(default-val (if (>= (len args) 2)
|
||||
(trampoline (eval-expr (nth args 1) env))
|
||||
nil))
|
||||
(val (scope-peek name)))
|
||||
(make-cek-value (if (nil? val) default-val val) env kont))))
|
||||
(frame (kont-find-provide kont name)))
|
||||
(make-cek-value (if (nil? frame) default-val (get frame "value")) env kont))))
|
||||
|
||||
;; emit!: append to scope accumulator.
|
||||
;; emit!: walk kont for nearest ScopeAccFrame, append to its emitted list.
|
||||
(define step-sf-emit
|
||||
(fn (args env kont)
|
||||
(let ((name (trampoline (eval-expr (first args) env)))
|
||||
(val (trampoline (eval-expr (nth args 1) env))))
|
||||
(scope-emit! name val)
|
||||
(val (trampoline (eval-expr (nth args 1) env)))
|
||||
(frame (kont-find-scope-acc kont name)))
|
||||
(when frame
|
||||
(dict-set! frame "emitted" (append (get frame "emitted") (list val))))
|
||||
(make-cek-value nil env kont))))
|
||||
|
||||
;; emitted: read accumulated scope values.
|
||||
;; emitted: walk kont for nearest ScopeAccFrame, return its emitted list.
|
||||
(define step-sf-emitted
|
||||
(fn (args env kont)
|
||||
(let ((name (trampoline (eval-expr (first args) env)))
|
||||
(val (scope-peek name)))
|
||||
(make-cek-value (if (nil? val) (list) val) env kont))))
|
||||
(frame (kont-find-scope-acc kont name)))
|
||||
(make-cek-value (if (nil? frame) (list) (get frame "emitted")) env kont))))
|
||||
|
||||
;; reset: push ResetFrame, evaluate body
|
||||
(define step-sf-reset
|
||||
|
||||
Reference in New Issue
Block a user