diff --git a/lang/el-compiler/src/codegen.el b/lang/el-compiler/src/codegen.el index a20569a..0ecc4a4 100644 --- a/lang/el-compiler/src/codegen.el +++ b/lang/el-compiler/src/codegen.el @@ -3627,6 +3627,24 @@ fn codegen_streaming(tokens: [Any], sigs: [Map], source: String) -> let pos: Int = 0 let el_main_body: [Map] = native_list_empty() let toplevel_exec_stmts: [Map] = native_list_empty() + // CGI IDENTITY CAPTURE (2026-08-09). A cgi block is a top-level DECLARATION, so + // the classifier below correctly excludes it from toplevel_exec_stmts and calls + // el_release on it. The identity emission further down then searched + // toplevel_exec_stmts for it — a list that structurally can never contain it — + // found nothing, and emitted nothing, silently. Measured: that search sees only + // [Let, Expr] for a program whose first statement is a cgi block. + // Fix: copy the values out BEFORE the release (strings, so no dangling reference) + // and emit from these. No search, so the failure mode is removed rather than moved. + let cgi_have: Bool = false + let cgi_name_v: String = "" + let cgi_did_v: String = "" + let cgi_prin_v: String = "" + let cgi_net_v: String = "" + let cgi_eng_v: String = "" + let cgi_has_did: Bool = false + let cgi_has_prin: Bool = false + let cgi_has_net: Bool = false + let cgi_has_eng: Bool = false let has_toplevel_exec: Bool = false let stream_running: Bool = true @@ -3737,6 +3755,20 @@ fn codegen_streaming(tokens: [Any], sigs: [Map], source: String) -> if is_top_level_decl(stmt) { // Import, TypeDef, EnumDef, CgiBlock, ServiceBlock, ExternFn // These are no-ops in codegen (forward decls already emitted) + // — except a CgiBlock, whose declared identity must survive + // this release to be emitted as a compiled constant. + if str_eq(sk, "CgiBlock") { + let cgi_have = true + let cgi_name_v = stmt["name"] + let cgi_did_v = stmt["dharma_id"] + let cgi_prin_v = stmt["principal"] + let cgi_net_v = stmt["network"] + let cgi_eng_v = stmt["engram"] + let cgi_has_did = stmt["has_dharma_id"] + let cgi_has_prin = stmt["has_principal"] + let cgi_has_net = stmt["has_network"] + let cgi_has_eng = stmt["has_engram"] + } el_release(stmt) } else { if str_eq(sk, "Let") { @@ -3815,33 +3847,17 @@ fn codegen_streaming(tokens: [Any], sigs: [Map], source: String) -> let sig2 = native_list_get(sigs, si2) let sk3: String = sig2["kind"] if str_eq(sk3, "cgi_block") { - // We need the full cgi_block data — it was parsed by scan_fn_sigs - // but scan only stored the name. For cgi_init we need dharma_id etc. - // Since cgi blocks are rare and small, they end up in toplevel_exec_stmts. - // Find the CgiBlock in toplevel_exec_stmts. - let tes_n: Int = native_list_len(toplevel_exec_stmts) - let tes_i: Int = 0 - while tes_i < tes_n { - let tes = native_list_get(toplevel_exec_stmts, tes_i) - let tes_k: String = tes["stmt"] - if str_eq(tes_k, "CgiBlock") { - let cname2: String = tes["name"] - let cdid2: String = tes["dharma_id"] - let cprin2: String = tes["principal"] - let cnet2: String = tes["network"] - let ceng2: String = tes["engram"] - let has_did2: Bool = tes["has_dharma_id"] - let has_prin2: Bool = tes["has_principal"] - let has_net2: Bool = tes["has_network"] - let has_eng2: Bool = tes["has_engram"] - let arg_name2: String = "EL_STR(" + c_str_lit(cname2) + ")" - let arg_did2: String = cgi_arg(cdid2, has_did2) - let arg_prin2: String = cgi_arg(cprin2, has_prin2) - let arg_net2: String = cgi_arg(cnet2, has_net2) - let arg_eng2: String = cgi_arg(ceng2, has_eng2) - emit_line(" el_cgi_init(" + arg_name2 + ", " + arg_did2 + ", " + arg_prin2 + ", " + arg_net2 + ", " + arg_eng2 + ");") - } - let tes_i = tes_i + 1 + // Emit from the values captured before the declaration was released. + // The previous implementation searched toplevel_exec_stmts, which by + // construction never contains a declaration — so it emitted nothing and + // said nothing. See the capture block near toplevel_exec_stmts init. + if cgi_have { + let arg_name2: String = "EL_STR(" + c_str_lit(cgi_name_v) + ")" + let arg_did2: String = cgi_arg(cgi_did_v, cgi_has_did) + let arg_prin2: String = cgi_arg(cgi_prin_v, cgi_has_prin) + let arg_net2: String = cgi_arg(cgi_net_v, cgi_has_net) + let arg_eng2: String = cgi_arg(cgi_eng_v, cgi_has_eng) + emit_line(" el_cgi_init(" + arg_name2 + ", " + arg_did2 + ", " + arg_prin2 + ", " + arg_net2 + ", " + arg_eng2 + ");") } } let si2 = si2 + 1