Spec eval-cond and process-bindings in render.sx (remove platform implementations)
eval-cond and process-bindings were hand-written platform JS in bootstrap_js.py rather than specced in .sx files. This violated the SX host architecture principle. Now specced in render.sx as shared render adapter helpers, bootstrapped to both JS and Python. eval-cond handles both scheme-style ((test body) ...) and clojure-style (test body test body ...) cond clauses. Returns unevaluated body expression for the adapter to render in its own mode. process-bindings evaluates let-binding pairs and returns extended env. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -493,39 +493,7 @@
|
||||
"map":1,"map-indexed":1,"filter":1,"reduce":1,"some":1,"every?":1,"for-each":1
|
||||
}; }
|
||||
|
||||
// processBindings and evalCond — exposed for DOM adapter render forms
|
||||
function processBindings(bindings, env) {
|
||||
var local = merge(env);
|
||||
for (var i = 0; i < bindings.length; i++) {
|
||||
var pair = bindings[i];
|
||||
if (Array.isArray(pair) && pair.length >= 2) {
|
||||
var name = isSym(pair[0]) ? pair[0].name : String(pair[0]);
|
||||
local[name] = trampoline(evalExpr(pair[1], local));
|
||||
}
|
||||
}
|
||||
return local;
|
||||
}
|
||||
function evalCond(clauses, env) {
|
||||
// Detect scheme-style ((test body) ...) vs clojure-style (test body test body ...)
|
||||
var scheme = clauses.length > 0 && Array.isArray(clauses[0]) && clauses[0].length === 2;
|
||||
if (scheme) {
|
||||
for (var i = 0; i < clauses.length; i++) {
|
||||
var clause = clauses[i];
|
||||
var test = clause[0], body = clause[1];
|
||||
if (isSym(test) && (test.name === "else" || test.name === ":else")) return body;
|
||||
if (isKw(test) && test.name === "else") return body;
|
||||
if (isSxTruthy(trampoline(evalExpr(test, env)))) return body;
|
||||
}
|
||||
} else {
|
||||
for (var i = 0; i < clauses.length; i += 2) {
|
||||
var test = clauses[i];
|
||||
if (isSym(test) && test.name === ":else") return clauses[i + 1];
|
||||
if (isKw(test) && test.name === "else") return clauses[i + 1];
|
||||
if (isSxTruthy(trampoline(evalExpr(test, env)))) return clauses[i + 1];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
// processBindings and evalCond — now specced in render.sx, bootstrapped above
|
||||
|
||||
function isDefinitionForm(name) {
|
||||
return name === "define" || name === "defcomp" || name === "defmacro" ||
|
||||
@@ -1082,6 +1050,36 @@ return append_b(inits, nth(binding, 1)); }, bindings) : reduce(function(acc, pai
|
||||
return (isSxTruthy((isSxTruthy(contains(BOOLEAN_ATTRS, key)) && val)) ? (String(" ") + String(key)) : (isSxTruthy((isSxTruthy(contains(BOOLEAN_ATTRS, key)) && !val)) ? "" : (isSxTruthy(isNil(val)) ? "" : (isSxTruthy((isSxTruthy((key == "style")) && isStyleValue(val))) ? (String(" class=\"") + String(styleValueClass(val)) + String("\"")) : (String(" ") + String(key) + String("=\"") + String(escapeAttr((String(val)))) + String("\""))))));
|
||||
})(); }, keys(attrs))); };
|
||||
|
||||
// eval-cond
|
||||
var evalCond = function(clauses, env) { return (isSxTruthy((isSxTruthy(!isEmpty(clauses)) && isSxTruthy((typeOf(first(clauses)) == "list")) && (len(first(clauses)) == 2))) ? evalCondScheme(clauses, env) : evalCondClojure(clauses, env)); };
|
||||
|
||||
// eval-cond-scheme
|
||||
var evalCondScheme = 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")))) ? body : (isSxTruthy(trampoline(evalExpr(test, env))) ? body : evalCondScheme(rest(clauses), env)));
|
||||
})()); };
|
||||
|
||||
// eval-cond-clojure
|
||||
var evalCondClojure = 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"))))) ? body : (isSxTruthy(trampoline(evalExpr(test, env))) ? body : evalCondClojure(slice(clauses, 2), env)));
|
||||
})()); };
|
||||
|
||||
// process-bindings
|
||||
var processBindings = function(bindings, env) { return (function() {
|
||||
var local = merge(env);
|
||||
{ var _c = bindings; for (var _i = 0; _i < _c.length; _i++) { var pair = _c[_i]; if (isSxTruthy((isSxTruthy((typeOf(pair) == "list")) && (len(pair) >= 2)))) {
|
||||
(function() {
|
||||
var name = (isSxTruthy((typeOf(first(pair)) == "symbol")) ? symbolName(first(pair)) : (String(first(pair))));
|
||||
return envSet(local, name, trampoline(evalExpr(nth(pair, 1), local)));
|
||||
})();
|
||||
} } }
|
||||
return local;
|
||||
})(); };
|
||||
|
||||
|
||||
// === Transpiled from parser ===
|
||||
|
||||
|
||||
Reference in New Issue
Block a user