De Wikipedia, la enciclopedia libre
Saltar a navegación Saltar a búsqueda

En informática , un intérprete es un programa informático que ejecuta directamente instrucciones escritas en un lenguaje de programación o de scripting , sin necesidad de que hayan sido compiladas previamente en un programa de lenguaje de máquina . Un intérprete generalmente usa una de las siguientes estrategias para la ejecución del programa:

  1. Analizar el código fuente y realizar su comportamiento directamente;
  2. Traduzca el código fuente en una representación intermedia eficiente y ejecútelo inmediatamente;
  3. Ejecute explícitamente el código precompilado almacenado [1] creado por un compilador que es parte del sistema de interpretación.

Las primeras versiones del lenguaje de programación Lisp y minicomputadora y dialectos de BASIC microordenador serían ejemplos del primer tipo. Perl , Python , MATLAB y Ruby son ejemplos del segundo, mientras que UCSD Pascal es un ejemplo del tercer tipo. Los programas fuente se compilan con anticipación y se almacenan como código independiente de la máquina, que luego se vincula en tiempo de ejecución y es ejecutado por un intérprete y / o compilador (para sistemas JIT ). Algunos sistemas, como Smalltalk y las versiones contemporáneas de BASIC y Java , también pueden combinar dos y tres.[2] También se han construido intérpretes de varios tipos para muchos lenguajes tradicionalmente asociados con la compilación, como Algol , Fortran , Cobol , C y C ++ .

Si bien la interpretación y la compilación son los dos medios principales por los que se implementan los lenguajes de programación, no son mutuamente excluyentes, ya que la mayoría de los sistemas de interpretación también realizan algún trabajo de traducción, al igual que los compiladores. Los términos "lenguaje interpretado" o " lenguaje compilado " significan que la implementación canónica de ese lenguaje es un intérprete o un compilador, respectivamente. Un lenguaje de alto nivel es idealmente una abstracción independiente de implementaciones particulares.

Historia [ editar ]

Ya en 1952 se utilizaron intérpretes para facilitar la programación dentro de las limitaciones de las computadoras en ese momento (por ejemplo, una escasez de espacio de almacenamiento de programas o la falta de soporte nativo para números de punto flotante). También se utilizaron intérpretes para traducir entre lenguajes de máquina de bajo nivel, lo que permitió escribir código para máquinas que aún estaban en construcción y probarse en computadoras que ya existían. [3] El primer lenguaje de alto nivel interpretado fue Lisp . Lisp fue implementado por primera vez en 1958 por Steve Russell en una computadora IBM 704 . Russell había leído el artículo de John McCarthy y se dio cuenta (para sorpresa de McCarthy) de que la función de evaluación Lisp podía implementarse en código máquina. [4] El resultado fue un intérprete Lisp funcional que podría usarse para ejecutar programas Lisp, o más correctamente, "evaluar expresiones Lisp".

Compiladores versus intérpretes [ editar ]

Una ilustración del proceso de vinculación. Los archivos de objetos y las bibliotecas estáticas se ensamblan en una nueva biblioteca o ejecutable

Los programas escritos en un lenguaje de alto nivel son ejecutados directamente por algún tipo de intérprete o convertidos en código de máquina por un compilador (y ensamblador y enlazador ) para que la CPU los ejecute.

Si bien los compiladores (y ensambladores) generalmente producen código de máquina directamente ejecutable por hardware de computadora, a menudo (opcionalmente) pueden producir una forma intermedia llamada código objeto . Este es básicamente el mismo código específico de la máquina, pero aumentado con una tabla de símbolos con nombres y etiquetas para hacer que los bloques (o módulos) ejecutables sean identificables y reubicables. Los programas compilados normalmente utilizarán bloques de construcción (funciones) que se guardan en una biblioteca de dichos módulos de código objeto. Un enlazadorse utiliza para combinar archivos de biblioteca (prefabricados) con el (los) archivo (s) objeto (s) de la aplicación para formar un solo archivo ejecutable. Por lo tanto, los archivos de objeto que se utilizan para generar un archivo ejecutable a menudo se producen en diferentes momentos y, a veces, incluso en diferentes lenguajes (capaces de generar el mismo formato de objeto).

