Commit Graph
45 Commits
Author SHA1 Message Date
TermiNexus 2e80424d67 refactor(handles): 删除 CSpecialCallHandle/TSpecialCallHandle
EmitRawCopyLlvm 改为模块级函数;删除 c./t. 语法糖处理类及 BaseTranslator 实例化,全仓零引用。
2026-10-18 21:51:10 +08:00
TermiNexus 109e71a477 refactor: 删除保留性兼容兜底,仅保留新语法主路径
移除 len(list) 直读 __count__、list 方法裸模板回退、旧 C* 文本标记兼容、旧联合兼容;vast 扩展过期直接报错,已重建 _parser.pyd。
2026-10-18 19:22:32 +08:00
TermiNexus 0bded58999 refactor(type): 全面清理旧联合与 t/c 标记判断
审计并修复 23 个文件:类型注解中的 T1 | T2 一律 fail-fast;typedef/define/export/extern/static/const/volatile/attribute 优先读取 Markers/Attributes/ByteOrder/BitWidth;指针统一 CPtr/rawptr/CRef/CTempRef/CArrayPtr/CAutoPtr Subscript;stub 输出统一新语法。
2026-10-18 18:01:20 +08:00
TermiNexus 660a15bef8 refactor(tpc): 删除类型联合语法并将修饰迁移为 AST 字段
类型注解不再接受任何 T1 | T2;const/volatile/static/export/extern/inline/define/typedef/__attribute__/BigEndian/LittleEndian/Bit 改为注解节点字段 Markers/Attributes/ByteOrder/BitWidth;指针与引用改为 CPtr[T]/CRef[T]/CTempRef[T]/CArrayPtr[T]/CAutoPtr[T];Python 与 vast_c 两套解析器、类型解析与声明端同步;C 扩展早于 vast_c.c 时自动回退纯 Python 解析器。
2026-10-18 13:35:34 +08:00
TermiNexus f19d25782f refactor(tpc): 退役 t/c 模块并将定宽类型升级为内建
删除 lib/includes/t.py、c.py,类型模型迁入 lib/core/TypeSystem.py;移除 IsTModule/_T_MODULE_NAMES 等名称判据,语法糖与内部标记统一为裸名;builtins 的 sizet/intN/uintN/fast/least/uchar/short/long 等改为编译器内建短名。
2026-10-18 13:00:58 +08:00
TermiNexus 6b87a78239 fix(tpc): 全局注解赋值的一元负号常量按位宽还原带符号真值
_eval_global_const 对负常量直接用无符号读回值取负,负数被物化成 2 的位宽次方减绝对值,例如 -196608 变成 4294770688。改为先按常量自身位宽还原带符号真值再取负,最后按目标类型发射。

与 aaf9330b 同族,覆盖全局路径。
2026-10-14 20:49:52 +08:00
TermiNexus 23b47053d9 chore: 同步 TransPyV→ViperC 改名、new 表达式支持与定宽字面量/窄化适配 2026-10-12 20:59:39 +08:00
TermiNexus ddf40e02c5 feat(deref): 解引用写入 *p = v 采用 DerefAs 安全语义(方案1)
当 v 是指针且 pointee(p) != typeof(v)(原会因'指针<->非基本类型不匹配'fail-fast)时,把指针 p bitcast 成 typeof(v)* 再按值存 v,即 *(T*(p)) = v(DerefAs 期望写法;旧 DerefAs 的 *(intptr_t*(p))=(intptr_t)v 是错实现)。标量宽度等其余情形维持 pointee(p) 语义不变
2026-10-11 12:22:23 +08:00
TermiNexus 5a0eecc22f feat(core): 栈地址逃逸检查(LifetimeError)与标量→聚合 fail-fast
- MemoryOps._IsFrameStackAddr 判据 + HandlesReturn/HandlesAssign 汇点挂钩:禁止栈地址逃逸(&local 与数组退让);新增 LifetimeError(FailFastError) 承载该错误类。 - MemoryOps._coerce_value:标量(整数/浮点)不得初始化/赋值给聚合类型,改为 FailFastError(旧行为让 _store 抛 TypeError,非 strict 下被静默吞掉,聚合未初始化)。
2026-10-08 12:10:24 +08:00
TermiNexus 9656bb161a feat(codegen): 值引用自动取址收口到 _adjust_args,补齐 vtable/方法/构造等路径
查表键统一为真实发射出的函数名:FuncGen._adjust_args 开头以 func.name 调用 _apply_auto_addr,于是 direct/vtable 虚分派/构造/静态/__call__/下标赋值/c.Addr 构造/闭包/泛型/方法兜底全部自动取址,不再依赖每个调用点手写;同时删除 16 处冗余显式取址(t.CAutoPtr 的 always 模式不幂等,重复应用会多包一层指针)。登记侧:HandlesImports 把模式登记提前到 FuncName-in-Gen.functions 早退之前并按 func.name 主键写表,_TryLoadStructFromStub 改为无条件调用;HandlesFunctions 在函数对象就绪后按真实名登记,并在 _EmitFunctionForwardDeclLlvm 把逻辑名下的模式播种到 MangledName,覆盖同模块先调用后定义的场景。
2026-10-07 19:59:36 +08:00
TermiNexus 59378e6a2a fix(codegen): 内建标量别名双参指针包装 + 解引用赋值按 c.Load 原样拷贝
HandlesExprBuiltin: int/char/bool/float/double(v, t.CPtr) 不再被标量分支吞掉第二参,改由 TSpecialCallHandle._HandleTPtrCastLlvm 处理(等价 t.CInt(v, t.CPtr));此前退化为 ptrtoint+trunc,includes/argparse.vp get_bool 因此恒真,--version/--project 一律打印帮助。

