¿Existen programas que puedan 'traducir' el código fuente entre dos idiomas?

28

¿Existen programas que puedan 'traducir' el código fuente entre dos idiomas (suponiendo que el traductor tenga acceso a las bibliotecas necesarias)?

Si los hay, ¿cómo funcionan (técnicas utilizadas, conocimiento requerido, etc.)? ¿Cómo se construirían de manera factible?

Si no lo son, ¿cuáles son las restricciones que impiden su desarrollo? ¿Es este un problema completo de IA (la traducción del lenguaje natural se enumera como una)?

EDITAR La conversión solo se espera, cuando el idioma tiene el mismo poder de expresión, puede resolver el mismo tipo de problemas y el código a convertir puede expresarse en el idioma de destino. (Por ejemplo, no se espera la conversión de un script de shell a MATLAB).

Tobi Alafin
fuente
14
¿Qué quieres decir con "cualquier dos idiomas"? Ciertamente, hay programas que pueden traducir de un idioma a otro. Se llaman "compiladores". Esa es literalmente la definición de un compilador: un programa que traduce programas de un idioma a otro. ¿Pero "cualquier dos idiomas"? No creo que sea posible. El traductor debe conocer tanto el idioma de origen como el de destino, y generalmente es específico para un par particular de idiomas.
Jörg W Mittag
El programa proporciona los idiomas de origen y destino. Estoy pensando en escribir un programa en C ++, traducirlo a Java, Python, Perl, Ruby, Go, etc. Puede haber algunas restricciones (no espero que convierta su script de shell a MATLAB, por ejemplo).
Tobi Alafin
44
Sí, se llaman compiladores, funcionan como compiladores y se pueden construir como compiladores.
user253751
1
Si con "dos idiomas cualquiera" quiere decir literalmente que el programa (finito) debería ser capaz de leer y comprender un número infinito de idiomas de entrada, la respuesta es trivialmente no . Sin embargo, tome un conjunto finito de idiomas de entrada y puede encontrar un compilador para todos esos idiomas ..
Bakuriu

Respuestas:

57

TLDR; Esto es posible pero no práctico.

(suponiendo que el traductor tenga acceso a las bibliotecas necesarias)?

Esto termina siendo complicado, y es parte de por qué cosas como esta no terminan siendo utilizadas en la práctica.

  1. Todos los compiladores son traductores. Definitivamente es posible traducir de un idioma a otro, y esto es literalmente todo lo que un compilador está haciendo. El lenguaje que un compilador escupe como salida es generalmente código de máquina o ensamblado, pero este es solo otro idioma, y hay compiladores (a veces llamados transpiladores o transcompiladores) que traducen entre dos idiomas . Por ejemplo, hay una gama de lenguajes de compilación a Javascript como PureScript, Elm, ClojureScript, etc.

  2. Siempre es posible traducir entre dos idiomas completos de Turing. Ignorando cosas como llamadas a la biblioteca y FFI y otras partes prácticas desagradables que se interponen, eso es. Si un idioma es Turing completo, entonces tienes:

    • Una traducción que convierte una máquina de Turing en código en este idioma
    • Una traducción de este idioma a una máquina de Turing

    Entonces, para traducir del idioma A al idioma B, conviertes el código A en una máquina de Turing, luego conviertes esa máquina en código B.

    Por supuesto, en la práctica, los bits prácticos se interponen en el camino, y esto también requiere que tenga las traducciones accesibles para usted. Existen básicamente para todos los idiomas, pero eso no significa que alguien se haya tomado el tiempo para escribirlos.

  3. Hacer esta traducción eficientemente es difícil . Diferentes idiomas dan prioridad a diferentes cosas. Por ejemplo, si traduces de C a Python, probablemente tengas que terminar simulando la memoria de C como un diccionario de Python, para que puedas hacer aritmética de puntero. Habrá una sobrecarga asociada con esto, porque ahora no está accediendo a las instrucciones de memoria de metal desnudo.

    Los diferentes idiomas tienen diferentes prioridades de rendimiento, por lo que algo que un idioma optimiza (o más bien, una implementación de un idioma optimiza) podría ser imposible de hacer rápidamente en otro idioma. La traducción de un idioma funcional con llamadas de cola adecuadas se ralentizará si la traduce a un idioma sin las llamadas de cola adecuadas.

  4. Hacer esta traducción no hace que el código sea legible . Es fácil obtener un código en el lenguaje B que se comporta igual que el código del lenguaje A. Es difícil hacer que parezca un código que un humano habría escrito en B, por varias razones. A y B pueden tener diferentes herramientas de abstracción, y la computadora no tiene idea de qué hace que el código sea legible. Esto será particularmente cierto si terminas usando la traducción automática de Turing que describí anteriormente.

    Esto plantea la pregunta: ¿cuál es el punto de tal traducción? Si todo lo que obtiene al final es un bloque de código lento e ilegible, ¿por qué no solo compilarlo en código de máquina y usar algún tipo de comunicación FFI o entre procesos para unir las piezas?

    Hay algunas excepciones a esto. A veces necesitas cosas en un idioma determinado (como JavaScript). A veces el lenguaje es similar, y una traducción sensata es fácil. A veces, un idioma no está destinado a ejecutarse, sino a extraer su código en otro idioma (como Coq).

    Pero en general, no es algo muy práctico.