Un intérprete simple escrito en un lenguaje de bajo nivel (por ejemplo, ensamblador ) puede tener bloques de código máquina similares que implementan funciones del lenguaje de alto nivel almacenados y ejecutados cuando la entrada de una función en una tabla de búsqueda apunta a ese código. Sin embargo, un intérprete escrito en un lenguaje de alto nivel generalmente usa otro enfoque, como generar y luego recorrer un árbol de análisis , o generar y ejecutar instrucciones intermedias definidas por software, o ambos.

Por lo tanto, tanto los compiladores como los intérpretes generalmente convierten el código fuente (archivos de texto) en tokens, ambos pueden (o no) generar un árbol de análisis, y ambos pueden generar instrucciones inmediatas (para una máquina de pila , código cuádruple o por otros medios). La diferencia básica es que un sistema de compilación, que incluye un enlazador (integrado o separado), genera un programa de código de máquina independiente , mientras que un sistema de interpretación realiza las acciones descritas por el programa de alto nivel.

Por lo tanto, un compilador puede realizar casi todas las conversiones desde la semántica del código fuente al nivel de la máquina de una vez por todas (es decir, hasta que el programa tenga que cambiarse) mientras que un intérprete tiene que hacer parte de este trabajo de conversión cada vez que se ejecuta una declaración o función. . Sin embargo, en un intérprete eficiente, gran parte del trabajo de traducción (incluido el análisis de tipos y similares) se descarta y se realiza solo la primera vez que se ejecuta un programa, módulo, función o incluso declaración, por lo tanto, es bastante similar a cómo se ejecuta un intérprete. el compilador funciona. Sin embargo, un programa compilado aún se ejecuta mucho más rápido, en la mayoría de las circunstancias, en parte porque los compiladores están diseñados para optimizar el código y se les puede dar tiempo suficiente para esto. Esto es especialmente cierto para lenguajes de alto nivel más simples sin (muchas) estructuras de datos dinámicas, verificaciones ocomprobación de tipo .

En la compilación tradicional, la salida ejecutable de los enlazadores (archivos .exe o archivos .dll o una biblioteca, ver imagen) es típicamente reubicable cuando se ejecuta bajo un sistema operativo general, al igual que los módulos de código objeto, pero con la diferencia de que esta reubicación se realiza de forma dinámica en tiempo de ejecución, es decir, cuando el programa se carga para su ejecución. Por otro lado, los programas compilados y vinculados para pequeños sistemas embebidos suelen estar asignados estáticamente, a menudo codificados en una memoria flash NOR , ya que a menudo no hay almacenamiento secundario ni sistema operativo en este sentido.

Históricamente, la mayoría de los sistemas de interpretación han tenido un editor autónomo incorporado. Esto se está volviendo más común también para los compiladores (entonces a menudo llamado IDE ), aunque algunos programadores prefieren usar un editor de su elección y ejecutar el compilador, enlazador y otros. herramientas manualmente. Históricamente, los compiladores son anteriores a los intérpretes porque el hardware en ese momento no podía admitir tanto el intérprete como el código interpretado y el entorno de lotes típico de la época limitaba las ventajas de la interpretación. [5]

Ciclo de desarrollo [ editar ]

