Más simple que escribir un compilador y VM es registrar y trampolínar a su intérprete. Como tiene un intérprete y no un compilador (supongo), solo necesita un par de transformaciones sencillas para obtener el soporte adecuado para las llamadas finales.
Primero tendrá que escribir todo en el estilo de continuación de paso, lo que puede ser extraño pensar y hacer en C/C++. Dan Friedman ParentheC tutorial le guía a través de la transformación de un alto nivel, programa recursivo en una forma que es traducible a C.
Al final, se implementará esencialmente una sencilla máquina virtual, donde en lugar de utilizar la función normal llama a hacer eval, applyProc, etc., se pasa argumentos por los parámetros de variables globales y luego hacer un goto
al siguiente argumento (o utilizar un bucle de nivel superior y contador de programa) ...
return applyProc(rator, rand)
convierte
reg_rator = rator
reg_rand = rand
reg_pc = applyProc
return
Es decir, todas sus funciones que normalmente se llaman recíprocamente se reducen a un pseudoensamblaje en el que solo son bloques de código que no se repiten. Un bucle de nivel superior controla el programa:
for(;;) {
switch(reg_pc) {
case EVAL:
eval();
break;
case APPLY_PROC:
applyProc();
break;
...
}
}
Editar: que pasaron por el mismo proceso para mi hobby Esquema intérprete, escrito en JavaScript. Aproveché muchos procedimientos anónimos, pero podría ser una referencia concreta. Mira FoxScheme's commit history partir de 2011-03-13 (30707a0432563ce1632a) a través 2011-03-15 (5dd3b521dac582507086).
Editar^2: La recursividad sin cola seguirá consumiendo memoria, incluso si no está en la pila.
Veo que se ha formulado una pregunta muy similar: http://stackoverflow.com/questions/5986058/how-does-one-implement-a-stackless-interpreted-language – csl
Encontré que el JScheme original de Peter Norvig implementa esto muy bien con un simple trampolín. Desplácese hacia abajo hasta eval() en http://norvig.com/jscheme/Scheme.java – csl