better way of executing expression/statement in C?

D

David Faden

Hi,

Given arbitrary Python source code input by the user, I want to get the
result of executing that source as an expression if it is an expression
and otherwise execute the source as a statement. Currently, I'm
accomplishing this as follows (in a category on NSString), but it seems
kludgy to rely on detecting a syntax error.

- (PyObject*)executePythonSourceWithGlobals:(PyObject*)globals
{
const char* source = [self UTF8String];
PyObject* result = PyRun_String(source, Py_eval_input, globals,
globals);
if (!result && PyErr_ExceptionMatches(PyExc_SyntaxError)) {
PyErr_Clear();
result = PyRun_String(source, Py_file_input, globals, globals);
}
return result;
}

How would you accomplish this? How does the interpreter do it?

Thank you.

David
AIM: pitulx
 
R

Rick L. Ratzel

This might be slightly less kludgy...I tested it by implementing a
crude input loop. Here is the output:

[rlratzel@triumph ~/exp] ./pyexec
Here is the code:

file: pyexec.c
--------
#include <Python.h>
#define INLEN 1024

/*
* get string rep of a Python obj
*/
const char* getPyObjStringRepr( PyObject* pyObj ) {
if( pyObj == NULL ) {
return "NULL";
} else {
return PyString_AsString( PyObject_Str( pyObj ) );
}
}


/*
* print the results of evaluating Python expressions and statements
*/
int main( int argc, char** argv ) {

PyObject* mainModObj;
PyObject* mainDictObj;
PyObject* returnObj;
PyObject* resultObj;
char userInput[INLEN];

Py_Initialize();

/*
* create a different display hook to set a result var
* rather than print to stdout and set __builtin__._
*/
PyRun_SimpleString( "import sys, __main__" );
PyRun_SimpleString( "def my_displayhook(o): __main__.__result=o" );
PyRun_SimpleString( "sys.displayhook=my_displayhook" );

/*
* get the __main__ symbol table for evaluating within the top-most
* scope and retrieving the result
*/
mainModObj = PyImport_AddModule( "__main__" );
if( mainModObj == NULL ) {
return -1;
}
mainDictObj = PyModule_GetDict( mainModObj );

/*
* start an eval loop...only print 2 arrows since we are
* not really trying to be Python
*/
printf( ">> " );

/*
* start the loop
*/
while( fgets( userInput, INLEN, stdin ) != NULL ) {

/*
* run a string from the command line like the interactive interp
* does, handling both expressions and statements
*/
returnObj = PyRun_String( userInput, Py_single_input,
mainDictObj, mainDictObj );

if( returnObj == NULL ) {
PyErr_Print();
return -1;
}

/*
* get the result as set by the displayhook and print it out
*/
resultObj = PyDict_GetItemString( mainDictObj, "__result" );

printf( "RESULT: %s\n", getPyObjStringRepr( resultObj ) );

Py_DECREF( returnObj );
if( Py_FlushLine() ) {
PyErr_Clear();
}

/*
* if a result was set, delete it so statements which dont return
* a value dont return a prior set value
*/
if( resultObj != NULL ) {
PyRun_SimpleString( "del __main__.__result" );
}

printf( ">> " );
}

printf( "Done.\n" );
return 0;
}
--------

Not sure if that is exactly what you were looking for, but it does
allow one to execute statements and expressions and process the result
(if any).

-Rick Ratzel


David said:
Hi,

Given arbitrary Python source code input by the user, I want to get the
result of executing that source as an expression if it is an expression
and otherwise execute the source as a statement. Currently, I'm
accomplishing this as follows (in a category on NSString), but it seems
kludgy to rely on detecting a syntax error.

- (PyObject*)executePythonSourceWithGlobals:(PyObject*)globals
{
const char* source = [self UTF8String];
PyObject* result = PyRun_String(source, Py_eval_input, globals,
globals);
if (!result && PyErr_ExceptionMatches(PyExc_SyntaxError)) {
PyErr_Clear();
result = PyRun_String(source, Py_file_input, globals, globals);
}
return result;
}

How would you accomplish this? How does the interpreter do it?

Thank you.

David
AIM: pitulx
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,537
Members
45,022
Latest member
MaybelleMa

Latest Threads

Top