Durante el ciclo de desarrollo de software , los programadores realizan cambios frecuentes en el código fuente. Cuando se utiliza un compilador, cada vez que se realiza un cambio en el código fuente, deben esperar a que el compilador traduzca los archivos fuente alterados y el enlace.todos los archivos de código binario juntos antes de que se pueda ejecutar el programa. Cuanto mayor sea el programa, más larga será la espera. Por el contrario, un programador que usa un intérprete espera mucho menos, ya que el intérprete generalmente solo necesita traducir el código en el que se está trabajando a una representación intermedia (o no traducirlo en absoluto), por lo que requiere mucho menos tiempo antes de que se puedan realizar los cambios. probado. Los efectos son evidentes al guardar el código fuente y volver a cargar el programa. El código compilado generalmente se depura con menos facilidad, ya que la edición, compilación y vinculación son procesos secuenciales que deben realizarse en la secuencia adecuada con un conjunto adecuado de comandos. Por esta razón, muchos compiladores también tienen una ayuda ejecutiva, conocida como Makearchivo y programa. El archivo Make enumera las líneas de comando del compilador y enlazador y los archivos de código fuente del programa, pero puede tomar una entrada de menú de línea de comando simple (por ejemplo, "Make 3") que selecciona el tercer grupo (conjunto) de instrucciones y luego envía los comandos al compilador, y enlazador que alimenta los archivos de código fuente especificados.

Distribución [ editar ]

Un compilador convierte el código fuente en instrucciones binarias para la arquitectura de un procesador específico, lo que lo hace menos portátil . Esta conversión se realiza solo una vez, en el entorno del desarrollador, y luego el mismo binario se puede distribuir a las máquinas del usuario, donde se puede ejecutar sin más traducción. Un compilador cruzado puede generar código binario para la máquina del usuario incluso si tiene un procesador diferente al de la máquina donde se compila el código.

Un programa interpretado se puede distribuir como código fuente. Debe traducirse en cada máquina final, lo que lleva más tiempo pero hace que la distribución del programa sea independiente de la arquitectura de la máquina. Sin embargo, la portabilidad del código fuente interpretado depende de que la máquina de destino tenga realmente un intérprete adecuado. Si es necesario proporcionar el intérprete junto con la fuente, el proceso de instalación general es más complejo que la entrega de un ejecutable monolítico, ya que el intérprete en sí es parte de lo que debe instalarse.

El hecho de que el código interpretado pueda ser leído y copiado fácilmente por humanos puede ser motivo de preocupación desde el punto de vista de los derechos de autor . Sin embargo, existen varios sistemas de cifrado y ofuscación . La entrega de código intermedio, como el código de bytes, tiene un efecto similar al de la ofuscación, pero el código de bytes se puede decodificar con un descompilador o desensamblador . [ cita requerida ]

Eficiencia [ editar ]

La principal desventaja de los intérpretes es que un programa interpretado normalmente se ejecuta más lento que si se hubiera compilado . La diferencia de velocidades puede ser pequeña o grande; a menudo un orden de magnitud y, a veces, más. Por lo general, se tarda más en ejecutar un programa con un intérprete que en ejecutar el código compilado, pero puede llevar menos tiempo interpretarlo que el tiempo total necesario para compilarlo y ejecutarlo. Esto es especialmente importante cuando se crea un prototipo y se prueba el código cuando un ciclo de edición-interpretación-depuración a menudo puede ser mucho más corto que un ciclo de edición-compilación-ejecución-depuración. [ cita requerida ]

La interpretación del código es más lenta que la ejecución del código compilado porque el intérprete debe analizar cada declaración en el programa cada vez que se ejecuta y luego realizar la acción deseada, mientras que el código compilado solo realiza la acción dentro de un contexto fijo determinado por la compilación. Este análisis en tiempo de ejecución se conoce como "gastos generales interpretativos". El acceso a las variables también es más lento en un intérprete porque la asignación de identificadores a las ubicaciones de almacenamiento debe realizarse repetidamente en tiempo de ejecución en lugar de en tiempo de compilación . [ cita requerida ]