HandlesAssign: 目标与右值同为解引用(*a = *b)时按 c.Load 语义做原样字节拷贝,抽出 CSpecialCallHandle.EmitRawCopyLlvm 复用;此前按 fptosi/trunc 转换,mlirlite ConstFloat 的位双关 *&fv_bits = *&val 会把 double 位模式截断为整数,浮点字面量全部错误。
2026-10-05 14:14:25 +08:00
TermiNexus 9fe88831f3 fix(codegen): 修复模块级 str 字面量全局的初始化器缺失
模块级 `X: str = "字面量"` 有两条路径都没写出正确初始化器:

1) 新建全局分支在创建 GlobalVar 之后又查 `VarName not in Gen.module.globals`
(此时刚登记,条件恒假),于是永远走 else 分支、从不写初始化器:全局退化成
无初值的声明,第二遍再被升级成 `common global i8* null`,字符串常量沦为无人
引用的 @NAME_str。只读常量(如 BuildPipeline.MLIR_OPT_CMD)在 mlir 后端
strlen(NULL) 直接崩(ASan 0x0)。

2) 把既有 external 声明升级为本模块定义的分支一律设 common,但 LLVM 要求
common 全局的初始化器必须是零值,字符串字面量会触发 verifier 报错。

新增 _BuildStringPtrInitializer 统一产出「指向 @{Name}_str 常量数组首元素的
GEP」,两处改用它。

验证:TransPyV 自举通过;TPV 顺序回归 77/77 全通过。
2026-10-05 09:26:26 +08:00
TermiNexus 42c13e372b fix(HandlesAssign): 对"指针的指针"右值的自动解引用收窄为取地址形态
原判据只看右值的 LLVM 类型(Ptr(Ptr(...)))就 load 一层,于是显式 cast 的结果
(`entry = str*(uint64(argv) + idx*8)`,右值是 i8**)被多解一次引用 → 静默取到野指针
(includes/argparse.vp 的 parse_args 因此 ASan access-violation 0xffffffffffffffff)。

现限定为 Name/Attribute/Subscript 这类"取地址形态"(求值结果是存储地址,即"对象即指针"
返回 alloca/字段地址)才解引用;Call(显式 cast、构造/普通函数调用)与其它表达式给出的
是值本身,不再多解一层 —— 与 TransPyV 侧行为对齐(其 _deref_if_ptr_ptr 只用于字段访问
与调用分发,不在普通赋值路径)。
2026-10-01 18:33:21 +08:00
TermiNexus b0aa9f6d76 fix(Handles): 注解声明的类是权威类型,赋值不得改掉它
新增 var_annotated_class 台账(AnnAssign 声明完成时登记真实类名,随 var_struct_class 在函数作用域清空),HandlesAssign 三处「右值推出类」登记点命中该台账时不再覆盖声明类型。否则 node: rawptr[AST] = Name(...) 会把 node 记成 Name,后续 node = <AST*> 被判成被禁止的向下转型(includes/ast/parser.vp:1919)。
2026-09-30 19:09:37 +08:00
TermiNexus cad70fa8f3 chore(诊断): len 分派 fail-fast 追加成员槽来源明细(项数/base/下标/名序/布局槽/实例同源判定)
类别:b(机制漏豁免)/诊断增强,不改变任何成功路径。

现场:编译 StmtGenDeclMixin.vp:242 `len(mcc_pre.children)` 报
  [fast-fail] len(mcc_pre.children) 分派 'list[10f3f43ddd447eec.AST*].__len__' 失败:
  类='MatchCase' 偏移=6 接收者类型=i32
静态可查到的**正确**布局(temp/8c9751aec486f41c.stub.ll 实测 10 槽):
  [0]i8*(vtable) [1]AST*(parent) [2]MemManager*(pool) [3..6]i32(lineno/col_offset/
  end_lineno/end_col_offset) [7]list[AST*]*(children) [8]AST*(pattern) [9]AST*(guard)
声明侧(.vpi):`class AST` 7 字段 + `class MatchCase(AST)` 2 字段 ⇒ 表 9 项、
children 表内下标 6 ⇒ 正确 base=1 ⇒ 正确偏移 7。而失败现场是 6 ⇒ **base 被算成 0**
(表 10 项触发 `_Delta==0 ⇒ base=0`,或取值处实例与类键实例不同源)——
只看 `偏移=6` 无法区分,故把两侧读数打进报文。

- `AssignHandle._DescribeMemberSlot` 增可选 `StructHint`:base 与失败现场**同源**
  (不传时行为与改前逐字一致)。
- `HandlesExprBuiltin._HandleLenLlvm` 的 len 分派失败路径(仅该路径)追加上述明细:
  `class_members[类] 项数/base/下标/声明槽类型`、**完整名序**、
  `布局 struct name+元素数+elements[offset]`、`structs[类] 与布局是否同一对象`。
  明细生成失败只追加一行说明,绝不掩盖原始 TypeError。

静态核验:py_compile 通过;全仓 symtable 未定义名扫描 0 条。
2026-09-30 16:16:38 +08:00
TermiNexus 393ffefcd5 fix(HandlesAssign): self 属性写入的基址收口统一为 _ConcretizeGepBase;收口失败不再静默丢写
类别:a(编译器缺陷)。

