¿Cuál es la diferencia entre implementar un compilador y un intérprete?

Recientemente leí todo el Libro del Dragón (solo por diversión, realmente no estoy planeando implementar un compilador real), y me quedé con esta gran pregunta en mi cabeza.

¿Qué es diferente entre implementar un compilador y un intérprete?

Para mí, un compilador está compuesto por:

LexerAnalizador (que construye el árbol de sintaxis)Generar código intermedio (como código de 3 direcciones)Haz todas estas locuras para optimizar si quieres :-)Genere "ensamblado" o "código nativo" a partir del código de 3 direcciones.

Ahora, obviamente, el intérprete también tiene el mismo lexer y analizador que el compilador.
¿Pero qué hace después de eso?

¿"Lee" el árbol de sintaxis y lo ejecuta directamente? (algo así como tener un puntero de instrucción que apunta al nodo actual en el árbol, y la ejecución es un gran recorrido del árbol más la administración de memoria para la pila de llamadas) (y si es así, ¿cómo lo hace? Espero que el la ejecución es mejor que una gran declaración de cambio que verifica qué tipo de nodo es)

¿Genera 3 códigos de dirección e interpreta eso? (si es así, ¿cómo lo hace? De nuevo, estoy buscando algo más elegante que una declaración de cambio de una milla de largo)

¿Genera código nativo real, lo carga en la memoria y lo hace funcionar? (en ese momento supongo que ya no es un intérprete, sino más bien un compilador JIT)

Además, ¿en qué punto interviene el concepto de "máquina virtual"? ¿Para qué utiliza una máquina virtual en un idioma? (para ser claros acerca de mi nivel de ignorancia, para mí una máquina virtual es VMWare, no tengo idea de cómo se aplica el concepto de VM a los lenguajes de programación / ejecución de programas).

Como puede ver, mi pregunta es bastante amplia. Principalmente busco no solo qué método se usa, sino principalmente para comprender primero los grandes conceptos y luego profundizar en cómo funciona en detalle. Quiero los detalles feos y crudos. Obviamente, esta es más una búsqueda de referencias a cosas para leer en lugar de esperar que responda todos estos detalles aquí.

¡Gracias!
Daniel

EDITAR: Gracias por sus respuestas hasta ahora. Sin embargo, me di cuenta de que mi título era engañoso. Entiendo la diferencia "funcional" entre un compilador y un intérprete.
Lo que estoy buscando es la diferencia en cuanto a cómoimplementar un intérprete, vs un compilador.
Ahora entiendo cómo se implementa un compilador, la pregunta es cómo un intérprete difiere de eso.

Por ejemplo: VB6 es claramente un compilador y un intérprete. Ahora entiendo la parte del compilador. Sin embargo, no puedo entender cómo, cuando se ejecuta dentro del IDE, podría dejarme detener el programa en cualquier punto arbitrario, cambiar el código y reanudar la ejecución con el nuevo código. Ese es solo un pequeño ejemplo, no es la respuesta que estoy buscando. Lo que estoy tratando de entender, como explico a continuación, es lo que sucede después de que tengo un árbol de análisis. Un compilador generará un nuevo código a partir de él en el lenguaje "objetivo". ¿Qué hace un intérprete?

¡Gracias por tu ayuda!

Respuestas a la pregunta(10)

Su respuesta a la pregunta