Existen varios compromisos entre la velocidad de desarrollo cuando se usa un intérprete y la velocidad de ejecución cuando se usa un compilador. Algunos sistemas (como algunos Lisps ) permiten que el código interpretado y compilado se llame entre sí y comparta variables. Esto significa que una vez que se ha probado y depurado una rutina con el intérprete, se puede compilar y, por tanto, beneficiarse de una ejecución más rápida mientras se desarrollan otras rutinas. [ cita requerida ] Muchos intérpretes no ejecutan el código fuente tal como está, sino que lo convierten en una forma interna más compacta. Muchos intérpretes de BASIC reemplazan las palabras clave con tokens de un solo byteque se puede utilizar para encontrar la instrucción en una tabla de salto . Algunos intérpretes, como el intérprete PBASIC , logran niveles aún más altos de compactación del programa utilizando una estructura de memoria de programa orientada a bits en lugar de una orientada a bytes, donde los tokens de comandos ocupan quizás 5 bits, nominalmente se almacenan constantes de "16 bits". en un código de longitud variable que requiere 3, 6, 10 o 18 bits, y los operandos de dirección incluyen un "desplazamiento de bits". Muchos intérpretes de BASIC pueden almacenar y leer su propia representación interna tokenizada.

Un intérprete bien podría usar el mismo analizador léxico y analizador que el compilador y luego interpretar el árbol de sintaxis abstracta resultante . En el cuadro se muestran ejemplos de definiciones de tipos de datos para este último y un intérprete de juguete para árboles de sintaxis obtenidos a partir de expresiones C.

Regresión [ editar ]

La interpretación no puede usarse como el único método de ejecución: aunque un intérprete puede ser interpretado por sí mismo, etc., se necesita un programa ejecutado directamente en algún lugar en la parte inferior de la pila porque el código que se está interpretando no es, por definición, el mismo que el código de máquina que puede ejecutar la CPU. [6] [7]

Variaciones [ editar ]

Intérpretes de códigos de bytes [ editar ]

Existe un espectro de posibilidades entre la interpretación y la compilación, dependiendo de la cantidad de análisis realizado antes de que se ejecute el programa. Por ejemplo, Emacs Lisp se compila en código de bytes , que es una representación altamente comprimida y optimizada de la fuente Lisp, pero no es código de máquina (y por lo tanto no está vinculado a ningún hardware en particular). Este código "compilado" es luego interpretado por un intérprete de código de bytes (escrito en C ). El código compilado en este caso es código de máquina para una máquina virtual , que no se implementa en el hardware, sino en el intérprete de código de bytes. Estos intérpretes de compilación a veces también se denominan compreters . [8] [9]En un intérprete de código de bytes, cada instrucción comienza con un byte y, por lo tanto, los intérpretes de código de bytes tienen hasta 256 instrucciones, aunque no se pueden usar todas. Algunos códigos de bytes pueden ocupar varios bytes y pueden ser arbitrariamente complicados.

Las tablas de control , que no necesariamente tienen que pasar nunca por una fase de compilación, dictan el flujo de control algorítmico apropiado a través de intérpretes personalizados de manera similar a los intérpretes de códigos de bytes.

Intérpretes de código enhebrado [ editar ]

Los intérpretes de código enhebrado son similares a los intérpretes de código de bytes, pero en lugar de bytes utilizan punteros. Cada "instrucción" es una palabra que apunta a una función o secuencia de instrucciones, posiblemente seguida de un parámetro. El intérprete de código enhebrado realiza un bucle obteniendo instrucciones y llamando a las funciones a las que apuntan, o busca la primera instrucción y salta a ella, y cada secuencia de instrucciones termina con una búsqueda y salta a la siguiente instrucción. A diferencia del código de bytes, no existe un límite efectivo en el número de instrucciones diferentes que no sean la memoria disponible y el espacio de direcciones. El ejemplo clásico de código enhebrado es el código Forth utilizado en los sistemas Open Firmware : el lenguaje fuente se compila en "código F" (un código de bytes), que luego es interpretado por unmáquina virtual . [ cita requerida ]

Intérpretes de árbol de sintaxis abstracta [ editar ]

