it-swarm.cn

为什么没有从一种编程语言到另一种语言的自动翻译器?

大多数编程语言都是图灵完整的,这意味着可以用一种语言解决的任何任务都可以用另一种语言解决,甚至可以在图灵机上解决。那么为什么没有自动翻译器可以将程序从任何给定语言转换为任何其他语言呢?我已经看到了几种语言的几种尝试,但是它们总是只能在一种语言的有限子集上工作,并且几乎不能用于转换实际项目。

至少在理论上,是否有可能在所有语言之间编写100%正确的翻译器?实践中有哪些挑战?是否有现有的翻译人员在工作?

37
serg

最大的问题不是程序代码的实际翻译,而是平台API的移植。

考虑一个PHP到Java转换器。在不嵌入PHP二进制文件的一部分的情况下,唯一可行的方法是用Java重新实现所有PHP模块和API。这涉及实现超过10.000个功能。与之相比,实际翻译语法的工作很容易。甚至在完成所有工作后,您将没有Java代码,您也会遇到某种怪异的事情,它们恰好在Java平台上运行,但是结构类似于PHP放在里面。

这就是为什么想到的唯一此类工具都是翻译代码以进行部署而不是事后维护的原因。 Google的GWT将Java编译为JavaScript。 Facebook的hiphop将PHP编译为C。

32
Joeri Sebrechts

如果您有中间格式,则可以实现将语言X转换为格式的程序,以及from转换为语言Y。对所有您感兴趣并完成的语言进行转换,对吗?

好吧,你知道吗?这样的格式已经存在:程序集。编译器已经执行了“从X到汇编语言”的转换,并已将反汇编器转换为“从Y汇编语言”的转换。

现在,Assembly并不是进行反向转换的好语言,但是MSIL实际上并不是那么糟糕。下载 Reflector ,您将看到可以将.NET程序集反汇编为多种不同语言的选项(插件提供了更多选择)。因此,很有可能使用C#编写程序,将其编译为DLL(即MSIL),然后使用反射器将其反汇编为VB,C++/CLI,F#和整个当然还有其他所有转换工作,例如,将F#文件转换为DLL,然后使用Reflector将其转换为C#。

当然,您会发现两个大问题:

  1. 该代码基本上是不可读的。 MSIL(即使包含调试信息)也从原始源中删除了大量信息,因此翻译后的版本没有100%的保真度(理论上,执行C#-> MSIL-> C#转换应将原始代码带回您,但是惯于)。
  2. 许多.NET语言都有自己的自定义库(例如VB运行时库,F#库等)。在进行转换时,也需要包含(或转换)这些库。

确实没有什么可以绕过#2的,但是您可能可以绕过#1并在MSIL中添加一些其他注释(也许通过属性)。当然,那将是额外的工作。

20
Dean Harding

至少在理论上,是否有可能在所有语言之间编写100%正确的翻译器?实践中有哪些挑战?

  • 总是可以从结构更丰富的语言转换为仍然是图灵完整的结构更简单的语言。
    • 应该从严格的技术意义上看待这种主张:这意味着翻译后的程序在执行时将产生完全相同的结果。
    • 关于翻译后代码的可读性或原始程序结构的保留,没有任何暗示。
  • 可以从结构较少的语言转换为结构较深的语言,但是翻译后的代码将保持其结构较少的形式。
20
rwong

为什么要转换程序?

无论哪种语言,无论是源语言还是目标语言,都将被编译为(虚拟)机器代码*,因此出于技术原因,无需使用另一种高级语言的编译器。

语言是人类的语言。 因此,您的问题的隐含要求是:“为什么没有翻译器生成可读代码”,而答案可能是(imho):因为如果有两种语言完全不同,那么“可读代码”的编写方式就会有所不同,不仅需要翻译算法,而且采用不同的算法。

例如,比较一个典型的C迭代和一个LISP的迭代。或Python是惯用Ruby的“最佳方法”。

在这里,用真实的语言开始出现同样的问题,例如,当将英语翻译为德语时,将“正在下雨的猫和狗”翻译成意思是“就像从水桶里倾泻一样”,不再逐字逐字翻译,但您必须寻找意义。

而且“含义”并不是一个容易理解的概念。

*)好吧,有咖啡脚本...

10
keppla

从理论上讲这是可能的,但几乎没有用。源语言和目标语言几乎可以任意组合,但是在大多数情况下,没有人会想要查看或使用结果。

相当多的编译器确实针对C,这是因为C编译器几乎可用于所有存在的平台(并且有自动编译器生成器可以让您设计处理器,并自动生成针对您的新处理器的C编译器)。当然,还有许多针对各种虚拟机(例如.NET,JVM,C--和LLVM)使用的语言的实现。

但是,关键点是,仅当您将目标视为基本上是仅在编译过程中用作步骤的汇编语言时,它才真正有用。特别是,您通常not希望普通程序员读取或处理该结果;它通常不会很可读。

6
Jerry Coffin

FWIW,有一个从Java到D的翻译器。它被称为 TioPort 将SWT移植到D。它遇到的主要问题是,有必要移植Java)标准库的大部分。

