34

当前的 F# 编译器是用 F# 编写的,是开源的,可以在 .Net 和 Mono 上运行,允许它在包括 Windows、Mac 和 Linux 在内的许多平台上执行。F# 的代码引用机制已用于在WebSharperPitFunScript等项目中将 F# 编译为 JavaScript 。似乎也有人对在JVM 上运行 F# 代码感兴趣。

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

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

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

6 回答 6

12

可能应该考虑的另一个选项是将 .NET CLR 字节码转换为 JVM 字节码,就像http://www.ikvm.net对 JVM > CLR 字节码所做的那样。虽然这种做法已经被峡湾所有者考虑过并拒绝了

使用选项 1) 从顶部获得支持,并让 F# 编译器团队拥有可插入的后端,理论上可以发出 Java 字节码声音,就像它会产生最完美的解决方案一样。

但是,如果您查看已移植到不同平台的其他语言,情况很少见。大多数时候,它是从头开始重写的。但这也可能是由于原始语言团队本身对支持替代平台不感兴趣,并且原始主机实现可能无法支持多个后端,而且这已经太慢了,无法成为一个可行的选择.

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

于 2013-03-31T17:09:26.083 回答
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 没有实现尾调用。他们当然有这样做的才能和资金——他们没有的事实告诉我很多关于在 JVM 上进行 TCO 的实用性。对于我们的 .NET->JavaScript 端口,我可能会走类似的路线 - 没有 TCO 保证,除非您特别要求蹦床,这将工作但会花费您一个数量级(或两个)的性能。

于 2013-04-01T21:53:44.900 回答
9

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

于 2013-03-31T17:22:06.017 回答
8

我怀疑任何方法都会做很多工作,但我认为您的第一个建议是唯一可以避免引入大量额外不兼容性和错误的建议。编译器非常复杂,并且有很多关于重载解析等的极端情况(并且规范可能也有差距),因此新实现似乎不太可能具有一致兼容的语义。

于 2013-03-31T16:52:03.030 回答
1

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

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

我可能会选择第一种方式,因为这是唯一能让新编译器与 .net F# 编译器保持同步的方法。

fjord 项目似乎正在尝试用 Java 从头开始​​重新编写 F# 编译器?

这当然是最不优雅的方法,恕我直言。

还有什么?

编译器完成后,您将剩下 90% 的工作要做。

例如,不太了解 F#,但我认为使用任何 .NET 库都很容易。这意味着,基本问题是以某种方式移植 .NET 生态系统。

于 2013-04-02T14:11:24.027 回答
0

我一直在寻找类似的东西,尽管它更像是 F# 到 Akka 的翻译器/编译器。就 F# -> JVM 而言,我遇到了两个不太适合生产的选项:

  1. F# -> [Fjord][1] -> JVM.

  2. F# -> [Funscript][2] -> [Vert.X][3] -> JVM
于 2013-12-01T14:23:35.760 回答