En el espectro entre la interpretación y la compilación, otro enfoque es transformar el código fuente en un árbol de sintaxis abstracta optimizado (AST), luego ejecutar el programa siguiendo esta estructura de árbol, o usarlo para generar código nativo justo a tiempo . [10] En este enfoque, cada oración debe analizarse solo una vez. Como ventaja sobre el código de bytes, el AST mantiene la estructura del programa global y las relaciones entre las declaraciones (que se pierde en una representación de código de bytes), y cuando se comprime proporciona una representación más compacta. [11] Por lo tanto, se ha propuesto el uso de AST como un mejor formato intermedio para compiladores just-in-time que el código de bytes. Además, permite que el sistema realice un mejor análisis durante el tiempo de ejecución.

Sin embargo, para los intérpretes, un AST causa más sobrecarga que un intérprete de código de bytes, debido a que los nodos relacionados con la sintaxis no realizan un trabajo útil, a una representación menos secuencial (que requiere un recorrido de más punteros) y a una sobrecarga que visita el árbol. [12]

Recopilación justo a tiempo [ editar ]

Desdibujar aún más la distinción entre intérpretes, intérpretes de código de bytes y compilación es la compilación justo a tiempo (JIT), una técnica en la que la representación intermedia se compila en código de máquina nativo en tiempo de ejecución. Esto confiere la eficiencia de ejecutar código nativo, a costa del tiempo de inicio y un mayor uso de la memoria cuando se compila por primera vez el código de bytes o AST. El compilador JIT publicado más temprano generalmente se atribuye al trabajo en LISP de John McCarthy en 1960. [13] La optimización adaptativa es una técnica complementaria en la que el intérprete perfila el programa en ejecución y compila sus partes ejecutadas con mayor frecuencia en código nativo. Esta última técnica tiene algunas décadas de antigüedad y aparece en lenguajes comoSmalltalk en la década de 1980. [14]

La compilación justo a tiempo ha ganado la atención generalizada entre los implementadores de lenguajes en los últimos años, con Java , .NET Framework , la mayoría de las implementaciones modernas de JavaScript y Matlab ahora incluye compiladores JIT. [ cita requerida ]

Intérprete de plantilla [ editar ]

Una vez más, hacer la distinción entre compiladores e intérpretes aún más vaga es un diseño especial de intérprete conocido como intérprete de plantilla. En lugar de implementar la ejecución de código en virtud de una declaración de conmutación grande que contiene todos los códigos de bytes posibles, mientras opera en una pila de software o en un árbol, un intérprete de plantillas mantiene una gran variedad de códigos de bytes (o cualquier representación intermedia eficiente) mapeados directamente a correspondientes instrucciones nativas de la máquina que se pueden ejecutar en el hardware del host como pares clave-valor, [15] [16] conocido como "Plantilla". Cuando se ejecuta el segmento de código en particular, el intérprete simplemente carga el mapeo del código de operación en la plantilla y lo ejecuta directamente en el hardware. [17] [18]Debido a su diseño, el intérprete de plantillas se parece mucho a un compilador Just-in Time en lugar de a un intérprete tradicional, sin embargo, técnicamente no lo es debido al hecho de que simplemente traduce el código del lenguaje a llamadas nativas un código de operación a la vez. que crear secuencias optimizadas de instrucciones ejecutables de la CPU a partir de todo el segmento de código. Debido al diseño simple del intérprete de simplemente pasar las llamadas directamente al hardware en lugar de implementarlas directamente, es mucho más rápido que cualquier otro tipo, incluso los intérpretes de códigos de bytes, y hasta cierto punto menos propenso a errores, pero como compensación es más difícil de realizar. mantener debido a que el intérprete tiene que admitir la traducción a múltiples arquitecturas diferentes en lugar de una máquina virtual / pila independiente de la plataforma. Hasta la fecha,la única implementación de Intérprete de plantilla de un lenguaje que existe es el intérprete dentro de la implementación de referencia de la máquina virtual Java HotSpot / OpenJDK.[15] [15]

