Files
Viper_Wiki/17-flagship-project.md
2026-10-13 15:36:42 +08:00

15 KiB
Raw Permalink Blame History

17 - 旗舰项目

前面 16 章讲的是 Viper 这门语言本身。本章介绍用 Viper 写出来的几个真实、完整的工程——它们既是语言能力的实证,也是编译器最重要的回归对象。

项目 位置 定位
ViperC ../ViperC Viper 语言编译器本体(自举)
Test ../Test 回归测试工程集(编译器的质量门禁)
VET ../VET Viper 环境/产物检查器
ViperOS ../ViperApps/ViperOS 用 Viper 写的裸机操作系统
ViperMNIST ../ViperApps/ViperMNIST 用 Viper 做深度学习(手写数字识别)

ViperC —— 编译器本体

ViperC 是 Viper 的第二代编译器:用 Viper 写、也被 Viper 编译。整条编译链路没有任何 Python 运行时参与——词法/语法分析走自研的 includes/ast(9 个文件),IR 生成走 App/lib/core/Gen/,目标代码由 llc + clang++ 产出。

自举链路:

TransPyC(种子,CPython 实现)
    │  只做一次:把 ViperC 源码编译成 viperc.exe
    ▼
viperc.exe(第一阶段产物)
    │  自举:用这个 exe 再编译 ViperC 自身
    ▼
viperc.exe(自举产物,当前随 exe\ 提供的那份)
    │
    └─ 用它编译任意 Viper 工程(ViperApps\*、Test\* …)

规模(本机实测):

项 值
编译器源码 App/ 下 76 个 .vp 文件,约 64,656 行
翻译器核心 App/lib/core/Gen/ 52 个文件,约 49,978 行
阶段与合并 App/lib/Phase/ 6 文件;App/lib/Stub/ 9 文件
自测用例 Test/ 下 39 个 .vp(App/ 36 + NegativeTest/ 2 + Sha1Test/ 1)
平台 Windows x64(源码直接 import w32.*)

目录骨架:

ViperC/
├── project.vpj                 # 工程配置(source_dir=./App,输出 viperc.exe)
├── App/
│   ├── main.vp                 # CLI 入口:内存池、单例注入、参数解析、Phase 调度
│   └── lib/
│       ├── Projectrans/        # project.vpj 加载与路径解析
│       ├── core/Gen/           # 翻译器(AST → LLVM IR)
│       ├── Phase/              # Phase1(stub 分离)/ Phase2(组合编译)/ BuildPipeline
│       └── Stub/               # StubGen(.vpi 读取)/ StubMerger(拓扑合并)
└── Test/                       # 编译器自测(Viper)

内存模型:全程无系统 malloc 抖动,只有两个 MemBuddy 伙伴分配器池——主池 mb(1 GiB)与常驻池 perm_pool(≈512 MiB)。--detection 可把两个池切到检测模式(0xCDCD 填充 + 记录表探针)排查越界写。

编译任意工程(用自举产物):

exe\viperc.exe --project ViperApps\ViperMNIST\project.vpj --clean --run

命令行参数详见 12-compilation-system.md;自举过程与可行性分析详见 13-bootstrapping.md;交互式 REPL 见 15-repl.md。

自举注意点:自举后模块级全局变量带 SHA1 前缀(模块隔离),像 _g_gen 这类单例必须逐模块赋值,不能只在 main.vp 里赋裸名,否则部分模块会读到自己的 None。


Test —— 回归测试工程集

Test 是编译器的质量门禁:每个子目录一个独立可编译工程(App/main.vp + project.json),Test/README.md 收录 77 个并按实现难度升序排列,供编译器开发按序推进(另有 NegativeTest 负向测试容器,不计入难度序列)。

约定:

  • 几乎所有项目用 testcheck 库(begin / section / check / ok / end)输出 PASS/FAIL 并汇总;
  • 多数项目依赖 memhub 内存分配器与 C 互操作类型。

难度分层(README 口径):

