12 KiB
TransPyC 自举可行性分析
状态:进行中
创建时间:2026-06-26
最后更新:2026-06-30
结论:完全自举可行,核心障碍已被攻克,剩余工作明确
1. 背景
自举(bootstrapping)指用 TransPyC 语言重写 TransPyC 编译器自身,然后用现有编译器编译,得到新的原生编译器。本文档分析自举的可行性、进展与剩余工作。
当前目标:完全自举。TransPyC 的定位是独立的系统级语言,不是"Python → 原生 的工具"。自举是语言成熟度的证明,也是脱离 Python 运行时性能限制的必经之路。
2. LOC 统计
2.1 编译器主体(lib 目录)
| 子目录 | 文件数 | LOC | 说明 |
|---|---|---|---|
lib/core |
64 | 28,610 | 编译器核心 |
├─ core/Handles |
30 | 18,885 | AST 节点处理器(最大模块) |
├─ core/LLVMCG |
8 | 2,782 | LLVM 代码生成 |
└─ core/Translator |
6 | 1,751 | 翻译器框架 |
lib/Projectrans |
6 | 4,371 | 项目级翻译(Phase1/Phase2) |
lib/StubGen |
4 | 1,187 | Stub 生成器 |
lib/Shell |
4 | 630 | CLI 入口 |
lib/includes |
2 | 1,609 | t.py(968) + c.py(641) 类型定义 |
lib/utils |
1 | 40 | 辅助 |
lib/constants |
1 | 36 | 配置 |
| lib 总计 | 80 | 36,483 |
2.2 Top 15 文件
| 文件 | LOC |
|---|---|
lib/core/Handles/HandlesExprCall.py |
3,153 |
lib/Projectrans/Phase2Translator.py |
2,693 |
lib/core/Handles/HandlesImports.py |
1,994 |
lib/core/Handles/HandlesFunctions.py |
1,612 |
lib/core/Handles/HandlesAssign.py |
1,544 |
lib/core/Handles/HandlesExprAttr.py |
1,168 |
lib/core/Handles/HandlesClassDef.py |
1,039 |
lib/core/Handles/HandlesFor.py |
997 |
lib/core/Handles/HandlesTypeMerge.py |
991 |
lib/includes/t.py |
968 |
lib/StubGen/Converter.py |
893 |
lib/core/Handles/HandlesExprBuiltin.py |
868 |
lib/Projectrans/DeclarationGenerator.py |
845 |
lib/core/Handles/HandlesBase.py |
756 |
lib/core/stub_generator.py |
699 |
2.3 运行时库(includes 目录)
| 模块 | LOC | 说明 |
|---|---|---|
includes/numpy/__init__.py |
1,016 | ndarray n 维数组 |
includes/zlib/ |
~1,900 | 完整 deflate/inflate/huffman/checksum |
includes/ast/ |
4,176 | 自研 Python 解析器(自举组件) |
includes/llvmlite/ |
~1,500 | 自研 LLVM IR 生成库(自举组件) |
includes/linkedlist.py |
~400 | 泛型链表(@t.NoVTable + PEP 695) |
includes/vipermath.py |
450 | 数学库 |
| ...(30+ 文件) | ... | mpool/mbuddy/string/stdio/json/w32 等 |
| includes 总计 | ~12,000 |
2.4 全项目总计
全项目 .py 总计:~48,000 LOC
自举相关核心数字:
- 编译器主体(lib 不含 t.py/c.py):~34,874 LOC
- 自举基础组件(includes/ast + includes/llvmlite):~5,700 LOC ✅ 已完成
- 运行时库(includes 其余):~9,500 LOC
3. 自举进展(已完成的核心组件)
3.1 ✅ includes/ast —— Python 解析器自举
状态:完成,AstTest 通过(解析 CPython 几乎全部语法)
| 文件 | LOC | 功能 |
|---|---|---|
__tokens.py |
~600 | TokenType/Keyword/TokOp 枚举 + 查找表 |
__nodes.py |
~1,400 | AST 胖节点 + ASTVType/ASTCtx/OpKind CEnum |
__lexer.py |
~800 | 词法分析器 |
__parser.py |
4,176(含表格) | 递归下降语法分析器 |
覆盖语法:装饰器、async/await、match(含复杂模式 [x,*rest]/{'type':t,**rest}/Point(x,y)/0|1|2)、try/except/finally/raise from、with、lambda、列表/集合/字典/生成器推导式、f-string(含 !r/!s 转换和 :>{width} 格式说明)、链式比较、walrus、yield from、global/nonlocal、切片、嵌套三元。
设计要点:
- 胖节点设计(所有节点共用一个
ASTstruct,用vtype区分)—— 避免 REnum 在 70+ 变体下的内存膨胀 - 从
mpool.MPool分配,零 Python 运行时依赖 - API 与 Python
ast模块对齐:parse(src, pool) -> AST
3.2 ✅ includes/llvmlite —— LLVM IR 生成库自举
状态:完成,LLvmLiteTest 18/18 通过,TransPyV 自举实验跑通
| 文件 | 功能 |
|---|---|
__types.py |
LLVMType REnum + 类型构造/打印 |
__values.py |
Value/Constant/SSA 值表示 |
__function.py |
Function + BasicBlock + 参数管理 |
__module.py |
Module 容器 + 目标三元组 + 输出 .ll |
__builder.py |
IRBuilder(指令发射 + SSA 命名) |
设计要点:
LLVMType用t.REnum(tagged union)—— 少变体、无通用字段、match 分派的理想场景- 指令 opcode 用
t.CEnum(IROp)—— 类型安全且零开销 - IR 文本生成用
viperlib.snprintf格式化,避免手写逐字符拼接 - 对象分配用普通类 +
mpool,不持有全局mbuddy
验证:TransPyV/App/main.py 10 个测试覆盖类型打印、值打印、build_add、if-else、模块打印、lli 实际执行。TransPyV 程序运行时自己生成合法 IR,被 lli 成功执行。
3.3 ✅ 基础设施库
以下 includes/ 库为自举后的编译器提供数据结构和系统调用基础:
| 库 | 自举中的作用 |
|---|---|
linkedlist.py |
AST 节点树、符号表链、IR 指令链的容器(@t.NoVTable + PEP 695 递归泛型继承) |
mpool.py / mbuddy.py |
编译器内存管理(替代 Python GC) |
string.py / viperlib.py |
字符串处理 + snprintf(替代 Python 字符串方法) |
w32/ |
FFI 声明,自举后编译器调用 llc/clang/linker 的基础 |
json/ |
符号表序列化(替代 pickle) |
4. 障碍分析(修正版)
原版本文档列出的"三大致命依赖"已被逐一攻克或降级:
4.1 llvmlite 依赖(原:致命) → ✅ 已解决
原问题:编译器通过 llvmlite.ir 生成 IR,TransPyC 无法调用 Python 库。
解决:includes/llvmlite/ 用 TransPyC 自身实现了 LLVM IR 文本生成库,API 与 Python llvmlite.ir 对齐。采用"字符串拼 IR"路径(路径 A),不绑定 LLVM C API。18/18 测试通过,TransPyV 自举实验验证可生成可执行 IR。
4.2 ast 模块依赖(原:致命) → ✅ 已解决
原问题:编译器用 Python ast 模块解析源码,自举需自己写 Python 解析器(预计 5,000-10,000 LOC)。
解决:includes/ast/ 4,176 LOC 实现完整 Python 解析器,AstTest 解析 CPython 凥乎全部语法通过。预言已兑现,且实际规模(4,176 LOC)低于预估下限(5,000 LOC)。
4.3 动态反射 4241 处(原:致命) → ⚠️ 降级为可控
原问题:getattr/setattr/hasattr/isinstance/issubclass 共 4,241 处,静态语言无法直接表达。
修正分析:4241 这个数字按 Python 语法 grep 统计,未区分"语义上需要反射"和"用反射偷懒"。实际分类:
| 用法 | 数量估计 | 是否真反射 | TransPyC 解法 |
|---|---|---|---|
isinstance(node, ast.Xxx) AST 节点分派 |
~2000 | ❌ 否 | 胖节点 node.vtype == ASTVType.Xxx 整数比较 |
isinstance(x, ir.IntType) IR 类型分派 |
~500 | ❌ 否 | REnum match x: case LLVMType.Int: tag 比较 |
getattr(t, name, None) 字符串→类型查表 |
~35 | ❌ 否 | 注册表 t_type_registry: dict[str, t.CInt] |
CTypeInfo.__getattr__ 门面路由 |
~100 | ✅ 是 | 重构为 REnum + match 显式分派 |
copy.deepcopy / pickle |
~10 | ✅ 是 | 已解决(__getstate__/__setstate__) |
hasattr 防御性检查 |
~1500 | ⚠️ 多数可消除 | 显式字段声明 + None 检查 |
真实反射障碍约 200-500 处,集中体现在 CTypeInfo 门面模式(FIELD_ROUTES 动态路由到 _ts/_sm)。重构方案:用 REnum + match 替换 __getattr__ 路由,已在 includes/llvmlite/__types.py 验证此范式可行。
4.4 Python 标准库依赖(原:严重)→ ⚠️ 部分已解决
| Python 库 | 用途 | TransPyC 现状 |
|---|---|---|
ast |
源码解析 | ✅ includes/ast/ |
llvmlite.ir |
LLVM IR 生成 | ✅ includes/llvmlite/ |
json |
序列化 | ✅ includes/json/ |
os/sys |
文件/路径 | ⚠️ includes/os/ + w32/(Windows) |
subprocess |
调用 llc/clang | ❌ 待实现(w32 CreateProcess 可基础) |
pickle |
符号表序列化 | ❌ 待实现(json 替代) |
concurrent.futures |
并行编译 | ❌ 待实现(w32 线程可基础) |
re |
正则表达式 | ❌ 待实现 |
traceback |
异常栈 | ❌ 待实现 |
5. 自举路径
5.1 路径 A:完全自举(当前目标,可行)
已完成:
- ✅
includes/ast/Python 解析器(4,176 LOC) - ✅
includes/llvmlite/LLVM IR 生成库(~1,500 LOC) - ✅ 基础设施库(linkedlist/mpool/mbuddy/string/json/w32)
剩余工作:
- CTypeInfo 门面重构(~200-500 处真反射 → REnum + match)
- lib/core 重写(~20K LOC TransPyC,含 Handles/LLVMCG/Translator)
- lib/Projectrans 重写(~5K LOC,Phase1/Phase2/DeclarationGenerator)
- lib/StubGen 重写(~2K LOC)
- Python 标准库缺口补齐(os/subprocess/re/pickle,~5K LOC)
预计新增代码量:30-35K LOC TransPyC。与已完成的 includes/ast(4,176 LOC)+ includes/llvmlite(~1,500 LOC)+ 其他基础库为同一量级——已经证明过两次能做这件事。
5.2 关键技术验证点(已完成)
以下能力已在 includes/ 库中验证,证明 TransPyC 能承载编译器复杂度:
- 复杂泛型容器:
linkedlist.py的递归泛型继承class GNode(GSListNode[GNode])(C/C++/Rust 均无法如此简洁表达) - 复杂算法:
zlib/的完整 deflate/inflate/huffman(~1,900 LOC 生产级压缩) - n 维数组:
numpy/__init__.py的 ndarray + 运算符重载 +__new__堆分配 - 平台 FFI:
w32/的 Win32 API 绑定(file/memory/process/sync/console) - LLVM IR 生成:
llvmlite/的 REnum 类型系统 + IRBuilder + ModulePrint
6. 自举的意义
-
性能:当前 Python 编译器翻译 6 个文件 0.6s,全量编译 36K LOC 编译器自身时 Python 解释器开销显著。自举后编译器是原生码,编译速度数量级提升。
-
部署:当前分发需 Python 运行时 + llvmlite + ast 依赖。自举后只需一个可执行文件 + llc/clang——系统级语言编译器该有的形态。
-
语言成熟度证明:能写自己的编译器是系统级语言的"成人礼"。C、C++、Rust、Go、Zig 全都走过这条路。
-
dogfooding 闭环:自举后每次改编译器都用编译器自己编译自己,持续暴露 bug 和性能瓶颈,形成正反馈。
includes/ast和includes/llvmlite的开发过程已经产出了大量深层 bug 修复(REnum 变体名冲突、跨模块继承字段展平、NoVTable OOP 方法继承等)。
7. 结论
| 维度 | 评估 |
|---|---|
| 理论可行性 | ✅ 可行(图灵完备) |
| 实践可行性 | ✅ 完全自举可行(核心障碍已攻克) |
| 当前进展 | ⚠️ 前端(ast)+ 后端(llvmlite)+ 基础库已就位,剩中间层(lib/core)重构 |
| 剩余工作量 | ~30-35K LOC TransPyC 重写 + CTypeInfo 门面重构 |
| 推荐策略 | 路径 A:完全自举,按 lib/core → lib/Projectrans → lib/StubGen 顺序推进 |
核心判断:原版本文档的"三大致命依赖"结论已全部失效——llvmlite 和 ast 已被 includes/ 下的自研库替代,4241 处反射中 90% 是工程偷懒而非语义需要。完全自举从"几乎不可能"变为"明确可行",剩余工作是体量问题而非技术障碍。
8. 附录:原版本文档的修正说明
本文档(2026-06-30 版)修正了 2026-06-26 原版的以下错误判断:
| 原版断言 | 修正 |
|---|---|
| "完全自举几乎不可能" | 完全自举可行,核心障碍已攻克 |
| "llvmlite 依赖致命" | 已被 includes/llvmlite/ 解决(18/18 测试) |
| "ast 模块依赖致命" | 已被 includes/ast/ 解决(4,176 LOC,AstTest 通过) |
| "4241 处动态反射致命" | 90% 是工程偷懒(isinstance 节点分派/IR 类型分派),真实反射约 200-500 处 |
| "推荐路径 C:不自举" | 推荐路径 A:完全自举 |
| "预计自举后 60K-80K LOC" | 修正为 30-35K LOC(基础组件已 5,700 LOC 完成) |