He creado varios compiladores escritos a mano para lenguajes muy simples, pero ahora quiero intentar desarrollar un lenguaje dinámico, similar a un Python o Ruby simplificado. Sin embargo, fue fácil para mí entender cómo funcionan los compiladores. Los compiladores primitivos solo traducen. Pero no puedo hacer esto si el lenguaje es dinámico. Tengo que escribir un intérprete o VM que haga un seguimiento de la información en tiempo de ejecución y me ponga mucho más trabajo.
En resumen, ¿hay algún recurso que deba consultar considerando que sé cómo funcionan los compiladores pero quiero migrar para crear un intérprete? Hay algunas máquinas virtuales para los lenguajes dinámicos, pero no tengo ningún problema con el mío. Todo esto es solo para mi experiencia personal.
Estoy buscando información sobre cómo pasar de un compilador a un intérprete. Si ya he hecho un compilador para el lenguaje X pero ahora qué escribir un intérprete, ¿qué hay que hacer? ¿Hay algún recurso que vaya sobre el proceso?
No quiero recursos amplios o abstractos que analicen cómo funcionan los compiladores o las máquinas virtuales. Tengo muchos libros de texto sobre el tema. Todos los recursos que encontré en línea suponen que tiene 0 experiencia y, por lo tanto, comienzan con un análisis léxico o sintáctico o son extremadamente abstractos. Tengo un compilador que funciona, pero ahora quiero convertir esto en un intérprete y agregar funciones dinámicas al lenguaje.
No pude encontrar recursos en este proceso, puede tener un alcance demasiado limitado o recursos en el "back end" de un intérprete sin ser demasiado teórico, por eso publiqué aquí.
fuente
Respuestas:
Primero aprenda sobre la implementación de intérpretes. Recomiendo PLAI (Lenguajes de programación: aplicación e interpretación) . Llega a la carne de la interpretación rápidamente sin detenerse demasiado en la sintaxis.
Para su idioma, podrá reutilizar el front-end del compilador (analizador, en su mayoría) y la biblioteca de tiempo de ejecución (GC, estructuras de datos, operaciones primitivas, etc.).
Por supuesto, también puede implementar un lenguaje dinámico con un compilador que produce código que manipula (algunas de) las mismas estructuras de datos que usaría en un intérprete. Por ejemplo, en un intérprete puede implementar variables globales como una tabla hash indexada por cadenas. En un compilador, compilaría referencias de variables globales en el código que realiza la búsqueda utilizando la misma tabla. Por el contrario, podría compilar variables léxicas en una representación más eficiente (argumentos "nativos" y referencias de estructura de cierre).
fuente
Si desea aprender los conceptos básicos de la implementación de un intérprete para un lenguaje dinámico, no puedo imaginar un mejor lugar para comenzar que los orígenes del primer lenguaje de programación dinámico e interpretado: Lisp.
En su artículo original de 1960 , John McCarthy definió 5 funciones primitivas necesarias para un Lisp. Por supuesto, McCarthy solo pretendía que su artículo sobre Lisp fuera un ejercicio académico; Fue un estudiante de posgrado quien participó
eval
en la asamblea y creó el primer intérprete Lisp. Paul Graham identifica siete primitivas : cita, átomo, ecualización, contras, automóvil, cdr y cond.La cuestión es que realmente puedes implementar Lisp en cualquier idioma; una vez que lo implementa
eval
, es fácil configurar un REPL y tiene un intérprete interactivo . Las personas se aburrieron o tuvieron la curiosidad de implementar Lisps en C, Java, Ruby, Python y muchos otros lenguajes. Y no siempre a propósito; Es importante recordar la Décima Regla de Greenspun :No digo que su objetivo final sea una implementación de Lisp; pero la homoiconicidad tiene sus beneficios al aprender a implementar un lenguaje dinámico; ¿Por qué lidiar con problemas de sintaxis cuando puede aprender en un idioma en el que la sintaxis idiomática es idéntica a la AST de un idioma que utiliza un lexer / parser?
De todos modos ... solo una sugerencia. Pero es con razón que la mayoría de los grandes lenguajes de programación desde C tienen al menos un poco de la naturaleza Lisp.
fuente
Puse esto (~ 600 líneas de C #) en el dominio público, que admite quote / list / apply / eval / test / etc, y permite personalizar fácilmente una sintaxis tipo Lisp y / o las funciones semánticas incorporadas:
https://repl.it/CdjV/3
P.ej:
«HTH
fuente
Suponiendo que conoce un poco de Scheme (por ejemplo, si ha leído SICP ) o Lisp, le recomiendo el libro Lisp In Small Pieces de Queinnec . Explica varias variantes de intérpretes y compiladores similares a Lisp (incluso a bytecode o C).
Además, lea la Pragmática del lenguaje de programación de Scott , el último Libro del dragón , el manual de GC , los Tipos de Pierce y los lenguajes de programación .
Entonces, la evaluación parcial (y las proyecciones de Futamura) y el estilo de paso de continuación podrían ser relevantes.
fuente