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

什么';构建在JVM上运行并生成Java字节码的F#编译器的最简单方法是什么?,f#,jvm,ocaml,yeti,funscript,F#,Jvm,Ocaml,Yeti,Funscript,当前的F#编译器是用F#编写的,是开源的,运行在.Net和Mono上,允许它在许多平台上执行,包括Windows、Mac和Linux。F#的机制已被用于将F#编译为JavaScript的项目,如、和。人们似乎也对跑步感兴趣 我相信F#编译器最初使用的是一个版本的 如果有人想构建一个在JVM上运行的F#编译器,那么: 修改现有的F#编译器以发出,然后用它编译F#编译器 使用基于JVM的ML编译器,比如在JVM上引导最小的F#编译器 当项目似乎正在尝试时,用Java从头开始重新编写F#编译器 还有别

当前的F#编译器是用F#编写的,是开源的,运行在.Net和Mono上,允许它在许多平台上执行,包括Windows、Mac和Linux。F#的机制已被用于将F#编译为JavaScript的项目,如、和。人们似乎也对跑步感兴趣

我相信F#编译器最初使用的是一个版本的

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

  • 修改现有的F#编译器以发出,然后用它编译F#编译器
  • 使用基于JVM的ML编译器,比如在JVM上引导最小的F#编译器
  • 当项目似乎正在尝试时,用Java从头开始重新编写F#编译器
  • 还有别的吗

  • 我怀疑任何方法都需要大量的工作,但我认为您的第一个建议是唯一可以避免引入大量额外的不兼容性和bug的方法。编译器相当复杂,在重载解析等方面有很多特殊情况(规范可能也有漏洞),因此,新的实现似乎不太可能具有一致的兼容语义。

    另一个可能应该考虑的选项是将.NET CLR字节码转换为JVM字节码,就像JVM>CLR字节码一样。尽管这种方法已经被广泛采用

    让F#编译器团队拥有可插拔的后端,理论上可以发出Java字节码的声音,就像产生最完美的解决方案一样

    但是,如果你看看其他已经移植到不同平台的语言,这种情况很少发生。大多数时候,它都是从头重写的。但这也可能是因为最初的语言团队对支持替代平台本身没有兴趣,而且最初的主机实现可能无法支持多个后端,而且它已经太慢,无法作为一个可行的选项开始


    我的直觉是,从头开始重新编写代码,并能够从原始实现中尽可能多地实现代码共享和自动化。例如,如果测试套件可以在两种实现中重复使用,那么将减轻JVM端口的负担,并在确保语言奇偶性方面大有帮助。

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

    如果我真的必须这样做,我可能会从#1方法开始—将JVM后端添加到现有编译器中。但我也会尝试为不同的目标VM辩护

    引用语不是很相关——作为WebSharper的作者,我可以向你保证,虽然引用语可以为你提供一种很好的类似F#的编程语言,但它们是限制性的,并且没有经过优化。我想,对于潜在的JVM F#用户来说,标准会高得多——完全的语言兼容性和可比的性能。这很难

    以尾部呼叫为例。在WebSharper中,我们应用启发式优化JavaScript中对循环的一些局部尾部调用,但这还不够——一般来说,您不能像在一般F#库中那样依赖TCO。这对于WebSharper来说是可以的,因为我们的用户不希望有完整的F#,但对于JVM F#端口来说是不可以的。我相信大多数JVM实现都不会实现TCO,因此它必须通过一些间接的方式来实现,从而导致性能下降

    @mythz提到的字节码重新编译方法听起来非常有吸引力,因为它不仅允许移植F#,而且允许将更多的.NET软件移植到JVM。我在一个内部WebSharper3.0项目中进行了大量的.NET字节码分析工作——我们正在考虑将.NET字节码而不是F#引号编译为JavaScript的选项。但也存在巨大的挑战:

  • BCL中的许多代码都是不透明的(本机的),您无法对其进行反编译

  • 泛型模型相当复杂。我已经实现了一个JavaScript运行时,它以一定的精度和合理的性能对类和方法泛型、实例化、类型生成和基本反射进行建模。这在带有闭包的动态JavaScript中已经够难了,而且在JVM上似乎很难以一种高性能的方式实现——但也许我没有看到一个简单的解决方案

  • 值类型在字节码中造成了严重的复杂性。我还没有为WebSharper3.0解决这个问题。它们也不能被忽略,因为它们被许多需要移植的库广泛使用

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

  • 此外,字节码方法并没有消除关于如何实现尾部调用的问题。好吧,Scala不实现tailcall。他们当然有这样做的天赋和资金——事实上他们没有,这告诉我在JVM上进行TCO有多实际。对于我们的.NET->JavaScript端口,我可能会采用类似的方法-除非您特别要求蹦床,否则不会保证TCO,因为蹦床会起作用,但会使性能降低一个数量级(或两个数量级)

    修改现有的F#编译器以发出Java字节码,然后用它编译F#编译器? 使用基于JVM的ML编译器(如Yeti)在JVM上引导最小的F#编译器

    如果编译器是用F#编写的,那么移植它应该不会那么困难

    我可能会走第一条路,因为这是唯一的希望
      1. F# -> [Fjord][1] -> JVM.
    
      2. F# -> [Funscript][2] -> [Vert.X][3] -> JVM