Files
rose-ash/shared/static/scripts/sx-browser.js
giles 44b520a9e9 Step 10c: fix bind subscriber re-evaluation — track names not frames
Root cause: context called inside lambdas (e.g. swap!) went through
nested cek_run with empty kont, so provide frames weren't found and
never tracked to *bind-tracking*.

Three changes in evaluator.sx:
- step-sf-context: track context names (not frames) to *bind-tracking*
  — names work across cek_run boundaries via scope-peek fallback
- bind continue: resolve tracked names to frames via kont-find-provide
  on rest-k before registering subscribers
- subscriber: use empty kont instead of kont-extract-provides — old
  approach created provide frames whose continue handlers called
  scope-pop!, corrupting the scope stack

2752/2768 OCaml tests pass (all 7 bind subscriber tests fixed).
32/32 WASM native tests pass.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-05 11:05:17 +00:00

6032 lines
277 KiB
JavaScript
Raw Blame History

This file contains invisible Unicode characters
This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* sx-ref.js — Generated from reference SX evaluator specification.
*
* Bootstrap-compiled from shared/sx/ref/{eval,render,primitives}.sx
* Compare against hand-written sx.js for correctness verification.
*
* DO NOT EDIT — regenerate with: python bootstrap_js.py
*/
;(function(global) {
"use strict";
// =========================================================================
// Equality — used by transpiled code (= a b) → sxEq(a, b)
// =========================================================================
function sxEq(a, b) {
if (a === b) return true;
if (a && b && a._sym && b._sym) return a.name === b.name;
if (a && b && a._kw && b._kw) return a.name === b.name;
return false;
}
// =========================================================================
// Types
// =========================================================================
var NIL = Object.freeze({ _nil: true, toString: function() { return "nil"; } });
var SX_VERSION = "2026-04-05T11:01:51Z";
function isNil(x) { return x === NIL || x === null || x === undefined; }
function isSxTruthy(x) { return x !== false && !isNil(x); }
function Symbol(name) { this.name = name; }
Symbol.prototype.toString = function() { return this.name; };
Symbol.prototype._sym = true;
function Keyword(name) { this.name = name; }
Keyword.prototype.toString = function() { return ":" + this.name; };
Keyword.prototype._kw = true;
function Lambda(params, body, closure, name) {
this.params = params;
this.body = body;
this.closure = closure || {};
this.name = name || null;
}
Lambda.prototype._lambda = true;
function Component(name, params, hasChildren, body, closure, affinity) {
this.name = name;
this.params = params;
this.hasChildren = hasChildren;
this.body = body;
this.closure = closure || {};
this.affinity = affinity || "auto";
}
Component.prototype._component = true;
function Island(name, params, hasChildren, body, closure) {
this.name = name;
this.params = params;
this.hasChildren = hasChildren;
this.body = body;
this.closure = closure || {};
}
Island.prototype._island = true;
function Macro(params, restParam, body, closure, name) {
this.params = params;
this.restParam = restParam;
this.body = body;
this.closure = closure || {};
this.name = name || null;
}
Macro.prototype._macro = true;
function Thunk(expr, env) { this.expr = expr; this.env = env; }
Thunk.prototype._thunk = true;
function RawHTML(html) { this.html = html; }
RawHTML.prototype._raw = true;
function SxSpread(attrs) { this.attrs = attrs || {}; }
SxSpread.prototype._spread = true;
var _scopeStacks = {};
function isSym(x) { return x != null && x._sym === true; }
function isKw(x) { return x != null && x._kw === true; }
function merge() {
var out = {};
for (var i = 0; i < arguments.length; i++) {
var d = arguments[i];
if (d) for (var k in d) out[k] = d[k];
}
return out;
}
function sxOr() {
for (var i = 0; i < arguments.length; i++) {
if (isSxTruthy(arguments[i])) return arguments[i];
}
return arguments.length ? arguments[arguments.length - 1] : false;
}
// =========================================================================
// Platform interface — JS implementation
// =========================================================================
function typeOf(x) {
if (isNil(x)) return "nil";
if (typeof x === "number") return "number";
if (typeof x === "string") return "string";
if (typeof x === "boolean") return "boolean";
if (x._sym) return "symbol";
if (x._kw) return "keyword";
if (x._thunk) return "thunk";
if (x._lambda) return "lambda";
if (x._component) return "component";
if (x._island) return "island";
if (x._spread) return "spread";
if (x._macro) return "macro";
if (x._raw) return "raw-html";
if (x._sx_expr) return "sx-expr";
if (typeof Node !== "undefined" && x instanceof Node) return "dom-node";
if (Array.isArray(x)) return "list";
if (typeof x === "object") return "dict";
return "unknown";
}
function symbolName(s) { return s.name; }
function keywordName(k) { return k.name; }
function makeSymbol(n) { return new Symbol(n); }
function makeKeyword(n) { return new Keyword(n); }
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, env, affinity);
}
function makeMacro(params, restParam, body, env, name) {
return new Macro(params, restParam, body, env, name);
}
function makeThunk(expr, env) { return new Thunk(expr, env); }
function makeSpread(attrs) { return new SxSpread(attrs || {}); }
function isSpread(x) { return x != null && x._spread === true; }
function spreadAttrs(s) { return s && s._spread ? s.attrs : {}; }
function scopePush(name, value) {
if (!_scopeStacks[name]) _scopeStacks[name] = [];
_scopeStacks[name].push({value: value !== undefined ? value : NIL, emitted: [], dedup: false});
}
function scopePop(name) {
if (_scopeStacks[name] && _scopeStacks[name].length) _scopeStacks[name].pop();
}
// Aliases — provide-push!/provide-pop! map to scope-push!/scope-pop!
var providePush = scopePush;
var providePop = scopePop;
function sxContext(name) {
if (_scopeStacks[name] && _scopeStacks[name].length) {
return _scopeStacks[name][_scopeStacks[name].length - 1].value;
}
if (arguments.length > 1) return arguments[1];
throw new Error("No provider for: " + name);
}
function sxEmit(name, value) {
if (_scopeStacks[name] && _scopeStacks[name].length) {
var entry = _scopeStacks[name][_scopeStacks[name].length - 1];
if (entry.dedup && entry.emitted.indexOf(value) !== -1) return NIL;
entry.emitted.push(value);
}
return NIL;
}
function sxEmitted(name) {
if (_scopeStacks[name] && _scopeStacks[name].length) {
return _scopeStacks[name][_scopeStacks[name].length - 1].emitted.slice();
}
return [];
}
function sxCollect(bucket, value) {
if (!_scopeStacks[bucket] || !_scopeStacks[bucket].length) {
if (!_scopeStacks[bucket]) _scopeStacks[bucket] = [];
_scopeStacks[bucket].push({value: NIL, emitted: [], dedup: true});
}
var entry = _scopeStacks[bucket][_scopeStacks[bucket].length - 1];
if (entry.emitted.indexOf(value) === -1) entry.emitted.push(value);
}
function sxCollected(bucket) {
return sxEmitted(bucket);
}
function sxClearCollected(bucket) {
if (_scopeStacks[bucket] && _scopeStacks[bucket].length) {
_scopeStacks[bucket][_scopeStacks[bucket].length - 1].emitted = [];
}
}
function lambdaParams(f) { return f.params; }
function lambdaBody(f) { return f.body; }
function lambdaClosure(f) { return f.closure; }
function lambdaName(f) { return f.name; }
function setLambdaName(f, n) { f.name = n; }
function componentParams(c) { return c.params; }
function componentBody(c) { return c.body; }
function componentClosure(c) { return c.closure; }
function componentHasChildren(c) { return c.hasChildren; }
function componentName(c) { return c.name; }
function componentFile(c) { return (c && c.file) ? c.file : NIL; }
function componentAffinity(c) { return c.affinity || "auto"; }
function componentParamTypes(c) { return (c && c._paramTypes) ? c._paramTypes : NIL; }
function componentSetParamTypes_b(c, t) { if (c) c._paramTypes = t; return NIL; }
function macroParams(m) { return m.params; }
function macroRestParam(m) { return m.restParam; }
function macroBody(m) { return m.body; }
function macroClosure(m) { return m.closure; }
function isThunk(x) { return x != null && x._thunk === true; }
function thunkExpr(t) { return t.expr; }
function thunkEnv(t) { return t.env; }
function isCallable(x) { return typeof x === "function" || (x != null && x._lambda === true); }
function isLambda(x) { return x != null && x._lambda === true; }
function isComponent(x) { return x != null && x._component === true; }
function isIsland(x) { return x != null && x._island === true; }
function isMacro(x) { return x != null && x._macro === true; }
function isIdentical(a, b) { return a === b; }
// Island platform
function makeIsland(name, params, hasChildren, body, env) {
return new Island(name, params, hasChildren, body, env);
}
// JSON / dict helpers for island state serialization
function jsonSerialize(obj) {
return JSON.stringify(obj);
}
function isEmptyDict(d) {
if (!d || typeof d !== "object") return true;
for (var k in d) if (d.hasOwnProperty(k)) return false;
return true;
}
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;
while (obj !== null && obj !== Object.prototype) {
if (obj.hasOwnProperty(name)) { obj[name] = val; return; }
obj = Object.getPrototypeOf(obj);
}
// Not found in any parent scope — set on the immediate env
env[name] = val;
}
function envExtend(env) { return Object.create(env); }
function envMerge(base, overlay) {
// Same env or overlay is descendant of base — just extend, no copy.
// This prevents set! inside lambdas from modifying shadow copies.
if (base === overlay) return Object.create(base);
var p = overlay;
for (var d = 0; p && p !== Object.prototype && d < 100; d++) {
if (p === base) return Object.create(base);
p = Object.getPrototypeOf(p);
}
// General case: extend base, copy ONLY overlay properties that don't
// exist in the base chain (avoids shadowing closure bindings).
var child = Object.create(base);
if (overlay) {
for (var k in overlay) {
if (overlay.hasOwnProperty(k) && !(k in base)) child[k] = overlay[k];
}
}
return child;
}
function dictSet(d, k, v) { d[k] = v; return v; }
function dictGet(d, k) { var v = d[k]; return v !== undefined ? v : NIL; }
// Render-expression detection — lets the evaluator delegate to the active adapter.
// Matches HTML tags, SVG tags, <>, raw!, ~components, html: prefix, custom elements.
// Placeholder — overridden by transpiled version from render.sx
function isRenderExpr(expr) { return false; }
// Render dispatch — call the active adapter's render function.
// Set by each adapter when loaded; defaults to identity (no rendering).
var _renderExprFn = null;
// Render mode flag — set by render-to-html/aser, checked by eval-list.
// When false, render expressions fall through to evalCall.
var _renderMode = false;
function renderActiveP() { return _renderMode; }
function setRenderActiveB(val) { _renderMode = !!val; }
function renderExpr(expr, env) {
if (_renderExprFn) return _renderExprFn(expr, env);
// No adapter loaded — fall through to evalCall
return evalCall(first(expr), rest(expr), env);
}
function stripPrefix(s, prefix) {
return s.indexOf(prefix) === 0 ? s.slice(prefix.length) : s;
}
function error(msg) { throw new Error(msg); }
function inspect(x) { return JSON.stringify(x); }
function debugLog() { console.error.apply(console, ["[sx-debug]"].concat(Array.prototype.slice.call(arguments))); }
// =========================================================================
// Primitives
// =========================================================================
var PRIMITIVES = {};
// core.arithmetic
PRIMITIVES["+"] = function() { var s = 0; for (var i = 0; i < arguments.length; i++) s += arguments[i]; return s; };
PRIMITIVES["-"] = function(a, b) { return arguments.length === 1 ? -a : a - b; };
PRIMITIVES["*"] = function() { var s = 1; for (var i = 0; i < arguments.length; i++) s *= arguments[i]; return s; };
PRIMITIVES["/"] = function(a, b) { return a / b; };
PRIMITIVES["mod"] = function(a, b) { return a % b; };
PRIMITIVES["inc"] = function(n) { return n + 1; };
PRIMITIVES["dec"] = function(n) { return n - 1; };
PRIMITIVES["abs"] = Math.abs;
PRIMITIVES["floor"] = Math.floor;
PRIMITIVES["ceil"] = Math.ceil;
PRIMITIVES["round"] = function(x, n) {
if (n === undefined || n === 0) return Math.round(x);
var f = Math.pow(10, n); return Math.round(x * f) / f;
};
PRIMITIVES["min"] = Math.min;
PRIMITIVES["max"] = Math.max;
PRIMITIVES["sqrt"] = Math.sqrt;
PRIMITIVES["pow"] = Math.pow;
PRIMITIVES["clamp"] = function(x, lo, hi) { return Math.max(lo, Math.min(hi, x)); };
// core.comparison
PRIMITIVES["="] = sxEq;
PRIMITIVES["!="] = function(a, b) { return !sxEq(a, b); };
PRIMITIVES["<"] = function(a, b) { return a < b; };
PRIMITIVES[">"] = function(a, b) { return a > b; };
PRIMITIVES["<="] = function(a, b) { return a <= b; };
PRIMITIVES[">="] = function(a, b) { return a >= b; };
// core.logic
PRIMITIVES["not"] = function(x) { return !isSxTruthy(x); };
// core.predicates
PRIMITIVES["nil?"] = isNil;
PRIMITIVES["number?"] = function(x) { return typeof x === "number"; };
PRIMITIVES["string?"] = function(x) { return typeof x === "string"; };
PRIMITIVES["list?"] = Array.isArray;
PRIMITIVES["dict?"] = function(x) { return x !== null && typeof x === "object" && !Array.isArray(x) && !x._sym && !x._kw; };
PRIMITIVES["empty?"] = function(c) { return isNil(c) || (Array.isArray(c) ? c.length === 0 : typeof c === "string" ? c.length === 0 : Object.keys(c).length === 0); };
PRIMITIVES["contains?"] = function(c, k) {
if (typeof c === "string") return c.indexOf(String(k)) !== -1;
if (Array.isArray(c)) return c.indexOf(k) !== -1;
return k in c;
};
PRIMITIVES["odd?"] = function(n) { return n % 2 !== 0; };
PRIMITIVES["even?"] = function(n) { return n % 2 === 0; };
PRIMITIVES["zero?"] = function(n) { return n === 0; };
PRIMITIVES["boolean?"] = function(x) { return x === true || x === false; };
PRIMITIVES["symbol?"] = function(x) { return x != null && x._sym === true; };
PRIMITIVES["keyword?"] = function(x) { return x != null && x._kw === true; };
PRIMITIVES["component-affinity"] = componentAffinity;
// core.strings
PRIMITIVES["str"] = function() {
var p = [];
for (var i = 0; i < arguments.length; i++) {
var v = arguments[i]; if (isNil(v)) continue; p.push(String(v));
}
return p.join("");
};
PRIMITIVES["upper"] = function(s) { return String(s).toUpperCase(); };
PRIMITIVES["lower"] = function(s) { return String(s).toLowerCase(); };
PRIMITIVES["trim"] = function(s) { return String(s).trim(); };
PRIMITIVES["split"] = function(s, sep) { return String(s).split(sep || " "); };
PRIMITIVES["join"] = function(sep, coll) { return coll.join(sep); };
PRIMITIVES["replace"] = function(s, old, nw) { return s.split(old).join(nw); };
PRIMITIVES["index-of"] = function(s, needle, from) { return String(s).indexOf(needle, from || 0); };
PRIMITIVES["starts-with?"] = function(s, p) { return String(s).indexOf(p) === 0; };
PRIMITIVES["ends-with?"] = function(s, p) { var str = String(s); return str.indexOf(p, str.length - p.length) !== -1; };
PRIMITIVES["slice"] = function(c, a, b) { if (!c || typeof c.slice !== "function") { console.error("[sx-debug] slice called on non-sliceable:", typeof c, c, "a=", a, "b=", b, new Error().stack); return []; } return b !== undefined ? c.slice(a, b) : c.slice(a); };
PRIMITIVES["substring"] = function(s, a, b) { return String(s).substring(a, b); };
PRIMITIVES["char-from-code"] = function(n) { return String.fromCharCode(n); };
PRIMITIVES["string-length"] = function(s) { return String(s).length; };
var stringLength = PRIMITIVES["string-length"];
PRIMITIVES["string-contains?"] = function(s, sub) { return String(s).indexOf(String(sub)) !== -1; };
PRIMITIVES["concat"] = function() {
var out = [];
for (var i = 0; i < arguments.length; i++) if (!isNil(arguments[i])) out = out.concat(arguments[i]);
return out;
};
// core.collections
PRIMITIVES["list"] = function() { return Array.prototype.slice.call(arguments); };
PRIMITIVES["dict"] = function() {
var d = {};
for (var i = 0; i < arguments.length - 1; i += 2) d[arguments[i]] = arguments[i + 1];
return d;
};
PRIMITIVES["range"] = function(a, b, step) {
var r = []; step = step || 1;
for (var i = a; step > 0 ? i < b : i > b; i += step) r.push(i);
return r;
};
PRIMITIVES["get"] = function(c, k, def) { var v = (c && c[k]); return v !== undefined ? v : (def !== undefined ? def : NIL); };
PRIMITIVES["len"] = function(c) { return Array.isArray(c) ? c.length : typeof c === "string" ? c.length : Object.keys(c).length; };
PRIMITIVES["first"] = function(c) { return c && c.length > 0 ? c[0] : NIL; };
PRIMITIVES["last"] = function(c) { return c && c.length > 0 ? c[c.length - 1] : NIL; };
PRIMITIVES["rest"] = function(c) { if (!c || c._nil) return []; if (typeof c.slice !== "function") return []; return c.slice(1); };
PRIMITIVES["nth"] = function(c, n) { return c && n >= 0 && n < c.length ? c[n] : NIL; };
PRIMITIVES["cons"] = function(x, c) { return [x].concat(c || []); };
PRIMITIVES["append"] = function(c, x) { return (c || []).concat(Array.isArray(x) ? x : [x]); };
PRIMITIVES["append!"] = function(arr, x) { arr.push(x); return arr; };
PRIMITIVES["chunk-every"] = function(c, n) {
var r = []; for (var i = 0; i < c.length; i += n) r.push(c.slice(i, i + n)); return r;
};
PRIMITIVES["zip-pairs"] = function(c) {
var r = []; for (var i = 0; i < c.length - 1; i++) r.push([c[i], c[i + 1]]); return r;
};
PRIMITIVES["reverse"] = function(c) { return Array.isArray(c) ? c.slice().reverse() : String(c).split("").reverse().join(""); };
PRIMITIVES["flatten"] = function(c) {
var out = [];
function walk(a) { for (var i = 0; i < a.length; i++) Array.isArray(a[i]) ? walk(a[i]) : out.push(a[i]); }
walk(c || []); return out;
};
// core.dict
PRIMITIVES["keys"] = function(d) { return Object.keys(d || {}); };
PRIMITIVES["vals"] = function(d) { var r = []; for (var k in d) r.push(d[k]); return r; };
PRIMITIVES["merge"] = function() {
var out = {};
for (var i = 0; i < arguments.length; i++) { var d = arguments[i]; if (d && !isNil(d)) for (var k in d) out[k] = d[k]; }
return out;
};
PRIMITIVES["assoc"] = function(d) {
var out = {}; if (d && !isNil(d)) for (var k in d) out[k] = d[k];
for (var i = 1; i < arguments.length - 1; i += 2) out[arguments[i]] = arguments[i + 1];
return out;
};
PRIMITIVES["dissoc"] = function(d) {
var out = {}; for (var k in d) out[k] = d[k];
for (var i = 1; i < arguments.length; i++) delete out[arguments[i]];
return out;
};
PRIMITIVES["dict-set!"] = function(d, k, v) { d[k] = v; return v; };
PRIMITIVES["has-key?"] = function(d, k) { return d !== null && d !== undefined && k in d; };
PRIMITIVES["into"] = function(target, coll) {
if (target === "list") return Array.isArray(coll) ? coll.slice() : Object.entries(coll).map(function(e) { return [e[0], e[1]]; });
if (target === "dict") { var r = {}; for (var i = 0; i < coll.length; i++) { var p = coll[i]; if (Array.isArray(p) && p.length >= 2) r[p[0]] = p[1]; } return r; }
if (Array.isArray(target)) return Array.isArray(coll) ? coll.slice() : Object.entries(coll);
var r = {}; for (var i = 0; i < coll.length; i++) { var p = coll[i]; if (Array.isArray(p) && p.length >= 2) r[p[0]] = p[1]; }
return r;
};
// stdlib.format
PRIMITIVES["format-decimal"] = function(v, p) { return Number(v).toFixed(p || 2); };
PRIMITIVES["parse-int"] = function(v, d) { var n = parseInt(v, 10); return isNaN(n) ? (d || 0) : n; };
PRIMITIVES["format-date"] = function(s, fmt) {
if (!s) return "";
try {
var d = new Date(s);
if (isNaN(d.getTime())) return String(s);
var months = ["January","February","March","April","May","June","July","August","September","October","November","December"];
var short_months = ["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"];
return fmt.replace(/%-d/g, d.getDate()).replace(/%d/g, ("0"+d.getDate()).slice(-2))
.replace(/%B/g, months[d.getMonth()]).replace(/%b/g, short_months[d.getMonth()])
.replace(/%Y/g, d.getFullYear()).replace(/%m/g, ("0"+(d.getMonth()+1)).slice(-2))
.replace(/%H/g, ("0"+d.getHours()).slice(-2)).replace(/%M/g, ("0"+d.getMinutes()).slice(-2));
} catch (e) { return String(s); }
};
PRIMITIVES["parse-datetime"] = function(s) { return s ? String(s) : NIL; };
// stdlib.text
PRIMITIVES["pluralize"] = function(n, s, p) {
if (s || (p && p !== "s")) return n == 1 ? (s || "") : (p || "s");
return n == 1 ? "" : "s";
};
PRIMITIVES["escape"] = function(s) {
return String(s).replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/"/g,"&quot;").replace(/'/g,"&#x27;");
};
PRIMITIVES["strip-tags"] = function(s) { return String(s).replace(/<[^>]+>/g, ""); };
// stdlib.debug
PRIMITIVES["assert"] = function(cond, msg) {
if (!isSxTruthy(cond)) throw new Error("Assertion error: " + (msg || "Assertion failed"));
return true;
};
// stdlib.spread — spread + collect + scope primitives
PRIMITIVES["make-spread"] = makeSpread;
PRIMITIVES["spread?"] = isSpread;
PRIMITIVES["spread-attrs"] = spreadAttrs;
PRIMITIVES["collect!"] = sxCollect;
PRIMITIVES["collected"] = sxCollected;
PRIMITIVES["clear-collected!"] = sxClearCollected;
// scope — unified render-time dynamic scope
PRIMITIVES["scope-push!"] = scopePush;
PRIMITIVES["scope-pop!"] = scopePop;
// provide-push!/provide-pop! — aliases for scope-push!/scope-pop!
PRIMITIVES["provide-push!"] = providePush;
PRIMITIVES["provide-pop!"] = providePop;
PRIMITIVES["context"] = sxContext;
PRIMITIVES["emit!"] = sxEmit;
PRIMITIVES["emitted"] = sxEmitted;
// Aliases for aser adapter (avoids CEK special form conflict on server)
var scopeEmit = sxEmit;
function scopePeek(name) {
if (_scopeStacks[name] && _scopeStacks[name].length) {
return _scopeStacks[name][_scopeStacks[name].length - 1].value;
}
return NIL;
}
PRIMITIVES["scope-emit!"] = scopeEmit;
PRIMITIVES["scope-peek"] = scopePeek;
PRIMITIVES["scope-emitted"] = sxEmitted;
PRIMITIVES["scope-collected"] = sxCollected;
PRIMITIVES["scope-clear-collected!"] = sxClearCollected;
// ---- VM stack primitives ----
// The VM spec (vm.sx) requires these array-like operations.
// In JS, a plain Array serves as the stack.
PRIMITIVES["make-vm-stack"] = function(size) {
var a = new Array(size);
for (var i = 0; i < size; i++) a[i] = NIL;
return a;
};
PRIMITIVES["vm-stack-get"] = function(stack, idx) { return stack[idx]; };
PRIMITIVES["vm-stack-set!"] = function(stack, idx, value) { stack[idx] = value; return NIL; };
PRIMITIVES["vm-stack-length"] = function(stack) { return stack.length; };
PRIMITIVES["vm-stack-copy!"] = function(src, dst, count) {
for (var i = 0; i < count; i++) dst[i] = src[i];
return NIL;
};
PRIMITIVES["get-primitive"] = function(name) {
if (name in PRIMITIVES) return PRIMITIVES[name];
throw new Error("VM undefined: " + name);
};
PRIMITIVES["call-primitive"] = function(name, args) {
if (!(name in PRIMITIVES)) throw new Error("VM undefined: " + name);
var fn = PRIMITIVES[name];
return fn.apply(null, Array.isArray(args) ? args : []);
};
PRIMITIVES["primitive?"] = function(name) {
return name in PRIMITIVES;
};
PRIMITIVES["set-nth!"] = function(lst, idx, val) {
lst[idx] = val;
return NIL;
};
PRIMITIVES["env-parent"] = function(env) {
if (env && Object.getPrototypeOf(env) !== Object.prototype &&
Object.getPrototypeOf(env) !== null)
return Object.getPrototypeOf(env);
return NIL;
};
function isPrimitive(name) { return name in PRIMITIVES; }
function getPrimitive(name) { return PRIMITIVES[name]; }
// Higher-order helpers used by the transpiled code
function map(fn, coll) { return coll.map(fn); }
function mapIndexed(fn, coll) { return coll.map(function(item, i) { return fn(i, item); }); }
function filter(fn, coll) { return coll.filter(function(x) { return isSxTruthy(fn(x)); }); }
function reduce(fn, init, coll) {
var acc = init;
for (var i = 0; i < coll.length; i++) acc = fn(acc, coll[i]);
return acc;
}
function some(fn, coll) {
for (var i = 0; i < coll.length; i++) { var r = fn(coll[i]); if (isSxTruthy(r)) return r; }
return NIL;
}
function forEach(fn, coll) { for (var i = 0; i < coll.length; i++) fn(coll[i]); return NIL; }
function isEvery(fn, coll) {
for (var i = 0; i < coll.length; i++) { if (!isSxTruthy(fn(coll[i]))) return false; }
return true;
}
function mapDict(fn, d) { var r = {}; for (var k in d) r[k] = fn(k, d[k]); return r; }
// Predicate aliases used by transpiled code
// Both naming conventions: isX (from js-renames) and x_p (from js-mangle of x?)
var isNumber = PRIMITIVES["number?"]; var number_p = isNumber;
var isString = PRIMITIVES["string?"]; var string_p = isString;
var isBoolean = PRIMITIVES["boolean?"]; var boolean_p = isBoolean;
var isDict = PRIMITIVES["dict?"];
var isList = PRIMITIVES["list?"]; var list_p = isList;
var isKeyword = PRIMITIVES["keyword?"]; var keyword_p = isKeyword;
var isSymbol = PRIMITIVES["symbol?"]; var symbol_p = isSymbol;
// List primitives used directly by transpiled code
var len = PRIMITIVES["len"];
var first = PRIMITIVES["first"];
var last = PRIMITIVES["last"];
var rest = PRIMITIVES["rest"];
var nth = PRIMITIVES["nth"];
var cons = PRIMITIVES["cons"];
var append = PRIMITIVES["append"];
var isEmpty = PRIMITIVES["empty?"];
var contains = PRIMITIVES["contains?"];
var startsWith = PRIMITIVES["starts-with?"];
var slice = PRIMITIVES["slice"];
var concat = PRIMITIVES["concat"];
var str = PRIMITIVES["str"];
var join = PRIMITIVES["join"];
var keys = PRIMITIVES["keys"];
var get = PRIMITIVES["get"];
var assoc = PRIMITIVES["assoc"];
var range = PRIMITIVES["range"];
var floor = PRIMITIVES["floor"];
var pow = PRIMITIVES["pow"];
var mod = PRIMITIVES["mod"];
var indexOf_ = PRIMITIVES["index-of"];
var hasKey = PRIMITIVES["has-key?"];
function zip(a, b) { var r = []; for (var i = 0; i < Math.min(a.length, b.length); i++) r.push([a[i], b[i]]); return r; }
function append_b(arr, x) { arr.push(x); return arr; }
var apply = function(f, args) {
if (isLambda(f)) return trampoline(callLambda(f, args, lambdaClosure(f)));
return f.apply(null, args);
};
// Additional primitive aliases used by adapter/engine transpiled code
var split = PRIMITIVES["split"];
var trim = PRIMITIVES["trim"];
var upper = PRIMITIVES["upper"];
var lower = PRIMITIVES["lower"];
var replace_ = function(s, old, nw) { return s.split(old).join(nw); };
var endsWith = PRIMITIVES["ends-with?"];
var parseInt_ = PRIMITIVES["parse-int"];
var dict_fn = PRIMITIVES["dict"];
// HTML rendering helpers
// escape-html and escape-attr are now library functions defined in render.sx
function rawHtmlContent(r) { return r.html; }
function makeRawHtml(s) { return { _raw: true, html: s }; }
function makeSxExpr(s) { return { _sx_expr: true, source: s }; }
function sxExprSource(x) { return x && x.source ? x.source : String(x); }
// Placeholders — overridden by transpiled spec from parser.sx / adapter-sx.sx
function serialize(val) { return String(val); }
function isSpecialForm(n) { return false; }
function isHoForm(n) { return false; }
// -----------------------------------------------------------------------
// Host FFI — the irreducible web platform primitives
// All DOM/browser operations are built on these in web/lib/dom.sx
// -----------------------------------------------------------------------
PRIMITIVES["host-global"] = function(name) {
if (typeof globalThis !== "undefined" && name in globalThis) return globalThis[name];
if (typeof window !== "undefined" && name in window) return window[name];
return NIL;
};
PRIMITIVES["host-get"] = function(obj, prop) {
if (obj == null || obj === NIL) return NIL;
var v = obj[prop];
return v === undefined || v === null ? NIL : v;
};
PRIMITIVES["host-set!"] = function(obj, prop, val) {
if (obj != null && obj !== NIL) obj[prop] = val === NIL ? null : val;
};
PRIMITIVES["host-call"] = function() {
var obj = arguments[0], method = arguments[1];
var args = [];
for (var i = 2; i < arguments.length; i++) {
var a = arguments[i];
args.push(a === NIL ? null : a);
}
if (obj == null || obj === NIL) {
// Global function call
var fn = typeof globalThis !== "undefined" ? globalThis[method] : window[method];
if (typeof fn === "function") return fn.apply(null, args);
return NIL;
}
if (typeof obj[method] === "function") {
try { return obj[method].apply(obj, args); }
catch(e) { return NIL; }
}
return NIL;
};
PRIMITIVES["host-new"] = function() {
var name = arguments[0];
var args = Array.prototype.slice.call(arguments, 1).map(function(a) { return a === NIL ? null : a; });
var Ctor = typeof globalThis !== "undefined" ? globalThis[name] : window[name];
if (typeof Ctor !== "function") return NIL;
// Support 0-4 args (covers all practical cases)
switch (args.length) {
case 0: return new Ctor();
case 1: return new Ctor(args[0]);
case 2: return new Ctor(args[0], args[1]);
case 3: return new Ctor(args[0], args[1], args[2]);
default: return new Ctor(args[0], args[1], args[2], args[3]);
}
};
PRIMITIVES["host-callback"] = function(fn) {
// Wrap SX function/lambda as a native JS callback
if (typeof fn === "function") return fn;
if (fn && fn._type === "lambda") {
return function() {
var a = Array.prototype.slice.call(arguments);
return cekCall(fn, a);
};
}
return function() {};
};
PRIMITIVES["host-typeof"] = function(obj) {
if (obj == null || obj === NIL) return "nil";
if (obj instanceof Element) return "element";
if (obj instanceof Text) return "text";
if (obj instanceof DocumentFragment) return "fragment";
if (obj instanceof Document) return "document";
if (obj instanceof Event) return "event";
if (obj instanceof Promise) return "promise";
if (obj instanceof AbortController) return "abort-controller";
return typeof obj;
};
PRIMITIVES["host-await"] = function(promise, callback) {
if (promise && typeof promise.then === "function") {
var cb = typeof callback === "function" ? callback :
(callback && callback._type === "lambda") ?
function(v) { return cekCall(callback, [v]); } : function() {};
promise.then(cb);
}
};
// Aliases for transpiled dom.sx / browser.sx code (transpiler mangles host-* names)
var hostGlobal = PRIMITIVES["host-global"];
var hostGet = PRIMITIVES["host-get"];
var hostSet = PRIMITIVES["host-set!"];
var hostCall = PRIMITIVES["host-call"];
var hostNew = PRIMITIVES["host-new"];
var hostCallback = PRIMITIVES["host-callback"];
var hostTypeof = PRIMITIVES["host-typeof"];
var hostAwait = PRIMITIVES["host-await"];
// processBindings and evalCond — now specced in render.sx, bootstrapped above
function isDefinitionForm(name) {
return name === "define" || name === "defcomp" || name === "defmacro" ||
name === "defstyle" || name === "defhandler" ||
name === "deftype" || name === "defeffect";
}
function indexOf_(s, ch) {
return typeof s === "string" ? s.indexOf(ch) : -1;
}
function dictHas(d, k) { return d != null && k in d; }
function dictDelete(d, k) { delete d[k]; }
function forEachIndexed(fn, coll) {
for (var i = 0; i < coll.length; i++) fn(i, coll[i]);
return NIL;
}
// =========================================================================
// Performance overrides — evaluator hot path
// =========================================================================
// Override parseKeywordArgs: imperative loop instead of reduce+assoc
parseKeywordArgs = function(rawArgs, env) {
var kwargs = {};
var children = [];
for (var i = 0; i < rawArgs.length; i++) {
var arg = rawArgs[i];
if (arg && arg._kw && (i + 1) < rawArgs.length) {
kwargs[arg.name] = trampoline(evalExpr(rawArgs[i + 1], env));
i++;
} else {
children.push(trampoline(evalExpr(arg, env)));
}
}
return [kwargs, children];
};
// Override callComponent: use prototype chain env, imperative kwarg binding
callComponent = function(comp, rawArgs, env) {
var kwargs = {};
var children = [];
for (var i = 0; i < rawArgs.length; i++) {
var arg = rawArgs[i];
if (arg && arg._kw && (i + 1) < rawArgs.length) {
kwargs[arg.name] = trampoline(evalExpr(rawArgs[i + 1], env));
i++;
} else {
children.push(trampoline(evalExpr(arg, env)));
}
}
var local = Object.create(componentClosure(comp));
for (var k in env) if (env.hasOwnProperty(k)) local[k] = env[k];
var params = componentParams(comp);
for (var j = 0; j < params.length; j++) {
var p = params[j];
local[p] = p in kwargs ? kwargs[p] : NIL;
}
if (componentHasChildren(comp)) {
local["children"] = children;
}
return makeThunk(componentBody(comp), local);
};
// =========================================================================
// Platform: deps module — component dependency analysis
// =========================================================================
function componentDeps(c) {
return c.deps ? c.deps.slice() : [];
}
function componentSetDeps(c, deps) {
c.deps = deps;
}
function componentCssClasses(c) {
return c.cssClasses ? c.cssClasses.slice() : [];
}
function envComponents(env) {
var names = [];
for (var k in env) {
var v = env[k];
if (v && (v._component || v._macro)) names.push(k);
}
return names;
}
function regexFindAll(pattern, source) {
var re = new RegExp(pattern, "g");
var results = [];
var m;
while ((m = re.exec(source)) !== null) {
if (m[1] !== undefined) results.push(m[1]);
else results.push(m[0]);
}
return results;
}
function scanCssClasses(source) {
var classes = {};
var result = [];
var m;
var re1 = /:class\s+"([^"]*)"/g;
while ((m = re1.exec(source)) !== null) {
var parts = m[1].split(/\s+/);
for (var i = 0; i < parts.length; i++) {
if (parts[i] && !classes[parts[i]]) {
classes[parts[i]] = true;
result.push(parts[i]);
}
}
}
var re2 = /:class\s+\(str\s+((?:"[^"]*"\s*)+)\)/g;
while ((m = re2.exec(source)) !== null) {
var re3 = /"([^"]*)"/g;
var m2;
while ((m2 = re3.exec(m[1])) !== null) {
var parts2 = m2[1].split(/\s+/);
for (var j = 0; j < parts2.length; j++) {
if (parts2[j] && !classes[parts2[j]]) {
classes[parts2[j]] = true;
result.push(parts2[j]);
}
}
}
}
var re4 = /;;\s*@css\s+(.+)/g;
while ((m = re4.exec(source)) !== null) {
var parts3 = m[1].split(/\s+/);
for (var k = 0; k < parts3.length; k++) {
if (parts3[k] && !classes[parts3[k]]) {
classes[parts3[k]] = true;
result.push(parts3[k]);
}
}
}
return result;
}
function componentIoRefs(c) {
return c.ioRefs ? c.ioRefs.slice() : [];
}
function componentSetIoRefs(c, refs) {
c.ioRefs = refs;
}
// =========================================================================
// Platform interface — Parser
// =========================================================================
// Character classification derived from the grammar:
// ident-start → [a-zA-Z_~*+\-><=/!?&]
// ident-char → ident-start + [0-9.:\/\#,]
var _identStartRe = /[a-zA-Z_~*+\-><=/!?&]/;
var _identCharRe = /[a-zA-Z0-9_~*+\-><=/!?.:&/#,]/;
function isIdentStart(ch) { return _identStartRe.test(ch); }
function isIdentChar(ch) { return _identCharRe.test(ch); }
function parseNumber(s) { return Number(s); }
function escapeString(s) {
return s.replace(/\\/g, "\\\\").replace(/"/g, '\\"').replace(/\n/g, "\\n").replace(/\t/g, "\\t");
}
function sxExprSource(e) { return typeof e === "string" ? e : (e && e.source ? e.source : String(e)); }
var charFromCode = PRIMITIVES["char-from-code"];
// String/number utilities needed by transpiled spec code (content-hash etc)
PRIMITIVES["char-code-at"] = function(s, i) { return s.charCodeAt(i); };
var charCodeAt = PRIMITIVES["char-code-at"];
PRIMITIVES["to-hex"] = function(n) { return (n >>> 0).toString(16); };
var toHex = PRIMITIVES["to-hex"];
// =========================================================================
// Platform: CEK module — explicit CEK machine
// =========================================================================
// Continuation type — callable as JS function so isCallable/apply work.
// CEK is the canonical evaluator; continuations are always available.
function Continuation(fn) {
var c = function(value) { return fn(value !== undefined ? value : NIL); };
c.fn = fn;
c._continuation = true;
c.call = function(value) { return fn(value !== undefined ? value : NIL); };
return c;
}
PRIMITIVES["continuation?"] = function(x) { return x != null && x._continuation === true; };
// 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 : {};
}
// === Transpiled from evaluator (frames + eval + CEK) ===
// make-cek-state
var makeCekState = function(control, env, kont) { return {"control": control, "env": env, "kont": kont, "value": NIL, "phase": "eval"}; };
PRIMITIVES["make-cek-state"] = makeCekState;
// make-cek-value
var makeCekValue = function(value, env, kont) { return {"control": NIL, "env": env, "kont": kont, "value": value, "phase": "continue"}; };
PRIMITIVES["make-cek-value"] = makeCekValue;
// make-cek-suspended
var makeCekSuspended = function(request, env, kont) { return {"env": env, "kont": kont, "phase": "io-suspended", "request": request}; };
PRIMITIVES["make-cek-suspended"] = makeCekSuspended;
// cek-terminal?
var cekTerminal_p = function(state) { return (isSxTruthy(sxEq(get(state, "phase"), "continue")) && isEmpty(get(state, "kont"))); };
PRIMITIVES["cek-terminal?"] = cekTerminal_p;
// cek-suspended?
var cekSuspended_p = function(state) { return sxEq(get(state, "phase"), "io-suspended"); };
PRIMITIVES["cek-suspended?"] = cekSuspended_p;
// cek-control
var cekControl = function(s) { return get(s, "control"); };
PRIMITIVES["cek-control"] = cekControl;
// cek-env
var cekEnv = function(s) { return get(s, "env"); };
PRIMITIVES["cek-env"] = cekEnv;
// cek-kont
var cekKont = function(s) { return get(s, "kont"); };
PRIMITIVES["cek-kont"] = cekKont;
// cek-phase
var cekPhase = function(s) { return get(s, "phase"); };
PRIMITIVES["cek-phase"] = cekPhase;
// cek-io-request
var cekIoRequest = function(s) { return get(s, "request"); };
PRIMITIVES["cek-io-request"] = cekIoRequest;
// cek-value
var cekValue = function(s) { return get(s, "value"); };
PRIMITIVES["cek-value"] = cekValue;
// make-if-frame
var makeIfFrame = function(thenExpr, elseExpr, env) { return {"else": elseExpr, "env": env, "type": "if", "then": thenExpr}; };
PRIMITIVES["make-if-frame"] = makeIfFrame;
// make-when-frame
var makeWhenFrame = function(bodyExprs, env) { return {"body": bodyExprs, "env": env, "type": "when"}; };
PRIMITIVES["make-when-frame"] = makeWhenFrame;
// make-begin-frame
var makeBeginFrame = function(remaining, env) { return {"env": env, "type": "begin", "remaining": remaining}; };
PRIMITIVES["make-begin-frame"] = makeBeginFrame;
// make-let-frame
var makeLetFrame = function(name, remaining, body, local) { return {"body": body, "env": local, "type": "let", "remaining": remaining, "name": name}; };
PRIMITIVES["make-let-frame"] = makeLetFrame;
// make-define-frame
var makeDefineFrame = function(name, env, hasEffects, effectList) { return {"env": env, "effect-list": effectList, "has-effects": hasEffects, "type": "define", "name": name}; };
PRIMITIVES["make-define-frame"] = makeDefineFrame;
// make-set-frame
var makeSetFrame = function(name, env) { return {"env": env, "type": "set", "name": name}; };
PRIMITIVES["make-set-frame"] = makeSetFrame;
// make-arg-frame
var makeArgFrame = function(f, evaled, remaining, env, rawArgs, headName) { return {"env": env, "head-name": sxOr(headName, NIL), "evaled": evaled, "type": "arg", "f": f, "remaining": remaining, "raw-args": rawArgs}; };
PRIMITIVES["make-arg-frame"] = makeArgFrame;
// make-call-frame
var makeCallFrame = function(f, args, env) { return {"args": args, "env": env, "type": "call", "f": f}; };
PRIMITIVES["make-call-frame"] = makeCallFrame;
// make-cond-frame
var makeCondFrame = function(remaining, env, scheme_p) { return {"scheme": scheme_p, "env": env, "type": "cond", "remaining": remaining}; };
PRIMITIVES["make-cond-frame"] = makeCondFrame;
// make-cond-arrow-frame
var makeCondArrowFrame = function(testValue, env) { return {"env": env, "match-val": testValue, "type": "cond-arrow"}; };
PRIMITIVES["make-cond-arrow-frame"] = makeCondArrowFrame;
// make-case-frame
var makeCaseFrame = function(matchVal, remaining, env) { return {"match-val": matchVal, "env": env, "type": "case", "remaining": remaining}; };
PRIMITIVES["make-case-frame"] = makeCaseFrame;
// make-thread-frame
var makeThreadFrame = function(remaining, env, mode, name) { return {"env": env, "type": "thread", "extra": mode, "remaining": remaining, "name": name}; };
PRIMITIVES["make-thread-frame"] = makeThreadFrame;
// thread-insert-arg
var threadInsertArg = function(form, value, fenv) { return (isSxTruthy(sxEq(typeOf(form), "list")) ? evalExpr(cons(first(form), cons([new Symbol("quote"), value], rest(form))), fenv) : evalExpr([form, [new Symbol("quote"), value]], fenv)); };
PRIMITIVES["thread-insert-arg"] = threadInsertArg;
// thread-insert-arg-last
var threadInsertArgLast = function(form, value, fenv) { return (isSxTruthy(sxEq(typeOf(form), "list")) ? evalExpr(append(form, [[new Symbol("quote"), value]]), fenv) : evalExpr([form, [new Symbol("quote"), value]], fenv)); };
PRIMITIVES["thread-insert-arg-last"] = threadInsertArgLast;
// make-map-frame
var makeMapFrame = function(f, remaining, results, env) { return {"indexed": false, "env": env, "results": results, "type": "map", "f": f, "remaining": remaining}; };
PRIMITIVES["make-map-frame"] = makeMapFrame;
// make-map-indexed-frame
var makeMapIndexedFrame = function(f, remaining, results, env) { return {"indexed": true, "env": env, "results": results, "type": "map", "f": f, "remaining": remaining}; };
PRIMITIVES["make-map-indexed-frame"] = makeMapIndexedFrame;
// make-multi-map-frame
var makeMultiMapFrame = function(f, remainingLists, results, env) { return {"env": env, "results": results, "type": "multi-map", "f": f, "remaining": remainingLists}; };
PRIMITIVES["make-multi-map-frame"] = makeMultiMapFrame;
// make-filter-frame
var makeFilterFrame = function(f, remaining, results, currentItem, env) { return {"current-item": currentItem, "env": env, "results": results, "type": "filter", "f": f, "remaining": remaining}; };
PRIMITIVES["make-filter-frame"] = makeFilterFrame;
// make-reduce-frame
var makeReduceFrame = function(f, remaining, env) { return {"env": env, "type": "reduce", "f": f, "remaining": remaining}; };
PRIMITIVES["make-reduce-frame"] = makeReduceFrame;
// make-for-each-frame
var makeForEachFrame = function(f, remaining, env) { return {"env": env, "type": "for-each", "f": f, "remaining": remaining}; };
PRIMITIVES["make-for-each-frame"] = makeForEachFrame;
// make-some-frame
var makeSomeFrame = function(f, remaining, env) { return {"env": env, "type": "some", "f": f, "remaining": remaining}; };
PRIMITIVES["make-some-frame"] = makeSomeFrame;
// make-every-frame
var makeEveryFrame = function(f, remaining, env) { return {"env": env, "type": "every", "f": f, "remaining": remaining}; };
PRIMITIVES["make-every-frame"] = makeEveryFrame;
// make-scope-frame
var makeScopeFrame = function(name, remaining, env) { return {"env": env, "type": "scope", "remaining": remaining, "name": name}; };
PRIMITIVES["make-scope-frame"] = makeScopeFrame;
// make-provide-frame
var makeProvideFrame = function(name, value, remaining, env) { return {"subscribers": [], "env": env, "value": value, "type": "provide", "remaining": remaining, "name": name}; };
PRIMITIVES["make-provide-frame"] = makeProvideFrame;
// make-bind-frame
var makeBindFrame = function(body, env, prevTracking) { return {"body": body, "env": env, "type": "bind", "prev-tracking": prevTracking}; };
PRIMITIVES["make-bind-frame"] = makeBindFrame;
// make-provide-set-frame
var makeProvideSetFrame = function(name, env) { return {"env": env, "type": "provide-set", "name": name}; };
PRIMITIVES["make-provide-set-frame"] = makeProvideSetFrame;
// make-scope-acc-frame
var makeScopeAccFrame = function(name, value, remaining, env) { return {"env": env, "value": sxOr(value, NIL), "type": "scope-acc", "remaining": remaining, "emitted": [], "name": name}; };
PRIMITIVES["make-scope-acc-frame"] = makeScopeAccFrame;
// make-reset-frame
var makeResetFrame = function(env) { return {"env": env, "type": "reset"}; };
PRIMITIVES["make-reset-frame"] = makeResetFrame;
// make-dict-frame
var makeDictFrame = function(remaining, results, env) { return {"env": env, "results": results, "type": "dict", "remaining": remaining}; };
PRIMITIVES["make-dict-frame"] = makeDictFrame;
// make-and-frame
var makeAndFrame = function(remaining, env) { return {"env": env, "type": "and", "remaining": remaining}; };
PRIMITIVES["make-and-frame"] = makeAndFrame;
// make-or-frame
var makeOrFrame = function(remaining, env) { return {"env": env, "type": "or", "remaining": remaining}; };
PRIMITIVES["make-or-frame"] = makeOrFrame;
// make-dynamic-wind-frame
var makeDynamicWindFrame = function(phase, bodyThunk, afterThunk, env) { return {"env": env, "phase": phase, "after-thunk": afterThunk, "type": "dynamic-wind", "body-thunk": bodyThunk}; };
PRIMITIVES["make-dynamic-wind-frame"] = makeDynamicWindFrame;
// make-reactive-reset-frame
var makeReactiveResetFrame = function(env, updateFn, firstRender_p) { return {"first-render": firstRender_p, "update-fn": updateFn, "env": env, "type": "reactive-reset"}; };
PRIMITIVES["make-reactive-reset-frame"] = makeReactiveResetFrame;
// make-callcc-frame
var makeCallccFrame = function(env) { return {"env": env, "type": "callcc"}; };
PRIMITIVES["make-callcc-frame"] = makeCallccFrame;
// make-deref-frame
var makeDerefFrame = function(env) { return {"env": env, "type": "deref"}; };
PRIMITIVES["make-deref-frame"] = makeDerefFrame;
// make-ho-setup-frame
var makeHoSetupFrame = function(hoType, remainingArgs, evaledArgs, env) { return {"ho-type": hoType, "env": env, "evaled": evaledArgs, "type": "ho-setup", "remaining": remainingArgs}; };
PRIMITIVES["make-ho-setup-frame"] = makeHoSetupFrame;
// make-comp-trace-frame
var makeCompTraceFrame = function(name, file) { return {"env": file, "type": "comp-trace", "name": name}; };
PRIMITIVES["make-comp-trace-frame"] = makeCompTraceFrame;
// kont-collect-comp-trace
var kontCollectCompTrace = function(kont) { return (isSxTruthy(isEmpty(kont)) ? [] : (function() {
var frame = first(kont);
return (isSxTruthy(sxEq(frameType(frame), "comp-trace")) ? cons({"file": get(frame, "file"), "name": get(frame, "name")}, kontCollectCompTrace(rest(kont))) : kontCollectCompTrace(rest(kont)));
})()); };
PRIMITIVES["kont-collect-comp-trace"] = kontCollectCompTrace;
// make-handler-frame
var makeHandlerFrame = function(handlers, remaining, env) { return {"env": env, "type": "handler", "f": handlers, "remaining": remaining}; };
PRIMITIVES["make-handler-frame"] = makeHandlerFrame;
// make-restart-frame
var makeRestartFrame = function(restarts, remaining, env) { return {"env": env, "type": "restart", "f": restarts, "remaining": remaining}; };
PRIMITIVES["make-restart-frame"] = makeRestartFrame;
// make-signal-return-frame
var makeSignalReturnFrame = function(env, savedKont) { return {"env": env, "type": "signal-return", "f": savedKont}; };
PRIMITIVES["make-signal-return-frame"] = makeSignalReturnFrame;
// make-raise-eval-frame
var makeRaiseEvalFrame = function(env, continuable_p) { return {"scheme": continuable_p, "env": env, "type": "raise-eval"}; };
PRIMITIVES["make-raise-eval-frame"] = makeRaiseEvalFrame;
// make-raise-guard-frame
var makeRaiseGuardFrame = function(env, savedKont) { return {"env": env, "type": "raise-guard", "remaining": savedKont}; };
PRIMITIVES["make-raise-guard-frame"] = makeRaiseGuardFrame;
// make-perform-frame
var makePerformFrame = function(env) { return {"env": env, "type": "perform"}; };
PRIMITIVES["make-perform-frame"] = makePerformFrame;
// make-vm-resume-frame
var makeVmResumeFrame = function(resumeFn, env) { return {"env": env, "type": "vm-resume", "f": resumeFn}; };
PRIMITIVES["make-vm-resume-frame"] = makeVmResumeFrame;
// make-import-frame
var makeImportFrame = function(importSet, remainingSets, env) { return {"args": importSet, "env": env, "type": "import", "remaining": remainingSets}; };
PRIMITIVES["make-import-frame"] = makeImportFrame;
// make-parameterize-frame
var makeParameterizeFrame = function(remaining, currentParam, results, body, env) { return {"env": env, "body": body, "results": results, "type": "parameterize", "f": currentParam, "remaining": remaining}; };
PRIMITIVES["make-parameterize-frame"] = makeParameterizeFrame;
// find-matching-handler
var findMatchingHandler = function(handlers, condition) { return (isSxTruthy(isEmpty(handlers)) ? NIL : (function() {
var pair = first(handlers);
return (function() {
var pred = first(pair);
var handlerFn = nth(pair, 1);
return (isSxTruthy(cekCall(pred, [condition])) ? handlerFn : findMatchingHandler(rest(handlers), condition));
})();
})()); };
PRIMITIVES["find-matching-handler"] = findMatchingHandler;
// kont-find-handler
var kontFindHandler = function(kont, condition) { return (isSxTruthy(isEmpty(kont)) ? NIL : (function() {
var frame = first(kont);
return (isSxTruthy(sxEq(frameType(frame), "handler")) ? (function() {
var match = findMatchingHandler(get(frame, "f"), condition);
return (isSxTruthy(isNil(match)) ? kontFindHandler(rest(kont), condition) : match);
})() : kontFindHandler(rest(kont), condition));
})()); };
PRIMITIVES["kont-find-handler"] = kontFindHandler;
// find-named-restart
var findNamedRestart = function(restarts, name) { return (isSxTruthy(isEmpty(restarts)) ? NIL : (function() {
var entry = first(restarts);
return (isSxTruthy(sxEq(first(entry), name)) ? entry : findNamedRestart(rest(restarts), name));
})()); };
PRIMITIVES["find-named-restart"] = findNamedRestart;
// kont-find-restart
var kontFindRestart = function(kont, name) { return (isSxTruthy(isEmpty(kont)) ? NIL : (function() {
var frame = first(kont);
return (isSxTruthy(sxEq(frameType(frame), "restart")) ? (function() {
var match = findNamedRestart(get(frame, "f"), name);
return (isSxTruthy(isNil(match)) ? kontFindRestart(rest(kont), name) : [match, frame, rest(kont)]);
})() : kontFindRestart(rest(kont), name));
})()); };
PRIMITIVES["kont-find-restart"] = kontFindRestart;
// frame-type
var frameType = function(f) { return get(f, "type"); };
PRIMITIVES["frame-type"] = frameType;
// kont-push
var kontPush = function(frame, kont) { return cons(frame, kont); };
PRIMITIVES["kont-push"] = kontPush;
// kont-top
var kontTop = function(kont) { return first(kont); };
PRIMITIVES["kont-top"] = kontTop;
// kont-pop
var kontPop = function(kont) { return rest(kont); };
PRIMITIVES["kont-pop"] = kontPop;
// kont-empty?
var kontEmpty_p = function(kont) { return isEmpty(kont); };
PRIMITIVES["kont-empty?"] = kontEmpty_p;
// 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(sxEq(frameType(frame), "reset"), sxEq(frameType(frame), "reactive-reset"))) ? [captured, rest(k)] : scan(rest(k), append(captured, [frame])));
})()); };
PRIMITIVES["scan"] = scan;
return scan(kont, []); };
PRIMITIVES["kont-capture-to-reset"] = kontCaptureToReset;
// kont-push-provides
var kontPushProvides = function(pairs, env, kont) { return (isSxTruthy(isEmpty(pairs)) ? kont : (function() {
var pair = first(pairs);
return kontPushProvides(rest(pairs), env, cons(makeProvideFrame(first(pair), nth(pair, 1), [], env), kont));
})()); };
PRIMITIVES["kont-push-provides"] = kontPushProvides;
// kont-find-provide
var kontFindProvide = function(kont, name) { return (isSxTruthy(isEmpty(kont)) ? NIL : (function() {
var frame = first(kont);
return (isSxTruthy((isSxTruthy(sxEq(frameType(frame), "provide")) && sxEq(get(frame, "name"), name))) ? frame : kontFindProvide(rest(kont), name));
})()); };
PRIMITIVES["kont-find-provide"] = kontFindProvide;
// kont-find-scope-acc
var kontFindScopeAcc = function(kont, name) { return (isSxTruthy(isEmpty(kont)) ? NIL : (function() {
var frame = first(kont);
return (isSxTruthy((isSxTruthy(sxEq(frameType(frame), "scope-acc")) && sxEq(get(frame, "name"), name))) ? frame : kontFindScopeAcc(rest(kont), name));
})()); };
PRIMITIVES["kont-find-scope-acc"] = kontFindScopeAcc;
// has-reactive-reset-frame?
var hasReactiveResetFrame_p = function(kont) { return (isSxTruthy(isEmpty(kont)) ? false : (isSxTruthy(sxEq(frameType(first(kont)), "reactive-reset")) ? true : hasReactiveResetFrame_p(rest(kont)))); };
PRIMITIVES["has-reactive-reset-frame?"] = hasReactiveResetFrame_p;
// 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(sxEq(frameType(frame), "reactive-reset")) ? [captured, frame, rest(k)] : scan(rest(k), append(captured, [frame])));
})()); };
PRIMITIVES["scan"] = scan;
return scan(kont, []); };
PRIMITIVES["kont-capture-to-reactive-reset"] = kontCaptureToReactiveReset;
// *custom-special-forms*
var _customSpecialForms = {};
PRIMITIVES["*custom-special-forms*"] = _customSpecialForms;
// register-special-form!
var registerSpecialForm = function(name, handler) { return dictSet(_customSpecialForms, name, handler); };
PRIMITIVES["register-special-form!"] = registerSpecialForm;
// *render-check*
var _renderCheck = NIL;
PRIMITIVES["*render-check*"] = _renderCheck;
// *render-fn*
var _renderFn = NIL;
PRIMITIVES["*render-fn*"] = _renderFn;
// *bind-tracking*
var _bindTracking_ = NIL;
PRIMITIVES["*bind-tracking*"] = _bindTracking_;
// *library-registry*
var _libraryRegistry_ = {};
PRIMITIVES["*library-registry*"] = _libraryRegistry_;
// library-name-key
var libraryNameKey = function(spec) { return join(".", map(function(s) { return (isSxTruthy(symbol_p(s)) ? symbolName(s) : (String(s))); }, spec)); };
PRIMITIVES["library-name-key"] = libraryNameKey;
// library-loaded?
var libraryLoaded_p = function(spec) { return dictHas(_libraryRegistry_, libraryNameKey(spec)); };
PRIMITIVES["library-loaded?"] = libraryLoaded_p;
// library-exports
var libraryExports = function(spec) { return get(get(_libraryRegistry_, libraryNameKey(spec)), "exports"); };
PRIMITIVES["library-exports"] = libraryExports;
// register-library
var registerLibrary = function(spec, exports) { return dictSet(_libraryRegistry_, libraryNameKey(spec), {"exports": exports}); };
PRIMITIVES["register-library"] = registerLibrary;
// *io-registry*
var _ioRegistry_ = {};
PRIMITIVES["*io-registry*"] = _ioRegistry_;
// io-register!
var ioRegister_b = function(name, spec) { return dictSet(_ioRegistry_, name, spec); };
PRIMITIVES["io-register!"] = ioRegister_b;
// io-registered?
var ioRegistered_p = function(name) { return dictHas(_ioRegistry_, name); };
PRIMITIVES["io-registered?"] = ioRegistered_p;
// io-lookup
var ioLookup = function(name) { return get(_ioRegistry_, name); };
PRIMITIVES["io-lookup"] = ioLookup;
// io-names
var ioNames = function() { return keys(_ioRegistry_); };
PRIMITIVES["io-names"] = ioNames;
// step-sf-io
var stepSfIo = function(args, env, kont) { return (function() {
var name = first(args);
var ioArgs = rest(args);
if (isSxTruthy(!isSxTruthy(ioRegistered_p(name)))) {
error((String("io: unknown operation '") + String(name) + String("' — not in *io-registry*")));
}
return makeCekState(cons(new Symbol("perform"), [{"args": ioArgs, "op": name}]), env, kont);
})(); };
PRIMITIVES["step-sf-io"] = stepSfIo;
// trampoline
var trampoline = function(val) { return (function() {
var result = val;
return (isSxTruthy(isThunk(result)) ? trampoline(evalExpr(thunkExpr(result), thunkEnv(result))) : result);
})(); };
PRIMITIVES["trampoline"] = trampoline;
// *strict*
var _strict_ = false;
PRIMITIVES["*strict*"] = _strict_;
// set-strict!
var setStrict_b = function(val) { return (_strict_ = val); };
PRIMITIVES["set-strict!"] = setStrict_b;
// *prim-param-types*
var _primParamTypes_ = NIL;
PRIMITIVES["*prim-param-types*"] = _primParamTypes_;
// set-prim-param-types!
var setPrimParamTypes_b = function(types) { return (_primParamTypes_ = types); };
PRIMITIVES["set-prim-param-types!"] = setPrimParamTypes_b;
// value-matches-type?
var valueMatchesType_p = function(val, expectedType) { return (function() { var _m = expectedType; if (_m == "any") return true; if (_m == "number") return isNumber(val); if (_m == "string") return isString(val); if (_m == "boolean") return boolean_p(val); if (_m == "nil") return isNil(val); if (_m == "list") return isList(val); if (_m == "dict") return isDict(val); if (_m == "lambda") return isLambda(val); if (_m == "symbol") return sxEq(typeOf(val), "symbol"); if (_m == "keyword") return sxEq(typeOf(val), "keyword"); return (isSxTruthy((isSxTruthy(isString(expectedType)) && endsWith(expectedType, "?"))) ? sxOr(isNil(val), valueMatchesType_p(val, slice(expectedType, 0, (stringLength(expectedType) - 1)))) : true); })(); };
PRIMITIVES["value-matches-type?"] = valueMatchesType_p;
// strict-check-args
var strictCheckArgs = function(name, args) { return (isSxTruthy((isSxTruthy(_strict_) && _primParamTypes_)) ? (function() {
var spec = get(_primParamTypes_, name);
return (isSxTruthy(spec) ? (function() {
var positional = get(spec, "positional");
var restType = get(spec, "rest-type");
if (isSxTruthy(positional)) {
{ var _c = mapIndexed(function(i, p) { return [i, p]; }, positional); for (var _i = 0; _i < _c.length; _i++) { var pair = _c[_i]; (function() {
var idx = first(pair);
var param = nth(pair, 1);
var pName = first(param);
var pType = nth(param, 1);
return (isSxTruthy((idx < len(args))) ? (function() {
var val = nth(args, idx);
return (isSxTruthy(!isSxTruthy(valueMatchesType_p(val, pType))) ? error((String("Type error: ") + String(name) + String(" expected ") + String(pType) + String(" for param ") + String(pName) + String(", got ") + String(typeOf(val)) + String(" (") + String((String(val))) + String(")"))) : NIL);
})() : NIL);
})(); } }
}
return (isSxTruthy((isSxTruthy(restType) && (len(args) > len(sxOr(positional, []))))) ? forEach(function(pair) { return (function() {
var idx = first(pair);
var val = nth(pair, 1);
return (isSxTruthy(!isSxTruthy(valueMatchesType_p(val, restType))) ? error((String("Type error: ") + String(name) + String(" expected ") + String(restType) + String(" for rest arg ") + String(idx) + String(", got ") + String(typeOf(val)) + String(" (") + String((String(val))) + String(")"))) : NIL);
})(); }, mapIndexed(function(i, v) { return [i, v]; }, slice(args, len(sxOr(positional, []))))) : NIL);
})() : NIL);
})() : NIL); };
PRIMITIVES["strict-check-args"] = strictCheckArgs;
// eval-expr
var evalExpr = function(expr, env) { return NIL; };
PRIMITIVES["eval-expr"] = evalExpr;
// bind-lambda-params
var bindLambdaParams = function(params, args, local) { return (function() {
var restIdx = indexOf_(params, "&rest");
return (isSxTruthy((isSxTruthy(isNumber(restIdx)) && (restIdx < len(params)))) ? (function() {
var positional = slice(params, 0, restIdx);
var restName = nth(params, (restIdx + 1));
return (forEachIndexed(function(i, p) { return envBind(local, p, (isSxTruthy((i < len(args))) ? nth(args, i) : NIL)); }, positional), envBind(local, restName, (isSxTruthy((len(args) > restIdx)) ? slice(args, restIdx) : [])), true);
})() : false);
})(); };
PRIMITIVES["bind-lambda-params"] = bindLambdaParams;
// call-lambda
var callLambda = function(f, args, callerEnv) { return (function() {
var params = lambdaParams(f);
var local = envMerge(lambdaClosure(f), callerEnv);
if (isSxTruthy(!isSxTruthy(bindLambdaParams(params, args, local)))) {
if (isSxTruthy((len(args) > len(params)))) {
error((String(sxOr(lambdaName(f), "lambda")) + String(" expects ") + String(len(params)) + String(" args, got ") + String(len(args))));
}
{ var _c = zip(params, args); for (var _i = 0; _i < _c.length; _i++) { var pair = _c[_i]; envBind(local, first(pair), nth(pair, 1)); } }
{ var _c = slice(params, len(args)); for (var _i = 0; _i < _c.length; _i++) { var p = _c[_i]; envBind(local, p, NIL); } }
}
return makeThunk(lambdaBody(f), local);
})(); };
PRIMITIVES["call-lambda"] = callLambda;
// call-component
var callComponent = function(comp, rawArgs, env) { return (function() {
var parsed = parseKeywordArgs(rawArgs, env);
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]; envBind(local, p, sxOr(dictGet(kwargs, p), NIL)); } }
if (isSxTruthy(componentHasChildren(comp))) {
envBind(local, "children", children);
}
return makeThunk(componentBody(comp), local);
})(); };
PRIMITIVES["call-component"] = callComponent;
// parse-keyword-args
var parseKeywordArgs = function(rawArgs, env) { return (function() {
var kwargs = {};
var children = [];
var i = 0;
reduce(function(state, arg) { return (function() {
var idx = get(state, "i");
var skip = get(state, "skip");
return (isSxTruthy(skip) ? assoc(state, "skip", false, "i", (idx + 1)) : (isSxTruthy((isSxTruthy(sxEq(typeOf(arg), "keyword")) && ((idx + 1) < len(rawArgs)))) ? (dictSet(kwargs, keywordName(arg), trampoline(evalExpr(nth(rawArgs, (idx + 1)), env))), assoc(state, "skip", true, "i", (idx + 1))) : (append_b(children, trampoline(evalExpr(arg, env))), assoc(state, "i", (idx + 1)))));
})(); }, {["i"]: 0, ["skip"]: false}, rawArgs);
return [kwargs, children];
})(); };
PRIMITIVES["parse-keyword-args"] = parseKeywordArgs;
// cond-scheme?
var condScheme_p = function(clauses) { return isEvery(function(c) { return (isSxTruthy(sxEq(typeOf(c), "list")) && sxOr(sxEq(len(c), 2), (isSxTruthy(sxEq(len(c), 3)) && isSxTruthy(sxEq(typeOf(nth(c, 1)), "symbol")) && sxEq(symbolName(nth(c, 1)), "=>")))); }, clauses); };
PRIMITIVES["cond-scheme?"] = condScheme_p;
// is-else-clause?
var isElseClause = function(test) { return sxOr((isSxTruthy(sxEq(typeOf(test), "keyword")) && sxEq(keywordName(test), "else")), (isSxTruthy(sxEq(typeOf(test), "symbol")) && sxOr(sxEq(symbolName(test), "else"), sxEq(symbolName(test), ":else")))); };
PRIMITIVES["is-else-clause?"] = isElseClause;
// sf-named-let
var sfNamedLet = function(args, env) { return (function() {
var loopName = symbolName(first(args));
var bindings = nth(args, 1);
var body = slice(args, 2);
var params = [];
var inits = [];
(isSxTruthy((isSxTruthy(sxEq(typeOf(first(bindings)), "list")) && sxEq(len(first(bindings)), 2))) ? forEach(function(binding) { params.push((isSxTruthy(sxEq(typeOf(first(binding)), "symbol")) ? symbolName(first(binding)) : first(binding)));
return append_b(inits, nth(binding, 1)); }, bindings) : reduce(function(acc, pairIdx) { return (append_b(params, (isSxTruthy(sxEq(typeOf(nth(bindings, (pairIdx * 2))), "symbol")) ? symbolName(nth(bindings, (pairIdx * 2))) : nth(bindings, (pairIdx * 2)))), append_b(inits, nth(bindings, ((pairIdx * 2) + 1)))); }, NIL, range(0, (len(bindings) / 2))));
return (function() {
var loopBody = (isSxTruthy(sxEq(len(body), 1)) ? first(body) : cons(makeSymbol("begin"), body));
var loopFn = makeLambda(params, loopBody, env);
loopFn.name = loopName;
envBind(lambdaClosure(loopFn), loopName, loopFn);
return (function() {
var initVals = map(function(e) { return trampoline(evalExpr(e, env)); }, inits);
return cekCall(loopFn, initVals);
})();
})();
})(); };
PRIMITIVES["sf-named-let"] = sfNamedLet;
// sf-lambda
var sfLambda = function(args, env) { return (function() {
var paramsExpr = first(args);
var bodyExprs = rest(args);
var body = (isSxTruthy(sxEq(len(bodyExprs), 1)) ? first(bodyExprs) : cons(makeSymbol("begin"), bodyExprs));
var paramNames = map(function(p) { return (isSxTruthy(sxEq(typeOf(p), "symbol")) ? symbolName(p) : (isSxTruthy((isSxTruthy(sxEq(typeOf(p), "list")) && isSxTruthy(sxEq(len(p), 3)) && isSxTruthy(sxEq(typeOf(nth(p, 1)), "keyword")) && sxEq(keywordName(nth(p, 1)), "as"))) ? symbolName(first(p)) : p)); }, paramsExpr);
return makeLambda(paramNames, body, env);
})(); };
PRIMITIVES["sf-lambda"] = sfLambda;
// sf-defcomp
var sfDefcomp = function(args, env) { return (function() {
var nameSym = first(args);
var paramsRaw = nth(args, 1);
var body = last(args);
var compName = stripPrefix(symbolName(nameSym), "~");
var parsed = parseCompParams(paramsRaw);
var params = first(parsed);
var hasChildren = nth(parsed, 1);
var paramTypes = nth(parsed, 2);
var affinity = defcompKwarg(args, "affinity", "auto");
return (function() {
var comp = makeComponent(compName, params, hasChildren, body, env, affinity);
var effects = defcompKwarg(args, "effects", NIL);
if (isSxTruthy((isSxTruthy(!isSxTruthy(isNil(paramTypes))) && !isSxTruthy(isEmpty(keys(paramTypes)))))) {
componentSetParamTypes_b(comp, paramTypes);
}
if (isSxTruthy(!isSxTruthy(isNil(effects)))) {
(function() {
var effectList = (isSxTruthy(sxEq(typeOf(effects), "list")) ? map(function(e) { return (isSxTruthy(sxEq(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 envBind(env, "*effect-annotations*", effectAnns);
})();
}
if (isSxTruthy(envHas(env, "*current-file*"))) {
componentSetFile_b(comp, envGet(env, "*current-file*"));
}
envBind(env, symbolName(nameSym), comp);
return comp;
})();
})(); };
PRIMITIVES["sf-defcomp"] = sfDefcomp;
// defcomp-kwarg
var defcompKwarg = function(args, key, default_) { return (function() {
var end = (len(args) - 1);
var result = default_;
{ var _c = range(2, end, 1); for (var _i = 0; _i < _c.length; _i++) { var i = _c[_i]; if (isSxTruthy((isSxTruthy(sxEq(typeOf(nth(args, i)), "keyword")) && isSxTruthy(sxEq(keywordName(nth(args, i)), key)) && ((i + 1) < end)))) {
(function() {
var val = nth(args, (i + 1));
return (result = (isSxTruthy(sxEq(typeOf(val), "keyword")) ? keywordName(val) : val));
})();
} } }
return result;
})(); };
PRIMITIVES["defcomp-kwarg"] = defcompKwarg;
// parse-comp-params
var parseCompParams = function(paramsExpr) { return (function() {
var params = [];
var paramTypes = {};
var hasChildren = false;
var inKey = false;
{ var _c = paramsExpr; for (var _i = 0; _i < _c.length; _i++) { var p = _c[_i]; (isSxTruthy((isSxTruthy(sxEq(typeOf(p), "list")) && isSxTruthy(sxEq(len(p), 3)) && isSxTruthy(sxEq(typeOf(first(p)), "symbol")) && isSxTruthy(sxEq(typeOf(nth(p, 1)), "keyword")) && sxEq(keywordName(nth(p, 1)), "as"))) ? (function() {
var name = symbolName(first(p));
var ptype = nth(p, 2);
return (function() {
var typeVal = (isSxTruthy(sxEq(typeOf(ptype), "symbol")) ? symbolName(ptype) : ptype);
return (isSxTruthy(!isSxTruthy(hasChildren)) ? (append_b(params, name), dictSet(paramTypes, name, typeVal)) : NIL);
})();
})() : (isSxTruthy(sxEq(typeOf(p), "symbol")) ? (function() {
var name = symbolName(p);
return (isSxTruthy(sxEq(name, "&key")) ? (inKey = true) : (isSxTruthy(sxEq(name, "&rest")) ? (hasChildren = true) : (isSxTruthy(sxEq(name, "&children")) ? (hasChildren = true) : (isSxTruthy(hasChildren) ? NIL : (isSxTruthy(inKey) ? append_b(params, name) : append_b(params, name))))));
})() : NIL)); } }
return [params, hasChildren, paramTypes];
})(); };
PRIMITIVES["parse-comp-params"] = parseCompParams;
// sf-defisland
var sfDefisland = function(args, env) { return (function() {
var nameSym = first(args);
var paramsRaw = nth(args, 1);
var bodyExprs = slice(args, 2);
var body = (isSxTruthy(sxEq(len(bodyExprs), 1)) ? first(bodyExprs) : cons(makeSymbol("begin"), bodyExprs));
var compName = stripPrefix(symbolName(nameSym), "~");
var parsed = parseCompParams(paramsRaw);
var params = first(parsed);
var hasChildren = nth(parsed, 1);
return (function() {
var island = makeIsland(compName, params, hasChildren, body, env);
if (isSxTruthy(envHas(env, "*current-file*"))) {
componentSetFile_b(island, envGet(env, "*current-file*"));
}
envBind(env, symbolName(nameSym), island);
return island;
})();
})(); };
PRIMITIVES["sf-defisland"] = sfDefisland;
// defio-parse-kwargs!
var defioParseKwargs_b = function(spec, remaining) { return (isSxTruthy((isSxTruthy(!isSxTruthy(isEmpty(remaining))) && isSxTruthy((len(remaining) >= 2)) && keyword_p(first(remaining)))) ? (dictSet(spec, keywordName(first(remaining)), nth(remaining, 1)), defioParseKwargs_b(spec, rest(rest(remaining)))) : NIL); };
PRIMITIVES["defio-parse-kwargs!"] = defioParseKwargs_b;
// sf-defio
var sfDefio = function(args, env) { return (function() {
var name = first(args);
var spec = {};
spec["name"] = name;
defioParseKwargs_b(spec, rest(args));
ioRegister_b(name, spec);
return spec;
})(); };
PRIMITIVES["sf-defio"] = sfDefio;
// sf-defmacro
var sfDefmacro = function(args, env) { return (function() {
var nameSym = first(args);
var paramsRaw = nth(args, 1);
var body = nth(args, 2);
var parsed = parseMacroParams(paramsRaw);
var params = first(parsed);
var restParam = nth(parsed, 1);
return (function() {
var mac = makeMacro(params, restParam, body, env, symbolName(nameSym));
envBind(env, symbolName(nameSym), mac);
return mac;
})();
})(); };
PRIMITIVES["sf-defmacro"] = sfDefmacro;
// parse-macro-params
var parseMacroParams = function(paramsExpr) { return (function() {
var params = [];
var restParam = NIL;
reduce(function(state, p) { return (isSxTruthy((isSxTruthy(sxEq(typeOf(p), "symbol")) && sxEq(symbolName(p), "&rest"))) ? assoc(state, "in-rest", true) : (isSxTruthy(get(state, "in-rest")) ? ((restParam = (isSxTruthy(sxEq(typeOf(p), "symbol")) ? symbolName(p) : p)), state) : (append_b(params, (isSxTruthy(sxEq(typeOf(p), "symbol")) ? symbolName(p) : p)), state))); }, {["in-rest"]: false}, paramsExpr);
return [params, restParam];
})(); };
PRIMITIVES["parse-macro-params"] = parseMacroParams;
// qq-expand
var qqExpand = function(template, env) { return (isSxTruthy(!isSxTruthy(sxEq(typeOf(template), "list"))) ? template : (isSxTruthy(isEmpty(template)) ? [] : (function() {
var head = first(template);
return (isSxTruthy((isSxTruthy(sxEq(typeOf(head), "symbol")) && sxEq(symbolName(head), "unquote"))) ? trampoline(evalExpr(nth(template, 1), env)) : reduce(function(result, item) { return (isSxTruthy((isSxTruthy(sxEq(typeOf(item), "list")) && isSxTruthy(sxEq(len(item), 2)) && isSxTruthy(sxEq(typeOf(first(item)), "symbol")) && sxEq(symbolName(first(item)), "splice-unquote"))) ? (function() {
var spliced = trampoline(evalExpr(nth(item, 1), env));
return (isSxTruthy(sxEq(typeOf(spliced), "list")) ? concat(result, spliced) : (isSxTruthy(isNil(spliced)) ? result : concat(result, [spliced])));
})() : concat(result, [qqExpand(item, env)])); }, [], template));
})())); };
PRIMITIVES["qq-expand"] = qqExpand;
// sf-letrec
var sfLetrec = function(args, env) { return (function() {
var bindings = first(args);
var body = rest(args);
var local = envExtend(env);
var names = [];
var valExprs = [];
(isSxTruthy((isSxTruthy(sxEq(typeOf(first(bindings)), "list")) && sxEq(len(first(bindings)), 2))) ? forEach(function(binding) { return (function() {
var vname = (isSxTruthy(sxEq(typeOf(first(binding)), "symbol")) ? symbolName(first(binding)) : first(binding));
names.push(vname);
valExprs.push(nth(binding, 1));
return envBind(local, vname, NIL);
})(); }, bindings) : reduce(function(acc, pairIdx) { return (function() {
var vname = (isSxTruthy(sxEq(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 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]; 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);
})(); };
PRIMITIVES["sf-letrec"] = sfLetrec;
// step-sf-letrec
var stepSfLetrec = function(args, env, kont) { return (function() {
var thk = sfLetrec(args, env);
return makeCekState(thunkExpr(thk), thunkEnv(thk), kont);
})(); };
PRIMITIVES["step-sf-letrec"] = stepSfLetrec;
// sf-dynamic-wind
var sfDynamicWind = function(args, env) { return (function() {
var before = trampoline(evalExpr(first(args), env));
var body = trampoline(evalExpr(nth(args, 1), env));
var after = trampoline(evalExpr(nth(args, 2), env));
return dynamicWindCall(before, body, after, env);
})(); };
PRIMITIVES["sf-dynamic-wind"] = sfDynamicWind;
// sf-scope
var sfScope = function(args, env) { return (function() {
var name = trampoline(evalExpr(first(args), env));
var rest = slice(args, 1);
var val = NIL;
var bodyExprs = NIL;
(isSxTruthy((isSxTruthy((len(rest) >= 2)) && isSxTruthy(sxEq(typeOf(first(rest)), "keyword")) && sxEq(keywordName(first(rest)), "value"))) ? ((val = trampoline(evalExpr(nth(rest, 1), env))), (bodyExprs = slice(rest, 2))) : (bodyExprs = rest));
scopePush(name, val);
return (function() {
var result = NIL;
{ var _c = bodyExprs; for (var _i = 0; _i < _c.length; _i++) { var e = _c[_i]; result = trampoline(evalExpr(e, env)); } }
scopePop(name);
return result;
})();
})(); };
PRIMITIVES["sf-scope"] = sfScope;
// sf-provide
var sfProvide = function(args, env) { return (function() {
var name = trampoline(evalExpr(first(args), env));
var val = trampoline(evalExpr(nth(args, 1), env));
var bodyExprs = slice(args, 2);
var result = NIL;
scopePush(name, val);
{ var _c = bodyExprs; for (var _i = 0; _i < _c.length; _i++) { var e = _c[_i]; result = trampoline(evalExpr(e, env)); } }
scopePop(name);
return result;
})(); };
PRIMITIVES["sf-provide"] = sfProvide;
// expand-macro
var expandMacro = function(mac, rawArgs, env) { return (function() {
var body = macroBody(mac);
return (isSxTruthy((isSxTruthy(symbol_p(body)) && sxEq(symbolName(body), "__syntax-rules-body__"))) ? (function() {
var closure = macroClosure(mac);
return syntaxRulesExpand(envGet(closure, "__sr-literals"), envGet(closure, "__sr-rules"), rawArgs);
})() : (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]; envBind(local, first(pair), (isSxTruthy((nth(pair, 1) < len(rawArgs))) ? nth(rawArgs, nth(pair, 1)) : NIL)); } }
if (isSxTruthy(macroRestParam(mac))) {
envBind(local, macroRestParam(mac), slice(rawArgs, len(macroParams(mac))));
}
return trampoline(evalExpr(macroBody(mac), local));
})());
})(); };
PRIMITIVES["expand-macro"] = expandMacro;
// cek-step-loop
var cekStepLoop = function(state) { return (isSxTruthy(sxOr(cekTerminal_p(state), cekSuspended_p(state))) ? state : cekStepLoop(cekStep(state))); };
PRIMITIVES["cek-step-loop"] = cekStepLoop;
// cek-run
var cekRun = function(state) { return (function() {
var final_ = cekStepLoop(state);
return (isSxTruthy(cekSuspended_p(final_)) ? error("IO suspension in non-IO context") : cekValue(final_));
})(); };
PRIMITIVES["cek-run"] = cekRun;
// cek-resume
var cekResume = function(suspendedState, result) { return cekStepLoop(makeCekValue(result, cekEnv(suspendedState), cekKont(suspendedState))); };
PRIMITIVES["cek-resume"] = cekResume;
// cek-step
var cekStep = function(state) { return (isSxTruthy(sxEq(cekPhase(state), "eval")) ? stepEval(state) : stepContinue(state)); };
PRIMITIVES["cek-step"] = cekStep;
// 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(sxEq(name, "true")) ? true : (isSxTruthy(sxEq(name, "false")) ? false : (isSxTruthy(sxEq(name, "nil")) ? NIL : error((String("Undefined symbol: ") + String(name))))))));
if (isSxTruthy((isSxTruthy(isNil(val)) && startsWith(name, "~")))) {
debugLog("Component not found:", 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); })();
})(); };
PRIMITIVES["step-eval"] = stepEval;
// step-sf-raise
var stepSfRaise = function(args, env, kont) { return makeCekState(first(args), env, kontPush(makeRaiseEvalFrame(env, false), kont)); };
PRIMITIVES["step-sf-raise"] = stepSfRaise;
// step-sf-guard
var stepSfGuard = function(args, env, kont) { return (function() {
var varClauses = first(args);
var body = rest(args);
var var_ = first(varClauses);
var clauses = rest(varClauses);
var sentinel = makeSymbol("__guard-reraise__");
return stepEvalList([new Symbol("let"), [[new Symbol("__guard-result"), cons(new Symbol("call/cc"), [cons(new Symbol("fn"), cons([new Symbol("__guard-k")], [cons(new Symbol("handler-bind"), cons([[cons(new Symbol("fn"), cons([new Symbol("_")], [true])), cons(new Symbol("fn"), cons([var_], [[new Symbol("__guard-k"), cons(new Symbol("cond"), append(clauses, [[new Symbol("else"), [new Symbol("list"), [new Symbol("quote"), sentinel], var_]]]))]]))]], [[new Symbol("__guard-k"), cons(new Symbol("begin"), body)]]))]))])]], [new Symbol("if"), [new Symbol("and"), [new Symbol("list?"), new Symbol("__guard-result")], [new Symbol("="), [new Symbol("len"), new Symbol("__guard-result")], 2], [new Symbol("="), [new Symbol("first"), new Symbol("__guard-result")], [new Symbol("quote"), sentinel]]], [new Symbol("raise"), [new Symbol("nth"), new Symbol("__guard-result"), 1]], new Symbol("__guard-result")]], env, kont);
})(); };
PRIMITIVES["step-sf-guard"] = stepSfGuard;
// step-sf-callcc
var stepSfCallcc = function(args, env, kont) { return makeCekState(first(args), env, kontPush(makeCallccFrame(env), kont)); };
PRIMITIVES["step-sf-callcc"] = stepSfCallcc;
// step-sf-case
var stepSfCase = function(args, env, kont) { return makeCekState(first(args), env, kontPush(makeCaseFrame(NIL, rest(args), env), kont)); };
PRIMITIVES["step-sf-case"] = stepSfCase;
// step-sf-let-match
var stepSfLetMatch = function(args, env, kont) { return (function() {
var pattern = first(args);
var expr = nth(args, 1);
var body = rest(rest(args));
return stepSfMatch([expr, [pattern, cons(new Symbol("begin"), body)]], env, kont);
})(); };
PRIMITIVES["step-sf-let-match"] = stepSfLetMatch;
// step-eval-list
var stepEvalList = function(expr, env, kont) { return (function() {
var head = first(expr);
var args = rest(expr);
return (isSxTruthy(!isSxTruthy(sxOr(sxEq(typeOf(head), "symbol"), sxEq(typeOf(head), "lambda"), sxEq(typeOf(head), "list")))) ? (isSxTruthy(isEmpty(expr)) ? makeCekValue([], env, kont) : makeCekState(first(expr), env, kontPush(makeMapFrame(NIL, rest(expr), [], env), kont))) : (isSxTruthy(sxEq(typeOf(head), "symbol")) ? (function() {
var name = symbolName(head);
return (function() { var _m = name; if (_m == "if") return stepSfIf(args, env, kont); if (_m == "when") return stepSfWhen(args, env, kont); if (_m == "cond") return stepSfCond(args, env, kont); if (_m == "case") return stepSfCase(args, env, kont); if (_m == "and") return stepSfAnd(args, env, kont); if (_m == "or") return stepSfOr(args, env, kont); if (_m == "let") return stepSfLet(args, env, kont); if (_m == "let*") return stepSfLet(args, env, kont); if (_m == "lambda") return stepSfLambda(args, env, kont); if (_m == "fn") return stepSfLambda(args, env, kont); if (_m == "define") return stepSfDefine(args, env, kont); if (_m == "defcomp") return makeCekValue(sfDefcomp(args, env), env, kont); if (_m == "defisland") return makeCekValue(sfDefisland(args, env), env, kont); if (_m == "defmacro") return makeCekValue(sfDefmacro(args, env), env, kont); if (_m == "defio") return makeCekValue(sfDefio(args, env), env, kont); if (_m == "io") return stepSfIo(args, env, kont); if (_m == "begin") return stepSfBegin(args, env, kont); if (_m == "do") return (isSxTruthy((isSxTruthy(!isSxTruthy(isEmpty(args))) && isSxTruthy(isList(first(args))) && isSxTruthy(!isSxTruthy(isEmpty(first(args)))) && isList(first(first(args))))) ? (function() {
var bindings = first(args);
var testClause = nth(args, 1);
var body = rest(rest(args));
var vars = map(function(b) { return first(b); }, bindings);
var inits = map(function(b) { return nth(b, 1); }, bindings);
var steps = map(function(b) { return (isSxTruthy((len(b) > 2)) ? nth(b, 2) : first(b)); }, bindings);
var test = first(testClause);
var result = rest(testClause);
return stepEvalList(cons(new Symbol("let"), cons(new Symbol("__do-loop"), cons(map(function(b) { return [first(b), nth(b, 1)]; }, bindings), [cons(new Symbol("if"), cons(test, cons((isSxTruthy(isEmpty(result)) ? NIL : cons(new Symbol("begin"), result)), [cons(new Symbol("begin"), append(body, [cons(new Symbol("__do-loop"), steps)]))])))]))), env, kont);
})() : stepSfBegin(args, env, kont)); if (_m == "guard") return stepSfGuard(args, env, kont); if (_m == "quote") return makeCekValue((isSxTruthy(isEmpty(args)) ? NIL : first(args)), env, kont); if (_m == "quasiquote") return makeCekValue(qqExpand(first(args), env), env, kont); if (_m == "->") return stepSfThreadFirst(args, env, kont); if (_m == "->>") return stepSfThreadLast(args, env, kont); if (_m == "|>") return stepSfThreadLast(args, env, kont); if (_m == "as->") return stepSfThreadAs(args, env, kont); if (_m == "set!") return stepSfSet(args, env, kont); if (_m == "letrec") return stepSfLetrec(args, env, kont); if (_m == "reset") return stepSfReset(args, env, kont); if (_m == "shift") return stepSfShift(args, env, kont); if (_m == "deref") return stepSfDeref(args, env, kont); if (_m == "scope") return stepSfScope(args, env, kont); if (_m == "provide") return stepSfProvide(args, env, kont); if (_m == "peek") return stepSfPeek(args, env, kont); if (_m == "provide!") return stepSfProvide_b(args, env, kont); if (_m == "context") return stepSfContext(args, env, kont); if (_m == "bind") return stepSfBind(args, env, kont); if (_m == "emit!") return stepSfEmit(args, env, kont); if (_m == "emitted") return stepSfEmitted(args, env, kont); if (_m == "handler-bind") return stepSfHandlerBind(args, env, kont); if (_m == "restart-case") return stepSfRestartCase(args, env, kont); if (_m == "signal-condition") return stepSfSignal(args, env, kont); if (_m == "invoke-restart") return stepSfInvokeRestart(args, env, kont); if (_m == "match") return stepSfMatch(args, env, kont); if (_m == "let-match") return stepSfLetMatch(args, env, kont); if (_m == "dynamic-wind") return makeCekValue(sfDynamicWind(args, env), env, kont); if (_m == "map") return stepHoMap(args, env, kont); if (_m == "map-indexed") return stepHoMapIndexed(args, env, kont); if (_m == "filter") return stepHoFilter(args, env, kont); if (_m == "reduce") return stepHoReduce(args, env, kont); if (_m == "some") return stepHoSome(args, env, kont); if (_m == "every?") return stepHoEvery(args, env, kont); if (_m == "for-each") return stepHoForEach(args, env, kont); if (_m == "raise") return stepSfRaise(args, env, kont); if (_m == "raise-continuable") return makeCekState(first(args), env, kontPush(makeRaiseEvalFrame(env, true), kont)); if (_m == "call/cc") return stepSfCallcc(args, env, kont); if (_m == "call-with-current-continuation") return stepSfCallcc(args, env, kont); if (_m == "perform") return stepSfPerform(args, env, kont); if (_m == "define-library") return stepSfDefineLibrary(args, env, kont); if (_m == "import") return stepSfImport(args, env, kont); if (_m == "define-record-type") return makeCekValue(sfDefineRecordType(args, env), env, kont); if (_m == "define-protocol") return makeCekValue(sfDefineProtocol(args, env), env, kont); if (_m == "implement") return makeCekValue(sfImplement(args, env), env, kont); if (_m == "parameterize") return stepSfParameterize(args, env, kont); if (_m == "syntax-rules") return makeCekValue(sfSyntaxRules(args, env), env, kont); if (_m == "define-syntax") return stepSfDefine(args, env, kont); return (isSxTruthy(dictHas(_customSpecialForms, name)) ? makeCekValue((get(_customSpecialForms, name))(args, env), 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(_renderCheck) && _renderCheck(expr, env))) ? makeCekValue(_renderFn(expr, env), env, kont) : stepEvalCall(head, args, env, kont)))); })();
})() : stepEvalCall(head, args, env, kont)));
})(); };
PRIMITIVES["step-eval-list"] = stepEvalList;
// kont-extract-provides
var kontExtractProvides = function(kont) { return (isSxTruthy(isEmpty(kont)) ? [] : (function() {
var frame = first(kont);
var restFrames = kontExtractProvides(rest(kont));
return (isSxTruthy(sxEq(frameType(frame), "provide")) ? cons({"subscribers": [], "env": get(frame, "env"), "value": get(frame, "value"), "type": "provide", "remaining": [], "name": get(frame, "name")}, restFrames) : restFrames);
})()); };
PRIMITIVES["kont-extract-provides"] = kontExtractProvides;
// fire-provide-subscribers
var fireProvideSubscribers = function(frame, kont) { return (function() {
var subs = get(frame, "subscribers");
return (isSxTruthy(!isSxTruthy(isEmpty(subs))) ? forEach(function(sub) { return cekCall(sub, [kont]); }, subs) : NIL);
})(); };
PRIMITIVES["fire-provide-subscribers"] = fireProvideSubscribers;
// step-sf-bind
var stepSfBind = function(args, env, kont) { return (function() {
var body = first(args);
var prev = _bindTracking_;
_bindTracking_ = [];
return makeCekState(body, env, kontPush(makeBindFrame(body, env, prev), kont));
})(); };
PRIMITIVES["step-sf-bind"] = stepSfBind;
// step-sf-parameterize
var stepSfParameterize = function(args, env, kont) { return (function() {
var bindings = first(args);
var body = rest(args);
return (isSxTruthy(sxOr(isNil(bindings), isEmpty(bindings))) ? stepSfBegin(body, env, kont) : (function() {
var firstPair = first(bindings);
return makeCekState(first(firstPair), env, kontPush(makeParameterizeFrame(bindings, NIL, [], body, env), kont));
})());
})(); };
PRIMITIVES["step-sf-parameterize"] = stepSfParameterize;
// syntax-rules-match
var syntaxRulesMatch = function(pattern, form, literals) { return (isSxTruthy((isSxTruthy(symbol_p(pattern)) && sxEq(symbolName(pattern), "_"))) ? {} : (isSxTruthy((isSxTruthy(symbol_p(pattern)) && contains(literals, symbolName(pattern)))) ? (isSxTruthy((isSxTruthy(symbol_p(form)) && sxEq(symbolName(pattern), symbolName(form)))) ? {} : NIL) : (isSxTruthy(symbol_p(pattern)) ? (function() {
var d = {};
d[symbolName(pattern)] = form;
return d;
})() : (isSxTruthy((isSxTruthy(isList(pattern)) && isEmpty(pattern))) ? (isSxTruthy((isSxTruthy(isList(form)) && isEmpty(form))) ? {} : NIL) : (isSxTruthy((isSxTruthy(isList(pattern)) && isList(form))) ? syntaxRulesMatchList(pattern, 0, form, 0, literals) : (isSxTruthy(sxEq(pattern, form)) ? {} : NIL)))))); };
PRIMITIVES["syntax-rules-match"] = syntaxRulesMatch;
// syntax-rules-match-list
var syntaxRulesMatchList = function(pattern, pi, form, fi, literals) { return (function() {
var plen = len(pattern);
var flen = len(form);
return (isSxTruthy((isSxTruthy((pi >= plen)) && (fi >= flen))) ? {} : (isSxTruthy((pi >= plen)) ? NIL : (isSxTruthy((isSxTruthy(((pi + 1) < plen)) && isSxTruthy(symbol_p(nth(pattern, (pi + 1)))) && sxEq(symbolName(nth(pattern, (pi + 1))), "..."))) ? (function() {
var subPat = nth(pattern, pi);
var restPatCount = (plen - (pi + 2));
var available = (flen - fi);
var nEllipsis = ((flen - fi) - (plen - (pi + 2)));
return (isSxTruthy((nEllipsis < 0)) ? NIL : (function() {
var ellipsisForms = slice(form, fi, (fi + nEllipsis));
var subBindings = map(function(f) { return syntaxRulesMatch(subPat, f, literals); }, slice(form, fi, (fi + nEllipsis)));
return (isSxTruthy(contains(subBindings, NIL)) ? NIL : (function() {
var restResult = syntaxRulesMatchList(pattern, (pi + 2), form, (fi + nEllipsis), literals);
return (isSxTruthy(isNil(restResult)) ? NIL : (function() {
var merged = {};
{ var _c = subBindings; for (var _i = 0; _i < _c.length; _i++) { var b = _c[_i]; { var _c = keys(b); for (var _i = 0; _i < _c.length; _i++) { var key = _c[_i]; (function() {
var existing = dictGet(merged, key);
return (isSxTruthy(isNil(existing)) ? dictSet(merged, key, [get(b, key)]) : dictSet(merged, key, append(existing, [get(b, key)])));
})(); } } } }
{ var _c = keys(restResult); for (var _i = 0; _i < _c.length; _i++) { var key = _c[_i]; merged[key] = get(restResult, key); } }
return merged;
})());
})());
})());
})() : (isSxTruthy((fi >= flen)) ? NIL : (function() {
var subResult = syntaxRulesMatch(nth(pattern, pi), nth(form, fi), literals);
return (isSxTruthy(isNil(subResult)) ? NIL : (function() {
var restResult = syntaxRulesMatchList(pattern, (pi + 1), form, (fi + 1), literals);
return (isSxTruthy(isNil(restResult)) ? NIL : (forEach(function(key) { return dictSet(restResult, key, get(subResult, key)); }, keys(subResult)), restResult));
})());
})()))));
})(); };
PRIMITIVES["syntax-rules-match-list"] = syntaxRulesMatchList;
// syntax-rules-find-var
var syntaxRulesFindVar = function(template, bindings) { return (isSxTruthy((isSxTruthy(symbol_p(template)) && isSxTruthy(dictHas(bindings, symbolName(template))) && isList(get(bindings, symbolName(template))))) ? symbolName(template) : (isSxTruthy(isList(template)) ? reduce(function(found, t) { return (isSxTruthy(isNil(found)) ? syntaxRulesFindVar(t, bindings) : found); }, NIL, template) : NIL)); };
PRIMITIVES["syntax-rules-find-var"] = syntaxRulesFindVar;
// syntax-rules-find-all-vars
var syntaxRulesFindAllVars = function(template, bindings) { return (isSxTruthy((isSxTruthy(symbol_p(template)) && isSxTruthy(dictHas(bindings, symbolName(template))) && isList(get(bindings, symbolName(template))))) ? [symbolName(template)] : (isSxTruthy(isList(template)) ? reduce(function(acc, t) { return append(acc, syntaxRulesFindAllVars(t, bindings)); }, [], template) : [])); };
PRIMITIVES["syntax-rules-find-all-vars"] = syntaxRulesFindAllVars;
// syntax-rules-instantiate
var syntaxRulesInstantiate = function(template, bindings) { return (isSxTruthy((isSxTruthy(symbol_p(template)) && dictHas(bindings, symbolName(template)))) ? get(bindings, symbolName(template)) : (isSxTruthy(!isSxTruthy(isList(template))) ? template : (isSxTruthy(isEmpty(template)) ? template : syntaxRulesInstantiateList(template, 0, bindings)))); };
PRIMITIVES["syntax-rules-instantiate"] = syntaxRulesInstantiate;
// syntax-rules-instantiate-list
var syntaxRulesInstantiateList = function(template, i, bindings) { return (isSxTruthy((i >= len(template))) ? [] : (function() {
var elem = nth(template, i);
var hasEllipsis = (isSxTruthy(((i + 1) < len(template))) && isSxTruthy(symbol_p(nth(template, (i + 1)))) && sxEq(symbolName(nth(template, (i + 1))), "..."));
return (isSxTruthy(hasEllipsis) ? (function() {
var allVars = syntaxRulesFindAllVars(elem, bindings);
return (isSxTruthy(isEmpty(allVars)) ? syntaxRulesInstantiateList(template, (i + 2), bindings) : (function() {
var count = len(get(bindings, first(allVars)));
var expanded = map(function(idx) { return (function() {
var b = {};
{ var _c = keys(bindings); for (var _i = 0; _i < _c.length; _i++) { var key = _c[_i]; b[key] = get(bindings, key); } }
{ var _c = allVars; for (var _i = 0; _i < _c.length; _i++) { var varName = _c[_i]; b[varName] = nth(get(bindings, varName), idx); } }
return syntaxRulesInstantiate(elem, b);
})(); }, range(count));
var restResult = syntaxRulesInstantiateList(template, (i + 2), bindings);
return append(expanded, restResult);
})());
})() : cons(syntaxRulesInstantiate(elem, bindings), syntaxRulesInstantiateList(template, (i + 1), bindings)));
})()); };
PRIMITIVES["syntax-rules-instantiate-list"] = syntaxRulesInstantiateList;
// syntax-rules-expand
var syntaxRulesExpand = function(literals, rules, form) { return (function() {
var fullForm = cons(makeSymbol("_"), form);
return syntaxRulesTryRules(literals, rules, fullForm);
})(); };
PRIMITIVES["syntax-rules-expand"] = syntaxRulesExpand;
// syntax-rules-try-rules
var syntaxRulesTryRules = function(literals, rules, fullForm) { return (isSxTruthy(isEmpty(rules)) ? error((String("syntax-rules: no pattern matched for ") + String(inspect(fullForm)))) : (function() {
var rule = first(rules);
var pattern = first(rule);
var template = nth(rule, 1);
return (function() {
var bindings = syntaxRulesMatch(pattern, fullForm, literals);
return (isSxTruthy(!isSxTruthy(isNil(bindings))) ? syntaxRulesInstantiate(template, bindings) : syntaxRulesTryRules(literals, rest(rules), fullForm));
})();
})()); };
PRIMITIVES["syntax-rules-try-rules"] = syntaxRulesTryRules;
// sf-syntax-rules
var sfSyntaxRules = function(args, env) { return (function() {
var literals = (isSxTruthy(isList(first(args))) ? map(function(s) { return (isSxTruthy(symbol_p(s)) ? symbolName(s) : (String(s))); }, first(args)) : []);
var rules = rest(args);
return (function() {
var closure = envExtend(env);
envBind(closure, "__sr-literals", literals);
envBind(closure, "__sr-rules", rules);
return makeMacro([], "__sr-form", new Symbol("__syntax-rules-body__"), closure, "syntax-rules");
})();
})(); };
PRIMITIVES["sf-syntax-rules"] = sfSyntaxRules;
// step-sf-define-library
var stepSfDefineLibrary = function(args, env, kont) { return (function() {
var libSpec = first(args);
var decls = rest(args);
return (function() {
var libEnv = envExtend(env);
var exports = [];
var bodyForms = [];
{ var _c = decls; for (var _i = 0; _i < _c.length; _i++) { var decl = _c[_i]; if (isSxTruthy((isSxTruthy(isList(decl)) && isSxTruthy(!isSxTruthy(isEmpty(decl))) && symbol_p(first(decl))))) {
(function() {
var kind = symbolName(first(decl));
return (isSxTruthy(sxEq(kind, "export")) ? (exports = append(exports, map(function(s) { return (isSxTruthy(symbol_p(s)) ? symbolName(s) : (String(s))); }, rest(decl)))) : (isSxTruthy(sxEq(kind, "begin")) ? (bodyForms = append(bodyForms, rest(decl))) : NIL));
})();
} } }
{ var _c = bodyForms; for (var _i = 0; _i < _c.length; _i++) { var form = _c[_i]; evalExpr(form, libEnv); } }
return (function() {
var exportDict = {};
{ var _c = exports; for (var _i = 0; _i < _c.length; _i++) { var name = _c[_i]; if (isSxTruthy(envHas(libEnv, name))) {
exportDict[name] = envGet(libEnv, name);
} } }
registerLibrary(libSpec, exportDict);
return makeCekValue(NIL, env, kont);
})();
})();
})(); };
PRIMITIVES["step-sf-define-library"] = stepSfDefineLibrary;
// bind-import-set
var bindImportSet = function(importSet, env) { return (function() {
var head = (isSxTruthy((isSxTruthy(isList(importSet)) && isSxTruthy(!isSxTruthy(isEmpty(importSet))) && symbol_p(first(importSet)))) ? symbolName(first(importSet)) : NIL);
return (function() {
var libSpec = (isSxTruthy(sxOr(sxEq(head, "only"), sxEq(head, "except"), sxEq(head, "prefix"), sxEq(head, "rename"))) ? nth(importSet, 1) : importSet);
return (function() {
var exports = libraryExports(libSpec);
return (isSxTruthy(sxEq(head, "only")) ? forEach(function(s) { return (function() {
var id = (isSxTruthy(symbol_p(s)) ? symbolName(s) : (String(s)));
return (isSxTruthy(dictHas(exports, id)) ? envBind(env, id, get(exports, id)) : NIL);
})(); }, rest(rest(importSet))) : (isSxTruthy(sxEq(head, "prefix")) ? (function() {
var pfx = (String(nth(importSet, 2)));
return forEach(function(key) { return envBind(env, (String(pfx) + String(key)), get(exports, key)); }, keys(exports));
})() : forEach(function(key) { return envBind(env, key, get(exports, key)); }, keys(exports))));
})();
})();
})(); };
PRIMITIVES["bind-import-set"] = bindImportSet;
// step-sf-import
var stepSfImport = function(args, env, kont) { return (isSxTruthy(isEmpty(args)) ? makeCekValue(NIL, env, kont) : (function() {
var importSet = first(args);
var restSets = rest(args);
return (function() {
var libSpec = (function() {
var head = (isSxTruthy((isSxTruthy(isList(importSet)) && isSxTruthy(!isSxTruthy(isEmpty(importSet))) && symbol_p(first(importSet)))) ? symbolName(first(importSet)) : NIL);
return (isSxTruthy(sxOr(sxEq(head, "only"), sxEq(head, "except"), sxEq(head, "prefix"), sxEq(head, "rename"))) ? nth(importSet, 1) : importSet);
})();
return (isSxTruthy(libraryLoaded_p(libSpec)) ? (bindImportSet(importSet, env), (isSxTruthy(isEmpty(restSets)) ? makeCekValue(NIL, env, kont) : stepSfImport(restSets, env, kont))) : makeCekSuspended({"library": libSpec, "op": "import"}, env, kontPush(makeImportFrame(importSet, restSets, env), kont)));
})();
})()); };
PRIMITIVES["step-sf-import"] = stepSfImport;
// step-sf-perform
var stepSfPerform = function(args, env, kont) { return (isSxTruthy(isEmpty(args)) ? error("perform requires an IO request argument") : makeCekState(first(args), env, kontPush(makePerformFrame(env), kont))); };
PRIMITIVES["step-sf-perform"] = stepSfPerform;
// *protocol-registry*
var _protocolRegistry_ = {};
PRIMITIVES["*protocol-registry*"] = _protocolRegistry_;
// sf-define-record-type
var sfDefineRecordType = function(args, env) { return (function() {
var typeSym = first(args);
var ctorSpec = nth(args, 1);
var predSym = nth(args, 2);
var fieldSpecs = slice(args, 3);
return (function() {
var rawName = symbolName(typeSym);
return (function() {
var typeName = (isSxTruthy((isSxTruthy(startsWith(rawName, "<")) && endsWith(rawName, ">"))) ? slice(rawName, 1, (len(rawName) - 1)) : rawName);
var ctorName = symbolName(first(ctorSpec));
var ctorParams = map(function(s) { return symbolName(s); }, rest(ctorSpec));
var predName = symbolName(predSym);
var fieldNames = map(function(fs) { return symbolName(first(fs)); }, fieldSpecs);
return (function() {
var rtdUid = makeRtd(typeName, fieldNames, ctorParams);
envBind(env, ctorName, makeRecordConstructor(rtdUid));
envBind(env, predName, makeRecordPredicate(rtdUid));
forEachIndexed(function(idx, fs) { return (function() {
var accessorName = symbolName(nth(fs, 1));
envBind(env, accessorName, makeRecordAccessor(idx));
return (isSxTruthy((len(fs) >= 3)) ? (function() {
var mutatorName = symbolName(nth(fs, 2));
return envBind(env, mutatorName, makeRecordMutator(idx));
})() : NIL);
})(); }, fieldSpecs);
return NIL;
})();
})();
})();
})(); };
PRIMITIVES["sf-define-record-type"] = sfDefineRecordType;
// sf-define-protocol
var sfDefineProtocol = function(args, env) { return (function() {
var protoName = symbolName(first(args));
var methodSpecs = rest(args);
envBind(env, "*protocol-registry*", _protocolRegistry_);
envBind(env, "satisfies?", function(pname, val) { return satisfies_p(pname, val); });
_protocolRegistry_[protoName] = {"impls": {}, "methods": map(function(spec) { return {"arity": len(spec), "name": symbolName(first(spec))}; }, methodSpecs), "name": protoName};
{ var _c = methodSpecs; for (var _i = 0; _i < _c.length; _i++) { var spec = _c[_i]; (function() {
var methodName = symbolName(first(spec));
var params = rest(spec);
var pname = protoName;
return (function() {
var selfSym = first(params);
var lookupExpr = [new Symbol("get"), [new Symbol("get"), [new Symbol("get"), [new Symbol("get"), new Symbol("*protocol-registry*"), pname], "impls"], [new Symbol("type-of"), selfSym]], methodName];
return envBind(env, methodName, evalExpr([new Symbol("fn"), params, [new Symbol("let"), [[new Symbol("_impl"), lookupExpr]], [new Symbol("if"), [new Symbol("nil?"), new Symbol("_impl")], [new Symbol("error"), (String(pname) + String(".") + String(methodName) + String(": not implemented for this type"))], cons(new Symbol("_impl"), params)]]], env));
})();
})(); } }
return NIL;
})(); };
PRIMITIVES["sf-define-protocol"] = sfDefineProtocol;
// check-match-exhaustiveness
var checkMatchExhaustiveness = function(clauses) { return (function() {
var warnings = [];
var patterns = map(first, clauses);
var hasWildcard = some(function(p) { return sxOr(sxEq(p, new Symbol("_")), (isSxTruthy(symbol_p(p)) && isSxTruthy(!isSxTruthy(sxEq(p, true))) && !isSxTruthy(sxEq(p, false)))); }, patterns);
var hasElse = some(function(p) { return sxEq(p, "else"); }, patterns);
var hasTrue = some(function(p) { return sxEq(p, true); }, patterns);
var hasFalse = some(function(p) { return sxEq(p, false); }, patterns);
var hasNil = some(function(p) { return sxEq(p, NIL); }, patterns);
var hasPredicate = some(function(p) { return (isSxTruthy(isList(p)) && sxEq(first(p), new Symbol("?"))); }, patterns);
if (isSxTruthy((isSxTruthy(!isSxTruthy(hasWildcard)) && !isSxTruthy(hasElse)))) {
warnings = append(warnings, ["match may be non-exhaustive (no wildcard or :else pattern)"]);
}
if (isSxTruthy((isSxTruthy(sxOr(hasTrue, hasFalse)) && isSxTruthy(!isSxTruthy((isSxTruthy(hasTrue) && hasFalse))) && isSxTruthy(!isSxTruthy(hasWildcard)) && !isSxTruthy(hasElse)))) {
warnings = append(warnings, [(isSxTruthy(hasTrue) ? "match on boolean missing false case" : "match on boolean missing true case")]);
}
if (isSxTruthy((isSxTruthy(hasNil) && isSxTruthy(!isSxTruthy(hasWildcard)) && isSxTruthy(!isSxTruthy(hasElse)) && sxEq(len(patterns), 1)))) {
warnings = append(warnings, ["match checks nil but has no non-nil pattern"]);
}
return warnings;
})(); };
PRIMITIVES["check-match-exhaustiveness"] = checkMatchExhaustiveness;
// sf-implement
var sfImplement = function(args, env) { return (function() {
var protoName = symbolName(first(args));
var rawTypeName = symbolName(nth(args, 1));
var typeName = slice(rawTypeName, 1, (len(rawTypeName) - 1));
var methodDefs = rest(rest(args));
return (function() {
var proto = get(_protocolRegistry_, protoName);
return (isSxTruthy(isNil(proto)) ? error((String("Unknown protocol: ") + String(protoName))) : (function() {
var impls = get(proto, "impls");
var typeImpls = sxOr(get(impls, typeName), {});
{ var _c = methodDefs; for (var _i = 0; _i < _c.length; _i++) { var methodDef = _c[_i]; (function() {
var mname = symbolName(first(methodDef));
var protoMethod = first(filter(function(m) { return sxEq(get(m, "name"), mname); }, get(proto, "methods")));
return (isSxTruthy(isNil(protoMethod)) ? error((String("Unknown method ") + String(mname) + String(" in protocol ") + String(protoName))) : (function() {
var arity = get(protoMethod, "arity");
var params = slice(methodDef, 1, arity);
var body = (isSxTruthy(sxEq(len(methodDef), (arity + 1))) ? nth(methodDef, arity) : cons(new Symbol("begin"), slice(methodDef, arity)));
return dictSet(typeImpls, mname, evalExpr([new Symbol("fn"), params, body], env));
})());
})(); } }
impls[typeName] = typeImpls;
return NIL;
})());
})();
})(); };
PRIMITIVES["sf-implement"] = sfImplement;
// satisfies?
var satisfies_p = function(protoName, value) { return (isSxTruthy(!isSxTruthy(record_p(value))) ? false : (function() {
var proto = get(_protocolRegistry_, (isSxTruthy(symbol_p(protoName)) ? symbolName(protoName) : protoName));
return (isSxTruthy(isNil(proto)) ? false : !isSxTruthy(isNil(get(get(proto, "impls"), typeOf(value)))));
})()); };
PRIMITIVES["satisfies?"] = satisfies_p;
// check-match-exhaustiveness
var checkMatchExhaustiveness = function(clauses) { return (function() {
var warnings = [];
var patterns = map(function(c) { return first(c); }, clauses);
var hasWildcard = some(function(p) { return (isSxTruthy(symbol_p(p)) && isSxTruthy(!isSxTruthy(sxEq(p, true))) && !isSxTruthy(sxEq(p, false))); }, patterns);
var hasElse = some(function(p) { return sxEq(p, "else"); }, patterns);
var hasTrue = some(function(p) { return sxEq(p, true); }, patterns);
var hasFalse = some(function(p) { return sxEq(p, false); }, patterns);
if (isSxTruthy((isSxTruthy(!isSxTruthy(hasWildcard)) && !isSxTruthy(hasElse)))) {
warnings = append(warnings, ["match may be non-exhaustive (no wildcard or :else pattern)"]);
}
if (isSxTruthy((isSxTruthy(sxOr(hasTrue, hasFalse)) && isSxTruthy(!isSxTruthy((isSxTruthy(hasTrue) && hasFalse))) && isSxTruthy(!isSxTruthy(hasWildcard)) && !isSxTruthy(hasElse)))) {
warnings = append(warnings, [(isSxTruthy(hasTrue) ? "match on boolean missing false case" : "match on boolean missing true case")]);
}
return warnings;
})(); };
PRIMITIVES["check-match-exhaustiveness"] = checkMatchExhaustiveness;
// match-find-clause
var matchFindClause = function(val, clauses, env) { return (isSxTruthy(isEmpty(clauses)) ? NIL : (function() {
var clause = first(clauses);
var pattern = first(clause);
var body = nth(clause, 1);
var local = envExtend(env);
return (isSxTruthy(matchPattern(pattern, val, local)) ? [local, body] : matchFindClause(val, rest(clauses), env));
})()); };
PRIMITIVES["match-find-clause"] = matchFindClause;
// match-pattern
var matchPattern = function(pattern, value, env) { return (isSxTruthy(sxEq(pattern, new Symbol("_"))) ? true : (isSxTruthy((isSxTruthy(isList(pattern)) && isSxTruthy(sxEq(len(pattern), 2)) && sxEq(first(pattern), new Symbol("?")))) ? (function() {
var pred = evalExpr(nth(pattern, 1), env);
return cekCall(pred, [value]);
})() : (isSxTruthy((isSxTruthy(isList(pattern)) && isSxTruthy(!isSxTruthy(isEmpty(pattern))) && sxEq(first(pattern), new Symbol("quote")))) ? sxEq(value, nth(pattern, 1)) : (isSxTruthy(symbol_p(pattern)) ? (envBind(env, symbolName(pattern), value), true) : (isSxTruthy((isSxTruthy(isDict(pattern)) && isDict(value))) ? isEvery(function(k) { return matchPattern(get(pattern, k), get(value, k), env); }, keys(pattern)) : (isSxTruthy((isSxTruthy(isList(pattern)) && isSxTruthy(isList(value)) && contains(pattern, new Symbol("&rest")))) ? (function() {
var restIdx = indexOf_(pattern, new Symbol("&rest"));
return (isSxTruthy((len(value) >= restIdx)) && isSxTruthy(isEvery(function(pair) { return matchPattern(first(pair), nth(pair, 1), env); }, zip(slice(pattern, 0, restIdx), slice(value, 0, restIdx)))) && (function() {
var restName = nth(pattern, (restIdx + 1));
envBind(env, symbolName(restName), slice(value, restIdx));
return true;
})());
})() : (isSxTruthy((isSxTruthy(isList(pattern)) && isList(value))) ? (isSxTruthy(!isSxTruthy(sxEq(len(pattern), len(value)))) ? false : (function() {
var pairs = zip(pattern, value);
return isEvery(function(pair) { return matchPattern(first(pair), nth(pair, 1), env); }, pairs);
})()) : sxEq(pattern, value)))))))); };
PRIMITIVES["match-pattern"] = matchPattern;
// step-sf-match
var stepSfMatch = function(args, env, kont) { return (function() {
var val = trampoline(evalExpr(first(args), env));
var clauses = rest(args);
return (function() {
var result = matchFindClause(val, clauses, env);
return (isSxTruthy(isNil(result)) ? error((String("match: no clause matched ") + String(inspect(val)))) : makeCekState(nth(result, 1), first(result), kont));
})();
})(); };
PRIMITIVES["step-sf-match"] = stepSfMatch;
// step-sf-handler-bind
var stepSfHandlerBind = function(args, env, kont) { return (function() {
var handlerSpecs = first(args);
var body = rest(args);
var handlers = map(function(spec) { return [trampoline(evalExpr(first(spec), env)), trampoline(evalExpr(nth(spec, 1), env))]; }, handlerSpecs);
return (isSxTruthy(isEmpty(body)) ? makeCekValue(NIL, env, kont) : makeCekState(first(body), env, kontPush(makeHandlerFrame(handlers, rest(body), env), kont)));
})(); };
PRIMITIVES["step-sf-handler-bind"] = stepSfHandlerBind;
// step-sf-restart-case
var stepSfRestartCase = function(args, env, kont) { return (function() {
var body = first(args);
var restartSpecs = rest(args);
var restarts = map(function(spec) { return [(isSxTruthy(symbol_p(first(spec))) ? symbolName(first(spec)) : first(spec)), nth(spec, 1), nth(spec, 2)]; }, restartSpecs);
return makeCekState(body, env, kontPush(makeRestartFrame(restarts, [], env), kont));
})(); };
PRIMITIVES["step-sf-restart-case"] = stepSfRestartCase;
// step-sf-signal
var stepSfSignal = function(args, env, kont) { return (function() {
var condition = trampoline(evalExpr(first(args), env));
var handlerFn = kontFindHandler(kont, condition);
return (isSxTruthy(isNil(handlerFn)) ? error((String("Unhandled condition: ") + String(inspect(condition)))) : continueWithCall(handlerFn, [condition], env, [condition], kontPush(makeSignalReturnFrame(env, kont), kont)));
})(); };
PRIMITIVES["step-sf-signal"] = stepSfSignal;
// step-sf-invoke-restart
var stepSfInvokeRestart = function(args, env, kont) { return (function() {
var restartName = (function() {
var rn = (isSxTruthy(symbol_p(first(args))) ? symbolName(first(args)) : trampoline(evalExpr(first(args), env)));
return (isSxTruthy(symbol_p(rn)) ? symbolName(rn) : rn);
})();
var restartArg = (isSxTruthy((len(args) >= 2)) ? trampoline(evalExpr(nth(args, 1), env)) : NIL);
var found = kontFindRestart(kont, restartName);
return (isSxTruthy(isNil(found)) ? error((String("No restart named: ") + String(inspect(restartName)))) : (function() {
var entry = first(found);
var restartFrame = nth(found, 1);
var restKont = nth(found, 2);
return (function() {
var params = nth(entry, 1);
var body = nth(entry, 2);
var restartEnv = envExtend(get(restartFrame, "env"));
if (isSxTruthy(!isSxTruthy(isEmpty(params)))) {
envBind(restartEnv, first(params), restartArg);
}
return makeCekState(body, restartEnv, restKont);
})();
})());
})(); };
PRIMITIVES["step-sf-invoke-restart"] = stepSfInvokeRestart;
// 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)); };
PRIMITIVES["step-sf-if"] = stepSfIf;
// step-sf-when
var stepSfWhen = function(args, env, kont) { return makeCekState(first(args), env, kontPush(makeWhenFrame(rest(args), env), kont)); };
PRIMITIVES["step-sf-when"] = stepSfWhen;
// step-sf-begin
var stepSfBegin = function(args, env, kont) { return (isSxTruthy(isEmpty(args)) ? makeCekValue(NIL, env, kont) : (isSxTruthy(sxEq(len(args), 1)) ? makeCekState(first(args), env, kont) : makeCekState(first(args), env, kontPush(makeBeginFrame(rest(args), env), kont)))); };
PRIMITIVES["step-sf-begin"] = stepSfBegin;
// step-sf-let
var stepSfLet = function(args, env, kont) { return (isSxTruthy(sxEq(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(sxEq(typeOf(first(bindings)), "list")) && sxEq(len(first(bindings)), 2))) ? first(bindings) : [first(bindings), nth(bindings, 1)]);
var restBindings = (isSxTruthy((isSxTruthy(sxEq(typeOf(first(bindings)), "list")) && sxEq(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(sxEq(typeOf(first(firstBinding)), "symbol")) ? symbolName(first(firstBinding)) : first(firstBinding));
return makeCekState(nth(firstBinding, 1), local, kontPush(makeLetFrame(vname, restBindings, body, local), kont));
})();
})());
})()); };
PRIMITIVES["step-sf-let"] = stepSfLet;
// step-sf-define
var stepSfDefine = function(args, env, kont) { return (function() {
var nameSym = first(args);
var hasEffects = (isSxTruthy((len(args) >= 4)) && isSxTruthy(sxEq(typeOf(nth(args, 1)), "keyword")) && sxEq(keywordName(nth(args, 1)), "effects"));
var valIdx = (isSxTruthy((isSxTruthy((len(args) >= 4)) && isSxTruthy(sxEq(typeOf(nth(args, 1)), "keyword")) && sxEq(keywordName(nth(args, 1)), "effects"))) ? 3 : 1);
var effectList = (isSxTruthy((isSxTruthy((len(args) >= 4)) && isSxTruthy(sxEq(typeOf(nth(args, 1)), "keyword")) && sxEq(keywordName(nth(args, 1)), "effects"))) ? nth(args, 2) : NIL);
return makeCekState(nth(args, valIdx), env, kontPush(makeDefineFrame(symbolName(nameSym), env, hasEffects, effectList), kont));
})(); };
PRIMITIVES["step-sf-define"] = stepSfDefine;
// step-sf-set!
var stepSfSet = function(args, env, kont) { return makeCekState(nth(args, 1), env, kontPush(makeSetFrame(symbolName(first(args)), env), kont)); };
PRIMITIVES["step-sf-set!"] = stepSfSet;
// 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))); };
PRIMITIVES["step-sf-and"] = stepSfAnd;
// 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))); };
PRIMITIVES["step-sf-or"] = stepSfOr;
// 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(isElseClause(test)) ? 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(isElseClause(test)) ? makeCekState(nth(args, 1), env, kont) : makeCekState(test, env, kontPush(makeCondFrame(args, env, false), kont)));
})()));
})(); };
PRIMITIVES["step-sf-cond"] = stepSfCond;
// step-sf-thread-first
var stepSfThreadFirst = function(args, env, kont) { return makeCekState(first(args), env, kontPush(makeThreadFrame(rest(args), env, "first", NIL), kont)); };
PRIMITIVES["step-sf-thread-first"] = stepSfThreadFirst;
// step-sf-thread-last
var stepSfThreadLast = function(args, env, kont) { return makeCekState(first(args), env, kontPush(makeThreadFrame(rest(args), env, "last", NIL), kont)); };
PRIMITIVES["step-sf-thread-last"] = stepSfThreadLast;
// step-sf-thread-as
var stepSfThreadAs = function(args, env, kont) { return (function() {
var init = first(args);
var name = nth(args, 1);
var forms = rest(rest(args));
return makeCekState(init, env, kontPush(makeThreadFrame(forms, env, "as", name), kont));
})(); };
PRIMITIVES["step-sf-thread-as"] = stepSfThreadAs;
// step-sf-lambda
var stepSfLambda = function(args, env, kont) { return makeCekValue(sfLambda(args, env), env, kont); };
PRIMITIVES["step-sf-lambda"] = stepSfLambda;
// step-sf-scope
var stepSfScope = function(args, env, kont) { return (function() {
var name = trampoline(evalExpr(first(args), env));
var restArgs = slice(args, 1);
var val = NIL;
var body = NIL;
(isSxTruthy((isSxTruthy((len(restArgs) >= 2)) && isSxTruthy(sxEq(typeOf(first(restArgs)), "keyword")) && sxEq(keywordName(first(restArgs)), "value"))) ? ((val = trampoline(evalExpr(nth(restArgs, 1), env))), (body = slice(restArgs, 2))) : (body = restArgs));
return (isSxTruthy(isEmpty(body)) ? makeCekValue(NIL, env, kont) : makeCekState(first(body), env, kontPush(makeScopeAccFrame(name, val, rest(body), env), kont)));
})(); };
PRIMITIVES["step-sf-scope"] = stepSfScope;
// step-sf-provide
var stepSfProvide = function(args, env, kont) { return (function() {
var name = trampoline(evalExpr(first(args), env));
var val = trampoline(evalExpr(nth(args, 1), env));
var body = slice(args, 2);
scopePush(name, val);
return (isSxTruthy(isEmpty(body)) ? (scopePop(name), makeCekValue(NIL, env, kont)) : makeCekState(first(body), env, kontPush(makeProvideFrame(name, val, rest(body), env), kont)));
})(); };
PRIMITIVES["step-sf-provide"] = stepSfProvide;
// step-sf-context
var stepSfContext = function(args, env, kont) { return (function() {
var name = trampoline(evalExpr(first(args), env));
var defaultVal = (isSxTruthy((len(args) >= 2)) ? trampoline(evalExpr(nth(args, 1), env)) : NIL);
var frame = kontFindProvide(kont, name);
if (isSxTruthy(_bindTracking_)) {
if (isSxTruthy(!isSxTruthy(contains(_bindTracking_, name)))) {
_bindTracking_.push(name);
}
}
return makeCekValue((isSxTruthy(frame) ? get(frame, "value") : (function() {
var sv = scopePeek(name);
return (isSxTruthy(isNil(sv)) ? defaultVal : sv);
})()), env, kont);
})(); };
PRIMITIVES["step-sf-context"] = stepSfContext;
// step-sf-peek
var stepSfPeek = function(args, env, kont) { return (function() {
var name = trampoline(evalExpr(first(args), env));
var defaultVal = (isSxTruthy((len(args) >= 2)) ? trampoline(evalExpr(nth(args, 1), env)) : NIL);
var frame = kontFindProvide(kont, name);
return makeCekValue((isSxTruthy(frame) ? get(frame, "value") : (isSxTruthy(envHas(env, "peek")) ? apply(envGet(env, "peek"), [name, defaultVal]) : defaultVal)), env, kont);
})(); };
PRIMITIVES["step-sf-peek"] = stepSfPeek;
// step-sf-provide!
var stepSfProvide_b = function(args, env, kont) { return (function() {
var name = trampoline(evalExpr(first(args), env));
return makeCekState(nth(args, 1), env, kontPush(makeProvideSetFrame(name, env), kont));
})(); };
PRIMITIVES["step-sf-provide!"] = stepSfProvide_b;
// step-sf-emit
var stepSfEmit = function(args, env, kont) { return (function() {
var name = trampoline(evalExpr(first(args), env));
var val = trampoline(evalExpr(nth(args, 1), env));
var frame = kontFindScopeAcc(kont, name);
return (isSxTruthy(frame) ? (dictSet(frame, "emitted", append(get(frame, "emitted"), [val])), makeCekValue(NIL, env, kont)) : ((isSxTruthy(envHas(env, "scope-emit!")) ? apply(envGet(env, "scope-emit!"), [name, val]) : NIL), makeCekValue(NIL, env, kont)));
})(); };
PRIMITIVES["step-sf-emit"] = stepSfEmit;
// step-sf-emitted
var stepSfEmitted = function(args, env, kont) { return (function() {
var name = trampoline(evalExpr(first(args), env));
var frame = kontFindScopeAcc(kont, name);
return makeCekValue((isSxTruthy(frame) ? get(frame, "emitted") : (isSxTruthy(envHas(env, "emitted")) ? apply(envGet(env, "emitted"), [name]) : [])), env, kont);
})(); };
PRIMITIVES["step-sf-emitted"] = stepSfEmitted;
// step-sf-reset
var stepSfReset = function(args, env, kont) { return makeCekState(first(args), env, kontPush(makeResetFrame(env), kont)); };
PRIMITIVES["step-sf-reset"] = stepSfReset;
// 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);
envBind(shiftEnv, kName, k);
return makeCekState(body, shiftEnv, restKont);
})();
})();
})(); };
PRIMITIVES["step-sf-shift"] = stepSfShift;
// step-sf-deref
var stepSfDeref = function(args, env, kont) { return makeCekState(first(args), env, kontPush(makeDerefFrame(env), kont)); };
PRIMITIVES["step-sf-deref"] = stepSfDeref;
// cek-call
var cekCall = function(f, args) { return (function() {
var a = (isSxTruthy(isNil(args)) ? [] : args);
return (isSxTruthy(isNil(f)) ? NIL : (isSxTruthy(sxOr(isLambda(f), isCallable(f))) ? cekRun(continueWithCall(f, a, makeEnv(), a, [])) : NIL));
})(); };
PRIMITIVES["cek-call"] = cekCall;
// 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]; cekCall(d, NIL); } }
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 cekCall(d, NIL); }, subDisposers); });
return (function() {
var initialKont = concat(capturedFrames, [resetFrame], remainingKont);
return makeCekValue(signalValue(sig), env, initialKont);
})();
})();
})();
})(); };
PRIMITIVES["reactive-shift-deref"] = reactiveShiftDeref;
// step-eval-call
var stepEvalCall = function(head, args, env, kont) { return (function() {
var hname = (isSxTruthy(sxEq(typeOf(head), "symbol")) ? symbolName(head) : NIL);
return makeCekState(head, env, kontPush(makeArgFrame(NIL, [], args, env, args, hname), kont));
})(); };
PRIMITIVES["step-eval-call"] = stepEvalCall;
// ho-form-name?
var hoFormName_p = function(name) { return sxOr(sxEq(name, "map"), sxEq(name, "map-indexed"), sxEq(name, "filter"), sxEq(name, "reduce"), sxEq(name, "some"), sxEq(name, "every?"), sxEq(name, "for-each")); };
PRIMITIVES["ho-form-name?"] = hoFormName_p;
// ho-fn?
var hoFn_p = function(v) { return sxOr(isCallable(v), isLambda(v)); };
PRIMITIVES["ho-fn?"] = hoFn_p;
// ho-swap-args
var hoSwapArgs = function(hoType, evaled) { return (isSxTruthy(sxEq(hoType, "reduce")) ? (function() {
var a = first(evaled);
var b = nth(evaled, 1);
return (isSxTruthy((isSxTruthy(!isSxTruthy(hoFn_p(a))) && hoFn_p(b))) ? [b, nth(evaled, 2), a] : evaled);
})() : (function() {
var a = first(evaled);
var b = nth(evaled, 1);
return (isSxTruthy((isSxTruthy(!isSxTruthy(hoFn_p(a))) && hoFn_p(b))) ? [b, a] : evaled);
})()); };
PRIMITIVES["ho-swap-args"] = hoSwapArgs;
// ho-setup-dispatch
var hoSetupDispatch = function(hoType, evaled, env, kont) { return (function() {
var ordered = hoSwapArgs(hoType, evaled);
return (function() {
var f = first(ordered);
return (function() { var _m = hoType; if (_m == "map") return (isSxTruthy((len(ordered) > 2)) ? (function() {
var colls = rest(ordered);
return (isSxTruthy(some(function(c) { return isEmpty(c); }, colls)) ? makeCekValue([], env, kont) : (function() {
var heads = map(function(c) { return first(c); }, colls);
var tails = map(function(c) { return rest(c); }, colls);
return continueWithCall(f, heads, env, [], kontPush(makeMultiMapFrame(f, tails, [], env), kont));
})());
})() : (function() {
var coll = nth(ordered, 1);
return (isSxTruthy(isEmpty(coll)) ? makeCekValue([], env, kont) : continueWithCall(f, [first(coll)], env, [], kontPush(makeMapFrame(f, rest(coll), [], env), kont)));
})()); if (_m == "map-indexed") return (function() {
var coll = nth(ordered, 1);
return (isSxTruthy(isEmpty(coll)) ? makeCekValue([], env, kont) : continueWithCall(f, [0, first(coll)], env, [], kontPush(makeMapIndexedFrame(f, rest(coll), [], env), kont)));
})(); if (_m == "filter") return (function() {
var coll = nth(ordered, 1);
return (isSxTruthy(isEmpty(coll)) ? makeCekValue([], env, kont) : continueWithCall(f, [first(coll)], env, [], kontPush(makeFilterFrame(f, rest(coll), [], first(coll), env), kont)));
})(); if (_m == "reduce") return (function() {
var init = nth(ordered, 1);
var coll = nth(ordered, 2);
return (isSxTruthy(isEmpty(coll)) ? makeCekValue(init, env, kont) : continueWithCall(f, [init, first(coll)], env, [], kontPush(makeReduceFrame(f, rest(coll), env), kont)));
})(); if (_m == "some") return (function() {
var coll = nth(ordered, 1);
return (isSxTruthy(isEmpty(coll)) ? makeCekValue(false, env, kont) : continueWithCall(f, [first(coll)], env, [], kontPush(makeSomeFrame(f, rest(coll), env), kont)));
})(); if (_m == "every") return (function() {
var coll = nth(ordered, 1);
return (isSxTruthy(isEmpty(coll)) ? makeCekValue(true, env, kont) : continueWithCall(f, [first(coll)], env, [], kontPush(makeEveryFrame(f, rest(coll), env), kont)));
})(); if (_m == "for-each") return (function() {
var coll = nth(ordered, 1);
return (isSxTruthy(isEmpty(coll)) ? makeCekValue(NIL, env, kont) : continueWithCall(f, [first(coll)], env, [], kontPush(makeForEachFrame(f, rest(coll), env), kont)));
})(); return 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 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 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 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 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 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 makeCekState(first(args), env, kontPush(makeHoSetupFrame("for-each", rest(args), [], env), kont)); };
PRIMITIVES["step-ho-for-each"] = stepHoForEach;
// 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 (function() { var _m = ft; if (_m == "if") return (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))); if (_m == "when") return (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(sxEq(len(body), 1)) ? makeCekState(first(body), fenv, restK) : makeCekState(first(body), fenv, kontPush(makeBeginFrame(rest(body), fenv), restK))));
})() : makeCekValue(NIL, env, restK)); if (_m == "begin") return (function() {
var remaining = get(frame, "remaining");
var fenv = get(frame, "env");
return (isSxTruthy(isEmpty(remaining)) ? makeCekValue(value, fenv, restK) : (isSxTruthy(sxEq(len(remaining), 1)) ? makeCekState(first(remaining), fenv, restK) : makeCekState(first(remaining), fenv, kontPush(makeBeginFrame(rest(remaining), fenv), restK))));
})(); if (_m == "let") return (function() {
var name = get(frame, "name");
var remaining = get(frame, "remaining");
var body = get(frame, "body");
var local = get(frame, "env");
envBind(local, name, value);
return (isSxTruthy(isEmpty(remaining)) ? stepSfBegin(body, local, restK) : (function() {
var nextBinding = first(remaining);
var vname = (isSxTruthy(sxEq(typeOf(first(nextBinding)), "symbol")) ? symbolName(first(nextBinding)) : first(nextBinding));
return makeCekState(nth(nextBinding, 1), local, kontPush(makeLetFrame(vname, rest(remaining), body, local), restK));
})());
})(); if (_m == "define") return (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;
}
envBind(fenv, name, value);
if (isSxTruthy(hasEffects)) {
(function() {
var effectNames = map(function(e) { return (isSxTruthy(sxEq(typeOf(e), "symbol")) ? symbolName(e) : e); }, effectList);
var effectAnns = (isSxTruthy(envHas(fenv, "*effect-annotations*")) ? envGet(fenv, "*effect-annotations*") : {});
effectAnns[name] = effectNames;
return envBind(fenv, "*effect-annotations*", effectAnns);
})();
}
return makeCekValue(value, fenv, restK);
})(); if (_m == "set") return (function() {
var name = get(frame, "name");
var fenv = get(frame, "env");
envSet(fenv, name, value);
return makeCekValue(value, env, restK);
})(); if (_m == "and") return (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(sxEq(len(remaining), 1)) ? restK : kontPush(makeAndFrame(rest(remaining), get(frame, "env")), restK))));
})()); if (_m == "or") return (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(sxEq(len(remaining), 1)) ? restK : kontPush(makeOrFrame(rest(remaining), get(frame, "env")), restK))));
})()); if (_m == "cond") return (function() {
var remaining = get(frame, "remaining");
var fenv = get(frame, "env");
var scheme_p = get(frame, "scheme");
return (isSxTruthy(scheme_p) ? (isSxTruthy(value) ? (function() {
var clause = first(remaining);
return (isSxTruthy((isSxTruthy((len(clause) > 2)) && isSxTruthy(sxEq(typeOf(nth(clause, 1)), "symbol")) && sxEq(symbolName(nth(clause, 1)), "=>"))) ? makeCekState(nth(clause, 2), fenv, kontPush(makeCondArrowFrame(value, fenv), restK)) : makeCekState(nth(clause, 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(isElseClause(nextTest)) ? 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, len(remaining));
return (isSxTruthy((len(next) < 2)) ? makeCekValue(NIL, fenv, restK) : (function() {
var nextTest = first(next);
return (isSxTruthy(isElseClause(nextTest)) ? makeCekState(nth(next, 1), fenv, restK) : makeCekState(nextTest, fenv, kontPush(makeCondFrame(next, fenv, false), restK)));
})());
})()));
})(); if (_m == "case") return (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));
})(); if (_m == "thread") return (function() {
var remaining = get(frame, "remaining");
var fenv = get(frame, "env");
var mode = get(frame, "extra");
var bindName = get(frame, "name");
return (isSxTruthy(isEmpty(remaining)) ? makeCekValue(value, fenv, restK) : (function() {
var form = first(remaining);
var restForms = rest(remaining);
var newKont = (isSxTruthy(isEmpty(rest(remaining))) ? restK : kontPush(makeThreadFrame(rest(remaining), fenv, mode, bindName), restK));
return (isSxTruthy(sxEq(mode, "as")) ? (function() {
var newEnv = envExtend(fenv);
envBind(newEnv, symbolName(bindName), value);
return makeCekState(form, newEnv, newKont);
})() : (isSxTruthy((isSxTruthy(sxEq(typeOf(form), "list")) && isSxTruthy(!isSxTruthy(isEmpty(form))) && isSxTruthy(sxEq(typeOf(first(form)), "symbol")) && hoFormName_p(symbolName(first(form))))) ? makeCekState(cons(first(form), cons([new Symbol("quote"), value], rest(form))), fenv, newKont) : (isSxTruthy(sxEq(mode, "last")) ? (function() {
var result = threadInsertArgLast(form, value, fenv);
return (isSxTruthy(isEmpty(restForms)) ? makeCekValue(result, fenv, restK) : makeCekValue(result, fenv, kontPush(makeThreadFrame(restForms, fenv, mode, bindName), restK)));
})() : (function() {
var result = threadInsertArg(form, value, fenv);
return (isSxTruthy(isEmpty(restForms)) ? makeCekValue(result, fenv, restK) : makeCekValue(result, fenv, kontPush(makeThreadFrame(restForms, fenv, mode, bindName), restK)));
})())));
})());
})(); if (_m == "arg") return (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");
var hname = get(frame, "head-name");
return (isSxTruthy(isNil(f)) ? ((isSxTruthy((isSxTruthy(_strict_) && hname)) ? strictCheckArgs(hname, []) : NIL), (isSxTruthy(isEmpty(remaining)) ? continueWithCall(value, [], fenv, rawArgs, restK) : makeCekState(first(remaining), fenv, kontPush(makeArgFrame(value, [], rest(remaining), fenv, rawArgs, hname), restK)))) : (function() {
var newEvaled = append(evaled, [value]);
return (isSxTruthy(isEmpty(remaining)) ? ((isSxTruthy((isSxTruthy(_strict_) && hname)) ? strictCheckArgs(hname, newEvaled) : NIL), continueWithCall(f, newEvaled, fenv, rawArgs, restK)) : makeCekState(first(remaining), fenv, kontPush(makeArgFrame(f, newEvaled, rest(remaining), fenv, rawArgs, hname), restK)));
})());
})(); if (_m == "dict") return (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));
})());
})();
})(); if (_m == "ho-setup") return (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)));
})(); if (_m == "reset") return makeCekValue(value, env, restK); if (_m == "deref") return (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))));
})(); if (_m == "reactive-reset") return (function() {
var updateFn = get(frame, "update-fn");
var first_p = get(frame, "first-render");
if (isSxTruthy((isSxTruthy(updateFn) && !isSxTruthy(first_p)))) {
cekCall(updateFn, [value]);
}
return makeCekValue(value, env, restK);
})(); if (_m == "scope") return (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)));
})(); if (_m == "provide") return (function() {
var remaining = get(frame, "remaining");
var fenv = get(frame, "env");
return (isSxTruthy(isEmpty(remaining)) ? (scopePop(get(frame, "name")), makeCekValue(value, fenv, restK)) : (function() {
var newFrame = makeProvideFrame(get(frame, "name"), get(frame, "value"), rest(remaining), fenv);
newFrame["subscribers"] = get(frame, "subscribers");
return makeCekState(first(remaining), fenv, kontPush(newFrame, restK));
})());
})(); if (_m == "bind") return (function() {
var tracked = _bindTracking_;
var body = get(frame, "body");
var fenv = get(frame, "env");
var prev = get(frame, "prev-tracking");
_bindTracking_ = prev;
(function() {
var subscriber = function(fireKont) { return cekRun(makeCekState(body, fenv, [])); };
return forEach(function(name) { return (function() {
var pf = kontFindProvide(restK, name);
return (isSxTruthy(pf) ? dictSet(pf, "subscribers", append(get(pf, "subscribers"), [subscriber])) : NIL);
})(); }, tracked);
})();
return makeCekValue(value, fenv, restK);
})(); if (_m == "provide-set") return (function() {
var name = get(frame, "name");
var fenv = get(frame, "env");
var target = kontFindProvide(restK, name);
return (isSxTruthy(target) ? (function() {
var oldVal = get(target, "value");
target["value"] = value;
scopePop(name);
scopePush(name, value);
if (isSxTruthy(!isSxTruthy(sxEq(oldVal, value)))) {
fireProvideSubscribers(target, restK);
}
return makeCekValue(value, fenv, restK);
})() : (isSxTruthy(envHas(fenv, "provide-set!")) ? (apply(envGet(fenv, "provide-set!"), [name, value]), makeCekValue(value, fenv, restK)) : makeCekValue(NIL, fenv, restK)));
})(); if (_m == "scope-acc") return (function() {
var remaining = get(frame, "remaining");
var fenv = get(frame, "env");
return (isSxTruthy(isEmpty(remaining)) ? makeCekValue(value, fenv, restK) : makeCekState(first(remaining), fenv, kontPush((function() {
var newFrame = makeScopeAccFrame(get(frame, "name"), get(frame, "value"), rest(remaining), fenv);
newFrame["emitted"] = get(frame, "emitted");
return newFrame;
})(), restK)));
})(); if (_m == "map") return (function() {
var f = get(frame, "f");
var remaining = get(frame, "remaining");
var results = get(frame, "results");
var indexed = get(frame, "indexed");
var fenv = get(frame, "env");
return (function() {
var newResults = append(results, [value]);
return (isSxTruthy(isEmpty(remaining)) ? makeCekValue(newResults, fenv, restK) : (function() {
var callArgs = (isSxTruthy(indexed) ? [len(newResults), first(remaining)] : [first(remaining)]);
var nextFrame = (isSxTruthy(indexed) ? makeMapIndexedFrame(f, rest(remaining), newResults, fenv) : makeMapFrame(f, rest(remaining), newResults, fenv));
return continueWithCall(f, callArgs, fenv, [], kontPush(nextFrame, restK));
})());
})();
})(); if (_m == "filter") return (function() {
var f = get(frame, "f");
var remaining = get(frame, "remaining");
var results = get(frame, "results");
var currentItem = get(frame, "current-item");
var fenv = get(frame, "env");
return (function() {
var newResults = (isSxTruthy(value) ? append(results, [currentItem]) : results);
return (isSxTruthy(isEmpty(remaining)) ? makeCekValue(newResults, fenv, restK) : continueWithCall(f, [first(remaining)], fenv, [], kontPush(makeFilterFrame(f, rest(remaining), newResults, first(remaining), fenv), restK)));
})();
})(); if (_m == "reduce") return (function() {
var f = get(frame, "f");
var remaining = get(frame, "remaining");
var fenv = get(frame, "env");
return (isSxTruthy(isEmpty(remaining)) ? makeCekValue(value, fenv, restK) : continueWithCall(f, [value, first(remaining)], fenv, [], kontPush(makeReduceFrame(f, rest(remaining), fenv), restK)));
})(); if (_m == "for-each") return (function() {
var f = get(frame, "f");
var remaining = get(frame, "remaining");
var fenv = get(frame, "env");
return (isSxTruthy(isEmpty(remaining)) ? makeCekValue(NIL, fenv, restK) : continueWithCall(f, [first(remaining)], fenv, [], kontPush(makeForEachFrame(f, rest(remaining), fenv), restK)));
})(); if (_m == "some") return (function() {
var f = get(frame, "f");
var remaining = get(frame, "remaining");
var fenv = get(frame, "env");
return (isSxTruthy(value) ? makeCekValue(value, fenv, restK) : (isSxTruthy(isEmpty(remaining)) ? makeCekValue(false, fenv, restK) : continueWithCall(f, [first(remaining)], fenv, [], kontPush(makeSomeFrame(f, rest(remaining), fenv), restK))));
})(); if (_m == "every") return (function() {
var f = get(frame, "f");
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))));
})(); if (_m == "handler") return (function() {
var remaining = get(frame, "remaining");
var fenv = get(frame, "env");
return (isSxTruthy(isEmpty(remaining)) ? makeCekValue(value, fenv, restK) : makeCekState(first(remaining), fenv, kontPush(makeHandlerFrame(get(frame, "f"), rest(remaining), fenv), restK)));
})(); if (_m == "restart") return makeCekValue(value, env, restK); if (_m == "signal-return") return (function() {
var savedKont = get(frame, "saved-kont");
return makeCekValue(value, get(frame, "env"), savedKont);
})(); if (_m == "comp-trace") return makeCekValue(value, env, restK); if (_m == "cond-arrow") return (function() {
var testValue = get(frame, "match-val");
var fenv = get(frame, "env");
return continueWithCall(value, [testValue], fenv, [testValue], restK);
})(); if (_m == "raise-eval") return (function() {
var condition = value;
var fenv = get(frame, "env");
var continuable_p = get(frame, "scheme");
var handlerFn = kontFindHandler(restK, condition);
return (isSxTruthy(isNil(handlerFn)) ? ((_lastErrorKont_ = restK), hostError((String("Unhandled exception: ") + String(inspect(condition))))) : continueWithCall(handlerFn, [condition], fenv, [condition], (isSxTruthy(continuable_p) ? kontPush(makeSignalReturnFrame(fenv, restK), restK) : kontPush(makeRaiseGuardFrame(fenv, restK), restK))));
})(); if (_m == "raise-guard") return ((_lastErrorKont_ = restK), hostError("exception handler returned from non-continuable raise")); if (_m == "multi-map") return (function() {
var f = get(frame, "f");
var remaining = get(frame, "remaining");
var newResults = append(get(frame, "results"), [value]);
var fenv = get(frame, "env");
return (isSxTruthy(some(function(c) { return isEmpty(c); }, remaining)) ? makeCekValue(newResults, fenv, restK) : (function() {
var heads = map(function(c) { return first(c); }, remaining);
var tails = map(function(c) { return rest(c); }, remaining);
return continueWithCall(f, heads, fenv, [], kontPush(makeMultiMapFrame(f, tails, newResults, fenv), restK));
})());
})(); if (_m == "callcc") return (function() {
var k = makeCallccContinuation(restK);
return continueWithCall(value, [k], get(frame, "env"), [k], restK);
})(); if (_m == "vm-resume") return (function() {
var resumeFn = get(frame, "f");
return (function() {
var result = apply(resumeFn, [value]);
return (isSxTruthy((isSxTruthy(isDict(result)) && get(result, "__vm_suspended"))) ? makeCekSuspended(get(result, "request"), get(frame, "env"), kontPush(makeVmResumeFrame(get(result, "resume"), get(frame, "env")), restK)) : makeCekValue(result, get(frame, "env"), restK));
})();
})(); if (_m == "perform") return makeCekSuspended(value, get(frame, "env"), restK); if (_m == "import") return (function() {
var importSet = get(frame, "args");
var remainingSets = get(frame, "remaining");
var fenv = get(frame, "env");
return (bindImportSet(importSet, fenv), (isSxTruthy(isEmpty(remainingSets)) ? makeCekValue(NIL, fenv, restK) : stepSfImport(remainingSets, fenv, restK)));
})(); if (_m == "parameterize") return (function() {
var remaining = get(frame, "remaining");
var currentParam = get(frame, "f");
var results = get(frame, "results");
var body = get(frame, "body");
var fenv = get(frame, "env");
return (isSxTruthy(isNil(currentParam)) ? (function() {
var paramObj = value;
var valExpr = nth(first(remaining), 1);
return makeCekState(valExpr, fenv, kontPush(makeParameterizeFrame(remaining, paramObj, results, body, fenv), restK));
})() : (function() {
var convertedVal = value;
var newResults = append(results, [[parameterUid(currentParam), convertedVal]]);
var restBindings = rest(remaining);
return (isSxTruthy(isEmpty(restBindings)) ? (function() {
var bodyExpr = (isSxTruthy(sxEq(len(body), 1)) ? first(body) : cons(new Symbol("begin"), body));
var provideKont = kontPushProvides(newResults, fenv, restK);
return makeCekState(bodyExpr, fenv, provideKont);
})() : makeCekState(first(first(restBindings)), fenv, kontPush(makeParameterizeFrame(restBindings, NIL, newResults, body, fenv), restK)));
})());
})(); return ((_lastErrorKont_ = restK), error((String("Unknown frame type: ") + String(ft)))); })();
})());
})(); };
PRIMITIVES["step-continue"] = stepContinue;
// continue-with-call
var continueWithCall = function(f, args, env, rawArgs, kont) { return (isSxTruthy(parameter_p(f)) ? (function() {
var uid = parameterUid(f);
var frame = kontFindProvide(kont, uid);
return makeCekValue((isSxTruthy(frame) ? get(frame, "value") : parameterDefault(f)), env, kont);
})() : (isSxTruthy(callccContinuation_p(f)) ? (function() {
var arg = (isSxTruthy(isEmpty(args)) ? NIL : first(args));
var captured = callccContinuationData(f);
return makeCekValue(arg, env, captured);
})() : (isSxTruthy(continuation_p(f)) ? (function() {
var arg = (isSxTruthy(isEmpty(args)) ? NIL : first(args));
var contData = continuationData(f);
return (function() {
var captured = get(contData, "captured");
return (function() {
var result = cekRun(makeCekValue(arg, env, captured));
return makeCekValue(result, env, kont);
})();
})();
})() : (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);
if (isSxTruthy(!isSxTruthy(bindLambdaParams(params, args, local)))) {
if (isSxTruthy((len(args) > len(params)))) {
error((String(sxOr(lambdaName(f), "lambda")) + String(" expects ") + String(len(params)) + String(" args, got ") + String(len(args))));
}
{ var _c = zip(params, args); for (var _i = 0; _i < _c.length; _i++) { var pair = _c[_i]; envBind(local, first(pair), nth(pair, 1)); } }
{ var _c = slice(params, len(args)); for (var _i = 0; _i < _c.length; _i++) { var p = _c[_i]; envBind(local, p, NIL); } }
}
return (function() {
var jitResult = jitTryCall(f, args);
return (isSxTruthy(isNil(jitResult)) ? makeCekState(lambdaBody(f), local, kont) : (isSxTruthy((isSxTruthy(isDict(jitResult)) && get(jitResult, "__vm_suspended"))) ? makeCekSuspended(get(jitResult, "request"), env, kontPush(makeVmResumeFrame(get(jitResult, "resume"), env), kont)) : makeCekValue(jitResult, 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]; envBind(local, p, sxOr(dictGet(kwargs, p), NIL)); } }
if (isSxTruthy(componentHasChildren(f))) {
envBind(local, "children", children);
}
return makeCekState(componentBody(f), local, kontPush(makeCompTraceFrame(componentName(f), componentFile(f)), kont));
})() : error((String("Not callable: ") + String(inspect(f)))))))))); };
PRIMITIVES["continue-with-call"] = continueWithCall;
// 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(isElseClause(test)) ? makeCekState(body, env, kont) : (function() {
var testVal = trampoline(evalExpr(test, env));
return (isSxTruthy(sxEq(matchVal, testVal)) ? makeCekState(body, env, kont) : sfCaseStepLoop(matchVal, slice(clauses, 2), env, kont));
})());
})()); };
PRIMITIVES["sf-case-step-loop"] = sfCaseStepLoop;
// eval-expr-cek
var evalExprCek = function(expr, env) { return cekRun(makeCekState(expr, env, [])); };
PRIMITIVES["eval-expr-cek"] = evalExprCek;
// trampoline-cek
var trampolineCek = function(val) { return (isSxTruthy(isThunk(val)) ? evalExprCek(thunkExpr(val), thunkEnv(val)) : val); };
PRIMITIVES["trampoline-cek"] = trampolineCek;
// eval-expr
var evalExpr = function(expr, env) { return cekRun(makeCekState(expr, env, [])); };
PRIMITIVES["eval-expr"] = evalExpr;
// trampoline
var trampoline = function(val) { return (isSxTruthy(isThunk(val)) ? evalExpr(thunkExpr(val), thunkEnv(val)) : val); };
PRIMITIVES["trampoline"] = trampoline;
// === Transpiled from freeze (serializable state boundaries) ===
// === Transpiled from content (content-addressed computation) ===
// === Transpiled from render (core) ===
// === Transpiled from web-forms (defstyle, deftype, defeffect, defrelation) ===
// parse-key-params
var parseKeyParams = function(paramsExpr) { return (function() {
var params = [];
{ var _c = paramsExpr; for (var _i = 0; _i < _c.length; _i++) { var p = _c[_i]; if (isSxTruthy(sxEq(typeOf(p), "symbol"))) {
(function() {
var name = symbolName(p);
return (isSxTruthy(!isSxTruthy(sxEq(name, "&key"))) ? append_b(params, name) : NIL);
})();
} } }
return params;
})(); };
PRIMITIVES["parse-key-params"] = parseKeyParams;
// parse-handler-args
var parseHandlerArgs = function(args) { return (function() {
var opts = {};
var params = [];
var body = NIL;
var i = 0;
var n = len(args);
var done = false;
{ var _c = range(0, n); for (var _i = 0; _i < _c.length; _i++) { var idx = _c[_i]; if (isSxTruthy((isSxTruthy(!isSxTruthy(done)) && sxEq(idx, i)))) {
(function() {
var arg = nth(args, idx);
return (isSxTruthy(sxEq(typeOf(arg), "keyword")) ? ((isSxTruthy(((idx + 1) < n)) ? (function() {
var val = nth(args, (idx + 1));
return dictSet(opts, keywordName(arg), (isSxTruthy(sxEq(typeOf(val), "keyword")) ? keywordName(val) : val));
})() : NIL), (i = (idx + 2))) : (isSxTruthy(sxEq(typeOf(arg), "list")) ? ((params = parseKeyParams(arg)), (isSxTruthy(((idx + 1) < n)) ? (body = nth(args, (idx + 1))) : NIL), (done = true)) : ((body = arg), (done = true))));
})();
} } }
return {["opts"]: opts, ["params"]: params, ["body"]: body};
})(); };
PRIMITIVES["parse-handler-args"] = parseHandlerArgs;
// (register-special-form! ...)
registerSpecialForm("defhandler", function(args, env) { return (function() {
var nameSym = first(args);
var name = symbolName(first(args));
var parsed = parseHandlerArgs(rest(args));
var opts = get(parsed, "opts");
var params = get(parsed, "params");
var body = get(parsed, "body");
return (function() {
var hdef = {["__type"]: "handler", ["name"]: name, ["params"]: params, ["body"]: body, ["closure"]: env, ["path"]: sxOr(get(opts, "path"), NIL), ["method"]: sxOr(get(opts, "method"), "get"), ["csrf"]: (function() {
var v = get(opts, "csrf");
return (isSxTruthy(isNil(v)) ? true : v);
})(), ["returns"]: sxOr(get(opts, "returns"), "element")};
envBind(env, (String("handler:") + String(name)), hdef);
return hdef;
})();
})(); });
// (register-special-form! ...)
registerSpecialForm("defquery", function(args, env) { return (function() {
var name = symbolName(first(args));
var paramsRaw = nth(args, 1);
var params = parseKeyParams(paramsRaw);
var hasDoc = (isSxTruthy((len(args) >= 4)) && sxEq(typeOf(nth(args, 2)), "string"));
var doc = (isSxTruthy(hasDoc) ? nth(args, 2) : "");
var body = (isSxTruthy(hasDoc) ? nth(args, 3) : nth(args, 2));
return (function() {
var qdef = {["__type"]: "query", ["name"]: name, ["params"]: params, ["doc"]: doc, ["body"]: body, ["closure"]: env};
envBind(env, (String("query:") + String(name)), qdef);
return qdef;
})();
})(); });
// (register-special-form! ...)
registerSpecialForm("defaction", function(args, env) { return (function() {
var name = symbolName(first(args));
var paramsRaw = nth(args, 1);
var params = parseKeyParams(paramsRaw);
var hasDoc = (isSxTruthy((len(args) >= 4)) && sxEq(typeOf(nth(args, 2)), "string"));
var doc = (isSxTruthy(hasDoc) ? nth(args, 2) : "");
var body = (isSxTruthy(hasDoc) ? nth(args, 3) : nth(args, 2));
return (function() {
var adef = {["__type"]: "action", ["name"]: name, ["params"]: params, ["doc"]: doc, ["body"]: body, ["closure"]: env};
envBind(env, (String("action:") + String(name)), adef);
return adef;
})();
})(); });
// (register-special-form! ...)
registerSpecialForm("defpage", function(args, env) { return (function() {
var name = symbolName(first(args));
var slots = {};
var n = len(args);
{ var _c = range(0, ((n - 1) / 2)); for (var _i = 0; _i < _c.length; _i++) { var idx = _c[_i]; (function() {
var kIdx = (1 + (idx * 2));
var vIdx = (2 + (idx * 2));
return (isSxTruthy((isSxTruthy((kIdx < n)) && isSxTruthy((vIdx < n)) && sxEq(typeOf(nth(args, kIdx)), "keyword"))) ? dictSet(slots, keywordName(nth(args, kIdx)), nth(args, vIdx)) : NIL);
})(); } }
return (function() {
var pdef = {["__type"]: "page", ["name"]: name, ["path"]: sxOr(get(slots, "path"), ""), ["auth"]: sxOr(get(slots, "auth"), "public"), ["layout"]: get(slots, "layout"), ["data"]: get(slots, "data"), ["content"]: get(slots, "content"), ["filter"]: get(slots, "filter"), ["aside"]: get(slots, "aside"), ["menu"]: get(slots, "menu"), ["stream"]: get(slots, "stream"), ["fallback"]: get(slots, "fallback"), ["shell"]: get(slots, "shell"), ["closure"]: env};
envBind(env, (String("page:") + String(name)), pdef);
return pdef;
})();
})(); });
// (register-special-form! ...)
registerSpecialForm("defrelation", function(args, env) { return (function() {
var name = symbolName(first(args));
var slots = {};
var n = len(args);
{ var _c = range(0, ((n - 1) / 2)); for (var _i = 0; _i < _c.length; _i++) { var idx = _c[_i]; (function() {
var kIdx = (1 + (idx * 2));
var vIdx = (2 + (idx * 2));
return (isSxTruthy((isSxTruthy((kIdx < n)) && isSxTruthy((vIdx < n)) && sxEq(typeOf(nth(args, kIdx)), "keyword"))) ? dictSet(slots, keywordName(nth(args, kIdx)), nth(args, vIdx)) : NIL);
})(); } }
return (function() {
var rdef = {["__type"]: "relation", ["name"]: name, ["slots"]: slots, ["closure"]: env};
envBind(env, (String("relation:") + String(name)), rdef);
return rdef;
})();
})(); });
// (register-special-form! ...)
registerSpecialForm("defstyle", function(args, env) { return (function() {
var nameSym = first(args);
var value = trampoline(evalExpr(nth(args, 1), env));
envBind(env, symbolName(nameSym), value);
return value;
})(); });
// normalize-type-body
var normalizeTypeBody = function(body) { return (isSxTruthy(isNil(body)) ? "nil" : (isSxTruthy(sxEq(typeOf(body), "symbol")) ? symbolName(body) : (isSxTruthy(sxEq(typeOf(body), "string")) ? body : (isSxTruthy(sxEq(typeOf(body), "keyword")) ? keywordName(body) : (isSxTruthy(sxEq(typeOf(body), "dict")) ? mapDict(function(k, v) { return normalizeTypeBody(v); }, body) : (isSxTruthy(sxEq(typeOf(body), "list")) ? (isSxTruthy(isEmpty(body)) ? "any" : (function() {
var headName = (isSxTruthy(sxEq(typeOf(first(body)), "symbol")) ? symbolName(first(body)) : (String(first(body))));
return (isSxTruthy(sxEq(headName, "union")) ? cons("or", map(normalizeTypeBody, rest(body))) : cons(headName, map(normalizeTypeBody, rest(body))));
})()) : (String(body)))))))); };
PRIMITIVES["normalize-type-body"] = normalizeTypeBody;
// (register-special-form! ...)
registerSpecialForm("deftype", function(args, env) { return (function() {
var nameOrForm = first(args);
var bodyExpr = nth(args, 1);
var typeName = NIL;
var typeParams = [];
(isSxTruthy(sxEq(typeOf(nameOrForm), "symbol")) ? (typeName = symbolName(nameOrForm)) : (isSxTruthy(sxEq(typeOf(nameOrForm), "list")) ? ((typeName = symbolName(first(nameOrForm))), (typeParams = map(function(p) { return (isSxTruthy(sxEq(typeOf(p), "symbol")) ? symbolName(p) : (String(p))); }, rest(nameOrForm)))) : NIL));
return (function() {
var body = normalizeTypeBody(bodyExpr);
var registry = (isSxTruthy(envHas(env, "*type-registry*")) ? envGet(env, "*type-registry*") : {});
registry[typeName] = {"body": body, "params": typeParams, "name": typeName};
envBind(env, "*type-registry*", registry);
return NIL;
})();
})(); });
// (register-special-form! ...)
registerSpecialForm("defeffect", function(args, env) { return (function() {
var effectName = (isSxTruthy(sxEq(typeOf(first(args)), "symbol")) ? symbolName(first(args)) : (String(first(args))));
var registry = (isSxTruthy(envHas(env, "*effect-registry*")) ? envGet(env, "*effect-registry*") : []);
if (isSxTruthy(!isSxTruthy(contains(registry, effectName)))) {
registry.push(effectName);
}
envBind(env, "*effect-registry*", registry);
return NIL;
})(); });
// WEB_FORM_NAMES
var WEB_FORM_NAMES = ["defhandler", "defpage", "defquery", "defaction", "defrelation", "defstyle", "deftype", "defeffect"];
PRIMITIVES["WEB_FORM_NAMES"] = WEB_FORM_NAMES;
// === Transpiled from parser ===
// sx-parse
var sxParse = function(source) { return (function() {
var pos = 0;
var lenSrc = len(source);
var skipComment = function() { while(true) { if (isSxTruthy((isSxTruthy((pos < lenSrc)) && !isSxTruthy(sxEq(nth(source, pos), "\n"))))) { pos = (pos + 1);
continue; } else { return NIL; } } };
PRIMITIVES["skip-comment"] = skipComment;
var skipWs = function() { while(true) { if (isSxTruthy((pos < lenSrc))) { { var ch = nth(source, pos);
if (isSxTruthy(sxOr(sxEq(ch, " "), sxEq(ch, "\t"), sxEq(ch, "\n"), sxEq(ch, "\r")))) { pos = (pos + 1);
continue; } else if (isSxTruthy(sxEq(ch, ";"))) { pos = (pos + 1);
skipComment();
continue; } else { return NIL; } } } else { return NIL; } } };
PRIMITIVES["skip-ws"] = skipWs;
var hexDigitValue = function(ch) { return indexOf_("0123456789abcdef", lower(ch)); };
PRIMITIVES["hex-digit-value"] = hexDigitValue;
var readString = function() { pos = (pos + 1);
return (function() {
var buf = "";
var readStrLoop = function() { while(true) { if (isSxTruthy((pos >= lenSrc))) { return error("Unterminated string"); } else { { var ch = nth(source, pos);
if (isSxTruthy(sxEq(ch, "\""))) { pos = (pos + 1);
return NIL; } else if (isSxTruthy(sxEq(ch, "\\"))) { pos = (pos + 1);
{ var esc = nth(source, pos);
if (isSxTruthy(sxEq(esc, "u"))) { pos = (pos + 1);
{ var d0 = hexDigitValue(nth(source, pos));
var _ = (pos = (pos + 1));
var d1 = hexDigitValue(nth(source, pos));
var _ = (pos = (pos + 1));
var d2 = hexDigitValue(nth(source, pos));
var _ = (pos = (pos + 1));
var d3 = hexDigitValue(nth(source, pos));
var _ = (pos = (pos + 1));
buf = (String(buf) + String(charFromCode(((((d0 * 4096) + (d1 * 256)) + (d2 * 16)) + d3))));
continue; } } else { buf = (String(buf) + String((isSxTruthy(sxEq(esc, "n")) ? "\n" : (isSxTruthy(sxEq(esc, "t")) ? "\t" : (isSxTruthy(sxEq(esc, "r")) ? "\r" : esc)))));
pos = (pos + 1);
continue; } } } else { buf = (String(buf) + String(ch));
pos = (pos + 1);
continue; } } } } };
PRIMITIVES["read-str-loop"] = readStrLoop;
readStrLoop();
return buf;
})(); };
PRIMITIVES["read-string"] = readString;
var readIdent = function() { return (function() {
var start = pos;
var readIdentLoop = function() { while(true) { if (isSxTruthy((isSxTruthy((pos < lenSrc)) && isIdentChar(nth(source, pos))))) { pos = (pos + 1);
continue; } else { return NIL; } } };
PRIMITIVES["read-ident-loop"] = readIdentLoop;
readIdentLoop();
return slice(source, start, pos);
})(); };
PRIMITIVES["read-ident"] = readIdent;
var readKeyword = function() { pos = (pos + 1);
return makeKeyword(readIdent()); };
PRIMITIVES["read-keyword"] = readKeyword;
var readNumber = function() { return (function() {
var start = pos;
if (isSxTruthy((isSxTruthy((pos < lenSrc)) && sxEq(nth(source, pos), "-")))) {
pos = (pos + 1);
}
var readDigits = function() { while(true) { if (isSxTruthy((isSxTruthy((pos < lenSrc)) && (function() {
var c = nth(source, pos);
return (isSxTruthy((c >= "0")) && (c <= "9"));
})()))) { pos = (pos + 1);
continue; } else { return NIL; } } };
PRIMITIVES["read-digits"] = readDigits;
readDigits();
if (isSxTruthy((isSxTruthy((pos < lenSrc)) && sxEq(nth(source, pos), ".")))) {
pos = (pos + 1);
readDigits();
}
if (isSxTruthy((isSxTruthy((pos < lenSrc)) && sxOr(sxEq(nth(source, pos), "e"), sxEq(nth(source, pos), "E"))))) {
pos = (pos + 1);
if (isSxTruthy((isSxTruthy((pos < lenSrc)) && sxOr(sxEq(nth(source, pos), "+"), sxEq(nth(source, pos), "-"))))) {
pos = (pos + 1);
}
readDigits();
}
return parseNumber(slice(source, start, pos));
})(); };
PRIMITIVES["read-number"] = readNumber;
var readSymbol = function() { return (function() {
var name = readIdent();
return (isSxTruthy(sxEq(name, "true")) ? true : (isSxTruthy(sxEq(name, "false")) ? false : (isSxTruthy(sxEq(name, "nil")) ? NIL : makeSymbol(name))));
})(); };
PRIMITIVES["read-symbol"] = readSymbol;
var readList = function(closeCh) { return (function() {
var items = [];
var readListLoop = function() { while(true) { skipWs();
if (isSxTruthy((pos >= lenSrc))) { return error("Unterminated list"); } else { if (isSxTruthy(sxEq(nth(source, pos), closeCh))) { pos = (pos + 1);
return NIL; } else { items.push(readExpr());
continue; } } } };
PRIMITIVES["read-list-loop"] = readListLoop;
readListLoop();
return items;
})(); };
PRIMITIVES["read-list"] = readList;
var readMap = function() { return (function() {
var result = {};
var readMapLoop = function() { while(true) { skipWs();
if (isSxTruthy((pos >= lenSrc))) { return error("Unterminated map"); } else { if (isSxTruthy(sxEq(nth(source, pos), "}"))) { pos = (pos + 1);
return NIL; } else { { var keyExpr = readExpr();
var keyStr = (isSxTruthy(sxEq(typeOf(keyExpr), "keyword")) ? keywordName(keyExpr) : (String(keyExpr)));
var valExpr = readExpr();
result[keyStr] = valExpr;
continue; } } } } };
PRIMITIVES["read-map-loop"] = readMapLoop;
readMapLoop();
return result;
})(); };
PRIMITIVES["read-map"] = readMap;
var readRawString = function() { return (function() {
var buf = "";
var rawLoop = function() { while(true) { if (isSxTruthy((pos >= lenSrc))) { return error("Unterminated raw string"); } else { { var ch = nth(source, pos);
if (isSxTruthy(sxEq(ch, "|"))) { pos = (pos + 1);
return NIL; } else { buf = (String(buf) + String(ch));
pos = (pos + 1);
continue; } } } } };
PRIMITIVES["raw-loop"] = rawLoop;
rawLoop();
return buf;
})(); };
PRIMITIVES["read-raw-string"] = readRawString;
var readExpr = function() { while(true) { skipWs();
if (isSxTruthy((pos >= lenSrc))) { return error("Unexpected end of input"); } else { { var ch = nth(source, pos);
if (isSxTruthy(sxEq(ch, "("))) { pos = (pos + 1);
return readList(")"); } else if (isSxTruthy(sxEq(ch, "["))) { pos = (pos + 1);
return readList("]"); } else if (isSxTruthy(sxEq(ch, "{"))) { pos = (pos + 1);
return readMap(); } else if (isSxTruthy(sxEq(ch, "\""))) { return readString(); } else if (isSxTruthy(sxEq(ch, ":"))) { return readKeyword(); } else if (isSxTruthy(sxEq(ch, "'"))) { pos = (pos + 1);
return [makeSymbol("quote"), readExpr()]; } else if (isSxTruthy(sxEq(ch, "`"))) { pos = (pos + 1);
return [makeSymbol("quasiquote"), readExpr()]; } else if (isSxTruthy(sxEq(ch, ","))) { pos = (pos + 1);
if (isSxTruthy((isSxTruthy((pos < lenSrc)) && sxEq(nth(source, pos), "@")))) { pos = (pos + 1);
return [makeSymbol("splice-unquote"), readExpr()]; } else { return [makeSymbol("unquote"), readExpr()]; } } else if (isSxTruthy(sxEq(ch, "#"))) { pos = (pos + 1);
if (isSxTruthy((pos >= lenSrc))) { return error("Unexpected end of input after #"); } else { { var dispatchCh = nth(source, pos);
if (isSxTruthy(sxEq(dispatchCh, ";"))) { pos = (pos + 1);
readExpr();
continue; } else if (isSxTruthy(sxEq(dispatchCh, "|"))) { pos = (pos + 1);
return readRawString(); } else if (isSxTruthy(sxEq(dispatchCh, "'"))) { pos = (pos + 1);
return [makeSymbol("quote"), readExpr()]; } else if (isSxTruthy(isIdentStart(dispatchCh))) { { var macroName = readIdent();
{ var handler = readerMacroGet(macroName);
if (isSxTruthy(handler)) { return handler(readExpr()); } else { return error((String("Unknown reader macro: #") + String(macroName))); } } } } else { return error((String("Unknown reader macro: #") + String(dispatchCh))); } } } } else if (isSxTruthy(sxOr((isSxTruthy((ch >= "0")) && (ch <= "9")), (isSxTruthy(sxEq(ch, "-")) && isSxTruthy(((pos + 1) < lenSrc)) && (function() {
var nextCh = nth(source, (pos + 1));
return (isSxTruthy((nextCh >= "0")) && (nextCh <= "9"));
})())))) { return readNumber(); } else if (isSxTruthy((isSxTruthy(sxEq(ch, ".")) && isSxTruthy(((pos + 2) < lenSrc)) && isSxTruthy(sxEq(nth(source, (pos + 1)), ".")) && sxEq(nth(source, (pos + 2)), ".")))) { pos = (pos + 3);
return makeSymbol("..."); } else if (isSxTruthy(isIdentStart(ch))) { return readSymbol(); } else { return error((String("Unexpected character: ") + String(ch))); } } } } };
PRIMITIVES["read-expr"] = readExpr;
return (function() {
var exprs = [];
var parseLoop = function() { while(true) { skipWs();
if (isSxTruthy((pos < lenSrc))) { exprs.push(readExpr());
continue; } else { return NIL; } } };
PRIMITIVES["parse-loop"] = parseLoop;
parseLoop();
return exprs;
})();
})(); };
PRIMITIVES["sx-parse"] = sxParse;
// sx-serialize
var sxSerialize = function(val) { return (function() { var _m = typeOf(val); if (_m == "nil") return "nil"; if (_m == "boolean") return (isSxTruthy(val) ? "true" : "false"); if (_m == "number") return (String(val)); if (_m == "string") return (String("\"") + String(escapeString(val)) + String("\"")); if (_m == "symbol") return symbolName(val); if (_m == "keyword") return (String(":") + String(keywordName(val))); if (_m == "list") return (String("(") + String(join(" ", map(sxSerialize, val))) + String(")")); if (_m == "dict") return sxSerializeDict(val); if (_m == "sx-expr") return sxExprSource(val); if (_m == "spread") return (String("(make-spread ") + String(sxSerializeDict(spreadAttrs(val))) + String(")")); return (String(val)); })(); };
PRIMITIVES["sx-serialize"] = sxSerialize;
// sx-serialize-dict
var sxSerializeDict = function(d) { return (String("{") + String(join(" ", reduce(function(acc, key) { return concat(acc, [(String(":") + String(key)), sxSerialize(dictGet(d, key))]); }, [], keys(d)))) + String("}")); };
PRIMITIVES["sx-serialize-dict"] = sxSerializeDict;
// serialize
var serialize = sxSerialize;
PRIMITIVES["serialize"] = serialize;
// === Transpiled from adapter-html ===
// === Transpiled from adapter-sx ===
// === Transpiled from lib/dom (DOM library) ===
// === Transpiled from lib/browser (browser API library) ===
// === Transpiled from adapter-dom ===
// === Transpiled from engine ===
// === Transpiled from orchestration ===
// === Transpiled from boot ===
// HEAD_HOIST_SELECTOR
var HEAD_HOIST_SELECTOR = "meta, title, link[rel='canonical'], script[type='application/ld+json']";
PRIMITIVES["HEAD_HOIST_SELECTOR"] = HEAD_HOIST_SELECTOR;
// hoist-head-elements-full
var hoistHeadElementsFull = function(root) { return (function() {
var els = domQueryAll(root, HEAD_HOIST_SELECTOR);
return forEach(function(el) { return (function() {
var tag = lower(domTagName(el));
return (isSxTruthy(sxEq(tag, "title")) ? (setDocumentTitle(domTextContent(el)), domRemoveChild(domParent(el), el)) : (isSxTruthy(sxEq(tag, "meta")) ? ((function() {
var name = domGetAttr(el, "name");
var prop = domGetAttr(el, "property");
if (isSxTruthy(name)) {
removeHeadElement((String("meta[name=\"") + String(name) + String("\"]")));
}
return (isSxTruthy(prop) ? removeHeadElement((String("meta[property=\"") + String(prop) + String("\"]"))) : NIL);
})(), domRemoveChild(domParent(el), el), domAppendToHead(el)) : (isSxTruthy((isSxTruthy(sxEq(tag, "link")) && sxEq(domGetAttr(el, "rel"), "canonical"))) ? (removeHeadElement("link[rel=\"canonical\"]"), domRemoveChild(domParent(el), el), domAppendToHead(el)) : (domRemoveChild(domParent(el), el), domAppendToHead(el)))));
})(); }, els);
})(); };
PRIMITIVES["hoist-head-elements-full"] = hoistHeadElementsFull;
// sx-mount
var sxMount = function(target, source, extraEnv) { return (function() {
var el = resolveMountTarget(target);
return (isSxTruthy(el) ? ((isSxTruthy(isEmpty(domChildList(el))) ? (function() {
var node = sxRenderWithEnv(source, extraEnv);
domSetTextContent(el, "");
domAppend(el, node);
return hoistHeadElementsFull(el);
})() : NIL), processElements(el), sxHydrateElements(el), sxHydrateIslands(el), runPostRenderHooks()) : NIL);
})(); };
PRIMITIVES["sx-mount"] = sxMount;
// resolve-suspense
var resolveSuspense = function(id, sx) { processSxScripts(NIL);
return (function() {
var el = domQuery((String("[data-suspense=\"") + String(id) + String("\"]")));
return (isSxTruthy(el) ? (function() {
var exprs = parse(sx);
var env = getRenderEnv(NIL);
domSetTextContent(el, "");
{ var _c = exprs; for (var _i = 0; _i < _c.length; _i++) { var expr = _c[_i]; domAppend(el, renderToDom(expr, env, NIL)); } }
processElements(el);
sxHydrateElements(el);
sxHydrateIslands(el);
runPostRenderHooks();
return domDispatch(el, "sx:resolved", {"id": id});
})() : logWarn((String("resolveSuspense: no element for id=") + String(id))));
})(); };
PRIMITIVES["resolve-suspense"] = resolveSuspense;
// sx-hydrate-elements
var sxHydrateElements = function(root) { return (function() {
var els = domQueryAll(sxOr(root, domBody()), "[data-sx]");
return forEach(function(el) { return (isSxTruthy(!isSxTruthy(isProcessed(el, "hydrated"))) ? (markProcessed(el, "hydrated"), sxUpdateElement(el, NIL)) : NIL); }, els);
})(); };
PRIMITIVES["sx-hydrate-elements"] = sxHydrateElements;
// sx-update-element
var sxUpdateElement = function(el, newEnv) { return (function() {
var target = resolveMountTarget(el);
return (isSxTruthy(target) ? (function() {
var source = domGetAttr(target, "data-sx");
return (isSxTruthy(source) ? (function() {
var baseEnv = parseEnvAttr(target);
var env = mergeEnvs(baseEnv, newEnv);
return (function() {
var node = sxRenderWithEnv(source, env);
domSetTextContent(target, "");
domAppend(target, node);
return (isSxTruthy(newEnv) ? storeEnvAttr(target, baseEnv, newEnv) : NIL);
})();
})() : NIL);
})() : NIL);
})(); };
PRIMITIVES["sx-update-element"] = sxUpdateElement;
// sx-render-component
var sxRenderComponent = function(name, kwargs, extraEnv) { return (function() {
var fullName = (isSxTruthy(startsWith(name, "~")) ? name : (String("~") + String(name)));
return (function() {
var env = getRenderEnv(extraEnv);
var comp = envGet(env, fullName);
return (isSxTruthy(!isSxTruthy(isComponent(comp))) ? error((String("Unknown component: ") + String(fullName))) : (function() {
var callExpr = [makeSymbol(fullName)];
{ var _c = keys(kwargs); for (var _i = 0; _i < _c.length; _i++) { var k = _c[_i]; callExpr.push(makeKeyword(toKebab(k)));
callExpr.push(dictGet(kwargs, k)); } }
return renderToDom(callExpr, env, NIL);
})());
})();
})(); };
PRIMITIVES["sx-render-component"] = sxRenderComponent;
// process-sx-scripts
var processSxScripts = function(root) { return (function() {
var scripts = querySxScripts(root);
return forEach(function(s) { return (isSxTruthy(!isSxTruthy(isProcessed(s, "script"))) ? (markProcessed(s, "script"), (function() {
var text = domTextContent(s);
return (isSxTruthy(domHasAttr(s, "data-components")) ? processComponentScript(s, text) : (isSxTruthy(sxOr(isNil(text), isEmpty(trim(text)))) ? NIL : (isSxTruthy(domHasAttr(s, "data-init")) ? (function() {
var exprs = sxParse(text);
return forEach(function(expr) { return cekEval(expr); }, exprs);
})() : (isSxTruthy(domHasAttr(s, "data-mount")) ? (function() {
var mountSel = domGetAttr(s, "data-mount");
var target = domQuery(mountSel);
return (isSxTruthy(target) ? sxMount(target, text, NIL) : NIL);
})() : sxLoadComponents(text)))));
})()) : NIL); }, scripts);
})(); };
PRIMITIVES["process-sx-scripts"] = processSxScripts;
// process-component-script
var processComponentScript = function(script, text) { return (function() {
var hash = domGetAttr(script, "data-hash");
return (isSxTruthy(isNil(hash)) ? (isSxTruthy((isSxTruthy(text) && !isSxTruthy(isEmpty(trim(text))))) ? sxLoadComponents(text) : NIL) : (function() {
var hasInline = (isSxTruthy(text) && !isSxTruthy(isEmpty(trim(text))));
(function() {
var cachedHash = localStorageGet("sx-components-hash");
return (isSxTruthy(sxEq(cachedHash, hash)) ? (isSxTruthy(hasInline) ? (localStorageSet("sx-components-hash", hash), localStorageSet("sx-components-src", text), sxLoadComponents(text), logInfo("components: downloaded (cookie stale)")) : (function() {
var cached = localStorageGet("sx-components-src");
return (isSxTruthy(cached) ? (sxLoadComponents(cached), logInfo((String("components: cached (") + String(hash) + String(")")))) : (clearSxCompCookie(), browserReload()));
})()) : (isSxTruthy(hasInline) ? (localStorageSet("sx-components-hash", hash), localStorageSet("sx-components-src", text), sxLoadComponents(text), logInfo((String("components: downloaded (") + String(hash) + String(")")))) : (localStorageRemove("sx-components-hash"), localStorageRemove("sx-components-src"), clearSxCompCookie(), browserReload())));
})();
return setSxCompCookie(hash);
})());
})(); };
PRIMITIVES["process-component-script"] = processComponentScript;
// _page-routes
var _pageRoutes = [];
PRIMITIVES["_page-routes"] = _pageRoutes;
// process-page-scripts
var processPageScripts = function() { return (function() {
var scripts = queryPageScripts();
logInfo((String("pages: found ") + String(len(scripts)) + String(" script tags")));
{ var _c = scripts; for (var _i = 0; _i < _c.length; _i++) { var s = _c[_i]; if (isSxTruthy(!isSxTruthy(isProcessed(s, "pages")))) {
markProcessed(s, "pages");
(function() {
var text = domTextContent(s);
logInfo((String("pages: script text length=") + String((isSxTruthy(text) ? len(text) : 0))));
return (isSxTruthy((isSxTruthy(text) && !isSxTruthy(isEmpty(trim(text))))) ? (function() {
var pages = parse(text);
logInfo((String("pages: parsed ") + String(len(pages)) + String(" entries")));
return forEach(function(page) { return append_b(_pageRoutes, merge(page, {"parsed": parseRoutePattern(get(page, "path"))})); }, pages);
})() : logWarn("pages: script tag is empty"));
})();
} } }
return logInfo((String("pages: ") + String(len(_pageRoutes)) + String(" routes loaded")));
})(); };
PRIMITIVES["process-page-scripts"] = processPageScripts;
// sx-hydrate-islands
var sxHydrateIslands = function(root) { return (function() {
var els = domQueryAll(sxOr(root, domBody()), "[data-sx-island]");
logInfo((String("sx-hydrate-islands: ") + String(len(els)) + String(" island(s) in ") + String((isSxTruthy(root) ? "subtree" : "document"))));
return forEach(function(el) { return (isSxTruthy(isProcessed(el, "island-hydrated")) ? logInfo((String(" skip (already hydrated): ") + String(domGetAttr(el, "data-sx-island")))) : (logInfo((String(" hydrating: ") + String(domGetAttr(el, "data-sx-island")))), markProcessed(el, "island-hydrated"), hydrateIsland(el))); }, els);
})(); };
PRIMITIVES["sx-hydrate-islands"] = sxHydrateIslands;
// hydrate-island
var hydrateIsland = function(el) { return (function() {
var name = domGetAttr(el, "data-sx-island");
var stateSx = sxOr(domGetAttr(el, "data-sx-state"), "{}");
return (function() {
var compName = (String("~") + String(name));
var env = getRenderEnv(NIL);
return (function() {
var comp = envGet(env, compName);
return (isSxTruthy(!isSxTruthy(sxOr(isComponent(comp), isIsland(comp)))) ? logWarn((String("hydrate-island: unknown island ") + String(compName))) : (function() {
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]; envBind(local, p, (isSxTruthy(dictHas(kwargs, p)) ? dictGet(kwargs, p) : NIL)); } }
return (function() {
var bodyDom = cekTry(function() { return withIslandScope(function(disposable) { return append_b(disposers, disposable); }, function() { return renderToDom(componentBody(comp), local, NIL); }); }, function(err) { logWarn((String("hydrate-island FAILED: ") + String(compName) + String(" — ") + String(err)));
return (function() {
var errorEl = domCreateElement("div", NIL);
domSetAttr(errorEl, "class", "sx-island-error");
domSetAttr(errorEl, "style", "padding:8px;margin:4px 0;border:1px solid #ef4444;border-radius:4px;background:#fef2f2;color:#b91c1c;font-family:monospace;font-size:12px;white-space:pre-wrap");
domSetTextContent(errorEl, (String("Island error: ") + String(compName) + String("\n") + String(err)));
return errorEl;
})(); });
domSetTextContent(el, "");
domAppend(el, bodyDom);
domSetData(el, "sx-disposers", disposers);
setTimeout_(function() { return processElements(el); }, 0);
return logInfo((String("hydrated island: ") + String(compName) + String(" (") + String(len(disposers)) + String(" disposers)")));
})();
})());
})();
})();
})(); };
PRIMITIVES["hydrate-island"] = hydrateIsland;
// dispose-island
var disposeIsland = function(el) { (function() {
var disposers = domGetData(el, "sx-disposers");
return (isSxTruthy(disposers) ? (forEach(function(d) { return (isSxTruthy(isCallable(d)) ? d() : NIL); }, disposers), domSetData(el, "sx-disposers", NIL)) : NIL);
})();
return clearProcessed(el, "island-hydrated"); };
PRIMITIVES["dispose-island"] = disposeIsland;
// dispose-islands-in
var disposeIslandsIn = function(root) { return (isSxTruthy(root) ? (function() {
var islands = domQueryAll(root, "[data-sx-island]");
return (isSxTruthy((isSxTruthy(islands) && !isSxTruthy(isEmpty(islands)))) ? (function() {
var toDispose = filter(function(el) { return !isSxTruthy(isProcessed(el, "island-hydrated")); }, islands);
return (isSxTruthy(!isSxTruthy(isEmpty(toDispose))) ? (logInfo((String("disposing ") + String(len(toDispose)) + String(" island(s)"))), forEach(disposeIsland, toDispose)) : NIL);
})() : NIL);
})() : NIL); };
PRIMITIVES["dispose-islands-in"] = disposeIslandsIn;
// force-dispose-islands-in
var forceDisposeIslandsIn = function(root) { return (isSxTruthy(root) ? (function() {
var islands = domQueryAll(root, "[data-sx-island]");
return (isSxTruthy((isSxTruthy(islands) && !isSxTruthy(isEmpty(islands)))) ? (logInfo((String("force-disposing ") + String(len(islands)) + String(" island(s)"))), forEach(disposeIsland, islands)) : NIL);
})() : NIL); };
PRIMITIVES["force-dispose-islands-in"] = forceDisposeIslandsIn;
// *pre-render-hooks*
var _preRenderHooks_ = [];
PRIMITIVES["*pre-render-hooks*"] = _preRenderHooks_;
// *post-render-hooks*
var _postRenderHooks_ = [];
PRIMITIVES["*post-render-hooks*"] = _postRenderHooks_;
// register-pre-render-hook
var registerPreRenderHook = function(hookFn) { return append_b(_preRenderHooks_, hookFn); };
PRIMITIVES["register-pre-render-hook"] = registerPreRenderHook;
// register-post-render-hook
var registerPostRenderHook = function(hookFn) { return append_b(_postRenderHooks_, hookFn); };
PRIMITIVES["register-post-render-hook"] = registerPostRenderHook;
// run-pre-render-hooks
var runPreRenderHooks = function() { return forEach(function(hook) { return cekCall(hook, NIL); }, _preRenderHooks_); };
PRIMITIVES["run-pre-render-hooks"] = runPreRenderHooks;
// run-post-render-hooks
var runPostRenderHooks = function() { logInfo((String("run-post-render-hooks: ") + String(len(_postRenderHooks_)) + String(" hooks")));
{ var _c = _postRenderHooks_; for (var _i = 0; _i < _c.length; _i++) { var hook = _c[_i]; logInfo((String(" hook type: ") + String(typeOf(hook)) + String(" callable: ") + String(isCallable(hook)) + String(" lambda: ") + String(isLambda(hook))));
cekCall(hook, NIL); } }
return flushCollectedStyles(); };
PRIMITIVES["run-post-render-hooks"] = runPostRenderHooks;
// boot-init
var bootInit = function() { return (logInfo((String("sx-browser ") + String(SX_VERSION))), processPageScripts(), processSxScripts(NIL), sxHydrateElements(NIL), sxHydrateIslands(NIL), runPostRenderHooks(), flushCollectedStyles(), setTimeout_(function() { return processElements(NIL); }, 0), domSetAttr(hostGet(domDocument(), "documentElement"), "data-sx-ready", "true"), domDispatch(domDocument(), "sx:ready", NIL), logInfo("sx:ready")); };
PRIMITIVES["boot-init"] = bootInit;
// === Transpiled from deps (component dependency analysis) ===
// === Transpiled from page-helpers (pure data transformation helpers) ===
// === Transpiled from router (client-side route matching) ===
// === Transpiled from signals (reactive signal runtime) ===
// === Transpiled from signals-web (stores, events, resources) ===
// =========================================================================
// Post-transpilation fixups
// =========================================================================
// The reference spec's call-lambda only handles Lambda objects, but HO forms
// (map, reduce, etc.) may receive native primitives. Wrap to handle both.
var _rawCallLambda = callLambda;
callLambda = function(f, args, callerEnv) {
if (typeof f === "function") return f.apply(null, args);
return _rawCallLambda(f, args, callerEnv);
};
// -----------------------------------------------------------------------
// Core primitives that require native JS (cannot be expressed via FFI)
// -----------------------------------------------------------------------
PRIMITIVES["error"] = function(msg) { throw new Error(msg); };
PRIMITIVES["sort"] = function(lst) {
if (!Array.isArray(lst)) return lst;
return lst.slice().sort(function(a, b) {
if (a < b) return -1; if (a > b) return 1; return 0;
});
};
// Aliases for VM bytecode compatibility
PRIMITIVES["length"] = PRIMITIVES["len"];
// FFI library functions — defined in dom.sx/browser.sx but not transpiled.
// Registered here so runtime-evaluated SX code (data-init, islands) can use them.
PRIMITIVES["prevent-default"] = preventDefault_;
PRIMITIVES["stop-propagation"] = stopPropagation_;
PRIMITIVES["event-modifier-key?"] = eventModifierKey_p;
PRIMITIVES["element-value"] = elementValue;
PRIMITIVES["error-message"] = errorMessage;
PRIMITIVES["schedule-idle"] = scheduleIdle;
PRIMITIVES["console-log"] = function() {
var args = Array.prototype.slice.call(arguments);
console.log.apply(console, ["[sx]"].concat(args));
return args.length > 0 ? args[0] : NIL;
};
PRIMITIVES["set-cookie"] = function(name, value, days) {
var d = days || 365;
var expires = new Date(Date.now() + d * 864e5).toUTCString();
document.cookie = name + "=" + encodeURIComponent(value) + ";expires=" + expires + ";path=/;SameSite=Lax";
return NIL;
};
PRIMITIVES["get-cookie"] = function(name) {
var m = document.cookie.match(new RegExp("(?:^|;\\s*)" + name + "=([^;]*)"));
return m ? decodeURIComponent(m[1]) : NIL;
};
// dom.sx / browser.sx library functions — not transpiled, registered from
// native platform implementations so runtime-eval'd SX code can use them.
if (typeof domBody === "function") PRIMITIVES["dom-body"] = domBody;
if (typeof domQuery === "function") PRIMITIVES["dom-query"] = domQuery;
if (typeof domQueryAll === "function") PRIMITIVES["dom-query-all"] = domQueryAll;
if (typeof domQueryById === "function") PRIMITIVES["dom-query-by-id"] = domQueryById;
if (typeof domSetAttr === "function") PRIMITIVES["dom-set-attr"] = domSetAttr;
if (typeof domGetAttr === "function") PRIMITIVES["dom-get-attr"] = domGetAttr;
if (typeof domRemoveAttr === "function") PRIMITIVES["dom-remove-attr"] = domRemoveAttr;
if (typeof domHasAttr === "function") PRIMITIVES["dom-has-attr?"] = domHasAttr;
if (typeof domAddClass === "function") PRIMITIVES["dom-add-class"] = domAddClass;
if (typeof domRemoveClass === "function") PRIMITIVES["dom-remove-class"] = domRemoveClass;
if (typeof domHasClass === "function") PRIMITIVES["dom-has-class?"] = domHasClass;
if (typeof domClosest === "function") PRIMITIVES["dom-closest"] = domClosest;
if (typeof domMatches === "function") PRIMITIVES["dom-matches?"] = domMatches;
if (typeof domOuterHtml === "function") PRIMITIVES["dom-outer-html"] = domOuterHtml;
if (typeof domInnerHtml === "function") PRIMITIVES["dom-inner-html"] = domInnerHtml;
if (typeof domTextContent === "function") PRIMITIVES["dom-text-content"] = domTextContent;
if (typeof domCreateElement === "function") PRIMITIVES["dom-create-element"] = domCreateElement;
if (typeof domAppend === "function") PRIMITIVES["dom-append"] = domAppend;
if (typeof domAppendToHead === "function") PRIMITIVES["dom-append-to-head"] = domAppendToHead;
if (typeof jsonParse === "function") PRIMITIVES["json-parse"] = jsonParse;
if (typeof nowMs === "function") PRIMITIVES["now-ms"] = nowMs;
PRIMITIVES["log-info"] = logInfo;
PRIMITIVES["log-warn"] = logWarn;
PRIMITIVES["dom-listen"] = domListen;
PRIMITIVES["dom-dispatch"] = domDispatch;
PRIMITIVES["event-detail"] = eventDetail;
PRIMITIVES["create-text-node"] = createTextNode;
PRIMITIVES["dom-set-text-content"] = domSetTextContent;
PRIMITIVES["dom-focus"] = domFocus;
PRIMITIVES["dom-tag-name"] = domTagName;
PRIMITIVES["dom-get-prop"] = domGetProp;
PRIMITIVES["dom-set-prop"] = domSetProp;
PRIMITIVES["reactive-text"] = reactiveText;
PRIMITIVES["set-interval"] = setInterval_;
PRIMITIVES["clear-interval"] = clearInterval_;
PRIMITIVES["promise-then"] = promiseThen;
PRIMITIVES["promise-delayed"] = promiseDelayed;
PRIMITIVES["local-storage-get"] = function(key) {
try { var v = localStorage.getItem(key); return v === null ? NIL : v; }
catch (e) { return NIL; }
};
PRIMITIVES["local-storage-set"] = function(key, val) {
try { localStorage.setItem(key, val); } catch (e) {}
return NIL;
};
PRIMITIVES["local-storage-remove"] = function(key) {
try { localStorage.removeItem(key); } catch (e) {}
return NIL;
};
if (typeof sxParse === "function") PRIMITIVES["sx-parse"] = sxParse;
PRIMITIVES["cek-try"] = function(thunkFn, handlerFn) {
try {
var result = _wrapSxFn(thunkFn)();
if (!handlerFn || handlerFn === NIL) return [makeSymbol("ok"), result];
return result;
} catch (e) {
var msg = (e && e.message) ? e.message : String(e);
if (handlerFn && handlerFn !== NIL) return _wrapSxFn(handlerFn)(msg);
return [makeSymbol("error"), msg];
}
};
// Named stores — global mutable registry (mirrors OCaml sx_primitives.ml)
var _storeRegistry = {};
function defStore(name, initFn) {
if (!_storeRegistry.hasOwnProperty(name)) {
_storeRegistry[name] = _wrapSxFn(initFn)();
}
return _storeRegistry[name];
}
function useStore(name) {
if (!_storeRegistry.hasOwnProperty(name)) throw new Error("Store not found: " + name);
return _storeRegistry[name];
}
function clearStores() { _storeRegistry = {}; return NIL; }
PRIMITIVES["def-store"] = defStore;
PRIMITIVES["use-store"] = useStore;
PRIMITIVES["clear-stores"] = clearStores;
// Platform deps functions (native JS, not transpiled — need explicit registration)
PRIMITIVES["component-deps"] = componentDeps;
PRIMITIVES["component-set-deps!"] = componentSetDeps;
PRIMITIVES["component-css-classes"] = componentCssClasses;
PRIMITIVES["regex-find-all"] = regexFindAll;
PRIMITIVES["scan-css-classes"] = scanCssClasses;
// Override recursive cekRun with iterative loop (avoids stack overflow)
cekRun = function(state) {
while (!cekTerminal_p(state) && !cekSuspended_p(state)) { state = cekStep(state); }
if (cekSuspended_p(state)) { throw new Error("IO suspension in non-IO context"); }
return cekValue(state);
};
// CEK is the canonical evaluator — override evalExpr to use it.
// The tree-walk evaluator (evalExpr from eval.sx) is superseded.
var _treeWalkEvalExpr = evalExpr;
evalExpr = function(expr, env) {
return cekRun(makeCekState(expr, env, []));
};
// CEK never produces thunks — trampoline resolves any legacy thunks
var _treeWalkTrampoline = trampoline;
trampoline = function(val) {
if (isThunk(val)) return evalExpr(thunkExpr(val), thunkEnv(val));
return val;
};
// Platform functions — defined in platform_js.py, not in .sx spec files.
// Spec defines self-register via js-emit-define; these are the platform interface.
PRIMITIVES["type-of"] = typeOf;
PRIMITIVES["symbol-name"] = symbolName;
PRIMITIVES["keyword-name"] = keywordName;
PRIMITIVES["callable?"] = isCallable;
PRIMITIVES["lambda?"] = isLambda;
PRIMITIVES["lambda-name"] = lambdaName;
PRIMITIVES["component?"] = isComponent;
PRIMITIVES["island?"] = isIsland;
PRIMITIVES["make-symbol"] = function(n) { return new Symbol(n); };
PRIMITIVES["is-html-tag?"] = function(n) { return HTML_TAGS.indexOf(n) >= 0; };
function makeEnv() { return merge(componentEnv, PRIMITIVES); }
PRIMITIVES["make-env"] = makeEnv;
// === stdlib.sx (eval'd at runtime, not transpiled) ===
(function() {
var src = ";; ==========================================================================\n;; stdlib.sx — Standard library functions\n;;\n;; Every function here is expressed in SX using the irreducible primitive\n;; set. They are library functions — in band, auditable, portable.\n;;\n;; Depends on: evaluator.sx (special forms)\n;; Must load before: render.sx, freeze.sx, types.sx, user code\n;; ==========================================================================\n\n\n;; Logic + comparison: not, !=, <=, >= stay as primitives.\n;; Replacing them with SX lambdas changes behavior inside shift/reset\n;; because the transpiled evaluator code uses them directly.\n\n\n(define-library (sx stdlib)\n (export\n eq?\n eqv?\n equal?\n boolean?\n number?\n string?\n list?\n dict?\n continuation?\n zero?\n odd?\n even?\n empty?\n abs\n ceil\n round\n min\n max\n clamp\n first\n last\n rest\n nth\n cons\n append\n reverse\n flatten\n range\n chunk-every\n zip-pairs\n vals\n has-key?\n assoc\n dissoc\n into\n upcase\n downcase\n string-length\n substring\n string-contains?\n starts-with?\n ends-with?\n contains?\n pluralize\n escape\n parse-datetime\n assert)\n (begin\n\n(define eq? (fn (a b) (= a b)))\n(define eqv? (fn (a b) (= a b)))\n(define equal? (fn (a b) (= a b)))\n\n\n;; --------------------------------------------------------------------------\n;; Type predicates\n;; --------------------------------------------------------------------------\n\n;; nil? stays as primitive — host's type-of uses it internally.\n\n(define boolean?\n (fn (x) (= (type-of x) \"boolean\")))\n\n(define number?\n (fn (x) (= (type-of x) \"number\")))\n\n(define string?\n (fn (x) (= (type-of x) \"string\")))\n\n(define list?\n (fn (x) (= (type-of x) \"list\")))\n\n(define dict?\n (fn (x) (= (type-of x) \"dict\")))\n\n(define continuation?\n (fn (x) (= (type-of x) \"continuation\")))\n\n(define zero?\n (fn (n) (= n 0)))\n\n(define odd?\n (fn (n) (= (mod n 2) 1)))\n\n(define even?\n (fn (n) (= (mod n 2) 0)))\n\n(define empty?\n (fn (coll) (or (nil? coll) (= (len coll) 0))))\n\n\n;; --------------------------------------------------------------------------\n;; Arithmetic\n;; --------------------------------------------------------------------------\n\n;; inc and dec stay as primitives — used inside continuation contexts.\n\n(define abs\n (fn (x) (if (< x 0) (- x) x)))\n\n(define ceil\n (fn (x)\n (let ((f (floor x)))\n (if (= x f) f (+ f 1)))))\n\n(define round\n (fn (x ndigits)\n (if (nil? ndigits)\n (floor (+ x 0.5))\n (let ((f (pow 10 ndigits)))\n (/ (floor (+ (* x f) 0.5)) f)))))\n\n(define min\n (fn (a b) (if (< a b) a b)))\n\n(define max\n (fn (a b) (if (> a b) a b)))\n\n(define clamp\n (fn (x lo hi) (max lo (min hi x))))\n\n\n;; --------------------------------------------------------------------------\n;; Collection accessors\n;; --------------------------------------------------------------------------\n\n(define first\n (fn (coll)\n (if (and coll (> (len coll) 0)) (get coll 0) nil)))\n\n(define last\n (fn (coll)\n (if (and coll (> (len coll) 0))\n (get coll (- (len coll) 1))\n nil)))\n\n(define rest\n (fn (coll) (if coll (slice coll 1) (list))))\n\n(define nth\n (fn (coll n)\n (if (and coll (>= n 0) (< n (len coll)))\n (get coll n)\n nil)))\n\n(define cons\n (fn (x coll) (concat (list x) (or coll (list)))))\n\n(define append\n (fn (coll x)\n (if (list? x) (concat coll x) (concat coll (list x)))))\n\n\n;; --------------------------------------------------------------------------\n;; Collection transforms\n;; --------------------------------------------------------------------------\n\n(define reverse\n (fn (coll)\n (reduce (fn (acc x) (cons x acc)) (list) coll)))\n\n(define flatten\n (fn (coll)\n (reduce\n (fn (acc x)\n (if (list? x) (concat acc x) (concat acc (list x))))\n (list) coll)))\n\n(define range\n (fn (start end step)\n (let ((s (if (nil? step) 1 step))\n (result (list)))\n (let loop ((i start))\n (when (< i end)\n (append! result i)\n (loop (+ i s))))\n result)))\n\n(define chunk-every\n (fn (coll n)\n (let ((result (list))\n (clen (len coll)))\n (let loop ((i 0))\n (when (< i clen)\n (append! result (slice coll i (min (+ i n) clen)))\n (loop (+ i n))))\n result)))\n\n(define zip-pairs\n (fn (coll)\n (let ((result (list))\n (clen (len coll)))\n (let loop ((i 0))\n (when (< i (- clen 1))\n (append! result (list (get coll i) (get coll (+ i 1))))\n (loop (+ i 1))))\n result)))\n\n\n;; --------------------------------------------------------------------------\n;; Dict operations\n;; --------------------------------------------------------------------------\n\n(define vals\n (fn (d)\n (map (fn (k) (get d k)) (keys d))))\n\n(define has-key?\n (fn (d key)\n (some (fn (k) (= k key)) (keys d))))\n\n(define assoc\n (fn (d key val)\n (let ((result (merge d (dict))))\n (dict-set! result key val)\n result)))\n\n(define dissoc\n (fn (d key)\n (let ((result (dict)))\n (for-each\n (fn (k)\n (when (!= k key)\n (dict-set! result k (get d k))))\n (keys d))\n result)))\n\n(define into\n (fn (target coll)\n (cond\n (list? target)\n (if (list? coll)\n (concat coll (list))\n (let ((result (list)))\n (for-each (fn (k) (append! result (list k (get coll k)))) (keys coll))\n result))\n (dict? target)\n (let ((result (dict)))\n (for-each\n (fn (pair)\n (when (and (list? pair) (>= (len pair) 2))\n (dict-set! result (get pair 0) (get pair 1))))\n coll)\n result)\n :else target)))\n\n\n;; --------------------------------------------------------------------------\n;; String operations\n;; --------------------------------------------------------------------------\n\n(define upcase (fn (s) (upper s)))\n(define downcase (fn (s) (lower s)))\n(define string-length (fn (s) (len s)))\n(define substring (fn (s start end) (slice s start end)))\n\n(define string-contains?\n (fn (s needle) (!= (index-of s needle) -1)))\n\n(define starts-with?\n (fn (s prefix) (= (index-of s prefix) 0)))\n\n(define ends-with?\n (fn (s suffix)\n (let ((slen (len s))\n (plen (len suffix)))\n (if (< slen plen) false\n (= (slice s (- slen plen)) suffix)))))\n\n;; split, join, replace stay as primitives — the stdlib versions cause\n;; stack overflows due to PRIMITIVES entry shadowing in the transpiled output.\n\n(define contains?\n (fn (coll key)\n (cond\n (string? coll) (!= (index-of coll (str key)) -1)\n (dict? coll) (has-key? coll key)\n (list? coll) (some (fn (x) (= x key)) coll)\n :else false)))\n\n\n;; --------------------------------------------------------------------------\n;; Text utilities\n;; --------------------------------------------------------------------------\n\n(define pluralize\n (fn (count singular plural)\n (if (= count 1)\n (or singular \"\")\n (or plural \"s\"))))\n\n(define escape\n (fn (s)\n (let ((r (str s)))\n (set! r (replace r \"&\" \"&amp;\"))\n (set! r (replace r \"<\" \"&lt;\"))\n (set! r (replace r \">\" \"&gt;\"))\n (set! r (replace r \"\\\"\" \"&quot;\"))\n (set! r (replace r \"'\" \"&#x27;\"))\n r)))\n\n(define parse-datetime\n (fn (s) (if s (str s) nil)))\n\n(define assert\n (fn (condition message)\n (when (not condition)\n (error (or message \"Assertion failed\")))\n true))\n\n\n)) ;; end define-library\n\n;; Re-export to global namespace for backward compatibility\n(import (sx stdlib))\n";
var forms = sxParse(src);
var tmpEnv = merge({}, PRIMITIVES);
for (var i = 0; i < forms.length; i++) {
trampoline(evalExpr(forms[i], tmpEnv));
}
for (var k in tmpEnv) {
if (!PRIMITIVES[k]) PRIMITIVES[k] = tmpEnv[k];
}
})();
// =========================================================================
// Platform interface — DOM adapter (browser-only)
// =========================================================================
var _hasDom = typeof document !== "undefined";
// Register DOM adapter as the render dispatch target for the evaluator.
_renderExprFn = function(expr, env) { return renderToDom(expr, env, null); };
_renderMode = true; // Browser always evaluates in render context.
// Wire CEK render hooks — evaluator checks _renderCheck/_renderFn instead of
// the old renderActiveP()/isRenderExpr()/renderExpr() triple.
_renderCheck = function(expr, env) { return _renderMode && isRenderExpr(expr); };
_renderFn = function(expr, env) { return renderToDom(expr, env, null); };
var SVG_NS = "http://www.w3.org/2000/svg";
var MATH_NS = "http://www.w3.org/1998/Math/MathML";
function domCreateElement(tag, ns) {
if (!_hasDom) return null;
if (ns && ns !== NIL) return document.createElementNS(ns, tag);
return document.createElement(tag);
}
function createTextNode(s) {
return _hasDom ? document.createTextNode(s) : null;
}
function createComment(s) {
return _hasDom ? document.createComment(s || "") : null;
}
function createFragment() {
return _hasDom ? document.createDocumentFragment() : null;
}
function domAppend(parent, child) {
if (parent && child && !child._spread) parent.appendChild(child);
}
function domPrepend(parent, child) {
if (parent && child) parent.insertBefore(child, parent.firstChild);
}
function domSetAttr(el, name, val) {
if (el && el.setAttribute) el.setAttribute(name, val);
}
function domGetAttr(el, name) {
if (!el || !el.getAttribute) return NIL;
var v = el.getAttribute(name);
return v === null ? NIL : v;
}
function domRemoveAttr(el, name) {
if (el && el.removeAttribute) el.removeAttribute(name);
}
function domHasAttr(el, name) {
return !!(el && el.hasAttribute && el.hasAttribute(name));
}
function domParseHtml(html) {
if (!_hasDom) return null;
var tpl = document.createElement("template");
tpl.innerHTML = html;
return tpl.content;
}
function domClone(node) {
return node && node.cloneNode ? node.cloneNode(true) : node;
}
function domParent(el) { return el ? el.parentNode : null; }
function domId(el) { return el && el.id ? el.id : NIL; }
function domNodeType(el) { return el ? el.nodeType : 0; }
function domNodeName(el) { return el ? el.nodeName : ""; }
function domTextContent(el) { return el ? el.textContent || el.nodeValue || "" : ""; }
function domSetTextContent(el, s) { if (el) { if (el.nodeType === 3 || el.nodeType === 8) el.nodeValue = s; else el.textContent = s; } }
function domIsFragment(el) { return el ? el.nodeType === 11 : false; }
function domIsChildOf(child, parent) { return !!(parent && child && child.parentNode === parent); }
function domIsActiveElement(el) { return _hasDom && el === document.activeElement; }
function domIsInputElement(el) {
if (!el || !el.tagName) return false;
var t = el.tagName;
return t === "INPUT" || t === "TEXTAREA" || t === "SELECT";
}
function domFirstChild(el) { return el ? el.firstChild : null; }
function domNextSibling(el) { return el ? el.nextSibling : null; }
function domChildList(el) {
if (!el || !el.childNodes) return [];
return Array.prototype.slice.call(el.childNodes);
}
function domAttrList(el) {
if (!el || !el.attributes) return [];
var r = [];
for (var i = 0; i < el.attributes.length; i++) {
r.push([el.attributes[i].name, el.attributes[i].value]);
}
return r;
}
function domInsertBefore(parent, node, ref) {
if (parent && node) parent.insertBefore(node, ref || null);
}
function domInsertAfter(ref, node) {
if (ref && ref.parentNode && node && !node._spread) {
ref.parentNode.insertBefore(node, ref.nextSibling);
}
}
function domRemoveChild(parent, child) {
if (parent && child && child.parentNode === parent) parent.removeChild(child);
}
function domReplaceChild(parent, newChild, oldChild) {
if (parent && newChild && oldChild) parent.replaceChild(newChild, oldChild);
}
function domSetInnerHtml(el, html) {
if (el) el.innerHTML = html;
}
function domInsertAdjacentHtml(el, pos, html) {
if (el && el.insertAdjacentHTML) el.insertAdjacentHTML(pos, html);
}
function domGetStyle(el, prop) {
return el && el.style ? el.style[prop] || "" : "";
}
function domSetStyle(el, prop, val) {
if (el && el.style) el.style[prop] = val;
}
function domGetProp(el, name) { return el ? el[name] : NIL; }
function domSetProp(el, name, val) { if (el) el[name] = val; }
// Call a method on an object with correct this binding: (dom-call-method obj "methodName" arg1 arg2 ...)
function domCallMethod() {
var obj = arguments[0], method = arguments[1];
var args = Array.prototype.slice.call(arguments, 2);
if (obj && typeof obj[method] === 'function') {
try { return obj[method].apply(obj, args); }
catch(e) { console.error("[sx] dom-call-method error:", e); return NIL; }
}
return NIL;
}
// Post a message to an iframe's contentWindow without exposing the cross-origin
// Window object to the SX evaluator (which would trigger _thunk access errors).
function domPostMessage(iframe, msg, origin) {
try {
if (iframe && iframe.contentWindow) {
iframe.contentWindow.postMessage(msg, origin || '*');
}
} catch(e) { console.error("[sx] domPostMessage error:", e); }
return NIL;
}
function domAddClass(el, cls) {
if (el && el.classList) el.classList.add(cls);
}
function domRemoveClass(el, cls) {
if (el && el.classList) el.classList.remove(cls);
}
function domDispatch(el, name, detail) {
if (!_hasDom || !el) return false;
var evt = new CustomEvent(name, { bubbles: true, cancelable: true, detail: detail || {} });
return el.dispatchEvent(evt);
}
function domListen(el, name, handler) {
if (!_hasDom || !el) return function() {};
// Wrap SX lambdas from runtime-evaluated island code into native fns
// If lambda takes 0 params, call without event arg (convenience for on-click handlers)
var wrapped = isLambda(handler)
? (lambdaParams(handler).length === 0
? function(e) { try { cekCall(handler, NIL); } catch(err) { console.error("[sx-ref] domListen handler error:", name, err); } }
: function(e) { try { cekCall(handler, [e]); } catch(err) { console.error("[sx-ref] domListen handler error:", name, err); } })
: handler;
if (name === "click") logInfo("domListen: click on <" + (el.tagName||"?").toLowerCase() + "> text=" + (el.textContent||"").substring(0,20) + " isLambda=" + isLambda(handler));
var passiveEvents = { touchstart: 1, touchmove: 1, wheel: 1, scroll: 1 };
var opts = passiveEvents[name] ? { passive: true } : undefined;
el.addEventListener(name, wrapped, opts);
return function() { el.removeEventListener(name, wrapped, opts); };
}
function eventDetail(e) {
return (e && e.detail != null) ? e.detail : NIL;
}
function domQuery(sel) {
return _hasDom ? document.querySelector(sel) : null;
}
function domEnsureElement(sel) {
if (!_hasDom) return null;
var el = document.querySelector(sel);
if (el) return el;
// Parse #id selector → create div with that id, append to body
if (sel.charAt(0) === '#') {
el = document.createElement('div');
el.id = sel.slice(1);
document.body.appendChild(el);
return el;
}
return null;
}
function domQueryAll(root, sel) {
if (!root || !root.querySelectorAll) return [];
return Array.prototype.slice.call(root.querySelectorAll(sel));
}
function domTagName(el) { return el && el.tagName ? el.tagName : ""; }
// Island DOM helpers
function domRemove(node) {
if (node && node.parentNode) node.parentNode.removeChild(node);
}
function domChildNodes(el) {
if (!el || !el.childNodes) return [];
return Array.prototype.slice.call(el.childNodes);
}
function domRemoveChildrenAfter(marker) {
if (!marker || !marker.parentNode) return;
var parent = marker.parentNode;
while (marker.nextSibling) parent.removeChild(marker.nextSibling);
}
function domSetData(el, key, val) {
if (el) { if (!el._sxData) el._sxData = {}; el._sxData[key] = val; }
}
function domGetData(el, key) {
return (el && el._sxData) ? (el._sxData[key] != null ? el._sxData[key] : NIL) : NIL;
}
function domInnerHtml(el) {
return (el && el.innerHTML != null) ? el.innerHTML : "";
}
function jsonParse(s) {
try { return JSON.parse(s); } catch(e) { return {}; }
}
// renderDomComponent and renderDomElement are transpiled from
// adapter-dom.sx — no imperative overrides needed.
// =========================================================================
// Platform interface — Engine pure logic (browser + node compatible)
// =========================================================================
function browserLocationHref() {
return typeof location !== "undefined" ? location.href : "";
}
function browserSameOrigin(url) {
try { return new URL(url, location.href).origin === location.origin; }
catch (e) { return true; }
}
function browserPushState(url) {
if (typeof history !== "undefined") {
try { history.pushState({ sxUrl: url, scrollY: typeof window !== "undefined" ? window.scrollY : 0 }, "", url); }
catch (e) {}
}
}
function browserReplaceState(url) {
if (typeof history !== "undefined") {
try { history.replaceState({ sxUrl: url, scrollY: typeof window !== "undefined" ? window.scrollY : 0 }, "", url); }
catch (e) {}
}
}
function nowMs() { return (typeof performance !== "undefined") ? performance.now() : Date.now(); }
function parseHeaderValue(s) {
if (!s) return null;
try {
if (s.charAt(0) === "{" && s.charAt(1) === ":") return parse(s);
return JSON.parse(s);
} catch (e) { return null; }
}
// =========================================================================
// Platform interface — Orchestration (browser-only)
// =========================================================================
// --- Browser/Network ---
function browserNavigate(url) {
if (typeof location !== "undefined") location.assign(url);
}
function browserReload() {
if (typeof location !== "undefined") location.reload();
}
function browserScrollTo(x, y) {
if (typeof window !== "undefined") window.scrollTo(x, y);
}
function browserMediaMatches(query) {
if (typeof window === "undefined") return false;
return window.matchMedia(query).matches;
}
function browserConfirm(msg) {
if (typeof window === "undefined") return false;
return window.confirm(msg);
}
function browserPrompt(msg) {
if (typeof window === "undefined") return NIL;
var r = window.prompt(msg);
return r === null ? NIL : r;
}
function csrfToken() {
if (!_hasDom) return NIL;
var m = document.querySelector('meta[name="csrf-token"]');
return m ? m.getAttribute("content") : NIL;
}
function isCrossOrigin(url) {
try {
var h = new URL(url, location.href).hostname;
return h !== location.hostname &&
(h.indexOf(".rose-ash.com") >= 0 || h.indexOf(".localhost") >= 0);
} catch (e) { return false; }
}
// --- Promises ---
function promiseResolve(val) { return Promise.resolve(val); }
function promiseThen(p, onResolve, onReject) {
if (!p || !p.then) return p;
return onReject ? p.then(onResolve, onReject) : p.then(onResolve);
}
function promiseCatch(p, fn) { return p && p.catch ? p.catch(fn) : p; }
function promiseDelayed(ms, value) {
return new Promise(function(resolve) {
setTimeout(function() { resolve(value); }, ms);
});
}
// --- Abort controllers ---
var _controllers = typeof WeakMap !== "undefined" ? new WeakMap() : null;
function abortPrevious(el) {
if (_controllers) {
var prev = _controllers.get(el);
if (prev) prev.abort();
}
}
function trackController(el, ctrl) {
if (_controllers) _controllers.set(el, ctrl);
}
var _targetControllers = typeof WeakMap !== "undefined" ? new WeakMap() : null;
function abortPreviousTarget(el) {
if (_targetControllers) {
var prev = _targetControllers.get(el);
if (prev) prev.abort();
}
}
function trackControllerTarget(el, ctrl) {
if (_targetControllers) _targetControllers.set(el, ctrl);
}
function newAbortController() {
return typeof AbortController !== "undefined" ? new AbortController() : { signal: null, abort: function() {} };
}
function controllerSignal(ctrl) { return ctrl ? ctrl.signal : null; }
function isAbortError(err) { return err && err.name === "AbortError"; }
// --- Timers ---
function _wrapSxFn(fn) {
if (fn && fn._lambda) {
return function() { return trampoline(callLambda(fn, [], lambdaClosure(fn))); };
}
return fn;
}
function setTimeout_(fn, ms) { return setTimeout(_wrapSxFn(fn), ms || 0); }
function setInterval_(fn, ms) { return setInterval(_wrapSxFn(fn), ms || 1000); }
function clearTimeout_(id) { clearTimeout(id); }
function clearInterval_(id) { clearInterval(id); }
function requestAnimationFrame_(fn) {
var cb = _wrapSxFn(fn);
if (typeof requestAnimationFrame !== "undefined") requestAnimationFrame(cb);
else setTimeout(cb, 16);
}
// --- Fetch ---
function fetchRequest(config, successFn, errorFn) {
var opts = { method: config.method, headers: config.headers };
if (config.signal) opts.signal = config.signal;
if (config.body && config.method !== "GET") opts.body = config.body;
if (config["cross-origin"]) opts.credentials = "include";
var p = (config.preloaded && config.preloaded !== NIL)
? Promise.resolve({
ok: true, status: 200,
headers: new Headers({ "Content-Type": config.preloaded["content-type"] || "" }),
text: function() { return Promise.resolve(config.preloaded.text); }
})
: fetch(config.url, opts);
return p.then(function(resp) {
return resp.text().then(function(text) {
var getHeader = function(name) {
var v = resp.headers.get(name);
return v === null ? NIL : v;
};
return successFn(resp.ok, resp.status, getHeader, text);
});
}).catch(function(err) {
return errorFn(err);
});
}
function fetchLocation(headerVal) {
if (!_hasDom) return;
var locUrl = headerVal;
try { var obj = JSON.parse(headerVal); locUrl = obj.path || obj; } catch (e) {}
fetch(locUrl, { headers: { "SX-Request": "true" } }).then(function(r) {
return r.text().then(function(t) {
var main = document.getElementById("main-panel");
if (main) {
main.innerHTML = t;
postSwap(main);
try { history.pushState({ sxUrl: locUrl }, "", locUrl); } catch (e) {}
}
});
});
}
function fetchAndRestore(main, url, headers, scrollY) {
var opts = { headers: headers };
try {
var h = new URL(url, location.href).hostname;
if (h !== location.hostname &&
(h.indexOf(".rose-ash.com") >= 0 || h.indexOf(".localhost") >= 0)) {
opts.credentials = "include";
}
} catch (e) {}
fetch(url, opts).then(function(resp) {
return resp.text().then(function(text) {
text = stripComponentScripts(text);
text = extractResponseCss(text);
text = text.trim();
if (text.charAt(0) === "(") {
try {
var dom = sxRender(text);
var container = document.createElement("div");
container.appendChild(dom);
processOobSwaps(container, function(t, oob, s) {
swapDomNodes(t, oob, s);
sxHydrate(t);
processElements(t);
});
var newMain = container.querySelector("#main-panel");
morphChildren(main, newMain || container);
postSwap(main);
if (typeof window !== "undefined") window.scrollTo(0, scrollY || 0);
} catch (err) {
console.error("sx-ref popstate error:", err);
location.reload();
}
} else {
var parser = new DOMParser();
var doc = parser.parseFromString(text, "text/html");
var newMain = doc.getElementById("main-panel");
if (newMain) {
morphChildren(main, newMain);
postSwap(main);
if (typeof window !== "undefined") window.scrollTo(0, scrollY || 0);
} else {
location.reload();
}
}
});
}).catch(function(err) {
logWarn("sx:popstate fetch error " + url + " — " + (err && err.message ? err.message : err));
location.reload();
});
}
function fetchStreaming(target, url, headers) {
// Streaming fetch for multi-stream pages.
// First chunk = OOB SX swap (shell with skeletons).
// Subsequent chunks = __sxResolve script tags filling suspense slots.
var opts = { headers: headers };
try {
var h = new URL(url, location.href).hostname;
if (h !== location.hostname &&
(h.indexOf(".rose-ash.com") >= 0 || h.indexOf(".localhost") >= 0)) {
opts.credentials = "include";
}
} catch (e) {}
fetch(url, opts).then(function(resp) {
if (!resp.ok || !resp.body) {
// Fallback: non-streaming
return resp.text().then(function(text) {
text = stripComponentScripts(text);
text = extractResponseCss(text);
text = text.trim();
if (text.charAt(0) === "(") {
var dom = sxRender(text);
var container = document.createElement("div");
container.appendChild(dom);
processOobSwaps(container, function(t, oob, s) {
swapDomNodes(t, oob, s);
sxHydrate(t);
processElements(t);
});
var newMain = container.querySelector("#main-panel");
morphChildren(target, newMain || container);
postSwap(target);
}
});
}
var reader = resp.body.getReader();
var decoder = new TextDecoder();
var buffer = "";
var initialSwapDone = false;
// Regex to match __sxResolve script tags
var RESOLVE_START = "<script>window.__sxResolve&&window.__sxResolve(";
var RESOLVE_END = ")</script>";
function processResolveScripts() {
// Strip and load any extra component defs before resolve scripts
buffer = stripSxScripts(buffer);
var idx;
while ((idx = buffer.indexOf(RESOLVE_START)) >= 0) {
var endIdx = buffer.indexOf(RESOLVE_END, idx);
if (endIdx < 0) break; // incomplete, wait for more data
var argsStr = buffer.substring(idx + RESOLVE_START.length, endIdx);
buffer = buffer.substring(endIdx + RESOLVE_END.length);
// argsStr is: "stream-id","sx source"
var commaIdx = argsStr.indexOf(",");
if (commaIdx >= 0) {
try {
var id = JSON.parse(argsStr.substring(0, commaIdx));
var sx = JSON.parse(argsStr.substring(commaIdx + 1));
if (typeof Sx !== "undefined" && Sx.resolveSuspense) {
Sx.resolveSuspense(id, sx);
}
} catch (e) {
console.error("[sx-ref] resolve parse error:", e);
}
}
}
}
function pump() {
return reader.read().then(function(result) {
buffer += decoder.decode(result.value || new Uint8Array(), { stream: !result.done });
if (!initialSwapDone) {
// Look for the first resolve script — everything before it is OOB content
var scriptIdx = buffer.indexOf("<script>window.__sxResolve");
// If we found a script tag, or the stream is done, process OOB
var oobEnd = scriptIdx >= 0 ? scriptIdx : (result.done ? buffer.length : -1);
if (oobEnd >= 0) {
var oobContent = buffer.substring(0, oobEnd);
buffer = buffer.substring(oobEnd);
initialSwapDone = true;
// Process OOB SX content (same as fetchAndRestore)
oobContent = stripComponentScripts(oobContent);
// Also strip bare <script type="text/sx"> (extra defs from resolve chunks)
oobContent = stripSxScripts(oobContent);
oobContent = extractResponseCss(oobContent);
oobContent = oobContent.trim();
if (oobContent.charAt(0) === "(") {
try {
var dom = sxRender(oobContent);
var container = document.createElement("div");
container.appendChild(dom);
processOobSwaps(container, function(t, oob, s) {
swapDomNodes(t, oob, s);
sxHydrate(t);
processElements(t);
});
var newMain = container.querySelector("#main-panel");
morphChildren(target, newMain || container);
postSwap(target);
// Dispatch clientRoute so nav links update active state
domDispatch(target, "sx:clientRoute",
{ pathname: new URL(url, location.href).pathname });
} catch (err) {
console.error("[sx-ref] streaming OOB swap error:", err);
}
}
// Process any resolve scripts already in buffer
processResolveScripts();
}
} else {
// Process resolve scripts as they arrive
processResolveScripts();
}
if (!result.done) return pump();
});
}
return pump();
}).catch(function(err) {
console.error("[sx-ref] streaming fetch error:", err);
location.reload();
});
}
function fetchPreload(url, headers, cache) {
fetch(url, { headers: headers }).then(function(resp) {
if (!resp.ok) return;
var ct = resp.headers.get("Content-Type") || "";
return resp.text().then(function(text) {
preloadCacheSet(cache, url, text, ct);
});
}).catch(function(err) {
logInfo("sx:preload error " + url + " — " + (err && err.message ? err.message : err));
});
}
// --- Request body building ---
function buildRequestBody(el, method, url) {
if (!_hasDom) return { body: null, url: url, "content-type": NIL };
var body = null;
var ct = NIL;
var finalUrl = url;
var isJson = el.getAttribute("sx-encoding") === "json";
if (method !== "GET") {
var form = el.closest("form") || (el.tagName === "FORM" ? el : null);
if (form) {
if (isJson) {
var fd = new FormData(form);
var obj = {};
fd.forEach(function(v, k) {
if (obj[k] !== undefined) {
if (!Array.isArray(obj[k])) obj[k] = [obj[k]];
obj[k].push(v);
} else { obj[k] = v; }
});
body = JSON.stringify(obj);
ct = "application/json";
} else {
body = new URLSearchParams(new FormData(form));
ct = "application/x-www-form-urlencoded";
}
}
}
// sx-params
var paramsSpec = el.getAttribute("sx-params");
if (paramsSpec && body instanceof URLSearchParams) {
if (paramsSpec === "none") {
body = new URLSearchParams();
} else if (paramsSpec.indexOf("not ") === 0) {
paramsSpec.substring(4).split(",").forEach(function(k) { body.delete(k.trim()); });
} else if (paramsSpec !== "*") {
var allowed = paramsSpec.split(",").map(function(s) { return s.trim(); });
var filtered = new URLSearchParams();
allowed.forEach(function(k) {
body.getAll(k).forEach(function(v) { filtered.append(k, v); });
});
body = filtered;
}
}
// sx-include
var includeSel = el.getAttribute("sx-include");
if (includeSel && method !== "GET") {
if (!body) body = new URLSearchParams();
document.querySelectorAll(includeSel).forEach(function(inp) {
if (inp.name) body.append(inp.name, inp.value);
});
}
// sx-vals
var valsAttr = el.getAttribute("sx-vals");
if (valsAttr) {
try {
var vals = valsAttr.charAt(0) === "{" && valsAttr.charAt(1) === ":" ? parse(valsAttr) : JSON.parse(valsAttr);
if (method === "GET") {
for (var vk in vals) finalUrl += (finalUrl.indexOf("?") >= 0 ? "&" : "?") + encodeURIComponent(vk) + "=" + encodeURIComponent(vals[vk]);
} else if (body instanceof URLSearchParams) {
for (var vk2 in vals) body.append(vk2, vals[vk2]);
} else if (!body) {
body = new URLSearchParams();
for (var vk3 in vals) body.append(vk3, vals[vk3]);
ct = "application/x-www-form-urlencoded";
}
} catch (e) {}
}
// GET form data → URL
if (method === "GET") {
var form2 = el.closest("form") || (el.tagName === "FORM" ? el : null);
if (form2) {
var qs = new URLSearchParams(new FormData(form2)).toString();
if (qs) finalUrl += (finalUrl.indexOf("?") >= 0 ? "&" : "?") + qs;
}
if ((el.tagName === "INPUT" || el.tagName === "SELECT" || el.tagName === "TEXTAREA") && el.name) {
finalUrl += (finalUrl.indexOf("?") >= 0 ? "&" : "?") + encodeURIComponent(el.name) + "=" + encodeURIComponent(el.value);
}
}
return { body: body, url: finalUrl, "content-type": ct };
}
// --- Loading state ---
function showIndicator(el) {
if (!_hasDom) return NIL;
var sel = el.getAttribute("sx-indicator");
var ind = sel ? (document.querySelector(sel) || el.closest(sel)) : null;
if (ind) { ind.classList.add("sx-request"); ind.style.display = ""; }
return ind || NIL;
}
function disableElements(el) {
if (!_hasDom) return [];
var sel = el.getAttribute("sx-disabled-elt");
if (!sel) return [];
var elts = Array.prototype.slice.call(document.querySelectorAll(sel));
elts.forEach(function(e) { e.disabled = true; });
return elts;
}
function clearLoadingState(el, indicator, disabledElts) {
el.classList.remove("sx-request");
el.removeAttribute("aria-busy");
if (indicator && !isNil(indicator)) {
indicator.classList.remove("sx-request");
indicator.style.display = "none";
}
if (disabledElts) {
for (var i = 0; i < disabledElts.length; i++) disabledElts[i].disabled = false;
}
}
// --- DOM extras ---
function domQueryById(id) {
return _hasDom ? document.getElementById(id) : null;
}
function domMatches(el, sel) {
return el && el.matches ? el.matches(sel) : false;
}
function domClosest(el, sel) {
return el && el.closest ? el.closest(sel) : null;
}
function domBody() {
return _hasDom ? document.body : null;
}
function domHasClass(el, cls) {
return el && el.classList ? el.classList.contains(cls) : false;
}
function domAppendToHead(el) {
if (_hasDom && document.head) document.head.appendChild(el);
}
function domParseHtmlDocument(text) {
if (!_hasDom) return null;
return new DOMParser().parseFromString(text, "text/html");
}
function domOuterHtml(el) {
return el ? el.outerHTML : "";
}
function domBodyInnerHtml(doc) {
return doc && doc.body ? doc.body.innerHTML : "";
}
// --- Events ---
function preventDefault_(e) { if (e && e.preventDefault) e.preventDefault(); }
function stopPropagation_(e) { if (e && e.stopPropagation) e.stopPropagation(); }
function eventModifierKey_p(e) { return !!(e && (e.ctrlKey || e.metaKey || e.shiftKey || e.altKey)); }
function domFocus(el) { if (el && el.focus) el.focus(); }
function tryCatch(tryFn, catchFn) {
var t = _wrapSxFn(tryFn);
var c = catchFn && catchFn._lambda
? function(e) { return trampoline(callLambda(catchFn, [e], lambdaClosure(catchFn))); }
: catchFn;
try { return t(); } catch (e) { return c(e); }
}
function cekTry(thunkFn, handlerFn) {
try {
var result = _wrapSxFn(thunkFn)();
if (!handlerFn || handlerFn === NIL) return [makeSymbol("ok"), result];
return result;
} catch (e) {
var msg = (e && e.message) ? e.message : String(e);
if (handlerFn && handlerFn !== NIL) return _wrapSxFn(handlerFn)(msg);
return [makeSymbol("error"), msg];
}
}
function errorMessage(e) {
return e && e.message ? e.message : String(e);
}
function scheduleIdle(fn) {
var cb = _wrapSxFn(fn);
if (typeof cb !== "function") {
console.error("[sx-ref] scheduleIdle: callback not callable, fn type:", typeof fn, "fn:", fn, "_lambda:", fn && fn._lambda);
return;
}
if (typeof requestIdleCallback !== "undefined") requestIdleCallback(cb);
else setTimeout(cb, 0);
}
function elementValue(el) { return el && el.value !== undefined ? el.value : NIL; }
function domAddListener(el, event, fn, opts) {
if (!el || !el.addEventListener) return;
var o = {};
if (opts && !isNil(opts)) {
if (opts.once || opts["once"]) o.once = true;
}
el.addEventListener(event, function(e) {
try { fn(e); } catch (err) { logInfo("EVENT ERROR: " + event + " " + (err && err.message ? err.message : err)); console.error("[sx-ref] event handler error:", event, err); }
}, o);
}
// --- Validation ---
function validateForRequest(el) {
if (!_hasDom) return true;
var attr = el.getAttribute("sx-validate");
if (attr === null) {
var vForm = el.closest("[sx-validate]");
if (vForm) attr = vForm.getAttribute("sx-validate");
}
if (attr === null) return true; // no validation configured
var form = el.tagName === "FORM" ? el : el.closest("form");
if (form && !form.reportValidity()) return false;
if (attr && attr !== "true" && attr !== "") {
var fn = window[attr];
if (typeof fn === "function" && !fn(el)) return false;
}
return true;
}
// --- View Transitions ---
function withTransition(enabled, fn) {
if (enabled && _hasDom && document.startViewTransition) {
document.startViewTransition(fn);
} else {
fn();
}
}
// --- IntersectionObserver ---
function observeIntersection(el, fn, once, delay) {
if (!_hasDom || !("IntersectionObserver" in window)) { fn(); return; }
var fired = false;
var d = isNil(delay) ? 0 : delay;
var obs = new IntersectionObserver(function(entries) {
entries.forEach(function(entry) {
if (!entry.isIntersecting) return;
if (once && fired) return;
fired = true;
if (once) obs.unobserve(el);
if (d) setTimeout(fn, d); else fn();
});
});
obs.observe(el);
}
// --- EventSource ---
function eventSourceConnect(url, el) {
var source = new EventSource(url);
source.addEventListener("error", function() { domDispatch(el, "sx:sseError", {}); });
source.addEventListener("open", function() { domDispatch(el, "sx:sseOpen", {}); });
if (typeof MutationObserver !== "undefined") {
var obs = new MutationObserver(function() {
if (!document.body.contains(el)) { source.close(); obs.disconnect(); }
});
obs.observe(document.body, { childList: true, subtree: true });
}
return source;
}
function eventSourceListen(source, event, fn) {
source.addEventListener(event, function(e) { fn(e.data); });
}
// --- Boost bindings ---
function bindBoostLink(el, _href) {
el.addEventListener("click", function(e) {
if (e.ctrlKey || e.metaKey || e.shiftKey || e.altKey) return;
e.preventDefault();
// Re-read href from element at click time (not closed-over value)
var liveHref = el.getAttribute("href") || _href;
console.log("[sx-debug] bindBoostLink click:", liveHref, "el:", el.tagName, el.textContent.slice(0,30));
executeRequest(el, { method: "GET", url: liveHref }).then(function() {
console.log("[sx-debug] boost fetch OK, pushState:", liveHref);
try { history.pushState({ sxUrl: liveHref, scrollY: window.scrollY }, "", liveHref); } catch (err) {}
}).catch(function(err) {
console.error("[sx-debug] boost fetch ERROR:", err);
});
});
}
function bindBoostForm(form, _method, _action) {
form.addEventListener("submit", function(e) {
e.preventDefault();
// Re-read from element at submit time
var liveMethod = (form.getAttribute("method") || _method || "GET").toUpperCase();
var liveAction = form.getAttribute("action") || _action || location.href;
executeRequest(form, { method: liveMethod, url: liveAction }).then(function() {
try { history.pushState({ sxUrl: liveAction, scrollY: window.scrollY }, "", liveAction); } catch (err) {}
}).catch(function(err) {
logWarn("sx:boost form error " + liveMethod + " " + liveAction + " — " + (err && err.message ? err.message : err));
});
});
}
// --- Client-side route bindings ---
function bindClientRouteClick(link, _href, fallbackFn) {
link.addEventListener("click", function(e) {
if (e.ctrlKey || e.metaKey || e.shiftKey || e.altKey) return;
e.preventDefault();
// Re-read href from element at click time (not closed-over value)
var liveHref = link.getAttribute("href") || _href;
var pathname = urlPathname(liveHref);
console.log("[sx-debug] bindClientRouteClick:", pathname, "el:", link.tagName, link.textContent.slice(0,30));
// Find target selector: sx-boost ancestor, explicit sx-target, or #main-panel
var boostEl = link.closest("[sx-boost]");
var targetSel = boostEl ? boostEl.getAttribute("sx-boost") : null;
if (!targetSel || targetSel === "true") {
targetSel = link.getAttribute("sx-target") || "#main-panel";
}
console.log("[sx-debug] targetSel:", targetSel, "trying client route...");
if (tryClientRoute(pathname, targetSel)) {
console.log("[sx-debug] client route SUCCESS, pushState:", liveHref);
try { history.pushState({ sxUrl: liveHref, scrollY: window.scrollY }, "", liveHref); } catch (err) {}
if (typeof window !== "undefined") window.scrollTo(0, 0);
} else {
console.log("[sx-debug] client route FAILED, server fetch:", liveHref);
executeRequest(link, { method: "GET", url: liveHref }).then(function() {
console.log("[sx-debug] server fetch OK, pushState:", liveHref);
try { history.pushState({ sxUrl: liveHref, scrollY: window.scrollY }, "", liveHref); } catch (err) {}
}).catch(function(err) {
console.error("[sx-debug] server fetch ERROR:", err);
});
}
});
}
function tryEvalContent(source, env) {
try {
var merged = merge(componentEnv);
if (env && !isNil(env)) {
var ks = Object.keys(env);
for (var i = 0; i < ks.length; i++) merged[ks[i]] = env[ks[i]];
}
return sxRenderWithEnv(source, merged);
} catch (e) {
logInfo("sx:route eval miss: " + (e && e.message ? e.message : e));
return NIL;
}
}
// Async eval with callback — used for pages with IO deps.
// Calls callback(rendered) when done, callback(null) on failure.
function tryAsyncEvalContent(source, env, callback) {
var merged = merge(componentEnv);
if (env && !isNil(env)) {
var ks = Object.keys(env);
for (var i = 0; i < ks.length; i++) merged[ks[i]] = env[ks[i]];
}
try {
var result = asyncSxRenderWithEnv(source, merged);
if (isPromise(result)) {
result.then(function(rendered) {
callback(rendered);
}).catch(function(e) {
logWarn("sx:async eval miss: " + (e && e.message ? e.message : e));
callback(null);
});
} else {
callback(result);
}
} catch (e) {
logInfo("sx:async eval miss: " + (e && e.message ? e.message : e));
callback(null);
}
}
function resolvePageData(pageName, params, callback) {
// Platform implementation: fetch page data via HTTP from /sx/data/ endpoint.
// The spec only knows about resolve-page-data(name, params, callback) —
// this function provides the concrete transport.
var url = "/sx/data/" + encodeURIComponent(pageName);
if (params && !isNil(params)) {
var qs = [];
var ks = Object.keys(params);
for (var i = 0; i < ks.length; i++) {
var v = params[ks[i]];
if (v !== null && v !== undefined && v !== NIL) {
qs.push(encodeURIComponent(ks[i]) + "=" + encodeURIComponent(v));
}
}
if (qs.length) url += "?" + qs.join("&");
}
var headers = { "SX-Request": "true" };
fetch(url, { headers: headers }).then(function(resp) {
if (!resp.ok) {
logWarn("sx:data resolve failed " + resp.status + " for " + pageName);
return;
}
return resp.text().then(function(text) {
try {
var exprs = parse(text);
var data = exprs.length === 1 ? exprs[0] : {};
callback(data || {});
} catch (e) {
logWarn("sx:data parse error for " + pageName + ": " + (e && e.message ? e.message : e));
}
});
}).catch(function(err) {
logWarn("sx:data resolve error for " + pageName + ": " + (err && err.message ? err.message : err));
});
}
function parseSxData(text) {
// Parse SX text into a data value. Returns the first parsed expression,
// or NIL on error. Used by cache update directives.
try {
var exprs = parse(text);
return exprs.length >= 1 ? exprs[0] : NIL;
} catch (e) {
logWarn("sx:cache parse error: " + (e && e.message ? e.message : e));
return NIL;
}
}
function swPostMessage(msg) {
// Send a message to the active service worker (if registered).
// Used to notify SW of cache invalidation.
if (typeof navigator !== "undefined" && navigator.serviceWorker &&
navigator.serviceWorker.controller) {
navigator.serviceWorker.controller.postMessage(msg);
}
}
function urlPathname(href) {
try {
return new URL(href, location.href).pathname;
} catch (e) {
// Fallback: strip query/hash
var idx = href.indexOf("?");
if (idx >= 0) href = href.substring(0, idx);
idx = href.indexOf("#");
if (idx >= 0) href = href.substring(0, idx);
return href;
}
}
// --- Preload binding ---
function bindPreload(el, events, debounceMs, fn) {
var timer = null;
events.forEach(function(evt) {
el.addEventListener(evt, function() {
if (debounceMs) {
clearTimeout(timer);
timer = setTimeout(fn, debounceMs);
} else {
fn();
}
}, { passive: true });
});
}
// --- Processing markers ---
var PROCESSED = "_sxBound";
function markProcessed(el, key) { el[PROCESSED + key] = true; }
function isProcessed(el, key) { return !!el[PROCESSED + key]; }
function clearProcessed(el, key) { delete el[PROCESSED + key]; }
// --- Script cloning ---
function createScriptClone(dead) {
var live = document.createElement("script");
for (var i = 0; i < dead.attributes.length; i++)
live.setAttribute(dead.attributes[i].name, dead.attributes[i].value);
live.textContent = dead.textContent;
return live;
}
// --- SX API references ---
function sxRender(source) {
var SxObj = typeof Sx !== "undefined" ? Sx : null;
if (SxObj && SxObj.render) return SxObj.render(source);
throw new Error("No SX renderer available");
}
function sxProcessScripts(root) {
var SxObj = typeof Sx !== "undefined" ? Sx : null;
var r = (root && root !== NIL) ? root : undefined;
if (SxObj && SxObj.processScripts) SxObj.processScripts(r);
}
function sxHydrate(root) {
var SxObj = typeof Sx !== "undefined" ? Sx : null;
var r = (root && root !== NIL) ? root : undefined;
if (SxObj && SxObj.hydrate) SxObj.hydrate(r);
}
function loadedComponentNames() {
var SxObj = typeof Sx !== "undefined" ? Sx : null;
if (!SxObj) return [];
var env = SxObj.componentEnv || (SxObj.getEnv ? SxObj.getEnv() : {});
return Object.keys(env).filter(function(k) { return k.charAt(0) === "~"; });
}
// --- Response processing ---
function stripComponentScripts(text) {
var SxObj = typeof Sx !== "undefined" ? Sx : null;
return text.replace(/<script[^>]*type="text\/sx"[^>]*data-components[^>]*>([\s\S]*?)<\/script>/gi,
function(_, defs) { if (SxObj && SxObj.loadComponents) SxObj.loadComponents(defs); return ""; });
}
function stripSxScripts(text) {
// Strip <script type="text/sx">...</script> (without data-components or data-init).
// These contain extra component defs from streaming resolve chunks.
// data-init scripts are preserved for process-sx-scripts to evaluate as side effects.
var SxObj = typeof Sx !== "undefined" ? Sx : null;
return text.replace(/<script[^>]*type="text\/sx"[^>]*>[\s\S]*?<\/script>/gi,
function(match) {
if (/data-init/.test(match)) return match; // preserve data-init scripts
var m = match.match(/<script[^>]*>([\s\S]*?)<\/script>/i);
if (m && SxObj && SxObj.loadComponents) SxObj.loadComponents(m[1]);
return "";
});
}
function extractResponseCss(text) {
if (!_hasDom) return text;
var target = document.getElementById("sx-css");
if (!target) return text;
return text.replace(/<style[^>]*data-sx-css[^>]*>([\s\S]*?)<\/style>/gi,
function(_, css) { target.textContent += css; return ""; });
}
function selectFromContainer(container, sel) {
var frag = document.createDocumentFragment();
sel.split(",").forEach(function(s) {
container.querySelectorAll(s.trim()).forEach(function(m) { frag.appendChild(m); });
});
return frag;
}
function childrenToFragment(container) {
var frag = document.createDocumentFragment();
while (container.firstChild) frag.appendChild(container.firstChild);
return frag;
}
function selectHtmlFromDoc(doc, sel) {
var parts = sel.split(",").map(function(s) { return s.trim(); });
var frags = [];
parts.forEach(function(s) {
doc.querySelectorAll(s).forEach(function(m) { frags.push(m.outerHTML); });
});
return frags.join("");
}
// --- Parsing ---
function tryParseJson(s) {
if (!s) return NIL;
try { return JSON.parse(s); } catch (e) { return NIL; }
}
// =========================================================================
// Platform interface — Boot (mount, hydrate, scripts, cookies)
// =========================================================================
function resolveMountTarget(target) {
if (typeof target === "string") return _hasDom ? document.querySelector(target) : null;
return target;
}
function sxRenderWithEnv(source, extraEnv) {
var env = extraEnv ? merge(componentEnv, extraEnv) : componentEnv;
var exprs = parse(source);
if (!_hasDom) return null;
var frag = document.createDocumentFragment();
for (var i = 0; i < exprs.length; i++) {
var node = renderToDom(exprs[i], env, null);
if (node && !node._spread) frag.appendChild(node);
}
return frag;
}
function getRenderEnv(extraEnv) {
return extraEnv ? merge(componentEnv, PRIMITIVES, extraEnv) : merge(componentEnv, PRIMITIVES);
}
function mergeEnvs(base, newEnv) {
return newEnv ? merge(componentEnv, base, newEnv) : merge(componentEnv, base);
}
function sxLoadComponents(text) {
try {
var exprs = parse(text);
for (var i = 0; i < exprs.length; i++) trampoline(evalExpr(exprs[i], componentEnv));
} catch (err) {
logParseError("loadComponents", text, err);
throw err;
}
}
function setDocumentTitle(s) {
if (_hasDom) document.title = s || "";
}
function removeHeadElement(sel) {
if (!_hasDom) return;
var old = document.head.querySelector(sel);
if (old) old.parentNode.removeChild(old);
}
function querySxScripts(root) {
if (!_hasDom) return [];
var r = (root && root !== NIL) ? root : document;
return Array.prototype.slice.call(
r.querySelectorAll('script[type="text/sx"]'));
}
function queryPageScripts() {
if (!_hasDom) return [];
return Array.prototype.slice.call(
document.querySelectorAll('script[type="text/sx-pages"]'));
}
// --- localStorage ---
function localStorageGet(key) {
try { var v = localStorage.getItem(key); return v === null ? NIL : v; }
catch (e) { return NIL; }
}
function localStorageSet(key, val) {
try { localStorage.setItem(key, val); } catch (e) {}
}
function localStorageRemove(key) {
try { localStorage.removeItem(key); } catch (e) {}
}
// localStorage primitives registered in CEK_FIXUPS_JS for ordering
// --- Cookies ---
function setSxCompCookie(hash) {
if (_hasDom) document.cookie = "sx-comp-hash=" + hash + ";path=/;max-age=31536000;SameSite=Lax";
}
function clearSxCompCookie() {
if (_hasDom) document.cookie = "sx-comp-hash=;path=/;max-age=0;SameSite=Lax";
}
// --- Env helpers ---
function parseEnvAttr(el) {
var attr = el && el.getAttribute ? el.getAttribute("data-sx-env") : null;
if (!attr) return {};
try { return JSON.parse(attr); } catch (e) { return {}; }
}
function storeEnvAttr(el, base, newEnv) {
var merged = merge(base, newEnv);
if (el && el.setAttribute) el.setAttribute("data-sx-env", JSON.stringify(merged));
}
function toKebab(s) { return s.replace(/_/g, "-"); }
// --- Logging ---
function logInfo(msg) {
if (typeof console !== "undefined") console.log("[sx-ref] " + msg);
}
function logWarn(msg) {
if (typeof console !== "undefined") console.warn("[sx-ref] " + msg);
}
function logParseError(label, text, err) {
if (typeof console === "undefined") return;
var msg = err && err.message ? err.message : String(err);
var colMatch = msg.match(/col (\d+)/);
var lineMatch = msg.match(/line (\d+)/);
if (colMatch && text) {
var errLine = lineMatch ? parseInt(lineMatch[1]) : 1;
var errCol = parseInt(colMatch[1]);
var lines = text.split("\n");
var pos = 0;
for (var i = 0; i < errLine - 1 && i < lines.length; i++) pos += lines[i].length + 1;
pos += errCol;
var ws = 80;
var start = Math.max(0, pos - ws);
var end = Math.min(text.length, pos + ws);
console.error("[sx-ref] " + label + ":", msg,
"\n around error (pos ~" + pos + "):",
"\n \u00ab" + text.substring(start, pos) + "\u26d4" + text.substring(pos, end) + "\u00bb");
} else {
console.error("[sx-ref] " + label + ":", msg);
}
}
// =========================================================================
// Async IO: Promise-aware rendering for client-side IO primitives
// =========================================================================
//
// IO primitives (query, current-user, etc.) return Promises on the client.
// asyncRenderToDom walks the component tree; when it encounters an IO
// primitive, it awaits the Promise and continues rendering.
//
// The sync evaluator/renderer is untouched. This is a separate async path
// used only when a page's component tree contains IO references.
var IO_PRIMITIVES = {};
function registerIoPrimitive(name, fn) {
IO_PRIMITIVES[name] = fn;
}
function isPromise(x) {
return x != null && typeof x === "object" && typeof x.then === "function";
}
// Async trampoline: resolves thunks, awaits Promises
function asyncTrampoline(val) {
if (isPromise(val)) return val.then(asyncTrampoline);
if (isThunk(val)) return asyncTrampoline(evalExpr(thunkExpr(val), thunkEnv(val)));
return val;
}
// Async eval: like trampoline(evalExpr(...)) but handles IO primitives
function asyncEval(expr, env) {
// Intercept IO primitive calls at the AST level
if (Array.isArray(expr) && expr.length > 0) {
var head = expr[0];
if (head && head._sym) {
var name = head.name;
if (IO_PRIMITIVES[name]) {
// Evaluate args, then call the IO primitive
return asyncEvalIoCall(name, expr.slice(1), env);
}
}
}
// Non-IO: use sync eval, but result might be a thunk
var result = evalExpr(expr, env);
return asyncTrampoline(result);
}
function asyncEvalIoCall(name, rawArgs, env) {
// Parse keyword args and positional args, evaluating each (may be async)
var kwargs = {};
var args = [];
var promises = [];
var i = 0;
while (i < rawArgs.length) {
var arg = rawArgs[i];
if (arg && arg._kw && (i + 1) < rawArgs.length) {
var kName = arg.name;
var kVal = asyncEval(rawArgs[i + 1], env);
if (isPromise(kVal)) {
(function(k) { promises.push(kVal.then(function(v) { kwargs[k] = v; })); })(kName);
} else {
kwargs[kName] = kVal;
}
i += 2;
} else {
var aVal = asyncEval(arg, env);
if (isPromise(aVal)) {
(function(idx) { promises.push(aVal.then(function(v) { args[idx] = v; })); })(args.length);
args.push(null); // placeholder
} else {
args.push(aVal);
}
i++;
}
}
var ioFn = IO_PRIMITIVES[name];
if (promises.length > 0) {
return Promise.all(promises).then(function() { return ioFn(args, kwargs); });
}
return ioFn(args, kwargs);
}
// Async render-to-dom: returns Promise<Node> or Node
function asyncRenderToDom(expr, env, ns) {
// Literals
if (expr === NIL || expr === null || expr === undefined) return null;
if (expr === true || expr === false) return null;
if (typeof expr === "string") return document.createTextNode(expr);
if (typeof expr === "number") return document.createTextNode(String(expr));
// Symbol -> async eval then render
if (expr && expr._sym) {
var val = asyncEval(expr, env);
if (isPromise(val)) return val.then(function(v) { return asyncRenderToDom(v, env, ns); });
return asyncRenderToDom(val, env, ns);
}
// Keyword
if (expr && expr._kw) return document.createTextNode(expr.name);
// DocumentFragment / DOM nodes pass through
if (expr instanceof DocumentFragment || (expr && expr.nodeType)) return expr;
// Dict -> skip
if (expr && typeof expr === "object" && !Array.isArray(expr)) return null;
// List
if (!Array.isArray(expr) || expr.length === 0) return null;
var head = expr[0];
if (!head) return null;
// Symbol head
if (head._sym) {
var hname = head.name;
// IO primitive
if (IO_PRIMITIVES[hname]) {
var ioResult = asyncEval(expr, env);
if (isPromise(ioResult)) return ioResult.then(function(v) { return asyncRenderToDom(v, env, ns); });
return asyncRenderToDom(ioResult, env, ns);
}
// Fragment
if (hname === "<>") return asyncRenderChildren(expr.slice(1), env, ns);
// raw!
if (hname === "raw!") {
return asyncEvalRaw(expr.slice(1), env);
}
// Special forms that need async handling
if (hname === "if") return asyncRenderIf(expr, env, ns);
if (hname === "when") return asyncRenderWhen(expr, env, ns);
if (hname === "cond") return asyncRenderCond(expr, env, ns);
if (hname === "case") return asyncRenderCase(expr, env, ns);
if (hname === "let" || hname === "let*") return asyncRenderLet(expr, env, ns);
if (hname === "begin" || hname === "do") return asyncRenderChildren(expr.slice(1), env, ns);
if (hname === "map") return asyncRenderMap(expr, env, ns);
if (hname === "map-indexed") return asyncRenderMapIndexed(expr, env, ns);
if (hname === "for-each") return asyncRenderMap(expr, env, ns);
// define/defcomp/defmacro and custom special forms — eval for side effects
if (hname === "define" || hname === "defcomp" || hname === "defmacro" ||
hname === "defstyle" || hname === "defhandler" ||
hname === "deftype" || hname === "defeffect" ||
(typeof _customSpecialForms !== "undefined" && _customSpecialForms[hname])) {
trampoline(evalExpr(expr, env));
return null;
}
// quote
if (hname === "quote") return null;
// lambda/fn
if (hname === "lambda" || hname === "fn") {
trampoline(evalExpr(expr, env));
return null;
}
// and/or — eval and render result
if (hname === "and" || hname === "or" || hname === "->") {
var aoResult = asyncEval(expr, env);
if (isPromise(aoResult)) return aoResult.then(function(v) { return asyncRenderToDom(v, env, ns); });
return asyncRenderToDom(aoResult, env, ns);
}
// set!
if (hname === "set!") {
asyncEval(expr, env);
return null;
}
// Component or Island
if (hname.charAt(0) === "~") {
var comp = env[hname];
if (comp && comp._island) return renderDomIsland(comp, expr.slice(1), env, ns);
if (comp && comp._component) return asyncRenderComponent(comp, expr.slice(1), env, ns);
if (comp && comp._macro) {
var expanded = trampoline(expandMacro(comp, expr.slice(1), env));
return asyncRenderToDom(expanded, env, ns);
}
}
// Macro
if (env[hname] && env[hname]._macro) {
var mac = env[hname];
var expanded = trampoline(expandMacro(mac, expr.slice(1), env));
return asyncRenderToDom(expanded, env, ns);
}
// HTML tag
if (typeof renderDomElement === "function" && contains(HTML_TAGS, hname)) {
return asyncRenderElement(hname, expr.slice(1), env, ns);
}
// html: prefix
if (hname.indexOf("html:") === 0) {
return asyncRenderElement(hname.slice(5), expr.slice(1), env, ns);
}
// Custom element
if (hname.indexOf("-") >= 0 && expr.length > 1 && expr[1] && expr[1]._kw) {
return asyncRenderElement(hname, expr.slice(1), env, ns);
}
// SVG context
if (ns) return asyncRenderElement(hname, expr.slice(1), env, ns);
// Fallback: eval and render
var fResult = asyncEval(expr, env);
if (isPromise(fResult)) return fResult.then(function(v) { return asyncRenderToDom(v, env, ns); });
return asyncRenderToDom(fResult, env, ns);
}
// Non-symbol head: eval call
var cResult = asyncEval(expr, env);
if (isPromise(cResult)) return cResult.then(function(v) { return asyncRenderToDom(v, env, ns); });
return asyncRenderToDom(cResult, env, ns);
}
function asyncRenderChildren(exprs, env, ns) {
var frag = document.createDocumentFragment();
var pending = [];
for (var i = 0; i < exprs.length; i++) {
var result = asyncRenderToDom(exprs[i], env, ns);
if (isPromise(result)) {
// Insert placeholder, replace when resolved
var placeholder = document.createComment("async");
frag.appendChild(placeholder);
(function(ph) {
pending.push(result.then(function(node) {
if (node) ph.parentNode.replaceChild(node, ph);
else ph.parentNode.removeChild(ph);
}));
})(placeholder);
} else if (result && !result._spread) {
frag.appendChild(result);
}
}
if (pending.length > 0) {
return Promise.all(pending).then(function() { return frag; });
}
return frag;
}
function asyncRenderElement(tag, args, env, ns) {
var newNs = tag === "svg" ? SVG_NS : tag === "math" ? MATH_NS : ns;
var el = domCreateElement(tag, newNs);
var pending = [];
var isVoid = contains(VOID_ELEMENTS, tag);
for (var i = 0; i < args.length; i++) {
var arg = args[i];
if (arg && arg._kw && (i + 1) < args.length) {
var attrName = arg.name;
var attrVal = asyncEval(args[i + 1], env);
i++;
if (isPromise(attrVal)) {
(function(an, av) {
pending.push(av.then(function(v) {
if (!isNil(v) && v !== false) {
if (contains(BOOLEAN_ATTRS, an)) { if (isSxTruthy(v)) el.setAttribute(an, ""); }
else if (v === true) el.setAttribute(an, "");
else el.setAttribute(an, String(v));
}
}));
})(attrName, attrVal);
} else {
if (!isNil(attrVal) && attrVal !== false) {
if (contains(BOOLEAN_ATTRS, attrName)) {
if (isSxTruthy(attrVal)) el.setAttribute(attrName, "");
} else if (attrVal === true) {
el.setAttribute(attrName, "");
} else {
el.setAttribute(attrName, String(attrVal));
}
}
}
} else if (!isVoid) {
var child = asyncRenderToDom(arg, env, newNs);
if (isPromise(child)) {
var placeholder = document.createComment("async");
el.appendChild(placeholder);
(function(ph) {
pending.push(child.then(function(node) {
if (node) ph.parentNode.replaceChild(node, ph);
else ph.parentNode.removeChild(ph);
}));
})(placeholder);
} else if (child) {
if (child._spread) {
// Spread: merge attrs onto parent element
var sa = child.attrs || {};
for (var sk in sa) {
if (sk === "class") {
var ec = el.getAttribute("class") || "";
el.setAttribute("class", ec ? ec + " " + sa[sk] : sa[sk]);
} else if (sk === "style") {
var es = el.getAttribute("style") || "";
el.setAttribute("style", es ? es + ";" + sa[sk] : sa[sk]);
} else {
el.setAttribute(sk, String(sa[sk]));
}
}
} else {
el.appendChild(child);
}
}
}
}
if (pending.length > 0) return Promise.all(pending).then(function() { return el; });
return el;
}
function asyncRenderComponent(comp, args, env, ns) {
var kwargs = {};
var children = [];
var pending = [];
for (var i = 0; i < args.length; i++) {
var arg = args[i];
if (arg && arg._kw && (i + 1) < args.length) {
var kName = arg.name;
var kVal = asyncEval(args[i + 1], env);
if (isPromise(kVal)) {
(function(k) { pending.push(kVal.then(function(v) { kwargs[k] = v; })); })(kName);
} else {
kwargs[kName] = kVal;
}
i++;
} else {
children.push(arg);
}
}
function doRender() {
var local = Object.create(componentClosure(comp));
for (var k in env) if (env.hasOwnProperty(k)) local[k] = env[k];
var params = componentParams(comp);
for (var j = 0; j < params.length; j++) {
local[params[j]] = params[j] in kwargs ? kwargs[params[j]] : NIL;
}
if (componentHasChildren(comp)) {
var childResult = asyncRenderChildren(children, env, ns);
if (isPromise(childResult)) {
return childResult.then(function(childFrag) {
local["children"] = childFrag;
return asyncRenderToDom(componentBody(comp), local, ns);
});
}
local["children"] = childResult;
}
return asyncRenderToDom(componentBody(comp), local, ns);
}
if (pending.length > 0) return Promise.all(pending).then(doRender);
return doRender();
}
function asyncRenderIf(expr, env, ns) {
var cond = asyncEval(expr[1], env);
if (isPromise(cond)) {
return cond.then(function(v) {
return isSxTruthy(v)
? asyncRenderToDom(expr[2], env, ns)
: (expr.length > 3 ? asyncRenderToDom(expr[3], env, ns) : null);
});
}
return isSxTruthy(cond)
? asyncRenderToDom(expr[2], env, ns)
: (expr.length > 3 ? asyncRenderToDom(expr[3], env, ns) : null);
}
function asyncRenderWhen(expr, env, ns) {
var cond = asyncEval(expr[1], env);
if (isPromise(cond)) {
return cond.then(function(v) {
return isSxTruthy(v) ? asyncRenderChildren(expr.slice(2), env, ns) : null;
});
}
return isSxTruthy(cond) ? asyncRenderChildren(expr.slice(2), env, ns) : null;
}
function asyncRenderCond(expr, env, ns) {
var clauses = expr.slice(1);
function step(idx) {
if (idx >= clauses.length) return null;
var clause = clauses[idx];
if (!Array.isArray(clause) || clause.length < 2) return step(idx + 1);
var test = clause[0];
if ((test && test._sym && (test.name === "else" || test.name === ":else")) ||
(test && test._kw && test.name === "else")) {
return asyncRenderToDom(clause[1], env, ns);
}
var v = asyncEval(test, env);
if (isPromise(v)) return v.then(function(r) { return isSxTruthy(r) ? asyncRenderToDom(clause[1], env, ns) : step(idx + 1); });
return isSxTruthy(v) ? asyncRenderToDom(clause[1], env, ns) : step(idx + 1);
}
return step(0);
}
function asyncRenderCase(expr, env, ns) {
var matchVal = asyncEval(expr[1], env);
function doCase(mv) {
var clauses = expr.slice(2);
for (var i = 0; i < clauses.length - 1; i += 2) {
var test = clauses[i];
if ((test && test._kw && test.name === "else") ||
(test && test._sym && (test.name === "else" || test.name === ":else"))) {
return asyncRenderToDom(clauses[i + 1], env, ns);
}
var tv = trampoline(evalExpr(test, env));
if (mv === tv || (typeof mv === "string" && typeof tv === "string" && mv === tv)) {
return asyncRenderToDom(clauses[i + 1], env, ns);
}
}
return null;
}
if (isPromise(matchVal)) return matchVal.then(doCase);
return doCase(matchVal);
}
function asyncRenderLet(expr, env, ns) {
var bindings = expr[1];
var local = Object.create(env);
for (var k in env) if (env.hasOwnProperty(k)) local[k] = env[k];
function bindStep(idx) {
if (!Array.isArray(bindings)) return asyncRenderChildren(expr.slice(2), local, ns);
// Nested pairs: ((a 1) (b 2))
if (bindings.length > 0 && Array.isArray(bindings[0])) {
if (idx >= bindings.length) return asyncRenderChildren(expr.slice(2), local, ns);
var b = bindings[idx];
var vname = b[0]._sym ? b[0].name : String(b[0]);
var val = asyncEval(b[1], local);
if (isPromise(val)) return val.then(function(v) { local[vname] = v; return bindStep(idx + 1); });
local[vname] = val;
return bindStep(idx + 1);
}
// Flat pairs: (a 1 b 2)
if (idx >= bindings.length) return asyncRenderChildren(expr.slice(2), local, ns);
var vn = bindings[idx]._sym ? bindings[idx].name : String(bindings[idx]);
var vv = asyncEval(bindings[idx + 1], local);
if (isPromise(vv)) return vv.then(function(v) { local[vn] = v; return bindStep(idx + 2); });
local[vn] = vv;
return bindStep(idx + 2);
}
return bindStep(0);
}
function asyncRenderMap(expr, env, ns) {
var fn = asyncEval(expr[1], env);
var coll = asyncEval(expr[2], env);
function doMap(f, c) {
if (!Array.isArray(c)) return null;
var frag = document.createDocumentFragment();
var pending = [];
for (var i = 0; i < c.length; i++) {
var item = c[i];
var result;
if (f && f._lambda) {
var lenv = Object.create(f.closure || env);
for (var k in env) if (env.hasOwnProperty(k)) lenv[k] = env[k];
lenv[f.params[0]] = item;
result = asyncRenderToDom(f.body, lenv, null);
} else if (typeof f === "function") {
var r = f(item);
result = isPromise(r) ? r.then(function(v) { return asyncRenderToDom(v, env, null); }) : asyncRenderToDom(r, env, null);
} else {
result = asyncRenderToDom(item, env, null);
}
if (isPromise(result)) {
var ph = document.createComment("async");
frag.appendChild(ph);
(function(p) { pending.push(result.then(function(n) { if (n) p.parentNode.replaceChild(n, p); else p.parentNode.removeChild(p); })); })(ph);
} else if (result && !result._spread) {
frag.appendChild(result);
}
}
if (pending.length) return Promise.all(pending).then(function() { return frag; });
return frag;
}
if (isPromise(fn) || isPromise(coll)) {
return Promise.all([isPromise(fn) ? fn : Promise.resolve(fn), isPromise(coll) ? coll : Promise.resolve(coll)])
.then(function(r) { return doMap(r[0], r[1]); });
}
return doMap(fn, coll);
}
function asyncRenderMapIndexed(expr, env, ns) {
var fn = asyncEval(expr[1], env);
var coll = asyncEval(expr[2], env);
function doMap(f, c) {
if (!Array.isArray(c)) return null;
var frag = document.createDocumentFragment();
var pending = [];
for (var i = 0; i < c.length; i++) {
var item = c[i];
var result;
if (f && f._lambda) {
var lenv = Object.create(f.closure || env);
for (var k in env) if (env.hasOwnProperty(k)) lenv[k] = env[k];
lenv[f.params[0]] = i;
lenv[f.params[1]] = item;
result = asyncRenderToDom(f.body, lenv, null);
} else if (typeof f === "function") {
var r = f(i, item);
result = isPromise(r) ? r.then(function(v) { return asyncRenderToDom(v, env, null); }) : asyncRenderToDom(r, env, null);
} else {
result = asyncRenderToDom(item, env, null);
}
if (isPromise(result)) {
var ph = document.createComment("async");
frag.appendChild(ph);
(function(p) { pending.push(result.then(function(n) { if (n) p.parentNode.replaceChild(n, p); else p.parentNode.removeChild(p); })); })(ph);
} else if (result && !result._spread) {
frag.appendChild(result);
}
}
if (pending.length) return Promise.all(pending).then(function() { return frag; });
return frag;
}
if (isPromise(fn) || isPromise(coll)) {
return Promise.all([isPromise(fn) ? fn : Promise.resolve(fn), isPromise(coll) ? coll : Promise.resolve(coll)])
.then(function(r) { return doMap(r[0], r[1]); });
}
return doMap(fn, coll);
}
function asyncEvalRaw(args, env) {
var parts = [];
var pending = [];
for (var i = 0; i < args.length; i++) {
var val = asyncEval(args[i], env);
if (isPromise(val)) {
(function(idx) {
pending.push(val.then(function(v) { parts[idx] = v; }));
})(parts.length);
parts.push(null);
} else {
parts.push(val);
}
}
function assemble() {
var html = "";
for (var j = 0; j < parts.length; j++) {
var p = parts[j];
if (p && p._rawHtml) html += p.html;
else if (typeof p === "string") html += p;
else if (p != null && !isNil(p)) html += String(p);
}
var el = document.createElement("span");
el.innerHTML = html;
var frag = document.createDocumentFragment();
while (el.firstChild) frag.appendChild(el.firstChild);
return frag;
}
if (pending.length) return Promise.all(pending).then(assemble);
return assemble();
}
// Async version of sxRenderWithEnv — returns Promise<DocumentFragment>
function asyncSxRenderWithEnv(source, extraEnv) {
var env = extraEnv ? merge(componentEnv, extraEnv) : componentEnv;
var exprs = parse(source);
if (!_hasDom) return Promise.resolve(null);
return asyncRenderChildren(exprs, env, null);
}
// IO proxy cache: key → { value, expires }
var _ioCache = {};
var IO_CACHE_TTL = 300000; // 5 minutes
// Register a server-proxied IO primitive: fetches from /sx/io/<name>
// Uses GET for short args, POST for long payloads (URL length safety).
// Results are cached client-side by (name + args) with a TTL.
function registerProxiedIo(name) {
registerIoPrimitive(name, function(args, kwargs) {
// Cache key: name + serialized args
var cacheKey = name;
for (var ci = 0; ci < args.length; ci++) cacheKey += "" + String(args[ci]);
for (var ck in kwargs) {
if (kwargs.hasOwnProperty(ck)) cacheKey += "" + ck + "=" + String(kwargs[ck]);
}
var cached = _ioCache[cacheKey];
if (cached && cached.expires > Date.now()) return cached.value;
var url = "/sx/io/" + encodeURIComponent(name);
var qs = [];
for (var i = 0; i < args.length; i++) {
qs.push("_arg" + i + "=" + encodeURIComponent(String(args[i])));
}
for (var k in kwargs) {
if (kwargs.hasOwnProperty(k)) {
qs.push(encodeURIComponent(k) + "=" + encodeURIComponent(String(kwargs[k])));
}
}
var queryStr = qs.join("&");
var fetchOpts;
if (queryStr.length > 1500) {
// POST with JSON body for long payloads
var sArgs = [];
for (var j = 0; j < args.length; j++) sArgs.push(String(args[j]));
var sKwargs = {};
for (var kk in kwargs) {
if (kwargs.hasOwnProperty(kk)) sKwargs[kk] = String(kwargs[kk]);
}
var postHeaders = { "SX-Request": "true", "Content-Type": "application/json" };
var csrf = csrfToken();
if (csrf && csrf !== NIL) postHeaders["X-CSRFToken"] = csrf;
fetchOpts = {
method: "POST",
headers: postHeaders,
body: JSON.stringify({ args: sArgs, kwargs: sKwargs })
};
} else {
if (queryStr) url += "?" + queryStr;
fetchOpts = { headers: { "SX-Request": "true" } };
}
var result = fetch(url, fetchOpts)
.then(function(resp) {
if (!resp.ok) {
logWarn("sx:io " + name + " failed " + resp.status);
return NIL;
}
return resp.text();
})
.then(function(text) {
if (!text || text === "nil") return NIL;
try {
var exprs = parse(text);
var val = exprs.length === 1 ? exprs[0] : exprs;
_ioCache[cacheKey] = { value: val, expires: Date.now() + IO_CACHE_TTL };
return val;
} catch (e) {
logWarn("sx:io " + name + " parse error: " + (e && e.message ? e.message : e));
return NIL;
}
})
.catch(function(e) {
logWarn("sx:io " + name + " network error: " + (e && e.message ? e.message : e));
return NIL;
});
// Cache the in-flight promise too (dedup concurrent calls for same args)
_ioCache[cacheKey] = { value: result, expires: Date.now() + IO_CACHE_TTL };
return result;
});
}
// Register IO deps as proxied primitives (idempotent, called per-page)
function registerIoDeps(names) {
if (!names || !names.length) return;
var registered = 0;
for (var i = 0; i < names.length; i++) {
var name = names[i];
if (!IO_PRIMITIVES[name]) {
registerProxiedIo(name);
registered++;
}
}
if (registered > 0) {
logInfo("sx:io registered " + registered + " proxied primitives: " + names.join(", "));
}
}
// Parser — compiled from parser.sx (see PLATFORM_PARSER_JS for ident char classes)
var parse = sxParse;
// =========================================================================
// Public API
// =========================================================================
var componentEnv = {};
function loadComponents(source) {
var exprs = parse(source);
for (var i = 0; i < exprs.length; i++) {
trampoline(evalExpr(exprs[i], componentEnv));
}
}
function render(source) {
if (!_hasDom) {
var exprs = parse(source);
var parts = [];
for (var i = 0; i < exprs.length; i++) parts.push(renderToHtml(exprs[i], merge(componentEnv)));
return parts.join("");
}
var exprs = parse(source);
var frag = document.createDocumentFragment();
for (var i = 0; i < exprs.length; i++) { var _r = renderToDom(exprs[i], merge(componentEnv), null); if (_r && !_r._spread) frag.appendChild(_r); }
return frag;
}
function renderToString(source) {
var exprs = parse(source);
var parts = [];
for (var i = 0; i < exprs.length; i++) parts.push(renderToHtml(exprs[i], merge(componentEnv)));
return parts.join("");
}
var Sx = {
VERSION: "ref-2.0",
parse: parse,
parseAll: parse,
eval: function(expr, env) { return trampoline(evalExpr(expr, env || merge(componentEnv))); },
loadComponents: loadComponents,
render: render,
renderToString: renderToString,
serialize: serialize,
NIL: NIL,
Symbol: Symbol,
Keyword: Keyword,
isTruthy: isSxTruthy,
isNil: isNil,
componentEnv: componentEnv,
setRenderActive: function(val) { setRenderActiveB(val); },
renderToHtml: function(expr, env) { return renderToHtml(expr, env || merge(componentEnv)); },
renderToSx: function(expr, env) { return renderToSx(expr, env || merge(componentEnv)); },
renderToDom: _hasDom ? function(expr, env, ns) { return renderToDom(expr, env || merge(componentEnv), ns || null); } : null,
parseTriggerSpec: typeof parseTriggerSpec === "function" ? parseTriggerSpec : null,
parseTime: typeof parseTime === "function" ? parseTime : null,
defaultTrigger: typeof defaultTrigger === "function" ? defaultTrigger : null,
parseSwapSpec: typeof parseSwapSpec === "function" ? parseSwapSpec : null,
parseRetrySpec: typeof parseRetrySpec === "function" ? parseRetrySpec : null,
nextRetryMs: typeof nextRetryMs === "function" ? nextRetryMs : null,
filterParams: typeof filterParams === "function" ? filterParams : null,
morphNode: typeof morphNode === "function" ? morphNode : null,
morphChildren: typeof morphChildren === "function" ? morphChildren : null,
swapDomNodes: typeof swapDomNodes === "function" ? swapDomNodes : null,
process: typeof processElements === "function" ? processElements : null,
executeRequest: typeof executeRequest === "function" ? executeRequest : null,
postSwap: typeof postSwap === "function" ? postSwap : null,
processScripts: typeof processSxScripts === "function" ? processSxScripts : null,
mount: typeof sxMount === "function" ? sxMount : null,
hydrate: typeof sxHydrateElements === "function" ? sxHydrateElements : null,
update: typeof sxUpdateElement === "function" ? sxUpdateElement : null,
renderComponent: typeof sxRenderComponent === "function" ? sxRenderComponent : null,
getEnv: function() { return componentEnv; },
resolveSuspense: typeof resolveSuspense === "function" ? resolveSuspense : null,
hydrateIslands: typeof sxHydrateIslands === "function" ? sxHydrateIslands : null,
disposeIsland: typeof disposeIsland === "function" ? disposeIsland : null,
init: typeof bootInit === "function" ? bootInit : null,
scanRefs: scanRefs,
scanComponentsFromSource: scanComponentsFromSource,
transitiveDeps: transitiveDeps,
computeAllDeps: computeAllDeps,
componentsNeeded: componentsNeeded,
pageComponentBundle: pageComponentBundle,
pageCssClasses: pageCssClasses,
scanIoRefs: scanIoRefs,
transitiveIoRefs: transitiveIoRefs,
computeAllIoRefs: computeAllIoRefs,
componentPure_p: componentPure_p,
categorizeSpecialForms: categorizeSpecialForms,
buildReferenceData: buildReferenceData,
buildAttrDetail: buildAttrDetail,
buildHeaderDetail: buildHeaderDetail,
buildEventDetail: buildEventDetail,
buildComponentSource: buildComponentSource,
buildBundleAnalysis: buildBundleAnalysis,
buildRoutingAnalysis: buildRoutingAnalysis,
buildAffinityAnalysis: buildAffinityAnalysis,
splitPathSegments: splitPathSegments,
parseRoutePattern: parseRoutePattern,
matchRoute: matchRoute,
findMatchingRoute: findMatchingRoute,
urlToExpr: urlToExpr,
autoQuoteUnknowns: autoQuoteUnknowns,
prepareUrlExpr: prepareUrlExpr,
registerIo: typeof registerIoPrimitive === "function" ? registerIoPrimitive : null,
registerIoDeps: typeof registerIoDeps === "function" ? registerIoDeps : null,
asyncRender: typeof asyncSxRenderWithEnv === "function" ? asyncSxRenderWithEnv : null,
asyncRenderToDom: typeof asyncRenderToDom === "function" ? asyncRenderToDom : null,
signal: signal,
deref: deref,
reset: reset_b,
swap: swap_b,
computed: computed,
effect: effect,
batch: batch,
isSignal: isSignal,
makeSignal: makeSignal,
defStore: defStore,
useStore: useStore,
clearStores: clearStores,
emitEvent: emitEvent,
onEvent: onEvent,
bridgeEvent: bridgeEvent,
makeSpread: makeSpread,
isSpread: isSpread,
spreadAttrs: spreadAttrs,
collect: sxCollect,
collected: sxCollected,
clearCollected: sxClearCollected,
scopePush: scopePush,
scopePop: scopePop,
providePush: providePush,
providePop: providePop,
context: sxContext,
emit: sxEmit,
emitted: sxEmitted,
cekRun: cekRun,
makeCekState: makeCekState,
makeCekValue: makeCekValue,
cekStep: cekStep,
cekTerminal: cekTerminal_p,
cekValue: cekValue,
makeReactiveResetFrame: makeReactiveResetFrame,
evalExpr: evalExpr,
_version: "ref-2.0 (boot+browser-lib+dom+dom-lib+engine+html+orchestration+parser+sx, bootstrap-compiled)"
};
// --- Popstate listener ---
if (typeof window !== "undefined") {
window.addEventListener("popstate", function(e) {
handlePopstate(e && e.state ? e.state.scrollY || 0 : 0);
});
}
// --- Auto-init ---
if (typeof document !== "undefined") {
var _sxInit = function() {
bootInit();
// Process any suspense resolutions that arrived before init
if (global.__sxPending) {
for (var pi = 0; pi < global.__sxPending.length; pi++) {
resolveSuspense(global.__sxPending[pi].id, global.__sxPending[pi].sx);
}
global.__sxPending = null;
}
// Set up direct resolution for future chunks
global.__sxResolve = function(id, sx) { resolveSuspense(id, sx); };
// Register service worker for offline data caching
if ("serviceWorker" in navigator) {
navigator.serviceWorker.register("/sx-sw.js", { scope: "/" }).then(function(reg) {
logInfo("sx:sw registered (scope: " + reg.scope + ")");
}).catch(function(err) {
logWarn("sx:sw registration failed: " + (err && err.message ? err.message : err));
});
}
};
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", _sxInit);
} else {
_sxInit();
}
}
if (typeof module !== "undefined" && module.exports) module.exports = Sx;
else global.Sx = Sx;
})(typeof globalThis !== "undefined" ? globalThis : typeof window !== "undefined" ? window : this);