1 个月,我 Vibecoding 了一门新语言

9 阅读8分钟

先说结论:我花了大概 1 个月,借助 AI 以 Vibecoding 的方式,做了一门新语言,叫 EzLang

项目地址:github.com/ZYF93/EzLan…

它现在还不是一门“可以放心上生产”的语言,更准确地说,它是一个能跑、能编译、能写 demo、能看到方向的语言实验项目。但我确实把一整套东西从 0 搭起来了:语法、编译器、LLVM IR、CLI、标准库、LSP、VS Code 插件、WebAssembly、Android/iOS UI 绑定雏形,以及一堆测试。

所以这篇文章不是“我发明了未来编程语言”的宣言,而是一次比较真实的复盘:一个普通开发者,在 AI 辅助下,为什么会开始造一门语言,中间踩了哪些坑,以及这个项目后面还需要什么样的人一起把它做下去。

起因:我只是想试试“语言设计能不能 Vibecoding”

最开始的动机其实很朴素。

过去写业务、写工具、写框架时,我经常会冒出一些“不如语言层面就支持”的想法。比如:

  • 能不能默认值语义,少一点到处共享可变状态的心智负担?
  • 能不能有 Arena 风格的内存模型,但又不要把使用体验做得太硬核?
  • 能不能把并发写得像同步代码,而不是一层层 async/await 传染?
  • 能不能同时面向 native、WebAssembly、移动端?
  • 能不能让标准库和工具链一开始就作为语言的一部分,而不是后面补?

这些想法单独看都不新。很多成熟语言都在不同方向上做过更深入、更严谨的探索。

但我当时真正好奇的是:如果今天有 AI,当一个人想从 0 做一门小语言时,边界到底在哪里?

于是 EzLang 就开始了。

我的工作方式大概是:我负责判断方向、拆问题、看 diff、跑测试、砍掉不合理抽象;AI 负责大量重复实现、文档初稿、测试样例、边界条件补全。听起来很美好,但实际过程里,AI 会很自信地写错,尤其在编译器这种地方,错得还挺像真的。

EzLang 大概是什么

EzLang 是一门表达式优先、默认值语义的系统编程语言实验。

一个最小例子大概长这样:

from "std/io" import { println };

let name: Str = "EzLang";
println(msg = "Hello {{name}}");

它目前有这些设计方向:

  • 表达式优先:变量、控制流、match、函数调用等尽量可以自然组合。
  • 类型系统:支持泛型、可选类型、联合类型、结构体、类型别名、List / Dict 等。
  • 值语义 + Arena:默认按值复制,临时内存由 Arena 管理。
  • Flow 并发:用 flow {}parallel {}race(pl) 表达并发语义,尽量保留同步代码的写法。
  • 外部 ABI:通过 extern 和 declare 调 C、JS 或平台库。
  • 跨平台目标:native、emcc/WebAssembly、Android、iOS 都有不同程度的支持。
  • 工具链:有 ez buildez runez testez fmt、LSP 和 VS Code 插件。

这不是说这些能力都已经成熟。恰恰相反,它们很多还处于 demo 或最小可用状态。但至少现在已经不是只停留在 README 里的幻想了。

最难的不是写代码,是不断发现“语言设计没有小改动”

做业务系统时,一个字段设计错了,大不了迁移一下。做语言不一样。

你今天随手加一个语法糖,明天它就会影响 parser、语义分析、类型推断、codegen、formatter、LSP、文档和测试。

比如字符串插值。一开始只是想支持:

"Hello {{name}}"

很快就会变成:那 {{first + last}} 要不要支持?插值表达式类型必须是 Str,还是自动调用 toString?如果报错,错误位置要指向字符串内部还是整行?LSP hover 怎么办?formatter 能不能保持原样?

再比如 parallel。语义上我希望它像同步代码一样好理解,但实现上又要区分:

  • 是否在 flow 内;
  • 是否零捕获;
  • 返回值是不是 I32
  • native 目标和 emcc 目标 runtime 完全不同;
  • 读取结果时要不要自动 join;
  • Flow 退出时未读取任务如何处理副作用。

语言里很多设计都是这样:看起来只是“加个特性”,实际上是在同时改一条生态链。

AI 帮了很多,也坑了很多

Vibecoding 最大的好处是,它让一个人可以快速推进大量工程面工作。

比如标准库 API、测试样例、文档翻译、CLI 子命令、VS Code 插件骨架,这些如果全手写,速度会慢很多。AI 在这类“有明确局部目标”的任务里很有用。

