aboutsummaryrefslogtreecommitdiffstats
path: root/3rdparty/python-console/Interpreter.cpp
diff options
context:
space:
mode:
authorMiodrag Milanovic <mmicko@gmail.com>2018-06-28 13:16:53 +0200
committerMiodrag Milanovic <mmicko@gmail.com>2018-06-28 17:57:26 +0200
commitc63274342f1aaa3d1087c0df5ffdaccfd0afcd56 (patch)
treeb04628f6c8c6768e2d5771737f3f13687cd0ed29 /3rdparty/python-console/Interpreter.cpp
parent66670831b89d934ef00c47c0527137f6ec38a0b0 (diff)
downloadnextpnr-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.cpp231
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);
+ }
+}