9

Por lo general, los compiladores se traducen del idioma que admiten al ensamblaje. O como mucho a un lenguaje de ensamblaje (bytecode), como GIMPLE/GENERIC para GCC o Python/Java/.NET bytecode.¿Por qué los compiladores no se traducen en idiomas más simples?

¿No sería más simple para un compilador traducir a un lenguaje más simple, que ya implementa un gran subconjunto de su gramática?

Por ejemplo, un compilador de Objective-C, que es 100% compatible con C, podría agregar la semántica solo para la sintaxis que se extiende a C, traduciéndolo en C. Puedo ver muchas ventajas de hacer esto; se podría usar este compilador de Objective-C para traducir su código a C para compilar el código C generado con un compilador diferente que no admite C++ (pero que optimiza más, o compila más rápido o puede compilar para más arquitecturas) O uno podría usar el código C generado en un proyecto donde solo se permite C.

supongo/espero que si las cosas funcionaban así, habría sido mucho más fácil de escribir extensiones para los idiomas actuales (por ejemplo: la adición de palabras clave C++ para facilitar la implementación de patrones comunes, o, todavía en C++, eliminando el declara antes de usar la regla moviendo las funciones de miembros en línea al final de los archivos de encabezado)

¿Qué tipo de sanciones habría? ¿El código generado sería muy difícil de ser entendido por los humanos? ¿Los compiladores no podrían optimizar tanto como ahora? ¿Qué más?

+7

Por cierto, el primer compilador C++ trabajaron que manera- Compilar código C++ a código C que fue luego compilado a través de un compilador C. Se encontraron con problemas, sin embargo, a medida que el lenguaje C++ se volvió más complejo: http://en.wikipedia.org/wiki/Cfront – bdk

+0

De hecho, Ratfor fue diseñado para ser solo esto: http://en.wikipedia.org/wiki/Ratfor – Gabe

Respuesta

6

Esto es en realidad utilizado por una gran cantidad de idiomas, a través del uso de Intermediate languages. El mayor ejemplo de esto sería Pascal, que tenía el sistema Pascal-P: Pascal se compiló en un lenguaje de ensamblaje hipotético. Al puerto pascal solo significaría hacer un compilador para este lenguaje ensamblador: una tarea mucho más simple que portar todo el compilador pascal. Después de escribir este compilador, solo necesitaría compilar el compilador pascal (independiente de la máquina) que se escribió en este.

Bootstrapping también se utiliza con bastante frecuencia en el diseño del lenguaje de programación. Muchos idiomas tienen sus compiladores escritos en el mismo idioma (Haskell viene a la mente aquí). Al hacer esto, escribir una nueva funcionalidad para el lenguaje simplemente significa traducir esa idea al idioma actual, ponerlo en el compilador y luego recompilarlo.

No creo que el problema con este método sea realmente la legibilidad del código generado (no selecciono a través del ensamblado el código de bytes generado a través de los compiladores, personalmente), sino uno de optimización. Muchas ideas en lenguajes de programación de alto nivel (mecanografía débil vienen a la mente) son difíciles de traducir automáticamente a lenguajes de sistema de nivel inferior como C. Hay una razón por la cual GCC tiende a hacer su optimización antes de la generación de código.

Pero, en su mayor parte, los compiladores se traducen a lenguajes más simples, excepto quizás el más básico de los idiomas del sistema.

+0

Consulte también la pregunta: [Bootstrapping a compilador: ¿por qué?] (Http://stackoverflow.com/questions/1493747/bootstrapping-a-compiler-why) –

1

Dado que Objective-C es un superconjunto estricto de C y C++ contiene una cantidad muy grande que se parece mucho a C, para analizar o bien ya es necesario poder analizar C. En ese caso, dar salida al código de máquina y la salida a más código C no es sustancialmente diferente en el costo de procesamiento, el principal costo para el usuario es que la compilación ahora lleva tanto tiempo como originalmente, más la cantidad de tiempo que tarda un segundo compilador.

Cualquier intento de copiar y pegar cosas que se vean como C y traducir el resto a su alrededor sería propenso a problemas. En primer lugar, C++ no es un superconjunto estricto de C, por lo que las cosas que parecen C no necesariamente compilan exactamente lo mismo de todos modos (especialmente en comparación con C99).E incluso si lo hicieran, suponiendo que un usuario cometiera un error en sus C, los compiladores no tienden a proporcionar información de error en un formato legible por máquina, por lo que sería muy difícil para la capa Objective-C a C dar el usuario un error significativo después de recibir, por ejemplo "error en la línea 99".

Dicho esto, muchos compiladores, como GCC e incluso más como el próximo Clang + LLVM, usan una forma intermedia para desacoplar el bit que conoce los detalles de una arquitectura del bit que conoce los detalles de un particular idioma. Sin embargo, tiende a ser más una estructura de datos que algo intencionalmente fácil de expresar como un lenguaje escrito.

Entonces: los compiladores no funcionan así por razones puramente prácticas.

2

Dicho sea de paso, como contraejemplo, Tcl es un idioma que se sabe que es muy, muy difícil (si no totalmente imposible) traducir a C. En los últimos 20 años ha habido un par de proyectos que probaron esto, incluso una promesa de un producto comercial pero ninguna se ha materializado.

En parte es porque Tcl es un lenguaje muy dinámico (como cualquier lenguaje con una función eval). En parte, se debe a que la única forma de saber si algo es código o datos es ejecutar el programa.

+4

todos los idiomas divertidos son difíciles de traducir a C :-) –

0

Hay una pila de construcción de compiladores que se basa completamente en esta idea. Cualquier lenguaje nuevo se implementa como una traducción trivial a un lenguaje de nivel inferior o una combinación de idiomas que ya están definidos dentro de esta pila.

http://www.meta-alternative.net/mbase.html

Sin embargo, con el fin de ser capaz de hacerlo, se necesitaría al menos algunas capacidades metaprogramación en cada pequeña lengua se agrega a una jerarquía. Este requisito agrega algunas limitaciones severas a la semántica de los lenguajes.

1

Haskell se compila de esta manera: el compilador GHC primero traduce el código fuente a un lenguaje funcional intermediario (que es menos rico que el propio Haskell), realiza optimizaciones y luego lo reduce al código C, que luego compila GCC. Estas soluciones tienen problemas difíciles, y los proyectos comenzaron a reemplazar este back-end.

http://blog.llvm.org/2010/05/glasgow-haskell-compiler-and-llvm.html

Cuestiones relacionadas