层 数量 代表项目
简单 16 FuncTest、LoopTest、StringTest、StructTest、EqTest、ShortCircuitTest、IterTest
简单→中等 3 GenericTest、GenericTest3 / GenericTest4(泛型入门)
中等 21 TypeCastTest、PointerTest、DictTest、ClassArrayTest、HashLibTest、ArgparseTest
较难 26 GenericTest2、G4/G5/G7、MultiInheritTest、SuperTest、IsinstanceTest、AstTest、NewAstTest、LLvmLiteTest、ZlibTest、CPythonTest
环境依赖 / 回归 2 WebTest(需真实网络)、NoVTableCrossMixinTest
补录(2026-10) 9 CharTest、RawArrayTest、DefaultArgTest、CoroTest、ThreadingTest、ZlibDbg、MLIRLiteTest、PtrOpProbe、ProbeGen

回归复现型(缺陷最小化)——修 bug 时常单独跑这几个:

项目 复现的问题
G7 类名与全局变量同名导致 struct body 不完整(符号表命名冲突)
ClosureCallTest 闭包返回函数指针后直接 f() 调用
Extern2Test 外部声明被重复 define(应只生成一次 declare)
SlotsBugTest __slots__ + 类型注解误判崩溃(编译通过即达标)
SprintfTest %g 精度 / 变参整数提升
NoVTableCrossMixinTest NoVTable 多继承下跨 Mixin self. 调用(this 指针前移 sizeof(定义类))

自举相关(编译器自身依赖的库,自举前置检查):

  • AstTest —— AST 解析 / 遍历 / dump,运行时 isinstance 区分节点;
  • NewAstTest —— ast 模块 93 项全面回归,语法面最广(match / async / lambda / f-string);
  • LLvmLiteTest —— llvmlite 库 27 节(类型 / 指令 / phi / switch / 原子操作 / SSA 验证)。

负向测试 —— Test/NegativeTest:9 个故意编译失败的用例(call_too_few / call_too_many / call_wrong_type / call_float_to_int / missing_return / undefined_func / import_missing_module / import_wrong_path / import_stale_path)+ run_negative_tests.py,用于验证 fail-fast 报错行为。

运行方式:

:: 全量回归:遍历所有含 project.json 的工程,编译后多线程运行(超时强制结束)
python Test\regression_test.py

:: 顺序回归:按 README 的「建议实现顺序」逐个编译并立即运行,失败即停
python Test\SequentialRegressionTest.py

regression_test.py 会把 stdout 中出现 failed / error / traceback 等关键词的运行也记为失败,并回显匹配行与上下 5 行。

VPC 侧另有自测套件 ViperC/Test(39 个 .vp:App/ 36 + NegativeTest/ 2 + Sha1Test/ 1),入口 test_main.vp 聚合全部用例:

exe\viperc.exe --project ViperC\Test\project.vpj --clean --run

注:Test/README.md 的清单已补录至 77 个(含 CharTest / RawArrayTest / DefaultArgTest / CoroTest / ThreadingTest / ZlibDbg / MLIRLiteTest / PtrOpProbe / ProbeGen),并列出 NegativeTest 负向测试容器。


VET —— Viper 环境 / 产物检查器

VET(Viper Environment Tool)是一个用 Viper 写的工具链产物检查器,定位类似 PET。两种模式:

  • ver <exe>:对给定 Windows PE 做三项校验,确认它确由 ViperC 工具链生成。

    检查项 说明
    [0/3] 常用目录表 构建常用目录清单(C:\Viper、D:\Viper + 各盘 Program Files + 用户桌面),非空即通过
    [1/3] 内嵌版本段 解析 PE 段表,定位 .PRVERSN 段并读出其中的版本串
    [2/3] --version 前缀 执行 <目标 exe> --version,校验 stdout 前 5 个字符是否为 Viper
  • scan --cache <path>:常驻扫盘发现器,默认每 10 秒一轮(--sleep 可改),递归查找所有同时满足"可解析 PE + 含 .PRVERSN 段 + --version 输出以 Viper 开头"的 exe,结果以单行 JSON 数组写到 stdout,并把发现记录写入缓存文件。另提供 scan --search-paths 查询开关(建表后打印即退出,不扫盘)。

