Files
TransPyC/wiki/10-imports.md
2026-07-18 19:25:40 +08:00

259 lines
8.3 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 10 - 模块与导入系统
Viper 的模块系统基于 Python 的 `import` 语法,但编译时通过 TransPyC 的符号表和类型系统实现跨模块的类型解析。
## 导入语法
### 标准导入
```python
import t, c # Viper 内置类型和操作模块
import asm # 汇编辅助模块
import string # 字符串操作模块
```
### 模块导入
```python
import bootinfo
import intr
import platform.pch as pch
import drivers.serial.uart.serial as serial
```
### from 导入
```python
from stdint import * # 导入所有 stdint 类型别名
from drivers.video.vesafb.vga import _VGAScreenDriver
```
### 相对导入
```python
from . import submodule
from .. import parent_module
```
## 特殊模块
### `t` 模块
类型定义模块,提供所有 C 类型对应的 Viper 类型。每个 Viper 文件通常都需要导入:
```python
import t
```
### `c` 模块
C 语言操作模块,提供指针操作、内联汇编、预处理指令等:
```python
import c
```
### `asm` 模块
汇编辅助模块,提供常用汇编指令的封装:
```python
import asm
asm.sti() # __asm__ __volatile__("sti");
asm.hlt() # __asm__ __volatile__("hlt");
asm.cli() # __asm__ __volatile__("cli");
asm.nop() # __asm__ __volatile__("nop");
asm.BSSClean() # 清零 BSS 段
```
### `string` 模块
字符串/内存操作模块,对应 C 标准库的 `string.h`
> string 部分使用 x86_64 专有汇编进行加速,因此某些函数在其它架构可能需要手动重新编写。
```python
import string
string.memset(c.Addr(buf), 0, 64) # memset(&buf, 0, 64);
string.memcpy(dst, src, size) # memcpy(dst, src, size);
string.memmove(dst, src, size) # memmove(dst, src, size);
string.memcmp(a, b, size) # memcmp(a, b, size);
string.strcmp(a, b) # strcmp(a, b);
string.strcpy(dst, src) # strcpy(dst, src);
```
### `stdint` 模块
提供 C `stdint.h` 中的类型别名:
```python
from stdint import *
# 提供以下类型别名:
# UINT8PTR, UINT16PTR, UINT32PTR, UINT64PTR
# INT8PTR, INT16PTR, INT32PTR, INT64PTR
# 等等
```
### `viperlib` 模块
ViperOS 标准库,提供常用 C 库函数:
```python
import viperlib
viperlib.snprintf(c.Addr(buf), 64, "value=%d", 42) # snprintf(&buf, 64, "value=%d", 42);
```
### `vpsdk` 模块
> vpsdk 模块 专供于基于 Viper 开发的示例操作系统 ViperOS不可用于其它平台且需要特殊配置。
ViperOS 应用 SDK提供系统调用和窗口管理
```python
import vpsdk.window as window
import vpsdk.process as process
import vpsdk.dynlib as dynlib
import vpsdk.syscall as syscall
```
### `ast` 模块(自研解析器)
[includes/ast](../includes/ast) 是**完全自研的 Python 解析器**(词法器 + 语法器 + AST 构造,约 4176 LOC覆盖 CPython 几乎全部语法。这是向 `TransPyV` 完全自举的关键组件——自举后编译器不再依赖 Python 运行时解析源文件。
```python
from ast import parse, parse_expression
root: AST | t.CPtr = parse(src, pool) # 解析整个源文件
expr: AST | t.CPtr = parse_expression(src, pool) # 解析单个表达式
```
AST 采用**胖节点**设计70+ 变体共用一个 struct`vtype``ASTVType` 枚举)区分类型,通用字段直接属性访问。详见 [13-bootstrapping.md](13-bootstrapping.md) 和 [Test/AstTest](../Test/AstTest)。
### `llvmlite` 模块(自研 IR 生成库)
[includes/llvmlite](../includes/llvmlite) 是**完全自研的 LLVM IR 文本生成库**(约 1500 LOC封装类型/值/模块/函数/基本块/构造器的创建与打印。同样是自举的关键组件。
```python
from llvmlite import LLVMTypeCore, LLVMModuleCore
type_core: LLVMTypeCore = LLVMTypeCore(pool)
i32: LLVMType | t.CPtr = type_core.Int32()
ptr_ty: LLVMType | t.CPtr = type_core.Ptr(i32)
mod_core: LLVMModuleCore = LLVMModuleCore(pool)
mod: Module | t.CPtr = mod_core.NewModule("main")
func: Function | t.CPtr = mod_core.CreateFunction(mod, "main", ret_ty)
```
类型系统用 `t.REnum``LLVMType`,少变体适合 match指令 opcode 用 `t.CEnum``IROp`),对象分配用普通类 + `mpool`。详见 [includes/llvmlite/README.md](../includes/llvmlite/README.md) 的选型论证。
### `linkedlist` 模块NoVTable + PEP 695 泛型示范)
[includes/linkedlist](../includes/linkedlist.py) 提供链表实现,是 `@t.NoVTable` 非多态继承和 PEP 695 递归泛型继承的典范用例:
```python
from linkedlist import LinkedNode, GSList
@t.NoVTable
class Node(LinkedNode): # 非多态继承,零 vtable 开销
value: t.CInt
lst: GSList[Node] | t.CPtr = GSList[Node]()
node: Node | t.CPtr = Node()
node.value = 42
lst.append(node) # 类型安全append 只接受 Node
```
包含 `LinkedNode`/`SListNode`(双向/单向节点)和 `GSList[T]`(泛型链表,支持递归泛型继承 `class GNode(GSListNode[GNode])`)。详见 [05-classes.md 的泛型类章节](05-classes.md#泛型类pep-695-语法) 和 [06-oop.md 的 NoVTable 章节](06-oop.md#tnovtable-非多态继承)。
### `w32` 模块Win32 FFI 绑定)
[includes/w32](../includes/w32) 提供 Win32 API 绑定,全部通过 `t.State` 的 FFI 机制声明(零特殊语法):
```python
from w32.win32file import CreateFileA, ReadFile, WriteFile
from w32.win32console import WriteConsole
from w32.win32memory import HeapAlloc, HeapFree
from w32.win32process import CreateProcess
from w32.win32sync import CreateMutex, WaitForSingleObject
handle: HANDLE = CreateFileA("test.txt", GENERIC_READ, FILE_SHARE_READ,
None, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, None)
```
子模块:`win32base`(基础类型/常量)、`win32file`(文件 IO`win32console`(控制台)、`win32memory`(内存)、`win32process`(进程/线程)、`win32sync`(同步对象)、`fileio`(高层文件操作封装)。详见 [08-c-operations.md 的 FFI 章节](08-c-operations.md#ffi-外部函数声明)。
## 模块解析流程
### 编译时模块加载
Viper 的 `import` 是编译时操作,不涉及运行时模块加载。完整的模块解析流程与两阶段编译紧密耦合:
1. **阶段一**:从入口文件出发,通过 `import` 语句递归发现所有可达的源文件
2. **阶段一**:对每个源文件生成 `<SHA1>.pyi` 签名存根和 `<SHA1>.stub.ll` LLVM IR 声明
3. **阶段二**:加载所有 `.pyi``.stub.ll`,构建共享符号表
4. **阶段二**:翻译源文件时,通过符号表解析跨模块的类型和函数引用
5. **阶段二**:将被引用模块的 `.stub.ll` 声明嵌入到生成的 `.ll` 文件头部
### 类型存根文件(.pyi
`.pyi` 文件是模块的声明接口,由 `PythonToStubConverter` 在阶段一生成。存根文件的内容规则:
| 元素 | 存根表示 |
|------|---------|
| `t.CDefine` 常量 | 保留完整定义(含赋值) |
| `t.CDefine` 函数 | 保留完整函数体 |
| 普通函数 | 仅签名 + `t.State` |
| 全局变量 | 添加 `t.CExtern` |
| 类定义 | 保留成员类型注解和方法签名 |
存根文件还自动添加宏守卫(`c.CIfndef`/`c.CEndif()`),防止重复包含。
### SHA1 命名空间与导入
每个模块的函数和结构体在 LLVM IR 中自动加上 SHA1 前缀,消除跨模块符号冲突。只有标记为 `t.CExport` 的函数保持原始名称。详见 [01-overview.md 中 SHA1 命名空间机制](01-overview.md#sha1-命名空间机制)。
### 符号表
所有模块的类型信息统一存储在 `SymbolTable` 中,包含:
- 结构体/联合体/枚举定义
- 函数签名
- 全局变量
- typedef 别名
- `t.CDefine` 常量
### 跨模块类型引用
```python
# 在 fat32_types.py 中定义
class fat32_fileinfo:
fname: list[t.CChar, 13]
attr: t.CUInt8T
file_size: t.CUInt32T
# 在其他模块中引用
import fat32_types
info: fat32_types.fat32_fileinfo
```
跨模块引用的结构体在 LLVM IR 中使用 SHA1 前缀的类型名:
```llvm
%"<SHA1_of_fat32_types>.fat32_fileinfo" = type { [13 x i8], i8, i32 }
```
## 项目 includes 配置
`project.json` 中配置模块搜索路径:
```json
{
"includes": ["../.."],
"source_dir": "./Kernel"
}
```
编译器会在 `includes` 指定的目录中搜索导入的模块。