¿Por qué los compiladores de alojamiento propio se consideran un rito de iniciación para nuevos idiomas?

30

Ahora he escuchado en varios lugares que la gente espera que los idiomas usen, o al menos tengan, un compilador de alojamiento propio para merecer respeto.

Tengo curiosidad de por qué es esto. Un compilador parece una pieza de software muy importante para escribir, e imagino que no todos los idiomas son adecuados para crearlos. ¿No tendría más sentido gastar el esfuerzo trabajando en algo que dé mejores resultados?

Chris Cooper
fuente
17
"Un compilador parece una pieza de software muy importante para escribir, e imagino que no todos los idiomas son adecuados para crearlos". Consideraría que esta es una muy buena razón para intentar escribir un compilador en un nuevo idioma, a saber para demostrar que el idioma está a la altura de la tarea.
Giorgio
13
A menos que sea un lenguaje de propósito especial, un lenguaje que no sea adecuado para escribir un compilador probablemente tampoco sea adecuado para lo que quiero hacer.
CodesInChaos
3
AFAIK, esto no siempre es cierto para Fortran. Varios compiladores de Fortran (por ejemplo, gfortrande GCC ...) no están codificados en Fortran.
Basile Starynkevitch

Respuestas:

29

¿No tendría más sentido gastar el esfuerzo trabajando en algo que dé mejores resultados?

¿Como que?

Lo bueno de los compiladores es que no tienen muchas dependencias. Esto los convierte en buenos candidatos para un nuevo idioma que probablemente aún no tenga una biblioteca estándar muy grande o diversa.

Mejor aún, requieren una variedad de cosas, a la vez que están bien estudiadas. La variedad ayuda a garantizar que su ejemplo pruebe varias partes del idioma. Estar bien estudiado significa que tienes otros compiladores con los que comparar, además de dar más crédito a los tipos académicos que sabes lo que estás haciendo.

Y aunque los compiladores parecen un montón de trabajo, son bastante pequeños en el gran esquema de las cosas. Si los implementadores del lenguaje ni siquiera pueden hacer algo que hayan hecho antes en el nuevo lenguaje, ¿cómo van a hacer cosas nuevas? ¿Cómo van a manejar las cosas realmente grandes como las bibliotecas estándar o un IDE?

Telastyn
fuente
Solo como nota al margen, me gustaría mencionar que a pesar de ser amable, todavía hay una variedad de razones por las que un compilador podría estar escrito en otro idioma. Por ejemplo, la mayoría de los motores de JavaScript no están escritos en JavaScript. Hay muchas razones para esto: integración con otro software, vinculación a bibliotecas / dependencias existentes, herramientas superiores, rendimiento, código heredado ... A veces, la compilación automática del lenguaje es buena, pero aún tiene sentido mantener el compilador central en otro. Sin embargo, el lenguaje en sí mismo tiene sentido. Es solo que generalmente no puede darse el lujo de volver a desarrollar un ecosistema completo.
Dagnelies
2
@arnaud Y el hecho de que un compilador de Javascript requeriría un entorno Javascript, que no se puede escribir en Javascript porque Javascript requiere un entorno Javascript, <repetir paradójicamente> , porque el sistema operativo no proporciona un entorno Javascript (y si era, no estaría escrito en Javascript).
Qix
3
@Qix en.wikipedia.org/wiki/Bootstrapping_%28compilers%29 Pero principalmente no hay razón para usarlo. Es ampliamente conocido como un lenguaje pobre, los navegadores evitan usarlo para compilar porque tienen el control de la situación :), mientras que el resto de nosotros no tiene otra opción en la web.
Den
3
No estoy tan seguro sobre el reclamo "no tengo muchas dependencias". Eso podría ser cierto para el compilador front-end . Pero tan pronto como tenga un AST, rodar su propio optimizador y generador de código no parece una ruta prometedora. Además del hecho de que las técnicas modernas de optimización requieren sofisticados motores lógicos formales para los que uno podría desear usar una biblioteca de terceros, no hay razón para reinventar la rueda para cada nuevo idioma en lugar de construir sobre una base sólida de la industria como GCC o LLVM.
5gon12eder
30

