为 JVM 编写语言

Writing languages for the JVM

假设我写了一种编程语言;为了同名,我将其命名为 lang.

为了开始编写lang的漫长旅程,我决定从编写lang本身开始。我实际上不能运行,因为运行程序本身运行没有任何东西。

所以我开始为 Java 中的 lang 编写另一个编译器。这一次,当我完成后,我决定将它转换为字节码,并就此保留。我现在有一个可以工作的编译器,它将我所有的 lang 代码转换成字节码。

所以我决定将我的语言自编译器插入到我刚刚在 Java 中制作的编译器中。然后我将自编译器转换为字节码,并剔除 Java 编译器。我现在有一个lang编译器,纯自己写的,转成Bytecode,可以用

这创建了一个可靠的程序,我理解所有这些,但我的问题是,相对于 JVM 的编译器设计,如果我决定为我的语言发布更新怎么办?我该如何去更新字节码?我是否只是用旧语言重写更新版本的语言?

我问这个是因为这是我想做的。自己写一个不存在的语言,然后 bootstrap 通过首先在 Java.

中创建一个编译器,将它 bootstrap 到 JVM

这和用C++做的一样。写了 类 的 C,然后写了 C++,最后放弃了 类 的 C,取而代之的是 bootstrapped C++。但是他们到底是怎么更新语言的呢?

我认为您的编译器不是解决此问题的最佳方法。

我会从我的语言的语法开始。

接下来 lexer/parser 将我的语言中的表达式转换为抽象语法树 (AST)。 AST 是表达式的正确中间表示。

您可以通过编写遍历 AST 的代码生成器来为您选择的虚拟机或处理器发出字节码或汇编语言指令。

您的更新发生在哪里?

如果是语言基础,你必须同时修改语法和字节码输出。

如果您要优化字节码或移植到新处理器,则必须修改代码生成器。

第一个 lang 编译器可以写在 lang 的 子集 中。而且您只需要一个子集 (bootstrap) 编译器(甚至是 interoreter)。这个可以写成java.

以后可以用lang编写更广泛的编译器。较新的版本也可以。


您甚至可以编写一个将 lang 程序转换为 java 的翻译器,并使用它创建第一个 lang 翻译器,然后将其转换为字节码编译器。

我将从您开发中的两种可能场景来回答这个问题。使用任何 byte-code 语言,您可以随时更新虚拟机或语言。

假设首先您想要更新您的语言以获得新语法或更改当前语义。然后你会保持你当前编译的编译器在 lang(编译器 A​​)中编写并编辑它的源代码以便它可以正确编译你的新功能。然后你使用旧的编译器编译你的编译器给你编译器B。如有必要,您现在可以重写编译器以使用新功能,然后使用编译器 B 编译它,得到编译器 C

如果 JVM 发生变化怎么办?那么在那种情况下,你保留一个旧版本的 JVM,调整你的编译器以应对新的字节码变化,然后用旧版本编译它(这类似于编译器 B从以前)。这将为您提供一个编译为新字节码但在旧 VM 上运行的编译器。下一步是让它自己编译,现在你有一个在新 VM 上运行的新编译器(类似于编译器 C)。