构建在JVM上运行并生成Java字节码的F#编译器的最简单方法是什么?

Phi*_*ord 33 f# ocaml jvm yeti funscript

目前的F#编译器是用F#编写的,是开源的,可以在.Net和Mono上运行,允许它在许多平台上运行,包括Windows,Mac和Linux.F#的Code Quotations机制已用于在WebSharper,PitFunScript等项目中将F#编译为JavaScript .在JVM上运行F#代码似乎也有一些兴趣.

我相信OCaml编译器的一个版本最初用于引导 F#编译器.

如果有人想构建一个在JVM上运行的F#编译器,那么更容易:

  1. 修改现有的F#编译器以发出Java字节码,然后用它编译F#编译器?
  2. 使用像Yeti这样的基于JVM的ML编译器来引导JVM上的最小F#编译器?
  3. fjord项目似乎正在尝试时,在Java中从头开始重写F#编译器?
  4. 别的什么?

myt*_*thz 12

应该考虑的另一个选择是将.NET CLR字节代码转换为JVM字节代码,如http://www.ikvm.net,使用JVM> CLR字节代码.虽然这种方法已被峡湾所有者考虑和驳回.

通过选项1)从顶部获得支持并让F#编译器团队具有可插拔的后端,理论上可以发出Java字节码声音,就像它会产生最精确的解决方案一样.

但是,如果你看一下移植到不同平台的其他语言,这种情况很少发生.大部分时间都是从头开始重写.但这也可能是由于原始语言团队本身并不感兴趣支持替代平台,并且原始主机实现可能无法支持多个后端,而且这已经太慢了,因此开始时这可能是一个可行的选择. .

我的预感是从头开始重写并能够从原始实现中尽可能多地进行代码共享和自动化.例如,如果测试套件可以在两个实现中重复使用,那么JVM端口将承担很多负担并且在确保语言奇偶校验方面有很长的路要走.


t0y*_*yv0 12

如果我真的必须这样做,我可能会从#1方法开始 - 将JVM后端添加到现有编译器.但我也会尝试争论不同的目标虚拟机.

引用不是很相关 - 作为WebSharper的作者,我可以向你保证,虽然引用可以为你提供一个很好的F#语言来编程,但它们是限制性的,而不是优化的.我想,对于潜在的JVM F#用户来说,这个标准要高得多 - 完全语言兼容性和可比性能.这很难.

举个尾巴电话.在WebSharper中,我们应用启发式来优化JavaScript中对循环的一些本地尾调用,但这还不够 - 你通常不能像通常的F#库那样依赖TCO.这对于WebSharper来说没问题,因为我们的用户不希望有完整的F#,但是对于JVM F#端口来说也不行.我相信大多数JVM实现都没有进行TCO,所以它必须通过一些间接实现,从而引入性能损失.

@mythz提到的字节码重新编译方法听起来非常有吸引力,因为它不仅可以移植F# - 理想情况下它允许将更多.NET软件移植到JVM.我在内部WebSharper 3.0项目上使用.NET字节码分析工作了很多 - 我们正在考虑编译.NET字节码而不是F#引用JavaScript的选项.但那里面临着巨大的挑战:

  1. BCL中的很多代码都是不透明的(本机的) - 你无法反编译它

  2. 泛型模型相当复杂.我已经实现了一个JavaScript运行时,它以一些精确和合理的性能对类和方法泛型,实例化,类型生成和基本反射进行建模.这在带有闭包的动态JavaScript中很难实现,并且在JVM上以高效的方式执行起来似乎很难 - 但也许我只是看不到简单的解决方案.

  3. 值类型在字节码中产生了明显的复杂性.我还没有为WebSharper 3.0找到这个.它们也不容忽视,因为它们被许多想要移植的库广泛使用.

  4. 类似地,在许多现实世界的.NET库中使用基本反射 - 根据大量本机代码和对泛型和值类型的适当支持,交叉编译是一场噩梦.

此外,字节码方法不会删除有关如何实现尾调用的问题.AFAIK,Scala没有实现tailcalls.他们肯定有这方面的才能和资金 - 事实上他们不这样做,告诉我很多关于在JVM上做TCO的实际可行性.对于我们的.NET-> JavaScript端口,我可能会采用类似的方法 - 没有TCO保证,除非您特别要求进行蹦床,但这会使您的性能降低一个数量级(或两个).


gas*_*che 9

有一个项目将OCaml编译到JVM,OCaml-Java:它非常完整,特别是可以编译OCaml的编译器(用OCaml编写)源代码.我不确定你感兴趣的F#语言的哪些方面,但是如果你主要想要为JVM提供一个成熟的严格类型的函数语言,这可能是一个不错的选择.


kvb*_*kvb 8

我怀疑任何方法都会有很多工作,但我认为你的第一个建议是唯一一个避免引入大量额外不兼容性和错误的建议.编译器非常复杂,并且在重载决策等方面存在许多极端情况(并且规范也可能存在间隙),因此新实现似乎不太可能具有一致的语义兼容性.