|
|
|
|
@@ -14,7 +14,7 @@
|
|
|
|
|
// =========================================================================
|
|
|
|
|
|
|
|
|
|
var NIL = Object.freeze({ _nil: true, toString: function() { return "nil"; } });
|
|
|
|
|
var SX_VERSION = "2026-03-26T16:13:53Z";
|
|
|
|
|
var SX_VERSION = "2026-03-28T12:33:20Z";
|
|
|
|
|
|
|
|
|
|
function isNil(x) { return x === NIL || x === null || x === undefined; }
|
|
|
|
|
function isSxTruthy(x) { return x !== false && !isNil(x); }
|
|
|
|
|
@@ -3169,10 +3169,7 @@ PRIMITIVES["dom-body"] = domBody;
|
|
|
|
|
PRIMITIVES["dom-head"] = domHead;
|
|
|
|
|
|
|
|
|
|
// dom-create-element
|
|
|
|
|
var domCreateElement = function(tag) { var nsArg = Array.prototype.slice.call(arguments, 1); return (function() {
|
|
|
|
|
var ns = (isSxTruthy((isSxTruthy(nsArg) && !isSxTruthy(isEmpty(nsArg)))) ? first(nsArg) : NIL);
|
|
|
|
|
return (isSxTruthy(ns) ? hostCall(domDocument(), "createElementNS", ns, tag) : hostCall(domDocument(), "createElement", tag));
|
|
|
|
|
})(); };
|
|
|
|
|
var domCreateElement = function(tag, ns) { return (isSxTruthy(ns) ? hostCall(domDocument(), "createElementNS", ns, tag) : hostCall(domDocument(), "createElement", tag)); };
|
|
|
|
|
PRIMITIVES["dom-create-element"] = domCreateElement;
|
|
|
|
|
|
|
|
|
|
// create-text-node
|
|
|
|
|
@@ -3262,7 +3259,7 @@ PRIMITIVES["dom-replace-child"] = domReplaceChild;
|
|
|
|
|
PRIMITIVES["dom-clone"] = domClone;
|
|
|
|
|
|
|
|
|
|
// dom-query
|
|
|
|
|
var domQuery = function(rootOrSel) { var rest = Array.prototype.slice.call(arguments, 1); return (isSxTruthy(isEmpty(rest)) ? hostCall(domDocument(), "querySelector", rootOrSel) : hostCall(rootOrSel, "querySelector", first(rest))); };
|
|
|
|
|
var domQuery = function(rootOrSel, sel) { return (isSxTruthy(isNil(sel)) ? hostCall(domDocument(), "querySelector", rootOrSel) : hostCall(rootOrSel, "querySelector", sel)); };
|
|
|
|
|
PRIMITIVES["dom-query"] = domQuery;
|
|
|
|
|
|
|
|
|
|
// dom-query-all
|
|
|
|
|
@@ -3455,9 +3452,9 @@ PRIMITIVES["dom-parse-html"] = domParseHtml;
|
|
|
|
|
PRIMITIVES["dom-listen"] = domListen;
|
|
|
|
|
|
|
|
|
|
// dom-add-listener
|
|
|
|
|
var domAddListener = function(el, eventName, handler) { var opts = Array.prototype.slice.call(arguments, 3); return (function() {
|
|
|
|
|
var domAddListener = function(el, eventName, handler, opts) { return (function() {
|
|
|
|
|
var cb = hostCallback(handler);
|
|
|
|
|
(isSxTruthy((isSxTruthy(opts) && !isSxTruthy(isEmpty(opts)))) ? hostCall(el, "addEventListener", eventName, cb, first(opts)) : hostCall(el, "addEventListener", eventName, cb));
|
|
|
|
|
(isSxTruthy(opts) ? hostCall(el, "addEventListener", eventName, cb, opts) : hostCall(el, "addEventListener", eventName, cb));
|
|
|
|
|
return function() { return hostCall(el, "removeEventListener", eventName, cb); };
|
|
|
|
|
})(); };
|
|
|
|
|
PRIMITIVES["dom-add-listener"] = domAddListener;
|
|
|
|
|
@@ -3539,11 +3536,11 @@ PRIMITIVES["browser-same-origin?"] = browserSameOrigin;
|
|
|
|
|
PRIMITIVES["url-pathname"] = urlPathname;
|
|
|
|
|
|
|
|
|
|
// browser-push-state
|
|
|
|
|
var browserPushState = function(urlOrState) { var rest = Array.prototype.slice.call(arguments, 1); return (isSxTruthy(isEmpty(rest)) ? hostCall(hostGet(domWindow(), "history"), "pushState", NIL, "", urlOrState) : hostCall(hostGet(domWindow(), "history"), "pushState", urlOrState, first(rest), nth(rest, 1))); };
|
|
|
|
|
var browserPushState = function(urlOrState, title, url) { return (isSxTruthy(isNil(title)) ? hostCall(hostGet(domWindow(), "history"), "pushState", NIL, "", urlOrState) : hostCall(hostGet(domWindow(), "history"), "pushState", urlOrState, title, url)); };
|
|
|
|
|
PRIMITIVES["browser-push-state"] = browserPushState;
|
|
|
|
|
|
|
|
|
|
// browser-replace-state
|
|
|
|
|
var browserReplaceState = function(urlOrState) { var rest = Array.prototype.slice.call(arguments, 1); return (isSxTruthy(isEmpty(rest)) ? hostCall(hostGet(domWindow(), "history"), "replaceState", NIL, "", urlOrState) : hostCall(hostGet(domWindow(), "history"), "replaceState", urlOrState, first(rest), nth(rest, 1))); };
|
|
|
|
|
var browserReplaceState = function(urlOrState, title, url) { return (isSxTruthy(isNil(title)) ? hostCall(hostGet(domWindow(), "history"), "replaceState", NIL, "", urlOrState) : hostCall(hostGet(domWindow(), "history"), "replaceState", urlOrState, title, url)); };
|
|
|
|
|
PRIMITIVES["browser-replace-state"] = browserReplaceState;
|
|
|
|
|
|
|
|
|
|
// browser-reload
|
|
|
|
|
@@ -3643,7 +3640,7 @@ PRIMITIVES["log-info"] = logInfo;
|
|
|
|
|
PRIMITIVES["log-warn"] = logWarn;
|
|
|
|
|
|
|
|
|
|
// console-log
|
|
|
|
|
var consoleLog = function() { var args = Array.prototype.slice.call(arguments, 0); return hostCall(hostGlobal("console"), "log", join(" ", cons("[sx]", map(str, args)))); };
|
|
|
|
|
var consoleLog = function(msg) { return hostCall(hostGlobal("console"), "log", (String("[sx] ") + String(msg))); };
|
|
|
|
|
PRIMITIVES["console-log"] = consoleLog;
|
|
|
|
|
|
|
|
|
|
// now-ms
|
|
|
|
|
@@ -4772,7 +4769,7 @@ PRIMITIVES["init-css-tracking"] = initCssTracking;
|
|
|
|
|
})()) ? promiseResolve(NIL) : (function() {
|
|
|
|
|
var promptMsg = domGetAttr(el, "sx-prompt");
|
|
|
|
|
var promptVal = (isSxTruthy(promptMsg) ? browserPrompt(promptMsg) : NIL);
|
|
|
|
|
return (isSxTruthy((isSxTruthy(promptMsg) && isNil(promptVal))) ? promiseResolve(NIL) : (isSxTruthy(!isSxTruthy(validateForRequest(el))) ? promiseResolve(NIL) : doFetch(el, verb, verb, url, (isSxTruthy(promptVal) ? assoc(sxOr(extraParams, {}), "SX-Prompt", promptVal) : extraParams))));
|
|
|
|
|
return (isSxTruthy((isSxTruthy(promptMsg) && isNil(promptVal))) ? promiseResolve(NIL) : (isSxTruthy(sxOr(isNil(verb), isNil(url), !isSxTruthy(validateForRequest(el)))) ? promiseResolve(NIL) : doFetch(el, verb, verb, url, (isSxTruthy(promptVal) ? assoc(sxOr(extraParams, {}), "SX-Prompt", promptVal) : extraParams))));
|
|
|
|
|
})()));
|
|
|
|
|
})());
|
|
|
|
|
})(); };
|
|
|
|
|
@@ -4942,12 +4939,12 @@ PRIMITIVES["bind-triggers"] = bindTriggers;
|
|
|
|
|
var shouldFire = true;
|
|
|
|
|
if (isSxTruthy(get(mods, "changed"))) {
|
|
|
|
|
(function() {
|
|
|
|
|
var val = elementValue(el);
|
|
|
|
|
var val = domValue(el);
|
|
|
|
|
return (isSxTruthy((val == lastVal)) ? (shouldFire = false) : (lastVal = val));
|
|
|
|
|
})();
|
|
|
|
|
}
|
|
|
|
|
return (isSxTruthy((isSxTruthy(shouldFire) && !isSxTruthy((isSxTruthy((eventName == "click")) && eventModifierKey_p(e))))) ? ((isSxTruthy(sxOr((eventName == "submit"), (isSxTruthy((eventName == "click")) && domHasAttr(el, "href")))) ? preventDefault_(e) : NIL), (function() {
|
|
|
|
|
var liveInfo = sxOr(getVerbInfo(el), verbInfo);
|
|
|
|
|
var liveInfo = getVerbInfo(el);
|
|
|
|
|
var isGetLink = (isSxTruthy((eventName == "click")) && isSxTruthy((get(liveInfo, "method") == "GET")) && isSxTruthy(domHasAttr(el, "href")) && !isSxTruthy(get(mods, "delay")));
|
|
|
|
|
var clientRouted = false;
|
|
|
|
|
if (isSxTruthy(isGetLink)) {
|
|
|
|
|
@@ -5537,7 +5534,7 @@ PRIMITIVES["sx-render-component"] = sxRenderComponent;
|
|
|
|
|
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 evalExpr(expr, envExtend({})); }, exprs);
|
|
|
|
|
return forEach(function(expr) { return cekEval(expr); }, exprs);
|
|
|
|
|
})() : (isSxTruthy(domHasAttr(s, "data-mount")) ? (function() {
|
|
|
|
|
var mountSel = domGetAttr(s, "data-mount");
|
|
|
|
|
var target = domQuery(mountSel);
|
|
|
|
|
@@ -6533,28 +6530,6 @@ PRIMITIVES["with-marsh-scope"] = withMarshScope;
|
|
|
|
|
})(); };
|
|
|
|
|
PRIMITIVES["dispose-marsh-scope"] = disposeMarshScope;
|
|
|
|
|
|
|
|
|
|
// *store-registry*
|
|
|
|
|
var _storeRegistry = {};
|
|
|
|
|
PRIMITIVES["*store-registry*"] = _storeRegistry;
|
|
|
|
|
|
|
|
|
|
// def-store
|
|
|
|
|
var defStore = function(name, initFn) { return (function() {
|
|
|
|
|
var registry = _storeRegistry;
|
|
|
|
|
if (isSxTruthy(!isSxTruthy(dictHas(registry, name)))) {
|
|
|
|
|
_storeRegistry = assoc(registry, name, cekCall(initFn, NIL));
|
|
|
|
|
}
|
|
|
|
|
return get(_storeRegistry, name);
|
|
|
|
|
})(); };
|
|
|
|
|
PRIMITIVES["def-store"] = defStore;
|
|
|
|
|
|
|
|
|
|
// use-store
|
|
|
|
|
var useStore = function(name) { return (isSxTruthy(dictHas(_storeRegistry, name)) ? get(_storeRegistry, name) : error((String("Store not found: ") + String(name) + String(". Call (def-store ...) before (use-store ...).")))); };
|
|
|
|
|
PRIMITIVES["use-store"] = useStore;
|
|
|
|
|
|
|
|
|
|
// clear-stores
|
|
|
|
|
var clearStores = function() { return (_storeRegistry = {}); };
|
|
|
|
|
PRIMITIVES["clear-stores"] = clearStores;
|
|
|
|
|
|
|
|
|
|
// emit-event
|
|
|
|
|
var emitEvent = function(el, eventName, detail) { return domDispatch(el, eventName, detail); };
|
|
|
|
|
PRIMITIVES["emit-event"] = emitEvent;
|
|
|
|
|
@@ -6583,400 +6558,6 @@ PRIMITIVES["bridge-event"] = bridgeEvent;
|
|
|
|
|
PRIMITIVES["resource"] = resource;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// === Transpiled from types (gradual type system) ===
|
|
|
|
|
|
|
|
|
|
// base-types
|
|
|
|
|
var baseTypes = ["number", "string", "boolean", "nil", "symbol", "keyword", "element", "any", "never", "list", "dict", "lambda", "component", "island", "macro", "signal"];
|
|
|
|
|
PRIMITIVES["base-types"] = baseTypes;
|
|
|
|
|
|
|
|
|
|
// type-any?
|
|
|
|
|
var typeAny_p = function(t) { return (t == "any"); };
|
|
|
|
|
PRIMITIVES["type-any?"] = typeAny_p;
|
|
|
|
|
|
|
|
|
|
// type-never?
|
|
|
|
|
var typeNever_p = function(t) { return (t == "never"); };
|
|
|
|
|
PRIMITIVES["type-never?"] = typeNever_p;
|
|
|
|
|
|
|
|
|
|
// type-nullable?
|
|
|
|
|
var typeNullable_p = function(t) { return (isSxTruthy((t == "any")) ? true : (isSxTruthy((t == "nil")) ? true : (isSxTruthy((isSxTruthy((typeOf(t) == "string")) && endsWith(t, "?"))) ? true : (isSxTruthy((isSxTruthy((typeOf(t) == "list")) && isSxTruthy(!isSxTruthy(isEmpty(t))) && (first(t) == "or"))) ? contains(rest(t), "nil") : false)))); };
|
|
|
|
|
PRIMITIVES["type-nullable?"] = typeNullable_p;
|
|
|
|
|
|
|
|
|
|
// nullable-base
|
|
|
|
|
var nullableBase = function(t) { return (isSxTruthy((isSxTruthy((typeOf(t) == "string")) && isSxTruthy(endsWith(t, "?")) && !isSxTruthy((t == "?")))) ? slice(t, 0, (stringLength(t) - 1)) : t); };
|
|
|
|
|
PRIMITIVES["nullable-base"] = nullableBase;
|
|
|
|
|
|
|
|
|
|
// subtype?
|
|
|
|
|
var subtype_p = function(a, b) { return (isSxTruthy(typeAny_p(b)) ? true : (isSxTruthy(typeNever_p(a)) ? true : (isSxTruthy(typeAny_p(a)) ? false : (isSxTruthy((a == b)) ? true : (isSxTruthy((a == "nil")) ? typeNullable_p(b) : (isSxTruthy((isSxTruthy((typeOf(b) == "string")) && endsWith(b, "?"))) ? (function() {
|
|
|
|
|
var base = nullableBase(b);
|
|
|
|
|
return sxOr((a == base), (a == "nil"));
|
|
|
|
|
})() : (isSxTruthy((isSxTruthy((typeOf(a) == "list")) && isSxTruthy(!isSxTruthy(isEmpty(a))) && (first(a) == "or"))) ? isEvery(function(member) { return subtype_p(member, b); }, rest(a)) : (isSxTruthy((isSxTruthy((typeOf(b) == "list")) && isSxTruthy(!isSxTruthy(isEmpty(b))) && (first(b) == "or"))) ? some(function(member) { return subtype_p(a, member); }, rest(b)) : (isSxTruthy((isSxTruthy((typeOf(a) == "list")) && isSxTruthy((typeOf(b) == "list")) && isSxTruthy((len(a) == 2)) && isSxTruthy((len(b) == 2)) && isSxTruthy((first(a) == "list-of")) && (first(b) == "list-of"))) ? subtype_p(nth(a, 1), nth(b, 1)) : (isSxTruthy((isSxTruthy((a == "list")) && isSxTruthy((typeOf(b) == "list")) && isSxTruthy((len(b) == 2)) && (first(b) == "list-of"))) ? typeAny_p(nth(b, 1)) : (isSxTruthy((isSxTruthy((typeOf(a) == "list")) && isSxTruthy((len(a) == 2)) && isSxTruthy((first(a) == "list-of")) && (b == "list"))) ? true : false))))))))))); };
|
|
|
|
|
PRIMITIVES["subtype?"] = subtype_p;
|
|
|
|
|
|
|
|
|
|
// type-union
|
|
|
|
|
var typeUnion = function(a, b) { return (isSxTruthy((a == b)) ? a : (isSxTruthy(typeAny_p(a)) ? "any" : (isSxTruthy(typeAny_p(b)) ? "any" : (isSxTruthy(typeNever_p(a)) ? b : (isSxTruthy(typeNever_p(b)) ? a : (isSxTruthy(subtype_p(a, b)) ? b : (isSxTruthy(subtype_p(b, a)) ? a : (isSxTruthy((a == "nil")) ? (isSxTruthy((isSxTruthy((typeOf(b) == "string")) && !isSxTruthy(endsWith(b, "?")))) ? (String(b) + String("?")) : ["or", a, b]) : (isSxTruthy((b == "nil")) ? (isSxTruthy((isSxTruthy((typeOf(a) == "string")) && !isSxTruthy(endsWith(a, "?")))) ? (String(a) + String("?")) : ["or", a, b]) : ["or", a, b]))))))))); };
|
|
|
|
|
PRIMITIVES["type-union"] = typeUnion;
|
|
|
|
|
|
|
|
|
|
// narrow-type
|
|
|
|
|
var narrowType = function(t, predicateName) { return (isSxTruthy((predicateName == "nil?")) ? ["nil", narrowExcludeNil(t)] : (isSxTruthy((predicateName == "string?")) ? ["string", narrowExclude(t, "string")] : (isSxTruthy((predicateName == "number?")) ? ["number", narrowExclude(t, "number")] : (isSxTruthy((predicateName == "list?")) ? ["list", narrowExclude(t, "list")] : (isSxTruthy((predicateName == "dict?")) ? ["dict", narrowExclude(t, "dict")] : (isSxTruthy((predicateName == "boolean?")) ? ["boolean", narrowExclude(t, "boolean")] : [t, t])))))); };
|
|
|
|
|
PRIMITIVES["narrow-type"] = narrowType;
|
|
|
|
|
|
|
|
|
|
// narrow-exclude-nil
|
|
|
|
|
var narrowExcludeNil = function(t) { return (isSxTruthy((t == "nil")) ? "never" : (isSxTruthy((t == "any")) ? "any" : (isSxTruthy((isSxTruthy((typeOf(t) == "string")) && endsWith(t, "?"))) ? nullableBase(t) : (isSxTruthy((isSxTruthy((typeOf(t) == "list")) && isSxTruthy(!isSxTruthy(isEmpty(t))) && (first(t) == "or"))) ? (function() {
|
|
|
|
|
var members = filter(function(m) { return !isSxTruthy((m == "nil")); }, rest(t));
|
|
|
|
|
return (isSxTruthy((len(members) == 1)) ? first(members) : (isSxTruthy(isEmpty(members)) ? "never" : cons("or", members)));
|
|
|
|
|
})() : t)))); };
|
|
|
|
|
PRIMITIVES["narrow-exclude-nil"] = narrowExcludeNil;
|
|
|
|
|
|
|
|
|
|
// narrow-exclude
|
|
|
|
|
var narrowExclude = function(t, excluded) { return (isSxTruthy((t == excluded)) ? "never" : (isSxTruthy((t == "any")) ? "any" : (isSxTruthy((isSxTruthy((typeOf(t) == "list")) && isSxTruthy(!isSxTruthy(isEmpty(t))) && (first(t) == "or"))) ? (function() {
|
|
|
|
|
var members = filter(function(m) { return !isSxTruthy((m == excluded)); }, rest(t));
|
|
|
|
|
return (isSxTruthy((len(members) == 1)) ? first(members) : (isSxTruthy(isEmpty(members)) ? "never" : cons("or", members)));
|
|
|
|
|
})() : t))); };
|
|
|
|
|
PRIMITIVES["narrow-exclude"] = narrowExclude;
|
|
|
|
|
|
|
|
|
|
// infer-type
|
|
|
|
|
var inferType = function(node, typeEnv, primTypes, typeRegistry) { return (function() {
|
|
|
|
|
var kind = typeOf(node);
|
|
|
|
|
return (isSxTruthy((kind == "number")) ? "number" : (isSxTruthy((kind == "string")) ? "string" : (isSxTruthy((kind == "boolean")) ? "boolean" : (isSxTruthy(isNil(node)) ? "nil" : (isSxTruthy((kind == "keyword")) ? "keyword" : (isSxTruthy((kind == "symbol")) ? (function() {
|
|
|
|
|
var name = symbolName(node);
|
|
|
|
|
return (isSxTruthy(dictHas(typeEnv, name)) ? get(typeEnv, name) : (isSxTruthy((name == "true")) ? "boolean" : (isSxTruthy((name == "false")) ? "boolean" : (isSxTruthy((name == "nil")) ? "nil" : (isSxTruthy(dictHas(primTypes, name)) ? get(primTypes, name) : "any")))));
|
|
|
|
|
})() : (isSxTruthy((kind == "dict")) ? "dict" : (isSxTruthy((kind == "list")) ? inferListType(node, typeEnv, primTypes, typeRegistry) : "any"))))))));
|
|
|
|
|
})(); };
|
|
|
|
|
PRIMITIVES["infer-type"] = inferType;
|
|
|
|
|
|
|
|
|
|
// infer-list-type
|
|
|
|
|
var inferListType = function(node, typeEnv, primTypes, typeRegistry) { return (isSxTruthy(isEmpty(node)) ? "list" : (function() {
|
|
|
|
|
var head = first(node);
|
|
|
|
|
var args = rest(node);
|
|
|
|
|
return (isSxTruthy(!isSxTruthy((typeOf(head) == "symbol"))) ? "any" : (function() {
|
|
|
|
|
var name = symbolName(head);
|
|
|
|
|
return (isSxTruthy((name == "if")) ? inferIfType(args, typeEnv, primTypes, typeRegistry) : (isSxTruthy((name == "when")) ? (isSxTruthy((len(args) >= 2)) ? typeUnion(inferType(last(args), typeEnv, primTypes, typeRegistry), "nil") : "nil") : (isSxTruthy(sxOr((name == "cond"), (name == "case"))) ? "any" : (isSxTruthy((name == "let")) ? inferLetType(args, typeEnv, primTypes, typeRegistry) : (isSxTruthy(sxOr((name == "do"), (name == "begin"))) ? (isSxTruthy(isEmpty(args)) ? "nil" : inferType(last(args), typeEnv, primTypes, typeRegistry)) : (isSxTruthy(sxOr((name == "lambda"), (name == "fn"))) ? "lambda" : (isSxTruthy((name == "and")) ? (isSxTruthy(isEmpty(args)) ? "boolean" : inferType(last(args), typeEnv, primTypes, typeRegistry)) : (isSxTruthy((name == "or")) ? (isSxTruthy(isEmpty(args)) ? "boolean" : reduce(typeUnion, "never", map(function(a) { return inferType(a, typeEnv, primTypes, typeRegistry); }, args))) : (isSxTruthy((name == "map")) ? (isSxTruthy((len(args) >= 2)) ? (function() {
|
|
|
|
|
var fnType = inferType(first(args), typeEnv, primTypes, typeRegistry);
|
|
|
|
|
return (isSxTruthy((isSxTruthy((typeOf(fnType) == "list")) && (first(fnType) == "->"))) ? ["list-of", last(fnType)] : "list");
|
|
|
|
|
})() : "list") : (isSxTruthy((name == "filter")) ? (isSxTruthy((len(args) >= 2)) ? inferType(nth(args, 1), typeEnv, primTypes, typeRegistry) : "list") : (isSxTruthy((name == "reduce")) ? "any" : (isSxTruthy((name == "list")) ? "list" : (isSxTruthy((name == "dict")) ? "dict" : (isSxTruthy((name == "quote")) ? "any" : (isSxTruthy((name == "str")) ? "string" : (isSxTruthy((name == "not")) ? "boolean" : (isSxTruthy((name == "get")) ? (isSxTruthy((isSxTruthy((len(args) >= 2)) && !isSxTruthy(isNil(typeRegistry)))) ? (function() {
|
|
|
|
|
var dictType = inferType(first(args), typeEnv, primTypes, typeRegistry);
|
|
|
|
|
var keyArg = nth(args, 1);
|
|
|
|
|
var keyName = (isSxTruthy((typeOf(keyArg) == "keyword")) ? keywordName(keyArg) : (isSxTruthy((typeOf(keyArg) == "string")) ? keyArg : NIL));
|
|
|
|
|
return (isSxTruthy((isSxTruthy(keyName) && isSxTruthy((typeOf(dictType) == "string")) && dictHas(typeRegistry, dictType))) ? (function() {
|
|
|
|
|
var resolved = resolveType(dictType, typeRegistry);
|
|
|
|
|
return (isSxTruthy((isSxTruthy((typeOf(resolved) == "dict")) && dictHas(resolved, keyName))) ? get(resolved, keyName) : "any");
|
|
|
|
|
})() : "any");
|
|
|
|
|
})() : "any") : (isSxTruthy(startsWith(name, "~")) ? "element" : (isSxTruthy(dictHas(primTypes, name)) ? get(primTypes, name) : "any")))))))))))))))))));
|
|
|
|
|
})());
|
|
|
|
|
})()); };
|
|
|
|
|
PRIMITIVES["infer-list-type"] = inferListType;
|
|
|
|
|
|
|
|
|
|
// infer-if-type
|
|
|
|
|
var inferIfType = function(args, typeEnv, primTypes, typeRegistry) { return (isSxTruthy((len(args) < 2)) ? "nil" : (function() {
|
|
|
|
|
var thenType = inferType(nth(args, 1), typeEnv, primTypes, typeRegistry);
|
|
|
|
|
return (isSxTruthy((len(args) >= 3)) ? typeUnion(thenType, inferType(nth(args, 2), typeEnv, primTypes, typeRegistry)) : typeUnion(thenType, "nil"));
|
|
|
|
|
})()); };
|
|
|
|
|
PRIMITIVES["infer-if-type"] = inferIfType;
|
|
|
|
|
|
|
|
|
|
// infer-let-type
|
|
|
|
|
var inferLetType = function(args, typeEnv, primTypes, typeRegistry) { return (isSxTruthy((len(args) < 2)) ? "nil" : (function() {
|
|
|
|
|
var bindings = first(args);
|
|
|
|
|
var body = last(args);
|
|
|
|
|
var extended = merge(typeEnv, {});
|
|
|
|
|
{ var _c = bindings; for (var _i = 0; _i < _c.length; _i++) { var binding = _c[_i]; if (isSxTruthy((isSxTruthy((typeOf(binding) == "list")) && (len(binding) >= 2)))) {
|
|
|
|
|
(function() {
|
|
|
|
|
var name = (isSxTruthy((typeOf(first(binding)) == "symbol")) ? symbolName(first(binding)) : (String(first(binding))));
|
|
|
|
|
var valType = inferType(nth(binding, 1), extended, primTypes, typeRegistry);
|
|
|
|
|
return dictSet(extended, name, valType);
|
|
|
|
|
})();
|
|
|
|
|
} } }
|
|
|
|
|
return inferType(body, extended, primTypes, typeRegistry);
|
|
|
|
|
})()); };
|
|
|
|
|
PRIMITIVES["infer-let-type"] = inferLetType;
|
|
|
|
|
|
|
|
|
|
// make-diagnostic
|
|
|
|
|
var makeDiagnostic = function(level, message, component, expr) { return {"level": level, "component": component, "expr": expr, "message": message}; };
|
|
|
|
|
PRIMITIVES["make-diagnostic"] = makeDiagnostic;
|
|
|
|
|
|
|
|
|
|
// check-primitive-call
|
|
|
|
|
var checkPrimitiveCall = function(name, args, typeEnv, primTypes, primParamTypes, compName, typeRegistry) { return (function() {
|
|
|
|
|
var diagnostics = [];
|
|
|
|
|
if (isSxTruthy((isSxTruthy(!isSxTruthy(isNil(primParamTypes))) && dictHas(primParamTypes, name)))) {
|
|
|
|
|
(function() {
|
|
|
|
|
var sig = get(primParamTypes, name);
|
|
|
|
|
var positional = get(sig, "positional");
|
|
|
|
|
var restType = get(sig, "rest-type");
|
|
|
|
|
return forEach(function(idx) { return (isSxTruthy((idx < len(args))) ? (isSxTruthy((idx < len(positional))) ? (function() {
|
|
|
|
|
var paramInfo = nth(positional, idx);
|
|
|
|
|
var argExpr = nth(args, idx);
|
|
|
|
|
return (function() {
|
|
|
|
|
var expectedType = nth(paramInfo, 1);
|
|
|
|
|
return (isSxTruthy(!isSxTruthy(isNil(expectedType))) ? (function() {
|
|
|
|
|
var actual = inferType(argExpr, typeEnv, primTypes, typeRegistry);
|
|
|
|
|
return (isSxTruthy((isSxTruthy(!isSxTruthy(typeAny_p(expectedType))) && isSxTruthy(!isSxTruthy(typeAny_p(actual))) && !isSxTruthy(subtypeResolved_p(actual, expectedType, typeRegistry)))) ? append_b(diagnostics, makeDiagnostic("error", (String("Argument ") + String((idx + 1)) + String(" of `") + String(name) + String("` expects ") + String(expectedType) + String(", got ") + String(actual)), compName, argExpr)) : NIL);
|
|
|
|
|
})() : NIL);
|
|
|
|
|
})();
|
|
|
|
|
})() : (isSxTruthy(!isSxTruthy(isNil(restType))) ? (function() {
|
|
|
|
|
var argExpr = nth(args, idx);
|
|
|
|
|
var actual = inferType(argExpr, typeEnv, primTypes, typeRegistry);
|
|
|
|
|
return (isSxTruthy((isSxTruthy(!isSxTruthy(typeAny_p(restType))) && isSxTruthy(!isSxTruthy(typeAny_p(actual))) && !isSxTruthy(subtypeResolved_p(actual, restType, typeRegistry)))) ? append_b(diagnostics, makeDiagnostic("error", (String("Argument ") + String((idx + 1)) + String(" of `") + String(name) + String("` expects ") + String(restType) + String(", got ") + String(actual)), compName, argExpr)) : NIL);
|
|
|
|
|
})() : NIL)) : NIL); }, range(0, len(args), 1));
|
|
|
|
|
})();
|
|
|
|
|
}
|
|
|
|
|
return diagnostics;
|
|
|
|
|
})(); };
|
|
|
|
|
PRIMITIVES["check-primitive-call"] = checkPrimitiveCall;
|
|
|
|
|
|
|
|
|
|
// check-component-call
|
|
|
|
|
var checkComponentCall = function(compName, comp, callArgs, typeEnv, primTypes, typeRegistry) { return (function() {
|
|
|
|
|
var diagnostics = [];
|
|
|
|
|
var paramTypes = componentParamTypes(comp);
|
|
|
|
|
var params = componentParams(comp);
|
|
|
|
|
if (isSxTruthy((isSxTruthy(!isSxTruthy(isNil(paramTypes))) && !isSxTruthy(isEmpty(keys(paramTypes)))))) {
|
|
|
|
|
(function() {
|
|
|
|
|
var i = 0;
|
|
|
|
|
var providedKeys = [];
|
|
|
|
|
{ var _c = range(0, len(callArgs), 1); for (var _i = 0; _i < _c.length; _i++) { var idx = _c[_i]; if (isSxTruthy((idx < len(callArgs)))) {
|
|
|
|
|
(function() {
|
|
|
|
|
var arg = nth(callArgs, idx);
|
|
|
|
|
return (isSxTruthy((typeOf(arg) == "keyword")) ? (function() {
|
|
|
|
|
var keyName = keywordName(arg);
|
|
|
|
|
providedKeys.push(keyName);
|
|
|
|
|
return (isSxTruthy(((idx + 1) < len(callArgs))) ? (function() {
|
|
|
|
|
var valExpr = nth(callArgs, (idx + 1));
|
|
|
|
|
return (isSxTruthy(dictHas(paramTypes, keyName)) ? (function() {
|
|
|
|
|
var expected = get(paramTypes, keyName);
|
|
|
|
|
var actual = inferType(valExpr, typeEnv, primTypes, typeRegistry);
|
|
|
|
|
return (isSxTruthy((isSxTruthy(!isSxTruthy(typeAny_p(expected))) && isSxTruthy(!isSxTruthy(typeAny_p(actual))) && !isSxTruthy(subtypeResolved_p(actual, expected, typeRegistry)))) ? append_b(diagnostics, makeDiagnostic("error", (String("Keyword :") + String(keyName) + String(" of ") + String(compName) + String(" expects ") + String(expected) + String(", got ") + String(actual)), compName, valExpr)) : NIL);
|
|
|
|
|
})() : NIL);
|
|
|
|
|
})() : NIL);
|
|
|
|
|
})() : NIL);
|
|
|
|
|
})();
|
|
|
|
|
} } }
|
|
|
|
|
{ var _c = params; for (var _i = 0; _i < _c.length; _i++) { var paramName = _c[_i]; if (isSxTruthy((isSxTruthy(dictHas(paramTypes, paramName)) && isSxTruthy(!isSxTruthy(contains(providedKeys, paramName))) && !isSxTruthy(typeNullable_p(get(paramTypes, paramName)))))) {
|
|
|
|
|
diagnostics.push(makeDiagnostic("warning", (String("Required param :") + String(paramName) + String(" of ") + String(compName) + String(" not provided")), compName, NIL));
|
|
|
|
|
} } }
|
|
|
|
|
return forEach(function(key) { return (isSxTruthy(!isSxTruthy(contains(params, key))) ? append_b(diagnostics, makeDiagnostic("warning", (String("Unknown keyword :") + String(key) + String(" passed to ") + String(compName)), compName, NIL)) : NIL); }, providedKeys);
|
|
|
|
|
})();
|
|
|
|
|
}
|
|
|
|
|
return diagnostics;
|
|
|
|
|
})(); };
|
|
|
|
|
PRIMITIVES["check-component-call"] = checkComponentCall;
|
|
|
|
|
|
|
|
|
|
// check-body-walk
|
|
|
|
|
var checkBodyWalk = function(node, compName, typeEnv, primTypes, primParamTypes, env, diagnostics, typeRegistry, effectAnnotations) { return (function() {
|
|
|
|
|
var kind = typeOf(node);
|
|
|
|
|
return (isSxTruthy((kind == "list")) ? (isSxTruthy(!isSxTruthy(isEmpty(node))) ? (function() {
|
|
|
|
|
var head = first(node);
|
|
|
|
|
var args = rest(node);
|
|
|
|
|
if (isSxTruthy((typeOf(head) == "symbol"))) {
|
|
|
|
|
(function() {
|
|
|
|
|
var name = symbolName(head);
|
|
|
|
|
if (isSxTruthy(startsWith(name, "~"))) {
|
|
|
|
|
(function() {
|
|
|
|
|
var compVal = envGet(env, name);
|
|
|
|
|
return (isSxTruthy((typeOf(compVal) == "component")) ? forEach(function(d) { return append_b(diagnostics, d); }, checkComponentCall(name, compVal, args, typeEnv, primTypes, typeRegistry)) : NIL);
|
|
|
|
|
})();
|
|
|
|
|
if (isSxTruthy(!isSxTruthy(isNil(effectAnnotations)))) {
|
|
|
|
|
(function() {
|
|
|
|
|
var callerEffects = getEffects(compName, effectAnnotations);
|
|
|
|
|
return forEach(function(d) { return append_b(diagnostics, d); }, checkEffectCall(name, callerEffects, effectAnnotations, compName));
|
|
|
|
|
})();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (isSxTruthy((isSxTruthy(!isSxTruthy(startsWith(name, "~"))) && isSxTruthy(!isSxTruthy(isNil(primParamTypes))) && dictHas(primParamTypes, name)))) {
|
|
|
|
|
{ var _c = checkPrimitiveCall(name, args, typeEnv, primTypes, primParamTypes, compName, typeRegistry); for (var _i = 0; _i < _c.length; _i++) { var d = _c[_i]; diagnostics.push(d); } }
|
|
|
|
|
}
|
|
|
|
|
if (isSxTruthy((isSxTruthy(!isSxTruthy(startsWith(name, "~"))) && !isSxTruthy(isNil(effectAnnotations))))) {
|
|
|
|
|
(function() {
|
|
|
|
|
var callerEffects = getEffects(compName, effectAnnotations);
|
|
|
|
|
return forEach(function(d) { return append_b(diagnostics, d); }, checkEffectCall(name, callerEffects, effectAnnotations, compName));
|
|
|
|
|
})();
|
|
|
|
|
}
|
|
|
|
|
if (isSxTruthy(sxOr((name == "let"), (name == "let*")))) {
|
|
|
|
|
if (isSxTruthy((len(args) >= 2))) {
|
|
|
|
|
(function() {
|
|
|
|
|
var bindings = first(args);
|
|
|
|
|
var bodyExprs = rest(args);
|
|
|
|
|
var extended = merge(typeEnv, {});
|
|
|
|
|
{ var _c = bindings; for (var _i = 0; _i < _c.length; _i++) { var binding = _c[_i]; if (isSxTruthy((isSxTruthy((typeOf(binding) == "list")) && (len(binding) >= 2)))) {
|
|
|
|
|
(function() {
|
|
|
|
|
var bname = (isSxTruthy((typeOf(first(binding)) == "symbol")) ? symbolName(first(binding)) : (String(first(binding))));
|
|
|
|
|
var valType = inferType(nth(binding, 1), extended, primTypes, typeRegistry);
|
|
|
|
|
return dictSet(extended, bname, valType);
|
|
|
|
|
})();
|
|
|
|
|
} } }
|
|
|
|
|
return forEach(function(body) { return checkBodyWalk(body, compName, extended, primTypes, primParamTypes, env, diagnostics, typeRegistry, effectAnnotations); }, bodyExprs);
|
|
|
|
|
})();
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return (isSxTruthy((name == "define")) ? (isSxTruthy((len(args) >= 2)) ? (function() {
|
|
|
|
|
var defName = (isSxTruthy((typeOf(first(args)) == "symbol")) ? symbolName(first(args)) : NIL);
|
|
|
|
|
var defVal = nth(args, 1);
|
|
|
|
|
if (isSxTruthy(defName)) {
|
|
|
|
|
typeEnv[defName] = inferType(defVal, typeEnv, primTypes, typeRegistry);
|
|
|
|
|
}
|
|
|
|
|
return checkBodyWalk(defVal, compName, typeEnv, primTypes, primParamTypes, env, diagnostics, typeRegistry, effectAnnotations);
|
|
|
|
|
})() : NIL) : NIL);
|
|
|
|
|
})();
|
|
|
|
|
}
|
|
|
|
|
return forEach(function(child) { return checkBodyWalk(child, compName, typeEnv, primTypes, primParamTypes, env, diagnostics, typeRegistry, effectAnnotations); }, args);
|
|
|
|
|
})() : NIL) : NIL);
|
|
|
|
|
})(); };
|
|
|
|
|
PRIMITIVES["check-body-walk"] = checkBodyWalk;
|
|
|
|
|
|
|
|
|
|
// check-component
|
|
|
|
|
var checkComponent = function(compName, env, primTypes, primParamTypes, typeRegistry, effectAnnotations) { return (function() {
|
|
|
|
|
var comp = envGet(env, compName);
|
|
|
|
|
var diagnostics = [];
|
|
|
|
|
if (isSxTruthy((typeOf(comp) == "component"))) {
|
|
|
|
|
(function() {
|
|
|
|
|
var body = componentBody(comp);
|
|
|
|
|
var params = componentParams(comp);
|
|
|
|
|
var paramTypes = componentParamTypes(comp);
|
|
|
|
|
var typeEnv = {};
|
|
|
|
|
{ var _c = params; for (var _i = 0; _i < _c.length; _i++) { var p = _c[_i]; typeEnv[p] = (isSxTruthy((isSxTruthy(!isSxTruthy(isNil(paramTypes))) && dictHas(paramTypes, p))) ? get(paramTypes, p) : "any"); } }
|
|
|
|
|
if (isSxTruthy(componentHasChildren(comp))) {
|
|
|
|
|
typeEnv["children"] = ["list-of", "element"];
|
|
|
|
|
}
|
|
|
|
|
return checkBodyWalk(body, compName, typeEnv, primTypes, primParamTypes, env, diagnostics, typeRegistry, effectAnnotations);
|
|
|
|
|
})();
|
|
|
|
|
}
|
|
|
|
|
return diagnostics;
|
|
|
|
|
})(); };
|
|
|
|
|
PRIMITIVES["check-component"] = checkComponent;
|
|
|
|
|
|
|
|
|
|
// check-all
|
|
|
|
|
var checkAll = function(env, primTypes, primParamTypes, typeRegistry, effectAnnotations) { return (function() {
|
|
|
|
|
var allDiagnostics = [];
|
|
|
|
|
{ var _c = keys(env); for (var _i = 0; _i < _c.length; _i++) { var name = _c[_i]; (function() {
|
|
|
|
|
var val = envGet(env, name);
|
|
|
|
|
return (isSxTruthy((typeOf(val) == "component")) ? forEach(function(d) { return append_b(allDiagnostics, d); }, checkComponent(name, env, primTypes, primParamTypes, typeRegistry, effectAnnotations)) : NIL);
|
|
|
|
|
})(); } }
|
|
|
|
|
return allDiagnostics;
|
|
|
|
|
})(); };
|
|
|
|
|
PRIMITIVES["check-all"] = checkAll;
|
|
|
|
|
|
|
|
|
|
// build-type-registry
|
|
|
|
|
var buildTypeRegistry = function(primDeclarations, ioDeclarations) { return (function() {
|
|
|
|
|
var registry = {};
|
|
|
|
|
{ var _c = primDeclarations; for (var _i = 0; _i < _c.length; _i++) { var decl = _c[_i]; (function() {
|
|
|
|
|
var name = get(decl, "name");
|
|
|
|
|
var returns = get(decl, "returns");
|
|
|
|
|
return (isSxTruthy((isSxTruthy(!isSxTruthy(isNil(name))) && !isSxTruthy(isNil(returns)))) ? dictSet(registry, name, returns) : NIL);
|
|
|
|
|
})(); } }
|
|
|
|
|
{ var _c = ioDeclarations; for (var _i = 0; _i < _c.length; _i++) { var decl = _c[_i]; (function() {
|
|
|
|
|
var name = get(decl, "name");
|
|
|
|
|
var returns = get(decl, "returns");
|
|
|
|
|
return (isSxTruthy((isSxTruthy(!isSxTruthy(isNil(name))) && !isSxTruthy(isNil(returns)))) ? dictSet(registry, name, returns) : NIL);
|
|
|
|
|
})(); } }
|
|
|
|
|
return registry;
|
|
|
|
|
})(); };
|
|
|
|
|
PRIMITIVES["build-type-registry"] = buildTypeRegistry;
|
|
|
|
|
|
|
|
|
|
// type-def-name
|
|
|
|
|
var typeDefName = function(td) { return get(td, "name"); };
|
|
|
|
|
PRIMITIVES["type-def-name"] = typeDefName;
|
|
|
|
|
|
|
|
|
|
// type-def-params
|
|
|
|
|
var typeDefParams = function(td) { return get(td, "params"); };
|
|
|
|
|
PRIMITIVES["type-def-params"] = typeDefParams;
|
|
|
|
|
|
|
|
|
|
// type-def-body
|
|
|
|
|
var typeDefBody = function(td) { return get(td, "body"); };
|
|
|
|
|
PRIMITIVES["type-def-body"] = typeDefBody;
|
|
|
|
|
|
|
|
|
|
// resolve-type
|
|
|
|
|
var resolveType = function(t, registry) { return (isSxTruthy(isNil(registry)) ? t : (isSxTruthy((typeOf(t) == "string")) ? (isSxTruthy(dictHas(registry, t)) ? (function() {
|
|
|
|
|
var td = get(registry, t);
|
|
|
|
|
return (function() {
|
|
|
|
|
var params = typeDefParams(td);
|
|
|
|
|
var body = typeDefBody(td);
|
|
|
|
|
return (isSxTruthy(isEmpty(params)) ? resolveType(body, registry) : t);
|
|
|
|
|
})();
|
|
|
|
|
})() : t) : (isSxTruthy((typeOf(t) == "list")) ? (isSxTruthy(isEmpty(t)) ? t : (function() {
|
|
|
|
|
var head = first(t);
|
|
|
|
|
return (isSxTruthy(sxOr((head == "or"), (head == "list-of"), (head == "->"), (head == "dict-of"))) ? cons(head, map(function(m) { return resolveType(m, registry); }, rest(t))) : (isSxTruthy((isSxTruthy((typeOf(head) == "string")) && dictHas(registry, head))) ? (function() {
|
|
|
|
|
var td = get(registry, head);
|
|
|
|
|
var params = typeDefParams(td);
|
|
|
|
|
var body = typeDefBody(td);
|
|
|
|
|
var args = rest(t);
|
|
|
|
|
return (isSxTruthy((len(params) == len(args))) ? resolveType(substituteTypeVars(body, params, args), registry) : t);
|
|
|
|
|
})() : t));
|
|
|
|
|
})()) : (isSxTruthy((typeOf(t) == "dict")) ? mapDict(function(k, v) { return resolveType(v, registry); }, t) : t)))); };
|
|
|
|
|
PRIMITIVES["resolve-type"] = resolveType;
|
|
|
|
|
|
|
|
|
|
// substitute-type-vars
|
|
|
|
|
var substituteTypeVars = function(body, params, args) { return (function() {
|
|
|
|
|
var subst = {};
|
|
|
|
|
{ var _c = range(0, len(params), 1); for (var _i = 0; _i < _c.length; _i++) { var i = _c[_i]; subst[nth(params, i)] = nth(args, i); } }
|
|
|
|
|
return substituteInType(body, subst);
|
|
|
|
|
})(); };
|
|
|
|
|
PRIMITIVES["substitute-type-vars"] = substituteTypeVars;
|
|
|
|
|
|
|
|
|
|
// substitute-in-type
|
|
|
|
|
var substituteInType = function(t, subst) { return (isSxTruthy((typeOf(t) == "string")) ? (isSxTruthy(dictHas(subst, t)) ? get(subst, t) : t) : (isSxTruthy((typeOf(t) == "list")) ? map(function(m) { return substituteInType(m, subst); }, t) : (isSxTruthy((typeOf(t) == "dict")) ? mapDict(function(k, v) { return substituteInType(v, subst); }, t) : t))); };
|
|
|
|
|
PRIMITIVES["substitute-in-type"] = substituteInType;
|
|
|
|
|
|
|
|
|
|
// subtype-resolved?
|
|
|
|
|
var subtypeResolved_p = function(a, b, registry) { return (isSxTruthy(isNil(registry)) ? subtype_p(a, b) : (function() {
|
|
|
|
|
var ra = resolveType(a, registry);
|
|
|
|
|
var rb = resolveType(b, registry);
|
|
|
|
|
return (isSxTruthy((isSxTruthy((typeOf(ra) == "dict")) && (typeOf(rb) == "dict"))) ? isEvery(function(key) { return (isSxTruthy(dictHas(ra, key)) && subtypeResolved_p(get(ra, key), get(rb, key), registry)); }, keys(rb)) : subtype_p(ra, rb));
|
|
|
|
|
})()); };
|
|
|
|
|
PRIMITIVES["subtype-resolved?"] = subtypeResolved_p;
|
|
|
|
|
|
|
|
|
|
// get-effects
|
|
|
|
|
var getEffects = function(name, effectAnnotations) { return (isSxTruthy(isNil(effectAnnotations)) ? NIL : (isSxTruthy(dictHas(effectAnnotations, name)) ? get(effectAnnotations, name) : NIL)); };
|
|
|
|
|
PRIMITIVES["get-effects"] = getEffects;
|
|
|
|
|
|
|
|
|
|
// effects-subset?
|
|
|
|
|
var effectsSubset_p = function(calleeEffects, callerEffects) { return (isSxTruthy(isNil(callerEffects)) ? true : (isSxTruthy(isNil(calleeEffects)) ? true : isEvery(function(e) { return contains(callerEffects, e); }, calleeEffects))); };
|
|
|
|
|
PRIMITIVES["effects-subset?"] = effectsSubset_p;
|
|
|
|
|
|
|
|
|
|
// check-effect-call
|
|
|
|
|
var checkEffectCall = function(calleeName, callerEffects, effectAnnotations, compName) { return (function() {
|
|
|
|
|
var diagnostics = [];
|
|
|
|
|
var calleeEffects = getEffects(calleeName, effectAnnotations);
|
|
|
|
|
if (isSxTruthy((isSxTruthy(!isSxTruthy(isNil(callerEffects))) && isSxTruthy(!isSxTruthy(isNil(calleeEffects))) && !isSxTruthy(effectsSubset_p(calleeEffects, callerEffects))))) {
|
|
|
|
|
diagnostics.push(makeDiagnostic("error", (String("`") + String(calleeName) + String("` has effects ") + String(join(", ", calleeEffects)) + String(" but `") + String(compName) + String("` only allows ") + String((isSxTruthy(isEmpty(callerEffects)) ? "[pure]" : join(", ", callerEffects)))), compName, NIL));
|
|
|
|
|
}
|
|
|
|
|
return diagnostics;
|
|
|
|
|
})(); };
|
|
|
|
|
PRIMITIVES["check-effect-call"] = checkEffectCall;
|
|
|
|
|
|
|
|
|
|
// build-effect-annotations
|
|
|
|
|
var buildEffectAnnotations = function(ioDeclarations) { return (function() {
|
|
|
|
|
var annotations = {};
|
|
|
|
|
{ var _c = ioDeclarations; for (var _i = 0; _i < _c.length; _i++) { var decl = _c[_i]; (function() {
|
|
|
|
|
var name = get(decl, "name");
|
|
|
|
|
return (isSxTruthy(!isSxTruthy(isNil(name))) ? dictSet(annotations, name, ["io"]) : NIL);
|
|
|
|
|
})(); } }
|
|
|
|
|
return annotations;
|
|
|
|
|
})(); };
|
|
|
|
|
PRIMITIVES["build-effect-annotations"] = buildEffectAnnotations;
|
|
|
|
|
|
|
|
|
|
// check-component-effects
|
|
|
|
|
var checkComponentEffects = function(compName, env, effectAnnotations) { return (function() {
|
|
|
|
|
var comp = envGet(env, compName);
|
|
|
|
|
var diagnostics = [];
|
|
|
|
|
if (isSxTruthy((typeOf(comp) == "component"))) {
|
|
|
|
|
(function() {
|
|
|
|
|
var body = componentBody(comp);
|
|
|
|
|
return checkBodyWalk(body, compName, {}, {}, NIL, env, diagnostics, NIL, effectAnnotations);
|
|
|
|
|
})();
|
|
|
|
|
}
|
|
|
|
|
return diagnostics;
|
|
|
|
|
})(); };
|
|
|
|
|
PRIMITIVES["check-component-effects"] = checkComponentEffects;
|
|
|
|
|
|
|
|
|
|
// check-all-effects
|
|
|
|
|
var checkAllEffects = function(env, effectAnnotations) { return (function() {
|
|
|
|
|
var allDiagnostics = [];
|
|
|
|
|
{ var _c = keys(env); for (var _i = 0; _i < _c.length; _i++) { var name = _c[_i]; (function() {
|
|
|
|
|
var val = envGet(env, name);
|
|
|
|
|
return (isSxTruthy((typeOf(val) == "component")) ? forEach(function(d) { return append_b(allDiagnostics, d); }, checkComponentEffects(name, env, effectAnnotations)) : NIL);
|
|
|
|
|
})(); } }
|
|
|
|
|
return allDiagnostics;
|
|
|
|
|
})(); };
|
|
|
|
|
PRIMITIVES["check-all-effects"] = checkAllEffects;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// =========================================================================
|
|
|
|
|
// Post-transpilation fixups
|
|
|
|
|
// =========================================================================
|
|
|
|
|
|