是否有可以在任何两种语言之间“翻译”源代码的程序?


28

是否存在可以在任何两种语言之间“翻译”源代码的程序(假设翻译者可以访问必需的库)?

如果存在,它们如何工作(使用的技术,所需的知识等)?它们将如何可行地构造?

如果不是,阻碍其发展的限制因素是什么?这是AI的完整问题(自然语言翻译列为其中一个)吗?

仅当语言具有相同的表达能力时,才可以预期 EDIT转换,可以解决相同类型的问题,并且要转换的代码可以用目标语言表示。(例如,不建议将Shell脚本转换为MATLAB)。



14
“任何两种语言”是什么意思?当然,有些程序可以将一种语言翻译成另一种语言。他们被称为“编译器”。从字面上看,这就是编译器的定义:将程序从一种语言翻译成另一种语言的程序。但是“任何两种语言”?我认为那是不可能的。译者必须同时知道源语言和目标语言,并且它通常特定于特定的一对语言。
约尔格W¯¯米塔格

该程序提供了源语言和目标语言。我正在考虑用C ++编写程序,将其翻译为Java,python,Perl,Ruby,Go等。可能存在一些限制(例如,我不希望它将您的Shell脚本转换为MATLAB)。
Tobi Alafin '16

4
是的,它们被称为编译器,它们像编译器一样工作,并且可以像编译器一样构造。
user253751 '16

1
如果用“任何两种语言”的字面意思是(有限的)程序应该能够阅读和理解无限数量的输入语言,那么答案是肯定的。然而,采取一组有限的输入语言,你可以找到一个编译器对所有这些语言..
Bakuriu

Answers:


57

TLDR;这是可能的,但不切实际。

(假设翻译者可以访问必需的库)?

这最终是棘手的事情,也是为什么这样的事情最终没有在实践中使用的原因之一。

  1. 所有编译器都是翻译器。从一种语言到另一种语言的转换绝对是可能的,这实际上是编译器所做的全部工作。编译器作为输出输出的语言通常是机器代码或汇编语言,但这只是另一种语言,并且存在编译器(有时称为翻译器或编译器),它们在两种语言之间进行翻译。例如,有各种各样的可编译为Javascript语言,例如PureScript,Elm,ClojureScript等。

  2. 始终可以在任何两种Turing Complete语言之间进行翻译。就是忽略诸如库调用和FFI之类的东西以及其他讨厌的实用位。如果一种语言是图灵完备,那么您将:

    • 将图灵机转换为该语言代码的翻译
    • 从这种语言到图灵机的翻译

    因此,要从语言A转换为语言B,您需要将A代码转换为图灵机,然后将该机器转换为B代码。

    当然,在实践中,实用的工具会妨碍您的工作,这也需要您可以使用翻译。它们几乎适用于每种语言,但这并不意味着有人花时间将它们写出来。

  3. 有效地执行此翻译非常困难。不同的语言会优先处理不同的事情。例如,如果您从C转换为Python,则可能最终不得不将C的内存模拟为Python字典,以便可以执行指针算术。与此相关的开销很大,因为您现在不访问裸机存储器指令。

    不同的语言具有不同的性能优先级,因此用一种语言进行优化(或者用一种语言的实现进行优化)可能无法用另一种语言快速完成。如果将功能语言翻译为没有正确的尾部调用的功能语言,则会减慢其速度。

  4. 进行这种翻译不会使代码可读。用语言B获得的一段代码与语言A中的代码具有相同的功能是很容易的。由于多种原因,很难使它看起来像人类用B编写的代码。A和B可能具有不同的抽象工具,并且计算机不知道是什么使代码可读。如果您最终使用了我之前描述的Turing Machine转换,则尤其如此。

    这就提出了一个问题:这样的翻译有什么意义?如果最后您得到的是一块缓慢的,无法读取的代码,为什么不将其编译为机器代码并使用某种FFI或进程间通信将各部分链接在一起呢?

    这有一些例外。有时,您需要使用某种特定语言(例如JavaScript)的内容。有时语言是相似的,明智的翻译很容易。有时,一种语言不是要运行的,而是要将其代码提取到另一种语言(例如Coq)中。

    但是总的来说,这不是一件很实际的事情。


