¿Convertir un intérprete a un compilador?

8

En primer lugar, sé que esta es una pregunta hecha por MUCHOS otros programadores antes que yo. Pero no pude encontrar ningún recurso utilizable que pudiera ayudarme.

Bueno, estoy creando un lenguaje de programación llamado "Light", la sintaxis es comparable a Python pero tiene un concepto estricto orientado a objetos.

He hecho un intérprete (en C ++) para este lenguaje todavía, mi problema es cómo convertir esto en un ejecutable. (O simplemente: ¿cómo hago un compilador?)

Gracias por tu atención

PD: He encontrado algunos enlaces a un tutorial muy antiguo, pero está en Pascal ...

EDITAR: Bueno, bueno. Ahora he encontrado un tutorial adecuado para C ++. Sobre el proyecto: Ha habido algunos cambios. Ahora el idioma se llama "Q". (Punto kju).

LaVolpe
fuente
primero aprenda el idioma de destino, luego vea cómo traduciría los bloques de código básicos de su idioma al otro idioma
ratchet freak
1
¿Está "simplemente" tratando de escribir un compilador (con los conocimientos previos de la implementación previa de un intérprete para el mismo idioma), o literalmente está tratando de convertir su intérprete en un compilador? Tu fraseo me está dando ideas ;-)
44
¿Una proyección de Futamura?
Dan D.
1
Eso es trivial: solo especialice a su intérprete contra un código fuente particular para obtener su versión compilada.
SK-logic
La pregunta es sobre la técnica llamada "compilador de rastreo"
Dmitry Ponyatov

Respuestas:

12

El primer par de pasos lexing / parsing (y análisis, dependiendo de cómo esté estructurado) puede ser el mismo. Pero necesitará convertir su representación en una representación generadora de código. Normalmente, LLVM se usa para aficionados, ya que es prácticamente la única biblioteca de generación de código gratuita remotamente decente.

DeadMG
fuente
Esto es exactamente lo que iba a escribir, pero lo conseguiste primero. Tener un +1.
Mason Wheeler
3
Incorrecto. Simplemente emitir C (o C ++, o lo que sea) es mucho más popular para los proyectos de compilación de aficionados. LLVM es mucho más complicado. Y JVM o .NET no son peores que LLVM para este propósito.
SK-logic
Esos compiladores no producen ejecutables, lo que el OP sí quiere. En cuanto a .NET / JVM, realmente depende de la semántica de su lenguaje.
DeadMG
1
@DeadMG, ghcpor ejemplo, es perfectamente capaz de producir ejecutables a través de C. Además de cientos de otros compiladores basados ​​en C. ¿Tu religión te prohíbe usar popen(...)en un compilador? Entonces tienes que tirar a la basura gcc. En cuanto a .NET, a diferencia de JVM, es capaz de satisfacer una gran variedad de semánticas, debido a sus características inseguras.
SK-logic
Usé LLVM (con enlaces de python) y funcionó de maravilla. :)
LaVolpe
4

Si todo lo que realmente desea es un ejecutable, puede agregar el script al final de un ejecutable de intérprete y hacer que lo ejecute.

Ver: /programming/5795446/appending-data-to-an-exe

Alternativamente, puede hacer que el intérprete cargue el código de un archivo en el mismo directorio que el intérprete y obtenga en gran medida el mismo resultado, solo con varios archivos.

Un verdadero compilador convertiría el código a otro idioma y usaría el compilador para ese idioma. Pero si solo desea distribuir ejecutables, no hay necesidad de hacerlo.

Winston Ewert
fuente
Bueno, sé que esta forma de empacar :) lo usó para Python (antes de escuchar sobre py2exe). Para mí esto es trampa y el otro problema es el rendimiento. Mi lenguaje como es ahora es de bajo nivel PERO estrictamente orientado a objetos.
LaVolpe
definitivamente no hace compilador, solo intérprete incrustado
Dmitry Ponyatov
1
@DmitryPonyatov, ¿sintió la necesidad de comentar casi siete años después diciendo lo que ya había dicho en mi respuesta?
Winston Ewert
3

También puede considerar usar System.Reflection.Emit desde el tiempo de ejecución .NET para generar un ejecutable .NET. Esto le dará acceso a un entorno orientado a objetos existente que ya le ha resuelto algunos problemas, y el exe resultante puede ser independiente de la plataforma. El tiempo de ejecución compilará el código intermedio en el .exe al código de la máquina según sea necesario, por lo que el rendimiento debe ser comparable al que obtendría compilando directamente al código nativo.

Vincent Povirk
fuente
Probablemente sea una buena idea, pero diseñé mi lenguaje para que sea de bajo nivel en algún momento;) Ahora estoy tratando de investigar la Documentación de Intels de OpCodes.
LaVolpe
0

Está preguntando acerca de la técnica conocida como "compilador de rastreo": el intérprete recopila información sobre la ejecución del código y construye de manera incremental el código de bajo nivel utilizando los datos recopilados.

https://en.wikipedia.org/wiki/Tracing_just-in-time_compilation

https://stefan-marr.de/papers/oopsla-marr-ducasse-meta-tracing-vs-partial-evaluation/

La diferencia con el JIT clásico es el hecho de que los datos de rastreo recopilados y el código compilado se conservan de cada ejecución de un programa, lo que le brinda no solo el código de máquina ejecutable sino también la optimización de datos reales (o de capacitación). El primer paso es un conjunto de pruebas, que deben pasar todas las ramas del programa, para crear código para cada parte de su programa. Los siguientes son programas que se ejecutan en datos reales (uso de producción), que recopila y aplica optimizaciones (cosas como el orden de sucursales a los casos más utilizados).

Este método es mucho más complejo de implementar que un esquema de construcción de compilador clásico, por lo que no se usa con frecuencia y es complejo encontrar un buen conjunto de tutoriales sobre cómo hacer un compilador similar.

Dmitry Ponyatov
fuente