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:
@@ -14,7 +14,7 @@
|
||||
// =========================================================================
|
||||
|
||||
var NIL = Object.freeze({ _nil: true, toString: function() { return "nil"; } });
|
||||
var SX_VERSION = "2026-03-23T23:36:04Z";
|
||||
var SX_VERSION = "2026-03-23T23:55:49Z";
|
||||
|
||||
function isNil(x) { return x === NIL || x === null || x === undefined; }
|
||||
function isSxTruthy(x) { return x !== false && !isNil(x); }
|
||||
@@ -512,7 +512,12 @@
|
||||
PRIMITIVES["emitted"] = sxEmitted;
|
||||
// Aliases for aser adapter (avoids CEK special form conflict on server)
|
||||
var scopeEmit = sxEmit;
|
||||
var scopePeek = sxEmitted;
|
||||
function scopePeek(name) {
|
||||
if (_scopeStacks[name] && _scopeStacks[name].length) {
|
||||
return _scopeStacks[name][_scopeStacks[name].length - 1].value;
|
||||
}
|
||||
return NIL;
|
||||
}
|
||||
PRIMITIVES["scope-emit!"] = scopeEmit;
|
||||
PRIMITIVES["scope-peek"] = scopePeek;
|
||||
|
||||
@@ -1589,13 +1594,7 @@ PRIMITIVES["step-sf-lambda"] = stepSfLambda;
|
||||
var val = NIL;
|
||||
var body = NIL;
|
||||
(isSxTruthy((isSxTruthy((len(restArgs) >= 2)) && isSxTruthy((typeOf(first(restArgs)) == "keyword")) && (keywordName(first(restArgs)) == "value"))) ? ((val = trampoline(evalExpr(nth(restArgs, 1), env))), (body = slice(restArgs, 2))) : (body = restArgs));
|
||||
scopePush(name, val);
|
||||
return (function() {
|
||||
var result = NIL;
|
||||
{ var _c = body; for (var _i = 0; _i < _c.length; _i++) { var expr = _c[_i]; result = trampoline(evalExpr(expr, env)); } }
|
||||
scopePop(name);
|
||||
return makeCekValue(result, env, kont);
|
||||
})();
|
||||
return (isSxTruthy(isEmpty(body)) ? makeCekValue(NIL, env, kont) : makeCekState(first(body), env, kontPush(makeScopeAccFrame(name, val, rest(body), env), kont)));
|
||||
})(); };
|
||||
PRIMITIVES["step-sf-scope"] = stepSfScope;
|
||||
|
||||
@@ -1604,13 +1603,7 @@ PRIMITIVES["step-sf-scope"] = stepSfScope;
|
||||
var name = trampoline(evalExpr(first(args), env));
|
||||
var val = trampoline(evalExpr(nth(args, 1), env));
|
||||
var body = slice(args, 2);
|
||||
scopePush(name, val);
|
||||
return (function() {
|
||||
var result = NIL;
|
||||
{ var _c = body; for (var _i = 0; _i < _c.length; _i++) { var expr = _c[_i]; result = trampoline(evalExpr(expr, env)); } }
|
||||
scopePop(name);
|
||||
return makeCekValue(result, env, kont);
|
||||
})();
|
||||
return (isSxTruthy(isEmpty(body)) ? makeCekValue(NIL, env, kont) : makeCekState(first(body), env, kontPush(makeProvideFrame(name, val, rest(body), env), kont)));
|
||||
})(); };
|
||||
PRIMITIVES["step-sf-provide"] = stepSfProvide;
|
||||
|
||||
@@ -1618,8 +1611,8 @@ PRIMITIVES["step-sf-provide"] = stepSfProvide;
|
||||
var stepSfContext = function(args, env, kont) { return (function() {
|
||||
var name = trampoline(evalExpr(first(args), env));
|
||||
var defaultVal = (isSxTruthy((len(args) >= 2)) ? trampoline(evalExpr(nth(args, 1), env)) : NIL);
|
||||
var val = scopePeek(name);
|
||||
return makeCekValue((isSxTruthy(isNil(val)) ? defaultVal : val), env, kont);
|
||||
var frame = kontFindProvide(kont, name);
|
||||
return makeCekValue((isSxTruthy(isNil(frame)) ? defaultVal : get(frame, "value")), env, kont);
|
||||
})(); };
|
||||
PRIMITIVES["step-sf-context"] = stepSfContext;
|
||||
|
||||
@@ -1627,7 +1620,10 @@ PRIMITIVES["step-sf-context"] = stepSfContext;
|
||||
var stepSfEmit = function(args, env, kont) { return (function() {
|
||||
var name = trampoline(evalExpr(first(args), env));
|
||||
var val = trampoline(evalExpr(nth(args, 1), env));
|
||||
scopeEmit(name, val);
|
||||
var frame = kontFindScopeAcc(kont, name);
|
||||
if (isSxTruthy(frame)) {
|
||||
frame["emitted"] = append(get(frame, "emitted"), [val]);
|
||||
}
|
||||
return makeCekValue(NIL, env, kont);
|
||||
})(); };
|
||||
PRIMITIVES["step-sf-emit"] = stepSfEmit;
|
||||
@@ -1635,8 +1631,8 @@ PRIMITIVES["step-sf-emit"] = stepSfEmit;
|
||||
// step-sf-emitted
|
||||
var stepSfEmitted = function(args, env, kont) { return (function() {
|
||||
var name = trampoline(evalExpr(first(args), env));
|
||||
var val = scopePeek(name);
|
||||
return makeCekValue((isSxTruthy(isNil(val)) ? [] : val), env, kont);
|
||||
var frame = kontFindScopeAcc(kont, name);
|
||||
return makeCekValue((isSxTruthy(isNil(frame)) ? [] : get(frame, "emitted")), env, kont);
|
||||
})(); };
|
||||
PRIMITIVES["step-sf-emitted"] = stepSfEmitted;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user