Split env-bind! from env-set!: fix lexical scoping and closures
Two fundamental environment bugs fixed: 1. env-set! was used for both binding creation (let, define, params) and mutation (set!). Binding creation must NOT walk the scope chain — it should set on the immediate env. Only set! should walk. Fix: introduce env-bind! for all binding creation. env-set! now exclusively means "mutate existing binding, walk scope chain". Changed across spec (eval.sx, cek.sx, render.sx) and all web adapters (dom, html, sx, async, boot, orchestration, forms). 2. makeLambda/makeComponent/makeMacro/makeIsland used merge(env) to flatten the closure into a plain object, destroying the prototype chain. This meant set! inside closures couldn't reach the original binding — it modified a snapshot copy instead. Fix: store env directly as closure (no merge). The prototype chain is preserved, so set! walks up to the original scope. Tests: 499/516 passing (96.7%), up from 485/516. Fixed: define self-reference, let scope isolation, set! through closures, counter-via-closure pattern, recursive functions. 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-15T11:07:52Z";
|
||||
var SX_VERSION = "2026-03-15T11:38:02Z";
|
||||
|
||||
function isNil(x) { return x === NIL || x === null || x === undefined; }
|
||||
function isSxTruthy(x) { return x !== false && !isNil(x); }
|
||||
@@ -122,12 +122,12 @@
|
||||
function makeSymbol(n) { return new Symbol(n); }
|
||||
function makeKeyword(n) { return new Keyword(n); }
|
||||
|
||||
function makeLambda(params, body, env) { return new Lambda(params, body, merge(env)); }
|
||||
function makeLambda(params, body, env) { return new Lambda(params, body, env); }
|
||||
function makeComponent(name, params, hasChildren, body, env, affinity) {
|
||||
return new Component(name, params, hasChildren, body, merge(env), affinity);
|
||||
return new Component(name, params, hasChildren, body, env, affinity);
|
||||
}
|
||||
function makeMacro(params, restParam, body, env, name) {
|
||||
return new Macro(params, restParam, body, merge(env), name);
|
||||
return new Macro(params, restParam, body, env, name);
|
||||
}
|
||||
function makeThunk(expr, env) { return new Thunk(expr, env); }
|
||||
|
||||
@@ -217,7 +217,7 @@
|
||||
|
||||
// Island platform
|
||||
function makeIsland(name, params, hasChildren, body, env) {
|
||||
return new Island(name, params, hasChildren, body, merge(env));
|
||||
return new Island(name, params, hasChildren, body, env);
|
||||
}
|
||||
|
||||
// JSON / dict helpers for island state serialization
|
||||
@@ -232,6 +232,11 @@
|
||||
|
||||
function envHas(env, name) { return name in env; }
|
||||
function envGet(env, name) { return env[name]; }
|
||||
function envBind(env, name, val) {
|
||||
// Direct property set — creates or overwrites on THIS env only.
|
||||
// Used by let, define, defcomp, lambda param binding.
|
||||
env[name] = val;
|
||||
}
|
||||
function envSet(env, name, val) {
|
||||
// Walk prototype chain to find where the variable is defined (for set!)
|
||||
var obj = env;
|
||||
@@ -843,7 +848,7 @@ PRIMITIVES["eval-call"] = evalCall;
|
||||
var callLambda = function(f, args, callerEnv) { return (function() {
|
||||
var params = lambdaParams(f);
|
||||
var local = envMerge(lambdaClosure(f), callerEnv);
|
||||
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))), makeThunk(lambdaBody(f), local)));
|
||||
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 envBind(local, first(pair), nth(pair, 1)); }, zip(params, args)), forEach(function(p) { return envBind(local, p, NIL); }, slice(params, len(args))), makeThunk(lambdaBody(f), local)));
|
||||
})(); };
|
||||
PRIMITIVES["call-lambda"] = callLambda;
|
||||
|
||||
@@ -853,9 +858,9 @@ PRIMITIVES["call-lambda"] = callLambda;
|
||||
var kwargs = first(parsed);
|
||||
var children = nth(parsed, 1);
|
||||
var local = envMerge(componentClosure(comp), env);
|
||||
{ var _c = componentParams(comp); for (var _i = 0; _i < _c.length; _i++) { var p = _c[_i]; envSet(local, p, sxOr(dictGet(kwargs, p), NIL)); } }
|
||||
{ var _c = componentParams(comp); for (var _i = 0; _i < _c.length; _i++) { var p = _c[_i]; envBind(local, p, sxOr(dictGet(kwargs, p), NIL)); } }
|
||||
if (isSxTruthy(componentHasChildren(comp))) {
|
||||
envSet(local, "children", children);
|
||||
envBind(local, "children", children);
|
||||
}
|
||||
return makeThunk(componentBody(comp), local);
|
||||
})(); };
|
||||
@@ -951,13 +956,13 @@ PRIMITIVES["sf-or"] = sfOr;
|
||||
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 envSet(local, vname, trampoline(evalExpr(nth(binding, 1), local)));
|
||||
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 envSet(local, vname, trampoline(evalExpr(valExpr, local)));
|
||||
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)); } }
|
||||
@@ -978,7 +983,7 @@ return append_b(inits, nth(binding, 1)); }, bindings) : reduce(function(acc, pai
|
||||
var loopBody = (isSxTruthy((len(body) == 1)) ? first(body) : cons(makeSymbol("begin"), body));
|
||||
var loopFn = makeLambda(params, loopBody, env);
|
||||
loopFn.name = loopName;
|
||||
envSet(lambdaClosure(loopFn), loopName, loopFn);
|
||||
envBind(lambdaClosure(loopFn), loopName, loopFn);
|
||||
return (function() {
|
||||
var initVals = map(function(e) { return trampoline(evalExpr(e, env)); }, inits);
|
||||
return callLambda(loopFn, initVals, env);
|
||||
@@ -1006,14 +1011,14 @@ PRIMITIVES["sf-lambda"] = sfLambda;
|
||||
if (isSxTruthy((isSxTruthy(isLambda(value)) && isNil(lambdaName(value))))) {
|
||||
value.name = symbolName(nameSym);
|
||||
}
|
||||
envSet(env, symbolName(nameSym), value);
|
||||
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 envSet(env, "*effect-annotations*", effectAnns);
|
||||
return envBind(env, "*effect-annotations*", effectAnns);
|
||||
})();
|
||||
}
|
||||
return value;
|
||||
@@ -1042,10 +1047,10 @@ PRIMITIVES["sf-define"] = sfDefine;
|
||||
var effectList = (isSxTruthy((typeOf(effects) == "list")) ? map(function(e) { return (isSxTruthy((typeOf(e) == "symbol")) ? symbolName(e) : (String(e))); }, effects) : [(String(effects))]);
|
||||
var effectAnns = (isSxTruthy(envHas(env, "*effect-annotations*")) ? envGet(env, "*effect-annotations*") : {});
|
||||
effectAnns[symbolName(nameSym)] = effectList;
|
||||
return envSet(env, "*effect-annotations*", effectAnns);
|
||||
return envBind(env, "*effect-annotations*", effectAnns);
|
||||
})();
|
||||
}
|
||||
envSet(env, symbolName(nameSym), comp);
|
||||
envBind(env, symbolName(nameSym), comp);
|
||||
return comp;
|
||||
})();
|
||||
})(); };
|
||||
@@ -1097,7 +1102,7 @@ PRIMITIVES["parse-comp-params"] = parseCompParams;
|
||||
var hasChildren = nth(parsed, 1);
|
||||
return (function() {
|
||||
var island = makeIsland(compName, params, hasChildren, body, env);
|
||||
envSet(env, symbolName(nameSym), island);
|
||||
envBind(env, symbolName(nameSym), island);
|
||||
return island;
|
||||
})();
|
||||
})(); };
|
||||
@@ -1113,7 +1118,7 @@ PRIMITIVES["sf-defisland"] = sfDefisland;
|
||||
var restParam = nth(parsed, 1);
|
||||
return (function() {
|
||||
var mac = makeMacro(params, restParam, body, env, symbolName(nameSym));
|
||||
envSet(env, symbolName(nameSym), mac);
|
||||
envBind(env, symbolName(nameSym), mac);
|
||||
return mac;
|
||||
})();
|
||||
})(); };
|
||||
@@ -1132,7 +1137,7 @@ PRIMITIVES["parse-macro-params"] = parseMacroParams;
|
||||
var sfDefstyle = function(args, env) { return (function() {
|
||||
var nameSym = first(args);
|
||||
var value = trampoline(evalExpr(nth(args, 1), env));
|
||||
envSet(env, symbolName(nameSym), value);
|
||||
envBind(env, symbolName(nameSym), value);
|
||||
return value;
|
||||
})(); };
|
||||
PRIMITIVES["sf-defstyle"] = sfDefstyle;
|
||||
@@ -1162,7 +1167,7 @@ PRIMITIVES["normalize-type-body"] = normalizeTypeBody;
|
||||
var body = normalizeTypeBody(bodyExpr);
|
||||
var registry = (isSxTruthy(envHas(env, "*type-registry*")) ? envGet(env, "*type-registry*") : {});
|
||||
registry[typeName] = makeTypeDef(typeName, typeParams, body);
|
||||
envSet(env, "*type-registry*", registry);
|
||||
envBind(env, "*type-registry*", registry);
|
||||
return NIL;
|
||||
})();
|
||||
})(); };
|
||||
@@ -1175,7 +1180,7 @@ PRIMITIVES["sf-deftype"] = sfDeftype;
|
||||
if (isSxTruthy(!isSxTruthy(contains(registry, effectName)))) {
|
||||
registry.push(effectName);
|
||||
}
|
||||
envSet(env, "*effect-registry*", registry);
|
||||
envBind(env, "*effect-registry*", registry);
|
||||
return NIL;
|
||||
})(); };
|
||||
PRIMITIVES["sf-defeffect"] = sfDefeffect;
|
||||
@@ -1237,18 +1242,18 @@ PRIMITIVES["sf-set!"] = sfSetBang;
|
||||
var vname = (isSxTruthy((typeOf(first(binding)) == "symbol")) ? symbolName(first(binding)) : first(binding));
|
||||
names.push(vname);
|
||||
valExprs.push(nth(binding, 1));
|
||||
return envSet(local, vname, NIL);
|
||||
return envBind(local, vname, NIL);
|
||||
})(); }, bindings) : 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));
|
||||
names.push(vname);
|
||||
valExprs.push(valExpr);
|
||||
return envSet(local, vname, NIL);
|
||||
return envBind(local, vname, NIL);
|
||||
})(); }, NIL, range(0, (len(bindings) / 2))));
|
||||
(function() {
|
||||
var values = map(function(e) { return trampoline(evalExpr(e, local)); }, valExprs);
|
||||
{ var _c = zip(names, values); for (var _i = 0; _i < _c.length; _i++) { var pair = _c[_i]; envSet(local, first(pair), nth(pair, 1)); } }
|
||||
return forEach(function(val) { return (isSxTruthy(isLambda(val)) ? forEach(function(n) { return envSet(lambdaClosure(val), n, envGet(local, n)); }, names) : NIL); }, values);
|
||||
{ var _c = zip(names, values); for (var _i = 0; _i < _c.length; _i++) { var pair = _c[_i]; envBind(local, first(pair), nth(pair, 1)); } }
|
||||
return forEach(function(val) { return (isSxTruthy(isLambda(val)) ? forEach(function(n) { return envBind(lambdaClosure(val), n, envGet(local, n)); }, names) : NIL); }, values);
|
||||
})();
|
||||
{ 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);
|
||||
@@ -1297,9 +1302,9 @@ PRIMITIVES["sf-provide"] = sfProvide;
|
||||
// expand-macro
|
||||
var expandMacro = function(mac, rawArgs, env) { return (function() {
|
||||
var local = envMerge(macroClosure(mac), env);
|
||||
{ var _c = mapIndexed(function(i, p) { return [p, i]; }, macroParams(mac)); for (var _i = 0; _i < _c.length; _i++) { var pair = _c[_i]; envSet(local, first(pair), (isSxTruthy((nth(pair, 1) < len(rawArgs))) ? nth(rawArgs, nth(pair, 1)) : NIL)); } }
|
||||
{ var _c = mapIndexed(function(i, p) { return [p, i]; }, macroParams(mac)); for (var _i = 0; _i < _c.length; _i++) { var pair = _c[_i]; envBind(local, first(pair), (isSxTruthy((nth(pair, 1) < len(rawArgs))) ? nth(rawArgs, nth(pair, 1)) : NIL)); } }
|
||||
if (isSxTruthy(macroRestParam(mac))) {
|
||||
envSet(local, macroRestParam(mac), slice(rawArgs, len(macroParams(mac))));
|
||||
envBind(local, macroRestParam(mac), slice(rawArgs, len(macroParams(mac))));
|
||||
}
|
||||
return trampoline(evalExpr(macroBody(mac), local));
|
||||
})(); };
|
||||
@@ -1435,7 +1440,7 @@ PRIMITIVES["eval-cond-clojure"] = evalCondClojure;
|
||||
{ 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 envBind(local, name, trampoline(evalExpr(nth(pair, 1), local)));
|
||||
})();
|
||||
} } }
|
||||
return local;
|
||||
@@ -1722,7 +1727,7 @@ PRIMITIVES["dispatch-html-form"] = dispatchHtmlForm;
|
||||
// render-lambda-html
|
||||
var renderLambdaHtml = function(f, args, env) { return (function() {
|
||||
var local = envMerge(lambdaClosure(f), env);
|
||||
forEachIndexed(function(i, p) { return envSet(local, p, nth(args, i)); }, lambdaParams(f));
|
||||
forEachIndexed(function(i, p) { return envBind(local, p, nth(args, i)); }, lambdaParams(f));
|
||||
return renderToHtml(lambdaBody(f), local);
|
||||
})(); };
|
||||
PRIMITIVES["render-lambda-html"] = renderLambdaHtml;
|
||||
@@ -1741,9 +1746,9 @@ PRIMITIVES["render-lambda-html"] = renderLambdaHtml;
|
||||
})(); }, {["i"]: 0, ["skip"]: false}, args);
|
||||
return (function() {
|
||||
var local = envMerge(componentClosure(comp), env);
|
||||
{ var _c = componentParams(comp); for (var _i = 0; _i < _c.length; _i++) { var p = _c[_i]; envSet(local, p, (isSxTruthy(dictHas(kwargs, p)) ? dictGet(kwargs, p) : NIL)); } }
|
||||
{ var _c = componentParams(comp); for (var _i = 0; _i < _c.length; _i++) { var p = _c[_i]; envBind(local, p, (isSxTruthy(dictHas(kwargs, p)) ? dictGet(kwargs, p) : NIL)); } }
|
||||
if (isSxTruthy(componentHasChildren(comp))) {
|
||||
envSet(local, "children", makeRawHtml(join("", map(function(c) { return renderToHtml(c, env); }, children))));
|
||||
envBind(local, "children", makeRawHtml(join("", map(function(c) { return renderToHtml(c, env); }, children))));
|
||||
}
|
||||
return renderToHtml(componentBody(comp), local);
|
||||
})();
|
||||
@@ -1834,9 +1839,9 @@ PRIMITIVES["render-html-marsh"] = renderHtmlMarsh;
|
||||
return (function() {
|
||||
var local = envMerge(componentClosure(island), env);
|
||||
var islandName = componentName(island);
|
||||
{ var _c = componentParams(island); for (var _i = 0; _i < _c.length; _i++) { var p = _c[_i]; envSet(local, p, (isSxTruthy(dictHas(kwargs, p)) ? dictGet(kwargs, p) : NIL)); } }
|
||||
{ var _c = componentParams(island); for (var _i = 0; _i < _c.length; _i++) { var p = _c[_i]; envBind(local, p, (isSxTruthy(dictHas(kwargs, p)) ? dictGet(kwargs, p) : NIL)); } }
|
||||
if (isSxTruthy(componentHasChildren(island))) {
|
||||
envSet(local, "children", makeRawHtml(join("", map(function(c) { return renderToHtml(c, env); }, children))));
|
||||
envBind(local, "children", makeRawHtml(join("", map(function(c) { return renderToHtml(c, env); }, children))));
|
||||
}
|
||||
return (function() {
|
||||
var bodyHtml = renderToHtml(componentBody(island), local);
|
||||
@@ -1987,7 +1992,7 @@ return result; }, args);
|
||||
var coll = trampoline(evalExpr(nth(args, 1), env));
|
||||
return map(function(item) { return (isSxTruthy(isLambda(f)) ? (function() {
|
||||
var local = envMerge(lambdaClosure(f), env);
|
||||
envSet(local, first(lambdaParams(f)), item);
|
||||
envBind(local, first(lambdaParams(f)), item);
|
||||
return aser(lambdaBody(f), local);
|
||||
})() : cekCall(f, [item])); }, coll);
|
||||
})() : (isSxTruthy((name == "map-indexed")) ? (function() {
|
||||
@@ -1995,8 +2000,8 @@ return result; }, args);
|
||||
var coll = trampoline(evalExpr(nth(args, 1), env));
|
||||
return mapIndexed(function(i, item) { return (isSxTruthy(isLambda(f)) ? (function() {
|
||||
var local = envMerge(lambdaClosure(f), env);
|
||||
envSet(local, first(lambdaParams(f)), i);
|
||||
envSet(local, nth(lambdaParams(f), 1), item);
|
||||
envBind(local, first(lambdaParams(f)), i);
|
||||
envBind(local, nth(lambdaParams(f), 1), item);
|
||||
return aser(lambdaBody(f), local);
|
||||
})() : cekCall(f, [i, item])); }, coll);
|
||||
})() : (isSxTruthy((name == "for-each")) ? (function() {
|
||||
@@ -2005,7 +2010,7 @@ return result; }, args);
|
||||
var results = [];
|
||||
{ var _c = coll; for (var _i = 0; _i < _c.length; _i++) { var item = _c[_i]; (isSxTruthy(isLambda(f)) ? (function() {
|
||||
var local = envMerge(lambdaClosure(f), env);
|
||||
envSet(local, first(lambdaParams(f)), item);
|
||||
envBind(local, first(lambdaParams(f)), item);
|
||||
return append_b(results, aser(lambdaBody(f), local));
|
||||
})() : cekCall(f, [item])); } }
|
||||
return (isSxTruthy(isEmpty(results)) ? NIL : results);
|
||||
@@ -2143,7 +2148,7 @@ PRIMITIVES["render-dom-element"] = renderDomElement;
|
||||
})(); }, {["i"]: 0, ["skip"]: false}, args);
|
||||
return (function() {
|
||||
var local = envMerge(componentClosure(comp), env);
|
||||
{ var _c = componentParams(comp); for (var _i = 0; _i < _c.length; _i++) { var p = _c[_i]; envSet(local, p, (isSxTruthy(dictHas(kwargs, p)) ? dictGet(kwargs, p) : NIL)); } }
|
||||
{ var _c = componentParams(comp); for (var _i = 0; _i < _c.length; _i++) { var p = _c[_i]; envBind(local, p, (isSxTruthy(dictHas(kwargs, p)) ? dictGet(kwargs, p) : NIL)); } }
|
||||
if (isSxTruthy(componentHasChildren(comp))) {
|
||||
(function() {
|
||||
var childFrag = createFragment();
|
||||
@@ -2151,7 +2156,7 @@ PRIMITIVES["render-dom-element"] = renderDomElement;
|
||||
var result = renderToDom(c, env, ns);
|
||||
return (isSxTruthy(!isSxTruthy(isSpread(result))) ? domAppend(childFrag, result) : NIL);
|
||||
})(); } }
|
||||
return envSet(local, "children", childFrag);
|
||||
return envBind(local, "children", childFrag);
|
||||
})();
|
||||
}
|
||||
return renderToDom(componentBody(comp), local, ns);
|
||||
@@ -2355,7 +2360,7 @@ PRIMITIVES["dispatch-render-form"] = dispatchRenderForm;
|
||||
// render-lambda-dom
|
||||
var renderLambdaDom = function(f, args, env, ns) { return (function() {
|
||||
var local = envMerge(lambdaClosure(f), env);
|
||||
forEachIndexed(function(i, p) { return envSet(local, p, nth(args, i)); }, lambdaParams(f));
|
||||
forEachIndexed(function(i, p) { return envBind(local, p, nth(args, i)); }, lambdaParams(f));
|
||||
return renderToDom(lambdaBody(f), local, ns);
|
||||
})(); };
|
||||
PRIMITIVES["render-lambda-dom"] = renderLambdaDom;
|
||||
@@ -2375,12 +2380,12 @@ PRIMITIVES["render-lambda-dom"] = renderLambdaDom;
|
||||
return (function() {
|
||||
var local = envMerge(componentClosure(island), env);
|
||||
var islandName = componentName(island);
|
||||
{ var _c = componentParams(island); for (var _i = 0; _i < _c.length; _i++) { var p = _c[_i]; envSet(local, p, (isSxTruthy(dictHas(kwargs, p)) ? dictGet(kwargs, p) : NIL)); } }
|
||||
{ var _c = componentParams(island); for (var _i = 0; _i < _c.length; _i++) { var p = _c[_i]; envBind(local, p, (isSxTruthy(dictHas(kwargs, p)) ? dictGet(kwargs, p) : NIL)); } }
|
||||
if (isSxTruthy(componentHasChildren(island))) {
|
||||
(function() {
|
||||
var childFrag = createFragment();
|
||||
{ var _c = children; for (var _i = 0; _i < _c.length; _i++) { var c = _c[_i]; domAppend(childFrag, renderToDom(c, env, ns)); } }
|
||||
return envSet(local, "children", childFrag);
|
||||
return envBind(local, "children", childFrag);
|
||||
})();
|
||||
}
|
||||
return (function() {
|
||||
@@ -3657,9 +3662,9 @@ PRIMITIVES["bind-sse-swap"] = bindSseSwap;
|
||||
var exprs = sxParse(body);
|
||||
return domListen(el, eventName, function(e) { return (function() {
|
||||
var handlerEnv = envExtend({});
|
||||
envSet(handlerEnv, "event", e);
|
||||
envSet(handlerEnv, "this", el);
|
||||
envSet(handlerEnv, "detail", eventDetail(e));
|
||||
envBind(handlerEnv, "event", e);
|
||||
envBind(handlerEnv, "this", el);
|
||||
envBind(handlerEnv, "detail", eventDetail(e));
|
||||
return forEach(function(expr) { return evalExpr(expr, handlerEnv); }, exprs);
|
||||
})(); });
|
||||
})()) : NIL);
|
||||
@@ -3921,7 +3926,7 @@ PRIMITIVES["sx-hydrate-islands"] = sxHydrateIslands;
|
||||
var kwargs = sxOr(first(sxParse(stateSx)), {});
|
||||
var disposers = [];
|
||||
var local = envMerge(componentClosure(comp), env);
|
||||
{ var _c = componentParams(comp); for (var _i = 0; _i < _c.length; _i++) { var p = _c[_i]; envSet(local, p, (isSxTruthy(dictHas(kwargs, p)) ? dictGet(kwargs, p) : NIL)); } }
|
||||
{ var _c = componentParams(comp); for (var _i = 0; _i < _c.length; _i++) { var p = _c[_i]; envBind(local, p, (isSxTruthy(dictHas(kwargs, p)) ? dictGet(kwargs, p) : NIL)); } }
|
||||
return (function() {
|
||||
var bodyDom = withIslandScope(function(disposable) { return append_b(disposers, disposable); }, function() { return renderToDom(componentBody(comp), local, NIL); });
|
||||
domSetTextContent(el, "");
|
||||
@@ -4957,7 +4962,7 @@ PRIMITIVES["step-sf-reset"] = stepSfReset;
|
||||
var k = makeCekContinuation(captured, restKont);
|
||||
return (function() {
|
||||
var shiftEnv = envExtend(env);
|
||||
envSet(shiftEnv, kName, k);
|
||||
envBind(shiftEnv, kName, k);
|
||||
return makeCekState(body, shiftEnv, restKont);
|
||||
})();
|
||||
})();
|
||||
@@ -5087,7 +5092,7 @@ PRIMITIVES["step-ho-for-each"] = stepHoForEach;
|
||||
var remaining = get(frame, "remaining");
|
||||
var body = get(frame, "body");
|
||||
var local = get(frame, "env");
|
||||
envSet(local, name, value);
|
||||
envBind(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));
|
||||
@@ -5101,13 +5106,13 @@ PRIMITIVES["step-ho-for-each"] = stepHoForEach;
|
||||
if (isSxTruthy((isSxTruthy(isLambda(value)) && isNil(lambdaName(value))))) {
|
||||
value.name = name;
|
||||
}
|
||||
envSet(fenv, name, value);
|
||||
envBind(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 envBind(fenv, "*effect-annotations*", effectAnns);
|
||||
})();
|
||||
}
|
||||
return makeCekValue(value, fenv, restK);
|
||||
@@ -5274,15 +5279,15 @@ PRIMITIVES["step-continue"] = stepContinue;
|
||||
})() : (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)));
|
||||
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 envBind(local, first(pair), nth(pair, 1)); }, zip(params, args)), forEach(function(p) { return envBind(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)); } }
|
||||
{ var _c = componentParams(f); for (var _i = 0; _i < _c.length; _i++) { var p = _c[_i]; envBind(local, p, sxOr(dictGet(kwargs, p), NIL)); } }
|
||||
if (isSxTruthy(componentHasChildren(f))) {
|
||||
envSet(local, "children", children);
|
||||
envBind(local, "children", children);
|
||||
}
|
||||
return makeCekState(componentBody(f), local, kont);
|
||||
})() : error((String("Not callable: ") + String(inspect(f)))))))); };
|
||||
|
||||
Reference in New Issue
Block a user