2011-05-03 12 views
9

muchos (¿pueden ser todos?) El lenguaje de programación consiste en el lenguaje de ensamblajecómo se implementó lisp en lenguaje ensamblador?

¿cómo se implementa lisp en el lenguaje de ensamblador?

¿hay alguna buena referencia, manual, tutorial o palabra clave para google?

¿alguna regla/convención oficial para construir su propia implementación de lisp?

como recursión de cola debe seguir alguna regla de realización o algo ..

gracias

+2

Esto no tiene ningún sentido – Mehrdad

Respuesta

21

Aunque los otros comentarios y publicaciones son correctos, esta pregunta es demasiado vaga y tal vez un poco confusa, no puedo dejar de compartir algunas recomendaciones. He recopilado varios enlaces y libros sobre la implementación de Lisp ya que recientemente he desarrollado cierta fascinación con la implementación del lenguaje.Es un tema profundo, por supuesto, pero leer cosas relacionadas con Lisp es especialmente convincente porque puedes omitir muchas de las lecturas intensas en el análisis si implementas un compilador Lisp o un intérprete en Lisp, y simplemente usas read. Esto permite a los autores llegar rápidamente a la compilación o interpretación. Estas recomendaciones son libros que he leído o comenzado, o que estoy leyendo, y que tratan principalmente con Scheme, no con Common Lisp, pero que pueden ser de algún interés.

Si no tiene experiencia en la implementación del lenguaje y nunca ha tenido el placer de leer acerca de los clásicos "evaluadores metacirculares" de Lisp y Scheme, recomendaría Structure and Interpretation of Computer Programs. Si ha visto Lisp-in-Lisp (o Scheme-in-Scheme ...) puede saltar adelante. En los dos últimos capítulos de SICP, los autores presentan algunos intérpretes diferentes para Lisp/Scheme y algunas variantes, así como un compilador de código de bytes y una máquina virtual. Es simplemente un libro brillante, y gratis.

Si no tiene tiempo para leer SICP, o si no desea recorrerlo solo para acceder a los capítulos de interpretación y compilación, le recomiendo The Little Schemer. Aunque es muy corta y está destinada a los recién llegados a Lisp y Scheme, si nunca has visto un intérprete de Lisp escrito en Lisp, presentan uno, y es un libro bastante encantador, pero podría no serlo para todos debido al estilo lindo. .

Hay otro libro gratis en Scheme similar al SICP, llamado An Introduction to Scheme and its Implementation, que no he leído, pero he usado como referencia para algunos bits. Hay secciones sobre intérpretes y compiladores allí, y parece ir un poco más profundo que SICP, tratando con cosas más peludas como el análisis también. Quizás necesite un editor, pero es una oferta impresionante, no obstante.

Con una buena idea de cómo hacer Lisp en Lisp, puedes acercarte a implementar Lisp en un nivel inferior.

Lisp in Small Pieces se recomienda con frecuencia. He leído la mayor parte, y puedo decir que definitivamente es un gran libro, lleno de cosas insignificantes. Volveré sobre esto con un peine fino, porque es fácil raspar cuando no entiendes algo. También tuve problemas para ejecutar el código del sitio del autor; si lo obtiene, le recomiendo usar Gambit Scheme y ejecutar el código que se basa en Meroonet con Meroon, de la distribución this. Lisp en Small Pieces presenta una serie de intérpretes escritos en Scheme, así como un compilador de código de bytes y un compilador a C.

Lisp en Small Pieces se mueve rápido, y es bastante denso. Si es demasiado para ti, quizás comiences con The Essentials of Programming Languages. He leído algo y es bastante bueno, pero son más intérpretes. Aparentemente, una de las ediciones más antiguas (¿1º? No estoy seguro ...) incluía un compilador. Parece haber muchos cambios entre las 3 ediciones, pero el primero es súper barato en Amazon, así que échale un vistazo.

En cuanto a la compilación de C, esta es una especie de tema denso con muchas partes peludas. La compilación para C saca a relucir todos estos problemas raros de las esquinas, como la optimización de las interceptaciones y los cierres, las continuaciones de primera clase y la recolección de basura, pero es bastante interesante, y muchas implementaciones "reales" de Scheme siguen esta ruta. La presentación de Marc Feeley sobre esto es bastante interesante, titulada The 90 Minute Scheme to C compiler.

Tengo menos recursos en la compilación hasta el ensamblaje, pero a menudo hay un documento recomendado que presenta la compilación de Scheme en x86, llamado An Incremental Approach to Compiler Construction.. Asume poco del lector, pero descubrí que simplemente va demasiado rápido y no completa suficientes detalles. Quizás tengas mejor suerte.

Gran parte de la recomendación anterior proviene de este monstruoso comentario en Hacker News desde hace más de un año, desde mahmud. Hace referencia a una cantidad de recursos ML y una compilación utilizando continuaciones.No he llegado tan lejos en mi estudio, así que no puedo decir lo que es bueno o no. Pero es un comentario increíblemente valioso. Los trabajos mencionados incluyen "Compilación con Continuaciones" de Andrew Appel y el documento "Técnicas de Colección de Basura Uniprocesador" de Paul Wilson.

