Bootstrap CEK as default evaluator on both JS and Python sides
SPEC_MODULES + SPEC_MODULE_ORDER for frames/cek in platform_js.py, PLATFORM_CEK_JS + CEK_FIXUPS_JS constants, auto-inclusion in run_js_sx.py, 70+ RENAMES in js.sx. Python: CEK always-include in bootstrap_py.py, eval_expr/trampoline overridden to cek_run in platform_py.py with _tree_walk_* preserved for test runners. Co-Authored-By: Claude Opus 4.6 <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-13T23:56:11Z";
|
||||
var SX_VERSION = "2026-03-14T01:00:32Z";
|
||||
|
||||
function isNil(x) { return x === NIL || x === null || x === undefined; }
|
||||
function isSxTruthy(x) { return x !== false && !isNil(x); }
|
||||
@@ -2428,6 +2428,37 @@ return (isSxTruthy(testFn()) ? (function() {
|
||||
return domListen(el, (isSxTruthy(isCheckbox) ? "change" : "input"), function(e) { return (isSxTruthy(isCheckbox) ? reset_b(sig, domGetProp(el, "checked")) : reset_b(sig, domGetProp(el, "value"))); });
|
||||
})(); };
|
||||
|
||||
// *use-cek-reactive*
|
||||
var _useCekReactive = true;
|
||||
|
||||
// enable-cek-reactive!
|
||||
var enableCekReactive = function() { return (_useCekReactive = true); };
|
||||
|
||||
// cek-reactive-text
|
||||
var cekReactiveText = function(expr, env) { return (function() {
|
||||
var node = createTextNode("");
|
||||
var updateFn = function(val) { return domSetTextContent(node, (String(val))); };
|
||||
return (function() {
|
||||
var initial = cekRun(makeCekState(expr, env, [makeReactiveResetFrame(env, updateFn, true)]));
|
||||
domSetTextContent(node, (String(initial)));
|
||||
return node;
|
||||
})();
|
||||
})(); };
|
||||
|
||||
// cek-reactive-attr
|
||||
var cekReactiveAttr = function(el, attrName, expr, env) { return (function() {
|
||||
var updateFn = function(val) { return (isSxTruthy(sxOr(isNil(val), (val == false))) ? domRemoveAttr(el, attrName) : (isSxTruthy((val == true)) ? domSetAttr(el, attrName, "") : domSetAttr(el, attrName, (String(val))))); };
|
||||
(function() {
|
||||
var existing = sxOr(domGetAttr(el, "data-sx-reactive-attrs"), "");
|
||||
var updated = (isSxTruthy(isEmpty(existing)) ? attrName : (String(existing) + String(",") + String(attrName)));
|
||||
return domSetAttr(el, "data-sx-reactive-attrs", updated);
|
||||
})();
|
||||
return (function() {
|
||||
var initial = cekRun(makeCekState(expr, env, [makeReactiveResetFrame(env, updateFn, true)]));
|
||||
return invoke(updateFn, initial);
|
||||
})();
|
||||
})(); };
|
||||
|
||||
// render-dom-portal
|
||||
var renderDomPortal = function(args, env, ns) { return (function() {
|
||||
var selector = trampoline(evalExpr(first(args), env));
|
||||
@@ -3812,6 +3843,134 @@ callExpr.push(dictGet(kwargs, k)); } }
|
||||
})(); }, keys(env)); };
|
||||
|
||||
|
||||
// === Transpiled from frames (CEK continuation frames) ===
|
||||
|
||||
// make-cek-state
|
||||
var makeCekState = function(control, env, kont) { return {"control": control, "env": env, "kont": kont, "phase": "eval", "value": NIL}; };
|
||||
|
||||
// make-cek-value
|
||||
var makeCekValue = function(value, env, kont) { return {"control": NIL, "env": env, "kont": kont, "phase": "continue", "value": value}; };
|
||||
|
||||
// cek-terminal?
|
||||
var cekTerminal_p = function(state) { return (isSxTruthy((get(state, "phase") == "continue")) && isEmpty(get(state, "kont"))); };
|
||||
|
||||
// cek-control
|
||||
var cekControl = function(s) { return get(s, "control"); };
|
||||
|
||||
// cek-env
|
||||
var cekEnv = function(s) { return get(s, "env"); };
|
||||
|
||||
// cek-kont
|
||||
var cekKont = function(s) { return get(s, "kont"); };
|
||||
|
||||
// cek-phase
|
||||
var cekPhase = function(s) { return get(s, "phase"); };
|
||||
|
||||
// cek-value
|
||||
var cekValue = function(s) { return get(s, "value"); };
|
||||
|
||||
// make-if-frame
|
||||
var makeIfFrame = function(thenExpr, elseExpr, env) { return {"type": "if", "then": thenExpr, "else": elseExpr, "env": env}; };
|
||||
|
||||
// make-when-frame
|
||||
var makeWhenFrame = function(bodyExprs, env) { return {"type": "when", "body": bodyExprs, "env": env}; };
|
||||
|
||||
// make-begin-frame
|
||||
var makeBeginFrame = function(remaining, env) { return {"type": "begin", "remaining": remaining, "env": env}; };
|
||||
|
||||
// make-let-frame
|
||||
var makeLetFrame = function(name, remaining, body, local) { return {"type": "let", "name": name, "remaining": remaining, "body": body, "env": local}; };
|
||||
|
||||
// make-define-frame
|
||||
var makeDefineFrame = function(name, env, hasEffects, effectList) { return {"type": "define", "name": name, "env": env, "has-effects": hasEffects, "effect-list": effectList}; };
|
||||
|
||||
// make-set-frame
|
||||
var makeSetFrame = function(name, env) { return {"type": "set", "name": name, "env": env}; };
|
||||
|
||||
// make-arg-frame
|
||||
var makeArgFrame = function(f, evaled, remaining, env, rawArgs) { return {"type": "arg", "f": f, "evaled": evaled, "remaining": remaining, "env": env, "raw-args": rawArgs}; };
|
||||
|
||||
// make-call-frame
|
||||
var makeCallFrame = function(f, args, env) { return {"type": "call", "f": f, "args": args, "env": env}; };
|
||||
|
||||
// make-cond-frame
|
||||
var makeCondFrame = function(remaining, env, scheme_p) { return {"type": "cond", "remaining": remaining, "env": env, "scheme": scheme_p}; };
|
||||
|
||||
// make-case-frame
|
||||
var makeCaseFrame = function(matchVal, remaining, env) { return {"type": "case", "match-val": matchVal, "remaining": remaining, "env": env}; };
|
||||
|
||||
// make-thread-frame
|
||||
var makeThreadFrame = function(remaining, env) { return {"type": "thread", "remaining": remaining, "env": env}; };
|
||||
|
||||
// make-map-frame
|
||||
var makeMapFrame = function(f, remaining, results, env) { return {"type": "map", "f": f, "remaining": remaining, "results": results, "env": env}; };
|
||||
|
||||
// make-filter-frame
|
||||
var makeFilterFrame = function(f, remaining, results, currentItem, env) { return {"type": "filter", "f": f, "remaining": remaining, "results": results, "current-item": currentItem, "env": env}; };
|
||||
|
||||
// make-reduce-frame
|
||||
var makeReduceFrame = function(f, remaining, env) { return {"type": "reduce", "f": f, "remaining": remaining, "env": env}; };
|
||||
|
||||
// make-for-each-frame
|
||||
var makeForEachFrame = function(f, remaining, env) { return {"type": "for-each", "f": f, "remaining": remaining, "env": env}; };
|
||||
|
||||
// make-scope-frame
|
||||
var makeScopeFrame = function(name, remaining, env) { return {"type": "scope", "name": name, "remaining": remaining, "env": env}; };
|
||||
|
||||
// make-reset-frame
|
||||
var makeResetFrame = function(env) { return {"type": "reset", "env": env}; };
|
||||
|
||||
// make-dict-frame
|
||||
var makeDictFrame = function(remaining, results, env) { return {"type": "dict", "remaining": remaining, "results": results, "env": env}; };
|
||||
|
||||
// make-and-frame
|
||||
var makeAndFrame = function(remaining, env) { return {"type": "and", "remaining": remaining, "env": env}; };
|
||||
|
||||
// make-or-frame
|
||||
var makeOrFrame = function(remaining, env) { return {"type": "or", "remaining": remaining, "env": env}; };
|
||||
|
||||
// make-dynamic-wind-frame
|
||||
var makeDynamicWindFrame = function(phase, bodyThunk, afterThunk, env) { return {"type": "dynamic-wind", "phase": phase, "body-thunk": bodyThunk, "after-thunk": afterThunk, "env": env}; };
|
||||
|
||||
// make-reactive-reset-frame
|
||||
var makeReactiveResetFrame = function(env, updateFn, firstRender_p) { return {"type": "reactive-reset", "env": env, "update-fn": updateFn, "first-render": firstRender_p}; };
|
||||
|
||||
// make-deref-frame
|
||||
var makeDerefFrame = function(env) { return {"type": "deref", "env": env}; };
|
||||
|
||||
// frame-type
|
||||
var frameType = function(f) { return get(f, "type"); };
|
||||
|
||||
// kont-push
|
||||
var kontPush = function(frame, kont) { return cons(frame, kont); };
|
||||
|
||||
// kont-top
|
||||
var kontTop = function(kont) { return first(kont); };
|
||||
|
||||
// kont-pop
|
||||
var kontPop = function(kont) { return rest(kont); };
|
||||
|
||||
// kont-empty?
|
||||
var kontEmpty_p = function(kont) { return isEmpty(kont); };
|
||||
|
||||
// kont-capture-to-reset
|
||||
var kontCaptureToReset = function(kont) { var scan = function(k, captured) { return (isSxTruthy(isEmpty(k)) ? error("shift without enclosing reset") : (function() {
|
||||
var frame = first(k);
|
||||
return (isSxTruthy(sxOr((frameType(frame) == "reset"), (frameType(frame) == "reactive-reset"))) ? [captured, rest(k)] : scan(rest(k), append(captured, [frame])));
|
||||
})()); };
|
||||
return scan(kont, []); };
|
||||
|
||||
// has-reactive-reset-frame?
|
||||
var hasReactiveResetFrame_p = function(kont) { return (isSxTruthy(isEmpty(kont)) ? false : (isSxTruthy((frameType(first(kont)) == "reactive-reset")) ? true : hasReactiveResetFrame_p(rest(kont)))); };
|
||||
|
||||
// kont-capture-to-reactive-reset
|
||||
var kontCaptureToReactiveReset = function(kont) { var scan = function(k, captured) { return (isSxTruthy(isEmpty(k)) ? error("reactive deref without enclosing reactive-reset") : (function() {
|
||||
var frame = first(k);
|
||||
return (isSxTruthy((frameType(frame) == "reactive-reset")) ? [captured, frame, rest(k)] : scan(rest(k), append(captured, [frame])));
|
||||
})()); };
|
||||
return scan(kont, []); };
|
||||
|
||||
|
||||
// === Transpiled from page-helpers (pure data transformation helpers) ===
|
||||
|
||||
// special-form-category-map
|
||||
@@ -4444,6 +4603,383 @@ return (function() {
|
||||
})(); };
|
||||
|
||||
|
||||
// === Transpiled from cek (explicit CEK machine evaluator) ===
|
||||
|
||||
// cek-run
|
||||
var cekRun = function(state) { return (isSxTruthy(cekTerminal_p(state)) ? cekValue(state) : cekRun(cekStep(state))); };
|
||||
|
||||
// cek-step
|
||||
var cekStep = function(state) { return (isSxTruthy((cekPhase(state) == "eval")) ? stepEval(state) : stepContinue(state)); };
|
||||
|
||||
// step-eval
|
||||
var stepEval = function(state) { return (function() {
|
||||
var expr = cekControl(state);
|
||||
var env = cekEnv(state);
|
||||
var kont = cekKont(state);
|
||||
return (function() { var _m = typeOf(expr); if (_m == "number") return makeCekValue(expr, env, kont); if (_m == "string") return makeCekValue(expr, env, kont); if (_m == "boolean") return makeCekValue(expr, env, kont); if (_m == "nil") return makeCekValue(NIL, env, kont); if (_m == "symbol") return (function() {
|
||||
var name = symbolName(expr);
|
||||
return (function() {
|
||||
var val = (isSxTruthy(envHas(env, name)) ? envGet(env, name) : (isSxTruthy(isPrimitive(name)) ? getPrimitive(name) : (isSxTruthy((name == "true")) ? true : (isSxTruthy((name == "false")) ? false : (isSxTruthy((name == "nil")) ? NIL : error((String("Undefined symbol: ") + String(name))))))));
|
||||
return makeCekValue(val, env, kont);
|
||||
})();
|
||||
})(); if (_m == "keyword") return makeCekValue(keywordName(expr), env, kont); if (_m == "dict") return (function() {
|
||||
var ks = keys(expr);
|
||||
return (isSxTruthy(isEmpty(ks)) ? makeCekValue({}, env, kont) : (function() {
|
||||
var firstKey = first(ks);
|
||||
var remainingEntries = [];
|
||||
{ var _c = rest(ks); for (var _i = 0; _i < _c.length; _i++) { var k = _c[_i]; remainingEntries.push([k, get(expr, k)]); } }
|
||||
return makeCekState(get(expr, firstKey), env, kontPush(makeDictFrame(remainingEntries, [[firstKey]], env), kont));
|
||||
})());
|
||||
})(); if (_m == "list") return (isSxTruthy(isEmpty(expr)) ? makeCekValue([], env, kont) : stepEvalList(expr, env, kont)); return makeCekValue(expr, env, kont); })();
|
||||
})(); };
|
||||
|
||||
// step-eval-list
|
||||
var stepEvalList = function(expr, env, kont) { return (function() {
|
||||
var head = first(expr);
|
||||
var args = rest(expr);
|
||||
return (isSxTruthy(!isSxTruthy(sxOr((typeOf(head) == "symbol"), (typeOf(head) == "lambda"), (typeOf(head) == "list")))) ? (isSxTruthy(isEmpty(expr)) ? makeCekValue([], env, kont) : makeCekState(first(expr), env, kontPush(makeMapFrame(NIL, rest(expr), [], env), kont))) : (isSxTruthy((typeOf(head) == "symbol")) ? (function() {
|
||||
var name = symbolName(head);
|
||||
return (isSxTruthy((name == "if")) ? stepSfIf(args, env, kont) : (isSxTruthy((name == "when")) ? stepSfWhen(args, env, kont) : (isSxTruthy((name == "cond")) ? stepSfCond(args, env, kont) : (isSxTruthy((name == "case")) ? stepSfCase(args, env, kont) : (isSxTruthy((name == "and")) ? stepSfAnd(args, env, kont) : (isSxTruthy((name == "or")) ? stepSfOr(args, env, kont) : (isSxTruthy((name == "let")) ? stepSfLet(args, env, kont) : (isSxTruthy((name == "let*")) ? stepSfLet(args, env, kont) : (isSxTruthy((name == "lambda")) ? stepSfLambda(args, env, kont) : (isSxTruthy((name == "fn")) ? stepSfLambda(args, env, kont) : (isSxTruthy((name == "define")) ? stepSfDefine(args, env, kont) : (isSxTruthy((name == "defcomp")) ? makeCekValue(sfDefcomp(args, env), env, kont) : (isSxTruthy((name == "defisland")) ? makeCekValue(sfDefisland(args, env), env, kont) : (isSxTruthy((name == "defmacro")) ? makeCekValue(sfDefmacro(args, env), env, kont) : (isSxTruthy((name == "defstyle")) ? makeCekValue(sfDefstyle(args, env), env, kont) : (isSxTruthy((name == "defhandler")) ? makeCekValue(sfDefhandler(args, env), env, kont) : (isSxTruthy((name == "defpage")) ? makeCekValue(sfDefpage(args, env), env, kont) : (isSxTruthy((name == "defquery")) ? makeCekValue(sfDefquery(args, env), env, kont) : (isSxTruthy((name == "defaction")) ? makeCekValue(sfDefaction(args, env), env, kont) : (isSxTruthy((name == "deftype")) ? makeCekValue(sfDeftype(args, env), env, kont) : (isSxTruthy((name == "defeffect")) ? makeCekValue(sfDefeffect(args, env), env, kont) : (isSxTruthy((name == "begin")) ? stepSfBegin(args, env, kont) : (isSxTruthy((name == "do")) ? stepSfBegin(args, env, kont) : (isSxTruthy((name == "quote")) ? makeCekValue((isSxTruthy(isEmpty(args)) ? NIL : first(args)), env, kont) : (isSxTruthy((name == "quasiquote")) ? makeCekValue(qqExpand(first(args), env), env, kont) : (isSxTruthy((name == "->")) ? stepSfThreadFirst(args, env, kont) : (isSxTruthy((name == "set!")) ? stepSfSet(args, env, kont) : (isSxTruthy((name == "letrec")) ? makeCekValue(sfLetrec(args, env), env, kont) : (isSxTruthy((name == "reset")) ? stepSfReset(args, env, kont) : (isSxTruthy((name == "shift")) ? stepSfShift(args, env, kont) : (isSxTruthy((name == "deref")) ? stepSfDeref(args, env, kont) : (isSxTruthy((name == "scope")) ? stepSfScope(args, env, kont) : (isSxTruthy((name == "provide")) ? stepSfProvide(args, env, kont) : (isSxTruthy((name == "dynamic-wind")) ? makeCekValue(sfDynamicWind(args, env), env, kont) : (isSxTruthy((name == "map")) ? stepHoMap(args, env, kont) : (isSxTruthy((name == "map-indexed")) ? makeCekValue(hoMapIndexed(args, env), env, kont) : (isSxTruthy((name == "filter")) ? stepHoFilter(args, env, kont) : (isSxTruthy((name == "reduce")) ? stepHoReduce(args, env, kont) : (isSxTruthy((name == "some")) ? makeCekValue(hoSome(args, env), env, kont) : (isSxTruthy((name == "every?")) ? makeCekValue(hoEvery(args, env), env, kont) : (isSxTruthy((name == "for-each")) ? stepHoForEach(args, env, kont) : (isSxTruthy((isSxTruthy(envHas(env, name)) && isMacro(envGet(env, name)))) ? (function() {
|
||||
var mac = envGet(env, name);
|
||||
return makeCekState(expandMacro(mac, args, env), env, kont);
|
||||
})() : (isSxTruthy((isSxTruthy(renderActiveP()) && isRenderExpr(expr))) ? makeCekValue(renderExpr(expr, env), env, kont) : stepEvalCall(head, args, env, kont))))))))))))))))))))))))))))))))))))))))))));
|
||||
})() : stepEvalCall(head, args, env, kont)));
|
||||
})(); };
|
||||
|
||||
// step-sf-if
|
||||
var stepSfIf = function(args, env, kont) { return makeCekState(first(args), env, kontPush(makeIfFrame(nth(args, 1), (isSxTruthy((len(args) > 2)) ? nth(args, 2) : NIL), env), kont)); };
|
||||
|
||||
// step-sf-when
|
||||
var stepSfWhen = function(args, env, kont) { return makeCekState(first(args), env, kontPush(makeWhenFrame(rest(args), env), kont)); };
|
||||
|
||||
// step-sf-begin
|
||||
var stepSfBegin = function(args, env, kont) { return (isSxTruthy(isEmpty(args)) ? makeCekValue(NIL, env, kont) : (isSxTruthy((len(args) == 1)) ? makeCekState(first(args), env, kont) : makeCekState(first(args), env, kontPush(makeBeginFrame(rest(args), env), kont)))); };
|
||||
|
||||
// step-sf-let
|
||||
var stepSfLet = function(args, env, kont) { return (isSxTruthy((typeOf(first(args)) == "symbol")) ? makeCekValue(sfNamedLet(args, env), env, kont) : (function() {
|
||||
var bindings = first(args);
|
||||
var body = rest(args);
|
||||
var local = envExtend(env);
|
||||
return (isSxTruthy(isEmpty(bindings)) ? stepSfBegin(body, local, kont) : (function() {
|
||||
var firstBinding = (isSxTruthy((isSxTruthy((typeOf(first(bindings)) == "list")) && (len(first(bindings)) == 2))) ? first(bindings) : [first(bindings), nth(bindings, 1)]);
|
||||
var restBindings = (isSxTruthy((isSxTruthy((typeOf(first(bindings)) == "list")) && (len(first(bindings)) == 2))) ? rest(bindings) : (function() {
|
||||
var pairs = [];
|
||||
reduce(function(acc, i) { return append_b(pairs, [nth(bindings, (i * 2)), nth(bindings, ((i * 2) + 1))]); }, NIL, range(1, (len(bindings) / 2)));
|
||||
return pairs;
|
||||
})());
|
||||
return (function() {
|
||||
var vname = (isSxTruthy((typeOf(first(firstBinding)) == "symbol")) ? symbolName(first(firstBinding)) : first(firstBinding));
|
||||
return makeCekState(nth(firstBinding, 1), local, kontPush(makeLetFrame(vname, restBindings, body, local), kont));
|
||||
})();
|
||||
})());
|
||||
})()); };
|
||||
|
||||
// step-sf-define
|
||||
var stepSfDefine = function(args, env, kont) { 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 effectList = (isSxTruthy((isSxTruthy((len(args) >= 4)) && isSxTruthy((typeOf(nth(args, 1)) == "keyword")) && (keywordName(nth(args, 1)) == "effects"))) ? nth(args, 2) : NIL);
|
||||
return makeCekState(nth(args, valIdx), env, kontPush(makeDefineFrame(symbolName(nameSym), env, hasEffects, effectList), kont));
|
||||
})(); };
|
||||
|
||||
// step-sf-set!
|
||||
var stepSfSet = function(args, env, kont) { return makeCekState(nth(args, 1), env, kontPush(makeSetFrame(symbolName(first(args)), env), kont)); };
|
||||
|
||||
// step-sf-and
|
||||
var stepSfAnd = function(args, env, kont) { return (isSxTruthy(isEmpty(args)) ? makeCekValue(true, env, kont) : makeCekState(first(args), env, kontPush(makeAndFrame(rest(args), env), kont))); };
|
||||
|
||||
// step-sf-or
|
||||
var stepSfOr = function(args, env, kont) { return (isSxTruthy(isEmpty(args)) ? makeCekValue(false, env, kont) : makeCekState(first(args), env, kontPush(makeOrFrame(rest(args), env), kont))); };
|
||||
|
||||
// step-sf-cond
|
||||
var stepSfCond = function(args, env, kont) { return (function() {
|
||||
var scheme_p = condScheme_p(args);
|
||||
return (isSxTruthy(scheme_p) ? (isSxTruthy(isEmpty(args)) ? makeCekValue(NIL, env, kont) : (function() {
|
||||
var clause = first(args);
|
||||
var test = first(clause);
|
||||
return (isSxTruthy(sxOr((isSxTruthy((typeOf(test) == "symbol")) && sxOr((symbolName(test) == "else"), (symbolName(test) == ":else"))), (isSxTruthy((typeOf(test) == "keyword")) && (keywordName(test) == "else")))) ? makeCekState(nth(clause, 1), env, kont) : makeCekState(test, env, kontPush(makeCondFrame(args, env, true), kont)));
|
||||
})()) : (isSxTruthy((len(args) < 2)) ? makeCekValue(NIL, env, kont) : (function() {
|
||||
var test = first(args);
|
||||
return (isSxTruthy(sxOr((isSxTruthy((typeOf(test) == "keyword")) && (keywordName(test) == "else")), (isSxTruthy((typeOf(test) == "symbol")) && sxOr((symbolName(test) == "else"), (symbolName(test) == ":else"))))) ? makeCekState(nth(args, 1), env, kont) : makeCekState(test, env, kontPush(makeCondFrame(args, env, false), kont)));
|
||||
})()));
|
||||
})(); };
|
||||
|
||||
// step-sf-case
|
||||
var stepSfCase = function(args, env, kont) { return makeCekState(first(args), env, kontPush(makeCaseFrame(NIL, rest(args), env), kont)); };
|
||||
|
||||
// step-sf-thread-first
|
||||
var stepSfThreadFirst = function(args, env, kont) { return makeCekState(first(args), env, kontPush(makeThreadFrame(rest(args), env), kont)); };
|
||||
|
||||
// step-sf-lambda
|
||||
var stepSfLambda = function(args, env, kont) { return makeCekValue(sfLambda(args, env), env, kont); };
|
||||
|
||||
// step-sf-scope
|
||||
var stepSfScope = function(args, env, kont) { return makeCekValue(sfScope(args, env), env, kont); };
|
||||
|
||||
// step-sf-provide
|
||||
var stepSfProvide = function(args, env, kont) { return makeCekValue(sfProvide(args, env), env, kont); };
|
||||
|
||||
// step-sf-reset
|
||||
var stepSfReset = function(args, env, kont) { return makeCekState(first(args), env, kontPush(makeResetFrame(env), kont)); };
|
||||
|
||||
// step-sf-shift
|
||||
var stepSfShift = function(args, env, kont) { return (function() {
|
||||
var kName = symbolName(first(args));
|
||||
var body = nth(args, 1);
|
||||
var capturedResult = kontCaptureToReset(kont);
|
||||
var captured = first(capturedResult);
|
||||
var restKont = nth(capturedResult, 1);
|
||||
return (function() {
|
||||
var k = makeCekContinuation(captured, restKont);
|
||||
return (function() {
|
||||
var shiftEnv = envExtend(env);
|
||||
envSet(shiftEnv, kName, k);
|
||||
return makeCekState(body, shiftEnv, restKont);
|
||||
})();
|
||||
})();
|
||||
})(); };
|
||||
|
||||
// step-sf-deref
|
||||
var stepSfDeref = function(args, env, kont) { return makeCekState(first(args), env, kontPush(makeDerefFrame(env), kont)); };
|
||||
|
||||
// reactive-shift-deref
|
||||
var reactiveShiftDeref = function(sig, env, kont) { return (function() {
|
||||
var scanResult = kontCaptureToReactiveReset(kont);
|
||||
var capturedFrames = first(scanResult);
|
||||
var resetFrame = nth(scanResult, 1);
|
||||
var remainingKont = nth(scanResult, 2);
|
||||
var updateFn = get(resetFrame, "update-fn");
|
||||
return (function() {
|
||||
var subDisposers = [];
|
||||
return (function() {
|
||||
var subscriber = function() { { var _c = subDisposers; for (var _i = 0; _i < _c.length; _i++) { var d = _c[_i]; invoke(d); } }
|
||||
subDisposers = [];
|
||||
return (function() {
|
||||
var newReset = makeReactiveResetFrame(env, updateFn, false);
|
||||
var newKont = concat(capturedFrames, [newReset], remainingKont);
|
||||
return withIslandScope(function(d) { return append_b(subDisposers, d); }, function() { return cekRun(makeCekValue(signalValue(sig), env, newKont)); });
|
||||
})(); };
|
||||
signalAddSub(sig, subscriber);
|
||||
registerInScope(function() { signalRemoveSub(sig, subscriber);
|
||||
return forEach(function(d) { return invoke(d); }, subDisposers); });
|
||||
return (function() {
|
||||
var initialKont = concat(capturedFrames, [resetFrame], remainingKont);
|
||||
return makeCekValue(signalValue(sig), env, initialKont);
|
||||
})();
|
||||
})();
|
||||
})();
|
||||
})(); };
|
||||
|
||||
// step-eval-call
|
||||
var stepEvalCall = function(head, args, env, kont) { return makeCekState(head, env, kontPush(makeArgFrame(NIL, [], args, env, args), kont)); };
|
||||
|
||||
// step-ho-map
|
||||
var stepHoMap = function(args, env, kont) { return makeCekValue(hoMap(args, env), env, kont); };
|
||||
|
||||
// step-ho-filter
|
||||
var stepHoFilter = function(args, env, kont) { return makeCekValue(hoFilter(args, env), env, kont); };
|
||||
|
||||
// step-ho-reduce
|
||||
var stepHoReduce = function(args, env, kont) { return makeCekValue(hoReduce(args, env), env, kont); };
|
||||
|
||||
// step-ho-for-each
|
||||
var stepHoForEach = function(args, env, kont) { return makeCekValue(hoForEach(args, env), env, kont); };
|
||||
|
||||
// step-continue
|
||||
var stepContinue = function(state) { return (function() {
|
||||
var value = cekValue(state);
|
||||
var env = cekEnv(state);
|
||||
var kont = cekKont(state);
|
||||
return (isSxTruthy(kontEmpty_p(kont)) ? state : (function() {
|
||||
var frame = kontTop(kont);
|
||||
var restK = kontPop(kont);
|
||||
var ft = frameType(frame);
|
||||
return (isSxTruthy((ft == "if")) ? (isSxTruthy((isSxTruthy(value) && !isSxTruthy(isNil(value)))) ? makeCekState(get(frame, "then"), get(frame, "env"), restK) : (isSxTruthy(isNil(get(frame, "else"))) ? makeCekValue(NIL, env, restK) : makeCekState(get(frame, "else"), get(frame, "env"), restK))) : (isSxTruthy((ft == "when")) ? (isSxTruthy((isSxTruthy(value) && !isSxTruthy(isNil(value)))) ? (function() {
|
||||
var body = get(frame, "body");
|
||||
var fenv = get(frame, "env");
|
||||
return (isSxTruthy(isEmpty(body)) ? makeCekValue(NIL, fenv, restK) : (isSxTruthy((len(body) == 1)) ? makeCekState(first(body), fenv, restK) : makeCekState(first(body), fenv, kontPush(makeBeginFrame(rest(body), fenv), restK))));
|
||||
})() : makeCekValue(NIL, env, restK)) : (isSxTruthy((ft == "begin")) ? (function() {
|
||||
var remaining = get(frame, "remaining");
|
||||
var fenv = get(frame, "env");
|
||||
return (isSxTruthy(isEmpty(remaining)) ? makeCekValue(value, fenv, restK) : (isSxTruthy((len(remaining) == 1)) ? makeCekState(first(remaining), fenv, restK) : makeCekState(first(remaining), fenv, kontPush(makeBeginFrame(rest(remaining), fenv), restK))));
|
||||
})() : (isSxTruthy((ft == "let")) ? (function() {
|
||||
var name = get(frame, "name");
|
||||
var remaining = get(frame, "remaining");
|
||||
var body = get(frame, "body");
|
||||
var local = get(frame, "env");
|
||||
envSet(local, name, value);
|
||||
return (isSxTruthy(isEmpty(remaining)) ? stepSfBegin(body, local, restK) : (function() {
|
||||
var nextBinding = first(remaining);
|
||||
var vname = (isSxTruthy((typeOf(first(nextBinding)) == "symbol")) ? symbolName(first(nextBinding)) : first(nextBinding));
|
||||
return makeCekState(nth(nextBinding, 1), local, kontPush(makeLetFrame(vname, rest(remaining), body, local), restK));
|
||||
})());
|
||||
})() : (isSxTruthy((ft == "define")) ? (function() {
|
||||
var name = get(frame, "name");
|
||||
var fenv = get(frame, "env");
|
||||
var hasEffects = get(frame, "has-effects");
|
||||
var effectList = get(frame, "effect-list");
|
||||
if (isSxTruthy((isSxTruthy(isLambda(value)) && isNil(lambdaName(value))))) {
|
||||
value.name = name;
|
||||
}
|
||||
envSet(fenv, name, value);
|
||||
if (isSxTruthy(hasEffects)) {
|
||||
(function() {
|
||||
var effectNames = (isSxTruthy((typeOf(effectList) == "list")) ? map(function(e) { return (isSxTruthy((typeOf(e) == "symbol")) ? symbolName(e) : (String(e))); }, effectList) : [(String(effectList))]);
|
||||
var effectAnns = (isSxTruthy(envHas(fenv, "*effect-annotations*")) ? envGet(fenv, "*effect-annotations*") : {});
|
||||
effectAnns[name] = effectNames;
|
||||
return envSet(fenv, "*effect-annotations*", effectAnns);
|
||||
})();
|
||||
}
|
||||
return makeCekValue(value, fenv, restK);
|
||||
})() : (isSxTruthy((ft == "set")) ? (function() {
|
||||
var name = get(frame, "name");
|
||||
var fenv = get(frame, "env");
|
||||
envSet(fenv, name, value);
|
||||
return makeCekValue(value, env, restK);
|
||||
})() : (isSxTruthy((ft == "and")) ? (isSxTruthy(!isSxTruthy(value)) ? makeCekValue(value, env, restK) : (function() {
|
||||
var remaining = get(frame, "remaining");
|
||||
return (isSxTruthy(isEmpty(remaining)) ? makeCekValue(value, env, restK) : makeCekState(first(remaining), get(frame, "env"), (isSxTruthy((len(remaining) == 1)) ? restK : kontPush(makeAndFrame(rest(remaining), get(frame, "env")), restK))));
|
||||
})()) : (isSxTruthy((ft == "or")) ? (isSxTruthy(value) ? makeCekValue(value, env, restK) : (function() {
|
||||
var remaining = get(frame, "remaining");
|
||||
return (isSxTruthy(isEmpty(remaining)) ? makeCekValue(false, env, restK) : makeCekState(first(remaining), get(frame, "env"), (isSxTruthy((len(remaining) == 1)) ? restK : kontPush(makeOrFrame(rest(remaining), get(frame, "env")), restK))));
|
||||
})()) : (isSxTruthy((ft == "cond")) ? (function() {
|
||||
var remaining = get(frame, "remaining");
|
||||
var fenv = get(frame, "env");
|
||||
var scheme_p = get(frame, "scheme");
|
||||
return (isSxTruthy(scheme_p) ? (isSxTruthy(value) ? makeCekState(nth(first(remaining), 1), fenv, restK) : (function() {
|
||||
var nextClauses = rest(remaining);
|
||||
return (isSxTruthy(isEmpty(nextClauses)) ? makeCekValue(NIL, fenv, restK) : (function() {
|
||||
var nextClause = first(nextClauses);
|
||||
var nextTest = first(nextClause);
|
||||
return (isSxTruthy(sxOr((isSxTruthy((typeOf(nextTest) == "symbol")) && sxOr((symbolName(nextTest) == "else"), (symbolName(nextTest) == ":else"))), (isSxTruthy((typeOf(nextTest) == "keyword")) && (keywordName(nextTest) == "else")))) ? makeCekState(nth(nextClause, 1), fenv, restK) : makeCekState(nextTest, fenv, kontPush(makeCondFrame(nextClauses, fenv, true), restK)));
|
||||
})());
|
||||
})()) : (isSxTruthy(value) ? makeCekState(nth(remaining, 1), fenv, restK) : (function() {
|
||||
var next = slice(remaining, 2);
|
||||
return (isSxTruthy((len(next) < 2)) ? makeCekValue(NIL, fenv, restK) : (function() {
|
||||
var nextTest = first(next);
|
||||
return (isSxTruthy(sxOr((isSxTruthy((typeOf(nextTest) == "keyword")) && (keywordName(nextTest) == "else")), (isSxTruthy((typeOf(nextTest) == "symbol")) && sxOr((symbolName(nextTest) == "else"), (symbolName(nextTest) == ":else"))))) ? makeCekState(nth(next, 1), fenv, restK) : makeCekState(nextTest, fenv, kontPush(makeCondFrame(next, fenv, false), restK)));
|
||||
})());
|
||||
})()));
|
||||
})() : (isSxTruthy((ft == "case")) ? (function() {
|
||||
var matchVal = get(frame, "match-val");
|
||||
var remaining = get(frame, "remaining");
|
||||
var fenv = get(frame, "env");
|
||||
return (isSxTruthy(isNil(matchVal)) ? sfCaseStepLoop(value, remaining, fenv, restK) : sfCaseStepLoop(matchVal, remaining, fenv, restK));
|
||||
})() : (isSxTruthy((ft == "thread")) ? (function() {
|
||||
var remaining = get(frame, "remaining");
|
||||
var fenv = get(frame, "env");
|
||||
return (isSxTruthy(isEmpty(remaining)) ? makeCekValue(value, fenv, restK) : (function() {
|
||||
var form = first(remaining);
|
||||
var restForms = rest(remaining);
|
||||
return (function() {
|
||||
var result = (isSxTruthy((typeOf(form) == "list")) ? (function() {
|
||||
var f = trampoline(evalExpr(first(form), fenv));
|
||||
var rargs = map(function(a) { return trampoline(evalExpr(a, fenv)); }, rest(form));
|
||||
var allArgs = cons(value, rargs);
|
||||
return (isSxTruthy((isSxTruthy(isCallable(f)) && !isSxTruthy(isLambda(f)))) ? apply(f, allArgs) : (isSxTruthy(isLambda(f)) ? trampoline(callLambda(f, allArgs, fenv)) : error((String("-> form not callable: ") + String(inspect(f))))));
|
||||
})() : (function() {
|
||||
var f = trampoline(evalExpr(form, fenv));
|
||||
return (isSxTruthy((isSxTruthy(isCallable(f)) && !isSxTruthy(isLambda(f)))) ? f(value) : (isSxTruthy(isLambda(f)) ? trampoline(callLambda(f, [value], fenv)) : error((String("-> form not callable: ") + String(inspect(f))))));
|
||||
})());
|
||||
return (isSxTruthy(isEmpty(restForms)) ? makeCekValue(result, fenv, restK) : makeCekValue(result, fenv, kontPush(makeThreadFrame(restForms, fenv), restK)));
|
||||
})();
|
||||
})());
|
||||
})() : (isSxTruthy((ft == "arg")) ? (function() {
|
||||
var f = get(frame, "f");
|
||||
var evaled = get(frame, "evaled");
|
||||
var remaining = get(frame, "remaining");
|
||||
var fenv = get(frame, "env");
|
||||
var rawArgs = get(frame, "raw-args");
|
||||
return (isSxTruthy(isNil(f)) ? (isSxTruthy(isEmpty(remaining)) ? continueWithCall(value, [], fenv, rawArgs, restK) : makeCekState(first(remaining), fenv, kontPush(makeArgFrame(value, [], rest(remaining), fenv, rawArgs), restK))) : (function() {
|
||||
var newEvaled = append(evaled, [value]);
|
||||
return (isSxTruthy(isEmpty(remaining)) ? continueWithCall(f, newEvaled, fenv, rawArgs, restK) : makeCekState(first(remaining), fenv, kontPush(makeArgFrame(f, newEvaled, rest(remaining), fenv, rawArgs), restK)));
|
||||
})());
|
||||
})() : (isSxTruthy((ft == "dict")) ? (function() {
|
||||
var remaining = get(frame, "remaining");
|
||||
var results = get(frame, "results");
|
||||
var fenv = get(frame, "env");
|
||||
return (function() {
|
||||
var lastResult = last(results);
|
||||
var completed = append(slice(results, 0, (len(results) - 1)), [[first(lastResult), value]]);
|
||||
return (isSxTruthy(isEmpty(remaining)) ? (function() {
|
||||
var d = {};
|
||||
{ var _c = completed; for (var _i = 0; _i < _c.length; _i++) { var pair = _c[_i]; d[first(pair)] = nth(pair, 1); } }
|
||||
return makeCekValue(d, fenv, restK);
|
||||
})() : (function() {
|
||||
var nextEntry = first(remaining);
|
||||
return makeCekState(nth(nextEntry, 1), fenv, kontPush(makeDictFrame(rest(remaining), append(completed, [[first(nextEntry)]]), fenv), restK));
|
||||
})());
|
||||
})();
|
||||
})() : (isSxTruthy((ft == "reset")) ? makeCekValue(value, env, restK) : (isSxTruthy((ft == "deref")) ? (function() {
|
||||
var val = value;
|
||||
var fenv = get(frame, "env");
|
||||
return (isSxTruthy(!isSxTruthy(isSignal(val))) ? makeCekValue(val, fenv, restK) : (isSxTruthy(hasReactiveResetFrame_p(restK)) ? reactiveShiftDeref(val, fenv, restK) : ((function() {
|
||||
var ctx = sxContext("sx-reactive", NIL);
|
||||
return (isSxTruthy(ctx) ? (function() {
|
||||
var depList = get(ctx, "deps");
|
||||
var notifyFn = get(ctx, "notify");
|
||||
return (isSxTruthy(!isSxTruthy(contains(depList, val))) ? (append_b(depList, val), signalAddSub(val, notifyFn)) : NIL);
|
||||
})() : NIL);
|
||||
})(), makeCekValue(signalValue(val), fenv, restK))));
|
||||
})() : (isSxTruthy((ft == "reactive-reset")) ? (function() {
|
||||
var updateFn = get(frame, "update-fn");
|
||||
var first_p = get(frame, "first-render");
|
||||
if (isSxTruthy((isSxTruthy(updateFn) && !isSxTruthy(first_p)))) {
|
||||
invoke(updateFn, value);
|
||||
}
|
||||
return makeCekValue(value, env, restK);
|
||||
})() : (isSxTruthy((ft == "scope")) ? (function() {
|
||||
var name = get(frame, "name");
|
||||
var remaining = get(frame, "remaining");
|
||||
var fenv = get(frame, "env");
|
||||
return (isSxTruthy(isEmpty(remaining)) ? (scopePop(name), makeCekValue(value, fenv, restK)) : makeCekState(first(remaining), fenv, kontPush(makeScopeFrame(name, rest(remaining), fenv), restK)));
|
||||
})() : error((String("Unknown frame type: ") + String(ft))))))))))))))))))));
|
||||
})());
|
||||
})(); };
|
||||
|
||||
// continue-with-call
|
||||
var continueWithCall = function(f, args, env, rawArgs, kont) { return (isSxTruthy(continuation_p(f)) ? (function() {
|
||||
var arg = (isSxTruthy(isEmpty(args)) ? NIL : first(args));
|
||||
var contData = continuationData(f);
|
||||
return (function() {
|
||||
var captured = get(contData, "captured");
|
||||
var restK = get(contData, "rest-kont");
|
||||
return makeCekValue(arg, env, concat(captured, restK));
|
||||
})();
|
||||
})() : (isSxTruthy((isSxTruthy(isCallable(f)) && isSxTruthy(!isSxTruthy(isLambda(f))) && isSxTruthy(!isSxTruthy(isComponent(f))) && !isSxTruthy(isIsland(f)))) ? makeCekValue(apply(f, args), env, kont) : (isSxTruthy(isLambda(f)) ? (function() {
|
||||
var params = lambdaParams(f);
|
||||
var local = envMerge(lambdaClosure(f), env);
|
||||
return (isSxTruthy((len(args) > len(params))) ? error((String(sxOr(lambdaName(f), "lambda")) + String(" expects ") + String(len(params)) + String(" args, got ") + String(len(args)))) : (forEach(function(pair) { return envSet(local, first(pair), nth(pair, 1)); }, zip(params, args)), forEach(function(p) { return envSet(local, p, NIL); }, slice(params, len(args))), makeCekState(lambdaBody(f), local, kont)));
|
||||
})() : (isSxTruthy(sxOr(isComponent(f), isIsland(f))) ? (function() {
|
||||
var parsed = parseKeywordArgs(rawArgs, env);
|
||||
var kwargs = first(parsed);
|
||||
var children = nth(parsed, 1);
|
||||
var local = envMerge(componentClosure(f), env);
|
||||
{ var _c = componentParams(f); for (var _i = 0; _i < _c.length; _i++) { var p = _c[_i]; envSet(local, p, sxOr(dictGet(kwargs, p), NIL)); } }
|
||||
if (isSxTruthy(componentHasChildren(f))) {
|
||||
envSet(local, "children", children);
|
||||
}
|
||||
return makeCekState(componentBody(f), local, kont);
|
||||
})() : error((String("Not callable: ") + String(inspect(f)))))))); };
|
||||
|
||||
// sf-case-step-loop
|
||||
var sfCaseStepLoop = function(matchVal, clauses, env, kont) { return (isSxTruthy((len(clauses) < 2)) ? makeCekValue(NIL, env, kont) : (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"))))) ? makeCekState(body, env, kont) : (function() {
|
||||
var testVal = trampoline(evalExpr(test, env));
|
||||
return (isSxTruthy((matchVal == testVal)) ? makeCekState(body, env, kont) : sfCaseStepLoop(matchVal, slice(clauses, 2), env, kont));
|
||||
})());
|
||||
})()); };
|
||||
|
||||
// eval-expr-cek
|
||||
var evalExprCek = function(expr, env) { return cekRun(makeCekState(expr, env, [])); };
|
||||
|
||||
// trampoline-cek
|
||||
var trampolineCek = function(val) { return (isSxTruthy(isThunk(val)) ? evalExprCek(thunkExpr(val), thunkEnv(val)) : val); };
|
||||
|
||||
|
||||
// =========================================================================
|
||||
// Platform interface — DOM adapter (browser-only)
|
||||
// =========================================================================
|
||||
@@ -5754,6 +6290,27 @@ return (function() {
|
||||
|
||||
|
||||
|
||||
// =========================================================================
|
||||
// Platform: CEK module — explicit CEK machine
|
||||
// =========================================================================
|
||||
|
||||
// Standalone aliases for primitives used by cek.sx / frames.sx
|
||||
var inc = PRIMITIVES["inc"];
|
||||
var dec = PRIMITIVES["dec"];
|
||||
var zip_pairs = PRIMITIVES["zip-pairs"];
|
||||
|
||||
var continuation_p = PRIMITIVES["continuation?"];
|
||||
|
||||
function makeCekContinuation(captured, restKont) {
|
||||
var c = new Continuation(function(v) { return v !== undefined ? v : NIL; });
|
||||
c._cek_data = {"captured": captured, "rest-kont": restKont};
|
||||
return c;
|
||||
}
|
||||
function continuationData(c) {
|
||||
return (c && c._cek_data) ? c._cek_data : {};
|
||||
}
|
||||
|
||||
|
||||
// =========================================================================
|
||||
// Post-transpilation fixups
|
||||
// =========================================================================
|
||||
@@ -5878,6 +6435,94 @@ return (function() {
|
||||
PRIMITIVES["build-routing-analysis"] = buildRoutingAnalysis;
|
||||
PRIMITIVES["build-affinity-analysis"] = buildAffinityAnalysis;
|
||||
|
||||
// Override recursive cekRun with iterative loop (avoids stack overflow)
|
||||
cekRun = function(state) {
|
||||
while (!cekTerminal_p(state)) { state = cekStep(state); }
|
||||
return cekValue(state);
|
||||
};
|
||||
|
||||
|
||||
// =========================================================================
|
||||
// Extension: Delimited continuations (shift/reset)
|
||||
// =========================================================================
|
||||
|
||||
function Continuation(fn) { this.fn = fn; }
|
||||
Continuation.prototype._continuation = true;
|
||||
Continuation.prototype.call = function(value) { return this.fn(value !== undefined ? value : NIL); };
|
||||
|
||||
function ShiftSignal(kName, body, env) {
|
||||
this.kName = kName;
|
||||
this.body = body;
|
||||
this.env = env;
|
||||
}
|
||||
|
||||
PRIMITIVES["continuation?"] = function(x) { return x != null && x._continuation === true; };
|
||||
|
||||
var _resetResume = [];
|
||||
|
||||
function sfReset(args, env) {
|
||||
var body = args[0];
|
||||
try {
|
||||
return trampoline(evalExpr(body, env));
|
||||
} catch (e) {
|
||||
if (e instanceof ShiftSignal) {
|
||||
var sig = e;
|
||||
var cont = new Continuation(function(value) {
|
||||
if (value === undefined) value = NIL;
|
||||
_resetResume.push(value);
|
||||
try {
|
||||
return trampoline(evalExpr(body, env));
|
||||
} finally {
|
||||
_resetResume.pop();
|
||||
}
|
||||
});
|
||||
var sigEnv = merge(sig.env);
|
||||
sigEnv[sig.kName] = cont;
|
||||
return trampoline(evalExpr(sig.body, sigEnv));
|
||||
}
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
function sfShift(args, env) {
|
||||
if (_resetResume.length > 0) {
|
||||
return _resetResume[_resetResume.length - 1];
|
||||
}
|
||||
var kName = symbolName(args[0]);
|
||||
var body = args[1];
|
||||
throw new ShiftSignal(kName, body, env);
|
||||
}
|
||||
|
||||
// Wrap evalList to intercept reset/shift
|
||||
var _baseEvalList = evalList;
|
||||
evalList = function(expr, env) {
|
||||
var head = expr[0];
|
||||
if (isSym(head)) {
|
||||
var name = head.name;
|
||||
if (name === "reset") return sfReset(expr.slice(1), env);
|
||||
if (name === "shift") return sfShift(expr.slice(1), env);
|
||||
}
|
||||
return _baseEvalList(expr, env);
|
||||
};
|
||||
|
||||
// Wrap aserSpecial to handle reset/shift in SX wire mode
|
||||
if (typeof aserSpecial === "function") {
|
||||
var _baseAserSpecial = aserSpecial;
|
||||
aserSpecial = function(name, expr, env) {
|
||||
if (name === "reset") return sfReset(expr.slice(1), env);
|
||||
if (name === "shift") return sfShift(expr.slice(1), env);
|
||||
return _baseAserSpecial(name, expr, env);
|
||||
};
|
||||
}
|
||||
|
||||
// Wrap typeOf to recognize continuations
|
||||
var _baseTypeOf = typeOf;
|
||||
typeOf = function(x) {
|
||||
if (x != null && x._continuation) return "continuation";
|
||||
return _baseTypeOf(x);
|
||||
};
|
||||
|
||||
|
||||
// =========================================================================
|
||||
// Async IO: Promise-aware rendering for client-side IO primitives
|
||||
// =========================================================================
|
||||
|
||||
Reference in New Issue
Block a user