fix: add __-prefixed runtime primitives for El compiler #21
@@ -11221,6 +11221,159 @@ el_val_t hash_sha256(el_val_t sv) {
|
||||
return el_hex_encode(digest, 32);
|
||||
}
|
||||
|
||||
/* ── __ prefixed aliases — public boundary for compiled El programs ──────────
|
||||
*
|
||||
* The El compiler's self-hosting back-end emits calls to __-prefixed function
|
||||
* names (e.g. __println, __str_len). These wrappers forward to the existing
|
||||
* el_runtime implementations so both naming conventions resolve at link time.
|
||||
*
|
||||
* Note: __thread_create and __thread_join are already defined above in the
|
||||
* threading section; they are not repeated here.
|
||||
* ──────────────────────────────────────────────────────────────────────────── */
|
||||
|
||||
/* I/O */
|
||||
el_val_t __println(el_val_t s) { return println(s); }
|
||||
el_val_t __print(el_val_t s) { return print(s); }
|
||||
el_val_t __readline(void) { return readline(); }
|
||||
|
||||
/* String */
|
||||
el_val_t __int_to_str(el_val_t n) { return int_to_str(n); }
|
||||
el_val_t __str_to_int(el_val_t s) { return str_to_int(s); }
|
||||
el_val_t __float_to_str(el_val_t f) { return float_to_str(f); }
|
||||
el_val_t __str_to_float(el_val_t s) { return str_to_float(s); }
|
||||
el_val_t __str_len(el_val_t s) { return str_len(s); }
|
||||
el_val_t __str_char_at(el_val_t s, el_val_t i) { return str_char_at(s, i); }
|
||||
|
||||
el_val_t __str_cmp(el_val_t a, el_val_t b) {
|
||||
const char* ca = EL_CSTR(a);
|
||||
const char* cb = EL_CSTR(b);
|
||||
if (!ca) ca = "";
|
||||
if (!cb) cb = "";
|
||||
return (el_val_t)strcmp(ca, cb);
|
||||
}
|
||||
|
||||
el_val_t __str_ncmp(el_val_t a, el_val_t b, el_val_t n) {
|
||||
const char* ca = EL_CSTR(a);
|
||||
const char* cb = EL_CSTR(b);
|
||||
if (!ca) ca = "";
|
||||
if (!cb) cb = "";
|
||||
return (el_val_t)strncmp(ca, cb, (size_t)n);
|
||||
}
|
||||
|
||||
el_val_t __str_concat_raw(el_val_t a, el_val_t b) { return str_concat(a, b); }
|
||||
el_val_t __str_slice_raw(el_val_t s, el_val_t start, el_val_t end) { return str_slice(s, start, end); }
|
||||
|
||||
el_val_t __str_alloc(el_val_t n) {
|
||||
if (n <= 0) n = 0;
|
||||
char* buf = el_strbuf((size_t)n + 1);
|
||||
memset(buf, 0, (size_t)n + 1);
|
||||
return el_wrap_str(buf);
|
||||
}
|
||||
|
||||
el_val_t __str_set_char(el_val_t s, el_val_t i, el_val_t c) {
|
||||
char* buf = (char*)(uintptr_t)s;
|
||||
if (buf) buf[(size_t)i] = (char)c;
|
||||
return s;
|
||||
}
|
||||
|
||||
/* URL encoding */
|
||||
el_val_t __url_encode(el_val_t s) { return url_encode(s); }
|
||||
el_val_t __url_decode(el_val_t s) { return url_decode(s); }
|
||||
|
||||
/* Environment */
|
||||
el_val_t __env_get(el_val_t key) { return env(key); }
|
||||
|
||||
/* Subprocess */
|
||||
el_val_t __exec(el_val_t cmd) { return exec(cmd); }
|
||||
el_val_t __exec_bg(el_val_t cmd) { return exec_bg(cmd); }
|
||||
|
||||
/* Process */
|
||||
el_val_t __exit_program(el_val_t code) { return exit_program(code); }
|
||||
|
||||
/* Filesystem */
|
||||
el_val_t __fs_exists(el_val_t path) { return fs_exists(path); }
|
||||
el_val_t __fs_mkdir(el_val_t path) { return fs_mkdir(path); }
|
||||
el_val_t __fs_read(el_val_t path) { return fs_read(path); }
|
||||
el_val_t __fs_write(el_val_t path, el_val_t content) { return fs_write(path, content); }
|
||||
el_val_t __fs_write_bytes(el_val_t path, el_val_t bytes, el_val_t n) { return fs_write_bytes(path, bytes, n); }
|
||||
el_val_t __fs_list_raw(el_val_t path) { return fs_list_json(path); }
|
||||
|
||||
/* HTTP server (no curl dependency) */
|
||||
el_val_t __http_response(el_val_t status, el_val_t headers_json, el_val_t body) { return http_response(status, headers_json, body); }
|
||||
el_val_t __http_serve(el_val_t port, el_val_t handler) { return http_serve(port, handler); }
|
||||
el_val_t __http_serve_v2(el_val_t port, el_val_t handler) { return http_serve_v2(port, handler); }
|
||||
|
||||
/* HTTP conn fd / SSE — __http_conn_fd lives in el_seed.c; stubs provided here
|
||||
* so el_runtime.c compiles standalone. When both translation units are linked
|
||||
* the el_seed.c definitions win via their non-static linkage (strong symbols).
|
||||
* These stubs are marked weak so they are silently overridden. */
|
||||
__attribute__((weak)) el_val_t __http_conn_fd(void) { return (el_val_t)(-1); }
|
||||
__attribute__((weak)) el_val_t __http_sse_open(el_val_t conn_id) { (void)conn_id; return 0; }
|
||||
__attribute__((weak)) el_val_t __http_sse_send(el_val_t conn_id, el_val_t data) { (void)conn_id; (void)data; return 0; }
|
||||
__attribute__((weak)) el_val_t __http_sse_close(el_val_t conn_id) { (void)conn_id; return 0; }
|
||||
|
||||
/* JSON */
|
||||
el_val_t __json_array_get(el_val_t json, el_val_t index) { return json_array_get(json, index); }
|
||||
el_val_t __json_array_get_string(el_val_t json, el_val_t index) { return json_array_get_string(json, index); }
|
||||
el_val_t __json_array_len(el_val_t json) { return json_array_len(json); }
|
||||
el_val_t __json_get(el_val_t json, el_val_t key) { return json_get(json, key); }
|
||||
el_val_t __json_get_raw(el_val_t json, el_val_t key) { return json_get_raw(json, key); }
|
||||
el_val_t __json_set(el_val_t json, el_val_t key, el_val_t value){ return json_set(json, key, value); }
|
||||
el_val_t __json_parse_map(el_val_t json_str) { return json_parse(json_str); }
|
||||
el_val_t __json_stringify_val(el_val_t val) { return json_stringify(val); }
|
||||
|
||||
/* Hashing */
|
||||
el_val_t __sha256_hex(el_val_t s) { return hash_sha256(s); }
|
||||
|
||||
/* State K/V */
|
||||
el_val_t __state_del(el_val_t key) { return state_del(key); }
|
||||
el_val_t __state_get(el_val_t key) { return state_get(key); }
|
||||
el_val_t __state_keys(void) { return state_keys(); }
|
||||
el_val_t __state_set(el_val_t key, el_val_t val) { return state_set(key, val); }
|
||||
|
||||
/* UUID */
|
||||
el_val_t __uuid_v4(void) { return uuid_v4(); }
|
||||
|
||||
/* Args */
|
||||
el_val_t __args_json(void) { return args(); }
|
||||
|
||||
/* HTTP client aliases — require curl; defined inside #ifdef HAVE_CURL below
|
||||
* with a matching stub in the #ifndef HAVE_CURL block. */
|
||||
#ifdef HAVE_CURL
|
||||
el_val_t __http_do(el_val_t method, el_val_t url, el_val_t body,
|
||||
el_val_t headers_map, el_val_t timeout_ms) {
|
||||
/* timeout_ms is accepted for API compatibility but ignored here;
|
||||
* el_runtime's http_do uses the EL_HTTP_TIMEOUT_MS env var instead. */
|
||||
(void)timeout_ms;
|
||||
struct curl_slist* h = headers_from_map(headers_map);
|
||||
el_val_t r = http_do(EL_CSTR(method), EL_CSTR(url), EL_CSTR(body), h);
|
||||
if (h) curl_slist_free_all(h);
|
||||
return r;
|
||||
}
|
||||
|
||||
/* __http_do_map — same as __http_do but headers_map arg is a JSON-string
|
||||
* rather than an ElMap. Parse it first, then delegate. */
|
||||
el_val_t __http_do_map(el_val_t method, el_val_t url, el_val_t body,
|
||||
el_val_t headers_json, el_val_t timeout_ms) {
|
||||
(void)timeout_ms;
|
||||
/* Build a curl_slist from a JSON object {"Header":"value",...}. */
|
||||
const char* hj = EL_CSTR(headers_json);
|
||||
struct curl_slist* h = NULL;
|
||||
if (hj && *hj && *hj == '{') {
|
||||
/* Walk the JSON pairs with a simple parser reusing json_get_string logic. */
|
||||
/* For correctness we just call the existing json_get iteration path.
|
||||
* We duplicate the key-extraction loop from headers_from_map but driven
|
||||
* by JSON rather than ElMap. Use json_get_raw to iterate is not easy
|
||||
* without knowing keys, so accept the JSON string and build a tmp map. */
|
||||
el_val_t map = json_parse(EL_STR(hj));
|
||||
h = headers_from_map(map);
|
||||
}
|
||||
el_val_t r = http_do(EL_CSTR(method), EL_CSTR(url), EL_CSTR(body), h);
|
||||
if (h) curl_slist_free_all(h);
|
||||
return r;
|
||||
}
|
||||
#endif /* HAVE_CURL */
|
||||
|
||||
#ifndef HAVE_CURL
|
||||
/* ── HAVE_CURL=0 stubs — compile without -lcurl for the elc CLI binary. ───── *
|
||||
* These return a JSON error string so El programs get a clear message if they
|
||||
@@ -11247,4 +11400,7 @@ el_val_t llm_call_agentic(el_val_t m, el_val_t s, el_val_t u, el_val_t t) { (voi
|
||||
el_val_t llm_vision(el_val_t m, el_val_t s, el_val_t p, el_val_t i) { (void)m; (void)s; (void)p; (void)i; return _no_curl_err(); }
|
||||
el_val_t llm_models(void) { return el_list_empty(); }
|
||||
void llm_register_tool(el_val_t n, el_val_t f) { (void)n; (void)f; }
|
||||
/* __ HTTP stubs (no-curl build) */
|
||||
el_val_t __http_do(el_val_t m, el_val_t u, el_val_t b, el_val_t h, el_val_t t) { (void)m; (void)u; (void)b; (void)h; (void)t; return _no_curl_err(); }
|
||||
el_val_t __http_do_map(el_val_t m, el_val_t u, el_val_t b, el_val_t h, el_val_t t) { (void)m; (void)u; (void)b; (void)h; (void)t; return _no_curl_err(); }
|
||||
#endif /* !HAVE_CURL */
|
||||
|
||||
@@ -781,6 +781,93 @@ el_val_t emit_event(el_val_t name, el_val_t duration_ms);
|
||||
el_val_t __thread_create(el_val_t fn_name_v, el_val_t arg_v);
|
||||
el_val_t __thread_join(el_val_t tid_v);
|
||||
|
||||
/* ── __ prefixed aliases (self-hosting compiler ABI) ─────────────────────────
|
||||
* The El self-hosting compiler emits calls to __-prefixed names. These are
|
||||
* forwarding wrappers around the existing el_runtime functions above. */
|
||||
|
||||
/* I/O */
|
||||
el_val_t __println(el_val_t s);
|
||||
el_val_t __print(el_val_t s);
|
||||
el_val_t __readline(void);
|
||||
|
||||
/* String */
|
||||
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);
|
||||
el_val_t __str_to_float(el_val_t s);
|
||||
el_val_t __str_len(el_val_t s);
|
||||
el_val_t __str_char_at(el_val_t s, el_val_t i);
|
||||
el_val_t __str_cmp(el_val_t a, el_val_t b);
|
||||
el_val_t __str_ncmp(el_val_t a, el_val_t b, el_val_t n);
|
||||
el_val_t __str_concat_raw(el_val_t a, el_val_t b);
|
||||
el_val_t __str_slice_raw(el_val_t s, el_val_t start, el_val_t end);
|
||||
el_val_t __str_alloc(el_val_t n);
|
||||
el_val_t __str_set_char(el_val_t s, el_val_t i, el_val_t c);
|
||||
|
||||
/* URL encoding */
|
||||
el_val_t __url_encode(el_val_t s);
|
||||
el_val_t __url_decode(el_val_t s);
|
||||
|
||||
/* Environment */
|
||||
el_val_t __env_get(el_val_t key);
|
||||
|
||||
/* Subprocess */
|
||||
el_val_t __exec(el_val_t cmd);
|
||||
el_val_t __exec_bg(el_val_t cmd);
|
||||
|
||||
/* Process */
|
||||
el_val_t __exit_program(el_val_t code);
|
||||
|
||||
/* Filesystem */
|
||||
el_val_t __fs_exists(el_val_t path);
|
||||
el_val_t __fs_mkdir(el_val_t path);
|
||||
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_write_bytes(el_val_t path, el_val_t bytes, el_val_t n);
|
||||
el_val_t __fs_list_raw(el_val_t path);
|
||||
|
||||
/* HTTP server */
|
||||
el_val_t __http_response(el_val_t status, el_val_t headers_json, el_val_t body);
|
||||
el_val_t __http_serve(el_val_t port, el_val_t handler);
|
||||
el_val_t __http_serve_v2(el_val_t port, el_val_t handler);
|
||||
|
||||
/* HTTP conn fd / SSE (weak; overridden by el_seed.c when linked together) */
|
||||
el_val_t __http_conn_fd(void);
|
||||
el_val_t __http_sse_open(el_val_t conn_id);
|
||||
el_val_t __http_sse_send(el_val_t conn_id, el_val_t data);
|
||||
el_val_t __http_sse_close(el_val_t conn_id);
|
||||
|
||||
/* HTTP client (requires HAVE_CURL; stubs provided for no-curl builds) */
|
||||
el_val_t __http_do(el_val_t method, el_val_t url, el_val_t body,
|
||||
el_val_t headers_map, el_val_t timeout_ms);
|
||||
el_val_t __http_do_map(el_val_t method, el_val_t url, el_val_t body,
|
||||
el_val_t headers_json, el_val_t timeout_ms);
|
||||
|
||||
/* JSON */
|
||||
el_val_t __json_array_get(el_val_t json, el_val_t index);
|
||||
el_val_t __json_array_get_string(el_val_t json, el_val_t index);
|
||||
el_val_t __json_array_len(el_val_t json);
|
||||
el_val_t __json_get(el_val_t json, el_val_t key);
|
||||
el_val_t __json_get_raw(el_val_t json, el_val_t key);
|
||||
el_val_t __json_set(el_val_t json, el_val_t key, el_val_t value);
|
||||
el_val_t __json_parse_map(el_val_t json_str);
|
||||
el_val_t __json_stringify_val(el_val_t val);
|
||||
|
||||
/* Hashing */
|
||||
el_val_t __sha256_hex(el_val_t s);
|
||||
|
||||
/* State K/V */
|
||||
el_val_t __state_del(el_val_t key);
|
||||
el_val_t __state_get(el_val_t key);
|
||||
el_val_t __state_keys(void);
|
||||
el_val_t __state_set(el_val_t key, el_val_t val);
|
||||
|
||||
/* UUID */
|
||||
el_val_t __uuid_v4(void);
|
||||
|
||||
/* Args */
|
||||
el_val_t __args_json(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -990,6 +990,8 @@ el_val_t __json_get(el_val_t json, el_val_t key) { return j
|
||||
el_val_t __json_get_raw(el_val_t json_str, el_val_t key) { return json_get_raw(json_str, key); }
|
||||
el_val_t __json_parse(el_val_t s) { return json_parse(s); }
|
||||
el_val_t __json_stringify(el_val_t v) { return json_stringify(v); }
|
||||
el_val_t __json_parse_map(el_val_t json_str) { return json_parse(json_str); }
|
||||
el_val_t __json_stringify_val(el_val_t val) { return json_stringify(val); }
|
||||
el_val_t __json_array_len(el_val_t json_str) { return json_array_len(json_str); }
|
||||
el_val_t __json_array_get(el_val_t json_str, el_val_t index) { return json_array_get(json_str, index); }
|
||||
el_val_t __json_array_get_string(el_val_t json_str, el_val_t index) { return json_array_get_string(json_str, index); }
|
||||
|
||||
@@ -174,6 +174,8 @@ 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);
|
||||
|
||||
Reference in New Issue
Block a user