Merge specced eval-cond/process-bindings from render.sx
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 4m18s
All checks were successful
Build and Deploy / build-and-deploy (push) Successful in 4m18s
This commit is contained in:
@@ -493,39 +493,7 @@
|
|||||||
"map":1,"map-indexed":1,"filter":1,"reduce":1,"some":1,"every?":1,"for-each":1
|
"map":1,"map-indexed":1,"filter":1,"reduce":1,"some":1,"every?":1,"for-each":1
|
||||||
}; }
|
}; }
|
||||||
|
|
||||||
// processBindings and evalCond — exposed for DOM adapter render forms
|
// processBindings and evalCond — now specced in render.sx, bootstrapped above
|
||||||
function processBindings(bindings, env) {
|
|
||||||
var local = merge(env);
|
|
||||||
for (var i = 0; i < bindings.length; i++) {
|
|
||||||
var pair = bindings[i];
|
|
||||||
if (Array.isArray(pair) && pair.length >= 2) {
|
|
||||||
var name = isSym(pair[0]) ? pair[0].name : String(pair[0]);
|
|
||||||
local[name] = trampoline(evalExpr(pair[1], local));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return local;
|
|
||||||
}
|
|
||||||
function evalCond(clauses, env) {
|
|
||||||
// Detect scheme-style ((test body) ...) vs clojure-style (test body test body ...)
|
|
||||||
var scheme = clauses.length > 0 && Array.isArray(clauses[0]) && clauses[0].length === 2;
|
|
||||||
if (scheme) {
|
|
||||||
for (var i = 0; i < clauses.length; i++) {
|
|
||||||
var clause = clauses[i];
|
|
||||||
var test = clause[0], body = clause[1];
|
|
||||||
if (isSym(test) && (test.name === "else" || test.name === ":else")) return body;
|
|
||||||
if (isKw(test) && test.name === "else") return body;
|
|
||||||
if (isSxTruthy(trampoline(evalExpr(test, env)))) return body;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (var i = 0; i < clauses.length; i += 2) {
|
|
||||||
var test = clauses[i];
|
|
||||||
if (isSym(test) && test.name === ":else") return clauses[i + 1];
|
|
||||||
if (isKw(test) && test.name === "else") return clauses[i + 1];
|
|
||||||
if (isSxTruthy(trampoline(evalExpr(test, env)))) return clauses[i + 1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function isDefinitionForm(name) {
|
function isDefinitionForm(name) {
|
||||||
return name === "define" || name === "defcomp" || name === "defmacro" ||
|
return name === "define" || name === "defcomp" || name === "defmacro" ||
|
||||||
@@ -1082,6 +1050,36 @@ return append_b(inits, nth(binding, 1)); }, bindings) : reduce(function(acc, pai
|
|||||||
return (isSxTruthy((isSxTruthy(contains(BOOLEAN_ATTRS, key)) && val)) ? (String(" ") + String(key)) : (isSxTruthy((isSxTruthy(contains(BOOLEAN_ATTRS, key)) && !val)) ? "" : (isSxTruthy(isNil(val)) ? "" : (isSxTruthy((isSxTruthy((key == "style")) && isStyleValue(val))) ? (String(" class=\"") + String(styleValueClass(val)) + String("\"")) : (String(" ") + String(key) + String("=\"") + String(escapeAttr((String(val)))) + String("\""))))));
|
return (isSxTruthy((isSxTruthy(contains(BOOLEAN_ATTRS, key)) && val)) ? (String(" ") + String(key)) : (isSxTruthy((isSxTruthy(contains(BOOLEAN_ATTRS, key)) && !val)) ? "" : (isSxTruthy(isNil(val)) ? "" : (isSxTruthy((isSxTruthy((key == "style")) && isStyleValue(val))) ? (String(" class=\"") + String(styleValueClass(val)) + String("\"")) : (String(" ") + String(key) + String("=\"") + String(escapeAttr((String(val)))) + String("\""))))));
|
||||||
})(); }, keys(attrs))); };
|
})(); }, keys(attrs))); };
|
||||||
|
|
||||||
|
// eval-cond
|
||||||
|
var evalCond = function(clauses, env) { return (isSxTruthy((isSxTruthy(!isEmpty(clauses)) && isSxTruthy((typeOf(first(clauses)) == "list")) && (len(first(clauses)) == 2))) ? evalCondScheme(clauses, env) : evalCondClojure(clauses, env)); };
|
||||||
|
|
||||||
|
// eval-cond-scheme
|
||||||
|
var evalCondScheme = function(clauses, env) { return (isSxTruthy(isEmpty(clauses)) ? NIL : (function() {
|
||||||
|
var clause = first(clauses);
|
||||||
|
var test = first(clause);
|
||||||
|
var body = nth(clause, 1);
|
||||||
|
return (isSxTruthy(sxOr((isSxTruthy((typeOf(test) == "symbol")) && sxOr((symbolName(test) == "else"), (symbolName(test) == ":else"))), (isSxTruthy((typeOf(test) == "keyword")) && (keywordName(test) == "else")))) ? body : (isSxTruthy(trampoline(evalExpr(test, env))) ? body : evalCondScheme(rest(clauses), env)));
|
||||||
|
})()); };
|
||||||
|
|
||||||
|
// eval-cond-clojure
|
||||||
|
var evalCondClojure = function(clauses, env) { return (isSxTruthy((len(clauses) < 2)) ? NIL : (function() {
|
||||||
|
var test = first(clauses);
|
||||||
|
var body = nth(clauses, 1);
|
||||||
|
return (isSxTruthy(sxOr((isSxTruthy((typeOf(test) == "keyword")) && (keywordName(test) == "else")), (isSxTruthy((typeOf(test) == "symbol")) && sxOr((symbolName(test) == "else"), (symbolName(test) == ":else"))))) ? body : (isSxTruthy(trampoline(evalExpr(test, env))) ? body : evalCondClojure(slice(clauses, 2), env)));
|
||||||
|
})()); };
|
||||||
|
|
||||||
|
// process-bindings
|
||||||
|
var processBindings = function(bindings, env) { return (function() {
|
||||||
|
var local = merge(env);
|
||||||
|
{ var _c = bindings; for (var _i = 0; _i < _c.length; _i++) { var pair = _c[_i]; if (isSxTruthy((isSxTruthy((typeOf(pair) == "list")) && (len(pair) >= 2)))) {
|
||||||
|
(function() {
|
||||||
|
var name = (isSxTruthy((typeOf(first(pair)) == "symbol")) ? symbolName(first(pair)) : (String(first(pair))));
|
||||||
|
return envSet(local, name, trampoline(evalExpr(nth(pair, 1), local)));
|
||||||
|
})();
|
||||||
|
} } }
|
||||||
|
return local;
|
||||||
|
})(); };
|
||||||
|
|
||||||
|
|
||||||
// === Transpiled from parser ===
|
// === Transpiled from parser ===
|
||||||
|
|
||||||
|
|||||||
@@ -273,6 +273,8 @@ class JSEmitter:
|
|||||||
"dict-delete!": "dictDelete",
|
"dict-delete!": "dictDelete",
|
||||||
"process-bindings": "processBindings",
|
"process-bindings": "processBindings",
|
||||||
"eval-cond": "evalCond",
|
"eval-cond": "evalCond",
|
||||||
|
"eval-cond-scheme": "evalCondScheme",
|
||||||
|
"eval-cond-clojure": "evalCondClojure",
|
||||||
"for-each-indexed": "forEachIndexed",
|
"for-each-indexed": "forEachIndexed",
|
||||||
"index-of": "indexOf_",
|
"index-of": "indexOf_",
|
||||||
"component-has-children?": "componentHasChildren",
|
"component-has-children?": "componentHasChildren",
|
||||||
@@ -1823,39 +1825,7 @@ PLATFORM_JS_POST = '''
|
|||||||
"map":1,"map-indexed":1,"filter":1,"reduce":1,"some":1,"every?":1,"for-each":1
|
"map":1,"map-indexed":1,"filter":1,"reduce":1,"some":1,"every?":1,"for-each":1
|
||||||
}; }
|
}; }
|
||||||
|
|
||||||
// processBindings and evalCond — exposed for DOM adapter render forms
|
// processBindings and evalCond — now specced in render.sx, bootstrapped above
|
||||||
function processBindings(bindings, env) {
|
|
||||||
var local = merge(env);
|
|
||||||
for (var i = 0; i < bindings.length; i++) {
|
|
||||||
var pair = bindings[i];
|
|
||||||
if (Array.isArray(pair) && pair.length >= 2) {
|
|
||||||
var name = isSym(pair[0]) ? pair[0].name : String(pair[0]);
|
|
||||||
local[name] = trampoline(evalExpr(pair[1], local));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return local;
|
|
||||||
}
|
|
||||||
function evalCond(clauses, env) {
|
|
||||||
// Detect scheme-style ((test body) ...) vs clojure-style (test body test body ...)
|
|
||||||
var scheme = clauses.length > 0 && Array.isArray(clauses[0]) && clauses[0].length === 2;
|
|
||||||
if (scheme) {
|
|
||||||
for (var i = 0; i < clauses.length; i++) {
|
|
||||||
var clause = clauses[i];
|
|
||||||
var test = clause[0], body = clause[1];
|
|
||||||
if (isSym(test) && (test.name === "else" || test.name === ":else")) return body;
|
|
||||||
if (isKw(test) && test.name === "else") return body;
|
|
||||||
if (isSxTruthy(trampoline(evalExpr(test, env)))) return body;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (var i = 0; i < clauses.length; i += 2) {
|
|
||||||
var test = clauses[i];
|
|
||||||
if (isSym(test) && test.name === ":else") return clauses[i + 1];
|
|
||||||
if (isKw(test) && test.name === "else") return clauses[i + 1];
|
|
||||||
if (isSxTruthy(trampoline(evalExpr(test, env)))) return clauses[i + 1];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
function isDefinitionForm(name) {
|
function isDefinitionForm(name) {
|
||||||
return name === "define" || name === "defcomp" || name === "defmacro" ||
|
return name === "define" || name === "defcomp" || name === "defmacro" ||
|
||||||
|
|||||||
@@ -236,6 +236,8 @@ class PyEmitter:
|
|||||||
"map-indexed": "map_indexed",
|
"map-indexed": "map_indexed",
|
||||||
"map-dict": "map_dict",
|
"map-dict": "map_dict",
|
||||||
"eval-cond": "eval_cond",
|
"eval-cond": "eval_cond",
|
||||||
|
"eval-cond-scheme": "eval_cond_scheme",
|
||||||
|
"eval-cond-clojure": "eval_cond_clojure",
|
||||||
"process-bindings": "process_bindings",
|
"process-bindings": "process_bindings",
|
||||||
# deps.sx
|
# deps.sx
|
||||||
"scan-refs": "scan_refs",
|
"scan-refs": "scan_refs",
|
||||||
|
|||||||
@@ -124,6 +124,75 @@
|
|||||||
(keys attrs)))))
|
(keys attrs)))))
|
||||||
|
|
||||||
|
|
||||||
|
;; --------------------------------------------------------------------------
|
||||||
|
;; Render adapter helpers
|
||||||
|
;; --------------------------------------------------------------------------
|
||||||
|
;; Shared by HTML and DOM adapters for evaluating control forms during
|
||||||
|
;; rendering. Unlike sf-cond (eval.sx) which returns a thunk for TCO,
|
||||||
|
;; eval-cond returns the unevaluated body expression so the adapter
|
||||||
|
;; can render it in its own mode (HTML string vs DOM nodes).
|
||||||
|
|
||||||
|
;; eval-cond: find matching cond branch, return unevaluated body expr.
|
||||||
|
;; Handles both scheme-style ((test body) ...) and clojure-style
|
||||||
|
;; (test body test body ...).
|
||||||
|
(define eval-cond
|
||||||
|
(fn (clauses env)
|
||||||
|
(if (and (not (empty? clauses))
|
||||||
|
(= (type-of (first clauses)) "list")
|
||||||
|
(= (len (first clauses)) 2))
|
||||||
|
;; Scheme-style
|
||||||
|
(eval-cond-scheme clauses env)
|
||||||
|
;; Clojure-style
|
||||||
|
(eval-cond-clojure clauses env))))
|
||||||
|
|
||||||
|
(define eval-cond-scheme
|
||||||
|
(fn (clauses env)
|
||||||
|
(if (empty? clauses)
|
||||||
|
nil
|
||||||
|
(let ((clause (first clauses))
|
||||||
|
(test (first clause))
|
||||||
|
(body (nth clause 1)))
|
||||||
|
(if (or (and (= (type-of test) "symbol")
|
||||||
|
(or (= (symbol-name test) "else")
|
||||||
|
(= (symbol-name test) ":else")))
|
||||||
|
(and (= (type-of test) "keyword")
|
||||||
|
(= (keyword-name test) "else")))
|
||||||
|
body
|
||||||
|
(if (trampoline (eval-expr test env))
|
||||||
|
body
|
||||||
|
(eval-cond-scheme (rest clauses) env)))))))
|
||||||
|
|
||||||
|
(define eval-cond-clojure
|
||||||
|
(fn (clauses env)
|
||||||
|
(if (< (len clauses) 2)
|
||||||
|
nil
|
||||||
|
(let ((test (first clauses))
|
||||||
|
(body (nth clauses 1)))
|
||||||
|
(if (or (and (= (type-of test) "keyword") (= (keyword-name test) "else"))
|
||||||
|
(and (= (type-of test) "symbol")
|
||||||
|
(or (= (symbol-name test) "else")
|
||||||
|
(= (symbol-name test) ":else"))))
|
||||||
|
body
|
||||||
|
(if (trampoline (eval-expr test env))
|
||||||
|
body
|
||||||
|
(eval-cond-clojure (slice clauses 2) env)))))))
|
||||||
|
|
||||||
|
;; process-bindings: evaluate let-binding pairs, return extended env.
|
||||||
|
;; bindings = ((name1 expr1) (name2 expr2) ...)
|
||||||
|
(define process-bindings
|
||||||
|
(fn (bindings env)
|
||||||
|
(let ((local (merge env)))
|
||||||
|
(for-each
|
||||||
|
(fn (pair)
|
||||||
|
(when (and (= (type-of pair) "list") (>= (len pair) 2))
|
||||||
|
(let ((name (if (= (type-of (first pair)) "symbol")
|
||||||
|
(symbol-name (first pair))
|
||||||
|
(str (first pair)))))
|
||||||
|
(env-set! local name (trampoline (eval-expr (nth pair 1) local))))))
|
||||||
|
bindings)
|
||||||
|
local)))
|
||||||
|
|
||||||
|
|
||||||
;; --------------------------------------------------------------------------
|
;; --------------------------------------------------------------------------
|
||||||
;; Platform interface (shared across adapters)
|
;; Platform interface (shared across adapters)
|
||||||
;; --------------------------------------------------------------------------
|
;; --------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -1140,6 +1140,18 @@ parse_element_args = lambda args, env: (lambda attrs: (lambda children: _sx_begi
|
|||||||
# render-attrs
|
# render-attrs
|
||||||
render_attrs = lambda attrs: join('', map(lambda key: (lambda val: (sx_str(' ', key) if sx_truthy((contains_p(BOOLEAN_ATTRS, key) if not sx_truthy(contains_p(BOOLEAN_ATTRS, key)) else val)) else ('' if sx_truthy((contains_p(BOOLEAN_ATTRS, key) if not sx_truthy(contains_p(BOOLEAN_ATTRS, key)) else (not sx_truthy(val)))) else ('' if sx_truthy(is_nil(val)) else (sx_str(' class="', style_value_class(val), '"') if sx_truthy(((key == 'style') if not sx_truthy((key == 'style')) else is_style_value(val))) else sx_str(' ', key, '="', escape_attr(sx_str(val)), '"'))))))(dict_get(attrs, key)), keys(attrs)))
|
render_attrs = lambda attrs: join('', map(lambda key: (lambda val: (sx_str(' ', key) if sx_truthy((contains_p(BOOLEAN_ATTRS, key) if not sx_truthy(contains_p(BOOLEAN_ATTRS, key)) else val)) else ('' if sx_truthy((contains_p(BOOLEAN_ATTRS, key) if not sx_truthy(contains_p(BOOLEAN_ATTRS, key)) else (not sx_truthy(val)))) else ('' if sx_truthy(is_nil(val)) else (sx_str(' class="', style_value_class(val), '"') if sx_truthy(((key == 'style') if not sx_truthy((key == 'style')) else is_style_value(val))) else sx_str(' ', key, '="', escape_attr(sx_str(val)), '"'))))))(dict_get(attrs, key)), keys(attrs)))
|
||||||
|
|
||||||
|
# eval-cond
|
||||||
|
eval_cond = lambda clauses, env: (eval_cond_scheme(clauses, env) if sx_truthy(((not sx_truthy(empty_p(clauses))) if not sx_truthy((not sx_truthy(empty_p(clauses)))) else ((type_of(first(clauses)) == 'list') if not sx_truthy((type_of(first(clauses)) == 'list')) else (len(first(clauses)) == 2)))) else eval_cond_clojure(clauses, env))
|
||||||
|
|
||||||
|
# eval-cond-scheme
|
||||||
|
eval_cond_scheme = lambda clauses, env: (NIL if sx_truthy(empty_p(clauses)) else (lambda clause: (lambda test: (lambda body: (body if sx_truthy((((type_of(test) == 'symbol') if not sx_truthy((type_of(test) == 'symbol')) else ((symbol_name(test) == 'else') if sx_truthy((symbol_name(test) == 'else')) else (symbol_name(test) == ':else'))) if sx_truthy(((type_of(test) == 'symbol') if not sx_truthy((type_of(test) == 'symbol')) else ((symbol_name(test) == 'else') if sx_truthy((symbol_name(test) == 'else')) else (symbol_name(test) == ':else')))) else ((type_of(test) == 'keyword') if not sx_truthy((type_of(test) == 'keyword')) else (keyword_name(test) == 'else')))) else (body if sx_truthy(trampoline(eval_expr(test, env))) else eval_cond_scheme(rest(clauses), env))))(nth(clause, 1)))(first(clause)))(first(clauses)))
|
||||||
|
|
||||||
|
# eval-cond-clojure
|
||||||
|
eval_cond_clojure = lambda clauses, env: (NIL if sx_truthy((len(clauses) < 2)) else (lambda test: (lambda body: (body if sx_truthy((((type_of(test) == 'keyword') if not sx_truthy((type_of(test) == 'keyword')) else (keyword_name(test) == 'else')) if sx_truthy(((type_of(test) == 'keyword') if not sx_truthy((type_of(test) == 'keyword')) else (keyword_name(test) == 'else'))) else ((type_of(test) == 'symbol') if not sx_truthy((type_of(test) == 'symbol')) else ((symbol_name(test) == 'else') if sx_truthy((symbol_name(test) == 'else')) else (symbol_name(test) == ':else'))))) else (body if sx_truthy(trampoline(eval_expr(test, env))) else eval_cond_clojure(slice(clauses, 2), env))))(nth(clauses, 1)))(first(clauses)))
|
||||||
|
|
||||||
|
# process-bindings
|
||||||
|
process_bindings = lambda bindings, env: (lambda local: _sx_begin(for_each(lambda pair: ((lambda name: _sx_dict_set(local, name, trampoline(eval_expr(nth(pair, 1), local))))((symbol_name(first(pair)) if sx_truthy((type_of(first(pair)) == 'symbol')) else sx_str(first(pair)))) if sx_truthy(((type_of(pair) == 'list') if not sx_truthy((type_of(pair) == 'list')) else (len(pair) >= 2))) else NIL), bindings), local))(merge(env))
|
||||||
|
|
||||||
|
|
||||||
# === Transpiled from adapter-html ===
|
# === Transpiled from adapter-html ===
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user