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.
14
Respuestas:
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.
fuente
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:
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.
fuente
javac
lí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.¿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.
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.
fuente
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).
fuente
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).
fuente
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 ...
fuente
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.
fuente
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 .
fuente