1) 收口统一:`self.字段 = v` 的基址此前走**内联**孪生体搜索,缺
   `_TryLoadStructFromStub` 一步 —— 类键那份仍 opaque 且 Gen.structs 里尚无已具化
   孪生体时(body 只在 stub 文件里待加载),内联版会一路走到 GEP 撞 opaque 守卫
   (现场:includes/ast/astaux.vp:165 `self.arg = _copy_str(pool, arg)`,基址 pointee
   是 opaque 的 %"8312ce86a2fd82c0.Keyword"*,而同短名 'Keyword' 键那份已具化 10 槽)。
   现改为调用读路径的**同一判据源** HandlesExprAttr._ConcretizeGepBase /
   _ConcretePointeeFor:① 类键那份 + stub 补 body → ② 同短名已具化孪生体 →
   ③ 都拿不到则原样返回、由守卫报根因。偏移与 GEP 同源(返回实例同时作为
   _get_member_offset 的 StructHint)。

2) 收口失败改 fail-fast:三条路都拿不到 elements 时,此前会落回
   `offset >= max_offset` 的「存回临时变量」分支 —— 该临时变量不在对象布局里,
   后续 `self.attr` 读路径按 GEP 取值,写入被**静默丢弃**。现直接 FailFastError,
   并报出三次尝试的结果(不兜底)。

静态核验:py_compile 通过;全仓 symtable 未定义名扫描 0 条;以 _GuardIrBuilder +
真实 _ConcretizeGepBase 复现现场实例形状(opaque '8312ce86a2fd82c0.Keyword' +
已具化 'fef783da4d24330d.Keyword'(10 槽))→ 解析成功、GEP 正常发出(索引 3);
未收口的裸 opaque 基址仍被守卫拦下。
2026-09-30 15:14:31 +08:00
TermiNexus 2aa55f36b9 fix(LLVMCG/Handles): GEP 基址 opaque 时按同短名找已具化孪生体并 bitcast;守卫报文补实例清单
现场:includes/ast/astaux.vp:165 `self.arg = _copy_str(pool, arg)` 的基址 pointee 是
opaque 的 `%"<sha1>.Keyword"*` —— 同一类名常有两份 struct 实例(短名 'Keyword' /
sha1 全名 '<sha1>.Keyword'),"函数签名里的 self 用哪一份"与"StructGen 具化的是哪一份"
并不保证一致 ⇒ GEP 无法在编译期算元素类型(llvmlite 抛裸 TypeError),
_GuardIrBuilder 的 opaque 守卫先行 fail-fast。

改动:
1) 新增 BaseGen._FindConcreteTwin:按**同短名**(IR 全名相同者优先)在 structs 里取一份
   已具化实例(元素最多者),与既有"同名实例取字段最多版本"(HandlesAssign:1156-1163)
   同一判据;返回 None 表示确无孪生体(真因 = "body 从未 set_body")。
2) 写入路径 HandlesAssign(`self.字段 = ...`):pointee opaque 时 bitcast 到孪生体,
   并把它同时用作 struct_type 与 `_get_member_offset` 的 hint ⇒ 偏移与 GEP 同源。
3) 读取路径 HandlesExprAttr._gep_and_Load_member 共用同一工具函数(读写两路同判据,
   避免"写修了读没修"再吃一轮)。
4) opaque-GEP 守卫报文补"同短名 struct 实例(key(IR 名)=槽数)"清单:清单含已具化项
   ⇒ 属"偏移与 GEP 未同源";全是 opaque ⇒ 属"body 从未 set_body"——一次报文即可判定是哪一侧。

找不到孪生体时**不兜底**:仍由守卫 fail-fast 并报出实例清单(本仓"不许静默兜底"约定)。

验证:py_compile 通过(BaseGen / HandlesAssign / HandlesExprAttr 三文件)。
2026-09-30 11:57:07 +08:00
TermiNexus a43513c9a7 fix(FuncGen): 成员表与 body 等长时不再做类型对齐校准(base 恒为 0),修 TypeGenMixin 字段偏移平移
判据:_member_base 的 delta 长度启发式在 _Delta == 0 时给出 base=0(FuncGen.py:441),
而 base=2 **只可能**来自其后的"类型一致性校准"(:446-480,对 b∈{0,1,2} 逐项比类型取高分)。
但该校准用的是**严格类型相等**:声明侧的联合类型(如 `list[str] | t.CPtr`)可能被记成
折叠后的 i8*,而 body 槽仍是具体指针(`%list[str]*`)⇒ b=0 丢掉这些匹配,某个平移 b
却能靠指针槽互相撞分拿到更高分。
_Delta == 0(成员表项数 == body 槽数)本身就是"逐位对齐"(定义端 body 由成员表生成;
跨模块端 body(.stub.ll) 与 .vpi 同一声明顺序)⇒ base 必须为 0,此时不应再校准。

现场(本次):TypeGenMixin 41 成员 / 41 槽(@t.NoVTable,_Delta=0),base 被抬到 2 ⇒
Generator.vp:136 `SubTypeGen.Gen = self`(Gen 声明 `%"47382dc8277c9d28.Generator"*`、
正确槽为 0)写到槽 40(`%"6fbe68e8fca81223.TypeSpecArena"*`)⇒
"指针隐式转换已禁止(非基本类型(结构体/类/联合)):不能把指针类型 … 隐式转为 …"。
(该报文本身是上一提交 909d8ff0 补的"成员槽来源明细",这次正是靠它直接读出了
base/下标/声明槽类型/布局槽类型四项事实。)

附带:成员槽失败报文再补"名序"(_DescribeMemberSlot 打印 index:name 全表)——偏移算错时
第一现场就是"名序与 body 布局不同源",逐项列出即可直接判定是哪一侧漂移,不必再猜。