约定:stdout 只放 JSON,所有人类可读日志走 stderr(安静模式默认只保留启动摘要 + 每轮一行 + 告警,--verbose 恢复全部过程日志)。

# 单 exe 校验(日志在 stderr)
VET.exe ver ..\exe\viperc.exe

# 扫盘:只跑一轮;stdout 重定向即得到 JSON
VET.exe scan --cache .\vet_cache.json --once > result.json

# 查询将搜索的路径(建表后逐行打印到 stderr 即退出)
VET.exe scan --search-paths

看点:--need-confirm <秒> 的心跳确认由独立的看门狗子进程(VET.exe confirm-watch …)驱动,失败时 TerminateProcess 强杀 scan——用子进程而非线程,是为了避开 VLog / VScan 进程级缓冲与 MemBuddy 的线程安全假设。--need-confirm 开启时另有一条附带的 check 请求通道(往 stdin 写一行 JSON 即可点名校验某个 exe)。

构建(本机自编译,本仓库不预置产物):

$env:PATH = "D:\msys64\mingw64\bin;D:\LLVM\bin;$env:PATH"
..\exe\viperc.exe --project .\project.vpj

产物位于 VET\__vpcbuild__\output\VET.exe。


ViperOS —— 用 Viper 写的操作系统

ViperOS 是 Viper 的旗舰演示项目:一个完整可启动的裸机 64 位操作系统。与"教学用 mini-OS"不同,ViperOS 用 Viper 写一切——内核、驱动、用户程序、库、SDK 都是同一种语言。

主要组成:

  • VKernel —— 64 位微内核(目标三元组 x86_64-none-elf)
  • UEFI 引导器 —— boot/boot.c(GNU-EFI 编译为 disk/EFI/BOOT/bootx64.efi)
  • FAT32 驱动 —— 自研实现,支持挂载 / 目录 / 文件操作
  • 4 个用户应用 —— HelloWorld / Terminal / Gargantua / Scene3D
  • 2 个动态库 —— SerialLogger / VPUI64
  • ViperPOS SDK —— 用户态开发库(系统调用、窗口、文件系统、进程)
ViperOS/
├── build.py                # 顶层构建入口:构建 → 打包 → 启动 QEMU
├── boot/                   # UEFI 引导器(Makefile + boot.c)
├── VKernel/Kernel/         # 内核
│   ├── drivers/            # core/cpu、devfs、fs/fat32、input、serial、storage、usb、video
│   ├── execrunner/         # ELF 加载器
│   ├── intr/               # GDT/IDT/ISR/Syscall
│   ├── mm/ paging/ sched/  # 内存管理 / 分页 / 协程·进程·调度
│   ├── services/           # 内核服务
│   └── platform/           # PIC / PIT / RTC / Timer
├── Apps/                   # 用户应用(每个子目录一个独立 ELF)
├── Libs/                   # 动态库(每个子目录一个 .so)
├── vpsdk/                  # ViperPOS SDK(应用开发用)
├── Scripts/                # disk.ps1(ImDisk 打包 FAT32 镜像)/ disk.sh
└── disk/                   # 被打包进 disk.img 的文件

快速开始:

cd D:\Users\TermiNexus\Desktop\TransPyC\ViperApps\ViperOS
python build.py            # 完整构建并启动 QEMU

build.py 会依次:编译 VKernel → 编译 2 个动态库与 4 个应用 → 拷贝产物到 disk/apps/、disk/libs/、disk/sys/kernel/x86_64/ → 用 Scripts/disk.ps1 生成 64 MB FAT32 镜像 disk.img → 启动 QEMU(-no-reboot 防止三重错误后重启)。退出 QEMU 后查看 serial.log 可见内核启动日志。常用参数:--noclean(保留 temp/ 加速二次构建)、--kernel-only(只重编译内核)。

