关于Vim下的表达式编译

为了给Vim修跑到的一个bug读了好久代码… 于是来随手总结一下Vim9的执行流程… (超小声(

编译

首先, Vim9会编译每一行需要直接执行的代码, 并且以字符串的形式保存见到的每个函数的代码, 在真正执行函数的时候再编译, 对lambda也是这样. 我们来看一个例子:

vim9script

echom "Hello world"  # 是旧式的命令, 会被直接以字符串的形式保存和执行
var a = 0  # Vim9语句, 会被编译成字节码之后执行

# 一个函数, 它的代码会被原样保存, 在执行的时候再编译成字节码, 并以字节码的形式保存
def F()
    var a = 0
    echom "Hello world"  # 但这些命令会被原样保留, 或者说, 有一条字节码是用来保存这些命令的
enddef

F()  # 真正执行F, 这个时候F才会被编译

然后, Vim9的编译流程就是简单的递归下降, 一遍从源码编译出字节码.

执行

Vim9的执行流程好像没什么可以细讲的, 就是朴素地遍历每条字节码, 分别执行它们, 遇到函数调用时递归一下.

orz的是, Vim9的虚拟姬是典型的栈式虚拟姬, 所有值都被push到栈上, 字节码本身只携带很少的静态信息, 动态的信息都从栈上而非字节码本身或者某些寄存器里获取, 这样的虚拟姬设计会简单不少, 但运行效率相对来说也会更低.

2 Likes

学术futa