验证:py_compile 通过。_Delta != 0 的既有校准现场(ast.Constant 的 `cnst.lineno` 落到
pool 槽等)不受影响(本次只加前置条件,未改校准逻辑本身)。
2026-09-30 11:15:58 +08:00
TermiNexus 909d8ff0eb fix(诊断): _get_node_info 还原自动注入 import 的行偏移;属性写入失败补成员槽来源明细
1) 行号还原(b 机制缺陷,实测可证):Phase2Translator._inject_auto_imports 在源码头
   注入 import _list/_dict/json,AST 节点行号整体下移 N
   (translator._line_offset = N),而 Gen._current_source_lines 是**磁盘**原文。
   BaseGen._get_node_info / _DescribeValueNode 此前直接用 AST 行号读源码 ⇒ 同一次
   fail-fast 里出现两套互相矛盾的行号:_ErrorStack 帧印磁盘行 1140/1141,
   _get_node_info 印 1142,并把源码显示成 1142 行的 `return "t.CPtr"`
   (真实错误行是 1141 的 `...LastBuiltinsTypedefResult = "t.CPtr"`,与被指语句无关)。
   新增 BaseGen._DiskLineno,判据与 HandlesBase._FailFastFixedArrayKeyword:687、
   HandlesAssign._RaiseGlobalAttrError:2051、LlvmGenerator/HandlesBody 的
   _ErrorStack 各站点逐字一致;标签行号(_current_node_info)与源码行一并还原。

2) 成员槽来源明细:HandlesAssign 的「对象.字段 = 值」写入路径(:1182)此前
   _StoreWithCoerce 失败时只报隐式转换禁令,不报目标槽来源,报文与被指语句、
   偏移对不上。现与 `self.x = ...` 路径(:897-905)同口径补 _DescribeMemberSlot:
   附上 class_members 声明侧(项数/base/表内下标/声明槽类型)与布局侧
   (struct name/元素数/elements[offset])两侧数据,可直接判定是声明侧退化
   还是布局侧退化(本次现场即"表内下标被同名继承项过滤移位"一类)。
2026-09-30 10:46:42 +08:00
TermiNexus c86ecb0c89 refactor(LLVMCG/Handles): 直建 ir.Function 点全部收敛到幂等入口,3 处不再吞 fail-fast
类别:a 编译器缺陷(同一根因的其它变体收口:函数声明创建的唯一入口 + fail-fast 不被吞)

背景(前几轮已修两处):llvmlite 的 `Function.__init__` 不是事务性的(名字在 `_set_name`
就进 module.scope,之后建 Argument/ReturnValue 才断言类型,最后才 add_global),中途失败会
留下悬空名字;本仓已加两道防线:全局守卫 `InstallFuncCreateGuard()`(回滚名字 + 带调用点的
FailFastError)与唯一幂等入口 `_CreateOrReuseFuncDecl`(创建前自检、同名同类型复用、异类型
带两侧签名 fail-fast)。但仍有 20+ 处**绕过入口直建**(同名时抛裸 DuplicatedNameError、且
名字被占/半注册时只能看到没有上下文的名字),以及若干处 `except Exception` 会把这颗
FailFastError 吞掉(声明静默缺失、真因丢失)。

改动:
1. 创建点收敛(21 处,行为等价或更严)——`X = ir.Function(<gen>.module, <fty>, name=<N>)`
   → `X = <gen>._CreateOrReuseFuncDecl(<N>, <fty>)`:
   · Handles:HandlesAnnAssign[llvm.memcpy]、HandlesAssign[llvm.memcpy.p0i8.p0i8.i64 ×2]、
     HandlesBase[GetOrCreateFuncDecl / GetOrCreateStubFuncDecl]、
     HandlesExpr[malloc]、HandlesExprBuiltin[strlen / llvm.memcpy]、
     HandlesExprCall[llvm.* 与普通 / win32 API / strlen / llvm.memcpy]、
     HandlesAsyncFunctions[malloc / create_* / resume_* / CRT 声明 / free]、
     HandlesExprLambda[lambda 包装]、HandlesFunctions[_replace_function_decl 的 old_func=None 分支]、
     HandlesImports[output stub 按需加载]
   · LLVMCG:BaseGen[_DeclareExternalFunc 与 6 处 --hotspot-sites 内部符号]、
     ExprGen[llvm.pow.f64]、VaArg[llvm.va_start / llvm.va_end]
   原有 globals/functions 预检查与随后的 `Gen.functions[...] = X` 赋值一律保留。
   注:`_DeclareExternalFunc` 收敛后外部声明会同时登记进 `self.functions`(幂等入口固有行为,
   与既有 `get_or_declare_c_func` 一致;该路径仅 --hotspot-sites 调试特性使用)。
2. fail-fast 不再被吞(3 处):在包裹创建的 `except Exception` 首部加
   `isinstance(_e, FailFastError) → raise`:
   · HandlesExpr[malloc 的 null 回退分支]、HandlesExprBuiltin[strlen]、HandlesExprCall[strlen]
   (其余异常维持原行为,本轮不扩大 fatal 面。)
   另有 HandlesFunctions / HandlesImports 的同类 handler 前几轮已具备 FFE 重抛,本次未重复改。

验证:13 个改动文件 `py_compile` 全部 EXIT=0;冒烟 4 例通过——同名同类型复用同一对象、
异签名 → FailFastError(报文含两侧签名 i64/i32)、名字被非函数全局占用 → FailFastError、
`llvm.va_start` 幂等。另:`ir.Function(` 在 lib 内仅剩 `BaseGen._CreateOrReuseFuncDecl` 内部
这一处(豁免点);`DecoratorPass.py` 的 `module` 为外部传入(非 Gen 的模块)故其两处保持原样。
2026-09-30 09:53:41 +08:00
TermiNexus 90d81df4f8 fix(tpc): 自指针指向 opaque 同名实例时归一为具化实例;GEP 边界拦下 opaque pointee
类别 a(编译器缺陷):llvmlite 的 typed pointer GEP 必须在编译期算出元素类型——
`GEPInstr` → `ptr.type.gep(i)` → `IdentifiedStructType.gep` → `self.elements[i]`,
对 **opaque**(elements is None)pointee 抛裸 TypeError('NoneType' object is not
subscriptable)。现场:includes/ast/astaux.vp `Keyword.__init__` 的
`self.arg = _copy_str(pool, arg)`,经 HandlesAssign._HandleAttributeStoreLlvm:869
的 GEP 崩溃。成因:同名 struct 存在**两份实例**——函数签名/变量里那份仍 opaque,
类键 `Gen.structs[ClassName]` 上那份已具化;偏移取自类键那份、GEP 却用 self 那份。