Auto-intérprete [ editar ]

Un auto-intérprete es un intérprete de lenguaje de programación escrito en un lenguaje de programación que puede interpretarse a sí mismo; un ejemplo es un intérprete BASIC escrito en BASIC. Los auto-intérpretes están relacionados con los compiladores autohospedados .

Si no existe un compilador para el lenguaje a interpretar, la creación de un auto-intérprete requiere la implementación del lenguaje en un lenguaje anfitrión (que puede ser otro lenguaje de programación o ensamblador ). Al tener un primer intérprete como este, el sistema se inicia y se pueden desarrollar nuevas versiones del intérprete en el propio idioma. Fue así como Donald Knuth desarrolló el intérprete TANGLE para el lenguaje WEB del sistema de composición tipográfica estándar industrial TeX .

La definición de un lenguaje informático generalmente se hace en relación con una máquina abstracta (la llamada semántica operativa ) o como una función matemática ( semántica denotacional ). Un intérprete también puede definir un idioma en el que se da la semántica del idioma anfitrión. La definición de un idioma por un auto-intérprete no está bien fundada (no puede definir un idioma), pero un auto-intérprete le dice al lector sobre la expresividad y la elegancia de un idioma. También permite al intérprete interpretar su código fuente, el primer paso hacia la interpretación reflexiva.

Una dimensión de diseño importante en la implementación de un auto-intérprete es si una característica del idioma interpretado se implementa con la misma característica en el idioma anfitrión del intérprete. Un ejemplo es si un cierre en un lenguaje similar a Lisp se implementa utilizando cierres en el lenguaje del intérprete o se implementa "manualmente" con una estructura de datos que almacena explícitamente el entorno. Cuantas más funciones implemente la misma función en el idioma anfitrión, menos control tendrá el programador del intérprete; no se puede realizar un comportamiento diferente para lidiar con desbordamientos numéricos si las operaciones aritméticas se delegan a las operaciones correspondientes en el idioma anfitrión.

Algunos lenguajes como Lisp y Prolog tienen elegantes auto-intérpretes. [19] Gran parte de la investigación sobre los auto-intérpretes (en particular, los intérpretes reflexivos) se ha realizado en el lenguaje de programación Scheme , un dialecto de Lisp. Sin embargo, en general, cualquier lenguaje Turing completo permite la escritura de su propio intérprete. Lisp es un lenguaje de este tipo, porque los programas Lisp son listas de símbolos y otras listas. XSLT es un lenguaje de este tipo, porque los programas XSLT están escritos en XML. Un subdominio de la metaprogramación es la escritura de lenguajes específicos de dominio (DSL).

Clive Gifford introdujo [20] una medida de la calidad del auto-intérprete (la relación propia), el límite de la relación entre el tiempo de la computadora dedicado a ejecutar una pila de N auto-intérpretes y el tiempo dedicado a ejecutar una pila de N - 1 auto-intérpretes como N va al infinito. Este valor no depende del programa que se esté ejecutando.

El libro Estructura e interpretación de programas de computadora presenta ejemplos de interpretación meta-circular para Scheme y sus dialectos. Otros ejemplos de lenguajes con auto-intérprete son Forth y Pascal .

Microcódigo [ editar ]

El microcódigo es una técnica muy utilizada "que impone un intérprete entre el hardware y el nivel arquitectónico de una computadora". [21] Como tal, el microcódigo es una capa de instrucciones a nivel de hardware que implementan instrucciones de código de máquina de nivel superior o secuenciación de máquina de estado interna en muchos elementos de procesamiento digital . El microcódigo se utiliza en unidades de procesamiento central de propósito general , así como en procesadores más especializados como microcontroladores , procesadores de señales digitales , controladores de canal , controladores de disco , controladores de interfaz de red ,procesadores de red , unidades de procesamiento de gráficos y otro hardware.

