# 01 - 语言概述与编译流程

## 语言定位

`Viper` 是一种 **系统级编程语言**，其语法基于 `Python`，但编译目标为 `LLVM IR`，最终生成原生机器码。`Viper` 不是 `Python` 的超集或子集，也不是"`C` 的语法糖"——它是一门拥有独立类型系统、独立编译模型、独立模块体系的语言。`Viper` 选择 `Python` 语法作为表达形式，是因为 `Python` 的 `AST` 可被标准库直接解析，从而将编译器的精力集中在语义翻译而非词法/语法分析上。同时也是因为 `Python` 是人类公认的可读性最高的语言。

而实际上，下文中所有提到的 `C` 语言都是为了便于使用 `C` 的底层开发者理解。由于历史原因，在旧版本中我们使用 `C` 来作为中间语言，如同旧版本的 `C++` 一样，但现在 `target="c"` 的路径已经完全删除，`C` 路径永久不再受维护。

### 核心设计决策

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`"工具的关键架构
4. **`SHA1` 命名空间**：每个源文件按内容 `SHA1` 哈希命名，非导出函数和结构体自动加上 `SHA1` 前缀，从根本上消除跨模块的符号冲突
5. **万物皆数据**：为便于底层开发，实际上所有的变量和类型一般并不适用于鸭子类型，但在语义层面我们会尽可能贴近鸭子类型。

### 与 `Python` 的关系

| 特性 | `Python` | `Viper` |
|------|--------|-------|
| 类型系统 | 动态类型 | 静态类型（通过 `t` 模块注解，编译时确定） |
| 内存管理 | `GC` 自动回收 | 手动管理，无 `GC`，无运行时 |
| 运行时 | 解释执行 + 字节码 | 编译为原生机器码（通过 `LLVM`） |
| 对象模型 | 万物皆对象 | 仅 `@t.Object` 类有对象语义，`@t.CVTable` 为多态，普通 `class` 仅为结构体布局 |
| 标准库 | `Python` 标准库 | `Viper` 标准库（`includes/`）+ `ViperOS SDK` |
| 空值 | `None` | `None`（编译为 `NULL`/零值） |
| 模块系统 | 运行时 `import` | 编译时解析，插入 `.stub.ll`，`SHA1` 命名空间隔离 |

### 与 C 的关系

Viper 编译后的代码在底层等价于 `C` 编译后的机器码（都经过 LLVM），但 Viper 在语言层面提供了 C 所没有的能力：

- **SHA1 命名空间**：自动消除符号冲突，无需手动管理 `static`/命名前缀
- **类型组合语法**：`t.CConst | t.CInt | t.CPtr` 比 `const int*` 更具组合性
- **声明式内联汇编**：`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`
- **存根驱动的模块系统**：`.pyi` 存根文件实现跨模块类型解析，无需头文件
- **更多内容**：额外更多的不依赖操作系统的函数和语法

## 两阶段编译流程

Viper 的编译由 `Projectrans.py` 驱动，分为两个阶段。这是 Viper 编译模型的核心，理解两阶段编译是理解 `t.CDefine`、`t.CExport`、`t.CInline` 等关键概念的前提。

```
源文件 (.py) ──────────────────────────────────────────────────────
    │                                                              │
    │  ┌─────────────── 阶段一：声明提取 ───────────────┐          │
    │  │                                               │          │
    │  │  1. 计算源文件 SHA1                            │          │
    │  │  2. 生成 <SHA1>.pyi（签名存根）                │          │
    │  │  3. 构建结构体注册表                           │          │
    │  │  4. 生成 <SHA1>.stub.ll（LLVM IR 声明）        │          │
    │  │                                                │          │
    │  └────────────────────────────────────────────────┘          │
    │                                                              │
    │  ┌─────────────── 阶段二：代码翻译 ───────────────┐          │
    │  │                                                │          │
    │  │  1. 加载所有 .pyi 和 .stub.ll                  │          │
    │  │  2. 构建共享符号表                             │          │
    │  │  3. 收集内联函数符号                           │          │
    │  │  4. 翻译源文件 → <SHA1>.ll（含代码）           │          │
    │  │  5. llc 编译 → <SHA1>.o（目标文件）            │          │
    │  │  6. ld.lld 链接 → 可执行文件                   │          │
    │  │                                                │          │
    │  └────────────────────────────────────────────────┘          │
    │                                                              │
    └──────────────────────────────────────────────────────────────┘
```

### 阶段一：声明提取（Phase1Generator）

阶段一的目标是从每个源文件提取**声明接口**，使其他模块在阶段二翻译时能够正确解析跨模块引用。

#### 步骤 1：可达文件发现与拓扑排序

从入口文件（`main.py` 或 `project.json` 指定）出发，通过 `import` 语句递归遍历，找出所有可达的 `.py` 源文件。然后对文件进行拓扑排序，确保被依赖的模块先被处理。

```
main.py → import serial → import drivers.serial.uart.serial → ...
```

#### 步骤 2：生成 `.pyi` 签名存根

对每个源文件，计算其内容的 SHA1 哈希（16位），然后调用 `PythonToStubConverter` 生成签名存根文件 `<SHA1>.pyi`。

**SHA1 计算方式**：
```python
sha1 = hashlib.sha1(content.encode('utf-8')).hexdigest()[:16]
```

**存根文件的内容规则**：

| 源文件元素 | 存根文件中的表示 |
|-----------|----------------|
| `t.CDefine` 常量 | 保留原样（含赋值）：`MAX_SIZE: t.CDefine = 1024` |
| `t.CDefine` 函数（返回 `t.CDefine` 的函数） | 保留完整函数体（宏展开需要） |
| 普通函数 | 仅保留签名，添加 `| c.State`：`def foo(x: t.CInt) -> t.CVoid | c.State: pass` |
| 类定义 | 保留成员类型注解和方法签名 |
| 全局变量 | 添加 `t.CExtern`：`x: t.CExtern | t.CInt` |
| `c.CIfdef`/`c.CEndif()` 等预处理指令 | 保留原样 |
| `import` 语句 | 保留原样 |

**关键设计**：`t.CDefine` 常量和 `t.CDefine` 函数在存根中**保留完整定义**（包括赋值和函数体），因为它们是编译时常量/宏，其他模块引用时需要完整展开。普通函数只保留签名并标记 `c.State`（仅声明），因为函数体在阶段二生成。


#### 步骤 3：构建结构体注册表

扫描所有已生成的 `.pyi` 文件，提取：
- **结构体名称集合**：所有非枚举、非异常的 `class` 定义
- **枚举名称集合**：继承 `t.CEnum` 的类
- **异常名称集合**：继承 `Exception` 的类
- **结构体→SHA1 映射**：记录每个结构体定义在哪个模块中

这个注册表用于阶段一的声明生成和阶段二的类型解析，确保跨模块的结构体引用使用正确的 SHA1 命名空间。

#### 步骤 4：生成 `.stub.ll` LLVM IR 声明

对每个 `.pyi` 文件，由 `DeclarationGenerator` 生成对应的 LLVM IR 声明文件 `<SHA1>.stub.ll`。

**声明生成规则**：

| 元素 | 生成的 LLVM IR |
|------|---------------|
| 普通函数 | `declare void @"<SHA1>.foo"(i32)` — 非 CExport 函数加 SHA1 前缀 |
| CExport 函数 | `declare i32 @main()` — CExport 函数不加前缀，全局可见 |
| 结构体 | `%"<SHA1>.ClassName" = type { i32, i32* }` — 类型名加 SHA1 前缀 |
| 全局变量 | `@varname = external global i32` |
| `t.CDefine` 常量 | **不生成声明**（编译时常量，直接内联展开） |
| `t.CTypedef` 别名 | **不生成声明**（类型别名，在类型解析时展开） |
| 枚举 | 为每个枚举成员生成 `@__config_EnumName_member = external global i32` |

**增量编译**：如果 `<SHA1>.pyi` 或 `<SHA1>.stub.ll` 已存在，则跳过生成（缓存命中）。只有源文件内容变化导致 SHA1 变化时才重新生成。

### 阶段二：代码翻译（Phase2Translator）

阶段二使用阶段一生成的声明接口，将源文件翻译为包含完整代码的 LLVM IR。

#### 步骤 1：加载声明接口

加载 `temp/` 目录中所有的 `.pyi` 和 `.stub.ll` 文件，构建：
- `sig_files`：SHA1 → `.pyi` 文件路径映射
- `stub_files`：SHA1 → `.stub.ll` 文件路径映射
- `sha1_map`：SHA1 → 源文件相对路径映射

#### 步骤 2：构建共享符号表

一次性构建所有文件共享的符号表数据，避免每个文件重复加载。将所有 `.pyi` 存根和 `.stub.ll` 声明中的类型信息注册到统一的 `SymbolTable` 中。

#### 步骤 3：收集内联函数符号

扫描 `includes/` 目录中被引用的模块，收集标记为 `t.CInline` 的函数。内联函数的完整 AST body 被保存，在翻译调用点时直接展开。值得注意的是，和 C 语言不同，`t.CInline` 不是优化建议，而是强制性的。

#### 步骤 4：翻译源文件

对每个源文件，使用 `TransPyC` 翻译器将 Python AST 翻译为 LLVM IR：
1. 将对应模块的 `.stub.ll` 声明嵌入到生成的 `.ll` 文件头部
2. 所有被引用模块的 `.stub.ll` 声明也被嵌入
3. 翻译 AST 节点为 LLVM IR 指令
4. 输出 `<SHA1>.ll` 文件

#### 步骤 5：编译与链接

- `llc`：将每个 `.ll` 编译为 `.o` 目标文件
- `ld.lld`：将所有 `.o` 链接为最终可执行文件

## SHA1 命名空间机制

SHA1 命名空间是 Viper 解决跨模块符号冲突的核心机制。

### 问题

在 C 语言中，多个模块可能定义同名函数或结构体，导致链接时符号冲突。C 的解决方案是 `static`（限制可见性）和命名前缀（手动避免冲突）。

### Viper 的解决方案

Viper 使用源文件内容的 SHA1 哈希作为命名空间前缀：

```
源文件 A.py（SHA1 = a1b2c3d4e5f6g7h8）中定义：
    class Point: x: t.CInt; y: t.CInt
    def draw(p: Point) -> t.CVoid: ...

源文件 B.py（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"*)

    B.py 的结构体 → %"i9j0k1l2m3n4o5p6.Point" = type { float, float }
    B.py 的函数   → declare void @"i9j0k1l2m3n4o5p6.draw"(%"i9j0k1l2m3n4o5p6.Point"*)
```

**没有符号冲突**——即使两个模块定义了同名类型和函数，它们的 LLVM IR 符号也是不同的。即便有两个内容完全相同的文件也不会冲突，他们会被识别为同一个文件，然后进行单次编译。

### SHA1 前缀的豁免：`t.CExport`

标记为 `t.CExport` 的函数**不加 SHA1 前缀**，保持原始函数名。这是模块向外部暴露 API/ABI 的机制：

```python
# main.py — 入口函数，必须全局可见
def main() -> t.CInt | t.CExport:
    return 0

# 编译后：define i32 @main() — 无 SHA1 前缀
```

```python
# serial.py — 驱动接口，对外暴露
def init() -> t.CVoid | t.CExport:
    serial_puts("init\n")

# 编译后：define void @init() — 无 SHA1 前缀，其他模块可直接调用
```

### SHA1 与增量编译

SHA1 同时服务于增量编译：
- 源文件内容不变 → SHA1 不变 → `.pyi` 和 `.stub.ll` 缓存命中，跳过阶段一
- 源文件内容变化 → SHA1 变化 → 重新生成声明接口
- `temp/_sha1_map.txt` 记录 SHA1 → 源文件路径的映射，供阶段二加载

理论上，如果一个未经变动的模块的依赖路径上存在变动的模块，暂时的方法是将其简单做 SHA1 替换，暨将旧 SHA1 替换为新 SHA1，但不适用于签名改变的情况，不过签名改变这个未经变动的模块必然也需要改变，但是由于宏展开的存在，不能完全保证不会发生错误情况。且依赖路径的 SHA1 替换成功性未经完整测试，可能出现未定义行为。

## `t.CDefine` 深度解析

`t.CDefine` 是 Viper 中最特殊的类型——它不是数据类型，而是**编译时元指令**，控制编译器的代码生成行为。

### `t.CDefine` 常量

```python
MAX_SIZE: t.CDefine = 1024
PAGE_SIZE: t.CDefine = 4096
FA_READ: t.CDefine = 0x01
CPU_FEATURE_FPU: t.CDefine = (1 << 0)
```

**编译行为**：
1. **阶段一**：存根生成器保留 `t.CDefine` 常量的完整定义（包括赋值值），因为其他模块可能引用此常量
2. **阶段一**：`.stub.ll` 声明生成器**跳过** `t.CDefine` 常量，不生成 `external global` 声明
3. **阶段二**：翻译器遇到 `t.CDefine` 常量的引用时，直接内联其值，不生成任何加载指令

这意味着 `t.CDefine` 常量在 LLVM IR 层面**不存在**——它们在编译时被完全展开，等价于 C 的 `#define` 宏。

