取消了 i8* == i8* 实际使用 strcmp 的规则
This commit is contained in:
@@ -11,13 +11,13 @@ TransPyC 已用自身实现以下组件,证明其作为系统级语言的成
|
||||
- **自研 LLVM IR 生成库** —— [includes/llvmlite/](includes/llvmlite/)(~1,500 LOC),用 TransPyC 自己写的 IR 文本生成器,18/18 测试通过
|
||||
- **zlib 移植** —— [Test/ZlibTest/](Test/ZlibTest/),完整 deflate/inflate/huffman/checksum(~1,900 LOC)
|
||||
- **Win32 FFI 绑定** —— [includes/w32/](includes/w32/),file/memory/process/sync/console 全覆盖
|
||||
- **泛型容器** —— [includes/linkedlist.py](includes/linkedlist.py),`@t.NoVTable` + PEP 695 递归泛型继承 `class GNode(GSListNode[GNode])`
|
||||
- **泛型容器** —— [includes/linkedlist.vp](includes/linkedlist.vp),`@t.NoVTable` + PEP 695 递归泛型继承 `class GNode(GSListNode[GNode])`
|
||||
|
||||
## 核心设计理念
|
||||
|
||||
- **Python 语法,LLVM 语义**:源文件是合法的 Python 语法,但通过 `t` 模块类型注解赋予 LLVM 级别的语义
|
||||
- **类型注解即编译指令**:类型注解决定 LLVM IR 的生成,不是可选的提示
|
||||
- **两阶段编译**:先提取声明接口(`.pyi` + `.stub.ll`),再翻译源文件为含代码的 `.ll`
|
||||
- **两阶段编译**:先提取声明接口(`.vpi` + `.stub.ll`),再翻译源文件为含代码的 `.ll`
|
||||
- **SHA1 命名空间**:每个源文件按内容 SHA1 哈希命名,自动消除跨模块符号冲突
|
||||
- **零运行时开销**:编译为原生代码,无 GC、无解释器、无虚拟机
|
||||
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -3,8 +3,7 @@
|
||||
"name": "TransPyV",
|
||||
"version": "1.0.0",
|
||||
"source_dir": "./App",
|
||||
"temp_dir": "./temp",
|
||||
"output_dir": "./output",
|
||||
"build_dir": "./.tpv_build",
|
||||
"compiler": {
|
||||
"cmd": "llc",
|
||||
"flags": ["-filetype=obj", "-relocation-model=pic"]
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1,9 +1,8 @@
|
||||
067c78e9f121dce3:includes/w32\win32process.vp
|
||||
06f53cc594b4ac6c:includes/w32\win32sync.vp
|
||||
0c67644125bea0fd:includes/sys.vp
|
||||
0ccfde54972334b1:lib/core/Handles/HandlesImports.vp
|
||||
0df65b8ed15664b0:includes/hashlib\__sha1.vp
|
||||
1073ffca7e27aae5:lib/core/Handles/HandlesFunctions.vp
|
||||
15bb32adb7093ed7:lib/core/Handles/HandlesAnnAssign.vp
|
||||
19f8024d10c828e8:includes/hashlib\__md5.vp
|
||||
1d74d1d3a174c684:includes/llvmlite\__init__.vp
|
||||
20cd49775c100a38:includes/json\__writer.vp
|
||||
@@ -11,70 +10,71 @@
|
||||
240a9a4157959a9f:includes/json\__parser.vp
|
||||
285b6aa29a34754d:includes/stdio.vp
|
||||
28de517e3820658a:includes/posix.vp
|
||||
2b30cc2ce96fa464:lib/core/Handles/HandlesType.vp
|
||||
2b59175b77f1304e:lib/core/Handles/HandlesAssign.vp
|
||||
2b77d783c41d21d1:includes/hashtable.vp
|
||||
2d8debefda779c40:includes/llvmlite\__types.vp
|
||||
2fbec3db55b30ad4:includes/hashtable.vp
|
||||
31e49accebfc8aac:lib/core/Handles/HandlesAugAssign.vp
|
||||
371fa89e15d8c015:lib/core/Handles/HandlesStruct.vp
|
||||
3aa6057398be5673:includes/stdlib.vp
|
||||
3c5f1c61545644a9:lib/StubGen/Converter.vp
|
||||
4337fb260448bbe2:includes/ast\astaux.vp
|
||||
456fb516ba3c5002:lib/core/Handles/HandlesFor.vp
|
||||
4650533467115342:lib/Projectrans/Utils.vp
|
||||
484879ffecdf2b08:main.vp
|
||||
4a7b57e6bd18f65e:lib/core/Handles/HandlesMain.vp
|
||||
4c644ade1f0d6d02:lib/core/Handles/HandlesReturn.vp
|
||||
4daf5ed3f8e421a1:includes/string.vp
|
||||
4dd6b3f1427d1cc5:includes/ast\match.vp
|
||||
57288496f7c2d1ad:includes/json\__init__.vp
|
||||
4e052c29b4fe769c:lib/core/IncludesScanner.vp
|
||||
53812752bc672fdb:lib/core/Handles/HandlesAnnAssign.vp
|
||||
553972e4135f827e:lib/core/Phase1.vp
|
||||
5a1d8c48f1243746:includes/llvmlite\__builder.vp
|
||||
62805d8ad3e9b5ba:lib/core/Handles/HandlesTranslator.vp
|
||||
6293eee0a5805aa5:lib/core/Handles/HandlesImports.vp
|
||||
63a3d17e96a083ac:lib/core/Handles/HandlesBase.vp
|
||||
657e182b27c2a022:includes/ast\stmts.vp
|
||||
692919c5a194ac8d:includes/llvmlite\__module.vp
|
||||
6a19179426e9a883:lib/__init__.vp
|
||||
6b3bc463fd044545:includes/llvmlite\__verify.vp
|
||||
6ddf430432a0e373:includes/json\__init__.vp
|
||||
6ff26590374ae6fc:includes/hashlib\__sha512.vp
|
||||
71e0a3ffcb3ebfad:includes/stdarg.vp
|
||||
72dbbb563aa943b0:includes/w32\fileio.vp
|
||||
787e3cfd2e1cf583:lib/core/Handles/HandlesExpr.vp
|
||||
7cadfe07e983fd90:includes/_list.vp
|
||||
81eb28ba912467a6:lib/core/Handles/HandlesBody.vp
|
||||
82ee4327adfe0c18:lib/core/Handles/HandlesExprCall.vp
|
||||
874bac141c97bae9:includes/llvmlite\__function.vp
|
||||
8d6185cf886c0334:lib/core/IncludesScanner.vp
|
||||
8dc65d4c71e2936a:lib/core/Handles/HandlesWhile.vp
|
||||
96837bcc64032444:includes/hashlib\__init__.vp
|
||||
9dbc46e5249ed198:lib/core/StubMerger.vp
|
||||
a26c73d7332b54b4:lib/core/StubMerger.vp
|
||||
a335eb99f2e34479:includes/subprocess.vp
|
||||
a38b726f4a82545f:lib/core/BuildPipeline.vp
|
||||
a5e9a83e9db303ad:includes/linkedlist.vp
|
||||
aa246c6e6aa30484:includes/atom.vp
|
||||
aa34a7a33a3afab0:lib/core/Phase2.vp
|
||||
aa45364399b86a03:lib/core/Handles/HandlesClassDef.vp
|
||||
af1cc6aaab47a7d1:lib/core/Handles/HandlesType.vp
|
||||
af9484a65085bf4b:lib/core/Handles/HandlesNonlocal.vp
|
||||
b370d93b74bf55cc:includes/argparse.vp
|
||||
b543bc1dfb592119:includes/ast\exprs.vp
|
||||
b547ac4f380bddb6:includes/ast\tokens.vp
|
||||
b57252077e6b596b:includes/platmacro.vp
|
||||
b8a6e05318020e54:lib/core/Handles/HandlesFunctions.vp
|
||||
bbdf3bbd4c3bc28c:includes/w32\win32console.vp
|
||||
bde6b4cc0847ee6d:lib/core/Handles/HandlesExpr.vp
|
||||
bdf5730851fb95f2:lib/core/VLogger.vp
|
||||
be8c2d7b882881c8:lib/core/Handles/HandlesExprOps.vp
|
||||
c0042adc0b7ec5df:lib/Projectrans/Config.vp
|
||||
c1bb03b1eae141e0:lib/core/Phase2.vp
|
||||
c2a4277744568003:lib/__init__.vp
|
||||
c9d54a4158f7f5a8:includes/hashlib\__sha256.vp
|
||||
c9f4be41ca1cc2b4:includes/viperio.vp
|
||||
ca40915f11b8b6ad:includes/memhub.vp
|
||||
cb1aa3a78af6f362:lib/core/Handles/HandlesVar.vp
|
||||
cba5876ccb277f42:lib/StubGen/Converter.vp
|
||||
e217def267d3d4a8:includes/ast\lexer.vp
|
||||
e307a2d809cef071:includes/viperlib.vp
|
||||
efefa18c5d6c2d81:lib/core/Handles/HandlesExprCall.vp
|
||||
f05b14a2ad5767a7:lib/core/Handles/HandlesEnum.vp
|
||||
f30a3b2d5f6bf092:main.vp
|
||||
f3444ec56937284f:includes/ast\__init__.vp
|
||||
f4cdbca2f8802c12:lib/core/Handles/HandlesIf.vp
|
||||
f5522571bcce7bcb:includes/stdint.vp
|
||||
f6b51804a0ba8ff0:includes/w32\win32file.vp
|
||||
f9e36e2cd6fa659f:includes/llvmlite\__values.vp
|
||||
fc26f66203d7cbb7:lib/core/Phase1.vp
|
||||
fc980acec33d69a7:includes/w32\win32base.vp
|
||||
fde6db0747bdd959:includes/ast\parser.vp
|
||||
|
||||
Binary file not shown.
@@ -61,7 +61,7 @@ class dict:
|
||||
"""Find index of target key; returns __count__ if not found"""
|
||||
for i in range(self.__count__):
|
||||
key_ptr: str | t.CPtr = t.CPtr(t.CUInt64T(self.__keys__) + i * 8)
|
||||
if key_ptr[0] == key: return i
|
||||
if string.strcmp(key_ptr[0], key) == 0: return i
|
||||
return self.__count__
|
||||
|
||||
def __getitem__(self, key: str) -> t.CPtr:
|
||||
|
||||
@@ -111,7 +111,7 @@ class HashTable:
|
||||
else:
|
||||
if sh == h:
|
||||
sk: str = self._slot_key(idx)
|
||||
if sk == key:
|
||||
if string.strcmp(sk, key) == 0:
|
||||
return idx
|
||||
idx = (idx + 1) & mask
|
||||
i += 1
|
||||
|
||||
@@ -86,7 +86,7 @@ class JsonValue:
|
||||
cur: JsonValue | t.CPtr = self.child
|
||||
while cur != None:
|
||||
if cur.key != None:
|
||||
if cur.key == key:
|
||||
if string.strcmp(cur.key, key) == 0:
|
||||
return cur
|
||||
cur = cur.next
|
||||
return None
|
||||
@@ -98,7 +98,7 @@ class JsonValue:
|
||||
cur: JsonValue | t.CPtr = self.child
|
||||
while cur != None:
|
||||
if cur.key != None:
|
||||
if cur.key == key:
|
||||
if string.strcmp(cur.key, key) == 0:
|
||||
cur.vtype = val.vtype
|
||||
cur.bool_val = val.bool_val
|
||||
cur.int_val = val.int_val
|
||||
@@ -212,7 +212,7 @@ def object_set(pool: memhub.MemManager | t.CPtr, obj: JsonValue | t.CPtr, key: t
|
||||
cur: JsonValue | t.CPtr = obj.child
|
||||
while cur != None:
|
||||
if cur.key != None:
|
||||
if cur.key == key:
|
||||
if string.strcmp(cur.key, key) == 0:
|
||||
cur.vtype = val.vtype
|
||||
cur.bool_val = val.bool_val
|
||||
cur.int_val = val.int_val
|
||||
|
||||
@@ -25,7 +25,7 @@ LLVM 类型变体少、无通用字段、字段都是指针/小整数、操作
|
||||
|
||||
### 2.4 对象分配用普通类 + `mpool`
|
||||
|
||||
像 `mbuddy` 一样用普通类(无 `__new__`),由调用方注入 `mpool.MPool` 做批量分配。库内部不持有全局 `mbuddy`,遵循项目约定(`_mbuddy` 指针由 `os.py` 或调用方设置)。
|
||||
像 `mbuddy` 一样用普通类(无 `__new__`),由调用方注入 `mpool.MPool` 做批量分配。库内部不持有全局 `mbuddy`,遵循项目约定(`_mbuddy` 指针由 `os.vp` 或调用方设置)。
|
||||
|
||||
---
|
||||
|
||||
@@ -68,22 +68,22 @@ AST 采用"胖节点"设计(所有节点共用一个 `AST` struct,用 `vtype
|
||||
|
||||
```
|
||||
includes/llvmlite/
|
||||
├── __init__.py # 公共导出 + 便捷工厂函数
|
||||
├── __types.py # LLVMType (REnum) + 类型构造/打印
|
||||
├── __values.py # Value/Constant/SSA 值表示
|
||||
├── __module.py # Module 容器(函数列表 + 目标三元组 + 输出 .ll)
|
||||
├── __function.py # Function + BasicBlock + 参数管理
|
||||
├── __builder.py # IRBuilder(指令发射 + SSA 命名 + 块跳转)
|
||||
├── __init__.vp # 公共导出 + 便捷工厂函数
|
||||
├── __types.vp # LLVMType (REnum) + 类型构造/打印
|
||||
├── __values.vp # Value/Constant/SSA 值表示
|
||||
├── __module.vp # Module 容器(函数列表 + 目标三元组 + 输出 .ll)
|
||||
├── __function.vp # Function + BasicBlock + 参数管理
|
||||
├── __builder.vp # IRBuilder(指令发射 + SSA 命名 + 块跳转)
|
||||
└── README.md # 本文件
|
||||
```
|
||||
|
||||
### 职责划分
|
||||
|
||||
- `__types.py`:`LLVMType` REnum 定义 + `TypePrint(buf, ty)` 将类型序列化为 IR 文本(如 `i32`/`i32*`/`{i32, i8*}`)
|
||||
- `__values.py`:`Value` 表示一个 SSA 值(`%0`/`%result`/常量),含类型指针 + 名字 + 是否常量
|
||||
- `__module.py`:`Module` 持有函数链表 + 目标三元组 + 数据布局,`ModulePrint` 输出完整 `.ll`
|
||||
- `__function.py`:`Function` 持有基本块链表 + 参数 + 返回类型;`BasicBlock` 持有指令文本缓冲
|
||||
- `__builder.py`:`IRBuilder` 游标式 API,`build_add`/`build_load`/`build_br`/... 发射指令到当前块
|
||||
- `__types.vp`:`LLVMType` REnum 定义 + `TypePrint(buf, ty)` 将类型序列化为 IR 文本(如 `i32`/`i32*`/`{i32, i8*}`)
|
||||
- `__values.vp`:`Value` 表示一个 SSA 值(`%0`/`%result`/常量),含类型指针 + 名字 + 是否常量
|
||||
- `__module.vp`:`Module` 持有函数链表 + 目标三元组 + 数据布局,`ModulePrint` 输出完整 `.ll`
|
||||
- `__function.vp`:`Function` 持有基本块链表 + 参数 + 返回类型;`BasicBlock` 持有指令文本缓冲
|
||||
- `__builder.vp`:`IRBuilder` 游标式 API,`build_add`/`build_load`/`build_br`/... 发射指令到当前块
|
||||
|
||||
---
|
||||
|
||||
@@ -120,7 +120,7 @@ class LLVMType(t.REnum):
|
||||
# (REnum 允许空变体,仅靠 __tag 区分)
|
||||
```
|
||||
|
||||
### 类型工厂(`__init__.py` 导出)
|
||||
### 类型工厂(`__init__.vp` 导出)
|
||||
|
||||
```python
|
||||
def Int1() -> LLVMType | t.CPtr: ... # i1
|
||||
@@ -295,7 +295,7 @@ def ModulePrint(mod: Module | t.CPtr, out_path: t.CChar | t.CPtr):
|
||||
## 12. 与现有架构的对接点
|
||||
|
||||
- **`lib/core/Codegen/LLVMCG.py`**:当前用 Python `llvmlite` 生成 IR,自举时改用本库
|
||||
- **`includes/viperlib.py`**:提供 `snprintf` / `sprintf`
|
||||
- **`includes/mpool.py`**:提供 `MPool` 内存池
|
||||
- **`includes/string.py`**:提供 `strcpy`/`strlen`/`memcpy`
|
||||
- **`includes/viperlib.vp`**:提供 `snprintf` / `sprintf`
|
||||
- **`includes/mpool.vp`**:提供 `MPool` 内存池
|
||||
- **`includes/string.vp`**:提供 `strcpy`/`strlen`/`memcpy`
|
||||
- **`includes/ast/`**:参考其"胖节点 + mpool + CEnum 常量"的组织方式(但类型系统用 REnum 而非胖节点)
|
||||
|
||||
@@ -63,7 +63,7 @@ def strcmp(str1: str, str2: str) -> t.CInt:
|
||||
return str1[0] - str2[0]
|
||||
|
||||
def samestr(str1: str, str2: str) -> bool:
|
||||
return str1 == str2
|
||||
return strcmp(str1, str2) == 0
|
||||
|
||||
|
||||
# String compare function with limited length
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
```
|
||||
+--------------------+ +-----------------------+ +------------+
|
||||
| Viper 用户代码 | FFI | vqt6 桥接层 (libvqt6) | C++ | Qt6 C++ |
|
||||
| (app.py) | <----> | - t.State 声明 | <-----> | QtCore |
|
||||
| (app.vp) | <----> | - t.State 声明 | <-----> | QtCore |
|
||||
| | | - C 桥接函数 | | QtGui |
|
||||
| vqt6.QApplication | | (extern "C") | | QtWidgets |
|
||||
| vqt6.QLabel | | - 静态库 / 动态库 | | QtNetwork |
|
||||
@@ -36,12 +36,12 @@ vqt6 同一套 C 桥接源代码,可同时编译为两种产物。Viper 项目
|
||||
```
|
||||
includes/vqt6/
|
||||
├── README.md # 本文件
|
||||
├── __init__.py # 公共 Pythonic API(用户使用)
|
||||
├── _types.py # 公共类型(不透明指针 typedef)
|
||||
├── _qtcore.py # QtCore 的 t.State FFI 声明
|
||||
├── _qtwidgets.py # QtWidgets 的 t.State FFI 声明
|
||||
├── _qtgui.py # QtGui 的 t.State FFI 声明
|
||||
├── _qtnetwork.py # QtNetwork 的 t.State FFI 声明
|
||||
├── __init__.vp # 公共 Pythonic API(用户使用)
|
||||
├── _types.vp # 公共类型(不透明指针 typedef)
|
||||
├── _qtcore.vp # QtCore 的 t.State FFI 声明
|
||||
├── _qtwidgets.vp # QtWidgets 的 t.State FFI 声明
|
||||
├── _qtgui.vp # QtGui 的 t.State FFI 声明
|
||||
├── _qtnetwork.vp # QtNetwork 的 t.State FFI 声明
|
||||
├── _bridge.h # C 桥接层头文件
|
||||
├── _bridge.cpp # C 桥接层实现(extern "C" 包装 Qt6 C++ API)
|
||||
└── CMakeLists.txt # 构建脚本(生成 libvqt6_bridge.a)
|
||||
@@ -50,7 +50,7 @@ includes/vqt6/
|
||||
## 使用示例
|
||||
|
||||
```python
|
||||
# App/main.py
|
||||
# App/main.vp
|
||||
import t
|
||||
import c
|
||||
import vqt6
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
```
|
||||
+--------------------+ +-----------------------+ +------------+
|
||||
| Viper 用户代码 | FFI | vqt6 桥接层 (libvqt6) | C++ | Qt6 C++ |
|
||||
| (app.py) | <----> | - t.State 声明 | <-----> | QtCore |
|
||||
| (app.vp) | <----> | - t.State 声明 | <-----> | QtCore |
|
||||
| | | - C 桥接函数 | | QtGui |
|
||||
| vqt6.QApplication | | (extern "C") | | QtWidgets |
|
||||
| vqt6.QLabel | | - 静态库 / 动态库 | | QtNetwork |
|
||||
@@ -36,12 +36,12 @@ vqt6 同一套 C 桥接源代码,可同时编译为两种产物。Viper 项目
|
||||
```
|
||||
includes/vqt6/
|
||||
├── README.md # 本文件
|
||||
├── __init__.py # 公共 Pythonic API(用户使用)
|
||||
├── _types.py # 公共类型(不透明指针 typedef)
|
||||
├── _qtcore.py # QtCore 的 t.State FFI 声明
|
||||
├── _qtwidgets.py # QtWidgets 的 t.State FFI 声明
|
||||
├── _qtgui.py # QtGui 的 t.State FFI 声明
|
||||
├── _qtnetwork.py # QtNetwork 的 t.State FFI 声明
|
||||
├── __init__.vp # 公共 Pythonic API(用户使用)
|
||||
├── _types.vp # 公共类型(不透明指针 typedef)
|
||||
├── _qtcore.vp # QtCore 的 t.State FFI 声明
|
||||
├── _qtwidgets.vp # QtWidgets 的 t.State FFI 声明
|
||||
├── _qtgui.vp # QtGui 的 t.State FFI 声明
|
||||
├── _qtnetwork.vp # QtNetwork 的 t.State FFI 声明
|
||||
├── _bridge.h # C 桥接层头文件
|
||||
├── _bridge.cpp # C 桥接层实现(extern "C" 包装 Qt6 C++ API)
|
||||
└── CMakeLists.txt # 构建脚本(生成 libvqt6_bridge.a)
|
||||
@@ -50,7 +50,7 @@ includes/vqt6/
|
||||
## 使用示例
|
||||
|
||||
```python
|
||||
# App/main.py
|
||||
# App/main.vp
|
||||
import t
|
||||
import c
|
||||
import vqt6
|
||||
|
||||
@@ -385,7 +385,7 @@ class ExprOpsHandle(BaseHandle):
|
||||
if isinstance(RightVal, ir.Constant) and RightVal.constant == 0:
|
||||
RightVal = ir.Constant(LeftVal.type, None)
|
||||
else:
|
||||
# 不将整数转为指针(避免 strcmp 解引用无效地址),改为将指针转为整数走正常 ==
|
||||
# 指针 vs 非零整数: 将指针转为整数走正常 ==(地址值比较)
|
||||
LeftVal = Gen.builder.ptrtoint(LeftVal, RightVal.type, name="ptr2int_cmp")
|
||||
elif isinstance(RightVal.type, ir.PointerType) and isinstance(LeftVal.type, ir.IntType):
|
||||
if isinstance(RightVal.type.pointee, ir.IntType) and RightVal.type.pointee.width == 8 and isinstance(LeftVal.type, ir.IntType) and LeftVal.type.width == 8:
|
||||
@@ -394,7 +394,7 @@ class ExprOpsHandle(BaseHandle):
|
||||
if isinstance(LeftVal, ir.Constant) and LeftVal.constant == 0:
|
||||
LeftVal = ir.Constant(RightVal.type, None)
|
||||
else:
|
||||
# 不将整数转为指针(避免 strcmp 解引用无效地址),改为将指针转为整数走正常 ==
|
||||
# 非零整数 vs 指针: 将指针转为整数走正常 ==(地址值比较)
|
||||
RightVal = Gen.builder.ptrtoint(RightVal, LeftVal.type, name="ptr2int_cmp")
|
||||
# is / is not: 地址比较(指针)或值比较(int)
|
||||
if ComparatorSymbol in ('is', 'is not'):
|
||||
@@ -408,20 +408,8 @@ class ExprOpsHandle(BaseHandle):
|
||||
if ComparatorSymbol == 'is not':
|
||||
val_cmp = Gen.builder.not_(val_cmp, name="is_not_result")
|
||||
return val_cmp
|
||||
# str/bytes == str/bytes: 值比较(调用 strcmp),None 比较用地址
|
||||
if ComparatorSymbol in ('==', '!='):
|
||||
if (isinstance(LeftVal.type, ir.PointerType) and isinstance(LeftVal.type.pointee, ir.IntType) and LeftVal.type.pointee.width == 8
|
||||
and isinstance(RightVal.type, ir.PointerType) and isinstance(RightVal.type.pointee, ir.IntType) and RightVal.type.pointee.width == 8):
|
||||
left_is_null: bool = isinstance(LeftVal, ir.Constant) and LeftVal.constant is None
|
||||
right_is_null: bool = isinstance(RightVal, ir.Constant) and RightVal.constant is None
|
||||
if not (left_is_null or right_is_null):
|
||||
strcmp_func = Gen.get_or_declare_c_func('strcmp', ir.FunctionType(ir.IntType(32), [ir.IntType(8).as_pointer(), ir.IntType(8).as_pointer()]))
|
||||
cmp_result = Gen.builder.call(strcmp_func, [LeftVal, RightVal], name="str_eq_cmp")
|
||||
zero = ir.Constant(ir.IntType(32), 0)
|
||||
eq_result = Gen.builder.icmp_signed('==', cmp_result, zero, name="str_eq")
|
||||
if ComparatorSymbol == '!=':
|
||||
eq_result = Gen.builder.not_(eq_result, name="str_neq")
|
||||
return eq_result
|
||||
# == / !=: 指针间做地址比较(C-Like 语义,不隐式调用 strcmp)
|
||||
# 如需字符串内容比较,应显式调用 string.strcmp()
|
||||
if isinstance(LeftVal.type, ir.PointerType) and isinstance(RightVal.type, ir.PointerType):
|
||||
result = Gen.builder.icmp_unsigned(ComparatorSymbol, LeftVal, RightVal, name="cmpresult")
|
||||
elif isinstance(LeftVal.type, (ir.FloatType, ir.DoubleType)) or isinstance(RightVal.type, (ir.FloatType, ir.DoubleType)):
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -12,7 +12,7 @@
|
||||
|
||||
1. **Python 语法,LLVM 语义**:源文件是完全合法的 `Python` 语法,但通过 `t` 模块的类型注解系统赋予完全不同的语义 —— `t.CInt` 不是 `Python` 的 `int`,而是 `LLVM` 的 `i32`
|
||||
2. **类型注解即编译指令**:Viper 的类型注解不是可选的提示,而是编译器生成 `LLVM IR` 的决定性依据。`x: t.CInt` 生成 `i32`,`x: t.CInt | t.CPtr` 生成 `i32*`,但无注解时会自动推导,详见下文。
|
||||
3. **两阶段编译**:先从源文件提取声明接口(`.pyi` + `.stub.ll`),再使用声明接口翻译源文件为含代码的 `.ll`。这是 `Viper` 区别于简单"`Python` 转 `C`"工具的关键架构
|
||||
3. **两阶段编译**:先从源文件提取声明接口(`.vpi` + `.stub.ll`),再使用声明接口翻译源文件为含代码的 `.ll`。这是 `Viper` 区别于简单"`Python` 转 `C`"工具的关键架构
|
||||
4. **`SHA1` 命名空间**:每个源文件按内容 `SHA1` 哈希命名,非导出函数和结构体自动加上 `SHA1` 前缀,从根本上消除跨模块的符号冲突
|
||||
5. **万物皆数据**:为便于底层开发,实际上所有的变量和类型一般并不适用于鸭子类型,但在语义层面我们会尽可能贴近鸭子类型。
|
||||
|
||||
@@ -37,7 +37,7 @@ Viper 编译后的代码在底层等价于 `C` 编译后的机器码(都经过
|
||||
- **声明式内联汇编**:`c.Asm(f"mov {c.AsmOut(x, t.ASM_DESCR.OUTPUT_REG)}, rdi")` 比裸 `__asm__` 更安全,也更具可读性。
|
||||
- **结构化预处理**:`c.CIfdef`/`c.CEndif()` 替代 `#ifdef`/`#endif`。
|
||||
- **面向对象**:`@t.Object` + `@t.CVTable` 提供 `vtable` 支持的多态 `OOP`;`@t.NoVTable` 提供 C++ 风格的非多态继承(零 vtable 开销);PEP 695 泛型 + 递归泛型继承实现强类型自引用结构
|
||||
- **存根驱动的模块系统**:`.pyi` 存根文件实现跨模块类型解析,无需头文件
|
||||
- **存根驱动的模块系统**:`.vpi` 存根文件实现跨模块类型解析,无需头文件
|
||||
- **更多内容**:额外更多的不依赖操作系统的函数和语法
|
||||
|
||||
## 两阶段编译流程
|
||||
@@ -45,12 +45,12 @@ Viper 编译后的代码在底层等价于 `C` 编译后的机器码(都经过
|
||||
Viper 的编译由 `Projectrans.py` 驱动,分为两个阶段。这是 Viper 编译模型的核心,理解两阶段编译是理解 `t.CDefine`、`t.CExport`、`t.CInline` 等关键概念的前提。
|
||||
|
||||
```
|
||||
源文件 (.py) ──────────────────────────────────────────────────────
|
||||
源文件 (.vp) ──────────────────────────────────────────────────────
|
||||
│ │
|
||||
│ ┌─────────────── 阶段一:声明提取 ───────────────┐ │
|
||||
│ │ │ │
|
||||
│ │ 1. 计算源文件 SHA1 │ │
|
||||
│ │ 2. 生成 <SHA1>.pyi(签名存根) │ │
|
||||
│ │ 2. 生成 <SHA1>.vpi(签名存根) │ │
|
||||
│ │ 3. 构建结构体注册表 │ │
|
||||
│ │ 4. 生成 <SHA1>.stub.ll(LLVM IR 声明) │ │
|
||||
│ │ │ │
|
||||
@@ -58,7 +58,7 @@ Viper 的编译由 `Projectrans.py` 驱动,分为两个阶段。这是 Viper
|
||||
│ │
|
||||
│ ┌─────────────── 阶段二:代码翻译 ───────────────┐ │
|
||||
│ │ │ │
|
||||
│ │ 1. 加载所有 .pyi 和 .stub.ll │ │
|
||||
│ │ 1. 加载所有 .vpi 和 .stub.ll │ │
|
||||
│ │ 2. 构建共享符号表 │ │
|
||||
│ │ 3. 收集内联函数符号 │ │
|
||||
│ │ 4. 翻译源文件 → <SHA1>.ll(含代码) │ │
|
||||
@@ -76,15 +76,15 @@ Viper 的编译由 `Projectrans.py` 驱动,分为两个阶段。这是 Viper
|
||||
|
||||
#### 步骤 1:可达文件发现与拓扑排序
|
||||
|
||||
从入口文件(`main.py` 或 `project.json` 指定)出发,通过 `import` 语句递归遍历,找出所有可达的 `.py` 源文件。然后对文件进行拓扑排序,确保被依赖的模块先被处理。
|
||||
从入口文件(`main.vp` 或 `project.json` 指定)出发,通过 `import` 语句递归遍历,找出所有可达的 `.vp` 源文件。然后对文件进行拓扑排序,确保被依赖的模块先被处理。
|
||||
|
||||
```
|
||||
main.py → import serial → import drivers.serial.uart.serial → ...
|
||||
main.vp → import serial → import drivers.serial.uart.serial → ...
|
||||
```
|
||||
|
||||
#### 步骤 2:生成 `.pyi` 签名存根
|
||||
#### 步骤 2:生成 `.vpi` 签名存根
|
||||
|
||||
对每个源文件,计算其内容的 SHA1 哈希(16位),然后调用 `PythonToStubConverter` 生成签名存根文件 `<SHA1>.pyi`。
|
||||
对每个源文件,计算其内容的 SHA1 哈希(16位),然后调用 `PythonToStubConverter` 生成签名存根文件 `<SHA1>.vpi`。
|
||||
|
||||
**SHA1 计算方式**:
|
||||
```python
|
||||
@@ -108,7 +108,7 @@ sha1 = hashlib.sha1(content.encode('utf-8')).hexdigest()[:16]
|
||||
|
||||
#### 步骤 3:构建结构体注册表
|
||||
|
||||
扫描所有已生成的 `.pyi` 文件,提取:
|
||||
扫描所有已生成的 `.vpi` 文件,提取:
|
||||
- **结构体名称集合**:所有非枚举、非异常的 `class` 定义
|
||||
- **枚举名称集合**:继承 `t.CEnum` 的类
|
||||
- **异常名称集合**:继承 `Exception` 的类
|
||||
@@ -118,7 +118,7 @@ sha1 = hashlib.sha1(content.encode('utf-8')).hexdigest()[:16]
|
||||
|
||||
#### 步骤 4:生成 `.stub.ll` LLVM IR 声明
|
||||
|
||||
对每个 `.pyi` 文件,由 `DeclarationGenerator` 生成对应的 LLVM IR 声明文件 `<SHA1>.stub.ll`。
|
||||
对每个 `.vpi` 文件,由 `DeclarationGenerator` 生成对应的 LLVM IR 声明文件 `<SHA1>.stub.ll`。
|
||||
|
||||
**声明生成规则**:
|
||||
|
||||
@@ -132,7 +132,7 @@ sha1 = hashlib.sha1(content.encode('utf-8')).hexdigest()[:16]
|
||||
| `t.CTypedef` 别名 | **不生成声明**(类型别名,在类型解析时展开) |
|
||||
| 枚举 | 为每个枚举成员生成 `@__config_EnumName_member = external global i32` |
|
||||
|
||||
**增量编译**:如果 `<SHA1>.pyi` 或 `<SHA1>.stub.ll` 已存在,则跳过生成(缓存命中)。只有源文件内容变化导致 SHA1 变化时才重新生成。
|
||||
**增量编译**:如果 `<SHA1>.vpi` 或 `<SHA1>.stub.ll` 已存在,则跳过生成(缓存命中)。只有源文件内容变化导致 SHA1 变化时才重新生成。
|
||||
|
||||
### 阶段二:代码翻译(Phase2Translator)
|
||||
|
||||
@@ -140,14 +140,14 @@ sha1 = hashlib.sha1(content.encode('utf-8')).hexdigest()[:16]
|
||||
|
||||
#### 步骤 1:加载声明接口
|
||||
|
||||
加载 `temp/` 目录中所有的 `.pyi` 和 `.stub.ll` 文件,构建:
|
||||
- `sig_files`:SHA1 → `.pyi` 文件路径映射
|
||||
加载 `temp/` 目录中所有的 `.vpi` 和 `.stub.ll` 文件,构建:
|
||||
- `sig_files`:SHA1 → `.vpi` 文件路径映射
|
||||
- `stub_files`:SHA1 → `.stub.ll` 文件路径映射
|
||||
- `sha1_map`:SHA1 → 源文件相对路径映射
|
||||
|
||||
#### 步骤 2:构建共享符号表
|
||||
|
||||
一次性构建所有文件共享的符号表数据,避免每个文件重复加载。将所有 `.pyi` 存根和 `.stub.ll` 声明中的类型信息注册到统一的 `SymbolTable` 中。
|
||||
一次性构建所有文件共享的符号表数据,避免每个文件重复加载。将所有 `.vpi` 存根和 `.stub.ll` 声明中的类型信息注册到统一的 `SymbolTable` 中。
|
||||
|
||||
#### 步骤 3:收集内联函数符号
|
||||
|
||||
@@ -179,20 +179,20 @@ SHA1 命名空间是 Viper 解决跨模块符号冲突的核心机制。
|
||||
Viper 使用源文件内容的 SHA1 哈希作为命名空间前缀:
|
||||
|
||||
```
|
||||
源文件 A.py(SHA1 = a1b2c3d4e5f6g7h8)中定义:
|
||||
源文件 A.vp(SHA1 = a1b2c3d4e5f6g7h8)中定义:
|
||||
class Point: x: t.CInt; y: t.CInt
|
||||
def draw(p: Point) -> t.CVoid: ...
|
||||
|
||||
源文件 B.py(SHA1 = i9j0k1l2m3n4o5p6)中也定义:
|
||||
源文件 B.vp(SHA1 = i9j0k1l2m3n4o5p6)中也定义:
|
||||
class Point: x: t.CFloat; y: t.CFloat # 不同的结构体!
|
||||
def draw(p: Point) -> t.CVoid: ...
|
||||
|
||||
编译后:
|
||||
A.py 的结构体 → %"a1b2c3d4e5f6g7h8.Point" = type { i32, i32 }
|
||||
A.py 的函数 → declare void @"a1b2c3d4e5f6g7h8.draw"(%"a1b2c3d4e5f6g7h8.Point"*)
|
||||
A.vp 的结构体 → %"a1b2c3d4e5f6g7h8.Point" = type { i32, i32 }
|
||||
A.vp 的函数 → declare void @"a1b2c3d4e5f6g7h8.draw"(%"a1b2c3d4e5f6g7h8.Point"*)
|
||||
|
||||
B.py 的结构体 → %"i9j0k1l2m3n4o5p6.Point" = type { float, float }
|
||||
B.py 的函数 → declare void @"i9j0k1l2m3n4o5p6.draw"(%"i9j0k1l2m3n4o5p6.Point"*)
|
||||
B.vp 的结构体 → %"i9j0k1l2m3n4o5p6.Point" = type { float, float }
|
||||
B.vp 的函数 → declare void @"i9j0k1l2m3n4o5p6.draw"(%"i9j0k1l2m3n4o5p6.Point"*)
|
||||
```
|
||||
|
||||
**没有符号冲突**——即使两个模块定义了同名类型和函数,它们的 LLVM IR 符号也是不同的。即便有两个内容完全相同的文件也不会冲突,他们会被识别为同一个文件,然后进行单次编译。
|
||||
@@ -202,7 +202,7 @@ Viper 使用源文件内容的 SHA1 哈希作为命名空间前缀:
|
||||
标记为 `t.CExport` 的函数**不加 SHA1 前缀**,保持原始函数名。这是模块向外部暴露 API/ABI 的机制:
|
||||
|
||||
```python
|
||||
# main.py — 入口函数,必须全局可见
|
||||
# main.vp — 入口函数,必须全局可见
|
||||
def main() -> t.CInt | t.CExport:
|
||||
return 0
|
||||
|
||||
@@ -210,7 +210,7 @@ def main() -> t.CInt | t.CExport:
|
||||
```
|
||||
|
||||
```python
|
||||
# serial.py — 驱动接口,对外暴露
|
||||
# serial.vp — 驱动接口,对外暴露
|
||||
def init() -> t.CVoid | t.CExport:
|
||||
serial_puts("init\n")
|
||||
|
||||
@@ -220,7 +220,7 @@ def init() -> t.CVoid | t.CExport:
|
||||
### SHA1 与增量编译
|
||||
|
||||
SHA1 同时服务于增量编译:
|
||||
- 源文件内容不变 → SHA1 不变 → `.pyi` 和 `.stub.ll` 缓存命中,跳过阶段一
|
||||
- 源文件内容不变 → SHA1 不变 → `.vpi` 和 `.stub.ll` 缓存命中,跳过阶段一
|
||||
- 源文件内容变化 → SHA1 变化 → 重新生成声明接口
|
||||
- `temp/_sha1_map.txt` 记录 SHA1 → 源文件路径的映射,供阶段二加载
|
||||
|
||||
@@ -305,7 +305,7 @@ def _helper() -> t.CInt:
|
||||
|
||||
### `t.CExport` 在存根中的表现
|
||||
|
||||
在 `.pyi` 存根文件中,`t.CExport` 函数与普通函数一样只保留签名(添加 `c.State`,表示单纯声明),但 `t.CExport` 标记被保留在返回类型注解中。阶段一的 `DeclarationGenerator` 检查 `t.CExport` 标记来决定是否添加 SHA1 前缀。
|
||||
在 `.vpi` 存根文件中,`t.CExport` 函数与普通函数一样只保留签名(添加 `c.State`,表示单纯声明),但 `t.CExport` 标记被保留在返回类型注解中。阶段一的 `DeclarationGenerator` 检查 `t.CExport` 标记来决定是否添加 SHA1 前缀。
|
||||
|
||||
## `t.CInline` 深度解析
|
||||
|
||||
@@ -351,7 +351,7 @@ def main() -> t.CInt | t.CExport:
|
||||
|
||||
编译流程:
|
||||
|
||||
1. **阶段一**:计算 `main.py` 的 SHA1,生成 `.pyi` 存根(`def main() -> t.CInt | t.CExport | c.State: pass`),生成 `.stub.ll` 声明(`declare i32 @main()`,因为是 CExport 不加前缀)
|
||||
2. **阶段二**:翻译 `main.py` 为 `<SHA1>.ll`,嵌入 `print` 对应的 `puts`/`printf` 声明,生成 `define i32 @main()` 函数体
|
||||
1. **阶段一**:计算 `main.vp` 的 SHA1,生成 `.vpi` 存根(`def main() -> t.CInt | t.CExport | c.State: pass`),生成 `.stub.ll` 声明(`declare i32 @main()`,因为是 CExport 不加前缀)
|
||||
2. **阶段二**:翻译 `main.vp` 为 `<SHA1>.ll`,嵌入 `print` 对应的 `puts`/`printf` 声明,生成 `define i32 @main()` 函数体
|
||||
3. **编译**:`llc` 将 `.ll` 编译为 `.o`
|
||||
4. **链接**:`ld.lld` 链接为可执行文件
|
||||
|
||||
@@ -200,7 +200,7 @@ match ty:
|
||||
string.strcpy(buf, "void")
|
||||
```
|
||||
|
||||
详见 [includes/llvmlite/__types.py](../includes/llvmlite/__types.py) 的 `LLVMType` 实现。
|
||||
详见 [includes/llvmlite/__types.vp](../includes/llvmlite/__types.vp) 的 `LLVMType` 实现。
|
||||
|
||||
## Typedef
|
||||
|
||||
@@ -258,7 +258,7 @@ node: GNode | t.CPtr = GNode()
|
||||
lst.append(node) # 类型安全:append 只接受 GNode
|
||||
```
|
||||
|
||||
详见 [includes/linkedlist.py](../includes/linkedlist.py) 和 [includes/vector.py](../includes/vector.py)。
|
||||
详见 [includes/linkedlist.vp](../includes/linkedlist.vp) 和 [includes/vector.vp](../includes/vector.vp)。
|
||||
|
||||
## 位域
|
||||
|
||||
|
||||
@@ -152,7 +152,7 @@ func: Function | t.CPtr = mod_core.CreateFunction(mod, "main", ret_ty)
|
||||
|
||||
### `linkedlist` 模块(NoVTable + PEP 695 泛型示范)
|
||||
|
||||
[includes/linkedlist](../includes/linkedlist.py) 提供链表实现,是 `@t.NoVTable` 非多态继承和 PEP 695 递归泛型继承的典范用例:
|
||||
[includes/linkedlist](../includes/linkedlist.vp) 提供链表实现,是 `@t.NoVTable` 非多态继承和 PEP 695 递归泛型继承的典范用例:
|
||||
|
||||
```python
|
||||
from linkedlist import LinkedNode, GSList
|
||||
@@ -193,14 +193,14 @@ handle: HANDLE = CreateFileA("test.txt", GENERIC_READ, FILE_SHARE_READ,
|
||||
Viper 的 `import` 是编译时操作,不涉及运行时模块加载。完整的模块解析流程与两阶段编译紧密耦合:
|
||||
|
||||
1. **阶段一**:从入口文件出发,通过 `import` 语句递归发现所有可达的源文件
|
||||
2. **阶段一**:对每个源文件生成 `<SHA1>.pyi` 签名存根和 `<SHA1>.stub.ll` LLVM IR 声明
|
||||
3. **阶段二**:加载所有 `.pyi` 和 `.stub.ll`,构建共享符号表
|
||||
2. **阶段一**:对每个源文件生成 `<SHA1>.vpi` 签名存根和 `<SHA1>.stub.ll` LLVM IR 声明
|
||||
3. **阶段二**:加载所有 `.vpi` 和 `.stub.ll`,构建共享符号表
|
||||
4. **阶段二**:翻译源文件时,通过符号表解析跨模块的类型和函数引用
|
||||
5. **阶段二**:将被引用模块的 `.stub.ll` 声明嵌入到生成的 `.ll` 文件头部
|
||||
|
||||
### 类型存根文件(.pyi)
|
||||
### 类型存根文件(.vpi)
|
||||
|
||||
`.pyi` 文件是模块的声明接口,由 `PythonToStubConverter` 在阶段一生成。存根文件的内容规则:
|
||||
`.vpi` 文件是模块的声明接口,由 `PythonToStubConverter` 在阶段一生成。存根文件的内容规则:
|
||||
|
||||
| 元素 | 存根表示 |
|
||||
|------|---------|
|
||||
@@ -228,7 +228,7 @@ Viper 的 `import` 是编译时操作,不涉及运行时模块加载。完整
|
||||
### 跨模块类型引用
|
||||
|
||||
```python
|
||||
# 在 fat32_types.py 中定义
|
||||
# 在 fat32_types.vp 中定义
|
||||
class fat32_fileinfo:
|
||||
fname: list[t.CChar, 13]
|
||||
attr: t.CUInt8T
|
||||
|
||||
@@ -47,7 +47,7 @@ Viper 项目使用 `project.json` 配置文件管理编译和链接参数。
|
||||
| `name` | string | 项目名称 |
|
||||
| `version` | string | 项目版本 |
|
||||
| `source_dir` | string | 源代码目录(相对于 project.json 所在目录) |
|
||||
| `temp_dir` | string | 临时文件目录(存放 .pyi 存根等) |
|
||||
| `temp_dir` | string | 临时文件目录(存放 .vpi 存根等) |
|
||||
| `output_dir` | string | 输出文件目录 |
|
||||
|
||||
### 编译器配置
|
||||
@@ -122,12 +122,12 @@ VKernel/
|
||||
├── project.json # 项目配置
|
||||
├── linker.ld # 链接脚本
|
||||
├── Kernel/ # 源代码目录
|
||||
│ ├── main.py # 内核入口
|
||||
│ ├── bootinfo.py
|
||||
│ ├── main.vp # 内核入口
|
||||
│ ├── bootinfo.vp
|
||||
│ ├── intr/
|
||||
│ │ ├── gdt.py
|
||||
│ │ ├── idt.py
|
||||
│ │ └── syscall.py
|
||||
│ │ ├── gdt.vp
|
||||
│ │ ├── idt.vp
|
||||
│ │ └── syscall.vp
|
||||
│ ├── drivers/
|
||||
│ │ ├── serial/
|
||||
│ │ ├── video/
|
||||
@@ -135,7 +135,7 @@ VKernel/
|
||||
│ │ └── ...
|
||||
│ └── ...
|
||||
├── temp/ # 临时文件(自动生成)
|
||||
│ ├── <SHA1>.pyi # 签名存根(阶段一生成)
|
||||
│ ├── <SHA1>.vpi # 签名存根(阶段一生成)
|
||||
│ ├── <SHA1>.stub.ll # LLVM IR 声明(阶段一生成)
|
||||
│ └── _sha1_map.txt # SHA1→源文件路径映射
|
||||
└── output/ # 输出文件(自动生成)
|
||||
@@ -150,7 +150,7 @@ VKernel/
|
||||
HelloWorld/
|
||||
├── project.json # 项目配置
|
||||
├── linker.ld # 链接脚本
|
||||
├── main.py # 应用入口
|
||||
├── main.vp # 应用入口
|
||||
├── temp/ # 临时文件
|
||||
└── output/ # 输出文件
|
||||
└── helloworld.elf # ELF 可执行文件
|
||||
@@ -162,7 +162,7 @@ HelloWorld/
|
||||
SerialLogger/
|
||||
├── project.json # 项目配置
|
||||
├── linker.ld # 链接脚本
|
||||
├── serial_logger.py # 库源码
|
||||
├── serial_logger.vp # 库源码
|
||||
├── temp/ # 临时文件
|
||||
└── output/ # 输出文件
|
||||
```
|
||||
@@ -233,14 +233,14 @@ TransPyC 支持基于 SHA1 的增量编译,与两阶段编译模型紧密耦
|
||||
### 阶段一增量
|
||||
|
||||
- 每个源文件按内容计算 SHA1 哈希(16位)
|
||||
- 如果 `<SHA1>.pyi` 和 `<SHA1>.stub.ll` 已存在,则跳过生成(缓存命中)
|
||||
- 如果 `<SHA1>.vpi` 和 `<SHA1>.stub.ll` 已存在,则跳过生成(缓存命中)
|
||||
- 只有源文件内容变化导致 SHA1 变化时才重新生成声明接口
|
||||
- `temp/_sha1_map.txt` 记录 SHA1 → 源文件路径的映射,格式为 `<sha1>:<relative_path>`
|
||||
|
||||
### 阶段二增量
|
||||
|
||||
- 阶段二加载 `temp/_sha1_map.txt` 重建 SHA1 映射
|
||||
- 过滤掉不在当前 SHA1 映射中的旧 `.pyi` 和 `.stub.ll` 文件
|
||||
- 过滤掉不在当前 SHA1 映射中的旧 `.vpi` 和 `.stub.ll` 文件
|
||||
- 共享符号表一次性构建,避免每个文件重复加载
|
||||
|
||||
### SHA1 命名空间与增量编译的协同
|
||||
|
||||
@@ -57,19 +57,19 @@
|
||||
|
||||
| 模块 | LOC | 说明 |
|
||||
|------|-----|------|
|
||||
| `includes/numpy/__init__.py` | 1,016 | ndarray n 维数组 |
|
||||
| `includes/numpy/__init__.vp` | 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 | 数学库 |
|
||||
| `includes/linkedlist.vp` | ~400 | 泛型链表(@t.NoVTable + PEP 695) |
|
||||
| `includes/vipermath.vp` | 450 | 数学库 |
|
||||
| ...(30+ 文件) | ... | mpool/mbuddy/string/stdio/json/w32 等 |
|
||||
| **includes 总计** | **~12,000** | |
|
||||
|
||||
### 2.4 全项目总计
|
||||
|
||||
```
|
||||
全项目 .py 总计:~48,000 LOC
|
||||
全项目总计:~48,000 LOC
|
||||
```
|
||||
|
||||
**自举相关核心数字:**
|
||||
@@ -87,10 +87,10 @@
|
||||
|
||||
| 文件 | LOC | 功能 |
|
||||
|------|-----|------|
|
||||
| `__tokens.py` | ~600 | TokenType/Keyword/TokOp 枚举 + 查找表 |
|
||||
| `__nodes.py` | ~1,400 | AST 胖节点 + ASTVType/ASTCtx/OpKind CEnum |
|
||||
| `__lexer.py` | ~800 | 词法分析器 |
|
||||
| `__parser.py` | 4,176(含表格) | 递归下降语法分析器 |
|
||||
| `__tokens.vp` | ~600 | TokenType/Keyword/TokOp 枚举 + 查找表 |
|
||||
| `__nodes.vp` | ~1,400 | AST 胖节点 + ASTVType/ASTCtx/OpKind CEnum |
|
||||
| `__lexer.vp` | ~800 | 词法分析器 |
|
||||
| `__parser.vp` | 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、切片、嵌套三元。
|
||||
|
||||
@@ -105,11 +105,11 @@
|
||||
|
||||
| 文件 | 功能 |
|
||||
|------|------|
|
||||
| `__types.py` | `LLVMType` REnum + 类型构造/打印 |
|
||||
| `__values.py` | Value/Constant/SSA 值表示 |
|
||||
| `__function.py` | Function + BasicBlock + 参数管理 |
|
||||
| `__module.py` | Module 容器 + 目标三元组 + 输出 .ll |
|
||||
| `__builder.py` | IRBuilder(指令发射 + SSA 命名) |
|
||||
| `__types.vp` | `LLVMType` REnum + 类型构造/打印 |
|
||||
| `__values.vp` | Value/Constant/SSA 值表示 |
|
||||
| `__function.vp` | Function + BasicBlock + 参数管理 |
|
||||
| `__module.vp` | Module 容器 + 目标三元组 + 输出 .ll |
|
||||
| `__builder.vp` | IRBuilder(指令发射 + SSA 命名) |
|
||||
|
||||
**设计要点**:
|
||||
- `LLVMType` 用 `t.REnum`(tagged union)—— 少变体、无通用字段、match 分派的理想场景
|
||||
@@ -117,7 +117,7 @@
|
||||
- IR 文本生成用 `viperlib.snprintf` 格式化,避免手写逐字符拼接
|
||||
- 对象分配用普通类 + `mpool`,不持有全局 `mbuddy`
|
||||
|
||||
**验证**:[TransPyV/App/main.py](../TransPyV/App/main.py) 10 个测试覆盖类型打印、值打印、build_add、if-else、模块打印、lli 实际执行。TransPyV 程序运行时自己生成合法 IR,被 `lli` 成功执行。
|
||||
**验证**:[TransPyV/App/main.vp](../TransPyV/App/main.vp) 10 个测试覆盖类型打印、值打印、build_add、if-else、模块打印、lli 实际执行。TransPyV 程序运行时自己生成合法 IR,被 `lli` 成功执行。
|
||||
|
||||
### 3.3 ✅ 基础设施库
|
||||
|
||||
@@ -125,9 +125,9 @@
|
||||
|
||||
| 库 | 自举中的作用 |
|
||||
|----|-------------|
|
||||
| `linkedlist.py` | AST 节点树、符号表链、IR 指令链的容器(`@t.NoVTable` + PEP 695 递归泛型继承) |
|
||||
| `mpool.py` / `mbuddy.py` | 编译器内存管理(替代 Python GC) |
|
||||
| `string.py` / `viperlib.py` | 字符串处理 + snprintf(替代 Python 字符串方法) |
|
||||
| `linkedlist.vp` | AST 节点树、符号表链、IR 指令链的容器(`@t.NoVTable` + PEP 695 递归泛型继承) |
|
||||
| `mpool.vp` / `mbuddy.vp` | 编译器内存管理(替代 Python GC) |
|
||||
| `string.vp` / `viperlib.vp` | 字符串处理 + snprintf(替代 Python 字符串方法) |
|
||||
| `w32/` | FFI 声明,自举后编译器调用 llc/clang/linker 的基础 |
|
||||
| `json/` | 符号表序列化(替代 pickle) |
|
||||
|
||||
@@ -164,7 +164,7 @@
|
||||
| `copy.deepcopy` / `pickle` | ~10 | ✅ 是 | 已解决(`__getstate__/__setstate__`) |
|
||||
| `hasattr` 防御性检查 | ~1500 | ⚠️ 多数可消除 | 显式字段声明 + None 检查 |
|
||||
|
||||
**真实反射障碍约 200-500 处**,集中体现在 `CTypeInfo` 门面模式(FIELD_ROUTES 动态路由到 `_ts`/`_sm`)。重构方案:用 REnum + match 替换 `__getattr__` 路由,已在 `includes/llvmlite/__types.py` 验证此范式可行。
|
||||
**真实反射障碍约 200-500 处**,集中体现在 `CTypeInfo` 门面模式(FIELD_ROUTES 动态路由到 `_ts`/`_sm`)。重构方案:用 REnum + match 替换 `__getattr__` 路由,已在 `includes/llvmlite/__types.vp` 验证此范式可行。
|
||||
|
||||
### 4.4 Python 标准库依赖(原:严重)→ ⚠️ 部分已解决
|
||||
|
||||
@@ -204,9 +204,9 @@
|
||||
|
||||
以下能力已在 includes/ 库中验证,证明 TransPyC 能承载编译器复杂度:
|
||||
|
||||
- **复杂泛型容器**:`linkedlist.py` 的递归泛型继承 `class GNode(GSListNode[GNode])`(C/C++/Rust 均无法如此简洁表达)
|
||||
- **复杂泛型容器**:`linkedlist.vp` 的递归泛型继承 `class GNode(GSListNode[GNode])`(C/C++/Rust 均无法如此简洁表达)
|
||||
- **复杂算法**:`zlib/` 的完整 deflate/inflate/huffman(~1,900 LOC 生产级压缩)
|
||||
- **n 维数组**:`numpy/__init__.py` 的 ndarray + 运算符重载 + `__new__` 堆分配
|
||||
- **n 维数组**:`numpy/__init__.vp` 的 ndarray + 运算符重载 + `__new__` 堆分配
|
||||
- **平台 FFI**:`w32/` 的 Win32 API 绑定(file/memory/process/sync/console)
|
||||
- **LLVM IR 生成**:`llvmlite/` 的 REnum 类型系统 + IRBuilder + ModulePrint
|
||||
|
||||
|
||||
3555
wiki/all.md
3555
wiki/all.md
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user