【问题标题】:Output language/format for toy compiler玩具编译器的输出语言/格式
【发布时间】:2012-05-15 11:21:50
【问题描述】:

我在大学里学习了编译器课程,它内容丰富且很有趣,虽然也有很多工作。由于我们获得了要实现的语言规范,因此我没有学到太多的一件事是语言设计。我现在正在考虑创建一种简单的玩具语言来获得乐趣,这样我就可以四处玩耍并尝试不同的语言设计原则。

我尚未决定的一件事是我希望我的编译器输出什么语言或格式。理想情况下,我想为易于使用且具有一些调试功能的虚拟机输出字节码(例如,能够暂停执行并随时查看堆栈。)我还没有找到一个令人震惊的不过,我还看中。为了让您了解我在寻找什么,以下是我考虑过的一些选项,以及我所看到的它们的优缺点:

  • 我可以输出文本 x86 汇编语言,然后调用像 NASM 或 FASM 这样的汇编程序。这会给我一些为实际硬件编译的经验,因为我之前的编译器工作是在 VM 上完成的。我可能可以使用 gdb 调试生成的程序,尽管它可能不像使用具有调试支持的 VM 那样简单。这样做的主要缺点是我对 x86 汇编的经验有限,而且作为 CISC 指令集,这有点令人生畏。

  • 我可以为流行的虚拟机输出字节码,比如 JVM 或 Lua 虚拟机。这些的优缺点可能会根据我选择的特定 VM 而有所不同,但总的来说,我在这里看到的缺点可能是必须学习可能对我未来项目的适用性有限的字节码。我也不确定哪个 VM 最适合我的需求。

  • 我可以使用我的编译器课程中使用的同一 VM, 这是我的大学专门为此目的设计的。我已经熟悉它的设计和指令集,并且它具有不错的调试功能,所以这是一个巨大的优势。但是,它的功能非常有限,我觉得如果我尝试做任何中等程度的高级操作,我很快就会遇到这些限制。

  • 我可以使用 LLVM 并输出 LLVM Intermediate Representation LLVM IR 似乎非常强大,熟悉它肯定对我将来有用。另一方面,我真的不知道使用和调试有多容易,因此我非常感谢在该领域有经验的人提供的建议。

  • 我可以设计和实现我自己的虚拟机。这有一个巨大而明显的缺点:我实际上是将我的项目变成两个项目,大大降低了我实际完成任何事情的可能性。然而,它仍然有点吸引人,因为它可以让我制作一个对我想要的语言功能具有“一流”支持的 VM——例如,Lua VM 对表具有一流的支持,这使得它很容易在 Lua 字节码中使用它们。

所以,总而言之,我正在寻找一个我可以定位的 VM 或汇编器,它相对容易学习和使用,并且易于调试。由于这是一个爱好项目,理想情况下,我还想尽量减少我花大量时间学习一些我永远不会再使用的工具或语言的机会。不过,我希望从这个练习中获得的主要内容是对语言设计的复杂性有一些第一手的了解,所以任何有助于相对快速实现的东西都会很棒。

【问题讨论】:

  • 如果您更改了代码生成,一个好的编译器设计将允许您将 IR 转换为任何东西。我将首先将您的语言转换为某种 IR,然后创建一个将其转换为 C\C++ 的后端。这样您就可以了解编译器的不同组件,而不必担心在 asm 或字节码中验证一些低级语言结构。

标签: assembly compiler-construction language-design vm-implementation


【解决方案1】:

如果您只是在玩语言设计,那么解释语言呢?让整个 AST 在运行时仍然存在可以让您做一些非常酷的事情。

