docs/current/01-定位与路线/结构重构与C23锚定决议.md
GitHub ↗
当前有效

结构重构决议与执行计划(2026-09-11,v2)

6193 字·约 16 分钟 阅读 2026-10-10 17:07

⚡ 执行状态(2026-09-13 补记):R1~R4 结构批次已全部交付(R1 动态堆起点 / R2 出口层收敛(flutter_bridge 整删)/ R3 语义单源(审计清单已归档 docs/archive/ARCHIVE_语义单源审计20260912.md)/ R4 债务与防线收口 G1/G2/G10/G11/G12/G13 + D14/D16,销项见 项目路线图.md §四缺口表);C23 锚定(E1)与模块化预处理器(E2)、C23 语义级(E3)已落地于 C语言子集规范.md §2.10~§2.12。后续重构排期权威已于 2026-09-18 让位至 MoonBit迁移总计划.md §10(S 系列;U 系列未完项由其承接,统一整备路线图保留为历史口径与未闭环项索引),本文保留为决议与执行记录。

决策背景:前端切割后仓库表面积最小、无外部借用(SharpTutor 未接入、社区前端未认领)—— 这是改内部结构零外部成本的唯一窗口。fix 历史的解剖显示脉冲式清偿(6-16 一波 14 个、9 月两波 6 个)间隔在缩短,且每波根因高度集中于同一结构病:同一概念存在多个真相来源。 与其等下一波脉冲,不如按手术清单一次收口。

v2 增补(同日后续讨论):重构批次与 C23 语言锚定 + 模块化预处理器合并规划—— 结构收口(R 系列)与语言能力(E 系列)交替推进,E3 大半是"从 C++ 路径移植"而非新写。

基线锚点:标签 pre-restructure。Shadow 636 用例 0 非预期差异 / cargo test 全绿 / clippy 零警告 / serve 冒烟 26/26 —— 重构期间全程在线,任何一批导致行为漂移即回滚。

1. 换什么、不换什么(边界声明)

换(结构):

  • 会话模型:全局单例(flutter_bridge 799 行,u64 map + static)→ Session + session_api 单轨
  • 内存协调:全局区/堆区静态边界(HEAP_START 写死)→ 堆起点动态化
  • 语义真相来源:已收口的(输出/stdin/行号/配置)保持;未收口的(教学标注双来源)单源化
  • 模块边界:>800 行文件拆分、host IO 家族收敛(fmt 解析单源)
  • 预处理器:文本变换黑箱 → 模块化内核 + 预处理皮肤(见 §3)

不换(行为资产):

  • 编译管线五段结构(Lexer → Parser → TypeChecker → CodeGen → VM)
  • 字节码格式与 636 个 Shadow golden(Clang 对照的行为锚)
  • 出口协议(capi ABI 1.2.0 / serve 协议 / StepPayload schema v0.1)
  • VM 1MB 线性内存模型与教学检测语义(UAF/Double-Free/泄漏报告)

明确不做:推倒重写编译器/VM。教学引擎的价值锚在行为正确性,重写等于重新欠一遍 行为债,且无第二套防线能兜住重写期间的行为漂移。

2. C23 锚定决议(替代 C99)

锚定 ISO C23(ISO/IEC 9899:2024)。三个理由:① nullptr/typeof/auto 在 C++ 子集路径已实现(t12/t18/t19 守护),E3 大半是移植;② 一次锚定到位,避免 做完 C99 又追 C23;③ __STDC_VERSION__ 固定 202311L,诊断文案按 C23 条款引用, C语言子集规范.md / 标准库支持矩阵.md 口径全面换锚。

实测盘点(2026-09-11,两轮探针:vitro_cli 13 项 + 复核 27 项,PASS 8 / FAIL 19):

