why?
我决定用 VM 来实现 x-lisp, 因为对于动态类型语言而言, GC 相关的问题太复杂了。
对于之后要实现的静态类型语言再实现编译器,比如 meta-lisp。
或者更合适地,是对于不需要 GC 的语言来实现编译器, 比如 system-lisp 和 linear-lisp。
[2025-11-23] 现在还不确定要放弃编译到 native code。 xvm 作为备选方案。 再继续调研一下。
行动
新的任务大概是:
port x-sexp-tael.js to runtime。
port basic-lisp to runtime。
- 保持现在的极简 instruction, 对于 call 指令和某些 primitive function 做 inline 优化(比如 iadd), basic-lisp 的解释器要能写成一个简单的, 有 switch 和很多 case 的 C 函数。
还是需要 GC,只不过这次 root scanning 问题简单多了。
但是可能不能直接实现 basic-lisp 的 vm。 因为对于底层 vm 或者 native 汇编来说, call 和 assign 应该是两个指令。 而 basic-lisp 中 call 和 assign 到 dest 是一个指令。
也就是说:
- 要么在 c 的 byte code 解释器中拆分指令;
- 要么实现一个 basic-lisp 到 vm 的 instruction selection。
我想可能后者更合理一些。
可能要回到 xvm 和 xasm 以及 xrom 或 xexe 的设计。
xvm
需求:
- 我需要 vm 因为 basic-lisp 的 call 指令是带有 dest 变量的,这与 vm 是有差别的。
- 我不需要指令集编码,因为我不需要稳定的二进制接口。
- 我不需要类 forth 的栈 vm,而是需要寄存器 vm, 因为 basic-lisp 的函数有很多局部变量。
前面提到,把带有 GC 的纯动态类型语言,编译到 native code,不是很合理。 类似的,为带有 tag 的语言实现 instruction encoding 也不是很合理。 tag encoding 应该在软件层次进行。
行动:
- 用 c 实现 xvm 的模拟器(类似 inet-lisp 的 worker)。
- 用 c 实现 xvm.machine 的解释器(lisp 语法)。
- 编译出来 xvm.machine 文件,然后用 xvm 解释执行。
看之前 xvm 和 x-forth 的笔记, 发现很多设计上的问题都是因为语言没有分层。 现在的分层是:
- x-lisp -- 负责语言的功能
- basic-lisp -- 负责优化
- machine-lisp -- 负责具体执行
目前的计划只是解释 xvm.machine 文件, 之后如果有了稳定的 byte code 编码, 也可以考虑编译到 xrom 或 xexe。
现在 machine-lisp 真的有用了, 因为有 x86.machine 和 xvm.machine。
SPARC
[2025-11-23]
了解到了 SPARC 指令集的存在, 它除了支持 tagged value 之外, 也支持正常的 value。
这样思路就打开了, 因为只单独支持 tagged value, imm 之类的初始化数据的指令都不知道应该怎么处理。
而 SPARC 就是正常的一个 RISC 构架, 只不过增加了一些处理带有 tagged value 的指令。
程序员和编译器可以灵活选择。
mmix
[2025-11-25]
为了简单的指令集编码,可以模仿 mmix, 但是改为 little-endian 和 at&t operand order。
root scanning
[2025-11-29]
但是考虑 vm 实现,是因为 GC 的 root scanning 问题。 但是如果使用了类似 SPARC 的可选 tagged value 设计。 那么不是所有的 value 都有 tag。 root scanning 问题就还是困难的。 这与针对 x86 解决 root scanning 问题没有差异。
[2025-12-03]
但是也可以保证在 gc safepoint, 所有的寄存器都保存着 tagged value。
machine-lisp as assembly language
[2025-11-29]
xvm 可以让我们有动机来把 machine-lisp 设计成完整的汇编语言。
其实是要嵌入一个解释器在汇编语言中, 使得汇编语言可以使用变量和表达式。
xvi -- extensible vector instruction set
这么说来 xvm 应该不是一个 vm, 而是一个 risc 指令集构架。
作为 指令集构架 是不能用 c 扩展的, 或者说用 c 扩展的方式是系统调用。
xvi project
[2025-11-29]
设置 xvi 这个新的项目,用来探索 risc 指令集构架的设计。
学习 mmix 的简单指令集编码。
但是改为 little-endian 和 at&t operand order。
以 machine-lisp 为汇编语言。
需要把 machine-lisp 设计成完整的汇编语言。 要嵌入一个解释器在汇编语言中,使得汇编语言可以使用变量和表达式。
学习 SPARC,在正常的 RISC 集之外, 增加处理带有 tagged value 的指令。
探索 vector 相关的指令集。
永恒
[2025-12-03]
knuth 设计 mmix, dev 设计 uxn, 都在于让程序变为永恒。
其实自己设计指令集构架, 如果没有真实硬件的实现, 其意义很小的。
knuth 认为自己设计出了 clean 的指令集构架, 但是就算是我这种人看到了 mmix, 也想把它改成 little-endian 和 at&t operand order。
hacker mindset
[2025-12-03]
新的指令集构架是很有趣的项目, 但是对于 x-lisp 目前的项目状态来说是不适合的。
想要用 vm 的方案来取代 native 编译器, 是为了逃避 root scanning 问题, 或者认为 root scanning 问题太难解决。
但是编译器的使命就是 bridging the differences, 写编译器的人如何能抱怨 differences?