El microcódigo normalmente reside en una memoria especial de alta velocidad y traduce las instrucciones de la máquina, los datos de la máquina de estado u otra entrada en secuencias de operaciones detalladas a nivel de circuito. Separa las instrucciones de la máquina de la electrónica subyacente para que las instrucciones se puedan diseñar y modificar con mayor libertad. También facilita la construcción de instrucciones complejas de varios pasos, al tiempo que reduce la complejidad de los circuitos de la computadora. La escritura de microcódigo a menudo se denomina microprogramación y el microcódigo en una implementación de procesador particular a veces se denomina microprograma .

Más extensa microcoding permite a las pequeñas y simples microarquitectura a emular arquitecturas más potentes con mayor longitud de la palabra , más unidades de ejecución y así sucesivamente, que es una forma relativamente sencilla de lograr la compatibilidad de software entre los diferentes productos en una familia de procesadores.

Procesador de computadora [ editar ]

Incluso un procesador de computadora sin microcodificación en sí mismo puede considerarse un intérprete de ejecución inmediata de análisis que está escrito en un lenguaje de descripción de hardware de propósito general como VHDL para crear un sistema que analiza las instrucciones del código de máquina y las ejecuta inmediatamente.

Aplicaciones [ editar ]

  • Los intérpretes se utilizan con frecuencia para ejecutar lenguajes de comandos y lenguajes de unión, ya que cada operador ejecutado en el lenguaje de comandos suele ser una invocación de una rutina compleja, como un editor o un compilador. [ cita requerida ]
  • El código auto modificable se puede implementar fácilmente en un lenguaje interpretado. Esto se relaciona con los orígenes de la interpretación en Lisp y la investigación de inteligencia artificial . [ cita requerida ]
  • Virtualización . El código de máquina destinado a una arquitectura de hardware se puede ejecutar mediante una máquina virtual . Esto se usa a menudo cuando la arquitectura deseada no está disponible, o entre otros usos, para ejecutar múltiples copias.
  • Sandboxing : si bien algunos tipos de sandboxes dependen de las protecciones del sistema operativo, a menudo se utiliza un intérprete o una máquina virtual. La arquitectura de hardware real y la arquitectura de hardware prevista originalmente pueden o no ser las mismas. Esto puede parecer inútil, excepto que las cajas de arena no están obligadas a ejecutar todas las instrucciones del código fuente que está procesando. En particular, puede negarse a ejecutar código que viole cualquier restricción de seguridad bajo la que esté operando. [ cita requerida ]
  • Emuladores para ejecutar software de computadora escrito para hardware obsoleto y no disponible en equipos más modernos.

Ver también [ editar ]

  • Intérprete BÁSICO
  • Intérprete de línea de comandos
  • Lenguaje compilado
  • Compilación dinámica
  • Evaluador meta-circular
  • Evaluación parcial
  • Homoiconicidad