- HandlesAssign._HandleAttributeStoreLlvm:GEP 前把 self 指针 bitcast 到**有 body 的
  那份实例**(仅当 self 的 pointee opaque 且类键实例已具化),并把该实例作为
  StructHint 传给 _get_member_offset —— 偏移与 GEP 必须同源(与属性读取路径
  _gep_and_Load_member 的 415916b3 同口径);max_offset 的取值也补上 elements 为
  None 的判据(原实现会对 opaque 实例 len() 触发断言)。
- BaseGen.RequirePointerOperand 新增 RequireConcretePointee(GEP 专用):基址指向
  opaque 具名结构体时 fail-fast,报文给出基址类型、结构体名、GEP 名与当前节点位置,
  不再落到 llvmlite 的裸 TypeError(typed pointer 下"GEP 指向 opaque 结构体"无任何
  合法场景:元素类型必须编译期可知)。

本地冒烟:opaque pointee 被拦下(FailFastError,而非 llvmlite 的 TypeError);
具化 pointee 正常通过。
2026-09-29 22:10:11 +08:00
TermiNexus b652634356 fix(tpc): 裸赋值 RHS 是"联合注解返回"的调用时,从返回注解恢复被指类名
类别:a(编译器缺陷)—— 类型信息被静默丢成通用指针 i8*,后果在数行之后以看不出真因
的报文暴露。

现场(Test/FakeDuckTest/App/main.vp:111/115):
  `parts = s1.split(',')` → `p0: str = parts[0]`
  报"整数隐式转指针已禁止…出错表达式: 下标表达式 Subscript"。

证据链(三段各有代码/探针依据):
1. `_fakeduck.vp:273` 的 `def split(...) -> list[str]*`:只读探针确认 `list[str]*`
   与 `list[str] | t.CPtr` 的 AST **逐字同形**
   (`BinOp(BitOr, Subscript(Name(list)), Attribute(t.CPtr))`)⇒ 注解写法没问题。
2. 该联合形态在 LLVM 层映射成**通用指针 i8***(`list[T] | t.CPtr` 的既有约定,
   见 HandlesAnnAssign:372-383)。
3. `HandlesAssign` 原有的类名推断整块以 `Value.type.pointee` 是结构体为前提
   (:186 的 `isinstance(..., (LiteralStructType, IdentifiedStructType))`)⇒ i8* 直接
   整块跳过 ⇒ `var_struct_class['parts']` 从不登记 ⇒ `parts[0]` 不走
   `list[str].__getitem__`,退化成通用指针/字节索引 ⇒ 结果类型是整数 i8 ⇒ 赋给
   `str` 时触发 int→ptr 拦截。真因位置比报文位置早 4 行。

修复(编译器侧,不要求源码补注解):
- `HandlesExprCall._CallReturnClass(Node, Gen)`:从被调者的 **returns 注解**取回被指
  类名。被调者候选键覆盖三种既有形态(`Name` 函数名、`<接收者类>.<方法>`、
  FakeDuck 影子类 `_str`/`_bytes`、裸 `<方法>`),取第一个能解析出类名的。
- `HandlesExprCall._ClassFromAnnotation(Ann, Gen)`:剔除 `| t.CPtr` 侧取核类型,
  泛型 Subscript 走 `_resolve_generic_slice_type` 构特化名(`list[str]`),并要求该名
  能在 `Gen.structs` / `Gen.class_members` 命中(含 sha1 前缀全名的短名归一);
  取不到一律返回 None —— **不硬塞名字**。
- `HandlesAssign`:仅当"RHS 是调用 + 值类型是通用指针(pointee 非结构体)+
  var_struct_class 尚无该变量"这三个条件同时成立时,才据上恢复登记
  `var_struct_class` / `global_struct_class` / `_var_to_heap_ptr`。其余路径逐字不变。

验证:只读探针覆盖 7 种注解形态(`list[str]*` / `list[str] | t.CPtr` / `Foo*` /
`Foo | t.CPtr` / `ast.AST*` …),提取结果全部符合预期(未命中类名时返回 None);
GetDiagnostics 干净。未跑编译器。

遗留(同族,下一轮):上游"联合注解→i8*"这一步丢类名才是真根因;本次是在调用点
恢复。另外 `parts.__len__()` 在类名缺失时可能被 FakeDuck `_str.__len__` 错接,
修完建议跑一次该测试确认 `split len OK`。
2026-09-29 17:09:42 +08:00
TermiNexus f4c8c48748 fix(tpc): 函数声明创建全部收口到唯一幂等入口,消除 DuplicatedNameError 裸抛
类别 a(编译器缺陷)+ b(机制漏豁免)。报错:翻译 lib\core\Gen\Expr\ExprGenName.vp
失败,报文只有名字 dddc595175f00c66.ExprGenAttr.find_global_in_module
⇒ llvmlite DuplicatedNameError(NameScope.register 对 GlobalValue
deduplicate_name=False,同名 global 再建必抛,__str__ 只回名字)。

根因(已取证,非猜测):
- llvmlite Module 里 `scope`(NameScope,注册/去重)与 `globals`(OrderedDict)
  是两套结构;`add_global` 只在构造时写入 ===> 「名字已在 scope._useset、
  但 globals 查不到」这一状态一旦出现,任何"先查 globals 再建"的守卫都会失效。
