¿Por qué C ++ para escribir un compilador?


14

Me preguntaba por qué C ++ es una buena opción para escribir un compilador. Por supuesto, C también es bueno para este propósito, porque muchos compiladores están escritos en C o C ++, pero esta vez estoy más interesado en C ++. ¿Alguna buena razón? Estaba buscando eso en Internet, pero no puedo encontrar ninguna buena razón.


3
"Muchos compiladores están escritos [...] en C ++" - ¿alguna referencia? ¿Cuáles? ¿Qué te hace pensar que C ++ se usa con más frecuencia para la construcción de compiladores que otros lenguajes populares?
Doc Brown

55
@DocBrown Bueno, Clang y MSVC están escritos principalmente en C ++, gcc tiene un poco de C ++ ahora, Java JVM está escrito en C ++ stackoverflow.com/questions/410320/what-is-java-written-in y también superusuario. com / preguntas / 136136 / ...
Klaim

@DocBrown DMD el compilador de referencia para D está escrito en C ++
ratchet freak

3
¿Quién dice que es una buena opción?
Phil

1
@ Phil ¿Crees que tomaron esta decisión sin tener en cuenta las alternativas? No es una "buena" opción, es una opción "eficiente".
Klaim

Respuestas:


24

C ++ tiene dos lados. Tiene un lado de desarrollo de bajo nivel que lo hace parecer un lenguaje natural para hacer cosas de bajo nivel como la generación de código. También tiene un lado de alto nivel (que C no tiene) que le permite estructurar una aplicación compleja (como un compilador) de una manera lógica y orientada a objetos, mientras mantiene el rendimiento. Debido a que tiene los aspectos de bajo y alto nivel, es una buena opción para aplicaciones grandes que requieren características o rendimiento de bajo nivel.


10
Hasta donde sé, gran parte de la lógica dentro de un compilador es de naturaleza funcional (transformando estructuras de datos complejas en otras estructuras de datos), por lo que no estoy seguro de si las instalaciones orientadas a objetos (que están más orientadas a la programación en general) , aspectos arquitectónicos) aportan una ventaja real a la construcción del compilador wrt a un estilo de programación procesal. Solo mis 2 centavos.
Giorgio

55
@Giorgio Tener objetos ayuda en muchos otros aspectos de la escritura del compilador. Por ejemplo, hay mucho estado con el que un compilador tiene que lidiar cuando se optimiza y ese tipo de cosas se presta bien a OOP. Además, la programación funcional y OOP puede ser bastante complementaria, por lo que el hecho de que los algoritmos sean mayormente funcionales no significa que los objetos no ayuden.
Oleksi

3
@Giorgio y Oleksi: Puedo confirmarlos a los dos. Escribí un compilador con Haskell para un idioma del mundo real. Fue un muy buen ajuste. Pero a veces echaba de menos algo de OO. Si tuviera que escribir otro compilador definitivamente elegiría Haskell, pero este es realmente un caso especial. No elegiría a Haskell sin dudarlo para otros tipos de proyectos.
scarfridge

26
¿Por qué necesita tener un lenguaje con un "lado de bajo nivel" para generar código? No puedo ver cómo estos dos están conectados de ninguna manera.
phant0m

55
No necesita un "lado de bajo nivel" para generar código más de lo que necesita identificadores Unicode para poder escribir texto japonés en un archivo.
dan04

15

Mi experiencia no está de acuerdo con su premisa aquí. De hecho, para lenguajes de propósito general de alto nivel, es una práctica muy común escribir el compilador en el mismo idioma que el idioma de origen (el idioma que se está compilando). Por ejemplo:

  • El compilador Java de Sun está escrito en Java
  • El compilador de Scala está escrito en Scala
  • El compilador C # de Mono está escrito en C #
  • El compilador Smalltalk de Squick está escrito en Smalltalk
  • ... y muchos más

Una excepción son los front-end del compilador escritos para frameworks de compilación existentes, como GCC, LLVM o Polyglot, que luego se escriben en el lenguaje del framework, o compiladores que dependen de generadores de analizadores existentes como Yacc. Dado que GCC, LLVM y Yacc son herramientas comunes y establecidas escritas en C y C ++, esto incentiva a los escritores de compiladores a usarlas, lo que puede llevar a que C y C ++ obtengan una gran participación en la distribución del lenguaje de implementación del compilador.


2
Creo que tiene mucho más que ver con que las personas que escriben el compilador conozcan bien y les guste mucho el lenguaje para el que escriben un compilador que por razones técnicas objetivas.
Thomas Bonini

1
@Krelp Estoy de acuerdo que no se trata de una razón técnica objetiva, pero tampoco es realmente "gusto", simplemente se considera un rito de iniciación para un idioma, "¿es lo suficientemente maduro como para poder servir como el lenguaje de implementación propio? compilador".
Roble