Referencias [ editar ]

  1. ^ En este sentido, la CPU también es un intérprete de las instrucciones de la máquina.
  2. ^ Aunque este esquema (combinando la estrategia 2 y 3) se usó para implementar ciertos intérpretes BASIC ya en la década de 1970, como el eficiente intérprete BASIC del ABC 80 , por ejemplo.
  3. ^ Bennett, JM; Prinz, DG; Woods, ML (1952). "Subrutinas interpretativas". Actas de la Conferencia Nacional ACM, Toronto .
  4. ^ Según lo informado por Paul Graham en Hackers & Painters , p. 185, McCarthy dijo: "Steve Russell dijo, mira, ¿por qué no programo esta evaluación ... y le dije, ho, ho, estás confundiendo la teoría con la práctica, esta evaluación está destinada a la lectura, no para la informática. Pero siguió adelante y lo hizo. Es decir, compiló la evaluación en mi artículo en elcódigo de máquina IBM 704 , corrigiendo el error , y luego lo anunció como un intérprete Lisp, lo que ciertamente era. esencialmente la forma que tiene hoy ... "
  5. ^ "¿Por qué se escribió el primer compilador antes que el primer intérprete?" . Ars Technica . Consultado el 9 de noviembre de 2014 .
  6. ^ Theodore H. Romer, Dennis Lee, Geoffrey M. Voelker, Alec Wolman, Wayne A. Wong, Jean-Loup Baer, ​​Brian N. Bershad y Henry M. Levy, La estructura y desempeño de los intérpretes
  7. ^ Terence Parr, Johannes Luber, La diferencia entre compiladores e intérpretes Archivado el 6 de enero de 2014 en la Wayback Machine.
  8. ^ Kühnel, Claus (1987) [1986]. "4. Kleincomputer - Eigenschaften und Möglichkeiten" [4. Microordenador - Propiedades y posibilidades]. En Erlekampf, Rainer; Mönk, Hans-Joachim (eds.). Mikroelektronik in der Amateurpraxis [ Microelectrónica para el aficionado práctico ] (en alemán) (3 ed.). Berlín: Militärverlag der Deutschen Demokratischen Republik  [ de ] , Leipzig. pag. 222. ISBN 3-327-00357-2. 7469332.
  9. ^ Heyne, R. (1984). "Basic-Compreter für U880" [Compreter BÁSICO para U880 (Z80)]. radio-fernsehn-elektronik  [ de ] (en alemán). 1984 (3): 150-152.
  10. ^ Representaciones intermedias de AST , Foro Lambda the Ultimate
  11. ^ Kistler, Thomas; Franz, Michael (febrero de 1999). "Una alternativa basada en árboles a los códigos de bytes de Java" (PDF) . Revista Internacional de Programación Paralela . 27 (1): 21–33. CiteSeerX 10.1.1.87.2257 . doi : 10.1023 / A: 1018740018601 . ISSN 0885-7458 . S2CID 14330985 . Consultado el 20 de diciembre de 2020 .    
  12. ^ Surfin 'Safari - Blog Archive »Anuncio de SquirrelFish . Webkit.org (2 de junio de 2008). Consultado el 10 de agosto de 2013.
  13. ^ Aycock 2003 , 2. Técnicas de compilación JIT, 2.1 Génesis, p. 98.
  14. ^ L. Deutsch, A. Schiffman, Implementación eficiente del sistema Smalltalk-80 , Actas del 11 ° simposio POPL, 1984.
  15. ^ a b c "openjdk / jdk" . GitHub .
  16. ^ https://openjdk.java.net/groups/hotspot/docs/RuntimeOverview.html#Interpreter
  17. ^ "Desmitificando la JVM: variantes de JVM, Cppinterpreter y TemplateInterpreter" . metebalci.com .
  18. ^ "Intérprete de plantilla JVM" . ProgrammerSought .
  19. ^ Bondorf, Anders. " Logimix: un evaluador parcial autoaplicable para Prolog ". Síntesis y transformación de programas lógicos. Springer, Londres, 1993. 214-227.
  20. ^ Gifford, Clive. "Eigenratios de los auto-intérpretes" . Blogger . Consultado el 10 de noviembre de 2019 .
  21. ^ Kent, Allen; Williams, James G. (5 de abril de 1993). Enciclopedia de Ciencias de la Computación y Tecnología: Volumen 28 - Suplemento 13 . Nueva York: Marcel Dekker, Inc. ISBN 0-8247-2281-7. Consultado el 17 de enero de 2016 .

Enlaces externos [ editar ]

  • Página de IBM Card Interpreters en la Universidad de Columbia
  • Fundamentos teóricos para la práctica 'Programación totalmente funcional' (Capítulo 7 especialmente) Tesis doctoral que aborda el problema de formalizar lo que es un intérprete
  • Animación breve que explica la diferencia conceptual clave entre intérpretes y compiladores