Nine's blog

RakuAST 项目资助报告

2025-04-10 12:18:00

RakuAST 项目是对编译器前端的重写和重新设计,即解析原始源代码、确定不同部分的功能、执行检查和优化,并创建低级表示的部分,然后由后端将其转换为字节码。

当我申请资助时,许多基本的基础设施已经到位。许多简单的程序已经可以运行,例如,你可以定义变量、类、函数,创建对象,调用方法等等。

然而,Raku 是一种大型语言。例如,不仅仅有方法,还有私有方法、元方法、具有完全限定名称的方法(即,当你想要特定基类的方法时),名称在编译时确定的方法调用(例如 $foo."$bar"()),超方法调用,以及更多晦涩的调用代码的方式。这些都还有待完成。所有其他编译器领域也是如此。

我解决这个问题的方法很简单:一次一个 spec test。我按字典顺序浏览了失败的 spec test 文件列表。这些 spec test 按概要分组,概要本身的编号大致按其基础性排序。例如,一开始是名称和类型处理的测试,而后面的 spec test 则处理标准库的细节。这种顺序有助于我专注于特定领域。至少在某种程度上是这样。由于测试本身是 Raku 代码,即使是对非常基础的东西的测试也可能使用高级语法特性,仅仅因为它们是表达测试的便捷方式。因此,我经常必须先支持这些特性,才能处理更基本的功能。

如果要我说出这个项目中最困难的部分,那肯定是时序或排序。Raku 是一种不容易编译的语言。很多代码已经在编译期间运行。例如,在 class Foo does Bar { } 中,我们调用了 Bar 角色(role)的主体,它实际上只是一个伪装的 sub,并且我们在编译期间执行此操作。还有更明显的例子,比如 BEGIN 代码块或语句、常量声明和 trait 应用(同样,实际上只是带有趣怪名称的编译时调用的 sub)。

这段在编译期间运行的代码可能会引用尚未存在的 scope 中的变量(因为我们仍在编译它),或者引用尚未定义的 subroutine。Traits 尤其会修改元对象(例如,类、函数或参数本身),而这些元对象甚至尚未完全定义。

所有这些意味着,程序的不同部分的声明、定义、类型设置和代码生成以完全正确的顺序完成至关重要。然而,这个顺序既没有被指定,也没有被记录。它纯粹是从旧的编译器前端的实现中涌现出来的,因为它是经过 20 年的开发才完成的。我必须一个 spec test 一个 spec test 地发现并重新创建这个顺序。

当我撰写资助申请时,我已经完成了许多这项工作。我对剩余 200 个 commit 的估计是基于过去在 Rakudo 中进行大型重构的经验,一旦基础到位,每个额外的修复都有很大机会修复多个 spec test。然而,这种希望并未在 RakuAST 项目中实现。我没有预料到需要处理的特殊情况的长尾。这包括数百个编译时检查,用于检查不同的错误情况,以提供信息丰富且有用的消息。因此,与我所想的相反:修复解锁多个 spec test 文件的现象变得越来越罕见。最终,我在本次资助工作期间所做的 commit 总数超过了 900 个。

谢天谢地,该项目的第二个目标的工作量要少得多,尽管它仍然不容易。Rakudo 编译器是自举的,也就是说,它本身是用 Raku 编写的。对于 spec test 修复工作,我仍然使用旧的编译器前端来编译编译器本身。完全替换旧的前端意味着 RakuAST 必须能够在没有帮助的情况下做到这一点。这带来了一些有趣的问题。RakuAST 的一个驱动目标是启用适当的基于 AST 的宏支持。这会将许多编译器内部机制暴露给用户。因此,这些内部机制应该使用用户期望的 Raku 类型,而不是一些低级表示。当我们编译编译器及其标准库本身时,这些类型甚至可能尚未定义,或者它们可能没有执行我们需要操作的方法。

为了解决这些循环依赖关系,我需要添加一些解决方法,例如直接访问对象的内部属性,而不是通过适当的访问器方法。很多时候,这仅仅是为了使错误报告达到我可以找出编译器到底遇到了什么问题的程度。

标准库本身是由真正喜欢 Raku 的人编写的,大约有 10 万行代码,这意味着他们知道并且不回避使用高级功能。这揭示了 spec test 没有涵盖的许多缺陷。

尽管数量达到数十万,但 spec test 甚至不仅仅是不完整。有时它们是荒谬的或完全错误的。它们包含明显的错误,以前只是没有出现,因为旧编译器前端中的错误意味着代码在某种程度上可以工作。它们还经常依赖于编译器在遇到其他错误之前以特定错误中止。然而,RakuAST 前端试图避免退出,而是旨在报告它可以找到的所有错误。因此,需要对相当数量的 spec test 进行调整或澄清。

阅读我自己的报告,我理解为什么社区对这个项目的贡献涌入量远低于我的预期。很容易被代码库的规模和问题的复杂性吓倒。尽管如此,Elizabeth Mattijsen(她负责所有 RakuDoc 和其他事情)、John HaltiwangerVadim BelmanJimmy ZhuoDaniel Green 提供了帮助。没有他们,我仍然会在困境中绝望。