1
El compilador Java de Sun está escrito en C ++: stackoverflow.com/questions/410320/what-is-java-written-in
Klaim

11
@Klaim estás confundiendo dos productos aquí. Uno es el compilador Java de Sun ( javaclínea de comandos), que compila Java a Java Bytecode. Está escrito en Java, lo he modificado muchas veces y puedo navegar por sus fuentes de Java en línea . El otro es el compilador justo a tiempo incrustado en la JVM Hotspot, que compila Java Bytecode en el código de máquina nativo. Como la mayoría de JVM, está escrito en C ++, pero no es un compilador de Java ; de hecho, no sabe nada sobre el lenguaje Java.
Roble

@Oak, absolutamente correcto! En otras palabras, JVM! = Javac
Paul Draper

6

¿Para compilar qué a qué? Un compilador transforma un código fuente de un idioma ( idioma fuente) a otro (idioma de destino), lo que no indica nada sobre el bajo nivel del idioma de destino.

  • CoffeeScript compila a JavaScript, el compilador se escribe en CoffeeScript.
  • Script # compila C # en JavaScript, el compilador se escribe, si mal no recuerdo, C #.
  • etc.

El idioma que elija para escribir un compilador depende del contexto. Por ejemplo, trabajando en un proyecto que compila un lenguaje derivado de PHP a un código PHP nativo, utilicé una mezcla de PHP y C # para escribir el compilador, porque tenía más sentido para mí dadas mis habilidades. Otra persona elegiría Python, o Java y PHP, o C ++ con un poco de JavaScript, o lo que sea.

C o C ++ es una opción popular debido al soporte de herramientas relacionadas con el compilador (vea la respuesta de Telastyn), y porque esos dos lenguajes le permiten volverse realmente nativo. Pero no hay nada malo en elegir otro idioma.

Tenga en cuenta que para ser más geek , puede elegir el idioma de origen para escribir el compilador. Es lo que sucedió con el compilador CoffeeScript y muchos otros compiladores. También es popular entre los IDE: uno de los primeros Visual Studio se creó con el mismo Visual Studio.


55
El autohospedaje no es geek, es una propiedad importante para portar un compilador.

55
La razón es que inmediatamente permite que el compilador mismo sea un programa de prueba. Es muy probable que también sea el programa más grande para ese compilador durante bastante tiempo.

6

Tiendo a cuestionar la premisa básica aquí. Mientras que C y C ++ funcionan perfectamente bien para escribir compiladores, muchos otros lenguajes parecen funcionar perfectamente también para la tarea.

Sin embargo, un poco depende del idioma que esté compilando. Para lenguajes pequeños y simples, C y Pascal funcionan bastante bien. Si va a compilar algo grande y complejo, su compilador también se vuelve grande y complejo, en cuyo caso, las funciones adicionales de C ++ para organizar y trabajar con programas más grandes obviamente son útiles. Sin embargo, eso no es realmente muy específico para la compilación, solo características útiles para programas más grandes en general.

Creo que también vale la pena mencionar otro punto. Los principiantes (parecen) pensar que los compiladores son principalmente manipuladores de texto, por lo que piensan que algo como Perl será de gran ayuda para escribir compiladores. En realidad, la mayoría de las partes interesantes de la compilación realmente no comienzan hasta después de haber construido su AST. Si bien estoy seguro de que Perl puede hacer el trabajo perfectamente bien, su capacidad de manipulación de texto tampoco le da una gran ventaja (la manipulación de texto se encuentra principalmente en el lexer, y los generadores de lexer para cosas como C son compatibles con los RE de todos modos).


2
AST = Árbol de sintaxis abstracta, RE = Expresiones regulares
chaotic3quilibrium

5

Los compiladores pueden implementarse en cualquier lenguaje moderno. Sin embargo, uno de los requisitos más importantes de un compilador es ser rápido.

C ++ tiene una clara ventaja aquí. La optimización en C ++ no es barata. Sin embargo, debido a la naturaleza de bajo nivel de este lenguaje, es posible optimizar manualmente el código C ++ más que en cualquier otro lenguaje (excepto el ensamblado que no es portátil).


10
Otro requisito importante es que el código generado sea correcto: prefiero tener un compilador lento en el que pueda confiar que uno rápido que genere código incorrecto.

1
Si bien es ciertamente posible optimizar C ++ en gran medida, hay muchos ... bueno ... menos que un código C ++ óptimo.
Donal Fellows

2
@DonalFellows Dale la vuelta: es posible escribir código menos que óptimo en cualquier idioma, pero hay optimizaciones que son imposibles de habilitar en otros lenguajes que no sean C ++ (aparte de Assembler. No incluyo C por falta de estructuras de alto nivel que permiten un forro más fuerte).
Klaim

3