5
为第4点的一个例子是asm.js。今天,它可以使八九不离十可读性,使用JavaScript源地图和元素督察,但没有人会想这样做...
伊斯梅尔·米格尔

1
Modelica是设计用于编译为另一种语言(在本例中为C)的另一种语言示例。
恢复莫妮卡

Webassembly从C ++转换为javascript。
Surt

从X到Y的编译器有很多示例,但这与通用的任何编译器都不相同。显然,在某些情况下转译是有意义的。
jmite 2016年

缺少IMO的一个重要例外:编译为C。原因是,许多不常见的系统都有一个现有的C编译器,该编译器通常可以发出相当合理的机器代码。因此,通过将语言编译为C,您无需为那些罕见的体系结构提供后端。
MSalters 2016年

2

有这样的程序。例如,Lisp到Fortran转换器在当时被广泛使用。唯一的Lisp编译器不会直接编译Lisp,而是生成C代码,然后由常规C编译器进行编译。另一个示例是Vala,它不会直接编译,而是在编译C ++代码之前首先转换为C ++。Qt用MOC编写,这是一种语言,可以翻译成C ++进行编译(但由于MOC只是C ++,还有一些其他命令,如果它真的要被命名为“新语言”,则可以争论)-在此之前是C ++编译器,还有C ++到C转换器。而且有些项目是用Pascal编写的,然后翻译为C。clang和Java也倾向于将C ++和Java代码翻译为某种中间语言,然后可以进一步处理。

您不会期望语言翻译器的输出是对人类读者有意义的结果:该程序的任务是编写代码,使程序与原始代码具有相同的功能(根据我的经验,这可能或可能无效,具体取决于语言的功能和所使用的外部库。但是由于它不知道目的是为了完成程序其余部分的意义,因此可能会在很大程度上丢失该任务。


0

这不是一个直接的答案,但是其中有一个工具调用ILSpy,它是为.Net Framework编写的,允许您将.Net程序集反编译为C#或VB.Net。

如果您不熟悉.Net的性质,则可以使用多种语言(主要是C#或VB.Net)编写.Net代码。当编译器编译应用程序时,它将代码转换为“中间语言”(或简称为IL)代码。然后将此代码编译为.Net二进制文件。

由于.Net应用程序是从IL代码编译的二进制文件,因此ILSpy可以使用.Net应用程序,将其反向转换为IL代码,然后再进一步将其反向执行,然后反向转换为C#或VB.Net。

使用此工具,您所需要做的就是编译应用程序,然后您可以将编译后的文件浏览为IL,C#或VB.Net代码。清楚地说,代码最初使用哪种语言都没有关系。只要二进制文件是.Net程序集,它就可以对工程文件进行反向工程并将其内容输出为这三种语言中的任何一种。

我知道这不是一个完全编译器,但是它提供的最终结果与您所寻找的类似,实际上,我已经使用它来将VB.Net项目“翻译”成一些东西我更熟悉-C#。


0

对于您的用例(基于评论),听起来SWIG可能有用。

SWIG是一种软件开发工具,可将用C和C ++编写的程序与各种高级编程语言相连接。SWIG与不同类型的目标语言一起使用,包括常见的脚本语言,例如Javascript,Perl,PHP,Python,Tcl和Ruby。支持的语言列表还包括非脚本语言,例如C#,Common Lisp(CLISP,Allegro CL,CFFI,UFFI),D,Go语言,Java(包括Android),Lua,Modula-3,OCAML,Octave,Scilab和R还支持几种解释和编译的Scheme实现(Guile,MzScheme / Racket,Chicken)。


0

我记得古老的f2c,它可以进行从Fortran 77到C的源到源转换。

它(有时是...)主要用于翻译几十年前的数字代码,而不必将fortran编译器集成到您的工具链中。


0

从理论上告诉您这样的程序存在的那一部分被称为允许编号。我们可以证明,在任何两个这样的编号之间都有可计算的编译器,并且每个图灵完备的形式主义(或编程语言)实质上都是一个。

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.