【讨论】:

    【解决方案2】:

    看看我的Programming Languages ZOO。它有许多语言的玩具实现,包括一些虚拟机和组成的程序集(堆栈机器)。它应该可以帮助您入门。

    【讨论】:

    • 这不是完全破坏了乐趣因素吗?你无法通过复制别人的编译器来获得人机交互的快感。
    • 我从来没有说过他应该复制它,但是重新发明轮子有什么意义呢?这些实现非常短,大​​约 500 行,包括很多 cmets。它们不是真正的编程语言。
    • 我觉得这些都很棒!除了简单地掌握我认为相当广泛的范式和原则外,我在语言设计方面完全没有经验,我当然不期望在我第一次尝试时发明任何完全新颖的东西。我更感兴趣的是玩弄不同的想法,看看哪些想​​法很好地融合在一起,看看实现它们需要什么。为此,我认为这些示例可能会很有帮助。谢谢,安德烈!
    • @Hans Passant:您的问题到底是什么?如果 OP 认为重新发明 50 年的编程语言经验很有趣,他就不必看其他人做了什么,也不必使用 Internet。 PL Zoo 是一个有用的资源,因为它展示了有关编程语言设计的基本要点:如何实现闭包,如何将函数式语言转换为字节码,将命令式语言转换为堆栈机器,如何惰性评估,如何实现类型推断,如何实现记录子类型化,如何实现prolog风格的搜索等
    • 绝对很棒的资源!杰出的!老实说,ML 也很漂亮。喜欢它。
    【解决方案3】:

    这实际上取决于您想要构建的语言有多完整,以及您想用它做什么。如果您想为与其他语言交互的实际项目创建一种成熟的语言,那么您的需求将远远大于您只想尝试编译特定语言功能的复杂性。

    输出到汇编语言文件是一种流行的选择。您可以使用程序中的实际代码(在 cmets 中)对汇编语言文件进行注释。这样,您可以准确地看到您的编译器对每种语言结构做了什么。可能(自从我使用这些工具以来已经有很长时间了)以使源代码级调试成为可能的方式对 ASM 文件进行注释。

    如果您打算从事语言设计工作,那么您几乎肯定需要了解 x86 汇编语言。因此,您花在学习上的时间不会被浪费。 CISC指令集真的不是问题。如果您已经使用过其他一些汇编语言(您似乎已经使用过),那么您将需要几个小时的学习时间来了解寄存器和不同的寻址模式,并且可能不到一周的时间就可以熟练掌握。

    为 JVM、lua 或 .NET 输出字节码是另一种合理的方法,但如果这样做,您就会将自己与 VM 所做的假设联系在一起。而且,正如您所说,这将需要对 VM 有详细的了解。任何流行的 VM 都可能具有您需要的功能,因此选择实际上是一个偏好问题,而不是功能问题。

    LLVM 是一个不错的选择。它功能强大并且越来越受欢迎。如果您输出 LLVM IR,您更有可能与他人的代码交互,并让他们的代码与您的交互。如果您想在编译器或语言设计领域找到一份工作,那么了解 LLVM 的工作原理无疑是一个加分项。

    在您对其他虚拟机有更多经验之前,我不建议您设计和实施您自己的虚拟机,这样您就可以看到并理解他们在实施中所做的权衡。如果你沿着这条路走下去,你最终会学习 JVM、lua、.NET 和许多其他 VM。我并不是说不要这样做,而是这样做会让你偏离探索语言设计的既定目的。

    知识很少是无用的。无论您决定使用什么,都需要您学习新事物。这一切都很好。但是,如果您想专注语言设计,请选择需要最少工作量的输出格式,而不是专门的语言设计。当然,与功能一致。

    在您的选择中,在我看来,您大学的虚拟机已失效。我会说设计自己的虚拟机也已经过时了。在其他三个中,我可能会选择 LLVM。但是,我对 x86 汇编非常熟悉,所以学习 LLVM 的想法有点吸引人。

    【讨论】:

    • 感谢您非常彻底的回复!我现在非常倾向于 LLVM IR。稍后我可能会考虑单独做我自己的 x86 后端。我不打算从事语言设计或编译器方面的专业工作,但我认为 x86 汇编对于任何程序员来说都是很有价值的知识。
    猜你喜欢
    • 1970-01-01
    • 2012-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多