C23 特性 现状 批次
bool/true/false、auto 推断、typeof(C 侧已可用,复核实测确认) ✅ 已支持 —
#warning、= {} 空初始化器、省略参数名的函数定义 ✅ 已支持(首轮盘点遗漏,复核补记) —
0b1010 二进制字面量 / ' 分隔符 / u8"a" 字符串 / alignof / typeof_unqual ❌ lexer/typeck 级 E1
enum E : int 底层类型 ❌ parser 级 E1
nullptr ❌ C 侧(C++ 路径已实现) E3 移植
static_assert 单参与双参均缺(双参是 C11 标准写法、教学更常用) ❌ E3
constexpr 对象 ❌ 类型系统级 E3
[[属性]] / unreachable() ❌ E3
__has_include ❌(E1011,预处理器不解) E2(模块化内核下天然支持)
K&R 定义、隐式 int 本就不支持 C23 已移除,天然对齐

明确不做(撞 VM 槽位/布局边界):_BitInt(N)、_Decimal32/64/128、 bitfield、long double/_Complex、setjmp/longjmp、alignas(布局控制撞简化对齐 模型)、标签后置(无教学价值)、char8_t(独立类型徒增困惑)——全部进 "明确不支持 + 替代话术"(如 long double → 清晰诊断建议改 double)。

__STDC_VERSION__ 口径(v3 定案):版本宏尚未实现(实测 E3023,首轮文档 误写成现状)。E2 实现预定义宏,值报 202311L(名义锚点)——不报保守值:bitfield 等是 C89/C99 特性,版本值再低也挡不住老代码走进不支持分支;报高值反而让 C23 新特性 代码走对路径。病根"把版本当能力探测"用三层配套解决:

  1. vitro_get_capabilities_json()(capi/serve 出口):机器可读真实能力清单(与已规划 的错误码机器可读导出同源)——教学消费方真正需要的通道;
  2. __VITRO_SUBSET__ 预定义宏:条件编译的引擎专属探测;
  3. C语言子集规范.md 顶部声明:"版本宏为名义锚点,实际为 C23 教学子集,不支持 清单见 §X"。