### `t.CDefine` 函数

当函数的返回类型注解包含 `t.CDefine` 时，该函数被编译器视为**宏函数**：

```python
def MAKE_FLAG(bit) -> t.CDefine:
    return (1 << bit)

def GET_PAGE_ORDER(size) -> t.CDefine:
    return size // PAGE_SIZE
```

**编译行为**：
1. **阶段一**：存根生成器保留 `t.CDefine` 函数的**完整函数体**（不像普通函数那样只保留签名）
2. **阶段二**：翻译器遇到 `t.CDefine` 函数的调用时，将调用内联展开为函数体的计算结果

`t.CDefine` 函数在 LLVM IR 中**不生成函数定义**——它们是纯粹的编译时宏。

### `t.CDefine` 与类型组合

`t.CDefine` 可以与具体类型组合使用，为常量指定底层类型：

```python
CODE_SEG: t.CDefine | t.CUInt16T = 0x08
DATA_SEG: t.CDefine | t.CUInt16T = 0x10
```

这表示常量在类型检查时被视为 `t.CUInt16T`（`uint16_t`），但在代码生成时仍然内联展开。

## `t.CExport` 深度解析

`t.CExport` 控制函数的符号可见性，是 SHA1 命名空间的豁免机制。

### 语义

| 修饰 | LLVM IR 函数名 | 链接可见性 | 用途 |
|------|---------------|-----------|------|
| 无修饰 | `@<SHA1>.funcname` | 模块内部 | 模块私有函数 |
| `t.CExport` | `@funcname` | 全局可见 | 对外暴露的 API |
| `t.CExtern` | `@funcname`（仅声明） | 外部定义 | 引用外部函数 |

### 使用场景

```python
# 入口函数 — 必须全局可见，链接器需要找到它
def _start() -> t.CInt | t.CExport:
    return kernel_main()

# 驱动接口 — 其他模块/应用需要调用
def init() -> t.CVoid | t.CExport:
    uart_init()

# 内部辅助函数 — 不需要全局可见，自动加 SHA1 前缀
def _helper() -> t.CInt:
    return 42
```

### `t.CExport` 在存根中的表现

在 `.pyi` 存根文件中，`t.CExport` 函数与普通函数一样只保留签名（添加 `c.State`，表示单纯声明），但 `t.CExport` 标记被保留在返回类型注解中。阶段一的 `DeclarationGenerator` 检查 `t.CExport` 标记来决定是否添加 SHA1 前缀。

## `t.CInline` 深度解析

`t.CInline` 标记函数为内联函数，编译器在调用点直接展开函数体。

### 语义

```python
def fast_add(a: t.CInt, b: t.CInt) -> t.CInt | t.CInline:
    return a + b
```

**编译行为**：
1. **阶段二预收集**：`_collect_inline_symbols` 扫描 `includes/` 目录中被引用的模块，收集所有 `t.CInline` 函数的 AST body
2. **翻译时展开**：遇到内联函数调用时，将函数体的 AST 直接嵌入调用点，替换参数为实际值
3. **不生成独立函数**：内联函数不生成 LLVM IR 函数定义（除非也被非内联调用）

### `t.CInline` 与 `t.CDefine` 函数的区别

| 特性 | `t.CInline` | `t.CDefine` 函数 |
|------|------------|-----------------|
| 展开时机 | 阶段二翻译时 | 阶段二翻译时 |
| 类型检查 | 完整的参数和返回类型检查 | 返回类型为宏，类型检查较弱 |
| 存根表示 | 签名 + `c.State` | 完整函数体 |
| LLVM IR | 可能生成函数定义（如果有非内联调用） | 不生成函数定义 |
| 适用场景 | 性能关键的短函数 | 编译时常量和宏计算 |

## 目标平台

默认目标三元组：`x86_64-none-elf`

数据布局：`e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128`

## Hello World 示例

```python
import t, c

def main() -> t.CInt | t.CExport:
    print("Hello, ViperOS!\n")
    return 0
```

编译流程：

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()` 函数体
3. **编译**：`llc` 将 `.ll` 编译为 `.o`
4. **链接**：`ld.lld` 链接为可执行文件


# 02 - 类型系统

Viper 的类型系统通过 `t` 模块提供，所有类型注解继承 `t.CType` 。大都以 `t.C{TypeName:PascalCase}`为类型，类型注解是 Viper 的核心机制，决定了变量的内存布局、大小和对齐方式。

## 基本类型

### 整数类型

| Viper 类型 | C 等价 | 大小（位） | 有符号 |
|------------|--------|-----------|--------|
| `t.CChar` | `char` | 8 | 是 |
| `t.CShort` | `short` | 16 | 是 |
| `t.CInt` | `int` | 32 | 是 |
| `t.CLong` | `long` | 64 | 是 |
| `t.CUnsignedChar` | `unsigned char` | 8 | 否 |
| `t.CUnsignedShort` | `unsigned short` | 16 | 否 |
| `t.CUnsigned` / `t.CUnsignedInt` | `unsigned int` | 32 | 否 |
| `t.CUnsignedLong` | `unsigned long` | 64 | 否 |
| `t.CSignedChar` | `signed char` | 8 | 是 |

值得注意的是，t.CUnsigned 一般不单独使用，而是配合其它有符号类型，替换表示无符号，比如 `t.CUnsigned | t.CInt`，由于为了便于使用一些常用类型，则将其组合为常用的 `t.CUnginedInt` 等。

### 固定宽度整数类型

| Viper 类型 | C 等价 | 大小（位） | 有符号 |
|------------|--------|-----------|--------|
| `t.CInt8T` | `int8_t` | 8 | 是 |
| `t.CInt16T` | `int16_t` | 16 | 是 |
| `t.CInt32T` | `int32_t` | 32 | 是 |
| `t.CInt64T` | `int64_t` | 64 | 是 |
| `t.CUInt8T` | `uint8_t` | 8 | 否 |
| `t.CUInt16T` | `uint16_t` | 16 | 否 |
| `t.CUInt32T` | `uint32_t` | 32 | 否 |
| `t.CUInt64T` | `uint64_t` | 64 | 否 |

### 最小宽度整数类型

| Viper 类型 | C 等价 | 大小（位） | 有符号 |
|------------|--------|-----------|--------|
| `t.CIntLeast8T` | `int_least8_t` | ≥8 | 是 |
| `t.CIntLeast16T` | `int_least16_t` | ≥16 | 是 |
| `t.CIntLeast32T` | `int_least32_t` | ≥32 | 是 |
| `t.CIntLeast64T` | `int_least64_t` | ≥64 | 是 |
| `t.CUIntLeast8T` | `uint_least8_t` | ≥8 | 否 |
| `t.CUIntLeast16T` | `uint_least16_t` | ≥16 | 否 |
| `t.CUIntLeast32T` | `uint_least32_t` | ≥32 | 否 |
| `t.CUIntLeast64T` | `uint_least64_t` | ≥64 | 否 |

### 最快最小宽度整数类型

| Viper 类型 | C 等价 | 大小（位） | 有符号 |
|------------|--------|-----------|--------|
| `t.CIntFast8T` | `int_fast8_t` | ≥8 | 是 |
| `t.CIntFast16T` | `int_fast16_t` | ≥16 | 是 |
| `t.CIntFast32T` | `int_fast32_t` | ≥32 | 是 |
| `t.CIntFast64T` | `int_fast64_t` | ≥64 | 是 |
| `t.CUIntFast8T` | `uint_fast8_t` | ≥8 | 否 |
| `t.CUIntFast16T` | `uint_fast16_t` | ≥16 | 否 |
| `t.CUIntFast32T` | `uint_fast32_t` | ≥32 | 否 |
| `t.CUIntFast64T` | `uint_fast64_t` | ≥64 | 否 |

### 最大宽度整数类型

| Viper 类型 | C 等价 | 大小（位） | 有符号 |
|------------|--------|-----------|--------|
| `t.CIntMaxT` | `intmax_t` | ≥64 | 是 |
| `t.CUIntMaxT` | `uintmax_t` | ≥64 | 否 |

### stdint 短名别名

通过 `import stdint` 引入，这些短名是上述类型的 `t.CTypedef` 别名，便于在系统编程场景中快速使用。允许直接使用 `from stdint import *` 来直接使用。

#### 基本类型短名

| 短名 | 等价展开 | 说明 |
|------|---------|------|
| `stdint.INT` | `t.CInt` | - |
| `stdint.UINT` | `t.CUnsignedInt` | - |
| `stdint.BOOL` | `t.CInt` | 1 为真，0 为假 |
| `stdint.SHORT` | `t.CShort` | - |
| `stdint.USHORT` | `t.CUnsignedShort` | - |
| `stdint.LONG` | `t.CLong` | - |
| `stdint.ULONG` | `t.CUnsignedLong` | - |
| `stdint.LONGLONG` | `t.CLong \| t.CLong` | - |
| `stdint.ULONGLONG` | `t.CUnsignedLong \| t.CLong` | - |
| `stdint.FLOAT` | `t.CFloat` | - |
| `stdint.DOUBLE` | `t.CDouble` | - |

#### 固定宽度短名

| 短名 | 等价展开 |
|------|---------|
| `stdint.INT8` | `t.CInt8T` |
| `stdint.INT16` | `t.CInt16T` |
| `stdint.INT32` | `t.CInt32T` |
| `stdint.INT64` | `t.CInt64T` |
| `stdint.UINT8` | `t.CUInt8T` |
| `stdint.UINT16` | `t.CUInt16T` |
| `stdint.UINT32` | `t.CUInt32T` |
| `stdint.UINT64` | `t.CUInt64T` |

#### 字节与字短名

| 短名 | 等价展开 | 说明 |
|------|---------|------|
| `stdint.BYTE` | `t.CUnsignedChar` | 8 位无符号 |
| `stdint.WORD` | `t.CUInt16T` | 16 位无符号 |
| `stdint.DWORD` | `t.CUInt32T` | 32 位无符号 |
| `stdint.QWORD` | `t.CUInt64T` | 64 位无符号 |

#### 字符类型短名

| 短名 | 等价展开 | 说明 |
|------|---------|------|
| `stdint.TCHAR` | `t.CChar` | - |
| `stdint.CHARLIST` | `str \| t.CPtr` / `list[str, None]` | - |
| `stdint.WCHAR` | `stdint.WORD` | UTF-16 代码单元 |
| `stdint.CHAR8` | `t.CChar8T` | - |
| `stdint.CHAR16` | `t.CChar16T` | - |
| `stdint.CHAR32` | `t.CChar32T` | - |

#### 指针短名

| 短名 | 等价展开 |
|------|---------|
| `stdint.INTPTR` | `t.CInt \| t.CPtr` |
| `stdint.UINTPTR` | `t.CUnsignedInt \| t.CPtr` |
| `stdint.BYTEPTR` | `stdint.BYTE \| t.CPtr` |
| `stdint.SHORTPTR` | `t.CShort \| t.CPtr` |
| `stdint.USHORTPTR` | `t.CUnsignedShort \| t.CPtr` |
| `stdint.WCHARPTR` | `stdint.WORD \| t.CPtr` |
| `stdint.VOIDPTR` | `t.CVoid \| t.CPtr` |
| `stdint.INT8PTR` | `t.CInt8T \| t.CPtr` |
| `stdint.INT16PTR` | `t.CInt16T \| t.CPtr` |
| `stdint.INT32PTR` | `t.CInt32T \| t.CPtr` |
| `stdint.INT64PTR` | `t.CInt64T \| t.CPtr` |
| `stdint.UINT8PTR` | `t.CUInt8T \| t.CPtr` |
| `stdint.UINT16PTR` | `t.CUInt16T \| t.CPtr` |
| `stdint.UINT32PTR` | `t.CUInt32T \| t.CPtr` |
| `stdint.UINT64PTR` | `t.CUInt64T \| t.CPtr` |
| `stdint.CHAR8PTR` | `t.CChar8T \| t.CPtr` |
| `stdint.CHAR16PTR` | `t.CChar16T \| t.CPtr` |
| `stdint.CHAR32PTR` | `t.CChar32T \| t.CPtr` |

#### 平台特定短名

| 短名 | 等价展开 | 说明 |
|------|---------|------|
| `stdint.FSIZE_t` | `stdint.DWORD` | 文件大小 |
| `stdint.LBA_t` | `stdint.DWORD` | 逻辑块地址 |

### 平台相关类型

| Viper 类型 | C 等价 | 大小（位） | 有符号 |
|------------|--------|-----------|--------|
| `t.CSizeT` | `size_t` | 64 | 否 |
| `t.CIntPtrT` | `intptr_t` | 64 | 是 |
| `t.CUIntPtrT` | `uintptr_t` | 64 | 否 |
| `t.CPtrDiffT` | `ptrdiff_t` | 64 | 是 |

### stdint 短名别名

Viper 在 `stdint` 模块中提供了更简短的类型别名，通过 `t.CTypedef` 映射到对应的完整类型。使用时需 `import stdint`。

#### 固定宽度整数短名

| 短名 | 等价 Viper 类型 | C 等价 |
|------|----------------|--------|
| `INT8` | `t.CInt8T` | `int8_t` |
| `INT16` | `t.CInt16T` | `int16_t` |
| `INT32` | `t.CInt32T` | `int32_t` |
| `INT64` | `t.CInt64T` | `int64_t` |
| `UINT8` | `t.CUInt8T` | `uint8_t` |
| `UINT16` | `t.CUInt16T` | `uint16_t` |
| `UINT32` | `t.CUInt32T` | `uint32_t` |
| `UINT64` | `t.CUInt64T` | `uint64_t` |

#### 固定宽度指针短名

| 短名 | 等价 Viper 类型 | C 等价 |
|------|----------------|--------|
| `INT8PTR` | `t.CInt8T \| t.CPtr` | `int8_t*` |
| `INT16PTR` | `t.CInt16T \| t.CPtr` | `int16_t*` |
| `INT32PTR` | `t.CInt32T \| t.CPtr` | `int32_t*` |
| `INT64PTR` | `t.CInt64T \| t.CPtr` | `int64_t*` |
| `UINT8PTR` | `t.CUInt8T \| t.CPtr` | `uint8_t*` |
| `UINT16PTR` | `t.CUInt16T \| t.CPtr` | `uint16_t*` |
| `UINT32PTR` | `t.CUInt32T \| t.CPtr` | `uint32_t*` |
| `UINT64PTR` | `t.CUInt64T \| t.CPtr` | `uint64_t*` |

#### 字符类型短名

| 短名 | 等价 Viper 类型 | C 等价 |
|------|----------------|--------|
| `CHAR8` | `t.CChar8T` | `char8_t` |
| `CHAR16` | `t.CChar16T` | `char16_t` |
| `CHAR32` | `t.CChar32T` | `char32_t` |
| `CHAR8PTR` | `t.CChar8T \| t.CPtr` | `char8_t*` |
| `CHAR16PTR` | `t.CChar16T \| t.CPtr` | `char16_t*` |
| `CHAR32PTR` | `t.CChar32T \| t.CPtr` | `char32_t*` |

#### 基本类型短名

| 短名 | 等价 Viper 类型 | C 等价 |
|------|----------------|--------|
| `INT` | `t.CInt` | `int` |
| `UINT` | `t.CUnsignedInt` | `unsigned int` |
| `BOOL` | `t.CInt` | `int`（0/1） |
| `SHORT` | `t.CShort` | `short` |
| `USHORT` | `t.CUnsignedShort` | `unsigned short` |
| `LONG` | `t.CLong` | `long` |
| `ULONG` | `t.CUnsignedLong` | `unsigned long` |
| `LONGLONG` | `t.CLong \| t.CLong` | `long long` |
| `ULONGLONG` | `t.CUnsignedLong \| t.CLong` | `unsigned long long` |
| `FLOAT` | `t.CFloat` | `float` |
| `DOUBLE` | `t.CDouble` | `double` |

#### 平台 / Windows 风格短名

| 短名 | 等价 Viper 类型 | C 等价 |
|------|----------------|--------|
| `BYTE` | `t.CUnsignedChar` | `unsigned char`（8位） |
| `BYTEPTR` | `BYTE \| t.CPtr` | `unsigned char*` |
| `WORD` | `t.CUInt16T` | `uint16_t`（16位） |
| `DWORD` | `t.CUInt32T` | `uint32_t`（32位） |
| `QWORD` | `t.CUInt64T` | `uint64_t`（64位） |
| `INTPTR` | `t.CInt \| t.CPtr` | `int*` |
| `UINTPTR` | `t.CUnsignedInt \| t.CPtr` | `unsigned int*` |
| `SHORTPTR` | `t.CShort \| t.CPtr` | `short*` |
| `USHORTPTR` | `t.CUnsignedShort \| t.CPtr` | `unsigned short*` |
| `VOIDPTR` | `t.CVoid \| t.CPtr` | `void*` |
| `TCHAR` | `t.CChar` | `char` |
| `WCHAR` | `WORD` | `uint16_t`（UTF-16） |
| `WCHARPTR` | `WORD \| t.CPtr` | `uint16_t*`（UTF-16） |
| `CHARLIST` | `str \| t.CPtr` | `char*` |
| `FSIZE_t` | `DWORD` | `uint32_t` |
| `LBA_t` | `DWORD` | `uint32_t` |

### 浮点类型

| Viper 类型 | C 等价 | 大小（位） |
|------------|--------|-----------|
| `t.CFloat` | `float` | 32 |
| `t.CDouble` | `double` | 64 |

### 其他基本类型

| Viper 类型 | C 等价 | 说明 |
|------------|--------|------|
| `t.CVoid` | `void` | 空类型 |
| `t.CBool` | `bool` | 布尔类型（8位） |
| `t.CWCharT` | `wchar_t` | 宽字符（32位） |
| `t.CChar8T` | `char8_t` | UTF-8 字符（8位，无符号） |
| `t.CChar16T` | `char16_t` | UTF-16 字符（16位，无符号） |
| `t.CChar32T` | `char32_t` | UTF-32 字符（32位，无符号） |

### Python 便捷映射类型
| Python 类型| Viper 类型 | Viper 值 |
|--------|--------|------|
|`int`|`t.CInt`|-|
|`float`|`t.CFloat`|-|
|`str`|`t.CChar \| t.CPtr`|-|
|`bool`|`t.CBool`|-|
|`True`|`t.CBool`|`1`|
|`False`|`t.CBool`|`0`|
|`None`|`NULL`|`t.CIntPtr(0)`|

对于 t.py 和 c.py 的引用，必须使用 import，不能使用 from ... import ...，也不能使用 as，因为这两者都是直接以字符串识别的。

## 类型组合

Viper 使用 Python 的 `|` 来组合类型修饰符（TypeUnion），其仅在左值注解中有效，其它位置均为位或语义（至少重载前是这样的），这是 Viper 最重要的语法特性之一。

### 指针类型

使用 `t.CPtr` 表示指针，通过 `|` 与基本类型组合：

```python
x: t.CInt  | t.CPtr          # int* — 指向 int 的指针
p: t.CVoid | t.CPtr         # void* — 通用指针
s: t.CChar | t.CPtr         # char* — 字符串指针
pp: t.CInt | t.CPtr | t.CPtr  # int** — 指向指针的指针
```

等价 C 代码：
```c
int* x;
void* p;
char* s;
int** pp;
```

同时，指针也可以用 `Ptr[T]` 的方法表示，但在 Viper 中不太推荐，虽然说这样做一直是类似工程的常见用法，但是如果此处 `T` 是一个多态，同时我们想要复用 Python 的高亮插件，插件无法识别 `Ptr[T]` 的属性取值，但是对于 `T | Ptr` 可以。

```python
x: t.CPtr[t.CInt]
p: t.CPtr[t.CVoid]
s: t.CPtr[t.CChar]
pp: t.CPtr[t.CPtr[t.CInt]]
pp2: t.CInt | t.CPtr[t.CPtr] # 同时也可以这么表示
```

等价 C 代码：

```c
int* x;
void* p;
char* s:
int** pp;
int** pp2;
```

### 类型限定符组合

```python
x: t.CConst | t.CInt        # const int
p: t.CConst | t.CChar | t.CPtr  # const char*
```

### 存储类组合

```python
x: t.CStatic | t.CInt       # static int
f: t.CExtern | t.CInt       # extern int（声明其存在于外部）
```

### 函数返回类型组合

```python
def foo() -> t.CInt | t.CExport:     # 导出函数，返回 int
    return 0