¡Buena suerte!

+2

vea también el Esquema 9 de Empty Space: http://www.lulu.com/product/paperback/scheme-9-from-empty-space/13002199 –

+0

El libro PAIP (Paradigmas de la Programación de IA) por Peter Norvig contiene un Esquema compilador en Common Lisp. –

+0

Sí, pensé en incluir PAIP, pero aún no lo he leído todo. ¿Qué emite el compilador? – spacemanaki

-2

Esa es una gran pregunta a responder bien.

Respuesta corta: JIT.

Respuesta grande: Dragon book.

+3

¿Estás seguro de que esos recursos son relevantes para Lisp? –

+0

Un compilador lisp (no un intérprete) es un compilador regular con soporte jit. No es posible estudiar jit sin el conocimiento regular del compilador. –

+4

La mayoría de las implementaciones de Lisp con un compilador no usan una compilación JIT en absoluto. No, los compiladores Lisp tampoco son compiladores 'normales' como se describe en el libro del Dragón. –

2

Su pregunta se basa en suposiciones muy desactualizadas. Actualmente, casi ninguna implementación de idioma está escrita en lenguaje ensamblador, y no conozco ninguna implementación de Lisp. Además de las implementaciones de autohospedaje, C es un lenguaje de implementación común en estos días.

Si desea ver una representación en lenguaje ensamblador de una función de lisp, está el DISASSEMBLE function.

7

Lo pensé un poco en el pasado (luego recurrí al uso de un kernel C en su lugar). Por supuesto no hay un "montaje" sola, pero para x86/32 bits esto es lo que estaba pensando:

valores básicos se almacenan en los nodos de 64 bits con tres bits más baja utilizada como etiqueta con el siguiente significado:

000 -> cell (64 bits are basically two pointers: car/cdr) 
001 -> fixnum (64-3-1 bits usable for values) 
010 -> vector (32-3 bits for size and 32 bit for pointer to first element) 
011 -> symbol (32 bits pointing to values in global env, 32 pointing to name) 
100 -> native code (32 bits pointing to executable machine code, 32 bits to args) 
101 -> float (using 64-3-1 bit by dropping 4 bits from mantissa) 
110 -> string (using 32-3 bits for size and 32 bits pointing to bytes) 
111 -> struct (32 bits pointing to definition, 32 bits pointing to content) 

Se pueden utilizar 3 bits al considerar los punteros si se supone que todas las asignaciones son un múltiplo de 8 bytes (razonable con un tamaño de celda de 8 bytes). Se necesitaría un poco más para implementar un recolector de basura simple (el bit "vivo"). En la implementación de C, terminé asignando este bit en varias partes (por ejemplo, un bit menos significativo de 32 bits más altos si eso era un puntero) dependiendo del tipo de nodo.

Mi idea era tener memoria de dos tipos: "memoria de nodos" (con el diseño descrito anteriormente) que se asignó en páginas y reutilizar con una lista libre, y "memoria binaria" para cadenas de tamaño variable/código/matrices.

Se necesita un código específico dependiendo del tipo de nodo para implementar una función touch que marque recursivamente como nodos vivos referidos por un nodo activo.

Todo esto es, por supuesto, sólo un enfoque ingenuo, pero todavía tiene que trabajar en "C" y estoy seguro de que podría haber hecho que también en el montaje (mi código C está utilizando void * todas partes así que es básicamente una ensamblador portátil de 32 bits). Para la pereza en mi implementación C solo usé 32 bits para flotantes y enteros (usando los 32 bits más altos) en lugar de usar todos los bits disponibles.

6

Eche un vistazo a Clozure Common Lisp para ver un ejemplo de lenguaje ensamblador utilizado para implementar un lisp. Clozure CL se implementa principalmente en Common Lisp, pero hay un kernel escrito en C y algunas funcionalidades de bajo nivel en el ensamblado.

Por ejemplo, aquí es una macro desde compilador/X86/x86-lapmacros.lisp la implementación de una función primitiva CAR en hardware x86, con la instrucción de un montaje para 32 y 64 bits respectivamente:

(defx86lapmacro %car (src dest) 
    (target-arch-case 
     (:x8632 
      `(movl (@ x8632::cons.car (% ,src)) (% ,dest))) 
     (:x8664 
      `(movq (@ x8664::cons.car (% ,src)) (% ,dest))))) 

Como se muestra, el código de ensamblaje se codifica a sí mismo en forma de Lisp. La migración a otra plataforma implica (entre otras cosas) traducir estas operaciones de bajo nivel a otro lenguaje ensamblador y compilación cruzada para crear un tiempo de ejecución en la nueva plataforma.

ECL (Embeddable Common Lisp) toma otro enfoque mediante la compilación en C. Esto hace que sea conveniente para portar la implementación a las plataformas que tienen un compilador de C.

Cuestiones relacionadas