平台:Windows 10/11 + mingw + QEMU 为主平台;Linux 理论可用(需改用 disk.sh);macOS 未测试;真实硬件暂未支持(仅 UEFI x86_64)。


ViperMNIST —— 用 Viper 做深度学习

ViperMNIST 是 28×28 手写数字识别示例,纯 Viper 实现的 MLP / CNN 训练与推理(torch-lite)。

模型:

  • MLP:Linear(784→hidden) → ReLU → Linear(hidden→10)
  • CNN:Conv(1→c1,3×3,pad1) → ReLU → MaxPool2 → Conv(c1→c2,3×3,pad1) → ReLU → MaxPool2 → Linear(49*c2→hidden) → ReLU → Linear(hidden→10)

权重形状同 PyTorch(Conv(out,in,k,k) / Linear(out,in),偏置 b(out));线性前向走 vipersimd.simd_dot4d,relu 走 simd_max4d——即用 Viper 的 SIMD 封装做计算加速。

入口分发:

  • 无命令行参数 → 启动 Qt6 图形面板(数据 / 训练 / 推理,含 3D 网络图)
  • 带命令行参数 → 走 CLI(train / use)
:: 训练(MLP,5 轮,批 64)
app.exe --mode train --data-dir data --epochs 5 --batch 64 --lr 0.01 ^
        --hidden 256 --save models/mnist.bin --limit 60000

:: 训练(CNN:卷积 + 池化,更抗形变)
app.exe --mode train --arch cnn --c1 8 --c2 16

:: 推理:加载模型并打印前 10 条预测
app.exe --mode use --data-dir data --load models/mnist.bin --show 10

常用开关:

开关 含义
--arch mlp|cnn 架构:全连接 / 卷积+池化
--hidden / --c1 / --c2 隐藏层宽度 / CNN 两段卷积通道数
--epochs / --batch / --lr 训练轮数 / 批大小 / 学习率
--no-aug 关闭数据增强(默认开启:训练时随机平移 ±2px)
--download / --file 自动下载缺失的 MNIST 数据 / 指定本地已下载的 .gz
--seed 随机种子
--limit 样本上限(0 = 全部)
--save / --load 训练保存路径 / 推理加载路径

目录:App/main.vp(入口与 CLI)、App/lib/MnistData.vp(IDX 数据加载)、App/lib/MnistNet.vp(网络与训练)、App/lib/AppGui.vp(Qt6 面板)、data/(MNIST 数据与 mnist.bin)。

use 模式的架构 / hidden / 通道数以模型文件头为准,无需与命令行走一致。


它们证明了什么

能力 由谁验证
自举(编译器编译自己,无 Python 运行时) ViperC
全语言面回归(语法 / 类型 / 泛型 / OOP / 闭包 / 容器 / 自举库 / 负向报错) Test、ViperC/Test
FFI、PE 解析、Win32 绑定、进程/管道、JSON 库 VET
裸机内核、中断/分页/调度、驱动(FAT32/USB/IDE/网络)、ELF + 动态库、UEFI 启动 ViperOS
数值计算、SIMD 加速、Qt6 GUI、自定义训练循环 ViperMNIST

这些工程是编译器最真实的回归面:任何一处语言/代码生成回退,通常都能在这里暴露出来。


未来展望

上面这些项目证明的是 Viper 的当下能力;我们对它的期望不止于此——我们未来期望 Viper 在高并发、底层、AI 场景、边缘(端侧)能够发光发热:

  • 高并发:微内核调度、协程与进程模型已在 ViperOS 里跑通;无 GC 的确定性内存模型(MemBuddy 池 + 显式所有权)让延迟可预测,适合并发密集的场景。
  • 底层:裸机、驱动、引导器、可自举的工具链都已用 Viper 自己写成,且不依赖任何运行时。
  • AI 场景:ViperMNIST 已经开了个头(用 Viper 做手写数字识别);强类型 + 零开销抽象适合把数值计算与算子直接编译到原生机器码。
  • 边缘(端侧):编译目标就是原生机器码、启动即运行、无解释器与运行时开销,适合资源受限的端侧设备。