From a0e7ff7f6f590bb2bc346bb0ecc43ca0dbcec0d1 Mon Sep 17 00:00:00 2001 From: Drew T <50529377+Druthulu@users.noreply.github.com> Date: Mon, 13 Jul 2026 21:49:22 -0600 Subject: [PATCH] =?UTF-8?q?fix(phase-26):=20scope=5Fdata=5Fexterns=20ANSI-?= =?UTF-8?q?brace=20fix=20+=20wire=20=C2=A78d=20into=20family=5Fsweep=20--h?= =?UTF-8?q?seq;=20780-class=20diagnosed?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - _body_open_brace only matched a `{` on its own line (the K&R shape), so fix() SILENTLY NO-OP'D on every ANSI draft — the same silent-skip disease as the four catalogued in §40/§8d, caught because the h_seq re-sweep banked 0/780. Now brace-scans forward from the signature (ANSI same-line, ANSI own-line, and K&R all work). Load-bearing for func_80178D40's upcoming ×134 bank. - family_sweep --hseq now applies the §8d scoped stage at staging time. - HONEST RESULT: still 0/780 — the substantial-band h_seq rejections are a DIFFERENT (sibling) class, now fully diagnosed against the bytes: gcc-2.7.2 decl-conflict semantics: a VISIBLE file-scope decl + a conflicting later decl (file OR block) is a HARD ERROR; a limbo-only block decl (scope closed) + a conflicting later decl is a warning. The h_seq drafts carry the EXEMPLAR TU's spellings; sibling TUs legitimately spell the same symbol differently (loose typing), and the visible decl is often MACRO-INJECTED — a DEFINE_func_* leading extern (§8c), invisible to any col-0 scan (e.g. D_80115158's `short` decl enters ov_SC01_000.c via DEFINE_func_8014168C() @4637; the draft carries ov077's `unsigned short` -> conflicting types at ANY scope). Sub-class (a) no-visible-decl -> §8d demotion (the jr class, proven x133). Sub-class (b) visible decl, different spelling -> needs reconcile-to-TU-VISIBLE (rewrite the draft decl to the TU-visible spelling + byte-neutral access cast; oracle = col-0 decls above the stub + engine_core.h macro externs for the DEFINE_ invocations above). Parked as a designed follow-up task; the 780 members are mechanical-recovery fodder once the tool exists. --- tools/family_sweep.py | 14 ++++++++++++++ tools/scope_data_externs.py | 16 +++++++++++----- 2 files changed, 25 insertions(+), 5 deletions(-) diff --git a/tools/family_sweep.py b/tools/family_sweep.py index f48bb1e3f..090976ce0 100644 --- a/tools/family_sweep.py +++ b/tools/family_sweep.py @@ -20,6 +20,7 @@ import json, glob, re, subprocess, os, sys, shutil, collections, argparse sys.path.insert(0, os.path.dirname(os.path.abspath(__file__))) import family_remap as FR import canon_sig_reconcile as CSR # v3.2 (Phase-25 T7-M2 per-sibling re-reconcile, Q5-proven) +from scope_data_externs import fix as scope_data_fix # §8d (Phase-26 session 8) REPO = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) PY = ".venv/bin/python" @@ -244,6 +245,19 @@ def hseq_sweep(a): skip[r[:24]] += 1; continue if re.search(r'__asm__\s*\(\s*"\$', draft): # hard-reg pin (§42e): ×1-only, cc1-crashes skip["pinned-exemplar"] += 1; continue # sibling TUs → skip the family, don't bisect-storm + # §8d — place the carried DATA externs at a scope this sibling's TU can accept. + # `remap_hseq` (via gather_externs) prepends them at FILE scope; for a per-location symbol the + # sibling declares only at BLOCK scope inside its own later functions, that ESTABLISHES A GLOBAL + # THE TU NEVER HAD and every later block-scope extern must now agree with it — loose typing ⇒ they + # don't ⇒ `conflicting types for D_80115128`. Byte-proven to be the dominant gate-rejection class + # here (as it was for the jr sweeps). Demoting is byte-neutral and never worse than raw, and the + # whole-binary gate remains the sole arbiter (G3/P9). + to_func = f"func_{to_addr:08X}" + tu_path = os.path.join(REPO, src_rel) + tu = open(tu_path).read() + mstub = re.search(rf'INCLUDE_ASM\("[^"]*",\s*{to_func}\);', tu) + if mstub: + draft, _moved = scope_data_fix(draft, tu, mstub.start(), to_func) d = os.path.join(REPO, SWEEP, ov) os.makedirs(d, exist_ok=True) open(os.path.join(d, f"func_{to_addr:08X}.c"), "w").write(draft + "\n") diff --git a/tools/scope_data_externs.py b/tools/scope_data_externs.py index bbdc7b725..1efb989b8 100644 --- a/tools/scope_data_externs.py +++ b/tools/scope_data_externs.py @@ -72,14 +72,20 @@ def _file_scope_data_syms(text): def _body_open_brace(body, func): - """Index of the newline ending the line that opens `func`'s body — i.e. where block-scope decls go. - Handles both the ANSI form and the K&R form (mandatory whenever a zero-arg engine_core.h thunk calls - the function), whose param decls sit between the signature and the `{`.""" + r"""Index just past the `{` that opens `func`'s body — i.e. where block-scope decls go. Scans forward + from the signature to the first `{` at depth 0 of the *statement* (so it handles the ANSI form with + the brace on the signature line, the ANSI form with the brace on its own line, AND the K&R form whose + param decls sit between the signature and the `{`). The first cut of this used `^\s*\{\s*$` — own-line + braces only — and silently no-op'd on every ANSI draft (the same silent-skip disease as the four + catalogued in §40/§8d; caught because the h_seq re-sweep banked 0/780).""" sig = re.search(rf'^[^\n]*\b{re.escape(func)}\s*\(', body, re.M) if not sig: return None - brace = re.compile(r'^\s*\{\s*$', re.M).search(body, sig.end()) - return brace.end() if brace else None + i = body.find('{', sig.end()) + if i < 0: + return None + j = body.find('\n', i) + return (j + 1) if j >= 0 else (i + 1) def fix(body, tu_text, insert_pos, func):