从 4 月底开始就很少玩游戏,因为迷上了另外一件事情,基于 Lua,创建一个语法上类似 Swift 的编程语言,一方面学习 LPeg, 另外一方面,按照自己的想法,对 Lua 的语法修修改改。
基本上,Lua 用了很多的词来分割语意单元,比如 C/C++ 里面的语法块,是放在 '{' 和 '}' 包裹中的,在 Lua 中是 do 和 end 中,或者 then 和 end 中, 当内容一多的时候,都是词;还有就是 function,连 Swift 都是 func 就可以了,为何要一个完整的单词呢。
还有少不了的 local,避免全局变量污染,就只好都是 local 了,我觉得默认就行,总是 local 有点多余。
其实最开始就是上面这 3 点,当然也参考了一下有名的 MoonScript,因为它是 MIT 协议开源的嘛,还想抄来着,结果实际上,从头到尾几乎都是重新构建的, 只有 global name,真的是抄的,加上了 LuaJIT 的 jit 等不多的几个而已。
LPeg 的 P、S、Cg、Ct、Cmt、Cp、Cb、Cf,刚开始的一两天,真的头大,后面就变成肌肉记忆了。
LPeg 的匹配规则有两种,一种是全文完全匹配,得到的是完整的 AST,另外一种是寻找匹配,拿到部分匹配的内容。对于一门编程语言,只能选择第一种。
语言中的 class / struct 当然是基于 metamethod 的,其中,class 被设计为跟普通的 table 一样,可以随机创建 key / value,当然少不了继承;而 struct,想学 Swift,没有继承, 且 key 不能为 nil,为了效率考虑,子类以及实例,都会读取自己的类或者父类,如果不为 nil,就 rawset 到本地,下次访问就快了,但是对于父类不断变动的信息,实际上是获取不到的, 这种情况只有通过类方法来解决。
实际上还加了 extension 的逻辑,使得 struct 不能继承这点其实是可以被突破的,而且 class 和 struct 两者就单单使用上来说,区分没有那么大。
我还加了 guard、switch 关键字,都是 if 的语法糖。
还有 defer 这个关键字,处理比较有意思,实际上我是能做到在任何 scope 都是起作用的,但是我嫌麻烦,而且还读到某 Swift 大 V 直觉认为 Swift 的 defer 只支持 function scope 而导致某开源软件的 bug,当然我之前也是这么认为的,所以最后在这个语言中,我将 defer 限定为了 function scope,毕竟能用就行了,直觉理解不好的我觉得也不大好。
说一下 continue,我在这个语言中也实现了,基于 goto,我的理解 continue 其实就是 goto 的语法糖,为何 Lua 不选择支持不理解。
语言鼓励偏向 Swift 一样基于 class / struct 的数据和方法来编程,也有相关 VSCode 的 extension 做简单的支持,比如高亮、outline,至于 LSP 嘛,那是没有的。
最后爆地址,在 MoonCake.