Miva:从Rust到新语言的蜕变之旅
Miva:一个语言的第一步
概况
Miva是我创建的语言。Miva既是语言的名字,也是一个缩写——
Memory-Safe, Intuitive, Verifiable, Adaptable
乍一看很像Rust,我也承认,Miva是受Rust的启发的。之所以设计Miva,是为了规避Rust的复杂性。我以前写Rust,就感觉很复杂,很繁琐,老是被所有权束缚的不自在。Miva,就是在完全不安全和安全但严谨之间找到一个平衡点——
信任程序员,但不考验程序员的记忆
官网:Miva Official
艰难的第一步
当然,这篇文章不只是介绍,甚至说不是介绍,我更多的想分享语言设计中的真实历程。
首先肯定是和AI商讨语言哲学。如今,Miva和第一版的哲学有些不同,甚至于某些时候大相径庭,但是核心是不变的——内存安全,简洁,信任。
设计完后,是实现部分。作为一个对Rust了解不少的开发者,第一选项肯定是Rust。我当时在网页端让AI生成,然后手动复制——结果到Parser,进行不下去了。
Parser的测试一直挂,修到最后AI也不明所以。这也难怪,因为Parser是最复杂的部分,也是最重要的部分。在请教CodeGeeX之后,终于把为数不多的9个测试全过了,然后是Semantic。
结果到了Semantic部分,全部失效。我失去了信心。奋战一天了,四大关(Lexer -> Parser -> Semantic -> Codegen)才到一半。这里,就不得不推荐我认为非常好的快速原型语言了:OCaml。
OCaml:不错的原型,但也就是不错的原型
OCaml作为原型,有许多优点:
- Lexer和Parser都现成,不用手写,成功率非常高
- ADT天然适合表示编程语言结构(Rust也是)
- 编译器生态成熟
不过我在使用过程中,也遇到了很多问题,主要是语法晦涩和工具链落后。
先说语法晦涩。
OCaml是纯函数,虽然有过程式语法如for/while,但是也丑,和C/C++的风格完全不同。
然后是函数返回值。OCaml必须用最后一个语句返回,无法提前返回,也造成了不小麻烦。
然后是工具链落后。
VS Code的OCaml,报错信息基本跟不上,还是得靠编译;dune的配置文件写起来难,编译逻辑也很诡异,一个错误修完再给一个,很神奇。
Neovim的OCaml,识别不了Dune……
所以后来,我陆续把前端和后端迁移到了Rust,那时Agent已经兴起,在AI的帮助下,进展很快。
模块化:C++的模块
作为一个语言,现代的语言,模块化,或者说包管理,是迟早要做的功能。但为图简便,Miva最开始是编译到C++的,这就为模块化造成了不小的麻烦。现在为了避免C++,推出了LLVM和自研的虚拟机后端,不过这是后面的事情了。
当时我花了两天时间(没有AI)解决这个问题。第一天专攻导入,第二天专攻导出。具体方法,就是将导入转成C++的#include,导出写入到头文件。
代码是写完了,不过成了屎山代码,重构为Rust前,我没有动过这一坨。
TypeChecker:最痛的经历
要是说哪个最难,我认为模块化只是其次,TypeChecker才是第一。得益于编译到C++,Miva不用写就得到了一个非常好的TypeChecker。不过这终究不是长久之策,于是我决定手写一个TypeChecker。
TypeChecker最难的是变量的类型推导,因为这涉及到变量生命周期(借用一下Rust概念)的问题,弄了大半天,发现频繁出BUG。
当我把Miva从OCaml重构为Rust的时候,只有TypeChecker是另起炉灶的。
结语
今天我分享这个故事,当然有介绍Miva的成分,不过更多想鼓励大家。
当时我不会Agent,尚且做成了一门编程语言;
如今Agent火遍全球,制作语言的时间从天缩短到了分钟。
不要怕难,因为编译器的核心,在前两周。
挺过那两周,是一片坦途。