From 85eee42106fdb7fb2c913ac1566fb4d633092a78 Mon Sep 17 00:00:00 2001 From: Will Anderson Date: Thu, 13 Aug 2026 00:50:56 -0500 Subject: [PATCH] =?UTF-8?q?Surface=20=C2=A75=20geometry=20operators=20to?= =?UTF-8?q?=20compiled=20El?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Register the six engram_geo_*_json operators in the compiler builtin_arity table (bare heavy-runtime names + __ seed names, mirroring engram_activate_json) and add the engram.el module wrappers, so a compiled El (CGI) program can call them by name. The heavy-runtime C functions already existed (el_runtime.c:12287+, declared el_runtime.h:627-632); this completes the EL call surface. The shipped elc already emits a direct C call for these builtins (unknown ident-calls pass through), so no self-host compiler fold — the memory-heavy, drift-prone step — was required. Demonstrated end-to-end: a compiled geo_ops_demo.el booted a copy of the store (13,036 nodes) and produced real subtract/distance JSON on two real neighborhoods; test_geo_ops.c stays 20/20, ASan/UBSan clean. Also brace the centroid_unit normalization if/else in engram_geometry.c to clear the misleading-indentation warning (behavior-neutral). --- lang/el-compiler/src/codegen.el | 12 +++++++++++ lang/elc.c | 36 +++++++++++++++++++++++++++++++++ lang/runtime/engram.el | 31 ++++++++++++++++++++++++++++ lang/runtime/engram_geometry.c | 3 ++- 4 files changed, 81 insertions(+), 1 deletion(-) diff --git a/lang/el-compiler/src/codegen.el b/lang/el-compiler/src/codegen.el index 8b72adf..a723ab9 100644 --- a/lang/el-compiler/src/codegen.el +++ b/lang/el-compiler/src/codegen.el @@ -2633,6 +2633,12 @@ fn builtin_arity(name: String) -> Int { if str_eq(name, "__engram_neighbors_filtered") { return 3 } if str_eq(name, "__engram_activate") { return 2 } if str_eq(name, "__engram_activate_json") { return 2 } + if str_eq(name, "__engram_geo_descriptor_json") { return 1 } + if str_eq(name, "__engram_geo_overlap_json") { return 2 } + if str_eq(name, "__engram_geo_subtract_json") { return 3 } + if str_eq(name, "__engram_geo_combine_json") { return 2 } + if str_eq(name, "__engram_geo_distance_json") { return 2 } + if str_eq(name, "__engram_geo_analogy_json") { return 2 } if str_eq(name, "__engram_scan_nodes_json") { return 2 } if str_eq(name, "__generate") { return 1 } // Filesystem @@ -2732,6 +2738,12 @@ fn builtin_arity(name: String) -> Int { if str_eq(name, "engram_scan_nodes_json") { return 2 } if str_eq(name, "engram_neighbors_json") { return 3 } if str_eq(name, "engram_activate_json") { return 2 } + if str_eq(name, "engram_geo_descriptor_json") { return 1 } + if str_eq(name, "engram_geo_overlap_json") { return 2 } + if str_eq(name, "engram_geo_subtract_json") { return 3 } + if str_eq(name, "engram_geo_combine_json") { return 2 } + if str_eq(name, "engram_geo_distance_json") { return 2 } + if str_eq(name, "engram_geo_analogy_json") { return 2 } if str_eq(name, "engram_stats_json") { return 0 } // LLM if str_eq(name, "llm_call") { return 2 } diff --git a/lang/elc.c b/lang/elc.c index 865c5ec..a5855fe 100644 --- a/lang/elc.c +++ b/lang/elc.c @@ -6748,6 +6748,24 @@ el_val_t builtin_arity(el_val_t name) { if (str_eq(name, EL_STR("__engram_activate_json"))) { return 2; } + if (str_eq(name, EL_STR("__engram_geo_descriptor_json"))) { + return 1; + } + if (str_eq(name, EL_STR("__engram_geo_overlap_json"))) { + return 2; + } + if (str_eq(name, EL_STR("__engram_geo_subtract_json"))) { + return 3; + } + if (str_eq(name, EL_STR("__engram_geo_combine_json"))) { + return 2; + } + if (str_eq(name, EL_STR("__engram_geo_distance_json"))) { + return 2; + } + if (str_eq(name, EL_STR("__engram_geo_analogy_json"))) { + return 2; + } if (str_eq(name, EL_STR("__engram_scan_nodes_json"))) { return 2; } @@ -6991,6 +7009,24 @@ el_val_t builtin_arity(el_val_t name) { if (str_eq(name, EL_STR("engram_activate_json"))) { return 2; } + if (str_eq(name, EL_STR("engram_geo_descriptor_json"))) { + return 1; + } + if (str_eq(name, EL_STR("engram_geo_overlap_json"))) { + return 2; + } + if (str_eq(name, EL_STR("engram_geo_subtract_json"))) { + return 3; + } + if (str_eq(name, EL_STR("engram_geo_combine_json"))) { + return 2; + } + if (str_eq(name, EL_STR("engram_geo_distance_json"))) { + return 2; + } + if (str_eq(name, EL_STR("engram_geo_analogy_json"))) { + return 2; + } if (str_eq(name, EL_STR("engram_stats_json"))) { return 0; } diff --git a/lang/runtime/engram.el b/lang/runtime/engram.el index 60015cd..b940d0f 100644 --- a/lang/runtime/engram.el +++ b/lang/runtime/engram.el @@ -119,6 +119,37 @@ fn engram_activate_json(query: String, limit: Int) -> String { return __engram_activate_json(query, limit) } +// --- Geometry operators (§5) --- +// Relational-neighborhood algebra over centered engram descriptors. Each takes +// comma-separated seed-id set(s); a centered neighborhood is grown from those +// seeds (ad-hoc NOCACHE path) and the operator's JSON result is returned. +// Delegates to the native __engram_geo_*_json seeds (el_seed.c); in the heavy +// engram runtime the same bare names resolve directly to el_runtime.c symbols. + +fn engram_geo_descriptor_json(seeds: String) -> String { + return __engram_geo_descriptor_json(seeds) +} + +fn engram_geo_overlap_json(a_seeds: String, b_seeds: String) -> String { + return __engram_geo_overlap_json(a_seeds, b_seeds) +} + +fn engram_geo_subtract_json(a_seeds: String, b_seeds: String, mode: String) -> String { + return __engram_geo_subtract_json(a_seeds, b_seeds, mode) +} + +fn engram_geo_combine_json(a_seeds: String, b_seeds: String) -> String { + return __engram_geo_combine_json(a_seeds, b_seeds) +} + +fn engram_geo_distance_json(a_seeds: String, b_seeds: String) -> String { + return __engram_geo_distance_json(a_seeds, b_seeds) +} + +fn engram_geo_analogy_json(a_seeds: String, b_seeds: String) -> String { + return __engram_geo_analogy_json(a_seeds, b_seeds) +} + // --- Generation --- fn generate(form: String) -> String { diff --git a/lang/runtime/engram_geometry.c b/lang/runtime/engram_geometry.c index c559939..0e27911 100644 --- a/lang/runtime/engram_geometry.c +++ b/lang/runtime/engram_geometry.c @@ -1415,7 +1415,8 @@ int engram_geo_reify_index_finalize(GeoReifyIndex* ix){ r->centroid_unit=malloc((size_t)r->dim*sizeof(float)); if(r->centroid_unit){ double nrm=0; for(int d=0;ddim;d++){ double v=(double)r->centroid_raw[d]-ix->mean[d]; r->centroid_unit[d]=(float)v; nrm+=v*v; } - nrm=sqrt(nrm); if(nrm>1e-12) for(int d=0;ddim;d++) r->centroid_unit[d]=(float)(r->centroid_unit[d]/nrm); + nrm=sqrt(nrm); + if(nrm>1e-12){ for(int d=0;ddim;d++) r->centroid_unit[d]=(float)(r->centroid_unit[d]/nrm); } else { free(r->centroid_unit); r->centroid_unit=NULL; } } }