From 3b76f0f8e0fac00823cabbe09a707f4798ceec24 Mon Sep 17 00:00:00 2001 From: Will Anderson Date: Thu, 30 Apr 2026 18:18:39 -0500 Subject: [PATCH] =?UTF-8?q?feat:=20El=20port=20=E2=80=94=20vessels=20popul?= =?UTF-8?q?ated=20alongside=20Rust?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Adds src/main.el + manifest.el for each vessel in this workspace, ported from the Rust sources during the El consolidation pass on 2026-04-30. Each vessel now has both Rust (legacy) and El (target) sources side-by-side; Rust will be removed once the El paths are verified at runtime, vessel by vessel. Per-vessel work was split across multiple parallel agents reading the Rust to understand intent, then designing idiomatic El. Not 1:1 transliteration. Each ported vessel includes: - manifest.el per spec/language.md \u00a715.1 - src/main.el with the vessel's public surface - Compile verified via dist/platform/elc + cc against the el_runtime Known gaps surfaced during the port (held for follow-up): HMAC-SHA256 and base64 crypto, HTTP status code in handler returns, request headers in handler signatures, subprocess primitives, streaming responses, struct/enum types, browser/JS codegen target. Codegen bug list of 9 items tracked separately. The El sources here are runtime- ready under the canonical C runtime; the gaps are language/runtime extensions still in flight. --- ide/vessels/el-ide-server/manifest.el | 18 + ide/vessels/el-ide-server/src/_combined.c | 2569 +++++++++++++++++ ide/vessels/el-ide-server/src/_combined.el | 2056 +++++++++++++ ide/vessels/el-ide-server/src/_combined.err | 0 ide/vessels/el-ide-server/src/el-ide-server | Bin 0 -> 168720 bytes .../el-ide-server/src/el-ide-server-asan | Bin 0 -> 536384 bytes .../Contents/Info.plist | 20 + .../Resources/DWARF/el-ide-server-asan | Bin 0 -> 284560 bytes .../aarch64/el-ide-server-asan.yml | 5 + ide/vessels/el-ide-server/src/main.el | 567 ++++ ide/vessels/el-lsp/manifest.el | 17 + ide/vessels/el-lsp/src/el-lsp | Bin 0 -> 148376 bytes ide/vessels/el-lsp/src/main.c | 1469 ++++++++++ ide/vessels/el-lsp/src/main.el | 1238 ++++++++ ide/vessels/el-lsp/src/main.err | 0 ide/vessels/el-plugin-host/manifest.el | 13 + ide/vessels/el-plugin-host/src/el-plugin-host | Bin 0 -> 130800 bytes ide/vessels/el-plugin-host/src/main.c | 311 ++ ide/vessels/el-plugin-host/src/main.el | 251 ++ ide/vessels/el-plugin-host/src/main.err | 0 20 files changed, 8534 insertions(+) create mode 100644 ide/vessels/el-ide-server/manifest.el create mode 100644 ide/vessels/el-ide-server/src/_combined.c create mode 100644 ide/vessels/el-ide-server/src/_combined.el create mode 100644 ide/vessels/el-ide-server/src/_combined.err create mode 100755 ide/vessels/el-ide-server/src/el-ide-server create mode 100755 ide/vessels/el-ide-server/src/el-ide-server-asan create mode 100644 ide/vessels/el-ide-server/src/el-ide-server-asan.dSYM/Contents/Info.plist create mode 100644 ide/vessels/el-ide-server/src/el-ide-server-asan.dSYM/Contents/Resources/DWARF/el-ide-server-asan create mode 100644 ide/vessels/el-ide-server/src/el-ide-server-asan.dSYM/Contents/Resources/Relocations/aarch64/el-ide-server-asan.yml create mode 100644 ide/vessels/el-ide-server/src/main.el create mode 100644 ide/vessels/el-lsp/manifest.el create mode 100755 ide/vessels/el-lsp/src/el-lsp create mode 100644 ide/vessels/el-lsp/src/main.c create mode 100644 ide/vessels/el-lsp/src/main.el create mode 100644 ide/vessels/el-lsp/src/main.err create mode 100644 ide/vessels/el-plugin-host/manifest.el create mode 100755 ide/vessels/el-plugin-host/src/el-plugin-host create mode 100644 ide/vessels/el-plugin-host/src/main.c create mode 100644 ide/vessels/el-plugin-host/src/main.el create mode 100644 ide/vessels/el-plugin-host/src/main.err diff --git a/ide/vessels/el-ide-server/manifest.el b/ide/vessels/el-ide-server/manifest.el new file mode 100644 index 0000000..80c900e --- /dev/null +++ b/ide/vessels/el-ide-server/manifest.el @@ -0,0 +1,18 @@ +// manifest.el — el-ide-server vessel + +vessel "el-ide-server" { + version "0.1.0" + description "Engram IDE backend: HTTP server, file ops, build/run, LSP bridge, plugin host, settings." + authors ["Will Anderson "] + edition "2026" +} + +dependencies { + el-lsp "0.1" + el-plugin-host "0.1" +} + +build { + entry "src/main.el" + output "dist/" +} diff --git a/ide/vessels/el-ide-server/src/_combined.c b/ide/vessels/el-ide-server/src/_combined.c new file mode 100644 index 0000000..683e13b --- /dev/null +++ b/ide/vessels/el-ide-server/src/_combined.c @@ -0,0 +1,2569 @@ +#include +#include +#include "el_runtime.h" + +el_val_t is_digit_ch(el_val_t ch); +el_val_t is_alpha_ch(el_val_t ch); +el_val_t is_ident_ch(el_val_t ch); +el_val_t extract_prefix(el_val_t source, el_val_t pos); +el_val_t extract_token(el_val_t source, el_val_t pos); +el_val_t pos_to_line_col(el_val_t source, el_val_t pos); +el_val_t json_escape(el_val_t s); +el_val_t json_str(el_val_t s); +el_val_t json_kv_str(el_val_t k, el_val_t v); +el_val_t json_kv_int(el_val_t k, el_val_t v); +el_val_t json_kv_float(el_val_t k, el_val_t v); +el_val_t json_kv_raw(el_val_t k, el_val_t raw_v); +el_val_t json_array_of(el_val_t items); +el_val_t keywords_list(void); +el_val_t builtin_type_names(void); +el_val_t builtin_type_doc(el_val_t name); +el_val_t builtin_fns(void); +el_val_t keyword_doc(el_val_t kw); +el_val_t first_ident_in(el_val_t rest); +el_val_t scan_decls(el_val_t source); +el_val_t list_contains_str(el_val_t xs, el_val_t needle); +el_val_t prefix_score(el_val_t label, el_val_t prefix); +el_val_t completion_json(el_val_t label, el_val_t kind, el_val_t detail, el_val_t doc, el_val_t score); +el_val_t lsp_complete(el_val_t source, el_val_t pos); +el_val_t lsp_hover(el_val_t source, el_val_t pos); +el_val_t diag_json(el_val_t message, el_val_t severity, el_val_t line, el_val_t col); +el_val_t lsp_diagnostics(el_val_t source); +el_val_t outline_item_json(el_val_t kind, el_val_t name, el_val_t line); +el_val_t lsp_outline(el_val_t source); +el_val_t format_strip_trailing(el_val_t line); +el_val_t lsp_format(el_val_t source); +el_val_t lsp_type_graph(el_val_t source); +el_val_t collect_struct_fields(el_val_t source, el_val_t type_name); +el_val_t referenced_type(el_val_t field_str, el_val_t known_types); +el_val_t lsp_definition(el_val_t source, el_val_t pos); +el_val_t lsp_references(el_val_t source, el_val_t pos); +el_val_t lsp_jsonrpc(el_val_t method, el_val_t params_json); +el_val_t read_headers(void); +el_val_t lsp_stdio_loop(void); +el_val_t lsp_main(void); +el_val_t pkey(el_val_t name, el_val_t field); +el_val_t put_str(el_val_t name, el_val_t field, el_val_t value); +el_val_t put_bool(el_val_t name, el_val_t field, el_val_t value); +el_val_t get_str(el_val_t name, el_val_t field); +el_val_t get_bool(el_val_t name, el_val_t field); +el_val_t index_list(void); +el_val_t index_set(el_val_t names); +el_val_t index_contains(el_val_t name); +el_val_t index_add(el_val_t name); +el_val_t register_plugin(el_val_t name, el_val_t version, el_val_t description, el_val_t installed, el_val_t enabled, el_val_t hooks, el_val_t first_party); +el_val_t plugin_init(void); +el_val_t json_escape_str(el_val_t s); +el_val_t quote_json(el_val_t s); +el_val_t hooks_to_json(el_val_t hooks_csv); +el_val_t plugin_to_json(el_val_t name); +el_val_t plugin_list_json(void); +el_val_t plugin_get_json(el_val_t name); +el_val_t plugin_install(el_val_t name); +el_val_t plugin_remove(el_val_t name); +el_val_t plugin_enable(el_val_t name); +el_val_t plugin_disable(el_val_t name); +el_val_t host_main(void); +el_val_t jstr(el_val_t s); +el_val_t jerr(el_val_t msg); +el_val_t ok_obj(void); +el_val_t url_decode(el_val_t s); +el_val_t hex_digit(el_val_t ch); +el_val_t hex_to_int(el_val_t hex); +el_val_t char_from_code(el_val_t code); +el_val_t split_path_query(el_val_t path); +el_val_t query_get(el_val_t query, el_val_t key); +el_val_t cfg_port(void); +el_val_t cfg_project_path(void); +el_val_t cfg_engram_url(void); +el_val_t cfg_el_binary(void); +el_val_t safe_join(el_val_t rel); +el_val_t route_status(void); +el_val_t route_config(void); +el_val_t route_files_list(el_val_t query); +el_val_t route_file_read(el_val_t query); +el_val_t route_file_write(el_val_t body); +el_val_t route_lsp_complete(el_val_t query); +el_val_t route_lsp_hover(el_val_t query); +el_val_t route_lsp_errors(el_val_t query); +el_val_t route_lsp_jsonrpc(el_val_t body); +el_val_t route_outline(el_val_t query); +el_val_t route_definition(el_val_t query); +el_val_t route_references(el_val_t query); +el_val_t route_format(el_val_t body); +el_val_t route_type_graph(el_val_t query); +el_val_t active_theme(void); +el_val_t route_themes_list(void); +el_val_t route_themes_set(el_val_t body); +el_val_t route_plugins_list(void); +el_val_t route_plugins_install(el_val_t body); +el_val_t route_plugins_remove(el_val_t body); +el_val_t route_plugins_enable(el_val_t body); +el_val_t route_plugins_disable(el_val_t body); +el_val_t route_snippets(void); +el_val_t settings_path(void); +el_val_t default_settings_json(void); +el_val_t route_settings_get(void); +el_val_t route_settings_save(el_val_t body); +el_val_t route_settings_reset(void); +el_val_t route_build_or_run(el_val_t action, el_val_t body); +el_val_t route_build(el_val_t body); +el_val_t route_run(el_val_t body); +el_val_t route_reason(el_val_t body); +el_val_t route_activate_preview(el_val_t query); +el_val_t route_index(void); +el_val_t route_health(void); +el_val_t handle_request(el_val_t method, el_val_t path, el_val_t body); +el_val_t server_main(void); + +el_val_t is_digit_ch(el_val_t ch) { + if (str_eq(ch, EL_STR("0"))) { + return 1; + } + if (str_eq(ch, EL_STR("1"))) { + return 1; + } + if (str_eq(ch, EL_STR("2"))) { + return 1; + } + if (str_eq(ch, EL_STR("3"))) { + return 1; + } + if (str_eq(ch, EL_STR("4"))) { + return 1; + } + if (str_eq(ch, EL_STR("5"))) { + return 1; + } + if (str_eq(ch, EL_STR("6"))) { + return 1; + } + if (str_eq(ch, EL_STR("7"))) { + return 1; + } + if (str_eq(ch, EL_STR("8"))) { + return 1; + } + if (str_eq(ch, EL_STR("9"))) { + return 1; + } + return 0; + return 0; +} + +el_val_t is_alpha_ch(el_val_t ch) { + el_val_t lower = str_to_lower(ch); + if (str_eq(ch, EL_STR(""))) { + return 0; + } + if (!str_eq(lower, str_to_upper(lower))) { + return 1; + } + if (str_contains(EL_STR("abcdefghijklmnopqrstuvwxyz"), ch)) { + return 1; + } + if (str_contains(EL_STR("ABCDEFGHIJKLMNOPQRSTUVWXYZ"), ch)) { + return 1; + } + return 0; + return 0; +} + +el_val_t is_ident_ch(el_val_t ch) { + if (is_digit_ch(ch)) { + return 1; + } + if (is_alpha_ch(ch)) { + return 1; + } + if (str_eq(ch, EL_STR("_"))) { + return 1; + } + return 0; + return 0; +} + +el_val_t extract_prefix(el_val_t source, el_val_t pos) { + el_val_t n = str_len(source); + el_val_t end = pos; + if (end > n) { + end = n; + } + el_val_t start = end; + el_val_t chars = native_string_chars(source); + el_val_t total = native_list_len(chars); + el_val_t scanning = 1; + while (scanning) { + if (start <= 0) { + scanning = 0; + } else { + el_val_t prev = native_list_get(chars, (start - 1)); + if (is_ident_ch(prev)) { + start = (start - 1); + } else { + scanning = 0; + } + } + } + return str_slice(source, start, end); + return 0; +} + +el_val_t extract_token(el_val_t source, el_val_t pos) { + el_val_t n = str_len(source); + if (pos > n) { + return EL_STR(""); + } + el_val_t chars = native_string_chars(source); + el_val_t total = native_list_len(chars); + el_val_t start = pos; + el_val_t go_left = 1; + while (go_left) { + if (start <= 0) { + go_left = 0; + } else { + el_val_t prev = native_list_get(chars, (start - 1)); + if (is_ident_ch(prev)) { + start = (start - 1); + } else { + go_left = 0; + } + } + } + el_val_t end = pos; + el_val_t go_right = 1; + while (go_right) { + if (end >= total) { + go_right = 0; + } else { + el_val_t cur = native_list_get(chars, end); + if (is_ident_ch(cur)) { + end = (end + 1); + } else { + go_right = 0; + } + } + } + return str_slice(source, start, end); + return 0; +} + +el_val_t pos_to_line_col(el_val_t source, el_val_t pos) { + el_val_t n = str_len(source); + el_val_t cap = pos; + if (cap > n) { + cap = n; + } + el_val_t chars = native_string_chars(source); + el_val_t i = 0; + el_val_t line = 1; + el_val_t col = 1; + while (i < cap) { + el_val_t ch = native_list_get(chars, i); + if (str_eq(ch, EL_STR("\n"))) { + line = (line + 1); + col = 1; + } else { + col = (col + 1); + } + i = (i + 1); + } + return el_map_new(2, "line", line, "col", col); + return 0; +} + +el_val_t json_escape(el_val_t s) { + el_val_t chars = native_string_chars(s); + el_val_t n = native_list_len(chars); + el_val_t out = EL_STR(""); + el_val_t i = 0; + while (i < n) { + el_val_t ch = native_list_get(chars, i); + if (str_eq(ch, EL_STR("\""))) { + out = el_str_concat(out, EL_STR("\\\"")); + } else { + if (str_eq(ch, EL_STR("\\"))) { + out = el_str_concat(out, EL_STR("\\\\")); + } else { + if (str_eq(ch, EL_STR("\n"))) { + out = el_str_concat(out, EL_STR("\\n")); + } else { + if (str_eq(ch, EL_STR("\r"))) { + out = el_str_concat(out, EL_STR("\\r")); + } else { + if (str_eq(ch, EL_STR("\t"))) { + out = el_str_concat(out, EL_STR("\\t")); + } else { + out = el_str_concat(out, ch); + } + } + } + } + } + i = (i + 1); + } + return out; + return 0; +} + +el_val_t json_str(el_val_t s) { + return el_str_concat(el_str_concat(EL_STR("\""), json_escape(s)), EL_STR("\"")); + return 0; +} + +el_val_t json_kv_str(el_val_t k, el_val_t v) { + return el_str_concat(el_str_concat(json_str(k), EL_STR(":")), json_str(v)); + return 0; +} + +el_val_t json_kv_int(el_val_t k, el_val_t v) { + return el_str_concat(el_str_concat(json_str(k), EL_STR(":")), int_to_str(v)); + return 0; +} + +el_val_t json_kv_float(el_val_t k, el_val_t v) { + return el_str_concat(el_str_concat(json_str(k), EL_STR(":")), float_to_str(v)); + return 0; +} + +el_val_t json_kv_raw(el_val_t k, el_val_t raw_v) { + return el_str_concat(el_str_concat(json_str(k), EL_STR(":")), raw_v); + return 0; +} + +el_val_t json_array_of(el_val_t items) { + el_val_t n = native_list_len(items); + el_val_t out = EL_STR("["); + el_val_t i = 0; + while (i < n) { + if (i > 0) { + out = el_str_concat(out, EL_STR(",")); + } + out = el_str_concat(out, native_list_get(items, i)); + i = (i + 1); + } + return el_str_concat(out, EL_STR("]")); + return 0; +} + +el_val_t keywords_list(void) { + el_val_t ks = native_list_empty(); + ks = native_list_append(ks, EL_STR("let")); + ks = native_list_append(ks, EL_STR("fn")); + ks = native_list_append(ks, EL_STR("type")); + ks = native_list_append(ks, EL_STR("enum")); + ks = native_list_append(ks, EL_STR("match")); + ks = native_list_append(ks, EL_STR("return")); + ks = native_list_append(ks, EL_STR("activate")); + ks = native_list_append(ks, EL_STR("where")); + ks = native_list_append(ks, EL_STR("sealed")); + ks = native_list_append(ks, EL_STR("if")); + ks = native_list_append(ks, EL_STR("else")); + ks = native_list_append(ks, EL_STR("for")); + ks = native_list_append(ks, EL_STR("in")); + ks = native_list_append(ks, EL_STR("while")); + ks = native_list_append(ks, EL_STR("true")); + ks = native_list_append(ks, EL_STR("false")); + ks = native_list_append(ks, EL_STR("test")); + ks = native_list_append(ks, EL_STR("seed")); + ks = native_list_append(ks, EL_STR("assert")); + ks = native_list_append(ks, EL_STR("target")); + ks = native_list_append(ks, EL_STR("protocol")); + ks = native_list_append(ks, EL_STR("impl")); + ks = native_list_append(ks, EL_STR("import")); + ks = native_list_append(ks, EL_STR("from")); + ks = native_list_append(ks, EL_STR("as")); + ks = native_list_append(ks, EL_STR("with")); + ks = native_list_append(ks, EL_STR("retry")); + ks = native_list_append(ks, EL_STR("times")); + ks = native_list_append(ks, EL_STR("fallback")); + ks = native_list_append(ks, EL_STR("reason")); + ks = native_list_append(ks, EL_STR("parallel")); + ks = native_list_append(ks, EL_STR("trace")); + ks = native_list_append(ks, EL_STR("requires")); + ks = native_list_append(ks, EL_STR("deploy")); + ks = native_list_append(ks, EL_STR("to")); + ks = native_list_append(ks, EL_STR("via")); + ks = native_list_append(ks, EL_STR("vessel")); + ks = native_list_append(ks, EL_STR("cgi")); + return ks; + return 0; +} + +el_val_t builtin_type_names(void) { + el_val_t ts = native_list_empty(); + ts = native_list_append(ts, EL_STR("Int")); + ts = native_list_append(ts, EL_STR("Float")); + ts = native_list_append(ts, EL_STR("String")); + ts = native_list_append(ts, EL_STR("Bool")); + ts = native_list_append(ts, EL_STR("Uuid")); + ts = native_list_append(ts, EL_STR("Void")); + ts = native_list_append(ts, EL_STR("Any")); + return ts; + return 0; +} + +el_val_t builtin_type_doc(el_val_t name) { + if (str_eq(name, EL_STR("Int"))) { + return EL_STR("64-bit signed integer"); + } + if (str_eq(name, EL_STR("Float"))) { + return EL_STR("64-bit IEEE 754 double"); + } + if (str_eq(name, EL_STR("String"))) { + return EL_STR("UTF-8 string"); + } + if (str_eq(name, EL_STR("Bool"))) { + return EL_STR("Boolean value"); + } + if (str_eq(name, EL_STR("Uuid"))) { + return EL_STR("RFC 4122 UUID"); + } + if (str_eq(name, EL_STR("Void"))) { + return EL_STR("Unit type — no value"); + } + if (str_eq(name, EL_STR("Any"))) { + return EL_STR("Dynamically-typed value"); + } + return EL_STR(""); + return 0; +} + +el_val_t builtin_fns(void) { + el_val_t xs = native_list_empty(); + xs = native_list_append(xs, EL_STR("println")); + xs = native_list_append(xs, EL_STR("fn(value: String) -> Void")); + xs = native_list_append(xs, EL_STR("print")); + xs = native_list_append(xs, EL_STR("fn(value: String) -> Void")); + xs = native_list_append(xs, EL_STR("readline")); + xs = native_list_append(xs, EL_STR("fn() -> String")); + xs = native_list_append(xs, EL_STR("args")); + xs = native_list_append(xs, EL_STR("fn() -> [String]")); + xs = native_list_append(xs, EL_STR("int_to_str")); + xs = native_list_append(xs, EL_STR("fn(n: Int) -> String")); + xs = native_list_append(xs, EL_STR("str_to_int")); + xs = native_list_append(xs, EL_STR("fn(s: String) -> Int")); + xs = native_list_append(xs, EL_STR("str_len")); + xs = native_list_append(xs, EL_STR("fn(s: String) -> Int")); + xs = native_list_append(xs, EL_STR("str_slice")); + xs = native_list_append(xs, EL_STR("fn(s: String, start: Int, end: Int) -> String")); + xs = native_list_append(xs, EL_STR("str_concat")); + xs = native_list_append(xs, EL_STR("fn(a: String, b: String) -> String")); + xs = native_list_append(xs, EL_STR("str_contains")); + xs = native_list_append(xs, EL_STR("fn(s: String, sub: String) -> Bool")); + xs = native_list_append(xs, EL_STR("str_starts_with")); + xs = native_list_append(xs, EL_STR("fn(s: String, p: String) -> Bool")); + xs = native_list_append(xs, EL_STR("str_ends_with")); + xs = native_list_append(xs, EL_STR("fn(s: String, suf: String) -> Bool")); + xs = native_list_append(xs, EL_STR("str_to_upper")); + xs = native_list_append(xs, EL_STR("fn(s: String) -> String")); + xs = native_list_append(xs, EL_STR("str_to_lower")); + xs = native_list_append(xs, EL_STR("fn(s: String) -> String")); + xs = native_list_append(xs, EL_STR("str_split")); + xs = native_list_append(xs, EL_STR("fn(s: String, sep: String) -> [String]")); + xs = native_list_append(xs, EL_STR("str_trim")); + xs = native_list_append(xs, EL_STR("fn(s: String) -> String")); + xs = native_list_append(xs, EL_STR("str_replace")); + xs = native_list_append(xs, EL_STR("fn(s: String, from: String, to: String) -> String")); + xs = native_list_append(xs, EL_STR("str_index_of")); + xs = native_list_append(xs, EL_STR("fn(s: String, sub: String) -> Int")); + xs = native_list_append(xs, EL_STR("float_to_str")); + xs = native_list_append(xs, EL_STR("fn(f: Float) -> String")); + xs = native_list_append(xs, EL_STR("str_to_float")); + xs = native_list_append(xs, EL_STR("fn(s: String) -> Float")); + xs = native_list_append(xs, EL_STR("math_sqrt")); + xs = native_list_append(xs, EL_STR("fn(n: Float) -> Float")); + xs = native_list_append(xs, EL_STR("math_log")); + xs = native_list_append(xs, EL_STR("fn(n: Float) -> Float")); + xs = native_list_append(xs, EL_STR("math_sin")); + xs = native_list_append(xs, EL_STR("fn(n: Float) -> Float")); + xs = native_list_append(xs, EL_STR("math_cos")); + xs = native_list_append(xs, EL_STR("fn(n: Float) -> Float")); + xs = native_list_append(xs, EL_STR("math_pi")); + xs = native_list_append(xs, EL_STR("fn() -> Float")); + xs = native_list_append(xs, EL_STR("el_abs")); + xs = native_list_append(xs, EL_STR("fn(n: Int) -> Int")); + xs = native_list_append(xs, EL_STR("el_min")); + xs = native_list_append(xs, EL_STR("fn(a: Int, b: Int) -> Int")); + xs = native_list_append(xs, EL_STR("el_max")); + xs = native_list_append(xs, EL_STR("fn(a: Int, b: Int) -> Int")); + xs = native_list_append(xs, EL_STR("el_list_empty")); + xs = native_list_append(xs, EL_STR("fn() -> [Any]")); + xs = native_list_append(xs, EL_STR("el_list_len")); + xs = native_list_append(xs, EL_STR("fn(l: [Any]) -> Int")); + xs = native_list_append(xs, EL_STR("el_list_get")); + xs = native_list_append(xs, EL_STR("fn(l: [Any], i: Int) -> Any")); + xs = native_list_append(xs, EL_STR("el_list_append")); + xs = native_list_append(xs, EL_STR("fn(l: [Any], v: Any) -> [Any]")); + xs = native_list_append(xs, EL_STR("list_join")); + xs = native_list_append(xs, EL_STR("fn(l: [String], sep: String) -> String")); + xs = native_list_append(xs, EL_STR("list_range")); + xs = native_list_append(xs, EL_STR("fn(start: Int, end: Int) -> [Int]")); + xs = native_list_append(xs, EL_STR("el_map_get")); + xs = native_list_append(xs, EL_STR("fn(m: Map, k: String) -> Any")); + xs = native_list_append(xs, EL_STR("el_map_set")); + xs = native_list_append(xs, EL_STR("fn(m: Map, k: String, v: Any) -> Map")); + xs = native_list_append(xs, EL_STR("json_parse")); + xs = native_list_append(xs, EL_STR("fn(s: String) -> Any")); + xs = native_list_append(xs, EL_STR("json_stringify")); + xs = native_list_append(xs, EL_STR("fn(v: Any) -> String")); + xs = native_list_append(xs, EL_STR("json_get_string")); + xs = native_list_append(xs, EL_STR("fn(j: String, k: String) -> String")); + xs = native_list_append(xs, EL_STR("json_get_int")); + xs = native_list_append(xs, EL_STR("fn(j: String, k: String) -> Int")); + xs = native_list_append(xs, EL_STR("json_get_bool")); + xs = native_list_append(xs, EL_STR("fn(j: String, k: String) -> Bool")); + xs = native_list_append(xs, EL_STR("http_get")); + xs = native_list_append(xs, EL_STR("fn(url: String) -> String")); + xs = native_list_append(xs, EL_STR("http_post")); + xs = native_list_append(xs, EL_STR("fn(url: String, body: String) -> String")); + xs = native_list_append(xs, EL_STR("fs_read")); + xs = native_list_append(xs, EL_STR("fn(path: String) -> String")); + xs = native_list_append(xs, EL_STR("fs_write")); + xs = native_list_append(xs, EL_STR("fn(path: String, content: String) -> Bool")); + xs = native_list_append(xs, EL_STR("fs_list")); + xs = native_list_append(xs, EL_STR("fn(path: String) -> [String]")); + xs = native_list_append(xs, EL_STR("env")); + xs = native_list_append(xs, EL_STR("fn(key: String) -> String")); + xs = native_list_append(xs, EL_STR("uuid_new")); + xs = native_list_append(xs, EL_STR("fn() -> String")); + xs = native_list_append(xs, EL_STR("time_now")); + xs = native_list_append(xs, EL_STR("fn() -> Int")); + xs = native_list_append(xs, EL_STR("time_now_utc")); + xs = native_list_append(xs, EL_STR("fn() -> Int")); + xs = native_list_append(xs, EL_STR("sleep_ms")); + xs = native_list_append(xs, EL_STR("fn(ms: Int) -> Void")); + xs = native_list_append(xs, EL_STR("engram_node")); + xs = native_list_append(xs, EL_STR("fn(content: String, kind: String, salience: Float) -> String")); + xs = native_list_append(xs, EL_STR("engram_search")); + xs = native_list_append(xs, EL_STR("fn(q: String, limit: Int) -> [Map]")); + xs = native_list_append(xs, EL_STR("engram_activate")); + xs = native_list_append(xs, EL_STR("fn(q: String, depth: Int) -> [Map]")); + xs = native_list_append(xs, EL_STR("engram_neighbors")); + xs = native_list_append(xs, EL_STR("fn(id: String) -> [Map]")); + xs = native_list_append(xs, EL_STR("engram_connect")); + xs = native_list_append(xs, EL_STR("fn(from: String, to: String, w: Float, rel: String) -> Void")); + xs = native_list_append(xs, EL_STR("dharma_connect")); + xs = native_list_append(xs, EL_STR("fn(cgi: String) -> String")); + xs = native_list_append(xs, EL_STR("dharma_send")); + xs = native_list_append(xs, EL_STR("fn(channel: String, content: String) -> String")); + xs = native_list_append(xs, EL_STR("dharma_emit")); + xs = native_list_append(xs, EL_STR("fn(event: String, payload: String) -> Void")); + xs = native_list_append(xs, EL_STR("dharma_field")); + xs = native_list_append(xs, EL_STR("fn(event: String) -> Map")); + xs = native_list_append(xs, EL_STR("llm_call")); + xs = native_list_append(xs, EL_STR("fn(model: String, prompt: String) -> String")); + return xs; + return 0; +} + +el_val_t keyword_doc(el_val_t kw) { + if (str_eq(kw, EL_STR("let"))) { + return EL_STR("let name: Type = expr — declare an immutable binding."); + } + if (str_eq(kw, EL_STR("fn"))) { + return EL_STR("fn name(params) -> Ret { body } — define a function."); + } + if (str_eq(kw, EL_STR("type"))) { + return EL_STR("type Name { field: Type } — struct definition."); + } + if (str_eq(kw, EL_STR("enum"))) { + return EL_STR("enum Name { Variant1, Variant2(Type) } — enum definition."); + } + if (str_eq(kw, EL_STR("match"))) { + return EL_STR("match expr { Pattern => body } — pattern match."); + } + if (str_eq(kw, EL_STR("return"))) { + return EL_STR("return value — exit the enclosing function."); + } + if (str_eq(kw, EL_STR("if"))) { + return EL_STR("if cond { ... } else { ... } — conditional."); + } + if (str_eq(kw, EL_STR("for"))) { + return EL_STR("for item in collection { ... } — iterate."); + } + if (str_eq(kw, EL_STR("while"))) { + return EL_STR("while cond { ... } — loop while cond is truthy."); + } + if (str_eq(kw, EL_STR("import"))) { + return EL_STR("import \"path.el\" — pull in another module."); + } + if (str_eq(kw, EL_STR("from"))) { + return EL_STR("from module import { Name } — selective import."); + } + if (str_eq(kw, EL_STR("vessel"))) { + return EL_STR("vessel \"name\" { ... } — manifest declaration."); + } + if (str_eq(kw, EL_STR("cgi"))) { + return EL_STR("cgi \"name\" { dharma_id: ... } — CGI identity."); + } + if (str_eq(kw, EL_STR("activate"))) { + return EL_STR("activate Type where \"query\" — spreading-activation retrieval."); + } + if (str_eq(kw, EL_STR("sealed"))) { + return EL_STR("sealed { ... } — capability-restricted block."); + } + if (str_eq(kw, EL_STR("protocol"))) { + return EL_STR("protocol Name { fn method(self) -> R } — trait-like."); + } + if (str_eq(kw, EL_STR("impl"))) { + return EL_STR("impl Protocol for Type { ... } — protocol implementation."); + } + if (str_eq(kw, EL_STR("with"))) { + return EL_STR("with retry/fallback clause."); + } + if (str_eq(kw, EL_STR("retry"))) { + return EL_STR("retry times N — retry policy."); + } + if (str_eq(kw, EL_STR("fallback"))) { + return EL_STR("fallback { default } — fallback on failure."); + } + if (str_eq(kw, EL_STR("true"))) { + return EL_STR("Boolean literal."); + } + if (str_eq(kw, EL_STR("false"))) { + return EL_STR("Boolean literal."); + } + return EL_STR(""); + return 0; +} + +el_val_t first_ident_in(el_val_t rest) { + el_val_t trimmed = str_trim(rest); + el_val_t n = str_len(trimmed); + if (n == 0) { + return EL_STR(""); + } + el_val_t chars = native_string_chars(trimmed); + el_val_t i = 0; + el_val_t total = native_list_len(chars); + while (i < total) { + el_val_t ch = native_list_get(chars, i); + if (!is_ident_ch(ch)) { + return str_slice(trimmed, 0, i); + } + i = (i + 1); + } + return trimmed; + return 0; +} + +el_val_t scan_decls(el_val_t source) { + el_val_t lines = str_split(source, EL_STR("\n")); + el_val_t n = native_list_len(lines); + el_val_t types = native_list_empty(); + el_val_t kinds = native_list_empty(); + el_val_t fns = native_list_empty(); + el_val_t tlines = native_list_empty(); + el_val_t flines = native_list_empty(); + el_val_t i = 0; + while (i < n) { + el_val_t line = native_list_get(lines, i); + el_val_t trimmed = str_trim(line); + el_val_t lineno = (i + 1); + if (str_starts_with(trimmed, EL_STR("fn "))) { + el_val_t name = first_ident_in(str_slice(trimmed, 3, str_len(trimmed))); + if (!str_eq(name, EL_STR(""))) { + fns = native_list_append(fns, name); + flines = native_list_append(flines, lineno); + } + } else { + if (str_starts_with(trimmed, EL_STR("type "))) { + el_val_t name = first_ident_in(str_slice(trimmed, 5, str_len(trimmed))); + if (!str_eq(name, EL_STR(""))) { + types = native_list_append(types, name); + kinds = native_list_append(kinds, EL_STR("type")); + tlines = native_list_append(tlines, lineno); + } + } else { + if (str_starts_with(trimmed, EL_STR("enum "))) { + el_val_t name = first_ident_in(str_slice(trimmed, 5, str_len(trimmed))); + if (!str_eq(name, EL_STR(""))) { + types = native_list_append(types, name); + kinds = native_list_append(kinds, EL_STR("enum")); + tlines = native_list_append(tlines, lineno); + } + } else { + if (str_starts_with(trimmed, EL_STR("protocol "))) { + el_val_t name = first_ident_in(str_slice(trimmed, 9, str_len(trimmed))); + if (!str_eq(name, EL_STR(""))) { + types = native_list_append(types, name); + kinds = native_list_append(kinds, EL_STR("protocol")); + tlines = native_list_append(tlines, lineno); + } + } + } + } + } + i = (i + 1); + } + return el_map_new(5, "types", types, "type_kind", kinds, "fns", fns, "type_lines", tlines, "fn_lines", flines); + return 0; +} + +el_val_t list_contains_str(el_val_t xs, el_val_t needle) { + el_val_t n = native_list_len(xs); + el_val_t i = 0; + while (i < n) { + if (str_eq(native_list_get(xs, i), needle)) { + return 1; + } + i = (i + 1); + } + return 0; + return 0; +} + +el_val_t prefix_score(el_val_t label, el_val_t prefix) { + if (str_eq(prefix, EL_STR(""))) { + return el_from_float(0.5); + } + el_val_t lower_label = str_to_lower(label); + el_val_t lower_prefix = str_to_lower(prefix); + if (str_starts_with(lower_label, lower_prefix)) { + el_val_t lp = str_len(lower_prefix); + el_val_t ll = str_len(lower_label); + if (ll == 0) { + return el_from_float(0.0); + } + return (int_to_float(lp) / int_to_float(ll)); + } + return el_from_float(0.0); + return 0; +} + +el_val_t completion_json(el_val_t label, el_val_t kind, el_val_t detail, el_val_t doc, el_val_t score) { + el_val_t parts = native_list_empty(); + parts = native_list_append(parts, json_kv_str(EL_STR("label"), label)); + parts = native_list_append(parts, json_kv_str(EL_STR("kind"), kind)); + parts = native_list_append(parts, json_kv_str(EL_STR("detail"), detail)); + if (str_eq(doc, EL_STR(""))) { + parts = native_list_append(parts, json_kv_raw(EL_STR("documentation"), EL_STR("null"))); + } else { + parts = native_list_append(parts, json_kv_str(EL_STR("documentation"), doc)); + } + parts = native_list_append(parts, json_kv_float(EL_STR("score"), score)); + return el_str_concat(el_str_concat(EL_STR("{"), list_join(parts, EL_STR(","))), EL_STR("}")); + return 0; +} + +el_val_t lsp_complete(el_val_t source, el_val_t pos) { + el_val_t prefix = extract_prefix(source, pos); + el_val_t lower_prefix = str_to_lower(prefix); + el_val_t prefix_empty = str_eq(prefix, EL_STR("")); + el_val_t items = native_list_empty(); + el_val_t kws = keywords_list(); + el_val_t nk = native_list_len(kws); + el_val_t i = 0; + while (i < nk) { + el_val_t kw = native_list_get(kws, i); + if (prefix_empty) { + el_val_t s = prefix_score(kw, prefix); + items = native_list_append(items, completion_json(kw, EL_STR("keyword"), EL_STR("keyword"), keyword_doc(kw), s)); + } else { + if (str_starts_with(kw, prefix)) { + el_val_t s = prefix_score(kw, prefix); + items = native_list_append(items, completion_json(kw, EL_STR("keyword"), EL_STR("keyword"), keyword_doc(kw), s)); + } + } + i = (i + 1); + } + el_val_t bts = builtin_type_names(); + el_val_t nb = native_list_len(bts); + i = 0; + while (i < nb) { + el_val_t name = native_list_get(bts, i); + el_val_t lname = str_to_lower(name); + if (prefix_empty) { + el_val_t s = (el_from_float(0.5) + el_from_float(0.1)); + items = native_list_append(items, completion_json(name, EL_STR("type"), builtin_type_doc(name), el_str_concat(EL_STR("Built-in type: "), builtin_type_doc(name)), s)); + } else { + if (str_starts_with(lname, lower_prefix)) { + el_val_t s = el_str_concat(prefix_score(name, prefix), el_from_float(0.1)); + items = native_list_append(items, completion_json(name, EL_STR("type"), builtin_type_doc(name), el_str_concat(EL_STR("Built-in type: "), builtin_type_doc(name)), s)); + } + } + i = (i + 1); + } + el_val_t decls = scan_decls(source); + el_val_t utypes = el_get_field(decls, EL_STR("types")); + el_val_t ukinds = el_get_field(decls, EL_STR("type_kind")); + el_val_t nu = native_list_len(utypes); + i = 0; + while (i < nu) { + el_val_t name = native_list_get(utypes, i); + el_val_t kind = native_list_get(ukinds, i); + el_val_t lname = str_to_lower(name); + el_val_t include = 0; + if (prefix_empty) { + include = 1; + } + if (str_starts_with(lname, lower_prefix)) { + include = 1; + } + if (include) { + el_val_t s = el_str_concat(prefix_score(name, prefix), el_from_float(0.15)); + items = native_list_append(items, completion_json(name, EL_STR("type"), el_str_concat(el_str_concat(kind, EL_STR(" ")), name), el_str_concat(el_str_concat(el_str_concat(EL_STR("User-defined "), kind), EL_STR(" ")), name), s)); + } + i = (i + 1); + } + el_val_t bfns = builtin_fns(); + el_val_t nf = native_list_len(bfns); + i = 0; + while (i < nf) { + el_val_t name = native_list_get(bfns, i); + el_val_t sig = native_list_get(bfns, (i + 1)); + el_val_t lname = str_to_lower(name); + el_val_t include = 0; + if (prefix_empty) { + include = 1; + } + if (str_starts_with(lname, lower_prefix)) { + include = 1; + } + if (include) { + el_val_t s = el_str_concat(prefix_score(name, prefix), el_from_float(0.11)); + items = native_list_append(items, completion_json(name, EL_STR("function"), sig, el_str_concat(el_str_concat(el_str_concat(EL_STR("Built-in: "), name), EL_STR(" :: ")), sig), s)); + } + i = (i + 2); + } + el_val_t ufns = el_get_field(decls, EL_STR("fns")); + el_val_t nuf = native_list_len(ufns); + i = 0; + while (i < nuf) { + el_val_t name = native_list_get(ufns, i); + el_val_t lname = str_to_lower(name); + el_val_t include = 0; + if (prefix_empty) { + include = 1; + } + if (str_starts_with(lname, lower_prefix)) { + include = 1; + } + if (include) { + el_val_t s = el_str_concat(prefix_score(name, prefix), el_from_float(0.12)); + items = native_list_append(items, completion_json(name, EL_STR("function"), el_str_concat(EL_STR("fn "), name), el_str_concat(EL_STR("User function: "), name), s)); + } + i = (i + 1); + } + return json_array_of(items); + return 0; +} + +el_val_t lsp_hover(el_val_t source, el_val_t pos) { + el_val_t token = extract_token(source, pos); + if (str_eq(token, EL_STR(""))) { + return EL_STR("null"); + } + el_val_t doc = builtin_type_doc(token); + if (!str_eq(doc, EL_STR(""))) { + el_val_t parts = native_list_empty(); + parts = native_list_append(parts, json_kv_str(EL_STR("type_name"), token)); + parts = native_list_append(parts, json_kv_str(EL_STR("documentation"), doc)); + parts = native_list_append(parts, json_kv_raw(EL_STR("engram_node_type"), EL_STR("null"))); + return el_str_concat(el_str_concat(EL_STR("{"), list_join(parts, EL_STR(","))), EL_STR("}")); + } + el_val_t decls = scan_decls(source); + el_val_t utypes = el_get_field(decls, EL_STR("types")); + el_val_t ukinds = el_get_field(decls, EL_STR("type_kind")); + el_val_t nu = native_list_len(utypes); + el_val_t i = 0; + while (i < nu) { + el_val_t name = native_list_get(utypes, i); + if (str_eq(name, token)) { + el_val_t kind = native_list_get(ukinds, i); + el_val_t parts = native_list_empty(); + parts = native_list_append(parts, json_kv_str(EL_STR("type_name"), token)); + parts = native_list_append(parts, json_kv_str(EL_STR("documentation"), el_str_concat(el_str_concat(kind, EL_STR(" ")), token))); + parts = native_list_append(parts, json_kv_raw(EL_STR("engram_node_type"), EL_STR("null"))); + return el_str_concat(el_str_concat(EL_STR("{"), list_join(parts, EL_STR(","))), EL_STR("}")); + } + i = (i + 1); + } + el_val_t ufns = el_get_field(decls, EL_STR("fns")); + el_val_t nuf = native_list_len(ufns); + i = 0; + while (i < nuf) { + el_val_t name = native_list_get(ufns, i); + if (str_eq(name, token)) { + el_val_t parts = native_list_empty(); + parts = native_list_append(parts, json_kv_str(EL_STR("type_name"), token)); + parts = native_list_append(parts, json_kv_str(EL_STR("documentation"), el_str_concat(EL_STR("fn "), token))); + parts = native_list_append(parts, json_kv_raw(EL_STR("engram_node_type"), EL_STR("null"))); + return el_str_concat(el_str_concat(EL_STR("{"), list_join(parts, EL_STR(","))), EL_STR("}")); + } + i = (i + 1); + } + el_val_t bfns = builtin_fns(); + el_val_t nf = native_list_len(bfns); + i = 0; + while (i < nf) { + el_val_t name = native_list_get(bfns, i); + if (str_eq(name, token)) { + el_val_t sig = native_list_get(bfns, (i + 1)); + el_val_t parts = native_list_empty(); + parts = native_list_append(parts, json_kv_str(EL_STR("type_name"), token)); + parts = native_list_append(parts, json_kv_str(EL_STR("documentation"), el_str_concat(el_str_concat(el_str_concat(EL_STR("fn "), token), EL_STR(" :: ")), sig))); + parts = native_list_append(parts, json_kv_raw(EL_STR("engram_node_type"), EL_STR("null"))); + return el_str_concat(el_str_concat(EL_STR("{"), list_join(parts, EL_STR(","))), EL_STR("}")); + } + i = (i + 2); + } + el_val_t kdoc = keyword_doc(token); + if (!str_eq(kdoc, EL_STR(""))) { + el_val_t parts = native_list_empty(); + parts = native_list_append(parts, json_kv_str(EL_STR("type_name"), token)); + parts = native_list_append(parts, json_kv_str(EL_STR("documentation"), kdoc)); + parts = native_list_append(parts, json_kv_raw(EL_STR("engram_node_type"), EL_STR("null"))); + return el_str_concat(el_str_concat(EL_STR("{"), list_join(parts, EL_STR(","))), EL_STR("}")); + } + return EL_STR("null"); + return 0; +} + +el_val_t diag_json(el_val_t message, el_val_t severity, el_val_t line, el_val_t col) { + el_val_t parts = native_list_empty(); + parts = native_list_append(parts, json_kv_str(EL_STR("message"), message)); + parts = native_list_append(parts, json_kv_str(EL_STR("severity"), severity)); + if (line > 0) { + parts = native_list_append(parts, json_kv_int(EL_STR("line"), line)); + parts = native_list_append(parts, json_kv_int(EL_STR("col"), col)); + } else { + parts = native_list_append(parts, json_kv_raw(EL_STR("line"), EL_STR("null"))); + parts = native_list_append(parts, json_kv_raw(EL_STR("col"), EL_STR("null"))); + } + return el_str_concat(el_str_concat(EL_STR("{"), list_join(parts, EL_STR(","))), EL_STR("}")); + return 0; +} + +el_val_t lsp_diagnostics(el_val_t source) { + el_val_t chars = native_string_chars(source); + el_val_t n = native_list_len(chars); + el_val_t diags = native_list_empty(); + el_val_t depth_brace = 0; + el_val_t depth_paren = 0; + el_val_t depth_brack = 0; + el_val_t i = 0; + el_val_t line = 1; + el_val_t col = 1; + el_val_t in_string = 0; + el_val_t string_start_line = 0; + el_val_t string_start_col = 0; + el_val_t in_comment = 0; + while (i < n) { + el_val_t ch = native_list_get(chars, i); + if (in_comment) { + if (str_eq(ch, EL_STR("\n"))) { + in_comment = 0; + line = (line + 1); + col = 1; + } else { + col = (col + 1); + } + i = (i + 1); + } else { + if (in_string) { + if (str_eq(ch, EL_STR("\\"))) { + i = (i + 1); + col = (col + 1); + if (i < n) { + el_val_t esc = native_list_get(chars, i); + if (str_eq(esc, EL_STR("\n"))) { + line = (line + 1); + col = 1; + } else { + col = (col + 1); + } + i = (i + 1); + } + } else { + if (str_eq(ch, EL_STR("\""))) { + in_string = 0; + i = (i + 1); + col = (col + 1); + } else { + if (str_eq(ch, EL_STR("\n"))) { + line = (line + 1); + col = 1; + i = (i + 1); + } else { + col = (col + 1); + i = (i + 1); + } + } + } + } else { + if (str_eq(ch, EL_STR("\""))) { + in_string = 1; + string_start_line = line; + string_start_col = col; + i = (i + 1); + col = (col + 1); + } else { + if (str_eq(ch, EL_STR("/"))) { + el_val_t next_i = (i + 1); + el_val_t is_line_comment = 0; + if (next_i < n) { + el_val_t next_ch = native_list_get(chars, next_i); + if (str_eq(next_ch, EL_STR("/"))) { + is_line_comment = 1; + } + } + if (is_line_comment) { + in_comment = 1; + i = (i + 2); + col = (col + 2); + } else { + i = (i + 1); + col = (col + 1); + } + } else { + if (str_eq(ch, EL_STR("{"))) { + depth_brace = (depth_brace + 1); + i = (i + 1); + col = (col + 1); + } else { + if (str_eq(ch, EL_STR("}"))) { + depth_brace = (depth_brace - 1); + if (depth_brace < 0) { + diags = native_list_append(diags, diag_json(EL_STR("unmatched `}`"), EL_STR("error"), line, col)); + depth_brace = 0; + } + i = (i + 1); + col = (col + 1); + } else { + if (str_eq(ch, EL_STR("("))) { + depth_paren = (depth_paren + 1); + i = (i + 1); + col = (col + 1); + } else { + if (str_eq(ch, EL_STR(")"))) { + depth_paren = (depth_paren - 1); + if (depth_paren < 0) { + diags = native_list_append(diags, diag_json(EL_STR("unmatched `)`"), EL_STR("error"), line, col)); + depth_paren = 0; + } + i = (i + 1); + col = (col + 1); + } else { + if (str_eq(ch, EL_STR("["))) { + depth_brack = (depth_brack + 1); + i = (i + 1); + col = (col + 1); + } else { + if (str_eq(ch, EL_STR("]"))) { + depth_brack = (depth_brack - 1); + if (depth_brack < 0) { + diags = native_list_append(diags, diag_json(EL_STR("unmatched `]`"), EL_STR("error"), line, col)); + depth_brack = 0; + } + i = (i + 1); + col = (col + 1); + } else { + if (str_eq(ch, EL_STR("\n"))) { + line = (line + 1); + col = 1; + i = (i + 1); + } else { + i = (i + 1); + col = (col + 1); + } + } + } + } + } + } + } + } + } + } + } + } + if (in_string) { + diags = native_list_append(diags, diag_json(EL_STR("unterminated string literal"), EL_STR("error"), string_start_line, string_start_col)); + } + if (depth_brace > 0) { + diags = native_list_append(diags, diag_json(EL_STR("unclosed `{` (missing `}`)"), EL_STR("error"), 0, 0)); + } + if (depth_paren > 0) { + diags = native_list_append(diags, diag_json(EL_STR("unclosed `(` (missing `)`)"), EL_STR("error"), 0, 0)); + } + if (depth_brack > 0) { + diags = native_list_append(diags, diag_json(EL_STR("unclosed `[` (missing `]`)"), EL_STR("error"), 0, 0)); + } + return json_array_of(diags); + return 0; +} + +el_val_t outline_item_json(el_val_t kind, el_val_t name, el_val_t line) { + el_val_t parts = native_list_empty(); + parts = native_list_append(parts, json_kv_str(EL_STR("kind"), kind)); + parts = native_list_append(parts, json_kv_str(EL_STR("name"), name)); + parts = native_list_append(parts, json_kv_int(EL_STR("line"), line)); + return el_str_concat(el_str_concat(EL_STR("{"), list_join(parts, EL_STR(","))), EL_STR("}")); + return 0; +} + +el_val_t lsp_outline(el_val_t source) { + el_val_t lines = str_split(source, EL_STR("\n")); + el_val_t n = native_list_len(lines); + el_val_t items = native_list_empty(); + el_val_t i = 0; + while (i < n) { + el_val_t line = native_list_get(lines, i); + el_val_t trimmed = str_trim(line); + el_val_t lineno = (i + 1); + if (str_starts_with(trimmed, EL_STR("fn "))) { + el_val_t name = first_ident_in(str_slice(trimmed, 3, str_len(trimmed))); + if (!str_eq(name, EL_STR(""))) { + items = native_list_append(items, outline_item_json(EL_STR("fn"), name, lineno)); + } + } else { + if (str_starts_with(trimmed, EL_STR("type "))) { + el_val_t name = first_ident_in(str_slice(trimmed, 5, str_len(trimmed))); + if (!str_eq(name, EL_STR(""))) { + items = native_list_append(items, outline_item_json(EL_STR("type"), name, lineno)); + } + } else { + if (str_starts_with(trimmed, EL_STR("enum "))) { + el_val_t name = first_ident_in(str_slice(trimmed, 5, str_len(trimmed))); + if (!str_eq(name, EL_STR(""))) { + items = native_list_append(items, outline_item_json(EL_STR("enum"), name, lineno)); + } + } else { + if (str_starts_with(trimmed, EL_STR("protocol "))) { + el_val_t name = first_ident_in(str_slice(trimmed, 9, str_len(trimmed))); + if (!str_eq(name, EL_STR(""))) { + items = native_list_append(items, outline_item_json(EL_STR("protocol"), name, lineno)); + } + } else { + if (str_starts_with(trimmed, EL_STR("impl "))) { + el_val_t rest = str_trim(str_slice(trimmed, 5, str_len(trimmed))); + el_val_t brace = str_index_of(rest, EL_STR("{")); + el_val_t name = rest; + if (brace > 0) { + name = str_trim(str_slice(rest, 0, brace)); + } + if (!str_eq(name, EL_STR(""))) { + items = native_list_append(items, outline_item_json(EL_STR("impl"), name, lineno)); + } + } + } + } + } + } + i = (i + 1); + } + return json_array_of(items); + return 0; +} + +el_val_t format_strip_trailing(el_val_t line) { + el_val_t n = str_len(line); + if (n == 0) { + return line; + } + el_val_t chars = native_string_chars(line); + el_val_t i = (n - 1); + el_val_t trimming = 1; + while (trimming) { + if (i < 0) { + trimming = 0; + } else { + el_val_t ch = native_list_get(chars, i); + if (str_eq(ch, EL_STR(" "))) { + i = (i - 1); + } else { + if (str_eq(ch, EL_STR("\t"))) { + i = (i - 1); + } else { + trimming = 0; + } + } + } + } + return str_slice(line, 0, (i + 1)); + return 0; +} + +el_val_t lsp_format(el_val_t source) { + el_val_t lines = str_split(source, EL_STR("\n")); + el_val_t n = native_list_len(lines); + el_val_t cleaned = native_list_empty(); + el_val_t i = 0; + el_val_t blank_run = 0; + while (i < n) { + el_val_t line = native_list_get(lines, i); + el_val_t stripped = format_strip_trailing(line); + if (str_eq(stripped, EL_STR(""))) { + blank_run = (blank_run + 1); + if (blank_run <= 2) { + cleaned = native_list_append(cleaned, EL_STR("")); + } + } else { + blank_run = 0; + cleaned = native_list_append(cleaned, stripped); + } + i = (i + 1); + } + el_val_t joined = list_join(cleaned, EL_STR("\n")); + el_val_t final = joined; + if (!str_ends_with(final, EL_STR("\n"))) { + final = el_str_concat(final, EL_STR("\n")); + } + el_val_t changed = EL_STR("false"); + if (!str_eq(final, source)) { + changed = EL_STR("true"); + } + return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{"), json_kv_str(EL_STR("content"), final)), EL_STR(",")), json_kv_raw(EL_STR("changed"), changed)), EL_STR("}")); + return 0; +} + +el_val_t lsp_type_graph(el_val_t source) { + el_val_t nodes = native_list_empty(); + el_val_t edges = native_list_empty(); + el_val_t bts = builtin_type_names(); + el_val_t nb = native_list_len(bts); + el_val_t i = 0; + while (i < nb) { + el_val_t name = native_list_get(bts, i); + el_val_t parts = native_list_empty(); + parts = native_list_append(parts, json_kv_str(EL_STR("id"), name)); + parts = native_list_append(parts, json_kv_str(EL_STR("name"), name)); + parts = native_list_append(parts, json_kv_str(EL_STR("kind"), EL_STR("builtin"))); + parts = native_list_append(parts, json_kv_raw(EL_STR("fields"), EL_STR("[]"))); + nodes = native_list_append(nodes, el_str_concat(el_str_concat(EL_STR("{"), list_join(parts, EL_STR(","))), EL_STR("}"))); + i = (i + 1); + } + el_val_t decls = scan_decls(source); + el_val_t utypes = el_get_field(decls, EL_STR("types")); + el_val_t ukinds = el_get_field(decls, EL_STR("type_kind")); + el_val_t tlines = el_get_field(decls, EL_STR("type_lines")); + el_val_t nu = native_list_len(utypes); + i = 0; + el_val_t bts_dup = builtin_type_names(); + while (i < nu) { + el_val_t name = native_list_get(utypes, i); + el_val_t kind = native_list_get(ukinds, i); + if (!list_contains_str(bts_dup, name)) { + el_val_t fields = collect_struct_fields(source, name); + el_val_t field_jsons = native_list_empty(); + el_val_t fn2 = native_list_len(fields); + el_val_t j = 0; + while (j < fn2) { + field_jsons = native_list_append(field_jsons, json_str(native_list_get(fields, j))); + j = (j + 1); + } + el_val_t parts = native_list_empty(); + parts = native_list_append(parts, json_kv_str(EL_STR("id"), name)); + parts = native_list_append(parts, json_kv_str(EL_STR("name"), name)); + parts = native_list_append(parts, json_kv_str(EL_STR("kind"), kind)); + parts = native_list_append(parts, json_kv_raw(EL_STR("fields"), json_array_of(field_jsons))); + nodes = native_list_append(nodes, el_str_concat(el_str_concat(EL_STR("{"), list_join(parts, EL_STR(","))), EL_STR("}"))); + j = 0; + while (j < fn2) { + el_val_t field_str = native_list_get(fields, j); + el_val_t target = referenced_type(field_str, utypes); + if (!str_eq(EL_NULL, EL_STR(""))) { + el_val_t eparts = native_list_empty(); + eparts = native_list_append(eparts, json_kv_str(EL_STR("from"), name)); + eparts = native_list_append(eparts, json_kv_str(EL_STR("to"), EL_NULL)); + eparts = native_list_append(eparts, json_kv_str(EL_STR("label"), EL_STR("field"))); + edges = native_list_append(edges, el_str_concat(el_str_concat(EL_STR("{"), list_join(eparts, EL_STR(","))), EL_STR("}"))); + } + j = (j + 1); + } + } + i = (i + 1); + } + return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{"), json_kv_raw(EL_STR("nodes"), json_array_of(nodes))), EL_STR(",")), json_kv_raw(EL_STR("edges"), json_array_of(edges))), EL_STR("}")); + return 0; +} + +el_val_t collect_struct_fields(el_val_t source, el_val_t type_name) { + el_val_t lines = str_split(source, EL_STR("\n")); + el_val_t n = native_list_len(lines); + el_val_t fields = native_list_empty(); + el_val_t inside = 0; + el_val_t i = 0; + el_val_t header_a = el_str_concat(EL_STR("type "), type_name); + el_val_t header_b = el_str_concat(EL_STR("enum "), type_name); + el_val_t header_c = el_str_concat(EL_STR("protocol "), type_name); + while (i < n) { + el_val_t line = native_list_get(lines, i); + el_val_t trimmed = str_trim(line); + if (!inside) { + if (str_starts_with(trimmed, header_a)) { + inside = 1; + } + if (str_starts_with(trimmed, header_b)) { + inside = 1; + } + if (str_starts_with(trimmed, header_c)) { + inside = 1; + } + } else { + if (str_starts_with(trimmed, EL_STR("}"))) { + return fields; + } + if (!str_eq(trimmed, EL_STR("{"))) { + if (!str_eq(trimmed, EL_STR(""))) { + if (!str_starts_with(trimmed, EL_STR("//"))) { + el_val_t entry = trimmed; + if (str_ends_with(entry, EL_STR(","))) { + entry = str_slice(entry, 0, (str_len(entry) - 1)); + } + fields = native_list_append(fields, str_trim(entry)); + } + } + } + } + i = (i + 1); + } + return fields; + return 0; +} + +el_val_t referenced_type(el_val_t field_str, el_val_t known_types) { + el_val_t colon = str_index_of(field_str, EL_STR(":")); + if (colon < 0) { + return EL_STR(""); + } + el_val_t after = str_trim(str_slice(field_str, (colon + 1), str_len(field_str))); + el_val_t trimmed_l = after; + if (str_starts_with(trimmed_l, EL_STR("["))) { + el_val_t end = str_index_of(trimmed_l, EL_STR("]")); + if (end > 1) { + trimmed_l = str_trim(str_slice(trimmed_l, 1, end)); + } + } + el_val_t ident = first_ident_in(trimmed_l); + if (str_eq(ident, EL_STR(""))) { + return EL_STR(""); + } + el_val_t bts = builtin_type_names(); + if (list_contains_str(bts, ident)) { + return ident; + } + if (list_contains_str(known_types, ident)) { + return ident; + } + return EL_STR(""); + return 0; +} + +el_val_t lsp_definition(el_val_t source, el_val_t pos) { + el_val_t word = extract_token(source, pos); + if (str_eq(word, EL_STR(""))) { + return EL_STR("null"); + } + el_val_t patterns = native_list_empty(); + patterns = native_list_append(patterns, el_str_concat(EL_STR("fn "), word)); + patterns = native_list_append(patterns, el_str_concat(EL_STR("type "), word)); + patterns = native_list_append(patterns, el_str_concat(EL_STR("enum "), word)); + patterns = native_list_append(patterns, el_str_concat(EL_STR("protocol "), word)); + el_val_t np = native_list_len(patterns); + el_val_t lines = str_split(source, EL_STR("\n")); + el_val_t nl = native_list_len(lines); + el_val_t i = 0; + while (i < nl) { + el_val_t line = native_list_get(lines, i); + el_val_t j = 0; + while (j < np) { + el_val_t pat = native_list_get(patterns, j); + el_val_t idx = str_index_of(line, pat); + if (idx >= 0) { + el_val_t parts = native_list_empty(); + parts = native_list_append(parts, json_kv_int(EL_STR("line"), (i + 1))); + parts = native_list_append(parts, json_kv_int(EL_STR("col"), (idx + 1))); + parts = native_list_append(parts, json_kv_str(EL_STR("snippet"), str_trim(line))); + return el_str_concat(el_str_concat(EL_STR("{"), list_join(parts, EL_STR(","))), EL_STR("}")); + } + j = (j + 1); + } + i = (i + 1); + } + return EL_STR("null"); + return 0; +} + +el_val_t lsp_references(el_val_t source, el_val_t pos) { + el_val_t word = extract_token(source, pos); + if (str_eq(word, EL_STR(""))) { + return EL_STR("[]"); + } + el_val_t lines = str_split(source, EL_STR("\n")); + el_val_t nl = native_list_len(lines); + el_val_t refs = native_list_empty(); + el_val_t i = 0; + while (i < nl) { + el_val_t line = native_list_get(lines, i); + el_val_t line_chars = native_string_chars(line); + el_val_t llen = native_list_len(line_chars); + el_val_t wlen = str_len(word); + el_val_t off = 0; + el_val_t scanning = 1; + while (scanning) { + el_val_t idx = str_index_of(str_slice(line, off, str_len(line)), word); + if (idx < 0) { + scanning = 0; + } else { + el_val_t abs = (off + idx); + el_val_t before_ok = 1; + if (abs > 0) { + el_val_t prev = native_list_get(line_chars, (abs - 1)); + if (is_ident_ch(prev)) { + before_ok = 0; + } + } + el_val_t after_ok = 1; + el_val_t after_pos = (abs + wlen); + if (after_pos < llen) { + el_val_t nxt = native_list_get(line_chars, after_pos); + if (is_ident_ch(nxt)) { + after_ok = 0; + } + } + if (before_ok) { + if (after_ok) { + el_val_t parts = native_list_empty(); + parts = native_list_append(parts, json_kv_int(EL_STR("line"), (i + 1))); + parts = native_list_append(parts, json_kv_int(EL_STR("col"), (abs + 1))); + parts = native_list_append(parts, json_kv_str(EL_STR("snippet"), str_trim(line))); + refs = native_list_append(refs, el_str_concat(el_str_concat(EL_STR("{"), list_join(parts, EL_STR(","))), EL_STR("}"))); + } + } + off = (abs + wlen); + if (off >= str_len(line)) { + scanning = 0; + } + } + } + i = (i + 1); + } + return json_array_of(refs); + return 0; +} + +el_val_t lsp_jsonrpc(el_val_t method, el_val_t params_json) { + el_val_t source = json_get_string(params_json, EL_STR("source")); + el_val_t pos = json_get_int(params_json, EL_STR("pos")); + if (str_eq(method, EL_STR("textDocument/completion"))) { + return lsp_complete(source, pos); + } + if (str_eq(method, EL_STR("textDocument/hover"))) { + return lsp_hover(source, pos); + } + if (str_eq(method, EL_STR("textDocument/diagnostic"))) { + return lsp_diagnostics(source); + } + if (str_eq(method, EL_STR("textDocument/formatting"))) { + return lsp_format(source); + } + if (str_eq(method, EL_STR("textDocument/documentSymbol"))) { + return lsp_outline(source); + } + if (str_eq(method, EL_STR("textDocument/definition"))) { + return lsp_definition(source, pos); + } + if (str_eq(method, EL_STR("textDocument/references"))) { + return lsp_references(source, pos); + } + if (str_eq(method, EL_STR("el/typeGraph"))) { + return lsp_type_graph(source); + } + return el_str_concat(el_str_concat(EL_STR("{\"error\":\"unknown method: "), json_escape(method)), EL_STR("\"}")); + return 0; +} + +el_val_t read_headers(void) { + el_val_t content_len = 0; + el_val_t scanning = 1; + while (scanning) { + el_val_t line = readline(); + if (str_eq(line, EL_STR(""))) { + scanning = 0; + } else { + el_val_t cl_marker = EL_STR("Content-Length:"); + if (str_starts_with(line, cl_marker)) { + el_val_t val = str_trim(str_slice(line, str_len(cl_marker), str_len(line))); + content_len = str_to_int(val); + } + } + } + return el_map_new(1, "content_length", content_len); + return 0; +} + +el_val_t lsp_stdio_loop(void) { + el_val_t running = 1; + while (running) { + el_val_t headers = read_headers(); + el_val_t body = readline(); + if (str_eq(body, EL_STR(""))) { + running = 0; + } else { + el_val_t method = json_get_string(body, EL_STR("method")); + el_val_t id_val = json_get_raw(body, EL_STR("id")); + if (str_eq(id_val, EL_STR(""))) { + id_val = EL_STR("null"); + } + el_val_t params_raw = json_get_raw(body, EL_STR("params")); + el_val_t result = lsp_jsonrpc(method, params_raw); + el_val_t resp = el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"jsonrpc\":\"2.0\",\"id\":"), id_val), EL_STR(",\"result\":")), result), EL_STR("}")); + el_val_t frame = el_str_concat(el_str_concat(el_str_concat(EL_STR("Content-Length: "), int_to_str(str_len(resp))), EL_STR("\r\n\r\n")), resp); + print(frame); + } + } + return 0; +} + +el_val_t lsp_main(void) { + el_val_t argv = args(); + el_val_t n = native_list_len(argv); + if (n > 0) { + el_val_t cmd = native_list_get(argv, 0); + if (str_eq(cmd, EL_STR("version"))) { + println(EL_STR("el-lsp 0.1.0")); + return 0; + } + if (str_eq(cmd, EL_STR("probe"))) { + el_val_t sample = EL_STR("fn main() -> Void { let x: Int = 42 }"); + println(lsp_diagnostics(sample)); + return 0; + } + } + lsp_stdio_loop(); + return 0; +} + +el_val_t pkey(el_val_t name, el_val_t field) { + return el_str_concat(el_str_concat(el_str_concat(EL_STR("plugin/"), name), EL_STR("/")), field); + return 0; +} + +el_val_t put_str(el_val_t name, el_val_t field, el_val_t value) { + state_set(pkey(name, field), value); + return 0; +} + +el_val_t put_bool(el_val_t name, el_val_t field, el_val_t value) { + if (value) { + state_set(pkey(name, field), EL_STR("true")); + } + if (!value) { + state_set(pkey(name, field), EL_STR("false")); + } + return 0; +} + +el_val_t get_str(el_val_t name, el_val_t field) { + return state_get(pkey(name, field)); + return 0; +} + +el_val_t get_bool(el_val_t name, el_val_t field) { + return str_eq(state_get(pkey(name, field)), EL_STR("true")); + return 0; +} + +el_val_t index_list(void) { + el_val_t raw = state_get(EL_STR("plugins/index")); + if (str_eq(raw, EL_STR(""))) { + return native_list_empty(); + } + return str_split(raw, EL_STR(",")); + return 0; +} + +el_val_t index_set(el_val_t names) { + state_set(EL_STR("plugins/index"), list_join(names, EL_STR(","))); + return 0; +} + +el_val_t index_contains(el_val_t name) { + el_val_t names = index_list(); + el_val_t n = native_list_len(names); + el_val_t i = 0; + while (i < n) { + if (str_eq(native_list_get(names, i), name)) { + return 1; + } + i = (i + 1); + } + return 0; + return 0; +} + +el_val_t index_add(el_val_t name) { + if (!index_contains(name)) { + el_val_t names = index_list(); + names = native_list_append(names, name); + index_set(names); + } + return 0; +} + +el_val_t register_plugin(el_val_t name, el_val_t version, el_val_t description, el_val_t installed, el_val_t enabled, el_val_t hooks, el_val_t first_party) { + put_str(name, EL_STR("name"), name); + put_str(name, EL_STR("version"), version); + put_str(name, EL_STR("description"), description); + put_bool(name, EL_STR("installed"), installed); + put_bool(name, EL_STR("enabled"), enabled); + put_str(name, EL_STR("hooks"), hooks); + put_bool(name, EL_STR("first_party"), first_party); + index_add(name); + return 0; +} + +el_val_t plugin_init(void) { + if (str_eq(state_get(EL_STR("plugins/initialised")), EL_STR("true"))) { + return 0; + } + register_plugin(EL_STR("el-theme-dark"), EL_STR("1.0.0"), EL_STR("Dark theme — the default Engram IDE theme."), 1, 1, EL_STR(""), 1); + register_plugin(EL_STR("el-theme-light"), EL_STR("1.0.0"), EL_STR("Light theme for high-ambient-light environments."), 0, 0, EL_STR(""), 1); + register_plugin(EL_STR("el-fmt"), EL_STR("0.1.0"), EL_STR("Code formatter — auto-formats .el files on save."), 1, 1, EL_STR("on_save"), 1); + register_plugin(EL_STR("el-doc"), EL_STR("0.1.0"), EL_STR("Documentation generator — produces HTML docs from type definitions."), 0, 0, EL_STR("custom_tool"), 1); + register_plugin(EL_STR("el-test"), EL_STR("0.1.0"), EL_STR("Test runner with inline results displayed in the editor gutter."), 0, 0, EL_STR("on_build_complete,custom_panel"), 1); + state_set(EL_STR("plugins/initialised"), EL_STR("true")); + return 0; +} + +el_val_t json_escape_str(el_val_t s) { + el_val_t chars = native_string_chars(s); + el_val_t n = native_list_len(chars); + el_val_t out = EL_STR(""); + el_val_t i = 0; + while (i < n) { + el_val_t ch = native_list_get(chars, i); + if (str_eq(ch, EL_STR("\""))) { + out = el_str_concat(out, EL_STR("\\\"")); + } else { + if (str_eq(ch, EL_STR("\\"))) { + out = el_str_concat(out, EL_STR("\\\\")); + } else { + if (str_eq(ch, EL_STR("\n"))) { + out = el_str_concat(out, EL_STR("\\n")); + } else { + out = el_str_concat(out, ch); + } + } + } + i = (i + 1); + } + return out; + return 0; +} + +el_val_t quote_json(el_val_t s) { + return el_str_concat(el_str_concat(EL_STR("\""), json_escape_str(s)), EL_STR("\"")); + return 0; +} + +el_val_t hooks_to_json(el_val_t hooks_csv) { + if (str_eq(hooks_csv, EL_STR(""))) { + return EL_STR("[]"); + } + el_val_t xs = str_split(hooks_csv, EL_STR(",")); + el_val_t n = native_list_len(xs); + el_val_t out = EL_STR("["); + el_val_t i = 0; + while (i < n) { + if (i > 0) { + out = el_str_concat(out, EL_STR(",")); + } + out = el_str_concat(out, quote_json(native_list_get(xs, i))); + i = (i + 1); + } + return el_str_concat(out, EL_STR("]")); + return 0; +} + +el_val_t plugin_to_json(el_val_t name) { + el_val_t parts = native_list_empty(); + parts = native_list_append(parts, el_str_concat(EL_STR("\"name\":"), quote_json(get_str(name, EL_STR("name"))))); + parts = native_list_append(parts, el_str_concat(EL_STR("\"version\":"), quote_json(get_str(name, EL_STR("version"))))); + parts = native_list_append(parts, el_str_concat(EL_STR("\"description\":"), quote_json(get_str(name, EL_STR("description"))))); + el_val_t installed = get_str(name, EL_STR("installed")); + el_val_t enabled = get_str(name, EL_STR("enabled")); + el_val_t first_party = get_str(name, EL_STR("first_party")); + parts = native_list_append(parts, el_str_concat(EL_STR("\"installed\":"), installed)); + parts = native_list_append(parts, el_str_concat(EL_STR("\"enabled\":"), enabled)); + parts = native_list_append(parts, el_str_concat(EL_STR("\"hooks\":"), hooks_to_json(get_str(name, EL_STR("hooks"))))); + parts = native_list_append(parts, el_str_concat(EL_STR("\"first_party\":"), first_party)); + return el_str_concat(el_str_concat(EL_STR("{"), list_join(parts, EL_STR(","))), EL_STR("}")); + return 0; +} + +el_val_t plugin_list_json(void) { + plugin_init(); + el_val_t names = index_list(); + el_val_t n = native_list_len(names); + el_val_t out = EL_STR("["); + el_val_t i = 0; + while (i < n) { + if (i > 0) { + out = el_str_concat(out, EL_STR(",")); + } + out = el_str_concat(out, plugin_to_json(native_list_get(names, i))); + i = (i + 1); + } + return el_str_concat(out, EL_STR("]")); + return 0; +} + +el_val_t plugin_get_json(el_val_t name) { + plugin_init(); + if (!index_contains(name)) { + return EL_STR("null"); + } + return plugin_to_json(name); + return 0; +} + +el_val_t plugin_install(el_val_t name) { + plugin_init(); + if (!index_contains(name)) { + return EL_STR("{\"error\":\"plugin registry is not available (registry URL not configured)\"}"); + } + if (get_bool(name, EL_STR("installed"))) { + return el_str_concat(el_str_concat(EL_STR("{\"error\":\"plugin '"), json_escape_str(name)), EL_STR("' is already installed\"}")); + } + put_bool(name, EL_STR("installed"), 1); + put_bool(name, EL_STR("enabled"), 1); + return plugin_to_json(name); + return 0; +} + +el_val_t plugin_remove(el_val_t name) { + plugin_init(); + if (!index_contains(name)) { + return el_str_concat(el_str_concat(EL_STR("{\"error\":\"plugin '"), json_escape_str(name)), EL_STR("' not found\"}")); + } + if (str_eq(name, EL_STR("el-theme-dark"))) { + return el_str_concat(el_str_concat(EL_STR("{\"error\":\"plugin '"), json_escape_str(name)), EL_STR("' cannot be removed: it is a required built-in\"}")); + } + put_bool(name, EL_STR("installed"), 0); + put_bool(name, EL_STR("enabled"), 0); + return EL_STR("{\"ok\":true}"); + return 0; +} + +el_val_t plugin_enable(el_val_t name) { + plugin_init(); + if (!index_contains(name)) { + return el_str_concat(el_str_concat(EL_STR("{\"error\":\"plugin '"), json_escape_str(name)), EL_STR("' not found\"}")); + } + put_bool(name, EL_STR("enabled"), 1); + return EL_STR("{\"ok\":true}"); + return 0; +} + +el_val_t plugin_disable(el_val_t name) { + plugin_init(); + if (!index_contains(name)) { + return el_str_concat(el_str_concat(EL_STR("{\"error\":\"plugin '"), json_escape_str(name)), EL_STR("' not found\"}")); + } + put_bool(name, EL_STR("enabled"), 0); + return EL_STR("{\"ok\":true}"); + return 0; +} + +el_val_t host_main(void) { + el_val_t argv = args(); + el_val_t n = native_list_len(argv); + if (n == 0) { + println(plugin_list_json()); + return 0; + } + el_val_t cmd = native_list_get(argv, 0); + if (str_eq(cmd, EL_STR("list"))) { + println(plugin_list_json()); + return 0; + } + if (str_eq(cmd, EL_STR("get"))) { + if (n >= 2) { + println(plugin_get_json(native_list_get(argv, 1))); + } + return 0; + } + if (str_eq(cmd, EL_STR("install"))) { + if (n >= 2) { + println(plugin_install(native_list_get(argv, 1))); + } + return 0; + } + if (str_eq(cmd, EL_STR("remove"))) { + if (n >= 2) { + println(plugin_remove(native_list_get(argv, 1))); + } + return 0; + } + if (str_eq(cmd, EL_STR("enable"))) { + if (n >= 2) { + println(plugin_enable(native_list_get(argv, 1))); + } + return 0; + } + if (str_eq(cmd, EL_STR("disable"))) { + if (n >= 2) { + println(plugin_disable(native_list_get(argv, 1))); + } + return 0; + } + println(EL_STR("usage: el-plugin-host [list|get|install|remove|enable|disable] ")); + return 0; +} + +el_val_t jstr(el_val_t s) { + el_val_t chars = native_string_chars(s); + el_val_t n = native_list_len(chars); + el_val_t out = EL_STR("\""); + el_val_t i = 0; + while (i < n) { + el_val_t ch = native_list_get(chars, i); + if (str_eq(ch, EL_STR("\""))) { + out = el_str_concat(out, EL_STR("\\\"")); + } else { + if (str_eq(ch, EL_STR("\\"))) { + out = el_str_concat(out, EL_STR("\\\\")); + } else { + if (str_eq(ch, EL_STR("\n"))) { + out = el_str_concat(out, EL_STR("\\n")); + } else { + if (str_eq(ch, EL_STR("\r"))) { + out = el_str_concat(out, EL_STR("\\r")); + } else { + if (str_eq(ch, EL_STR("\t"))) { + out = el_str_concat(out, EL_STR("\\t")); + } else { + out = el_str_concat(out, ch); + } + } + } + } + } + i = (i + 1); + } + return el_str_concat(out, EL_STR("\"")); + return 0; +} + +el_val_t jerr(el_val_t msg) { + return el_str_concat(el_str_concat(EL_STR("{\"error\":"), jstr(msg)), EL_STR("}")); + return 0; +} + +el_val_t ok_obj(void) { + return EL_STR("{\"ok\":true}"); + return 0; +} + +el_val_t url_decode(el_val_t s) { + el_val_t chars = native_string_chars(s); + el_val_t n = native_list_len(chars); + el_val_t out = EL_STR(""); + el_val_t i = 0; + while (i < n) { + el_val_t ch = native_list_get(chars, i); + if (str_eq(ch, EL_STR("+"))) { + out = el_str_concat(out, EL_STR(" ")); + i = (i + 1); + } else { + if (str_eq(ch, EL_STR("%"))) { + if ((i + 2) < n) { + el_val_t hex = el_str_concat(native_list_get(chars, (i + 1)), native_list_get(chars, (i + 2))); + el_val_t code = hex_to_int(hex); + out = el_str_concat(out, char_from_code(code)); + i = (i + 3); + } else { + out = el_str_concat(out, ch); + i = (i + 1); + } + } else { + out = el_str_concat(out, ch); + i = (i + 1); + } + } + } + return out; + return 0; +} + +el_val_t hex_digit(el_val_t ch) { + if (str_eq(ch, EL_STR("0"))) { + return 0; + } + if (str_eq(ch, EL_STR("1"))) { + return 1; + } + if (str_eq(ch, EL_STR("2"))) { + return 2; + } + if (str_eq(ch, EL_STR("3"))) { + return 3; + } + if (str_eq(ch, EL_STR("4"))) { + return 4; + } + if (str_eq(ch, EL_STR("5"))) { + return 5; + } + if (str_eq(ch, EL_STR("6"))) { + return 6; + } + if (str_eq(ch, EL_STR("7"))) { + return 7; + } + if (str_eq(ch, EL_STR("8"))) { + return 8; + } + if (str_eq(ch, EL_STR("9"))) { + return 9; + } + if (str_eq(ch, EL_STR("a"))) { + return 10; + } + if (str_eq(ch, EL_STR("A"))) { + return 10; + } + if (str_eq(ch, EL_STR("b"))) { + return 11; + } + if (str_eq(ch, EL_STR("B"))) { + return 11; + } + if (str_eq(ch, EL_STR("c"))) { + return 12; + } + if (str_eq(ch, EL_STR("C"))) { + return 12; + } + if (str_eq(ch, EL_STR("d"))) { + return 13; + } + if (str_eq(ch, EL_STR("D"))) { + return 13; + } + if (str_eq(ch, EL_STR("e"))) { + return 14; + } + if (str_eq(ch, EL_STR("E"))) { + return 14; + } + if (str_eq(ch, EL_STR("f"))) { + return 15; + } + return (/* if-expr */ ((str_eq(ch, EL_STR("F"))) ? (el_val_t)1 : (el_val_t)0) - 1); + return 0; +} + +el_val_t hex_to_int(el_val_t hex) { + el_val_t chars = native_string_chars(hex); + el_val_t n = native_list_len(chars); + el_val_t acc = 0; + el_val_t i = 0; + while (i < n) { + el_val_t d = hex_digit(native_list_get(chars, i)); + if (d < 0) { + return acc; + } + acc = el_str_concat((acc * 16), d); + i = (i + 1); + } + return acc; + return 0; +} + +el_val_t char_from_code(el_val_t code) { + el_val_t table = EL_STR(" !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"); + if (code < 32) { + return EL_STR(" "); + } + if (code > 126) { + return EL_STR("?"); + } + return str_slice(table, (code - 32), (code - 31)); + return 0; +} + +el_val_t split_path_query(el_val_t path) { + el_val_t q = str_index_of(path, EL_STR("?")); + if (q < 0) { + return el_map_new(2, "path", path, "query", EL_STR("")); + } + return el_map_new(2, "path", str_slice(path, 0, q), "query", str_slice(path, (q + 1), str_len(path))); + return 0; +} + +el_val_t query_get(el_val_t query, el_val_t key) { + if (str_eq(query, EL_STR(""))) { + return EL_STR(""); + } + el_val_t pairs = str_split(query, EL_STR("&")); + el_val_t n = native_list_len(pairs); + el_val_t prefix = el_str_concat(key, EL_STR("=")); + el_val_t i = 0; + while (i < n) { + el_val_t pair = native_list_get(pairs, i); + if (str_starts_with(pair, prefix)) { + return url_decode(str_slice(pair, str_len(prefix), str_len(pair))); + } + if (str_eq(pair, key)) { + return EL_STR(""); + } + i = (i + 1); + } + return EL_STR(""); + return 0; +} + +el_val_t cfg_port(void) { + el_val_t p = env(EL_STR("EL_IDE_PORT")); + if (str_eq(p, EL_STR(""))) { + return 7771; + } + return str_to_int(p); + return 0; +} + +el_val_t cfg_project_path(void) { + el_val_t p = env(EL_STR("EL_IDE_PROJECT_PATH")); + if (str_eq(p, EL_STR(""))) { + return EL_STR("."); + } + return p; + return 0; +} + +el_val_t cfg_engram_url(void) { + el_val_t u = env(EL_STR("EL_ENGRAM_URL")); + if (str_eq(u, EL_STR(""))) { + return EL_STR("http://localhost:8742"); + } + return u; + return 0; +} + +el_val_t cfg_el_binary(void) { + el_val_t b = env(EL_STR("EL_BINARY")); + if (str_eq(b, EL_STR(""))) { + return EL_STR("el"); + } + return b; + return 0; +} + +el_val_t safe_join(el_val_t rel) { + el_val_t root = cfg_project_path(); + if (str_contains(rel, EL_STR(".."))) { + return EL_STR(""); + } + if (str_starts_with(rel, EL_STR("/"))) { + return EL_STR(""); + } + if (str_eq(rel, EL_STR("."))) { + return root; + } + return el_str_concat(el_str_concat(root, EL_STR("/")), rel); + return 0; +} + +el_val_t route_status(void) { + el_val_t parts = native_list_empty(); + parts = native_list_append(parts, el_str_concat(EL_STR("\"project_name\":"), jstr(cfg_project_path()))); + parts = native_list_append(parts, el_str_concat(EL_STR("\"project_path\":"), jstr(cfg_project_path()))); + parts = native_list_append(parts, el_str_concat(EL_STR("\"version\":"), jstr(EL_STR("0.1.0")))); + parts = native_list_append(parts, el_str_concat(EL_STR("\"engine\":"), jstr(EL_STR("el-ide")))); + return el_str_concat(el_str_concat(EL_STR("{"), list_join(parts, EL_STR(","))), EL_STR("}")); + return 0; +} + +el_val_t route_config(void) { + el_val_t parts = native_list_empty(); + parts = native_list_append(parts, el_str_concat(EL_STR("\"port\":"), int_to_str(cfg_port()))); + parts = native_list_append(parts, el_str_concat(EL_STR("\"project_path\":"), jstr(cfg_project_path()))); + parts = native_list_append(parts, el_str_concat(EL_STR("\"engram_url\":"), jstr(cfg_engram_url()))); + parts = native_list_append(parts, el_str_concat(EL_STR("\"el_binary\":"), jstr(cfg_el_binary()))); + return el_str_concat(el_str_concat(EL_STR("{"), list_join(parts, EL_STR(","))), EL_STR("}")); + return 0; +} + +el_val_t route_files_list(el_val_t query) { + el_val_t rel = query_get(query, EL_STR("path")); + if (str_eq(rel, EL_STR(""))) { + rel = EL_STR("."); + } + el_val_t target = safe_join(rel); + if (str_eq(EL_NULL, EL_STR(""))) { + return jerr(EL_STR("path escapes project root")); + } + el_val_t entries = fs_list(EL_NULL); + el_val_t n = native_list_len(entries); + el_val_t out = EL_STR("["); + el_val_t i = 0; + while (i < n) { + el_val_t name = native_list_get(entries, i); + el_val_t skip = 0; + if (str_starts_with(name, EL_STR("."))) { + skip = 1; + } + if (str_eq(name, EL_STR("target"))) { + skip = 1; + } + if (str_eq(name, EL_STR("node_modules"))) { + skip = 1; + } + if (str_eq(name, EL_STR("dist"))) { + skip = 1; + } + if (!skip) { + if (i > 0) { + if (!str_eq(out, EL_STR("["))) { + out = el_str_concat(out, EL_STR(",")); + } + } + el_val_t dot = str_index_of(name, EL_STR(".")); + el_val_t is_dir = EL_STR("false"); + if (dot < 0) { + is_dir = EL_STR("true"); + } + out = el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(out, EL_STR("{\"name\":")), jstr(name)), EL_STR(",\"path\":")), jstr(el_str_concat(el_str_concat(rel, EL_STR("/")), name))), EL_STR(",\"is_dir\":")), is_dir), EL_STR(",\"children\":null}")); + } + i = (i + 1); + } + return el_str_concat(out, EL_STR("]")); + return 0; +} + +el_val_t route_file_read(el_val_t query) { + el_val_t rel = query_get(query, EL_STR("path")); + if (str_eq(rel, EL_STR(""))) { + return jerr(EL_STR("missing path parameter")); + } + el_val_t target = safe_join(rel); + if (str_eq(EL_NULL, EL_STR(""))) { + return jerr(EL_STR("path escapes project root")); + } + el_val_t content = fs_read(EL_NULL); + return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"path\":"), jstr(rel)), EL_STR(",\"content\":")), jstr(content)), EL_STR("}")); + return 0; +} + +el_val_t route_file_write(el_val_t body) { + el_val_t rel = json_get_string(body, EL_STR("path")); + el_val_t content = json_get_string(body, EL_STR("content")); + if (str_eq(rel, EL_STR(""))) { + return jerr(EL_STR("missing path")); + } + el_val_t target = safe_join(rel); + if (str_eq(EL_NULL, EL_STR(""))) { + return jerr(EL_STR("path escapes project root")); + } + el_val_t ok = fs_write(EL_NULL, content); + if (ok) { + return ok_obj(); + } + return jerr(EL_STR("cannot write file")); + return 0; +} + +el_val_t route_lsp_complete(el_val_t query) { + el_val_t source = query_get(query, EL_STR("source")); + el_val_t pos = str_to_int(query_get(query, EL_STR("pos"))); + return lsp_complete(source, pos); + return 0; +} + +el_val_t route_lsp_hover(el_val_t query) { + el_val_t source = query_get(query, EL_STR("source")); + el_val_t pos = str_to_int(query_get(query, EL_STR("pos"))); + return lsp_hover(source, pos); + return 0; +} + +el_val_t route_lsp_errors(el_val_t query) { + el_val_t source = query_get(query, EL_STR("source")); + return lsp_diagnostics(source); + return 0; +} + +el_val_t route_lsp_jsonrpc(el_val_t body) { + el_val_t method = json_get_string(body, EL_STR("method")); + el_val_t params_raw = json_get_raw(body, EL_STR("params")); + el_val_t id_val = json_get_raw(body, EL_STR("id")); + if (str_eq(id_val, EL_STR(""))) { + id_val = EL_STR("null"); + } + el_val_t result = lsp_jsonrpc(method, params_raw); + return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"jsonrpc\":\"2.0\",\"id\":"), id_val), EL_STR(",\"result\":")), result), EL_STR("}")); + return 0; +} + +el_val_t route_outline(el_val_t query) { + el_val_t source = query_get(query, EL_STR("source")); + return lsp_outline(source); + return 0; +} + +el_val_t route_definition(el_val_t query) { + el_val_t source = query_get(query, EL_STR("source")); + el_val_t pos = str_to_int(query_get(query, EL_STR("pos"))); + return lsp_definition(source, pos); + return 0; +} + +el_val_t route_references(el_val_t query) { + el_val_t source = query_get(query, EL_STR("source")); + el_val_t pos = str_to_int(query_get(query, EL_STR("pos"))); + return lsp_references(source, pos); + return 0; +} + +el_val_t route_format(el_val_t body) { + el_val_t content = json_get_string(body, EL_STR("content")); + return lsp_format(content); + return 0; +} + +el_val_t route_type_graph(el_val_t query) { + el_val_t source = query_get(query, EL_STR("source")); + return lsp_type_graph(source); + return 0; +} + +el_val_t active_theme(void) { + el_val_t t = state_get(EL_STR("ide/active_theme")); + if (str_eq(t, EL_STR(""))) { + return EL_STR("dark"); + } + return t; + return 0; +} + +el_val_t route_themes_list(void) { + el_val_t active = active_theme(); + el_val_t names = native_list_empty(); + names = native_list_append(names, EL_STR("dark")); + names = native_list_append(names, EL_STR("light")); + names = native_list_append(names, EL_STR("neuron")); + names = native_list_append(names, EL_STR("high-contrast")); + el_val_t labels = native_list_empty(); + labels = native_list_append(labels, EL_STR("Dark")); + labels = native_list_append(labels, EL_STR("Light")); + labels = native_list_append(labels, EL_STR("Neuron")); + labels = native_list_append(labels, EL_STR("High Contrast")); + el_val_t n = native_list_len(names); + el_val_t out = EL_STR("["); + el_val_t i = 0; + while (i < n) { + if (i > 0) { + out = el_str_concat(out, EL_STR(",")); + } + el_val_t nm = native_list_get(names, i); + el_val_t lbl = native_list_get(labels, i); + el_val_t act = EL_STR("false"); + if (str_eq(nm, active)) { + act = EL_STR("true"); + } + out = el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(out, EL_STR("{\"name\":")), jstr(nm)), EL_STR(",\"label\":")), jstr(lbl)), EL_STR(",\"active\":")), act), EL_STR("}")); + i = (i + 1); + } + return el_str_concat(out, EL_STR("]")); + return 0; +} + +el_val_t route_themes_set(el_val_t body) { + el_val_t name = json_get_string(body, EL_STR("name")); + el_val_t valid = 0; + if (str_eq(name, EL_STR("dark"))) { + valid = 1; + } + if (str_eq(name, EL_STR("light"))) { + valid = 1; + } + if (str_eq(name, EL_STR("neuron"))) { + valid = 1; + } + if (str_eq(name, EL_STR("high-contrast"))) { + valid = 1; + } + if (!valid) { + return jerr(el_str_concat(EL_STR("unknown theme: "), name)); + } + state_set(EL_STR("ide/active_theme"), name); + return el_str_concat(el_str_concat(EL_STR("{\"ok\":true,\"active\":"), jstr(name)), EL_STR("}")); + return 0; +} + +el_val_t route_plugins_list(void) { + return plugin_list_json(); + return 0; +} + +el_val_t route_plugins_install(el_val_t body) { + return plugin_install(json_get_string(body, EL_STR("name"))); + return 0; +} + +el_val_t route_plugins_remove(el_val_t body) { + return plugin_remove(json_get_string(body, EL_STR("name"))); + return 0; +} + +el_val_t route_plugins_enable(el_val_t body) { + return plugin_enable(json_get_string(body, EL_STR("name"))); + return 0; +} + +el_val_t route_plugins_disable(el_val_t body) { + return plugin_disable(json_get_string(body, EL_STR("name"))); + return 0; +} + +el_val_t route_snippets(void) { + el_val_t snips = native_list_empty(); + snips = native_list_append(snips, EL_STR("{\"label\":\"fn\",\"description\":\"Function definition\",\"body\":\"fn ${1:name}(${2:params}) -> ${3:Ret} {\\n\\t${4:body}\\n}\"}")); + snips = native_list_append(snips, EL_STR("{\"label\":\"type\",\"description\":\"Struct\",\"body\":\"type ${1:Name} {\\n\\t${2:field}: ${3:Type},\\n}\"}")); + snips = native_list_append(snips, EL_STR("{\"label\":\"enum\",\"description\":\"Enum\",\"body\":\"enum ${1:Name} {\\n\\t${2:Variant},\\n}\"}")); + snips = native_list_append(snips, EL_STR("{\"label\":\"match\",\"description\":\"Match expression\",\"body\":\"match ${1:expr} {\\n\\t${2:pat} => ${3:body},\\n\\t_ => ${4:default},\\n}\"}")); + snips = native_list_append(snips, EL_STR("{\"label\":\"let\",\"description\":\"Let binding\",\"body\":\"let ${1:name}: ${2:Type} = ${3:value}\"}")); + snips = native_list_append(snips, EL_STR("{\"label\":\"if\",\"description\":\"If expression\",\"body\":\"if ${1:cond} {\\n\\t${2:body}\\n}\"}")); + snips = native_list_append(snips, EL_STR("{\"label\":\"for\",\"description\":\"For loop\",\"body\":\"for ${1:item} in ${2:iter} {\\n\\t${3:body}\\n}\"}")); + snips = native_list_append(snips, EL_STR("{\"label\":\"activate\",\"description\":\"Activate\",\"body\":\"activate ${1:Type}\"}")); + return el_str_concat(el_str_concat(EL_STR("["), list_join(snips, EL_STR(","))), EL_STR("]")); + return 0; +} + +el_val_t settings_path(void) { + el_val_t home = env(EL_STR("HOME")); + if (str_eq(home, EL_STR(""))) { + home = EL_STR("/tmp"); + } + return el_str_concat(home, EL_STR("/.el-ide/settings.json")); + return 0; +} + +el_val_t default_settings_json(void) { + return EL_STR("{\"theme\":\"dark\",\"fontSize\":13,\"tabSize\":4,\"wordWrap\":false,\"formatOnSave\":false,\"vimMode\":false,\"minimap\":true,\"elBinaryPath\":\"el\",\"engramUrl\":\"http://localhost:8742\",\"stickyScroll\":true,\"lineNumbers\":true,\"bracketMatching\":true}"); + return 0; +} + +el_val_t route_settings_get(void) { + el_val_t s = fs_read(settings_path()); + if (str_eq(s, EL_STR(""))) { + return default_settings_json(); + } + return s; + return 0; +} + +el_val_t route_settings_save(el_val_t body) { + el_val_t blob = json_get_raw(body, EL_STR("settings")); + if (str_eq(blob, EL_STR(""))) { + return jerr(EL_STR("missing settings")); + } + fs_write(settings_path(), blob); + return blob; + return 0; +} + +el_val_t route_settings_reset(void) { + fs_write(settings_path(), default_settings_json()); + return default_settings_json(); + return 0; +} + +el_val_t route_build_or_run(el_val_t action, el_val_t body) { + el_val_t rel_file = json_get_string(body, EL_STR("file")); + if (str_eq(rel_file, EL_STR(""))) { + rel_file = EL_STR("src/main.el"); + } + el_val_t target = safe_join(rel_file); + if (str_eq(EL_NULL, EL_STR(""))) { + return jerr(EL_STR("path escapes project root")); + } + return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"event\":\"info\",\"action\":"), jstr(action)), EL_STR(",\"file\":")), jstr(rel_file)), EL_STR(",\"note\":\"el-ide-server: synchronous build requires a runtime exec primitive — el binary not invoked\"}")); + return 0; +} + +el_val_t route_build(el_val_t body) { + return route_build_or_run(EL_STR("build"), body); + return 0; +} + +el_val_t route_run(el_val_t body) { + return route_build_or_run(EL_STR("run"), body); + return 0; +} + +el_val_t route_reason(el_val_t body) { + el_val_t url = el_str_concat(cfg_engram_url(), EL_STR("/api/reason")); + el_val_t resp = http_post(url, body); + if (str_eq(resp, EL_STR(""))) { + return jerr(EL_STR("engram unreachable")); + } + return resp; + return 0; +} + +el_val_t route_activate_preview(el_val_t query) { + el_val_t type_name = query_get(query, EL_STR("type_name")); + el_val_t q = query_get(query, EL_STR("query")); + el_val_t url = el_str_concat(cfg_engram_url(), EL_STR("/api/activate-preview")); + el_val_t body = el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"type_name\":"), jstr(type_name)), EL_STR(",\"query\":")), jstr(q)), EL_STR(",\"limit\":5}")); + el_val_t resp = http_post(url, body); + if (str_eq(resp, EL_STR(""))) { + return EL_STR("{\"count\":0,\"nodes\":[],\"connected\":false}"); + } + return resp; + return 0; +} + +el_val_t route_index(void) { + el_val_t path = el_str_concat(cfg_project_path(), EL_STR("/ide/index.html")); + el_val_t html = fs_read(path); + if (!str_eq(html, EL_STR(""))) { + return html; + } + return el_str_concat(el_str_concat(EL_STR("el-ide

el-ide

Backend running. UI bundle missing at "), path), EL_STR(".

")); + return 0; +} + +el_val_t route_health(void) { + return EL_STR("{\"status\":\"ok\",\"engine\":\"el-ide-server\"}"); + return 0; +} + +el_val_t handle_request(el_val_t method, el_val_t path, el_val_t body) { + el_val_t parsed = split_path_query(path); + el_val_t route = el_get_field(parsed, EL_STR("path")); + el_val_t query = el_get_field(parsed, EL_STR("query")); + if (str_eq(route, EL_STR("/"))) { + return route_index(); + } + if (str_eq(route, EL_STR("/health"))) { + return route_health(); + } + if (str_eq(route, EL_STR("/api/status"))) { + return route_status(); + } + if (str_eq(route, EL_STR("/api/config"))) { + return route_config(); + } + if (str_eq(route, EL_STR("/api/files"))) { + return route_files_list(query); + } + if (str_eq(route, EL_STR("/api/file"))) { + if (str_eq(method, EL_STR("GET"))) { + return route_file_read(query); + } + if (str_eq(method, EL_STR("POST"))) { + return route_file_write(body); + } + } + if (str_eq(route, EL_STR("/api/search"))) { + el_val_t q = query_get(query, EL_STR("q")); + return el_str_concat(el_str_concat(EL_STR("{\"query\":"), jstr(q)), EL_STR(",\"results\":[]}")); + } + if (str_eq(route, EL_STR("/api/lsp/complete"))) { + return route_lsp_complete(query); + } + if (str_eq(route, EL_STR("/api/lsp/hover"))) { + return route_lsp_hover(query); + } + if (str_eq(route, EL_STR("/api/lsp/errors"))) { + return route_lsp_errors(query); + } + if (str_eq(route, EL_STR("/api/lsp/activate-preview"))) { + return route_activate_preview(query); + } + if (str_eq(route, EL_STR("/api/lsp/jsonrpc"))) { + return route_lsp_jsonrpc(body); + } + if (str_eq(route, EL_STR("/api/type-graph"))) { + return route_type_graph(query); + } + if (str_eq(route, EL_STR("/api/outline"))) { + return route_outline(query); + } + if (str_eq(route, EL_STR("/api/definition"))) { + return route_definition(query); + } + if (str_eq(route, EL_STR("/api/references"))) { + return route_references(query); + } + if (str_eq(route, EL_STR("/api/format"))) { + return route_format(body); + } + if (str_eq(route, EL_STR("/api/completions/snippet"))) { + return route_snippets(); + } + if (str_eq(route, EL_STR("/api/themes"))) { + return route_themes_list(); + } + if (str_eq(route, EL_STR("/api/themes/active"))) { + return route_themes_set(body); + } + if (str_eq(route, EL_STR("/api/plugins"))) { + return route_plugins_list(); + } + if (str_eq(route, EL_STR("/api/plugins/install"))) { + return route_plugins_install(body); + } + if (str_eq(route, EL_STR("/api/plugins/remove"))) { + return route_plugins_remove(body); + } + if (str_eq(route, EL_STR("/api/plugins/enable"))) { + return route_plugins_enable(body); + } + if (str_eq(route, EL_STR("/api/plugins/disable"))) { + return route_plugins_disable(body); + } + if (str_eq(route, EL_STR("/api/settings"))) { + if (str_eq(method, EL_STR("GET"))) { + return route_settings_get(); + } + if (str_eq(method, EL_STR("POST"))) { + return route_settings_save(body); + } + if (str_eq(method, EL_STR("DELETE"))) { + return route_settings_reset(); + } + } + if (str_eq(route, EL_STR("/api/build"))) { + return route_build(body); + } + if (str_eq(route, EL_STR("/api/run"))) { + return route_run(body); + } + if (str_eq(route, EL_STR("/api/reason"))) { + return route_reason(body); + } + if (str_eq(route, EL_STR("/api/git/status"))) { + return EL_STR("[]"); + } + if (str_eq(route, EL_STR("/api/git/diff"))) { + return EL_STR("\"\""); + } + return el_str_concat(el_str_concat(EL_STR("{\"error\":\"not found\",\"path\":"), jstr(route)), EL_STR("}")); + return 0; +} + +el_val_t server_main(void) { + plugin_init(); + el_val_t port = cfg_port(); + println(el_str_concat(EL_STR("[el-ide-server] project="), cfg_project_path())); + println(el_str_concat(EL_STR("[el-ide-server] engram="), cfg_engram_url())); + println(el_str_concat(EL_STR("[el-ide-server] listening on http://0.0.0.0:"), int_to_str(port))); + http_set_handler(EL_STR("handle_request")); + http_serve(port, EL_STR("handle_request")); + return 0; +} + +int main(int argc, char** argv) { + el_runtime_init_args(argc, argv); + server_main(); + return 0; +} + diff --git a/ide/vessels/el-ide-server/src/_combined.el b/ide/vessels/el-ide-server/src/_combined.el new file mode 100644 index 0000000..fc78f70 --- /dev/null +++ b/ide/vessels/el-ide-server/src/_combined.el @@ -0,0 +1,2056 @@ +// main.el — el-lsp +// +// Language Server for El. Pure-El port of the el-lsp Rust crate. +// +// Entry surface (callable from any El program that imports this file): +// +// lsp_complete(source: String, pos: Int) -> String // JSON array +// lsp_hover(source: String, pos: Int) -> String // JSON object or "null" +// lsp_diagnostics(source: String) -> String // JSON array +// lsp_outline(source: String) -> String // JSON array +// lsp_format(source: String) -> String // JSON { content, changed } +// lsp_type_graph(source: String) -> String // JSON { nodes, edges } +// lsp_definition(source: String, pos: Int) -> String // JSON object or "null" +// lsp_references(source: String, pos: Int) -> String // JSON array +// lsp_jsonrpc(method: String, params_json: String) -> String +// lsp_stdio_loop() -> Void +// +// Tokenisation reuses the lexer.el idiom (chars list + index walk) for the +// pieces we need (identifier scan, string scan, line counting). The full +// type checker referenced by the Rust crate is not yet available in El, so +// hover/completion/diagnostics fall back to source-scan heuristics over the +// declared types/enums/functions in the file. The wire shape is preserved. + +// ── Char helpers (mirrors lexer.el) ────────────────────────────────────────── + +fn is_digit_ch(ch: String) -> Bool { + if ch == "0" { return true } if ch == "1" { return true } + if ch == "2" { return true } if ch == "3" { return true } + if ch == "4" { return true } if ch == "5" { return true } + if ch == "6" { return true } if ch == "7" { return true } + if ch == "8" { return true } if ch == "9" { return true } + false +} + +fn is_alpha_ch(ch: String) -> Bool { + let lower: String = str_to_lower(ch) + if str_eq(ch, "") { return false } + if !str_eq(lower, str_to_upper(lower)) { return true } // letters differ in case + // covers a-z (lower-only) — uppercase already handled by inverse case test above + if str_contains("abcdefghijklmnopqrstuvwxyz", ch) { return true } + if str_contains("ABCDEFGHIJKLMNOPQRSTUVWXYZ", ch) { return true } + false +} + +fn is_ident_ch(ch: String) -> Bool { + if is_digit_ch(ch) { return true } + if is_alpha_ch(ch) { return true } + if ch == "_" { return true } + false +} + +// ── Source navigation ──────────────────────────────────────────────────────── + +// Extract the identifier fragment immediately before `pos` (cursor). +fn extract_prefix(source: String, pos: Int) -> String { + let n: Int = str_len(source) + let end: Int = pos + if end > n { let end = n } + let start: Int = end + let chars: [String] = native_string_chars(source) + let total: Int = native_list_len(chars) + let scanning: Bool = true + while scanning { + if start <= 0 { + let scanning = false + } else { + let prev: String = native_list_get(chars, start - 1) + if is_ident_ch(prev) { + let start = start - 1 + } else { + let scanning = false + } + } + } + str_slice(source, start, end) +} + +// Extract the full token (alphanumerics + underscore) surrounding `pos`. +fn extract_token(source: String, pos: Int) -> String { + let n: Int = str_len(source) + if pos > n { return "" } + let chars: [String] = native_string_chars(source) + let total: Int = native_list_len(chars) + let start: Int = pos + let go_left: Bool = true + while go_left { + if start <= 0 { + let go_left = false + } else { + let prev: String = native_list_get(chars, start - 1) + if is_ident_ch(prev) { + let start = start - 1 + } else { + let go_left = false + } + } + } + let end: Int = pos + let go_right: Bool = true + while go_right { + if end >= total { + let go_right = false + } else { + let cur: String = native_list_get(chars, end) + if is_ident_ch(cur) { + let end = end + 1 + } else { + let go_right = false + } + } + } + str_slice(source, start, end) +} + +// Translate a byte offset into 1-based (line, col). +fn pos_to_line_col(source: String, pos: Int) -> Map { + let n: Int = str_len(source) + let cap: Int = pos + if cap > n { let cap = n } + let chars: [String] = native_string_chars(source) + let i: Int = 0 + let line: Int = 1 + let col: Int = 1 + while i < cap { + let ch: String = native_list_get(chars, i) + if ch == "\n" { + let line = line + 1 + let col = 1 + } else { + let col = col + 1 + } + let i = i + 1 + } + { "line": line, "col": col } +} + +// ── JSON encoding helpers ──────────────────────────────────────────────────── + +// Escape a string for JSON. Handles ", \, newline, tab. +fn json_escape(s: String) -> String { + let chars: [String] = native_string_chars(s) + let n: Int = native_list_len(chars) + let out: String = "" + let i: Int = 0 + while i < n { + let ch: String = native_list_get(chars, i) + if ch == "\"" { let out = out + "\\\"" } + else { if ch == "\\" { let out = out + "\\\\" } + else { if ch == "\n" { let out = out + "\\n" } + else { if ch == "\r" { let out = out + "\\r" } + else { if ch == "\t" { let out = out + "\\t" } + else { let out = out + ch } } } } } + let i = i + 1 + } + out +} + +fn json_str(s: String) -> String { + "\"" + json_escape(s) + "\"" +} + +fn json_kv_str(k: String, v: String) -> String { + json_str(k) + ":" + json_str(v) +} + +fn json_kv_int(k: String, v: Int) -> String { + json_str(k) + ":" + int_to_str(v) +} + +fn json_kv_float(k: String, v: Float) -> String { + json_str(k) + ":" + float_to_str(v) +} + +fn json_kv_raw(k: String, raw_v: String) -> String { + json_str(k) + ":" + raw_v +} + +// Join a list of pre-encoded JSON strings into a JSON array. +fn json_array_of(items: [String]) -> String { + let n: Int = native_list_len(items) + let out: String = "[" + let i: Int = 0 + while i < n { + if i > 0 { let out = out + "," } + let out = out + native_list_get(items, i) + let i = i + 1 + } + out + "]" +} + +// ── Keyword/builtin tables ─────────────────────────────────────────────────── + +fn keywords_list() -> [String] { + let ks: [String] = native_list_empty() + let ks = native_list_append(ks, "let") + let ks = native_list_append(ks, "fn") + let ks = native_list_append(ks, "type") + let ks = native_list_append(ks, "enum") + let ks = native_list_append(ks, "match") + let ks = native_list_append(ks, "return") + let ks = native_list_append(ks, "activate") + let ks = native_list_append(ks, "where") + let ks = native_list_append(ks, "sealed") + let ks = native_list_append(ks, "if") + let ks = native_list_append(ks, "else") + let ks = native_list_append(ks, "for") + let ks = native_list_append(ks, "in") + let ks = native_list_append(ks, "while") + let ks = native_list_append(ks, "true") + let ks = native_list_append(ks, "false") + let ks = native_list_append(ks, "test") + let ks = native_list_append(ks, "seed") + let ks = native_list_append(ks, "assert") + let ks = native_list_append(ks, "target") + let ks = native_list_append(ks, "protocol") + let ks = native_list_append(ks, "impl") + let ks = native_list_append(ks, "import") + let ks = native_list_append(ks, "from") + let ks = native_list_append(ks, "as") + let ks = native_list_append(ks, "with") + let ks = native_list_append(ks, "retry") + let ks = native_list_append(ks, "times") + let ks = native_list_append(ks, "fallback") + let ks = native_list_append(ks, "reason") + let ks = native_list_append(ks, "parallel") + let ks = native_list_append(ks, "trace") + let ks = native_list_append(ks, "requires") + let ks = native_list_append(ks, "deploy") + let ks = native_list_append(ks, "to") + let ks = native_list_append(ks, "via") + let ks = native_list_append(ks, "vessel") + let ks = native_list_append(ks, "cgi") + ks +} + +// Built-in primitive type names. +fn builtin_type_names() -> [String] { + let ts: [String] = native_list_empty() + let ts = native_list_append(ts, "Int") + let ts = native_list_append(ts, "Float") + let ts = native_list_append(ts, "String") + let ts = native_list_append(ts, "Bool") + let ts = native_list_append(ts, "Uuid") + let ts = native_list_append(ts, "Void") + let ts = native_list_append(ts, "Any") + ts +} + +fn builtin_type_doc(name: String) -> String { + if str_eq(name, "Int") { return "64-bit signed integer" } + if str_eq(name, "Float") { return "64-bit IEEE 754 double" } + if str_eq(name, "String") { return "UTF-8 string" } + if str_eq(name, "Bool") { return "Boolean value" } + if str_eq(name, "Uuid") { return "RFC 4122 UUID" } + if str_eq(name, "Void") { return "Unit type — no value" } + if str_eq(name, "Any") { return "Dynamically-typed value" } + "" +} + +// Built-in function names → signatures. Encoded as flat [name, sig, name, sig, ...] +// to keep type maps simple. +fn builtin_fns() -> [String] { + let xs: [String] = native_list_empty() + let xs = native_list_append(xs, "println") let xs = native_list_append(xs, "fn(value: String) -> Void") + let xs = native_list_append(xs, "print") let xs = native_list_append(xs, "fn(value: String) -> Void") + let xs = native_list_append(xs, "readline") let xs = native_list_append(xs, "fn() -> String") + let xs = native_list_append(xs, "args") let xs = native_list_append(xs, "fn() -> [String]") + let xs = native_list_append(xs, "int_to_str") let xs = native_list_append(xs, "fn(n: Int) -> String") + let xs = native_list_append(xs, "str_to_int") let xs = native_list_append(xs, "fn(s: String) -> Int") + let xs = native_list_append(xs, "str_len") let xs = native_list_append(xs, "fn(s: String) -> Int") + let xs = native_list_append(xs, "str_slice") let xs = native_list_append(xs, "fn(s: String, start: Int, end: Int) -> String") + let xs = native_list_append(xs, "str_concat") let xs = native_list_append(xs, "fn(a: String, b: String) -> String") + let xs = native_list_append(xs, "str_contains") let xs = native_list_append(xs, "fn(s: String, sub: String) -> Bool") + let xs = native_list_append(xs, "str_starts_with") let xs = native_list_append(xs, "fn(s: String, p: String) -> Bool") + let xs = native_list_append(xs, "str_ends_with") let xs = native_list_append(xs, "fn(s: String, suf: String) -> Bool") + let xs = native_list_append(xs, "str_to_upper") let xs = native_list_append(xs, "fn(s: String) -> String") + let xs = native_list_append(xs, "str_to_lower") let xs = native_list_append(xs, "fn(s: String) -> String") + let xs = native_list_append(xs, "str_split") let xs = native_list_append(xs, "fn(s: String, sep: String) -> [String]") + let xs = native_list_append(xs, "str_trim") let xs = native_list_append(xs, "fn(s: String) -> String") + let xs = native_list_append(xs, "str_replace") let xs = native_list_append(xs, "fn(s: String, from: String, to: String) -> String") + let xs = native_list_append(xs, "str_index_of") let xs = native_list_append(xs, "fn(s: String, sub: String) -> Int") + let xs = native_list_append(xs, "float_to_str") let xs = native_list_append(xs, "fn(f: Float) -> String") + let xs = native_list_append(xs, "str_to_float") let xs = native_list_append(xs, "fn(s: String) -> Float") + let xs = native_list_append(xs, "math_sqrt") let xs = native_list_append(xs, "fn(n: Float) -> Float") + let xs = native_list_append(xs, "math_log") let xs = native_list_append(xs, "fn(n: Float) -> Float") + let xs = native_list_append(xs, "math_sin") let xs = native_list_append(xs, "fn(n: Float) -> Float") + let xs = native_list_append(xs, "math_cos") let xs = native_list_append(xs, "fn(n: Float) -> Float") + let xs = native_list_append(xs, "math_pi") let xs = native_list_append(xs, "fn() -> Float") + let xs = native_list_append(xs, "el_abs") let xs = native_list_append(xs, "fn(n: Int) -> Int") + let xs = native_list_append(xs, "el_min") let xs = native_list_append(xs, "fn(a: Int, b: Int) -> Int") + let xs = native_list_append(xs, "el_max") let xs = native_list_append(xs, "fn(a: Int, b: Int) -> Int") + let xs = native_list_append(xs, "el_list_empty") let xs = native_list_append(xs, "fn() -> [Any]") + let xs = native_list_append(xs, "el_list_len") let xs = native_list_append(xs, "fn(l: [Any]) -> Int") + let xs = native_list_append(xs, "el_list_get") let xs = native_list_append(xs, "fn(l: [Any], i: Int) -> Any") + let xs = native_list_append(xs, "el_list_append") let xs = native_list_append(xs, "fn(l: [Any], v: Any) -> [Any]") + let xs = native_list_append(xs, "list_join") let xs = native_list_append(xs, "fn(l: [String], sep: String) -> String") + let xs = native_list_append(xs, "list_range") let xs = native_list_append(xs, "fn(start: Int, end: Int) -> [Int]") + let xs = native_list_append(xs, "el_map_get") let xs = native_list_append(xs, "fn(m: Map, k: String) -> Any") + let xs = native_list_append(xs, "el_map_set") let xs = native_list_append(xs, "fn(m: Map, k: String, v: Any) -> Map") + let xs = native_list_append(xs, "json_parse") let xs = native_list_append(xs, "fn(s: String) -> Any") + let xs = native_list_append(xs, "json_stringify") let xs = native_list_append(xs, "fn(v: Any) -> String") + let xs = native_list_append(xs, "json_get_string") let xs = native_list_append(xs, "fn(j: String, k: String) -> String") + let xs = native_list_append(xs, "json_get_int") let xs = native_list_append(xs, "fn(j: String, k: String) -> Int") + let xs = native_list_append(xs, "json_get_bool") let xs = native_list_append(xs, "fn(j: String, k: String) -> Bool") + let xs = native_list_append(xs, "http_get") let xs = native_list_append(xs, "fn(url: String) -> String") + let xs = native_list_append(xs, "http_post") let xs = native_list_append(xs, "fn(url: String, body: String) -> String") + let xs = native_list_append(xs, "fs_read") let xs = native_list_append(xs, "fn(path: String) -> String") + let xs = native_list_append(xs, "fs_write") let xs = native_list_append(xs, "fn(path: String, content: String) -> Bool") + let xs = native_list_append(xs, "fs_list") let xs = native_list_append(xs, "fn(path: String) -> [String]") + let xs = native_list_append(xs, "env") let xs = native_list_append(xs, "fn(key: String) -> String") + let xs = native_list_append(xs, "uuid_new") let xs = native_list_append(xs, "fn() -> String") + let xs = native_list_append(xs, "time_now") let xs = native_list_append(xs, "fn() -> Int") + let xs = native_list_append(xs, "time_now_utc") let xs = native_list_append(xs, "fn() -> Int") + let xs = native_list_append(xs, "sleep_ms") let xs = native_list_append(xs, "fn(ms: Int) -> Void") + let xs = native_list_append(xs, "engram_node") let xs = native_list_append(xs, "fn(content: String, kind: String, salience: Float) -> String") + let xs = native_list_append(xs, "engram_search") let xs = native_list_append(xs, "fn(q: String, limit: Int) -> [Map]") + let xs = native_list_append(xs, "engram_activate") let xs = native_list_append(xs, "fn(q: String, depth: Int) -> [Map]") + let xs = native_list_append(xs, "engram_neighbors") let xs = native_list_append(xs, "fn(id: String) -> [Map]") + let xs = native_list_append(xs, "engram_connect") let xs = native_list_append(xs, "fn(from: String, to: String, w: Float, rel: String) -> Void") + let xs = native_list_append(xs, "dharma_connect") let xs = native_list_append(xs, "fn(cgi: String) -> String") + let xs = native_list_append(xs, "dharma_send") let xs = native_list_append(xs, "fn(channel: String, content: String) -> String") + let xs = native_list_append(xs, "dharma_emit") let xs = native_list_append(xs, "fn(event: String, payload: String) -> Void") + let xs = native_list_append(xs, "dharma_field") let xs = native_list_append(xs, "fn(event: String) -> Map") + let xs = native_list_append(xs, "llm_call") let xs = native_list_append(xs, "fn(model: String, prompt: String) -> String") + xs +} + +fn keyword_doc(kw: String) -> String { + if str_eq(kw, "let") { return "let name: Type = expr — declare an immutable binding." } + if str_eq(kw, "fn") { return "fn name(params) -> Ret { body } — define a function." } + if str_eq(kw, "type") { return "type Name { field: Type } — struct definition." } + if str_eq(kw, "enum") { return "enum Name { Variant1, Variant2(Type) } — enum definition." } + if str_eq(kw, "match") { return "match expr { Pattern => body } — pattern match." } + if str_eq(kw, "return") { return "return value — exit the enclosing function." } + if str_eq(kw, "if") { return "if cond { ... } else { ... } — conditional." } + if str_eq(kw, "for") { return "for item in collection { ... } — iterate." } + if str_eq(kw, "while") { return "while cond { ... } — loop while cond is truthy." } + if str_eq(kw, "import") { return "import \"path.el\" — pull in another module." } + if str_eq(kw, "from") { return "from module import { Name } — selective import." } + if str_eq(kw, "vessel") { return "vessel \"name\" { ... } — manifest declaration." } + if str_eq(kw, "cgi") { return "cgi \"name\" { dharma_id: ... } — CGI identity." } + if str_eq(kw, "activate") { return "activate Type where \"query\" — spreading-activation retrieval." } + if str_eq(kw, "sealed") { return "sealed { ... } — capability-restricted block." } + if str_eq(kw, "protocol") { return "protocol Name { fn method(self) -> R } — trait-like." } + if str_eq(kw, "impl") { return "impl Protocol for Type { ... } — protocol implementation." } + if str_eq(kw, "with") { return "with retry/fallback clause." } + if str_eq(kw, "retry") { return "retry times N — retry policy." } + if str_eq(kw, "fallback") { return "fallback { default } — fallback on failure." } + if str_eq(kw, "true") { return "Boolean literal." } + if str_eq(kw, "false") { return "Boolean literal." } + "" +} + +// ── Source-driven type/fn discovery (no full parser) ───────────────────────── +// +// The Rust crate calls into el-types::TypeChecker for a real env. That +// module isn't available in El yet, so we approximate by line-scan: find +// every `type X {`, `enum X {`, `protocol X {`, and `fn X(` declaration. +// Returns four parallel lists merged into one map for easy access. + +fn first_ident_in(rest: String) -> String { + let trimmed: String = str_trim(rest) + let n: Int = str_len(trimmed) + if n == 0 { return "" } + let chars: [String] = native_string_chars(trimmed) + let i: Int = 0 + let total: Int = native_list_len(chars) + while i < total { + let ch: String = native_list_get(chars, i) + if !is_ident_ch(ch) { + return str_slice(trimmed, 0, i) + } + let i = i + 1 + } + trimmed +} + +// scan_decls — produce a Map with parallel lists: +// "types" : [String] user-defined struct/enum/protocol names +// "type_kind" : [String] "type" | "enum" | "protocol" matching above +// "fns" : [String] user-defined function names +// "type_lines" : [Int] 1-based line numbers +// "fn_lines" : [Int] +fn scan_decls(source: String) -> Map { + let lines: [String] = str_split(source, "\n") + let n: Int = native_list_len(lines) + let types: [String] = native_list_empty() + let kinds: [String] = native_list_empty() + let fns: [String] = native_list_empty() + let tlines: [Int] = native_list_empty() + let flines: [Int] = native_list_empty() + let i: Int = 0 + while i < n { + let line: String = native_list_get(lines, i) + let trimmed: String = str_trim(line) + let lineno: Int = i + 1 + if str_starts_with(trimmed, "fn ") { + let name: String = first_ident_in(str_slice(trimmed, 3, str_len(trimmed))) + if !str_eq(name, "") { + let fns = native_list_append(fns, name) + let flines = native_list_append(flines, lineno) + } + } else { if str_starts_with(trimmed, "type ") { + let name: String = first_ident_in(str_slice(trimmed, 5, str_len(trimmed))) + if !str_eq(name, "") { + let types = native_list_append(types, name) + let kinds = native_list_append(kinds, "type") + let tlines = native_list_append(tlines, lineno) + } + } else { if str_starts_with(trimmed, "enum ") { + let name: String = first_ident_in(str_slice(trimmed, 5, str_len(trimmed))) + if !str_eq(name, "") { + let types = native_list_append(types, name) + let kinds = native_list_append(kinds, "enum") + let tlines = native_list_append(tlines, lineno) + } + } else { if str_starts_with(trimmed, "protocol ") { + let name: String = first_ident_in(str_slice(trimmed, 9, str_len(trimmed))) + if !str_eq(name, "") { + let types = native_list_append(types, name) + let kinds = native_list_append(kinds, "protocol") + let tlines = native_list_append(tlines, lineno) + } + } } } } + let i = i + 1 + } + { + "types": types, + "type_kind": kinds, + "fns": fns, + "type_lines": tlines, + "fn_lines": flines + } +} + +// list_contains — case-sensitive membership test on [String]. +fn list_contains_str(xs: [String], needle: String) -> Bool { + let n: Int = native_list_len(xs) + let i: Int = 0 + while i < n { + if str_eq(native_list_get(xs, i), needle) { return true } + let i = i + 1 + } + false +} + +// Score a label against a prefix: 0 if no prefix match, else (prefix_len/label_len). +fn prefix_score(label: String, prefix: String) -> Float { + if str_eq(prefix, "") { return 0.5 } + let lower_label: String = str_to_lower(label) + let lower_prefix: String = str_to_lower(prefix) + if str_starts_with(lower_label, lower_prefix) { + let lp: Int = str_len(lower_prefix) + let ll: Int = str_len(lower_label) + if ll == 0 { return 0.0 } + return int_to_float(lp) / int_to_float(ll) + } + 0.0 +} + +// Render a single completion item to JSON. +fn completion_json(label: String, kind: String, detail: String, doc: String, score: Float) -> String { + let parts: [String] = native_list_empty() + let parts = native_list_append(parts, json_kv_str("label", label)) + let parts = native_list_append(parts, json_kv_str("kind", kind)) + let parts = native_list_append(parts, json_kv_str("detail", detail)) + if str_eq(doc, "") { + let parts = native_list_append(parts, json_kv_raw("documentation", "null")) + } else { + let parts = native_list_append(parts, json_kv_str("documentation", doc)) + } + let parts = native_list_append(parts, json_kv_float("score", score)) + "{" + list_join(parts, ",") + "}" +} + +// ── Public: completion ─────────────────────────────────────────────────────── + +fn lsp_complete(source: String, pos: Int) -> String { + let prefix: String = extract_prefix(source, pos) + let lower_prefix: String = str_to_lower(prefix) + let prefix_empty: Bool = str_eq(prefix, "") + let items: [String] = native_list_empty() + + // Keywords + let kws: [String] = keywords_list() + let nk: Int = native_list_len(kws) + let i: Int = 0 + while i < nk { + let kw: String = native_list_get(kws, i) + if prefix_empty { + let s: Float = prefix_score(kw, prefix) + let items = native_list_append(items, completion_json(kw, "keyword", "keyword", keyword_doc(kw), s)) + } else { if str_starts_with(kw, prefix) { + let s: Float = prefix_score(kw, prefix) + let items = native_list_append(items, completion_json(kw, "keyword", "keyword", keyword_doc(kw), s)) + } } + let i = i + 1 + } + + // Built-in types + let bts: [String] = builtin_type_names() + let nb: Int = native_list_len(bts) + let i: Int = 0 + while i < nb { + let name: String = native_list_get(bts, i) + let lname: String = str_to_lower(name) + if prefix_empty { + let s: Float = 0.5 + 0.1 + let items = native_list_append(items, completion_json(name, "type", builtin_type_doc(name), "Built-in type: " + builtin_type_doc(name), s)) + } else { if str_starts_with(lname, lower_prefix) { + let s: Float = prefix_score(name, prefix) + 0.1 + let items = native_list_append(items, completion_json(name, "type", builtin_type_doc(name), "Built-in type: " + builtin_type_doc(name), s)) + } } + let i = i + 1 + } + + // User-defined types + let decls: Map = scan_decls(source) + let utypes: [String] = decls["types"] + let ukinds: [String] = decls["type_kind"] + let nu: Int = native_list_len(utypes) + let i: Int = 0 + while i < nu { + let name: String = native_list_get(utypes, i) + let kind: String = native_list_get(ukinds, i) + let lname: String = str_to_lower(name) + let include: Bool = false + if prefix_empty { let include = true } + if str_starts_with(lname, lower_prefix) { let include = true } + if include { + let s: Float = prefix_score(name, prefix) + 0.15 + let items = native_list_append(items, completion_json(name, "type", kind + " " + name, "User-defined " + kind + " " + name, s)) + } + let i = i + 1 + } + + // Built-in functions + let bfns: [String] = builtin_fns() + let nf: Int = native_list_len(bfns) + let i: Int = 0 + while i < nf { + let name: String = native_list_get(bfns, i) + let sig: String = native_list_get(bfns, i + 1) + let lname: String = str_to_lower(name) + let include: Bool = false + if prefix_empty { let include = true } + if str_starts_with(lname, lower_prefix) { let include = true } + if include { + let s: Float = prefix_score(name, prefix) + 0.11 + let items = native_list_append(items, completion_json(name, "function", sig, "Built-in: " + name + " :: " + sig, s)) + } + let i = i + 2 + } + + // User-defined functions + let ufns: [String] = decls["fns"] + let nuf: Int = native_list_len(ufns) + let i: Int = 0 + while i < nuf { + let name: String = native_list_get(ufns, i) + let lname: String = str_to_lower(name) + let include: Bool = false + if prefix_empty { let include = true } + if str_starts_with(lname, lower_prefix) { let include = true } + if include { + let s: Float = prefix_score(name, prefix) + 0.12 + let items = native_list_append(items, completion_json(name, "function", "fn " + name, "User function: " + name, s)) + } + let i = i + 1 + } + + // Output is a list of pre-encoded JSON objects. Sorting by score is a + // stretch goal — el's runtime has no sort-by-key primitive. Items are + // already ordered by category (keywords first), which matches the most + // common editor expectation. + json_array_of(items) +} + +// ── Public: hover ──────────────────────────────────────────────────────────── + +fn lsp_hover(source: String, pos: Int) -> String { + let token: String = extract_token(source, pos) + if str_eq(token, "") { return "null" } + + // Built-in primitives + let doc: String = builtin_type_doc(token) + if !str_eq(doc, "") { + let parts: [String] = native_list_empty() + let parts = native_list_append(parts, json_kv_str("type_name", token)) + let parts = native_list_append(parts, json_kv_str("documentation", doc)) + let parts = native_list_append(parts, json_kv_raw("engram_node_type", "null")) + return "{" + list_join(parts, ",") + "}" + } + + // User-declared types + let decls: Map = scan_decls(source) + let utypes: [String] = decls["types"] + let ukinds: [String] = decls["type_kind"] + let nu: Int = native_list_len(utypes) + let i: Int = 0 + while i < nu { + let name: String = native_list_get(utypes, i) + if str_eq(name, token) { + let kind: String = native_list_get(ukinds, i) + let parts: [String] = native_list_empty() + let parts = native_list_append(parts, json_kv_str("type_name", token)) + let parts = native_list_append(parts, json_kv_str("documentation", kind + " " + token)) + let parts = native_list_append(parts, json_kv_raw("engram_node_type", "null")) + return "{" + list_join(parts, ",") + "}" + } + let i = i + 1 + } + + // User-declared functions + let ufns: [String] = decls["fns"] + let nuf: Int = native_list_len(ufns) + let i: Int = 0 + while i < nuf { + let name: String = native_list_get(ufns, i) + if str_eq(name, token) { + let parts: [String] = native_list_empty() + let parts = native_list_append(parts, json_kv_str("type_name", token)) + let parts = native_list_append(parts, json_kv_str("documentation", "fn " + token)) + let parts = native_list_append(parts, json_kv_raw("engram_node_type", "null")) + return "{" + list_join(parts, ",") + "}" + } + let i = i + 1 + } + + // Built-in functions + let bfns: [String] = builtin_fns() + let nf: Int = native_list_len(bfns) + let i: Int = 0 + while i < nf { + let name: String = native_list_get(bfns, i) + if str_eq(name, token) { + let sig: String = native_list_get(bfns, i + 1) + let parts: [String] = native_list_empty() + let parts = native_list_append(parts, json_kv_str("type_name", token)) + let parts = native_list_append(parts, json_kv_str("documentation", "fn " + token + " :: " + sig)) + let parts = native_list_append(parts, json_kv_raw("engram_node_type", "null")) + return "{" + list_join(parts, ",") + "}" + } + let i = i + 2 + } + + // Keyword + let kdoc: String = keyword_doc(token) + if !str_eq(kdoc, "") { + let parts: [String] = native_list_empty() + let parts = native_list_append(parts, json_kv_str("type_name", token)) + let parts = native_list_append(parts, json_kv_str("documentation", kdoc)) + let parts = native_list_append(parts, json_kv_raw("engram_node_type", "null")) + return "{" + list_join(parts, ",") + "}" + } + + "null" +} + +// ── Public: diagnostics ────────────────────────────────────────────────────── +// +// Without the type checker port we surface only structural diagnostics: +// * unterminated string literal +// * unbalanced braces / parens / brackets +// * unknown type referenced after `:` in a let binding (unknown to source + +// builtins) — best-effort, conservative. + +fn diag_json(message: String, severity: String, line: Int, col: Int) -> String { + let parts: [String] = native_list_empty() + let parts = native_list_append(parts, json_kv_str("message", message)) + let parts = native_list_append(parts, json_kv_str("severity", severity)) + if line > 0 { + let parts = native_list_append(parts, json_kv_int("line", line)) + let parts = native_list_append(parts, json_kv_int("col", col)) + } else { + let parts = native_list_append(parts, json_kv_raw("line", "null")) + let parts = native_list_append(parts, json_kv_raw("col", "null")) + } + "{" + list_join(parts, ",") + "}" +} + +fn lsp_diagnostics(source: String) -> String { + let chars: [String] = native_string_chars(source) + let n: Int = native_list_len(chars) + let diags: [String] = native_list_empty() + + // Bracket balance + unterminated string scan + let depth_brace: Int = 0 + let depth_paren: Int = 0 + let depth_brack: Int = 0 + let i: Int = 0 + let line: Int = 1 + let col: Int = 1 + let in_string: Bool = false + let string_start_line: Int = 0 + let string_start_col: Int = 0 + let in_comment: Bool = false + while i < n { + let ch: String = native_list_get(chars, i) + if in_comment { + if ch == "\n" { + let in_comment = false + let line = line + 1 + let col = 1 + } else { + let col = col + 1 + } + let i = i + 1 + } else { + if in_string { + if ch == "\\" { + let i = i + 1 + let col = col + 1 + if i < n { + let esc: String = native_list_get(chars, i) + if esc == "\n" { let line = line + 1 let col = 1 } else { let col = col + 1 } + let i = i + 1 + } + } else { if ch == "\"" { + let in_string = false + let i = i + 1 + let col = col + 1 + } else { if ch == "\n" { + let line = line + 1 + let col = 1 + let i = i + 1 + } else { + let col = col + 1 + let i = i + 1 + } } } + } else { + if ch == "\"" { + let in_string = true + let string_start_line = line + let string_start_col = col + let i = i + 1 + let col = col + 1 + } else { if ch == "/" { + let next_i: Int = i + 1 + let is_line_comment: Bool = false + if next_i < n { + let next_ch: String = native_list_get(chars, next_i) + if next_ch == "/" { let is_line_comment = true } + } + if is_line_comment { + let in_comment = true + let i = i + 2 + let col = col + 2 + } else { + let i = i + 1 + let col = col + 1 + } + } else { if ch == "{" { + let depth_brace = depth_brace + 1 + let i = i + 1 let col = col + 1 + } else { if ch == "}" { + let depth_brace = depth_brace - 1 + if depth_brace < 0 { + let diags = native_list_append(diags, diag_json("unmatched `}`", "error", line, col)) + let depth_brace = 0 + } + let i = i + 1 let col = col + 1 + } else { if ch == "(" { + let depth_paren = depth_paren + 1 + let i = i + 1 let col = col + 1 + } else { if ch == ")" { + let depth_paren = depth_paren - 1 + if depth_paren < 0 { + let diags = native_list_append(diags, diag_json("unmatched `)`", "error", line, col)) + let depth_paren = 0 + } + let i = i + 1 let col = col + 1 + } else { if ch == "[" { + let depth_brack = depth_brack + 1 + let i = i + 1 let col = col + 1 + } else { if ch == "]" { + let depth_brack = depth_brack - 1 + if depth_brack < 0 { + let diags = native_list_append(diags, diag_json("unmatched `]`", "error", line, col)) + let depth_brack = 0 + } + let i = i + 1 let col = col + 1 + } else { if ch == "\n" { + let line = line + 1 + let col = 1 + let i = i + 1 + } else { + let i = i + 1 + let col = col + 1 + } } } } } } } } } + } + } + } + + if in_string { + let diags = native_list_append(diags, diag_json("unterminated string literal", "error", string_start_line, string_start_col)) + } + if depth_brace > 0 { let diags = native_list_append(diags, diag_json("unclosed `{` (missing `}`)", "error", 0, 0)) } + if depth_paren > 0 { let diags = native_list_append(diags, diag_json("unclosed `(` (missing `)`)", "error", 0, 0)) } + if depth_brack > 0 { let diags = native_list_append(diags, diag_json("unclosed `[` (missing `]`)", "error", 0, 0)) } + + json_array_of(diags) +} + +// ── Public: outline ────────────────────────────────────────────────────────── + +fn outline_item_json(kind: String, name: String, line: Int) -> String { + let parts: [String] = native_list_empty() + let parts = native_list_append(parts, json_kv_str("kind", kind)) + let parts = native_list_append(parts, json_kv_str("name", name)) + let parts = native_list_append(parts, json_kv_int("line", line)) + "{" + list_join(parts, ",") + "}" +} + +fn lsp_outline(source: String) -> String { + let lines: [String] = str_split(source, "\n") + let n: Int = native_list_len(lines) + let items: [String] = native_list_empty() + let i: Int = 0 + while i < n { + let line: String = native_list_get(lines, i) + let trimmed: String = str_trim(line) + let lineno: Int = i + 1 + if str_starts_with(trimmed, "fn ") { + let name: String = first_ident_in(str_slice(trimmed, 3, str_len(trimmed))) + if !str_eq(name, "") { + let items = native_list_append(items, outline_item_json("fn", name, lineno)) + } + } else { if str_starts_with(trimmed, "type ") { + let name: String = first_ident_in(str_slice(trimmed, 5, str_len(trimmed))) + if !str_eq(name, "") { + let items = native_list_append(items, outline_item_json("type", name, lineno)) + } + } else { if str_starts_with(trimmed, "enum ") { + let name: String = first_ident_in(str_slice(trimmed, 5, str_len(trimmed))) + if !str_eq(name, "") { + let items = native_list_append(items, outline_item_json("enum", name, lineno)) + } + } else { if str_starts_with(trimmed, "protocol ") { + let name: String = first_ident_in(str_slice(trimmed, 9, str_len(trimmed))) + if !str_eq(name, "") { + let items = native_list_append(items, outline_item_json("protocol", name, lineno)) + } + } else { if str_starts_with(trimmed, "impl ") { + let rest: String = str_trim(str_slice(trimmed, 5, str_len(trimmed))) + let brace: Int = str_index_of(rest, "{") + let name: String = rest + if brace > 0 { let name = str_trim(str_slice(rest, 0, brace)) } + if !str_eq(name, "") { + let items = native_list_append(items, outline_item_json("impl", name, lineno)) + } + } } } } } + let i = i + 1 + } + json_array_of(items) +} + +// ── Public: format ─────────────────────────────────────────────────────────── +// +// Idiomatic-El formatter. Until `el fmt` is a real thing, we apply a minimal +// canonicalisation pass: +// * trim trailing whitespace on every line +// * collapse 3+ blank lines to 2 +// * ensure file ends with exactly one newline +// This is safe for round-tripping and a noticeable quality-of-life win in +// the editor. + +fn format_strip_trailing(line: String) -> String { + // str_trim trims both ends; we want only trailing whitespace stripped. + let n: Int = str_len(line) + if n == 0 { return line } + let chars: [String] = native_string_chars(line) + let i: Int = n - 1 + let trimming: Bool = true + while trimming { + if i < 0 { + let trimming = false + } else { + let ch: String = native_list_get(chars, i) + if ch == " " { let i = i - 1 } else { if ch == "\t" { let i = i - 1 } else { let trimming = false } } + } + } + str_slice(line, 0, i + 1) +} + +fn lsp_format(source: String) -> String { + let lines: [String] = str_split(source, "\n") + let n: Int = native_list_len(lines) + let cleaned: [String] = native_list_empty() + let i: Int = 0 + let blank_run: Int = 0 + while i < n { + let line: String = native_list_get(lines, i) + let stripped: String = format_strip_trailing(line) + if str_eq(stripped, "") { + let blank_run = blank_run + 1 + if blank_run <= 2 { + let cleaned = native_list_append(cleaned, "") + } + } else { + let blank_run = 0 + let cleaned = native_list_append(cleaned, stripped) + } + let i = i + 1 + } + let joined: String = list_join(cleaned, "\n") + // Ensure trailing newline. + let final: String = joined + if !str_ends_with(final, "\n") { + let final = final + "\n" + } + let changed: String = "false" + if !str_eq(final, source) { let changed = "true" } + "{" + json_kv_str("content", final) + "," + json_kv_raw("changed", changed) + "}" +} + +// ── Public: type graph ─────────────────────────────────────────────────────── + +fn lsp_type_graph(source: String) -> String { + let nodes: [String] = native_list_empty() + let edges: [String] = native_list_empty() + + // Built-in nodes + let bts: [String] = builtin_type_names() + let nb: Int = native_list_len(bts) + let i: Int = 0 + while i < nb { + let name: String = native_list_get(bts, i) + let parts: [String] = native_list_empty() + let parts = native_list_append(parts, json_kv_str("id", name)) + let parts = native_list_append(parts, json_kv_str("name", name)) + let parts = native_list_append(parts, json_kv_str("kind", "builtin")) + let parts = native_list_append(parts, json_kv_raw("fields", "[]")) + let nodes = native_list_append(nodes, "{" + list_join(parts, ",") + "}") + let i = i + 1 + } + + // User-declared types + let decls: Map = scan_decls(source) + let utypes: [String] = decls["types"] + let ukinds: [String] = decls["type_kind"] + let tlines: [Int] = decls["type_lines"] + let nu: Int = native_list_len(utypes) + let i: Int = 0 + let bts_dup: [String] = builtin_type_names() + while i < nu { + let name: String = native_list_get(utypes, i) + let kind: String = native_list_get(ukinds, i) + // Skip if already a builtin (paranoia) + if !list_contains_str(bts_dup, name) { + let fields: [String] = collect_struct_fields(source, name) + let field_jsons: [String] = native_list_empty() + let fn2: Int = native_list_len(fields) + let j: Int = 0 + while j < fn2 { + let field_jsons = native_list_append(field_jsons, json_str(native_list_get(fields, j))) + let j = j + 1 + } + let parts: [String] = native_list_empty() + let parts = native_list_append(parts, json_kv_str("id", name)) + let parts = native_list_append(parts, json_kv_str("name", name)) + let parts = native_list_append(parts, json_kv_str("kind", kind)) + let parts = native_list_append(parts, json_kv_raw("fields", json_array_of(field_jsons))) + let nodes = native_list_append(nodes, "{" + list_join(parts, ",") + "}") + + // Edges: scan each field for a known type reference. + let j: Int = 0 + while j < fn2 { + let field_str: String = native_list_get(fields, j) + let target: String = referenced_type(field_str, utypes) + if !str_eq(target, "") { + let eparts: [String] = native_list_empty() + let eparts = native_list_append(eparts, json_kv_str("from", name)) + let eparts = native_list_append(eparts, json_kv_str("to", target)) + let eparts = native_list_append(eparts, json_kv_str("label", "field")) + let edges = native_list_append(edges, "{" + list_join(eparts, ",") + "}") + } + let j = j + 1 + } + } + let i = i + 1 + } + + "{" + json_kv_raw("nodes", json_array_of(nodes)) + "," + json_kv_raw("edges", json_array_of(edges)) + "}" +} + +// Extract the field list of a `type Name { ... }` block as ["field: Type", ...] +// or for an enum, the variant labels. Best-effort line-by-line scan. +fn collect_struct_fields(source: String, type_name: String) -> [String] { + let lines: [String] = str_split(source, "\n") + let n: Int = native_list_len(lines) + let fields: [String] = native_list_empty() + let inside: Bool = false + let i: Int = 0 + let header_a: String = "type " + type_name + let header_b: String = "enum " + type_name + let header_c: String = "protocol " + type_name + while i < n { + let line: String = native_list_get(lines, i) + let trimmed: String = str_trim(line) + if !inside { + if str_starts_with(trimmed, header_a) { let inside = true } + if str_starts_with(trimmed, header_b) { let inside = true } + if str_starts_with(trimmed, header_c) { let inside = true } + } else { + if str_starts_with(trimmed, "}") { + return fields + } + // skip the opening "{" line + if !str_eq(trimmed, "{") { + if !str_eq(trimmed, "") { + if !str_starts_with(trimmed, "//") { + // strip a trailing comma if present + let entry: String = trimmed + if str_ends_with(entry, ",") { + let entry = str_slice(entry, 0, str_len(entry) - 1) + } + let fields = native_list_append(fields, str_trim(entry)) + } + } + } + } + let i = i + 1 + } + fields +} + +// Pick the first known type name out of a `field: Type` string. Stops at non-ident. +fn referenced_type(field_str: String, known_types: [String]) -> String { + // Find ":" — type follows. + let colon: Int = str_index_of(field_str, ":") + if colon < 0 { return "" } + let after: String = str_trim(str_slice(field_str, colon + 1, str_len(field_str))) + // Strip array brackets and optional marker. + let trimmed_l: String = after + if str_starts_with(trimmed_l, "[") { + let end: Int = str_index_of(trimmed_l, "]") + if end > 1 { + let trimmed_l = str_trim(str_slice(trimmed_l, 1, end)) + } + } + // First identifier. + let ident: String = first_ident_in(trimmed_l) + if str_eq(ident, "") { return "" } + let bts: [String] = builtin_type_names() + if list_contains_str(bts, ident) { return ident } + if list_contains_str(known_types, ident) { return ident } + "" +} + +// ── Public: definition / references ────────────────────────────────────────── + +fn lsp_definition(source: String, pos: Int) -> String { + let word: String = extract_token(source, pos) + if str_eq(word, "") { return "null" } + let patterns: [String] = native_list_empty() + let patterns = native_list_append(patterns, "fn " + word) + let patterns = native_list_append(patterns, "type " + word) + let patterns = native_list_append(patterns, "enum " + word) + let patterns = native_list_append(patterns, "protocol " + word) + let np: Int = native_list_len(patterns) + let lines: [String] = str_split(source, "\n") + let nl: Int = native_list_len(lines) + let i: Int = 0 + while i < nl { + let line: String = native_list_get(lines, i) + let j: Int = 0 + while j < np { + let pat: String = native_list_get(patterns, j) + let idx: Int = str_index_of(line, pat) + if idx >= 0 { + let parts: [String] = native_list_empty() + let parts = native_list_append(parts, json_kv_int("line", i + 1)) + let parts = native_list_append(parts, json_kv_int("col", idx + 1)) + let parts = native_list_append(parts, json_kv_str("snippet", str_trim(line))) + return "{" + list_join(parts, ",") + "}" + } + let j = j + 1 + } + let i = i + 1 + } + "null" +} + +fn lsp_references(source: String, pos: Int) -> String { + let word: String = extract_token(source, pos) + if str_eq(word, "") { return "[]" } + let lines: [String] = str_split(source, "\n") + let nl: Int = native_list_len(lines) + let refs: [String] = native_list_empty() + let i: Int = 0 + while i < nl { + let line: String = native_list_get(lines, i) + let line_chars: [String] = native_string_chars(line) + let llen: Int = native_list_len(line_chars) + let wlen: Int = str_len(word) + let off: Int = 0 + let scanning: Bool = true + while scanning { + let idx: Int = str_index_of(str_slice(line, off, str_len(line)), word) + if idx < 0 { + let scanning = false + } else { + let abs: Int = off + idx + // Word-boundary check + let before_ok: Bool = true + if abs > 0 { + let prev: String = native_list_get(line_chars, abs - 1) + if is_ident_ch(prev) { let before_ok = false } + } + let after_ok: Bool = true + let after_pos: Int = abs + wlen + if after_pos < llen { + let nxt: String = native_list_get(line_chars, after_pos) + if is_ident_ch(nxt) { let after_ok = false } + } + if before_ok { + if after_ok { + let parts: [String] = native_list_empty() + let parts = native_list_append(parts, json_kv_int("line", i + 1)) + let parts = native_list_append(parts, json_kv_int("col", abs + 1)) + let parts = native_list_append(parts, json_kv_str("snippet", str_trim(line))) + let refs = native_list_append(refs, "{" + list_join(parts, ",") + "}") + } + } + let off = abs + wlen + if off >= str_len(line) { let scanning = false } + } + } + let i = i + 1 + } + json_array_of(refs) +} + +// ── JSON-RPC dispatch ──────────────────────────────────────────────────────── +// +// Method names follow LSP-ish conventions but stay aligned with the Rust crate's +// HTTP surface. Params are a JSON string the dispatcher pulls fields out of via +// json_get_string / json_get_int. +// +// "textDocument/completion" → params { source, pos } +// "textDocument/hover" → params { source, pos } +// "textDocument/diagnostic" → params { source } +// "textDocument/formatting" → params { source } +// "textDocument/documentSymbol"→ params { source } +// "textDocument/definition" → params { source, pos } +// "textDocument/references" → params { source, pos } +// "el/typeGraph" → params { source } + +fn lsp_jsonrpc(method: String, params_json: String) -> String { + let source: String = json_get_string(params_json, "source") + let pos: Int = json_get_int(params_json, "pos") + if str_eq(method, "textDocument/completion") { return lsp_complete(source, pos) } + if str_eq(method, "textDocument/hover") { return lsp_hover(source, pos) } + if str_eq(method, "textDocument/diagnostic") { return lsp_diagnostics(source) } + if str_eq(method, "textDocument/formatting") { return lsp_format(source) } + if str_eq(method, "textDocument/documentSymbol") { return lsp_outline(source) } + if str_eq(method, "textDocument/definition") { return lsp_definition(source, pos) } + if str_eq(method, "textDocument/references") { return lsp_references(source, pos) } + if str_eq(method, "el/typeGraph") { return lsp_type_graph(source) } + "{\"error\":\"unknown method: " + json_escape(method) + "\"}" +} + +// ── stdio loop (best-effort; see runtime gap note in the report) ───────────── +// +// LSP framing is `Content-Length: N\r\n\r\n` then exactly N bytes. The El +// runtime exposes only line-buffered `readline()`, which strips `\n` and is +// hostile to the binary body read. We approximate by reading lines until a +// blank line ends the headers, then reading exactly one more line as the +// body (works for compact, no-newline payloads — i.e. minified JSON-RPC). +// A dedicated `read_n(bytes)` runtime primitive would unblock the strict +// implementation. See report. + +fn read_headers() -> Map { + let content_len: Int = 0 + let scanning: Bool = true + while scanning { + let line: String = readline() + if str_eq(line, "") { + let scanning = false + } else { + let cl_marker: String = "Content-Length:" + if str_starts_with(line, cl_marker) { + let val: String = str_trim(str_slice(line, str_len(cl_marker), str_len(line))) + let content_len = str_to_int(val) + } + } + } + { "content_length": content_len } +} + +fn lsp_stdio_loop() -> Void { + let running: Bool = true + while running { + let headers: Map = read_headers() + let body: String = readline() + if str_eq(body, "") { + let running = false + } else { + let method: String = json_get_string(body, "method") + let id_val: String = json_get_raw(body, "id") + if str_eq(id_val, "") { let id_val = "null" } + let params_raw: String = json_get_raw(body, "params") + let result: String = lsp_jsonrpc(method, params_raw) + let resp: String = "{\"jsonrpc\":\"2.0\",\"id\":" + id_val + ",\"result\":" + result + "}" + let frame: String = "Content-Length: " + int_to_str(str_len(resp)) + "\r\n\r\n" + resp + print(frame) + } + } +} + +// ── Entry ──────────────────────────────────────────────────────────────────── +// +// When invoked as a standalone binary, default to stdio JSON-RPC so editors +// that drive the language server directly (without the HTTP wrapper) work +// out of the box. Pass a single CLI arg to short-circuit: +// ./el-lsp probe → emits a self-test diagnostic + exits +// ./el-lsp version → emits version + exits + +fn lsp_main() -> Void { + let argv: [String] = args() + let n: Int = native_list_len(argv) + if n > 0 { + let cmd: String = native_list_get(argv, 0) + if str_eq(cmd, "version") { + println("el-lsp 0.1.0") + return + } + if str_eq(cmd, "probe") { + let sample: String = "fn main() -> Void { let x: Int = 42 }" + println(lsp_diagnostics(sample)) + return + } + } + lsp_stdio_loop() +} + + +// main.el — el-plugin-host +// +// Plugin lifecycle manager for el-ide. Pure-El port of the el-plugin-host +// Rust crate. +// +// Plugins are stored in process-global state via state_get / state_set. +// Each plugin lives under a key prefix `plugin//`. The +// canonical list of plugin names is maintained at `plugins/index` as a +// comma-separated string (we don't have list serialisation in state yet). +// +// Public API: +// plugin_init() — seed first-party plugins (idempotent) +// plugin_list_json() -> String — JSON array of all plugins +// plugin_get_json(name) -> String — JSON object or "null" +// plugin_install(name) -> String — JSON { ok | error } +// plugin_remove(name) -> String +// plugin_enable(name) -> String +// plugin_disable(name) -> String + +// ── State helpers (string K/V) ─────────────────────────────────────────────── + +fn pkey(name: String, field: String) -> String { + "plugin/" + name + "/" + field +} + +fn put_str(name: String, field: String, value: String) -> Void { + state_set(pkey(name, field), value) +} + +fn put_bool(name: String, field: String, value: Bool) -> Void { + if value { state_set(pkey(name, field), "true") } + if !value { state_set(pkey(name, field), "false") } +} + +fn get_str(name: String, field: String) -> String { + state_get(pkey(name, field)) +} + +fn get_bool(name: String, field: String) -> Bool { + str_eq(state_get(pkey(name, field)), "true") +} + +// Plugin index: comma-separated list of names at "plugins/index". +fn index_list() -> [String] { + let raw: String = state_get("plugins/index") + if str_eq(raw, "") { return native_list_empty() } + str_split(raw, ",") +} + +fn index_set(names: [String]) -> Void { + state_set("plugins/index", list_join(names, ",")) +} + +fn index_contains(name: String) -> Bool { + let names: [String] = index_list() + let n: Int = native_list_len(names) + let i: Int = 0 + while i < n { + if str_eq(native_list_get(names, i), name) { return true } + let i = i + 1 + } + false +} + +fn index_add(name: String) -> Void { + if !index_contains(name) { + let names: [String] = index_list() + let names = native_list_append(names, name) + index_set(names) + } +} + +// ── Initialisation ─────────────────────────────────────────────────────────── + +fn register_plugin(name: String, version: String, description: String, + installed: Bool, enabled: Bool, hooks: String, + first_party: Bool) -> Void { + put_str(name, "name", name) + put_str(name, "version", version) + put_str(name, "description", description) + put_bool(name, "installed", installed) + put_bool(name, "enabled", enabled) + put_str(name, "hooks", hooks) + put_bool(name, "first_party", first_party) + index_add(name) +} + +fn plugin_init() -> Void { + if str_eq(state_get("plugins/initialised"), "true") { + return + } + register_plugin("el-theme-dark", "1.0.0", "Dark theme — the default Engram IDE theme.", true, true, "", true) + register_plugin("el-theme-light", "1.0.0", "Light theme for high-ambient-light environments.", false, false, "", true) + register_plugin("el-fmt", "0.1.0", "Code formatter — auto-formats .el files on save.", true, true, "on_save", true) + register_plugin("el-doc", "0.1.0", "Documentation generator — produces HTML docs from type definitions.", false, false, "custom_tool", true) + register_plugin("el-test", "0.1.0", "Test runner with inline results displayed in the editor gutter.", false, false, "on_build_complete,custom_panel", true) + state_set("plugins/initialised", "true") +} + +// ── Serialisation ──────────────────────────────────────────────────────────── + +fn json_escape_str(s: String) -> String { + let chars: [String] = native_string_chars(s) + let n: Int = native_list_len(chars) + let out: String = "" + let i: Int = 0 + while i < n { + let ch: String = native_list_get(chars, i) + if ch == "\"" { let out = out + "\\\"" } + else { if ch == "\\" { let out = out + "\\\\" } + else { if ch == "\n" { let out = out + "\\n" } + else { let out = out + ch } } } + let i = i + 1 + } + out +} + +fn quote_json(s: String) -> String { + "\"" + json_escape_str(s) + "\"" +} + +fn hooks_to_json(hooks_csv: String) -> String { + if str_eq(hooks_csv, "") { return "[]" } + let xs: [String] = str_split(hooks_csv, ",") + let n: Int = native_list_len(xs) + let out: String = "[" + let i: Int = 0 + while i < n { + if i > 0 { let out = out + "," } + let out = out + quote_json(native_list_get(xs, i)) + let i = i + 1 + } + out + "]" +} + +fn plugin_to_json(name: String) -> String { + let parts: [String] = native_list_empty() + let parts = native_list_append(parts, "\"name\":" + quote_json(get_str(name, "name"))) + let parts = native_list_append(parts, "\"version\":" + quote_json(get_str(name, "version"))) + let parts = native_list_append(parts, "\"description\":" + quote_json(get_str(name, "description"))) + let installed: String = get_str(name, "installed") + let enabled: String = get_str(name, "enabled") + let first_party: String = get_str(name, "first_party") + let parts = native_list_append(parts, "\"installed\":" + installed) + let parts = native_list_append(parts, "\"enabled\":" + enabled) + let parts = native_list_append(parts, "\"hooks\":" + hooks_to_json(get_str(name, "hooks"))) + let parts = native_list_append(parts, "\"first_party\":" + first_party) + "{" + list_join(parts, ",") + "}" +} + +fn plugin_list_json() -> String { + plugin_init() + let names: [String] = index_list() + let n: Int = native_list_len(names) + let out: String = "[" + let i: Int = 0 + while i < n { + if i > 0 { let out = out + "," } + let out = out + plugin_to_json(native_list_get(names, i)) + let i = i + 1 + } + out + "]" +} + +fn plugin_get_json(name: String) -> String { + plugin_init() + if !index_contains(name) { return "null" } + plugin_to_json(name) +} + +// ── Mutations ──────────────────────────────────────────────────────────────── + +fn plugin_install(name: String) -> String { + plugin_init() + if !index_contains(name) { + return "{\"error\":\"plugin registry is not available (registry URL not configured)\"}" + } + if get_bool(name, "installed") { + return "{\"error\":\"plugin '" + json_escape_str(name) + "' is already installed\"}" + } + put_bool(name, "installed", true) + put_bool(name, "enabled", true) + plugin_to_json(name) +} + +fn plugin_remove(name: String) -> String { + plugin_init() + if !index_contains(name) { + return "{\"error\":\"plugin '" + json_escape_str(name) + "' not found\"}" + } + if str_eq(name, "el-theme-dark") { + return "{\"error\":\"plugin '" + json_escape_str(name) + "' cannot be removed: it is a required built-in\"}" + } + put_bool(name, "installed", false) + put_bool(name, "enabled", false) + "{\"ok\":true}" +} + +fn plugin_enable(name: String) -> String { + plugin_init() + if !index_contains(name) { + return "{\"error\":\"plugin '" + json_escape_str(name) + "' not found\"}" + } + put_bool(name, "enabled", true) + "{\"ok\":true}" +} + +fn plugin_disable(name: String) -> String { + plugin_init() + if !index_contains(name) { + return "{\"error\":\"plugin '" + json_escape_str(name) + "' not found\"}" + } + put_bool(name, "enabled", false) + "{\"ok\":true}" +} + +// ── Standalone CLI ─────────────────────────────────────────────────────────── + +fn host_main() -> Void { + let argv: [String] = args() + let n: Int = native_list_len(argv) + if n == 0 { + println(plugin_list_json()) + return + } + let cmd: String = native_list_get(argv, 0) + if str_eq(cmd, "list") { println(plugin_list_json()) return } + if str_eq(cmd, "get") { + if n >= 2 { println(plugin_get_json(native_list_get(argv, 1))) } + return + } + if str_eq(cmd, "install") { + if n >= 2 { println(plugin_install(native_list_get(argv, 1))) } + return + } + if str_eq(cmd, "remove") { + if n >= 2 { println(plugin_remove(native_list_get(argv, 1))) } + return + } + if str_eq(cmd, "enable") { + if n >= 2 { println(plugin_enable(native_list_get(argv, 1))) } + return + } + if str_eq(cmd, "disable") { + if n >= 2 { println(plugin_disable(native_list_get(argv, 1))) } + return + } + println("usage: el-plugin-host [list|get|install|remove|enable|disable] ") +} + + +// main.el — el-ide-server +// +// HTTP backend for the Engram IDE. Pure-El port of the el-ide-server Rust +// crate. Wires the el-lsp and el-plugin-host vessels together and serves +// the IDE-frontend protocol used by the React-style frontend. +// +// El compilation note: `import` statements are parsed but the codegen +// concatenates nothing. The build script for this vessel concatenates +// +// vessels/el-lsp/src/main.el (without the trailing entry call) +// vessels/el-plugin-host/src/main.el +// vessels/el-ide-server/src/main.el (this file) +// +// into a single _combined.el before invoking elc. This file therefore +// assumes the lsp_* and plugin_* functions defined in those siblings are +// in scope. See README / build.sh. +// +// All routes serve JSON over HTTP. Query parameters are parsed by hand +// (the runtime gives us strings and a request body). Streaming endpoints +// (SSE) are emulated by returning the full output once — the runtime's +// http_serve handler signature is response-as-string, so true server-sent +// streaming requires a runtime extension. Flagged in the report. + +// ── Tiny utility layer ─────────────────────────────────────────────────────── + +fn jstr(s: String) -> String { + let chars: [String] = native_string_chars(s) + let n: Int = native_list_len(chars) + let out: String = "\"" + let i: Int = 0 + while i < n { + let ch: String = native_list_get(chars, i) + if ch == "\"" { let out = out + "\\\"" } + else { if ch == "\\" { let out = out + "\\\\" } + else { if ch == "\n" { let out = out + "\\n" } + else { if ch == "\r" { let out = out + "\\r" } + else { if ch == "\t" { let out = out + "\\t" } + else { let out = out + ch } } } } } + let i = i + 1 + } + out + "\"" +} + +fn jerr(msg: String) -> String { + "{\"error\":" + jstr(msg) + "}" +} + +fn ok_obj() -> String { + "{\"ok\":true}" +} + +// ── URL/query parsing ──────────────────────────────────────────────────────── + +fn url_decode(s: String) -> String { + let chars: [String] = native_string_chars(s) + let n: Int = native_list_len(chars) + let out: String = "" + let i: Int = 0 + while i < n { + let ch: String = native_list_get(chars, i) + if ch == "+" { + let out = out + " " + let i = i + 1 + } else { if ch == "%" { + // Read two hex digits + if i + 2 < n { + let hex: String = native_list_get(chars, i + 1) + native_list_get(chars, i + 2) + let code: Int = hex_to_int(hex) + let out = out + char_from_code(code) + let i = i + 3 + } else { + let out = out + ch + let i = i + 1 + } + } else { + let out = out + ch + let i = i + 1 + } } + } + out +} + +fn hex_digit(ch: String) -> Int { + if ch == "0" { return 0 } if ch == "1" { return 1 } + if ch == "2" { return 2 } if ch == "3" { return 3 } + if ch == "4" { return 4 } if ch == "5" { return 5 } + if ch == "6" { return 6 } if ch == "7" { return 7 } + if ch == "8" { return 8 } if ch == "9" { return 9 } + if ch == "a" { return 10 } if ch == "A" { return 10 } + if ch == "b" { return 11 } if ch == "B" { return 11 } + if ch == "c" { return 12 } if ch == "C" { return 12 } + if ch == "d" { return 13 } if ch == "D" { return 13 } + if ch == "e" { return 14 } if ch == "E" { return 14 } + if ch == "f" { return 15 } if ch == "F" { return 15 } + -1 +} + +fn hex_to_int(hex: String) -> Int { + let chars: [String] = native_string_chars(hex) + let n: Int = native_list_len(chars) + let acc: Int = 0 + let i: Int = 0 + while i < n { + let d: Int = hex_digit(native_list_get(chars, i)) + if d < 0 { return acc } + let acc = acc * 16 + d + let i = i + 1 + } + acc +} + +// Map an ASCII code point back to its single-byte string. Above 127 the +// runtime would need char_from_code(>127) → multi-byte; we only need +// printable ASCII for query strings here. +fn char_from_code(code: Int) -> String { + let table: String = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~" + if code < 32 { return " " } + if code > 126 { return "?" } + str_slice(table, code - 32, code - 31) +} + +fn split_path_query(path: String) -> Map { + let q: Int = str_index_of(path, "?") + if q < 0 { return { "path": path, "query": "" } } + { "path": str_slice(path, 0, q), "query": str_slice(path, q + 1, str_len(path)) } +} + +// query_get: pull the value of a single key out of `a=1&b=hello%20world`. +fn query_get(query: String, key: String) -> String { + if str_eq(query, "") { return "" } + let pairs: [String] = str_split(query, "&") + let n: Int = native_list_len(pairs) + let prefix: String = key + "=" + let i: Int = 0 + while i < n { + let pair: String = native_list_get(pairs, i) + if str_starts_with(pair, prefix) { + return url_decode(str_slice(pair, str_len(prefix), str_len(pair))) + } + if str_eq(pair, key) { + return "" + } + let i = i + 1 + } + "" +} + +// ── Configuration ──────────────────────────────────────────────────────────── + +fn cfg_port() -> Int { + let p: String = env("EL_IDE_PORT") + if str_eq(p, "") { return 7771 } + str_to_int(p) +} + +fn cfg_project_path() -> String { + let p: String = env("EL_IDE_PROJECT_PATH") + if str_eq(p, "") { return "." } + p +} + +fn cfg_engram_url() -> String { + let u: String = env("EL_ENGRAM_URL") + if str_eq(u, "") { return "http://localhost:8742" } + u +} + +fn cfg_el_binary() -> String { + let b: String = env("EL_BINARY") + if str_eq(b, "") { return "el" } + b +} + +// ── Path safety ────────────────────────────────────────────────────────────── + +fn safe_join(rel: String) -> String { + let root: String = cfg_project_path() + // Reject obvious traversals. + if str_contains(rel, "..") { return "" } + if str_starts_with(rel, "/") { return "" } + if str_eq(rel, ".") { return root } + root + "/" + rel +} + +// ── Status route ───────────────────────────────────────────────────────────── + +fn route_status() -> String { + let parts: [String] = native_list_empty() + let parts = native_list_append(parts, "\"project_name\":" + jstr(cfg_project_path())) + let parts = native_list_append(parts, "\"project_path\":" + jstr(cfg_project_path())) + let parts = native_list_append(parts, "\"version\":" + jstr("0.1.0")) + let parts = native_list_append(parts, "\"engine\":" + jstr("el-ide")) + "{" + list_join(parts, ",") + "}" +} + +// ── Config route ───────────────────────────────────────────────────────────── + +fn route_config() -> String { + let parts: [String] = native_list_empty() + let parts = native_list_append(parts, "\"port\":" + int_to_str(cfg_port())) + let parts = native_list_append(parts, "\"project_path\":" + jstr(cfg_project_path())) + let parts = native_list_append(parts, "\"engram_url\":" + jstr(cfg_engram_url())) + let parts = native_list_append(parts, "\"el_binary\":" + jstr(cfg_el_binary())) + "{" + list_join(parts, ",") + "}" +} + +// ── File API ───────────────────────────────────────────────────────────────── + +fn route_files_list(query: String) -> String { + let rel: String = query_get(query, "path") + if str_eq(rel, "") { let rel = "." } + let target: String = safe_join(rel) + if str_eq(target, "") { return jerr("path escapes project root") } + let entries: [String] = fs_list(target) + let n: Int = native_list_len(entries) + let out: String = "[" + let i: Int = 0 + while i < n { + let name: String = native_list_get(entries, i) + // Skip hidden + noise dirs + let skip: Bool = false + if str_starts_with(name, ".") { let skip = true } + if str_eq(name, "target") { let skip = true } + if str_eq(name, "node_modules") { let skip = true } + if str_eq(name, "dist") { let skip = true } + if !skip { + if i > 0 { + if !str_eq(out, "[") { let out = out + "," } + } + // Approximate is_dir by checking for an extension + let dot: Int = str_index_of(name, ".") + let is_dir: String = "false" + if dot < 0 { let is_dir = "true" } + let out = out + "{\"name\":" + jstr(name) + ",\"path\":" + jstr(rel + "/" + name) + ",\"is_dir\":" + is_dir + ",\"children\":null}" + } + let i = i + 1 + } + out + "]" +} + +fn route_file_read(query: String) -> String { + let rel: String = query_get(query, "path") + if str_eq(rel, "") { return jerr("missing path parameter") } + let target: String = safe_join(rel) + if str_eq(target, "") { return jerr("path escapes project root") } + let content: String = fs_read(target) + "{\"path\":" + jstr(rel) + ",\"content\":" + jstr(content) + "}" +} + +fn route_file_write(body: String) -> String { + let rel: String = json_get_string(body, "path") + let content: String = json_get_string(body, "content") + if str_eq(rel, "") { return jerr("missing path") } + let target: String = safe_join(rel) + if str_eq(target, "") { return jerr("path escapes project root") } + let ok: Bool = fs_write(target, content) + if ok { return ok_obj() } + jerr("cannot write file") +} + +// ── LSP routes (delegate to inlined lsp_* functions) ───────────────────────── + +fn route_lsp_complete(query: String) -> String { + let source: String = query_get(query, "source") + let pos: Int = str_to_int(query_get(query, "pos")) + lsp_complete(source, pos) +} + +fn route_lsp_hover(query: String) -> String { + let source: String = query_get(query, "source") + let pos: Int = str_to_int(query_get(query, "pos")) + lsp_hover(source, pos) +} + +fn route_lsp_errors(query: String) -> String { + let source: String = query_get(query, "source") + lsp_diagnostics(source) +} + +fn route_lsp_jsonrpc(body: String) -> String { + let method: String = json_get_string(body, "method") + let params_raw: String = json_get_raw(body, "params") + let id_val: String = json_get_raw(body, "id") + if str_eq(id_val, "") { let id_val = "null" } + let result: String = lsp_jsonrpc(method, params_raw) + "{\"jsonrpc\":\"2.0\",\"id\":" + id_val + ",\"result\":" + result + "}" +} + +fn route_outline(query: String) -> String { + let source: String = query_get(query, "source") + lsp_outline(source) +} + +fn route_definition(query: String) -> String { + let source: String = query_get(query, "source") + let pos: Int = str_to_int(query_get(query, "pos")) + lsp_definition(source, pos) +} + +fn route_references(query: String) -> String { + let source: String = query_get(query, "source") + let pos: Int = str_to_int(query_get(query, "pos")) + lsp_references(source, pos) +} + +fn route_format(body: String) -> String { + let content: String = json_get_string(body, "content") + lsp_format(content) +} + +fn route_type_graph(query: String) -> String { + let source: String = query_get(query, "source") + lsp_type_graph(source) +} + +// ── Themes ─────────────────────────────────────────────────────────────────── + +fn active_theme() -> String { + let t: String = state_get("ide/active_theme") + if str_eq(t, "") { return "dark" } + t +} + +fn route_themes_list() -> String { + let active: String = active_theme() + let names: [String] = native_list_empty() + let names = native_list_append(names, "dark") + let names = native_list_append(names, "light") + let names = native_list_append(names, "neuron") + let names = native_list_append(names, "high-contrast") + let labels: [String] = native_list_empty() + let labels = native_list_append(labels, "Dark") + let labels = native_list_append(labels, "Light") + let labels = native_list_append(labels, "Neuron") + let labels = native_list_append(labels, "High Contrast") + let n: Int = native_list_len(names) + let out: String = "[" + let i: Int = 0 + while i < n { + if i > 0 { let out = out + "," } + let nm: String = native_list_get(names, i) + let lbl: String = native_list_get(labels, i) + let act: String = "false" + if str_eq(nm, active) { let act = "true" } + let out = out + "{\"name\":" + jstr(nm) + ",\"label\":" + jstr(lbl) + ",\"active\":" + act + "}" + let i = i + 1 + } + out + "]" +} + +fn route_themes_set(body: String) -> String { + let name: String = json_get_string(body, "name") + let valid: Bool = false + if str_eq(name, "dark") { let valid = true } + if str_eq(name, "light") { let valid = true } + if str_eq(name, "neuron") { let valid = true } + if str_eq(name, "high-contrast") { let valid = true } + if !valid { return jerr("unknown theme: " + name) } + state_set("ide/active_theme", name) + "{\"ok\":true,\"active\":" + jstr(name) + "}" +} + +// ── Plugins (delegate to plugin_* in plugin-host) ──────────────────────────── + +fn route_plugins_list() -> String { plugin_list_json() } + +fn route_plugins_install(body: String) -> String { + plugin_install(json_get_string(body, "name")) +} + +fn route_plugins_remove(body: String) -> String { + plugin_remove(json_get_string(body, "name")) +} + +fn route_plugins_enable(body: String) -> String { + plugin_enable(json_get_string(body, "name")) +} + +fn route_plugins_disable(body: String) -> String { + plugin_disable(json_get_string(body, "name")) +} + +// ── Snippets ───────────────────────────────────────────────────────────────── + +fn route_snippets() -> String { + let snips: [String] = native_list_empty() + let snips = native_list_append(snips, "{\"label\":\"fn\",\"description\":\"Function definition\",\"body\":\"fn ${1:name}(${2:params}) -> ${3:Ret} {\\n\\t${4:body}\\n}\"}") + let snips = native_list_append(snips, "{\"label\":\"type\",\"description\":\"Struct\",\"body\":\"type ${1:Name} {\\n\\t${2:field}: ${3:Type},\\n}\"}") + let snips = native_list_append(snips, "{\"label\":\"enum\",\"description\":\"Enum\",\"body\":\"enum ${1:Name} {\\n\\t${2:Variant},\\n}\"}") + let snips = native_list_append(snips, "{\"label\":\"match\",\"description\":\"Match expression\",\"body\":\"match ${1:expr} {\\n\\t${2:pat} => ${3:body},\\n\\t_ => ${4:default},\\n}\"}") + let snips = native_list_append(snips, "{\"label\":\"let\",\"description\":\"Let binding\",\"body\":\"let ${1:name}: ${2:Type} = ${3:value}\"}") + let snips = native_list_append(snips, "{\"label\":\"if\",\"description\":\"If expression\",\"body\":\"if ${1:cond} {\\n\\t${2:body}\\n}\"}") + let snips = native_list_append(snips, "{\"label\":\"for\",\"description\":\"For loop\",\"body\":\"for ${1:item} in ${2:iter} {\\n\\t${3:body}\\n}\"}") + let snips = native_list_append(snips, "{\"label\":\"activate\",\"description\":\"Activate\",\"body\":\"activate ${1:Type}\"}") + "[" + list_join(snips, ",") + "]" +} + +// ── Settings (file-backed) ─────────────────────────────────────────────────── + +fn settings_path() -> String { + let home: String = env("HOME") + if str_eq(home, "") { let home = "/tmp" } + home + "/.el-ide/settings.json" +} + +fn default_settings_json() -> String { + "{\"theme\":\"dark\",\"fontSize\":13,\"tabSize\":4,\"wordWrap\":false,\"formatOnSave\":false,\"vimMode\":false,\"minimap\":true,\"elBinaryPath\":\"el\",\"engramUrl\":\"http://localhost:8742\",\"stickyScroll\":true,\"lineNumbers\":true,\"bracketMatching\":true}" +} + +fn route_settings_get() -> String { + let s: String = fs_read(settings_path()) + if str_eq(s, "") { return default_settings_json() } + s +} + +fn route_settings_save(body: String) -> String { + // Body is { "settings": {...} } — extract the inner blob. + let blob: String = json_get_raw(body, "settings") + if str_eq(blob, "") { return jerr("missing settings") } + fs_write(settings_path(), blob) + blob +} + +fn route_settings_reset() -> String { + fs_write(settings_path(), default_settings_json()) + default_settings_json() +} + +// ── Build / run (synchronous; no SSE in current http_serve runtime) ────────── +// +// The Rust crate spawned `el build/run` and streamed output as SSE events. +// El's `http_serve` is request/response only — handlers return one string. +// We call the el binary, capture stdout via fs_read of a redirected temp +// file, and return JSON. Streaming is a runtime gap (see report). + +fn route_build_or_run(action: String, body: String) -> String { + let rel_file: String = json_get_string(body, "file") + if str_eq(rel_file, "") { let rel_file = "src/main.el" } + let target: String = safe_join(rel_file) + if str_eq(target, "") { return jerr("path escapes project root") } + // No process-spawn primitive in the runtime; this is a stub that + // documents the planned behaviour. See report for runtime gap. + "{\"event\":\"info\",\"action\":" + jstr(action) + ",\"file\":" + jstr(rel_file) + ",\"note\":\"el-ide-server: synchronous build requires a runtime exec primitive — el binary not invoked\"}" +} + +fn route_build(body: String) -> String { route_build_or_run("build", body) } +fn route_run(body: String) -> String { route_build_or_run("run", body) } + +// ── Engram reasoning proxy ─────────────────────────────────────────────────── + +fn route_reason(body: String) -> String { + let url: String = cfg_engram_url() + "/api/reason" + let resp: String = http_post(url, body) + if str_eq(resp, "") { return jerr("engram unreachable") } + resp +} + +fn route_activate_preview(query: String) -> String { + let type_name: String = query_get(query, "type_name") + let q: String = query_get(query, "query") + let url: String = cfg_engram_url() + "/api/activate-preview" + let body: String = "{\"type_name\":" + jstr(type_name) + ",\"query\":" + jstr(q) + ",\"limit\":5}" + let resp: String = http_post(url, body) + if str_eq(resp, "") { + return "{\"count\":0,\"nodes\":[],\"connected\":false}" + } + resp +} + +// ── Index page (minimal placeholder; the real bundle lives in ide/index.html) ─ + +fn route_index() -> String { + let path: String = cfg_project_path() + "/ide/index.html" + let html: String = fs_read(path) + if !str_eq(html, "") { return html } + "el-ide

el-ide

Backend running. UI bundle missing at " + path + ".

" +} + +// ── Health ─────────────────────────────────────────────────────────────────── + +fn route_health() -> String { + "{\"status\":\"ok\",\"engine\":\"el-ide-server\"}" +} + +// ── Dispatcher ─────────────────────────────────────────────────────────────── + +fn handle_request(method: String, path: String, body: String) -> String { + let parsed: Map = split_path_query(path) + let route: String = parsed["path"] + let query: String = parsed["query"] + + if str_eq(route, "/") { return route_index() } + if str_eq(route, "/health") { return route_health() } + if str_eq(route, "/api/status") { return route_status() } + if str_eq(route, "/api/config") { return route_config() } + + // Files + if str_eq(route, "/api/files") { return route_files_list(query) } + if str_eq(route, "/api/file") { + if str_eq(method, "GET") { return route_file_read(query) } + if str_eq(method, "POST") { return route_file_write(body) } + } + + // Search — minimal stub (real impl needs recursive grep) + if str_eq(route, "/api/search") { + let q: String = query_get(query, "q") + return "{\"query\":" + jstr(q) + ",\"results\":[]}" + } + + // LSP + if str_eq(route, "/api/lsp/complete") { return route_lsp_complete(query) } + if str_eq(route, "/api/lsp/hover") { return route_lsp_hover(query) } + if str_eq(route, "/api/lsp/errors") { return route_lsp_errors(query) } + if str_eq(route, "/api/lsp/activate-preview") { return route_activate_preview(query) } + if str_eq(route, "/api/lsp/jsonrpc") { return route_lsp_jsonrpc(body) } + if str_eq(route, "/api/type-graph") { return route_type_graph(query) } + if str_eq(route, "/api/outline") { return route_outline(query) } + if str_eq(route, "/api/definition") { return route_definition(query) } + if str_eq(route, "/api/references") { return route_references(query) } + if str_eq(route, "/api/format") { return route_format(body) } + if str_eq(route, "/api/completions/snippet") { return route_snippets() } + + // Themes + if str_eq(route, "/api/themes") { return route_themes_list() } + if str_eq(route, "/api/themes/active") { return route_themes_set(body) } + + // Plugins + if str_eq(route, "/api/plugins") { return route_plugins_list() } + if str_eq(route, "/api/plugins/install") { return route_plugins_install(body) } + if str_eq(route, "/api/plugins/remove") { return route_plugins_remove(body) } + if str_eq(route, "/api/plugins/enable") { return route_plugins_enable(body) } + if str_eq(route, "/api/plugins/disable") { return route_plugins_disable(body) } + + // Settings + if str_eq(route, "/api/settings") { + if str_eq(method, "GET") { return route_settings_get() } + if str_eq(method, "POST") { return route_settings_save(body) } + if str_eq(method, "DELETE") { return route_settings_reset() } + } + + // Build / run + if str_eq(route, "/api/build") { return route_build(body) } + if str_eq(route, "/api/run") { return route_run(body) } + + // Reasoning proxy + if str_eq(route, "/api/reason") { return route_reason(body) } + + // Git — relies on shell exec; runtime gap. Stub returns empty. + if str_eq(route, "/api/git/status") { return "[]" } + if str_eq(route, "/api/git/diff") { return "\"\"" } + + "{\"error\":\"not found\",\"path\":" + jstr(route) + "}" +} + +// ── Entry ──────────────────────────────────────────────────────────────────── + +fn server_main() -> Void { + plugin_init() + let port: Int = cfg_port() + println("[el-ide-server] project=" + cfg_project_path()) + println("[el-ide-server] engram=" + cfg_engram_url()) + println("[el-ide-server] listening on http://0.0.0.0:" + int_to_str(port)) + http_set_handler("handle_request") + http_serve(port, "handle_request") +} + +server_main() diff --git a/ide/vessels/el-ide-server/src/_combined.err b/ide/vessels/el-ide-server/src/_combined.err new file mode 100644 index 0000000..e69de29 diff --git a/ide/vessels/el-ide-server/src/el-ide-server b/ide/vessels/el-ide-server/src/el-ide-server new file mode 100755 index 0000000000000000000000000000000000000000..55345e2bf33893dd272257b16a51c9c1ef8dbba3 GIT binary patch literal 168720 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

kq+M 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 literal 0 HcmV?d00001 diff --git a/ide/vessels/el-ide-server/src/el-ide-server-asan b/ide/vessels/el-ide-server/src/el-ide-server-asan new file mode 100755 index 0000000000000000000000000000000000000000..42f1470bb9b5c3cf5433d7f809bc0cbab5ec08e4 GIT binary patch literal 536384 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�r`ql!J8Stz!>j}E_gA-!xm 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 juX<#BgO`3?{$lMhlW(_~aynG%*GI + + + + CFBundleDevelopmentRegion + English + CFBundleIdentifier + com.apple.xcode.dsym.el-ide-server-asan + CFBundleInfoDictionaryVersion + 6.0 + CFBundlePackageType + dSYM + CFBundleSignature + ???? + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + + diff --git a/ide/vessels/el-ide-server/src/el-ide-server-asan.dSYM/Contents/Resources/DWARF/el-ide-server-asan b/ide/vessels/el-ide-server/src/el-ide-server-asan.dSYM/Contents/Resources/DWARF/el-ide-server-asan new file mode 100644 index 0000000000000000000000000000000000000000..bce9d7bf6d2d424edc18852011f4ebfaf8993a3a GIT binary patch literal 284560 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

cD?5dMH^p?ubpw0≪&Esg5flj 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 SeJfr0{jOWNZ#Qg)@qYj$# String { + let chars: [String] = native_string_chars(s) + let n: Int = native_list_len(chars) + let out: String = "\"" + let i: Int = 0 + while i < n { + let ch: String = native_list_get(chars, i) + if ch == "\"" { let out = out + "\\\"" } + else { if ch == "\\" { let out = out + "\\\\" } + else { if ch == "\n" { let out = out + "\\n" } + else { if ch == "\r" { let out = out + "\\r" } + else { if ch == "\t" { let out = out + "\\t" } + else { let out = out + ch } } } } } + let i = i + 1 + } + out + "\"" +} + +fn jerr(msg: String) -> String { + "{\"error\":" + jstr(msg) + "}" +} + +fn ok_obj() -> String { + "{\"ok\":true}" +} + +// ── URL/query parsing ──────────────────────────────────────────────────────── + +fn url_decode(s: String) -> String { + let chars: [String] = native_string_chars(s) + let n: Int = native_list_len(chars) + let out: String = "" + let i: Int = 0 + while i < n { + let ch: String = native_list_get(chars, i) + if ch == "+" { + let out = out + " " + let i = i + 1 + } else { if ch == "%" { + // Read two hex digits + if i + 2 < n { + let hex: String = native_list_get(chars, i + 1) + native_list_get(chars, i + 2) + let code: Int = hex_to_int(hex) + let out = out + char_from_code(code) + let i = i + 3 + } else { + let out = out + ch + let i = i + 1 + } + } else { + let out = out + ch + let i = i + 1 + } } + } + out +} + +fn hex_digit(ch: String) -> Int { + if ch == "0" { return 0 } if ch == "1" { return 1 } + if ch == "2" { return 2 } if ch == "3" { return 3 } + if ch == "4" { return 4 } if ch == "5" { return 5 } + if ch == "6" { return 6 } if ch == "7" { return 7 } + if ch == "8" { return 8 } if ch == "9" { return 9 } + if ch == "a" { return 10 } if ch == "A" { return 10 } + if ch == "b" { return 11 } if ch == "B" { return 11 } + if ch == "c" { return 12 } if ch == "C" { return 12 } + if ch == "d" { return 13 } if ch == "D" { return 13 } + if ch == "e" { return 14 } if ch == "E" { return 14 } + if ch == "f" { return 15 } if ch == "F" { return 15 } + -1 +} + +fn hex_to_int(hex: String) -> Int { + let chars: [String] = native_string_chars(hex) + let n: Int = native_list_len(chars) + let acc: Int = 0 + let i: Int = 0 + while i < n { + let d: Int = hex_digit(native_list_get(chars, i)) + if d < 0 { return acc } + let acc = acc * 16 + d + let i = i + 1 + } + acc +} + +// Map an ASCII code point back to its single-byte string. Above 127 the +// runtime would need char_from_code(>127) → multi-byte; we only need +// printable ASCII for query strings here. +fn char_from_code(code: Int) -> String { + let table: String = " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~" + if code < 32 { return " " } + if code > 126 { return "?" } + str_slice(table, code - 32, code - 31) +} + +fn split_path_query(path: String) -> Map { + let q: Int = str_index_of(path, "?") + if q < 0 { return { "path": path, "query": "" } } + { "path": str_slice(path, 0, q), "query": str_slice(path, q + 1, str_len(path)) } +} + +// query_get: pull the value of a single key out of `a=1&b=hello%20world`. +fn query_get(query: String, key: String) -> String { + if str_eq(query, "") { return "" } + let pairs: [String] = str_split(query, "&") + let n: Int = native_list_len(pairs) + let prefix: String = key + "=" + let i: Int = 0 + while i < n { + let pair: String = native_list_get(pairs, i) + if str_starts_with(pair, prefix) { + return url_decode(str_slice(pair, str_len(prefix), str_len(pair))) + } + if str_eq(pair, key) { + return "" + } + let i = i + 1 + } + "" +} + +// ── Configuration ──────────────────────────────────────────────────────────── + +fn cfg_port() -> Int { + let p: String = env("EL_IDE_PORT") + if str_eq(p, "") { return 7771 } + str_to_int(p) +} + +fn cfg_project_path() -> String { + let p: String = env("EL_IDE_PROJECT_PATH") + if str_eq(p, "") { return "." } + p +} + +fn cfg_engram_url() -> String { + let u: String = env("EL_ENGRAM_URL") + if str_eq(u, "") { return "http://localhost:8742" } + u +} + +fn cfg_el_binary() -> String { + let b: String = env("EL_BINARY") + if str_eq(b, "") { return "el" } + b +} + +// ── Path safety ────────────────────────────────────────────────────────────── + +fn safe_join(rel: String) -> String { + let root: String = cfg_project_path() + // Reject obvious traversals. + if str_contains(rel, "..") { return "" } + if str_starts_with(rel, "/") { return "" } + if str_eq(rel, ".") { return root } + root + "/" + rel +} + +// ── Status route ───────────────────────────────────────────────────────────── + +fn route_status() -> String { + let parts: [String] = native_list_empty() + let parts = native_list_append(parts, "\"project_name\":" + jstr(cfg_project_path())) + let parts = native_list_append(parts, "\"project_path\":" + jstr(cfg_project_path())) + let parts = native_list_append(parts, "\"version\":" + jstr("0.1.0")) + let parts = native_list_append(parts, "\"engine\":" + jstr("el-ide")) + "{" + list_join(parts, ",") + "}" +} + +// ── Config route ───────────────────────────────────────────────────────────── + +fn route_config() -> String { + let parts: [String] = native_list_empty() + let parts = native_list_append(parts, "\"port\":" + int_to_str(cfg_port())) + let parts = native_list_append(parts, "\"project_path\":" + jstr(cfg_project_path())) + let parts = native_list_append(parts, "\"engram_url\":" + jstr(cfg_engram_url())) + let parts = native_list_append(parts, "\"el_binary\":" + jstr(cfg_el_binary())) + "{" + list_join(parts, ",") + "}" +} + +// ── File API ───────────────────────────────────────────────────────────────── + +fn route_files_list(query: String) -> String { + let rel: String = query_get(query, "path") + if str_eq(rel, "") { let rel = "." } + let target: String = safe_join(rel) + if str_eq(target, "") { return jerr("path escapes project root") } + let entries: [String] = fs_list(target) + let n: Int = native_list_len(entries) + let out: String = "[" + let i: Int = 0 + while i < n { + let name: String = native_list_get(entries, i) + // Skip hidden + noise dirs + let skip: Bool = false + if str_starts_with(name, ".") { let skip = true } + if str_eq(name, "target") { let skip = true } + if str_eq(name, "node_modules") { let skip = true } + if str_eq(name, "dist") { let skip = true } + if !skip { + if i > 0 { + if !str_eq(out, "[") { let out = out + "," } + } + // Approximate is_dir by checking for an extension + let dot: Int = str_index_of(name, ".") + let is_dir: String = "false" + if dot < 0 { let is_dir = "true" } + let out = out + "{\"name\":" + jstr(name) + ",\"path\":" + jstr(rel + "/" + name) + ",\"is_dir\":" + is_dir + ",\"children\":null}" + } + let i = i + 1 + } + out + "]" +} + +fn route_file_read(query: String) -> String { + let rel: String = query_get(query, "path") + if str_eq(rel, "") { return jerr("missing path parameter") } + let target: String = safe_join(rel) + if str_eq(target, "") { return jerr("path escapes project root") } + let content: String = fs_read(target) + "{\"path\":" + jstr(rel) + ",\"content\":" + jstr(content) + "}" +} + +fn route_file_write(body: String) -> String { + let rel: String = json_get_string(body, "path") + let content: String = json_get_string(body, "content") + if str_eq(rel, "") { return jerr("missing path") } + let target: String = safe_join(rel) + if str_eq(target, "") { return jerr("path escapes project root") } + let ok: Bool = fs_write(target, content) + if ok { return ok_obj() } + jerr("cannot write file") +} + +// ── LSP routes (delegate to inlined lsp_* functions) ───────────────────────── + +fn route_lsp_complete(query: String) -> String { + let source: String = query_get(query, "source") + let pos: Int = str_to_int(query_get(query, "pos")) + lsp_complete(source, pos) +} + +fn route_lsp_hover(query: String) -> String { + let source: String = query_get(query, "source") + let pos: Int = str_to_int(query_get(query, "pos")) + lsp_hover(source, pos) +} + +fn route_lsp_errors(query: String) -> String { + let source: String = query_get(query, "source") + lsp_diagnostics(source) +} + +fn route_lsp_jsonrpc(body: String) -> String { + let method: String = json_get_string(body, "method") + let params_raw: String = json_get_raw(body, "params") + let id_val: String = json_get_raw(body, "id") + if str_eq(id_val, "") { let id_val = "null" } + let result: String = lsp_jsonrpc(method, params_raw) + "{\"jsonrpc\":\"2.0\",\"id\":" + id_val + ",\"result\":" + result + "}" +} + +fn route_outline(query: String) -> String { + let source: String = query_get(query, "source") + lsp_outline(source) +} + +fn route_definition(query: String) -> String { + let source: String = query_get(query, "source") + let pos: Int = str_to_int(query_get(query, "pos")) + lsp_definition(source, pos) +} + +fn route_references(query: String) -> String { + let source: String = query_get(query, "source") + let pos: Int = str_to_int(query_get(query, "pos")) + lsp_references(source, pos) +} + +fn route_format(body: String) -> String { + let content: String = json_get_string(body, "content") + lsp_format(content) +} + +fn route_type_graph(query: String) -> String { + let source: String = query_get(query, "source") + lsp_type_graph(source) +} + +// ── Themes ─────────────────────────────────────────────────────────────────── + +fn active_theme() -> String { + let t: String = state_get("ide/active_theme") + if str_eq(t, "") { return "dark" } + t +} + +fn route_themes_list() -> String { + let active: String = active_theme() + let names: [String] = native_list_empty() + let names = native_list_append(names, "dark") + let names = native_list_append(names, "light") + let names = native_list_append(names, "neuron") + let names = native_list_append(names, "high-contrast") + let labels: [String] = native_list_empty() + let labels = native_list_append(labels, "Dark") + let labels = native_list_append(labels, "Light") + let labels = native_list_append(labels, "Neuron") + let labels = native_list_append(labels, "High Contrast") + let n: Int = native_list_len(names) + let out: String = "[" + let i: Int = 0 + while i < n { + if i > 0 { let out = out + "," } + let nm: String = native_list_get(names, i) + let lbl: String = native_list_get(labels, i) + let act: String = "false" + if str_eq(nm, active) { let act = "true" } + let out = out + "{\"name\":" + jstr(nm) + ",\"label\":" + jstr(lbl) + ",\"active\":" + act + "}" + let i = i + 1 + } + out + "]" +} + +fn route_themes_set(body: String) -> String { + let name: String = json_get_string(body, "name") + let valid: Bool = false + if str_eq(name, "dark") { let valid = true } + if str_eq(name, "light") { let valid = true } + if str_eq(name, "neuron") { let valid = true } + if str_eq(name, "high-contrast") { let valid = true } + if !valid { return jerr("unknown theme: " + name) } + state_set("ide/active_theme", name) + "{\"ok\":true,\"active\":" + jstr(name) + "}" +} + +// ── Plugins (delegate to plugin_* in plugin-host) ──────────────────────────── + +fn route_plugins_list() -> String { plugin_list_json() } + +fn route_plugins_install(body: String) -> String { + plugin_install(json_get_string(body, "name")) +} + +fn route_plugins_remove(body: String) -> String { + plugin_remove(json_get_string(body, "name")) +} + +fn route_plugins_enable(body: String) -> String { + plugin_enable(json_get_string(body, "name")) +} + +fn route_plugins_disable(body: String) -> String { + plugin_disable(json_get_string(body, "name")) +} + +// ── Snippets ───────────────────────────────────────────────────────────────── + +fn route_snippets() -> String { + let snips: [String] = native_list_empty() + let snips = native_list_append(snips, "{\"label\":\"fn\",\"description\":\"Function definition\",\"body\":\"fn ${1:name}(${2:params}) -> ${3:Ret} {\\n\\t${4:body}\\n}\"}") + let snips = native_list_append(snips, "{\"label\":\"type\",\"description\":\"Struct\",\"body\":\"type ${1:Name} {\\n\\t${2:field}: ${3:Type},\\n}\"}") + let snips = native_list_append(snips, "{\"label\":\"enum\",\"description\":\"Enum\",\"body\":\"enum ${1:Name} {\\n\\t${2:Variant},\\n}\"}") + let snips = native_list_append(snips, "{\"label\":\"match\",\"description\":\"Match expression\",\"body\":\"match ${1:expr} {\\n\\t${2:pat} => ${3:body},\\n\\t_ => ${4:default},\\n}\"}") + let snips = native_list_append(snips, "{\"label\":\"let\",\"description\":\"Let binding\",\"body\":\"let ${1:name}: ${2:Type} = ${3:value}\"}") + let snips = native_list_append(snips, "{\"label\":\"if\",\"description\":\"If expression\",\"body\":\"if ${1:cond} {\\n\\t${2:body}\\n}\"}") + let snips = native_list_append(snips, "{\"label\":\"for\",\"description\":\"For loop\",\"body\":\"for ${1:item} in ${2:iter} {\\n\\t${3:body}\\n}\"}") + let snips = native_list_append(snips, "{\"label\":\"activate\",\"description\":\"Activate\",\"body\":\"activate ${1:Type}\"}") + "[" + list_join(snips, ",") + "]" +} + +// ── Settings (file-backed) ─────────────────────────────────────────────────── + +fn settings_path() -> String { + let home: String = env("HOME") + if str_eq(home, "") { let home = "/tmp" } + home + "/.el-ide/settings.json" +} + +fn default_settings_json() -> String { + "{\"theme\":\"dark\",\"fontSize\":13,\"tabSize\":4,\"wordWrap\":false,\"formatOnSave\":false,\"vimMode\":false,\"minimap\":true,\"elBinaryPath\":\"el\",\"engramUrl\":\"http://localhost:8742\",\"stickyScroll\":true,\"lineNumbers\":true,\"bracketMatching\":true}" +} + +fn route_settings_get() -> String { + let s: String = fs_read(settings_path()) + if str_eq(s, "") { return default_settings_json() } + s +} + +fn route_settings_save(body: String) -> String { + // Body is { "settings": {...} } — extract the inner blob. + let blob: String = json_get_raw(body, "settings") + if str_eq(blob, "") { return jerr("missing settings") } + fs_write(settings_path(), blob) + blob +} + +fn route_settings_reset() -> String { + fs_write(settings_path(), default_settings_json()) + default_settings_json() +} + +// ── Build / run (synchronous; no SSE in current http_serve runtime) ────────── +// +// The Rust crate spawned `el build/run` and streamed output as SSE events. +// El's `http_serve` is request/response only — handlers return one string. +// We call the el binary, capture stdout via fs_read of a redirected temp +// file, and return JSON. Streaming is a runtime gap (see report). + +fn route_build_or_run(action: String, body: String) -> String { + let rel_file: String = json_get_string(body, "file") + if str_eq(rel_file, "") { let rel_file = "src/main.el" } + let target: String = safe_join(rel_file) + if str_eq(target, "") { return jerr("path escapes project root") } + // No process-spawn primitive in the runtime; this is a stub that + // documents the planned behaviour. See report for runtime gap. + "{\"event\":\"info\",\"action\":" + jstr(action) + ",\"file\":" + jstr(rel_file) + ",\"note\":\"el-ide-server: synchronous build requires a runtime exec primitive — el binary not invoked\"}" +} + +fn route_build(body: String) -> String { route_build_or_run("build", body) } +fn route_run(body: String) -> String { route_build_or_run("run", body) } + +// ── Engram reasoning proxy ─────────────────────────────────────────────────── + +fn route_reason(body: String) -> String { + let url: String = cfg_engram_url() + "/api/reason" + let resp: String = http_post(url, body) + if str_eq(resp, "") { return jerr("engram unreachable") } + resp +} + +fn route_activate_preview(query: String) -> String { + let type_name: String = query_get(query, "type_name") + let q: String = query_get(query, "query") + let url: String = cfg_engram_url() + "/api/activate-preview" + let body: String = "{\"type_name\":" + jstr(type_name) + ",\"query\":" + jstr(q) + ",\"limit\":5}" + let resp: String = http_post(url, body) + if str_eq(resp, "") { + return "{\"count\":0,\"nodes\":[],\"connected\":false}" + } + resp +} + +// ── Index page (minimal placeholder; the real bundle lives in ide/index.html) ─ + +fn route_index() -> String { + let path: String = cfg_project_path() + "/ide/index.html" + let html: String = fs_read(path) + if !str_eq(html, "") { return html } + "el-ide

el-ide

Backend running. UI bundle missing at " + path + ".

" +} + +// ── Health ─────────────────────────────────────────────────────────────────── + +fn route_health() -> String { + "{\"status\":\"ok\",\"engine\":\"el-ide-server\"}" +} + +// ── Dispatcher ─────────────────────────────────────────────────────────────── + +fn handle_request(method: String, path: String, body: String) -> String { + let parsed: Map = split_path_query(path) + let route: String = parsed["path"] + let query: String = parsed["query"] + + if str_eq(route, "/") { return route_index() } + if str_eq(route, "/health") { return route_health() } + if str_eq(route, "/api/status") { return route_status() } + if str_eq(route, "/api/config") { return route_config() } + + // Files + if str_eq(route, "/api/files") { return route_files_list(query) } + if str_eq(route, "/api/file") { + if str_eq(method, "GET") { return route_file_read(query) } + if str_eq(method, "POST") { return route_file_write(body) } + } + + // Search — minimal stub (real impl needs recursive grep) + if str_eq(route, "/api/search") { + let q: String = query_get(query, "q") + return "{\"query\":" + jstr(q) + ",\"results\":[]}" + } + + // LSP + if str_eq(route, "/api/lsp/complete") { return route_lsp_complete(query) } + if str_eq(route, "/api/lsp/hover") { return route_lsp_hover(query) } + if str_eq(route, "/api/lsp/errors") { return route_lsp_errors(query) } + if str_eq(route, "/api/lsp/activate-preview") { return route_activate_preview(query) } + if str_eq(route, "/api/lsp/jsonrpc") { return route_lsp_jsonrpc(body) } + if str_eq(route, "/api/type-graph") { return route_type_graph(query) } + if str_eq(route, "/api/outline") { return route_outline(query) } + if str_eq(route, "/api/definition") { return route_definition(query) } + if str_eq(route, "/api/references") { return route_references(query) } + if str_eq(route, "/api/format") { return route_format(body) } + if str_eq(route, "/api/completions/snippet") { return route_snippets() } + + // Themes + if str_eq(route, "/api/themes") { return route_themes_list() } + if str_eq(route, "/api/themes/active") { return route_themes_set(body) } + + // Plugins + if str_eq(route, "/api/plugins") { return route_plugins_list() } + if str_eq(route, "/api/plugins/install") { return route_plugins_install(body) } + if str_eq(route, "/api/plugins/remove") { return route_plugins_remove(body) } + if str_eq(route, "/api/plugins/enable") { return route_plugins_enable(body) } + if str_eq(route, "/api/plugins/disable") { return route_plugins_disable(body) } + + // Settings + if str_eq(route, "/api/settings") { + if str_eq(method, "GET") { return route_settings_get() } + if str_eq(method, "POST") { return route_settings_save(body) } + if str_eq(method, "DELETE") { return route_settings_reset() } + } + + // Build / run + if str_eq(route, "/api/build") { return route_build(body) } + if str_eq(route, "/api/run") { return route_run(body) } + + // Reasoning proxy + if str_eq(route, "/api/reason") { return route_reason(body) } + + // Git — relies on shell exec; runtime gap. Stub returns empty. + if str_eq(route, "/api/git/status") { return "[]" } + if str_eq(route, "/api/git/diff") { return "\"\"" } + + "{\"error\":\"not found\",\"path\":" + jstr(route) + "}" +} + +// ── Entry ──────────────────────────────────────────────────────────────────── + +fn server_main() -> Void { + plugin_init() + let port: Int = cfg_port() + println("[el-ide-server] project=" + cfg_project_path()) + println("[el-ide-server] engram=" + cfg_engram_url()) + println("[el-ide-server] listening on http://0.0.0.0:" + int_to_str(port)) + http_set_handler("handle_request") + http_serve(port, "handle_request") +} + +server_main() diff --git a/ide/vessels/el-lsp/manifest.el b/ide/vessels/el-lsp/manifest.el new file mode 100644 index 0000000..925ed68 --- /dev/null +++ b/ide/vessels/el-lsp/manifest.el @@ -0,0 +1,17 @@ +// manifest.el — el-lsp vessel +// +// Language Server core for the El language. Exposes hover, completion, +// diagnostics, outline, format, and type-graph entry points consumed by +// el-ide-server (HTTP) and stdio-mode editors. + +vessel "el-lsp" { + version "0.1.0" + description "El language server: completion, hover, diagnostics, outline, format, type graph." + authors ["Will Anderson "] + edition "2026" +} + +build { + entry "src/main.el" + output "dist/" +} diff --git a/ide/vessels/el-lsp/src/el-lsp b/ide/vessels/el-lsp/src/el-lsp new file mode 100755 index 0000000000000000000000000000000000000000..49c1fa91aa7cd91c825f00faa9a3bd7847e82ed9 GIT binary patch literal 148376 zcmce<34B%6)%Snyy#a2*OzurW0wlqSfa1VlP?XD{GN@IImD(Xetqq`7iZfU)gEkuV z;V2FTTY~NLl$>fCTTp3j4Gt|8+XiUS_GxQSpBjtp|XI~B>&_4h7^S*pO zVehktwbx#It+m%)d$@o6^u5n}IZnjkUzERG{#JBzoI9KnVvaMAzp4CHR$esmymKx; zXXY1_dgwn>`Ou`pz69qr3RYHDoHMK9&}>sb-3dzY4JwZPQ?1I%8@_(a4F~IYhSx-4 zL0VDn!_&9=mHC(Dq%(0Mm6Z!_xbcbwnWWC}s?LrWcyGo0BKi))iwE$aq4`%?dF6r| zzBT8%Z)Cm??eCOHKD?=e{Q~+9{|m!bI`F=E-GYN1?u_4xN*`Wb07TzeLAKN7sU0E`2?FkT01`mxH&D;6B&w!`7oZ3@Oy9SZ)1;n`+v z-a+|1f7*pJ&Y3dJr#{(H$CORml75dKne2ZnFAQt6rPraD@ZHx(;}ob$AYwB ze%k&4&dQWcJH=1?gtWS7P_Eoh+e;cm^V>-IY44F%6$#R&`e`ksH9A4sMSj|wg6BBv zOPut~0}ChC@B6~@>l$N~I}E?{LX!S58U_JK3Dm5ey{d{ z%W!W?I8LHDmhd)GZYSjwf62#XJ#DXWuF7_ILYH&NR~_NfgE}U!$%NW8F=O$APJR3I8^5e?tBlltd|4D)#2C}8`UA0uyDt{;G_HR( zoNlY5Mia**UJ#V8}$gheN!;EAHm(c`xEr zyw=^>+8j%IJ4tJxZaXl(3BHY=cYymq??=R|g80r@zIQ9_HXl%4E_L#}H-LL!;S_M3 z46c*Fd1C#i-*{;qbWa?q49nQ0r>5ieh&0*qW-6}KPJ=9Lhss4KMM^lCItPoa1p)4 zF!&)il3QCHb=EJA=CuxozCP`8z1acnN-{79db2Vx2O5~eO@Ey|E%2}4v=}-j$jgV0 zxn0t6A$06`A+q(;Z$zPO3>s%a>u&Hv_xc0NBFMN;%ZmeA<~2M3KP0@1z~^;nQwxsb zmjwJj4*bjcJDtA`&}+lFKJV?M{Hc`R2_HlP96#y)@T&6sM^>%u?zpc<6Rn#*@2EhR zCRA52)=@t`JI8IgGE#5i7Z9&>>Qm&+NH{AGEIb!H&jH^l;5`|hm{dpQ6njS7f_}r@xis{*v#73v*mE zM&HSCf5G?V|B>TvBpkOo$Cd0h!=r2ZOC}s|1ASQ&O|~{>Y23uWN$+8LL6QKAn=|K5fzmdQLd~hdJ((q#K>}c#d1LUvd)Ec_zp8 z$dm3c^xBl;E{WBwdJR2h`z2ftEIbE#Oo1+wq0c1fG_ijFH-BSvVOYof6yA~!`#F7G z04>y?uN$1iN51}?-QP)keA%yn$9%9b3cqMhh<5B6;;k7$*=Z(Jev&pP(auEheqr5Y+708XHkWnL=C}aP>4b)6v^ko%##?RH zW#CK4_6m(-`vw3WaEG9=?=8uJ< zMZMe}HhxtvH_OJ;z1)b6KibRve0tFL#$N7cHvXqxZkvto?&W@D<5|7ky*A#jxBG#O zAKTk~*T%>9c6Zr$MQ`_?HhxQQ_e~pL+1qWl@n?Fwf4A|b-tJ#*d|z+(RU7Zu$NiIy z59;G?web`CxPP$mseKsZP3vBsesEkj+q_wQ+!t-Ux{tew_!7t2U7GIW{@TVL?c@H^ z#vA&$&)E2jecTN;{+i#$leBTDygQzOM?2TTi)m~h{&qVpeO%TR36n>=MrVcdQ+?eL zHXmG+|J88*qkY|DY(DrY|I%=NQ(u?$fe#;?m487vKi<#HwfXcz`R9c5Q~g}lGk$&g zru?(WuL1Y?_xiba5thx)cBR8hA~mb5-q4&D?*Da`KKuK*bBRAdy#+)18{6_~o435b zdnIw%o3m}&qy62l+49f(*?7MJZiS6k3~(>D@$>-qLL2|n0CxuQm9)Jw znoHXW?>w7Vk?T$&uCz%u?S@=;f{j0#>yEeaiiA7P#?uLRtc~|dx}$77m2^+B@mG@W zNjBaq&mC^#EAreEY_bYavvGG)~yTQgAirt^t_`AjKPi_3F68CW%zo*2lxA9@6?tj^MMXCD( z8~OO4a9;<88;dwKjhKv2Klx z-*c>chm98;=PtGJ^N({E+xRQTxr=N(>v;E88?QOuy~)NOKi*wnur4e3GTHv z{*=FYb9(Pi$}Y`mh({j!a3E^}wu_-keEr8b@#?#?7G z9deOPyK1<50db>q?j8;=SsL(LK$^r=H}VY~wX2xhL9qVx(JUI{DxEA{x<%@Q{6r`e$i=ePa9u;nj5$AmebsBHr{I#bEI!q zI@69YhhYOf+b1-KJv++9Z{^Ps*hHEm)`#;S9qs@_!i4 zA3xSbj(zypQ_6odoPXl!?madi8%y~s!}e1*e!*Gp`8FTBQu!6({MXKMr`UY#OXZ(`NdDO_eoCLd*n7&K63%~Qf;-yg zV*@IGe2{N!=o=jOM4OMzr~J|3{Hr4Fu{Iw&Q28f@^Zyia2ibh=LFFGC&aa5N37d~y ztNcOax7c+-ub5kdKh4-s*t*J3bjr`zDG}Kz=|k+4uGS>e`uc0`l<>%M)(d88s=p39 zolt9)o~)U*hSoa#VQdQdl(N86>x|b~Q{(hzO)XzW(i=jZHp>3}(~gIo4y}O;yyR#2 zz>FWMz^t|3?u|dveEVykH_RIH&@~BkPZ&MMnqN3|UbD#V>WIa*?*C?Y*2z6s$HZCB zWV5cxVZGIp^;Xn1bYi{!_7L9(5Cb=@o4OG;pX{{jTkFjTq1L(`=lQrFAe1kxLq3!~ zPDLU8HvWc7Vv^t8k6xMW;u%itrJTQBRlf?o_k;Q!(ZbfoUZP2!N&gG!A3$IEHZI3E zB|pP@Xn+sZ(0eEGH^@^zXS3Ej!1sf!Jym`uK7`eLR~cV}e0BKyfakBxZOA=Hiz0+OB-+Ty(rYiQod84GF~UA+SSG{fhihkTn!!3XD^1~ z-x70|h2S@Ig8vHNSB2ou75q;Q!v8^M_~^sO!|+$c+4av=#dco(nxxy=y!ey z{!GE&cMyJUXZXnbO5hv+%a|;;HMy zUC^cF1gE|Z+TD-L99TF5UYicjO@sHQ!h`4Gt2wtGo-}^0u4K*n>t=(S^0u$zW^9e-@`E-6B zDmO1EH^+p^ALw13i5Gakrw!@2@VM8KpJ}%)%Uu(KcUb`MQWNHRmk>U}n%&fYEz4#5 zFX8K&gy#nJRyt0T^&OsP>Lt8$OelPk-lR-C->U~7@k^R9a^B5y(*X>|vdNC+SW`af zjV7esrc!)?rxLgR$F~P*tbN!cGO!cg{lGTm|CZx^sn{=L+R5tXmin-Em-gz0o!7Nr zwV)UN^;ncSB#QjTkmD@mxf^nge|=#O=8%Zn+|y})w7uhD^`QcOZ|>`~n>GWP63)W& zdT@~}k7TYB{j2#lem>?-(S9Iuy9ydyp5M*P@!~(pRxUbBK4^Vc9_V=Z%^)tl{sw<< zq5n^zjNkt}@6w>1am*vdv4O4ZuQAW$18bl+fjsg47&BM+@C(7O4qx;>lfw{d(Yqiq~N$*IKEzY_`7-x1x}Z{b^W=7(=bes;;I z2lkHo@PoYt@R9m>V?ZCpzeQaAGGjKno4dZJv(on8;K`ix27MC^KKT3~4HC2^T5B$y z5G!nDj)MmN9Q^q?J`Hx!@BQet8|nMbzNz-tfbHurpDr5&5Bw&AU+E`r?|qPbjl-*& zgLyYv8fF^qH8u0G+6Qn(wBV_E(u3bG>Ubdb7Z5rESq*A3QT7?$e=U9 zXmBlRO|z%r<67ixr~E-bZjtv#zI|TE_cnsR@boo&E0on<$K`|>nOvm2LEfb%uK*pa zdU@W(LD?@5`eTx>zBiScF-ds)pwU~VO|@OjN{3~2LX z_(Oe`JQ!Q*>2AiB6hBXh<+rkd7tm**S4$n~S>^dO8|d9hny=prz3T%S%?3x&h&{FS z(z&A1S>RK8NA0$q7eBLi?U0xDE@6xZQBE{6{PvpqUFhYLX2vwDyPF^`+iU=#-)F%Z zgd7&ZgSp;?wvW(fLD0u-^wHFBi-9A2gN`urAM{u9VCCQRx2U^o^gyWJlH+ExFXhYe z1wkLngZ`C)kNUUH@PN<1-M}UC>auNXum9EF(wtZKZlZs0<%IfoQOwwxuaoA_*V@x6 z^8TA|D`UQnIXISiq5hp2^iO+K{@&Di=*4r^f;=OfA1R`zm4mmSDc(04=6m6XLs-q1u{!85!)t2<+#>p9F@ zcHaCg`5E5F29S)jF*bgFuJ>FxKi%D5J25_I0%JG&>lyMzI}885pl;X}m;x?>JBiTD z@5UxedS~-384&*IOq&U>JSacbgvu}QMrGpp-l{N8;5p3Aj4rKeZ z`OJiVU)wVAe6KQS)9~C4-QeLoZ@0`G=zlHwW{j9GYE0QY?@q!nO@13{W3efd@NPF@(pyOA>!n=pSD|t@2IUr* zP`KoI*JtAS-mBn}X#@HENvQ7CLEWoNnDnk7G&mx^l^Gbh-fw_GdQ&O(^1XpgZRm-; ze5tKt?Bzq(mKSCp?L1G6^;?wnTLjy|@qR)Zvi}U+7rVR513b-m1Z%f50zAtJS-Uma zwcBXE?YiowO#hPJ$e{d*CKPQ7y|PSvptpiH)wXH#t?uqOLUoISx`R!a=M@p!b=6lx z<&r_UTobB|fnL8%yuiDeHUjo1Cf~w>*Fwrq}zXeA0WD(2O7Jqg}*(*zALbU?-6s<2U=ObbPM& zdZ?{)JGC`9)Q3L@ZEO#<(PYwcy+34NB)l=euspQC$nS^cp%?wS!J6yvb79ZMS#M3& zdMk$gkcA!54SS+Hb_Hv#g>lXwMBUN=#{xq2uaNLLXgOmjc43E8-_a4l=5X3`nRh$# zop#yRn$LB<3Hz$)(erX#&8a%8)C*e3e%k_G+PD2MpRcL)ubDb(tAR4Y zZL{WW+Ejb-ZfjN*_H^7c!RbxkUTiA8KF9q}%E||*@`9=PUS&S{aTgY zrvrHE+pUxl9QEtW*mqZ1T7DQS_MV`e#ZCQSps*VQ{LwFSsoRWS!Io)ZZ4>Y2xGk)w ze;+Q3{;3Sgs!TC{Y@Jo4>{gX+4419y;Z{&qKF$nW)+GimYcSz%l}*)vV0Q+t^8 zc39;)jf=@-sCig>hzsdzbI7x6w2GNx|j7%Fi$l(7sWGl=VbY| z7=PEZja}IiF3hS83_2?z{fsZ@#O+Ppv+YDd4+}=@P@Z)>V3?7sQKcZiJ7^n$-%GK_)*4gX|O)Dn|k=R;SGf7{e}&J-F!XYcCPwaP)|B)Zcx73 zg#KLh^-LU}ByDEqs+HO94?=an9Mt`i36tJsgqk~LZ+tgY?&6@_7fh)90`L4x9G@g@ z$c}-h8#Eu@9jZGisGBk&_CKNKINASR1_t(jCeArc;4yX$vQ4fo%*-oI4!UC`<;=Jm z+vM>;%Gi*1DAcEuNU|>)DqefKFbI-$7rse(a)*ST8{m#rcY+ZT>K_Y1y{!0 z?-Gt%X!d;?wC}^(z2WkX95=_zEk*bS^1N?n{Bud~S__kPUtMp_DgIgMS)^ZwY|3|` zb)oz)qv%&7Yhn4qs)+l0Kt*N`Xc6BD)?O+vxkiSAJs|voM&9KIDDZ}o-W)`4q&lI^W!kAb=mGa$~SvJMP7agmij094Gd^%+J;yD zp6{>ETOFsu(jvmRawdFbpP;PhEtU^n)B6L_eI*C_I(ko|EVKclrQ1?z_a_O z;+0i=Yu?rQ@s-i|mK65ML-3LKOZ^iccJ`&Tc9+k!>%G&X$&319W#$p+DOp($ZjzO! z2-Qc~WVQ57dsp)HA}j4d;Y^L%D*Zp?OP?K@mQ_o1HJ=tUUT&vCw`XVup9 zpq}(|G$_x-w2Ym9pxdE3t(|X!EBfwZ;(;z@p3Qbo55fAt)Ju5pnK0?KnlRVfWkSF0 ze-bzRf0VtBzjwp-UMAZ+i#e|wb6>bUY!XCdfzAXea5+7 zbEw=SLAi%aC|VYI4`kwn-lr2nZ7`2+4b{CXsQVog4)pFIv~B!0RBmxl?sgOUZQPcL z<6owYjQxUr@Jy)g^+Db1OgPZHhA`9TUODa)p|W2O%3f(gwNvO-W#YNsZ^P}JnB#sw zRQHQP-3k*9^kxzoewv!&ejxuKjK7bgefQPy_cH(o1n~9!CFsufBe0Zgm*f5 zC7E$A@?OhQJ4N0O6RJLEoF^Euiq#qT_hG|8)#wZ0)3zYSo#WWqt-3xwiP`8K+R z%Ka)R_e&G{{P|2Kp74spZ6IqO@3rz=A^%jI+{S{bN-qtb?hvjV!<&3PL^RKpbic;;rr%p36rulh9Ye$8A z1IA`$Zq_~|^CaV%+nRbu`w7}J&Gnw7j%}gSsb~aF92GP;Cg$ zYeVIZ3(6g1LcfiYOq~6ogKac8v$EW;h3e)7brU8WR8nm7Pwm+_n9s0qHYjbg`{cF_GocplsP{#5D z+70-p!MO(iLVyQ@l)1b0wyB@+{)Z6TWQAQj!YjbV{};eFeWC6D=G)@+8gZjHX!}pV z4s4JH2VYlSrq2oQ4+ciUd&PuF?`0F_d7Dir8svH}5jVVQY>;W#6;rV<&cn_)7klFz z*4R_(u|M2j#;`-U)42be5z@Q9*Qj$q21nLxZQLgmjtOWZy_P2$VW*h>RB4a1!22)S z&ftEFpSG5?U=7^huqIKtM@f@h{FuFY>0#+c?L!;+=-bWQ|InSiEIWsxXWP&6+Z)Y# zL;KLrMF+Ol;p0%BW#7I*ejDSic@F+rFWLDO?WDPHEm(#o(A^`gIk+!q`o^B-f0C9u znATAGXpZ|6(sW)UsB8G=S(W=td)tG&9mJzqy0<&X*!_F?R@>T#HtPnyrK^>1)(w37 zc8Pzd@gctBP7$(>&c%mpWIL`gu%sMXNl`;lTQTEZG zzRJzO?;u!)_c<%7dG-sGN%wFz)G{^(Cbq$MY#iHQxs78REU|HHgKyh7w!uOh$2Pdd z#<2}w$4>%}67J4x?ejY89?jq4o7q9#R@OnbuEpQy zt9Xd5bfUOj=tnRPM*f+$N2Ch>+!Z43GXTsvj0aYTuRVa ze+a?&N+zD?y%4}tzof@A^UONdTp`$BFm@n^5#hdZ|o2 z&-)SWnQ>x1ye{d})Xqs`DMwy|e^&2so*Nnc*ZW4|hc`dycv$ncX$O85&Q+G5S<4*F z_ba|W$VUn9a>iO`|84?r!M=sCnf<1H%sp!~ha`R5TC&)J?%ao+xCZ;bIlP(0^ zt#k1~OUKXT+xK%xzYp}T<6Co35%@D_Je}tZtmS;ko_T@KWh^kouOGc{->4YqodkT& z|F1`f0nWeY|CeY%?F9C?evIE+dj~Dicn-er`8)X@6X0cd5nk^Z@WDRj*fz%9@OH4* z`y4iqV*_T|g!1%Uvy^VZ}N1LJBaRz7c41Q%(UhyKYkajXM1<&sRPhS=}{~N&l zkqL9X|0EQxBt!i(@QS=O8F=|#_W+*ghF{K|1|{r{s8uh0QP-^l0D(n6e?E} zl>5l^oAG6xx6GueY@V0S#Phwk&pgQgKVfcDKP>;>L^;d<3v3C%nwn354U75tH``dB(R1%%jP`CA&NFJHHw55w@6g zgTZgJbZpZ57U$8#%O=gt*GY2*S$u8M_W8Q_TH0@B&(G)QL*EG)iZ9iat?=*ZTyd1L zbJ&+LWrI6Cmr=GcfE#{$U`|_5&hhWYTyTVPn?4Q7Rr%#6AE8_;=h{rWO@6s?N5S#< z&x5k3`1g879;NK>ZP^um*<+5-e&REYd#*Ps;5oxDFZOodaRPohMR%|dzP<1kvfB}h zZ0-E+z)vY3jE$M+d(fWdL+M82552vQ+wx_nz63e{GI9~NBYm9E=Myw2FN{vDP5eB-}n>~p;`+VkZn=^anp*HQR;>CO0x7Xn*)m9a7X+0J(gdk?+Suwh3Z7hikBj=g<+U;Bl9wU^USfPHU#iVOSt zdpOVab@At{Sjf6f`oN6yGu(UU{FeAVlZJ2cDbmF6N|P@8n>i<{Z|;AAk6+&RNiPEz z+15#rDQX_DzXX!Q-!fKJPniGVhtBfKxKwNu<~l zDk4W5qep6M$7E-#sW*giMMW|4tTiWfh->E`vtVu)q1H~eGJ|a zNN_)I0(&~SktOEco+NGfwn45pfVgC)z)99R*m3^}yb{h9pzFtJPL#~)-rQrFBcjP# z@tXF4zR!2Z-12hGrC~YNJ0GH_q0L!7jnf+ImVWNFf{pBdg)jw;O8K*6_ZDfiIlqND zL}S++iw_r^Vkgq7H2WRqJMooxfw^q`ME;tYLv$bM@4)h9Uu)-t_j&-k*}y(XyOyB- zRL;9}o{zNNEQJmqadwBcJ@_P$O?(grUZQmlW1{x;2GF`_qSlExTa2IUkoFGhP4y=Q zFKh^S?tXNT^r(HeE{)M!nFcevWaD9Tuj`bHxk~3#BZXEu^A~RJv@^%+0Kp7QEM{C$wLm3 z-ua}bxqCY7%KX(%HfN~8zlyrD4<$cpN986_t^}Wr+G|J07RGY7NGJQUROoG?-l$k% ztzTa9mhb(Bv|FS3wYjmpAU)}w0vy3$-*N-`FkxkUag_Ia2Gp#A?i(!a^C+858NtjY zu6a~#+je`BCj0JaI=(9zUIbnmt9gW7>76S0Lv-IyzI2R}<+v+|Hyb|l>5^nzwNCj2 z+EnGG%7>EQnCFz^d)Tvtwegy{W6HJOv3+@ye1Bfl8%>9v89fqD&7_X-oJe>yJhzc= z@w}S&(eV6e+|lveNd5mUp2MgkJo5=V%Vu*opO%i38uuXje8UjVkVTx)jZXRL>!z2~ z#?MM^bRq)=)H%)=jc>%MnfU@ZLbuUXLsI39pLdMW_Y!wi|<)e-tu|J)9Z5L8TcyK3@qt@!N76?9U!{-Jj`8A(j`mJbb8M;|0!D9P;j&KDW}rvoy|}x>n7qSUenzR|wvsoUIX>qOr>%@LUlZZ~+$@Ln zlRt0JhOvuN;OAte+C>MeBU?z@*6G+Y?I)2ZJt>+$3_Tj* zSB*h6`LFkJ_H2gEI+qxx|L@?T?11)nQzs4W9dx63>2>)#=)=xFsrKjh-o9P@w45?O zziljYVS=aaoJ4l};_Y{f#`u&+Z@PPxkzMdwLiwLkwvIlDKB~KZXr%tB?x}XuCiv#w zI=1cK)gP09RYE(b5_Xo$H1>k}nS3o(ufETs40E;7dm8`O(Z|1|?-Q6i%Qii@>TdWi z74YAL{?49Zn`%}i0~$=DuK2GRytQZ0lQCFA{~x12=a8rQRP;X=`kVO--m$!)cknd6 zUGeDv>I(k|VOMK4!E(B#XO@v)7mS;5UyOXrSz6=c{QL6`Xl@a{4zd%EJMDSMjC>A7 z)D!JBe)`Vmo4ZKtO*?zC3R0gsoY@KU{*UQb3%Kus?}x+p@4)xN;d}2+r)~H||GNx6 z&R*`c!83dG7UTon1^ZB)Z|$0{`uyi|zt1lccFptj8JYOGnTsOcY{DDi57E69{IpiR z8QNR_t?pEnkluXTO>NBc>t#!xK|f16I>uBFkeuDrrZtIRcEwl!w{RHvzrf*0e)&4= z6!C!MU%bryh55&DHrBsi5%q3`F5-{1(9)r-mFo$8;fEJ$RvDRwKMY?W;{)O6q~VRE zw~{)tr+nT>dMo%gyaInnHpCxQ@W%wsT+I-D;h)*iee8#~Z`a!5JCvUdeI>*CUdHzu z_`bB>_4(m&-)&#U;YjbgcEu~xfhqYIN7&Ukg>B+|^rO}S9U(rsCB!Ek0iQSvEuSR4 z2Eh;bB!S);0)EvwsrC+Z>s)l)O-m=%=aLrIXXWU#D&Xcr2laI!Fhs{HXrb?$`L^_9 z4hBY~{+1l4{bt7M&$pf4R!x|=Wta)2cdL#3bbT(bE1Gl@&d_Av>DUV$Yi4H0Q}@5z z@!Wv86R$0f4p`vgeg0md@NY{Mm11^`CZ|)*s?2 z+V3CFayCjoh3Dua!QDiEI>SxVmW8c$)~an_S7WmPf4<GBhDs$O? zPOuN1Sc+tkZhKMWhLrk68X^7S$AP)HucW6NnT-P@PNYPGTJ zg|nKMEgA2m(=(qJF6<4|_4U`|9X~K@a^xb{oA}1^nG4CMPD6atX)be~NuT}FT{CYa zy+w9MkXB0B>q$GEv1PtC<(72Eh9|A22R`>8Z7n{Mt4XtEX7@_Zyh5;ka1hqSHW_7$z4o5FsUQtTcx){Q6OXZa%IdMV>u!TEwq*q`p^P8!v9 zJ?0X>Udu`DUgJkkczLurc9hoXhqtrS@aEz0B`>dyHRng0uGjS$UK38Vk(zjG13H;qA!4J?M++Sf=--mSN`oz9BxYZnw=JNbzxL1f z#GeH*r`E}J+pz8M?-NMqBC9%zI{M;eoVa<^ndhJH!!&J6ty^(}Qwj-ZbYf6x76;2**V`+Po_ z4;;1m5Odq+D6$bnHt1t-`fKd^wBxR&jA$j9z5-fLT0g+uxip{^w9$E&$^eeedEG|5 zE56b@82S{jr?Q8rvf$d#~+&Yfq)&UFJG(EK~)&3MV^wY#Y zdA_^bMn9UDRzP7s?@1IxeT;SAi zW}UKbo6|1eURSo=hf%X;G&pq5|Mu9f-o!TV@tE=pXb*X4O7EE1K9V@P)abm$@Tn7d z!1{5xrV=ozZQ_44Ssj0dbrNdk)3exEqVKfyl8VN`gSaTDgJaW2%R=_IJ9bvw2kcw)+XLvsX|Vi>vNeu z4u$#mF-}4<@NvGg@y$!Pn}dzD6nM+|>jlh?j%fWyKXS&^k$8IMli|F&TV6nzw01)BSG4Y((S+Q>(=0NEsi8w*}tq<6P>c> zjcli4<)@2Thx+f-sPD~jzivxxytgwtsCH>IZv3Xqi!&c5Up|?WIFC2T8C2UbcYL{D zH|hPi+BfgH)YMA}bCi|?RV3}=6TsB%=Nay7e8mr7CfKjRz2^y=a7yJHf29Kc_Y56i?g4M zZ4?ijLb~$BGwWiPA1+^X)Il$`)(T(-0`#E`* z?wX%l80UB-vPJKf6g>IhD)wL3i$+>2eoR^2>v;^i_J(gZMF(d1VHkK8a9&09eHWg7 zeeO6j&ReKsbzM%-*ZefyoeGZ)^oBC-#{w_KykOE_@zWmz<`B}W;j{RhQ{6d)Wq&!v zW$n3p`v08j{`k7c#qSp3?}_x9J1uh8DsY*fB+LRKsrwmrdT0AA&75m!IxFFp1JB`G`rF7G_)k*X^l37o zokv#^Ps6L15LVG=+8ZYuOLK?z%HE{>Nb;VWTLRDV?kaJuje>nMgU^ph3(vKIkMFSc zz(C3|x6h0dqT7vc3;UqUz04)xV)}Abg0YKxS!x#^ws^1LTX+g5AJ-(fCcM6+`*vHx z+XIaj^A4-Ok9w%>*?CQn2Csp(zD<*^Pq=II99LzIr>xr3{@!%rK8&RI3+k=M zpDi5DB%P-yYIFNL_znC!5!HJu%d?Ne&cWZt@0C;(FLCBG&sG%Q#hEwOEmlugo4uII z^5XfC`J3Q(-IJ-FdqcU(l~BG0-;(%jqx#GG$nu%pk9o?_;gJ292HBJSz$t96T7RnA zy^(#MGRAFqI=wB&d46wC_KFri$-V&X#|NkGA6B|~6@H+15D&#%uf?m zvyUenKV%$)*8`#-V;9iR&`JEi!rHS%8^T<13FoWPZ;3m!8GB|{p&@b8;6 z<2x3QXpE|(PHhW5l8z#0WAibN8)qHbQiQz{appVD8r~)L_X}-5^)5(P?|}%O!6jq6 z4r+^(r0OR)@z&?*ujrD~xP04ibo2;(Ig1&$5v5yJ&5PvReHHo{y;D)jUMGHlcGc0D zU4@UGfL%-Z$~lqwk7J`&GJbX30k7QP%wNKN#4_s4Q60{Byphi>kVy8H5s}omYc@F- zufZ;^VeVwEHD#vb7cXV(8LOGQkYUykiOOrCKW_(Dz89Gv;U4%f;6ami&9_lxY0gmk z0BrSPIQ4qchY|GQMA}$GAI>j*Wz{{Ao_8+~`e55q9n%NlRZ3mTS2ETq+8PU-eBhi8 z9Pz!$1J=t!UuM3_H}jR~(HWLxVn64vBtI4}&g1#8|Bd>>>5Af@{4QsHgm}1({|zkR zayx4X|D1>~$74eD`rp73UQ2n`#n1tHi4+}**P9=ARQ#H;n#P!Fty6>lVi&rn@(Fl! zcSi+#-sb$>256%(wPPq9x|uudmRA2KWB7b-fFE+pJBAg*#hRkaf!#RIp%e+CE>`2ZQl{0NYbFC+lA5#XNF><7~-_cx1 z`@&6lC~Yb>cZx9IoNVyv~^J5}@dD06m8wg3y5(XX7wyyjf} z{VBkZE&d0-ClVh6yu8Nc+s1a170<{@-ce=c&zUzx65fA=_#n)i{|b(1`dC2IO7SLp zJYku+l5^Ji>US{K!_ZNTbyNH=x(6E?Yn5SM6hFkFrQrwex7#wZH}9a&*i56Pdt}pA z4{$aHzR!lRk98AmbUq)fcTqG~SHhnq+$YpMd<#SN(Ob}5^R4bdNDn#OD}0-{+7kci z{pY(W(|N9tURQsd_wcL7@T)U^?+O-kNGh10G`5;Ib;hvS+)p}m&Zy~Pj`{^K#PjuP z6Te&d_Y+O|%seurZ8r8!SALM8=z*Qqw&0AHa1|~Q)|h>utYp5rA)cB&O4w>WU1#|p5@?GnUlS0*3U&oQ3jIl25hHb#T zi)_|A6YzVK61R5UPejG=5H2%qJL5KnDX1MPStnob5sQDswNiQJb2hruOyQ z)VFl{RD2r3!Q>-LQ}YjgU!m_J|NArMrk#w@FX{K|gl7`|olxT`dvEpL=SC-HAHa3%mx@U@;5oL2DA9Bg4*SRKrxl-K&Vp|oEw z&Y-7f{*|(R~Ri`D;Ra$RaU8VGDbQSGy6%Q;9#&I!p z--#ZSKI_e24u8Vwab)5reeo%gza?@{q3WGT-usM?be;Nf65oC37jNB+egeJpd+I$0 zF8B3cQ}{uwc=&U)e{bZz!uulsQ8*#u%)ht)y@k7S?-MMuuWHM42c+V;$gp{gsqDJ` z*}x|+cX6aQCZDhSNT1&b4TPiKLsTd~f$&nlhc{|HcjR^MPT**rD<0E2*U%TezYiFq zhxR{?bhrFN_S~vD_ocn;3HY4yID4N8d<`1c7W(h|5AwXr;4{quacmR4Jt!OHg_C_7 zMLvkYS2%7KI#7PMTagXTUwN^_7VT3NcZ=+~61mVmKxy0J?Zuo0+{}El)A+3OyHy}hPB2yX2f#~l=eb7XbkGOUARoje z@=Cz>RMRH+J%n@hs9TOxyXg5Bm5<*gsk^_(LJjnZ@2SM6m-LF^m5I>*LGm|(UwFQJ zhy2=TPVGF(%7@SkAHqG%n_7Q6z=3DCR&uscerevjnt6QCPqQBzoIBS#7H^*rD=<9Q7Vw<>w=;li`L0>MSlYDk`;aHt9h~*XH#}PP z#lsfX^UyC0t2_iNy|-h1J9TR~Gtxr+7RE9jN!A)WHNv_3fUicvSK{5x|AMbdfi2k( zU*QulZxl$b4)WF53}1DFuhP(C3UwqKp8)@3#@@&wvXR{dpJh{4u&)kaOV%AHzjg_5 zG?rVSv*fyX-q`YcDf6#>E5!chj^W#2oguvuU!JPZW*w}vz;gmT6qhcT%{j3u_K5#U zTUD~F`m>+R*#+4$O3%jLn!|aqY1mcS)x*lGkH;>XQ&#>6cJD0qG;V}{He7w0dlRy< zjG>mpgMS7V`VpiwGa(ce9I6cIICIF2&z*j7?QM z%9)>L-BWxz{!VnWY;N5nJ^?(6kMZs2;uG+3s>}#%LF)Qt@;#lQE5>eOxb>6SB3lKP**;7`Hmx$nS(!*H$`fz;Z@zA>%y)&4DUY%c>kKPj(Mmv-ki5T zL`ToXN3S(aPu4W^(9QDiBEJ=S(@5*7O6;JW@Z~V{ptI5IFkKNxXxVc zPx&^CZDQ=-L-$V{(&T$eHZJEkx*GRtpHuwzZS+mCliMnumo3}~4!O`$`v}GOb85ij zF0|vTjo)!M zvf=M5KM2iQ*jLNGo%!$f?A5z^rZ>+0#a%O}_j>GGWw#GsJ^aAp?PUk9exNLp)6>~h zR;zs%;22*{SMZknpTK*eJMZ}va3*gcXDtgkYuVlW)_hnGu3I*^t)>0@+p6b2yLa6U z+xONKytOyJXzJ?h1Lr+3?7-Ao^&@*p_Uhql`}U6?xT_W$b5F&ScNMmriJo{N;_iIY zalZ_X+p+s+qc2KVYQHSkdzLiT9;2JzjJR)7CQ_pPJbuqY=}~7x$D5IHI)l3Fm}zD4 zCkOY3-}|?Ym|FJUsPoF++a9fN{duI`=${`Z++9C*>IH}KY?saU05J4jPZ*pjIYeH? zGY1x4PQSmz`$n@khuGcF_YWuHds-&nQx^2-#<&6V-|M?;`+f;$1az0R?n-AXej;}e zIEWWNBZrZIjis7_PdXNv3FY2fA5`hWy{{OMbqH*nGZ}mFs;@( zHojUqva=qsXY3}S^FPA=pQ<(R24CjabtnFN*8hyX(C_N=uR!PuI@e{KL9$Rew9aTIe_JyA zr3aGqp)-&BdFMT#JCQ9r@7osN^y|G-FWj-W<=K{?-h~gCJGzfQx^45bKiwPO^6K9B z%w0iV#RH?z3zG3e_KZWiP-kjd79+FBhx`m*2S>@sk#wEP??Mjepo8ksL3g2pvTy(0 z>aqjpZO>smhONz6oinv&<~xzPZ^duVS-tC+gRn2`3ibeS@kWG zWA*P(h)VaanADPV-#tB2UzZ=<`p(Ht{aS3@(cqzP;jgnxb97Dyo4PELGJCS6%&!L) z&V=3J-XHA$tt-q<6x&B4crt0iXa0lPv4!-0sMVj{E zN7A14Qys}ioksRVI}1mC1l{3(2pF&aV`BSv2}i#@vHddUsz-+E-Q#@EF=vsIUO(Wc zkgbBrj(d4<=9Rs^-SIaknmZ`V=$G!E(W+Eds{ z8pFajBb+gq?* zHvc2Slf(z}-zDE+9xQ<$kK}Kz7TyQf=jJVe%Y`F#rV)15!zI|pHPlJ|ePa7Z;G{n2 zJN`ct+w-`4b_wwXoabr`&Ii9F9MGvdI5Ues+?<(}kIa_SxNT>Rv>@1<2#@2l)a|T8 zW%D0tOdq7}jf@>KWc-R5yto5*dJkvo8T6@*ar{%XvQ1+lf6Vu21D-PYajtADZ;6jn-YAy-tJE@q7Gp zIl_M(__MZJuXB2Ok4}75!Jpo1(b(S%4zd-*AG3pcdRI>Mgp2M#3BNeJ>&)TKlsU`A z+b+fy?fSlw>>O+37=Fm?ulesJ82R3xXZC4jQ=KiE9pktagnB2Tvs^Esea-uJ&R;lO zI{k|8%YUr7-EqD_{1y}Mcp*yL{ND4jsN1>iVT;!0{Equa#kX=FNp_@v7H-9)c)r_w zCG!Qktw^{KKlP}%Oh=#id!VzxB|HyHpQ@c*tYM4K^4oDDR}MLcagz+UOwArr8c!9M5}*C->>(uuRVg+Rr+@gtq%9IEARfJb3ueG%oX{sX3&50L@XY!{{e<}MHzZe&?CrR$Asw)9?T=*>H`)uZqSbuAA%Z~RT;Dy(R`@|!8q|2uH#oW{NhKc(eq0U0CLVr|# zz?mv|>x==;=oaIL&TIW0^Y#w*i;E+9#y2bdqJ0p~L>azpL`X*vh`4*eSK6x0@X#P-DXyT6llR*Cc3CEOt$hRw!z@tpGVQQYI! zeKp;o+rnOh_J9`#_n03AUS(`hD|T8%)xt&oeRt}88=OjLL-*YaZ(Y<@h<=N+c4=Yl zGBt)@FLbZx4eGKcXs?S!w??q7&791+mM@EDq}@y?Icd>e3H+e`mqDAZXfZyZMT$Ei zb-aVKmil9%$$s98tYP2$Xmw8t>Q=GW^$Y4o+1vMjuXmug8+ts<_tY5lf{!&$4?#c4 z=CpaC`$)X!8a@Xzm2ZP{_&!pb_B0B;iT{g!bq{b$Gry=`@_lQpUIwrHSbnYLo%!Ho zb?h-govzj=6VXTFp92fO1Ru|WpD%;2zX*R{${M8t`^NVbbtP|i(Wd0>7Q!?68~c7o zeoy}P@z>d=mX57LpUWP7m-iv#+{H|ApBfsPH!I@Y{g0M9TcuaitVJ~UJpxSO_5k}0 zc8;)bR-|dy1&-i_^ZrcRI-`5E-|jPgvHKppTRAn*{S%n?6ReLM?n`SP*SjW9@!qKR zQ@;r=oK-aIDaowf8kxaaR`%Go>33u#!-L@K{qXha@bs(PRby{s#kg1d8Jo5)T2#C9 z7+&&)!bY7SG>N2vZ7lZbB<|;`r?Um zLhV!|rv%hpns?DlY+JzjXXeO>Z>2!Nk227 zaXaTz?AZL!my0H?p}!i`ZQ;F9?E9why8WPB9Qk+HWK+URO?GW*9}hoEpXfIIn?reK6(cXj9uX`ub&Tlu*AA#=VUf=Kq$XkLreD@h6Xc&w+YWjZYwD_J+gFF%a0=U z@8TnGg}2R^G~~N3w9(nVgXj3WzUwTTPrr#Ld3u=kJ}jKlehL10>A47R9^?V1xiG7} zD$o)6_&-qoyz@wYAI_$bkDhD4IWI`dVZT6WymNCC`+(XP&7s`sr8%pex14V_FO5FY zyfng}^F(treO8j+&Biut(r;90jGb6|RTcE5ABJZe)IRW^(_P=#gNNkRE029G)92j< z?nBtHo3SDA&v2LFp;c>@&pxhnDl}f%3{IwOuYv9=`~LUqyO7^A zV7=(DUOXP%QS)i){_M{?wq-}MYs(JYxczSSgw}L-o@`y5o;h^Wj8DnCKUF&I(=6Wo zSPPF2>)Em`5>frxLm1nNbo7evNBUhiMBkCOoRghD5wZ>~d9-Rs^AP6%Jipu7!@1i5 z>9ab93vb_l>VV6?yQdUqPpRdxZuKo=IX8lymEO_bUo-xgst{c-2WDs6&z^~`hW4Fh z{N>|)8Q(}4mT&B?rU&2|`Fd{Py_Ny!L(4ngp==u7NnrzNeo4SHD9a4*EGA#Pb3=%C zZc`fLB;0j}wI_710{5DK+_F8AOl*mQx9Zff{?Zx3YTC?(znn<+>KcB3Eqmv!+e`b$ zw|pHqH!${L+3c!cD=8;@ml1Z>C28g+;hm(-8l7)vbP}iVn`G#$A5lIO{6iEY=;+v((e_mI3Nl}9_!ZMTDb zuZG8}Ig9Gc_v%&k%I93mr=(9M{Y!-F@cSu0mHY6j1iU!T*cSuMxY#i)WDHZ-A!Dgu zH^3i5`Q+tm&|S+>r0cE6#q-W64}6zq-0oF-oEtItphNKEVOv;y9$9sV@^kUqa=r!} z=#T%#q#gI$m5=>p>Z4*>4m(elUUjMd^X++1Qi=6{&fmwo{k=|O@ z2_^?Owm$bSU`EkfB_&rFy|osYOOA04ECptYwEw@lFb2$2$(07?QeZAU!8s5|x1yUX zVn#1sIYhpV`2M%I)fDq?UXbUIS3*3KcMLXcC@*F6KBwLZ=(@?i-u&5d=uO_U$?U}! z9eFQadb8#S-Rf&jKU8m~@zqy_^ky%{>|dP)=}OPs1}>7lIfT|Xh|hc_u-9u}V;sDy zaQ3^0uO-rf{**1V9$i}znx97kuMRmbp^WUFBsw-3(y_;rj~;7(Fr;Hkm4+NYh>nF1 z_S9k*twhJ_UeC(sBgUuSZ00N8&ouA2@mmzs(YjVXC+;2vZ?_z(-@5Aec-5odBM3X| zSLs#QT};9c*ZQ&#p!H8_2dKJSq3K%N?rr^m^AgFNd8Tp6z0$on6*u9-jl zI@}99q|SH3b?zy2AGURvOKdy$cdBz+xDLNlb+@gXkvqf?!0!*$jdy0_ap_y&xv z*L$Gpm+ab`I@SGJxbEgc_c~iQ?_hi4r7$fn4%hixp*!2wDGb`XE0JmM@=kRph3h&+ z?o9G`Lgy=ZLshgsBb*sLdbi=ZELq9>`c{f9^5NW!PKmok6JsEpJDD zHg(hkdxw4W_FiMZ4U?Vb+ifMUus1LWy*13Yt>VM{yS3Ib4LEAwiae1zuJNo?cKR&YuBu9cCUiF-lDZ)f-2^e#pL>l2-AVBgaHgg=$r zF)3p9*zV>GLZPektppF5l<{)aXA<-klamwbK<`ViRr2~)uPR3T>$+Z6JfD<2c; zEf3-PAnTLPHhO5kq9J6Xn|t6psViOEMA%u^HU@JD_IksE%psSC=8*4EUUqsFWu$jI z+vyLIU&kE62BvSjL&FtHgKwT(*+@s81z<4d1y>RpeLEr|{b2 z%Sxk9RrIOTy5TTf?xd`6xsmW+-PvMY+VCgvTM5mzf2Mj`TTh^Fqik^QDM()Pn7i}h z2iHfZlb;61heC8eO=;k$GoCfPH#mXw^aGz&mOsHe`8R8D&L*k-=O-~__lsFyr%P*yEyl$ z`AX}q6#*Rxx(|I6{9EYXE%@yn-aw6lpF>^l4)6_=R^9P9l7na57;I`{z>#b?3X=@|_oUU;f60J(jDF_8(8@LhJ(ut{(5Qd0Ovn2pFDBf$Tsegxbyfc zsRJKy-~IhqPjB~<%C`PPd#x@Vk~&brx}zIy@4lnBO>kakzUf83`aoy>UJm}0F5egY zh&@>Achep=>&S-OqC@ppIel@8&|kq@rv>m!K}a{8LcaLrmJq*;P#XO5DtkcuHqLtX zlUC|o#~k!^d9XfrSerYn%^lX}V?XYAc&f%MbmpqcU+Xl;U%XW~$Y0Jr?H?3pEiPHx zqB!gB6g=ddIM9XX&E7wDFn+fOSG}Nof1TW@dFnywvCW_XxY1tBk)4 z-52(k{gSepvr@ra-FeRXIr$p%@SOD%r7`BhGvhBqC)ea8Y9qTAZXZj(m7npK(PlRM zVEtwB?09YDy+zx<3mn1ySM%Ox%1NG|COndjs=Y7iCe3?)?qq8$rJm-zs{fC@H-WFR zy7vC}ISFurpkOAZ!T}rtGRZtC0Vf7W#GwvN4#|NW$YgQ?M6?FM77Ml+H0@9_S(=v(W$O;-mQGEr;R`M;B}3{XoF!~k?)Q-cz#TK#dj=%el*bDT=c=F zQ?F0JPuT<$k0)Bv_V~ktwD)@i9#49Gb?_;&bIDqE$06v;p-&w<<^6zDoxT4-d&`;e zKEhevgK7EqYR#*%KMybVW$G+AmEoQkPWFD(?OoUOGt^#S)a0Ij?7F5um+y7J$h)Q= zqcC7pN10!J&*1|Of=3BHcoV#>_TRNfE?qsrMBfA#(c`ZH$8Q72ne3@v3xE1!#tUH024N197>pnElRl_H28wciWSBxEJ$qfO$9rodiGjrnIMFWuM!% zpW)2K9emf`pd3G zkleZfSFjt#oYf4?3}&`IT}!y^&*@y%^W>%Rk$C?p?~bmN^Zgm#A7;PfC2a6EBQKQw z_m7c>1+jxfIc@647WxQ&scjVH-_5+5huZ?ZqYiEAU#)Gh>tuCT53{b|w8@f}Z(ZH0 zy}v+hr1gE)99mQTg86F&cu>IHwGzK{90u~NU~HVi969RtQ?}h0iP(8t=lhhm?COc$ zJjD44>8Qln-?aO!z9E|qGxnOkp5H2ZBinT|=`VPWTR!0~DRbJ~)_ga7vK#&};fKH> z&WmTkpDtD$)&@ISODsNQWw+V!xy&=emkf-Z?WSqrZsdS((CFQN?=`gnzH!)hIX}v{ zZjhcmHhK2K>olNeuldM{n>Bi)G1Fcbo|13ilU`Hjvk$nt4O8y9fK7zgL(YAC2=|cWpJ1e)uiC z*f#oM8!mcIjOW32JpYn(&iHlSU*=tNn{yv1_Ca`;tP{JY2OeWgYdnX*QT5@~;KyNb zs1RN9(`mQpMLp{`jq^i{{ez7AJD9glVfX%i)^`@2_J``0J_x+n%OPTEpeBm(gI?fCJ;# zQOCyOpl zchffzuWR{}mA1l?iRQgFAgnpi3F#jbdiA{lMW5UzmwaxOOCSE4Hbf48 z`QG>OFI>m|1$*WDS#x{s*Jb9?57PR^sn>yZ(D6I`8T+ZPwU4K@&3^J-**{~`O4c`hXxoS6J8DXwZKL3u zN?Fs4xqVJ!VUM{-gLnCk68}I5+BCm+>(jzF(J%*RGWQEc3uPyU^cm#y@`#LWc|A0j zai9O!89So_loGuipaOh)0*miN-0 z+I`fO>jpwYH7)|Rg}WLgQ=or*wS`BuKVQcBujTQ1jltUB(QMKGC(DH?! z5XXf>32-pim`0P~jJsFpPtgkDO5y&sZw#i6g^V%bvc~hKGdO2@O8&ifj5G&i+eSE| zd0jZt=;F%3p|lHJIUpBW@mIOP<3qWWi~J=wk!}TR`uEd%zw!z=`QiF`jeW31|0Hh%$*;hHD}ASK8s$4RwvsrTeZJU}Ji~^fV*_4S`U-aSL-tbV z`_j=Z^jSZD#wOoc`Nw>~>rd{!U^;c)^9A$TRk^vFCP4FpUomCdeP3#w0R0s2Q90Mm zW1T0DFLjg0z%F^L^W?EEQICR-dfeAd9@$;;@D+5__k=$%8SGY>O}d z83!Ku$CB{qIrn&YpfB7R9{Fv_JbJi!^zh_yem8lbXWS_d##SuRrXY-`3ylSLs>4Ousj<29x~# zl#II9N005jZ9h1+2pl^H9232e4)sFh_N<)`h3aSAAHye^Imgi(|L70oc#k^4{%)c3EqS<0>sNFUjDIlJ(|wjn^||>huHY}09yM9VUp?G zg*^X}jQl4b$?!d?yctKYJxn_!+v&p?l{{Z{S=rMpxthJ^>)}BLEFT!l1|DC;KV#US zm?7T(yxV@i^a`Zo_hrVc&iieo?Ger@1&3#Edlnmo&i>tCXxor@=)ax#$W^wRH3MU} zkVbsqQr4^DCBEqWzI$LSlK4)Z`hJ!BUGwMC#5ZV=zAfaN! zfsTpp{N@V|z4^6V=*=5)p*OF|h2H$94IdOA%{|#A=z4ngAFK_S=lL%FYdfyaAGH?v znRC;adppis*XKBEt^j9!^K#5&__r-x*T1!-*ZMbjf_99UWnE0t?a7Z(1DaXKLpI+rYVlxMKmjZ%o^@tjA=}XILKh2mmYb@aKSI;@xxT z&-<~N(pU5tI0RVtXbqHGGJTEu@sSZZ+nPt3*jEg9YC!XpUOfK$(8g@!3$55X37|VI z8$jrWb!(%CbDFk}%u_qhqnyLn&25ytA)ET|o~X3h);7sbtN)&D_1_QCKGjEi0Esph zvW6O)s3+$Mkne6Eb@QN@=G_d&Mdb1gix({aepSXTX4hNekX5VAB~zy-0-K#T7hupX$J20dV!gApwKiiKq3n zU?4j2F|cX){x=qHTrqXcuQ@}Y`%zg#ZXa%Kd1uD^6Cd8luKgu19!^=hw??+chp9|E zX1ON<|2ypO9kll;W80f|?T<)LLg}#K#dezHLY-~&C(g)8Z|m@NJ;48-tXX=oX7R-m zwrFg-XMj`mk8CjfBerNRpgd?;o5oNHxF$R)1P?QywX#JM!RC_J7L9H50~68Z=NuJ! zuEN=C7;m!8&)WFFBj{7;+XTMZxZ9n$Zz-6qTb?aCoArn3}4}6&SENK|OI{*0T5NIuam3tp~)Q#}OYwd{lu_xYU#e*+O z<~MtCGQamd@$OWeM(1;$rZUWEjczPRngHL|N?J}OO zPQ(dJwQ<^b?>e3qI&roPpWwv#NO8K1r@4tZF8;r#IL>(5(iQ)w@~ti>iLYDc6_c-v z|K|gX1pdFJc!NCgJa|3X6Yo`(g?^BW*IVX!@Nl#z-V2I1!V}Mfhe1!gU5a;>C*A`c z^~>?Z`vLL(5qv!Y&U{{cg${MHXK*5XoliUu|6|YCucJKSYbEX^o_!;qL4M^!-rz^> zkOnW5&Rl@qnYGLZ>wU3iWK-gU8v2>Z;LDcb+?%mNdAKqwoimJ z&+$tqzAyI2>)}1t^Ip%{9m$zG=CiDLfhWyn`0rpYtfB5*d9EQ!56_iebKtPQCi@Zp&q??PL$-9eAK~ST}HAcAM?X(%yDlKfzvgebDR}+|_2*!Q*Xa1)+`7 zS&+>v@fH8+bNGyR2047jE4<5=*6^Xu8YpqULIkXrl1$d!kUaU#B%xE7R zn+7foXxi}lbnIo_K-dlE42k7oCuA5l3Y&;uG8o-y*}K9Xe+0YBs)yDNjqkhmGtJ;v znt*i+_0d|!xtk^@{vPiSV~g(-Y#=dy?Rk%>?tXI<=RKM@@6p70k0#E0G_%gJ@IlY> zad^lka4H#w{wB7C(KGXep`ZCL3bW@p+_dOlKA4gpFX?8h%fC+4Cqa{L#-m z-15)m^``O~=fGC-zjy>%;Od@qoc-!J_a&J~f)0F_^>eeO18&%oAu({!p6yD;iw@EG5BEHm z8*lTF*nJAKbifT`d?S3ZXS?W+{l}H?L%Vo=!4HQzK1A}9E~rx zT*l|QaW41k#37qy%=JTQQ8Ii~*Cw`25?SF<| z{9gH-<;=f!Ou4Y0LwFuIbA)kk@su%D@&S7WBQ>T5*)b(N?K-Az=rX1hf1z(sa!egz zOkG7B@!DrmhIp{=VIY&j1I0Kf~2}>u7}^{xuE$H68x7 zvn)e(S_Loprn~>@)otBK`X>0vLe7v&Hj~pux3!M%;wSI(==rQw7-QM1+d6>#*MLW+ z_cC$R=6d#Er_j%`iClsm^?)(8Z*U&G1o~Hk{oRD#tM*N$&mi5`S;XH6FDkwEDd@gR zclj`|QzEuV~(poTaY$j|NcYmOAaC1)P9@#K=PA@lh_Ua z7G>vSH++6KYo^J3(|8?e>xV2%eOWSPjaNp{T5usacmaF1^El7!$O}$pOI~;=ynG|6 z`_rL^`=?w7FN5w{sViRoj_-xw>i?D6?rhroEuJ9XM_vv-?MbY`f!9Z}Ltjr{37@`!E8NTk zHzg-Mbj4ikQD()zL%4&hnbwv{wUw)9I(B8Kx5oND^*7_BMRN*a0h7I{5xmUEHq((k z&ggD#0UsSXmfAX^dp+ZOj?**F-CxI8y668?&v?D;UG`y&^o35J3Y|U;IYU3>4A{K9 zAl>T8SXd?G&DiN-eC*Nqc*E+c>-@hzsXH@}_KSAck8$Rmu4AOX;L~M{^iddNL~`^_ zI&$nY;<`J+0g{}(rXE9q6XGiQFq-eom|Z_VSGGtY$Xy7NZcP*?Y5C^YzN zaH|fQ#=7S>IgY#~@%{$y=nW;m|0nMn!-oc&w(Kvku41o$_YkvV2aopP)=`#p3OEDQ z+QOWru-ga|-nWcouM!vz20w?e=c2H~BmJYaMi<_;jyKOpH$wJu4yYdIXrIL#_;3jP z_{a+yXChA>$n&$_=74NdHi)iZPe%KAd%;UWle-Al^_P#dZ&xZck@ykAw^k|h%b<~(uJni=^L_ea0`R|z#L$zY>Wi;hw{^n#?b+RpvNT1RPJJr!GtLG*?!T|FDQVQ&62CDdi#$o#f!>fM4Hz&6-0 z-(Wk|*K+TI{JXUdB-_O$*! zjk%sZ;=D6Yp5O1>{E$QJD7j+8>$^XE@^2fTc=d1dFMRKB%(1Pk>23bXv$+WS+4R$@ zHtsX&b#Y_hY~}6S|9AFUBfy{&{iD9kHb3#V zmSlO;TLaKrwWp)Jf$?$BU-qS~{cg?OBN!v|`g|ewQ{@dE`z@|u+J=r)9`<;ItK!K8 zJJqWz996zxxy`McXy>(Vy)>SzyupY4G4d8(-blQCBQI>+r+RT`Li?wu9e9GVtUler zx4K)WwQ3z8ylVmPhaEfZz-G#AdvtE2aCS6)#cd?+`;3Ks#K}h=b0ClQ`}cvb{x?Bsq)*io$`;#CC=Y*4}x?Z>Z6Il;fNwjO4U9>5BR?&3)80o#p9aT&Oh%5Y3UU21`fo{s2ce+{DWhQJr0KtB&XK(bjgvFb zr#bT8T*v~n9~}pksq*foKTlNua>^6_stuxBvq{?w{+0aOHx|!dIcd$2(a0+(Ygoy& z>Cmxb&ERU1W?uM(Sf$bvrZFX5pM%H&N`S!$%O!8gJ+Jh%Q{`$+CcMw*97SS0^e2wm z2rX{wR4%l7v0JX{uX1x4=YqY3?|-+Su)PyK(um z{991`DeIOh!bQVFxW}E{M%PZV7VR69U|$z}*<%bko5Y3R*^}*?*Y+*q$e-0?o|XG- zWi1H5cAyEGQOBC34w|90&08u5I#vfQh5y{~Ht)(ik>@tvC5Mpgh`L$3H^PUm=d%?D z-q7;D%BzX>SR%eX`}pF??s_xv8uI?Je_q>a+}5ENw%v-mq}RN*ci`{RsB-{%lL4PN zEX^F4fj-D^bZ9ka-br2Zd->b)k(-G3hMH~4OB?Wt&bqZ^Vn=Uix|M4*`2B5Lb8j!OGoIU1{5SI&XCCi>pElh4aK8(Kmb2$J)}3W^uUgv!glVtUaL?}; z{B__0aB8zS@b1*uBd43#ErhF1CtDA8*Vjj=r~3LYxRPU>Y>&8!epNfw_rvbtoC|B^ zjavUa!Z{b0Wn{}JRK^y7Bn##z)2eAq7B&^a3UGhN(}-k)$INSZgJ8(PELzPxZK^2&=DmlrWEFJxR^z_^^pxa7_nc)3?jGg-hTb{DoYEDoU$MESx4 zdwz5-`MJ1d>y+-+DR5veXA$79?ivccG6$wweV?p2Ydd#;J171ee(@Ugl|7%@Zu{!~ z2X_%JxtMs5p98--_;$f(<7FEb&%flcDr6Z07X50@2$6c5TsJ z9=~z(kPLLAf6yk|=DkCcI(Z8&*|0dHzp0&dqw<@D&9I#KC!|pw2bsZ}=EM7(EdQS+ z@@L+ylf6yStB&glSN-N=d-`PQ|1FW8c{W+UzQbapp-a7erft+!`K=jOnbsSpCF++O zfBkdR@BT#ooJn`;CwtEW<2NSiXYJCS7=B+(r01-t>bKyrZ!FI6nOfPQRezqtcfo9w zb#voqTQ@V_h-=4gzKNZOUwGt>-97Uz92R?Io{8N_IK17S;cNO^UENPkchXqAFYZr& z3zk{v1R@Xpy>kXjWgaA+aHNkdD<|IDy4>qvU7f)?@py4%?%O>wt39Iq%2V{%LzIfZF zO^Y8|v|;f(6U{AU(13TQI`_xDQ^o!@a>#eSW^NhI*`OAycbT<+AM==O?dg26#)#xQ zLCR_ZuZNUOTXO`SU@0`?owL{vhj)EvH0fC{oh*GnrAG!k&`rOX^e2m-PW*iEe2^Re z;?IcR3M`wz>%ngPnV%8=1LDhe@&GsfIJM`?+!0NCgiGL1@?JdVfIYew?*M7Ud-kPn z!m*a5o#re{6TC1J?g(zLlScV9gVWZYG3jLk{XXSIoZnyzK{kz7vB!{euziZ|$Z~kD z?)%|6($&G&mTbMdbRqC0LDx@~{-x7Rmc`Ky z{>I`s_Pi~QkHY<+zuCI~oLy!6M*3KPo_K$${eq0wy!hUbHlP*SZs!BmF~|}fTNsPp zPUzWZ#V5FTy=pw1uQDe(cMi;l)&|i3CjFkkx?vr21A53(#<0{7Tt8{TFZ(_YpflN zbDjEp42+md?YudOxFz@pGMCTc?9k+|K8$`W_xr&g{eXC?cj7(HyJVD!_wVs8e8bk@ zjw88-r5pFd3x@ClS#xz}p0f+sUX`5h8p^4^byBO&4T^u9la^`Ekk!E>yywuV7;~Hp|z~9 zS&L?1V=IU7soXK#hD^0Lb&|}~(&-O|#b%Qp`m&=9S&C$V!?5MjjBG)&%&giqoRP?i zk0y@g4>*@b|@h`Bt{JXWr~!>@TDd+_MH=*cL_R z9)#ZeIH!8P8*T=2-XFQK>XC~)G}mM6V+wKL)!Xj(>`6^f7(D6ytWA0YH_4u43t=O? z_@I!9iGRQ00-rtKLE0txX$4jmvV^-`marDEZSNC|y-q$&$P4yTU$ya9yyx?tpGJRj zCfR{eFt%IeA-i38O8&7H`XocTL+H1}t$s_U-HWH6t(|M>ib#)WIOQh$Z&xt(aWnE- z?xMB4Ec!<3$L9}l#}0XCz~5>eE?J>;k($V>hBmYlrg#b)j{Wh0$U^eacN<38jojln z%9r`IGu-iL!6f1Byeg_d=@yjma{{WUpzq_oju>d@hbAsx}NpXjuz(fjp(SUPNjr9aRxG< z42DO^jb9D@6VDhF{=OZI6}fSoF}bF-(8H78#5bKe`aAN|MHwrH3O3T+nMWSVH!&V1 zU%iUBdkI_WTlO8Dr<_3?y-O!>8f{ShRHv8wiD%7<+kQc(!|9hC+b{J8kwv)uqJESt z;HSjzXKBOS#)Hg#A45ANFMXQuI^3PO^|(L6CG7#pxQ;L$54rL%+GFYBM|>Cm*C>}f z9=GqD|Fv#z{88M7wClAl?=%N$t)woiR-X#j}ZhcgQ%mLiFow7aw4s9cKUt?xGij4{3 zwdOF{NV2>IFe%5cc|r5wZKP=$;p&iJ_dYof_86X=2Q~J8Pdv%}v1u5~^~`}sEbo`= zu8(vlPj0-PxR&n>njM8_X%2L3@D~$4_-tgbtY-pteUxi?q3-hdhMNa8936$fgp_0qjLf7S&z;s}uR7TUY2G!um*SxB>B5gsXlf ztZPn|et9DO08jnG!;|Z`#!ER<#hNoC!#r~vYeJ`vIq|zcM;$MB%V=U9>(o)}jsfx0 z6Lp+(@;aWMNRQ1C-Ca5Vj=;7E_suTQeY1Cr>U7_%>>5RY^Js8v;kSp!7O~D_udQui zD8F@d$h59yy(qY7{$j4&K99RdtgH*1nMyhGFUA#)Xnp!c;6Ep=1ODzlOJPON8iN*<-h|?!LKt>(o1V4Z|%DZ z{>@)8t#83Mz-t_+hrTz755hKy%58;yCCd91`I5)>oo@|~O~rld*8VZwx32pg{!V_= z2s^T@f9!#;=EI{5i2KM}^)T=#-y*H%Ajx=#uNQo>EqpXjXbrlA?}E2ue?fPjWU?k5 z5PuT-tGuq@yJ&C;F8Zhk_OgH528}&L*`lFK3C9+r-GdTOkf`$`Hr>GZ4Y-;oppjd= z>x8+MM(VDS6WbJ7g#2f|;Ml?IZ`XR3d!H!laUDE=$EwUT_4zizS|9uZWNq&X!LD~mz_J8ZaM!lo2`>=iA`rvo_MsSMrL* zKLSo_TcDQx7I3GAI_$Ld&W@i=J=XBPisvnVn&s`8^J$ZG*|OuAe8-mkEe75waN4}K zJorKB$O%8RzuyLqZG`tbh+d_EMig4vaaQ~i(i!A~iZcpaT|xc}1rKDj3%Cz64|pWt zHOH5^e=cKYAn>^Z{Z9u*{#cswpsdG#?aW(2@-Tr@Vp9p%+*QIDlT1*y)6XSLyoz9| zdJlXnnP$7m8W9_nNTYp5H_aJc()97Bfj1hGNaLPeR5`g_(zJKfjk}yj#7^V8<%8g@ zRhJ{~_d@FWHTt2D@;AyQ&#&NWUfy6`;X>!Lp`R?*ecwL2pOJvcbHo))mb&@sUPq0Y z!`Jzdy<%H(E$64<&kK=fhzCVSYO=;nJ9q5r%$E8#gj}>4d{{IEgd|Q&y`n2#uxLMt1pBL^SQHl zA7yLoD$ioR)$xsSwcQ+@8l!(~+=TA0&QrG*ykze@Jel3v_VoeDUbZB7)`s-gRkmu^!SxTNvr;H%4nuy(dQNIrJ$Y0It9 zo&x5%S6J)HHjVIOFza1A$DSH=M}HT5=p)fem)GAu>Y8crqU_1A7b08&51c-%oEH15-tD}W9sfXn;N;X{ zV5~*&&{zBZ(6rdQdPh!R-#N?Ftar{bnZs!nO?R%JExVYz(amp$ZfHFb;d=}8A~{aD zi~eMD$QXtmy5 zI7a2C?Y95c1Y?zYPqd%@EY&;hC;#oH?Zxxz?!0q$qAw5k`Fw5L_^)Y=s~Atap*gZ| zD!Bz?>fVO+R{yCpKgb$O`~!4>HS_Uv+R=)iTbfcs9W34G!V~_4aM8&|T%E1xYCE}( z{an$rjp)aF=e6&DDn2*AZ9C~?*FpFK-Y$NPaM2dME6+Df>(e!irv~P=24p6tFET;e zqj@zOS7rNwflxuP@K$l9_!vbG!euDGs%-8? z1xG84x_+B}&BLagVSS@IKtC)k7O(cp-j04{LRL5#T-pk4nj#u?YtUK4d}%~dhA0_K z9rQLKL%a_9d7aA>zChm1uDr0`(#!1lPYDwZosXFFJ|exw^E`(^>! zIfuR2eCT}X=^05IKOe%wet>*{7(`#y6W`#v9_ zKPCGudBpVo$e$-bMDRq-!5z`(+TvP1)~2TmHt8#zZX ziu#X=jfe&53uxqdqyFP7i!+9s+TSeHelz-i?>qTNfd6s%QxE0;DeXw)&s@wtajui^ zAIY~z{*#9LB}N^X+nRB}*ZSMPC|}7BGUGw&B_3-4_u>Y?xx>iRbVsVn>U`&;%E^hp zOF3Gfs4TVPEZT91cGUTGudZz4=f=NFoS&_jK0T1DdY|~N*4Ny;M1vZ*pH=(Xjo<&b zstlibW>|mi{~*^Rj(7zK*j9(mWydRQnAYUS?=eds<67#Jr@rr?y<4;%zmasJK?`xU zu4parq0iBIZJ{!lbGDdwr^Q0VD|BrS3$K8W^z*kQ_R7ce-H|i0Ux44r8QE)JieE4V zMv@xQ`%X#2moZvk0Tg>0u_b6aLVlQiY!O=PMu)&^rINBTdA#*Nd|6F?= znbfbk_bIU%;DmDq_=Ue&TJrvk*lzY3w7%5dNi*}rk+hswGO!WA`Q}>!jE%q-^6$+X zx%fo$t9Qo$&cpql>S+pOT z8DC19n-~w4jV&hIP$qWZTUIz{{lYhbM=MzEbUixCtCy8 z>{^pPJZ>CENUL#tJ?>}eiGYM#c6ON?c6ON?a@{*bbtXr!2ytfHp*30YFX7iX_0Ab9 z)E3|olsx=%%^BJ8`_Z9kW6sFC;>8wVV&nIt;Dd4Xr)VoH2b7cR@gV zTeMfky(f8VPd0Zra?uHiI{BIxGA>&7{%*yz&n>K5;%8;H`W_$~2g)<2` zxb~*zq-F1KbmuDhCCj#Rp(}U0nlu^%YM0ulww2SiBebo_>TfxBtYi|eJt-eQf&Dl7 zOZ4!3Po9zw%|}+>LR!h6+nMWHf%(8kC8zJ0r#sb+vX##m^6|oaeiG&`OuCs*2R!V+ zTs+RDZawlCBPX<3=fa`Cr>rLU{wCn=>>uUE-^|cB%eCX|ofUc0Idd1=E7)=_Msu@t zj^(%e1l0Xg;@6`isrh3c@}3sX=xBT$dOW{zA@gdSc{RQwZ&x1nXA*PkzmP_C-e%qG z_^jkwB0GMc4bxoF{l1{ipWen9itfheI?`%hAv;n6q~t()HiT-6+lOWJ!S zSGk$=YLmuazUGpqwAfRGU4#F}r_XEqF?-S1;Xm?1zZi#1;=0d3H1r+fz^6|>!kjA} zbuRe#&Zpcl3?D6={UhJ$*N*~^^os@h=WH@pnMSSs8cz4ONzW+JCWFiuc(&Pj>xq%E z`K0S^Zj?;yW7Z#uI(8T5s~OCnFZMvkwLiL}rz3mHg!jlou9=NoGY30JJ!0#F>c6yj zNjhs5{F9(v)m>;;br;%|0qxp1i!%W5xT0U;Y3EVTAbW|H2e|-!UCykOxM%ztkkPg* zf{)et3hd`d4`vp9B|XqXmzXx$cw8%3K-Z*;BmBrDKh0(Raa*of&?vo_J2?Ax=#u<4 z>{cx~NI#U=J*@6@7&Sfz#IGf->Qe~K+z2nzvSQX6*$p}PPDWz`va3LCb?a_)S_buS zT(#G zqj};thZ1X?ocNpgMK?;$5xpH?$7u7_+_?lD^6JD27J{c>Q3u_-19%^CVhJDG$_ zFRO&LMfWZS2Y1g*u2BZDKB>M~^~#B#=GJR4XD^(+=o90?n{K{Z zqcoGRqhFdGf56sj*7R!TuRHu5>E*XH&eHh-@s|?m*&9p3>$Q%0E#Q9Q4C;0i9%Q5R zV^|9^p0@Lb|B}sFfDy6cy%Za&SNIZ4nNA9N;29koW8$am3B^iH8Q*Fqnzfle%eUR({`Sd7m3 zRp^}eh`n&EJvT9KKWpr*cFU~eTxkPzKx40YR({*r;B508XB|9+ICbc9CG>!rFJK+$ z;(hMhOEQl%&CY+cZg#;+Gh++sgp+|%+KnE04r4^)Rp;BJQ$E9UUdquW z8W_KtG%Clmw(rPanb4WYj^`5oqZKBmvpx;01jm6^r=hz%=DB$^A8NOHgF2(sP{ke~ zv`y!%G+zF@mqWKg#BGMQA=A_P-Z=-ITX&w$0S;-}@cL}@?*`+}Lf`Jl)uv5)|M}cg zD1Jb?&j-loKGx}nZQfI-A6}pTO#S-nT7OA6YmWZX^R17vCZNqN1r9v-s_g4n|9`}N z7N5l<-UvOGT;WlFY%k}6PKBR7*lST^iIpq(_AhYfd!32ZSlCM$&DU{mM(v`ELg+}D z_-ev*&M|{Fb|+8Jm~T;8oVjhG{{!f*iAS_$A%jx>Co1bNZhKVL;;v<#fKRL*N1i%= zIVZoZCv~-aw0jP7Zvpt_;bpqE?H80Myh^lh3S}Omef1i570*QdxM-mmW~bq&1?af{lg6=##_ZQBOXnb%n+AXC!I2rA5&1>a#>AbL0Pu zbe{(XcN5*!nr!aDA6Hyx6G?(&NaA4|LmL>yNH|q8~rGf;yZ4_vd-q@B_CE zvUP0x5?n~&`N!alXu$?-xrpY-{|;xLezL^5D_uH^;PjG>$SaUTWvPum;4mCH#Zt;> z(pokVhFs#-Ut<&Wi>$NPv;Kzvd6m4HbDPeqU;k|@WB4=g^=SiJgRiwawun4wSCY1g z`B?Id-N-PcyP1IuVU%x3Qg<^U!;nrT@~0)cyT~EX6Fg215wLQI!SB~e?t&Zw{_Hq8 z#I5fBzs^TCgXUytiW$Q#=yw-!mLtggMl=*&~Zshb*FgeQvAx9OOY( z79m~qpRFITtA3>awQmx?Vg2>2F_8Vh6DppCWy_4%C*ryuK)AxrjFi2kP1-E8ZS6aOP)_(y49Brmt`Z#px!_f2Hp@YDfd zAsMoC?1ekFJ)6&r{hYLBp7=*MZ2Ot9=Lu`_h7C9?_N>D4fd_NLP529&+Uy^&9`PFdRPe@dKny&?s0Ex2W&`E z_c(z=b6gzi%{(VN>Y32G-NL5~SFXj`mhR+QUGb@tT&tH^^2tb@6V7BT<#3*;cl^)7 zle5tQ@|&p#srP)l7RcVekFop7NbG`oY_i&0liRrXA?;kYAn4ZyxIb&QWd& zbNWVqVAHV3wCSUP(LrQU7CuMN?SY2aawy~QqVC(k*&e42)c+ppFBne(#)_{t$Zer~ z)nDaU+d0@(c-WnaF5@2>v66M6pto(=v%a1iV!6RtU7ck+zQKs#r5;*qX!&Q?K)e9Tt2EFQmf8$+azCO-9fs|`; z_NN}4{UJEJy>501ci@N?3@h!7yW_y!x{;1e$CeY&Jn+lPZAJ5jkFaaf#e*n2N}esk z*AXth4yV5tnP(2B<(`xVwsfI^zM%RLo{2F(9bC-;k0f_!qTJQAPc%U^M(2-K@%|2b zE{dC=gU67eH?uYkXm1JHqkesa_307DfoQ$ba_^~2g9bu_2JI59xq`M!ej%B&r5n(L zUBo*AE@GbvJ$75hN5ioJ`z~eFd1&o$(OU8r4Skw4>hFg29eGbD@8-dlhFCm{gKyA~ z*Bfw^|Mzf_&)PQIvRMbeLK#i2{=V7~0{0SSe5ac-hEayfmmCS+`E}VENY;7ttk?^D z2e&L-N}#a@dM3NEhtvFx(p3akEbYwk-S=R=bn=nk%%hz7_%r*@YrEQ!-|Uh6#*y9R z#4GvE9aC0z!?>}sn?zb{#BJTj8J9WehmiM2f$z?WWuk8O{_D{fn%|o)|b2jOO z`x*y@_qOlY2;KQebK@g z5A1E9f_x?GpmWB`;>u5m^G()I%Dd1%=PmDi%s#1b3LWG?e4p~9pS8Zbo4FjBR+4@Q zcU1;@iJ#fePm)ifpM&e6yYSVG@RS)o=dA4~?<{DX1kMOAP!hGY-%E!hU+-*hLUZ_D zbgAwqu6WPFd)jw$4`{AvQ3bB@`zCZn_!Nvm{^C(@y3J*#WFF=xjffu~TvXwISz*46=vbk5vH z`b_*Q3J%I&cY(FPXs}!1L*~hS;p@>?&^R7AE2h3x zpZXaaqRqDw-&|;7DoZqr?=#d^aD313D`#3sEmY*5lpQd`L9`lfw=uAF566NNh z$C20rw(UZ`@;l-N!H<`5+tYd?k3Ai^N+$A^EaWWNq(>IJHkUg}dSI82^fT-_nY&2_ zwSu2}j&za79zh;Eka#mVJ2;0nOif$&U;*xwv^yWX19wu|`Uh>DH=NBHkbMoxzLBz{X$0j@Z zaTgxn$CZA)V1u3VtkTj2JWw*`*PePhs}FaJpW`Z(X~-SVHA&0Sd3A%lm0-4hslUTlDiyPH39=wLc+ z(SDIJ{@4SgRbSJW!r?vhcAp*dv9It)!d2%I(taO#9=45UjOlM;cXR*RIepEHeQAB- z1;~cx%`i(YgC9I)<%;Pm&+B*f&j=d4OY zmIyZAbO-vc#$N1%Q@@8Zm`^D~_0=7QE3@%v}j7>(a4KP&!-3xA!T_zwPBc#L3LT5O^l z{&A6MwEeO@FE*U;)r6~GPP6WScwg)0#Iuw6XU9*+FB+=$*uD4l>+HJt3yRAe6rA)A z?3u!6Sb3OjTW)+Id`8Px=Qd_sCf%mv_rLba4iodxd2ShI0!f=4&Tif+sOLJmUr&S%Ny>NS2w0}c`C=2c>=kZEpu!~nS$y0 zl+bDgZMez)xUyv}7C(mMQoPW(l1!ItIA*_3FX&7ZMxvb?#s*Y;J@nVs`q zz}iOlD%m`#U#C1DIeDIMxp@Xz3wZk`39H|pbDW-%E$3f4%9(`BUpRb_ygm=Co_5R5 zM-SUuwgW5eHRr_F5a*wP6*40Wt3u8!d-Ki!KKsBa@rZ(%Z0g9ypM^hq+9!kmCO6Nf zft~YA!m4&mavx^Y0c?{TFs-)kH+R5FJPL#NbHNE47`82jd$qi6ao{9bcussAak_=m z7f#-$Yu&tqoX_*-tu|R6E5p=!^}lQx1HJ7*4$plRYS&+_n;HL5F5~{5!>+yt{ucM! zuL+a>?kMJF?|H7_+)sOK?RCua*D~KC!b-wIt z_{BH0dFH2eobTeEn5{R^Z+YGDeK+w!js4v7EpgBH5B{S)SF%q-U$n4ZejXj|j2>Dm`u5)gOap!M zu^AC+70;?Ta`TC2&;yYFJET_~ug2Za1Ap6zhZbD)eUV!i>W=;=^BDcGm33RoEHk5h z4ssdJwSLD_zm0Bu?vk6{f}XP4+Lecvj{32+oV|L{bm51Gu|9Ukht9{2&-JL(sxS}t%o4Ovc-w@{-{0&cC z@XRou@0N3b4}@p?))&%a>s}B~n-%|G#IfIxnOjQXr_tZ(-|$r0Gl@K2=DTq7UvTqX zT^{5k&%k?sG_RhukMIVVYTdC@aqap#Q+2SsW)$~o%B-f$LdtxKca=vuSE(G~>~{#$ zw;$k&t|)8*e$kcYUioeRir?F33EU&j_I_spTmP`Ptbeq}KhEQy=<#!pU^4zfkNuzw`M2%j5r($Nv|P|9y}De?0!bdHjbx z{!cvqPd$GB+(dtE>DSZa@9puQ>hYiM@#lE_gFODB9{&iB|16Jxw8uZr{m{PR5ii#`5@9{=SY|6-5-T95w*kN-;^|I&p2Tr<&3GLsQcPc_rbbTh-4(9)vf z@UrD4krgXT%gQS%Z>g$|)~s5+ruJ4dcisgTUUcy#^A{{!bm?W6UvcGCi?3dC&9&EE z|HT_jf$42ZBjsUJR8eY1n49=-ZsLEr>1%GPG8yKksF`VQG-J%orZgNi%gRl(wlZwO zJZdg3tq4WU)zPX*`EoO_g0iovi4>b_EBKjPUTdaK9=kLW4OT~%mxqgkk@9GG zdAKSOy5ORVE(%VYGC5dWQL~gLUbE!lvD1Uq9hrqg<-t{B8FbP+6piR@9Ew*J3xklG;T}%jt(ao7>EwQ{hp;vF8VE zRc#CbqS*E;5$!j(T|gIbxnVatfj84L(Sm420oB#F@|i*4;Z4N{eJ7f}S9dCus7BvQ z!{yekE{y6pQl*oTfaB0HZwKl|#h9c#*Ey?;& zP)+9)wi{JDTZ8HXi#eU^R@teDWCE($ZS?AzW!)zLJ~fqYiVCOhD)MSe zJZ?T7C!7zEZK_`tDqrs4!HI_0jWpUesVr1k;MN#4xhzyUCb+T_invu)ylSUq$Hf~H z^wgUy%nHbD0pwOBzAI%=e)c=K3r&qIvvBrg;5Nj@p=P2#qP=9aB2lrfb?llX;*g{h z##fIg^Is~WezM%{=r4&zlYpwJq9>d(ZCAO)+bES4OkL#Wi374#6xVi_Vp(;8NV4Kr zg5oELvbrk51llFen4pMVxEuoNsfn#Bxe5!qrf{&ziA>j*uTq4S;chEd!yH#o9$sx{ z(t`4e)ry9eX(U`;6z+zcxEaAeRKZ+OnOi!Nl}5@U&OG8Y5e!uOY{^OfqjM6be1SVr*BiY_ z%EOW6B}*%+Y>Ohv>K&gqttk%|Sva4F$c_oFb{jJ$SQYM!H5Nd{C84UaP=O~a7>`8L zY>_Tfl2KF=qVQyf-D5-Nq+y^W$c0yVux3oKGE@sW@7zpp)s{uVr4~awrL$Gj zP%kYlD-c7XoXhBDPnF=-Afw$i2A(kpCqqXs5s!0TFubO+%Cb7e;iA$|RX7M=6e%mK ziH2aCf=j^?NWeJCu*n!KU{$rP!(y^pYX?~Hb~lG*aIV2na9K?`%x6XUILn&`FQ+_W z+UB_BIti*_Jd2`1*yIRYmrWo(Hj&`kP*o&U9zAzV(DhBsQ>90_#o4Idw3hvK8niZe zWhfdASCt3PJKtMH#<~r)QOCiRiB)!3IopKr8gYLmVYs5A(hBCi<(|ewmTBY{)0A=J z#!(3|(#aQbi~4HY5h?{@6;(l~M;V+cAK-p1NIJ#ma}^x=IEM}IoVoHVt*EFBS{B{; z7O4&bv1m!{II-by;K30hUgN^0BW&#}Yf4L1T&TQ)HdF<{ikecg*BEhM=v$j`tpjAY zAHueFtHSQraV{$!93fO0(W%a5q4LNw776s4@FnDQ8$+ifvO8cjfE_@oEf-v}AQ&kI z|07YVpCAqn7TOg`aKtS&;i_7vCDoOp&VYZc8x!PU7&9M*VYA1%tC>y}D+*PHmPX*< zYR9s)AZAe%E`4cfMbXM}$>mD|wLs^xaI~bNIFA*_G6$Vqv|@=8iH;$iL zmp(!Ds2w#41W>yY3nPK9G+aglU66>iwNt6Rg1p!)71YFMir!b7 z8*g@eMs2P(;o{}|jvsHT%OmiuEbc05s#t5l?yy>46TQ&wnDIr>e8@W^rE_>m1%T=t zR2&H{FNa-<6m<>8E3(fL=`mMw*4>r`w91@0VP6<&ti0iJ>;l#W-|T~ZaQ zEHP_G*bW*ob3{$~N?4i1NTkR#7b6G z7LnP+aT7+284)QSG1H700Rdpl;O&xK(Dd!yw>Q+Ss#;(QmyRv1t_)5XckZ|e8YD}_ zDh10}$2uIBCSz!f=FBygWnsRYJTZ8?IkS|BnbkxUSOiBlGgwg*4OT3Jrj%7w)%G@* zT(rbodBxRBlI1V4W{JTvw#s?KWnib_Pvp^eno68JNVdxI%OD?u1d;&yey^65q;xEV~Z1`CDr5RwVw?7x{x z5-KW!K{HiL&FZCQ#F^E=aP948!PQroGbcbGbQl+~{S-nRCXf z@5*ViS~+w4c!+@WNM)#0FXRPb zTPd%@*5d1J@@mRikc~2z+3q&i5ko@;iCINaL?SoP!H(Xw7wt#KP#3<6cVGMV}U{@_& zFD({T)!UiXH$d0LTixv ztPGa}=E)OgOjVFG4-#nexO5CUwLsfXW&`Z zMKZr4){ua_0yz|nBh|3P+<~EeXSIaXx&rySlO^OwQ-Edq#5E|*_)3V*xD}Q5C%oJZ zTv3U49MT>4UA}Rv!%HjOckAuccS(>R57K0dHRaPR>uB`del!1!_}Sv{SUMR(Id<~c zDT$DZ%9?84rzPG?LXnjC5DS%Dj46tljWzhudkr6hworj}%o zJHpf^J*TC-^qO|ajhxweHJ14s=aLC2^US$3Ie z2ER+BZD)<3Pa@R?Zf14|@x37{;biK@?$_K4$ z1NDOvjrT9#`(m&#VE;aHT~6q9`kr|CXif*^OoV+tSNRU%3GiU!!T!lbhelV% z#?QGRv$>Z^n;kGc*Yq|fm}SyF$}+yqxhBn^2>-wUCIo9+zI?nit z&oyadCK_Mi`6ewZ-}LyyJmb6YV&mUE-}urOVi;nf>G{M$lm4dsi%i;umztipT}t_v z8vpFeO!}plnV#EmpS{fZZ@S#{+*V|sz{KTu%O&IlR* zfMVl&yTtgjR-ibu!uXLhm}g5(+Cx>wJP|cL#;h{FtTm?R+iQ%!xR(6ZnjVFBP?tN6 z|Lyg_WP=H8zRMWy6G#ty)%gE_QMh+Enx2(+lWvnq$NFW@D>s=QTQ(bi@E+iBk4cMu zo&3IT(m%p2{)RCxeZ%y8_ZuetW8C5`CVkBo6y>&<9xq`HzVu#`9=+G}*s&E@VBO{I z`%U`0_XC3mjPD~9pC)fJ=~r$uJ#X4({LgMP<^%j29x`crP#|h}*!c77jj!Khrsssm zjDPFn#BVS?qH*J2f|6SE_l@t(C+SBNkludE^tf`T@ipus&NHUh$1j+)*8gSvt*@9~ zJAQ4by-!o=Hi}8QlVtNdDpSB(_8SfqeC6Af3;HRd?WaIO< z_9y?p*az}I_rZ(onieSB$6eSJNa^z->X&h(|3Y@aWEw9jlA?elF$>+W%AO(RG1X2)4K_CTz6a-QbNI@V4ffNK%5ct0ifqr$) zZhXHw?c=l4Ugzw-_p5U@Hv84F{cgkAezz|B`_`2nfZ}JkE?e^U9s4@g?c=)Kd1BwO z`)^(J0<7E5b=ga`@29&i_ABf=#z3r_?Yh|bvG3Rkv@Toz*2T7sbqBfbVAqwdg6j7L z*B$D*=qd2muP*4i!(DfT>yC8YGhFvf*FDR1&vxBB*Tn`4fBou4yY4xzJH~a#y6!mF zb+kSD)nOBZzkYS+y6!~Ro#eWcU3ZG>PIcXBt~=dzIdRWlzq*;OJIi$)9gTi<=eh6a zyRM@s(yuPxeV^;P^IZ1=*S*knFLK?BUH1~#o$tB}To?5T{`%D|a$Qs??E7V|d%5dg z;ksA4?p3b4*mbc-!e75SY@t~98rQwnb+2>X>#b|*94Gagfkb*!80x1Zj zAdrGU3IZtzq#%%jKnemW2&5p8fkb*!80x1ZjAdrGU3IZtzq#%%jKnemW z2&5p8fkb*!80x1ZjAdrGU3IZtzq#%%jKnemW2&5p8fkb*!8 z0x1ZjAdrGU3IZtz{C^h$kAFYz96A3doA7@-{lEWkd*T{`f2aljr}h1RyS#s>QK?8N z2&5p8fkb*!80x1ZjAdrGU3IZtzq#%%jKnemW2&5p8fkb*!8 z0x1ZjAdrGU3IZtzq#%%jKnemW2&5p8fkb*!80x1ZjAdrGU3IZtzq#%%j zKnemW2&5p8fkb*!80x1ZjAdrGU3IhMXfIyH|=pObRK4ZR!ir!jRMvE}pmdGdI;7~WUTb1%iI8vp4$BY4K~T+DMNPccuF=PNv0d7j{TmgiNTKk$6OV|p2XKc3M%vw1G% zxrwKg=gYl}DJZI`DlG_ys%s01O2eV@no4g_q&yP!zE_5;mQ_@hd4sCM(Td7Wk*cFr z;i{^NDmPYjX{0(@5UQ*Umlt;mT2>Vf7lcYnO+mqh;bozk(&*xv^6;eRKQfULz1MbK@){5#N?o04TsB*E{ld$k7cW?B2hv~A1+^IT@_xjtT~p`Rc>?+znM zF^D^{JX990Hq#)f<<(|vw6-!_U}hVCMMWtCK&6|rYa*r5NO^%-m~L7(_(X2XfAS&g{qb0x!^4=>{6pgGBdVJ3Z{*_a>dBPVi1Erqw z+2YMEUu8I4Rc)U0RfS7Ksz!B5q|&_Pt2S@>(##Xr8z=3Nf64y7{X-_No-Vz6&(FYy zK7Hs9msLh<%|Sl{)U^54=k5OT@M?2cTDtjom(BKR{T}@Z$S*s){i5|0P{CpEpqD(e$eDa?y*bf)d6~Ddew_DJyI?r`MEQf@1!S zjGOgDMa|p9+VBT`Kl-%NH@}fc->USF zDy;snZSG5Hq+bT+hO5HG=H8wbAs^@oP!5vDdz{fXV zQncO7r{T!*lBE^k)l)qyio@o&e0(XUk{)}`{=S!}!%@C$d`4m0|C|Wh(ktCO^gD&U z`#Y5ridH)feymp#yW_n~dWeoV+_NZDUQkXU)#lD#;SdDH+}A5=w)ZlDB=$cCC>-p6 zwMV#kIivNzdN4r?d;Zo#9ia5)(;lTzXS2Cyx%qR?YO|YKv^=8nmsf?#3QS9{RVE$) zR+cP0a2jL!5B>OBSruLuSz}%bL@QPT_Ll?34`x(WRVbNxE)cDv9tGxC0h3l*V2-Aj zo9%%$W^W+Pd^CwB?r0Q1UusZ6%wp!A4AGDO-M+bpRaK>be4WEVxg3zYXjW+IIOZ6p znVLCjn&xO~YFSbT$pGbw%7GtYwi8rOT0025aOXqv86M|qhy(CJq0DE z*^pymQew&kwGpvu&eLEnI!nJb=V-jrC{mwzlLc3wdh>$!xwo<;relMVXs1z(u|Ch6 z@+5nuR(NBxf@`(aJHw{VBh#DOC{`YzOr85oCfl^c%miBkawJ<(gk4+h#}syXKmE?b zwep}Hk1b|OW`ZjB(F5mWpGK)Fk?O>LFkvW;2W!BVqwaV(Du7{wYH|wal#rn7A z7F`$Jrr)gVD2(TLSbnw5%4OPVrEYxRnjSMvePpE`Lr)#DBJKsM{4r!%+5&f~3dc`Q zOZ-$f$3n!3XZum&SN$mQLO-fpjvq`~4c)71HjR|a*Jw2sOtr%g zaX<8fMNLnSnPF1}*0_w=n6x;x$x6fgN9&}iHnr3*EhZg}xy3I-9rN>0j?T!+(F!%T z(YiL@KSOVP)L;E^9}EFBM=#v6WH;TobQk@W?7}RKPftZD-$g9vK8#xnW*6Dd488Qd z<3BMKAv}sf;nk8eVCc)-5bKBfZYWxk&rY2@!@lu>M(FUE;~5{%CFW*Jz?b_Adm@~JpQ zH}&fD6Ez|A>#jgr_Vxv$pvBZZ)$h=6Iesy~)#*TNUoRlAR0r1Sz)~HE0^SUqoSvzE z38enRq7;~nHG^h1H9uC+Bvl%mu8v|) zcVZ>AVqpQ95Vt+M6|B2yb_j;|JPLu~oEsuNX17rnsg)rp$OA}Q^Cq=$DSnkXIYaFU z!Cp2)eTcNz*6JQ8q~GH8^qaqiW(NkW`YeR%e>P-N+>8u$5ot2j*GQ7PnWA08FRgNF zL1-*3L^+{oAXqtMQ$)p~^}jGw&oK3NC=S;#={B`26yv#sVy>l_xrG!n#h#%}wK@_y zS)D+jV>{iTLU+GIXIX@4j5bSAKZfc<+ik?!T|%+45tnRVe5P6)mW~BHQ!Nj}R74q& z(R%vL-bfJ-)4j0F#Kx)8u(TxXCf^Ioj7i5TO$J{%ktkOWwJe<|Ya=DCdIyQb%3Tbj zZu&ZmkBwKu_{{hN(iLr@YQQYtLJ5-9%I0VTDzHzia)!pKQ=u~J{uYW;2+lRI(cgw9 zsX1Y3IAW@+OD*@@}O;lJuViuq%4Gv za5i-?1a=ZPtXe^pEMBQwE|-2w;Db`>`TkCLdTO!_b`&SgE#X)hmQakMB`}LPN2yQX zb!Hi&d*b}0R)^aYXIT%&gxw2NKPVrn;)(?W&X zk`r*`jf=(MO@^uRj!`YftFf`E>Up~=!S?beuXy#NH;t<`J_(tbs6nA`qI%UzcF3mA z`eCe1OT`I(iGPw>8JHZS)&-?thd&jqFh5vqlMScgWZqnD4o*`w!I(q^AsOnGaNf9H z3ZF715iPr{1s2!KCWmQ6xv2tAj>^p4rbk5$EiqMj*t5*#zBQherd6JqdHAXDsrId~ z9QJm2)LJS`*FEM1mU)zVRCv}lae9=ScAFihRsrF=O{JzDLo=-wyEWewS!XUX6`AIl ztyZhotR!os)9f@|H)Z2rp*hz))M*N@vxM76*O;O!Oy#B;Q;x;yz1x&!T4mbpF{0Wx zGv7Qb%cIs~@X$zysnDa!tH`s|w8}hUM6UUSxx)!$92r&UVd>$-qp#hjJd@pO&5Vu+ zXobI!-Z|!|pr)TD&Ytc8fJK+hn10ic*Q#zxd-S3P&&Um?E729P?b^ zs%YjM;kI_>HNv%t%$tQB>CEp7S5Id?B0TGP=Ci_eGnu~=?)DP1M>8&84n0E+=A7wrwoPC

irtf@)2|J}j~Ud#i8qk@=63g-kf#|odgk2zDgq&M>%;pm5% zml5OO^%ooS24XyNR8Hny!hMC03ezc;#>WL=r||c}*Mv=hoL}TVjvq+urBuFfd*LGC z?k@h2;|~=s5w;1J2`39Xg=Yv?2+tR;6wVW_5?&`R`{^+HQ}?uH-)bVP6}MxENUyj}WfGxFyE4*ZEKH&x~oSIRQ7KaEEZWrOYdZ zYi=+X3oDrqyM;?{bNE5wYaU$w&xEV|n72QE&Kk%0<9U`2pY<#=rj6#_lK!CZVBurJDw^Y;6)v?g*9upfxqZAafM~pQD&X+D zgd^jb9}u8VS6p}WZ{bK%s55r{ENz%X|qE2o4%JBhiuK3P0VG&)f<=( z3fGA}Juh5wjKePrSMFr~ML1#?a|_ryx?kiM%#p&Q*DyaU+;$7|2;qQr%;Sa2E0|M- z3%4=jm6OiD?Rn-mgi9p94Z`!zaQGhKR#%wukWHtzZ)CnGT${sOD;y#Hb3-@}HXGGa zc%Y@zN5RGtV}GsrS_|fO!lk*)U4;h-_Y-ys4;SwCAjgjvu1RH16)s9)o-S;c@Rx;e ziv5`@?3D4iShzBl(-#Sk7RDJ|mp>tn!z+Z7B)m%4OTw=SS54sfb;8$W{Q7%xennEh zR>G}Dar_R#ctxk%?*ZXT{7>!KUwE*z_i$myJPx-BNBJ?Q2xs~*&lJu|V}3<=`isoD z!kvT*g==2m@U6l{67CdMvVS@zTx#X`)xu+iuLuW7`F<9z_T~6ZQE!?bz0;Y4g{!id z?-VYU_rwQjh&YUHDttWGi za5NTfs^2o<4zeFyEnF;IBpkks<8KwNmi2p=aJleD!rdhP5#c%suM#d5z9^h6{eMH) zOV|f?i`p|p_)cM~aHQ~I>92mmb;3^whfDkk!hO4PeV!LC^k!ZtTq)ykg|I`~D_?k) z@CM-%!#Mp8;X(=DCmcC|!;cF)TQZ*$uK6o-t#GOEb>VBTbNH{q(ZW6`H?>dk5)Ka& zj#$jxS~zz(b7$de!Ve3Fi@keHxYKBk|CDgv6U_0#A;KxbjyE{`dEvp*|MP^clK*1i zBAKtNgnQ?4`nQF%CBL1*QBt1$!Vbyrm@B^A?~L$JDc=?0Tp4e-gtH`lQ`li@zpN+u z{-MHEW0>y|?(h`zpM;C0{5@Rp9UR`@6~2ghnDF2Q%+CmyNc>5{Me{j)ittV0Il@s3 zIsA3uzOON_60XT%UJFKbu*>1Uod*8cz@HlUjDc$ne8a$AZ1>&wyTick4IF9UhYb9v zfkztnX#+`lqW*Bl|H8mG4D8M8vOE4= z%JGS8aCgGp1$Q@G1YB#lHgNaAwS}YS8|~r#0M`NTk8mB~ z?uF|FN6$Mt!`%mmEw1VUcRyTLxNdL{z;%av5UvMYPdIF~6t-6iTSkS)h^i0VpW*t# z^@HmV_XykoxPfqw!VQ9>XD5%r4T1X$+)%h-aF4?chZ_Mm67C7OQE>lTTiinP*1`Q= zd*e}t!s8-kf%Am>SK9wSt&Jm~oBZwD9=8%yON?x!FmP$hY~w{-M(Q&+=oiWK7Qe9% zOV#Kd=N{vDI)z2*`=X%F~5m+2lESQH`4nvH)xHaD;>R% zqmbm7G`fxZx}iV4$mKZG`G34MCq_NBu#B&@xJ+M)Anf-fWevmY#bphB-I52F%!~rj zUM`K84Gl+9rTXqNc<_rpS2TAgN-V96a;e8$k+dfZy7pK7_a%;b+epF4VjF7HoVg_XJBI~jN+`=vbx3o+53&}L0g3{AjzYb@HT7ZK^ z8^xgOtYgto)>$I2~XtlJ5Xg~Bdi>~w~H4*8q zG-&CSzH+IrG&B%kX>Opw(%e9X1$$3M+->#gLU#q!UI{2N79o8F^^sigHv$NRdWyZY z7GB57AdMA16wtbhhND@$8m(9j{bbc@=p`#xLoYpc8+z!T7Y`mRqNK9@R`FrOS~rEO##$+)cZ+Lm`uhkQlu~k~rgiMMWe)I(PSACqWJKZBM^(bRD-e{#)2DIEe$yoiz*Cv$q&K%xY09g&Wqn~%KZ zix#>hX^~b%=@>*Tj?(B79BIHeJkTETrPf99Wdm)L_NX^+l)cNQ%XNbrBSgNY(P1Qr z(&@!hD|AR@q(5(fIfT-PFJ1N1F(B4->6JK?bV%+iEm~s2?O2&))0!W>&CyrTB>iW8 zd-VU|qp$yd|Aa~J`fv%Wnceo^@1N>FpZZt6f8u4`^(`B(YA}B`R!s6%3@?pc7M?Z( z$+Qg0E)813N%Upk#56J!8F99$F-cQk?Iw=5(eclXq&|e;+D?0t2C-qnusLe5@5z{i z{iz`j-j~6mAyfVujVvEbu6x@)Aw6}PeD2}eX!BM%#kJ1KX+{^J(Yb_xtgWt+F&3`_ zjc-F|A3AdKsY+K;=Rq5e#@_mrB;FJBnUu=i_#g~RO-00aC^)Cm$8l6mYAmiaed0-{ zcR3nz6DJ~$cvOJXUJXMh>60F@MQ0|TV=yM$SQE%&}bYFSEV^H|vdAsGjGDFOPPru;@^^$_ZN&mG~=05omW`!s9 z|A#+Q54<_kf2O#kKj9pphK=t~_{oDGgtnVwo%x>U*iLIF-hF!YYOk6@&t_hleAk$z z_l??hepvg_xAF$3t-8>^*RwqrweaYDW^mY&KK^Gz`jme#Y-)U2#Kkio-J7)RgLaSJ zGbSRyuSdzNZ~dBc6RA?A-m5(@0t#S?mqp^mY!>Vm~deDi}~-aOisMl z^!!~H_g&xXRnj+W+fzTe~lBZQB-NPg|%Ce6;+`{KY?8OP2QD8#<=8U10G370H+T&9F7E zTl<2&@4)Hbe)-IO)@>z+4#geaU%q(Ys7sZPzn)dwi_?cD29XKQjE(qU+_?^D9c`B=+#K z^en&o{*HCUFNB$&whw$f{g)d9UwZrde!C71%P#Kvd0klHH%}I9PYAhV_{Qz0B96|# z=W73u@*%wrUm7+tZOi1;trO!q4qE*B$k)!*M85p3>DNPB=bk;2)v;-@_m$P=K64jO zJoVupLOy+Y*}h4OQ?9LabYDJj{`S>HtyjtHFQ;zwo#u0L z^7I{Be4l&dsnj(a#>{x{{&OF6ul?d`T$BFYFTHSIw*y@}KRf8=;n*$lcr>yp!J)ONDnEmcU3#U3B8j{q1p6{H~Up#mu^PNS}CoW|C6xDL**R`AckN>h~ z{pp`JzEr$*Z0i26~B$EfcIeDZXgr@MEUv)6fK>)L;o{@)EB^z69JhZcAyN|RX0w=H@*Mi^!Mkf&pLTk^b0z^yrBC13uU&veKU`y z?>IGPMQxj2ZN9pr@~hbq;Ujxrj(E6VQudJWbt~rNzTxfJr|P7mf6&#lH=E7=Iy>}A z$4QZvjf*;}{wd#_8uLF*o;>ux>`T>Yw^zLO$P49d`(|gaXn!H9wSB^^J7$)=+beJM IhuRqZ10o}@K>z>% literal 0 HcmV?d00001 diff --git a/ide/vessels/el-lsp/src/main.c b/ide/vessels/el-lsp/src/main.c new file mode 100644 index 0000000..f36f443 --- /dev/null +++ b/ide/vessels/el-lsp/src/main.c @@ -0,0 +1,1469 @@ +#include +#include +#include "el_runtime.h" + +el_val_t is_digit_ch(el_val_t ch); +el_val_t is_alpha_ch(el_val_t ch); +el_val_t is_ident_ch(el_val_t ch); +el_val_t extract_prefix(el_val_t source, el_val_t pos); +el_val_t extract_token(el_val_t source, el_val_t pos); +el_val_t pos_to_line_col(el_val_t source, el_val_t pos); +el_val_t json_escape(el_val_t s); +el_val_t json_str(el_val_t s); +el_val_t json_kv_str(el_val_t k, el_val_t v); +el_val_t json_kv_int(el_val_t k, el_val_t v); +el_val_t json_kv_float(el_val_t k, el_val_t v); +el_val_t json_kv_raw(el_val_t k, el_val_t raw_v); +el_val_t json_array_of(el_val_t items); +el_val_t keywords_list(void); +el_val_t builtin_type_names(void); +el_val_t builtin_type_doc(el_val_t name); +el_val_t builtin_fns(void); +el_val_t keyword_doc(el_val_t kw); +el_val_t first_ident_in(el_val_t rest); +el_val_t scan_decls(el_val_t source); +el_val_t list_contains_str(el_val_t xs, el_val_t needle); +el_val_t prefix_score(el_val_t label, el_val_t prefix); +el_val_t completion_json(el_val_t label, el_val_t kind, el_val_t detail, el_val_t doc, el_val_t score); +el_val_t lsp_complete(el_val_t source, el_val_t pos); +el_val_t lsp_hover(el_val_t source, el_val_t pos); +el_val_t diag_json(el_val_t message, el_val_t severity, el_val_t line, el_val_t col); +el_val_t lsp_diagnostics(el_val_t source); +el_val_t outline_item_json(el_val_t kind, el_val_t name, el_val_t line); +el_val_t lsp_outline(el_val_t source); +el_val_t format_strip_trailing(el_val_t line); +el_val_t lsp_format(el_val_t source); +el_val_t lsp_type_graph(el_val_t source); +el_val_t collect_struct_fields(el_val_t source, el_val_t type_name); +el_val_t referenced_type(el_val_t field_str, el_val_t known_types); +el_val_t lsp_definition(el_val_t source, el_val_t pos); +el_val_t lsp_references(el_val_t source, el_val_t pos); +el_val_t lsp_jsonrpc(el_val_t method, el_val_t params_json); +el_val_t read_headers(void); +el_val_t lsp_stdio_loop(void); +el_val_t lsp_main(void); + +el_val_t is_digit_ch(el_val_t ch) { + if (str_eq(ch, EL_STR("0"))) { + return 1; + } + if (str_eq(ch, EL_STR("1"))) { + return 1; + } + if (str_eq(ch, EL_STR("2"))) { + return 1; + } + if (str_eq(ch, EL_STR("3"))) { + return 1; + } + if (str_eq(ch, EL_STR("4"))) { + return 1; + } + if (str_eq(ch, EL_STR("5"))) { + return 1; + } + if (str_eq(ch, EL_STR("6"))) { + return 1; + } + if (str_eq(ch, EL_STR("7"))) { + return 1; + } + if (str_eq(ch, EL_STR("8"))) { + return 1; + } + if (str_eq(ch, EL_STR("9"))) { + return 1; + } + return 0; + return 0; +} + +el_val_t is_alpha_ch(el_val_t ch) { + el_val_t lower = str_to_lower(ch); + if (str_eq(ch, EL_STR(""))) { + return 0; + } + if (!str_eq(lower, str_to_upper(lower))) { + return 1; + } + if (str_contains(EL_STR("abcdefghijklmnopqrstuvwxyz"), ch)) { + return 1; + } + if (str_contains(EL_STR("ABCDEFGHIJKLMNOPQRSTUVWXYZ"), ch)) { + return 1; + } + return 0; + return 0; +} + +el_val_t is_ident_ch(el_val_t ch) { + if (is_digit_ch(ch)) { + return 1; + } + if (is_alpha_ch(ch)) { + return 1; + } + if (str_eq(ch, EL_STR("_"))) { + return 1; + } + return 0; + return 0; +} + +el_val_t extract_prefix(el_val_t source, el_val_t pos) { + el_val_t n = str_len(source); + el_val_t end = pos; + if (end > n) { + end = n; + } + el_val_t start = end; + el_val_t chars = native_string_chars(source); + el_val_t total = native_list_len(chars); + el_val_t scanning = 1; + while (scanning) { + if (start <= 0) { + scanning = 0; + } else { + el_val_t prev = native_list_get(chars, (start - 1)); + if (is_ident_ch(prev)) { + start = (start - 1); + } else { + scanning = 0; + } + } + } + return str_slice(source, start, end); + return 0; +} + +el_val_t extract_token(el_val_t source, el_val_t pos) { + el_val_t n = str_len(source); + if (pos > n) { + return EL_STR(""); + } + el_val_t chars = native_string_chars(source); + el_val_t total = native_list_len(chars); + el_val_t start = pos; + el_val_t go_left = 1; + while (go_left) { + if (start <= 0) { + go_left = 0; + } else { + el_val_t prev = native_list_get(chars, (start - 1)); + if (is_ident_ch(prev)) { + start = (start - 1); + } else { + go_left = 0; + } + } + } + el_val_t end = pos; + el_val_t go_right = 1; + while (go_right) { + if (end >= total) { + go_right = 0; + } else { + el_val_t cur = native_list_get(chars, end); + if (is_ident_ch(cur)) { + end = (end + 1); + } else { + go_right = 0; + } + } + } + return str_slice(source, start, end); + return 0; +} + +el_val_t pos_to_line_col(el_val_t source, el_val_t pos) { + el_val_t n = str_len(source); + el_val_t cap = pos; + if (cap > n) { + cap = n; + } + el_val_t chars = native_string_chars(source); + el_val_t i = 0; + el_val_t line = 1; + el_val_t col = 1; + while (i < cap) { + el_val_t ch = native_list_get(chars, i); + if (str_eq(ch, EL_STR("\n"))) { + line = (line + 1); + col = 1; + } else { + col = (col + 1); + } + i = (i + 1); + } + return el_map_new(2, "line", line, "col", col); + return 0; +} + +el_val_t json_escape(el_val_t s) { + el_val_t chars = native_string_chars(s); + el_val_t n = native_list_len(chars); + el_val_t out = EL_STR(""); + el_val_t i = 0; + while (i < n) { + el_val_t ch = native_list_get(chars, i); + if (str_eq(ch, EL_STR("\""))) { + out = el_str_concat(out, EL_STR("\\\"")); + } else { + if (str_eq(ch, EL_STR("\\"))) { + out = el_str_concat(out, EL_STR("\\\\")); + } else { + if (str_eq(ch, EL_STR("\n"))) { + out = el_str_concat(out, EL_STR("\\n")); + } else { + if (str_eq(ch, EL_STR("\r"))) { + out = el_str_concat(out, EL_STR("\\r")); + } else { + if (str_eq(ch, EL_STR("\t"))) { + out = el_str_concat(out, EL_STR("\\t")); + } else { + out = el_str_concat(out, ch); + } + } + } + } + } + i = (i + 1); + } + return out; + return 0; +} + +el_val_t json_str(el_val_t s) { + return el_str_concat(el_str_concat(EL_STR("\""), json_escape(s)), EL_STR("\"")); + return 0; +} + +el_val_t json_kv_str(el_val_t k, el_val_t v) { + return el_str_concat(el_str_concat(json_str(k), EL_STR(":")), json_str(v)); + return 0; +} + +el_val_t json_kv_int(el_val_t k, el_val_t v) { + return el_str_concat(el_str_concat(json_str(k), EL_STR(":")), int_to_str(v)); + return 0; +} + +el_val_t json_kv_float(el_val_t k, el_val_t v) { + return el_str_concat(el_str_concat(json_str(k), EL_STR(":")), float_to_str(v)); + return 0; +} + +el_val_t json_kv_raw(el_val_t k, el_val_t raw_v) { + return el_str_concat(el_str_concat(json_str(k), EL_STR(":")), raw_v); + return 0; +} + +el_val_t json_array_of(el_val_t items) { + el_val_t n = native_list_len(items); + el_val_t out = EL_STR("["); + el_val_t i = 0; + while (i < n) { + if (i > 0) { + out = el_str_concat(out, EL_STR(",")); + } + out = el_str_concat(out, native_list_get(items, i)); + i = (i + 1); + } + return el_str_concat(out, EL_STR("]")); + return 0; +} + +el_val_t keywords_list(void) { + el_val_t ks = native_list_empty(); + ks = native_list_append(ks, EL_STR("let")); + ks = native_list_append(ks, EL_STR("fn")); + ks = native_list_append(ks, EL_STR("type")); + ks = native_list_append(ks, EL_STR("enum")); + ks = native_list_append(ks, EL_STR("match")); + ks = native_list_append(ks, EL_STR("return")); + ks = native_list_append(ks, EL_STR("activate")); + ks = native_list_append(ks, EL_STR("where")); + ks = native_list_append(ks, EL_STR("sealed")); + ks = native_list_append(ks, EL_STR("if")); + ks = native_list_append(ks, EL_STR("else")); + ks = native_list_append(ks, EL_STR("for")); + ks = native_list_append(ks, EL_STR("in")); + ks = native_list_append(ks, EL_STR("while")); + ks = native_list_append(ks, EL_STR("true")); + ks = native_list_append(ks, EL_STR("false")); + ks = native_list_append(ks, EL_STR("test")); + ks = native_list_append(ks, EL_STR("seed")); + ks = native_list_append(ks, EL_STR("assert")); + ks = native_list_append(ks, EL_STR("target")); + ks = native_list_append(ks, EL_STR("protocol")); + ks = native_list_append(ks, EL_STR("impl")); + ks = native_list_append(ks, EL_STR("import")); + ks = native_list_append(ks, EL_STR("from")); + ks = native_list_append(ks, EL_STR("as")); + ks = native_list_append(ks, EL_STR("with")); + ks = native_list_append(ks, EL_STR("retry")); + ks = native_list_append(ks, EL_STR("times")); + ks = native_list_append(ks, EL_STR("fallback")); + ks = native_list_append(ks, EL_STR("reason")); + ks = native_list_append(ks, EL_STR("parallel")); + ks = native_list_append(ks, EL_STR("trace")); + ks = native_list_append(ks, EL_STR("requires")); + ks = native_list_append(ks, EL_STR("deploy")); + ks = native_list_append(ks, EL_STR("to")); + ks = native_list_append(ks, EL_STR("via")); + ks = native_list_append(ks, EL_STR("vessel")); + ks = native_list_append(ks, EL_STR("cgi")); + return ks; + return 0; +} + +el_val_t builtin_type_names(void) { + el_val_t ts = native_list_empty(); + ts = native_list_append(ts, EL_STR("Int")); + ts = native_list_append(ts, EL_STR("Float")); + ts = native_list_append(ts, EL_STR("String")); + ts = native_list_append(ts, EL_STR("Bool")); + ts = native_list_append(ts, EL_STR("Uuid")); + ts = native_list_append(ts, EL_STR("Void")); + ts = native_list_append(ts, EL_STR("Any")); + return ts; + return 0; +} + +el_val_t builtin_type_doc(el_val_t name) { + if (str_eq(name, EL_STR("Int"))) { + return EL_STR("64-bit signed integer"); + } + if (str_eq(name, EL_STR("Float"))) { + return EL_STR("64-bit IEEE 754 double"); + } + if (str_eq(name, EL_STR("String"))) { + return EL_STR("UTF-8 string"); + } + if (str_eq(name, EL_STR("Bool"))) { + return EL_STR("Boolean value"); + } + if (str_eq(name, EL_STR("Uuid"))) { + return EL_STR("RFC 4122 UUID"); + } + if (str_eq(name, EL_STR("Void"))) { + return EL_STR("Unit type — no value"); + } + if (str_eq(name, EL_STR("Any"))) { + return EL_STR("Dynamically-typed value"); + } + return EL_STR(""); + return 0; +} + +el_val_t builtin_fns(void) { + el_val_t xs = native_list_empty(); + xs = native_list_append(xs, EL_STR("println")); + xs = native_list_append(xs, EL_STR("fn(value: String) -> Void")); + xs = native_list_append(xs, EL_STR("print")); + xs = native_list_append(xs, EL_STR("fn(value: String) -> Void")); + xs = native_list_append(xs, EL_STR("readline")); + xs = native_list_append(xs, EL_STR("fn() -> String")); + xs = native_list_append(xs, EL_STR("args")); + xs = native_list_append(xs, EL_STR("fn() -> [String]")); + xs = native_list_append(xs, EL_STR("int_to_str")); + xs = native_list_append(xs, EL_STR("fn(n: Int) -> String")); + xs = native_list_append(xs, EL_STR("str_to_int")); + xs = native_list_append(xs, EL_STR("fn(s: String) -> Int")); + xs = native_list_append(xs, EL_STR("str_len")); + xs = native_list_append(xs, EL_STR("fn(s: String) -> Int")); + xs = native_list_append(xs, EL_STR("str_slice")); + xs = native_list_append(xs, EL_STR("fn(s: String, start: Int, end: Int) -> String")); + xs = native_list_append(xs, EL_STR("str_concat")); + xs = native_list_append(xs, EL_STR("fn(a: String, b: String) -> String")); + xs = native_list_append(xs, EL_STR("str_contains")); + xs = native_list_append(xs, EL_STR("fn(s: String, sub: String) -> Bool")); + xs = native_list_append(xs, EL_STR("str_starts_with")); + xs = native_list_append(xs, EL_STR("fn(s: String, p: String) -> Bool")); + xs = native_list_append(xs, EL_STR("str_ends_with")); + xs = native_list_append(xs, EL_STR("fn(s: String, suf: String) -> Bool")); + xs = native_list_append(xs, EL_STR("str_to_upper")); + xs = native_list_append(xs, EL_STR("fn(s: String) -> String")); + xs = native_list_append(xs, EL_STR("str_to_lower")); + xs = native_list_append(xs, EL_STR("fn(s: String) -> String")); + xs = native_list_append(xs, EL_STR("str_split")); + xs = native_list_append(xs, EL_STR("fn(s: String, sep: String) -> [String]")); + xs = native_list_append(xs, EL_STR("str_trim")); + xs = native_list_append(xs, EL_STR("fn(s: String) -> String")); + xs = native_list_append(xs, EL_STR("str_replace")); + xs = native_list_append(xs, EL_STR("fn(s: String, from: String, to: String) -> String")); + xs = native_list_append(xs, EL_STR("str_index_of")); + xs = native_list_append(xs, EL_STR("fn(s: String, sub: String) -> Int")); + xs = native_list_append(xs, EL_STR("float_to_str")); + xs = native_list_append(xs, EL_STR("fn(f: Float) -> String")); + xs = native_list_append(xs, EL_STR("str_to_float")); + xs = native_list_append(xs, EL_STR("fn(s: String) -> Float")); + xs = native_list_append(xs, EL_STR("math_sqrt")); + xs = native_list_append(xs, EL_STR("fn(n: Float) -> Float")); + xs = native_list_append(xs, EL_STR("math_log")); + xs = native_list_append(xs, EL_STR("fn(n: Float) -> Float")); + xs = native_list_append(xs, EL_STR("math_sin")); + xs = native_list_append(xs, EL_STR("fn(n: Float) -> Float")); + xs = native_list_append(xs, EL_STR("math_cos")); + xs = native_list_append(xs, EL_STR("fn(n: Float) -> Float")); + xs = native_list_append(xs, EL_STR("math_pi")); + xs = native_list_append(xs, EL_STR("fn() -> Float")); + xs = native_list_append(xs, EL_STR("el_abs")); + xs = native_list_append(xs, EL_STR("fn(n: Int) -> Int")); + xs = native_list_append(xs, EL_STR("el_min")); + xs = native_list_append(xs, EL_STR("fn(a: Int, b: Int) -> Int")); + xs = native_list_append(xs, EL_STR("el_max")); + xs = native_list_append(xs, EL_STR("fn(a: Int, b: Int) -> Int")); + xs = native_list_append(xs, EL_STR("el_list_empty")); + xs = native_list_append(xs, EL_STR("fn() -> [Any]")); + xs = native_list_append(xs, EL_STR("el_list_len")); + xs = native_list_append(xs, EL_STR("fn(l: [Any]) -> Int")); + xs = native_list_append(xs, EL_STR("el_list_get")); + xs = native_list_append(xs, EL_STR("fn(l: [Any], i: Int) -> Any")); + xs = native_list_append(xs, EL_STR("el_list_append")); + xs = native_list_append(xs, EL_STR("fn(l: [Any], v: Any) -> [Any]")); + xs = native_list_append(xs, EL_STR("list_join")); + xs = native_list_append(xs, EL_STR("fn(l: [String], sep: String) -> String")); + xs = native_list_append(xs, EL_STR("list_range")); + xs = native_list_append(xs, EL_STR("fn(start: Int, end: Int) -> [Int]")); + xs = native_list_append(xs, EL_STR("el_map_get")); + xs = native_list_append(xs, EL_STR("fn(m: Map, k: String) -> Any")); + xs = native_list_append(xs, EL_STR("el_map_set")); + xs = native_list_append(xs, EL_STR("fn(m: Map, k: String, v: Any) -> Map")); + xs = native_list_append(xs, EL_STR("json_parse")); + xs = native_list_append(xs, EL_STR("fn(s: String) -> Any")); + xs = native_list_append(xs, EL_STR("json_stringify")); + xs = native_list_append(xs, EL_STR("fn(v: Any) -> String")); + xs = native_list_append(xs, EL_STR("json_get_string")); + xs = native_list_append(xs, EL_STR("fn(j: String, k: String) -> String")); + xs = native_list_append(xs, EL_STR("json_get_int")); + xs = native_list_append(xs, EL_STR("fn(j: String, k: String) -> Int")); + xs = native_list_append(xs, EL_STR("json_get_bool")); + xs = native_list_append(xs, EL_STR("fn(j: String, k: String) -> Bool")); + xs = native_list_append(xs, EL_STR("http_get")); + xs = native_list_append(xs, EL_STR("fn(url: String) -> String")); + xs = native_list_append(xs, EL_STR("http_post")); + xs = native_list_append(xs, EL_STR("fn(url: String, body: String) -> String")); + xs = native_list_append(xs, EL_STR("fs_read")); + xs = native_list_append(xs, EL_STR("fn(path: String) -> String")); + xs = native_list_append(xs, EL_STR("fs_write")); + xs = native_list_append(xs, EL_STR("fn(path: String, content: String) -> Bool")); + xs = native_list_append(xs, EL_STR("fs_list")); + xs = native_list_append(xs, EL_STR("fn(path: String) -> [String]")); + xs = native_list_append(xs, EL_STR("env")); + xs = native_list_append(xs, EL_STR("fn(key: String) -> String")); + xs = native_list_append(xs, EL_STR("uuid_new")); + xs = native_list_append(xs, EL_STR("fn() -> String")); + xs = native_list_append(xs, EL_STR("time_now")); + xs = native_list_append(xs, EL_STR("fn() -> Int")); + xs = native_list_append(xs, EL_STR("time_now_utc")); + xs = native_list_append(xs, EL_STR("fn() -> Int")); + xs = native_list_append(xs, EL_STR("sleep_ms")); + xs = native_list_append(xs, EL_STR("fn(ms: Int) -> Void")); + xs = native_list_append(xs, EL_STR("engram_node")); + xs = native_list_append(xs, EL_STR("fn(content: String, kind: String, salience: Float) -> String")); + xs = native_list_append(xs, EL_STR("engram_search")); + xs = native_list_append(xs, EL_STR("fn(q: String, limit: Int) -> [Map]")); + xs = native_list_append(xs, EL_STR("engram_activate")); + xs = native_list_append(xs, EL_STR("fn(q: String, depth: Int) -> [Map]")); + xs = native_list_append(xs, EL_STR("engram_neighbors")); + xs = native_list_append(xs, EL_STR("fn(id: String) -> [Map]")); + xs = native_list_append(xs, EL_STR("engram_connect")); + xs = native_list_append(xs, EL_STR("fn(from: String, to: String, w: Float, rel: String) -> Void")); + xs = native_list_append(xs, EL_STR("dharma_connect")); + xs = native_list_append(xs, EL_STR("fn(cgi: String) -> String")); + xs = native_list_append(xs, EL_STR("dharma_send")); + xs = native_list_append(xs, EL_STR("fn(channel: String, content: String) -> String")); + xs = native_list_append(xs, EL_STR("dharma_emit")); + xs = native_list_append(xs, EL_STR("fn(event: String, payload: String) -> Void")); + xs = native_list_append(xs, EL_STR("dharma_field")); + xs = native_list_append(xs, EL_STR("fn(event: String) -> Map")); + xs = native_list_append(xs, EL_STR("llm_call")); + xs = native_list_append(xs, EL_STR("fn(model: String, prompt: String) -> String")); + return xs; + return 0; +} + +el_val_t keyword_doc(el_val_t kw) { + if (str_eq(kw, EL_STR("let"))) { + return EL_STR("let name: Type = expr — declare an immutable binding."); + } + if (str_eq(kw, EL_STR("fn"))) { + return EL_STR("fn name(params) -> Ret { body } — define a function."); + } + if (str_eq(kw, EL_STR("type"))) { + return EL_STR("type Name { field: Type } — struct definition."); + } + if (str_eq(kw, EL_STR("enum"))) { + return EL_STR("enum Name { Variant1, Variant2(Type) } — enum definition."); + } + if (str_eq(kw, EL_STR("match"))) { + return EL_STR("match expr { Pattern => body } — pattern match."); + } + if (str_eq(kw, EL_STR("return"))) { + return EL_STR("return value — exit the enclosing function."); + } + if (str_eq(kw, EL_STR("if"))) { + return EL_STR("if cond { ... } else { ... } — conditional."); + } + if (str_eq(kw, EL_STR("for"))) { + return EL_STR("for item in collection { ... } — iterate."); + } + if (str_eq(kw, EL_STR("while"))) { + return EL_STR("while cond { ... } — loop while cond is truthy."); + } + if (str_eq(kw, EL_STR("import"))) { + return EL_STR("import \"path.el\" — pull in another module."); + } + if (str_eq(kw, EL_STR("from"))) { + return EL_STR("from module import { Name } — selective import."); + } + if (str_eq(kw, EL_STR("vessel"))) { + return EL_STR("vessel \"name\" { ... } — manifest declaration."); + } + if (str_eq(kw, EL_STR("cgi"))) { + return EL_STR("cgi \"name\" { dharma_id: ... } — CGI identity."); + } + if (str_eq(kw, EL_STR("activate"))) { + return EL_STR("activate Type where \"query\" — spreading-activation retrieval."); + } + if (str_eq(kw, EL_STR("sealed"))) { + return EL_STR("sealed { ... } — capability-restricted block."); + } + if (str_eq(kw, EL_STR("protocol"))) { + return EL_STR("protocol Name { fn method(self) -> R } — trait-like."); + } + if (str_eq(kw, EL_STR("impl"))) { + return EL_STR("impl Protocol for Type { ... } — protocol implementation."); + } + if (str_eq(kw, EL_STR("with"))) { + return EL_STR("with retry/fallback clause."); + } + if (str_eq(kw, EL_STR("retry"))) { + return EL_STR("retry times N — retry policy."); + } + if (str_eq(kw, EL_STR("fallback"))) { + return EL_STR("fallback { default } — fallback on failure."); + } + if (str_eq(kw, EL_STR("true"))) { + return EL_STR("Boolean literal."); + } + if (str_eq(kw, EL_STR("false"))) { + return EL_STR("Boolean literal."); + } + return EL_STR(""); + return 0; +} + +el_val_t first_ident_in(el_val_t rest) { + el_val_t trimmed = str_trim(rest); + el_val_t n = str_len(trimmed); + if (n == 0) { + return EL_STR(""); + } + el_val_t chars = native_string_chars(trimmed); + el_val_t i = 0; + el_val_t total = native_list_len(chars); + while (i < total) { + el_val_t ch = native_list_get(chars, i); + if (!is_ident_ch(ch)) { + return str_slice(trimmed, 0, i); + } + i = (i + 1); + } + return trimmed; + return 0; +} + +el_val_t scan_decls(el_val_t source) { + el_val_t lines = str_split(source, EL_STR("\n")); + el_val_t n = native_list_len(lines); + el_val_t types = native_list_empty(); + el_val_t kinds = native_list_empty(); + el_val_t fns = native_list_empty(); + el_val_t tlines = native_list_empty(); + el_val_t flines = native_list_empty(); + el_val_t i = 0; + while (i < n) { + el_val_t line = native_list_get(lines, i); + el_val_t trimmed = str_trim(line); + el_val_t lineno = (i + 1); + if (str_starts_with(trimmed, EL_STR("fn "))) { + el_val_t name = first_ident_in(str_slice(trimmed, 3, str_len(trimmed))); + if (!str_eq(name, EL_STR(""))) { + fns = native_list_append(fns, name); + flines = native_list_append(flines, lineno); + } + } else { + if (str_starts_with(trimmed, EL_STR("type "))) { + el_val_t name = first_ident_in(str_slice(trimmed, 5, str_len(trimmed))); + if (!str_eq(name, EL_STR(""))) { + types = native_list_append(types, name); + kinds = native_list_append(kinds, EL_STR("type")); + tlines = native_list_append(tlines, lineno); + } + } else { + if (str_starts_with(trimmed, EL_STR("enum "))) { + el_val_t name = first_ident_in(str_slice(trimmed, 5, str_len(trimmed))); + if (!str_eq(name, EL_STR(""))) { + types = native_list_append(types, name); + kinds = native_list_append(kinds, EL_STR("enum")); + tlines = native_list_append(tlines, lineno); + } + } else { + if (str_starts_with(trimmed, EL_STR("protocol "))) { + el_val_t name = first_ident_in(str_slice(trimmed, 9, str_len(trimmed))); + if (!str_eq(name, EL_STR(""))) { + types = native_list_append(types, name); + kinds = native_list_append(kinds, EL_STR("protocol")); + tlines = native_list_append(tlines, lineno); + } + } + } + } + } + i = (i + 1); + } + return el_map_new(5, "types", types, "type_kind", kinds, "fns", fns, "type_lines", tlines, "fn_lines", flines); + return 0; +} + +el_val_t list_contains_str(el_val_t xs, el_val_t needle) { + el_val_t n = native_list_len(xs); + el_val_t i = 0; + while (i < n) { + if (str_eq(native_list_get(xs, i), needle)) { + return 1; + } + i = (i + 1); + } + return 0; + return 0; +} + +el_val_t prefix_score(el_val_t label, el_val_t prefix) { + if (str_eq(prefix, EL_STR(""))) { + return el_from_float(0.5); + } + el_val_t lower_label = str_to_lower(label); + el_val_t lower_prefix = str_to_lower(prefix); + if (str_starts_with(lower_label, lower_prefix)) { + el_val_t lp = str_len(lower_prefix); + el_val_t ll = str_len(lower_label); + if (ll == 0) { + return el_from_float(0.0); + } + return (int_to_float(lp) / int_to_float(ll)); + } + return el_from_float(0.0); + return 0; +} + +el_val_t completion_json(el_val_t label, el_val_t kind, el_val_t detail, el_val_t doc, el_val_t score) { + el_val_t parts = native_list_empty(); + parts = native_list_append(parts, json_kv_str(EL_STR("label"), label)); + parts = native_list_append(parts, json_kv_str(EL_STR("kind"), kind)); + parts = native_list_append(parts, json_kv_str(EL_STR("detail"), detail)); + if (str_eq(doc, EL_STR(""))) { + parts = native_list_append(parts, json_kv_raw(EL_STR("documentation"), EL_STR("null"))); + } else { + parts = native_list_append(parts, json_kv_str(EL_STR("documentation"), doc)); + } + parts = native_list_append(parts, json_kv_float(EL_STR("score"), score)); + return el_str_concat(el_str_concat(EL_STR("{"), list_join(parts, EL_STR(","))), EL_STR("}")); + return 0; +} + +el_val_t lsp_complete(el_val_t source, el_val_t pos) { + el_val_t prefix = extract_prefix(source, pos); + el_val_t lower_prefix = str_to_lower(prefix); + el_val_t prefix_empty = str_eq(prefix, EL_STR("")); + el_val_t items = native_list_empty(); + el_val_t kws = keywords_list(); + el_val_t nk = native_list_len(kws); + el_val_t i = 0; + while (i < nk) { + el_val_t kw = native_list_get(kws, i); + if (prefix_empty) { + el_val_t s = prefix_score(kw, prefix); + items = native_list_append(items, completion_json(kw, EL_STR("keyword"), EL_STR("keyword"), keyword_doc(kw), s)); + } else { + if (str_starts_with(kw, prefix)) { + el_val_t s = prefix_score(kw, prefix); + items = native_list_append(items, completion_json(kw, EL_STR("keyword"), EL_STR("keyword"), keyword_doc(kw), s)); + } + } + i = (i + 1); + } + el_val_t bts = builtin_type_names(); + el_val_t nb = native_list_len(bts); + i = 0; + while (i < nb) { + el_val_t name = native_list_get(bts, i); + el_val_t lname = str_to_lower(name); + if (prefix_empty) { + el_val_t s = (el_from_float(0.5) + el_from_float(0.1)); + items = native_list_append(items, completion_json(name, EL_STR("type"), builtin_type_doc(name), el_str_concat(EL_STR("Built-in type: "), builtin_type_doc(name)), s)); + } else { + if (str_starts_with(lname, lower_prefix)) { + el_val_t s = el_str_concat(prefix_score(name, prefix), el_from_float(0.1)); + items = native_list_append(items, completion_json(name, EL_STR("type"), builtin_type_doc(name), el_str_concat(EL_STR("Built-in type: "), builtin_type_doc(name)), s)); + } + } + i = (i + 1); + } + el_val_t decls = scan_decls(source); + el_val_t utypes = el_get_field(decls, EL_STR("types")); + el_val_t ukinds = el_get_field(decls, EL_STR("type_kind")); + el_val_t nu = native_list_len(utypes); + i = 0; + while (i < nu) { + el_val_t name = native_list_get(utypes, i); + el_val_t kind = native_list_get(ukinds, i); + el_val_t lname = str_to_lower(name); + el_val_t include = 0; + if (prefix_empty) { + include = 1; + } + if (str_starts_with(lname, lower_prefix)) { + include = 1; + } + if (include) { + el_val_t s = el_str_concat(prefix_score(name, prefix), el_from_float(0.15)); + items = native_list_append(items, completion_json(name, EL_STR("type"), el_str_concat(el_str_concat(kind, EL_STR(" ")), name), el_str_concat(el_str_concat(el_str_concat(EL_STR("User-defined "), kind), EL_STR(" ")), name), s)); + } + i = (i + 1); + } + el_val_t bfns = builtin_fns(); + el_val_t nf = native_list_len(bfns); + i = 0; + while (i < nf) { + el_val_t name = native_list_get(bfns, i); + el_val_t sig = native_list_get(bfns, (i + 1)); + el_val_t lname = str_to_lower(name); + el_val_t include = 0; + if (prefix_empty) { + include = 1; + } + if (str_starts_with(lname, lower_prefix)) { + include = 1; + } + if (include) { + el_val_t s = el_str_concat(prefix_score(name, prefix), el_from_float(0.11)); + items = native_list_append(items, completion_json(name, EL_STR("function"), sig, el_str_concat(el_str_concat(el_str_concat(EL_STR("Built-in: "), name), EL_STR(" :: ")), sig), s)); + } + i = (i + 2); + } + el_val_t ufns = el_get_field(decls, EL_STR("fns")); + el_val_t nuf = native_list_len(ufns); + i = 0; + while (i < nuf) { + el_val_t name = native_list_get(ufns, i); + el_val_t lname = str_to_lower(name); + el_val_t include = 0; + if (prefix_empty) { + include = 1; + } + if (str_starts_with(lname, lower_prefix)) { + include = 1; + } + if (include) { + el_val_t s = el_str_concat(prefix_score(name, prefix), el_from_float(0.12)); + items = native_list_append(items, completion_json(name, EL_STR("function"), el_str_concat(EL_STR("fn "), name), el_str_concat(EL_STR("User function: "), name), s)); + } + i = (i + 1); + } + return json_array_of(items); + return 0; +} + +el_val_t lsp_hover(el_val_t source, el_val_t pos) { + el_val_t token = extract_token(source, pos); + if (str_eq(token, EL_STR(""))) { + return EL_STR("null"); + } + el_val_t doc = builtin_type_doc(token); + if (!str_eq(doc, EL_STR(""))) { + el_val_t parts = native_list_empty(); + parts = native_list_append(parts, json_kv_str(EL_STR("type_name"), token)); + parts = native_list_append(parts, json_kv_str(EL_STR("documentation"), doc)); + parts = native_list_append(parts, json_kv_raw(EL_STR("engram_node_type"), EL_STR("null"))); + return el_str_concat(el_str_concat(EL_STR("{"), list_join(parts, EL_STR(","))), EL_STR("}")); + } + el_val_t decls = scan_decls(source); + el_val_t utypes = el_get_field(decls, EL_STR("types")); + el_val_t ukinds = el_get_field(decls, EL_STR("type_kind")); + el_val_t nu = native_list_len(utypes); + el_val_t i = 0; + while (i < nu) { + el_val_t name = native_list_get(utypes, i); + if (str_eq(name, token)) { + el_val_t kind = native_list_get(ukinds, i); + el_val_t parts = native_list_empty(); + parts = native_list_append(parts, json_kv_str(EL_STR("type_name"), token)); + parts = native_list_append(parts, json_kv_str(EL_STR("documentation"), el_str_concat(el_str_concat(kind, EL_STR(" ")), token))); + parts = native_list_append(parts, json_kv_raw(EL_STR("engram_node_type"), EL_STR("null"))); + return el_str_concat(el_str_concat(EL_STR("{"), list_join(parts, EL_STR(","))), EL_STR("}")); + } + i = (i + 1); + } + el_val_t ufns = el_get_field(decls, EL_STR("fns")); + el_val_t nuf = native_list_len(ufns); + i = 0; + while (i < nuf) { + el_val_t name = native_list_get(ufns, i); + if (str_eq(name, token)) { + el_val_t parts = native_list_empty(); + parts = native_list_append(parts, json_kv_str(EL_STR("type_name"), token)); + parts = native_list_append(parts, json_kv_str(EL_STR("documentation"), el_str_concat(EL_STR("fn "), token))); + parts = native_list_append(parts, json_kv_raw(EL_STR("engram_node_type"), EL_STR("null"))); + return el_str_concat(el_str_concat(EL_STR("{"), list_join(parts, EL_STR(","))), EL_STR("}")); + } + i = (i + 1); + } + el_val_t bfns = builtin_fns(); + el_val_t nf = native_list_len(bfns); + i = 0; + while (i < nf) { + el_val_t name = native_list_get(bfns, i); + if (str_eq(name, token)) { + el_val_t sig = native_list_get(bfns, (i + 1)); + el_val_t parts = native_list_empty(); + parts = native_list_append(parts, json_kv_str(EL_STR("type_name"), token)); + parts = native_list_append(parts, json_kv_str(EL_STR("documentation"), el_str_concat(el_str_concat(el_str_concat(EL_STR("fn "), token), EL_STR(" :: ")), sig))); + parts = native_list_append(parts, json_kv_raw(EL_STR("engram_node_type"), EL_STR("null"))); + return el_str_concat(el_str_concat(EL_STR("{"), list_join(parts, EL_STR(","))), EL_STR("}")); + } + i = (i + 2); + } + el_val_t kdoc = keyword_doc(token); + if (!str_eq(kdoc, EL_STR(""))) { + el_val_t parts = native_list_empty(); + parts = native_list_append(parts, json_kv_str(EL_STR("type_name"), token)); + parts = native_list_append(parts, json_kv_str(EL_STR("documentation"), kdoc)); + parts = native_list_append(parts, json_kv_raw(EL_STR("engram_node_type"), EL_STR("null"))); + return el_str_concat(el_str_concat(EL_STR("{"), list_join(parts, EL_STR(","))), EL_STR("}")); + } + return EL_STR("null"); + return 0; +} + +el_val_t diag_json(el_val_t message, el_val_t severity, el_val_t line, el_val_t col) { + el_val_t parts = native_list_empty(); + parts = native_list_append(parts, json_kv_str(EL_STR("message"), message)); + parts = native_list_append(parts, json_kv_str(EL_STR("severity"), severity)); + if (line > 0) { + parts = native_list_append(parts, json_kv_int(EL_STR("line"), line)); + parts = native_list_append(parts, json_kv_int(EL_STR("col"), col)); + } else { + parts = native_list_append(parts, json_kv_raw(EL_STR("line"), EL_STR("null"))); + parts = native_list_append(parts, json_kv_raw(EL_STR("col"), EL_STR("null"))); + } + return el_str_concat(el_str_concat(EL_STR("{"), list_join(parts, EL_STR(","))), EL_STR("}")); + return 0; +} + +el_val_t lsp_diagnostics(el_val_t source) { + el_val_t chars = native_string_chars(source); + el_val_t n = native_list_len(chars); + el_val_t diags = native_list_empty(); + el_val_t depth_brace = 0; + el_val_t depth_paren = 0; + el_val_t depth_brack = 0; + el_val_t i = 0; + el_val_t line = 1; + el_val_t col = 1; + el_val_t in_string = 0; + el_val_t string_start_line = 0; + el_val_t string_start_col = 0; + el_val_t in_comment = 0; + while (i < n) { + el_val_t ch = native_list_get(chars, i); + if (in_comment) { + if (str_eq(ch, EL_STR("\n"))) { + in_comment = 0; + line = (line + 1); + col = 1; + } else { + col = (col + 1); + } + i = (i + 1); + } else { + if (in_string) { + if (str_eq(ch, EL_STR("\\"))) { + i = (i + 1); + col = (col + 1); + if (i < n) { + el_val_t esc = native_list_get(chars, i); + if (str_eq(esc, EL_STR("\n"))) { + line = (line + 1); + col = 1; + } else { + col = (col + 1); + } + i = (i + 1); + } + } else { + if (str_eq(ch, EL_STR("\""))) { + in_string = 0; + i = (i + 1); + col = (col + 1); + } else { + if (str_eq(ch, EL_STR("\n"))) { + line = (line + 1); + col = 1; + i = (i + 1); + } else { + col = (col + 1); + i = (i + 1); + } + } + } + } else { + if (str_eq(ch, EL_STR("\""))) { + in_string = 1; + string_start_line = line; + string_start_col = col; + i = (i + 1); + col = (col + 1); + } else { + if (str_eq(ch, EL_STR("/"))) { + el_val_t next_i = (i + 1); + el_val_t is_line_comment = 0; + if (next_i < n) { + el_val_t next_ch = native_list_get(chars, next_i); + if (str_eq(next_ch, EL_STR("/"))) { + is_line_comment = 1; + } + } + if (is_line_comment) { + in_comment = 1; + i = (i + 2); + col = (col + 2); + } else { + i = (i + 1); + col = (col + 1); + } + } else { + if (str_eq(ch, EL_STR("{"))) { + depth_brace = (depth_brace + 1); + i = (i + 1); + col = (col + 1); + } else { + if (str_eq(ch, EL_STR("}"))) { + depth_brace = (depth_brace - 1); + if (depth_brace < 0) { + diags = native_list_append(diags, diag_json(EL_STR("unmatched `}`"), EL_STR("error"), line, col)); + depth_brace = 0; + } + i = (i + 1); + col = (col + 1); + } else { + if (str_eq(ch, EL_STR("("))) { + depth_paren = (depth_paren + 1); + i = (i + 1); + col = (col + 1); + } else { + if (str_eq(ch, EL_STR(")"))) { + depth_paren = (depth_paren - 1); + if (depth_paren < 0) { + diags = native_list_append(diags, diag_json(EL_STR("unmatched `)`"), EL_STR("error"), line, col)); + depth_paren = 0; + } + i = (i + 1); + col = (col + 1); + } else { + if (str_eq(ch, EL_STR("["))) { + depth_brack = (depth_brack + 1); + i = (i + 1); + col = (col + 1); + } else { + if (str_eq(ch, EL_STR("]"))) { + depth_brack = (depth_brack - 1); + if (depth_brack < 0) { + diags = native_list_append(diags, diag_json(EL_STR("unmatched `]`"), EL_STR("error"), line, col)); + depth_brack = 0; + } + i = (i + 1); + col = (col + 1); + } else { + if (str_eq(ch, EL_STR("\n"))) { + line = (line + 1); + col = 1; + i = (i + 1); + } else { + i = (i + 1); + col = (col + 1); + } + } + } + } + } + } + } + } + } + } + } + } + if (in_string) { + diags = native_list_append(diags, diag_json(EL_STR("unterminated string literal"), EL_STR("error"), string_start_line, string_start_col)); + } + if (depth_brace > 0) { + diags = native_list_append(diags, diag_json(EL_STR("unclosed `{` (missing `}`)"), EL_STR("error"), 0, 0)); + } + if (depth_paren > 0) { + diags = native_list_append(diags, diag_json(EL_STR("unclosed `(` (missing `)`)"), EL_STR("error"), 0, 0)); + } + if (depth_brack > 0) { + diags = native_list_append(diags, diag_json(EL_STR("unclosed `[` (missing `]`)"), EL_STR("error"), 0, 0)); + } + return json_array_of(diags); + return 0; +} + +el_val_t outline_item_json(el_val_t kind, el_val_t name, el_val_t line) { + el_val_t parts = native_list_empty(); + parts = native_list_append(parts, json_kv_str(EL_STR("kind"), kind)); + parts = native_list_append(parts, json_kv_str(EL_STR("name"), name)); + parts = native_list_append(parts, json_kv_int(EL_STR("line"), line)); + return el_str_concat(el_str_concat(EL_STR("{"), list_join(parts, EL_STR(","))), EL_STR("}")); + return 0; +} + +el_val_t lsp_outline(el_val_t source) { + el_val_t lines = str_split(source, EL_STR("\n")); + el_val_t n = native_list_len(lines); + el_val_t items = native_list_empty(); + el_val_t i = 0; + while (i < n) { + el_val_t line = native_list_get(lines, i); + el_val_t trimmed = str_trim(line); + el_val_t lineno = (i + 1); + if (str_starts_with(trimmed, EL_STR("fn "))) { + el_val_t name = first_ident_in(str_slice(trimmed, 3, str_len(trimmed))); + if (!str_eq(name, EL_STR(""))) { + items = native_list_append(items, outline_item_json(EL_STR("fn"), name, lineno)); + } + } else { + if (str_starts_with(trimmed, EL_STR("type "))) { + el_val_t name = first_ident_in(str_slice(trimmed, 5, str_len(trimmed))); + if (!str_eq(name, EL_STR(""))) { + items = native_list_append(items, outline_item_json(EL_STR("type"), name, lineno)); + } + } else { + if (str_starts_with(trimmed, EL_STR("enum "))) { + el_val_t name = first_ident_in(str_slice(trimmed, 5, str_len(trimmed))); + if (!str_eq(name, EL_STR(""))) { + items = native_list_append(items, outline_item_json(EL_STR("enum"), name, lineno)); + } + } else { + if (str_starts_with(trimmed, EL_STR("protocol "))) { + el_val_t name = first_ident_in(str_slice(trimmed, 9, str_len(trimmed))); + if (!str_eq(name, EL_STR(""))) { + items = native_list_append(items, outline_item_json(EL_STR("protocol"), name, lineno)); + } + } else { + if (str_starts_with(trimmed, EL_STR("impl "))) { + el_val_t rest = str_trim(str_slice(trimmed, 5, str_len(trimmed))); + el_val_t brace = str_index_of(rest, EL_STR("{")); + el_val_t name = rest; + if (brace > 0) { + name = str_trim(str_slice(rest, 0, brace)); + } + if (!str_eq(name, EL_STR(""))) { + items = native_list_append(items, outline_item_json(EL_STR("impl"), name, lineno)); + } + } + } + } + } + } + i = (i + 1); + } + return json_array_of(items); + return 0; +} + +el_val_t format_strip_trailing(el_val_t line) { + el_val_t n = str_len(line); + if (n == 0) { + return line; + } + el_val_t chars = native_string_chars(line); + el_val_t i = (n - 1); + el_val_t trimming = 1; + while (trimming) { + if (i < 0) { + trimming = 0; + } else { + el_val_t ch = native_list_get(chars, i); + if (str_eq(ch, EL_STR(" "))) { + i = (i - 1); + } else { + if (str_eq(ch, EL_STR("\t"))) { + i = (i - 1); + } else { + trimming = 0; + } + } + } + } + return str_slice(line, 0, (i + 1)); + return 0; +} + +el_val_t lsp_format(el_val_t source) { + el_val_t lines = str_split(source, EL_STR("\n")); + el_val_t n = native_list_len(lines); + el_val_t cleaned = native_list_empty(); + el_val_t i = 0; + el_val_t blank_run = 0; + while (i < n) { + el_val_t line = native_list_get(lines, i); + el_val_t stripped = format_strip_trailing(line); + if (str_eq(stripped, EL_STR(""))) { + blank_run = (blank_run + 1); + if (blank_run <= 2) { + cleaned = native_list_append(cleaned, EL_STR("")); + } + } else { + blank_run = 0; + cleaned = native_list_append(cleaned, stripped); + } + i = (i + 1); + } + el_val_t joined = list_join(cleaned, EL_STR("\n")); + el_val_t final = joined; + if (!str_ends_with(final, EL_STR("\n"))) { + final = el_str_concat(final, EL_STR("\n")); + } + el_val_t changed = EL_STR("false"); + if (!str_eq(final, source)) { + changed = EL_STR("true"); + } + return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{"), json_kv_str(EL_STR("content"), final)), EL_STR(",")), json_kv_raw(EL_STR("changed"), changed)), EL_STR("}")); + return 0; +} + +el_val_t lsp_type_graph(el_val_t source) { + el_val_t nodes = native_list_empty(); + el_val_t edges = native_list_empty(); + el_val_t bts = builtin_type_names(); + el_val_t nb = native_list_len(bts); + el_val_t i = 0; + while (i < nb) { + el_val_t name = native_list_get(bts, i); + el_val_t parts = native_list_empty(); + parts = native_list_append(parts, json_kv_str(EL_STR("id"), name)); + parts = native_list_append(parts, json_kv_str(EL_STR("name"), name)); + parts = native_list_append(parts, json_kv_str(EL_STR("kind"), EL_STR("builtin"))); + parts = native_list_append(parts, json_kv_raw(EL_STR("fields"), EL_STR("[]"))); + nodes = native_list_append(nodes, el_str_concat(el_str_concat(EL_STR("{"), list_join(parts, EL_STR(","))), EL_STR("}"))); + i = (i + 1); + } + el_val_t decls = scan_decls(source); + el_val_t utypes = el_get_field(decls, EL_STR("types")); + el_val_t ukinds = el_get_field(decls, EL_STR("type_kind")); + el_val_t tlines = el_get_field(decls, EL_STR("type_lines")); + el_val_t nu = native_list_len(utypes); + i = 0; + el_val_t bts_dup = builtin_type_names(); + while (i < nu) { + el_val_t name = native_list_get(utypes, i); + el_val_t kind = native_list_get(ukinds, i); + if (!list_contains_str(bts_dup, name)) { + el_val_t fields = collect_struct_fields(source, name); + el_val_t field_jsons = native_list_empty(); + el_val_t fn2 = native_list_len(fields); + el_val_t j = 0; + while (j < fn2) { + field_jsons = native_list_append(field_jsons, json_str(native_list_get(fields, j))); + j = (j + 1); + } + el_val_t parts = native_list_empty(); + parts = native_list_append(parts, json_kv_str(EL_STR("id"), name)); + parts = native_list_append(parts, json_kv_str(EL_STR("name"), name)); + parts = native_list_append(parts, json_kv_str(EL_STR("kind"), kind)); + parts = native_list_append(parts, json_kv_raw(EL_STR("fields"), json_array_of(field_jsons))); + nodes = native_list_append(nodes, el_str_concat(el_str_concat(EL_STR("{"), list_join(parts, EL_STR(","))), EL_STR("}"))); + j = 0; + while (j < fn2) { + el_val_t field_str = native_list_get(fields, j); + el_val_t target = referenced_type(field_str, utypes); + if (!str_eq(EL_NULL, EL_STR(""))) { + el_val_t eparts = native_list_empty(); + eparts = native_list_append(eparts, json_kv_str(EL_STR("from"), name)); + eparts = native_list_append(eparts, json_kv_str(EL_STR("to"), EL_NULL)); + eparts = native_list_append(eparts, json_kv_str(EL_STR("label"), EL_STR("field"))); + edges = native_list_append(edges, el_str_concat(el_str_concat(EL_STR("{"), list_join(eparts, EL_STR(","))), EL_STR("}"))); + } + j = (j + 1); + } + } + i = (i + 1); + } + return el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{"), json_kv_raw(EL_STR("nodes"), json_array_of(nodes))), EL_STR(",")), json_kv_raw(EL_STR("edges"), json_array_of(edges))), EL_STR("}")); + return 0; +} + +el_val_t collect_struct_fields(el_val_t source, el_val_t type_name) { + el_val_t lines = str_split(source, EL_STR("\n")); + el_val_t n = native_list_len(lines); + el_val_t fields = native_list_empty(); + el_val_t inside = 0; + el_val_t i = 0; + el_val_t header_a = el_str_concat(EL_STR("type "), type_name); + el_val_t header_b = el_str_concat(EL_STR("enum "), type_name); + el_val_t header_c = el_str_concat(EL_STR("protocol "), type_name); + while (i < n) { + el_val_t line = native_list_get(lines, i); + el_val_t trimmed = str_trim(line); + if (!inside) { + if (str_starts_with(trimmed, header_a)) { + inside = 1; + } + if (str_starts_with(trimmed, header_b)) { + inside = 1; + } + if (str_starts_with(trimmed, header_c)) { + inside = 1; + } + } else { + if (str_starts_with(trimmed, EL_STR("}"))) { + return fields; + } + if (!str_eq(trimmed, EL_STR("{"))) { + if (!str_eq(trimmed, EL_STR(""))) { + if (!str_starts_with(trimmed, EL_STR("//"))) { + el_val_t entry = trimmed; + if (str_ends_with(entry, EL_STR(","))) { + entry = str_slice(entry, 0, (str_len(entry) - 1)); + } + fields = native_list_append(fields, str_trim(entry)); + } + } + } + } + i = (i + 1); + } + return fields; + return 0; +} + +el_val_t referenced_type(el_val_t field_str, el_val_t known_types) { + el_val_t colon = str_index_of(field_str, EL_STR(":")); + if (colon < 0) { + return EL_STR(""); + } + el_val_t after = str_trim(str_slice(field_str, (colon + 1), str_len(field_str))); + el_val_t trimmed_l = after; + if (str_starts_with(trimmed_l, EL_STR("["))) { + el_val_t end = str_index_of(trimmed_l, EL_STR("]")); + if (end > 1) { + trimmed_l = str_trim(str_slice(trimmed_l, 1, end)); + } + } + el_val_t ident = first_ident_in(trimmed_l); + if (str_eq(ident, EL_STR(""))) { + return EL_STR(""); + } + el_val_t bts = builtin_type_names(); + if (list_contains_str(bts, ident)) { + return ident; + } + if (list_contains_str(known_types, ident)) { + return ident; + } + return EL_STR(""); + return 0; +} + +el_val_t lsp_definition(el_val_t source, el_val_t pos) { + el_val_t word = extract_token(source, pos); + if (str_eq(word, EL_STR(""))) { + return EL_STR("null"); + } + el_val_t patterns = native_list_empty(); + patterns = native_list_append(patterns, el_str_concat(EL_STR("fn "), word)); + patterns = native_list_append(patterns, el_str_concat(EL_STR("type "), word)); + patterns = native_list_append(patterns, el_str_concat(EL_STR("enum "), word)); + patterns = native_list_append(patterns, el_str_concat(EL_STR("protocol "), word)); + el_val_t np = native_list_len(patterns); + el_val_t lines = str_split(source, EL_STR("\n")); + el_val_t nl = native_list_len(lines); + el_val_t i = 0; + while (i < nl) { + el_val_t line = native_list_get(lines, i); + el_val_t j = 0; + while (j < np) { + el_val_t pat = native_list_get(patterns, j); + el_val_t idx = str_index_of(line, pat); + if (idx >= 0) { + el_val_t parts = native_list_empty(); + parts = native_list_append(parts, json_kv_int(EL_STR("line"), (i + 1))); + parts = native_list_append(parts, json_kv_int(EL_STR("col"), (idx + 1))); + parts = native_list_append(parts, json_kv_str(EL_STR("snippet"), str_trim(line))); + return el_str_concat(el_str_concat(EL_STR("{"), list_join(parts, EL_STR(","))), EL_STR("}")); + } + j = (j + 1); + } + i = (i + 1); + } + return EL_STR("null"); + return 0; +} + +el_val_t lsp_references(el_val_t source, el_val_t pos) { + el_val_t word = extract_token(source, pos); + if (str_eq(word, EL_STR(""))) { + return EL_STR("[]"); + } + el_val_t lines = str_split(source, EL_STR("\n")); + el_val_t nl = native_list_len(lines); + el_val_t refs = native_list_empty(); + el_val_t i = 0; + while (i < nl) { + el_val_t line = native_list_get(lines, i); + el_val_t line_chars = native_string_chars(line); + el_val_t llen = native_list_len(line_chars); + el_val_t wlen = str_len(word); + el_val_t off = 0; + el_val_t scanning = 1; + while (scanning) { + el_val_t idx = str_index_of(str_slice(line, off, str_len(line)), word); + if (idx < 0) { + scanning = 0; + } else { + el_val_t abs = (off + idx); + el_val_t before_ok = 1; + if (abs > 0) { + el_val_t prev = native_list_get(line_chars, (abs - 1)); + if (is_ident_ch(prev)) { + before_ok = 0; + } + } + el_val_t after_ok = 1; + el_val_t after_pos = (abs + wlen); + if (after_pos < llen) { + el_val_t nxt = native_list_get(line_chars, after_pos); + if (is_ident_ch(nxt)) { + after_ok = 0; + } + } + if (before_ok) { + if (after_ok) { + el_val_t parts = native_list_empty(); + parts = native_list_append(parts, json_kv_int(EL_STR("line"), (i + 1))); + parts = native_list_append(parts, json_kv_int(EL_STR("col"), (abs + 1))); + parts = native_list_append(parts, json_kv_str(EL_STR("snippet"), str_trim(line))); + refs = native_list_append(refs, el_str_concat(el_str_concat(EL_STR("{"), list_join(parts, EL_STR(","))), EL_STR("}"))); + } + } + off = (abs + wlen); + if (off >= str_len(line)) { + scanning = 0; + } + } + } + i = (i + 1); + } + return json_array_of(refs); + return 0; +} + +el_val_t lsp_jsonrpc(el_val_t method, el_val_t params_json) { + el_val_t source = json_get_string(params_json, EL_STR("source")); + el_val_t pos = json_get_int(params_json, EL_STR("pos")); + if (str_eq(method, EL_STR("textDocument/completion"))) { + return lsp_complete(source, pos); + } + if (str_eq(method, EL_STR("textDocument/hover"))) { + return lsp_hover(source, pos); + } + if (str_eq(method, EL_STR("textDocument/diagnostic"))) { + return lsp_diagnostics(source); + } + if (str_eq(method, EL_STR("textDocument/formatting"))) { + return lsp_format(source); + } + if (str_eq(method, EL_STR("textDocument/documentSymbol"))) { + return lsp_outline(source); + } + if (str_eq(method, EL_STR("textDocument/definition"))) { + return lsp_definition(source, pos); + } + if (str_eq(method, EL_STR("textDocument/references"))) { + return lsp_references(source, pos); + } + if (str_eq(method, EL_STR("el/typeGraph"))) { + return lsp_type_graph(source); + } + return el_str_concat(el_str_concat(EL_STR("{\"error\":\"unknown method: "), json_escape(method)), EL_STR("\"}")); + return 0; +} + +el_val_t read_headers(void) { + el_val_t content_len = 0; + el_val_t scanning = 1; + while (scanning) { + el_val_t line = readline(); + if (str_eq(line, EL_STR(""))) { + scanning = 0; + } else { + el_val_t cl_marker = EL_STR("Content-Length:"); + if (str_starts_with(line, cl_marker)) { + el_val_t val = str_trim(str_slice(line, str_len(cl_marker), str_len(line))); + content_len = str_to_int(val); + } + } + } + return el_map_new(1, "content_length", content_len); + return 0; +} + +el_val_t lsp_stdio_loop(void) { + el_val_t running = 1; + while (running) { + el_val_t headers = read_headers(); + el_val_t body = readline(); + if (str_eq(body, EL_STR(""))) { + running = 0; + } else { + el_val_t method = json_get_string(body, EL_STR("method")); + el_val_t id_val = json_get_string(body, EL_STR("id")); + el_val_t params_raw = json_get_raw(body, EL_STR("params")); + el_val_t result = lsp_jsonrpc(method, params_raw); + el_val_t resp = el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("{\"jsonrpc\":\"2.0\",\"id\":"), id_val), EL_STR(",\"result\":")), result), EL_STR("}")); + el_val_t frame = el_str_concat(el_str_concat(el_str_concat(EL_STR("Content-Length: "), int_to_str(str_len(resp))), EL_STR("\r\n\r\n")), resp); + print(frame); + } + } + return 0; +} + +el_val_t lsp_main(void) { + el_val_t argv = args(); + el_val_t n = native_list_len(argv); + if (n > 0) { + el_val_t cmd = native_list_get(argv, 0); + if (str_eq(cmd, EL_STR("version"))) { + println(EL_STR("el-lsp 0.1.0")); + return 0; + } + if (str_eq(cmd, EL_STR("probe"))) { + el_val_t sample = EL_STR("fn main() -> Void { let x: Int = 42 }"); + println(lsp_diagnostics(sample)); + return 0; + } + } + lsp_stdio_loop(); + return 0; +} + +int main(int argc, char** argv) { + el_runtime_init_args(argc, argv); + lsp_main(); + return 0; +} + diff --git a/ide/vessels/el-lsp/src/main.el b/ide/vessels/el-lsp/src/main.el new file mode 100644 index 0000000..394bfe6 --- /dev/null +++ b/ide/vessels/el-lsp/src/main.el @@ -0,0 +1,1238 @@ +// main.el — el-lsp +// +// Language Server for El. Pure-El port of the el-lsp Rust crate. +// +// Entry surface (callable from any El program that imports this file): +// +// lsp_complete(source: String, pos: Int) -> String // JSON array +// lsp_hover(source: String, pos: Int) -> String // JSON object or "null" +// lsp_diagnostics(source: String) -> String // JSON array +// lsp_outline(source: String) -> String // JSON array +// lsp_format(source: String) -> String // JSON { content, changed } +// lsp_type_graph(source: String) -> String // JSON { nodes, edges } +// lsp_definition(source: String, pos: Int) -> String // JSON object or "null" +// lsp_references(source: String, pos: Int) -> String // JSON array +// lsp_jsonrpc(method: String, params_json: String) -> String +// lsp_stdio_loop() -> Void +// +// Tokenisation reuses the lexer.el idiom (chars list + index walk) for the +// pieces we need (identifier scan, string scan, line counting). The full +// type checker referenced by the Rust crate is not yet available in El, so +// hover/completion/diagnostics fall back to source-scan heuristics over the +// declared types/enums/functions in the file. The wire shape is preserved. + +// ── Char helpers (mirrors lexer.el) ────────────────────────────────────────── + +fn is_digit_ch(ch: String) -> Bool { + if ch == "0" { return true } if ch == "1" { return true } + if ch == "2" { return true } if ch == "3" { return true } + if ch == "4" { return true } if ch == "5" { return true } + if ch == "6" { return true } if ch == "7" { return true } + if ch == "8" { return true } if ch == "9" { return true } + false +} + +fn is_alpha_ch(ch: String) -> Bool { + let lower: String = str_to_lower(ch) + if str_eq(ch, "") { return false } + if !str_eq(lower, str_to_upper(lower)) { return true } // letters differ in case + // covers a-z (lower-only) — uppercase already handled by inverse case test above + if str_contains("abcdefghijklmnopqrstuvwxyz", ch) { return true } + if str_contains("ABCDEFGHIJKLMNOPQRSTUVWXYZ", ch) { return true } + false +} + +fn is_ident_ch(ch: String) -> Bool { + if is_digit_ch(ch) { return true } + if is_alpha_ch(ch) { return true } + if ch == "_" { return true } + false +} + +// ── Source navigation ──────────────────────────────────────────────────────── + +// Extract the identifier fragment immediately before `pos` (cursor). +fn extract_prefix(source: String, pos: Int) -> String { + let n: Int = str_len(source) + let end: Int = pos + if end > n { let end = n } + let start: Int = end + let chars: [String] = native_string_chars(source) + let total: Int = native_list_len(chars) + let scanning: Bool = true + while scanning { + if start <= 0 { + let scanning = false + } else { + let prev: String = native_list_get(chars, start - 1) + if is_ident_ch(prev) { + let start = start - 1 + } else { + let scanning = false + } + } + } + str_slice(source, start, end) +} + +// Extract the full token (alphanumerics + underscore) surrounding `pos`. +fn extract_token(source: String, pos: Int) -> String { + let n: Int = str_len(source) + if pos > n { return "" } + let chars: [String] = native_string_chars(source) + let total: Int = native_list_len(chars) + let start: Int = pos + let go_left: Bool = true + while go_left { + if start <= 0 { + let go_left = false + } else { + let prev: String = native_list_get(chars, start - 1) + if is_ident_ch(prev) { + let start = start - 1 + } else { + let go_left = false + } + } + } + let end: Int = pos + let go_right: Bool = true + while go_right { + if end >= total { + let go_right = false + } else { + let cur: String = native_list_get(chars, end) + if is_ident_ch(cur) { + let end = end + 1 + } else { + let go_right = false + } + } + } + str_slice(source, start, end) +} + +// Translate a byte offset into 1-based (line, col). +fn pos_to_line_col(source: String, pos: Int) -> Map { + let n: Int = str_len(source) + let cap: Int = pos + if cap > n { let cap = n } + let chars: [String] = native_string_chars(source) + let i: Int = 0 + let line: Int = 1 + let col: Int = 1 + while i < cap { + let ch: String = native_list_get(chars, i) + if ch == "\n" { + let line = line + 1 + let col = 1 + } else { + let col = col + 1 + } + let i = i + 1 + } + { "line": line, "col": col } +} + +// ── JSON encoding helpers ──────────────────────────────────────────────────── + +// Escape a string for JSON. Handles ", \, newline, tab. +fn json_escape(s: String) -> String { + let chars: [String] = native_string_chars(s) + let n: Int = native_list_len(chars) + let out: String = "" + let i: Int = 0 + while i < n { + let ch: String = native_list_get(chars, i) + if ch == "\"" { let out = out + "\\\"" } + else { if ch == "\\" { let out = out + "\\\\" } + else { if ch == "\n" { let out = out + "\\n" } + else { if ch == "\r" { let out = out + "\\r" } + else { if ch == "\t" { let out = out + "\\t" } + else { let out = out + ch } } } } } + let i = i + 1 + } + out +} + +fn json_str(s: String) -> String { + "\"" + json_escape(s) + "\"" +} + +fn json_kv_str(k: String, v: String) -> String { + json_str(k) + ":" + json_str(v) +} + +fn json_kv_int(k: String, v: Int) -> String { + json_str(k) + ":" + int_to_str(v) +} + +fn json_kv_float(k: String, v: Float) -> String { + json_str(k) + ":" + float_to_str(v) +} + +fn json_kv_raw(k: String, raw_v: String) -> String { + json_str(k) + ":" + raw_v +} + +// Join a list of pre-encoded JSON strings into a JSON array. +fn json_array_of(items: [String]) -> String { + let n: Int = native_list_len(items) + let out: String = "[" + let i: Int = 0 + while i < n { + if i > 0 { let out = out + "," } + let out = out + native_list_get(items, i) + let i = i + 1 + } + out + "]" +} + +// ── Keyword/builtin tables ─────────────────────────────────────────────────── + +fn keywords_list() -> [String] { + let ks: [String] = native_list_empty() + let ks = native_list_append(ks, "let") + let ks = native_list_append(ks, "fn") + let ks = native_list_append(ks, "type") + let ks = native_list_append(ks, "enum") + let ks = native_list_append(ks, "match") + let ks = native_list_append(ks, "return") + let ks = native_list_append(ks, "activate") + let ks = native_list_append(ks, "where") + let ks = native_list_append(ks, "sealed") + let ks = native_list_append(ks, "if") + let ks = native_list_append(ks, "else") + let ks = native_list_append(ks, "for") + let ks = native_list_append(ks, "in") + let ks = native_list_append(ks, "while") + let ks = native_list_append(ks, "true") + let ks = native_list_append(ks, "false") + let ks = native_list_append(ks, "test") + let ks = native_list_append(ks, "seed") + let ks = native_list_append(ks, "assert") + let ks = native_list_append(ks, "target") + let ks = native_list_append(ks, "protocol") + let ks = native_list_append(ks, "impl") + let ks = native_list_append(ks, "import") + let ks = native_list_append(ks, "from") + let ks = native_list_append(ks, "as") + let ks = native_list_append(ks, "with") + let ks = native_list_append(ks, "retry") + let ks = native_list_append(ks, "times") + let ks = native_list_append(ks, "fallback") + let ks = native_list_append(ks, "reason") + let ks = native_list_append(ks, "parallel") + let ks = native_list_append(ks, "trace") + let ks = native_list_append(ks, "requires") + let ks = native_list_append(ks, "deploy") + let ks = native_list_append(ks, "to") + let ks = native_list_append(ks, "via") + let ks = native_list_append(ks, "vessel") + let ks = native_list_append(ks, "cgi") + ks +} + +// Built-in primitive type names. +fn builtin_type_names() -> [String] { + let ts: [String] = native_list_empty() + let ts = native_list_append(ts, "Int") + let ts = native_list_append(ts, "Float") + let ts = native_list_append(ts, "String") + let ts = native_list_append(ts, "Bool") + let ts = native_list_append(ts, "Uuid") + let ts = native_list_append(ts, "Void") + let ts = native_list_append(ts, "Any") + ts +} + +fn builtin_type_doc(name: String) -> String { + if str_eq(name, "Int") { return "64-bit signed integer" } + if str_eq(name, "Float") { return "64-bit IEEE 754 double" } + if str_eq(name, "String") { return "UTF-8 string" } + if str_eq(name, "Bool") { return "Boolean value" } + if str_eq(name, "Uuid") { return "RFC 4122 UUID" } + if str_eq(name, "Void") { return "Unit type — no value" } + if str_eq(name, "Any") { return "Dynamically-typed value" } + "" +} + +// Built-in function names → signatures. Encoded as flat [name, sig, name, sig, ...] +// to keep type maps simple. +fn builtin_fns() -> [String] { + let xs: [String] = native_list_empty() + let xs = native_list_append(xs, "println") let xs = native_list_append(xs, "fn(value: String) -> Void") + let xs = native_list_append(xs, "print") let xs = native_list_append(xs, "fn(value: String) -> Void") + let xs = native_list_append(xs, "readline") let xs = native_list_append(xs, "fn() -> String") + let xs = native_list_append(xs, "args") let xs = native_list_append(xs, "fn() -> [String]") + let xs = native_list_append(xs, "int_to_str") let xs = native_list_append(xs, "fn(n: Int) -> String") + let xs = native_list_append(xs, "str_to_int") let xs = native_list_append(xs, "fn(s: String) -> Int") + let xs = native_list_append(xs, "str_len") let xs = native_list_append(xs, "fn(s: String) -> Int") + let xs = native_list_append(xs, "str_slice") let xs = native_list_append(xs, "fn(s: String, start: Int, end: Int) -> String") + let xs = native_list_append(xs, "str_concat") let xs = native_list_append(xs, "fn(a: String, b: String) -> String") + let xs = native_list_append(xs, "str_contains") let xs = native_list_append(xs, "fn(s: String, sub: String) -> Bool") + let xs = native_list_append(xs, "str_starts_with") let xs = native_list_append(xs, "fn(s: String, p: String) -> Bool") + let xs = native_list_append(xs, "str_ends_with") let xs = native_list_append(xs, "fn(s: String, suf: String) -> Bool") + let xs = native_list_append(xs, "str_to_upper") let xs = native_list_append(xs, "fn(s: String) -> String") + let xs = native_list_append(xs, "str_to_lower") let xs = native_list_append(xs, "fn(s: String) -> String") + let xs = native_list_append(xs, "str_split") let xs = native_list_append(xs, "fn(s: String, sep: String) -> [String]") + let xs = native_list_append(xs, "str_trim") let xs = native_list_append(xs, "fn(s: String) -> String") + let xs = native_list_append(xs, "str_replace") let xs = native_list_append(xs, "fn(s: String, from: String, to: String) -> String") + let xs = native_list_append(xs, "str_index_of") let xs = native_list_append(xs, "fn(s: String, sub: String) -> Int") + let xs = native_list_append(xs, "float_to_str") let xs = native_list_append(xs, "fn(f: Float) -> String") + let xs = native_list_append(xs, "str_to_float") let xs = native_list_append(xs, "fn(s: String) -> Float") + let xs = native_list_append(xs, "math_sqrt") let xs = native_list_append(xs, "fn(n: Float) -> Float") + let xs = native_list_append(xs, "math_log") let xs = native_list_append(xs, "fn(n: Float) -> Float") + let xs = native_list_append(xs, "math_sin") let xs = native_list_append(xs, "fn(n: Float) -> Float") + let xs = native_list_append(xs, "math_cos") let xs = native_list_append(xs, "fn(n: Float) -> Float") + let xs = native_list_append(xs, "math_pi") let xs = native_list_append(xs, "fn() -> Float") + let xs = native_list_append(xs, "el_abs") let xs = native_list_append(xs, "fn(n: Int) -> Int") + let xs = native_list_append(xs, "el_min") let xs = native_list_append(xs, "fn(a: Int, b: Int) -> Int") + let xs = native_list_append(xs, "el_max") let xs = native_list_append(xs, "fn(a: Int, b: Int) -> Int") + let xs = native_list_append(xs, "el_list_empty") let xs = native_list_append(xs, "fn() -> [Any]") + let xs = native_list_append(xs, "el_list_len") let xs = native_list_append(xs, "fn(l: [Any]) -> Int") + let xs = native_list_append(xs, "el_list_get") let xs = native_list_append(xs, "fn(l: [Any], i: Int) -> Any") + let xs = native_list_append(xs, "el_list_append") let xs = native_list_append(xs, "fn(l: [Any], v: Any) -> [Any]") + let xs = native_list_append(xs, "list_join") let xs = native_list_append(xs, "fn(l: [String], sep: String) -> String") + let xs = native_list_append(xs, "list_range") let xs = native_list_append(xs, "fn(start: Int, end: Int) -> [Int]") + let xs = native_list_append(xs, "el_map_get") let xs = native_list_append(xs, "fn(m: Map, k: String) -> Any") + let xs = native_list_append(xs, "el_map_set") let xs = native_list_append(xs, "fn(m: Map, k: String, v: Any) -> Map") + let xs = native_list_append(xs, "json_parse") let xs = native_list_append(xs, "fn(s: String) -> Any") + let xs = native_list_append(xs, "json_stringify") let xs = native_list_append(xs, "fn(v: Any) -> String") + let xs = native_list_append(xs, "json_get_string") let xs = native_list_append(xs, "fn(j: String, k: String) -> String") + let xs = native_list_append(xs, "json_get_int") let xs = native_list_append(xs, "fn(j: String, k: String) -> Int") + let xs = native_list_append(xs, "json_get_bool") let xs = native_list_append(xs, "fn(j: String, k: String) -> Bool") + let xs = native_list_append(xs, "http_get") let xs = native_list_append(xs, "fn(url: String) -> String") + let xs = native_list_append(xs, "http_post") let xs = native_list_append(xs, "fn(url: String, body: String) -> String") + let xs = native_list_append(xs, "fs_read") let xs = native_list_append(xs, "fn(path: String) -> String") + let xs = native_list_append(xs, "fs_write") let xs = native_list_append(xs, "fn(path: String, content: String) -> Bool") + let xs = native_list_append(xs, "fs_list") let xs = native_list_append(xs, "fn(path: String) -> [String]") + let xs = native_list_append(xs, "env") let xs = native_list_append(xs, "fn(key: String) -> String") + let xs = native_list_append(xs, "uuid_new") let xs = native_list_append(xs, "fn() -> String") + let xs = native_list_append(xs, "time_now") let xs = native_list_append(xs, "fn() -> Int") + let xs = native_list_append(xs, "time_now_utc") let xs = native_list_append(xs, "fn() -> Int") + let xs = native_list_append(xs, "sleep_ms") let xs = native_list_append(xs, "fn(ms: Int) -> Void") + let xs = native_list_append(xs, "engram_node") let xs = native_list_append(xs, "fn(content: String, kind: String, salience: Float) -> String") + let xs = native_list_append(xs, "engram_search") let xs = native_list_append(xs, "fn(q: String, limit: Int) -> [Map]") + let xs = native_list_append(xs, "engram_activate") let xs = native_list_append(xs, "fn(q: String, depth: Int) -> [Map]") + let xs = native_list_append(xs, "engram_neighbors") let xs = native_list_append(xs, "fn(id: String) -> [Map]") + let xs = native_list_append(xs, "engram_connect") let xs = native_list_append(xs, "fn(from: String, to: String, w: Float, rel: String) -> Void") + let xs = native_list_append(xs, "dharma_connect") let xs = native_list_append(xs, "fn(cgi: String) -> String") + let xs = native_list_append(xs, "dharma_send") let xs = native_list_append(xs, "fn(channel: String, content: String) -> String") + let xs = native_list_append(xs, "dharma_emit") let xs = native_list_append(xs, "fn(event: String, payload: String) -> Void") + let xs = native_list_append(xs, "dharma_field") let xs = native_list_append(xs, "fn(event: String) -> Map") + let xs = native_list_append(xs, "llm_call") let xs = native_list_append(xs, "fn(model: String, prompt: String) -> String") + xs +} + +fn keyword_doc(kw: String) -> String { + if str_eq(kw, "let") { return "let name: Type = expr — declare an immutable binding." } + if str_eq(kw, "fn") { return "fn name(params) -> Ret { body } — define a function." } + if str_eq(kw, "type") { return "type Name { field: Type } — struct definition." } + if str_eq(kw, "enum") { return "enum Name { Variant1, Variant2(Type) } — enum definition." } + if str_eq(kw, "match") { return "match expr { Pattern => body } — pattern match." } + if str_eq(kw, "return") { return "return value — exit the enclosing function." } + if str_eq(kw, "if") { return "if cond { ... } else { ... } — conditional." } + if str_eq(kw, "for") { return "for item in collection { ... } — iterate." } + if str_eq(kw, "while") { return "while cond { ... } — loop while cond is truthy." } + if str_eq(kw, "import") { return "import \"path.el\" — pull in another module." } + if str_eq(kw, "from") { return "from module import { Name } — selective import." } + if str_eq(kw, "vessel") { return "vessel \"name\" { ... } — manifest declaration." } + if str_eq(kw, "cgi") { return "cgi \"name\" { dharma_id: ... } — CGI identity." } + if str_eq(kw, "activate") { return "activate Type where \"query\" — spreading-activation retrieval." } + if str_eq(kw, "sealed") { return "sealed { ... } — capability-restricted block." } + if str_eq(kw, "protocol") { return "protocol Name { fn method(self) -> R } — trait-like." } + if str_eq(kw, "impl") { return "impl Protocol for Type { ... } — protocol implementation." } + if str_eq(kw, "with") { return "with retry/fallback clause." } + if str_eq(kw, "retry") { return "retry times N — retry policy." } + if str_eq(kw, "fallback") { return "fallback { default } — fallback on failure." } + if str_eq(kw, "true") { return "Boolean literal." } + if str_eq(kw, "false") { return "Boolean literal." } + "" +} + +// ── Source-driven type/fn discovery (no full parser) ───────────────────────── +// +// The Rust crate calls into el-types::TypeChecker for a real env. That +// module isn't available in El yet, so we approximate by line-scan: find +// every `type X {`, `enum X {`, `protocol X {`, and `fn X(` declaration. +// Returns four parallel lists merged into one map for easy access. + +fn first_ident_in(rest: String) -> String { + let trimmed: String = str_trim(rest) + let n: Int = str_len(trimmed) + if n == 0 { return "" } + let chars: [String] = native_string_chars(trimmed) + let i: Int = 0 + let total: Int = native_list_len(chars) + while i < total { + let ch: String = native_list_get(chars, i) + if !is_ident_ch(ch) { + return str_slice(trimmed, 0, i) + } + let i = i + 1 + } + trimmed +} + +// scan_decls — produce a Map with parallel lists: +// "types" : [String] user-defined struct/enum/protocol names +// "type_kind" : [String] "type" | "enum" | "protocol" matching above +// "fns" : [String] user-defined function names +// "type_lines" : [Int] 1-based line numbers +// "fn_lines" : [Int] +fn scan_decls(source: String) -> Map { + let lines: [String] = str_split(source, "\n") + let n: Int = native_list_len(lines) + let types: [String] = native_list_empty() + let kinds: [String] = native_list_empty() + let fns: [String] = native_list_empty() + let tlines: [Int] = native_list_empty() + let flines: [Int] = native_list_empty() + let i: Int = 0 + while i < n { + let line: String = native_list_get(lines, i) + let trimmed: String = str_trim(line) + let lineno: Int = i + 1 + if str_starts_with(trimmed, "fn ") { + let name: String = first_ident_in(str_slice(trimmed, 3, str_len(trimmed))) + if !str_eq(name, "") { + let fns = native_list_append(fns, name) + let flines = native_list_append(flines, lineno) + } + } else { if str_starts_with(trimmed, "type ") { + let name: String = first_ident_in(str_slice(trimmed, 5, str_len(trimmed))) + if !str_eq(name, "") { + let types = native_list_append(types, name) + let kinds = native_list_append(kinds, "type") + let tlines = native_list_append(tlines, lineno) + } + } else { if str_starts_with(trimmed, "enum ") { + let name: String = first_ident_in(str_slice(trimmed, 5, str_len(trimmed))) + if !str_eq(name, "") { + let types = native_list_append(types, name) + let kinds = native_list_append(kinds, "enum") + let tlines = native_list_append(tlines, lineno) + } + } else { if str_starts_with(trimmed, "protocol ") { + let name: String = first_ident_in(str_slice(trimmed, 9, str_len(trimmed))) + if !str_eq(name, "") { + let types = native_list_append(types, name) + let kinds = native_list_append(kinds, "protocol") + let tlines = native_list_append(tlines, lineno) + } + } } } } + let i = i + 1 + } + { + "types": types, + "type_kind": kinds, + "fns": fns, + "type_lines": tlines, + "fn_lines": flines + } +} + +// list_contains — case-sensitive membership test on [String]. +fn list_contains_str(xs: [String], needle: String) -> Bool { + let n: Int = native_list_len(xs) + let i: Int = 0 + while i < n { + if str_eq(native_list_get(xs, i), needle) { return true } + let i = i + 1 + } + false +} + +// Score a label against a prefix: 0 if no prefix match, else (prefix_len/label_len). +fn prefix_score(label: String, prefix: String) -> Float { + if str_eq(prefix, "") { return 0.5 } + let lower_label: String = str_to_lower(label) + let lower_prefix: String = str_to_lower(prefix) + if str_starts_with(lower_label, lower_prefix) { + let lp: Int = str_len(lower_prefix) + let ll: Int = str_len(lower_label) + if ll == 0 { return 0.0 } + return int_to_float(lp) / int_to_float(ll) + } + 0.0 +} + +// Render a single completion item to JSON. +fn completion_json(label: String, kind: String, detail: String, doc: String, score: Float) -> String { + let parts: [String] = native_list_empty() + let parts = native_list_append(parts, json_kv_str("label", label)) + let parts = native_list_append(parts, json_kv_str("kind", kind)) + let parts = native_list_append(parts, json_kv_str("detail", detail)) + if str_eq(doc, "") { + let parts = native_list_append(parts, json_kv_raw("documentation", "null")) + } else { + let parts = native_list_append(parts, json_kv_str("documentation", doc)) + } + let parts = native_list_append(parts, json_kv_float("score", score)) + "{" + list_join(parts, ",") + "}" +} + +// ── Public: completion ─────────────────────────────────────────────────────── + +fn lsp_complete(source: String, pos: Int) -> String { + let prefix: String = extract_prefix(source, pos) + let lower_prefix: String = str_to_lower(prefix) + let prefix_empty: Bool = str_eq(prefix, "") + let items: [String] = native_list_empty() + + // Keywords + let kws: [String] = keywords_list() + let nk: Int = native_list_len(kws) + let i: Int = 0 + while i < nk { + let kw: String = native_list_get(kws, i) + if prefix_empty { + let s: Float = prefix_score(kw, prefix) + let items = native_list_append(items, completion_json(kw, "keyword", "keyword", keyword_doc(kw), s)) + } else { if str_starts_with(kw, prefix) { + let s: Float = prefix_score(kw, prefix) + let items = native_list_append(items, completion_json(kw, "keyword", "keyword", keyword_doc(kw), s)) + } } + let i = i + 1 + } + + // Built-in types + let bts: [String] = builtin_type_names() + let nb: Int = native_list_len(bts) + let i: Int = 0 + while i < nb { + let name: String = native_list_get(bts, i) + let lname: String = str_to_lower(name) + if prefix_empty { + let s: Float = 0.5 + 0.1 + let items = native_list_append(items, completion_json(name, "type", builtin_type_doc(name), "Built-in type: " + builtin_type_doc(name), s)) + } else { if str_starts_with(lname, lower_prefix) { + let s: Float = prefix_score(name, prefix) + 0.1 + let items = native_list_append(items, completion_json(name, "type", builtin_type_doc(name), "Built-in type: " + builtin_type_doc(name), s)) + } } + let i = i + 1 + } + + // User-defined types + let decls: Map = scan_decls(source) + let utypes: [String] = decls["types"] + let ukinds: [String] = decls["type_kind"] + let nu: Int = native_list_len(utypes) + let i: Int = 0 + while i < nu { + let name: String = native_list_get(utypes, i) + let kind: String = native_list_get(ukinds, i) + let lname: String = str_to_lower(name) + let include: Bool = false + if prefix_empty { let include = true } + if str_starts_with(lname, lower_prefix) { let include = true } + if include { + let s: Float = prefix_score(name, prefix) + 0.15 + let items = native_list_append(items, completion_json(name, "type", kind + " " + name, "User-defined " + kind + " " + name, s)) + } + let i = i + 1 + } + + // Built-in functions + let bfns: [String] = builtin_fns() + let nf: Int = native_list_len(bfns) + let i: Int = 0 + while i < nf { + let name: String = native_list_get(bfns, i) + let sig: String = native_list_get(bfns, i + 1) + let lname: String = str_to_lower(name) + let include: Bool = false + if prefix_empty { let include = true } + if str_starts_with(lname, lower_prefix) { let include = true } + if include { + let s: Float = prefix_score(name, prefix) + 0.11 + let items = native_list_append(items, completion_json(name, "function", sig, "Built-in: " + name + " :: " + sig, s)) + } + let i = i + 2 + } + + // User-defined functions + let ufns: [String] = decls["fns"] + let nuf: Int = native_list_len(ufns) + let i: Int = 0 + while i < nuf { + let name: String = native_list_get(ufns, i) + let lname: String = str_to_lower(name) + let include: Bool = false + if prefix_empty { let include = true } + if str_starts_with(lname, lower_prefix) { let include = true } + if include { + let s: Float = prefix_score(name, prefix) + 0.12 + let items = native_list_append(items, completion_json(name, "function", "fn " + name, "User function: " + name, s)) + } + let i = i + 1 + } + + // Output is a list of pre-encoded JSON objects. Sorting by score is a + // stretch goal — el's runtime has no sort-by-key primitive. Items are + // already ordered by category (keywords first), which matches the most + // common editor expectation. + json_array_of(items) +} + +// ── Public: hover ──────────────────────────────────────────────────────────── + +fn lsp_hover(source: String, pos: Int) -> String { + let token: String = extract_token(source, pos) + if str_eq(token, "") { return "null" } + + // Built-in primitives + let doc: String = builtin_type_doc(token) + if !str_eq(doc, "") { + let parts: [String] = native_list_empty() + let parts = native_list_append(parts, json_kv_str("type_name", token)) + let parts = native_list_append(parts, json_kv_str("documentation", doc)) + let parts = native_list_append(parts, json_kv_raw("engram_node_type", "null")) + return "{" + list_join(parts, ",") + "}" + } + + // User-declared types + let decls: Map = scan_decls(source) + let utypes: [String] = decls["types"] + let ukinds: [String] = decls["type_kind"] + let nu: Int = native_list_len(utypes) + let i: Int = 0 + while i < nu { + let name: String = native_list_get(utypes, i) + if str_eq(name, token) { + let kind: String = native_list_get(ukinds, i) + let parts: [String] = native_list_empty() + let parts = native_list_append(parts, json_kv_str("type_name", token)) + let parts = native_list_append(parts, json_kv_str("documentation", kind + " " + token)) + let parts = native_list_append(parts, json_kv_raw("engram_node_type", "null")) + return "{" + list_join(parts, ",") + "}" + } + let i = i + 1 + } + + // User-declared functions + let ufns: [String] = decls["fns"] + let nuf: Int = native_list_len(ufns) + let i: Int = 0 + while i < nuf { + let name: String = native_list_get(ufns, i) + if str_eq(name, token) { + let parts: [String] = native_list_empty() + let parts = native_list_append(parts, json_kv_str("type_name", token)) + let parts = native_list_append(parts, json_kv_str("documentation", "fn " + token)) + let parts = native_list_append(parts, json_kv_raw("engram_node_type", "null")) + return "{" + list_join(parts, ",") + "}" + } + let i = i + 1 + } + + // Built-in functions + let bfns: [String] = builtin_fns() + let nf: Int = native_list_len(bfns) + let i: Int = 0 + while i < nf { + let name: String = native_list_get(bfns, i) + if str_eq(name, token) { + let sig: String = native_list_get(bfns, i + 1) + let parts: [String] = native_list_empty() + let parts = native_list_append(parts, json_kv_str("type_name", token)) + let parts = native_list_append(parts, json_kv_str("documentation", "fn " + token + " :: " + sig)) + let parts = native_list_append(parts, json_kv_raw("engram_node_type", "null")) + return "{" + list_join(parts, ",") + "}" + } + let i = i + 2 + } + + // Keyword + let kdoc: String = keyword_doc(token) + if !str_eq(kdoc, "") { + let parts: [String] = native_list_empty() + let parts = native_list_append(parts, json_kv_str("type_name", token)) + let parts = native_list_append(parts, json_kv_str("documentation", kdoc)) + let parts = native_list_append(parts, json_kv_raw("engram_node_type", "null")) + return "{" + list_join(parts, ",") + "}" + } + + "null" +} + +// ── Public: diagnostics ────────────────────────────────────────────────────── +// +// Without the type checker port we surface only structural diagnostics: +// * unterminated string literal +// * unbalanced braces / parens / brackets +// * unknown type referenced after `:` in a let binding (unknown to source + +// builtins) — best-effort, conservative. + +fn diag_json(message: String, severity: String, line: Int, col: Int) -> String { + let parts: [String] = native_list_empty() + let parts = native_list_append(parts, json_kv_str("message", message)) + let parts = native_list_append(parts, json_kv_str("severity", severity)) + if line > 0 { + let parts = native_list_append(parts, json_kv_int("line", line)) + let parts = native_list_append(parts, json_kv_int("col", col)) + } else { + let parts = native_list_append(parts, json_kv_raw("line", "null")) + let parts = native_list_append(parts, json_kv_raw("col", "null")) + } + "{" + list_join(parts, ",") + "}" +} + +fn lsp_diagnostics(source: String) -> String { + let chars: [String] = native_string_chars(source) + let n: Int = native_list_len(chars) + let diags: [String] = native_list_empty() + + // Bracket balance + unterminated string scan + let depth_brace: Int = 0 + let depth_paren: Int = 0 + let depth_brack: Int = 0 + let i: Int = 0 + let line: Int = 1 + let col: Int = 1 + let in_string: Bool = false + let string_start_line: Int = 0 + let string_start_col: Int = 0 + let in_comment: Bool = false + while i < n { + let ch: String = native_list_get(chars, i) + if in_comment { + if ch == "\n" { + let in_comment = false + let line = line + 1 + let col = 1 + } else { + let col = col + 1 + } + let i = i + 1 + } else { + if in_string { + if ch == "\\" { + let i = i + 1 + let col = col + 1 + if i < n { + let esc: String = native_list_get(chars, i) + if esc == "\n" { let line = line + 1 let col = 1 } else { let col = col + 1 } + let i = i + 1 + } + } else { if ch == "\"" { + let in_string = false + let i = i + 1 + let col = col + 1 + } else { if ch == "\n" { + let line = line + 1 + let col = 1 + let i = i + 1 + } else { + let col = col + 1 + let i = i + 1 + } } } + } else { + if ch == "\"" { + let in_string = true + let string_start_line = line + let string_start_col = col + let i = i + 1 + let col = col + 1 + } else { if ch == "/" { + let next_i: Int = i + 1 + let is_line_comment: Bool = false + if next_i < n { + let next_ch: String = native_list_get(chars, next_i) + if next_ch == "/" { let is_line_comment = true } + } + if is_line_comment { + let in_comment = true + let i = i + 2 + let col = col + 2 + } else { + let i = i + 1 + let col = col + 1 + } + } else { if ch == "{" { + let depth_brace = depth_brace + 1 + let i = i + 1 let col = col + 1 + } else { if ch == "}" { + let depth_brace = depth_brace - 1 + if depth_brace < 0 { + let diags = native_list_append(diags, diag_json("unmatched `}`", "error", line, col)) + let depth_brace = 0 + } + let i = i + 1 let col = col + 1 + } else { if ch == "(" { + let depth_paren = depth_paren + 1 + let i = i + 1 let col = col + 1 + } else { if ch == ")" { + let depth_paren = depth_paren - 1 + if depth_paren < 0 { + let diags = native_list_append(diags, diag_json("unmatched `)`", "error", line, col)) + let depth_paren = 0 + } + let i = i + 1 let col = col + 1 + } else { if ch == "[" { + let depth_brack = depth_brack + 1 + let i = i + 1 let col = col + 1 + } else { if ch == "]" { + let depth_brack = depth_brack - 1 + if depth_brack < 0 { + let diags = native_list_append(diags, diag_json("unmatched `]`", "error", line, col)) + let depth_brack = 0 + } + let i = i + 1 let col = col + 1 + } else { if ch == "\n" { + let line = line + 1 + let col = 1 + let i = i + 1 + } else { + let i = i + 1 + let col = col + 1 + } } } } } } } } } + } + } + } + + if in_string { + let diags = native_list_append(diags, diag_json("unterminated string literal", "error", string_start_line, string_start_col)) + } + if depth_brace > 0 { let diags = native_list_append(diags, diag_json("unclosed `{` (missing `}`)", "error", 0, 0)) } + if depth_paren > 0 { let diags = native_list_append(diags, diag_json("unclosed `(` (missing `)`)", "error", 0, 0)) } + if depth_brack > 0 { let diags = native_list_append(diags, diag_json("unclosed `[` (missing `]`)", "error", 0, 0)) } + + json_array_of(diags) +} + +// ── Public: outline ────────────────────────────────────────────────────────── + +fn outline_item_json(kind: String, name: String, line: Int) -> String { + let parts: [String] = native_list_empty() + let parts = native_list_append(parts, json_kv_str("kind", kind)) + let parts = native_list_append(parts, json_kv_str("name", name)) + let parts = native_list_append(parts, json_kv_int("line", line)) + "{" + list_join(parts, ",") + "}" +} + +fn lsp_outline(source: String) -> String { + let lines: [String] = str_split(source, "\n") + let n: Int = native_list_len(lines) + let items: [String] = native_list_empty() + let i: Int = 0 + while i < n { + let line: String = native_list_get(lines, i) + let trimmed: String = str_trim(line) + let lineno: Int = i + 1 + if str_starts_with(trimmed, "fn ") { + let name: String = first_ident_in(str_slice(trimmed, 3, str_len(trimmed))) + if !str_eq(name, "") { + let items = native_list_append(items, outline_item_json("fn", name, lineno)) + } + } else { if str_starts_with(trimmed, "type ") { + let name: String = first_ident_in(str_slice(trimmed, 5, str_len(trimmed))) + if !str_eq(name, "") { + let items = native_list_append(items, outline_item_json("type", name, lineno)) + } + } else { if str_starts_with(trimmed, "enum ") { + let name: String = first_ident_in(str_slice(trimmed, 5, str_len(trimmed))) + if !str_eq(name, "") { + let items = native_list_append(items, outline_item_json("enum", name, lineno)) + } + } else { if str_starts_with(trimmed, "protocol ") { + let name: String = first_ident_in(str_slice(trimmed, 9, str_len(trimmed))) + if !str_eq(name, "") { + let items = native_list_append(items, outline_item_json("protocol", name, lineno)) + } + } else { if str_starts_with(trimmed, "impl ") { + let rest: String = str_trim(str_slice(trimmed, 5, str_len(trimmed))) + let brace: Int = str_index_of(rest, "{") + let name: String = rest + if brace > 0 { let name = str_trim(str_slice(rest, 0, brace)) } + if !str_eq(name, "") { + let items = native_list_append(items, outline_item_json("impl", name, lineno)) + } + } } } } } + let i = i + 1 + } + json_array_of(items) +} + +// ── Public: format ─────────────────────────────────────────────────────────── +// +// Idiomatic-El formatter. Until `el fmt` is a real thing, we apply a minimal +// canonicalisation pass: +// * trim trailing whitespace on every line +// * collapse 3+ blank lines to 2 +// * ensure file ends with exactly one newline +// This is safe for round-tripping and a noticeable quality-of-life win in +// the editor. + +fn format_strip_trailing(line: String) -> String { + // str_trim trims both ends; we want only trailing whitespace stripped. + let n: Int = str_len(line) + if n == 0 { return line } + let chars: [String] = native_string_chars(line) + let i: Int = n - 1 + let trimming: Bool = true + while trimming { + if i < 0 { + let trimming = false + } else { + let ch: String = native_list_get(chars, i) + if ch == " " { let i = i - 1 } else { if ch == "\t" { let i = i - 1 } else { let trimming = false } } + } + } + str_slice(line, 0, i + 1) +} + +fn lsp_format(source: String) -> String { + let lines: [String] = str_split(source, "\n") + let n: Int = native_list_len(lines) + let cleaned: [String] = native_list_empty() + let i: Int = 0 + let blank_run: Int = 0 + while i < n { + let line: String = native_list_get(lines, i) + let stripped: String = format_strip_trailing(line) + if str_eq(stripped, "") { + let blank_run = blank_run + 1 + if blank_run <= 2 { + let cleaned = native_list_append(cleaned, "") + } + } else { + let blank_run = 0 + let cleaned = native_list_append(cleaned, stripped) + } + let i = i + 1 + } + let joined: String = list_join(cleaned, "\n") + // Ensure trailing newline. + let final: String = joined + if !str_ends_with(final, "\n") { + let final = final + "\n" + } + let changed: String = "false" + if !str_eq(final, source) { let changed = "true" } + "{" + json_kv_str("content", final) + "," + json_kv_raw("changed", changed) + "}" +} + +// ── Public: type graph ─────────────────────────────────────────────────────── + +fn lsp_type_graph(source: String) -> String { + let nodes: [String] = native_list_empty() + let edges: [String] = native_list_empty() + + // Built-in nodes + let bts: [String] = builtin_type_names() + let nb: Int = native_list_len(bts) + let i: Int = 0 + while i < nb { + let name: String = native_list_get(bts, i) + let parts: [String] = native_list_empty() + let parts = native_list_append(parts, json_kv_str("id", name)) + let parts = native_list_append(parts, json_kv_str("name", name)) + let parts = native_list_append(parts, json_kv_str("kind", "builtin")) + let parts = native_list_append(parts, json_kv_raw("fields", "[]")) + let nodes = native_list_append(nodes, "{" + list_join(parts, ",") + "}") + let i = i + 1 + } + + // User-declared types + let decls: Map = scan_decls(source) + let utypes: [String] = decls["types"] + let ukinds: [String] = decls["type_kind"] + let tlines: [Int] = decls["type_lines"] + let nu: Int = native_list_len(utypes) + let i: Int = 0 + let bts_dup: [String] = builtin_type_names() + while i < nu { + let name: String = native_list_get(utypes, i) + let kind: String = native_list_get(ukinds, i) + // Skip if already a builtin (paranoia) + if !list_contains_str(bts_dup, name) { + let fields: [String] = collect_struct_fields(source, name) + let field_jsons: [String] = native_list_empty() + let fn2: Int = native_list_len(fields) + let j: Int = 0 + while j < fn2 { + let field_jsons = native_list_append(field_jsons, json_str(native_list_get(fields, j))) + let j = j + 1 + } + let parts: [String] = native_list_empty() + let parts = native_list_append(parts, json_kv_str("id", name)) + let parts = native_list_append(parts, json_kv_str("name", name)) + let parts = native_list_append(parts, json_kv_str("kind", kind)) + let parts = native_list_append(parts, json_kv_raw("fields", json_array_of(field_jsons))) + let nodes = native_list_append(nodes, "{" + list_join(parts, ",") + "}") + + // Edges: scan each field for a known type reference. + let j: Int = 0 + while j < fn2 { + let field_str: String = native_list_get(fields, j) + let target: String = referenced_type(field_str, utypes) + if !str_eq(target, "") { + let eparts: [String] = native_list_empty() + let eparts = native_list_append(eparts, json_kv_str("from", name)) + let eparts = native_list_append(eparts, json_kv_str("to", target)) + let eparts = native_list_append(eparts, json_kv_str("label", "field")) + let edges = native_list_append(edges, "{" + list_join(eparts, ",") + "}") + } + let j = j + 1 + } + } + let i = i + 1 + } + + "{" + json_kv_raw("nodes", json_array_of(nodes)) + "," + json_kv_raw("edges", json_array_of(edges)) + "}" +} + +// Extract the field list of a `type Name { ... }` block as ["field: Type", ...] +// or for an enum, the variant labels. Best-effort line-by-line scan. +fn collect_struct_fields(source: String, type_name: String) -> [String] { + let lines: [String] = str_split(source, "\n") + let n: Int = native_list_len(lines) + let fields: [String] = native_list_empty() + let inside: Bool = false + let i: Int = 0 + let header_a: String = "type " + type_name + let header_b: String = "enum " + type_name + let header_c: String = "protocol " + type_name + while i < n { + let line: String = native_list_get(lines, i) + let trimmed: String = str_trim(line) + if !inside { + if str_starts_with(trimmed, header_a) { let inside = true } + if str_starts_with(trimmed, header_b) { let inside = true } + if str_starts_with(trimmed, header_c) { let inside = true } + } else { + if str_starts_with(trimmed, "}") { + return fields + } + // skip the opening "{" line + if !str_eq(trimmed, "{") { + if !str_eq(trimmed, "") { + if !str_starts_with(trimmed, "//") { + // strip a trailing comma if present + let entry: String = trimmed + if str_ends_with(entry, ",") { + let entry = str_slice(entry, 0, str_len(entry) - 1) + } + let fields = native_list_append(fields, str_trim(entry)) + } + } + } + } + let i = i + 1 + } + fields +} + +// Pick the first known type name out of a `field: Type` string. Stops at non-ident. +fn referenced_type(field_str: String, known_types: [String]) -> String { + // Find ":" — type follows. + let colon: Int = str_index_of(field_str, ":") + if colon < 0 { return "" } + let after: String = str_trim(str_slice(field_str, colon + 1, str_len(field_str))) + // Strip array brackets and optional marker. + let trimmed_l: String = after + if str_starts_with(trimmed_l, "[") { + let end: Int = str_index_of(trimmed_l, "]") + if end > 1 { + let trimmed_l = str_trim(str_slice(trimmed_l, 1, end)) + } + } + // First identifier. + let ident: String = first_ident_in(trimmed_l) + if str_eq(ident, "") { return "" } + let bts: [String] = builtin_type_names() + if list_contains_str(bts, ident) { return ident } + if list_contains_str(known_types, ident) { return ident } + "" +} + +// ── Public: definition / references ────────────────────────────────────────── + +fn lsp_definition(source: String, pos: Int) -> String { + let word: String = extract_token(source, pos) + if str_eq(word, "") { return "null" } + let patterns: [String] = native_list_empty() + let patterns = native_list_append(patterns, "fn " + word) + let patterns = native_list_append(patterns, "type " + word) + let patterns = native_list_append(patterns, "enum " + word) + let patterns = native_list_append(patterns, "protocol " + word) + let np: Int = native_list_len(patterns) + let lines: [String] = str_split(source, "\n") + let nl: Int = native_list_len(lines) + let i: Int = 0 + while i < nl { + let line: String = native_list_get(lines, i) + let j: Int = 0 + while j < np { + let pat: String = native_list_get(patterns, j) + let idx: Int = str_index_of(line, pat) + if idx >= 0 { + let parts: [String] = native_list_empty() + let parts = native_list_append(parts, json_kv_int("line", i + 1)) + let parts = native_list_append(parts, json_kv_int("col", idx + 1)) + let parts = native_list_append(parts, json_kv_str("snippet", str_trim(line))) + return "{" + list_join(parts, ",") + "}" + } + let j = j + 1 + } + let i = i + 1 + } + "null" +} + +fn lsp_references(source: String, pos: Int) -> String { + let word: String = extract_token(source, pos) + if str_eq(word, "") { return "[]" } + let lines: [String] = str_split(source, "\n") + let nl: Int = native_list_len(lines) + let refs: [String] = native_list_empty() + let i: Int = 0 + while i < nl { + let line: String = native_list_get(lines, i) + let line_chars: [String] = native_string_chars(line) + let llen: Int = native_list_len(line_chars) + let wlen: Int = str_len(word) + let off: Int = 0 + let scanning: Bool = true + while scanning { + let idx: Int = str_index_of(str_slice(line, off, str_len(line)), word) + if idx < 0 { + let scanning = false + } else { + let abs: Int = off + idx + // Word-boundary check + let before_ok: Bool = true + if abs > 0 { + let prev: String = native_list_get(line_chars, abs - 1) + if is_ident_ch(prev) { let before_ok = false } + } + let after_ok: Bool = true + let after_pos: Int = abs + wlen + if after_pos < llen { + let nxt: String = native_list_get(line_chars, after_pos) + if is_ident_ch(nxt) { let after_ok = false } + } + if before_ok { + if after_ok { + let parts: [String] = native_list_empty() + let parts = native_list_append(parts, json_kv_int("line", i + 1)) + let parts = native_list_append(parts, json_kv_int("col", abs + 1)) + let parts = native_list_append(parts, json_kv_str("snippet", str_trim(line))) + let refs = native_list_append(refs, "{" + list_join(parts, ",") + "}") + } + } + let off = abs + wlen + if off >= str_len(line) { let scanning = false } + } + } + let i = i + 1 + } + json_array_of(refs) +} + +// ── JSON-RPC dispatch ──────────────────────────────────────────────────────── +// +// Method names follow LSP-ish conventions but stay aligned with the Rust crate's +// HTTP surface. Params are a JSON string the dispatcher pulls fields out of via +// json_get_string / json_get_int. +// +// "textDocument/completion" → params { source, pos } +// "textDocument/hover" → params { source, pos } +// "textDocument/diagnostic" → params { source } +// "textDocument/formatting" → params { source } +// "textDocument/documentSymbol"→ params { source } +// "textDocument/definition" → params { source, pos } +// "textDocument/references" → params { source, pos } +// "el/typeGraph" → params { source } + +fn lsp_jsonrpc(method: String, params_json: String) -> String { + let source: String = json_get_string(params_json, "source") + let pos: Int = json_get_int(params_json, "pos") + if str_eq(method, "textDocument/completion") { return lsp_complete(source, pos) } + if str_eq(method, "textDocument/hover") { return lsp_hover(source, pos) } + if str_eq(method, "textDocument/diagnostic") { return lsp_diagnostics(source) } + if str_eq(method, "textDocument/formatting") { return lsp_format(source) } + if str_eq(method, "textDocument/documentSymbol") { return lsp_outline(source) } + if str_eq(method, "textDocument/definition") { return lsp_definition(source, pos) } + if str_eq(method, "textDocument/references") { return lsp_references(source, pos) } + if str_eq(method, "el/typeGraph") { return lsp_type_graph(source) } + "{\"error\":\"unknown method: " + json_escape(method) + "\"}" +} + +// ── stdio loop (best-effort; see runtime gap note in the report) ───────────── +// +// LSP framing is `Content-Length: N\r\n\r\n` then exactly N bytes. The El +// runtime exposes only line-buffered `readline()`, which strips `\n` and is +// hostile to the binary body read. We approximate by reading lines until a +// blank line ends the headers, then reading exactly one more line as the +// body (works for compact, no-newline payloads — i.e. minified JSON-RPC). +// A dedicated `read_n(bytes)` runtime primitive would unblock the strict +// implementation. See report. + +fn read_headers() -> Map { + let content_len: Int = 0 + let scanning: Bool = true + while scanning { + let line: String = readline() + if str_eq(line, "") { + let scanning = false + } else { + let cl_marker: String = "Content-Length:" + if str_starts_with(line, cl_marker) { + let val: String = str_trim(str_slice(line, str_len(cl_marker), str_len(line))) + let content_len = str_to_int(val) + } + } + } + { "content_length": content_len } +} + +fn lsp_stdio_loop() -> Void { + let running: Bool = true + while running { + let headers: Map = read_headers() + let body: String = readline() + if str_eq(body, "") { + let running = false + } else { + let method: String = json_get_string(body, "method") + let id_val: String = json_get_raw(body, "id") + if str_eq(id_val, "") { let id_val = "null" } + let params_raw: String = json_get_raw(body, "params") + let result: String = lsp_jsonrpc(method, params_raw) + let resp: String = "{\"jsonrpc\":\"2.0\",\"id\":" + id_val + ",\"result\":" + result + "}" + let frame: String = "Content-Length: " + int_to_str(str_len(resp)) + "\r\n\r\n" + resp + print(frame) + } + } +} + +// ── Entry ──────────────────────────────────────────────────────────────────── +// +// When invoked as a standalone binary, default to stdio JSON-RPC so editors +// that drive the language server directly (without the HTTP wrapper) work +// out of the box. Pass a single CLI arg to short-circuit: +// ./el-lsp probe → emits a self-test diagnostic + exits +// ./el-lsp version → emits version + exits + +fn lsp_main() -> Void { + let argv: [String] = args() + let n: Int = native_list_len(argv) + if n > 0 { + let cmd: String = native_list_get(argv, 0) + if str_eq(cmd, "version") { + println("el-lsp 0.1.0") + return + } + if str_eq(cmd, "probe") { + let sample: String = "fn main() -> Void { let x: Int = 42 }" + println(lsp_diagnostics(sample)) + return + } + } + lsp_stdio_loop() +} + +lsp_main() diff --git a/ide/vessels/el-lsp/src/main.err b/ide/vessels/el-lsp/src/main.err new file mode 100644 index 0000000..e69de29 diff --git a/ide/vessels/el-plugin-host/manifest.el b/ide/vessels/el-plugin-host/manifest.el new file mode 100644 index 0000000..0f496d7 --- /dev/null +++ b/ide/vessels/el-plugin-host/manifest.el @@ -0,0 +1,13 @@ +// manifest.el — el-plugin-host vessel + +vessel "el-plugin-host" { + version "0.1.0" + description "Plugin lifecycle manager for el-ide. First-party plugin registry, install/remove/enable/disable." + authors ["Will Anderson "] + edition "2026" +} + +build { + entry "src/main.el" + output "dist/" +} diff --git a/ide/vessels/el-plugin-host/src/el-plugin-host b/ide/vessels/el-plugin-host/src/el-plugin-host new file mode 100755 index 0000000000000000000000000000000000000000..ec8fdf5d37f5e4151e28f56ea3b9e12f8e24dda3 GIT binary patch literal 130800 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 literal 0 HcmV?d00001 diff --git a/ide/vessels/el-plugin-host/src/main.c b/ide/vessels/el-plugin-host/src/main.c new file mode 100644 index 0000000..e47c081 --- /dev/null +++ b/ide/vessels/el-plugin-host/src/main.c @@ -0,0 +1,311 @@ +#include +#include +#include "el_runtime.h" + +el_val_t pkey(el_val_t name, el_val_t field); +el_val_t put_str(el_val_t name, el_val_t field, el_val_t value); +el_val_t put_bool(el_val_t name, el_val_t field, el_val_t value); +el_val_t get_str(el_val_t name, el_val_t field); +el_val_t get_bool(el_val_t name, el_val_t field); +el_val_t index_list(void); +el_val_t index_set(el_val_t names); +el_val_t index_contains(el_val_t name); +el_val_t index_add(el_val_t name); +el_val_t register_plugin(el_val_t name, el_val_t version, el_val_t description, el_val_t installed, el_val_t enabled, el_val_t hooks, el_val_t first_party); +el_val_t plugin_init(void); +el_val_t json_escape_str(el_val_t s); +el_val_t quote_json(el_val_t s); +el_val_t hooks_to_json(el_val_t hooks_csv); +el_val_t plugin_to_json(el_val_t name); +el_val_t plugin_list_json(void); +el_val_t plugin_get_json(el_val_t name); +el_val_t plugin_install(el_val_t name); +el_val_t plugin_remove(el_val_t name); +el_val_t plugin_enable(el_val_t name); +el_val_t plugin_disable(el_val_t name); +el_val_t host_main(void); + +el_val_t pkey(el_val_t name, el_val_t field) { + return el_str_concat(el_str_concat(el_str_concat(EL_STR("plugin/"), name), EL_STR("/")), field); + return 0; +} + +el_val_t put_str(el_val_t name, el_val_t field, el_val_t value) { + state_set(pkey(name, field), value); + return 0; +} + +el_val_t put_bool(el_val_t name, el_val_t field, el_val_t value) { + if (value) { + state_set(pkey(name, field), EL_STR("true")); + } + if (!value) { + state_set(pkey(name, field), EL_STR("false")); + } + return 0; +} + +el_val_t get_str(el_val_t name, el_val_t field) { + return state_get(pkey(name, field)); + return 0; +} + +el_val_t get_bool(el_val_t name, el_val_t field) { + return str_eq(state_get(pkey(name, field)), EL_STR("true")); + return 0; +} + +el_val_t index_list(void) { + el_val_t raw = state_get(EL_STR("plugins/index")); + if (str_eq(raw, EL_STR(""))) { + return native_list_empty(); + } + return str_split(raw, EL_STR(",")); + return 0; +} + +el_val_t index_set(el_val_t names) { + state_set(EL_STR("plugins/index"), list_join(names, EL_STR(","))); + return 0; +} + +el_val_t index_contains(el_val_t name) { + el_val_t names = index_list(); + el_val_t n = native_list_len(names); + el_val_t i = 0; + while (i < n) { + if (str_eq(native_list_get(names, i), name)) { + return 1; + } + i = (i + 1); + } + return 0; + return 0; +} + +el_val_t index_add(el_val_t name) { + if (!index_contains(name)) { + el_val_t names = index_list(); + names = native_list_append(names, name); + index_set(names); + } + return 0; +} + +el_val_t register_plugin(el_val_t name, el_val_t version, el_val_t description, el_val_t installed, el_val_t enabled, el_val_t hooks, el_val_t first_party) { + put_str(name, EL_STR("name"), name); + put_str(name, EL_STR("version"), version); + put_str(name, EL_STR("description"), description); + put_bool(name, EL_STR("installed"), installed); + put_bool(name, EL_STR("enabled"), enabled); + put_str(name, EL_STR("hooks"), hooks); + put_bool(name, EL_STR("first_party"), first_party); + index_add(name); + return 0; +} + +el_val_t plugin_init(void) { + if (str_eq(state_get(EL_STR("plugins/initialised")), EL_STR("true"))) { + return 0; + } + register_plugin(EL_STR("el-theme-dark"), EL_STR("1.0.0"), EL_STR("Dark theme — the default Engram IDE theme."), 1, 1, EL_STR(""), 1); + register_plugin(EL_STR("el-theme-light"), EL_STR("1.0.0"), EL_STR("Light theme for high-ambient-light environments."), 0, 0, EL_STR(""), 1); + register_plugin(EL_STR("el-fmt"), EL_STR("0.1.0"), EL_STR("Code formatter — auto-formats .el files on save."), 1, 1, EL_STR("on_save"), 1); + register_plugin(EL_STR("el-doc"), EL_STR("0.1.0"), EL_STR("Documentation generator — produces HTML docs from type definitions."), 0, 0, EL_STR("custom_tool"), 1); + register_plugin(EL_STR("el-test"), EL_STR("0.1.0"), EL_STR("Test runner with inline results displayed in the editor gutter."), 0, 0, EL_STR("on_build_complete,custom_panel"), 1); + state_set(EL_STR("plugins/initialised"), EL_STR("true")); + return 0; +} + +el_val_t json_escape_str(el_val_t s) { + el_val_t chars = native_string_chars(s); + el_val_t n = native_list_len(chars); + el_val_t out = EL_STR(""); + el_val_t i = 0; + while (i < n) { + el_val_t ch = native_list_get(chars, i); + if (str_eq(ch, EL_STR("\""))) { + out = el_str_concat(out, EL_STR("\\\"")); + } else { + if (str_eq(ch, EL_STR("\\"))) { + out = el_str_concat(out, EL_STR("\\\\")); + } else { + if (str_eq(ch, EL_STR("\n"))) { + out = el_str_concat(out, EL_STR("\\n")); + } else { + out = el_str_concat(out, ch); + } + } + } + i = (i + 1); + } + return out; + return 0; +} + +el_val_t quote_json(el_val_t s) { + return el_str_concat(el_str_concat(EL_STR("\""), json_escape_str(s)), EL_STR("\"")); + return 0; +} + +el_val_t hooks_to_json(el_val_t hooks_csv) { + if (str_eq(hooks_csv, EL_STR(""))) { + return EL_STR("[]"); + } + el_val_t xs = str_split(hooks_csv, EL_STR(",")); + el_val_t n = native_list_len(xs); + el_val_t out = EL_STR("["); + el_val_t i = 0; + while (i < n) { + if (i > 0) { + out = el_str_concat(out, EL_STR(",")); + } + out = el_str_concat(out, quote_json(native_list_get(xs, i))); + i = (i + 1); + } + return el_str_concat(out, EL_STR("]")); + return 0; +} + +el_val_t plugin_to_json(el_val_t name) { + el_val_t parts = native_list_empty(); + parts = native_list_append(parts, el_str_concat(EL_STR("\"name\":"), quote_json(get_str(name, EL_STR("name"))))); + parts = native_list_append(parts, el_str_concat(EL_STR("\"version\":"), quote_json(get_str(name, EL_STR("version"))))); + parts = native_list_append(parts, el_str_concat(EL_STR("\"description\":"), quote_json(get_str(name, EL_STR("description"))))); + el_val_t installed = get_str(name, EL_STR("installed")); + el_val_t enabled = get_str(name, EL_STR("enabled")); + el_val_t first_party = get_str(name, EL_STR("first_party")); + parts = native_list_append(parts, el_str_concat(EL_STR("\"installed\":"), installed)); + parts = native_list_append(parts, el_str_concat(EL_STR("\"enabled\":"), enabled)); + parts = native_list_append(parts, el_str_concat(EL_STR("\"hooks\":"), hooks_to_json(get_str(name, EL_STR("hooks"))))); + parts = native_list_append(parts, el_str_concat(EL_STR("\"first_party\":"), first_party)); + return el_str_concat(el_str_concat(EL_STR("{"), list_join(parts, EL_STR(","))), EL_STR("}")); + return 0; +} + +el_val_t plugin_list_json(void) { + plugin_init(); + el_val_t names = index_list(); + el_val_t n = native_list_len(names); + el_val_t out = EL_STR("["); + el_val_t i = 0; + while (i < n) { + if (i > 0) { + out = el_str_concat(out, EL_STR(",")); + } + out = el_str_concat(out, plugin_to_json(native_list_get(names, i))); + i = (i + 1); + } + return el_str_concat(out, EL_STR("]")); + return 0; +} + +el_val_t plugin_get_json(el_val_t name) { + plugin_init(); + if (!index_contains(name)) { + return EL_STR("null"); + } + return plugin_to_json(name); + return 0; +} + +el_val_t plugin_install(el_val_t name) { + plugin_init(); + if (!index_contains(name)) { + return EL_STR("{\"error\":\"plugin registry is not available (registry URL not configured)\"}"); + } + if (get_bool(name, EL_STR("installed"))) { + return el_str_concat(el_str_concat(EL_STR("{\"error\":\"plugin '"), json_escape_str(name)), EL_STR("' is already installed\"}")); + } + put_bool(name, EL_STR("installed"), 1); + put_bool(name, EL_STR("enabled"), 1); + return plugin_to_json(name); + return 0; +} + +el_val_t plugin_remove(el_val_t name) { + plugin_init(); + if (!index_contains(name)) { + return el_str_concat(el_str_concat(EL_STR("{\"error\":\"plugin '"), json_escape_str(name)), EL_STR("' not found\"}")); + } + if (str_eq(name, EL_STR("el-theme-dark"))) { + return el_str_concat(el_str_concat(EL_STR("{\"error\":\"plugin '"), json_escape_str(name)), EL_STR("' cannot be removed: it is a required built-in\"}")); + } + put_bool(name, EL_STR("installed"), 0); + put_bool(name, EL_STR("enabled"), 0); + return EL_STR("{\"ok\":true}"); + return 0; +} + +el_val_t plugin_enable(el_val_t name) { + plugin_init(); + if (!index_contains(name)) { + return el_str_concat(el_str_concat(EL_STR("{\"error\":\"plugin '"), json_escape_str(name)), EL_STR("' not found\"}")); + } + put_bool(name, EL_STR("enabled"), 1); + return EL_STR("{\"ok\":true}"); + return 0; +} + +el_val_t plugin_disable(el_val_t name) { + plugin_init(); + if (!index_contains(name)) { + return el_str_concat(el_str_concat(EL_STR("{\"error\":\"plugin '"), json_escape_str(name)), EL_STR("' not found\"}")); + } + put_bool(name, EL_STR("enabled"), 0); + return EL_STR("{\"ok\":true}"); + return 0; +} + +el_val_t host_main(void) { + el_val_t argv = args(); + el_val_t n = native_list_len(argv); + if (n == 0) { + println(plugin_list_json()); + return 0; + } + el_val_t cmd = native_list_get(argv, 0); + if (str_eq(cmd, EL_STR("list"))) { + println(plugin_list_json()); + return 0; + } + if (str_eq(cmd, EL_STR("get"))) { + if (n >= 2) { + println(plugin_get_json(native_list_get(argv, 1))); + } + return 0; + } + if (str_eq(cmd, EL_STR("install"))) { + if (n >= 2) { + println(plugin_install(native_list_get(argv, 1))); + } + return 0; + } + if (str_eq(cmd, EL_STR("remove"))) { + if (n >= 2) { + println(plugin_remove(native_list_get(argv, 1))); + } + return 0; + } + if (str_eq(cmd, EL_STR("enable"))) { + if (n >= 2) { + println(plugin_enable(native_list_get(argv, 1))); + } + return 0; + } + if (str_eq(cmd, EL_STR("disable"))) { + if (n >= 2) { + println(plugin_disable(native_list_get(argv, 1))); + } + return 0; + } + println(EL_STR("usage: el-plugin-host [list|get|install|remove|enable|disable] ")); + return 0; +} + +int main(int argc, char** argv) { + el_runtime_init_args(argc, argv); + host_main(); + return 0; +} + diff --git a/ide/vessels/el-plugin-host/src/main.el b/ide/vessels/el-plugin-host/src/main.el new file mode 100644 index 0000000..b42fec0 --- /dev/null +++ b/ide/vessels/el-plugin-host/src/main.el @@ -0,0 +1,251 @@ +// main.el — el-plugin-host +// +// Plugin lifecycle manager for el-ide. Pure-El port of the el-plugin-host +// Rust crate. +// +// Plugins are stored in process-global state via state_get / state_set. +// Each plugin lives under a key prefix `plugin//`. The +// canonical list of plugin names is maintained at `plugins/index` as a +// comma-separated string (we don't have list serialisation in state yet). +// +// Public API: +// plugin_init() — seed first-party plugins (idempotent) +// plugin_list_json() -> String — JSON array of all plugins +// plugin_get_json(name) -> String — JSON object or "null" +// plugin_install(name) -> String — JSON { ok | error } +// plugin_remove(name) -> String +// plugin_enable(name) -> String +// plugin_disable(name) -> String + +// ── State helpers (string K/V) ─────────────────────────────────────────────── + +fn pkey(name: String, field: String) -> String { + "plugin/" + name + "/" + field +} + +fn put_str(name: String, field: String, value: String) -> Void { + state_set(pkey(name, field), value) +} + +fn put_bool(name: String, field: String, value: Bool) -> Void { + if value { state_set(pkey(name, field), "true") } + if !value { state_set(pkey(name, field), "false") } +} + +fn get_str(name: String, field: String) -> String { + state_get(pkey(name, field)) +} + +fn get_bool(name: String, field: String) -> Bool { + str_eq(state_get(pkey(name, field)), "true") +} + +// Plugin index: comma-separated list of names at "plugins/index". +fn index_list() -> [String] { + let raw: String = state_get("plugins/index") + if str_eq(raw, "") { return native_list_empty() } + str_split(raw, ",") +} + +fn index_set(names: [String]) -> Void { + state_set("plugins/index", list_join(names, ",")) +} + +fn index_contains(name: String) -> Bool { + let names: [String] = index_list() + let n: Int = native_list_len(names) + let i: Int = 0 + while i < n { + if str_eq(native_list_get(names, i), name) { return true } + let i = i + 1 + } + false +} + +fn index_add(name: String) -> Void { + if !index_contains(name) { + let names: [String] = index_list() + let names = native_list_append(names, name) + index_set(names) + } +} + +// ── Initialisation ─────────────────────────────────────────────────────────── + +fn register_plugin(name: String, version: String, description: String, + installed: Bool, enabled: Bool, hooks: String, + first_party: Bool) -> Void { + put_str(name, "name", name) + put_str(name, "version", version) + put_str(name, "description", description) + put_bool(name, "installed", installed) + put_bool(name, "enabled", enabled) + put_str(name, "hooks", hooks) + put_bool(name, "first_party", first_party) + index_add(name) +} + +fn plugin_init() -> Void { + if str_eq(state_get("plugins/initialised"), "true") { + return + } + register_plugin("el-theme-dark", "1.0.0", "Dark theme — the default Engram IDE theme.", true, true, "", true) + register_plugin("el-theme-light", "1.0.0", "Light theme for high-ambient-light environments.", false, false, "", true) + register_plugin("el-fmt", "0.1.0", "Code formatter — auto-formats .el files on save.", true, true, "on_save", true) + register_plugin("el-doc", "0.1.0", "Documentation generator — produces HTML docs from type definitions.", false, false, "custom_tool", true) + register_plugin("el-test", "0.1.0", "Test runner with inline results displayed in the editor gutter.", false, false, "on_build_complete,custom_panel", true) + state_set("plugins/initialised", "true") +} + +// ── Serialisation ──────────────────────────────────────────────────────────── + +fn json_escape_str(s: String) -> String { + let chars: [String] = native_string_chars(s) + let n: Int = native_list_len(chars) + let out: String = "" + let i: Int = 0 + while i < n { + let ch: String = native_list_get(chars, i) + if ch == "\"" { let out = out + "\\\"" } + else { if ch == "\\" { let out = out + "\\\\" } + else { if ch == "\n" { let out = out + "\\n" } + else { let out = out + ch } } } + let i = i + 1 + } + out +} + +fn quote_json(s: String) -> String { + "\"" + json_escape_str(s) + "\"" +} + +fn hooks_to_json(hooks_csv: String) -> String { + if str_eq(hooks_csv, "") { return "[]" } + let xs: [String] = str_split(hooks_csv, ",") + let n: Int = native_list_len(xs) + let out: String = "[" + let i: Int = 0 + while i < n { + if i > 0 { let out = out + "," } + let out = out + quote_json(native_list_get(xs, i)) + let i = i + 1 + } + out + "]" +} + +fn plugin_to_json(name: String) -> String { + let parts: [String] = native_list_empty() + let parts = native_list_append(parts, "\"name\":" + quote_json(get_str(name, "name"))) + let parts = native_list_append(parts, "\"version\":" + quote_json(get_str(name, "version"))) + let parts = native_list_append(parts, "\"description\":" + quote_json(get_str(name, "description"))) + let installed: String = get_str(name, "installed") + let enabled: String = get_str(name, "enabled") + let first_party: String = get_str(name, "first_party") + let parts = native_list_append(parts, "\"installed\":" + installed) + let parts = native_list_append(parts, "\"enabled\":" + enabled) + let parts = native_list_append(parts, "\"hooks\":" + hooks_to_json(get_str(name, "hooks"))) + let parts = native_list_append(parts, "\"first_party\":" + first_party) + "{" + list_join(parts, ",") + "}" +} + +fn plugin_list_json() -> String { + plugin_init() + let names: [String] = index_list() + let n: Int = native_list_len(names) + let out: String = "[" + let i: Int = 0 + while i < n { + if i > 0 { let out = out + "," } + let out = out + plugin_to_json(native_list_get(names, i)) + let i = i + 1 + } + out + "]" +} + +fn plugin_get_json(name: String) -> String { + plugin_init() + if !index_contains(name) { return "null" } + plugin_to_json(name) +} + +// ── Mutations ──────────────────────────────────────────────────────────────── + +fn plugin_install(name: String) -> String { + plugin_init() + if !index_contains(name) { + return "{\"error\":\"plugin registry is not available (registry URL not configured)\"}" + } + if get_bool(name, "installed") { + return "{\"error\":\"plugin '" + json_escape_str(name) + "' is already installed\"}" + } + put_bool(name, "installed", true) + put_bool(name, "enabled", true) + plugin_to_json(name) +} + +fn plugin_remove(name: String) -> String { + plugin_init() + if !index_contains(name) { + return "{\"error\":\"plugin '" + json_escape_str(name) + "' not found\"}" + } + if str_eq(name, "el-theme-dark") { + return "{\"error\":\"plugin '" + json_escape_str(name) + "' cannot be removed: it is a required built-in\"}" + } + put_bool(name, "installed", false) + put_bool(name, "enabled", false) + "{\"ok\":true}" +} + +fn plugin_enable(name: String) -> String { + plugin_init() + if !index_contains(name) { + return "{\"error\":\"plugin '" + json_escape_str(name) + "' not found\"}" + } + put_bool(name, "enabled", true) + "{\"ok\":true}" +} + +fn plugin_disable(name: String) -> String { + plugin_init() + if !index_contains(name) { + return "{\"error\":\"plugin '" + json_escape_str(name) + "' not found\"}" + } + put_bool(name, "enabled", false) + "{\"ok\":true}" +} + +// ── Standalone CLI ─────────────────────────────────────────────────────────── + +fn host_main() -> Void { + let argv: [String] = args() + let n: Int = native_list_len(argv) + if n == 0 { + println(plugin_list_json()) + return + } + let cmd: String = native_list_get(argv, 0) + if str_eq(cmd, "list") { println(plugin_list_json()) return } + if str_eq(cmd, "get") { + if n >= 2 { println(plugin_get_json(native_list_get(argv, 1))) } + return + } + if str_eq(cmd, "install") { + if n >= 2 { println(plugin_install(native_list_get(argv, 1))) } + return + } + if str_eq(cmd, "remove") { + if n >= 2 { println(plugin_remove(native_list_get(argv, 1))) } + return + } + if str_eq(cmd, "enable") { + if n >= 2 { println(plugin_enable(native_list_get(argv, 1))) } + return + } + if str_eq(cmd, "disable") { + if n >= 2 { println(plugin_disable(native_list_get(argv, 1))) } + return + } + println("usage: el-plugin-host [list|get|install|remove|enable|disable] ") +} + +host_main() diff --git a/ide/vessels/el-plugin-host/src/main.err b/ide/vessels/el-plugin-host/src/main.err new file mode 100644 index 0000000..e69de29