def bar() -> t.CVoid | t.CExtern:    # 外部函数声明
    pass
```

## 数组类型

使用 Python 的 `list[ElementType, Size]` 语法表示固定大小数组（通常的，这用于栈上和 BSS 段上）：

```python
buf: list[t.CChar, 64]           # char buf[64]
ids: list[t.CInt, 10]            # int ids[10]
matrix: list[t.CFloat, 16]       # float matrix[16]
entries: list[idt_entry, 256]    # struct idt_entry entries[256]
s: list[t.CChar, None]           # 自推长度 char s[];
```

等价 C 代码：
```c
char buf[64];
int ids[10];
float matrix[16];
struct idt_entry entries[256];
```

### 数组指针和函数指针

```python
lp: list[t.CInt, 12] | t.CPtr
vp: t.Callable[[t.CInt, t.CInt], t.CInt] = x # 其中 t.Callable = typing.Callable，可以直接使用。
```

## 结构体类型

使用 `class` 定义结构体，成员通过类型注解声明：

```python
class point:
    x: t.CInt
    y: t.CInt
```

等价 C 代码：
```c
struct point {
    int x;
    int y;
};
```

### 带指针成员的结构体

```python
class node:
    value: t.CInt
    next: node | t.CPtr     # struct node* next
```

### 匿名结构体成员（❌）

> WARNING: **警告：** 由于 Viper 在声明结构体，枚举等处不需要关键字，因此 `t.Anonymouse` 是不需要使用的。此关键字不再维护，强行使用可能导致未定义行为。

继承 `t.Anonymous` 的类作为匿名成员嵌入：

```python
class header(t.Anonymous):
    magic: t.CUInt32T
    version: t.CUInt32T

class packet:
    header          # 匿名嵌入，可直接访问 packet.magic
    length: t.CUInt32T
```

### 字节序标记

> WARNING: **警告：** 此关键字是实验性的。未经充分测试，不当使用可能导致未定义行为。

使用 `t.BigEndian` 或 `t.LittleEndian` 标记成员的字节序：

```python
class network_packet:
    length: t.CUInt16T | t.BigEndian     # 大端序存储
    type: t.CUInt8T                       # 默认小端序
```

## 联合体类型

继承 `t.CUnion` 定义联合体：

```python
class value(t.CUnion):
    ival: t.CInt
    fval: t.CFloat
    pval: t.CVoid | t.CPtr
```

等价 C 代码：
```c
union value {
    int ival;
    float fval;
    void* pval;
};
```

## 枚举类型

继承 `t.CEnum` 定义枚举：

```python
class color(t.CEnum):
    RED: t.CEnum = 0
    GREEN: t.CEnum = 1
    BLUE: t.CEnum = 2
```

等价 C 代码：
```c
enum color {
    RED = 0,
    GREEN = 1,
    BLUE = 2
};
```

枚举成员可直接使用名称：

```python
c: t.CInt = color.RED
```

## Typedef

使用 `t.CTypedef` 创建类型别名：

```python
irq_handler_t: t.CTypedef | t.Callable[[], t.CInt]   # typedef int (*irq_handler_t)();
```

或通过注解赋值：

```python
MyStruct: t.CTypedef = original_struct   # typedef struct original_struct MyStruct;
```

更推荐通过后者的形式，前者编译器不一定能够识别到注解是对 t.CTypedef 的，还是后面的注解的，而且容易触发未定义行为。

## 强制类型转换
在 Viper 中的强制类型转换有些不同，强制类型转换有两种方案，都是基于 `t.CType` 的用法，符合 Python 本意。
对于原先就继承自 `t.CType` 的类型来说，可以直接使用 call 的方法进行类型转换，比如
```python
x: t.CChar | t.CPtr = "Hello"
t.CVoid(x, t.CPtr)
```
其中用法为 `t.CType(x, ...)`，此处...可以是其它的 `t.CType` 或将要提到的 `Typedef`，将其视为组合类型对 `x` 进行强制转换。

额外补充一句，对于比较，四则运算，可以不使用强制类型转换，而是依靠隐式类型转换，但如果是严谨数学计算，推荐还是强制类型转换避免判断出错。

此外，若将一个不同类型的右值赋值到左值，则会隐式将右值转换为左值的类型。

如果你不喜欢 `t.CVoid(x, t.CPtr)` 的方法，认为这将 `void` 和 `ptr` 分开，不便于理解，那么还有一个方法，即将二者打包为一个 Typedef，即：
```python
VOIDPTR: t.CTypedef = t.CVoid | t.CPtr
```
则如果你想，你可以直接通过 call 的方式进行强转，比如：
```python
y: VOIDPTR = VOIDPTR(x)
```

## 宏定义常量

使用 `t.CDefine` 定义编译时常量。`t.CDefine` 不是数据类型，而是编译时元指令——标记为 `t.CDefine` 的常量在 LLVM IR 中不生成任何全局变量，而是在引用处直接内联展开。详见 [01-overview.md 中 t.CDefine 深度解析](01-overview.md#tcdefine-深度解析)。

```python
MAX_SIZE: t.CDefine = 1024
PAGE_SIZE: t.CDefine = 4096
FA_READ: t.CDefine = 0x01
```

语义上等价于 C 的 `#define`：
```c
#define MAX_SIZE 1024
#define PAGE_SIZE 4096
#define FA_READ 0x01
```

宏定义支持表达式：

```python
CPU_FEATURE_FPU: t.CDefine = (1 << 0)
CPU_FEATURE_APIC: t.CDefine = (1 << 6)
```

