95

我用 C 语言创建了一个编译器(使用 Lex 和 Bison),用于支持循环、函数内部的函数声明、递归调用等的动态类型编程语言。我还创建了一个运行编译器创建的中间代码的虚拟机。

我正在考虑将其编译为 Java 字节码而不是我自己的中间代码。

我看到关于创建 JVM 语言的问题已经被问到了,但是我没有找到非常有用的答案。

所以这是我的问题:

  1. 我想为 JVM 创建一门语言必须阅读JVM 规范书,您还能推荐哪些其他书籍(当然除了 Dragon Book)?我最关心的是有关如何创建 JVM 语言的书籍或教程,而不是一般的编译器。
  2. 有许多 Java 库可以读取、写入和更改.class文件,例如jclasslibbcelgnu bytecode等。您建议使用哪一个?另外,您知道做同样工作的 C 库吗?
  3. 我正在考虑看看另一种针对 JVM 的语言,例如 Clojure、Jython 或 JRuby。但是所有这些语言都非常高级且复杂(为它们创建编译器)。我一直在寻找一种更简单的(我不介意它是未知的还是未使用的)以 JVM 为目标并带有开源编译器的编程语言。有任何想法吗?
4

8 回答 8

64

I would also recommend ASM, but have a look at Jasmin, I used it (or, rather, had to use it) for a university project, and it worked quite well. I wrote a lexer-parser-analyzer-optimizer-generator combination for a programing language using Java and Jasmin, so it was generating JVM Code. I uploaded the code here; the interesting part should be the source code itself. In the folder bytecode/InsanelyFastByteCodeCreator.java, you find a piece of code which transforms an AST Tree into the input format of Jasmin assembler. It is quite straightforward.

The source language (which was transformed to the AST by the lexer-parser-analyzer) is a subset of Java called MiniJava. It lacks some “complicated” features like inheritance, constructors, static methods, private fields and methods. None of those features are difficult to implement, but there was another task to write an x86 backend (so to generate machine assembler), and those things tend to get difficult if you got no JVM which handles some of those things.

In case you wonder about the strange class name: The task of the university project was to transform the AST into an SSA Graph (representing the input code), optimize the graph, and then turn it into Java bytecode. That was about ¾ of the work of the project and the InsanlyFastByteCodeCreator was just a short-cut to test everything.

Have a look at the “Java Virtual Machine” book from Jon Meyer and Troy Downing. This book heavily references the Jasmin Assembler; it’s quite helpful for understanding the JVM internals.

于 2010-08-01T20:35:52.253 回答
16

上学期我参加了“编译器构造”课程。我们的项目正是您想要做的。

我用来编写语言的语言是Scala。它在 JVM 上运行,但支持许多 Java 不支持的高级功能(仍然与纯 Java JVM 完全兼容)。

为了输出 java 字节码,我使用了Scala CAFEBABE library。有据可查,您不必深入了解 Java 类来了解该做什么。

除了这本书,我想你可以通过我们在课程中完成的实验室找到很多信息。

于 2010-08-02T21:10:45.733 回答
5

ASM可以成为生成字节码的解决方案。首先,查看手册中关于生成元素的主题。

于 2010-08-01T02:46:25.990 回答
5

上周末,我问自己同样的问题,将我的玩具语言移植到 JVM。

