Phase 2: Remove dead tree-walk code from eval.sx

eval.sx: 1272 → 846 lines (-33%). sx-browser.js: 392KB → 377KB.

Deleted (superseded by CEK step handlers in cek.sx):
- eval-list: tree-walk dispatch table
- eval-call: tree-walk function dispatch
- sf-if, sf-when, sf-cond (3 variants), sf-case (2 variants)
- sf-and, sf-or, sf-let, sf-begin, sf-quote, sf-quasiquote
- sf-thread-first, sf-set!, sf-define
- ho-map, ho-filter, ho-reduce, ho-some, ho-every, ho-for-each,
  ho-map-indexed, call-fn

Kept (still called by CEK as delegates):
- sf-lambda, sf-defcomp, sf-defisland, sf-defmacro, sf-defstyle,
  sf-deftype, sf-defeffect, sf-letrec, sf-named-let
- sf-scope, sf-provide, sf-dynamic-wind
- expand-macro, qq-expand, cond-scheme?
- call-lambda, call-component, parse-keyword-args
- Strict mode, type helpers

eval-expr is now a stub overridden by CEK fixup.
All tests unchanged: JS 747/747, Full 864/870, Python 679/679.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-15 13:28:09 +00:00
parent 9b4f735a0e
commit b4df216fae
5 changed files with 27 additions and 684 deletions

View File

