Add letrec to render-aware HTML forms — stepper island now SSRs
letrec in adapter-html.sx: evaluate via CEK (which handles mutual recursion and returns a thunk), then render-value-to-html unwraps the thunk and renders the expression with the letrec's local env. Both islands (~layouts/header and ~home/stepper) now render server-side with hydration markers and CSS classes. 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-23T15:29:13Z";
|
||||
var SX_VERSION = "2026-03-23T15:39:32Z";
|
||||
|
||||
function isNil(x) { return x === NIL || x === null || x === undefined; }
|
||||
function isSxTruthy(x) { return x !== false && !isNil(x); }
|
||||
@@ -2464,7 +2464,7 @@ PRIMITIVES["render-to-html"] = renderToHtml;
|
||||
PRIMITIVES["render-value-to-html"] = renderValueToHtml;
|
||||
|
||||
// RENDER_HTML_FORMS
|
||||
var RENDER_HTML_FORMS = ["if", "when", "cond", "case", "let", "let*", "begin", "do", "define", "defcomp", "defisland", "defmacro", "defstyle", "defhandler", "deftype", "defeffect", "map", "map-indexed", "filter", "for-each", "scope", "provide"];
|
||||
var RENDER_HTML_FORMS = ["if", "when", "cond", "case", "let", "let*", "letrec", "begin", "do", "define", "defcomp", "defisland", "defmacro", "defstyle", "defhandler", "deftype", "defeffect", "map", "map-indexed", "filter", "for-each", "scope", "provide"];
|
||||
PRIMITIVES["RENDER_HTML_FORMS"] = RENDER_HTML_FORMS;
|
||||
|
||||
// render-html-form?
|
||||
@@ -2492,7 +2492,10 @@ PRIMITIVES["render-list-to-html"] = renderListToHtml;
|
||||
})() : (isSxTruthy((name == "when")) ? (isSxTruthy(!isSxTruthy(trampoline(evalExpr(nth(expr, 1), env)))) ? "" : (isSxTruthy((len(expr) == 3)) ? renderToHtml(nth(expr, 2), env) : join("", map(function(i) { return renderToHtml(nth(expr, i), env); }, range(2, len(expr)))))) : (isSxTruthy((name == "cond")) ? (function() {
|
||||
var branch = evalCond(rest(expr), env);
|
||||
return (isSxTruthy(branch) ? renderToHtml(branch, env) : "");
|
||||
})() : (isSxTruthy((name == "case")) ? renderToHtml(trampoline(evalExpr(expr, env)), env) : (isSxTruthy(sxOr((name == "let"), (name == "let*"))) ? (function() {
|
||||
})() : (isSxTruthy((name == "case")) ? renderToHtml(trampoline(evalExpr(expr, env)), env) : (isSxTruthy((name == "letrec")) ? (function() {
|
||||
var result = evalExpr(expr, env);
|
||||
return renderValueToHtml(result, env);
|
||||
})() : (isSxTruthy(sxOr((name == "let"), (name == "let*"))) ? (function() {
|
||||
var local = processBindings(nth(expr, 1), env);
|
||||
return (isSxTruthy((len(expr) == 3)) ? renderToHtml(nth(expr, 2), local) : join("", map(function(i) { return renderToHtml(nth(expr, i), local); }, range(2, len(expr)))));
|
||||
})() : (isSxTruthy(sxOr((name == "begin"), (name == "do"))) ? (isSxTruthy((len(expr) == 2)) ? renderToHtml(nth(expr, 1), env) : join("", map(function(i) { return renderToHtml(nth(expr, i), env); }, range(1, len(expr))))) : (isSxTruthy(isDefinitionForm(name)) ? (trampoline(evalExpr(expr, env)), "") : (isSxTruthy((name == "map")) ? (function() {
|
||||
@@ -2530,7 +2533,7 @@ PRIMITIVES["render-list-to-html"] = renderListToHtml;
|
||||
scopePop(provName);
|
||||
return result;
|
||||
})();
|
||||
})() : renderValueToHtml(trampoline(evalExpr(expr, env)), env)))))))))))))); };
|
||||
})() : renderValueToHtml(trampoline(evalExpr(expr, env)), env))))))))))))))); };
|
||||
PRIMITIVES["dispatch-html-form"] = dispatchHtmlForm;
|
||||
|
||||
// render-lambda-html
|
||||
|
||||
Reference in New Issue
Block a user