diff --git a/_Type.md b/_Type.md index dd72fa4..83bef1f 100644 --- a/_Type.md +++ b/_Type.md @@ -83,3 +83,72 @@ - `_strappend` 越界存疑(TypeGenErr.vp L396) - `_get_annotation_field_size` 缺类型白名单,未知类型按 8 字节(ClassGenEnum.vp L593-594) - `infer_expr_type` 参数 bits 仅识别 8/16/64 三档,32 位静默落 i32(TypeGenErr.vp L295-300) + +--- + +# 方案:类型系统收敛(t/c 库内部特判 + 正常库分析) + +> 记录日期:2026-08-28 +> 范围:TPV 侧(TPC 侧不再维护) +> 架构目标:t/c 库走编译器内部特判(map_t_type 保留核心原语);用户侧/库侧别名 +> 链(from-import 别名、`X: t.CTypedef = Y`、stdint.vp 声明)走正常库分析(CTypedef +> 动态表递归);vpnci/vpi 存根仅供高亮插件,编译器不感知。 +> **实施状态:阶段 1/2/3 已完成** ✅(2026-08-28) + +## 现状缺口 + +1. **Name 分支无 from-import 别名反查**(TypeGenResolve.vp L1371-1502): + `from t import CInt as XXX` 后裸名 `XXX` 不在 struct/CTypedef/map_t_type 任何表 → + 解析 None;`YYY: t.CTypedef = XXX` 链因此断(递归到 XXX 失败)。 +2. **Attribute 路径硬编码优先**(L1539 map_t_type 先于 CTypedef L1590):stdint.vp 声明的 + ~70 个 typedef 名在 map_t_type 重复硬编码,限定名(stdint.INT)吃硬编码不吃库定义 → 双事实源。 +3. **三张派生表未联动**:`__sizeof__`(CallGenDispatch L583-622)、REnum 尺寸 + (ClassGenEnum L555-583)、无符号名单(ExprGenOps L261-287)各自重复硬编码。 + +## 阶段 1:补正常库分析(已完成)✅ + +### 1a. Name 分支 from-import 别名反查(TypeGenResolve.vp) + +在 Name 分支 map_t_type 兜底之后插入:裸名 miss 时反查 +`ImportsGen.lookup_from_import_original(from_imports, nm.id)`(from_imports 格式 +`别名:模块:原始名`,返回内部指针需复制截断于空格/null)→ 用原始名 `_parse_type_string` +重建节点 → 递归 `resolve_annotation_type`。 + +- 效果:`from t import CInt as XXX` → XXX → CInt → map_t_type 命中; + `YYY: t.CTypedef = XXX` → YYY → CTypedef → "XXX" → 别名反查 → CInt ✅ +- 防递归:复用 resolve_annotation_type 的 depth 上限;别名==原名时跳过 + +### 1b. Attribute 路径 CTypedef 动态表优先(TypeGenResolve.vp) + +把 `map_t_type(at.attr)` 第一优先改为:先查 CTypedef 表(若 attr 是库 typedef 名且 +已注册 → 递归展开),miss 再 map_t_type。 + +- 效果:`t.CInt` → attr="CInt" 表无 → map_t_type 特判(t/c 内部特判保留)✅; + `stdint.INT` → attr="INT" 表命中 → 动态递归(正常库分析)✅;表未注册时回落 + map_t_type 硬编码兜底,不破坏现状 + +## 阶段 2:map_t_type 去重收敛(已完成)✅ + +删除 map_t_type 中与 stdint.vp 重复的 ~70 个名字(INT/BOOL/BYTE/WORD/HANDLE 之外的 +大写别名、定长、小写简写、指针别名、int8_t/size_t/_Bool 等),保留 t/c 核心原语 +(CInt/CUInt8T/CPtr/CBool/CNeedPtr 等)+ 内建小写 float/double + HANDLE/LPCSTR/LPCWSTR。 + +前置改造:新增统一口径 `TypeGenResolve.resolve_typedef_or_map`(CTypedef 动态表优先, +miss 回退 map_t_type)+ `get_type_size_bytes`(位宽/8)+ GenApi 委托;改造旁路调用点 +VpiReader(_resolve_single_vpi_type_str 两处)、ClassGenEnum(_resolve_enum_member_type +两处)、TypeGenErr(参数位宽提取)为统一口径,确保删除后 BYTE 等仍能经库 typedef 解析。 + +## 阶段 3:三张派生表联动(已完成)✅ + +- `__sizeof__`(CallGenDispatch):尺寸表前插入 `get_type_size_bytes` 动态兜底 +- REnum 尺寸(ClassGenEnum `_get_annotation_field_size`):加 pool 参数 + 动态兜底 +- 无符号名单(ExprGenOps `_type_name_unsigned`):末尾加 CTypedef 展开兜底 + (经 `_annot_str_unsigned` 子串判断符号性) + +## 风险 + +- 1a 递归深度:复用现有 depth 上限,别名链过长即报错(fail-fast 优于卡死) +- 1b 解析来源变化:若 CTypedef 表值与 map_t_type 硬编码不一致,限定名结果改变—— + 需先对比验证(预期一致,stdint.vp 为权威) +- 阶段 2 删除后:纯 map_t_type 独有域(t/c 核心 CXXX、HANDLE/LPCSTR/LPCWSTR)保留, + 其余靠注册,漏注册即编译期暴露(符合 fail-fast 原则)