C23 预处理特性(#elifdef / #elifndef / __VA_OPT__ / #embed)归入 §3 模块化 预处理器的范围。

3. 模块化预处理器设计(E2 选型定案)

皮肤与内核分离:学生写的仍是标准 C 预处理语法;引擎内部不做文本变换黑魔法。

表面(标准 C)                      内核(实际做的)
#include "list.h"          →   模块加载:头文件 → AST 缓存,天然
                                include-once + 依赖图 + 环检测
#ifndef FOO_H / #define    →   守卫语义内置;写不写都正确
#define MAX(a,b) ...        →   MacroTable:token 模板受控展开
#if defined(X) && N > 10    →   配置求值(非图灵完备),分支
                                选择原因记录进诊断
#x / a##b / __VA_ARGS__    →   受限 token 操作(结果必须合法)
#embed "font.bin"          →   字节数组资产导入(最自然的形态)

选型(抄架构不抄代码):

  • 展开器内核 = Rust macro_rules! 架构:token 树转录 + 展开深度保险丝(64)+ 展开链诊断。与 C 参数化宏同构(pattern → template),Vitro 是 Rust 写的,架构对齐。
  • 模块语义 = Zig @import / C++20 modules:ModuleGraph(AST 缓存 + once + 依赖图 + 环检测)。
  • 按 C 规则自己写的两处(不能照抄 Rust):① #/## 操作数不预先展开 (C99 6.10.3.1 特例);② 自引用停止 = 展开栈查重(等价红蓝标记,实现只要一个栈)。
  • 整个跳过 hygiene(Rust 宏实现最贵的 SyntaxContext 系统)——C 宏本来就要文本语义。

诚实放弃清单(记入 spec 已知差异,每条附教学替代建议):自引用宏 trick、 展开顺序敏感代码、## 动态拼标识符的元编程、X-macro 高级用法、宏拼 include 路径。 教学代码命中率 <5%,且每条在黑箱 clang 下也是被劝退的写法。

白箱教学层(黑箱给不了的增值):展开链可视化(复用时间旅行 step 语义)、宏参数 副作用检测(SQ(a++) 双重副作用警告)、#if 分支选择原因记录、#define 遮蔽诊断。

行为契约(v3 定案):

  • 保留既有扩展:参数化宏调用后跟分号自动包装 do{...}while(0)(AGENTS.md 已记录 的已知差异,SWAP(int,x,y); 在 if/else 中正确解析依赖它)。废弃会 break 教材写法 与存量 Shadow 用例;且它是宏调用收尾的 parser 容错,不属展开器语义,与模块化 内核不冲突——E2 时迁至新 expander 后处理阶段,spec 已知差异记录保持。
  • #embed 降级为延期:教学价值低(导入资产)而成本不低(VFS 资产路径 + 字节数组 codegen)。移出 E2 必做,进 ROADMAP 观察项(SharpTutor 有嵌入测试数据诉求再做)。
  • 预定义宏族(__STDC_VERSION__=202311L 名义锚点、__VITRO_SUBSET__、__has_include) 随 E2 落地,口径见 §2。

工时(v3 校准,采纳复核分解):cond 求值器 300–400 + token 操作 200 + MacroTable/展开器/保险丝 400 + ModuleGraph 400 + 教学层 300 ≈ 1.6–1.7k,含测试 ~2.5k。架构落点:vitro_lexer/preprocessor/ 子模块化(resolver / macro_table / expander / cond / splice)。

4. 批次计划(每批独立提交、独立过全防线)

结构收口(R)与语言能力(E)交替推进,避免连续同质地工作:

批次 内容 验收线
R1 内存边界 ① 堆起点动态化:heap_offset = max(HEAP_START, align4(global_end))——栈碰撞检查已确认用动态 heap_offset(control.rs:69)自动跟随;② 判据单源化:literal.rs(MEM_SIZE/16)与 state.rs(HEAP_START)两套魔数统一到 GLOBAL_REGION_LIMIT;③ argv 编址修复:global_count 恒 0,argv 与 codegen 全局数据重叠编址(预存 bug)——改自全局区上界向下分配;④ 影响面 6 逻辑点 + heap_base 统计字段;⑤ global_end > HEAP_START 编译 warning 提示堆可用空间 三方挤压用例(大全局 + malloc 失败明确 trap + 深递归栈溢出明确 trap);大全局 + malloc 不损坏;lc_22/lc_977 回归;Shadow 0 非预期差异
E1 C23 lexer/typeck 级 + B 档快赢 0b 二进制 / ' 分隔符 / u8"a" 字符串(按 char[] 处理,差异记录)/ alignof / typeof_unqual / enum : T(C23);字符串拼接 "ab" "cd"(C89)、long long 位运算(E3048 半成品缺陷)、ULLONG_MAX(u64 坑)/ <float.h> / va_copy / __func__ 每特性 ≤3 个 E2E 用例(Clang golden);Shadow 0 非预期差异
R2 会话收口 vitro_cli 四个子命令迁 Session + session_api(serve 同款);flutter_bridge 零消费后整删 CLI 行为不变(冒烟对照);G6 闭环;全局 static 清零
E2 模块化预处理器 §3 全部设计:ModuleGraph + MacroTable + cond 求值 + splice + 白箱教学层 + 预定义宏族(__STDC_VERSION__ / __VITRO_SUBSET__ / __has_include)+ vitro_get_capabilities_json() 出口 宏/守卫/条件编译全套 E2E;include 环检测诊断;放弃清单记入 spec
R3 语义单源审计 E-P1-5 模式扫全库枚举残留「多真相」点;教学标注单源化 审计清单归档;标注矛盾类缺陷结构性消除
E3 C23 语义级 nullptr 从 C++ 路径移植、static_assert 单参+双参、constexpr 对象、[[属性]](解析+忽略+记录)、unreachable()(typeof 已实测可用,无需移植) 移植项复用既有 C++ 守护用例形态;Clang golden
R4 债务与防线 decl.rs 拆分;unwrap×3 收敛;engineering_health 进 CI(G11);G1 生成器恢复;G10+G12 数字自动对账(须覆盖"文档声明数 vs 代码常量数"方向);G13 补入 C++子集规范;G2 wasm 冒烟进 CI CI 新增检查全绿;<800 行规约恢复

B 档不做/延期清单:0x1.8p3 十六进制浮点、int a[static 10](明确不支持); 匿名 struct/union 成员(~200-400 行,等防线真实用例出现再动;基础 union 已实测与 Clang 一致——alias=DCBA size=4 两边相同)。

G9 独立决策(能力缺口,不属结构债,不混入 R/E 批次)

validate_algorithm() / ValidationResult 的"运行时算法属性验证"随前端切割整体消失 (后端从未有过,原载体 algorithm_validation.dart 已迁出)。

  • 方案 A(默认采纳):列入 Phase 2a 出口演进——vitro_algorithm_steps 已有 41 个 模板元数据可作判定基础,落点 validation.rs(语言中立层),由 SharpTutor 诉求触发排期。
  • 方案 B(若放弃):项目路线图.md 的 G9 改标「能力已随前端迁出,待社区前端认领」。

二选一之前保持「待评估」;不允许默认沉默地丢掉教学能力。

2026-09-11 决议:SharpTutor 诉求已触发(C# 立项使其获得 C/C# 双消费者,价值翻倍), 采纳方案 A,排期落 CSharp前端引入计划.md CS5 批次(与认知管线出山同批)。

5. 升级为更大重构的判据(诚实记录)

R3 审计后若仍出现新的「多真相」类缺陷、或发生「修 A 坏 B」横切回归 ≥2 次、或 known_issue 趋势向上——重新评估结构性重写(届时 R3 的病灶地图即重写图纸)。

6. 已知风险与回滚

  • R1 触碰 MemoryState 初始化时机(快照/时间旅行兼容)与 HEAP_START 假设(6 逻辑点)
  • R2 触碰 CLI 全部子命令;Shadow 驱动走 capi 不受影响
  • E2 放弃病态宏后,Shadow 用例需回避该类写法(教学用例本就不写);行为差异全部入 spec
  • 回滚单位 = 批次提交;pre-restructure 标签保底整轮回退

7. 状态记录(2026-09-11)

  • R1 设计完成、首次实现已回滚(并入 C23/E 系列讨论后统一开工)
  • clippy 1.98 新 lint ×5 已修(0790a8e)
  • union 支持已实测确认(销项"未确认")
  • 本文档 v2 吸收:外部评审三点(三方挤压用例 / 判据分裂 / G12/G13 遗留)、 C23 锚定实测盘点、模块化预处理器选型定案
  • v3 吸收复核(27 项探针,PASS 8 / FAIL 19):typeof C 侧实测可用(E3 移植项 销项);标签后置系尾随逗号误测(裁决不做);补记已支持 3 项(#warning/= {}/ 省略参数名);6 项未盘点特性裁决(alignof/u8字符串/typeof_unqual 做,alignas/ 标签后置/char8_t 不做);__STDC_VERSION__ 口径定案(202311L 名义锚点 + capabilities JSON + __VITRO_SUBSET__ + spec 声明三层配套);static_assert 双参 纳入 E3;do{}while(0) 包装扩展定案保留;#embed 降级延期;E2 工时校准 ~2.5k 含测试
  • R1 已完成(2026-09-11,未提交待确认):手术清单 ①~⑤ 全部落地—— ① 动态堆起点 heap_base = max(HEAP_START, align4(global_data_end))(reset_runtime 经 vitro_runtime::compute_heap_base 单源落位,快照携带 heap_base); ② GLOBAL_REGION_LIMIT 单源取代 MEM_SIZE/16 与 setup_argv 的 HEAP_START 双魔数,全局区 7 个 bump 站点收敛至 codegen bump_global_offset 唯一入口, vitro_vm/core/state.rs 与 vitro_runtime 的同值双写常量改为再导出; ③ argv 自 GLOBAL_REGION_LIMIT 向下分配(global_count 恒 0 的重叠编址修复); ④ MemoryState.heap_base 字段贯通统计(build_heap_stats/fragmentation_rate 签名带 heap_base,flutter_bridge 内联复算改走单源,serve memory_regions 新增 heap_base);⑤ 全局数据越过 HEAP_START 的编译 warning(单/多文件管线均接)。 验收线全绿:r1_memory_boundary_test.rs 7 项(三方挤压 + 大全局 malloc 不损坏 + 超上限 fail loud + warning + argv 隔离 + 布局函数单元测试);cargo test 852/0; clippy 零警告;C Shadow 636 / C++ Shadow 100 均 0 非预期差异(lc_22/lc_977 回归通过)。 行为变化如实入 CHANGELOG:全局数据 >60 KB(旧可静默放行)现编译失败。
  • R1 已提交(47061c9)
  • E1 已完成(2026-09-11,未提交待确认):C23 lexer/typeck 级全项落地—— 0b 二进制、' 数字分隔符、u8"" 字符串、alignof/_Alignof、typeof_unqual、 enum : T(含 64 位成员常量);B 档快赢全项——字符串拼接(C89)、long long 位运算(新增 7 个 64 位 opcode,E3048 销项)、limits.h 全宏 + ULLONG_MAX u64 承载、科学计数法字面量(float.h 病根,比计划记录的更深一层:C89 基础 能力缺失)、va_copy、__func__。两处超出计划的语义修正(探针实测暴露): ① 无后缀浮点字面量 double 化(C 标准;原 float 建模致 DBL_MIN 下溢为 0 + typeck/codegen 位宽错位损坏二元浮点结果);② 浮点比较 epsilon 容差 → IEEE 精确(原容差使 0.1+0.2==0.3 判真,与 Clang golden 矛盾)。暴露并建档两项 预存差异:struct packed 布局、指针 4 字节模型(spec §2.10)。验收线全绿: 12 个 baseline 用例 Clang golden 全 match、探针 13/13、cargo test 856/0、 clippy 零警告、C Shadow 648(636+12)0 非预期、C++ Shadow 0 非预期、serve 冒烟通过。下一批:R2(会话收口)。
  • E1 已提交(5525475)
  • R2 已完成(2026-09-11,未提交待确认):vitro_cli compile/run/step 迁本地 Session 直驱(unified/export/serve 原已如此);flutter_bridge.rs 整删 (-836 行,全局会话单例/POISON_COUNT 退役,工程债务维护方案 D12 问题域 结构性消除,ROADMAP G6 销项);session_api 新增 vm_step/variables 语言中立入口(flutter_bridge 语义收口);孤儿类型 CompileResult/RunResult 移除;bench 改造。CLI 六子命令行为冒烟对照全过(含退出码契约、trap/stdin/ argv/等待输入、step 首步事件语义);cargo test 856/0、clippy 零警告、 C Shadow 648 用例 0 非预期、serve 冒烟过。下一批:E2(模块化预处理器)。
  • R2 已提交(9d87b45);CI 顺带修复三层积压:clippy 5 处系 0790a8e 已修未推送(远端落后),Shadow 驱动与 serve 冒烟的 Windows cp1252 编码崩溃 (Python subprocess/stdout 显式 UTF-8,440c150/ff96147)——均为 2026-09-11 随 E-P1-5/提速设施进库的预存缺陷,非引擎回归。
  • E1 已提交(5525475)
  • E2 已完成(2026-09-12,未提交待确认):§3 设计全项落地——preprocessor/ 子模块化(resolver/macro_table/expander/cond/splice/directives)、#/## (操作数不预先展开、结果必须合法)、#if/#elif 短路求值 + defined + __has_include、include-once + 环检测(E1015)、双展开保险丝(深度 64 + 产出 262144 token,E1017——深度限深不限宽,REP(x) x x 类指数展开由规模 预算熔断)、遮蔽 W1018/副作用 W1019 警告、展开链 + 分支原因教学追踪 (compile.preprocessor_trace,容量 64)、预定义宏族(__STDC_VERSION__= 202311L 名义锚点 + __VITRO_SUBSET__)、capabilities 出口(capi vitro_get_capabilities_json() + serve capabilities,内存常量单源)。 顺带修复三个暴露的预存缺陷:① 同宏嵌套 MAX(MAX(1,5),3) 失败(实参未先 展开,按 C99 实参先行展开、#/## 体例外);② include 拼接点在行尾之前、 行尾消费循环吃掉内容首行(存量头文件首行均为注释而未暴露);③ 嵌套自定义 头文件相对路径按源码目录解析(改"包含者目录优先"候选链 + 哨兵目录栈)。 do{}while(0) 包装契约保留于新展开器后处理。验收线:9 baseline 用例 (含环用例双侧失败=match 形态)+ 14 词法单测、cargo test 870/0、clippy 零 警告、C Shadow 657(648+9)0 非预期、serve 冒烟扩展 capabilities 断言全过; 放弃清单记入 spec §2.11。下一批:R3(语义单源审计)。
  • E2 已提交(706575b,CI 全绿)
  • R3 已完成(2026-09-12,未提交待确认):审计清单归档 docs/archive/ARCHIVE_语义单源审计20260912.md(A 收口 3 / B 历史复核 5 / C 有意保留 3 含归属)。收口三项:① 教学语义标注单源化——删 quick_semantic_label 第二 启发,infer_semantic_label 成全库唯一分类器(Option 局部变量双形态),检查点 判定与 StepPayload 标注同词汇;② 堆耗尽消息自常量格式化(DEFAULT_QUARANTINE_ BUDGET 补入 runtime 导出);③ reset_session_preserving_config 迁 session_api。验收线:审计清单归档 ✓、标注矛盾结构性消除 ✓、cargo test 870/0、 clippy 零警告、C Shadow 657 用例 0 非预期、serve 冒烟过。下一批:E3(C23 语义级)。- C# 教学子集前端立项(2026-09-11,v3 定稿):SharpTutor 诉求锚定,计划落
  • R3 已提交(e5aee40);E2 提交 CI 全绿(706575b)。
  • E3 已完成(2026-09-12,未提交待确认):nullptr(与 NULL 同路径,无独立 nullptr_t 入 spec)、static_assert/_Static_assert 真求值(E1020,双拼写/ 双参单参/块作用域,求值器扩展 sizeof 内建类型)、constexpr(按 const 口径, 边界入 spec)、[[属性]] 前缀解析忽略、unreachable()(stddef.h + Host Func, 执行到即教学 trap)。验收线:4 baseline 用例(static_assert 失败双侧失败=match、 unreachable 严格死代码——可到达处调用会使 clang 链接失败,故用例限定死代码)+ 5 管线单测;cargo test 875/0;clippy 零警告;C Shadow 660(656+4)0 非预期。 下一批:R4(债务与防线)。 CSharp前端引入计划.md——本计划全批次交付后启动(CS0 起独立批次,前置条件
  • E3 已提交(00a5c8c,含探针文件清理 fbaa3ac)
  • R4 已完成(2026-09-12,未提交待确认)——重构计划全批次(R1→E1→R2→E2→ R3→E3→R4)交付完毕: D14 unwrap×3 归零(let-else 化,语义不变);D16 decl.rs 905→792 非空行 (typeof/auto 家族移入 decl_types.rs);G1 sync_templates.py 恢复(去 Flutter 口径);G2 wasm 冒烟固化(scripts/wasm_smoke/wasm_smoke.js: __heap_base 传参 + capi 全链路 + 纯 stdout 断言 + bindgen Proxy 桩)并进 CI;G11 engineering_health 进 CI(看板 + artifact);G10 CPP_FAILURES 74→78 对账;G12 infixEvaluation_default 确认已修复、口径统一为 82/80 绿/ 2 已知失败;G13 两条 C++ 活约束补入 C++子集规范。验收线:cargo test 875/0、clippy 零警告、C Shadow 660 用例 0 非预期、serve 冒烟过、wasm 冒烟 本地全通。
  • 全批次交付声明:R1/R2/R3/R4 + E1/E2/E3 七批次全部完成(各批次独立 提交、独立过全防线;行为变化均已如实记录 CHANGELOG/spec)。按 §7 时序, CSharp前端引入计划.md 的 CS0~CS6 具备启动条件(锚定客户对齐后排期)。
  • R4 及其 CI 修复已提交(3c767bb + 5bbd815 wasm 步骤 working-directory + d2f7543 C++ Shadow 目录去重/clang 重试 + 968a408 wasm 暂存区 memory.grow),最终 CI 全绿(968a408,含新增 wasm 冒烟步骤)。CI 顺带 暴露并修复两处预存问题:C++ Shadow 驱动内嵌用例与目录用例同名双跑且内容 漂移(G10 同源病);__heap_base 在部分 Rust 版本默认不导出(冒烟暂存区 改 memory.grow 新增页,位于程序堆之上无重叠)。 定位扩展("后端语言锁定 C/C++" → C/C++ 主轴 + C# 教学子集)待定位主计划 同步声明。