宏定义也可与类型组合使用：

```python
CODE_SEG: t.CDefine | t.CUInt16T = 0x08
```

## 位域

使用 `t.Bit(n)` 定义位域成员：

```python
class flags:
    a: t.CUInt32T | t.Bit[1] # 此处，如果存入 2，二进制是 10，会被截断为 0
    b: t.CUInt32T | t.Bit[3]
    c: t.CUInt32T | t.Bit[4]
```

## LLVM IR 类型简写

Viper 提供了 LLVM IR 级别的类型简写：

```python
i1   # 1位整数
i8   # 8位有符号整数
i16  # 16位有符号整数
i32  # 32位有符号整数
i64  # 64位有符号整数
u1   # 1位无符号整数
u8   # 8位无符号整数
u16  # 16位无符号整数
u32  # 32位无符号整数
u64  # 64位无符号整数
```

仍然通过 `t.x` 的方式调用，比如 `t.i1` 等。

## `__attribute__` 属性

通过 `t.attr` 命名空间访问 GCC `__attribute__` 属性：

```python
t.attr.packed()                    # __attribute__((packed))
t.attr.aligned(16)                 # __attribute__((aligned(16)))
t.attr.section(".text.startup")    # __attribute__((section(".text.startup")))
t.attr.always_inline()             # __attribute__((always_inline))
t.attr.noinline()                  # __attribute__((noinline))
t.attr.noreturn()                  # __attribute__((noreturn))
t.attr.weak()                      # __attribute__((weak))
t.attr.unused()                    # __attribute__((unused))
t.attr.constructor()               # __attribute__((constructor))
t.attr.destructor()                # __attribute__((destructor))
t.attr.deprecated("use X")         # __attribute__((deprecated("use X")))
```

### LLVM 函数属性

通过 `t.attr.llvm` 命名空间指定 LLVM 函数属性：

```python
t.attr.llvm.nobuiltin
t.attr.llvm.nounwind
t.attr.llvm.noredzone
t.attr.llvm.willreturn
t.attr.llvm.mustprogress
t.attr.llvm.optnone
t.attr.llvm.noinline
t.attr.llvm.alwaysinline
t.attr.llvm.readnone
t.attr.llvm.readonly
t.attr.llvm.writeonly
t.attr.llvm.inaccessiblememonly
t.attr.llvm.inaccessiblemem_or_argmemonly
```

在函数返回类型注解中使用：

```python
def foo() -> t.CInt | t.attr.llvm.nobuiltin | t.attr.llvm.nounwind:
    return 0
```


# 03 - 变量声明与赋值

Viper 的变量声明使用 Python 的类型注解语法，通过 `t` 模块指定 C 级别的类型信息。

## 带注解的变量声明

使用 `变量名: 类型` 语法声明变量：

```python
x: t.CInt = 0                    # int x = 0;
y: t.CUInt32T = 42               # uint32_t y = 42;
name: list[t.CChar, 64]          # char name[64];
ptr: t.CVoid | t.CPtr            # void* ptr;
msg: t.CConst | str = "Hello"    # const char* msg = "Hello";
```

### 无初始值的声明

未赋值的变量声明会生成零初始化的变量，此处是未定义行为，即在不同环境位置可能会覆盖0，也可能不会，最好预先复制或用 memset 清除：

```python
count: t.CInt                     # int count = 0;
buffer: list[t.CChar, 256]        # char buffer[256] = {0};
```

### 延迟赋值

变量可以先声明后赋值：

```python
x: t.CInt
x = 10
```

### 指针变量

```python
p:       t.CInt | t.CPtr               # int* p;
fb:      t.CVoid | t.CPtr             # void* fb;
str_ptr: t.CConst | t.CChar | t.CPtr  # const char* str_ptr;
```

### 指针变量的特殊初始化

使用 `t.CVoid(0, t.CPtr)` 初始化指针为 NULL：

```python
p: t.CVoid | t.CPtr = t.CVoid(0, t.CPtr)  # void* p = NULL;
```

或使用 `None`：

```python
p: t.CVoid | t.CPtr = None      # void* p = NULL;
```

## 普通赋值

```python
x: t.CInt = 0
x = 42                            # x = 42;
```

## 增强赋值

支持所有 Python 增强赋值运算符：

```python
x: t.CInt = 0
x += 1                            # x += 1;
x -= 1                            # x -= 1;
x *= 2                            # x *= 2;
x //= 3                           # x /= 3; (整数除法)
x %= 5                            # x %= 5;
x <<= 1                           # x <<= 1;
x >>= 1                           # x >>= 1;
x |= 0xFF                         # x |= 0xFF;
x &= 0x0F                         # x &= 0x0F;
x ^= 0xAA                         # x ^= 0xAA;
```

## 全局变量

模块顶层声明的变量即为全局变量：

```python
kbd_tid: t.CInt = -1              # 全局 int kbd_tid = -1;
BootInfo: bootinfo | t.CPtr       # 全局 struct bootinfo* BootInfo;
```

### 静态全局变量

```python
x: t.CStatic | t.CInt = 0        # static int x = 0;
```

### 外部声明

```python
x: t.CExtern | t.CInt            # extern int x;
```

## 常量定义

