254cbe0ac2
El SDK CI - dev / build-and-test (pull_request) Successful in 3m22s
The El compiler generates calls to __-prefixed C primitives from within El stdlib compiled code (e.g. __println, __str_len, __json_get, etc). These were absent from el_runtime.c, causing linker failures when building el-install, elb, or epm with the current compiler. Add 46 __-prefixed aliases/implementations in el_runtime.c covering: - I/O: __println, __print, __readline - String: __str_len, __str_cmp, __str_ncmp, __str_alloc, __str_set_char, __str_concat_raw, __str_slice_raw, __str_char_at, plus numeric converters - FS: __fs_read, __fs_write, __fs_exists, __fs_mkdir, __fs_list_raw, etc - HTTP: __http_do, __http_do_map, __http_serve, __http_serve_v2, __http_response, __http_sse_* (weak stubs) - JSON: __json_get, __json_set, __json_parse_map, __json_stringify_val, etc - State, env, exec, uuid, sha256, args
251 lines
13 KiB
C
251 lines
13 KiB
C
/*
|
|
* el_seed.h — El language seed runtime header
|
|
*
|
|
* Declares all OS-boundary primitives available to compiled El programs.
|
|
* All functions use the __ prefix convention. Signatures use el_val_t (= int64_t)
|
|
* as the universal value type.
|
|
*
|
|
* el_seed.c is the complete C boundary for the El runtime. The heavy runtime
|
|
* (el_runtime.c) has been retired — everything lives in el_seed.c plus the
|
|
* native El runtime (runtime/ *.el files).
|
|
*
|
|
* Link requirements:
|
|
* -lcurl — HTTP client (__http_do, __http_do_to_file)
|
|
* -lpthread — threading (__thread_create, __thread_join, __mutex_new, ...)
|
|
*
|
|
* Canonical compile (via elb):
|
|
* elb builds and links el_seed.c automatically.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
|
|
/* ── Value model ─────────────────────────────────────────────────────────────
|
|
* All El values are el_val_t (int64_t). On 64-bit systems a pointer fits.
|
|
* String -> el_val_t (holds const char* via uintptr_t cast)
|
|
* Int -> el_val_t (stored directly)
|
|
* Bool -> el_val_t (0 = false, nonzero = true)
|
|
* Void -> void
|
|
*/
|
|
typedef int64_t el_val_t;
|
|
|
|
#define EL_STR(s) ((el_val_t)(uintptr_t)(s))
|
|
#define EL_CSTR(v) ((const char*)(uintptr_t)(v))
|
|
#define EL_INT(v) (v)
|
|
#define EL_NULL ((el_val_t)0)
|
|
|
|
/* Float values share the el_val_t slot via bit-cast. */
|
|
static inline double el_to_float(el_val_t v) {
|
|
union { int64_t i; double f; } u; u.i = (int64_t)v; return u.f;
|
|
}
|
|
static inline el_val_t el_from_float(double f) {
|
|
union { double f; int64_t i; } u; u.f = f; return (el_val_t)u.i;
|
|
}
|
|
|
|
#ifdef __cplusplus
|
|
extern "C" {
|
|
#endif
|
|
|
|
/* ── String primitives ───────────────────────────────────────────────────── */
|
|
|
|
el_val_t __str_len(el_val_t s);
|
|
el_val_t __str_char_at(el_val_t s, el_val_t i); /* returns Int (byte value) */
|
|
el_val_t __str_alloc(el_val_t n); /* malloc(n+1), zero-init, return String */
|
|
el_val_t __str_set_char(el_val_t s, el_val_t i, el_val_t c); /* s[i]=c, return s */
|
|
el_val_t __str_cmp(el_val_t a, el_val_t b); /* strcmp result as Int */
|
|
el_val_t __str_ncmp(el_val_t a, el_val_t b, el_val_t n); /* strncmp */
|
|
el_val_t __str_concat_raw(el_val_t a, el_val_t b); /* malloc+strcpy concat */
|
|
el_val_t __str_slice_raw(el_val_t s, el_val_t start, el_val_t end); /* substring copy */
|
|
el_val_t __int_to_str(el_val_t n);
|
|
el_val_t __str_to_int(el_val_t s);
|
|
el_val_t __float_to_str(el_val_t f); /* f is bit-cast double */
|
|
el_val_t __str_to_float(el_val_t s); /* strtod, bit-cast result */
|
|
|
|
/* ── I/O ─────────────────────────────────────────────────────────────────── */
|
|
|
|
void __println(el_val_t s);
|
|
void __print(el_val_t s);
|
|
el_val_t __readline(void);
|
|
|
|
/* ── Filesystem ──────────────────────────────────────────────────────────── */
|
|
|
|
el_val_t __fs_read(el_val_t path);
|
|
el_val_t __fs_write(el_val_t path, el_val_t content);
|
|
el_val_t __fs_exists(el_val_t path);
|
|
el_val_t __fs_list_raw(el_val_t path); /* newline-separated filenames */
|
|
el_val_t __fs_mkdir(el_val_t path);
|
|
el_val_t __fs_write_bytes(el_val_t path, el_val_t bytes, el_val_t n);
|
|
|
|
/* ── HTTP client ─────────────────────────────────────────────────────────── */
|
|
|
|
/* Unified HTTP call. headers_json is a JSON object of header name->value pairs
|
|
* (e.g. {"Authorization":"Bearer ...","Content-Type":"application/json"}).
|
|
* Use "" or "{}" for no extra headers. timeout_ms <= 0 uses the default. */
|
|
el_val_t __http_do(el_val_t method, el_val_t url, el_val_t body,
|
|
el_val_t headers_json, el_val_t timeout_ms);
|
|
|
|
/* Stream response body directly to a file. Returns 1 on success, 0 on failure. */
|
|
el_val_t __http_do_to_file(el_val_t method, el_val_t url, el_val_t body,
|
|
el_val_t headers_json, el_val_t out_path);
|
|
|
|
/* ── HTTP server ─────────────────────────────────────────────────────────── */
|
|
|
|
/* Blocking HTTP server. handler_name is the El function name to dispatch to.
|
|
* v1 handler: (method, path, body) -> String
|
|
* v2 handler: (method, path, headers_map, body) -> String or envelope */
|
|
void __http_serve(el_val_t port, el_val_t handler_name);
|
|
void __http_serve_v2(el_val_t port, el_val_t handler_name);
|
|
|
|
/* Build a structured HTTP response envelope.
|
|
* headers_json: JSON object literal like {"Content-Type":"text/plain"} or "{}" */
|
|
el_val_t __http_response(el_val_t status, el_val_t headers_json, el_val_t body);
|
|
|
|
/* ── HTTP SSE — Server-Sent Events streaming ─────────────────────────────── */
|
|
|
|
/* Returns the raw file descriptor for the current HTTP connection.
|
|
* Valid only inside an http_serve_v2 handler before it returns.
|
|
* Returns -1 if called outside a handler context. */
|
|
el_val_t __http_conn_fd(void);
|
|
|
|
/* Sends SSE response headers on conn_id (the fd from __http_conn_fd),
|
|
* keeping the connection open for streaming. Returns 1 on success, 0 on
|
|
* write failure. Call once at the start of an SSE handler. */
|
|
el_val_t __http_sse_open(el_val_t conn_id);
|
|
|
|
/* Writes one SSE event frame: "data: <data>\n\n". data must not contain
|
|
* newlines. Returns 1 on success, 0 if the client disconnected. */
|
|
el_val_t __http_sse_send(el_val_t conn_id, el_val_t data);
|
|
|
|
/* Closes the SSE connection. The handler must return http_sse_sentinel()
|
|
* so the HTTP worker does not double-close the fd. */
|
|
el_val_t __http_sse_close(el_val_t conn_id);
|
|
|
|
/* ── Threading ───────────────────────────────────────────────────────────── */
|
|
|
|
/* Create a thread that calls the named El function with a String argument.
|
|
* fn_name is resolved via dlsym(RTLD_DEFAULT, fn_name). Returns a thread
|
|
* handle Int that can be passed to __thread_join. Returns -1 on failure. */
|
|
el_val_t __thread_create(el_val_t fn_name, el_val_t arg);
|
|
|
|
/* Wait for thread tid (returned by __thread_create) to finish.
|
|
* Returns the thread's return value as a String. */
|
|
el_val_t __thread_join(el_val_t tid);
|
|
|
|
/* Allocate a new mutex. Returns a handle Int (index into internal table). */
|
|
el_val_t __mutex_new(void);
|
|
|
|
void __mutex_lock(el_val_t m);
|
|
void __mutex_unlock(el_val_t m);
|
|
|
|
/* ── Subprocess ──────────────────────────────────────────────────────────── */
|
|
|
|
el_val_t __exec(el_val_t cmd); /* popen, capture all stdout, return String */
|
|
void __exec_bg(el_val_t cmd); /* fire and forget */
|
|
|
|
/* ── Environment and process ─────────────────────────────────────────────── */
|
|
|
|
el_val_t __env_get(el_val_t key); /* getenv, return "" if not set */
|
|
void __exit_program(el_val_t code);
|
|
el_val_t __args_json(void); /* CLI args as JSON array string */
|
|
|
|
/* ── Time ────────────────────────────────────────────────────────────────── */
|
|
|
|
el_val_t __time_now_ns(void); /* clock_gettime REALTIME, nanoseconds */
|
|
void __sleep_ms(el_val_t ms);
|
|
|
|
/* ── UUID ────────────────────────────────────────────────────────────────── */
|
|
|
|
el_val_t __uuid_v4(void);
|
|
|
|
/* ── Math ────────────────────────────────────────────────────────────────── */
|
|
|
|
el_val_t __sqrt_f(el_val_t f);
|
|
el_val_t __log_f(el_val_t f);
|
|
el_val_t __ln_f(el_val_t f);
|
|
el_val_t __sin_f(el_val_t f);
|
|
el_val_t __cos_f(el_val_t f);
|
|
el_val_t __pi_f(void);
|
|
|
|
/* ── JSON ────────────────────────────────────────────────────────────────── */
|
|
|
|
el_val_t __json_get(el_val_t json, el_val_t key);
|
|
el_val_t __json_get_raw(el_val_t json_str, el_val_t key);
|
|
el_val_t __json_parse(el_val_t s);
|
|
el_val_t __json_stringify(el_val_t v);
|
|
el_val_t __json_parse_map(el_val_t json_str); /* alias for __json_parse */
|
|
el_val_t __json_stringify_val(el_val_t val); /* alias for __json_stringify */
|
|
el_val_t __json_array_len(el_val_t json_str);
|
|
el_val_t __json_array_get(el_val_t json_str, el_val_t index);
|
|
el_val_t __json_array_get_string(el_val_t json_str, el_val_t index);
|
|
el_val_t __json_get_string(el_val_t json_str, el_val_t key);
|
|
el_val_t __json_get_int(el_val_t json_str, el_val_t key);
|
|
el_val_t __json_get_float(el_val_t json_str, el_val_t key);
|
|
el_val_t __json_get_bool(el_val_t json_str, el_val_t key);
|
|
el_val_t __json_set(el_val_t json_str, el_val_t key, el_val_t value);
|
|
|
|
/* ── State K/V ───────────────────────────────────────────────────────────── */
|
|
|
|
el_val_t __state_set(el_val_t key, el_val_t value);
|
|
el_val_t __state_get(el_val_t key);
|
|
el_val_t __state_del(el_val_t key);
|
|
el_val_t __state_keys(void);
|
|
|
|
/* ── HTML/URL ────────────────────────────────────────────────────────────── */
|
|
|
|
el_val_t __html_sanitize(el_val_t input_html, el_val_t allowlist_json);
|
|
el_val_t __url_encode(el_val_t s);
|
|
el_val_t __url_decode(el_val_t s);
|
|
|
|
/* ── Engram ──────────────────────────────────────────────────────────────── */
|
|
|
|
el_val_t __engram_node(el_val_t content, el_val_t node_type, el_val_t salience);
|
|
el_val_t __engram_node_full(el_val_t content, el_val_t node_type, el_val_t label,
|
|
el_val_t salience, el_val_t importance, el_val_t confidence,
|
|
el_val_t tier, el_val_t tags);
|
|
el_val_t __engram_node_layered(el_val_t content, el_val_t node_type, el_val_t label,
|
|
el_val_t salience, el_val_t certainty, el_val_t confidence,
|
|
el_val_t status, el_val_t tags, el_val_t layer_id);
|
|
el_val_t __engram_add_layer(el_val_t name, el_val_t priority, el_val_t suppressible,
|
|
el_val_t transparent, el_val_t injectable);
|
|
el_val_t __engram_remove_layer(el_val_t layer_id);
|
|
el_val_t __engram_list_layers(void);
|
|
el_val_t __engram_get_node(el_val_t id);
|
|
void __engram_strengthen(el_val_t node_id);
|
|
void __engram_forget(el_val_t node_id);
|
|
el_val_t __engram_node_count(void);
|
|
el_val_t __engram_search(el_val_t query, el_val_t limit);
|
|
el_val_t __engram_scan_nodes(el_val_t limit, el_val_t offset);
|
|
void __engram_connect(el_val_t from_id, el_val_t to_id, el_val_t weight, el_val_t relation);
|
|
el_val_t __engram_edge_between(el_val_t from_id, el_val_t to_id);
|
|
el_val_t __engram_neighbors(el_val_t node_id);
|
|
el_val_t __engram_neighbors_filtered(el_val_t node_id, el_val_t max_depth, el_val_t direction);
|
|
el_val_t __engram_edge_count(void);
|
|
el_val_t __engram_activate(el_val_t query, el_val_t depth);
|
|
el_val_t __engram_save(el_val_t path);
|
|
el_val_t __engram_load(el_val_t path);
|
|
el_val_t __engram_get_node_json(el_val_t id);
|
|
el_val_t __engram_search_json(el_val_t query, el_val_t limit);
|
|
el_val_t __engram_scan_nodes_json(el_val_t limit, el_val_t offset);
|
|
el_val_t __engram_scan_nodes_by_type_json(el_val_t node_type, el_val_t limit, el_val_t offset);
|
|
el_val_t __engram_neighbors_json(el_val_t node_id, el_val_t max_depth, el_val_t direction);
|
|
el_val_t __engram_activate_json(el_val_t query, el_val_t depth);
|
|
el_val_t __engram_stats_json(void);
|
|
el_val_t __engram_list_layers_json(void);
|
|
el_val_t __engram_compile_layered_json(el_val_t intent, el_val_t depth);
|
|
|
|
/* ── Cryptographic hashing ────────────────────────────────────────────────── */
|
|
|
|
/* __sha256_hex — return the SHA-256 hex digest of a string.
|
|
* The returned string is 64 hex characters (lowercase). */
|
|
el_val_t __sha256_hex(el_val_t s);
|
|
|
|
/* ── args init (called from main) ────────────────────────────────────────── */
|
|
/* Store argc/argv for __args_json. Call once at the start of main(). */
|
|
void el_seed_init_args(int argc, char** argv);
|
|
|
|
#ifdef __cplusplus
|
|
}
|
|
#endif
|