- 该状态由**清理不完整**制造:删旧名时只删"对象真名 existing_func.name/old_name",
  而字典键/目标名(func_name / MangledName)仍留在 scope._useset。
  别名注册(Gen.functions[短名] = 名为全名的对象)恰好让二者不同名。
- 另有若干创建点只看 Gen.functions、完全不看 module.globals(裸建 ir.Function),
  只要 module.globals 已有同名声明就裸抛 DuplicatedNameError。

本次收口(函数声明创建的唯一入口 = BaseGen._CreateOrReuseFuncDecl):
1. BaseGen._CreateOrReuseFuncDecl:新增"名字被非函数 global 占住"分支,把冲突
   双方(类型 + repr)报出来,替代原 llvmlite 只给名字的裸抛。
2. 清理不完整处补全为「同时清 真名 + 目标名」:
   - HandlesImports.py 模板 declare 装载(clearing func_name 之外还清 existing_func.name)
   - HandlesFunctions._replace_function_decl(clearing {old_name, MangledName})
   - 其 except 对 FailFastError 改为上抛(不再回退成复用旧声明)
3. 裸建 ir.Function 的创建点改走唯一入口(module.globals 同名则复用、
   签名冲突/非函数冲突则 fail-fast):
   - HandlesExprCall._HandleStaticMethodCallLlvm({sha1}.Class.Method)  ← 本现场形态
   - HandlesExprCall._HandleMethodCallLlvm 的 class_sha1 回退分支
   - HandlesExprCall._try_declare_c_lib_func / HandlesExprBuiltin._try_declare_c_lib_func
   - HandlesAssign 模块级全局赋值处的函数声明
   - HandlesImports.__before_init__ 声明(原查 NewFuncName 却建 MangledName)
   - HandlesFunctions._EmitFunctionLlvm(补登记 module.globals 已有声明,
     使既有的签名修复路径生效,而不是裸建撞名)

行为等价性:上述各点原先"撞名"时必然抛 DuplicatedNameError(即必失败),
收口后要么复用同一符号、要么 fail-fast 报出两侧签名/冲突类型,无静默降级。
2026-09-29 13:50:44 +08:00
TermiNexus c49dc1d915 fix(tpc): 类型静默降级改 fail-fast + 成员槽写入失败附来源明细
a 编译器缺陷:类型信息缺失时静默兜底会掩盖上游根因,兜出来的"看着合理"的类型
(如 i8**)又会让下游报出与真因无关的错。按既定铁律改为响亮失败:

1) HandlesImports._parse_llvm_type:被指类型是具名聚合(%...)却在
   create_structs=True 下取不到结构体时,原静默 `return PointerType(i8)` ——
   结构体指针被悄悄变成通用指针,外层再套一层即成 i8**。改 fail-fast。
   (create_structs=False 属"尚未加载",非异常,保持原样。)

2) HandlesTypeMerge._HandleSubscript:新增判据自洽守卫 —— base 是指针标记
   (rawptr / t.CPtr / 裸名 CPtr / 别名)而 IsPtrSubscriptNode 未命中时,
   历史上会落到 CollectAll 当"数组下标"解析、静默产出「基座 void + 多层指针」
   (i8**)。现 fail-fast(判据分裂即内部不变量被破坏)。

3) HandlesAssign._HandleAttributeStoreLlvm(`self.字段 = 值`):成员槽写入失败
   时追加「成员槽来源」明细 —— class_members 声明侧(项数/base/下标/声明槽类型)
   + 布局侧(struct IR 名/元素数/elements[offset])+ structs 键数与是否同一对象,
   使"声明侧退化"与"布局侧退化"一眼可分,杜绝再靠猜。

现场:TransPyV/App/lib/core/Gen/Generator.vp:193 `self.ExprGenConst = SubExprGenConst`
  → 指针隐式转换已禁止(层数不同):不能把指针类型
    %"cfd1f3d0d7e87fea.ExprGenConst"* 隐式转为 i8**
2026-09-28 23:59:29 +08:00
TermiNexus 49ff1b995f fix(cast): 显式指针 cast 一律放行(按 bitcast 重解释)+ MemoryOps 改用 vast 解析器模块
① 新增 _IsExplicitPtrCastNode:值节点是写明的指针转换调用(t.CPtr(x)/CPtr(x)/c.CPtr(x)/rawptr[T](x)/t.CPtr[T](x)/(T*)x/T*(x))时,_ClassifyPtrImplicitConvert 直接放行(用户规则「显式转换都可以」),调用方按既有 bitcast 重解释;非 cast 调用(MemBuddy(x)/list[X](x)/foo(x))不受影响。

根因:includes/_list.vp:60 的 elem_ptr: T | t.CPtr = t.CPtr(地址) 在 list[X*] 特化下 T|t.CPtr = X**(T 本身是指针),而 t.CPtr(...) 的值是 i8* ⇒ 被判「层数不同」,与报错自己给的「如需转换请显式 cast(如 t.CPtr(...))」建议自相矛盾(ExprGenFstr.vp 编译失败的 2 条 elem_ptr 报错)。

② MemoryOps.py 的 import ast 是标准库 —— 但 TPC 全部源码由 vast 解析,节点类为 lib.vast.Nodes.*,与标准库 ast 互不兼容 ⇒ 该文件所有节点类型判据对 Viper 源码静默失效(_value_node_of 子表达式下沉、_CtorCallStructType 构造物化豁免、以及新增的 cast 判据都不生效)。改为 import vast as ast,一并修复。
2026-09-28 16:48:52 +08:00
TermiNexus d7158bd336 feat(cast): 指针隐式转换新规则 + None 可隐式转任意类型 + 诊断错位修复(9 文件)
MemoryOps._ClassifyPtrImplicitConvert:同类型放行;层数不同禁;任一侧通用指针(i8*)放行;皆非通用按被指类型(非基本类型禁、基本标量按位宽无损);指针与非基本值互换禁