使用 `t.CDefine` 定义编译时常量。`t.CDefine` 不是数据类型，而是编译时元指令——常量在 LLVM IR 中不生成全局变量，而是在引用处直接内联展开。详见 [01-overview.md 中 t.CDefine 深度解析](01-overview.md#tcdefine-深度解析)。

```python
MAX_SIZE: t.CDefine = 1024
PAGE_SIZE: t.CDefine = 4096
FA_READ: t.CDefine = 0x01
FA_WRITE: t.CDefine = 0x02
```

## 字符串常量

Viper 中的字符串字面量编译为 C 的字符串常量（`const char*`）：

```python
msg: t.CConst | str = "Hello, World!"
serial.puts(msg)
```

也可以直接传递字符串字面量：

```python
serial.puts("Hello, World!")
```

## 类型转换

使用类型构造函数进行显式类型转换：

```python
x: t.CInt = 42
y: t.CUInt32T = t.CUInt32T(x)    # (uint32_t)x
f: t.CFloat = float(x)           # (float)x
i: t.CInt = int(f)               # (int)f
```

### 指针类型转换

```python
ptr: t.CVoid | t.CPtr = some_ptr
int_val: t.CUInt64T = t.CUInt64T(ptr)  # (uint64_t)ptr — 指针转整数
```

## 结构体实例化

> 此处不理解参见 ([05-classes.md 中 结构体实例化与初始化](05-classes.md#结构体实例化与初始化))

直接使用类名作为构造函数：

```python
info: fat32_types.fat32_fileinfo
dp: fat32_types.fat32_dirobj
```

带初始化的实例化：

```python
obj: MyClass = MyClass(arg1, arg2)
```

使用 `c.Addr` 获取实例指针：

```python
obj_ptr: MyClass | t.CPtr = c.Addr(MyClass(arg1, arg2))
```

## delete 语句

`del` 语句可用于调用对象的 `__del__` 或 `__delete__` 方法：

```python
del obj        # 调用 obj.__del__() 或 obj.__delete__()
del arr[idx]   # 调用 arr.__delitem__(idx)
```


# 04 - 函数定义与调用

Viper 的函数定义使用 Python 的 `def` 语法，通过类型注解指定参数类型和返回类型。

## 基本函数定义

```python
def add(a: t.CInt, b: t.CInt) -> t.CInt:
    return a + b
```

等价 C 代码：
```c
int add(int a, int b) {
    return a + b;
}
```

## 无返回值函数

```python
def print_msg(msg: t.CConst | t.CChar | t.CPtr) -> t.CVoid:
    serial.puts(msg)
```

等价 C 代码：
```c
void print_msg(const char* msg) {
    serial_puts(msg);
}
```

## 函数修饰符

通过返回类型的 `|` 组合添加函数修饰符：

### 导出函数

` t.CExport` 控制函数的符号可见性——标记为 `t.CExport` 的函数不加 SHA1 前缀，全局可见。详见 [01-overview.md 中 t.CExport 深度解析](01-overview.md#tcexport-深度解析)。

```python
def _start() -> t.CInt | t.CExport:
    return 0
```

### 外部函数声明

使用 `c.State` 表示仅声明不定义：

```python
def isr0() -> t.CExtern | t.CVoid | c.State: pass
def isr1() -> t.CExtern | t.CVoid | c.State: pass
```

等价 C 代码：
```c
extern void isr0();
extern void isr1();
```

### 内联函数

`t.CInline` 标记函数为内联函数，编译器在调用点直接展开函数体。详见 [01-overview.md 中 t.CInline 深度解析](01-overview.md#tcinline-深度解析)。

```python
def fast_add(a: t.CInt, b: t.CInt) -> t.CInt | t.CInline:
    return a + b
```

### 宏函数

当函数返回类型注解包含 `t.CDefine` 时，该函数被视为宏函数，不生成 LLVM IR 函数定义，在调用处内联展开。详见 [01-overview.md 中 t.CDefine 函数](01-overview.md#tcdefine-函数)。

```python
def MAKE_FLAG(bit) -> t.CDefine:
    return (1 << bit)
```

### 静态函数

```python
def helper() -> t.CVoid | t.CStatic:
    pass
```

## 函数属性装饰器

使用 `@c.Attribute` 添加 GCC `__attribute__` 属性：

```python
@c.Attribute(t.attr.section(".text.startup"), t.attr.aligned(16))
def _start() -> t.CInt:
    return 0
```

等价 C 代码：
```c
__attribute__((section(".text.startup"), aligned(16)))
int _start() {
    return 0;
}
```

### 常用属性组合

```python
@c.Attribute(t.attr.always_inline())
def hot_path() -> t.CInt:
    return 0

@c.Attribute(t.attr.noreturn())
def panic(msg: t.CConst | t.CChar | t.CPtr) -> t.CVoid:
    serial.puts(msg)
    while True: pass

@c.Attribute(t.attr.packed)
```

## LLVM 函数属性

在返回类型注解中通过 `t.attr.llvm` 指定 LLVM 属性：

```python
def foo() -> t.CInt | t.attr.llvm.nobuiltin | t.attr.llvm.nounwind:
    return 0
```

## 多返回值（CReturn）

使用 `@c.CReturn` 装饰器实现多返回值，通过指针参数实现：

```python
@c.CReturn(t.CInt, t.CInt)
def divmod(a: t.CInt, b: t.CInt) -> t.CVoid:
    q: t.CInt = a // b
    r: t.CInt = a % b
    return q, r
```

规则：
1. `CReturn` 中的类型数量决定返回值个数
2. 自动为每个返回类型添加指针参数（`t.CInt` → `t.CInt | t.CPtr`）
3. 参数名自动生成为 `__ReturnValue0__`、`__ReturnValue1__` 等
4. 调用处自动传参 `&xxx`
5. 必须使用左右值赋值，返回值不能直接传入函数。

## 指针参数

```python
def read_data(buf: t.CChar | t.CPtr, size: t.CSizeT) -> t.CInt:
    pass
```

等价 C 代码：
```c
int read_data(char* buf, size_t size);
```

### 输出参数模式

使用 `c.Addr` 传递变量地址作为输出参数：

```python
res: t.CInt = fat32.opendir("/", c.Addr(dp))
```

等价 C 代码：
```c
int res = fat32_opendir("/", &dp);
```

后续会使用隐式左值获取来减少 `c.Addr` 的直接使用。

## 函数指针类型

使用 `t.Callable` 定义函数指针类型：

```python
irq_handler_t: t.CTypedef | t.Callable[[], t.CInt]
```

等价 C 代码：
```c
typedef int (*irq_handler_t)();
```

带参数的函数指针：

```python
callback_t: t.Callable[[t.CInt, t.CInt], t.CVoid]
```

## 默认参数

Viper 支持函数默认参数值：

```python
def create_window(x: t.CInt, y: t.CInt, w: t.CInt, h: t.CInt, title: t.CConst | str = "Window") -> t.CInt:
    pass
```

## return 语句

```python
return 0                          # return 0;
return                            # return; (void 函数)
return a, b                       # 多返回值（需配合 @c.CReturn）
```

## 全局变量声明

函数外的变量声明为全局变量，函数内通过 `global` 关键字访问：

```python
BootInfo: bootinfo | t.CPtr

def init() -> t.CVoid:
    global BootInfo
    BootInfo = saved_rdi
```

支持 func-in-func 嵌套函数。

## Call Func 函数调用

函数调用最好通过顺序调用来实现

```python
def add(x: int, y: int, z: int):
    return (x + y) * z

def main() -> int | t.CExport:
    print(add(1, 2, 3)) # (1 + 2) * 3 = 9
```

这也是 C 中的标准实现方法，但实际上，你也可以乱序传参。

```python
# 仍然用刚才的 add 举例
def main() -> int | t.CExport:
    print(add(z=3, x=1, y=2)) # (1 + 2) * 3 = 9
```

乱序传参或带参传参对于结构体的初始化同样有效。同时，你也能够给函数指定默认值。

```python
def add(x: int, y: int, z: int = 1):
    return (x + y) * z

def main() -> int | t.CExport:
    print(add(1, 2)) # (1 + 2) * 1 = 3
```

在结构体中也可以指定默认值。


# 05 - 类与数据布局

Viper 中的 `class` 有两种用途：定义**数据布局**（结构体/联合体/枚举，本章内容），以及定义**面向对象的对象类型**（见 [06-oop.md](06-oop.md)）。

## 结构体定义

普通 `class` 定义编译为 LLVM 结构体类型：

```python
class point:
    x: t.CInt
    y: t.CInt
```

在 C 中：
```c
struct point {
    int x;
    int y;
};
```

在 LLVM IR 中：
```llvm
%"<SHA1>.point" = type { i32, i32 }
```

### 带属性的结构体

```python
@c.Attribute(t.attr.packed)
class idt_entry:
    base_low:    t.CUInt16T
    selector:    t.CUInt16T
    ist_attr:    t.CUInt8T
    type_attr:   t.CUInt8T
    base_middle: t.CUInt16T
    base_high:   t.CUInt32T
    reserved1:   t.CUInt32T
```

### 结构体数组

```python
idt: list[idt_entry, 256] = []
```

### 结构体指针成员

```python
class node:
    value: t.CInt
    next: node | t.CPtr          # 指向自身的指针（有向图链表）
```

### 结构体实例化与初始化

```python
entry: idt_entry = idt_entry()
```

或带构造函数：

```python
mousepoint = Point(x=1, y=2)
```

乱序传参或带参传参对于结构体的初始化同样有效：

```python
entry: idt_entry = idt_entry(selector=0x08, base_low=0x0000)
```

也可以给结构体成员指定默认值：

```python
class config:
    width: t.CInt = 640
    height: t.CInt = 480
    depth: t.CInt = 32
```

使用 `c.Addr` 获取实例指针：

```python
obj_ptr: MyClass | t.CPtr = c.Addr(MyClass(arg1, arg2))
```

### 匿名结构体成员（❌）

> WARNING: **警告：** 由于 Viper 在声明结构体，枚举等处不需要关键字，因此 `t.Anonymouse` 是不需要使用的。此关键字不再维护，强行使用可能导致未定义行为。

继承 `t.Anonymous` 的类作为匿名成员嵌入：

```python
class header(t.Anonymous):
    magic: t.CUInt32T
    version: t.CUInt32T

class packet:
    header          # 匿名嵌入，可直接访问 packet.magic
    length: t.CUInt32T
```

### 字节序标记

> WARNING: **警告：** 此关键字是实验性的。未经充分测试，不当使用可能导致未定义行为。

使用 `t.BigEndian` 或 `t.LittleEndian` 标记成员的字节序：

```python
class network_packet:
    length: t.CUInt16T | t.BigEndian     # 大端序存储
    type: t.CUInt8T                       # 默认小端序
```

## 联合体

继承 `t.CUnion` 定义联合体：

```python
class value(t.CUnion):
    ival: t.CInt
    fval: t.CFloat
    pval: t.CVoid | t.CPtr
```

等价 C 代码：
```c
union value {
    int ival;
    float fval;
    void* pval;
};
```

## 枚举

继承 `t.CEnum` 定义枚举：

```python
class color(t.CEnum):
    RED:   t.CEnum = 0
    GREEN: t.CEnum = 1
    BLUE:  t.CEnum = 2
```

等价 C 代码：
```c
enum color {
    RED = 0,
    GREEN = 1,
    BLUE = 2
};
```

枚举成员可直接使用名称：

```python
c: t.CInt = color.RED
```

## Typedef

使用 `t.CTypedef` 创建类型别名：

```python
irq_handler_t: t.CTypedef | t.Callable[[], t.CInt]   # typedef int (*irq_handler_t)();
```

或通过注解赋值：

```python
MyStruct: t.CTypedef = original_struct   # typedef struct original_struct MyStruct;
```

更推荐通过后者的形式，前者编译器不一定能够识别到注解是对 `t.CTypedef` 的，还是后面的注解的，而且容易触发未定义行为。

## 位域

使用 `t.Bit(n)` 定义位域成员：

```python
class flags:
    a: t.CUInt32T | t.Bit[1]
    b: t.CUInt32T | t.Bit[3]
    c: t.CUInt32T | t.Bit[4]
```

注意：如果存入超出位域宽度的值，会被截断。例如 `a` 为 1 位，存入 2（二进制 `10`）会被截断为 0。


# 06 - 面向对象与运算符重载

Viper 中的 `class` 有两种语义：**数据布局**（结构体/联合体/枚举，见 [05-classes.md](05-classes.md)）和**面向对象**。面向对象特性通过 `@t.Object` 装饰器启用，多态通过 `@t.CVTable` 装饰器启用。

## `@t.Object` 面向对象

使用 `@t.Object` 装饰器启用面向对象特性，类将拥有成员方法、运算符重载、属性装饰器等 OOP 支持。编译器也会自动识别：如果结构体内有函数定义，会自动使用 `@t.Object` 行为，但在实际工程中更推荐明确标记，避免未定义行为。

### 基本定义

```python
@t.Object
class ViperKernel:
    BootInfo: bootinfo | t.CPtr
    VGA: vga._VGAScreenDriver | t.CPtr
    VGA_drv: vga._VGAScreenDriver

    def __init__(self):
        self.BootInfo = BootInfo
        serial.init()
        serial.puts("ViperOS VKernel Test\n")
```

避免在 `__init__` 中使用 `return`，虽然不会报错，但是你永远无法获得 `return` 的结果，如果需要提前结束代码流，`return` 也不失为一种办法。

### 成员方法

```python
@t.Object
class Sheet:
    id: t.CInt
    x: t.CInt
    y: t.CInt
    w: t.CInt
    h: t.CInt

    def __init__(self, x: t.CInt, y: t.CInt, w: t.CInt, h: t.CInt):
        self.x = x
        self.y = y
        self.w = w
        self.h = h

    def MoveTo(self, nx: t.CInt, ny: t.CInt):
        self.x = nx
        self.y = ny

    def Resize(self, nw: t.CInt, nh: t.CInt):
        self.w = nw
        self.h = nh
```

### 方法调用

```python
sheet: Sheet = Sheet(0, 0, 640, 480)
sheet.MoveTo(100, 100)
sheet.Resize(800, 600)
```

### 属性装饰器

支持 Python 的 `@property` 和 `@xxx.setter` 装饰器：

> `@xxx.setter` 和自定义装饰器正在试验阶段，尽可能不要使用

```python
@t.Object
class MyObj:
    _value: t.CInt

    @property
    def value(self) -> t.CInt:
        return self._value

    @value.setter
    def value(self, v: t.CInt):
        self._value = v
```

### 静态方法

```python
@staticmethod
def _yield():
    pass
```

### 对象指针与解引用

`@t.Object` 的实例通常通过指针操作：

```python
obj_ptr: MyClass | t.CPtr = c.Addr(MyClass())
obj: MyClass = c.Deref(obj_ptr)
```

### 成员访问

通过 `self` 访问成员变量和方法：

```python
def method(self) -> t.CVoid:
    self.x = 10
    y: t.CInt = self.y
    self.DoSomething()
```

### 内嵌对象

`@t.Object` 可以包含其他对象实例（非指针）：

```python
@t.Object
class Sheet:
    _surf_obj: gfx.Surface
    _renderer_obj: gfx.Renderer
    surf: gfx.Surface | t.CPtr
    renderer: gfx.Renderer | t.CPtr

    def __init__(self, fb: UINT32PTR, zb: float | t.CPtr, w: t.CInt, h: t.CInt):
        self._surf_obj = gfx.Surface(fb, zb, w, h)
        self.surf = c.Addr(self._surf_obj)
        self._renderer_obj = gfx.Renderer(self.surf)
        self.renderer = c.Addr(self._renderer_obj)
```

### `__before_init__` 方法

`@t.Object` 或 `@t.CVTable` 类自动生成 `__before_init__` 方法声明，用于在 `__init__` 之前初始化 vtable：

```llvm
declare void @"<SHA1>.ClassName.__before_init__"(%"<SHA1>.ClassName"*)
```

值得注意的是，`__before_init__` 并不帮忙初始化内存，而只是初始化虚表等准备工作，实际上，我们更希望用户能自己管理内存。实验性阶段内容中，我们通过内存池机制来帮助用户管理碎片化内容，包括部分小的结构体，但较大内容最好还是由用户手动处理。

## `@t.CVTable` 虚函数表与多态

> 尽可能避免使用 `self[0]` 来获取结构体成员，其不稳定，也不要手动操作虚表。

使用 `@t.CVTable` 装饰器可以启用虚函数表支持。启用后，结构体第一个成员自动插入 `i8*` 类型的 vtable 指针。`@t.CVTable` 的操作必须配合 `@t.Object`，但有时编译器会自动识别是否存在结构体内函数，自动使用 `@t.Object`。

### 基本定义

```python
@t.Object
@t.CVTable
class Base:
    def __init__(self):
        pass
    def method(self) -> t.CInt:
        return 0
```

在 LLVM IR 中，`@t.CVTable` 类的结构体类型自动插入 vtable 指针：

```llvm
%"<SHA1>.Base" = type { i8*, i32 }
```

同时，编译器会生成全局 vtable 变量：

```llvm
@"<SHA1>.Base_Vtable" = internal global [1 x i8*] zeroinitializer
```

### 继承与多态

虚表可以帮你使用继承语法实现多态：

```python
@t.Object
@t.CVTable
class Base:
    def __init__(self):
        pass
    def method(self) -> t.CInt:
        return 0

@t.Object
@t.CVTable
class M1(Base):
    def method(self) -> t.CInt:
        return 1
```

当 M1 被初始化时，VTable 会自动修改，这点和 C++ 相同，尽可能避免直接操作 VTable。

继承时，子类会自动继承父类的成员变量和方法。子类重写父类方法时，vtable 中对应位置的函数指针被子类方法替换，实现多态。

### VTable 运行时修改

如果需要临时构造一个额外的 `Base` 结构体，还可以使用：

```python
@t.Object
@t.CVTable
class Base:
    def __init__(self):
        pass
    def method(self) -> t.CInt:
        return 0

def __method1(self) -> t.CInt:
    return 1

def main() -> t.CInt | t.CExport:
    b: Base = Base()
    b.method = __method1
```

启用 `VTable` 的表中，允许直接修改内部函数为函数指针，在底层，此操作将修改 `VTable` 来达成目的。编译器会检测当前 vtable 是否与类 vtable 相同，如果相同则创建 vtable 的副本（memcpy），避免修改影响所有实例。

### 虚方法调度机制

虚方法调用的核心流程：

1. 从对象指针 GEP 获取第 0 个 slot（vtable 指针）
2. 加载 vtable 指针
3. bitcast 为 `[N x i8*]*` 类型
4. GEP 获取方法索引处的函数指针
5. 加载函数指针
6. bitcast 为正确的函数指针类型
7. 间接调用

## 继承

### 结构体成员继承

当子类继承父类（父类在 `Gen.class_members` 中存在）时：

- 父类的成员变量被继承到子类（排在子类成员之前）
- 父类的默认值也被继承
- 父类的方法被继承（重命名为 `子类名.方法名`）

```python
@t.Object
class Animal:
    name: list[t.CChar, 32]
    age: t.CInt

    def __init__(self, age: t.CInt):
        self.age = age

    def Speak(self) -> t.CVoid:
        serial.puts("...\n")

@t.Object
class Dog(Animal):
    breed: t.CInt

    def Speak(self) -> t.CVoid:
        serial.puts("Woof!\n")
```

### 异常类继承

Viper 支持异常类的继承，用于 `try/except` 的异常匹配：

```python
class MyError(Exception):
    pass

class SpecificError(MyError):
    pass
```

详见 [09-exceptions.md](09-exceptions.md)。

## 运算符重载

`@t.Object` 类支持运算符重载。编译器在遇到运算符时，首先检查左操作数是否为结构体类型，如果是则尝试调用对应的 dunder 方法。

### 算术运算符重载

| 运算符 | Dunder 方法 | 示例 |
|--------|------------|------|
| `+` | `__add__` | `a + b` → `a.__add__(b)` |
| `-` | `__sub__` | `a - b` → `a.__sub__(b)` |
| `*` | `__mul__` | `a * b` → `a.__mul__(b)` |
| `/` | `__truediv__` | `a / b` → `a.__truediv__(b)` |
| `//` | `__floordiv__` | `a // b` → `a.__floordiv__(b)` |
| `%` | `__mod__` | `a % b` → `a.__mod__(b)` |
| `**` | `__pow__` | `a ** b` → `a.__pow__(b)` |

示例：

```python
@t.Object
class Vec2:
    x: t.CFloat
    y: t.CFloat

    def __init__(self, x: t.CFloat, y: t.CFloat):
        self.x = x
        self.y = y

    def __add__(self, other: Vec2) -> Vec2:
        result: Vec2 = Vec2(0.0, 0.0)
        result.x = self.x + other.x
        result.y = self.y + other.y
        return result

    def __mul__(self, scalar: t.CFloat) -> Vec2:
        result: Vec2 = Vec2(0.0, 0.0)
        result.x = self.x * scalar
        result.y = self.y * scalar
        return result
```

### 增量赋值运算符重载

| 增量运算符 | 优先 Dunder | 回退 Dunder |
|-----------|------------|------------|
| `+=` | `__iadd__` | `__add__` |
| `-=` | `__isub__` | `__sub__` |
| `*=` | `__imul__` | `__mul__` |
| `/=` | `__itruediv__` | `__truediv__` |
| `//=` | `__ifloordiv__` | `__floordiv__` |
| `%=` | `__imod__` | `__mod__` |
| `**=` | `__ipow__` | `__pow__` |

如果未定义增量版本（如 `__iadd__`），编译器自动回退到普通版本（如 `__add__`）。

### 比较运算符重载

> **实验性**：以下比较运算符 dunder 方法在编译器中被识别，但尚未实现自动调度。定义它们不会报错，但比较运算不会自动调用。

| 运算符 | Dunder 方法 | 状态 |
|--------|------------|------|
| `==` | `__eq__` | 仅类型推断识别 |
| `!=` | `__ne__` | 仅类型推断识别 |
| `<` | `__lt__` | 仅类型推断识别 |
| `<=` | `__le__` | 仅类型推断识别 |
| `>` | `__gt__` | 仅类型推断识别 |
| `>=` | `__ge__` | 仅类型推断识别 |

### 反向运算符重载

> **实验性**：以下反向运算符 dunder 方法在编译器中被识别，但尚未实现自动调度。

| Dunder 方法 | 预期语义 | 状态 |
|------------|---------|------|
| `__radd__` | 右操作数加法 | 仅类型推断识别 |
| `__rsub__` | 右操作数减法 | 仅类型推断识别 |
| `__rmul__` | 右操作数乘法 | 仅类型推断识别 |
| `__rtruediv__` | 右操作数真除法 | 仅类型推断识别 |
| `__rfloordiv__` | 右操作数整除 | 仅类型推断识别 |
| `__rmod__` | 右操作数取模 | 仅类型推断识别 |
| `__rpow__` | 右操作数幂运算 | 仅类型推断识别 |

### 一元运算符重载

> **实验性**：以下一元运算符 dunder 方法在编译器中被识别，但尚未实现自动调度。

| 运算符 | Dunder 方法 | 状态 |
|--------|------------|------|
| `-a` | `__neg__` | 仅类型推断识别 |
| `+a` | `__pos__` | 仅类型推断识别 |

## 可调用对象 `__call__`

```python
@t.Object
class Counter:
    value: t.CInt

    def __init__(self):
        self.value = 0

    def __call__(self) -> t.CInt:
        self.value += 1
        return self.value

c: Counter = Counter()
x: t.CInt = c()   # x = 1
y: t.CInt = c()   # y = 2
```

## 下标访问重载

### `__getitem__` — 读取

```python
def __getitem__(self, key: t.CInt) -> t.CInt:
    return self.data[key]
```

### `__setitem__` — 赋值

```python
def __setitem__(self, key: t.CInt, value: t.CInt):
    self.data[key] = value
```

### `__delitem__` — 删除

```python
def __delitem__(self, key: t.CInt):
    pass
```

## 布尔转换 `__bool__`

```python
@t.Object
class Buffer:
    size: t.CInt
    data: list[t.CChar, 1024]

    def __bool__(self) -> t.CBool:
        return self.size > 0

buf: Buffer = Buffer()
if buf:
    serial.puts("buffer is not empty\n")
```

## 长度 `__len__`

```python
@t.Object
class Buffer:
    size: t.CInt

    def __len__(self) -> t.CInt:
        return self.size

buf: Buffer = Buffer()
n: t.CInt = len(buf)
```

## 字符串转换 `__str__`

```python
@t.Object
class Point:
    x: t.CInt
    y: t.CInt

    def __str__(self) -> t.CConst | t.CChar | t.CPtr:
        return "Point"

p: Point = Point(1, 2)
print(p)          # 调用 p.__str__()
```

## 绝对值 `__abs__`

```python
@t.Object
class SignedValue:
    val: t.CInt

    def __abs__(self) -> t.CInt:
        if self.val < 0:
            return -self.val
        return self.val

sv: SignedValue = SignedValue()
sv.val = -42
a: t.CInt = abs(sv)   # a = 42
```

## 迭代器协议

Viper 的迭代器协议与 Python 相同，但 `__next__` 的实现方式通过 `StopIteration` 异常来结束。

### `__iter__` 和 `__next__`

```python
@t.Object
class IntRange:
    start: t.CInt
    end: t.CInt
    current: t.CInt

    def __init__(self, start: t.CInt, end: t.CInt):
        self.start = start
        self.end = end
        self.current = start

    def __iter__(self):
        return self

    def __next__(self, stop_flag) -> t.CInt:
        if self.current >= self.end:
            raise StopIteration
        val: t.CInt = self.current
        self.current += 1
        return val
```

### for 循环使用

```python
r: IntRange = IntRange(0, 10)
for i in r:
    print(i)
```

编译器生成的等价逻辑：

```c
IntRange r = IntRange_init(0, 10);
IntRange iter = IntRange___iter__(&r);
while (1) {
    i1 stop_flag = 0;
    int i = IntRange___next__(&iter, &stop_flag);
    if (stop_flag == 1) break;
    print_int(i);
}
```

## 上下文管理器

`with` 语句要求对象实现 `__enter__` 和 `__exit__` 方法：

```python
@t.Object
class File:
    fd: t.CInt
    path: t.CConst | t.CChar | t.CPtr

    def __init__(self, path: t.CConst | t.CChar | t.CPtr, flags: t.CInt):
        self.path = path
        self.fd = -1

    def __enter__(self):
        self.fd = fat32.open(self.path, self.flags)
        return self

    def __exit__(self):
        fat32.close(self.fd)

    def read(self) -> t.CInt:
        return fat32.read(self.fd)
```

使用方式：

```python
with File("/test.txt", FA_READ) as f:
    data: t.CInt = f.read()
```

编译器会自动保证 `__exit__` 在 `with` 块结束时被调用。

## 析构 `__del__` / `__delete__`

```python
del obj        # 调用 obj.__del__() 或 obj.__delete__()
del arr[idx]   # 调用 arr.__delitem__(idx)
```

## Dunder 方法完整参考

### 已实现自动调度的 Dunder 方法

| Dunder 方法 | 触发语法 | 说明 |
|------------|---------|------|
| `__init__` | `ClassName(args)` | 构造函数 |
| `__before_init__` | 自动生成 | vtable 初始化，在 `__init__` 之前执行 |
| `__add__` | `a + b` | 加法 |
| `__sub__` | `a - b` | 减法 |
| `__mul__` | `a * b` | 乘法 |
| `__truediv__` | `a / b` | 真除法 |
| `__floordiv__` | `a // b` | 整除 |
| `__mod__` | `a % b` | 取模 |
| `__pow__` | `a ** b` | 幂运算 |
| `__iadd__` | `a += b` | 增量加法（回退到 `__add__`） |
| `__isub__` | `a -= b` | 增量减法（回退到 `__sub__`） |
| `__imul__` | `a *= b` | 增量乘法（回退到 `__mul__`） |
| `__itruediv__` | `a /= b` | 增量真除法（回退到 `__truediv__`） |
| `__ifloordiv__` | `a //= b` | 增量整除（回退到 `__floordiv__`） |
| `__imod__` | `a %= b` | 增量取模（回退到 `__mod__`） |
| `__ipow__` | `a **= b` | 增量幂运算（回退到 `__pow__`） |
| `__call__` | `obj(args)` | 可调用对象 |
| `__getitem__` | `obj[key]` | 下标读取 |
| `__setitem__` | `obj[key] = value` | 下标赋值 |
| `__delitem__` | `del obj[key]` | 下标删除 |
| `__bool__` | `if obj:` | 布尔转换 |
| `__len__` | `len(obj)` | 长度 |
| `__str__` | `str(obj)` / `print(obj)` | 字符串转换 |
| `__abs__` | `abs(obj)` | 绝对值 |
| `__iter__` | `for x in obj:` | 获取迭代器 |
| `__next__` | `for x in obj:` | 获取下一个值（标志位方式） |
| `__enter__` | `with obj as x:` | 上下文管理器进入 |
| `__exit__` | `with obj as x:` | 上下文管理器退出 |
| `__del__` | `del obj` | 析构 |
| `__delete__` | `del obj` | 删除描述符 |

### 声明支持但未实现自动调度的 Dunder 方法

| Dunder 方法 | 预期触发语法 | 当前状态 |
|------------|------------|---------|
| `__eq__` | `a == b` | 仅类型推断识别，比较运算不自动调度 |
| `__ne__` | `a != b` | 同上 |
| `__lt__` | `a < b` | 同上 |
| `__le__` | `a <= b` | 同上 |
| `__gt__` | `a > b` | 同上 |
| `__ge__` | `a >= b` | 同上 |
| `__neg__` | `-a` | 仅类型推断识别，一元负号不自动调度 |
| `__pos__` | `+a` | 同上 |
| `__radd__` | 右操作数加法 | 仅类型推断识别 |
| `__rsub__` | 右操作数减法 | 同上 |
| `__rmul__` | 右操作数乘法 | 同上 |
| `__rtruediv__` | 右操作数真除法 | 同上 |
| `__rfloordiv__` | 右操作数整除 | 同上 |
| `__rmod__` | 右操作数取模 | 同上 |
| `__rpow__` | 右操作数幂运算 | 同上 |


# 07 - 控制流

Viper 支持 Python 风格的控制流语句，编译为 LLVM IR 的基本块和分支指令。

## 条件语句

### if / elif / else

```python
if x > 0:
    y = 1
elif x == 0:
    y = 0
else:
    y = -1
```

等价 C 代码：
```c
if (x > 0) {
    y = 1;
} else if (x == 0) {
    y = 0;
} else {
    y = -1;
}
```

### 条件表达式

```python
is_dir: t.CInt = 1 if (info.attr & AM_DIR) else 0
```

等价 C 代码：
```c
int is_dir = (info.attr & AM_DIR) ? 1 : 0;
```

### None 检查

```python
if BootInfo != None:
    paging.init(BootInfo.MemmapAddr, BootInfo.MemmapSize)
else:
    paging.init(0, 0)
```

等价 C 代码：
```c
if (BootInfo != NULL) {
    paging_init(BootInfo->MemmapAddr, BootInfo->MemmapSize);
} else {
    paging_init(0, 0);
}
```

## 循环语句

### while 循环

```python
i: t.CInt = 0
while i < 10:
    buf[i] = 0
    i += 1
```

等价 C 代码：
```c
int i = 0;
while (i < 10) {
    buf[i] = 0;
    i += 1;
}
```

### while-else

```python
while i < count:
    if found:
        break
else:
    serial.puts("not found\n")
```

`else` 块在循环正常结束（非 `break` 退出）时执行。

### 无限循环

```python
while True:
    sched.Scheduler._yield()
```

等价 C 代码：
```c
while (1) {
    scheduler_yield();
}
```

### for 循环（range）（关于 for 循环的更多用法，参见 [06-oop.md 中 迭代器协议](06-oop.md#迭代器协议)）

```python
for i in range(10):
    buf[i] = 0

for i in range(5, 10):
    buf[i] = 0

for i in range(0, 100, 2):
    buf[i] = 0
```

等价 C 代码：
```c
for (int i = 0; i < 10; i++) {
    buf[i] = 0;
}

for (int i = 5; i < 10; i++) {
    buf[i] = 0;
}

for (int i = 0; i < 100; i += 2) {
    buf[i] = 0;
}
```

### for 循环（迭代器）

如果类实现了 `__iter__` 和 `__next__` 方法，可以使用 `for ... in` 迭代：

```python
container: Iter = Iter()
for item in container:
    process(item)
```

### for-else

```python
for i in range(count):
    if items[i] == target:
        break
else:
    serial.puts("not found\n")
```

### break 和 continue

```python
while True:
    if done:
        break
    if skip:
        continue
    process()
```

## match 语句

Viper 支持 Python 3.10+ 的 `match` 语句，编译为 C 的 `switch` 语句：

```python
match self.ctype:
    case UI_LABEL:
        self.RenderLabel(sh)
    case UI_BUTTON:
        self.RenderButton(sh)
    case UI_PANEL:
        self.RenderPanel(sh)
    case _:
        pass
```

等价 C 代码：
```c
switch (self->ctype) {
    case UI_LABEL:
        self_RenderLabel(self, sh);
        break;
    case UI_BUTTON:
        self_RenderButton(self, sh);
        break;
    case UI_PANEL:
        self_RenderPanel(self, sh);
        break;
    default:
        break;
}
```

### match 值匹配

```python
match code:
    case 0:
        serial.puts("OK\n")
    case 1:
        serial.puts("Error\n")
    case _:
        serial.puts("Unknown\n")
```

### match 或模式

```python
match value:
    case 1 | 2 | 3:
        serial.puts("small\n")
    case _:
        serial.puts("other\n")
```

### fallthrough（无 break）

默认每个 `case` 自动添加 `break`。如需 fallthrough，使用 `c.NoBreak`：

```python
match value:
    case 1:
        do_one()
        c.NoBreak
    case 2:
        do_two()
```

如果需要提前 break，需要使用 `c.Break()`，因为在 `Python` 中，`match` 分支不支持直接使用 `break`。

## assert 语句
> 避免使用此语句，此语句未经充分测试，在多数情况下，编译器不知道如何展示结果。

```python
assert ptr != None, "null pointer"
```

编译为条件检查和错误报告。

## with 语句

`with` 语句用于资源管理，要求对象实现 `__enter__` 和 `__exit__` 方法：

```python
with File("/test.txt", FA_READ) as f:
    data: t.CInt = f.read()
```

等价 C 代码：
```c
File* f = File_enter(File_new("/test.txt", FA_READ));
int data = File_read(f);
File_exit(f);
```


# 08 - C 语言操作

Viper 通过 `c` 模块提供对 C 语言底层特性的访问，包括指针操作、内联汇编、预处理指令等。

## 指针操作

### 取地址 `c.Addr`

```python
x: t.CInt = 42
p: t.CInt | t.CPtr = c.Addr(x)         # int* p = &x;
```

对结构体成员取地址：

```python
res: t.CInt = fat32.opendir("/", c.Addr(dp))   # res = fat32_opendir("/", &dp);
```

对数组取地址：

```python
viperlib.snprintf(c.Addr(buf), 64, "hello %d", 42)   # snprintf(&buf, 64, "hello %d", 42);
```

### 解引用 `c.Deref`

```python
ptr: Sheet | t.CPtr = c.Addr(sheet_obj)
obj: Sheet = c.Deref(ptr)               # struct Sheet obj = *ptr;
```

### 内存拷贝 `c.Load`

```python
c.Load(ptr, value)                        # *ptr = *value;
```

### 解引用赋值 `c.DerefAs`

```python
c.DerefAs(ptr, value)                    # *ptr = value;
```


### 赋值 `c.Set`

```python
c.Set(target, value)                    # target = value;
```

## 内联汇编 `c.Asm`

Viper 提供了声明式的内联汇编语法，编译为 GCC 风格的 `__asm__ __volatile__` 语句。

### 基本用法

```python
c.Asm("nop")                            # __asm__ __volatile__("nop");
```

### 带操作数的汇编

使用 f-string 和 `c.AsmInp` / `c.AsmOut` 标记操作数：

```python
saved_rdi: t.CUnsignedLong
c.Asm(f"mov {c.AsmOut(saved_rdi, t.ASM_DESCR.OUTPUT_REG)}, rdi",
    op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RDI])
```

等价 C 代码：
```c
__asm__ __volatile__(
    "mov %0, rdi"
    : "=r"(saved_rdi)
    : 
    : "memory", "rdi"
);
```

### 输入操作数 `c.AsmInp`

```python
msg: t.CConst | t.CChar | t.CPtr = "Hello"
c.Asm(f"mov rdi, {c.AsmInp(msg, t.ASM_DESCR.REG_ANY)}",
    op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX])
```

### 完整示例

```python
c.Asm(f"""mov rdi, {c.AsmInp(msg, t.ASM_DESCR.REG_ANY)}
        call {c.AsmInp(log_info_fn, t.ASM_DESCR.REG_ANY)}""",
    op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX,
        t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDX,
        t.ASM_DESCR.CLOBBER_RDI, t.ASM_DESCR.CLOBBER_RSI,
        t.ASM_DESCR.CLOBBER_R8, t.ASM_DESCR.CLOBBER_R9,
        t.ASM_DESCR.CLOBBER_R10, t.ASM_DESCR.CLOBBER_R11])
```

### ASM_DESCR 约束字符

#### 操作数修饰符

| 常量 | 值 | 说明 |
|------|----|------|
| `MODIFIER_OUTPUT` | `=` | 输出操作数 |
| `MODIFIER_READWRITE` | `+` | 读写操作数 |
| `MODIFIER_INPUT` | `` | 输入操作数（默认） |
| `MODIFIER_GLOBAL` | `&` | 全局操作数 |

#### 寄存器约束

| 常量 | 值 | 说明 |
|------|----|------|
| `REG_ANY` | `r` | 任何通用寄存器 |
| `REG_EAX` / `REG_RAX` | `a` | EAX/RAX |
| `REG_EBX` / `REG_RBX` | `b` | EBX/RBX |
| `REG_ECX` / `REG_RCX` | `c` | ECX/RCX |
| `REG_EDX` / `REG_RDX` | `d` | EDX/RDX |
| `REG_ESI` / `REG_RSI` | `S` | ESI/RSI |
| `REG_EDI` / `REG_RDI` | `D` | EDI/RDI |
| `REG_XMM` | `x` | XMM 寄存器 |

#### 内存与立即数

| 常量 | 值 | 说明 |
|------|----|------|
| `MEMORY` | `m` | 内存操作数 |
| `IMMEDIATE` | `i` | 立即数 |
| `ANY` | `g` | 通用寄存器/内存/立即数 |

#### 预定义组合约束

| 常量 | 值 | 说明 |
|------|----|------|
| `OUTPUT_REG` | `=r` | 输出，通用寄存器 |
| `OUTPUT_MEM` | `=m` | 输出，内存 |
| `OUTPUT_EAX` | `=a` | 输出，EAX/RAX |
| `INPUT_REG` | `r` | 输入，通用寄存器 |
| `INPUT_MEM` | `m` | 输入，内存 |
| `INPUT_IMM` | `i` | 输入，立即数 |

#### 破坏描述符

| 常量 | 说明 |
|------|------|
| `CLOBBER_EAX` / `CLOBBER_RAX` | 破坏 EAX/RAX |
| `CLOBBER_EBX` / `CLOBBER_RBX` | 破坏 EBX/RBX |
| `CLOBBER_ECX` / `CLOBBER_RCX` | 破坏 ECX/RCX |
| `CLOBBER_EDX` / `CLOBBER_RDX` | 破坏 EDX/RDX |
| `CLOBBER_ESI` / `CLOBBER_RSI` | 破坏 ESI/RSI |
| `CLOBBER_EDI` / `CLOBBER_RDI` | 破坏 EDI/RDI |
| `CLOBBER_CC` | 破坏条件码（标志寄存器） |
| `CLOBBER_MEMORY` | 破坏内存 |
| `CLOBBER_R8` ~ `CLOBBER_R15` | 破坏 R8~R15 |

## 预处理指令

Viper 通过 `c` 模块的函数调用实现 C 预处理指令。

### #define

```python
c.CDefine("MAX_SIZE", 1024)             # #define MAX_SIZE 1024
```

上述方法容易引起未定义行为，至少是不便于理解，更常用的方式是使用类型注解：

```python
MAX_SIZE: t.CDefine = 1024              # #define MAX_SIZE 1024
```

### 条件编译

```python
c.CIfndef(HEADER_H)                  # #ifndef HEADER_H
c.CDefine(HEADER_H)                  # #define HEADER_H
c.CEndif()                           # #endif
```

```python
c.CIfdef(DEBUG)                         # #ifdef DEBUG
c.CEndif()                              # #endif
```

```python
c.CIf(VERSION > 2)                      # #if VERSION > 2
c.CElif(VERSION > 1)                    # #elif VERSION > 1
c.CElse()                               # #else
c.CEndif()                              # #endif
```

### #undef

```python
c.Undef(MACRO_NAME)                   # #undef MACRO_NAME
```

### #error

```python
c.CError("Platform not supported")      # #error "Platform not supported"
```

### #pragma
> 此关键字已不再支持
```python
c.CPragma("GCC diagnostic push")        # #pragma GCC diagnostic push
```

### ## 连接符
> 此方法可能已经不再支持
```python
c.TokenPast("PREFIX_", "NAME")          # PREFIX_ ## NAME
```

由于编译器设计，以及不需要像 `C` 一样做大量字符替换，对于上述所有的条件宏都远比 `C` 差，实际工程中不推荐使用条件宏，后期将完善宏的设计，引入模板等。

## 仅声明 `c.State`

`c.State` 用于声明但不定义函数或变量：

```python
def isr0() -> t.CExtern | t.CVoid | c.State: pass   # extern void isr0();
```

## LLVM IR 内联

### c.LLVMIR

直接嵌入 LLVM IR 指令来实现高效且跨平台的汇编操作：

```python
c.LLVMIR(f"add i32 {c.LInp(a)}, {c.LInp(b)}", t.CInt)
```

### c.LInp / c.LOut

标记 LLVM IR 的输入/输出操作数：

```python
c.LInp(expr)    # 输入操作数
c.LOut(expr)    # 输出操作数
```

## 运算符重载

`@t.Object` 类支持运算符重载，详见 [06-oop.md 中 运算符重载](06-oop.md#运算符重载)。


# 09 - 异常处理

Viper 支持 Python 风格的 `try/except/finally` 异常处理，编译为基于 jmp_buf 和错误码的 C 级别异常处理机制。

## 异常处理机制

Viper 的异常处理不使用 C++ 风格的零开销异常，而是通过函数参数传递错误码和错误消息实现。编译器自动为可能抛出异常的函数添加 `__eh_msg_out__` 和 `__eh_code_out__` 参数。

## try / except

```python
try:
    result = risky_operation()
except ValueError:
    serial.puts("ValueError occurred\n")
except OSError:
    serial.puts("OSError occurred\n")
except Exception:
    serial.puts("Unknown error\n")
```

### 内置异常类型

Viper 预定义了以下异常类型及其错误码：

| 异常类型 | 错误码 |
|---------|--------|
| `ValueError` | 1 |
| `TypeError` | 2 |
| `RuntimeError` | 3 |
| `ZeroDivisionError` | 4 |
| `IndexError` | 5 |
| `KeyError` | 6 |
| `IOError` | 7 |
| `OSError` | 8 |
| `AssertionError` | 9 |
| `Exception` | 99 |

### 自定义异常

```python
class DiskFullError(Exception):
    pass

class ReadOnlyError(DiskFullError):
    pass
```

自定义异常会自动分配递增的错误码（从 100 开始），并支持继承匹配。

### 多异常捕获

```python
try:
    result = operation()
except (ValueError, TypeError):
    serial.puts("Value or Type error\n")
```

### 获取异常信息

```python
try:
    result = operation()
except Exception as e:
    serial.puts("Error occurred\n")
```

## try / finally

```python
try:
    result = operation()
finally:
    cleanup()
```

`finally` 块无论是否发生异常都会执行。

## try / except / finally

```python
try:
    result = operation()
except ValueError:
    handle_value_error()
finally:
    cleanup()
```

## raise 语句

### 抛出异常

```python
raise ValueError("invalid value")
```

### 抛出自定义异常

```python
raise MyCustomError("something went wrong")
```

### 重新抛出异常

```python
raise
```

### StopIteration

`StopIteration` 有特殊处理，用于迭代器协议：

```python
raise StopIteration
```

## 异常处理的编译实现

### 函数签名变换

可能抛出异常的函数会自动添加错误输出参数：

```python
def risky_operation() -> t.CInt:
    if error:
        raise ValueError("bad value")
    return 0
```

编译后等价于：

```c
int risky_operation(char** __eh_msg_out__, int* __eh_code_out__) {
    if (error) {
        *__eh_code_out__ = 1;  // ValueError code
        *__eh_msg_out__ = "bad value";
        return 0;
    }
    return 0;
}
```

### 调用点变换

```python
try:
    result = risky_operation()
except ValueError:
    handle_error()
```

编译后等价于：

```c
char* __eh_msg = NULL;
int __eh_code = 0;
int result = risky_operation(&__eh_msg, &__eh_code);
if (__eh_msg != NULL) {
    if (__eh_code == 1) {  // ValueError
        handle_error();
    }
}
```

## 异常继承匹配

异常匹配支持继承体系。捕获父类异常时，子类异常也会被匹配：

```python
class FileSystemError(Exception):
    pass

class FileNotFoundError(FileSystemError):
    pass

class PermissionError(FileSystemError):
    pass

try:
    operation()
except FileSystemError:
    # 也会捕获 FileNotFoundError 和 PermissionError
    handle_fs_error()
```


# 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
```

## 模块解析流程

### 编译时模块加载

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` 函数 | 保留完整函数体 |
| 普通函数 | 仅签名 + `c.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` 指定的目录中搜索导入的模块。


# 11 - 内置函数与运算符

Viper 支持 Python 内置函数和运算符，编译为对应的 C/LLVM 操作。

## 内置函数

### print

```python
print("Hello, World!")           # 调用 puts 或 printf
print(x, y)                      # 多参数输出
```

### len

```python
n: t.CInt = len(array)           # 获取数组长度（编译时常量）
```

### sizeof

```python
s: t.CSizeT = sizeof(t.CInt)     # sizeof(int)
s: t.CSizeT = obj.__sizeof__()        # sizeof(obj)
```

### abs

```python
a: t.CInt = abs(x)               # abs(x)
```

### int / float / bool

```python
i: t.CInt = int(3.14)            # (int)3.14
f: t.CFloat = float(42)          # (float)42
b: t.CBool = bool(x)             # x != 0
```

### min / max

```python
m: t.CInt = min(a, b)            # a < b ? a : b
m: t.CInt = max(a, b)            # a > b ? a : b
```

### chr / ord

```python
c: t.CChar = chr(65)             # 'A' (整数转字符)
n: t.CInt = ord('A')             # 65 (字符转整数)
```

### range

用于 `for` 循环：

```python
for i in range(10): pass         # for (int i = 0; i < 10; i++)
for i in range(5, 10): pass      # for (int i = 5; i < 10; i++)
for i in range(0, 10, 2): pass   # for (int i = 0; i < 10; i += 2)
```

## 运算符

### 算术运算符

| Viper | C 等价 | 说明 |
|-------|--------|------|
| `a + b` | `a + b` | 加法 |
| `a - b` | `a - b` | 减法 |
| `a * b` | `a * b` | 乘法 |
| `a / b` | `a / b` | 浮点除法 |
| `a // b` | `a / b` | 整数除法 |
| `a % b` | `a % b` | 取模 |
| `a ** b` | `pow(a, b)` | 幂运算 |
| `-a` | `-a` | 取负 |
| `+a` | `+a` | 正号 |

### 位运算符

| Viper | C 等价 | 说明 |
|-------|--------|------|
| `a & b` | `a & b` | 按位与 |
| `a \| b` | `a \| b` | 按位或 |
| `a ^ b` | `a ^ b` | 按位异或 |
| `~a` | `~a` | 按位取反 |
| `a << n` | `a << n` | 左移 |
| `a >> n` | `a >> n` | 右移 |

> **注意**：`|` 运算符在类型注解中表示类型组合，在表达式中表示按位或。编译器根据上下文区分。

### 比较运算符

| Viper | C 等价 | 说明 |
|-------|--------|------|
| `a == b` | `a == b` | 等于 |
| `a != b` | `a != b` | 不等于 |
| `a < b` | `a < b` | 小于 |
| `a > b` | `a > b` | 大于 |
| `a <= b` | `a <= b` | 小于等于 |
| `a >= b` | `a >= b` | 大于等于 |

### 逻辑运算符

| Viper | C 等价 | 说明 |
|-------|--------|------|
| `a and b` | `a && b` | 逻辑与 |
| `a or b` | `a \|\| b` | 逻辑或 |
| `not a` | `!a` | 逻辑非 |

### 增强赋值运算符

| Viper | C 等价 |
|-------|--------|
| `a += b` | `a += b` |
| `a -= b` | `a -= b` |
| `a *= b` | `a *= b` |
| `a //= b` | `a /= b` |
| `a %= b` | `a %= b` |
| `a <<= b` | `a <<= b` |
| `a >>= b` | `a >>= b` |
| `a &= b` | `a &= b` |
| `a \|= b` | `a \|= b` |
| `a ^= b` | `a ^= b` |

## 类型自动转换

Viper 在算术运算中自动进行类型提升：

1. **整数宽度提升**：较窄的整数类型自动扩展为较宽的类型
   - 有符号类型使用符号扩展（`sext`）
   - 无符号类型使用零扩展（`zext`）

2. **整数到浮点**：整数与浮点数运算时，整数自动转换为浮点

3. **浮点精度提升**：`float` 与 `double` 运算时，`float` 提升为 `double`

## 指针算术

指针与整数的加法支持自动计算偏移：

```python
buf: t.CUInt32T | t.CPtr
buf[i] = value                    # buf[i] = value; (自动计算偏移)
```

## 数组下标

```python
buf: list[t.CChar, 64]
buf[0] = 'H'                      # buf[0] = 'H';
buf[i] = value                    # buf[i] = value;

info.fname[0]                     # info.fname[0] (结构体数组成员访问)
```

## 成员访问

```python
obj.x                             # obj.x (直接成员)
obj.method()                      # obj.method() (方法调用)
ptr.x                             # ptr->x (指针自动解引用)
```

## 字符串字面量

字符串字面量编译为 C 字符串常量（`const char*`），其为只读：

```python
serial.puts("Hello")              # 传递 const char*
```

### 字符串索引

```python
msg: t.CConst | str = "Hello"
serial.puts(c.Addr(msg[4]))       # 访问 msg[4] 的地址，输出 'o'
```

## C 标准库函数

Viper 内置支持以下 C 标准库函数的直接调用：

| 函数 | 签名 |
|------|------|
| `strlen(s)` | `size_t strlen(const char* s)` |
| `memset(s, c, n)` | `void* memset(void* s, int c, size_t n)` |
| `memcpy(d, s, n)` | `void* memcpy(void* d, const void* s, size_t n)` |
| `memmove(d, s, n)` | `void* memmove(void* d, const void* s, size_t n)` |
| `memcmp(a, b, n)` | `int memcmp(const void* a, const void* b, size_t n)` |
| `strcmp(a, b)` | `int strcmp(const char* a, const char* b)` |
| `strncmp(a, b, n)` | `int strncmp(const char* a, const char* b, size_t n)` |
| `strcpy(d, s)` | `char* strcpy(char* d, const char* s)` |
| `strncpy(d, s, n)` | `char* strncpy(char* d, const char* s, size_t n)` |
| `strcat(d, s)` | `char* strcat(char* d, const char* s)` |
| `puts(s)` | `int puts(const char* s)` |
| `atoi(s)` | `int atoi(const char* s)` |
| `atol(s)` | `long atol(const char* s)` |
| `abs(x)` | `int abs(int x)` |
| `labs(x)` | `long labs(long x)` |

部分模式比如裸机没有 libc，则不能使用这些函数，即使环境满足，Viper 标准库也可能和 C 标准库冲突。


# 12 - 项目配置与构建

Viper 项目使用 `project.json` 配置文件管理编译和链接参数。

## project.json 结构

```json
{
    "name": "Kernel",
    "version": "1.0.0",
    "source_dir": "./Kernel",
    "temp_dir": "./temp",
    "output_dir": "./output",
    "compiler": {
        "cmd": "llc",
        "flags": ["-filetype=obj", "-mtriple=x86_64-none-elf", "-relocation-model=static", "-O2"]
    },
    "linker": {
        "cmd": "ld.lld.exe",
        "flags": [
            "-m", "elf_x86_64",
            "-T", "linker.ld",
            "--oformat", "elf64-x86-64",
            "--strip-all"
        ],
        "output": "kernel.bin"
    },
    "includes": ["../../includes"],
    "target": {
        "triple": "x86_64-none-elf",
        "datalayout": "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
    },
    "options": {
        "slice_level": 3,
        "target": "llvm",
        "strict_mode": true
    }
}
```

## 配置项说明

### 基本信息字段

| 字段 | 类型 | 说明 |
|------|------|------|
| `name` | string | 项目名称 |
| `version` | string | 项目版本 |
| `source_dir` | string | 源代码目录（相对于 project.json 所在目录） |
| `temp_dir` | string | 临时文件目录（存放 .pyi 存根等） |
| `output_dir` | string | 输出文件目录 |

### 编译器配置

| 字段 | 类型 | 说明 |
|------|------|------|
| `compiler.cmd` | string | 编译器命令（通常为 `llc`） |
| `compiler.flags` | string[] | 编译器标志 |

常用 `llc` 标志：
- `-filetype=obj`：输出目标文件
- `-mtriple=x86_64-none-elf`：目标三元组
- `-relocation-model=static`：静态重定位
- `-O2`：优化级别

### 链接器配置

| 字段 | 类型 | 说明 |
|------|------|------|
| `linker.cmd` | string | 链接器命令（通常为 `ld.lld.exe`） |
| `linker.flags` | string[] | 链接器标志 |
| `linker.output` | string | 输出文件名 |

常用 `ld.lld` 标志：
- `-m elf_x86_64`：ELF x86_64 格式
- `-T linker.ld`：链接脚本
- `--oformat elf64-x86-64`：输出 ELF 格式
- `--oformat binary`：输出原始二进制（用于内核）
- `--strip-all`：去除所有符号信息

### 目标平台配置

| 字段 | 类型 | 说明 |
|------|------|------|
| `target.triple` | string | LLVM 目标三元组 |
| `target.datalayout` | string | LLVM 数据布局字符串 |

默认值：
- triple: `x86_64-none-elf`
- datalayout: `e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128`

### 包含路径

| 字段 | 类型 | 说明 |
|------|------|------|
| `includes` | string[] | 模块搜索路径列表 |

### 编译选项

| 字段 | 类型 | 说明 |
|------|------|------|
| `options.slice_level` | int | 切片优化级别（0-3） |
| `options.target` | string | 编译目标（目前仅支持 `llvm`） |
| `options.strict_mode` | bool | 严格模式 |

## 切片优化级别

| 级别 | 名称 | 说明 |
|------|------|------|
| `0` | `no_optimize` | 无优化 |
| `1` | `conservative` | 保守优化 |
| `2` | `moderate` | 适度优化 |
| `3` | `aggressive` | 激进优化（默认） |
| `s` | `size` | 体积优化 |

## 项目结构示例

### 内核项目

```
VKernel/
├── project.json          # 项目配置
├── linker.ld             # 链接脚本
├── Kernel/               # 源代码目录
│   ├── main.py           # 内核入口
│   ├── bootinfo.py
│   ├── intr/
│   │   ├── gdt.py
│   │   ├── idt.py
│   │   └── syscall.py
│   ├── drivers/
│   │   ├── serial/
│   │   ├── video/
│   │   ├── storage/
│   │   └── ...
│   └── ...
├── temp/                 # 临时文件（自动生成）
│   ├── <SHA1>.pyi        # 签名存根（阶段一生成）
│   ├── <SHA1>.stub.ll    # LLVM IR 声明（阶段一生成）
│   └── _sha1_map.txt     # SHA1→源文件路径映射
└── output/               # 输出文件（自动生成）
    ├── kernel.bin         # 内核二进制
    ├── *.deps.json        # 依赖信息
    └── linker.ld          # 生成的链接脚本
```

### 应用项目

```
HelloWorld/
├── project.json          # 项目配置
├── linker.ld             # 链接脚本
├── main.py               # 应用入口
├── temp/                 # 临时文件
└── output/               # 输出文件
    └── helloworld.elf    # ELF 可执行文件
```

### 库项目

```
SerialLogger/
├── project.json          # 项目配置
├── linker.ld             # 链接脚本
├── serial_logger.py      # 库源码
├── temp/                 # 临时文件
└── output/               # 输出文件
```

## 链接脚本

ViperOS 使用自定义链接脚本控制内存布局：

```ld
ENTRY(_start)

SECTIONS
{
    . = 0x100000;  /* 加载地址 */

    .text : {
        *(.text.startup)
        *(.text*)
    }

    .rodata : {
        *(.rodata*)
    }

    .data : {
        *(.data*)
    }

    .bss : {
        *(.bss*)
        *(COMMON)
    }
}
```

## 编译命令

TransPyC 编译器的基本用法（注：适用于单个文件，而不适用于工程）：

```bash
python TransPyC.py -f InputFile -o OutputFile [options]
```

### 命令行参数

| 参数 | 说明 |
|------|------|
| `-f` | 输入文件路径 |
| `-o` | 输出文件路径 |
| `-wh` | 头文件列表 |
| `-debug` | 调试输出文件 |
| `-cc` | 编译命令 |
| `-cflags` | 编译标志 |
| `-run` | 编译后运行 |
| `-args` | 运行参数 |
| `-h` | 辅助文件（C 或 Python） |

工程编译使用：
```bash
python Projectrans.py xxx.json
```
即可

## 增量编译

TransPyC 支持基于 SHA1 的增量编译，与两阶段编译模型紧密耦合：

### 阶段一增量

- 每个源文件按内容计算 SHA1 哈希（16位）
- 如果 `<SHA1>.pyi` 和 `<SHA1>.stub.ll` 已存在，则跳过生成（缓存命中）
- 只有源文件内容变化导致 SHA1 变化时才重新生成声明接口
- `temp/_sha1_map.txt` 记录 SHA1 → 源文件路径的映射，格式为 `<sha1>:<relative_path>`

### 阶段二增量

- 阶段二加载 `temp/_sha1_map.txt` 重建 SHA1 映射
- 过滤掉不在当前 SHA1 映射中的旧 `.pyi` 和 `.stub.ll` 文件
- 共享符号表一次性构建，避免每个文件重复加载

### SHA1 命名空间与增量编译的协同

SHA1 同时服务于命名空间隔离和增量编译：
- **命名空间**：非 `t.CExport` 函数和结构体使用 SHA1 前缀，消除符号冲突
- **增量编译**：SHA1 不变则缓存命中，SHA1 变化则重新生成

详见 [01-overview.md 中 SHA1 命名空间机制](01-overview.md#sha1-命名空间机制)。