El objetivo de tener un compilador en el idioma que se está compilando es a menudo parte de la práctica de " comer su propia comida para perros ". Demuestra al mundo que usted considera que el lenguaje, el compilador y el ecosistema de los módulos y herramientas de soporte son "lo suficientemente buenos para un trabajo serio" o "listos para la producción".

También tiene el efecto virtuoso de obligar a las personas más cercanas al lenguaje, al compilador y al diseño de tiempo de ejecución a enfrentar directamente los efectos de todas las decisiones que han tomado y las prioridades de desarrollo que han elegido: verrugas y todo. Esto a menudo conduce a un grupo central que no solo comprende el entorno del lenguaje en teoría, sino que tiene una amplia experiencia práctica en el uso del lenguaje / herramientas en el crisol de condiciones difíciles de palabras reales.

Jonathan Eunice
fuente
1
para completar: comer su propia comida para perros ; ver alimentado con perros (adj.) o alimentando con perros (verbo)
Qix
17

Las personas crean nuevos lenguajes de propósito general por una razón principal: odian al menos una cosa sobre cualquier otro idioma. Es por eso que tantos idiomas no despegan. Tienes una gran idea para un lenguaje que mejoraría tu vida de programación, pero debes hacer la primera implementación en un lenguaje que te moleste al menos de una manera. El autohospedaje significa que ya no tienes que trabajar en ese viejo idioma molesto. Es por eso que los creadores de un lenguaje trabajan hacia ese paso y lo ven como un hito importante.

Muchas de las características del lenguaje se ven bien en el papel, pero cuando empiezas a usarlas en un proyecto real, comienzas a ver sus limitaciones. Por ejemplo, muchos idiomas no tienen un buen soporte Unicode al principio. Completar un proyecto grande ayuda a garantizar que se hayan enfrentado y abordado muchos de esos tipos de situaciones, y un compilador de alojamiento propio es un proyecto tan bueno como cualquier otro. Es por eso que otras personas además de los creadores del lenguaje lo ven como un hito importante.

Eso no significa que sea el único hito digno de mención. Hay una funcionalidad que no es ejercida por un compilador, como la integración de bases de datos, interfaces gráficas, redes, etc.

Karl Bielefeldt
fuente
Siento que un idioma (nativo) es un lenguaje cuando puede compilarse y se le puede transferir un kernel de Linux (ya que abarca la mayoría / todas las tareas necesarias para que funcionen la mayoría de los sistemas operativos modernos).
Qix
Sin embargo, no es realmente necesario un buen soporte Unicode para escribir un compilador.
Paŭlo Ebermann
11

Steve Yegge escribió una gran publicación de blog que, de manera indirecta, aborda esto.

Gran punto # 1: los compiladores abarcan casi todos los aspectos de la informática. Son un curso de nivel superior porque necesitas saber todas las demás cosas que aprendes en el plan de estudios de informática para comenzar. ¿Estructuras de datos, búsqueda y clasificación, rendimiento asintótico, coloración gráfica? Todo está ahí.

Hay una razón por la que Knuth ha estado trabajando en su monumental (e interminable) "Arte de la programación de computadoras" durante varias décadas, a pesar de que comenzó como (solo) un libro de texto de compilación. De la misma manera que Carl Sagan dijo: "Si desea hacer un pastel de manzana desde cero, primero debe inventar el universo", si desea escribir un compilador, primero debe ocuparse de casi todos los aspectos de la informática.

Eso significa que si el compilador es autohospedado, entonces es bastante seguro que pueda hacer lo que necesito, sin importar lo que esté haciendo. Por el contrario, si no escribió un compilador en su idioma, hay una buena posibilidad de que se pierda algo que es realmente importante para alguien, porque los implementadores del lenguaje nunca tuvieron que escribir un programa que les obligue a pensar en todos esos problemas.