但 AI 也有明显问题:

  • 它很容易过度设计,写出看起来很完整、实际没必要的抽象。
  • 它会在编译器里编出不存在的 ABI。
  • 它会修一个测试,顺手破坏另一个语义。
  • 它会写文档时把“未来目标”说成“当前已支持”。
  • 它对跨平台细节特别容易自信,比如 emcc、Android NDK、iOS SDK 这些边界。

所以这个项目里最重要的不是“让 AI 写”,而是“人要不断收缩问题、跑测试、删掉假正确”。

我越来越觉得,Vibecoding 不是降低工程判断要求,而是把工程判断的密度提高了。你不一定每行都亲手敲,但你必须更频繁地判断:这个东西是不是真的对?是不是过度?是不是和现有语义一致?

目前我觉得 EzLang 有意思的地方

第一,默认值语义 + Arena 这条路我还挺喜欢。

很多语言要么把内存交给 GC,要么把生命周期做得很显式。EzLang 目前尝试的是另一种手感:多数值默认复制,临时对象走 Arena,作用域结束回收。它不一定适合所有场景,但对于很多系统工具、小型运行时、编译期明确的数据结构,我觉得很有探索价值。

第二,Flow 并发 是一个想继续深挖的方向。

我不太想把并发写成到处传染的语法噪声。EzLang 现在的目标是:用户写接近同步的代码,runtime 在不改变可观察行为的前提下调度阻塞点。这个方向当然很难,现在也只是初版,但它是我个人最想继续做的部分。

第三,工具链从一开始就一起做

这个项目不只是一个 parser demo。现在已经有 CLI、测试、格式化、LSP、VS Code 插件、标准库文档。哪怕很多地方还粗糙,但“语言不只是语法”的意识是从第一天就放进去的。

第四,跨平台不是后补的口号

现在 native、emcc、Android、iOS 都在设计里有位置。Web UI、Android UI、iOS UI 都有低层绑定文档和部分桥接实现。它们还远远不是成熟框架,但这让语言的边界从一开始就不只停在命令行程序上。

但它的问题也非常多

必须诚实地说,EzLang 现在就是 demo 状态。

它的劣势也很明确:

  • 编译器还不成熟,很多语义后面可能会调整。
  • 性能没有严肃 benchmark,不能拿来吹。
  • 标准库覆盖面看起来大,但不少模块还只是基础能力。
  • Flow runtime 还很早期,native 事件源式调度没有完整接入。
  • 移动端 UI 包是底层绑定,不是成熟 UI 框架。
  • 语法设计还需要更多真实代码验证。
  • 文档虽然补了中英文,但后续维护压力会很大。
  • 生态为零,除了我自己,没有真正用户。

所以如果你问“我能不能拿它写生产项目”,我的回答是:现在不建议。

但如果你问“这是不是一个值得参与的语言实验”,我觉得是。

我希望什么样的人来一起做

如果你对下面任何一块感兴趣,都欢迎来看看:

  • 编译器前端、语义分析、类型系统;
  • LLVM IR/codegen;
  • runtime、Arena、Flow 调度;
  • WebAssembly / Emscripten;
  • Android NDK / JNI;
  • iOS / Objective-C runtime / UIKit bridge;
  • 标准库设计;
  • LSP、formatter、VS Code 插件;
  • 文档、教程、示例项目;
  • 语言设计讨论。

我不希望它变成一个“为了造轮子而造轮子”的玩具仓库。更理想的状态是:把它当成一个公开的语言实验场。可以讨论语义,可以推翻设计,可以写测试,可以做小 demo,也可以专门来挑刺。

挑刺其实很重要。语言项目最怕作者自嗨,越早被真实使用和质疑,越容易长出正确的形状。

最后,求个 star

EzLang 目前还很小,也很不成熟。

但过去这 1 个月,我确实把一个模糊的想法做成了一个能跑起来的项目。它有编译器,有标准库,有工具链,有文档,有一些跨平台尝试,也有一堆还没填完的坑。

如果你觉得这个方向有意思,欢迎来 GitHub 看看,提 issue,提 PR,或者单纯点个 star 支持一下:

github.com/ZYF93/EzLan…

一个 star 对成熟项目可能只是数字,对这种早期语言实验来说,至少能说明:这事不是只有我一个人在自言自语。


最后的最后

失业快 1 年了, 快没钱花了, 有工作机会私我一下- -