Question

I'm using python to implement another programming language named 'foo'. All of foo's code will be translated to python, and will also be run in the same python interpreter, so it will JIT translate to python.

Here is a small piece of foo's code:

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

which will translate to :

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

The 'watchdog' is a greenlet(the generated code is also running in a greenlet context) which will monitor/limit resource usage, since the language will run untrusted code.

As can be seen in the example, before the python code is generated, small changes will be made to the parse tree in order to add watchdog switches and make small changes to function identifiers.

To meet all the requeriments, I must also add traceback/debugging capabilities to the language, so that when the python runtime throws an exception, what the user will see is foo's code traceback(as oposed to showing the generated python code traceback).

Consider that the user creates a file named 'program.foo' with the following contents:

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();

which will translate to:

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

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

watchdog.switch()
_foo()

Then, the output of 'program.foo' should be something like:

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

Is there an easy way to do that? I would prefer a solution that doesn't involve instrumenting python bytecode, since it is internal to the interpreter implementation, but if there's nothing else, then instrumenting bytecode will also do it.

Was it helpful?

Solution

You could decorate each generated Python function with a decorator which record the context (filename, function, line number, etc.) to a global stack. Then you could derive your own Exception class and catch it at the top level of the interpreter. Finally, you print out what you like, using information from the global debug stack.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top