Gran punto # 2: desde 30,000 pies, un sorprendente número de problemas se parecen a los compiladores.

Los compiladores toman una secuencia de símbolos, calculan su estructura de acuerdo con algunas reglas predefinidas específicas del dominio y las transforman en otra secuencia de símbolos. Suena bastante general, ¿no? Bueno sí.

Ya sea que esté en el equipo de Visual C ++ o no, a menudo tendrá que hacer algo que parezca parte de un compilador. Lo hago literalmente todos los días.

A diferencia de la mayoría de las otras profesiones, los programadores no solo usan herramientas, sino que construyen sus propias herramientas. Un programador que no puede (debido a la falta de habilidad o la falta de herramientas utilizables con las que construir otras herramientas) escribirá herramientas para siempre, limitado a las herramientas que alguien más proporciona.

Si un lenguaje "no es adecuado para crear" programas que pueden tomar una secuencia de símbolos, aplicarles reglas y transformarlos en otra secuencia de símbolos, eso suena como un lenguaje bastante limitado, y no uno que sería útil a mi.

(Afortunadamente, no creo que haya muchos lenguajes de programación que no sean adecuados para la transformación de símbolos. C es probablemente uno de los peores lenguajes que se usan actualmente, sin embargo, los compiladores de C suelen ser autohospedados, por lo que nunca se detuvo a nadie).

Una tercera razón por la que terminaré, por experiencia personal, no mencionada por Yegge (porque no estaba escribiendo sobre "por qué auto-anfitrión"): sacude los errores. Cuando escribes un compilador, eso significa que cada vez que lo compilas (no solo cada vez que lo ejecutas ), dependes de que funcione y funcione correctamente contra una base de código de tamaño decente (el compilador en sí).

Este mes he estado usando un compilador no autohospedado relativamente nuevo y famoso (probablemente puedas adivinar cuál), y no puedo pasar 2 días sin segfalarlo. Me pregunto cuánto los diseñadores realmente tuvieron que usarlo.

DefinitivamenteNotSteve
fuente
8

Si desea que un compilador para el lenguaje X sea autohospedado, primero debe implementarlo en otro idioma, digamos Y, de modo que tome la entrada para el lenguaje X y escupe código ensamblador, o algún código intermedio, o incluso código objeto para la máquina en la que se ejecuta el compilador. Desea elegir el idioma Y para que sea lo más similar posible al idioma X, ya que en algún momento traducirá el código escrito en Y a X.

Pero no desea escribir más del compilador en el lenguaje Y de lo necesario, por lo que, para comenzar, implementa solo un subconjunto del lenguaje, eliminando construcciones redundantes. En el caso de un lenguaje tipo 'C', while pero no for o do while . si pero no caso u terciario op. Sin estructuras ni uniones ni enumeraciones. Etc. Lo que le queda es suficiente lenguaje para escribir un analizador sintáctico y un generador de código rudimentario para el lenguaje X. Luego verifique la salida. Otra vez.

Una vez que tenga esto funcionando, puede reescribir la fuente del compilador que se escribió en el lenguaje Y en el lenguaje X, y compilar la fuente del idioma X usando el compilador escrito en el lenguaje Y. La salida será un nuevo compilador escrito en el nuevo idioma X que compila el lenguaje X, es decir, ahora es autohospedaje. Sin embargo, no está completo ya que solo implementó un subconjunto del idioma en el lenguaje Y.

Así que ahora agrega las características que faltan, probando cada una (o grupo de características) para que generen el código correcto. es decir, una vez que la característica se implementa en el compilador, puede escribir programas de prueba usando las nuevas características, compilarlas y probarlas, pero aún no debe usarlas en la fuente del compilador. Una vez que se verifican las nuevas características, puede usar estas nuevas características en la fuente del compilador en sí, tal vez reemplazando parte del código original escrito en el subconjunto de idiomas, vuelva a compilar la fuente del compilador utilizando la versión con las nuevas características.

