yfaming on Nostr: 本章将 vm 的运行时栈和常量表所支持的数据类型,从 double ...
本章将 vm 的运行时栈和常量表所支持的数据类型,从 double 升级为了用 tagged union 实现的 Value,从而可以支持 bool、number、nil 等类型。后续章节还将继续扩展。
这里使用了 tagged union 技法,本质上是用 C 来实现像 Rust 那样的 enum。大体做法是:用一个 enum 字段,标记类型,再用一个 union 字段,保存具体类型的值。根据不同的类型,使用 union 里的不同字段。
接下来,添加了操作布尔值和 nil 的指令,它们只是向 stack 里放入相应的值。这当然可以用 `OP_CONSTANT` 指令来完成,但是,用专用指令的话,可以使得生成的字节码代码少一个字节,性能更好。
最后,支持了「逻辑非」运算和比较运算。值得一提的是,支持比较运算时,只增加了三个指令 `OP_EQUAL`、`OP_GREATER`、`OP_LESS`。对于 `!=`,`<=`,`>=`,则由这三个指令与 `OP_NOT` 组合完成。作者强调,字节码指令与用户代码不需要一一对应,虚拟机有自由选择任何指令与代码序列,只要它们有正确的用户可见的行为即可。而从性能考虑,则不如每个运算符一个指令了。但是,作者强调的这一点,是值得注意的。
总体上这一章还是比较简单的。
接下来,开始 Crafting Interpreters 第二部分,用 C 实现的 Lox 字节码解释器 clox。
在第一部分,用 Java 实现的 tree-walk interpreter jlox 中,我们完整实现了 Lox 解释器,包括 scanner、parser、resolver、interpreter 等等。
但是,第一部分的解释器利用了 Java 语言的许多特性。
比如,Lox 的值,全部用 Java 的 Object 类型表示。
Lox 里的 return,用 Java 的异常来实现。
而 Java 自带 GC,所以 Lox 中对象的生命周期,我们也完全没考虑过。
在第二部分,我们将使用 C 语言实现解释器。C 比 Java 更加 low-level,它不支持 OOP,不支持异常和 GC。
因此,这几个问题,我们就需要在 C 里面手动处理了。
而且,第二部分我们实现的是字节码解释器。我们需要定义字节码,并在 parsing 将 ast 编译为字节码。
用不同语言实现同一门语言,但采用略有不同的技术,可以加深我们的理解,并学习 compiler/interpreter 领域的不同主题。
Published at
2026-08-21 12:44:44 UTCEvent JSON
{
"id": "a53e09a7d9db10951f33f5bb2cf522511810308500d021446d90414150b69854",
"pubkey": "908fbc3babc322eea473a0ab1e6bf6b3adcf899288ac97b2fa79f34ad408d4e4",
"created_at": 1787316284,
"kind": 1,
"tags": [
[
"q",
"1aea59b1f714db6bebf6019f30c55e36795d9bbba666682c752163c90db1acff",
"wss://relay.damus.io/",
"908fbc3babc322eea473a0ab1e6bf6b3adcf899288ac97b2fa79f34ad408d4e4"
]
],
"content": "本章将 vm 的运行时栈和常量表所支持的数据类型,从 double 升级为了用 tagged union 实现的 Value,从而可以支持 bool、number、nil 等类型。后续章节还将继续扩展。\n\n这里使用了 tagged union 技法,本质上是用 C 来实现像 Rust 那样的 enum。大体做法是:用一个 enum 字段,标记类型,再用一个 union 字段,保存具体类型的值。根据不同的类型,使用 union 里的不同字段。\n\n接下来,添加了操作布尔值和 nil 的指令,它们只是向 stack 里放入相应的值。这当然可以用 `OP_CONSTANT` 指令来完成,但是,用专用指令的话,可以使得生成的字节码代码少一个字节,性能更好。\n\n最后,支持了「逻辑非」运算和比较运算。值得一提的是,支持比较运算时,只增加了三个指令 `OP_EQUAL`、`OP_GREATER`、`OP_LESS`。对于 `!=`,`\u003c=`,`\u003e=`,则由这三个指令与 `OP_NOT` 组合完成。作者强调,字节码指令与用户代码不需要一一对应,虚拟机有自由选择任何指令与代码序列,只要它们有正确的用户可见的行为即可。而从性能考虑,则不如每个运算符一个指令了。但是,作者强调的这一点,是值得注意的。\n\n总体上这一章还是比较简单的。\n\nnostr:nevent1qvzqqqqqqypzpyy0hsa6hseza6j88g9tre4ldvade7ye9z9vj7e0570nft2q348yqy2hwumn8ghj7un9d3shjtnyv9kh2uewd9hj7qgewaehxw309akxzmn89eex2mrp09ejumrpdejz77ngqqsp46jek8m3fkmta0mqr8esc40rv72anwa6veng936jzc7fpkc6elcmzqjf3",
"sig": "931b8fecef89a00d770a5b9c7d17a838ff861d6e19733d1081cd5596787dc39fa22d5460686769ccadd4bd68835646f8ba984fd9959c28fd289316e1e1a23685"
}