56,000行DOOM代码,用我自创的语言编写
摘要
作者构建了一种名为bet的玩笑编程语言,通过LLVM编译,采用基于区域的内存管理,并且成功运行了完整的DOOM游戏(56,000行代码),无需代码审查,仅依赖测试。
暂无内容
查看缓存全文
缓存时间: 2026/07/16 16:52
# 关于 — betlang
来源:https://betlang.dev/about/
## 我为什么构建 bet
bet 是一门小巧、真正可用的编程语言:表面上是俚语关键字,底层是一个严肃的编译器。它通过 LLVM 编译为原生代码,自行管理内存,能够自举,还能运行《DOOM》。我将它作为一个封闭实验来构建,并完整完成了它。
我在尝试做能卖钱的产品之余休息时,构建了 bet。我想要一个边界清晰、真正能做完的项目,而构建编译器在我清单上很久了。一门玩笑语言给了我借口:关键字读起来像群聊记录,包裹在一个必须真正工作的编译器外面。一开始我定了一条规则:不做调研。我从没查过是否有人已经做过这个,因为我不想在写下一行代码之前,互联网就把这个想法扼杀了。后来发现,Geoffrey Huntley(https://betlang.dev/about/#prior-art) 已经做过了,而我直到很晚才知道。
一门只在语法层面工作的语言其实只是一件戏服,所以我给了它一个真正的任务。游戏不断分配和释放对象,手动记账和垃圾回收都会消耗你赔不起的帧数。bet 用区域(arena)来处理这个问题:在作用域内分配,用于一帧,然后一次性释放整个作用域。这个模式本身并不新鲜。Zig 提供了一个 arena 分配器,可以在一次调用中释放所有内容;Odin 也为游戏代码内置了相同的 arena 和临时分配器思路。我希望 bet 将其作为一等特性携带,配有自己的关键字,这样这门语言就会读起来有它自己的设计,而不是已有语言的俚语翻版。
> 这是个玩笑。但我还是希望它能真正做点事。
我构建 bet 的另一个原因是运行一个实验。我想看看,如果我不插手实现,一个人工智能编码助手在一个困难、明确定义的项目上能走多远。我的角色是架构师:我设定问题和验收标准,然后坚持它们。我做了零代码审查。只有通过测试、满足验收标准并通过语料库的变更才能发布。这是唯一的门槛。
证明它有效的是完整移植的《DOOM》。id Software 关于渲染器、游戏逻辑、WAD 加载和音频的原始 C 源代码被重写为 bet:超过 56,000 行代码,编译成一个原生二进制文件,能在窗口中运行真正的共享版游戏。
启动它,《DOOM》会在演示模式(attract mode)中自动运行。那些片段是游戏原始的录制输入,通过仿真回放。定点数学(fixed-point math)才是真正的考验:偏差一步,玩家就会开始撞墙。bet 与参考的 C 构建在同一时间步长上重放输入,逐帧相同,因此整个模拟结果按位一致。在没有捷径的情况下做到这一点,是把玩具语言和能承载真正软件的语言区分开的关键,也是我在从未进行代码审查的构建中最信任的结果。
因此,它端到端地完成了:编译器、自举、文档和这个网站。到此为止。如果有功能请求,我会审查,但没有路线图,也不会有版本二。bet 是一个玩笑、一个实验,也是一种了解这种构建实际需要什么的方式,这些都做到了。如果我想让它代表我什么,那就是我做事有始有终。
## 我认真对待的部分
手动 `free()` 记账和 GC 暂停都会破坏帧预算。在 bet 中,你分配到一个 `crib`(作用域区域)中,然后使用 `evict` 在 O(1) 时间内一次性释放整个区域。没有每个对象的跟踪,没有帧中间的停顿。
这就是实验。表面上是玩笑,底层解决了一个难题,而构建的唯一门槛就是它的测试。它编译为原生代码,能自举,还能运行《DOOM》。它从未打算成为产品,也不需要。它已经完成了。
## 它是如何构建的
来自提交跟踪时间日志的真实数据,计算活跃工作量时去掉了空闲时间。这个限定有一个缺口:三个参与移植《DOOM》的助手因使用限制而停滞,同时时钟继续运行,因此移植游戏那一行大约多了 12 小时。去掉这些时间后,实际总数接近 22 小时。
| 项 | 明细 | 耗时 |
| --- | --- | --- |
| 移植游戏 | DOOM、俄勒冈之旅、乒乓球 | 18小时 |
| 自举编译器 | bet 编译 bet | 4小时 |
| 安全审查 | cwage 问题 #30–#48 | 3小时 |
| 基础设施、工具与网站 | CI、Docker、冻结、文档 | 3小时 |
| 前端 | 词法分析器 · 解析器 · 语法 | 2小时 |
| 语言与集合 | 关键字、类型、容器 | 2小时 |
| LLVM 后端 | 实际困难部分 | 1小时 |
| 区域内存 | crib · evict · 关键点 | 29分钟 |
| **总计** | **大部分花在移植游戏上** | |
相似文章
构建Clang后端并将Doom移植到我的自定义字节码虚拟机
作者复活了他的自定义字节码虚拟机(UVM),并借助AI解析文本LLVM IR构建了一个Clang后端,成功将Doom移植到该虚拟机上。
在我们的自定义CPU上运行Doom并走红
作者描述了在逻辑门级别设计自定义CPU、集成带有缓存的DDR3内存,并成功在FPGA上运行Doom的经历,该经历随后走红网络。
DOOMQL
Peter Gostev 使用 SQLite 作为游戏引擎构建了一款类似 Doom 的游戏,通过递归 CTE 实现光线追踪,并与 Datasette 集成提供实时网页界面。该项目由 GPT-5.6 Sol 创建,展示了使用 SQL 构建游戏逻辑的创造性潜力。
为什么fastDoom这么快
关于fastDOOM移植版相比原始Doom可执行文件实现显著性能提升的详细技术分析,涵盖了Doom源代码传承历史及具体优化技巧。
在E. coli细胞上运行‘Doom’……非常非常缓慢
MIT研究员Lauren Ramlan发表了一篇论文,证明经典游戏Doom可以在由E. coli细胞制成的显示器上运行,但帧率极低,完成一次通关需要几个世纪。