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


37

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

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


5
请记住,“所有语言”甚至包括像Oook这样的愚蠢语言!(改变完整性不是全部;在实践中,您也需要系统调用。)
Donal Fellows

有一些。从C到Pascal和从Pascal到C的翻译器很常见。正如下面的答案所暗示的,如果没有至少一些手动整理,输出通常不那么可读。而且这些是相对简单的语言,具有相对简单的库-可能无法完成例如C ++到Haskell或反之亦然的工作。
Steve314 2011年

签出Roslyn作为服务的.net编译器能够将C#转换为VB,反之亦然。
丹尼尔·利特尔

2
所有的编译器转换一个PL到另一个,他们不保证代码在目标PL易于阅读,虽然
JK。

看到Google翻译的准确性之后,我坚信我将在我的一生中看到通用翻译。是的,这将是一项具有挑战性的工作,并且可能需要巨大的精力,例如在分析大型代码库(例如github或stackoverflow)的情况下,但是这种情况会发生,并且随着时代的推移,对此类工具的需求也会增加,尤其是在现在有大量的程序员学习AI和ML。可能没有人一个人一个人开发这种工具。但是,可能会开发一种机器人来开发机器人来解决这一问题。
Ganesh Kamath-“疯狂代码”

Answers:


32

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

考虑使用PHP到Java的翻译器。做到不嵌入PHP二进制代码部分的唯一可行方法是用Java重新实现所有PHP模块和API。这涉及实现超过10.000个功能。与之相比,实际翻译语法的工作很容易。即使完成了所有这些工作,您也没有Java代码,但您还是会碰巧在Java平台上运行,但内部却像PHP那样结构化。

这就是为什么我想到的唯一此类工具都是翻译代码以进行部署,而不是随后进行维护。Google的GWT将Java“编译”为JavaScript。Facebook的嘻哈将PHP编译为C。



看起来有人创建了一个PHP到Java转换器,并确实嵌入了PHP二进制文件。同意,尽管这不会改变您的观点。runtimeconverter.com/single-post/2017/09/15/…–
user1122069

20

如果你有一个中间格式,那么你可以实现的东西,在语言转换X的程序,以这种格式,并且还该格式语言Y.实现您感兴趣的所有语言的转换,就大功告成了,对不对?

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

现在,汇编不是进行反向转换的好语言,但是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确实没有什么可以解决的,但是您可以通过MSIL中的一些附加注释(可能通过属性)解决#1的问题。当然,那将是额外的工作。


MSIL中包含了许多原始来源的元数据(包括XML注释以及原始方法,属性和成员名称),因此我认为向C#的转换并不像您所说的那样难以理解。尝试分解.NET框架的各个部分;这是非常可读的。当然,从F#到C#的转换情况可能有所不同。
罗伯特·哈维

@Robert:MSIL中不包含XML注释。Microsoft.NET\Framework\v2.0.50727\en例如,如果您查看,则可以看到系统库的所有XML文档。这就是Reflector(等)用于显示评论的内容。转换不是不可读的,我只是说它不是源代码级翻译所期望的100%保真度。
迪恩·哈丁2010年

2
反汇编程序将计算机可执行二进制文件转换回该特定处理器类型的汇编程序(并非世界上所有的计算机都是x86)。您的意思确实是反编译器,将编译后的代码带回源代码。这是一项艰巨的任务,因为来自每个制造商的每个编译器在每个优化级别都会将源代码行转换为不同的输出二进制格式。
uɐɪ

20

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

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

1
你击中了要害。尝试阅读LLVM C后端发出的代码。从技术上讲,这是合法的C代码,但不是很漂亮(TM)。
dsimcha 2011年

1
@dsimcha:除了可读性之外,C后端使输出比调试或反汇编更易于阅读。我很高兴在后端停止维护一小会儿之后又将后端重新带回了。
JM Becker 2013年

10

您为什么要转换程序?

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

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

例如,比较一个典型的C迭代和一个Lisp的迭代。或python与惯用红宝石的“一种最佳方式”。

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

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

*)好吧,有咖啡稿...


1
好答案。可以补充说,如果两种语言具有完全相同的一组特征和惯用语,则可以相当有效地将一种语言翻译成另一种语言,但是大多数语言的设计目的都是为了支持其创建者认为不够充分的特征和惯用语。支持其他语言。当目标语言中的功能和惯用语是源语言中的功能和惯用语的超集时,可维护代码的机械翻译有时是可行的,但是这种情况并不常见。
2012年

6

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

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

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


5

FWIW,有一个从Java到D的翻译器。它称为TioPort,用于将SWT移植到D的相当认真的尝试。它遇到的主要问题是,有必要移植Java标准库的大部分内容。


4

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

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

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

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


您能列举其中一些小组吗?
Qwertie

4

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

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


3

这一直都在做。

每个编译器都会 “基本语言”(如C ++)转换为机器的本机汇编语言或使用解释型语言的与体系结构无关的字节码。

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

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

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

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

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

简而言之,这是不值得的。


您的类比也将适用于普通编译,而根据经验,它并不适用!计算机会“生成”(而不是编写)高质量的代码。他们经常做的不好的事情就是可读性/可维护性。如果有人确实需要这样的过程(相信我的人偶尔会这样做),那么这两个问题都不会成为阻碍。如果是这样的话,那么显然翻译本来就不重要。
JM Becker 2013年

1

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

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

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

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


我认为没有必要知道现有的库,它可以随需翻译库(假设它们有可用的源)。
塞格2010年

1
这实际上增加了第二个问题的复杂性。前提是您有权访问源代码以对其进行翻译。无论哪种方式,这仍然是不可行的。
indyK1ng 2010年

关于库的+1点是完全有效的,并且总是有库。
Dan Rosenstark 2012年

1

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

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

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.