我在C中创建了一个编译器(使用lex& bison),用于支持循环,函数内部函数声明,递归调用等动态类型编程语言。我还创建了一个运行由中间代码创建的虚拟机。编译器。
我现在正在思考而不是编译到我自己的中间代码,将其编译为java字节代码。
我看到有关创建JVM语言的问题已经asked,但我找不到答案非常有用。
所以这是我的问题:
答案 0 :(得分:58)
我也会推荐ASM,但看看Jasmin,我用它(或者:必须使用它)进行大学项目,它运作得很好,我写了一个lexer / parse /分析器/优化器/生成器组合,用于使用java和jasmin编程语言,因此生成JVM代码。我上传了代码here,有趣的部分应该是source-code itself。在文件夹“bytecode / InsanelyFastByteCodeCreator.java”中,您可以找到一组代码,它将AST树转换为jasmin汇编器的输入格式。很直接。
源语言(由Lexer + Parser + Analyzer转换为AST)是Java的一个子集,称为MiniJava。它缺少一些“复杂”的功能,如继承,构造函数,静态方法,私有字段/方法。这些功能都不难实现,但是编写X86后端还有另外一个任务(所以生成机器组装器),如果你没有处理某些东西的JVM,这些事情往往会变得困难。
如果您想知道奇怪的类名:大学项目的任务是将AST转换为aa SSA图形(这是一个表示输入代码的图形),然后优化图形和然后将图形转换为java字节代码。这大约是项目工作的3/4,而InsanlyFastByteCodeCreator只是测试一切的捷径。
查看Jon Meyer和Troy Downing撰写的“Java虚拟机”一书。本书大量引用了Jasmin-Assembler,它对理解JVM内部结构很有帮助。
答案 1 :(得分:10)
上学期我参加了“编译器构建”课程。我们的项目正是您想要做的。
我用来写我的语言的语言是Scala。它在JVM上运行,但支持Java没有的许多高级功能(仍然与纯Java JVM完全兼容)。
要输出java字节码,我使用了Scala CAFEBABE library。记录良好,您不必深入了解Java类以了解该做什么。
除了这本书之外,我认为你可以通过我们在课程中所做的labs找到很多信息。
答案 2 :(得分:4)
答案 3 :(得分:3)
我正想着看看也许吧 另一种针对JVM的语言 像Clojure,Jython或JRuby。但是所有 这些语言水平很高 和复杂(创建一个编译器 他们)。
建议:您可以查看Lua Programming Language,其中有JVM实现,如LuaJ。
轻量级,快速,以Java为中心的Lua 为J2ME和J2SE编写的解释器, 用于基本的库,字符串, 表,包,数学,io,操作系统,调试 和coroutine包,编译器, luajava绑定和JSR-233 可插入的脚本引擎绑定。
(不要与使用JNI方法的本地库的LuaJava混淆。)
答案 4 :(得分:2)
上周末,我问自己同样的问题,将我的玩具语言移植到JVM。
我只花了几个小时搜索信息,所以请参考这些参考文献。
语言实施模式。 我讨厌antlr,但这本书看起来非常好。如果你不喜欢antlr,那么解析“解析技术。实用指南”是非常好的。
学习构建配置文件读取器,数据读取器,模型驱动的代码生成器,源到源转换器,源分析器和解释器。您不需要计算机科学背景 - ANTLR创建者Terence Parr通过将其分解为最常见的设计模式来揭开语言实现的神秘面纱。按模式模式,您将学习实现自己的计算机语言所需的关键技能。
第10章涵盖30页(快速IMO)这个主题。但是还有其他章节可能你会感兴趣。
- 10 Building Bytecode口译员
http://pragprog.com/titles/tpdsl/language-implementation-patterns
- 10.1编程字节码解释器。
- 10.2定义汇编语言语法
- 10.3字节码机器结构。 。 。 。
- 10.4从这里开始。 。 。 。 。 。 。 。 。
- P.26。字节码汇编程序。 。 。 。 。 。 。 。 。 。
- P.27。基于堆栈的字节码解释器。 。
- P.28。基于注册的字节码解释器
Lua 5.0的实施这是一篇关于注册的好文章 - 基于字节码的机器。即使是为了它,也要阅读它。
Lisp in Small Pieces。这本书教授如何编写一个编译为C的2个schme编译器。从本书可以学到很多课程。我拥有这本书的副本,这对任何有趣的人来说都是非常好的,但也许不是你的一杯茶。
这是对Lisp,Scheme和相关方言的整个Lisp语言系列的语义和实现的综合描述。它描述了11个口译员和2个编译器......
http://www.amazon.com/Lisp-Small-Pieces-Christian-Queinnec/dp/0521562473
检查Dalvik7 VM,这是一个基于寄存器的VM。 DVM对从Java编译器编译的Java类文件转换的字节码进行操作。
有一个关于这个主题的邮件列表,jvm-languages。
您打算将代码上传到任何地方吗?我想看看。
答案 5 :(得分:1)
我建议您首先了解JVM程序集的工作原理,如果您还不知道的话。
许多说明的格式为?name
,如果指令适用于整数类型,则?
为i
;如果适用于引用类型,则为a
。< / p>
基本上,JVM是没有寄存器的堆栈机器,因此所有指令都直接在堆栈上处理数据。您可以使用?push/?pop
来推送/弹出数据,并使用?store/?load
在局部变量(由偏移引用的堆栈位置)和堆栈顶部之间移动数据。其他一些重要说明是invoke???
和if_???
。
对于my university's compiler course,我们使用Jasmin来汇编程序。我不知道这是不是最好的方法,但至少它是一个容易开始的地方。
Here is an instruction reference用于旧版本的JVM,其中可能包含的指令少于新版本。
答案 6 :(得分:1)
开头的最佳资源可能是Ola Bini's presentation。抓住幻灯片。
答案 7 :(得分:0)
首先,我退出,修改我的编译器以输出实际的Java而不是Java字节代码(这意味着创建更多的翻译器而不是编译器),并使用任何方便的Java环境编译Java输出(这可能会生成比我自己的编译器更好的目标代码。)
您可以使用相同的技术(例如,编译为C#)来生成CLI字节代码,或者编译为Pascal以生成P代码等。
目前尚不清楚为什么要考虑使用Java代码而不是使用自己的VM,但如果是为了提高性能,那么您当然也应该考虑编译实际的机器代码。
答案 8 :(得分:0)
当然曾经可以使用Java编写新语言。使用Java Reflection-API,您可以实现一个llot。如果速度不太重要,我将优先选择Java而不是ASM。在Java (IMHO)中,编程更加容易,而且不易出错。看看RPN语言7th。 它完全用Java编写。