Phase 4: Eliminate nested CEK from HO form handlers
Higher-order forms (map, filter, reduce, some, every?, for-each, map-indexed) now evaluate their arguments via CEK frames instead of nested trampoline(eval-expr(...)) calls. Added HoSetupFrame — staged evaluation of HO form arguments. When all args are evaluated, ho-setup-dispatch sets up the iteration frame. This keeps a single linear CEK continuation chain instead of spawning nested CEK instances. 14 nested eval-expr calls eliminated (39 → 25 remaining). The remaining 25 are in delegate functions (sf-letrec, sf-scope, parse-keyword-args, qq-expand, etc.) called infrequently. 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:
@@ -14,7 +14,7 @@
|
||||
// =========================================================================
|
||||
|
||||
var NIL = Object.freeze({ _nil: true, toString: function() { return "nil"; } });
|
||||
var SX_VERSION = "2026-03-15T13:41:19Z";
|
||||
var SX_VERSION = "2026-03-15T14:09:57Z";
|
||||
|
||||
function isNil(x) { return x === NIL || x === null || x === undefined; }
|
||||
function isSxTruthy(x) { return x !== false && !isNil(x); }
|
||||
@@ -941,6 +941,10 @@ PRIMITIVES["make-reactive-reset-frame"] = makeReactiveResetFrame;
|
||||
var makeDerefFrame = function(env) { return {"type": "deref", "env": env}; };
|
||||
PRIMITIVES["make-deref-frame"] = makeDerefFrame;
|
||||
|
||||
// make-ho-setup-frame
|
||||
var makeHoSetupFrame = function(hoType, remainingArgs, evaledArgs, env) { return {"type": "ho-setup", "ho-type": hoType, "remaining": remainingArgs, "evaled": evaledArgs, "env": env}; };
|
||||
PRIMITIVES["make-ho-setup-frame"] = makeHoSetupFrame;
|
||||
|
||||
// frame-type
|
||||
var frameType = function(f) { return get(f, "type"); };
|
||||
PRIMITIVES["frame-type"] = frameType;
|
||||
@@ -1564,61 +1568,61 @@ PRIMITIVES["reactive-shift-deref"] = reactiveShiftDeref;
|
||||
})(); };
|
||||
PRIMITIVES["step-eval-call"] = stepEvalCall;
|
||||
|
||||
// step-ho-map
|
||||
var stepHoMap = function(args, env, kont) { return (function() {
|
||||
var f = trampoline(evalExpr(first(args), env));
|
||||
var coll = trampoline(evalExpr(nth(args, 1), env));
|
||||
// ho-setup-dispatch
|
||||
var hoSetupDispatch = function(hoType, evaled, env, kont) { return (function() {
|
||||
var f = first(evaled);
|
||||
return (isSxTruthy((hoType == "map")) ? (function() {
|
||||
var coll = nth(evaled, 1);
|
||||
return (isSxTruthy(isEmpty(coll)) ? makeCekValue([], env, kont) : continueWithCall(f, [first(coll)], env, [], kontPush(makeMapFrame(f, rest(coll), [], env), kont)));
|
||||
})() : (isSxTruthy((hoType == "map-indexed")) ? (function() {
|
||||
var coll = nth(evaled, 1);
|
||||
return (isSxTruthy(isEmpty(coll)) ? makeCekValue([], env, kont) : continueWithCall(f, [0, first(coll)], env, [], kontPush(makeMapIndexedFrame(f, rest(coll), [], env), kont)));
|
||||
})() : (isSxTruthy((hoType == "filter")) ? (function() {
|
||||
var coll = nth(evaled, 1);
|
||||
return (isSxTruthy(isEmpty(coll)) ? makeCekValue([], env, kont) : continueWithCall(f, [first(coll)], env, [], kontPush(makeFilterFrame(f, rest(coll), [], first(coll), env), kont)));
|
||||
})() : (isSxTruthy((hoType == "reduce")) ? (function() {
|
||||
var init = nth(evaled, 1);
|
||||
var coll = nth(evaled, 2);
|
||||
return (isSxTruthy(isEmpty(coll)) ? makeCekValue(init, env, kont) : continueWithCall(f, [init, first(coll)], env, [], kontPush(makeReduceFrame(f, rest(coll), env), kont)));
|
||||
})() : (isSxTruthy((hoType == "some")) ? (function() {
|
||||
var coll = nth(evaled, 1);
|
||||
return (isSxTruthy(isEmpty(coll)) ? makeCekValue(false, env, kont) : continueWithCall(f, [first(coll)], env, [], kontPush(makeSomeFrame(f, rest(coll), env), kont)));
|
||||
})() : (isSxTruthy((hoType == "every")) ? (function() {
|
||||
var coll = nth(evaled, 1);
|
||||
return (isSxTruthy(isEmpty(coll)) ? makeCekValue(true, env, kont) : continueWithCall(f, [first(coll)], env, [], kontPush(makeEveryFrame(f, rest(coll), env), kont)));
|
||||
})() : (isSxTruthy((hoType == "for-each")) ? (function() {
|
||||
var coll = nth(evaled, 1);
|
||||
return (isSxTruthy(isEmpty(coll)) ? makeCekValue(NIL, env, kont) : continueWithCall(f, [first(coll)], env, [], kontPush(makeForEachFrame(f, rest(coll), env), kont)));
|
||||
})() : error((String("Unknown HO type: ") + String(hoType))))))))));
|
||||
})(); };
|
||||
PRIMITIVES["ho-setup-dispatch"] = hoSetupDispatch;
|
||||
|
||||
// step-ho-map
|
||||
var stepHoMap = function(args, env, kont) { return makeCekState(first(args), env, kontPush(makeHoSetupFrame("map", rest(args), [], env), kont)); };
|
||||
PRIMITIVES["step-ho-map"] = stepHoMap;
|
||||
|
||||
// step-ho-map-indexed
|
||||
var stepHoMapIndexed = function(args, env, kont) { return (function() {
|
||||
var f = trampoline(evalExpr(first(args), env));
|
||||
var coll = trampoline(evalExpr(nth(args, 1), env));
|
||||
return (isSxTruthy(isEmpty(coll)) ? makeCekValue([], env, kont) : continueWithCall(f, [0, first(coll)], env, [], kontPush(makeMapIndexedFrame(f, rest(coll), [], env), kont)));
|
||||
})(); };
|
||||
var stepHoMapIndexed = function(args, env, kont) { return makeCekState(first(args), env, kontPush(makeHoSetupFrame("map-indexed", rest(args), [], env), kont)); };
|
||||
PRIMITIVES["step-ho-map-indexed"] = stepHoMapIndexed;
|
||||
|
||||
// step-ho-filter
|
||||
var stepHoFilter = function(args, env, kont) { return (function() {
|
||||
var f = trampoline(evalExpr(first(args), env));
|
||||
var coll = trampoline(evalExpr(nth(args, 1), env));
|
||||
return (isSxTruthy(isEmpty(coll)) ? makeCekValue([], env, kont) : continueWithCall(f, [first(coll)], env, [], kontPush(makeFilterFrame(f, rest(coll), [], first(coll), env), kont)));
|
||||
})(); };
|
||||
var stepHoFilter = function(args, env, kont) { return makeCekState(first(args), env, kontPush(makeHoSetupFrame("filter", rest(args), [], env), kont)); };
|
||||
PRIMITIVES["step-ho-filter"] = stepHoFilter;
|
||||
|
||||
// step-ho-reduce
|
||||
var stepHoReduce = function(args, env, kont) { 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 (isSxTruthy(isEmpty(coll)) ? makeCekValue(init, env, kont) : continueWithCall(f, [init, first(coll)], env, [], kontPush(makeReduceFrame(f, rest(coll), env), kont)));
|
||||
})(); };
|
||||
var stepHoReduce = function(args, env, kont) { return makeCekState(first(args), env, kontPush(makeHoSetupFrame("reduce", rest(args), [], env), kont)); };
|
||||
PRIMITIVES["step-ho-reduce"] = stepHoReduce;
|
||||
|
||||
// step-ho-some
|
||||
var stepHoSome = function(args, env, kont) { return (function() {
|
||||
var f = trampoline(evalExpr(first(args), env));
|
||||
var coll = trampoline(evalExpr(nth(args, 1), env));
|
||||
return (isSxTruthy(isEmpty(coll)) ? makeCekValue(false, env, kont) : continueWithCall(f, [first(coll)], env, [], kontPush(makeSomeFrame(f, rest(coll), env), kont)));
|
||||
})(); };
|
||||
var stepHoSome = function(args, env, kont) { return makeCekState(first(args), env, kontPush(makeHoSetupFrame("some", rest(args), [], env), kont)); };
|
||||
PRIMITIVES["step-ho-some"] = stepHoSome;
|
||||
|
||||
// step-ho-every
|
||||
var stepHoEvery = function(args, env, kont) { return (function() {
|
||||
var f = trampoline(evalExpr(first(args), env));
|
||||
var coll = trampoline(evalExpr(nth(args, 1), env));
|
||||
return (isSxTruthy(isEmpty(coll)) ? makeCekValue(true, env, kont) : continueWithCall(f, [first(coll)], env, [], kontPush(makeEveryFrame(f, rest(coll), env), kont)));
|
||||
})(); };
|
||||
var stepHoEvery = function(args, env, kont) { return makeCekState(first(args), env, kontPush(makeHoSetupFrame("every", rest(args), [], env), kont)); };
|
||||
PRIMITIVES["step-ho-every"] = stepHoEvery;
|
||||
|
||||
// step-ho-for-each
|
||||
var stepHoForEach = function(args, env, kont) { return (function() {
|
||||
var f = trampoline(evalExpr(first(args), env));
|
||||
var coll = trampoline(evalExpr(nth(args, 1), env));
|
||||
return (isSxTruthy(isEmpty(coll)) ? makeCekValue(NIL, env, kont) : continueWithCall(f, [first(coll)], env, [], kontPush(makeForEachFrame(f, rest(coll), env), kont)));
|
||||
})(); };
|
||||
var stepHoForEach = function(args, env, kont) { return makeCekState(first(args), env, kontPush(makeHoSetupFrame("for-each", rest(args), [], env), kont)); };
|
||||
PRIMITIVES["step-ho-for-each"] = stepHoForEach;
|
||||
|
||||
// step-continue
|
||||
@@ -1747,6 +1751,12 @@ PRIMITIVES["step-ho-for-each"] = stepHoForEach;
|
||||
return makeCekState(nth(nextEntry, 1), fenv, kontPush(makeDictFrame(rest(remaining), append(completed, [[first(nextEntry)]]), fenv), restK));
|
||||
})());
|
||||
})();
|
||||
})() : (isSxTruthy((ft == "ho-setup")) ? (function() {
|
||||
var hoType = get(frame, "ho-type");
|
||||
var remaining = get(frame, "remaining");
|
||||
var evaled = append(get(frame, "evaled"), [value]);
|
||||
var fenv = get(frame, "env");
|
||||
return (isSxTruthy(isEmpty(remaining)) ? hoSetupDispatch(hoType, evaled, fenv, restK) : makeCekState(first(remaining), fenv, kontPush(makeHoSetupFrame(hoType, rest(remaining), evaled, fenv), restK)));
|
||||
})() : (isSxTruthy((ft == "reset")) ? makeCekValue(value, env, restK) : (isSxTruthy((ft == "deref")) ? (function() {
|
||||
var val = value;
|
||||
var fenv = get(frame, "env");
|
||||
@@ -1814,7 +1824,7 @@ PRIMITIVES["step-ho-for-each"] = stepHoForEach;
|
||||
var remaining = get(frame, "remaining");
|
||||
var fenv = get(frame, "env");
|
||||
return (isSxTruthy(!isSxTruthy(value)) ? makeCekValue(false, fenv, restK) : (isSxTruthy(isEmpty(remaining)) ? makeCekValue(true, fenv, restK) : continueWithCall(f, [first(remaining)], fenv, [], kontPush(makeEveryFrame(f, rest(remaining), fenv), restK))));
|
||||
})() : error((String("Unknown frame type: ") + String(ft))))))))))))))))))))))))));
|
||||
})() : error((String("Unknown frame type: ") + String(ft)))))))))))))))))))))))))));
|
||||
})());
|
||||
})(); };
|
||||
PRIMITIVES["step-continue"] = stepContinue;
|
||||
|
||||
Reference in New Issue
Block a user