From 12d5e7777e60601ae897fa6b1470fdb8d97f5506 Mon Sep 17 00:00:00 2001 From: Will Anderson Date: Thu, 30 Apr 2026 14:06:19 -0500 Subject: [PATCH] runtime + compiler: dharma, match, cgi blocks, VBD, agentic LLM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two parallel agent sweeps closing the remaining structural gaps. == Compiler completions == - match codegen: lowers Match into GCC/Clang statement-expression ({ ... }). Patterns: Wildcard, Binding, LitInt (==), LitStr (str_eq), LitBool. Per-match unique label via state counter. Verified: classify(0)→"zero", classify(1)→"one", classify(7)→"other". - cgi block parsing: `cgi "name" { dharma_id, principal, network, engram }` → CgiBlock AST node → el_cgi_init() emitted as the first call in main() after el_runtime_init_args. Multiple cgi blocks per program emit a #error directive. Missing optional fields → EL_NULL. - VBD compile-time enforcement: parser attaches `decorator: ` to FnDef. Codegen recursively walks fn bodies (Call/BinOp/Not/Neg/ Field/Index/Try/Array/Map/If/For/Match plus Let/Return/Expr/While/ For). If a non-@manager function calls dharma_emit or dharma_field, emit `#error "VBD violation: ... fn ''"` before the function body. Verified: @engine fn calling dharma_emit → cc fails with the message. @manager fn calling dharma_emit → compiles clean. Three-stage closure: stage1.c == stage2.c == stage3.c (2791 lines each, byte-identical). dist/platform/elc rebuilt at 165 KB; .prev5 preserved. == Runtime completions == - Real dharma_* primitives, no more stubs. Channel registry, request/response over HTTP, network-wide spreading activation, fire-and-forget event emission, blocking dharma_field with pthread_cond_timedwait (30s default), Hebbian relationship weights stored as Engram edges between dharma:self and dharma:peer:, sorted-by-weight peer list. URL/ID arrays snapshotted before network I/O so mutexes never block on socket. - New public C contract: el_runtime_dharma_event_arrive(type, payload, source) — application HTTP handler calls this when /dharma/event arrives, runtime broadcasts on _dharma_event_cv. Keeps the HTTP server generic; events flow through the application's router. - llm_call_agentic real multi-turn loop. Tool registry (mutex- protected, dlsym-resolved, mirroring http_set_handler). Loop: build request with tools+messages → POST → dispatch on stop_reason. end_turn → return text. max_tokens → text + "[truncated]". tool_use → walk content[], call registered handler per block, build tool_result message, append to conversation, loop. Iteration cap 10. Tools not registered return {"error":"tool not registered: X"} with is_error: true. - New builtin: llm_register_tool(name, handler_fn_name). Compile clean: cc -std=c11 -Wall -Wextra -c → zero warnings, zero errors. Smoke test exercises every new dharma_* primitive + llm_register_tool round-trip. Runtime grew 3309→4079 lines (.c, ~155 KB), 312→342 lines (.h). == Integration == Engram rebuilt against the new runtime: 130 KB binary, daemon swapped on :8742 cleanly, /health and /api/stats both returning correctly under launchd. No regressions. == Status of "planned" items in language.md == - match codegen → IMPLEMENTED - cgi block parsing → IMPLEMENTED - VBD enforcement → IMPLEMENTED - % operator → IMPLEMENTED (earlier today) - vessel keyword → lexed (codegen uses package compatible) - activate construct → still planned (low priority; engram_activate builtin covers the use case for now) - sealed block → still planned - dharma_emit fanout parallelization → potential future work, current serial behavior matches spec --- dist/platform/elc | Bin 147768 -> 165560 bytes dist/platform/elc.c | 374 +++++++++++- dist/platform/elc.prev5 | Bin 0 -> 147768 bytes el-compiler/runtime/el_runtime.c | 946 ++++++++++++++++++++++++++++--- el-compiler/runtime/el_runtime.h | 34 +- el-compiler/src/codegen.el | 262 +++++++++ el-compiler/src/parser.el | 87 ++- elc-combined.el | 349 +++++++++++- 8 files changed, 1955 insertions(+), 97 deletions(-) create mode 100755 dist/platform/elc.prev5 diff --git a/dist/platform/elc b/dist/platform/elc index 88d4d3c08b8f01aa7ac2bd584f113141b89dbdbb..a4ed6f4739176bc6ad413606edba1d10bfc95e84 100755 GIT binary patch literal 165560 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 KfA9eJNB;&TJ4yZk diff --git a/dist/platform/elc.c b/dist/platform/elc.c index cfdb4f2..23d69ba 100644 --- a/dist/platform/elc.c +++ b/dist/platform/elc.c @@ -39,6 +39,8 @@ el_val_t emit_line(el_val_t line); el_val_t emit_blank(void); el_val_t binop_to_c(el_val_t op); el_val_t cg_expr(el_val_t expr); +el_val_t next_match_id(void); +el_val_t cg_match(el_val_t expr); el_val_t list_contains(el_val_t lst, el_val_t s); el_val_t cg_stmt(el_val_t stmt, el_val_t indent, el_val_t declared); el_val_t strip_outer_parens(el_val_t s); @@ -56,6 +58,10 @@ el_val_t build_int_names_for_params(el_val_t params); el_val_t cg_fn(el_val_t stmt); el_val_t is_fndef(el_val_t stmt); el_val_t is_top_level_decl(el_val_t stmt); +el_val_t cgi_arg(el_val_t value, el_val_t has_value); +el_val_t vbd_is_restricted_name(el_val_t name); +el_val_t vbd_expr_has_restricted_call(el_val_t expr); +el_val_t vbd_has_restricted_call(el_val_t stmts); el_val_t codegen(el_val_t stmts, el_val_t source); el_val_t compile(el_val_t source); @@ -1491,8 +1497,70 @@ el_val_t parse_stmt(el_val_t tokens, el_val_t pos) { } if (str_eq(k, EL_STR("At"))) { el_val_t p = (pos + 1); + el_val_t dec_name = tok_value(tokens, p); p = (p + 1); - return parse_stmt(tokens, p); + el_val_t r = parse_stmt(tokens, p); + el_val_t inner = el_get_field(r, EL_STR("node")); + el_val_t p2 = el_get_field(r, EL_STR("pos")); + el_val_t inner_kind = el_get_field(inner, EL_STR("stmt")); + if (str_eq(inner_kind, EL_STR("FnDef"))) { + el_val_t with_dec = el_map_new(6, "stmt", EL_STR("FnDef"), "name", el_get_field(inner, EL_STR("name")), "params", el_get_field(inner, EL_STR("params")), "body", el_get_field(inner, EL_STR("body")), "ret_type", el_get_field(inner, EL_STR("ret_type")), "decorator", dec_name); + return make_result(with_dec, p2); + } + return r; + } + if (str_eq(k, EL_STR("Cgi"))) { + el_val_t p = (pos + 1); + el_val_t name = tok_value(tokens, p); + p = (p + 1); + p = expect(tokens, p, EL_STR("LBrace")); + el_val_t dharma_id = EL_STR(""); + el_val_t principal = EL_STR(""); + el_val_t network = EL_STR(""); + el_val_t engram = EL_STR(""); + el_val_t has_dharma_id = 0; + el_val_t has_principal = 0; + el_val_t has_network = 0; + el_val_t has_engram = 0; + el_val_t running = 1; + while (running) { + el_val_t k2 = tok_kind(tokens, p); + if (str_eq(k2, EL_STR("RBrace"))) { + running = 0; + } else { + if (str_eq(k2, EL_STR("Eof"))) { + running = 0; + } else { + el_val_t fname = tok_value(tokens, p); + p = (p + 1); + p = expect(tokens, p, EL_STR("Colon")); + el_val_t fval = tok_value(tokens, p); + p = (p + 1); + if (str_eq(fname, EL_STR("dharma_id"))) { + dharma_id = fval; + has_dharma_id = 1; + } + if (str_eq(fname, EL_STR("principal"))) { + principal = fval; + has_principal = 1; + } + if (str_eq(fname, EL_STR("network"))) { + network = fval; + has_network = 1; + } + if (str_eq(fname, EL_STR("engram"))) { + engram = fval; + has_engram = 1; + } + el_val_t k3 = tok_kind(tokens, p); + if (str_eq(k3, EL_STR("Comma"))) { + p = (p + 1); + } + } + } + } + p = expect(tokens, p, EL_STR("RBrace")); + return make_result(el_map_new(10, "stmt", EL_STR("CgiBlock"), "name", name, "dharma_id", dharma_id, "principal", principal, "network", network, "engram", engram, "has_dharma_id", has_dharma_id, "has_principal", has_principal, "has_network", has_network, "has_engram", has_engram), p); } el_val_t r = parse_expr(tokens, pos); el_val_t val = el_get_field(r, EL_STR("node")); @@ -1930,10 +1998,78 @@ el_val_t cg_expr(el_val_t expr) { el_val_t cond_c = cg_expr(cond); return el_str_concat(el_str_concat(EL_STR("/* if-expr */ (("), cond_c), EL_STR(") ? (el_val_t)1 : (el_val_t)0)")); } + if (str_eq(kind, EL_STR("Match"))) { + return cg_match(expr); + } return EL_STR("EL_NULL"); return 0; } +el_val_t next_match_id(void) { + el_val_t csv = state_get(EL_STR("__match_counter")); + el_val_t n = 0; + if (!str_eq(csv, EL_STR(""))) { + n = str_to_int(csv); + } + n = (n + 1); + state_set(EL_STR("__match_counter"), native_int_to_str(n)); + return native_int_to_str(n); + return 0; +} + +el_val_t cg_match(el_val_t expr) { + el_val_t subject = el_get_field(expr, EL_STR("subject")); + el_val_t arms = el_get_field(expr, EL_STR("arms")); + el_val_t subj_c = cg_expr(subject); + el_val_t id = next_match_id(); + el_val_t subj_var = el_str_concat(EL_STR("_match_subj_"), id); + el_val_t result_var = el_str_concat(EL_STR("_match_result_"), id); + el_val_t done_label = el_str_concat(EL_STR("_match_done_"), id); + el_val_t out = el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("({ el_val_t "), subj_var), EL_STR(" = ")), subj_c), EL_STR("; el_val_t ")), result_var), EL_STR(" = 0; ")); + el_val_t n = native_list_len(arms); + el_val_t i = 0; + while (i < n) { + el_val_t arm = native_list_get(arms, i); + el_val_t pat = el_get_field(arm, EL_STR("pattern")); + el_val_t body = el_get_field(arm, EL_STR("body")); + el_val_t pkind = el_get_field(pat, EL_STR("pattern")); + el_val_t body_c = cg_expr(body); + if (str_eq(pkind, EL_STR("Wildcard"))) { + 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("{ ")), result_var), EL_STR(" = (")), body_c), EL_STR("); goto ")), done_label), EL_STR("; } ")); + } else { + if (str_eq(pkind, EL_STR("Binding"))) { + el_val_t bname = el_get_field(pat, EL_STR("name")); + out = el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(out, EL_STR("{ el_val_t ")), bname), EL_STR(" = ")), subj_var), EL_STR("; ")), result_var), EL_STR(" = (")), body_c), EL_STR("); goto ")), done_label), EL_STR("; } ")); + } else { + if (str_eq(pkind, EL_STR("LitInt"))) { + el_val_t v = el_get_field(pat, EL_STR("value")); + out = el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(out, EL_STR("if (")), subj_var), EL_STR(" == ")), v), EL_STR(") { ")), result_var), EL_STR(" = (")), body_c), EL_STR("); goto ")), done_label), EL_STR("; } ")); + } else { + if (str_eq(pkind, EL_STR("LitStr"))) { + el_val_t v = el_get_field(pat, EL_STR("value")); + out = el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(out, EL_STR("if (str_eq(")), subj_var), EL_STR(", EL_STR(")), c_str_lit(v)), EL_STR("))) { ")), result_var), EL_STR(" = (")), body_c), EL_STR("); goto ")), done_label), EL_STR("; } ")); + } else { + if (str_eq(pkind, EL_STR("LitBool"))) { + el_val_t v = el_get_field(pat, EL_STR("value")); + el_val_t bv = EL_STR("0"); + if (str_eq(v, EL_STR("true"))) { + bv = EL_STR("1"); + } + out = el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(out, EL_STR("if (")), subj_var), EL_STR(" == ")), bv), EL_STR(") { ")), result_var), EL_STR(" = (")), body_c), EL_STR("); goto ")), done_label), EL_STR("; } ")); + } else { + 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("{ ")), result_var), EL_STR(" = (")), body_c), EL_STR("); goto ")), done_label), EL_STR("; } ")); + } + } + } + } + } + i = (i + 1); + } + out = el_str_concat(el_str_concat(el_str_concat(el_str_concat(out, done_label), EL_STR(":; ")), result_var), EL_STR("; })")); + return out; + return 0; +} + el_val_t list_contains(el_val_t lst, el_val_t s) { el_val_t n = native_list_len(lst); el_val_t i = 0; @@ -2025,6 +2161,9 @@ el_val_t cg_stmt(el_val_t stmt, el_val_t indent, el_val_t declared) { if (str_eq(kind, EL_STR("Import"))) { return declared; } + if (str_eq(kind, EL_STR("CgiBlock"))) { + return declared; + } return declared; return 0; } @@ -2304,6 +2443,12 @@ el_val_t cg_fn(el_val_t stmt) { el_val_t body = el_get_field(stmt, EL_STR("body")); el_val_t ret_type = el_get_field(stmt, EL_STR("ret_type")); el_val_t params_c = params_to_c(params); + el_val_t decorator = el_get_field(stmt, EL_STR("decorator")); + if (vbd_has_restricted_call(body)) { + if (!str_eq(decorator, EL_STR("manager"))) { + emit_line(el_str_concat(el_str_concat(EL_STR("#error \"VBD violation: dharma_emit/dharma_field called from non-@manager fn '"), fn_name), EL_STR("'\""))); + } + } build_int_names_for_params(params); emit_line(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR("el_val_t "), fn_name), EL_STR("(")), params_c), EL_STR(") {"))); el_val_t decl = native_list_empty(); @@ -2346,11 +2491,221 @@ el_val_t is_top_level_decl(el_val_t stmt) { if (str_eq(kind, EL_STR("Import"))) { return 1; } + if (str_eq(kind, EL_STR("CgiBlock"))) { + return 1; + } + return 0; + return 0; +} + +el_val_t cgi_arg(el_val_t value, el_val_t has_value) { + if (has_value) { + return el_str_concat(el_str_concat(EL_STR("EL_STR("), c_str_lit(value)), EL_STR(")")); + } + return EL_STR("EL_NULL"); + return 0; +} + +el_val_t vbd_is_restricted_name(el_val_t name) { + if (str_eq(name, EL_STR("dharma_emit"))) { + return 1; + } + if (str_eq(name, EL_STR("dharma_field"))) { + return 1; + } + return 0; + return 0; +} + +el_val_t vbd_expr_has_restricted_call(el_val_t expr) { + el_val_t kind = el_get_field(expr, EL_STR("expr")); + if (str_eq(kind, EL_STR("Call"))) { + el_val_t func = el_get_field(expr, EL_STR("func")); + el_val_t fk = el_get_field(func, EL_STR("expr")); + if (str_eq(fk, EL_STR("Ident"))) { + el_val_t fname = el_get_field(func, EL_STR("name")); + if (vbd_is_restricted_name(fname)) { + return 1; + } + } + if (vbd_expr_has_restricted_call(func)) { + return 1; + } + el_val_t args = el_get_field(expr, EL_STR("args")); + el_val_t an = native_list_len(args); + el_val_t ai = 0; + while (ai < an) { + el_val_t a = native_list_get(args, ai); + if (vbd_expr_has_restricted_call(a)) { + return 1; + } + ai = (ai + 1); + } + return 0; + } + if (str_eq(kind, EL_STR("BinOp"))) { + el_val_t l = el_get_field(expr, EL_STR("left")); + el_val_t r = el_get_field(expr, EL_STR("right")); + if (vbd_expr_has_restricted_call(l)) { + return 1; + } + if (vbd_expr_has_restricted_call(r)) { + return 1; + } + return 0; + } + if (str_eq(kind, EL_STR("Not"))) { + return vbd_expr_has_restricted_call(el_get_field(expr, EL_STR("inner"))); + } + if (str_eq(kind, EL_STR("Neg"))) { + return vbd_expr_has_restricted_call(el_get_field(expr, EL_STR("inner"))); + } + if (str_eq(kind, EL_STR("Field"))) { + return vbd_expr_has_restricted_call(el_get_field(expr, EL_STR("object"))); + } + if (str_eq(kind, EL_STR("Index"))) { + if (vbd_expr_has_restricted_call(el_get_field(expr, EL_STR("object")))) { + return 1; + } + if (vbd_expr_has_restricted_call(el_get_field(expr, EL_STR("index")))) { + return 1; + } + return 0; + } + if (str_eq(kind, EL_STR("Try"))) { + return vbd_expr_has_restricted_call(el_get_field(expr, EL_STR("inner"))); + } + if (str_eq(kind, EL_STR("Array"))) { + el_val_t elems = el_get_field(expr, EL_STR("elems")); + el_val_t n = native_list_len(elems); + el_val_t i = 0; + while (i < n) { + el_val_t e = native_list_get(elems, i); + if (vbd_expr_has_restricted_call(e)) { + return 1; + } + i = (i + 1); + } + return 0; + } + if (str_eq(kind, EL_STR("Map"))) { + el_val_t pairs = el_get_field(expr, EL_STR("pairs")); + el_val_t n = native_list_len(pairs); + el_val_t i = 0; + while (i < n) { + el_val_t pair = native_list_get(pairs, i); + el_val_t v = el_get_field(pair, EL_STR("value")); + if (vbd_expr_has_restricted_call(v)) { + return 1; + } + i = (i + 1); + } + return 0; + } + if (str_eq(kind, EL_STR("If"))) { + if (vbd_expr_has_restricted_call(el_get_field(expr, EL_STR("cond")))) { + return 1; + } + if (vbd_has_restricted_call(el_get_field(expr, EL_STR("then")))) { + return 1; + } + if (vbd_has_restricted_call(el_get_field(expr, EL_STR("else")))) { + return 1; + } + return 0; + } + if (str_eq(kind, EL_STR("For"))) { + if (vbd_expr_has_restricted_call(el_get_field(expr, EL_STR("list")))) { + return 1; + } + if (vbd_has_restricted_call(el_get_field(expr, EL_STR("body")))) { + return 1; + } + return 0; + } + if (str_eq(kind, EL_STR("Match"))) { + if (vbd_expr_has_restricted_call(el_get_field(expr, EL_STR("subject")))) { + return 1; + } + el_val_t arms = el_get_field(expr, EL_STR("arms")); + el_val_t n = native_list_len(arms); + el_val_t i = 0; + while (i < n) { + el_val_t arm = native_list_get(arms, i); + el_val_t body = el_get_field(arm, EL_STR("body")); + if (vbd_expr_has_restricted_call(body)) { + return 1; + } + i = (i + 1); + } + return 0; + } + return 0; + return 0; +} + +el_val_t vbd_has_restricted_call(el_val_t stmts) { + el_val_t n = native_list_len(stmts); + el_val_t i = 0; + while (i < n) { + el_val_t s = native_list_get(stmts, i); + el_val_t sk = el_get_field(s, EL_STR("stmt")); + if (str_eq(sk, EL_STR("Let"))) { + if (vbd_expr_has_restricted_call(el_get_field(s, EL_STR("value")))) { + return 1; + } + } + if (str_eq(sk, EL_STR("Return"))) { + if (vbd_expr_has_restricted_call(el_get_field(s, EL_STR("value")))) { + return 1; + } + } + if (str_eq(sk, EL_STR("Expr"))) { + if (vbd_expr_has_restricted_call(el_get_field(s, EL_STR("value")))) { + return 1; + } + } + if (str_eq(sk, EL_STR("While"))) { + if (vbd_expr_has_restricted_call(el_get_field(s, EL_STR("cond")))) { + return 1; + } + if (vbd_has_restricted_call(el_get_field(s, EL_STR("body")))) { + return 1; + } + } + if (str_eq(sk, EL_STR("For"))) { + if (vbd_expr_has_restricted_call(el_get_field(s, EL_STR("list")))) { + return 1; + } + if (vbd_has_restricted_call(el_get_field(s, EL_STR("body")))) { + return 1; + } + } + i = (i + 1); + } return 0; return 0; } el_val_t codegen(el_val_t stmts, el_val_t source) { + el_val_t n_top = native_list_len(stmts); + el_val_t cgi_count = 0; + el_val_t cgi_block = el_map_new(1, "stmt", EL_STR("None")); + el_val_t ti = 0; + while (ti < n_top) { + el_val_t s = native_list_get(stmts, ti); + el_val_t sk = el_get_field(s, EL_STR("stmt")); + if (str_eq(sk, EL_STR("CgiBlock"))) { + cgi_count = (cgi_count + 1); + if (cgi_count == 1) { + cgi_block = s; + } + } + ti = (ti + 1); + } + if (cgi_count > 1) { + emit_line(EL_STR("#error \"El: multiple cgi blocks in program (only one allowed)\"")); + } emit_line(EL_STR("#include ")); emit_line(EL_STR("#include ")); emit_line(EL_STR("#include \"el_runtime.h\"")); @@ -2381,6 +2736,23 @@ el_val_t codegen(el_val_t stmts, el_val_t source) { } emit_line(EL_STR("int main(int argc, char** argv) {")); emit_line(EL_STR(" el_runtime_init_args(argc, argv);")); + if (cgi_count >= 1) { + el_val_t cname = el_get_field(cgi_block, EL_STR("name")); + el_val_t cdid = el_get_field(cgi_block, EL_STR("dharma_id")); + el_val_t cprin = el_get_field(cgi_block, EL_STR("principal")); + el_val_t cnet = el_get_field(cgi_block, EL_STR("network")); + el_val_t ceng = el_get_field(cgi_block, EL_STR("engram")); + el_val_t has_did = el_get_field(cgi_block, EL_STR("has_dharma_id")); + el_val_t has_prin = el_get_field(cgi_block, EL_STR("has_principal")); + el_val_t has_net = el_get_field(cgi_block, EL_STR("has_network")); + el_val_t has_eng = el_get_field(cgi_block, EL_STR("has_engram")); + el_val_t arg_name = el_str_concat(el_str_concat(EL_STR("EL_STR("), c_str_lit(cname)), EL_STR(")")); + el_val_t arg_did = cgi_arg(cdid, has_did); + el_val_t arg_prin = cgi_arg(cprin, has_prin); + el_val_t arg_net = cgi_arg(cnet, has_net); + el_val_t arg_eng = cgi_arg(ceng, has_eng); + emit_line(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(el_str_concat(EL_STR(" el_cgi_init("), arg_name), EL_STR(", ")), arg_did), EL_STR(", ")), arg_prin), EL_STR(", ")), arg_net), EL_STR(", ")), arg_eng), EL_STR(");"))); + } el_val_t main_decl = native_list_empty(); i = 0; while (i < n) { diff --git a/dist/platform/elc.prev5 b/dist/platform/elc.prev5 new file mode 100755 index 0000000000000000000000000000000000000000..88d4d3c08b8f01aa7ac2bd584f113141b89dbdbb GIT binary patch literal 147768 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 KfA9eJNB;&TJ4yZk literal 0 HcmV?d00001 diff --git a/el-compiler/runtime/el_runtime.c b/el-compiler/runtime/el_runtime.c index bf60cd6..bcc7a99 100644 --- a/el-compiler/runtime/el_runtime.c +++ b/el-compiler/runtime/el_runtime.c @@ -1926,84 +1926,6 @@ void el_cgi_init(el_val_t name, el_val_t dharma_id, el_val_t principal, _el_cgi_engram); } -/* ── DHARMA network stubs ─────────────────────────────────────────────────── - * Stub implementations for all dharma_* and engram_* builtins. - * Each stub prints a descriptive line to stdout so calls are visible in tests. - * Full implementations are provided by the DHARMA runtime linked at deploy. */ - -el_val_t dharma_connect(el_val_t cgi_id) { - const char* id = EL_CSTR(cgi_id); - if (!id) id = "(null)"; - char buf[256]; - snprintf(buf, sizeof(buf), "[dharma] connect: %s", id); - puts(buf); - /* Return a synthetic channel ID of the form "ch:" */ - char ch[272]; - snprintf(ch, sizeof(ch), "ch:%s", id); - return el_wrap_str(el_strdup(ch)); -} - -el_val_t dharma_send(el_val_t channel, el_val_t content) { - const char* ch = EL_CSTR(channel); - const char* msg = EL_CSTR(content); - if (!ch) ch = "(null)"; - if (!msg) msg = "(null)"; - char buf[1024]; - snprintf(buf, sizeof(buf), "[dharma] send on %s: %s", ch, msg); - puts(buf); - return el_wrap_str(el_strdup("")); -} - -el_val_t dharma_activate(el_val_t query) { - const char* q = EL_CSTR(query); - if (!q) q = "(null)"; - char buf[512]; - snprintf(buf, sizeof(buf), "[dharma] activate: %s", q); - puts(buf); - return el_list_empty(); -} - -void dharma_emit(el_val_t event_type, el_val_t payload) { - const char* et = EL_CSTR(event_type); - const char* pay = EL_CSTR(payload); - if (!et) et = "(null)"; - if (!pay) pay = "(null)"; - char buf[1024]; - snprintf(buf, sizeof(buf), "[dharma] emit: %s %s", et, pay); - puts(buf); -} - -el_val_t dharma_field(el_val_t event_type) { - const char* et = EL_CSTR(event_type); - if (!et) et = "(null)"; - char buf[512]; - snprintf(buf, sizeof(buf), "[dharma] field: %s", et); - puts(buf); - return el_map_new(0); -} - -void dharma_strengthen(el_val_t cgi_id, el_val_t weight) { - const char* id = EL_CSTR(cgi_id); - if (!id) id = "(null)"; - /* weight is encoded as el_val_t; print as integer (float encoding TBD) */ - char buf[256]; - snprintf(buf, sizeof(buf), "[dharma] strengthen: %s +%lld", id, (long long)weight); - puts(buf); -} - -el_val_t dharma_relationship(el_val_t cgi_id) { - const char* id = EL_CSTR(cgi_id); - if (!id) id = "(null)"; - char buf[256]; - snprintf(buf, sizeof(buf), "[dharma] relationship: %s", id); - puts(buf); - return 0; /* 0.0 — no prior relationship in stub mode */ -} - -el_val_t dharma_peers(void) { - puts("[dharma] peers"); - return el_list_empty(); -} /* ── Batch 3: Engram in-process graph store ──────────────────────────────── */ /* @@ -2981,17 +2903,526 @@ el_val_t engram_stats_json(void) { return el_wrap_str(el_strdup(buf)); } +/* ── DHARMA network ───────────────────────────────────────────────────────── + * Real implementation. Peers are addressed by `dharma_id` — either bare + * (e.g. "ntn-genesis", transport defaults to http://localhost:7770) or + * "@" where is the peer's Engram-exposed daemon. + * + * Channels are logical handles cached per-cgi: `dharma_connect` is + * idempotent and returns "ch:". The channel registry below tracks + * every cgi_id we've connected to and its resolved transport URL. + * + * Relationship weights live in the local Engram graph: edges of type + * "dharma-relation" between a synthetic local node ("dharma:self") and + * synthetic peer nodes ("dharma:peer:"). Hebbian increments + * accumulate in EngramEdge.weight, clamped to [0.0, 1.0]. + * + * Events arrive over HTTP via the application's request handler, which is + * expected to call el_runtime_dharma_event_arrive() when it sees a + * /dharma/event POST. dharma_field() blocks on a per-event-type queue. + */ + +#define DHARMA_DEFAULT_URL "http://localhost:7770" + +/* Channel registry — one entry per known peer. */ +typedef struct DharmaChannel { + char* cgi_id; /* full dharma_id including any @ suffix */ + char* base_id; /* registry-id portion (before @) for relationship lookup */ + char* url; /* resolved transport URL */ + char* channel_id; /* "ch:" */ +} DharmaChannel; + +static DharmaChannel* _dharma_channels = NULL; +static size_t _dharma_channel_count = 0; +static size_t _dharma_channel_cap = 0; +static pthread_mutex_t _dharma_channel_mu = PTHREAD_MUTEX_INITIALIZER; + +/* Event queue — per-type linked list. dharma_field blocks on _dharma_event_cv. */ +typedef struct DharmaEvent { + char* event_type; + char* payload; + char* source; + int64_t timestamp; + struct DharmaEvent* next; +} DharmaEvent; + +static DharmaEvent* _dharma_event_head = NULL; +static DharmaEvent* _dharma_event_tail = NULL; +static pthread_mutex_t _dharma_event_mu = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t _dharma_event_cv = PTHREAD_COND_INITIALIZER; + +/* Split "@" → (base_id, url). If no "@", base_id = full, url = default. + * Returned strings are heap-allocated; caller must free. */ +static void dharma_parse_id(const char* full, char** out_base, char** out_url) { + if (!full) full = ""; + const char* at = strchr(full, '@'); + if (at) { + size_t bn = (size_t)(at - full); + char* b = malloc(bn + 1); + memcpy(b, full, bn); b[bn] = '\0'; + *out_base = b; + *out_url = el_strdup(at + 1); + if (!**out_url) { free(*out_url); *out_url = el_strdup(DHARMA_DEFAULT_URL); } + } else { + *out_base = el_strdup(full); + *out_url = el_strdup(DHARMA_DEFAULT_URL); + } +} + +/* Find existing channel by full cgi_id. Caller must hold _dharma_channel_mu. */ +static DharmaChannel* dharma_find_channel_locked(const char* cgi_id) { + if (!cgi_id) return NULL; + for (size_t i = 0; i < _dharma_channel_count; i++) { + if (_dharma_channels[i].cgi_id && + strcmp(_dharma_channels[i].cgi_id, cgi_id) == 0) { + return &_dharma_channels[i]; + } + } + return NULL; +} + +/* Add a new channel entry. Caller must hold _dharma_channel_mu. */ +static DharmaChannel* dharma_add_channel_locked(const char* cgi_id) { + if (_dharma_channel_count >= _dharma_channel_cap) { + size_t nc = _dharma_channel_cap ? _dharma_channel_cap * 2 : 8; + _dharma_channels = realloc(_dharma_channels, nc * sizeof(DharmaChannel)); + if (!_dharma_channels) { fputs("el_runtime: out of memory\n", stderr); exit(1); } + memset(_dharma_channels + _dharma_channel_cap, 0, + (nc - _dharma_channel_cap) * sizeof(DharmaChannel)); + _dharma_channel_cap = nc; + } + DharmaChannel* ch = &_dharma_channels[_dharma_channel_count++]; + char* base = NULL; char* url = NULL; + dharma_parse_id(cgi_id, &base, &url); + ch->cgi_id = el_strdup(cgi_id ? cgi_id : ""); + ch->base_id = base; + ch->url = url; + size_t cn = strlen(ch->cgi_id) + 4; + ch->channel_id = malloc(cn); + snprintf(ch->channel_id, cn, "ch:%s", ch->cgi_id); + return ch; +} + +el_val_t dharma_connect(el_val_t cgi_id) { + const char* id = EL_CSTR(cgi_id); + if (!id || !*id) return el_wrap_str(el_strdup("")); + pthread_mutex_lock(&_dharma_channel_mu); + DharmaChannel* ch = dharma_find_channel_locked(id); + if (!ch) ch = dharma_add_channel_locked(id); + char* out = el_strdup(ch->channel_id); + pthread_mutex_unlock(&_dharma_channel_mu); + return el_wrap_str(out); +} + +/* Build an error JSON body — same shape http_error_json uses. */ +static el_val_t dharma_error_json(const char* msg) { + return http_error_json(msg); +} + +el_val_t dharma_send(el_val_t channel, el_val_t content) { + const char* ch_id = EL_CSTR(channel); + const char* msg = EL_CSTR(content); + if (!ch_id || strncmp(ch_id, "ch:", 3) != 0) { + return dharma_error_json("invalid channel"); + } + const char* peer_id = ch_id + 3; + /* Look up channel; if unknown (caller fabricated), auto-register. */ + pthread_mutex_lock(&_dharma_channel_mu); + DharmaChannel* ch = dharma_find_channel_locked(peer_id); + if (!ch) ch = dharma_add_channel_locked(peer_id); + char* url = el_strdup(ch->url); + pthread_mutex_unlock(&_dharma_channel_mu); + /* Build /dharma/recv body. */ + const char* from = _el_cgi_dharma_id ? _el_cgi_dharma_id : "(unknown)"; + char* esc_ch = json_escape_alloc(ch_id); + char* esc_from = json_escape_alloc(from); + char* esc_msg = json_escape_alloc(msg ? msg : ""); + JsonBuf b; jb_init(&b); + jb_puts(&b, "{\"channel\":\""); jb_puts(&b, esc_ch); + jb_puts(&b, "\",\"from\":\""); jb_puts(&b, esc_from); + jb_puts(&b, "\",\"content\":\""); jb_puts(&b, esc_msg); + jb_puts(&b, "\"}"); + free(esc_ch); free(esc_from); free(esc_msg); + size_t ul = strlen(url) + 16; + char* full_url = malloc(ul); + snprintf(full_url, ul, "%s/dharma/recv", url); + struct curl_slist* h = NULL; + h = curl_slist_append(h, "Content-Type: application/json"); + el_val_t resp = http_do("POST", full_url, b.buf, h); + curl_slist_free_all(h); + free(b.buf); free(full_url); free(url); + return resp; +} + +el_val_t dharma_activate(el_val_t query) { + const char* q = EL_CSTR(query); + if (!q) q = ""; + el_val_t out = el_list_empty(); + char* esc_q = json_escape_alloc(q); + JsonBuf body; jb_init(&body); + jb_puts(&body, "{\"query\":\""); jb_puts(&body, esc_q); jb_puts(&body, "\"}"); + free(esc_q); + + /* Snapshot the channel list under lock so we can iterate without + * holding the mutex during network I/O. */ + pthread_mutex_lock(&_dharma_channel_mu); + size_t n = _dharma_channel_count; + char** urls = calloc(n ? n : 1, sizeof(char*)); + char** ids = calloc(n ? n : 1, sizeof(char*)); + char** bases = calloc(n ? n : 1, sizeof(char*)); + for (size_t i = 0; i < n; i++) { + urls[i] = el_strdup(_dharma_channels[i].url); + ids[i] = el_strdup(_dharma_channels[i].cgi_id); + bases[i] = el_strdup(_dharma_channels[i].base_id); + } + pthread_mutex_unlock(&_dharma_channel_mu); + + for (size_t i = 0; i < n; i++) { + size_t ul = strlen(urls[i]) + 32; + char* full_url = malloc(ul); + snprintf(full_url, ul, "%s/api/activate", urls[i]); + struct curl_slist* h = NULL; + h = curl_slist_append(h, "Content-Type: application/json"); + el_val_t resp = http_do("POST", full_url, body.buf, h); + curl_slist_free_all(h); + free(full_url); + const char* rs = EL_CSTR(resp); + if (!rs || !*rs) continue; + if (rs[0] == '{' && strstr(rs, "\"error\"")) continue; + + /* Look up relationship weight (attenuation). */ + double rel_weight = 1.0; + { + const char* self_id = "dharma:self"; + char peer_node[512]; + snprintf(peer_node, sizeof(peer_node), "dharma:peer:%s", bases[i]); + EngramStore* g = engram_get(); + for (int64_t k = 0; k < g->edge_count; k++) { + EngramEdge* e = &g->edges[k]; + if (e->from_id && e->to_id && + strcmp(e->from_id, self_id) == 0 && + strcmp(e->to_id, peer_node) == 0 && + e->relation && strcmp(e->relation, "dharma-relation") == 0) { + rel_weight = e->weight; + break; + } + } + } + + /* Iterate the response array. Expect either a top-level array + * or an object whose "results" field is an array. */ + const char* arr = rs; + while (*arr == ' ' || *arr == '\t' || *arr == '\n' || *arr == '\r') arr++; + char* arr_owned = NULL; + if (*arr == '{') { + el_val_t r = json_get_raw(EL_STR(rs), EL_STR("results")); + const char* rr = EL_CSTR(r); + if (rr && *rr == '[') { + arr_owned = el_strdup(rr); + arr = arr_owned; + } else { + continue; + } + } + if (*arr != '[') { free(arr_owned); continue; } + const char* p = arr + 1; + while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') p++; + while (*p && *p != ']') { + const char* end = json_skip_value(p); + size_t en = (size_t)(end - p); + char* obj = el_strbuf(en); + memcpy(obj, p, en); obj[en] = '\0'; + + /* Pull activation_strength if present, else 1.0. */ + el_val_t act_v = json_get_float(EL_STR(obj), EL_STR("activation_strength")); + double act = el_to_float(act_v); + if (!(act > 0.0 && act <= 100.0)) act = 1.0; + double final_act = act * rel_weight; + + el_val_t entry = el_map_new(0); + /* node = the inner JSON if present, else the entire obj. */ + el_val_t node_raw = json_get_raw(EL_STR(obj), EL_STR("node")); + const char* nr = EL_CSTR(node_raw); + entry = el_map_set(entry, EL_STR(el_strdup("node")), + (nr && *nr) ? node_raw : EL_STR(el_strdup(obj))); + entry = el_map_set(entry, EL_STR(el_strdup("source_cgi")), + EL_STR(el_strdup(ids[i]))); + entry = el_map_set(entry, EL_STR(el_strdup("activation_strength")), + el_from_float(final_act)); + out = el_list_append(out, entry); + free(obj); + p = end; + while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r' || *p == ',') p++; + } + free(arr_owned); + } + for (size_t i = 0; i < n; i++) { free(urls[i]); free(ids[i]); free(bases[i]); } + free(urls); free(ids); free(bases); + free(body.buf); + return out; +} + +void dharma_emit(el_val_t event_type, el_val_t payload) { + const char* et = EL_CSTR(event_type); + const char* pay = EL_CSTR(payload); + if (!et) et = ""; + if (!pay) pay = ""; + const char* src = _el_cgi_dharma_id ? _el_cgi_dharma_id : "(unknown)"; + int64_t ts = engram_now_ms(); + + char* esc_et = json_escape_alloc(et); + char* esc_pay = json_escape_alloc(pay); + char* esc_src = json_escape_alloc(src); + JsonBuf b; jb_init(&b); + jb_puts(&b, "{\"type\":\""); jb_puts(&b, esc_et); + jb_puts(&b, "\",\"payload\":\""); jb_puts(&b, esc_pay); + jb_puts(&b, "\",\"source\":\""); jb_puts(&b, esc_src); + jb_puts(&b, "\",\"timestamp\":"); jb_emit_int(&b, ts); + jb_putc(&b, '}'); + free(esc_et); free(esc_pay); free(esc_src); + + /* Snapshot URLs to avoid holding the channel mutex during I/O. */ + pthread_mutex_lock(&_dharma_channel_mu); + size_t n = _dharma_channel_count; + char** urls = calloc(n ? n : 1, sizeof(char*)); + for (size_t i = 0; i < n; i++) urls[i] = el_strdup(_dharma_channels[i].url); + pthread_mutex_unlock(&_dharma_channel_mu); + + for (size_t i = 0; i < n; i++) { + size_t ul = strlen(urls[i]) + 32; + char* full_url = malloc(ul); + snprintf(full_url, ul, "%s/dharma/event", urls[i]); + struct curl_slist* h = NULL; + h = curl_slist_append(h, "Content-Type: application/json"); + el_val_t r = http_do("POST", full_url, b.buf, h); + (void)r; /* fire-and-forget — emit is not synchronous */ + curl_slist_free_all(h); + free(full_url); + } + for (size_t i = 0; i < n; i++) free(urls[i]); + free(urls); + free(b.buf); +} + +void el_runtime_dharma_event_arrive(const char* event_type, const char* payload, + const char* source) { + DharmaEvent* ev = calloc(1, sizeof(DharmaEvent)); + if (!ev) return; + ev->event_type = el_strdup(event_type ? event_type : ""); + ev->payload = el_strdup(payload ? payload : ""); + ev->source = el_strdup(source ? source : ""); + ev->timestamp = engram_now_ms(); + ev->next = NULL; + pthread_mutex_lock(&_dharma_event_mu); + if (_dharma_event_tail) _dharma_event_tail->next = ev; + else _dharma_event_head = ev; + _dharma_event_tail = ev; + pthread_cond_broadcast(&_dharma_event_cv); + pthread_mutex_unlock(&_dharma_event_mu); +} + +el_val_t dharma_field(el_val_t event_type) { + const char* et = EL_CSTR(event_type); + if (!et) et = ""; + + /* Compute deadline: now + 30 seconds. */ + struct timespec deadline; + clock_gettime(CLOCK_REALTIME, &deadline); + deadline.tv_sec += 30; + + DharmaEvent* found = NULL; + pthread_mutex_lock(&_dharma_event_mu); + while (1) { + /* Scan queue for matching type; pop and return first match. */ + DharmaEvent* prev = NULL; + DharmaEvent* cur = _dharma_event_head; + while (cur) { + if (cur->event_type && strcmp(cur->event_type, et) == 0) { + if (prev) prev->next = cur->next; + else _dharma_event_head = cur->next; + if (_dharma_event_tail == cur) _dharma_event_tail = prev; + cur->next = NULL; + found = cur; + break; + } + prev = cur; cur = cur->next; + } + if (found) break; + int rc = pthread_cond_timedwait(&_dharma_event_cv, &_dharma_event_mu, &deadline); + if (rc == ETIMEDOUT) break; + } + pthread_mutex_unlock(&_dharma_event_mu); + + if (!found) return el_map_new(0); + el_val_t m = el_map_new(0); + m = el_map_set(m, EL_STR(el_strdup("type")), + EL_STR(el_strdup(found->event_type ? found->event_type : ""))); + m = el_map_set(m, EL_STR(el_strdup("payload")), + EL_STR(el_strdup(found->payload ? found->payload : ""))); + m = el_map_set(m, EL_STR(el_strdup("source_cgi")), + EL_STR(el_strdup(found->source ? found->source : ""))); + m = el_map_set(m, EL_STR(el_strdup("timestamp")), (el_val_t)found->timestamp); + free(found->event_type); free(found->payload); free(found->source); free(found); + return m; +} + +/* Locate (or create) the local "dharma:self" node and the synthetic peer + * node "dharma:peer:". Returns the index of the dharma-relation + * edge, or -1 if not found. If `create` is non-zero, ensure the nodes + * and edge exist (creating them as needed) and return the edge index. */ +static int64_t dharma_find_or_create_relation_edge(const char* peer_base, int create) { + if (!peer_base || !*peer_base) return -1; + EngramStore* g = engram_get(); + const char* self_id = "dharma:self"; + char peer_node[512]; + snprintf(peer_node, sizeof(peer_node), "dharma:peer:%s", peer_base); + + /* Look for the edge first. */ + for (int64_t i = 0; i < g->edge_count; i++) { + EngramEdge* e = &g->edges[i]; + if (e->from_id && e->to_id && + strcmp(e->from_id, self_id) == 0 && + strcmp(e->to_id, peer_node) == 0 && + e->relation && strcmp(e->relation, "dharma-relation") == 0) { + return i; + } + } + if (!create) return -1; + + /* Ensure self node exists. We use a fixed id (not engram_new_id) so + * subsequent calls reuse the same one. */ + if (!engram_find_node(self_id)) { + engram_grow_nodes(); + EngramNode* n = &g->nodes[g->node_count]; + memset(n, 0, sizeof(*n)); + n->id = el_strdup(self_id); + n->content = el_strdup(_el_cgi_dharma_id ? _el_cgi_dharma_id : "(self)"); + n->node_type = el_strdup("DharmaSelf"); + n->label = el_strdup("dharma:self"); + n->tier = el_strdup("Working"); + n->tags = el_strdup("dharma"); + n->metadata = el_strdup("{}"); + n->salience = 1.0; n->importance = 1.0; n->confidence = 1.0; + int64_t now = engram_now_ms(); + n->created_at = now; n->updated_at = now; n->last_activated = now; + g->node_count++; + } + if (!engram_find_node(peer_node)) { + engram_grow_nodes(); + EngramNode* n = &g->nodes[g->node_count]; + memset(n, 0, sizeof(*n)); + n->id = el_strdup(peer_node); + n->content = el_strdup(peer_base); + n->node_type = el_strdup("DharmaPeer"); + n->label = el_strdup(peer_node); + n->tier = el_strdup("Working"); + n->tags = el_strdup("dharma"); + n->metadata = el_strdup("{}"); + n->salience = 0.5; n->importance = 0.5; n->confidence = 1.0; + int64_t now = engram_now_ms(); + n->created_at = now; n->updated_at = now; n->last_activated = now; + g->node_count++; + } + /* Create the edge with weight 0.0 — caller will increment. */ + engram_grow_edges(); + EngramEdge* e = &g->edges[g->edge_count]; + memset(e, 0, sizeof(*e)); + e->id = engram_new_id(); + e->from_id = el_strdup(self_id); + e->to_id = el_strdup(peer_node); + e->relation = el_strdup("dharma-relation"); + e->metadata = el_strdup("{}"); + e->weight = 0.0; + e->confidence = 1.0; + int64_t now = engram_now_ms(); + e->created_at = now; e->updated_at = now; + int64_t idx = g->edge_count; + g->edge_count++; + return idx; +} + +void dharma_strengthen(el_val_t cgi_id, el_val_t weight) { + const char* id = EL_CSTR(cgi_id); + if (!id || !*id) return; + char* base = NULL; char* url = NULL; + dharma_parse_id(id, &base, &url); + free(url); + int64_t ei = dharma_find_or_create_relation_edge(base, 1); + free(base); + if (ei < 0) return; + EngramStore* g = engram_get(); + double inc = engram_decode_score(weight); + if (!(inc >= 0.0)) inc = 0.0; + double w = g->edges[ei].weight + inc; + if (w < 0.0) w = 0.0; + if (w > 1.0) w = 1.0; + g->edges[ei].weight = w; + g->edges[ei].updated_at = engram_now_ms(); + g->edges[ei].last_fired = g->edges[ei].updated_at; +} + +el_val_t dharma_relationship(el_val_t cgi_id) { + const char* id = EL_CSTR(cgi_id); + if (!id || !*id) return el_from_float(0.0); + char* base = NULL; char* url = NULL; + dharma_parse_id(id, &base, &url); + free(url); + int64_t ei = dharma_find_or_create_relation_edge(base, 0); + free(base); + if (ei < 0) return el_from_float(0.0); + EngramStore* g = engram_get(); + return el_from_float(g->edges[ei].weight); +} + +el_val_t dharma_peers(void) { + /* Walk dharma-relation edges out of "dharma:self", weight > 0, sort desc. */ + EngramStore* g = engram_get(); + const char* self_id = "dharma:self"; + typedef struct { char* peer_base; double weight; } PeerEntry; + PeerEntry* peers = malloc((size_t)(g->edge_count + 1) * sizeof(PeerEntry)); + int64_t pcount = 0; + if (!peers) return el_list_empty(); + for (int64_t i = 0; i < g->edge_count; i++) { + EngramEdge* e = &g->edges[i]; + if (!e->from_id || !e->to_id) continue; + if (strcmp(e->from_id, self_id) != 0) continue; + if (!e->relation || strcmp(e->relation, "dharma-relation") != 0) continue; + if (e->weight <= 0.0) continue; + const char* prefix = "dharma:peer:"; + size_t pl = strlen(prefix); + if (strncmp(e->to_id, prefix, pl) != 0) continue; + peers[pcount].peer_base = el_strdup(e->to_id + pl); + peers[pcount].weight = e->weight; + pcount++; + } + /* Sort desc by weight. */ + for (int64_t i = 1; i < pcount; i++) { + PeerEntry key = peers[i]; + int64_t j = i - 1; + while (j >= 0 && peers[j].weight < key.weight) { + peers[j + 1] = peers[j]; j--; + } + peers[j + 1] = key; + } + el_val_t out = el_list_empty(); + for (int64_t i = 0; i < pcount; i++) { + out = el_list_append(out, EL_STR(peers[i].peer_base)); + } + free(peers); + return out; +} + /* ── Batch 4: LLM (Anthropic API client) ─────────────────────────────────── */ /* * All LLM builtins call https://api.anthropic.com/v1/messages with the API * key from env ANTHROPIC_API_KEY. Default model is "claude-sonnet-4-5" * when the supplied model is empty/null. * - * `llm_call_agentic` is currently implemented as a single-turn fallback - * delegating to `llm_call_system` — TODO: implement the full multi-turn - * tool_use / tool_result loop. Programs that need agentic tool dispatch - * should register a tool handler via state_set("tools/", json) and - * loop themselves until the model emits stop_reason=end_turn. + * `llm_call_agentic` runs a real multi-turn tool_use/tool_result loop. + * Tool handlers are registered with `llm_register_tool(name, fn_name)`, + * which dlsym()s the named symbol. Each tool handler has the C signature + * el_val_t handler(el_val_t input_json); + * and returns a JSON-string el_val_t result. Iteration is capped at 10. */ static const char* LLM_DEFAULT_MODEL = "claude-sonnet-4-5"; @@ -3121,12 +3552,351 @@ el_val_t llm_call_system(el_val_t model, el_val_t system_prompt, el_val_t user_p return llm_extract_text(resp); } +/* ── Tool registry for llm_call_agentic ─────────────────────────────────── */ + +typedef el_val_t (*llm_tool_fn)(el_val_t input); + +typedef struct LlmToolEntry { + char* name; + llm_tool_fn fn; +} LlmToolEntry; + +static LlmToolEntry _llm_tools[64]; +static size_t _llm_tool_count = 0; +static pthread_mutex_t _llm_tool_mu = PTHREAD_MUTEX_INITIALIZER; + +static llm_tool_fn llm_tool_lookup(const char* name) { + if (!name) return NULL; + llm_tool_fn fn = NULL; + pthread_mutex_lock(&_llm_tool_mu); + for (size_t i = 0; i < _llm_tool_count; i++) { + if (strcmp(_llm_tools[i].name, name) == 0) { fn = _llm_tools[i].fn; break; } + } + pthread_mutex_unlock(&_llm_tool_mu); + return fn; +} + +void llm_register_tool(el_val_t name, el_val_t handler_fn_name) { + const char* nm = EL_CSTR(name); + const char* sym = EL_CSTR(handler_fn_name); + if (!nm || !*nm || !sym || !*sym) return; + void* p = dlsym(RTLD_DEFAULT, sym); + if (!p) { + fprintf(stderr, "[llm_register_tool] symbol not found: %s\n", sym); + return; + } + pthread_mutex_lock(&_llm_tool_mu); + /* Replace existing entry by name. */ + for (size_t i = 0; i < _llm_tool_count; i++) { + if (strcmp(_llm_tools[i].name, nm) == 0) { + _llm_tools[i].fn = (llm_tool_fn)p; + pthread_mutex_unlock(&_llm_tool_mu); + return; + } + } + if (_llm_tool_count < sizeof(_llm_tools) / sizeof(_llm_tools[0])) { + _llm_tools[_llm_tool_count].name = el_strdup(nm); + _llm_tools[_llm_tool_count].fn = (llm_tool_fn)p; + _llm_tool_count++; + } + pthread_mutex_unlock(&_llm_tool_mu); +} + +/* Serialize the El `tools` list into the JSON `tools:[...]` field expected + * by the Anthropic API. Each tool is an ElMap with name/description/ + * input_schema. input_schema is treated as either a JSON-object string + * (passed through verbatim) or a missing field (substitute {}). */ +static void llm_emit_tools_json(JsonBuf* b, el_val_t tools_list) { + jb_putc(b, '['); + ElList* lst = (ElList*)(uintptr_t)tools_list; + int64_t n = lst ? lst->length : 0; + for (int64_t i = 0; i < n; i++) { + if (i > 0) jb_putc(b, ','); + ElMap* tm = as_map(lst->elems[i]); + const char* name = ""; + const char* desc = ""; + const char* schema = "{}"; + if (tm) { + for (int64_t k = 0; k < tm->count; k++) { + const char* key = EL_CSTR(tm->keys[k]); + const char* val = EL_CSTR(tm->values[k]); + if (!key || !val) continue; + if (strcmp(key, "name") == 0) name = val; + else if (strcmp(key, "description") == 0) desc = val; + else if (strcmp(key, "input_schema") == 0) schema = val; + } + } + char* esc_name = json_escape_alloc(name); + char* esc_desc = json_escape_alloc(desc); + jb_puts(b, "{\"name\":\""); jb_puts(b, esc_name); + jb_puts(b, "\",\"description\":\""); jb_puts(b, esc_desc); + jb_puts(b, "\",\"input_schema\":"); jb_puts(b, schema && *schema ? schema : "{}"); + jb_putc(b, '}'); + free(esc_name); free(esc_desc); + } + jb_putc(b, ']'); +} + +/* Walk the assistant `content` array and emit each block back into b, + * preserving the verbatim JSON of every block — used to re-include the + * assistant turn in the next request. */ +static void llm_emit_content_blocks(JsonBuf* b, const char* resp) { + const char* p = json_find_key(resp, "content"); + jb_putc(b, '['); + if (!p) { jb_putc(b, ']'); return; } + while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') p++; + if (*p != '[') { jb_putc(b, ']'); return; } + p++; + int first = 1; + while (*p && *p != ']') { + while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r' || *p == ',') p++; + if (*p != '{') break; + const char* end = json_skip_value(p); + if (!first) jb_putc(b, ','); + first = 0; + size_t n = (size_t)(end - p); + jb_reserve(b, n); + memcpy(b->buf + b->len, p, n); + b->len += n; + b->buf[b->len] = '\0'; + p = end; + } + jb_putc(b, ']'); +} + +/* Concatenate all "text" blocks from a response. Returns owned string. */ +static char* llm_concat_text_blocks(const char* resp) { + JsonBuf out; jb_init(&out); + if (!resp) return out.buf; + const char* p = json_find_key(resp, "content"); + if (!p) return out.buf; + while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') p++; + if (*p != '[') return out.buf; + p++; + while (*p && *p != ']') { + while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r' || *p == ',') p++; + if (*p != '{') break; + const char* end = json_skip_value(p); + size_t n = (size_t)(end - p); + char* obj = malloc(n + 1); + memcpy(obj, p, n); obj[n] = '\0'; + const char* tp = json_find_key(obj, "type"); + if (tp && *tp == '"') { + JsonParser jp = { .p = tp, .end = tp + strlen(tp), .err = 0 }; + char* tname = jp_parse_string_raw(&jp); + if (!jp.err && tname && strcmp(tname, "text") == 0) { + const char* xp = json_find_key(obj, "text"); + if (xp && *xp == '"') { + JsonParser jp2 = { .p = xp, .end = xp + strlen(xp), .err = 0 }; + char* txt = jp_parse_string_raw(&jp2); + if (!jp2.err && txt) jb_puts(&out, txt); + free(txt); + } + } + free(tname); + } + free(obj); + p = end; + } + return out.buf; +} + +/* Build tool_result message blocks for every tool_use in a response. + * Appends to `b` an array element for each tool_use; caller wraps. */ +static int llm_build_tool_results(JsonBuf* b, const char* resp) { + int any = 0; + const char* p = json_find_key(resp, "content"); + if (!p) return 0; + while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r') p++; + if (*p != '[') return 0; + p++; + while (*p && *p != ']') { + while (*p == ' ' || *p == '\t' || *p == '\n' || *p == '\r' || *p == ',') p++; + if (*p != '{') break; + const char* end = json_skip_value(p); + size_t n = (size_t)(end - p); + char* obj = malloc(n + 1); + memcpy(obj, p, n); obj[n] = '\0'; + + const char* tp = json_find_key(obj, "type"); + char* type_s = NULL; + if (tp && *tp == '"') { + JsonParser jp = { .p = tp, .end = tp + strlen(tp), .err = 0 }; + type_s = jp_parse_string_raw(&jp); + } + if (type_s && strcmp(type_s, "tool_use") == 0) { + /* Extract id, name, input. */ + char* id_s = NULL; char* name_s = NULL; + const char* idp = json_find_key(obj, "id"); + if (idp && *idp == '"') { + JsonParser jp = { .p = idp, .end = idp + strlen(idp), .err = 0 }; + id_s = jp_parse_string_raw(&jp); + } + const char* np = json_find_key(obj, "name"); + if (np && *np == '"') { + JsonParser jp = { .p = np, .end = np + strlen(np), .err = 0 }; + name_s = jp_parse_string_raw(&jp); + } + el_val_t input_raw = json_get_raw(EL_STR(obj), EL_STR("input")); + const char* input_s = EL_CSTR(input_raw); + if (!input_s || !*input_s) input_s = "{}"; + + llm_tool_fn fn = llm_tool_lookup(name_s ? name_s : ""); + char* result = NULL; + int is_error = 0; + if (!fn) { + size_t en = strlen(name_s ? name_s : "(null)") + 64; + result = malloc(en); + snprintf(result, en, "{\"error\":\"tool not registered: %s\"}", + name_s ? name_s : "(null)"); + is_error = 1; + } else { + el_val_t out = fn(EL_STR(input_s)); + const char* os = EL_CSTR(out); + result = el_strdup(os ? os : ""); + } + + if (any) jb_putc(b, ','); + char* esc_id = json_escape_alloc(id_s ? id_s : ""); + char* esc_res = json_escape_alloc(result ? result : ""); + jb_puts(b, "{\"type\":\"tool_result\",\"tool_use_id\":\""); + jb_puts(b, esc_id); + jb_puts(b, "\",\"content\":\""); + jb_puts(b, esc_res); + jb_puts(b, "\""); + if (is_error) jb_puts(b, ",\"is_error\":true"); + jb_putc(b, '}'); + free(esc_id); free(esc_res); free(result); + free(id_s); free(name_s); + any = 1; + } + free(type_s); + free(obj); + p = end; + } + return any; +} + el_val_t llm_call_agentic(el_val_t model, el_val_t system, el_val_t user, el_val_t tools) { - /* TODO: full multi-turn tool_use / tool_result loop. For now we delegate - * to llm_call_system and ignore the tools list — programs needing real - * agentic dispatch should drive the loop themselves with raw http_post. */ - (void)tools; - return llm_call_system(model, system, user); + /* Empty tools list → degrade to plain system call. */ + ElList* tl = (ElList*)(uintptr_t)tools; + if (!tl || tl->length == 0) { + return llm_call_system(model, system, user); + } + const char* m = llm_resolve_model(EL_CSTR(model)); + const char* sys_p = EL_CSTR(system); if (!sys_p) sys_p = ""; + const char* usr_p = EL_CSTR(user); if (!usr_p) usr_p = ""; + + /* Build the static parts: tools JSON and system prompt — these don't + * change across iterations. */ + JsonBuf tools_buf; jb_init(&tools_buf); + llm_emit_tools_json(&tools_buf, tools); + char* esc_sys = json_escape_alloc(sys_p); + + /* messages array, accumulated as a mutable JSON fragment (no surrounding + * brackets — emitted at request time). */ + JsonBuf msgs; jb_init(&msgs); + /* First user message. */ + char* esc_user = json_escape_alloc(usr_p); + jb_puts(&msgs, "{\"role\":\"user\",\"content\":\""); + jb_puts(&msgs, esc_user); + jb_puts(&msgs, "\"}"); + free(esc_user); + + char* last_text = el_strdup(""); + el_val_t final_out = 0; + int reached_cap = 1; + + for (int iter = 0; iter < 10; iter++) { + /* Build request body. */ + JsonBuf body; jb_init(&body); + jb_putc(&body, '{'); + jb_puts(&body, "\"model\":"); jb_emit_escaped(&body, m); + jb_puts(&body, ",\"max_tokens\":4096"); + if (*sys_p) { + jb_puts(&body, ",\"system\":\""); + jb_puts(&body, esc_sys); + jb_puts(&body, "\""); + } + jb_puts(&body, ",\"tools\":"); + jb_puts(&body, tools_buf.buf); + jb_puts(&body, ",\"messages\":["); + jb_puts(&body, msgs.buf); + jb_puts(&body, "]}"); + + el_val_t resp_v = llm_request(body.buf); + free(body.buf); + const char* resp = EL_CSTR(resp_v); + if (!resp || !*resp) { + final_out = http_error_json("empty response"); + reached_cap = 0; + break; + } + if (resp[0] == '{' && strstr(resp, "\"error\"") && + !json_find_key(resp, "content")) { + final_out = el_wrap_str(el_strdup(resp)); + reached_cap = 0; + break; + } + + /* Update last_text from this response. */ + free(last_text); + last_text = llm_concat_text_blocks(resp); + + /* Inspect stop_reason. */ + el_val_t sr_v = json_get_string(EL_STR(resp), EL_STR("stop_reason")); + const char* sr = EL_CSTR(sr_v); if (!sr) sr = ""; + + if (strcmp(sr, "end_turn") == 0) { + final_out = el_wrap_str(el_strdup(last_text)); + reached_cap = 0; + break; + } + if (strcmp(sr, "max_tokens") == 0) { + size_t ln = strlen(last_text) + 16; + char* out = malloc(ln); + snprintf(out, ln, "%s\n[truncated]", last_text); + final_out = el_wrap_str(out); + reached_cap = 0; + break; + } + if (strcmp(sr, "tool_use") != 0) { + /* Unexpected stop reason; return the text we have. */ + final_out = el_wrap_str(el_strdup(last_text)); + reached_cap = 0; + break; + } + + /* Append the assistant turn (raw content blocks) to messages. */ + JsonBuf ab; jb_init(&ab); + jb_puts(&ab, ",{\"role\":\"assistant\",\"content\":"); + llm_emit_content_blocks(&ab, resp); + jb_putc(&ab, '}'); + jb_puts(&msgs, ab.buf); + free(ab.buf); + + /* Build tool_result message. */ + JsonBuf tr; jb_init(&tr); + jb_puts(&tr, ",{\"role\":\"user\",\"content\":["); + int any = llm_build_tool_results(&tr, resp); + jb_puts(&tr, "]}"); + if (any) { + jb_puts(&msgs, tr.buf); + } + free(tr.buf); + } + + if (reached_cap) { + size_t ln = strlen(last_text) + 32; + char* out = malloc(ln); + snprintf(out, ln, "[loop_cap_reached]\n%s", last_text); + final_out = el_wrap_str(out); + } + free(last_text); + free(esc_sys); + free(tools_buf.buf); + free(msgs.buf); + return final_out; } /* base64-encode arbitrary bytes (returns owned C string). */ diff --git a/el-compiler/runtime/el_runtime.h b/el-compiler/runtime/el_runtime.h index c471cef..da4d968 100644 --- a/el-compiler/runtime/el_runtime.h +++ b/el-compiler/runtime/el_runtime.h @@ -219,8 +219,22 @@ void el_cgi_init(el_val_t name, el_val_t dharma_id, el_val_t principal, /* ── DHARMA network builtins ───────────────────────────────────────────────── * Available to CGI programs (declared with a `cgi {}` block). - * Stubs print descriptive output and return empty/zero values. - * Full implementations are linked from the DHARMA runtime at deploy time. */ + * + * Peers are addressed by `dharma_id` of the form + * "@" e.g. "ntn-genesis@http://localhost:7770" + * If the @ portion is omitted, transport defaults to + * "http://localhost:7770" (the local CGI daemon assumption). + * + * Wire protocol (all peers expose): + * POST /dharma/recv { channel, from, content } → response body + * POST /dharma/event { type, payload, source, timestamp } + * POST /api/activate { query } → list of nodes + * + * Hosting application's responsibility: an El program with a `cgi {}` block + * runs http_serve() with its own request handler; that handler should route + * "/dharma/event" requests by calling el_runtime_dharma_event_arrive() so + * incoming events feed dharma_field() queues. The runtime itself does not + * intercept any /dharma path. */ el_val_t dharma_connect(el_val_t cgi_id); el_val_t dharma_send(el_val_t channel, el_val_t content); @@ -231,6 +245,14 @@ void dharma_strengthen(el_val_t cgi_id, el_val_t weight); el_val_t dharma_relationship(el_val_t cgi_id); el_val_t dharma_peers(void); +/* Public C API: called by an El program's HTTP handler when a /dharma/event + * request arrives. Pushes onto the per-event-type queue and signals any + * pending dharma_field() blockers. All three arguments must be NUL-terminated + * C strings (or NULL — then treated as empty). */ +void el_runtime_dharma_event_arrive(const char* event_type, + const char* payload, + const char* source); + /* ── Engram local graph primitives ─────────────────────────────────────────── * Operate on the CGI's local Engram knowledge graph. * `engram_activate` queries the local graph only; `dharma_activate` is @@ -275,6 +297,14 @@ el_val_t llm_call_agentic(el_val_t model, el_val_t system, el_val_t user, el_va el_val_t llm_vision(el_val_t model, el_val_t system, el_val_t prompt, el_val_t image_url_or_b64); el_val_t llm_models(void); +/* Register a tool handler by name. The handler is looked up via dlsym + * (mirroring http_set_handler), so any El `fn (input)` compiles to + * a global C symbol that this function can locate at runtime. + * Handler signature: `el_val_t handler(el_val_t input_json)` — receives + * the tool input as a JSON-string el_val_t and returns a JSON-string + * el_val_t result. Used by llm_call_agentic. */ +void llm_register_tool(el_val_t name, el_val_t handler_fn_name); + /* ── args() ───────────────────────────────────────────────────────────────── * Provides access to command-line arguments passed to the program. * Populated by el_runtime_init_args() before main() runs. */ diff --git a/el-compiler/src/codegen.el b/el-compiler/src/codegen.el index a31eaf5..69886fe 100644 --- a/el-compiler/src/codegen.el +++ b/el-compiler/src/codegen.el @@ -433,9 +433,82 @@ fn cg_expr(expr: Map) -> String { return "/* if-expr */ ((" + cond_c + ") ? (el_val_t)1 : (el_val_t)0)" } + if kind == "Match" { + return cg_match(expr) + } + "EL_NULL" } +// ── Match codegen ───────────────────────────────────────────────────────────── +// +// Lower a match expression to a GCC/Clang statement-expression. +// A unique label suffix is allocated per match via state_set("__match_counter"). + +fn next_match_id() -> String { + let csv: String = state_get("__match_counter") + let n = 0 + if !str_eq(csv, "") { + let n = str_to_int(csv) + } + let n = n + 1 + state_set("__match_counter", native_int_to_str(n)) + native_int_to_str(n) +} + +fn cg_match(expr: Map) -> String { + let subject = expr["subject"] + let arms = expr["arms"] + let subj_c: String = cg_expr(subject) + let id: String = next_match_id() + let subj_var: String = "_match_subj_" + id + let result_var: String = "_match_result_" + id + let done_label: String = "_match_done_" + id + let out: String = "({ el_val_t " + subj_var + " = " + subj_c + "; el_val_t " + result_var + " = 0; " + let n: Int = native_list_len(arms) + let i = 0 + while i < n { + let arm = native_list_get(arms, i) + let pat = arm["pattern"] + let body = arm["body"] + let pkind: String = pat["pattern"] + let body_c: String = cg_expr(body) + if str_eq(pkind, "Wildcard") { + let out = out + "{ " + result_var + " = (" + body_c + "); goto " + done_label + "; } " + } else { + if str_eq(pkind, "Binding") { + let bname: String = pat["name"] + let out = out + "{ el_val_t " + bname + " = " + subj_var + "; " + result_var + " = (" + body_c + "); goto " + done_label + "; } " + } else { + if str_eq(pkind, "LitInt") { + let v: String = pat["value"] + let out = out + "if (" + subj_var + " == " + v + ") { " + result_var + " = (" + body_c + "); goto " + done_label + "; } " + } else { + if str_eq(pkind, "LitStr") { + let v: String = pat["value"] + let out = out + "if (str_eq(" + subj_var + ", EL_STR(" + c_str_lit(v) + "))) { " + result_var + " = (" + body_c + "); goto " + done_label + "; } " + } else { + if str_eq(pkind, "LitBool") { + let v: String = pat["value"] + let bv = "0" + if str_eq(v, "true") { + let bv = "1" + } + let out = out + "if (" + subj_var + " == " + bv + ") { " + result_var + " = (" + body_c + "); goto " + done_label + "; } " + } else { + // unknown pattern → wildcard + let out = out + "{ " + result_var + " = (" + body_c + "); goto " + done_label + "; } " + } + } + } + } + } + let i = i + 1 + } + let out = out + done_label + ":; " + result_var + "; })" + out +} + // ── Variable scope tracking ─────────────────────────────────────────────────── // // El allows `let x = expr` to both declare and reassign x in the same scope. @@ -538,6 +611,7 @@ fn cg_stmt(stmt: Map, indent: String, declared: [String]) -> [Strin if kind == "TypeDef" { return declared } if kind == "EnumDef" { return declared } if kind == "Import" { return declared } + if kind == "CgiBlock" { return declared } declared } @@ -767,6 +841,15 @@ fn cg_fn(stmt: Map) -> Void { let body = stmt["body"] let ret_type: String = stmt["ret_type"] let params_c: String = params_to_c(params) + // VBD role enforcement: dharma_emit / dharma_field may only be called + // from @manager-decorated functions. Surface violations to the C compiler + // via #error directives emitted before the function definition. + let decorator: String = stmt["decorator"] + if vbd_has_restricted_call(body) { + if !str_eq(decorator, "manager") { + emit_line("#error \"VBD violation: dharma_emit/dharma_field called from non-@manager fn '" + fn_name + "'\"") + } + } // Seed the per-function int-name set so the `+` codegen can dispatch // arithmetic vs concat on type-annotated identifiers. build_int_names_for_params(params) @@ -808,12 +891,174 @@ fn is_top_level_decl(stmt: Map) -> Bool { if kind == "TypeDef" { return true } if kind == "EnumDef" { return true } if kind == "Import" { return true } + if kind == "CgiBlock" { return true } + false +} + +// Format a string-or-EL_NULL argument for el_cgi_init. +fn cgi_arg(value: String, has_value: Bool) -> String { + if has_value { + return "EL_STR(" + c_str_lit(value) + ")" + } + return "EL_NULL" +} + +// ── VBD role enforcement ────────────────────────────────────────────────────── +// +// Scan a function body for direct calls to DHARMA-restricted builtins +// (dharma_emit, dharma_field). These may only appear inside @manager fns. + +fn vbd_is_restricted_name(name: String) -> Bool { + if str_eq(name, "dharma_emit") { return true } + if str_eq(name, "dharma_field") { return true } + false +} + +fn vbd_expr_has_restricted_call(expr: Map) -> Bool { + let kind: String = expr["expr"] + if str_eq(kind, "Call") { + let func = expr["func"] + let fk: String = func["expr"] + if str_eq(fk, "Ident") { + let fname: String = func["name"] + if vbd_is_restricted_name(fname) { return true } + } + if vbd_expr_has_restricted_call(func) { return true } + let args = expr["args"] + let an: Int = native_list_len(args) + let ai = 0 + while ai < an { + let a = native_list_get(args, ai) + if vbd_expr_has_restricted_call(a) { return true } + let ai = ai + 1 + } + return false + } + if str_eq(kind, "BinOp") { + let l = expr["left"] + let r = expr["right"] + if vbd_expr_has_restricted_call(l) { return true } + if vbd_expr_has_restricted_call(r) { return true } + return false + } + if str_eq(kind, "Not") { + return vbd_expr_has_restricted_call(expr["inner"]) + } + if str_eq(kind, "Neg") { + return vbd_expr_has_restricted_call(expr["inner"]) + } + if str_eq(kind, "Field") { + return vbd_expr_has_restricted_call(expr["object"]) + } + if str_eq(kind, "Index") { + if vbd_expr_has_restricted_call(expr["object"]) { return true } + if vbd_expr_has_restricted_call(expr["index"]) { return true } + return false + } + if str_eq(kind, "Try") { + return vbd_expr_has_restricted_call(expr["inner"]) + } + if str_eq(kind, "Array") { + let elems = expr["elems"] + let n: Int = native_list_len(elems) + let i = 0 + while i < n { + let e = native_list_get(elems, i) + if vbd_expr_has_restricted_call(e) { return true } + let i = i + 1 + } + return false + } + if str_eq(kind, "Map") { + let pairs = expr["pairs"] + let n: Int = native_list_len(pairs) + let i = 0 + while i < n { + let pair = native_list_get(pairs, i) + let v = pair["value"] + if vbd_expr_has_restricted_call(v) { return true } + let i = i + 1 + } + return false + } + if str_eq(kind, "If") { + if vbd_expr_has_restricted_call(expr["cond"]) { return true } + if vbd_has_restricted_call(expr["then"]) { return true } + if vbd_has_restricted_call(expr["else"]) { return true } + return false + } + if str_eq(kind, "For") { + if vbd_expr_has_restricted_call(expr["list"]) { return true } + if vbd_has_restricted_call(expr["body"]) { return true } + return false + } + if str_eq(kind, "Match") { + if vbd_expr_has_restricted_call(expr["subject"]) { return true } + let arms = expr["arms"] + let n: Int = native_list_len(arms) + let i = 0 + while i < n { + let arm = native_list_get(arms, i) + let body = arm["body"] + if vbd_expr_has_restricted_call(body) { return true } + let i = i + 1 + } + return false + } + false +} + +fn vbd_has_restricted_call(stmts: [Map]) -> Bool { + let n: Int = native_list_len(stmts) + let i = 0 + while i < n { + let s = native_list_get(stmts, i) + let sk: String = s["stmt"] + if str_eq(sk, "Let") { + if vbd_expr_has_restricted_call(s["value"]) { return true } + } + if str_eq(sk, "Return") { + if vbd_expr_has_restricted_call(s["value"]) { return true } + } + if str_eq(sk, "Expr") { + if vbd_expr_has_restricted_call(s["value"]) { return true } + } + if str_eq(sk, "While") { + if vbd_expr_has_restricted_call(s["cond"]) { return true } + if vbd_has_restricted_call(s["body"]) { return true } + } + if str_eq(sk, "For") { + if vbd_expr_has_restricted_call(s["list"]) { return true } + if vbd_has_restricted_call(s["body"]) { return true } + } + let i = i + 1 + } false } // ── Entry point ──────────────────────────────────────────────────────────────── fn codegen(stmts: [Map], source: String) -> String { + // Detect cgi blocks: at most one allowed. Emit a #error if more than one. + let n_top: Int = native_list_len(stmts) + let cgi_count = 0 + let cgi_block: Map = { "stmt": "None" } + let ti = 0 + while ti < n_top { + let s = native_list_get(stmts, ti) + let sk: String = s["stmt"] + if str_eq(sk, "CgiBlock") { + let cgi_count = cgi_count + 1 + if cgi_count == 1 { + let cgi_block = s + } + } + let ti = ti + 1 + } + if cgi_count > 1 { + emit_line("#error \"El: multiple cgi blocks in program (only one allowed)\"") + } + // Preamble emit_line("#include ") emit_line("#include ") @@ -851,6 +1096,23 @@ fn codegen(stmts: [Map], source: String) -> String { // main() emit_line("int main(int argc, char** argv) {") emit_line(" el_runtime_init_args(argc, argv);") + if cgi_count >= 1 { + let cname: String = cgi_block["name"] + let cdid: String = cgi_block["dharma_id"] + let cprin: String = cgi_block["principal"] + let cnet: String = cgi_block["network"] + let ceng: String = cgi_block["engram"] + let has_did: Bool = cgi_block["has_dharma_id"] + let has_prin: Bool = cgi_block["has_principal"] + let has_net: Bool = cgi_block["has_network"] + let has_eng: Bool = cgi_block["has_engram"] + let arg_name: String = "EL_STR(" + c_str_lit(cname) + ")" + let arg_did: String = cgi_arg(cdid, has_did) + let arg_prin: String = cgi_arg(cprin, has_prin) + let arg_net: String = cgi_arg(cnet, has_net) + let arg_eng: String = cgi_arg(ceng, has_eng) + emit_line(" el_cgi_init(" + arg_name + ", " + arg_did + ", " + arg_prin + ", " + arg_net + ", " + arg_eng + ");") + } let main_decl = native_list_empty() let i = 0 while i < n { diff --git a/el-compiler/src/parser.el b/el-compiler/src/parser.el index d1339a8..d194392 100644 --- a/el-compiler/src/parser.el +++ b/el-compiler/src/parser.el @@ -736,12 +736,93 @@ fn parse_stmt(tokens: [Map], pos: Int) -> Map { return make_result({ "stmt": "For", "item": item_name, "list": list_expr, "body": body }, p) } - // @decorator — skip and parse next stmt + // @decorator — capture decorator name and attach to following stmt if k == "At" { let p = pos + 1 - // skip decorator name + let dec_name = tok_value(tokens, p) let p = p + 1 - return parse_stmt(tokens, p) + let r = parse_stmt(tokens, p) + let inner = r["node"] + let p2 = r["pos"] + let inner_kind: String = inner["stmt"] + if str_eq(inner_kind, "FnDef") { + let with_dec = { + "stmt": "FnDef", + "name": inner["name"], + "params": inner["params"], + "body": inner["body"], + "ret_type": inner["ret_type"], + "decorator": dec_name + } + return make_result(with_dec, p2) + } + return r + } + + // cgi block: cgi "name" { field: "val", ... } + if k == "Cgi" { + let p = pos + 1 + let name = tok_value(tokens, p) + let p = p + 1 + let p = expect(tokens, p, "LBrace") + let dharma_id = "" + let principal = "" + let network = "" + let engram = "" + let has_dharma_id = false + let has_principal = false + let has_network = false + let has_engram = false + let running = true + while running { + let k2 = tok_kind(tokens, p) + if k2 == "RBrace" { + let running = false + } else { + if k2 == "Eof" { + let running = false + } else { + let fname = tok_value(tokens, p) + let p = p + 1 + let p = expect(tokens, p, "Colon") + let fval = tok_value(tokens, p) + let p = p + 1 + if str_eq(fname, "dharma_id") { + let dharma_id = fval + let has_dharma_id = true + } + if str_eq(fname, "principal") { + let principal = fval + let has_principal = true + } + if str_eq(fname, "network") { + let network = fval + let has_network = true + } + if str_eq(fname, "engram") { + let engram = fval + let has_engram = true + } + let k3 = tok_kind(tokens, p) + if k3 == "Comma" { + let p = p + 1 + } + } + } + } + let p = expect(tokens, p, "RBrace") + return make_result({ + "stmt": "CgiBlock", + "name": name, + "dharma_id": dharma_id, + "principal": principal, + "network": network, + "engram": engram, + "has_dharma_id": has_dharma_id, + "has_principal": has_principal, + "has_network": has_network, + "has_engram": has_engram + }, p) } // bare expression or if/match statement diff --git a/elc-combined.el b/elc-combined.el index 90a46b8..7886ad6 100644 --- a/elc-combined.el +++ b/elc-combined.el @@ -1272,12 +1272,93 @@ fn parse_stmt(tokens: [Map], pos: Int) -> Map { return make_result({ "stmt": "For", "item": item_name, "list": list_expr, "body": body }, p) } - // @decorator — skip and parse next stmt + // @decorator — capture decorator name and attach to following stmt if k == "At" { let p = pos + 1 - // skip decorator name + let dec_name = tok_value(tokens, p) let p = p + 1 - return parse_stmt(tokens, p) + let r = parse_stmt(tokens, p) + let inner = r["node"] + let p2 = r["pos"] + let inner_kind: String = inner["stmt"] + if str_eq(inner_kind, "FnDef") { + let with_dec = { + "stmt": "FnDef", + "name": inner["name"], + "params": inner["params"], + "body": inner["body"], + "ret_type": inner["ret_type"], + "decorator": dec_name + } + return make_result(with_dec, p2) + } + return r + } + + // cgi block: cgi "name" { field: "val", ... } + if k == "Cgi" { + let p = pos + 1 + let name = tok_value(tokens, p) + let p = p + 1 + let p = expect(tokens, p, "LBrace") + let dharma_id = "" + let principal = "" + let network = "" + let engram = "" + let has_dharma_id = false + let has_principal = false + let has_network = false + let has_engram = false + let running = true + while running { + let k2 = tok_kind(tokens, p) + if k2 == "RBrace" { + let running = false + } else { + if k2 == "Eof" { + let running = false + } else { + let fname = tok_value(tokens, p) + let p = p + 1 + let p = expect(tokens, p, "Colon") + let fval = tok_value(tokens, p) + let p = p + 1 + if str_eq(fname, "dharma_id") { + let dharma_id = fval + let has_dharma_id = true + } + if str_eq(fname, "principal") { + let principal = fval + let has_principal = true + } + if str_eq(fname, "network") { + let network = fval + let has_network = true + } + if str_eq(fname, "engram") { + let engram = fval + let has_engram = true + } + let k3 = tok_kind(tokens, p) + if k3 == "Comma" { + let p = p + 1 + } + } + } + } + let p = expect(tokens, p, "RBrace") + return make_result({ + "stmt": "CgiBlock", + "name": name, + "dharma_id": dharma_id, + "principal": principal, + "network": network, + "engram": engram, + "has_dharma_id": has_dharma_id, + "has_principal": has_principal, + "has_network": has_network, + "has_engram": has_engram + }, p) } // bare expression or if/match statement @@ -1752,9 +1833,82 @@ fn cg_expr(expr: Map) -> String { return "/* if-expr */ ((" + cond_c + ") ? (el_val_t)1 : (el_val_t)0)" } + if kind == "Match" { + return cg_match(expr) + } + "EL_NULL" } +// ── Match codegen ───────────────────────────────────────────────────────────── +// +// Lower a match expression to a GCC/Clang statement-expression. +// A unique label suffix is allocated per match via state_set("__match_counter"). + +fn next_match_id() -> String { + let csv: String = state_get("__match_counter") + let n = 0 + if !str_eq(csv, "") { + let n = str_to_int(csv) + } + let n = n + 1 + state_set("__match_counter", native_int_to_str(n)) + native_int_to_str(n) +} + +fn cg_match(expr: Map) -> String { + let subject = expr["subject"] + let arms = expr["arms"] + let subj_c: String = cg_expr(subject) + let id: String = next_match_id() + let subj_var: String = "_match_subj_" + id + let result_var: String = "_match_result_" + id + let done_label: String = "_match_done_" + id + let out: String = "({ el_val_t " + subj_var + " = " + subj_c + "; el_val_t " + result_var + " = 0; " + let n: Int = native_list_len(arms) + let i = 0 + while i < n { + let arm = native_list_get(arms, i) + let pat = arm["pattern"] + let body = arm["body"] + let pkind: String = pat["pattern"] + let body_c: String = cg_expr(body) + if str_eq(pkind, "Wildcard") { + let out = out + "{ " + result_var + " = (" + body_c + "); goto " + done_label + "; } " + } else { + if str_eq(pkind, "Binding") { + let bname: String = pat["name"] + let out = out + "{ el_val_t " + bname + " = " + subj_var + "; " + result_var + " = (" + body_c + "); goto " + done_label + "; } " + } else { + if str_eq(pkind, "LitInt") { + let v: String = pat["value"] + let out = out + "if (" + subj_var + " == " + v + ") { " + result_var + " = (" + body_c + "); goto " + done_label + "; } " + } else { + if str_eq(pkind, "LitStr") { + let v: String = pat["value"] + let out = out + "if (str_eq(" + subj_var + ", EL_STR(" + c_str_lit(v) + "))) { " + result_var + " = (" + body_c + "); goto " + done_label + "; } " + } else { + if str_eq(pkind, "LitBool") { + let v: String = pat["value"] + let bv = "0" + if str_eq(v, "true") { + let bv = "1" + } + let out = out + "if (" + subj_var + " == " + bv + ") { " + result_var + " = (" + body_c + "); goto " + done_label + "; } " + } else { + // unknown pattern → wildcard + let out = out + "{ " + result_var + " = (" + body_c + "); goto " + done_label + "; } " + } + } + } + } + } + let i = i + 1 + } + let out = out + done_label + ":; " + result_var + "; })" + out +} + // ── Variable scope tracking ─────────────────────────────────────────────────── // // El allows `let x = expr` to both declare and reassign x in the same scope. @@ -1857,6 +2011,7 @@ fn cg_stmt(stmt: Map, indent: String, declared: [String]) -> [Strin if kind == "TypeDef" { return declared } if kind == "EnumDef" { return declared } if kind == "Import" { return declared } + if kind == "CgiBlock" { return declared } declared } @@ -2086,6 +2241,15 @@ fn cg_fn(stmt: Map) -> Void { let body = stmt["body"] let ret_type: String = stmt["ret_type"] let params_c: String = params_to_c(params) + // VBD role enforcement: dharma_emit / dharma_field may only be called + // from @manager-decorated functions. Surface violations to the C compiler + // via #error directives emitted before the function definition. + let decorator: String = stmt["decorator"] + if vbd_has_restricted_call(body) { + if !str_eq(decorator, "manager") { + emit_line("#error \"VBD violation: dharma_emit/dharma_field called from non-@manager fn '" + fn_name + "'\"") + } + } // Seed the per-function int-name set so the `+` codegen can dispatch // arithmetic vs concat on type-annotated identifiers. build_int_names_for_params(params) @@ -2127,12 +2291,174 @@ fn is_top_level_decl(stmt: Map) -> Bool { if kind == "TypeDef" { return true } if kind == "EnumDef" { return true } if kind == "Import" { return true } + if kind == "CgiBlock" { return true } + false +} + +// Format a string-or-EL_NULL argument for el_cgi_init. +fn cgi_arg(value: String, has_value: Bool) -> String { + if has_value { + return "EL_STR(" + c_str_lit(value) + ")" + } + return "EL_NULL" +} + +// ── VBD role enforcement ────────────────────────────────────────────────────── +// +// Scan a function body for direct calls to DHARMA-restricted builtins +// (dharma_emit, dharma_field). These may only appear inside @manager fns. + +fn vbd_is_restricted_name(name: String) -> Bool { + if str_eq(name, "dharma_emit") { return true } + if str_eq(name, "dharma_field") { return true } + false +} + +fn vbd_expr_has_restricted_call(expr: Map) -> Bool { + let kind: String = expr["expr"] + if str_eq(kind, "Call") { + let func = expr["func"] + let fk: String = func["expr"] + if str_eq(fk, "Ident") { + let fname: String = func["name"] + if vbd_is_restricted_name(fname) { return true } + } + if vbd_expr_has_restricted_call(func) { return true } + let args = expr["args"] + let an: Int = native_list_len(args) + let ai = 0 + while ai < an { + let a = native_list_get(args, ai) + if vbd_expr_has_restricted_call(a) { return true } + let ai = ai + 1 + } + return false + } + if str_eq(kind, "BinOp") { + let l = expr["left"] + let r = expr["right"] + if vbd_expr_has_restricted_call(l) { return true } + if vbd_expr_has_restricted_call(r) { return true } + return false + } + if str_eq(kind, "Not") { + return vbd_expr_has_restricted_call(expr["inner"]) + } + if str_eq(kind, "Neg") { + return vbd_expr_has_restricted_call(expr["inner"]) + } + if str_eq(kind, "Field") { + return vbd_expr_has_restricted_call(expr["object"]) + } + if str_eq(kind, "Index") { + if vbd_expr_has_restricted_call(expr["object"]) { return true } + if vbd_expr_has_restricted_call(expr["index"]) { return true } + return false + } + if str_eq(kind, "Try") { + return vbd_expr_has_restricted_call(expr["inner"]) + } + if str_eq(kind, "Array") { + let elems = expr["elems"] + let n: Int = native_list_len(elems) + let i = 0 + while i < n { + let e = native_list_get(elems, i) + if vbd_expr_has_restricted_call(e) { return true } + let i = i + 1 + } + return false + } + if str_eq(kind, "Map") { + let pairs = expr["pairs"] + let n: Int = native_list_len(pairs) + let i = 0 + while i < n { + let pair = native_list_get(pairs, i) + let v = pair["value"] + if vbd_expr_has_restricted_call(v) { return true } + let i = i + 1 + } + return false + } + if str_eq(kind, "If") { + if vbd_expr_has_restricted_call(expr["cond"]) { return true } + if vbd_has_restricted_call(expr["then"]) { return true } + if vbd_has_restricted_call(expr["else"]) { return true } + return false + } + if str_eq(kind, "For") { + if vbd_expr_has_restricted_call(expr["list"]) { return true } + if vbd_has_restricted_call(expr["body"]) { return true } + return false + } + if str_eq(kind, "Match") { + if vbd_expr_has_restricted_call(expr["subject"]) { return true } + let arms = expr["arms"] + let n: Int = native_list_len(arms) + let i = 0 + while i < n { + let arm = native_list_get(arms, i) + let body = arm["body"] + if vbd_expr_has_restricted_call(body) { return true } + let i = i + 1 + } + return false + } + false +} + +fn vbd_has_restricted_call(stmts: [Map]) -> Bool { + let n: Int = native_list_len(stmts) + let i = 0 + while i < n { + let s = native_list_get(stmts, i) + let sk: String = s["stmt"] + if str_eq(sk, "Let") { + if vbd_expr_has_restricted_call(s["value"]) { return true } + } + if str_eq(sk, "Return") { + if vbd_expr_has_restricted_call(s["value"]) { return true } + } + if str_eq(sk, "Expr") { + if vbd_expr_has_restricted_call(s["value"]) { return true } + } + if str_eq(sk, "While") { + if vbd_expr_has_restricted_call(s["cond"]) { return true } + if vbd_has_restricted_call(s["body"]) { return true } + } + if str_eq(sk, "For") { + if vbd_expr_has_restricted_call(s["list"]) { return true } + if vbd_has_restricted_call(s["body"]) { return true } + } + let i = i + 1 + } false } // ── Entry point ──────────────────────────────────────────────────────────────── fn codegen(stmts: [Map], source: String) -> String { + // Detect cgi blocks: at most one allowed. Emit a #error if more than one. + let n_top: Int = native_list_len(stmts) + let cgi_count = 0 + let cgi_block: Map = { "stmt": "None" } + let ti = 0 + while ti < n_top { + let s = native_list_get(stmts, ti) + let sk: String = s["stmt"] + if str_eq(sk, "CgiBlock") { + let cgi_count = cgi_count + 1 + if cgi_count == 1 { + let cgi_block = s + } + } + let ti = ti + 1 + } + if cgi_count > 1 { + emit_line("#error \"El: multiple cgi blocks in program (only one allowed)\"") + } + // Preamble emit_line("#include ") emit_line("#include ") @@ -2170,6 +2496,23 @@ fn codegen(stmts: [Map], source: String) -> String { // main() emit_line("int main(int argc, char** argv) {") emit_line(" el_runtime_init_args(argc, argv);") + if cgi_count >= 1 { + let cname: String = cgi_block["name"] + let cdid: String = cgi_block["dharma_id"] + let cprin: String = cgi_block["principal"] + let cnet: String = cgi_block["network"] + let ceng: String = cgi_block["engram"] + let has_did: Bool = cgi_block["has_dharma_id"] + let has_prin: Bool = cgi_block["has_principal"] + let has_net: Bool = cgi_block["has_network"] + let has_eng: Bool = cgi_block["has_engram"] + let arg_name: String = "EL_STR(" + c_str_lit(cname) + ")" + let arg_did: String = cgi_arg(cdid, has_did) + let arg_prin: String = cgi_arg(cprin, has_prin) + let arg_net: String = cgi_arg(cnet, has_net) + let arg_eng: String = cgi_arg(ceng, has_eng) + emit_line(" el_cgi_init(" + arg_name + ", " + arg_did + ", " + arg_prin + ", " + arg_net + ", " + arg_eng + ");") + } let main_decl = native_list_empty() let i = 0 while i < n {