5
dsimcha

语言工作台 本身不是代码翻译,但它说明了如何实现类似于所有语言之间100%正确的翻译器的功能。

在我们当前的方法中,源代码以文本格式存储。在编译期间,这些人类可读的文本文件被解析为抽象语法树表示形式,该语法树表示形式又用于生成字节码或机器代码。但是,此抽象表示是临时的,对于编译器而言是内部的。

在语言工作台方法中,类似的抽象语法树表示形式是永久性存储的工件。机器代码和文本“源”代码都是基于此抽象表示生成的。这种方法的后果之一是程序的抽象表示实际上与语言无关,并且可以用来生成任何已实现语言的文本代码。这意味着一个人可以使用他们认为最合适的任何一种语言自由地在系统的不同方面进行工作,或者团队的每个成员都可以使用他们最熟悉的语言来从事共享项目。

据我所知,该技术仍无法在主流开发中使用,但是有数个小组在独立开发该技术。很难说他们中的任何一个是否能兑现诺言,但是看到这种情况会很有趣。

4
scrwtp

are一些自动翻译器。如果您的目标是生成可编译的代码,而不是可读的代码,则很有可能并且偶尔有用,只是很少使用。著名的是,第一个C++编译器实际上不是编译器,而是将C++转换为(确实很复杂的)C源代码,然后由C编译器编译。许多编译器可以根据请求生成汇编代码-但是,除了吐出汇编文本然后将其翻译为机器代码外,它们通常可以直接生成机器代码。

给定语言A的完整规范,原则上编写用某种语言B表示其指令的程序并不难。但是通常遇到麻烦的人都会为“语言B”选择非常低级的东西:机器代码,或最近的字节码:Jython是python的实现,它生成Java字节码,由Java = VM。无需费心写出和编译Java类层次结构!

4
alexis

这一直都在做。

每个编译器都会将“主要语言”(如C++)翻译到机器的本机汇编语言或就解释语言而言是与体系结构无关的字节码。

我想那不是你在说什么。您可能想要一个将C++转换为Java或Python)的转换器。但是,这样做的目的是什么?充其量,最终结果将具有与原始源完全相同的效率。实际上,情况会更糟。)

如果您只想翻译代码,以便以您理解的语言来阅读代码,那么这种翻译器将具有与预期效果相反的效果。您将获得大量的含糊不清,不直观和不可读的代码。

这是因为只有最琐碎的事物才能直接从一种语言翻译成另一种语言。通常,一种语言的简单性需要另一种语言的大量库-或完全不可能。因此:

  1. 如果程序很简单,您可能会得到不错的结果。但是,如果那么简单,那么通过翻译器运行它又有什么意义呢?
  2. 如果程序不平凡,则代码的质量将很低。

最后,编写好的代码的唯一方法是实际编写代码。在可读性,最佳实践和优雅的解决方案上,计算机根本无法(至少目前还不能)与人类相提并论。

简而言之,这不值得。

3
Maxpm

没有编程语言的语言转换器,因为编程语言非常复杂。尽管这是可能的,但仍然存在许多挑战。

第一个挑战仅仅是在可接受的语言实践中。在两种面向对象的语言(例如Java和C++)之间进行转换非常复杂,而且它们都是基于C的。翻译器程序必须具有两种语言的标准库的完备知识,并且能够知道行为上的差异,您将不得不创建一个庞大的字典,即使如此,程序员之间编程风格的差异也意味着它必须猜测如何执行某些更改。

掌握语法翻译后,就必须弄清楚如何将第一种语言的结构转换为第二种语言的结构。如果要将C++中的对象移到Java(相对来说比较容易),但是对C++结构做什么呢?还是C++类之外的函数,那很好?决定如何处理它可能很棘手,因为它可能导致另一个问题,即创建blob对象,该blob是足够常见的反模式。

这不是问题的完整列表,但只是两个而已,它们很大。我的一位教授提到,有人说服了他的雇主,他们可以在80年代从机器代码制作到C语言,但是那时候不起作用。我怀疑会不会有一个完全有效的方法。

1
indyK1ng

编译的目的是为计算机获取有用的东西。即可以运行的东西。为什么要编译成甚至可能比您编写的东西还要高级的东西?

我更喜欢.NET的策略。将所有内容编译为通用语言。这提供了语言能够进行通信而无需创建(N ^ 2)-N个跨语言编译器的优势。

例如,如果您有10种编程语言,则只需要在.NET模型下编写10个编译器,它们就可以相互通信。如果制作了所有可能的跨语言编译器,则需要编写90个编译器。那是很多额外的工作,却没有什么好处。

1
mike30