我只花了几个小时搜索信息,因此请谨慎对待这些参考资料。

  • 语言实现模式。我讨厌antlr,但这本书看起来很不错。如果你也不喜欢 antlr,有一个很好的关于解析的“Parsing Techniques. A Practical Guide”。

    学习构建配置文件阅读器、数据阅读器、模型驱动的代码生成器、源代码到源代码的翻译器、源代码分析器和解释器。您不需要计算机科学背景——ANTLR 的创建者 Terence Parr 通过将语言实现分解为最常见的设计模式来揭开它的神秘面纱。模式一个模式,您将学习实现自己的计算机语言所需的关键技能。

    第 10 章涵盖 30 页(以快速 IMO)这个主题。但是还有其他章节可能您会感兴趣。

    • 10 构建字节码解释器
      • 10.1 编程字节码解释器。.
      • 10.2 定义汇编语言语法
      • 10.3 字节码机器架构。. . . .
      • 10.4 从这里去哪里。. . . . . . . . .
      • 第 26 页。字节码汇编器。. . . . . . . . . .
      • 第 27 页。基于堆栈的字节码解释器。. .
      • 第 28 页。基于寄存器的字节码解释器
      http://pragprog.com/titles/tpdsl/language-implementation-patterns
    • Lua 5.0 的实现这是一篇关于基于寄存器的字节码机器的好论文。即使是为了它,也要阅读它。

    • Lisp 小片段。这本书教如何编写 2 个编译为 C 的 schme 编译器。从这本书中可以学到很多教训。我拥有这本书的副本,对于任何有趣的是 lisp 的人来说,这真的很好,但也许不是你的那杯茶。

      这是对整个 Lisp 语言家族(即 Lisp、Scheme 和相关方言)的语义和实现的全面说明。它描述了 11 个解释器和 2 个编译器......

    http://www.amazon.com/Lisp-Small-Pieces-Christian-Queinnec/dp/0521562473

检查基于寄存器的虚拟机 Dalvik7 虚拟机。DVM 对从 Java 编译器编译的 Java 类文件转换而来的字节码进行操作。

有一个关于该主题的邮件列表,jvm-languages。

您打算将代码上传到任何地方吗?我想看看。

于 2010-08-03T18:13:48.143 回答
4

我想看看另一种针对 JVM 的语言,比如 Clojure、Jython 或 JRuby。但是所有这些语言都非常高级且复杂(为它们创建编译器)。

建议:你可以看看Lua Programming Language,有它的 JVM 实现,比如LuaJ

为 J2ME 和 J2SE 编写的轻量级、快速、以 Java 为中心的 Lua 解释器,具有基本、字符串、表、包、数学、io、os、调试和协程包的库、编译器、luajava 绑定和 JSR-233 可插入脚本引擎绑定。

(不要与使用带有 JNI 方法的本机库的 LuaJava 混淆。)

于 2010-08-01T20:53:22.853 回答
2

如果您还不知道,我建议您首先了解 JVM 汇编的工作原理。

许多指令的形式是?name,其中?i指令是否适用于整数类型以及a是否适用于引用类型。

基本上,JVM 是一个没有寄存器的堆栈机器,因此所有指令都直接在堆栈上处理数据。您可以?push/?pop使用?store/?load. 其他一些重要的指令是invoke???if_???

对于我大学的编译器课程,我们使用Jasmin来组装程序。我不知道这是否是最好的方法,但至少这是一个容易开始的地方。

这是旧版本 JVM 的指令参考,其中包含的指令可能比新版本少。

于 2010-08-03T17:36:26.547 回答
1

当然曾经可以用Java写一门新的语言。使用 Java 反射 API,您可以实现很多目标。如果速度不太重要,我会优先考虑 Java 而不是 ASM。Java (恕我直言)中的编程更容易且不易出错。看看 RPN 语言7th。它完全是用 Java 编写的。

于 2018-07-09T20:46:27.877 回答
0

首先我会退后一步,修改我的编译器以输出实际的 Java 而不是 Java 字节码(这意味着创建比编译器更多的翻译器),并使用任何方便的 Java 环境编译 Java 输出(这可能会生成更好的目标代码比我自己的编译器)。

您可以使用相同的技术(例如,编译为 C#)来生成 CLI 字节代码,或者编译为 Pascal 以生成 P 代码等。

目前尚不清楚您为什么要考虑使用 Java 代码而不是使用自己的 VM,但如果是为了性能,那么您当然也应该考虑编译为实际的机器代码。

于 2010-08-04T20:28:04.893 回答