_IsNoneValue 收敛:AST None 常量 或 指针型 null 常量 → 放行任意目标(指针目标给 null,非指针目标给零值);整数 0 不误命中;短路口覆盖 9 处禁令

诊断:新增 BaseGen._DescribeValueNode(子表达式下沉 + 有符号列号 + 源码片段),9 处禁令统一使用,不再打印外层 Assign 与 4294967295 列号

注:TPC 侧规则③比 TPV 更严(指针→非基本值恒禁),可能与既有按值回读冲突;待实机编译确认后再统一两侧口径
2026-09-28 15:10:39 +08:00
TermiNexus 35de6321f6 refactor(return): 移除 @c.CReturn 多返回值处理器,只保留 -> tuple[ty1, ty2, ...],遇到 CReturn 一律报错
DeclarationGenerator:tuple[...] 分支逐字保留(仅 CReturnTypes 机械改名 MultiRetTypes),装饰器分支改为 SyntaxError,报文含函数名与“请改用 -> tuple[ty1, ty2, ...]”提示

HandlesAssign(a, b = f() 解包路径):删除装饰器收集分支并改为报错;tuple[...] 恢复与逐个解包逻辑逐字不变

HandlesFunctions:新增 _CRETURN_REMOVED_HINT 与 _RejectCReturnDecorator,在函数定义入口(_GetFunctionSignatureLlvm / _EmitFunctionLlvm)fail-fast——即使只有装饰器、没有 -> 注解,也不会让返回类型静默退化成 i32

HandlesImports:外部函数声明处同样报错,并删除下游已失效的 CReturnTypes 参数拼接死代码

HandlesReturn / HandlesFor / BaseTranslator:CurrentCReturnTypes 等机械改名(读写端一致,无行为变化)

includes/c.py:保留 CReturn 名字作墓碑(删掉会让 @c.CReturn 变成未知属性、可能被静默忽略),docstring 写明已移除并指路 -> tuple[...];README 措辞同步
2026-09-28 13:57:04 +08:00
TermiNexus f9957787a0 feat(codegen): TPC 模块级 t.State 全局只声明不定义(external linkage)
extern 名字: 类型的展开产物(名字: 类型 | t.State):本模块生成 @名字 = external global T,不写定义(否则 duplicate symbol)

位置早于「已存在则升级 common 定义」分支,避免 extern 被反向升级成定义;与 import 侧 _EmitExternalGlobalDeclLlvm 同名分支同口径

export(t.CExport)侧无需改动:TPC 模块级全局本就用裸名(_mangle_name 不作用于全局变量),裸名导出语义天然满足
2026-09-27 18:01:49 +08:00
TermiNexus 3b5d85ce9d fix(handles): 补指针操作符目标写入与实参解引用,消除静默丢弃
- HandlesAssign: 新增 ast.UnaryOp 赋值目标分支(*p = v 复用 _StoreWithCoerce);Tuple/List 目标合并;删除 Tuple 分支里未绑定的死代码(UnboundLocalError)

- HandlesAugAssign: 新增 ast.UnaryOp 目标分支实现真 *p += v,其余形态 fail-fast

- HandlesExpr: 新增 ast.Starred 分支,值位置 *p 归一为 UnaryOp(Deref)(修 t.CPtr(*((uint64*)(blk))) 恒为 0)
2026-09-27 00:19:44 +08:00
TermiNexus c83fc752c6 fix(sizeof,parse): 尺寸链去静默兜底,解析报错可定位,补 C 解析器缺口
StructGen: _get_struct_size/_get_align 去 opaque→8/ptr_size、未知→4 兜底并补 VectorType;LiteralStructType.fields→.elements(llvmlite 无 fields,必然 AttributeError)

HandlesClassDef: union 载荷尺寸经不存在的 ir.DataLayout 静默退化成 8 字节;HandlesExprCall/ExprBuiltin: sizeof 各静默 0 分支改 fail-fast,数组元素 sizeof 统一走 _get_struct_size

HandlesFor: nonlocal struct/array 堆分配不再退化成 malloc(8)

vast/vast_c: 补一元 * / & 解析,装饰器后 extern/export 分派修复,C 侧报错带 token 与行号;StubGen.Converter: 宏展开丢尾随空行修 .pyi 缩进非法

