2010-07-21 13 views
7

Hola a todos Actualmente estoy implementando un lenguaje de programación simple para la experiencia de aprendizaje, pero necesito algunos consejos. Actualmente estoy diseñando mi intérprete y he tenido un problema.Implementación de una máquina virtual basada en pila para un subconjunto de C

Mi lenguaje es un subconjunto de C y estoy teniendo un problema con respecto a la implementación del intérprete de la pila. En el lenguaje de la siguiente compilará:

somefunc() 
{ 
    1 + 2; 
} 

main() 
{ 
    somefunc(); 
} 

Ahora bien, esto está bien, pero cuando "1 + 2" se calcula el resultado es empujado sobre una pila y luego se devuelve la función pero todavía hay un número en la pila, y no debería haber. ¿Cómo puedo evitar este problema?

He pensado en guardar un "estado" de la pila antes de una llamada de función y restaurar el "estado" después de la llamada a la función. Por ejemplo, guardando la cantidad de elementos en la pila, ejecuta el código de la función, regresa y luego sal de la pila hasta que tengamos la misma cantidad de elementos que antes (o quizás +1 si la función devuelve algo).

¿Alguna idea? Gracias por cualquier consejo!

Respuesta

8

¡Gran pregunta! Uno de mis pasatiempos es escribir compiladores para los idiomas de los juguetes, así que felicitaciones por su excelente gusto de programación.

Una declaración de expresión es una en la que el código en el enunciado es simplemente una expresión. Esto significa cualquier cosa del tipo <expression> ;, que incluye cosas como asignaciones y llamadas a funciones, pero no if s, while s, o return s. Cualquier declaración de expresión tendrá un valor restante en la pila al final, que debe descartarse.

1 + 2 es una declaración de la expresión, pero también lo son los siguientes:

  • x = 5;
    La asignación expresión deja el valor 5 en la pila ya que el resultado de una asignación es el valor de la izquierda operando de la mano. Una vez finalizada la declaración que el pop fuera el valor no utilizado 5.

  • printf("hello world!\n");
    printf() devuelve el número de caracteres de salida. Tendrás este valor sobrante en la pila, por lo que aparecerá cuando finalice la instrucción.

Efectivamente cada declaración de la expresión dejará un valor en la pila a menos que el tipo de la expresión es void. En ese caso, o bien las declaraciones de casos especiales void y luego no reventa nada, o inserta un valor de simulación "vacío" en la pila para que siempre pueda mostrar un valor.

+0

Es curioso que lo nombre porque en mi representación de AST tengo un nodo llamado "ASTStmtExpr" solo para esto. Creo que estoy empezando a entender, más o menos ... Esto es de lo que no estoy seguro: Debido a las limitaciones de estas respuestas de comentarios, tengo para pegar una snipplet: \t vacío Compiler :: visita (const ASTStmtExpr y expr_stmt, std :: shared_ptr func) \t \t { \t \t \t expr_stmt.expr() -> aceptar (* esto, func); \t ¿Estás diciendo que debería agregar un OP_POP después de esto, y para cosas como asignaciones empujaría un objeto "Nil" ficticio para que se salte? –

+0

Lo siento, no sabía que los comentarios no están formateados –

+1

Para las asignaciones no, no inserta un valor ficticio, porque ya tendrá el resultado de la asignación en la pila. Una asignación es solo una expresión usando el operador '=', que no es diferente de '+' o '-' excepto' = 'tiene un efecto secundario de asignación a una variable. De lo contrario, se comporta como todos los demás operadores. –

2

Necesitará un analizador más inteligente. Cuando ve una expresión cuyo valor no se usa, debe emitir un POP.

+0

Hola, gracias por la respuesta. Todavía estoy en la fase infantil de los compiladores de codificación y he pensado en hacer una optimización como esta, pero no pude encontrar una solución viable :(Tal vez lo intente de nuevo, de nuevo, ¡gracias! –

0

Esta es una oportunidad importante para la optimización del aprendizaje. usted tiene una función que hace matemáticas numéricas pero enteras, el resultado de matemática interna ni siquiera se utiliza de ninguna manera, forma o forma.

Tener su compilador optimizar la función de distancia reduciría una gran cantidad de bytecode que se genera y se ejecuta para nada!

Cuestiones relacionadas