Sospecho que el principal motivador para su uso es que la salida de Lex / Yacc / Bison está (principalmente) en C. Dado que ha sido el estándar durante tanto tiempo, tiene impulso.

No es que esas sean razones particularmente buenas ...


En realidad no me satisface, pero gracias por intentarlo.
Kobra

Eso no responde a la pregunta "por qué elegir C ++ sobre C para la construcción del compilador".
Doc Brown

3
No es una buena razón en absoluto. Existen herramientas análogas a Lex y Yacc para muchas plataformas. PLY y ANTLR, por ejemplo.
user16764

Además, los compiladores más populares del mundo real (estoy bastante seguro de que Clang y GCC, por ejemplo) usan analizadores escritos a mano.

@delnan: Sí, pero probablemente comenzaron usando uno generado para despegar. La generación manual del analizador es un paso de optimización que realmente no desea hacer hasta que pueda probar que otras cosas están funcionando.
Martin York

1

Tengo experiencia con este asunto. He escrito compiladores en C y C ++. La principal diferencia entre C y C ++ es que C no tiene gestión de memoria dinámica de forma automática. Toda la gestión de memoria en C debe hacerse explícitamente. Escribir un compilador se ocupa mucho del procesamiento de cadenas y la gestión de matrices. En C, se ve obligado a pensar en el tamaño de cada cadena y cada matriz que declara y también verificar los índices cuando accede a esos objetos (si desea que su código sea seguro y estable). En C puede tener una administración de memoria dinámica, por supuesto, pero nada es automático. Debe asignar explícitamente y liberar memoria usando malloc () y free (), mantener el tamaño de sus objetos dinámicos en variables separadas para asegurarse de no acceder a ellos fuera de los límites.

En C ++ puede tener los mismos mecanismos, pero es realmente eficiente en el tiempo de desarrollo porque toda su administración de memoria puede encapsularse dentro de constructores y destructores a los que no tiene que llamar explícitamente. Entonces el compilador está asignando y liberando recursos para usted. El tamaño de sus objetos dinámicos también puede encapsularse si crea sus propias clases, y los índices pueden verificarse para el acceso a límites mediante el operador de sobrecarga []. Estas abstracciones ayudan a que su código sea más limpio, más fácil de entender y depurar, y definitivamente hace que el desarrollo sea más rápido.

Si crea un compilador en C, seguramente le llevará más tiempo. C ++ te hará terminar tu proyecto en menos tiempo. C y C ++ tienen el mismo rendimiento, pero C ++ tiene muchas ventajas que C no tiene.


0

El proyecto CompCert es un compilador de investigación C que no está escrito en C ni en C ++, sino más en Ocaml y Coq.

Observe que C ++ solía traducirse a C (en Cfront ). Ahora puede usar el front-end GCC para Gimple , luego volcar el Gimple en alguna base de datos, luego escribir un Gimple en su traductor ensamblador. Pero las razones legales (la excepción de la biblioteca de tiempo de ejecución de GCC ) requieren que dicho compilador sea de código abierto. Pídale detalles a su abogado, no soy un abogado. Las variantes antiguas de GCC se han escrito en C (+ varios lenguajes específicos de dominio) con un front-end para alguna variante de C ++. OpenWatcom podría ser un compilador de C ++ escrito en C (lo dejo para verificar eso).

La fuente de Compcert está disponible gratuitamente para fines académicos y de investigación. Si desea usarlo industrialmente (y legalmente), necesita obtener una licencia de Absint.

Vea también esto y aquello que responde a dos preguntas relacionadas.

Si en 2020 se me asignó la tarea de escribir un compilador C (o C ++) desde cero (ejecutándose en Linux, tal vez algún compilador cruzado ), probablemente no lo escribiré en C ++. Consideraría escribirlo usando Ocaml , Go o Rust . Y podría basarlo en Frama-C si así lo permite. Si fuera necesario para codificar en C o C ++, primero codificaría una biblioteca recolectora de basura , probablemente alguna capa de persistencia , muy útil para la optimización de todo el programa , y luego consideraría un enfoque de metaprogramación (generando la mayor parte del código C o C ++ del compilador con mis herramientas ad-hoc, tal vez Bismon o RefPerSys si está permitido)

Puede encontrar algunos compiladores de C (más o menos de código abierto) codificados en Common Lisp o en Python (por ejemplo, ShivyC o nqcc ). Mira también en ZetaC .

Tenga en cuenta que las versiones recientes de GCC técnicamente no están codificadas en C ++ puro, son una docena de lenguajes específicos de dominio involucrados en GCC (varios de ellos son completos de Turing ). Vea también mi antiguo proyecto GCC MELT .

No me sorprendería si, en futuras versiones de GCC, algún intérprete de Python o Guile se integrara dentro de ellos (por ejemplo, como un reemplazo para el administrador de pases de GCC).

Mire también el proyecto MILEPOST GCC .

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.