Ahora tiene un mecanismo para agregar nuevas funciones al lenguaje y, una vez que la generación de código para las funciones se ha verificado correctamente, se pueden usar en la próxima generación del compilador.

Hace unos 60 años, cuando las computadoras llegaron por primera vez a la escena (y más tarde cuando llegaron los microprocesadores), no había otros idiomas adecuados para implementar el compilador inicial. Entonces, los primeros compiladores tuvieron que escribirse en código ensamblador, y luego, cuando se estaba ejecutando suficiente compilador, el código ensamblador sería reemplazado por la versión escrita en un nuevo lenguaje. ¿Ningún ensamblador tampoco? Todo el procesador bajó otro nivel, con el ensamblador inicialmente escrito en código máquina .

tcrosley
fuente
2

¿Es posible producir un lenguaje de programación que no esté bien diseñado para escribir un compilador pero que esté bien diseñado para algún otro propósito?

Mirando un lenguaje como SQL, supongo que la respuesta es sí. Pero los idiomas de esa naturaleza no son de uso general.

Jaydee
fuente
1
Desafío aceptado: escribir un compilador de C en SQL.
Qix
2

¿Quién dice eso? ... de todos modos, es solo una opinión. Algunos podrían estar de acuerdo, otros no, no hay correcto o incorrecto aquí. Algunos idiomas tienen compiladores escritos en sí mismos, otros no. Lo que sea.

Sin embargo, creo que es un buen ejercicio / prueba de concepto si un lenguaje es capaz de "autocompilarse" ... es simplemente ... agradable ... y demuestra que el lenguaje es adecuado para hacer algunas cosas complejas.

También me gustaría mencionar que, a pesar de ser amable, todavía hay una variedad de razones por las que un compilador podría estar escrito en otro idioma. Por ejemplo, la mayoría de los motores de JavaScript no están escritos en JavaScript. Hay muchas razones para esto: integración con otro software, vinculación a bibliotecas / dependencias existentes, herramientas superiores, rendimiento, código heredado ... A veces, la compilación automática del lenguaje es buena, pero aún tiene sentido mantener el compilador central en otro. Sin embargo, el lenguaje en sí mismo tiene sentido. Es solo que generalmente no puede darse el lujo de volver a desarrollar un ecosistema completo.

dagnelies
fuente
2

Clang está escrito en C ++. No sería demasiado difícil reescribir el compilador Clang Objective-C en Objective-C, pero sería bastante inútil. Cualquier cambio en el compilador de C ++ tendría que rehacerse en Objective-C y viceversa. ¿Entonces por qué?

Ahora hay un compilador Clang Swift. Seguramente ese compilador podría reescribirse en Swift. ¿Pero qué propósito sería? ¿Para demostrar que el lenguaje es lo suficientemente poderoso como para escribir un compilador en él? A nadie le importa si puedes escribir compiladores en Swift. A la gente le importa si puede escribir interfaces de usuario en Swift, y usted sí puede hacerlo .

Si tiene un compilador bien probado que se puede adaptar fácilmente para compilar diferentes idiomas, no tiene sentido reescribirlo en diferentes idiomas, a menos que la reescritura en un idioma diferente haga que sea más fácil trabajar con el compilador. Y si tendría sentido escribir Clang en Swift, por ejemplo, entonces el estruendo C, C ++ y Objective-C compiladores sería todo ser escrito en Swift.

Hay cosas más importantes que hacer que demostrar que puedes escribir un compilador en algún lenguaje de programación.

gnasher729
fuente
1

Muestra que el idioma es capaz de procesar el procesamiento de cadenas complejas y traducirlo a otro idioma / interpretarse a sí mismo.

En el proceso de creación de un compilador (el primer gran proyecto) habrá problemas que saldrán a la luz.

monstruo de trinquete
fuente