diff options
author | Miodrag Milanovic <mmicko@gmail.com> | 2018-06-28 13:16:53 +0200 |
---|---|---|
committer | Miodrag Milanovic <mmicko@gmail.com> | 2018-06-28 17:57:26 +0200 |
commit | c63274342f1aaa3d1087c0df5ffdaccfd0afcd56 (patch) | |
tree | b04628f6c8c6768e2d5771737f3f13687cd0ed29 /3rdparty/python-console/Interpreter.cpp | |
parent | 66670831b89d934ef00c47c0527137f6ec38a0b0 (diff) | |
download | nextpnr-c63274342f1aaa3d1087c0df5ffdaccfd0afcd56.tar.gz nextpnr-c63274342f1aaa3d1087c0df5ffdaccfd0afcd56.tar.bz2 nextpnr-c63274342f1aaa3d1087c0df5ffdaccfd0afcd56.zip |
initial import of python-console
Diffstat (limited to '3rdparty/python-console/Interpreter.cpp')
-rw-r--r-- | 3rdparty/python-console/Interpreter.cpp | 231 |
1 files changed, 231 insertions, 0 deletions
diff --git a/3rdparty/python-console/Interpreter.cpp b/3rdparty/python-console/Interpreter.cpp new file mode 100644 index 00000000..95615ed2 --- /dev/null +++ b/3rdparty/python-console/Interpreter.cpp @@ -0,0 +1,231 @@ +#include "Interpreter.h" +#include <iostream> +#include <map> +#include <boost/format.hpp> + +PyThreadState* Interpreter::MainThreadState = NULL; + +Interpreter::Interpreter( ) +{ + PyEval_AcquireLock( ); + m_threadState = Py_NewInterpreter( ); + + PyObject *module = PyImport_ImportModule("__main__"); + loc = glb = PyModule_GetDict(module); + SetupRedirector( m_threadState ); + PyRun_SimpleString("import sys\n" + "import redirector\n" + "sys.path.insert(0, \".\")\n" // add current path + "sys.stdout = redirector.redirector()\n" + "sys.stderr = sys.stdout\n" + "import rlcompleter\n" + "sys.completer = rlcompleter.Completer()\n" + ); + + PyEval_ReleaseThread( m_threadState ); +} + +Interpreter::~Interpreter( ) +{ +#ifndef NDEBUG + std::cout << "delete interpreter\n"; +#endif + PyEval_AcquireThread( m_threadState ); + Py_EndInterpreter( m_threadState ); + PyEval_ReleaseLock( ); +} + +void +Interpreter::test( ) +{ + PyEval_AcquireThread( m_threadState ); + + PyObject* py_result; + PyObject* dum; + std::string command = "print 'Hello world'\n"; + py_result = Py_CompileString(command.c_str(), "<stdin>", Py_single_input); + if ( py_result == 0 ) + { + std::cout << "Huh?\n"; + PyEval_ReleaseThread( m_threadState ); + return; + } + dum = PyEval_EvalCode ((PyCodeObject *)py_result, glb, loc); + Py_XDECREF (dum); + Py_XDECREF (py_result); + + std::cout << GetResultString( m_threadState ); + GetResultString( m_threadState ) = ""; + + PyEval_ReleaseThread( m_threadState ); +} + +std::string +Interpreter::interpret( const std::string& command, int* errorCode ) +{ + PyEval_AcquireThread( m_threadState ); + *errorCode = 0; + + PyObject* py_result; + PyObject* dum; + std::string res; +#ifndef NDEBUG + std::cout << "interpreting (" << command << ")\n"; +#endif + py_result = Py_CompileString(command.c_str(), "<stdin>", Py_single_input); + if ( py_result == 0 ) + { +#ifndef NDEBUG + std::cout << "Huh?\n"; +#endif + if ( PyErr_Occurred( ) ) + { + *errorCode = 1; + PyErr_Print( ); + res = GetResultString( m_threadState ); + GetResultString( m_threadState ) = ""; + } + + PyEval_ReleaseThread( m_threadState ); + return res; + } + dum = PyEval_EvalCode ((PyCodeObject *)py_result, glb, loc); + Py_XDECREF (dum); + Py_XDECREF (py_result); + if ( PyErr_Occurred( ) ) + { + *errorCode = 1; + PyErr_Print( ); + } + + res = GetResultString( m_threadState ); + GetResultString( m_threadState ) = ""; + + PyEval_ReleaseThread( m_threadState ); + return res; +} + +const std::list<std::string>& Interpreter::suggest( const std::string& hint ) +{ + PyEval_AcquireThread( m_threadState ); + m_suggestions.clear(); + int i = 0; + std::string command = boost::str( + boost::format("sys.completer.complete('%1%', %2%)\n") + % hint + % i); +#ifndef NDEBUG + std::cout << command << "\n"; +#endif + std::string res; + do + { + PyObject* py_result; + PyObject* dum; + py_result = Py_CompileString(command.c_str(), "<stdin>", Py_single_input); + dum = PyEval_EvalCode ((PyCodeObject *)py_result, glb, loc); + Py_XDECREF (dum); + Py_XDECREF (py_result); + res = GetResultString( m_threadState ); + GetResultString( m_threadState ) = ""; + ++i; + command = boost::str( + boost::format("sys.completer.complete('%1%', %2%)\n") + % hint + % i); + if (res.size()) + { + // throw away the newline + res = res.substr(1, res.size() - 3); + m_suggestions.push_back(res); + } + } + while (res.size()); + + PyEval_ReleaseThread( m_threadState ); + return m_suggestions; +} + +void +Interpreter::Initialize( ) +{ + Py_Initialize( ); + PyEval_InitThreads( ); + MainThreadState = PyEval_SaveThread( ); +} + +void +Interpreter::Finalize( ) +{ + PyEval_RestoreThread( MainThreadState ); + Py_Finalize( ); +} + +std::string& Interpreter::GetResultString( PyThreadState* threadState ) +{ + static std::map< PyThreadState*, std::string > ResultStrings; + if ( !ResultStrings.count( threadState ) ) + { + ResultStrings[ threadState ] = ""; + } + return ResultStrings[ threadState ]; +} + +PyObject* Interpreter::RedirectorInit(PyObject *, PyObject *) +{ + Py_INCREF(Py_None); + return Py_None; +} + +PyObject* Interpreter::RedirectorWrite(PyObject *, PyObject *args) +{ + char* output; + PyObject *selfi; + + if (!PyArg_ParseTuple(args,"Os",&selfi,&output)) + { + return NULL; + } + + std::string outputString( output ); + PyThreadState* currentThread = PyThreadState_Get( ); + std::string& resultString = GetResultString( currentThread ); + resultString = resultString + outputString; + Py_INCREF(Py_None); + return Py_None; +} + +PyMethodDef Interpreter::ModuleMethods[] = { {NULL,NULL,0,NULL} }; +PyMethodDef Interpreter::RedirectorMethods[] = +{ + {"__init__", Interpreter::RedirectorInit, METH_VARARGS, + "initialize the stdout/err redirector"}, + {"write", Interpreter::RedirectorWrite, METH_VARARGS, + "implement the write method to redirect stdout/err"}, + {NULL,NULL,0,NULL}, +}; + +void Interpreter::SetupRedirector( PyThreadState* threadState ) +{ + PyMethodDef *def; + + /* create a new module and class */ + PyObject *module = Py_InitModule("redirector", ModuleMethods); + PyObject *moduleDict = PyModule_GetDict(module); + PyObject *classDict = PyDict_New(); + PyObject *className = PyString_FromString("redirector"); + PyObject *fooClass = PyClass_New(NULL, classDict, className); + PyDict_SetItemString(moduleDict, "redirector", fooClass); + Py_DECREF(classDict); + Py_DECREF(className); + Py_DECREF(fooClass); + + /* add methods to class */ + for (def = RedirectorMethods; def->ml_name != NULL; def++) { + PyObject *func = PyCFunction_New(def, NULL); + PyObject *method = PyMethod_New(func, NULL, fooClass); + PyDict_SetItemString(classDict, def->ml_name, method); + Py_DECREF(func); + Py_DECREF(method); + } +} |