# 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` 指定的目录中搜索导入的模块。
