From 7036621be82e95f58430ce15a645f66ad8dde59b Mon Sep 17 00:00:00 2001 From: giles Date: Sun, 15 Mar 2026 02:18:56 +0000 Subject: [PATCH] Phase 3: Move host files to hosts/python/ and hosts/javascript/ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Python: bootstrap.py, platform.py, transpiler.sx, boundary_parser.py, tests/ JavaScript: bootstrap.py, cli.py, platform.py, transpiler.sx Both bootstrappers verified — build from new locations, output to shared/. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../javascript/bootstrap.py | 9 +- .../javascript/cli.py | 8 +- .../javascript/platform.py | 0 .../js.sx => hosts/javascript/transpiler.sx | 0 .../python/bootstrap.py | 8 +- .../ref => hosts/python}/boundary_parser.py | 0 .../python/platform.py | 0 .../python/tests}/run_cek_reactive_tests.py | 0 .../python/tests}/run_cek_tests.py | 0 .../python/tests}/run_continuation_tests.py | 0 .../python/tests}/run_signal_tests.py | 0 .../python/tests}/run_type_tests.py | 0 .../ref/py.sx => hosts/python/transpiler.sx | 0 shared/static/scripts/sx-browser.js | 2 +- shared/sx/ref/sx_ref.py | 2084 ----------------- 15 files changed, 14 insertions(+), 2097 deletions(-) rename shared/sx/ref/run_js_sx.py => hosts/javascript/bootstrap.py (97%) rename shared/sx/ref/bootstrap_js.py => hosts/javascript/cli.py (88%) rename shared/sx/ref/platform_js.py => hosts/javascript/platform.py (100%) rename shared/sx/ref/js.sx => hosts/javascript/transpiler.sx (100%) rename shared/sx/ref/bootstrap_py.py => hosts/python/bootstrap.py (99%) rename {shared/sx/ref => hosts/python}/boundary_parser.py (100%) rename shared/sx/ref/platform_py.py => hosts/python/platform.py (100%) rename {shared/sx/ref => hosts/python/tests}/run_cek_reactive_tests.py (100%) rename {shared/sx/ref => hosts/python/tests}/run_cek_tests.py (100%) rename {shared/sx/ref => hosts/python/tests}/run_continuation_tests.py (100%) rename {shared/sx/ref => hosts/python/tests}/run_signal_tests.py (100%) rename {shared/sx/ref => hosts/python/tests}/run_type_tests.py (100%) rename shared/sx/ref/py.sx => hosts/python/transpiler.sx (100%) diff --git a/shared/sx/ref/run_js_sx.py b/hosts/javascript/bootstrap.py similarity index 97% rename from shared/sx/ref/run_js_sx.py rename to hosts/javascript/bootstrap.py index 096e92a..02edb56 100644 --- a/shared/sx/ref/run_js_sx.py +++ b/hosts/javascript/bootstrap.py @@ -16,13 +16,13 @@ import os import sys _HERE = os.path.dirname(os.path.abspath(__file__)) -_PROJECT = os.path.abspath(os.path.join(_HERE, "..", "..", "..")) +_PROJECT = os.path.abspath(os.path.join(_HERE, "..", "..")) if _PROJECT not in sys.path: sys.path.insert(0, _PROJECT) from shared.sx.parser import parse_all from shared.sx.types import Symbol -from shared.sx.ref.platform_js import ( +from hosts.javascript.platform import ( extract_defines, ADAPTER_FILES, ADAPTER_DEPS, SPEC_MODULES, SPEC_MODULE_ORDER, EXTENSION_NAMES, PREAMBLE, PLATFORM_JS_PRE, PLATFORM_JS_POST, @@ -44,7 +44,7 @@ def load_js_sx() -> dict: if _js_sx_env is not None: return _js_sx_env - js_sx_path = os.path.join(_HERE, "js.sx") + js_sx_path = os.path.join(_HERE, "transpiler.sx") with open(js_sx_path) as f: source = f.read() @@ -77,8 +77,7 @@ def compile_ref_to_js( from datetime import datetime, timezone from shared.sx.ref.sx_ref import evaluate - ref_dir = _HERE - _PROJECT = os.path.abspath(os.path.join(_HERE, "..", "..", "..")) + ref_dir = os.path.join(_PROJECT, "shared", "sx", "ref") # Source directories: core spec, web framework, and legacy ref (for bootstrapper tools) _source_dirs = [ os.path.join(_PROJECT, "spec"), # Core spec diff --git a/shared/sx/ref/bootstrap_js.py b/hosts/javascript/cli.py similarity index 88% rename from shared/sx/ref/bootstrap_js.py rename to hosts/javascript/cli.py index 1af6eaa..3176a4f 100644 --- a/shared/sx/ref/bootstrap_js.py +++ b/hosts/javascript/cli.py @@ -20,8 +20,10 @@ if _PROJECT not in sys.path: # Re-export everything that consumers import from this module. # Canonical source is now run_js_sx.py (self-hosting via js.sx) and platform_js.py. -from shared.sx.ref.run_js_sx import compile_ref_to_js, load_js_sx # noqa: F401 -from shared.sx.ref.platform_js import ( # noqa: F401 +import sys, os +sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..", ".."))) +from hosts.javascript.bootstrap import compile_ref_to_js, load_js_sx # noqa: F401 +from hosts.javascript.platform import ( # noqa: F401 extract_defines, ADAPTER_FILES, ADAPTER_DEPS, SPEC_MODULES, EXTENSION_NAMES, PREAMBLE, PLATFORM_JS_PRE, PLATFORM_JS_POST, @@ -44,7 +46,7 @@ if __name__ == "__main__": help="Comma-separated extensions (continuations). Default: none.") p.add_argument("--spec-modules", help="Comma-separated spec modules (deps). Default: none.") - default_output = os.path.join(_HERE, "..", "..", "static", "scripts", "sx-browser.js") + default_output = os.path.join(_HERE, "..", "..", "shared", "static", "scripts", "sx-browser.js") p.add_argument("--output", "-o", default=default_output, help="Output file (default: shared/static/scripts/sx-browser.js)") args = p.parse_args() diff --git a/shared/sx/ref/platform_js.py b/hosts/javascript/platform.py similarity index 100% rename from shared/sx/ref/platform_js.py rename to hosts/javascript/platform.py diff --git a/shared/sx/ref/js.sx b/hosts/javascript/transpiler.sx similarity index 100% rename from shared/sx/ref/js.sx rename to hosts/javascript/transpiler.sx diff --git a/shared/sx/ref/bootstrap_py.py b/hosts/python/bootstrap.py similarity index 99% rename from shared/sx/ref/bootstrap_py.py rename to hosts/python/bootstrap.py index af42b0a..d478f4a 100644 --- a/shared/sx/ref/bootstrap_py.py +++ b/hosts/python/bootstrap.py @@ -20,7 +20,7 @@ import sys # Add project root to path for imports _HERE = os.path.dirname(os.path.abspath(__file__)) -_PROJECT = os.path.abspath(os.path.join(_HERE, "..", "..", "..")) +_PROJECT = os.path.abspath(os.path.join(_HERE, "..", "..")) sys.path.insert(0, _PROJECT) from shared.sx.parser import parse_all @@ -1313,7 +1313,7 @@ try: EXTENSION_NAMES, EXTENSION_FORMS, ) except ImportError: - from shared.sx.ref.platform_py import ( + from hosts.python.platform import ( PREAMBLE, PLATFORM_PY, PRIMITIVES_PY_PRE, PRIMITIVES_PY_POST, PRIMITIVES_PY_MODULES, _ALL_PY_MODULES, PLATFORM_PARSER_PY, @@ -1439,8 +1439,8 @@ def compile_ref_to_py( raise ValueError(f"Unknown module: {m!r}. Valid: {', '.join(PRIMITIVES_PY_MODULES)}") prim_modules.append(m) - ref_dir = os.path.dirname(os.path.abspath(__file__)) - _project = os.path.abspath(os.path.join(ref_dir, "..", "..", "..")) + ref_dir = os.path.join(os.path.abspath(os.path.join(os.path.dirname(os.path.abspath(__file__)), "..", "..")), "shared", "sx", "ref") + _project = os.path.abspath(os.path.join(ref_dir, "..", "..")) _source_dirs = [ os.path.join(_project, "spec"), os.path.join(_project, "web"), diff --git a/shared/sx/ref/boundary_parser.py b/hosts/python/boundary_parser.py similarity index 100% rename from shared/sx/ref/boundary_parser.py rename to hosts/python/boundary_parser.py diff --git a/shared/sx/ref/platform_py.py b/hosts/python/platform.py similarity index 100% rename from shared/sx/ref/platform_py.py rename to hosts/python/platform.py diff --git a/shared/sx/ref/run_cek_reactive_tests.py b/hosts/python/tests/run_cek_reactive_tests.py similarity index 100% rename from shared/sx/ref/run_cek_reactive_tests.py rename to hosts/python/tests/run_cek_reactive_tests.py diff --git a/shared/sx/ref/run_cek_tests.py b/hosts/python/tests/run_cek_tests.py similarity index 100% rename from shared/sx/ref/run_cek_tests.py rename to hosts/python/tests/run_cek_tests.py diff --git a/shared/sx/ref/run_continuation_tests.py b/hosts/python/tests/run_continuation_tests.py similarity index 100% rename from shared/sx/ref/run_continuation_tests.py rename to hosts/python/tests/run_continuation_tests.py diff --git a/shared/sx/ref/run_signal_tests.py b/hosts/python/tests/run_signal_tests.py similarity index 100% rename from shared/sx/ref/run_signal_tests.py rename to hosts/python/tests/run_signal_tests.py diff --git a/shared/sx/ref/run_type_tests.py b/hosts/python/tests/run_type_tests.py similarity index 100% rename from shared/sx/ref/run_type_tests.py rename to hosts/python/tests/run_type_tests.py diff --git a/shared/sx/ref/py.sx b/hosts/python/transpiler.sx similarity index 100% rename from shared/sx/ref/py.sx rename to hosts/python/transpiler.sx diff --git a/shared/static/scripts/sx-browser.js b/shared/static/scripts/sx-browser.js index 48db83e..5c3b46b 100644 --- a/shared/static/scripts/sx-browser.js +++ b/shared/static/scripts/sx-browser.js @@ -14,7 +14,7 @@ // ========================================================================= var NIL = Object.freeze({ _nil: true, toString: function() { return "nil"; } }); - var SX_VERSION = "2026-03-15T02:11:58Z"; + var SX_VERSION = "2026-03-15T02:18:33Z"; function isNil(x) { return x === NIL || x === null || x === undefined; } function isSxTruthy(x) { return x !== false && !isNil(x); } diff --git a/shared/sx/ref/sx_ref.py b/shared/sx/ref/sx_ref.py index 70a81cf..2e269f9 100644 --- a/shared/sx/ref/sx_ref.py +++ b/shared/sx/ref/sx_ref.py @@ -1242,711 +1242,6 @@ async def async_eval_slot_to_sx(expr, env, ctx=None): _expand_components_cv.reset(token) -# === Transpiled from eval === - -# trampoline -def trampoline(val): - result = val - if sx_truthy(is_thunk(result)): - return trampoline(eval_expr(thunk_expr(result), thunk_env(result))) - else: - return result - -# eval-expr -def eval_expr(expr, env): - _match = type_of(expr) - if _match == 'number': - return expr - elif _match == 'string': - return expr - elif _match == 'boolean': - return expr - elif _match == 'nil': - return NIL - elif _match == 'symbol': - name = symbol_name(expr) - if sx_truthy(env_has(env, name)): - return env_get(env, name) - elif sx_truthy(is_primitive(name)): - return get_primitive(name) - elif sx_truthy((name == 'true')): - return True - elif sx_truthy((name == 'false')): - return False - elif sx_truthy((name == 'nil')): - return NIL - else: - debug_log('Undefined symbol:', name, 'primitive?:', is_primitive(name)) - return error(sx_str('Undefined symbol: ', name)) - elif _match == 'keyword': - return keyword_name(expr) - elif _match == 'dict': - return map_dict(lambda k, v: trampoline(eval_expr(v, env)), expr) - elif _match == 'list': - if sx_truthy(empty_p(expr)): - return [] - else: - return eval_list(expr, env) - else: - return expr - -# eval-list -def eval_list(expr, env): - head = first(expr) - args = rest(expr) - if sx_truthy((not sx_truthy(((type_of(head) == 'symbol') if sx_truthy((type_of(head) == 'symbol')) else ((type_of(head) == 'lambda') if sx_truthy((type_of(head) == 'lambda')) else (type_of(head) == 'list')))))): - return map(lambda x: trampoline(eval_expr(x, env)), expr) - else: - if sx_truthy((type_of(head) == 'symbol')): - name = symbol_name(head) - if sx_truthy((name == 'if')): - return sf_if(args, env) - elif sx_truthy((name == 'when')): - return sf_when(args, env) - elif sx_truthy((name == 'cond')): - return sf_cond(args, env) - elif sx_truthy((name == 'case')): - return sf_case(args, env) - elif sx_truthy((name == 'and')): - return sf_and(args, env) - elif sx_truthy((name == 'or')): - return sf_or(args, env) - elif sx_truthy((name == 'let')): - return sf_let(args, env) - elif sx_truthy((name == 'let*')): - return sf_let(args, env) - elif sx_truthy((name == 'letrec')): - return sf_letrec(args, env) - elif sx_truthy((name == 'lambda')): - return sf_lambda(args, env) - elif sx_truthy((name == 'fn')): - return sf_lambda(args, env) - elif sx_truthy((name == 'define')): - return sf_define(args, env) - elif sx_truthy((name == 'defcomp')): - return sf_defcomp(args, env) - elif sx_truthy((name == 'defisland')): - return sf_defisland(args, env) - elif sx_truthy((name == 'defmacro')): - return sf_defmacro(args, env) - elif sx_truthy((name == 'defstyle')): - return sf_defstyle(args, env) - elif sx_truthy((name == 'defhandler')): - return sf_defhandler(args, env) - elif sx_truthy((name == 'defpage')): - return sf_defpage(args, env) - elif sx_truthy((name == 'defquery')): - return sf_defquery(args, env) - elif sx_truthy((name == 'defaction')): - return sf_defaction(args, env) - elif sx_truthy((name == 'deftype')): - return sf_deftype(args, env) - elif sx_truthy((name == 'defeffect')): - return sf_defeffect(args, env) - elif sx_truthy((name == 'begin')): - return sf_begin(args, env) - elif sx_truthy((name == 'do')): - return sf_begin(args, env) - elif sx_truthy((name == 'quote')): - return sf_quote(args, env) - elif sx_truthy((name == 'quasiquote')): - return sf_quasiquote(args, env) - elif sx_truthy((name == '->')): - return sf_thread_first(args, env) - elif sx_truthy((name == 'set!')): - return sf_set_bang(args, env) - elif sx_truthy((name == 'reset')): - return sf_reset(args, env) - elif sx_truthy((name == 'shift')): - return sf_shift(args, env) - elif sx_truthy((name == 'dynamic-wind')): - return sf_dynamic_wind(args, env) - elif sx_truthy((name == 'scope')): - return sf_scope(args, env) - elif sx_truthy((name == 'provide')): - return sf_provide(args, env) - elif sx_truthy((name == 'map')): - return ho_map(args, env) - elif sx_truthy((name == 'map-indexed')): - return ho_map_indexed(args, env) - elif sx_truthy((name == 'filter')): - return ho_filter(args, env) - elif sx_truthy((name == 'reduce')): - return ho_reduce(args, env) - elif sx_truthy((name == 'some')): - return ho_some(args, env) - elif sx_truthy((name == 'every?')): - return ho_every(args, env) - elif sx_truthy((name == 'for-each')): - return ho_for_each(args, env) - elif sx_truthy((env_has(env, name) if not sx_truthy(env_has(env, name)) else is_macro(env_get(env, name)))): - mac = env_get(env, name) - return make_thunk(expand_macro(mac, args, env), env) - elif sx_truthy((render_active_p() if not sx_truthy(render_active_p()) else is_render_expr(expr))): - return render_expr(expr, env) - else: - return eval_call(head, args, env) - else: - return eval_call(head, args, env) - -# eval-call -def eval_call(head, args, env): - f = trampoline(eval_expr(head, env)) - evaluated_args = map(lambda a: trampoline(eval_expr(a, env)), args) - if sx_truthy((is_callable(f) if not sx_truthy(is_callable(f)) else ((not sx_truthy(is_lambda(f))) if not sx_truthy((not sx_truthy(is_lambda(f)))) else ((not sx_truthy(is_component(f))) if not sx_truthy((not sx_truthy(is_component(f)))) else (not sx_truthy(is_island(f))))))): - return apply(f, evaluated_args) - elif sx_truthy(is_lambda(f)): - return call_lambda(f, evaluated_args, env) - elif sx_truthy(is_component(f)): - return call_component(f, args, env) - elif sx_truthy(is_island(f)): - return call_component(f, args, env) - else: - return error(sx_str('Not callable: ', inspect(f))) - -# call-lambda -def call_lambda(f, args, caller_env): - params = lambda_params(f) - local = env_merge(lambda_closure(f), caller_env) - if sx_truthy((len(args) > len(params))): - return error(sx_str((lambda_name(f) if sx_truthy(lambda_name(f)) else 'lambda'), ' expects ', len(params), ' args, got ', len(args))) - else: - for pair in zip(params, args): - local[first(pair)] = nth(pair, 1) - for p in slice(params, len(args)): - local[p] = NIL - return make_thunk(lambda_body(f), local) - -# call-component -def call_component(comp, raw_args, env): - parsed = parse_keyword_args(raw_args, env) - kwargs = first(parsed) - children = nth(parsed, 1) - local = env_merge(component_closure(comp), env) - for p in component_params(comp): - local[p] = (dict_get(kwargs, p) if sx_truthy(dict_get(kwargs, p)) else NIL) - if sx_truthy(component_has_children(comp)): - local['children'] = children - return make_thunk(component_body(comp), local) - -# parse-keyword-args -def parse_keyword_args(raw_args, env): - kwargs = {} - children = [] - i = 0 - reduce(lambda state, arg: (lambda idx: (lambda skip: (assoc(state, 'skip', False, 'i', (idx + 1)) if sx_truthy(skip) else (_sx_begin(_sx_dict_set(kwargs, keyword_name(arg), trampoline(eval_expr(nth(raw_args, (idx + 1)), env))), assoc(state, 'skip', True, 'i', (idx + 1))) if sx_truthy(((type_of(arg) == 'keyword') if not sx_truthy((type_of(arg) == 'keyword')) else ((idx + 1) < len(raw_args)))) else _sx_begin(_sx_append(children, trampoline(eval_expr(arg, env))), assoc(state, 'i', (idx + 1))))))(get(state, 'skip')))(get(state, 'i')), {'i': 0, 'skip': False}, raw_args) - return [kwargs, children] - -# sf-if -def sf_if(args, env): - condition = trampoline(eval_expr(first(args), env)) - if sx_truthy((condition if not sx_truthy(condition) else (not sx_truthy(is_nil(condition))))): - return make_thunk(nth(args, 1), env) - else: - if sx_truthy((len(args) > 2)): - return make_thunk(nth(args, 2), env) - else: - return NIL - -# sf-when -def sf_when(args, env): - condition = trampoline(eval_expr(first(args), env)) - if sx_truthy((condition if not sx_truthy(condition) else (not sx_truthy(is_nil(condition))))): - for e in slice(args, 1, (len(args) - 1)): - trampoline(eval_expr(e, env)) - return make_thunk(last(args), env) - else: - return NIL - -# cond-scheme? -def cond_scheme_p(clauses): - return every_p(lambda c: ((type_of(c) == 'list') if not sx_truthy((type_of(c) == 'list')) else (len(c) == 2)), clauses) - -# sf-cond -def sf_cond(args, env): - if sx_truthy(cond_scheme_p(args)): - return sf_cond_scheme(args, env) - else: - return sf_cond_clojure(args, env) - -# sf-cond-scheme -def sf_cond_scheme(clauses, env): - if sx_truthy(empty_p(clauses)): - return NIL - else: - clause = first(clauses) - test = first(clause) - body = nth(clause, 1) - 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')))): - return make_thunk(body, env) - else: - if sx_truthy(trampoline(eval_expr(test, env))): - return make_thunk(body, env) - else: - return sf_cond_scheme(rest(clauses), env) - -# sf-cond-clojure -def sf_cond_clojure(clauses, env): - if sx_truthy((len(clauses) < 2)): - return NIL - else: - test = first(clauses) - body = nth(clauses, 1) - 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'))))): - return make_thunk(body, env) - else: - if sx_truthy(trampoline(eval_expr(test, env))): - return make_thunk(body, env) - else: - return sf_cond_clojure(slice(clauses, 2), env) - -# sf-case -def sf_case(args, env): - match_val = trampoline(eval_expr(first(args), env)) - clauses = rest(args) - return sf_case_loop(match_val, clauses, env) - -# sf-case-loop -def sf_case_loop(match_val, clauses, env): - if sx_truthy((len(clauses) < 2)): - return NIL - else: - test = first(clauses) - body = nth(clauses, 1) - 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'))))): - return make_thunk(body, env) - else: - if sx_truthy((match_val == trampoline(eval_expr(test, env)))): - return make_thunk(body, env) - else: - return sf_case_loop(match_val, slice(clauses, 2), env) - -# sf-and -def sf_and(args, env): - if sx_truthy(empty_p(args)): - return True - else: - val = trampoline(eval_expr(first(args), env)) - if sx_truthy((not sx_truthy(val))): - return val - else: - if sx_truthy((len(args) == 1)): - return val - else: - return sf_and(rest(args), env) - -# sf-or -def sf_or(args, env): - if sx_truthy(empty_p(args)): - return False - else: - val = trampoline(eval_expr(first(args), env)) - if sx_truthy(val): - return val - else: - return sf_or(rest(args), env) - -# sf-let -def sf_let(args, env): - if sx_truthy((type_of(first(args)) == 'symbol')): - return sf_named_let(args, env) - else: - bindings = first(args) - body = rest(args) - local = env_extend(env) - if sx_truthy(((type_of(first(bindings)) == 'list') if not sx_truthy((type_of(first(bindings)) == 'list')) else (len(first(bindings)) == 2))): - for binding in bindings: - vname = (symbol_name(first(binding)) if sx_truthy((type_of(first(binding)) == 'symbol')) else first(binding)) - local[vname] = trampoline(eval_expr(nth(binding, 1), local)) - else: - i = 0 - reduce(lambda acc, pair_idx: (lambda vname: (lambda val_expr: _sx_dict_set(local, vname, trampoline(eval_expr(val_expr, local))))(nth(bindings, ((pair_idx * 2) + 1))))((symbol_name(nth(bindings, (pair_idx * 2))) if sx_truthy((type_of(nth(bindings, (pair_idx * 2))) == 'symbol')) else nth(bindings, (pair_idx * 2)))), NIL, range(0, (len(bindings) / 2))) - for e in slice(body, 0, (len(body) - 1)): - trampoline(eval_expr(e, local)) - return make_thunk(last(body), local) - -# sf-named-let -def sf_named_let(args, env): - loop_name = symbol_name(first(args)) - bindings = nth(args, 1) - body = slice(args, 2) - params = [] - inits = [] - if sx_truthy(((type_of(first(bindings)) == 'list') if not sx_truthy((type_of(first(bindings)) == 'list')) else (len(first(bindings)) == 2))): - for binding in bindings: - params.append((symbol_name(first(binding)) if sx_truthy((type_of(first(binding)) == 'symbol')) else first(binding))) - inits.append(nth(binding, 1)) - else: - reduce(lambda acc, pair_idx: _sx_begin(_sx_append(params, (symbol_name(nth(bindings, (pair_idx * 2))) if sx_truthy((type_of(nth(bindings, (pair_idx * 2))) == 'symbol')) else nth(bindings, (pair_idx * 2)))), _sx_append(inits, nth(bindings, ((pair_idx * 2) + 1)))), NIL, range(0, (len(bindings) / 2))) - loop_body = (first(body) if sx_truthy((len(body) == 1)) else cons(make_symbol('begin'), body)) - loop_fn = make_lambda(params, loop_body, env) - loop_fn.name = loop_name - lambda_closure(loop_fn)[loop_name] = loop_fn - init_vals = map(lambda e: trampoline(eval_expr(e, env)), inits) - return call_lambda(loop_fn, init_vals, env) - -# sf-lambda -def sf_lambda(args, env): - params_expr = first(args) - body_exprs = rest(args) - body = (first(body_exprs) if sx_truthy((len(body_exprs) == 1)) else cons(make_symbol('begin'), body_exprs)) - param_names = map(lambda p: (symbol_name(p) if sx_truthy((type_of(p) == 'symbol')) else (symbol_name(first(p)) if sx_truthy(((type_of(p) == 'list') if not sx_truthy((type_of(p) == 'list')) else ((len(p) == 3) if not sx_truthy((len(p) == 3)) else ((type_of(nth(p, 1)) == 'keyword') if not sx_truthy((type_of(nth(p, 1)) == 'keyword')) else (keyword_name(nth(p, 1)) == 'as'))))) else p)), params_expr) - return make_lambda(param_names, body, env) - -# sf-define -def sf_define(args, env): - name_sym = first(args) - has_effects = ((len(args) >= 4) if not sx_truthy((len(args) >= 4)) else ((type_of(nth(args, 1)) == 'keyword') if not sx_truthy((type_of(nth(args, 1)) == 'keyword')) else (keyword_name(nth(args, 1)) == 'effects'))) - val_idx = (3 if sx_truthy(((len(args) >= 4) if not sx_truthy((len(args) >= 4)) else ((type_of(nth(args, 1)) == 'keyword') if not sx_truthy((type_of(nth(args, 1)) == 'keyword')) else (keyword_name(nth(args, 1)) == 'effects')))) else 1) - value = trampoline(eval_expr(nth(args, val_idx), env)) - if sx_truthy((is_lambda(value) if not sx_truthy(is_lambda(value)) else is_nil(lambda_name(value)))): - value.name = symbol_name(name_sym) - env[symbol_name(name_sym)] = value - if sx_truthy(has_effects): - effects_raw = nth(args, 2) - effect_list = (map(lambda e: (symbol_name(e) if sx_truthy((type_of(e) == 'symbol')) else sx_str(e)), effects_raw) if sx_truthy((type_of(effects_raw) == 'list')) else [sx_str(effects_raw)]) - effect_anns = (env_get(env, '*effect-annotations*') if sx_truthy(env_has(env, '*effect-annotations*')) else {}) - effect_anns[symbol_name(name_sym)] = effect_list - env['*effect-annotations*'] = effect_anns - return value - -# sf-defcomp -def sf_defcomp(args, env): - name_sym = first(args) - params_raw = nth(args, 1) - body = last(args) - comp_name = strip_prefix(symbol_name(name_sym), '~') - parsed = parse_comp_params(params_raw) - params = first(parsed) - has_children = nth(parsed, 1) - param_types = nth(parsed, 2) - affinity = defcomp_kwarg(args, 'affinity', 'auto') - comp = make_component(comp_name, params, has_children, body, env, affinity) - effects = defcomp_kwarg(args, 'effects', NIL) - if sx_truthy(((not sx_truthy(is_nil(param_types))) if not sx_truthy((not sx_truthy(is_nil(param_types)))) else (not sx_truthy(empty_p(keys(param_types)))))): - component_set_param_types(comp, param_types) - if sx_truthy((not sx_truthy(is_nil(effects)))): - effect_list = (map(lambda e: (symbol_name(e) if sx_truthy((type_of(e) == 'symbol')) else sx_str(e)), effects) if sx_truthy((type_of(effects) == 'list')) else [sx_str(effects)]) - effect_anns = (env_get(env, '*effect-annotations*') if sx_truthy(env_has(env, '*effect-annotations*')) else {}) - effect_anns[symbol_name(name_sym)] = effect_list - env['*effect-annotations*'] = effect_anns - env[symbol_name(name_sym)] = comp - return comp - -# defcomp-kwarg -def defcomp_kwarg(args, key, default_): - _cells = {} - end = (len(args) - 1) - _cells['result'] = default_ - for i in range(2, end, 1): - if sx_truthy(((type_of(nth(args, i)) == 'keyword') if not sx_truthy((type_of(nth(args, i)) == 'keyword')) else ((keyword_name(nth(args, i)) == key) if not sx_truthy((keyword_name(nth(args, i)) == key)) else ((i + 1) < end)))): - val = nth(args, (i + 1)) - _cells['result'] = (keyword_name(val) if sx_truthy((type_of(val) == 'keyword')) else val) - return _cells['result'] - -# parse-comp-params -def parse_comp_params(params_expr): - _cells = {} - params = [] - param_types = {} - _cells['has_children'] = False - _cells['in_key'] = False - for p in params_expr: - if sx_truthy(((type_of(p) == 'list') if not sx_truthy((type_of(p) == 'list')) else ((len(p) == 3) if not sx_truthy((len(p) == 3)) else ((type_of(first(p)) == 'symbol') if not sx_truthy((type_of(first(p)) == 'symbol')) else ((type_of(nth(p, 1)) == 'keyword') if not sx_truthy((type_of(nth(p, 1)) == 'keyword')) else (keyword_name(nth(p, 1)) == 'as')))))): - name = symbol_name(first(p)) - ptype = nth(p, 2) - type_val = (symbol_name(ptype) if sx_truthy((type_of(ptype) == 'symbol')) else ptype) - if sx_truthy((not sx_truthy(_cells['has_children']))): - params.append(name) - param_types[name] = type_val - else: - if sx_truthy((type_of(p) == 'symbol')): - name = symbol_name(p) - if sx_truthy((name == '&key')): - _cells['in_key'] = True - elif sx_truthy((name == '&rest')): - _cells['has_children'] = True - elif sx_truthy((name == '&children')): - _cells['has_children'] = True - elif sx_truthy(_cells['has_children']): - NIL - elif sx_truthy(_cells['in_key']): - params.append(name) - else: - params.append(name) - return [params, _cells['has_children'], param_types] - -# sf-defisland -def sf_defisland(args, env): - name_sym = first(args) - params_raw = nth(args, 1) - body = last(args) - comp_name = strip_prefix(symbol_name(name_sym), '~') - parsed = parse_comp_params(params_raw) - params = first(parsed) - has_children = nth(parsed, 1) - island = make_island(comp_name, params, has_children, body, env) - env[symbol_name(name_sym)] = island - return island - -# sf-defmacro -def sf_defmacro(args, env): - name_sym = first(args) - params_raw = nth(args, 1) - body = nth(args, 2) - parsed = parse_macro_params(params_raw) - params = first(parsed) - rest_param = nth(parsed, 1) - mac = make_macro(params, rest_param, body, env, symbol_name(name_sym)) - env[symbol_name(name_sym)] = mac - return mac - -# parse-macro-params -def parse_macro_params(params_expr): - _cells = {} - params = [] - _cells['rest_param'] = NIL - reduce(lambda state, p: (assoc(state, 'in-rest', True) if sx_truthy(((type_of(p) == 'symbol') if not sx_truthy((type_of(p) == 'symbol')) else (symbol_name(p) == '&rest'))) else (_sx_begin(_sx_cell_set(_cells, 'rest_param', (symbol_name(p) if sx_truthy((type_of(p) == 'symbol')) else p)), state) if sx_truthy(get(state, 'in-rest')) else _sx_begin(_sx_append(params, (symbol_name(p) if sx_truthy((type_of(p) == 'symbol')) else p)), state))), {'in-rest': False}, params_expr) - return [params, _cells['rest_param']] - -# sf-defstyle -def sf_defstyle(args, env): - name_sym = first(args) - value = trampoline(eval_expr(nth(args, 1), env)) - env[symbol_name(name_sym)] = value - return value - -# make-type-def -def make_type_def(name, params, body): - return {'name': name, 'params': params, 'body': body} - -# normalize-type-body -def normalize_type_body(body): - if sx_truthy(is_nil(body)): - return 'nil' - elif sx_truthy((type_of(body) == 'symbol')): - return symbol_name(body) - elif sx_truthy((type_of(body) == 'string')): - return body - elif sx_truthy((type_of(body) == 'keyword')): - return keyword_name(body) - elif sx_truthy((type_of(body) == 'dict')): - return map_dict(lambda k, v: normalize_type_body(v), body) - elif sx_truthy((type_of(body) == 'list')): - if sx_truthy(empty_p(body)): - return 'any' - else: - head = first(body) - head_name = (symbol_name(head) if sx_truthy((type_of(head) == 'symbol')) else sx_str(head)) - if sx_truthy((head_name == 'union')): - return cons('or', map(normalize_type_body, rest(body))) - else: - return cons(head_name, map(normalize_type_body, rest(body))) - else: - return sx_str(body) - -# sf-deftype -def sf_deftype(args, env): - name_or_form = first(args) - body_expr = nth(args, 1) - type_name = NIL - type_params = [] - if sx_truthy((type_of(name_or_form) == 'symbol')): - type_name = symbol_name(name_or_form) - else: - if sx_truthy((type_of(name_or_form) == 'list')): - type_name = symbol_name(first(name_or_form)) - type_params = map(lambda p: (symbol_name(p) if sx_truthy((type_of(p) == 'symbol')) else sx_str(p)), rest(name_or_form)) - body = normalize_type_body(body_expr) - registry = (env_get(env, '*type-registry*') if sx_truthy(env_has(env, '*type-registry*')) else {}) - registry[type_name] = make_type_def(type_name, type_params, body) - env['*type-registry*'] = registry - return NIL - -# sf-defeffect -def sf_defeffect(args, env): - effect_name = (symbol_name(first(args)) if sx_truthy((type_of(first(args)) == 'symbol')) else sx_str(first(args))) - registry = (env_get(env, '*effect-registry*') if sx_truthy(env_has(env, '*effect-registry*')) else []) - if sx_truthy((not sx_truthy(contains_p(registry, effect_name)))): - registry.append(effect_name) - env['*effect-registry*'] = registry - return NIL - -# sf-begin -def sf_begin(args, env): - if sx_truthy(empty_p(args)): - return NIL - else: - for e in slice(args, 0, (len(args) - 1)): - trampoline(eval_expr(e, env)) - return make_thunk(last(args), env) - -# sf-quote -def sf_quote(args, env): - if sx_truthy(empty_p(args)): - return NIL - else: - return first(args) - -# sf-quasiquote -def sf_quasiquote(args, env): - return qq_expand(first(args), env) - -# qq-expand -def qq_expand(template, env): - if sx_truthy((not sx_truthy((type_of(template) == 'list')))): - return template - else: - if sx_truthy(empty_p(template)): - return [] - else: - head = first(template) - if sx_truthy(((type_of(head) == 'symbol') if not sx_truthy((type_of(head) == 'symbol')) else (symbol_name(head) == 'unquote'))): - return trampoline(eval_expr(nth(template, 1), env)) - else: - return reduce(lambda result, item: ((lambda spliced: (concat(result, spliced) if sx_truthy((type_of(spliced) == 'list')) else (result if sx_truthy(is_nil(spliced)) else concat(result, [spliced]))))(trampoline(eval_expr(nth(item, 1), env))) if sx_truthy(((type_of(item) == 'list') if not sx_truthy((type_of(item) == 'list')) else ((len(item) == 2) if not sx_truthy((len(item) == 2)) else ((type_of(first(item)) == 'symbol') if not sx_truthy((type_of(first(item)) == 'symbol')) else (symbol_name(first(item)) == 'splice-unquote'))))) else concat(result, [qq_expand(item, env)])), [], template) - -# sf-thread-first -def sf_thread_first(args, env): - val = trampoline(eval_expr(first(args), env)) - return reduce(lambda result, form: ((lambda f: (lambda rest_args: (lambda all_args: (apply(f, all_args) if sx_truthy((is_callable(f) if not sx_truthy(is_callable(f)) else (not sx_truthy(is_lambda(f))))) else (trampoline(call_lambda(f, all_args, env)) if sx_truthy(is_lambda(f)) else error(sx_str('-> form not callable: ', inspect(f))))))(cons(result, rest_args)))(map(lambda a: trampoline(eval_expr(a, env)), rest(form))))(trampoline(eval_expr(first(form), env))) if sx_truthy((type_of(form) == 'list')) else (lambda f: (f(result) if sx_truthy((is_callable(f) if not sx_truthy(is_callable(f)) else (not sx_truthy(is_lambda(f))))) else (trampoline(call_lambda(f, [result], env)) if sx_truthy(is_lambda(f)) else error(sx_str('-> form not callable: ', inspect(f))))))(trampoline(eval_expr(form, env)))), val, rest(args)) - -# sf-set! -def sf_set_bang(args, env): - name = symbol_name(first(args)) - value = trampoline(eval_expr(nth(args, 1), env)) - env[name] = value - return value - -# sf-letrec -def sf_letrec(args, env): - bindings = first(args) - body = rest(args) - local = env_extend(env) - names = [] - val_exprs = [] - if sx_truthy(((type_of(first(bindings)) == 'list') if not sx_truthy((type_of(first(bindings)) == 'list')) else (len(first(bindings)) == 2))): - for binding in bindings: - vname = (symbol_name(first(binding)) if sx_truthy((type_of(first(binding)) == 'symbol')) else first(binding)) - names.append(vname) - val_exprs.append(nth(binding, 1)) - local[vname] = NIL - else: - reduce(lambda acc, pair_idx: (lambda vname: (lambda val_expr: _sx_begin(_sx_append(names, vname), _sx_append(val_exprs, val_expr), _sx_dict_set(local, vname, NIL)))(nth(bindings, ((pair_idx * 2) + 1))))((symbol_name(nth(bindings, (pair_idx * 2))) if sx_truthy((type_of(nth(bindings, (pair_idx * 2))) == 'symbol')) else nth(bindings, (pair_idx * 2)))), NIL, range(0, (len(bindings) / 2))) - values = map(lambda e: trampoline(eval_expr(e, local)), val_exprs) - for pair in zip(names, values): - local[first(pair)] = nth(pair, 1) - for val in values: - if sx_truthy(is_lambda(val)): - for n in names: - lambda_closure(val)[n] = env_get(local, n) - for e in slice(body, 0, (len(body) - 1)): - trampoline(eval_expr(e, local)) - return make_thunk(last(body), local) - -# sf-dynamic-wind -def sf_dynamic_wind(args, env): - before = trampoline(eval_expr(first(args), env)) - body = trampoline(eval_expr(nth(args, 1), env)) - after = trampoline(eval_expr(nth(args, 2), env)) - return dynamic_wind_call(before, body, after, env) - -# sf-scope -def sf_scope(args, env): - _cells = {} - name = trampoline(eval_expr(first(args), env)) - rest = slice(args, 1) - val = NIL - body_exprs = NIL - if sx_truthy(((len(rest) >= 2) if not sx_truthy((len(rest) >= 2)) else ((type_of(first(rest)) == 'keyword') if not sx_truthy((type_of(first(rest)) == 'keyword')) else (keyword_name(first(rest)) == 'value')))): - val = trampoline(eval_expr(nth(rest, 1), env)) - body_exprs = slice(rest, 2) - else: - body_exprs = rest - scope_push(name, val) - _cells['result'] = NIL - for e in body_exprs: - _cells['result'] = trampoline(eval_expr(e, env)) - scope_pop(name) - return _cells['result'] - -# sf-provide -def sf_provide(args, env): - _cells = {} - name = trampoline(eval_expr(first(args), env)) - val = trampoline(eval_expr(nth(args, 1), env)) - body_exprs = slice(args, 2) - _cells['result'] = NIL - scope_push(name, val) - for e in body_exprs: - _cells['result'] = trampoline(eval_expr(e, env)) - scope_pop(name) - return _cells['result'] - -# expand-macro -def expand_macro(mac, raw_args, env): - local = env_merge(macro_closure(mac), env) - for pair in map_indexed(lambda i, p: [p, i], macro_params(mac)): - local[first(pair)] = (nth(raw_args, nth(pair, 1)) if sx_truthy((nth(pair, 1) < len(raw_args))) else NIL) - if sx_truthy(macro_rest_param(mac)): - local[macro_rest_param(mac)] = slice(raw_args, len(macro_params(mac))) - return trampoline(eval_expr(macro_body(mac), local)) - -# call-fn -def call_fn(f, args, env): - if sx_truthy(is_lambda(f)): - return trampoline(call_lambda(f, args, env)) - elif sx_truthy(is_callable(f)): - return apply(f, args) - else: - return error(sx_str('Not callable in HO form: ', inspect(f))) - -# ho-map -def ho_map(args, env): - f = trampoline(eval_expr(first(args), env)) - coll = trampoline(eval_expr(nth(args, 1), env)) - return map(lambda item: call_fn(f, [item], env), coll) - -# ho-map-indexed -def ho_map_indexed(args, env): - f = trampoline(eval_expr(first(args), env)) - coll = trampoline(eval_expr(nth(args, 1), env)) - return map_indexed(lambda i, item: call_fn(f, [i, item], env), coll) - -# ho-filter -def ho_filter(args, env): - f = trampoline(eval_expr(first(args), env)) - coll = trampoline(eval_expr(nth(args, 1), env)) - return filter(lambda item: call_fn(f, [item], env), coll) - -# ho-reduce -def ho_reduce(args, env): - f = trampoline(eval_expr(first(args), env)) - init = trampoline(eval_expr(nth(args, 1), env)) - coll = trampoline(eval_expr(nth(args, 2), env)) - return reduce(lambda acc, item: call_fn(f, [acc, item], env), init, coll) - -# ho-some -def ho_some(args, env): - f = trampoline(eval_expr(first(args), env)) - coll = trampoline(eval_expr(nth(args, 1), env)) - return some(lambda item: call_fn(f, [item], env), coll) - -# ho-every -def ho_every(args, env): - f = trampoline(eval_expr(first(args), env)) - coll = trampoline(eval_expr(nth(args, 1), env)) - return every_p(lambda item: call_fn(f, [item], env), coll) - -# ho-for-each -def ho_for_each(args, env): - f = trampoline(eval_expr(first(args), env)) - coll = trampoline(eval_expr(nth(args, 1), env)) - for item in coll: - call_fn(f, [item], env) - return NIL - - # === Transpiled from forms (server definition forms) === # parse-key-params @@ -2074,374 +1369,6 @@ def validate_stream_data(data): return ((type_of(data) == 'list') if not sx_truthy((type_of(data) == 'list')) else every_p(lambda item: (type_of(item) == 'dict'), data)) -# === Transpiled from render (core) === - -# HTML_TAGS -HTML_TAGS = ['html', 'head', 'body', 'title', 'meta', 'link', 'script', 'style', 'noscript', 'header', 'nav', 'main', 'section', 'article', 'aside', 'footer', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'hgroup', 'div', 'p', 'blockquote', 'pre', 'figure', 'figcaption', 'address', 'details', 'summary', 'a', 'span', 'em', 'strong', 'small', 'b', 'i', 'u', 's', 'mark', 'sub', 'sup', 'abbr', 'cite', 'code', 'time', 'br', 'wbr', 'hr', 'ul', 'ol', 'li', 'dl', 'dt', 'dd', 'table', 'thead', 'tbody', 'tfoot', 'tr', 'th', 'td', 'caption', 'colgroup', 'col', 'form', 'input', 'textarea', 'select', 'option', 'optgroup', 'button', 'label', 'fieldset', 'legend', 'output', 'datalist', 'img', 'video', 'audio', 'source', 'picture', 'canvas', 'iframe', 'svg', 'math', 'path', 'circle', 'ellipse', 'rect', 'line', 'polyline', 'polygon', 'text', 'tspan', 'g', 'defs', 'use', 'clipPath', 'mask', 'pattern', 'linearGradient', 'radialGradient', 'stop', 'filter', 'feGaussianBlur', 'feOffset', 'feBlend', 'feColorMatrix', 'feComposite', 'feMerge', 'feMergeNode', 'feTurbulence', 'feComponentTransfer', 'feFuncR', 'feFuncG', 'feFuncB', 'feFuncA', 'feDisplacementMap', 'feFlood', 'feImage', 'feMorphology', 'feSpecularLighting', 'feDiffuseLighting', 'fePointLight', 'feSpotLight', 'feDistantLight', 'animate', 'animateTransform', 'foreignObject', 'template', 'slot', 'dialog', 'menu'] - -# VOID_ELEMENTS -VOID_ELEMENTS = ['area', 'base', 'br', 'col', 'embed', 'hr', 'img', 'input', 'link', 'meta', 'param', 'source', 'track', 'wbr'] - -# BOOLEAN_ATTRS -BOOLEAN_ATTRS = ['async', 'autofocus', 'autoplay', 'checked', 'controls', 'default', 'defer', 'disabled', 'formnovalidate', 'hidden', 'inert', 'ismap', 'loop', 'multiple', 'muted', 'nomodule', 'novalidate', 'open', 'playsinline', 'readonly', 'required', 'reversed', 'selected'] - -# definition-form? -def is_definition_form(name): - return ((name == 'define') if sx_truthy((name == 'define')) else ((name == 'defcomp') if sx_truthy((name == 'defcomp')) else ((name == 'defisland') if sx_truthy((name == 'defisland')) else ((name == 'defmacro') if sx_truthy((name == 'defmacro')) else ((name == 'defstyle') if sx_truthy((name == 'defstyle')) else ((name == 'defhandler') if sx_truthy((name == 'defhandler')) else ((name == 'deftype') if sx_truthy((name == 'deftype')) else (name == 'defeffect')))))))) - -# parse-element-args -def parse_element_args(args, env): - attrs = {} - children = [] - reduce(lambda state, arg: (lambda skip: (assoc(state, 'skip', False, 'i', (get(state, 'i') + 1)) if sx_truthy(skip) else ((lambda val: _sx_begin(_sx_dict_set(attrs, keyword_name(arg), val), assoc(state, 'skip', True, 'i', (get(state, 'i') + 1))))(trampoline(eval_expr(nth(args, (get(state, 'i') + 1)), env))) if sx_truthy(((type_of(arg) == 'keyword') if not sx_truthy((type_of(arg) == 'keyword')) else ((get(state, 'i') + 1) < len(args)))) else _sx_begin(_sx_append(children, arg), assoc(state, 'i', (get(state, 'i') + 1))))))(get(state, 'skip')), {'i': 0, 'skip': False}, args) - return [attrs, children] - -# render-attrs -def render_attrs(attrs): - return 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(' ', key, '="', escape_attr(sx_str(val)), '"')))))(dict_get(attrs, key)), keys(attrs))) - -# eval-cond -def eval_cond(clauses, env): - if sx_truthy(cond_scheme_p(clauses)): - return eval_cond_scheme(clauses, env) - else: - return eval_cond_clojure(clauses, env) - -# eval-cond-scheme -def eval_cond_scheme(clauses, env): - if sx_truthy(empty_p(clauses)): - return NIL - else: - clause = first(clauses) - test = first(clause) - body = nth(clause, 1) - 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')))): - return body - else: - if sx_truthy(trampoline(eval_expr(test, env))): - return body - else: - return eval_cond_scheme(rest(clauses), env) - -# eval-cond-clojure -def eval_cond_clojure(clauses, env): - if sx_truthy((len(clauses) < 2)): - return NIL - else: - test = first(clauses) - body = nth(clauses, 1) - 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'))))): - return body - else: - if sx_truthy(trampoline(eval_expr(test, env))): - return body - else: - return eval_cond_clojure(slice(clauses, 2), env) - -# process-bindings -def process_bindings(bindings, env): - local = env_extend(env) - for pair in bindings: - if sx_truthy(((type_of(pair) == 'list') if not sx_truthy((type_of(pair) == 'list')) else (len(pair) >= 2))): - name = (symbol_name(first(pair)) if sx_truthy((type_of(first(pair)) == 'symbol')) else sx_str(first(pair))) - local[name] = trampoline(eval_expr(nth(pair, 1), local)) - return local - -# is-render-expr? -def is_render_expr(expr): - if sx_truthy(((not sx_truthy((type_of(expr) == 'list'))) if sx_truthy((not sx_truthy((type_of(expr) == 'list')))) else empty_p(expr))): - return False - else: - h = first(expr) - if sx_truthy((not sx_truthy((type_of(h) == 'symbol')))): - return False - else: - n = symbol_name(h) - return ((n == '<>') if sx_truthy((n == '<>')) else ((n == 'raw!') if sx_truthy((n == 'raw!')) else (starts_with_p(n, '~') if sx_truthy(starts_with_p(n, '~')) else (starts_with_p(n, 'html:') if sx_truthy(starts_with_p(n, 'html:')) else (contains_p(HTML_TAGS, n) if sx_truthy(contains_p(HTML_TAGS, n)) else ((index_of(n, '-') > 0) if not sx_truthy((index_of(n, '-') > 0)) else ((len(expr) > 1) if not sx_truthy((len(expr) > 1)) else (type_of(nth(expr, 1)) == 'keyword')))))))) - -# merge-spread-attrs -def merge_spread_attrs(target, spread_dict): - for key in keys(spread_dict): - val = dict_get(spread_dict, key) - if sx_truthy((key == 'class')): - existing = dict_get(target, 'class') - target['class'] = (sx_str(existing, ' ', val) if sx_truthy((existing if not sx_truthy(existing) else (not sx_truthy((existing == ''))))) else val) - else: - if sx_truthy((key == 'style')): - existing = dict_get(target, 'style') - target['style'] = (sx_str(existing, ';', val) if sx_truthy((existing if not sx_truthy(existing) else (not sx_truthy((existing == ''))))) else val) - else: - target[key] = val - return NIL - - -# === Transpiled from parser === - -# sx-parse -def sx_parse(source): - _cells = {} - _cells['pos'] = 0 - len_src = len(source) - def skip_comment(): - while True: - if sx_truthy(((_cells['pos'] < len_src) if not sx_truthy((_cells['pos'] < len_src)) else (not sx_truthy((nth(source, _cells['pos']) == '\n'))))): - _cells['pos'] = (_cells['pos'] + 1) - continue - break - def skip_ws(): - while True: - if sx_truthy((_cells['pos'] < len_src)): - ch = nth(source, _cells['pos']) - if sx_truthy(((ch == ' ') if sx_truthy((ch == ' ')) else ((ch == '\t') if sx_truthy((ch == '\t')) else ((ch == '\n') if sx_truthy((ch == '\n')) else (ch == '\r'))))): - _cells['pos'] = (_cells['pos'] + 1) - continue - elif sx_truthy((ch == ';')): - _cells['pos'] = (_cells['pos'] + 1) - skip_comment() - continue - else: - break - break - def hex_digit_value(ch): - return index_of('0123456789abcdef', lower(ch)) - def read_string(): - _cells['pos'] = (_cells['pos'] + 1) - _cells['buf'] = '' - while True: - if sx_truthy((_cells['pos'] >= len_src)): - error('Unterminated string') - break - else: - ch = nth(source, _cells['pos']) - if sx_truthy((ch == '"')): - _cells['pos'] = (_cells['pos'] + 1) - break - elif sx_truthy((ch == '\\')): - _cells['pos'] = (_cells['pos'] + 1) - esc = nth(source, _cells['pos']) - if sx_truthy((esc == 'u')): - _cells['pos'] = (_cells['pos'] + 1) - d0 = hex_digit_value(nth(source, _cells['pos'])) - _ = _sx_cell_set(_cells, 'pos', (_cells['pos'] + 1)) - d1 = hex_digit_value(nth(source, _cells['pos'])) - _ = _sx_cell_set(_cells, 'pos', (_cells['pos'] + 1)) - d2 = hex_digit_value(nth(source, _cells['pos'])) - _ = _sx_cell_set(_cells, 'pos', (_cells['pos'] + 1)) - d3 = hex_digit_value(nth(source, _cells['pos'])) - _ = _sx_cell_set(_cells, 'pos', (_cells['pos'] + 1)) - _cells['buf'] = sx_str(_cells['buf'], char_from_code(((d0 * 4096) + (d1 * 256)))) - continue - else: - _cells['buf'] = sx_str(_cells['buf'], ('\n' if sx_truthy((esc == 'n')) else ('\t' if sx_truthy((esc == 't')) else ('\r' if sx_truthy((esc == 'r')) else esc)))) - _cells['pos'] = (_cells['pos'] + 1) - continue - else: - _cells['buf'] = sx_str(_cells['buf'], ch) - _cells['pos'] = (_cells['pos'] + 1) - continue - return _cells['buf'] - def read_ident(): - start = _cells['pos'] - while True: - if sx_truthy(((_cells['pos'] < len_src) if not sx_truthy((_cells['pos'] < len_src)) else ident_char_p(nth(source, _cells['pos'])))): - _cells['pos'] = (_cells['pos'] + 1) - continue - break - return slice(source, start, _cells['pos']) - def read_keyword(): - _cells['pos'] = (_cells['pos'] + 1) - return make_keyword(read_ident()) - def read_number(): - start = _cells['pos'] - if sx_truthy(((_cells['pos'] < len_src) if not sx_truthy((_cells['pos'] < len_src)) else (nth(source, _cells['pos']) == '-'))): - _cells['pos'] = (_cells['pos'] + 1) - def read_digits(): - while True: - if sx_truthy(((_cells['pos'] < len_src) if not sx_truthy((_cells['pos'] < len_src)) else (lambda c: ((c >= '0') if not sx_truthy((c >= '0')) else (c <= '9')))(nth(source, _cells['pos'])))): - _cells['pos'] = (_cells['pos'] + 1) - continue - break - read_digits() - if sx_truthy(((_cells['pos'] < len_src) if not sx_truthy((_cells['pos'] < len_src)) else (nth(source, _cells['pos']) == '.'))): - _cells['pos'] = (_cells['pos'] + 1) - read_digits() - if sx_truthy(((_cells['pos'] < len_src) if not sx_truthy((_cells['pos'] < len_src)) else ((nth(source, _cells['pos']) == 'e') if sx_truthy((nth(source, _cells['pos']) == 'e')) else (nth(source, _cells['pos']) == 'E')))): - _cells['pos'] = (_cells['pos'] + 1) - if sx_truthy(((_cells['pos'] < len_src) if not sx_truthy((_cells['pos'] < len_src)) else ((nth(source, _cells['pos']) == '+') if sx_truthy((nth(source, _cells['pos']) == '+')) else (nth(source, _cells['pos']) == '-')))): - _cells['pos'] = (_cells['pos'] + 1) - read_digits() - return parse_number(slice(source, start, _cells['pos'])) - def read_symbol(): - name = read_ident() - if sx_truthy((name == 'true')): - return True - elif sx_truthy((name == 'false')): - return False - elif sx_truthy((name == 'nil')): - return NIL - else: - return make_symbol(name) - def read_list(close_ch): - items = [] - while True: - skip_ws() - if sx_truthy((_cells['pos'] >= len_src)): - error('Unterminated list') - break - else: - if sx_truthy((nth(source, _cells['pos']) == close_ch)): - _cells['pos'] = (_cells['pos'] + 1) - break - else: - items.append(read_expr()) - continue - return items - def read_map(): - result = {} - while True: - skip_ws() - if sx_truthy((_cells['pos'] >= len_src)): - error('Unterminated map') - break - else: - if sx_truthy((nth(source, _cells['pos']) == '}')): - _cells['pos'] = (_cells['pos'] + 1) - break - else: - key_expr = read_expr() - key_str = (keyword_name(key_expr) if sx_truthy((type_of(key_expr) == 'keyword')) else sx_str(key_expr)) - val_expr = read_expr() - result[key_str] = val_expr - continue - return result - def read_raw_string(): - _cells['buf'] = '' - while True: - if sx_truthy((_cells['pos'] >= len_src)): - error('Unterminated raw string') - break - else: - ch = nth(source, _cells['pos']) - if sx_truthy((ch == '|')): - _cells['pos'] = (_cells['pos'] + 1) - break - else: - _cells['buf'] = sx_str(_cells['buf'], ch) - _cells['pos'] = (_cells['pos'] + 1) - continue - return _cells['buf'] - def read_expr(): - skip_ws() - if sx_truthy((_cells['pos'] >= len_src)): - return error('Unexpected end of input') - else: - ch = nth(source, _cells['pos']) - if sx_truthy((ch == '(')): - _cells['pos'] = (_cells['pos'] + 1) - return read_list(')') - elif sx_truthy((ch == '[')): - _cells['pos'] = (_cells['pos'] + 1) - return read_list(']') - elif sx_truthy((ch == '{')): - _cells['pos'] = (_cells['pos'] + 1) - return read_map() - elif sx_truthy((ch == '"')): - return read_string() - elif sx_truthy((ch == ':')): - return read_keyword() - elif sx_truthy((ch == "'")): - _cells['pos'] = (_cells['pos'] + 1) - return [make_symbol('quote'), read_expr()] - elif sx_truthy((ch == '`')): - _cells['pos'] = (_cells['pos'] + 1) - return [make_symbol('quasiquote'), read_expr()] - elif sx_truthy((ch == ',')): - _cells['pos'] = (_cells['pos'] + 1) - if sx_truthy(((_cells['pos'] < len_src) if not sx_truthy((_cells['pos'] < len_src)) else (nth(source, _cells['pos']) == '@'))): - _cells['pos'] = (_cells['pos'] + 1) - return [make_symbol('splice-unquote'), read_expr()] - else: - return [make_symbol('unquote'), read_expr()] - elif sx_truthy((ch == '#')): - _cells['pos'] = (_cells['pos'] + 1) - if sx_truthy((_cells['pos'] >= len_src)): - return error('Unexpected end of input after #') - else: - dispatch_ch = nth(source, _cells['pos']) - if sx_truthy((dispatch_ch == ';')): - _cells['pos'] = (_cells['pos'] + 1) - read_expr() - return read_expr() - elif sx_truthy((dispatch_ch == '|')): - _cells['pos'] = (_cells['pos'] + 1) - return read_raw_string() - elif sx_truthy((dispatch_ch == "'")): - _cells['pos'] = (_cells['pos'] + 1) - return [make_symbol('quote'), read_expr()] - elif sx_truthy(ident_start_p(dispatch_ch)): - macro_name = read_ident() - handler = reader_macro_get(macro_name) - if sx_truthy(handler): - return handler(read_expr()) - else: - return error(sx_str('Unknown reader macro: #', macro_name)) - else: - return error(sx_str('Unknown reader macro: #', dispatch_ch)) - elif sx_truthy((((ch >= '0') if not sx_truthy((ch >= '0')) else (ch <= '9')) if sx_truthy(((ch >= '0') if not sx_truthy((ch >= '0')) else (ch <= '9'))) else ((ch == '-') if not sx_truthy((ch == '-')) else (((_cells['pos'] + 1) < len_src) if not sx_truthy(((_cells['pos'] + 1) < len_src)) else (lambda next_ch: ((next_ch >= '0') if not sx_truthy((next_ch >= '0')) else (next_ch <= '9')))(nth(source, (_cells['pos'] + 1))))))): - return read_number() - elif sx_truthy(((ch == '.') if not sx_truthy((ch == '.')) else (((_cells['pos'] + 2) < len_src) if not sx_truthy(((_cells['pos'] + 2) < len_src)) else ((nth(source, (_cells['pos'] + 1)) == '.') if not sx_truthy((nth(source, (_cells['pos'] + 1)) == '.')) else (nth(source, (_cells['pos'] + 2)) == '.'))))): - _cells['pos'] = (_cells['pos'] + 3) - return make_symbol('...') - elif sx_truthy(ident_start_p(ch)): - return read_symbol() - else: - return error(sx_str('Unexpected character: ', ch)) - exprs = [] - while True: - skip_ws() - if sx_truthy((_cells['pos'] < len_src)): - exprs.append(read_expr()) - continue - break - return exprs - -# sx-serialize -def sx_serialize(val): - _match = type_of(val) - if _match == 'nil': - return 'nil' - elif _match == 'boolean': - if sx_truthy(val): - return 'true' - else: - return 'false' - elif _match == 'number': - return sx_str(val) - elif _match == 'string': - return sx_str('"', escape_string(val), '"') - elif _match == 'symbol': - return symbol_name(val) - elif _match == 'keyword': - return sx_str(':', keyword_name(val)) - elif _match == 'list': - return sx_str('(', join(' ', map(sx_serialize, val)), ')') - elif _match == 'dict': - return sx_serialize_dict(val) - elif _match == 'sx-expr': - return sx_expr_source(val) - elif _match == 'spread': - return sx_str('(make-spread ', sx_serialize_dict(spread_attrs(val)), ')') - else: - return sx_str(val) - -# sx-serialize-dict -def sx_serialize_dict(d): - return sx_str('{', join(' ', reduce(lambda acc, key: concat(acc, [sx_str(':', key), sx_serialize(dict_get(d, key))]), [], keys(d))), '}') - -# serialize -serialize = sx_serialize - - # === Transpiled from adapter-html === # render-to-html @@ -3189,201 +2116,6 @@ def env_components(env): return filter(lambda k: (lambda v: (is_component(v) if sx_truthy(is_component(v)) else is_macro(v)))(env_get(env, k)), keys(env)) -# === Transpiled from frames (CEK continuation frames) === - -# make-cek-state -def make_cek_state(control, env, kont): - return {'control': control, 'env': env, 'kont': kont, 'phase': 'eval', 'value': NIL} - -# make-cek-value -def make_cek_value(value, env, kont): - return {'control': NIL, 'env': env, 'kont': kont, 'phase': 'continue', 'value': value} - -# cek-terminal? -def cek_terminal_p(state): - return ((get(state, 'phase') == 'continue') if not sx_truthy((get(state, 'phase') == 'continue')) else empty_p(get(state, 'kont'))) - -# cek-control -def cek_control(s): - return get(s, 'control') - -# cek-env -def cek_env(s): - return get(s, 'env') - -# cek-kont -def cek_kont(s): - return get(s, 'kont') - -# cek-phase -def cek_phase(s): - return get(s, 'phase') - -# cek-value -def cek_value(s): - return get(s, 'value') - -# make-if-frame -def make_if_frame(then_expr, else_expr, env): - return {'type': 'if', 'then': then_expr, 'else': else_expr, 'env': env} - -# make-when-frame -def make_when_frame(body_exprs, env): - return {'type': 'when', 'body': body_exprs, 'env': env} - -# make-begin-frame -def make_begin_frame(remaining, env): - return {'type': 'begin', 'remaining': remaining, 'env': env} - -# make-let-frame -def make_let_frame(name, remaining, body, local): - return {'type': 'let', 'name': name, 'remaining': remaining, 'body': body, 'env': local} - -# make-define-frame -def make_define_frame(name, env, has_effects, effect_list): - return {'type': 'define', 'name': name, 'env': env, 'has-effects': has_effects, 'effect-list': effect_list} - -# make-set-frame -def make_set_frame(name, env): - return {'type': 'set', 'name': name, 'env': env} - -# make-arg-frame -def make_arg_frame(f, evaled, remaining, env, raw_args): - return {'type': 'arg', 'f': f, 'evaled': evaled, 'remaining': remaining, 'env': env, 'raw-args': raw_args} - -# make-call-frame -def make_call_frame(f, args, env): - return {'type': 'call', 'f': f, 'args': args, 'env': env} - -# make-cond-frame -def make_cond_frame(remaining, env, scheme_p): - return {'type': 'cond', 'remaining': remaining, 'env': env, 'scheme': scheme_p} - -# make-case-frame -def make_case_frame(match_val, remaining, env): - return {'type': 'case', 'match-val': match_val, 'remaining': remaining, 'env': env} - -# make-thread-frame -def make_thread_frame(remaining, env): - return {'type': 'thread', 'remaining': remaining, 'env': env} - -# make-map-frame -def make_map_frame(f, remaining, results, env): - return {'type': 'map', 'f': f, 'remaining': remaining, 'results': results, 'env': env, 'indexed': False} - -# make-map-indexed-frame -def make_map_indexed_frame(f, remaining, results, env): - return {'type': 'map', 'f': f, 'remaining': remaining, 'results': results, 'env': env, 'indexed': True} - -# make-filter-frame -def make_filter_frame(f, remaining, results, current_item, env): - return {'type': 'filter', 'f': f, 'remaining': remaining, 'results': results, 'current-item': current_item, 'env': env} - -# make-reduce-frame -def make_reduce_frame(f, remaining, env): - return {'type': 'reduce', 'f': f, 'remaining': remaining, 'env': env} - -# make-for-each-frame -def make_for_each_frame(f, remaining, env): - return {'type': 'for-each', 'f': f, 'remaining': remaining, 'env': env} - -# make-some-frame -def make_some_frame(f, remaining, env): - return {'type': 'some', 'f': f, 'remaining': remaining, 'env': env} - -# make-every-frame -def make_every_frame(f, remaining, env): - return {'type': 'every', 'f': f, 'remaining': remaining, 'env': env} - -# make-scope-frame -def make_scope_frame(name, remaining, env): - return {'type': 'scope', 'name': name, 'remaining': remaining, 'env': env} - -# make-reset-frame -def make_reset_frame(env): - return {'type': 'reset', 'env': env} - -# make-dict-frame -def make_dict_frame(remaining, results, env): - return {'type': 'dict', 'remaining': remaining, 'results': results, 'env': env} - -# make-and-frame -def make_and_frame(remaining, env): - return {'type': 'and', 'remaining': remaining, 'env': env} - -# make-or-frame -def make_or_frame(remaining, env): - return {'type': 'or', 'remaining': remaining, 'env': env} - -# make-dynamic-wind-frame -def make_dynamic_wind_frame(phase, body_thunk, after_thunk, env): - return {'type': 'dynamic-wind', 'phase': phase, 'body-thunk': body_thunk, 'after-thunk': after_thunk, 'env': env} - -# make-reactive-reset-frame -def make_reactive_reset_frame(env, update_fn, first_render_p): - return {'type': 'reactive-reset', 'env': env, 'update-fn': update_fn, 'first-render': first_render_p} - -# make-deref-frame -def make_deref_frame(env): - return {'type': 'deref', 'env': env} - -# frame-type -def frame_type(f): - return get(f, 'type') - -# kont-push -def kont_push(frame, kont): - return cons(frame, kont) - -# kont-top -def kont_top(kont): - return first(kont) - -# kont-pop -def kont_pop(kont): - return rest(kont) - -# kont-empty? -def kont_empty_p(kont): - return empty_p(kont) - -# kont-capture-to-reset -def kont_capture_to_reset(kont): - def scan(k, captured): - if sx_truthy(empty_p(k)): - return error('shift without enclosing reset') - else: - frame = first(k) - if sx_truthy(((frame_type(frame) == 'reset') if sx_truthy((frame_type(frame) == 'reset')) else (frame_type(frame) == 'reactive-reset'))): - return [captured, rest(k)] - else: - return scan(rest(k), append(captured, [frame])) - return scan(kont, []) - -# has-reactive-reset-frame? -def has_reactive_reset_frame_p(kont): - if sx_truthy(empty_p(kont)): - return False - else: - if sx_truthy((frame_type(first(kont)) == 'reactive-reset')): - return True - else: - return has_reactive_reset_frame_p(rest(kont)) - -# kont-capture-to-reactive-reset -def kont_capture_to_reactive_reset(kont): - def scan(k, captured): - if sx_truthy(empty_p(k)): - return error('reactive deref without enclosing reactive-reset') - else: - frame = first(k) - if sx_truthy((frame_type(frame) == 'reactive-reset')): - return [captured, frame, rest(k)] - else: - return scan(rest(k), append(captured, [frame])) - return scan(kont, []) - - # === Transpiled from page-helpers (pure data transformation helpers) === # special-form-category-map @@ -3882,822 +2614,6 @@ def prepare_url_expr(url_path, env): return auto_quote_unknowns(expr, env) -# === Transpiled from cek (explicit CEK machine evaluator) === - -# cek-run -def cek_run(state): - if sx_truthy(cek_terminal_p(state)): - return cek_value(state) - else: - return cek_run(cek_step(state)) - -# cek-step -def cek_step(state): - if sx_truthy((cek_phase(state) == 'eval')): - return step_eval(state) - else: - return step_continue(state) - -# step-eval -def step_eval(state): - expr = cek_control(state) - env = cek_env(state) - kont = cek_kont(state) - _match = type_of(expr) - if _match == 'number': - return make_cek_value(expr, env, kont) - elif _match == 'string': - return make_cek_value(expr, env, kont) - elif _match == 'boolean': - return make_cek_value(expr, env, kont) - elif _match == 'nil': - return make_cek_value(NIL, env, kont) - elif _match == 'symbol': - name = symbol_name(expr) - val = (env_get(env, name) if sx_truthy(env_has(env, name)) else (get_primitive(name) if sx_truthy(is_primitive(name)) else (True if sx_truthy((name == 'true')) else (False if sx_truthy((name == 'false')) else (NIL if sx_truthy((name == 'nil')) else error(sx_str('Undefined symbol: ', name))))))) - return make_cek_value(val, env, kont) - elif _match == 'keyword': - return make_cek_value(keyword_name(expr), env, kont) - elif _match == 'dict': - ks = keys(expr) - if sx_truthy(empty_p(ks)): - return make_cek_value({}, env, kont) - else: - first_key = first(ks) - remaining_entries = [] - for k in rest(ks): - remaining_entries.append([k, get(expr, k)]) - return make_cek_state(get(expr, first_key), env, kont_push(make_dict_frame(remaining_entries, [[first_key]], env), kont)) - elif _match == 'list': - if sx_truthy(empty_p(expr)): - return make_cek_value([], env, kont) - else: - return step_eval_list(expr, env, kont) - else: - return make_cek_value(expr, env, kont) - -# step-eval-list -def step_eval_list(expr, env, kont): - head = first(expr) - args = rest(expr) - if sx_truthy((not sx_truthy(((type_of(head) == 'symbol') if sx_truthy((type_of(head) == 'symbol')) else ((type_of(head) == 'lambda') if sx_truthy((type_of(head) == 'lambda')) else (type_of(head) == 'list')))))): - if sx_truthy(empty_p(expr)): - return make_cek_value([], env, kont) - else: - return make_cek_state(first(expr), env, kont_push(make_map_frame(NIL, rest(expr), [], env), kont)) - else: - if sx_truthy((type_of(head) == 'symbol')): - name = symbol_name(head) - if sx_truthy((name == 'if')): - return step_sf_if(args, env, kont) - elif sx_truthy((name == 'when')): - return step_sf_when(args, env, kont) - elif sx_truthy((name == 'cond')): - return step_sf_cond(args, env, kont) - elif sx_truthy((name == 'case')): - return step_sf_case(args, env, kont) - elif sx_truthy((name == 'and')): - return step_sf_and(args, env, kont) - elif sx_truthy((name == 'or')): - return step_sf_or(args, env, kont) - elif sx_truthy((name == 'let')): - return step_sf_let(args, env, kont) - elif sx_truthy((name == 'let*')): - return step_sf_let(args, env, kont) - elif sx_truthy((name == 'lambda')): - return step_sf_lambda(args, env, kont) - elif sx_truthy((name == 'fn')): - return step_sf_lambda(args, env, kont) - elif sx_truthy((name == 'define')): - return step_sf_define(args, env, kont) - elif sx_truthy((name == 'defcomp')): - return make_cek_value(sf_defcomp(args, env), env, kont) - elif sx_truthy((name == 'defisland')): - return make_cek_value(sf_defisland(args, env), env, kont) - elif sx_truthy((name == 'defmacro')): - return make_cek_value(sf_defmacro(args, env), env, kont) - elif sx_truthy((name == 'defstyle')): - return make_cek_value(sf_defstyle(args, env), env, kont) - elif sx_truthy((name == 'defhandler')): - return make_cek_value(sf_defhandler(args, env), env, kont) - elif sx_truthy((name == 'defpage')): - return make_cek_value(sf_defpage(args, env), env, kont) - elif sx_truthy((name == 'defquery')): - return make_cek_value(sf_defquery(args, env), env, kont) - elif sx_truthy((name == 'defaction')): - return make_cek_value(sf_defaction(args, env), env, kont) - elif sx_truthy((name == 'deftype')): - return make_cek_value(sf_deftype(args, env), env, kont) - elif sx_truthy((name == 'defeffect')): - return make_cek_value(sf_defeffect(args, env), env, kont) - elif sx_truthy((name == 'begin')): - return step_sf_begin(args, env, kont) - elif sx_truthy((name == 'do')): - return step_sf_begin(args, env, kont) - elif sx_truthy((name == 'quote')): - return make_cek_value((NIL if sx_truthy(empty_p(args)) else first(args)), env, kont) - elif sx_truthy((name == 'quasiquote')): - return make_cek_value(qq_expand(first(args), env), env, kont) - elif sx_truthy((name == '->')): - return step_sf_thread_first(args, env, kont) - elif sx_truthy((name == 'set!')): - return step_sf_set_b(args, env, kont) - elif sx_truthy((name == 'letrec')): - return make_cek_value(sf_letrec(args, env), env, kont) - elif sx_truthy((name == 'reset')): - return step_sf_reset(args, env, kont) - elif sx_truthy((name == 'shift')): - return step_sf_shift(args, env, kont) - elif sx_truthy((name == 'deref')): - return step_sf_deref(args, env, kont) - elif sx_truthy((name == 'scope')): - return step_sf_scope(args, env, kont) - elif sx_truthy((name == 'provide')): - return step_sf_provide(args, env, kont) - elif sx_truthy((name == 'dynamic-wind')): - return make_cek_value(sf_dynamic_wind(args, env), env, kont) - elif sx_truthy((name == 'map')): - return step_ho_map(args, env, kont) - elif sx_truthy((name == 'map-indexed')): - return step_ho_map_indexed(args, env, kont) - elif sx_truthy((name == 'filter')): - return step_ho_filter(args, env, kont) - elif sx_truthy((name == 'reduce')): - return step_ho_reduce(args, env, kont) - elif sx_truthy((name == 'some')): - return step_ho_some(args, env, kont) - elif sx_truthy((name == 'every?')): - return step_ho_every(args, env, kont) - elif sx_truthy((name == 'for-each')): - return step_ho_for_each(args, env, kont) - elif sx_truthy((env_has(env, name) if not sx_truthy(env_has(env, name)) else is_macro(env_get(env, name)))): - mac = env_get(env, name) - return make_cek_state(expand_macro(mac, args, env), env, kont) - elif sx_truthy((render_active_p() if not sx_truthy(render_active_p()) else is_render_expr(expr))): - return make_cek_value(render_expr(expr, env), env, kont) - else: - return step_eval_call(head, args, env, kont) - else: - return step_eval_call(head, args, env, kont) - -# step-sf-if -def step_sf_if(args, env, kont): - return make_cek_state(first(args), env, kont_push(make_if_frame(nth(args, 1), (nth(args, 2) if sx_truthy((len(args) > 2)) else NIL), env), kont)) - -# step-sf-when -def step_sf_when(args, env, kont): - return make_cek_state(first(args), env, kont_push(make_when_frame(rest(args), env), kont)) - -# step-sf-begin -def step_sf_begin(args, env, kont): - if sx_truthy(empty_p(args)): - return make_cek_value(NIL, env, kont) - else: - if sx_truthy((len(args) == 1)): - return make_cek_state(first(args), env, kont) - else: - return make_cek_state(first(args), env, kont_push(make_begin_frame(rest(args), env), kont)) - -# step-sf-let -def step_sf_let(args, env, kont): - if sx_truthy((type_of(first(args)) == 'symbol')): - return make_cek_value(sf_named_let(args, env), env, kont) - else: - bindings = first(args) - body = rest(args) - local = env_extend(env) - if sx_truthy(empty_p(bindings)): - return step_sf_begin(body, local, kont) - else: - first_binding = (first(bindings) if sx_truthy(((type_of(first(bindings)) == 'list') if not sx_truthy((type_of(first(bindings)) == 'list')) else (len(first(bindings)) == 2))) else [first(bindings), nth(bindings, 1)]) - rest_bindings = (rest(bindings) if sx_truthy(((type_of(first(bindings)) == 'list') if not sx_truthy((type_of(first(bindings)) == 'list')) else (len(first(bindings)) == 2))) else (lambda pairs: _sx_begin(reduce(lambda acc, i: _sx_append(pairs, [nth(bindings, (i * 2)), nth(bindings, ((i * 2) + 1))]), NIL, range(1, (len(bindings) / 2))), pairs))([])) - vname = (symbol_name(first(first_binding)) if sx_truthy((type_of(first(first_binding)) == 'symbol')) else first(first_binding)) - return make_cek_state(nth(first_binding, 1), local, kont_push(make_let_frame(vname, rest_bindings, body, local), kont)) - -# step-sf-define -def step_sf_define(args, env, kont): - name_sym = first(args) - has_effects = ((len(args) >= 4) if not sx_truthy((len(args) >= 4)) else ((type_of(nth(args, 1)) == 'keyword') if not sx_truthy((type_of(nth(args, 1)) == 'keyword')) else (keyword_name(nth(args, 1)) == 'effects'))) - val_idx = (3 if sx_truthy(((len(args) >= 4) if not sx_truthy((len(args) >= 4)) else ((type_of(nth(args, 1)) == 'keyword') if not sx_truthy((type_of(nth(args, 1)) == 'keyword')) else (keyword_name(nth(args, 1)) == 'effects')))) else 1) - effect_list = (nth(args, 2) if sx_truthy(((len(args) >= 4) if not sx_truthy((len(args) >= 4)) else ((type_of(nth(args, 1)) == 'keyword') if not sx_truthy((type_of(nth(args, 1)) == 'keyword')) else (keyword_name(nth(args, 1)) == 'effects')))) else NIL) - return make_cek_state(nth(args, val_idx), env, kont_push(make_define_frame(symbol_name(name_sym), env, has_effects, effect_list), kont)) - -# step-sf-set! -def step_sf_set_b(args, env, kont): - return make_cek_state(nth(args, 1), env, kont_push(make_set_frame(symbol_name(first(args)), env), kont)) - -# step-sf-and -def step_sf_and(args, env, kont): - if sx_truthy(empty_p(args)): - return make_cek_value(True, env, kont) - else: - return make_cek_state(first(args), env, kont_push(make_and_frame(rest(args), env), kont)) - -# step-sf-or -def step_sf_or(args, env, kont): - if sx_truthy(empty_p(args)): - return make_cek_value(False, env, kont) - else: - return make_cek_state(first(args), env, kont_push(make_or_frame(rest(args), env), kont)) - -# step-sf-cond -def step_sf_cond(args, env, kont): - scheme_p = cond_scheme_p(args) - if sx_truthy(scheme_p): - if sx_truthy(empty_p(args)): - return make_cek_value(NIL, env, kont) - else: - clause = first(args) - test = first(clause) - 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')))): - return make_cek_state(nth(clause, 1), env, kont) - else: - return make_cek_state(test, env, kont_push(make_cond_frame(args, env, True), kont)) - else: - if sx_truthy((len(args) < 2)): - return make_cek_value(NIL, env, kont) - else: - test = first(args) - 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'))))): - return make_cek_state(nth(args, 1), env, kont) - else: - return make_cek_state(test, env, kont_push(make_cond_frame(args, env, False), kont)) - -# step-sf-case -def step_sf_case(args, env, kont): - return make_cek_state(first(args), env, kont_push(make_case_frame(NIL, rest(args), env), kont)) - -# step-sf-thread-first -def step_sf_thread_first(args, env, kont): - return make_cek_state(first(args), env, kont_push(make_thread_frame(rest(args), env), kont)) - -# step-sf-lambda -def step_sf_lambda(args, env, kont): - return make_cek_value(sf_lambda(args, env), env, kont) - -# step-sf-scope -def step_sf_scope(args, env, kont): - return make_cek_value(sf_scope(args, env), env, kont) - -# step-sf-provide -def step_sf_provide(args, env, kont): - return make_cek_value(sf_provide(args, env), env, kont) - -# step-sf-reset -def step_sf_reset(args, env, kont): - return make_cek_state(first(args), env, kont_push(make_reset_frame(env), kont)) - -# step-sf-shift -def step_sf_shift(args, env, kont): - k_name = symbol_name(first(args)) - body = nth(args, 1) - captured_result = kont_capture_to_reset(kont) - captured = first(captured_result) - rest_kont = nth(captured_result, 1) - k = make_cek_continuation(captured, rest_kont) - shift_env = env_extend(env) - shift_env[k_name] = k - return make_cek_state(body, shift_env, rest_kont) - -# step-sf-deref -def step_sf_deref(args, env, kont): - return make_cek_state(first(args), env, kont_push(make_deref_frame(env), kont)) - -# cek-call -def cek_call(f, args): - a = ([] if sx_truthy(is_nil(args)) else args) - if sx_truthy(is_nil(f)): - return NIL - elif sx_truthy(is_lambda(f)): - return cek_run(continue_with_call(f, a, {}, a, [])) - elif sx_truthy(is_callable(f)): - return apply(f, a) - else: - return NIL - -# reactive-shift-deref -def reactive_shift_deref(sig, env, kont): - _cells = {} - scan_result = kont_capture_to_reactive_reset(kont) - captured_frames = first(scan_result) - reset_frame = nth(scan_result, 1) - remaining_kont = nth(scan_result, 2) - update_fn = get(reset_frame, 'update-fn') - _cells['sub_disposers'] = [] - subscriber = _sx_fn(lambda : ( - for_each(lambda d: cek_call(d, NIL), _cells['sub_disposers']), - _sx_cell_set(_cells, 'sub_disposers', []), - (lambda new_reset: (lambda new_kont: with_island_scope(lambda d: _sx_append(_cells['sub_disposers'], d), lambda : cek_run(make_cek_value(signal_value(sig), env, new_kont))))(concat(captured_frames, [new_reset], remaining_kont)))(make_reactive_reset_frame(env, update_fn, False)) -)[-1]) - signal_add_sub(sig, subscriber) - register_in_scope(_sx_fn(lambda : ( - signal_remove_sub(sig, subscriber), - for_each(lambda d: cek_call(d, NIL), _cells['sub_disposers']) -)[-1])) - initial_kont = concat(captured_frames, [reset_frame], remaining_kont) - return make_cek_value(signal_value(sig), env, initial_kont) - -# step-eval-call -def step_eval_call(head, args, env, kont): - return make_cek_state(head, env, kont_push(make_arg_frame(NIL, [], args, env, args), kont)) - -# step-ho-map -def step_ho_map(args, env, kont): - f = trampoline(eval_expr(first(args), env)) - coll = trampoline(eval_expr(nth(args, 1), env)) - if sx_truthy(empty_p(coll)): - return make_cek_value([], env, kont) - else: - return continue_with_call(f, [first(coll)], env, [], kont_push(make_map_frame(f, rest(coll), [], env), kont)) - -# step-ho-map-indexed -def step_ho_map_indexed(args, env, kont): - f = trampoline(eval_expr(first(args), env)) - coll = trampoline(eval_expr(nth(args, 1), env)) - if sx_truthy(empty_p(coll)): - return make_cek_value([], env, kont) - else: - return continue_with_call(f, [0, first(coll)], env, [], kont_push(make_map_indexed_frame(f, rest(coll), [], env), kont)) - -# step-ho-filter -def step_ho_filter(args, env, kont): - f = trampoline(eval_expr(first(args), env)) - coll = trampoline(eval_expr(nth(args, 1), env)) - if sx_truthy(empty_p(coll)): - return make_cek_value([], env, kont) - else: - return continue_with_call(f, [first(coll)], env, [], kont_push(make_filter_frame(f, rest(coll), [], first(coll), env), kont)) - -# step-ho-reduce -def step_ho_reduce(args, env, kont): - f = trampoline(eval_expr(first(args), env)) - init = trampoline(eval_expr(nth(args, 1), env)) - coll = trampoline(eval_expr(nth(args, 2), env)) - if sx_truthy(empty_p(coll)): - return make_cek_value(init, env, kont) - else: - return continue_with_call(f, [init, first(coll)], env, [], kont_push(make_reduce_frame(f, rest(coll), env), kont)) - -# step-ho-some -def step_ho_some(args, env, kont): - f = trampoline(eval_expr(first(args), env)) - coll = trampoline(eval_expr(nth(args, 1), env)) - if sx_truthy(empty_p(coll)): - return make_cek_value(False, env, kont) - else: - return continue_with_call(f, [first(coll)], env, [], kont_push(make_some_frame(f, rest(coll), env), kont)) - -# step-ho-every -def step_ho_every(args, env, kont): - f = trampoline(eval_expr(first(args), env)) - coll = trampoline(eval_expr(nth(args, 1), env)) - if sx_truthy(empty_p(coll)): - return make_cek_value(True, env, kont) - else: - return continue_with_call(f, [first(coll)], env, [], kont_push(make_every_frame(f, rest(coll), env), kont)) - -# step-ho-for-each -def step_ho_for_each(args, env, kont): - f = trampoline(eval_expr(first(args), env)) - coll = trampoline(eval_expr(nth(args, 1), env)) - if sx_truthy(empty_p(coll)): - return make_cek_value(NIL, env, kont) - else: - return continue_with_call(f, [first(coll)], env, [], kont_push(make_for_each_frame(f, rest(coll), env), kont)) - -# step-continue -def step_continue(state): - value = cek_value(state) - env = cek_env(state) - kont = cek_kont(state) - if sx_truthy(kont_empty_p(kont)): - return state - else: - frame = kont_top(kont) - rest_k = kont_pop(kont) - ft = frame_type(frame) - if sx_truthy((ft == 'if')): - if sx_truthy((value if not sx_truthy(value) else (not sx_truthy(is_nil(value))))): - return make_cek_state(get(frame, 'then'), get(frame, 'env'), rest_k) - else: - if sx_truthy(is_nil(get(frame, 'else'))): - return make_cek_value(NIL, env, rest_k) - else: - return make_cek_state(get(frame, 'else'), get(frame, 'env'), rest_k) - elif sx_truthy((ft == 'when')): - if sx_truthy((value if not sx_truthy(value) else (not sx_truthy(is_nil(value))))): - body = get(frame, 'body') - fenv = get(frame, 'env') - if sx_truthy(empty_p(body)): - return make_cek_value(NIL, fenv, rest_k) - else: - if sx_truthy((len(body) == 1)): - return make_cek_state(first(body), fenv, rest_k) - else: - return make_cek_state(first(body), fenv, kont_push(make_begin_frame(rest(body), fenv), rest_k)) - else: - return make_cek_value(NIL, env, rest_k) - elif sx_truthy((ft == 'begin')): - remaining = get(frame, 'remaining') - fenv = get(frame, 'env') - if sx_truthy(empty_p(remaining)): - return make_cek_value(value, fenv, rest_k) - else: - if sx_truthy((len(remaining) == 1)): - return make_cek_state(first(remaining), fenv, rest_k) - else: - return make_cek_state(first(remaining), fenv, kont_push(make_begin_frame(rest(remaining), fenv), rest_k)) - elif sx_truthy((ft == 'let')): - name = get(frame, 'name') - remaining = get(frame, 'remaining') - body = get(frame, 'body') - local = get(frame, 'env') - local[name] = value - if sx_truthy(empty_p(remaining)): - return step_sf_begin(body, local, rest_k) - else: - next_binding = first(remaining) - vname = (symbol_name(first(next_binding)) if sx_truthy((type_of(first(next_binding)) == 'symbol')) else first(next_binding)) - return make_cek_state(nth(next_binding, 1), local, kont_push(make_let_frame(vname, rest(remaining), body, local), rest_k)) - elif sx_truthy((ft == 'define')): - name = get(frame, 'name') - fenv = get(frame, 'env') - has_effects = get(frame, 'has-effects') - effect_list = get(frame, 'effect-list') - if sx_truthy((is_lambda(value) if not sx_truthy(is_lambda(value)) else is_nil(lambda_name(value)))): - value.name = name - fenv[name] = value - if sx_truthy(has_effects): - effect_names = (map(lambda e: (symbol_name(e) if sx_truthy((type_of(e) == 'symbol')) else sx_str(e)), effect_list) if sx_truthy((type_of(effect_list) == 'list')) else [sx_str(effect_list)]) - effect_anns = (env_get(fenv, '*effect-annotations*') if sx_truthy(env_has(fenv, '*effect-annotations*')) else {}) - effect_anns[name] = effect_names - fenv['*effect-annotations*'] = effect_anns - return make_cek_value(value, fenv, rest_k) - elif sx_truthy((ft == 'set')): - name = get(frame, 'name') - fenv = get(frame, 'env') - fenv[name] = value - return make_cek_value(value, env, rest_k) - elif sx_truthy((ft == 'and')): - if sx_truthy((not sx_truthy(value))): - return make_cek_value(value, env, rest_k) - else: - remaining = get(frame, 'remaining') - if sx_truthy(empty_p(remaining)): - return make_cek_value(value, env, rest_k) - else: - return make_cek_state(first(remaining), get(frame, 'env'), (rest_k if sx_truthy((len(remaining) == 1)) else kont_push(make_and_frame(rest(remaining), get(frame, 'env')), rest_k))) - elif sx_truthy((ft == 'or')): - if sx_truthy(value): - return make_cek_value(value, env, rest_k) - else: - remaining = get(frame, 'remaining') - if sx_truthy(empty_p(remaining)): - return make_cek_value(False, env, rest_k) - else: - return make_cek_state(first(remaining), get(frame, 'env'), (rest_k if sx_truthy((len(remaining) == 1)) else kont_push(make_or_frame(rest(remaining), get(frame, 'env')), rest_k))) - elif sx_truthy((ft == 'cond')): - remaining = get(frame, 'remaining') - fenv = get(frame, 'env') - scheme_p = get(frame, 'scheme') - if sx_truthy(scheme_p): - if sx_truthy(value): - return make_cek_state(nth(first(remaining), 1), fenv, rest_k) - else: - next_clauses = rest(remaining) - if sx_truthy(empty_p(next_clauses)): - return make_cek_value(NIL, fenv, rest_k) - else: - next_clause = first(next_clauses) - next_test = first(next_clause) - if sx_truthy((((type_of(next_test) == 'symbol') if not sx_truthy((type_of(next_test) == 'symbol')) else ((symbol_name(next_test) == 'else') if sx_truthy((symbol_name(next_test) == 'else')) else (symbol_name(next_test) == ':else'))) if sx_truthy(((type_of(next_test) == 'symbol') if not sx_truthy((type_of(next_test) == 'symbol')) else ((symbol_name(next_test) == 'else') if sx_truthy((symbol_name(next_test) == 'else')) else (symbol_name(next_test) == ':else')))) else ((type_of(next_test) == 'keyword') if not sx_truthy((type_of(next_test) == 'keyword')) else (keyword_name(next_test) == 'else')))): - return make_cek_state(nth(next_clause, 1), fenv, rest_k) - else: - return make_cek_state(next_test, fenv, kont_push(make_cond_frame(next_clauses, fenv, True), rest_k)) - else: - if sx_truthy(value): - return make_cek_state(nth(remaining, 1), fenv, rest_k) - else: - next = slice(remaining, 2) - if sx_truthy((len(next) < 2)): - return make_cek_value(NIL, fenv, rest_k) - else: - next_test = first(next) - if sx_truthy((((type_of(next_test) == 'keyword') if not sx_truthy((type_of(next_test) == 'keyword')) else (keyword_name(next_test) == 'else')) if sx_truthy(((type_of(next_test) == 'keyword') if not sx_truthy((type_of(next_test) == 'keyword')) else (keyword_name(next_test) == 'else'))) else ((type_of(next_test) == 'symbol') if not sx_truthy((type_of(next_test) == 'symbol')) else ((symbol_name(next_test) == 'else') if sx_truthy((symbol_name(next_test) == 'else')) else (symbol_name(next_test) == ':else'))))): - return make_cek_state(nth(next, 1), fenv, rest_k) - else: - return make_cek_state(next_test, fenv, kont_push(make_cond_frame(next, fenv, False), rest_k)) - elif sx_truthy((ft == 'case')): - match_val = get(frame, 'match-val') - remaining = get(frame, 'remaining') - fenv = get(frame, 'env') - if sx_truthy(is_nil(match_val)): - return sf_case_step_loop(value, remaining, fenv, rest_k) - else: - return sf_case_step_loop(match_val, remaining, fenv, rest_k) - elif sx_truthy((ft == 'thread')): - remaining = get(frame, 'remaining') - fenv = get(frame, 'env') - if sx_truthy(empty_p(remaining)): - return make_cek_value(value, fenv, rest_k) - else: - form = first(remaining) - rest_forms = rest(remaining) - result = ((lambda f: (lambda rargs: (lambda all_args: (apply(f, all_args) if sx_truthy((is_callable(f) if not sx_truthy(is_callable(f)) else (not sx_truthy(is_lambda(f))))) else (trampoline(call_lambda(f, all_args, fenv)) if sx_truthy(is_lambda(f)) else error(sx_str('-> form not callable: ', inspect(f))))))(cons(value, rargs)))(map(lambda a: trampoline(eval_expr(a, fenv)), rest(form))))(trampoline(eval_expr(first(form), fenv))) if sx_truthy((type_of(form) == 'list')) else (lambda f: (f(value) if sx_truthy((is_callable(f) if not sx_truthy(is_callable(f)) else (not sx_truthy(is_lambda(f))))) else (trampoline(call_lambda(f, [value], fenv)) if sx_truthy(is_lambda(f)) else error(sx_str('-> form not callable: ', inspect(f))))))(trampoline(eval_expr(form, fenv)))) - if sx_truthy(empty_p(rest_forms)): - return make_cek_value(result, fenv, rest_k) - else: - return make_cek_value(result, fenv, kont_push(make_thread_frame(rest_forms, fenv), rest_k)) - elif sx_truthy((ft == 'arg')): - f = get(frame, 'f') - evaled = get(frame, 'evaled') - remaining = get(frame, 'remaining') - fenv = get(frame, 'env') - raw_args = get(frame, 'raw-args') - if sx_truthy(is_nil(f)): - if sx_truthy(empty_p(remaining)): - return continue_with_call(value, [], fenv, raw_args, rest_k) - else: - return make_cek_state(first(remaining), fenv, kont_push(make_arg_frame(value, [], rest(remaining), fenv, raw_args), rest_k)) - else: - new_evaled = append(evaled, [value]) - if sx_truthy(empty_p(remaining)): - return continue_with_call(f, new_evaled, fenv, raw_args, rest_k) - else: - return make_cek_state(first(remaining), fenv, kont_push(make_arg_frame(f, new_evaled, rest(remaining), fenv, raw_args), rest_k)) - elif sx_truthy((ft == 'dict')): - remaining = get(frame, 'remaining') - results = get(frame, 'results') - fenv = get(frame, 'env') - last_result = last(results) - completed = append(slice(results, 0, (len(results) - 1)), [[first(last_result), value]]) - if sx_truthy(empty_p(remaining)): - d = {} - for pair in completed: - d[first(pair)] = nth(pair, 1) - return make_cek_value(d, fenv, rest_k) - else: - next_entry = first(remaining) - return make_cek_state(nth(next_entry, 1), fenv, kont_push(make_dict_frame(rest(remaining), append(completed, [[first(next_entry)]]), fenv), rest_k)) - elif sx_truthy((ft == 'reset')): - return make_cek_value(value, env, rest_k) - elif sx_truthy((ft == 'deref')): - val = value - fenv = get(frame, 'env') - if sx_truthy((not sx_truthy(is_signal(val)))): - return make_cek_value(val, fenv, rest_k) - else: - if sx_truthy(has_reactive_reset_frame_p(rest_k)): - return reactive_shift_deref(val, fenv, rest_k) - else: - ctx = sx_context('sx-reactive', NIL) - if sx_truthy(ctx): - dep_list = get(ctx, 'deps') - notify_fn = get(ctx, 'notify') - if sx_truthy((not sx_truthy(contains_p(dep_list, val)))): - dep_list.append(val) - signal_add_sub(val, notify_fn) - return make_cek_value(signal_value(val), fenv, rest_k) - elif sx_truthy((ft == 'reactive-reset')): - update_fn = get(frame, 'update-fn') - first_p = get(frame, 'first-render') - if sx_truthy((update_fn if not sx_truthy(update_fn) else (not sx_truthy(first_p)))): - cek_call(update_fn, [value]) - return make_cek_value(value, env, rest_k) - elif sx_truthy((ft == 'scope')): - name = get(frame, 'name') - remaining = get(frame, 'remaining') - fenv = get(frame, 'env') - if sx_truthy(empty_p(remaining)): - scope_pop(name) - return make_cek_value(value, fenv, rest_k) - else: - return make_cek_state(first(remaining), fenv, kont_push(make_scope_frame(name, rest(remaining), fenv), rest_k)) - elif sx_truthy((ft == 'map')): - f = get(frame, 'f') - remaining = get(frame, 'remaining') - results = get(frame, 'results') - indexed = get(frame, 'indexed') - fenv = get(frame, 'env') - new_results = append(results, [value]) - if sx_truthy(empty_p(remaining)): - return make_cek_value(new_results, fenv, rest_k) - else: - call_args = ([len(new_results), first(remaining)] if sx_truthy(indexed) else [first(remaining)]) - next_frame = (make_map_indexed_frame(f, rest(remaining), new_results, fenv) if sx_truthy(indexed) else make_map_frame(f, rest(remaining), new_results, fenv)) - return continue_with_call(f, call_args, fenv, [], kont_push(next_frame, rest_k)) - elif sx_truthy((ft == 'filter')): - f = get(frame, 'f') - remaining = get(frame, 'remaining') - results = get(frame, 'results') - current_item = get(frame, 'current-item') - fenv = get(frame, 'env') - new_results = (append(results, [current_item]) if sx_truthy(value) else results) - if sx_truthy(empty_p(remaining)): - return make_cek_value(new_results, fenv, rest_k) - else: - return continue_with_call(f, [first(remaining)], fenv, [], kont_push(make_filter_frame(f, rest(remaining), new_results, first(remaining), fenv), rest_k)) - elif sx_truthy((ft == 'reduce')): - f = get(frame, 'f') - remaining = get(frame, 'remaining') - fenv = get(frame, 'env') - if sx_truthy(empty_p(remaining)): - return make_cek_value(value, fenv, rest_k) - else: - return continue_with_call(f, [value, first(remaining)], fenv, [], kont_push(make_reduce_frame(f, rest(remaining), fenv), rest_k)) - elif sx_truthy((ft == 'for-each')): - f = get(frame, 'f') - remaining = get(frame, 'remaining') - fenv = get(frame, 'env') - if sx_truthy(empty_p(remaining)): - return make_cek_value(NIL, fenv, rest_k) - else: - return continue_with_call(f, [first(remaining)], fenv, [], kont_push(make_for_each_frame(f, rest(remaining), fenv), rest_k)) - elif sx_truthy((ft == 'some')): - f = get(frame, 'f') - remaining = get(frame, 'remaining') - fenv = get(frame, 'env') - if sx_truthy(value): - return make_cek_value(value, fenv, rest_k) - else: - if sx_truthy(empty_p(remaining)): - return make_cek_value(False, fenv, rest_k) - else: - return continue_with_call(f, [first(remaining)], fenv, [], kont_push(make_some_frame(f, rest(remaining), fenv), rest_k)) - elif sx_truthy((ft == 'every')): - f = get(frame, 'f') - remaining = get(frame, 'remaining') - fenv = get(frame, 'env') - if sx_truthy((not sx_truthy(value))): - return make_cek_value(False, fenv, rest_k) - else: - if sx_truthy(empty_p(remaining)): - return make_cek_value(True, fenv, rest_k) - else: - return continue_with_call(f, [first(remaining)], fenv, [], kont_push(make_every_frame(f, rest(remaining), fenv), rest_k)) - else: - return error(sx_str('Unknown frame type: ', ft)) - -# continue-with-call -def continue_with_call(f, args, env, raw_args, kont): - if sx_truthy(continuation_p(f)): - arg = (NIL if sx_truthy(empty_p(args)) else first(args)) - cont_data = continuation_data(f) - captured = get(cont_data, 'captured') - rest_k = get(cont_data, 'rest-kont') - return make_cek_value(arg, env, concat(captured, rest_k)) - elif sx_truthy((is_callable(f) if not sx_truthy(is_callable(f)) else ((not sx_truthy(is_lambda(f))) if not sx_truthy((not sx_truthy(is_lambda(f)))) else ((not sx_truthy(is_component(f))) if not sx_truthy((not sx_truthy(is_component(f)))) else (not sx_truthy(is_island(f))))))): - return make_cek_value(apply(f, args), env, kont) - elif sx_truthy(is_lambda(f)): - params = lambda_params(f) - local = env_merge(lambda_closure(f), env) - if sx_truthy((len(args) > len(params))): - return error(sx_str((lambda_name(f) if sx_truthy(lambda_name(f)) else 'lambda'), ' expects ', len(params), ' args, got ', len(args))) - else: - for pair in zip(params, args): - local[first(pair)] = nth(pair, 1) - for p in slice(params, len(args)): - local[p] = NIL - return make_cek_state(lambda_body(f), local, kont) - elif sx_truthy((is_component(f) if sx_truthy(is_component(f)) else is_island(f))): - parsed = parse_keyword_args(raw_args, env) - kwargs = first(parsed) - children = nth(parsed, 1) - local = env_merge(component_closure(f), env) - for p in component_params(f): - local[p] = (dict_get(kwargs, p) if sx_truthy(dict_get(kwargs, p)) else NIL) - if sx_truthy(component_has_children(f)): - local['children'] = children - return make_cek_state(component_body(f), local, kont) - else: - return error(sx_str('Not callable: ', inspect(f))) - -# sf-case-step-loop -def sf_case_step_loop(match_val, clauses, env, kont): - if sx_truthy((len(clauses) < 2)): - return make_cek_value(NIL, env, kont) - else: - test = first(clauses) - body = nth(clauses, 1) - 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'))))): - return make_cek_state(body, env, kont) - else: - test_val = trampoline(eval_expr(test, env)) - if sx_truthy((match_val == test_val)): - return make_cek_state(body, env, kont) - else: - return sf_case_step_loop(match_val, slice(clauses, 2), env, kont) - -# eval-expr-cek -def eval_expr_cek(expr, env): - return cek_run(make_cek_state(expr, env, [])) - -# trampoline-cek -def trampoline_cek(val): - if sx_truthy(is_thunk(val)): - return eval_expr_cek(thunk_expr(val), thunk_env(val)) - else: - return val - -# freeze-registry -freeze_registry = {} - -# freeze-signal -def freeze_signal(name, sig): - scope_name = sx_context('sx-freeze-scope', NIL) - if sx_truthy(scope_name): - entries = (get(freeze_registry, scope_name) if sx_truthy(get(freeze_registry, scope_name)) else []) - entries.append({'name': name, 'signal': sig}) - return _sx_dict_set(freeze_registry, scope_name, entries) - return NIL - -# freeze-scope -def freeze_scope(name, body_fn): - scope_push('sx-freeze-scope', name) - freeze_registry[name] = [] - cek_call(body_fn, NIL) - scope_pop('sx-freeze-scope') - return NIL - -# cek-freeze-scope -def cek_freeze_scope(name): - entries = (get(freeze_registry, name) if sx_truthy(get(freeze_registry, name)) else []) - signals_dict = {} - for entry in entries: - signals_dict[get(entry, 'name')] = signal_value(get(entry, 'signal')) - return {'name': name, 'signals': signals_dict} - -# cek-freeze-all -def cek_freeze_all(): - return map(lambda name: cek_freeze_scope(name), keys(freeze_registry)) - -# cek-thaw-scope -def cek_thaw_scope(name, frozen): - entries = (get(freeze_registry, name) if sx_truthy(get(freeze_registry, name)) else []) - values = get(frozen, 'signals') - if sx_truthy(values): - for entry in entries: - sig_name = get(entry, 'name') - sig = get(entry, 'signal') - val = get(values, sig_name) - if sx_truthy((not sx_truthy(is_nil(val)))): - reset_b(sig, val) - return NIL - return NIL - -# cek-thaw-all -def cek_thaw_all(frozen_list): - for frozen in frozen_list: - cek_thaw_scope(get(frozen, 'name'), frozen) - return NIL - -# freeze-to-sx -def freeze_to_sx(name): - return sx_serialize(cek_freeze_scope(name)) - -# thaw-from-sx -def thaw_from_sx(sx_text): - parsed = sx_parse(sx_text) - if sx_truthy((not sx_truthy(empty_p(parsed)))): - frozen = first(parsed) - return cek_thaw_scope(get(frozen, 'name'), frozen) - return NIL - -# content-store -content_store = {} - -# content-hash -def content_hash(sx_text): - _cells = {} - _cells['hash'] = 5381 - for i in range(0, len(sx_text)): - _cells['hash'] = (((_cells['hash'] * 33) + char_code_at(sx_text, i)) % 4294967296) - return to_hex(_cells['hash']) - -# content-put -def content_put(sx_text): - cid = content_hash(sx_text) - content_store[cid] = sx_text - return cid - -# content-get -def content_get(cid): - return get(content_store, cid) - -# freeze-to-cid -def freeze_to_cid(scope_name): - sx_text = freeze_to_sx(scope_name) - return content_put(sx_text) - -# thaw-from-cid -def thaw_from_cid(cid): - sx_text = content_get(cid) - if sx_truthy(sx_text): - thaw_from_sx(sx_text) - return True - return NIL - - # === Transpiled from signals (reactive signal runtime) === # make-signal