2012-03-09 5 views
5

Estoy usando python para implementar otro lenguaje de programación llamado 'foo'. Todo el código de foo se traducirá a python, y también se ejecutará en el mismo intérprete de python, por lo que se traducirá a python.¿Cómo agregar funcionalidades de rastreo/depuración a un lenguaje implementado en python?

Aquí es una pequeña pieza de código de foo:

function bar(arg1, arg2) { 
    while (arg1 > arg2) { 
     arg2 += 5; 
    } 
    return arg2 - arg1; 
} 

lo que se traducirá a:

def _bar(arg1, arg2): 
    while arg1 > arg2: 
     arg2 += 5 
     watchdog.switch() 
    watchdog.switch() 
    return arg2 - arg1 

El 'perro guardián' es una greenlet (el código generado también está en un contexto greenlet) que controlará/limitará el uso de recursos, ya que el lenguaje ejecutará código que no es de confianza.

Como se puede ver en el ejemplo, antes de que se genere el código python, se realizarán pequeños cambios en el árbol de análisis sintáctico para agregar interruptores de control y hacer pequeños cambios en los identificadores de funciones.

Para cumplir con todos los requisitos, también debo agregar capacidades de rastreo/depuración al lenguaje, de modo que cuando el tiempo de ejecución de Python arroje una excepción, lo que el usuario verá es el rastreo de código de foo (como opuesto a mostrar el código python generado rastrear).

consideran que el usuario crea un archivo llamado 'program.foo' con el siguiente contenido:

1 function bar() { 
2  throw Exception('Some exception message'); 
3 } 
4 
5 function foo() { 
6  output('invoking function bar'); 
7  bar(); 
8 } 
9 
10 foo(); 

lo que se traducirá a:

def _bar(): 
    watchdog.switch() 
    raise Exception('Some exception message') 

def _foo(): 
    print 'invoking function bar' 
    watchdog.switch() 
    _bar() 

watchdog.switch() 
_foo() 

Entonces, la salida de 'program.foo 'debe ser algo como:

invoking function bar 
Traceback (most recent call last): 
    File "program.foo", line 10 
    foo(); 
    File "program.foo", line 7, inside function 'foo' 
    bar(); 
    File "program.foo", line 2, inside function 'bar' 
    throw Exception('Some exception message'); 
Exception: Some exception message 

¿hay una manera fácil de hacer eso? Preferiría una solución que no implique instrumentar el bytecode de python, ya que es interno a la implementación del intérprete, pero si no hay nada más, entonces el bytecode instrumental también lo hará.

+0

¿Su traducción almacena algún tipo de mapeo entre líneas de código Python y líneas de código foo? Ciertamente puede personalizar un rastreo: IPython tiene un módulo llamado [ultratb] (https://github.com/ipython/ipython/blob/master/IPython/core/ultratb.py) para esto, aunque es bastante largo y complejo, y podría hacer algo de limpieza. –

+0

Hasta el momento solo hace la traducción. Pero si es parte de una solución, ciertamente podría mapear líneas de pitón a líneas de foo. –

Respuesta

2

Puede decorar cada función de Python generada con un decorador que registra el contexto (nombre de archivo, función, número de línea, etc.) en una pila global. Entonces podrías derivar tu propia clase de Excepción y atraparla en el nivel superior del intérprete. Finalmente, imprima lo que quiera, utilizando información de la pila de depuración global.

+0

Esto parece una buena ventaja. Puedo adaptar esta solución y en lugar de decorar cada función, agregaré una llamada a función para registrar la línea foo actual antes de cada grupo de declaraciones python que se asocien a ella. Pero ¿por qué necesitaría una clase de excepción personalizada? ¿No podría simplemente capturar cualquier excepción de Python e imprimir la información en la pila de contexto global? –

+0

Por supuesto que puedes. Pero declarar su propia clase de excepción le permitiría registrar cierta información personalizada en la excepción, específica de su problema. –

+0

Ok esta es la mejor solución hasta ahora, gracias. –

Cuestiones relacionadas