Archived
d3495476f4
El SDK Release / build-and-release (push) Failing after 13m0s
The generated C, amalgams, vendored runtime pins, and compiled binaries from the Claude Code era are removed from the worktree. The El sources survive; this tree is now source-only for the first-principles rebuild. Per Principal direction 2026-08-19.
174 lines
7.8 KiB
Plaintext
174 lines
7.8 KiB
Plaintext
diff --git a/lang/el-compiler/src/codegen.el b/lang/el-compiler/src/codegen.el
|
|
index bd90b266..eaaa4def 100644
|
|
--- a/lang/el-compiler/src/codegen.el
|
|
+++ b/lang/el-compiler/src/codegen.el
|
|
@@ -3215,44 +3215,15 @@ fn cg_entry_seam(stmt: Map<String, Any>, fn_name: String) -> Void {
|
|
// cg_exit_target / cg_exit_construct — the first construct on this fn that
|
|
// injects at exit, or "" if none.
|
|
|
|
-fn cg_wrap_target(stmt: Map<String, Any>) -> String {
|
|
- let wdl = stmt["decorators"]
|
|
- let n_wdl: Int = native_list_len(wdl)
|
|
- let wi = 0
|
|
- let found: String = ""
|
|
- while wi < n_wdl {
|
|
- if str_eq(found, "") {
|
|
- let wd = native_list_get(wdl, wi)
|
|
- let wdn: String = wd["name"]
|
|
- let wt: String = decorator_wrap(wdn)
|
|
- if !str_eq(wt, "") { let found = wt }
|
|
- }
|
|
- let wi = wi + 1
|
|
- }
|
|
- found
|
|
-}
|
|
|
|
-fn cg_wrap_construct(stmt: Map<String, Any>) -> String {
|
|
- let wdl = stmt["decorators"]
|
|
- let n_wdl: Int = native_list_len(wdl)
|
|
- let wi = 0
|
|
- let found: String = ""
|
|
- while wi < n_wdl {
|
|
- if str_eq(found, "") {
|
|
- let wd = native_list_get(wdl, wi)
|
|
- let wdn: String = wd["name"]
|
|
- let wt: String = decorator_wrap(wdn)
|
|
- if !str_eq(wt, "") { let found = wdn }
|
|
- }
|
|
- let wi = wi + 1
|
|
- }
|
|
- found
|
|
-}
|
|
|
|
// params_to_env_fields / params_to_env_init / params_to_env_args — the captured
|
|
// environment. This IS the closure: a struct of captured values, a function
|
|
// pointer that takes it, and the pair handed to the wrap target.
|
|
fn params_to_env_fields(params: [Any]) -> String {
|
|
+ // A zero-param fn would emit `struct __env_f { };` -- an empty struct is a
|
|
+ // GNU extension, not C99, and an empty initialiser is C23.
|
|
+ if native_list_len(params) == 0 { return " char __e0;" }
|
|
let out: String = ""
|
|
let n: Int = native_list_len(params)
|
|
let i = 0
|
|
@@ -3266,6 +3237,7 @@ fn params_to_env_fields(params: [Any]) -> String {
|
|
}
|
|
|
|
fn params_to_env_init(params: [Any]) -> String {
|
|
+ if native_list_len(params) == 0 { return "0" }
|
|
let out: String = ""
|
|
let n: Int = native_list_len(params)
|
|
let i = 0
|
|
@@ -3296,19 +3268,6 @@ fn params_to_env_args(params: [Any]) -> String {
|
|
|
|
// params_to_call_args — "a, b, c" from the param list, for the wrapper's call
|
|
// into the body helper.
|
|
-fn params_to_call_args(params: [Any]) -> String {
|
|
- let out: String = ""
|
|
- let n: Int = native_list_len(params)
|
|
- let i = 0
|
|
- while i < n {
|
|
- let p = native_list_get(params, i)
|
|
- let pn: String = p["name"]
|
|
- if i > 0 { let out = out + ", " }
|
|
- let out = out + pn
|
|
- let i = i + 1
|
|
- }
|
|
- out
|
|
-}
|
|
|
|
fn cg_fn(stmt: Map<String, Any>) -> Void {
|
|
let fn_name: String = stmt["name"]
|
|
@@ -3358,11 +3317,7 @@ fn cg_fn(stmt: Map<String, Any>) -> Void {
|
|
// silently miss every early return — which is precisely the class of
|
|
// failure this seam exists to remove. Fns with no exit construct emit
|
|
// exactly as before, byte for byte.
|
|
- let wrap_target: String = cg_wrap_target(stmt)
|
|
- let wrap_construct: String = cg_wrap_construct(stmt)
|
|
- let has_wrap: Bool = !str_eq(wrap_target, "")
|
|
- let has_exit: Bool = true
|
|
- if has_exit {
|
|
+ if true {
|
|
emit_line("static el_val_t __el_body_" + fn_name + "(" + params_c + ") {")
|
|
} else {
|
|
emit_line("el_val_t " + fn_name + "(" + params_c + ") {")
|
|
@@ -3393,27 +3348,21 @@ fn cg_fn(stmt: Map<String, Any>) -> Void {
|
|
// The wrapper: guards, entry injection, the body call, then the exit
|
|
// injection, which receives the result so it can observe what the fn
|
|
// actually returned.
|
|
- if has_wrap {
|
|
- // Codegen defines the wrap calling convention, so codegen declares it.
|
|
- // El has ONE type -- el_val_t = int64_t -- so El's own `extern fn` cannot
|
|
- // describe a callable, and asking it to produces an int/pointer
|
|
- // mismatch. The convention is not El-expressible; it is emitted.
|
|
- emit_line("extern el_val_t " + wrap_target + "(el_val_t, el_val_t, el_val_t(*)(void*), void*);")
|
|
+ if true {
|
|
+ // EVERY fn gets an env struct and a thunk. Codegen cannot know which fns
|
|
+ // a wrap construct will be bound to after the binary exists, and the
|
|
+ // wrapper unconditionally calls through el_seam_wrap.
|
|
emit_line("struct __env_" + fn_name + " { " + params_to_env_fields(params) + " };")
|
|
emit_line("static el_val_t __thunk_" + fn_name + "(void* __v) {")
|
|
emit_line(" struct __env_" + fn_name + "* __e = (struct __env_" + fn_name + "*)__v; (void)__e;")
|
|
emit_line(" return __el_body_" + fn_name + "(" + params_to_env_args(params) + ");")
|
|
emit_line("}")
|
|
}
|
|
- if has_exit {
|
|
+ if true {
|
|
emit_line("el_val_t " + fn_name + "(" + params_c + ") {")
|
|
cg_entry_seam(stmt, fn_name)
|
|
- if has_wrap {
|
|
- emit_line(" struct __env_" + fn_name + " __env = { " + params_to_env_init(params) + " };")
|
|
- emit_line(" el_val_t __r = " + wrap_target + "(EL_STR(" + c_str_lit(fn_name) + "), EL_STR(" + c_str_lit(wrap_construct) + "), __thunk_" + fn_name + ", &__env);")
|
|
- } else {
|
|
- emit_line(" el_val_t __r = __el_body_" + fn_name + "(" + params_to_call_args(params) + ");")
|
|
- }
|
|
+ emit_line(" struct __env_" + fn_name + " __env = { " + params_to_env_init(params) + " };")
|
|
+ emit_line(" el_val_t __r = el_seam_wrap(EL_STR(" + c_str_lit(fn_name) + "), __thunk_" + fn_name + ", &__env);")
|
|
emit_line(" __r = el_seam_run(EL_STR(" + c_str_lit(fn_name) + "), 1, __r);")
|
|
emit_line(" return __r;")
|
|
emit_line("}")
|
|
@@ -4291,13 +4240,7 @@ fn program_has_routes(recs: [Map<String, Any>]) -> Bool {
|
|
// only decide whether to repeat — no timeout, no rollback-and-retry, no
|
|
// parallel, no memoize-on-arguments. It would also have crippled the JS backend,
|
|
// which has closures natively, for a limit in the C one.
|
|
-fn declare_wrap(name: String, wraps: String) -> Void {
|
|
- state_set("__dec_wrap_" + name, wraps)
|
|
-}
|
|
|
|
-fn decorator_wrap(name: String) -> String {
|
|
- state_get("__dec_wrap_" + name)
|
|
-}
|
|
|
|
// A PROHIBITION is the other half of a boundary: not what runs when something
|
|
// crosses, but what may not cross at all.
|
|
@@ -4340,8 +4283,6 @@ fn prohibiting_constructs() -> String {
|
|
fn scan_declared_decorators(tokens: [Any]) -> Void {
|
|
declare_prohibition("manager", "dharma_emit,dharma_field")
|
|
let total: Int = native_list_len(tokens) / 2
|
|
- let has_pending_w: Bool = false
|
|
- let pending_wrap: String = ""
|
|
let has_pending_p: Bool = false
|
|
let pending_prohibit: String = ""
|
|
let pos: Int = 0
|
|
@@ -4382,10 +4323,6 @@ fn scan_declared_decorators(tokens: [Any]) -> Void {
|
|
if str_eq(dname, "decorator") {
|
|
if native_list_len(args) >= 2 {
|
|
let dkind: String = native_list_get(args, 0)
|
|
- if str_eq(dkind, "wraps_body") {
|
|
- let has_pending_w = true
|
|
- let pending_wrap = native_list_get(args, 1)
|
|
- }
|
|
if str_eq(dkind, "prohibits_outside") {
|
|
let has_pending_p = true
|
|
let pending_prohibit = native_list_get(args, 1)
|
|
@@ -4396,10 +4333,6 @@ fn scan_declared_decorators(tokens: [Any]) -> Void {
|
|
} else {
|
|
if str_eq(k, "Fn") {
|
|
let fname: String = tok_value(tokens, pos + 1)
|
|
- if has_pending_w {
|
|
- declare_wrap(fname, pending_wrap)
|
|
- let has_pending_w = false
|
|
- }
|
|
if has_pending_p {
|
|
declare_prohibition(fname, pending_prohibit)
|
|
let has_pending_p = false
|