jmite
fuente
55
Un ejemplo para el punto 4 es asm.js . Hoy en día, es posible que sea sortA fácil de leer, usando Javascript Fuente Mapas y el Inspector de elementos, pero nadie va a querer hacer eso ...
Ismael Miguel
1
Modelica es otro ejemplo de un lenguaje diseñado para compilar en otro idioma (en este caso, C).
Restablece a Monica el
Webassembly traduciendo de C ++ a javascript.
Surt
Existen numerosos ejemplos de transpiladores de X a Y, pero eso es diferente de un compilador universal de cualquier cosa. Obviamente, hay casos en los que la transpiración tiene sentido.
jmite
Una excepción importante que falta IMO: compilar a C. La razón es que muchos sistemas poco comunes tienen un compilador de C existente, que generalmente puede emitir un código de máquina bastante razonable. Por lo tanto, al compilar un lenguaje en C, no necesita tener backends para esas arquitecturas raras.
MSalters
2

Hay tales programas. Por ejemplo, los traductores de Lisp a Fortran, que fueron ampliamente utilizados en su momento. Los compiladores de Sole Lisp no compilan Lisp directamente, sino que generan código C que luego es compilado por un compilador de C normal. Otro ejemplo sería Vala que no se compila directamente, sino que primero se traduce a C ++ antes de compilar el código de C ++. Qt está escrito en MOC, un lenguaje que se traduce a C ++ para compilarlo (pero como MOC es solo C ++ con algunos comandos adicionales, se puede argumentar si realmente se va a llamar un "nuevo lenguaje"), y antes de eso eran compiladores de C ++ había traductores de C ++ a C. Y algunos proyectos se escribieron en Pascal y luego se tradujeron a C. Además, el clang y Java tienden a ser algo así, ya que traducen código C ++ y Java a algún lenguaje intermedio que luego se puede procesar más.

Lo que no puede esperar de la salida de un traductor de idiomas es que el resultado tenga sentido para un lector humano: la tarea del programa es escribir código que resulte en un programa que haga lo mismo que el código original (que en mi experiencia podría o podría no funciona, dependiendo de las características del idioma y las bibliotecas externas que estaba usando). Pero como no conoce el propósito de esta tarea para el resto del significado del programa, podría perderse en gran medida.

Gunter Königsmann
fuente
0

No es una respuesta directa, pero hay una herramienta llamada ILSpy , que fue escrita para .Net Framework, y le permite descompilar un ensamblado .Net en C # o VB.Net.

Si no está familiarizado con la naturaleza de .Net, puede escribir código .Net en muchos idiomas, pero principalmente C # o VB.Net. Cuando el compilador compila la aplicación, traduce el código a un código de "lenguaje intermedio" (o IL para abreviar). Este código luego se compila en binarios .Net.

Dado que las aplicaciones .Net son archivos binarios compilados a partir del código IL, ILSpy puede tomar la aplicación .Net, revertirla al código IL y, posteriormente, llevarla un paso más allá y volverla a C # o VB.Net.

Con esta herramienta, todo lo que tiene que hacer es compilar una aplicación, y luego puede examinar los archivos compilados como código IL, C # o VB.Net. Para ser claros, no importa en qué idioma se escribió inicialmente el código. Siempre que el binario sea un ensamblado .Net, puede realizar ingeniería inversa de los archivos compilados y generar el contenido como cualquiera de estos tres idiomas.

Sé que esto no es exactamente un compilador, pero es una herramienta que ofrece un resultado final similar a lo que está buscando y, de hecho, lo he usado para "traducir" proyectos de VB.Net en algo un poco más familiar para mí-- C #.

RLH
fuente
0

Para su caso de uso (basado en comentarios), parece que SWIG podría ser útil.

SWIG es una herramienta de desarrollo de software que conecta programas escritos en C y C ++ con una variedad de lenguajes de programación de alto nivel. SWIG se utiliza con diferentes tipos de idiomas de destino, incluidos los lenguajes de secuencias de comandos comunes, como Javascript, Perl, PHP, Python, Tcl y Ruby. La lista de idiomas admitidos también incluye lenguajes que no son scripts como C #, Common Lisp (CLISP, Allegro CL, CFFI, UFFI), D, Go language, Java, incluidos Android, Lua, Modula-3, OCAML, Octave, Scilab y R También se admiten varias implementaciones de esquemas interpretados y compilados (Guile, MzScheme / Racket, Chicken).

Nathan Ringo
fuente
0

Recuerdo el venerable f2c , que hace la traducción de fuente a fuente de Fortran 77 a C.

Fue (a veces es ...) utilizado principalmente para traducir código numérico de hace décadas sin tener que integrar un compilador fortran a su cadena de herramientas.

Alexandre C.
fuente
0

La teoría que le dice que tales programas existen, en principio, se llama numeración admisible . Podemos demostrar que existen compiladores computables entre dos numeraciones, y cada formalismo completo de Turing (o lenguaje de programación) es, en esencia, uno.

Rafael
fuente