@@ -14,7 +14,7 @@
// =========================================================================
var NIL = Object.freeze({ _nil: true, toString: function() { return "nil"; } });
var SX_VERSION = "2026-03-15T13:02:48Z";
var SX_VERSION = "2026-03-15T13:27:20Z";
function isNil(x) { return x === NIL || x === null || x === undefined; }
function isSxTruthy(x) { return x !== false && !isNil(x); }
@@ -860,34 +860,9 @@ PRIMITIVES["value-matches-type?"] = valueMatchesType_p;
PRIMITIVES["strict-check-args"] = strictCheckArgs;
// eval-expr
var evalExpr = function(expr, env) { return (function() { var _m = typeOf(expr); if (_m == "number") return expr; if (_m == "string") return expr; if (_m == "boolean") return expr; if (_m == "nil") return NIL; if (_m == "symbol") return (function() {
var name = symbolName(expr);
return (isSxTruthy(envHas(env, name)) ? envGet(env, name) : (isSxTruthy(isPrimitive(name)) ? getPrimitive(name) : (isSxTruthy((name == "true")) ? true : (isSxTruthy((name == "false")) ? false : (isSxTruthy((name == "nil")) ? NIL : (debugLog("Undefined symbol:", name, "primitive?:", isPrimitive(name)), error((String("Undefined symbol: ") + String(name)))))))));
})(); if (_m == "keyword") return keywordName(expr); if (_m == "dict") return mapDict(function(k, v) { return trampoline(evalExpr(v, env)); }, expr); if (_m == "list") return (isSxTruthy(isEmpty(expr)) ? [] : evalList(expr, env)); return expr; })(); };
var evalExpr = function(expr, env) { return error("eval-expr: CEK fixup not loaded"); };
PRIMITIVES["eval-expr"] = evalExpr;
// eval-list
var evalList = function(expr, env) { return (function() {
var head = first(expr);
var args = rest(expr);
return (isSxTruthy(!isSxTruthy(sxOr((typeOf(head) == "symbol"), (typeOf(head) == "lambda"), (typeOf(head) == "list")))) ? map(function(x) { return trampoline(evalExpr(x, env)); }, expr) : (isSxTruthy((typeOf(head) == "symbol")) ? (function() {
var name = symbolName(head);
return (isSxTruthy((name == "if")) ? sfIf(args, env) : (isSxTruthy((name == "when")) ? sfWhen(args, env) : (isSxTruthy((name == "cond")) ? sfCond(args, env) : (isSxTruthy((name == "case")) ? sfCase(args, env) : (isSxTruthy((name == "and")) ? sfAnd(args, env) : (isSxTruthy((name == "or")) ? sfOr(args, env) : (isSxTruthy((name == "let")) ? sfLet(args, env) : (isSxTruthy((name == "let*")) ? sfLet(args, env) : (isSxTruthy((name == "letrec")) ? sfLetrec(args, env) : (isSxTruthy((name == "lambda")) ? sfLambda(args, env) : (isSxTruthy((name == "fn")) ? sfLambda(args, env) : (isSxTruthy((name == "define")) ? sfDefine(args, env) : (isSxTruthy((name == "defcomp")) ? sfDefcomp(args, env) : (isSxTruthy((name == "defisland")) ? sfDefisland(args, env) : (isSxTruthy((name == "defmacro")) ? sfDefmacro(args, env) : (isSxTruthy((name == "defstyle")) ? sfDefstyle(args, env) : (isSxTruthy((name == "defhandler")) ? sfDefhandler(args, env) : (isSxTruthy((name == "defpage")) ? sfDefpage(args, env) : (isSxTruthy((name == "defquery")) ? sfDefquery(args, env) : (isSxTruthy((name == "defaction")) ? sfDefaction(args, env) : (isSxTruthy((name == "deftype")) ? sfDeftype(args, env) : (isSxTruthy((name == "defeffect")) ? sfDefeffect(args, env) : (isSxTruthy((name == "begin")) ? sfBegin(args, env) : (isSxTruthy((name == "do")) ? sfBegin(args, env) : (isSxTruthy((name == "quote")) ? sfQuote(args, env) : (isSxTruthy((name == "quasiquote")) ? sfQuasiquote(args, env) : (isSxTruthy((name == "->")) ? sfThreadFirst(args, env) : (isSxTruthy((name == "set!")) ? sfSetBang(args, env) : (isSxTruthy((name == "reset")) ? sfReset(args, env) : (isSxTruthy((name == "shift")) ? sfShift(args, env) : (isSxTruthy((name == "dynamic-wind")) ? sfDynamicWind(args, env) : (isSxTruthy((name == "scope")) ? sfScope(args, env) : (isSxTruthy((name == "provide")) ? sfProvide(args, env) : (isSxTruthy((name == "map")) ? hoMap(args, env) : (isSxTruthy((name == "map-indexed")) ? hoMapIndexed(args, env) : (isSxTruthy((name == "filter")) ? hoFilter(args, env) : (isSxTruthy((name == "reduce")) ? hoReduce(args, env) : (isSxTruthy((name == "some")) ? hoSome(args, env) : (isSxTruthy((name == "every?")) ? hoEvery(args, env) : (isSxTruthy((name == "for-each")) ? hoForEach(args, env) : (isSxTruthy((isSxTruthy(envHas(env, name)) && isMacro(envGet(env, name)))) ? (function() {
var mac = envGet(env, name);
return makeThunk(expandMacro(mac, args, env), env);
})() : (isSxTruthy((isSxTruthy(renderActiveP()) && isRenderExpr(expr))) ? renderExpr(expr, env) : evalCall(head, args, env)))))))))))))))))))))))))))))))))))))))))));
})() : evalCall(head, args, env)));
})(); };
PRIMITIVES["eval-list"] = evalList;
// eval-call
var evalCall = function(head, args, env) { return (function() {
var f = trampoline(evalExpr(head, env));
var evaluatedArgs = map(function(a) { return trampoline(evalExpr(a, env)); }, args);
return (isSxTruthy((isSxTruthy(isCallable(f)) && isSxTruthy(!isSxTruthy(isLambda(f))) && isSxTruthy(!isSxTruthy(isComponent(f))) && !isSxTruthy(isIsland(f)))) ? ((isSxTruthy((isSxTruthy(_strict_) && (typeOf(head) == "symbol"))) ? strictCheckArgs(symbolName(head), evaluatedArgs) : NIL), apply(f, evaluatedArgs)) : (isSxTruthy(isLambda(f)) ? callLambda(f, evaluatedArgs, env) : (isSxTruthy(isComponent(f)) ? callComponent(f, args, env) : (isSxTruthy(isIsland(f)) ? callComponent(f, args, env) : error((String("Not callable: ") + String(inspect(f))))))));
})(); };
PRIMITIVES["eval-call"] = evalCall;
// call-lambda
var callLambda = function(f, args, callerEnv) { return (function() {
var params = lambdaParams(f);
@@ -924,96 +899,10 @@ PRIMITIVES["call-component"] = callComponent;
})(); };
PRIMITIVES["parse-keyword-args"] = parseKeywordArgs;
// sf-if
var sfIf = function(args, env) { return (function() {
var condition = trampoline(evalExpr(first(args), env));
return (isSxTruthy((isSxTruthy(condition) && !isSxTruthy(isNil(condition)))) ? makeThunk(nth(args, 1), env) : (isSxTruthy((len(args) > 2)) ? makeThunk(nth(args, 2), env) : NIL));
})(); };
PRIMITIVES["sf-if"] = sfIf;
// sf-when
var sfWhen = function(args, env) { return (function() {
var condition = trampoline(evalExpr(first(args), env));
return (isSxTruthy((isSxTruthy(condition) && !isSxTruthy(isNil(condition)))) ? (forEach(function(e) { return trampoline(evalExpr(e, env)); }, slice(args, 1, (len(args) - 1))), makeThunk(last(args), env)) : NIL);
})(); };
PRIMITIVES["sf-when"] = sfWhen;
// cond-scheme?
var condScheme_p = function(clauses) { return isEvery(function(c) { return (isSxTruthy((typeOf(c) == "list")) && (len(c) == 2)); }, clauses); };
PRIMITIVES["cond-scheme?"] = condScheme_p;
// sf-cond
var sfCond = function(args, env) { return (isSxTruthy(condScheme_p(args)) ? sfCondScheme(args, env) : sfCondClojure(args, env)); };
PRIMITIVES["sf-cond"] = sfCond;
// sf-cond-scheme
var sfCondScheme = function(clauses, env) { return (isSxTruthy(isEmpty(clauses)) ? NIL : (function() {
var clause = first(clauses);
var test = first(clause);
var body = nth(clause, 1);
return (isSxTruthy(sxOr((isSxTruthy((typeOf(test) == "symbol")) && sxOr((symbolName(test) == "else"), (symbolName(test) == ":else"))), (isSxTruthy((typeOf(test) == "keyword")) && (keywordName(test) == "else")))) ? makeThunk(body, env) : (isSxTruthy(trampoline(evalExpr(test, env))) ? makeThunk(body, env) : sfCondScheme(rest(clauses), env)));
})()); };
PRIMITIVES["sf-cond-scheme"] = sfCondScheme;
// sf-cond-clojure
var sfCondClojure = function(clauses, env) { return (isSxTruthy((len(clauses) < 2)) ? NIL : (function() {
var test = first(clauses);
var body = nth(clauses, 1);
return (isSxTruthy(sxOr((isSxTruthy((typeOf(test) == "keyword")) && (keywordName(test) == "else")), (isSxTruthy((typeOf(test) == "symbol")) && sxOr((symbolName(test) == "else"), (symbolName(test) == ":else"))))) ? makeThunk(body, env) : (isSxTruthy(trampoline(evalExpr(test, env))) ? makeThunk(body, env) : sfCondClojure(slice(clauses, 2), env)));
})()); };
PRIMITIVES["sf-cond-clojure"] = sfCondClojure;
// sf-case
var sfCase = function(args, env) { return (function() {
var matchVal = trampoline(evalExpr(first(args), env));
var clauses = rest(args);
return sfCaseLoop(matchVal, clauses, env);
})(); };
PRIMITIVES["sf-case"] = sfCase;
// sf-case-loop
var sfCaseLoop = function(matchVal, clauses, env) { return (isSxTruthy((len(clauses) < 2)) ? NIL : (function() {
var test = first(clauses);
var body = nth(clauses, 1);
return (isSxTruthy(sxOr((isSxTruthy((typeOf(test) == "keyword")) && (keywordName(test) == "else")), (isSxTruthy((typeOf(test) == "symbol")) && sxOr((symbolName(test) == "else"), (symbolName(test) == ":else"))))) ? makeThunk(body, env) : (isSxTruthy((matchVal == trampoline(evalExpr(test, env)))) ? makeThunk(body, env) : sfCaseLoop(matchVal, slice(clauses, 2), env)));
})()); };
PRIMITIVES["sf-case-loop"] = sfCaseLoop;
// sf-and
var sfAnd = function(args, env) { return (isSxTruthy(isEmpty(args)) ? true : (function() {
var val = trampoline(evalExpr(first(args), env));
return (isSxTruthy(!isSxTruthy(val)) ? val : (isSxTruthy((len(args) == 1)) ? val : sfAnd(rest(args), env)));
})()); };
PRIMITIVES["sf-and"] = sfAnd;
// sf-or
var sfOr = function(args, env) { return (isSxTruthy(isEmpty(args)) ? false : (function() {
var val = trampoline(evalExpr(first(args), env));
return (isSxTruthy(val) ? val : sfOr(rest(args), env));
})()); };
PRIMITIVES["sf-or"] = sfOr;
// sf-let
var sfLet = function(args, env) { return (isSxTruthy((typeOf(first(args)) == "symbol")) ? sfNamedLet(args, env) : (function() {
var bindings = first(args);
var body = rest(args);
var local = envExtend(env);
(isSxTruthy((isSxTruthy((typeOf(first(bindings)) == "list")) && (len(first(bindings)) == 2))) ? forEach(function(binding) { return (function() {
var vname = (isSxTruthy((typeOf(first(binding)) == "symbol")) ? symbolName(first(binding)) : first(binding));
return envBind(local, vname, trampoline(evalExpr(nth(binding, 1), local)));
})(); }, bindings) : (function() {
var i = 0;
return reduce(function(acc, pairIdx) { return (function() {
var vname = (isSxTruthy((typeOf(nth(bindings, (pairIdx * 2))) == "symbol")) ? symbolName(nth(bindings, (pairIdx * 2))) : nth(bindings, (pairIdx * 2)));
var valExpr = nth(bindings, ((pairIdx * 2) + 1));
return envBind(local, vname, trampoline(evalExpr(valExpr, local)));
})(); }, NIL, range(0, (len(bindings) / 2)));
})());
{ var _c = slice(body, 0, (len(body) - 1)); for (var _i = 0; _i < _c.length; _i++) { var e = _c[_i]; trampoline(evalExpr(e, local)); } }
return makeThunk(last(body), local);
})()); };
PRIMITIVES["sf-let"] = sfLet;
// sf-named-let
var sfNamedLet = function(args, env) { return (function() {
var loopName = symbolName(first(args));
@@ -1046,29 +935,6 @@ PRIMITIVES["sf-named-let"] = sfNamedLet;
})(); };
PRIMITIVES["sf-lambda"] = sfLambda;
// sf-define
var sfDefine = function(args, env) { return (function() {
var nameSym = first(args);
var hasEffects = (isSxTruthy((len(args) >= 4)) && isSxTruthy((typeOf(nth(args, 1)) == "keyword")) && (keywordName(nth(args, 1)) == "effects"));
var valIdx = (isSxTruthy((isSxTruthy((len(args) >= 4)) && isSxTruthy((typeOf(nth(args, 1)) == "keyword")) && (keywordName(nth(args, 1)) == "effects"))) ? 3 : 1);
var value = trampoline(evalExpr(nth(args, valIdx), env));
if (isSxTruthy((isSxTruthy(isLambda(value)) && isNil(lambdaName(value))))) {
value.name = symbolName(nameSym);
}
envBind(env, symbolName(nameSym), value);
if (isSxTruthy(hasEffects)) {
(function() {
var effectsRaw = nth(args, 2);
var effectList = (isSxTruthy((typeOf(effectsRaw) == "list")) ? map(function(e) { return (isSxTruthy((typeOf(e) == "symbol")) ? symbolName(e) : (String(e))); }, effectsRaw) : [(String(effectsRaw))]);
var effectAnns = (isSxTruthy(envHas(env, "*effect-annotations*")) ? envGet(env, "*effect-annotations*") : {});
effectAnns[symbolName(nameSym)] = effectList;
return envBind(env, "*effect-annotations*", effectAnns);
})();
}
return value;
})(); };
PRIMITIVES["sf-define"] = sfDefine;
// sf-defcomp
var sfDefcomp = function(args, env) { return (function() {
var nameSym = first(args);
@@ -1229,18 +1095,6 @@ PRIMITIVES["sf-deftype"] = sfDeftype;
})(); };
PRIMITIVES["sf-defeffect"] = sfDefeffect;
// sf-begin
var sfBegin = function(args, env) { return (isSxTruthy(isEmpty(args)) ? NIL : (forEach(function(e) { return trampoline(evalExpr(e, env)); }, slice(args, 0, (len(args) - 1))), makeThunk(last(args), env))); };
PRIMITIVES["sf-begin"] = sfBegin;
// sf-quote
var sfQuote = function(args, env) { return (isSxTruthy(isEmpty(args)) ? NIL : first(args)); };
PRIMITIVES["sf-quote"] = sfQuote;
// sf-quasiquote
var sfQuasiquote = function(args, env) { return qqExpand(first(args), env); };
PRIMITIVES["sf-quasiquote"] = sfQuasiquote;
// qq-expand
var qqExpand = function(template, env) { return (isSxTruthy(!isSxTruthy((typeOf(template) == "list"))) ? template : (isSxTruthy(isEmpty(template)) ? [] : (function() {
var head = first(template);
@@ -1251,30 +1105,6 @@ PRIMITIVES["sf-quasiquote"] = sfQuasiquote;
})())); };
PRIMITIVES["qq-expand"] = qqExpand;
// sf-thread-first
var sfThreadFirst = function(args, env) { return (function() {
var val = trampoline(evalExpr(first(args), env));
return reduce(function(result, form) { return (isSxTruthy((typeOf(form) == "list")) ? (function() {
var f = trampoline(evalExpr(first(form), env));
var restArgs = map(function(a) { return trampoline(evalExpr(a, env)); }, rest(form));
var allArgs = cons(result, restArgs);
return (isSxTruthy((isSxTruthy(isCallable(f)) && !isSxTruthy(isLambda(f)))) ? apply(f, allArgs) : (isSxTruthy(isLambda(f)) ? trampoline(callLambda(f, allArgs, env)) : error((String("-> form not callable: ") + String(inspect(f))))));
})() : (function() {
var f = trampoline(evalExpr(form, env));
return (isSxTruthy((isSxTruthy(isCallable(f)) && !isSxTruthy(isLambda(f)))) ? f(result) : (isSxTruthy(isLambda(f)) ? trampoline(callLambda(f, [result], env)) : error((String("-> form not callable: ") + String(inspect(f))))));
})()); }, val, rest(args));
})(); };
PRIMITIVES["sf-thread-first"] = sfThreadFirst;
// sf-set!
var sfSetBang = function(args, env) { return (function() {
var name = symbolName(first(args));
var value = trampoline(evalExpr(nth(args, 1), env));
envSet(env, name, value);
return value;
})(); };
PRIMITIVES["sf-set!"] = sfSetBang;
// sf-letrec
var sfLetrec = function(args, env) { return (function() {
var bindings = first(args);
@@ -1354,67 +1184,6 @@ PRIMITIVES["sf-provide"] = sfProvide;
})(); };
PRIMITIVES["expand-macro"] = expandMacro;
// call-fn
var callFn = function(f, args, env) { return (isSxTruthy(isLambda(f)) ? trampoline(callLambda(f, args, env)) : (isSxTruthy(isCallable(f)) ? apply(f, args) : error((String("Not callable in HO form: ") + String(inspect(f)))))); };
PRIMITIVES["call-fn"] = callFn;
// ho-map
var hoMap = function(args, env) { return (function() {
var f = trampoline(evalExpr(first(args), env));
var coll = trampoline(evalExpr(nth(args, 1), env));
return map(function(item) { return callFn(f, [item], env); }, coll);
})(); };
PRIMITIVES["ho-map"] = hoMap;
// ho-map-indexed
var hoMapIndexed = function(args, env) { return (function() {
var f = trampoline(evalExpr(first(args), env));
var coll = trampoline(evalExpr(nth(args, 1), env));
return mapIndexed(function(i, item) { return callFn(f, [i, item], env); }, coll);
})(); };
PRIMITIVES["ho-map-indexed"] = hoMapIndexed;
// ho-filter
var hoFilter = function(args, env) { return (function() {
var f = trampoline(evalExpr(first(args), env));
var coll = trampoline(evalExpr(nth(args, 1), env));
return filter(function(item) { return callFn(f, [item], env); }, coll);
})(); };
PRIMITIVES["ho-filter"] = hoFilter;
// ho-reduce
var hoReduce = function(args, env) { return (function() {
var f = trampoline(evalExpr(first(args), env));
var init = trampoline(evalExpr(nth(args, 1), env));
var coll = trampoline(evalExpr(nth(args, 2), env));
return reduce(function(acc, item) { return callFn(f, [acc, item], env); }, init, coll);
})(); };
PRIMITIVES["ho-reduce"] = hoReduce;
// ho-some
var hoSome = function(args, env) { return (function() {
var f = trampoline(evalExpr(first(args), env));
var coll = trampoline(evalExpr(nth(args, 1), env));
return some(function(item) { return callFn(f, [item], env); }, coll);
})(); };
PRIMITIVES["ho-some"] = hoSome;
// ho-every
var hoEvery = function(args, env) { return (function() {
var f = trampoline(evalExpr(first(args), env));
var coll = trampoline(evalExpr(nth(args, 1), env));
return isEvery(function(item) { return callFn(f, [item], env); }, coll);
})(); };
PRIMITIVES["ho-every"] = hoEvery;
// ho-for-each
var hoForEach = function(args, env) { return (function() {
var f = trampoline(evalExpr(first(args), env));
var coll = trampoline(evalExpr(nth(args, 1), env));
return forEach(function(item) { return callFn(f, [item], env); }, coll);
})(); };
PRIMITIVES["ho-for-each"] = hoForEach;
// === Transpiled from render (core) ===