其余为 rawptr 迁移 / fail-fast 口径等历史改动一并入库
2026-09-26 19:27:22 +08:00
TermiNexus 76d1ee6076 fix(compiler,peephole): TPC 属性链解析与窥孔输出瘦身
- TPC(lib/core): 任意级属性链按链前向类解析恢复 stub 退化字段; cast 局部 rowptr[X] 登记回填; 通用指针槽按静态类名 bitcast 兜底; 赋值 RHS 求值失败 fail-fast 防未初始化变量; 报错行按源码文本锚定并附 ATTR-DIAG 现场
- 窥孔(includes/llvmlite/__function.vp): 成员访问单级链模式; 窥孔移至 Renumber 前使 SSA 编号连续; T3 no-op bitcast 消除; 替换缓冲按最坏上界分配
- __builder/__module/string.vp 配套; 清理 Test 构建产物与 PROF 杂项
2026-09-08 11:02:37 +08:00
TermiNexus 45e78ad107 基线重置,修复了一些 bug 2026-09-07 14:46:02 +08:00
TermiNexus 50ca560563 fix(tpc): list 联合类型方法分派保护 + str 压平条件收紧 + external global 裸名兼容
- HandlesAssign: 变量已有同 base 声明类型时不再覆盖 var_struct_class(sha1 前缀特化名覆盖裸名,导致 dbody.get 查表 miss 后 fallback 到 list[int].get,i32 返回值被截断成垃圾指针崩溃——TPC 侧根治)
- HandlesExprCall: IdentifiedStructType 真值判断改 is None(opaque 时 bool() 触发 __len__ assert)
- HandlesFunctions/HandlesImports: IsStr 压平条件加 PtrCount<=1,str|t.CPtr(i8**) 不压平;external global 正则兼容裸名格式
2026-08-24 23:31:08 +08:00
TermiNexus 015d5c38ea fix(global): external 声明升级用 initializer 判空(llvmlite.ir 无 is_declaration 属性)
上次修复用 getattr(g, 'is_declaration') 判断声明态,但该属性仅在
llvmlite.binding 层存在,ir.GlobalVariable 没有 -> 恒 False -> 升级不生效,
_g_gen 依旧无定义。改用 initializer is None 判断(external 声明必无
initializer;已定义全局必有),验证 common + null initializer 可设。
2026-08-20 07:53:33 +08:00
TermiNexus c904fac54d fix(global): import 注入的 external 全局声明遇本模块定义时升级为 common
根因:_EmitExternalGlobalDeclLlvm 把被 import 模块的下划线私有全局
(如各 Handles 模块 _g_gen)以裸名 external 声明注入本模块 module.globals,
_EmitGlobalAnnAssignLlvm 的"VarName in module.globals"误判已存在而跳过定义
创建 -> 全工程 _g_gen 无定义 -> ld.lld undefined symbol: _g_gen。

修复:定义端检测到 existing_gv 是 external 声明(is_declaration)时,
升级为 common linkage + null 初值(多模块同名合并为零值,对齐 _mbuddy
模式),而非静默跳过。
2026-08-20 07:46:36 +08:00
TermiNexus 6fc9e19e24 feat(vast): 新增自研 Viper/Python 语法解析器取代标准库 ast
TPC 侧取缔对 Python 标准库 ast 模块的依赖,改用 lib/vast 包:
- Nodes: 与 CPython 3.12 ast 完全同构的 131 个节点类(含抽象基类继承)
- Tokenizer: 词法分析(缩进/字符串/f-string/数字/运算符/软关键字)
- ExprParser: 表达式递归下降解析(优先级/lambda/推导式/f-string/切片)
- Parser: 语句解析(def/class/if/for/try/with/match/import/注解)
- Utils/Unparser: walk/dump/unparse/copy_location/literal_eval 等辅助
- 软关键字 fn/fun/func/function 并入解析器, 废除 ExpandSoftKeywords 预处理
- lib/_bootstrap 将 lib 目录加入 sys.path, import vast as ast 零修改替换
- 52 个文件 import ast 替换为 import vast as ast; 94 文件差分测试 0 失败
2026-08-17 09:36:38 +08:00
TermiNexus 2f0b741d55 fix(gen): TPC 治本——struct opaque 具化、多返回值 fail-fast、with MRO 修复
1. HandlesExprCall: vtable 分派前 _EnsureReceiverStructConcrete 主动具化 struct
   body(stub + class_members 双路径),消除元数据已注册、本体仍 opaque 的
   撕裂状态,失败即 fail-fast 暴露上游 stub 加载时序问题;
2. HandlesImports: stub 加载后仍 opaque 时不保留成功缓存(可重试),
   避免 opaque 状态被固化导致 vtable 分派 GEP 崩溃;
3. HandlesAssign: 跨模块多返回值 CReturnTypes 恢复(LiteralStructType 回退)
   + 解析失败 fail-fast,不再静默跳过致目标变量未初始化触发堆损坏;
4. HandlesWith: MRO 继承方法解析跳过无函数体的 stub declare(Phase1 继承
   包装声明),bitcast 目标改用函数签名参数类型避免 opaque 占位对象。
2026-08-13 07:51:27 +08:00
TermiNexus 8ccf5d2c18 fix(TPC/includes): 泛型特化 linkonce_odr + None 全局 common + includes 前缀
- TPC HandlesFunctions/HandlesClassDef: 泛型特化类方法(类名含 '[')设
  linkonce_odr,消除 GSList[NameEntry].__before_init__ 等 duplicate symbol
- TPC HandlesAssign: None 初值模块级全局用 common linkage,合并 _g_gen 等
  跨模块同名全局重复定义
- includes: binascii/hashlib 裸调用加 stdlib./string. 前缀(malloc/free/memset/memcpy)
- llvmlite: FunctionPrint 泛型特化方法输出 define linkonce_odr;__module 调整
- 删除 wiki/01-overview.md
2026-08-12 18:18:22 +08:00
TermiNexus a39b5da0f8 基本稳定 2026-08-05 20:11:38 +08:00
TermiNexus 0a10b20dde 修正了逻辑,使 TPV 能够正常编译 2026-08-03 02:00:49 +08:00
TermiNexus 4e17365b76 修正了 args 传参问题 2026-07-31 17:15:54 +08:00
TermiNexus ca7c2120b8 修正了种子编译器的错误 2026-07-22 21:55:36 +08:00
TermiNexus 135aa05485 尝试进行 Qt 测试,增加了 AI 人机调试工具 _console,以及 TransPyV 进行修正 2026-07-21 14:41:22 +08:00
TermiNexus a277ded8d4 修正了 TPC 的一些错误,包括 Test 维护后 TPV 无法重新编译或重编译后越界的部分问题 2026-07-20 11:12:30 +08:00
t 796222a300 snapshot before regression test 2026-07-18 19:25:40 +08:00