diff options
Diffstat (limited to '')
-rw-r--r-- | sca-cpp/trunk/modules/python/Makefile.am | 4 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/python/driver.hpp | 8 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/python/eval.hpp | 204 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/python/mod-python.cpp | 27 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/python/mod-python.hpp | 42 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/python/python-shell.cpp | 4 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/python/python-test.cpp | 165 |
7 files changed, 196 insertions, 258 deletions
diff --git a/sca-cpp/trunk/modules/python/Makefile.am b/sca-cpp/trunk/modules/python/Makefile.am index 80c3097b48..92548de6d0 100644 --- a/sca-cpp/trunk/modules/python/Makefile.am +++ b/sca-cpp/trunk/modules/python/Makefile.am @@ -35,7 +35,7 @@ EXTRA_DIST = domain-test.composite client-test.py server-test.py mod_LTLIBRARIES = libmod_tuscany_python.la libmod_tuscany_python_la_SOURCES = mod-python.cpp -libmod_tuscany_python_la_LDFLAGS = -lxml2 -lcurl -lmozjs -L${PYTHON_LIB} -R${PYTHON_LIB} -lpython${PYTHON_VERSION} +libmod_tuscany_python_la_LDFLAGS = -lxml2 -lcurl -ljansson -L${PYTHON_LIB} -R${PYTHON_LIB} -lpython${PYTHON_VERSION} noinst_DATA = libmod_tuscany_python${libsuffix} libmod_tuscany_python${libsuffix}: ln -s .libs/libmod_tuscany_python${libsuffix} @@ -47,7 +47,7 @@ python_shell_SOURCES = python-shell.cpp python_shell_LDFLAGS = -L${PYTHON_LIB} -R${PYTHON_LIB} -lpython${PYTHON_VERSION} client_test_SOURCES = client-test.cpp -client_test_LDFLAGS = -lxml2 -lcurl -lmozjs +client_test_LDFLAGS = -lxml2 -lcurl -ljansson dist_noinst_SCRIPTS = server-test wiring-test noinst_PROGRAMS = python-test client-test diff --git a/sca-cpp/trunk/modules/python/driver.hpp b/sca-cpp/trunk/modules/python/driver.hpp index a5d554172b..41daed32c3 100644 --- a/sca-cpp/trunk/modules/python/driver.hpp +++ b/sca-cpp/trunk/modules/python/driver.hpp @@ -35,9 +35,9 @@ namespace tuscany { namespace python { -const value evalDriverLoop(PyObject* script, istream& in, ostream& out, PythonRuntime& py) { +const value evalDriverLoop(PyObject* const script, istream& in, ostream& out, PythonRuntime& py) { scheme::promptForInput(scheme::evalInputPrompt, out); - value input = scheme::readValue(in); + const value input = content(scheme::readValue(in)); if (isNil(input)) return input; const failable<value> output = evalScript(input, script, py); @@ -46,11 +46,11 @@ const value evalDriverLoop(PyObject* script, istream& in, ostream& out, PythonRu return evalDriverLoop(script, in, out, py); } -const bool evalDriverRun(const char* path, istream& in, ostream& out) { +const bool evalDriverRun(const char* const path, istream& in, ostream& out) { PythonRuntime py; scheme::setupDisplay(out); ifstream is(path); - failable<PyObject*> script = readScript(moduleName(path), path, is, py); + const failable<PyObject*> script = readScript(moduleName(path), path, is, py); if (!hasContent(script)) return true; evalDriverLoop(content(script), in, out, py); diff --git a/sca-cpp/trunk/modules/python/eval.hpp b/sca-cpp/trunk/modules/python/eval.hpp index 5c0be7d261..3f9c6c20a2 100644 --- a/sca-cpp/trunk/modules/python/eval.hpp +++ b/sca-cpp/trunk/modules/python/eval.hpp @@ -53,8 +53,8 @@ class PythonRuntime; /** * Maintain a garbage collected reference to a Python object. */ -const bool pyIncRef(PyObject* o); -const bool pyDecRef(PyObject* o, PythonRuntime* py); +const bool pyIncRef(PyObject* const o); +const bool pyDecRef(PyObject* const o, PythonRuntime* const py); /** * Write to debug log from Python. @@ -70,7 +70,7 @@ const value pyDebug(const list<value>& args) { class PythonRuntime { public: - PythonRuntime() { + PythonRuntime() : owner(true) { debug("python::pythonruntime"); // Save current process id @@ -115,7 +115,7 @@ public: PySys_SetArgv(0, const_cast<char**>(&arg0)); // Install debug log function - PyObject* mkPyLambda(const lambda<value(const list<value>&)>& l, PythonRuntime* py); + PyObject* mkPyLambda(const lvvlambda& l, PythonRuntime* py); PyObject* pyd= mkPyLambda(pyDebug, this); PyObject* sys = PyImport_ImportModule("sys"); PyObject_SetAttrString(sys, "debug", pyd); @@ -127,10 +127,21 @@ public: #endif } +#ifdef WANT_THREADS + PythonRuntime(const PythonRuntime& py) : owner(false), mutex(py.mutex), pidmutex(py.pidmutex), pid(py.pid) { + } +#else + PythonRuntime(const PythonRuntime& py) : owner(false), pid(py.pid) { + } +#endif + + PythonRuntime& operator=(const PythonRuntime& py) = delete; + ~PythonRuntime() { } private: + const bool owner; #ifdef WANT_THREADS pthread_mutex_t mutex; pthread_mutex_t pidmutex; @@ -145,9 +156,9 @@ private: /** * Return the last python error. */ -const string lastErrorTrace(PyObject *trace) { +const string lastErrorTrace(PyObject* const trace) { if (trace == NULL) - return ""; + return emptyString; PyTracebackObject* tb = (PyTracebackObject*)trace; const int limit = 16; int depth = 0; @@ -167,16 +178,16 @@ const string lastErrorTrace(PyObject *trace) { return str(os); } -const string lastError(PythonRuntime* py) { +const string lastError(PythonRuntime* const py) { if(PyErr_Occurred()) { PyObject* type = NULL; PyObject* val = NULL; PyObject* trace = NULL; PyErr_Fetch(&type, &val, &trace); if (type != NULL && val != NULL) { - PyObject* stype = PyObject_Repr(type); - PyObject* sval = PyObject_Repr(val); - string msg = string() + PyString_AsString(stype) + " : " + PyString_AsString(sval) + lastErrorTrace(trace); + PyObject* const stype = PyObject_Repr(type); + PyObject* const sval = PyObject_Repr(val); + const string msg = string() + PyString_AsString(stype) + " : " + PyString_AsString(sval) + lastErrorTrace(trace); pyDecRef(stype, py); pyDecRef(sval, py); PyErr_Restore(type, val, trace); @@ -187,7 +198,7 @@ const string lastError(PythonRuntime* py) { PyErr_Clear(); return "Unknown Python error"; } - return ""; + return emptyString; } /** @@ -195,7 +206,7 @@ const string lastError(PythonRuntime* py) { */ class PythonRuntimeLock { public: - PythonRuntimeLock(PythonRuntime* py) : py(py) { + PythonRuntimeLock(PythonRuntime* const py) : py(py) { #ifdef WANT_THREADS pthread_mutex_lock(&py->mutex); #endif @@ -208,7 +219,7 @@ public: } private: - PythonRuntime* py; + PythonRuntime* const py; }; /** @@ -216,7 +227,7 @@ private: */ class PythonThreadIn { public: - PythonThreadIn(PythonRuntime* py) : py(py) { + PythonThreadIn(PythonRuntime* const py) : py(py) { // Reinitialize Python thread support after a fork const unsigned long pid = processId(); @@ -261,7 +272,7 @@ public: } private: - PythonRuntime* py; + PythonRuntime* const py; #ifdef WANT_THREADS PyGILState_STATE gstate; #endif @@ -272,7 +283,7 @@ private: */ class PythonThreadOut { public: - PythonThreadOut(PythonRuntime* py) : py(py) { + PythonThreadOut(PythonRuntime* const py) : py(py) { #ifdef WANT_THREADS //debug("python::gil::save"); tstate = PyEval_SaveThread(); @@ -289,7 +300,7 @@ public: } private: - PythonRuntime* py; + PythonRuntime* const py; #ifdef WANT_THREADS PyThreadState* tstate; #endif @@ -300,7 +311,7 @@ private: */ class PyGCRef { public: - PyGCRef(PyObject* o, PythonRuntime* py) : o(o), py(py) { + PyGCRef(PyObject* const o, PythonRuntime* const py) : o(o), py(py) { } ~PyGCRef() { @@ -311,21 +322,21 @@ public: } private: - PyObject* o; - PythonRuntime* py; + PyObject* const o; + PythonRuntime* const py; }; /** * Maintain a garbage collected reference to a Python object. */ -const bool pyIncRef(PyObject* o) { +const bool pyIncRef(PyObject* const o) { if (o == NULL) return true; Py_INCREF(o); return true; } -const bool pyDecRef(unused PyObject* o, unused PythonRuntime* py) { +const bool pyDecRef(unused PyObject* const o, unused PythonRuntime* const py) { if (o == NULL) return true; //new (gc_new<PyGCRef>()) PyGCRef(o, py); @@ -336,40 +347,40 @@ const bool pyDecRef(unused PyObject* o, unused PythonRuntime* py) { /** * Declare conversion functions. */ -PyObject* valueToPyObject(const value& v, PythonRuntime* py); -const value pyObjectToValue(PyObject *o, PythonRuntime* py); -PyObject* valuesToPyTuple(const list<value>& v, PythonRuntime* py); -const list<value> pyTupleToValues(PyObject* o, PythonRuntime* py); +PyObject* const valueToPyObject(const value& v, PythonRuntime* const py); +const value pyObjectToValue(PyObject* const o, PythonRuntime* const py); +PyObject* const valuesToPyTuple(const list<value>& v, PythonRuntime* const py); +const list<value> pyTupleToValues(PyObject* const o, PythonRuntime* const py); /** * Callable python type used to represent a lambda expression. */ typedef struct { PyObject_HEAD - lambda<value(const list<value>&)>* func; + lvvlambda* func; PythonRuntime* py; } pyLambda; -PyObject *mkPyLambda(const lambda<value(const list<value>&)>& l, PythonRuntime* py); +PyObject* const mkPyLambda(const lvvlambda& l, PythonRuntime* const py); -void pyLambda_dealloc(PyObject* self) { +void pyLambda_dealloc(PyObject* const self) { //debug(self, "python::pylambda_dealloc"); PyObject_Del(self); } -const string pyRepr(PyObject* o, PythonRuntime* py) { - PyObject* r = PyObject_Repr(o); +const string pyRepr(PyObject* const o, PythonRuntime* const py) { + PyObject* const r = PyObject_Repr(o); const string s = PyString_AsString(r); pyDecRef(r, py); return s; } -const value pyLambda_callout(const pyLambda* pyl, const list<value>& args, PythonRuntime* py) { +const value pyLambda_callout(const pyLambda* const pyl, const list<value>& args, PythonRuntime* const py) { PythonThreadOut pyout(py); return (*(pyl->func))(args); } -PyObject* pyLambda_call(PyObject* self, PyObject* args, unused PyObject* kwds) { +PyObject* const pyLambda_call(PyObject* const self, PyObject* const args, unused PyObject* const kwds) { debug("python::call"); const pyLambda* pyl = (const pyLambda*)self; const value result = pyLambda_callout(pyl, pyTupleToValues(args, pyl->py), pyl->py); @@ -378,22 +389,7 @@ PyObject* pyLambda_call(PyObject* self, PyObject* args, unused PyObject* kwds) { return pyr; } -struct pyProxy { - const value name; - const lambda<value(const list<value>&)> func; - - pyProxy(const value& name, const lambda<value(const list<value>&)>& func) : name(name), func(func) { - } - - const value operator()(const list<value>& args) const { - debug(name, "python::proxy::name"); - const value result = func(cons<value>(name, args)); - debug(result, "python::proxy::result"); - return result; - } -}; - -PyObject* pyLambda_getattr(PyObject *self, PyObject *attrname) { +PyObject* const pyLambda_getattr(PyObject* const self, PyObject* const attrname) { const string name = PyString_AsString(attrname); if (substr(name, 0, 1) == "_") return PyObject_GenericGetAttr(self, attrname); @@ -403,9 +399,18 @@ PyObject* pyLambda_getattr(PyObject *self, PyObject *attrname) { return self; } - const pyLambda* pyl = (pyLambda*)self; + const pyLambda* const pyl = (const pyLambda* const)self; debug(name, "python::getattr::name"); - PyObject* pyr = mkPyLambda(pyProxy(name, *(pyl->func)), pyl->py); + + const lvvlambda func = *(pyl->func); + const lvvlambda pyProxy = [name, func](const list<value>& args) -> const value { + debug(name, "python::proxy::name"); + const value result = func(cons<value>(name, args)); + debug(result, "python::proxy::result"); + return result; + }; + + PyObject* const pyr = mkPyLambda(pyProxy, pyl->py); return pyr; } @@ -464,10 +469,10 @@ PyObject* pyLambda_getattr(PyObject *self, PyObject *attrname) { /** * Create a new python object representing a lambda expression. */ -PyObject *mkPyLambda(const lambda<value(const list<value>&)>& l, PythonRuntime* py) { - pyLambda* pyl = PyObject_New(pyLambda, &pyLambda_type); +PyObject* const mkPyLambda(const lvvlambda& l, PythonRuntime* const py) { + pyLambda* const pyl = PyObject_New(pyLambda, &pyLambda_type); if (pyl != NULL) { - pyl->func = new (gc_new<lambda<value(const list<value>&)> >()) lambda<value(const list<value>&)>(l); + pyl->func = new (gc_new<lvvlambda >()) lvvlambda(l); pyl->py = py; } //debug(pyl, "python::mkpylambda"); @@ -477,18 +482,18 @@ PyObject *mkPyLambda(const lambda<value(const list<value>&)>& l, PythonRuntime* /** * Convert a list of values to a python list. */ -PyObject* valuesToPyListHelper(PyObject* l, const list<value>& v, PythonRuntime* py) { +PyObject* const valuesToPyListHelper(PyObject* const l, const list<value>& v, PythonRuntime* const py) { if (isNil(v)) return l; - PyObject* pyv = valueToPyObject(car(v), py); + PyObject* const pyv = valueToPyObject(car(v), py); PyList_Append(l, pyv); pyDecRef(pyv, py); return valuesToPyListHelper(l, cdr(v), py); } -PyObject* valuesToPyTuple(const list<value>& v, PythonRuntime* py) { - PyObject* pyl = valuesToPyListHelper(PyList_New(0), v, py); - PyObject* pyt = PyList_AsTuple(pyl); +PyObject* const valuesToPyTuple(const list<value>& v, PythonRuntime* const py) { + PyObject* const pyl = valuesToPyListHelper(PyList_New(0), v, py); + PyObject* const pyt = PyList_AsTuple(pyl); pyDecRef(pyl, py); return pyt; } @@ -496,14 +501,14 @@ PyObject* valuesToPyTuple(const list<value>& v, PythonRuntime* py) { /** * Convert a value to a python object. */ -PyObject* valueToPyObject(const value& v, PythonRuntime* py) { +PyObject* const valueToPyObject(const value& v, PythonRuntime* const py) { switch (type(v)) { case value::List: return valuesToPyTuple(v, py); case value::Lambda: return mkPyLambda(v, py); case value::Symbol: - return PyString_FromString(c_str(string("'") + v)); + return PyString_FromString(c_str(string("'") + (string)v)); case value::String: { const string s = (string)v; return PyString_FromStringAndSize(c_str(s), length(s)); @@ -511,12 +516,12 @@ PyObject* valueToPyObject(const value& v, PythonRuntime* py) { case value::Number: return PyFloat_FromDouble((double)v); case value::Bool: { - PyObject* b = (bool)v? Py_True : Py_False; + PyObject* const b = (bool)v? Py_True : Py_False; pyIncRef(b); return b; } default: { - PyObject* n = Py_None; + PyObject* const n = Py_None; pyIncRef(n); return n; } @@ -526,39 +531,29 @@ PyObject* valueToPyObject(const value& v, PythonRuntime* py) { /** * Convert a python tuple to a list of values. */ -const list<value> pyTupleToValuesHelper(PyObject* o, const size_t i, const size_t size, PythonRuntime* py) { +const list<value> pyTupleToValuesHelper(PyObject* const o, const size_t i, const size_t size, PythonRuntime* const py) { if (i == size) - return list<value>(); + return nilListValue; return cons(pyObjectToValue(PyTuple_GetItem(o, i), py), pyTupleToValuesHelper(o, i + 1, size, py)); } -const list<value> pyTupleToValues(PyObject* o, PythonRuntime* py) { +const list<value> pyTupleToValues(PyObject* const o, PythonRuntime* const py) { return pyTupleToValuesHelper(o, 0, PyTuple_Size(o), py); } /** * Lambda function used to represent a python callable object. */ -struct pyCallable { - PyObject* func; - PythonRuntime* py; - bool owner; - - pyCallable(PyObject* func, PythonRuntime* py) : func(func), py(py), owner(true) { +class pyCallable { +public: + pyCallable(PyObject* const func, PythonRuntime* const py) : func(func), py(py), owner(true) { pyIncRef(func); } pyCallable(const pyCallable& c) : func(c.func), py(c.py), owner(false) { } - const pyCallable& operator=(const pyCallable& c) { - if(this == &c) - return *this; - func = c.func; - py = c.py; - owner = false; - return *this; - } + pyCallable& operator=(const pyCallable& c) = delete; ~pyCallable() { if (!owner) @@ -569,16 +564,16 @@ struct pyCallable { const value operator()(const list<value>& args) const { PythonThreadIn pyin(py); if (debug_islogging()) { - PyObject* rfunc = PyObject_Repr(func); + PyObject* const rfunc = PyObject_Repr(func); char* s = NULL; Py_ssize_t l = 0; PyString_AsStringAndSize(rfunc, &s, &l); debug(string(s, l), "python::operator()::func"); pyDecRef(rfunc, py); } - PyObject* pyargs = valuesToPyTuple(args, py); + PyObject* const pyargs = valuesToPyTuple(args, py); if (debug_islogging()) { - PyObject* rargs = PyObject_Repr(pyargs); + PyObject* const rargs = PyObject_Repr(pyargs); char* s = NULL; Py_ssize_t l = 0; PyString_AsStringAndSize(rargs, &s, &l); @@ -586,21 +581,26 @@ struct pyCallable { pyDecRef(rargs, py); } - PyObject* result = PyObject_CallObject(func, pyargs); + PyObject* const result = PyObject_CallObject(func, pyargs); pyDecRef(pyargs, py); const value v = pyObjectToValue(result, py); pyDecRef(result, py); return v; } + +private: + PyObject* const func; + PythonRuntime* const py; + const bool owner; }; /** * Convert a python object to a value. */ -const value pyObjectToValue(PyObject *o, PythonRuntime* py) { +const value pyObjectToValue(PyObject* const o, PythonRuntime* const py) { if (o == NULL) - return value(); + return nilValue; if (PyString_Check(o)) { char* s = NULL; Py_ssize_t l = 0; @@ -622,8 +622,8 @@ const value pyObjectToValue(PyObject *o, PythonRuntime* py) { if (PyObject_TypeCheck(o, &pyLambda_type)) return *(((pyLambda*)o)->func); if (PyCallable_Check(o)) - return lambda<value(const list<value>&)>(pyCallable(o, py)); - return value(); + return lvvlambda(pyCallable(o, py)); + return nilValue; } /** @@ -636,37 +636,37 @@ const string moduleName(const string& path) { /** * Evaluate an expression against a script provided as a python object. */ -const failable<value> evalScript(const value& expr, PyObject* script, PythonRuntime& py) { +const failable<value> evalScript(const value& expr, PyObject* const script, PythonRuntime& py) { PythonThreadIn pyin(&py); // Get the requested function - PyObject* func = PyObject_GetAttrString(script, c_str(car<value>(expr))); + PyObject* const func = PyObject_GetAttrString(script, c_str(car<value>(expr))); if (func == NULL) { // The start, stop, and restart functions are optional const value fn = car<value>(expr); if (fn == "start" || fn == "stop") { PyErr_Clear(); - return value(lambda<value(const list<value>&)>()); + return value(lvvlambda()); } - return mkfailure<value>(string("Couldn't find function: ") + car<value>(expr) + " : " + lastError(&py)); + return mkfailure<value>(string("Couldn't find function: ") + (string)car<value>(expr) + " : " + lastError(&py)); } if (!PyCallable_Check(func)) { pyDecRef(func, &py); - return mkfailure<value>(string("Couldn't find callable function: ") + car<value>(expr)); + return mkfailure<value>(string("Couldn't find callable function: ") + (string)car<value>(expr)); } // Convert args to python objects - PyObject* args = valuesToPyTuple(cdr<value>(expr), &py); + PyObject* const args = valuesToPyTuple(cdr<value>(expr), &py); // Call the function - PyObject* result = PyObject_CallObject(func, args); + PyObject* const result = PyObject_CallObject(func, args); if (result == NULL) { const string msg = lastError(&py); pyDecRef(func, &py); pyDecRef(args, &py); - return mkfailure<value>(string("Function call failed: ") + car<value>(expr) + " : " + msg); + return mkfailure<value>(string("Function call failed: ") + (string)car<value>(expr) + " : " + msg); } pyDecRef(func, &py); pyDecRef(args, &py); @@ -684,8 +684,8 @@ const failable<PyObject*> readScript(const string& name, const string& path, ist PythonThreadIn pyin(&py); // Lookup already loaded module - PyObject *mods = PyImport_GetModuleDict(); - PyObject *emod = PyDict_GetItemString(mods, const_cast<char*>(c_str(name))); + PyObject* const mods = PyImport_GetModuleDict(); + PyObject* const emod = PyDict_GetItemString(mods, const_cast<char*>(c_str(name))); if (emod != NULL) return emod; @@ -695,10 +695,10 @@ const failable<PyObject*> readScript(const string& name, const string& path, ist const list<string> ls = streamList(is); ostringstream os; write(ls, os); - PyObject* code = Py_CompileStringFlags(c_str(str(os)), c_str(path), Py_file_input, NULL); + PyObject* const code = Py_CompileStringFlags(c_str(str(os)), c_str(path), Py_file_input, NULL); if (code == NULL) return mkfailure<PyObject*>(string("Couldn't compile script: ") + path + " : " + lastError(&py)); - PyObject* mod = PyImport_ExecCodeModuleEx(const_cast<char*>(c_str(name)), code, const_cast<char*>(c_str(path))); + PyObject* const mod = PyImport_ExecCodeModuleEx(const_cast<char*>(c_str(name)), code, const_cast<char*>(c_str(path))); if (mod == NULL) { const string msg = lastError(&py); pyDecRef(code, &py); @@ -708,7 +708,7 @@ const failable<PyObject*> readScript(const string& name, const string& path, ist pyDecRef(mod, &py); // Lookup the loaded module - PyObject *lmod = PyDict_GetItemString(mods, const_cast<char*>(c_str(name))); + PyObject* const lmod = PyDict_GetItemString(mods, const_cast<char*>(c_str(name))); if (lmod != NULL) return lmod; @@ -718,7 +718,7 @@ const failable<PyObject*> readScript(const string& name, const string& path, ist /** * Release a python script. */ -const failable<bool> releaseScript(unused PyObject* script, PythonRuntime& py) { +const failable<bool> releaseScript(unused PyObject* const script, PythonRuntime& py) { PythonThreadIn pyin(&py); // No need to decref the script here, as it's referenced only once from sys.modules return true; diff --git a/sca-cpp/trunk/modules/python/mod-python.cpp b/sca-cpp/trunk/modules/python/mod-python.cpp index 956edf1059..eaaeeb8e3e 100644 --- a/sca-cpp/trunk/modules/python/mod-python.cpp +++ b/sca-cpp/trunk/modules/python/mod-python.cpp @@ -40,42 +40,35 @@ namespace modeval { /** * Apply a lifecycle start or restart event. */ -struct pythonLifecycle { - python::PythonRuntime& py; - pythonLifecycle(python::PythonRuntime& py) : py(py) { - } - const value operator()(const list<value>& params) const { - const value func = car(params); - if (func == "pythonRuntime") - return (gc_ptr<value>)(value*)&py; - return lambda<value(const list<value>&)>(); - } -}; - const value applyLifecycle(unused const list<value>& params) { // Create a Python runtime python::PythonRuntime& py = *(new (gc_new<python::PythonRuntime>()) python::PythonRuntime()); // Return the function to invoke on subsequent events - return failable<value>(lambda<value(const list<value>&)>(pythonLifecycle(py))); + return failable<value>(lvvlambda([&py](const list<value>& params) -> const value { + const value func = car(params); + if (func == "pythonRuntime") + return (gc_ptr<value>)(value*)&py; + return lvvlambda(); + })); } /** * Evaluate a Python component implementation and convert it to an applicable * lambda function. */ -const failable<lambda<value(const list<value>&)> > evalImplementation(const string& path, const value& impl, const list<value>& px, const lambda<value(const list<value>&)>& lifecycle) { +const failable<lvvlambda > evalImplementation(const string& path, const value& impl, const list<value>& px, const lvvlambda& lifecycle) { const string itype(elementName(impl)); if (contains(itype, ".python")) { - const value* p = (gc_ptr<value>)lifecycle(mklist<value>("pythonRuntime")); + const value* const p = (gc_ptr<value>)lifecycle(mklist<value>("pythonRuntime")); return modpython::evalImplementation(path, impl, px, *(python::PythonRuntime*)p); } if (contains(itype, ".cpp")) return modcpp::evalImplementation(path, impl, px); if (contains(itype, ".widget")) - return mkfailure<lambda<value(const list<value>&)> >(string("Unsupported implementation type: ") + itype, -1, false); - return mkfailure<lambda<value(const list<value>&)> >(string("Unsupported implementation type: ") + itype); + return mkfailure<lvvlambda >(string("Unsupported implementation type: ") + itype, -1, false); + return mkfailure<lvvlambda >(string("Unsupported implementation type: ") + itype); } } diff --git a/sca-cpp/trunk/modules/python/mod-python.hpp b/sca-cpp/trunk/modules/python/mod-python.hpp index e6effb985b..00f2e4ab4e 100644 --- a/sca-cpp/trunk/modules/python/mod-python.hpp +++ b/sca-cpp/trunk/modules/python/mod-python.hpp @@ -40,38 +40,30 @@ namespace server { namespace modpython { /** - * Apply a Python component implementation function. - */ -struct applyImplementation { - PyObject* impl; - const list<value> px; - python::PythonRuntime& py; - applyImplementation(PyObject* impl, const list<value>& px, python::PythonRuntime& py) : impl(impl), px(px), py(py) { - } - const value operator()(const list<value>& params) const { - const value expr = append<value>(params, px); - debug(expr, "modeval::python::applyImplementation::input"); - const failable<value> res = python::evalScript(expr, impl, py); - const value val = !hasContent(res)? mklist<value>(value(), reason(res), rcode(res)) : mklist<value>(content(res)); - debug(val, "modeval::python::applyImplementation::result"); - return val; - } -}; - -/** * Evaluate a Python component implementation and convert it to an applicable * lambda function. */ -const failable<lambda<value(const list<value>&)> > evalImplementation(const string& path, const value& impl, const list<value>& px, python::PythonRuntime& py) { +const failable<lvvlambda > evalImplementation(const string& path, const value& impl, const list<value>& px, python::PythonRuntime& py) { const string spath(attributeValue("script", impl)); const string fpath(path + spath); ifstream is(fpath); if (fail(is)) - return mkfailure<lambda<value(const list<value>&)> >(string("Could not read implementation: ") + fpath); - const failable<PyObject*> script = python::readScript(python::moduleName(spath), fpath, is, py); - if (!hasContent(script)) - return mkfailure<lambda<value(const list<value>&)> >(script); - return lambda<value(const list<value>&)>(applyImplementation(content(script), px, py)); + return mkfailure<lvvlambda >(string("Could not read implementation: ") + fpath); + const failable<PyObject*> fscript = python::readScript(python::moduleName(spath), fpath, is, py); + if (!hasContent(fscript)) + return mkfailure<lvvlambda >(fscript); + PyObject* const script = content(fscript); + + const lvvlambda applyImplementation = [script, px, &py](const list<value>& params) -> const value { + // Apply a Python component implementation function + const value expr = append<value>(params, px); + debug(expr, "modeval::python::applyImplementation::input"); + const failable<value> res = python::evalScript(expr, script, py); + const value val = !hasContent(res)? mklist<value>(nilValue, reason(res), rcode(res)) : mklist<value>(content(res)); + debug(val, "modeval::python::applyImplementation::result"); + return val; + }; + return applyImplementation; } } diff --git a/sca-cpp/trunk/modules/python/python-shell.cpp b/sca-cpp/trunk/modules/python/python-shell.cpp index 89b47b8d44..7575ffa077 100644 --- a/sca-cpp/trunk/modules/python/python-shell.cpp +++ b/sca-cpp/trunk/modules/python/python-shell.cpp @@ -29,8 +29,8 @@ #include "string.hpp" #include "driver.hpp" -int main(const int argc, char** argv) { - tuscany::gc_scoped_pool pool; +int main(const int argc, const char** const argv) { + const tuscany::gc_scoped_pool pool; if (argc != 2) { tuscany::cerr << "Usage: python-shell <script.py>" << tuscany::endl; return 1; diff --git a/sca-cpp/trunk/modules/python/python-test.cpp b/sca-cpp/trunk/modules/python/python-test.cpp index 29a66cc2e7..44a72f8f88 100644 --- a/sca-cpp/trunk/modules/python/python-test.cpp +++ b/sca-cpp/trunk/modules/python/python-test.cpp @@ -37,12 +37,12 @@ const string testPythonAdd = "def add(x, y):\n" " return x + y\n"; -bool testEvalExpr() { - gc_scoped_pool pool; +const bool testEvalExpr() { + const gc_scoped_pool pool; PythonRuntime py; istringstream is(testPythonAdd); - failable<PyObject*> script = readScript("script1", "script1.py", is, py); + const failable<PyObject*> script = readScript("script1", "script1.py", is, py); assert(hasContent(script)); const value exp = mklist<value>("add", 2, 3); @@ -58,12 +58,12 @@ const string testPythonMap = "def addmap(x, y):\n" " return tuple(map(lambda i: i + y, x))\n"; -bool testEvalList() { - gc_scoped_pool pool; +const bool testEvalList() { + const gc_scoped_pool pool; PythonRuntime py; istringstream is(testPythonMap); - failable<PyObject*> script = readScript("script2", "script2.py", is, py); + const failable<PyObject*> script = readScript("script2", "script2.py", is, py); assert(hasContent(script)); const value exp = mklist<value>("addmap", mklist<value>(1, 2, 3), 1); @@ -94,8 +94,8 @@ const string testCallLambda( "def testCallLambda(l, x, y):\n" " return l(x, y)\n"); -bool testEvalLambda() { - gc_scoped_pool pool; +const bool testEvalLambda() { + const gc_scoped_pool pool; PythonRuntime py; const value trl = mklist<value>("testReturnLambda"); @@ -104,7 +104,7 @@ bool testEvalLambda() { assert(hasContent(trlv)); assert(isLambda(content(trlv))); - const lambda<value(const list<value>&)> trll(content(trlv)); + const lvvlambda trll(content(trlv)); assert(trll(mklist<value>(2, 3)) == value(6)); istringstream tclis(testCallLambda); @@ -114,20 +114,20 @@ bool testEvalLambda() { assert(content(tclv) == value(6)); istringstream tcelis(testCallLambda); - const value tcel = mklist<value>("testCallLambda", lambda<value(const list<value>&)>(mult), 3, 4); + const value tcel = mklist<value>("testCallLambda", lvvlambda(mult), 3, 4); const failable<value> tcelv = evalScript(tcel, tcelis, py); assert(hasContent(tcelv)); assert(content(tcelv) == value(12)); return true; } -struct testEvalReadAdd { - PythonRuntime& py; - testEvalReadAdd(PythonRuntime& py) : py(py) { - } - const bool operator()() const { +const bool testEvalPerf() { + const gc_scoped_pool pool; + PythonRuntime py; + + const blambda erl = [&py]() -> const bool { istringstream is(testPythonAdd); - failable<PyObject*> script = readScript("script3", "script3.py", is, py); + const failable<PyObject*> script = readScript("script3", "script3.py", is, py); assert(hasContent(script)); const value exp = mklist<value>("add", 2, 3); @@ -137,51 +137,36 @@ struct testEvalReadAdd { releaseScript(content(script), py); return true; - } -}; - -struct testEvalAdd { - PyObject* script; - PythonRuntime& py; - testEvalAdd(PyObject* script, PythonRuntime& py) : script(script), py(py) { - } - const bool operator()() const { + }; + cout << "Python read + eval test " << time(erl, 5, 10000) << " ms" << endl; + + istringstream is(testPythonAdd); + const failable<PyObject*> fscript = readScript("script4", "script4.py", is, py); + assert(hasContent(fscript)); + + PyObject* const script = content(fscript); + const blambda el = [script, &py]() -> const bool { const value exp = mklist<value>("add", 2, 3); const failable<value> r = evalScript(exp, script, py); assert(hasContent(r)); assert(content(r) == value(5)); return true; - } -}; - -bool testEvalPerf() { - gc_scoped_pool pool; - PythonRuntime py; - - const lambda<bool()> erl = lambda<bool()>(testEvalReadAdd(py)); - cout << "Python read + eval test " << time(erl, 5, 10000) << " ms" << endl; - - istringstream is(testPythonAdd); - failable<PyObject*> script = readScript("script4", "script4.py", is, py); - assert(hasContent(script)); - - const lambda<bool()> el = lambda<bool()>(testEvalAdd(content(script), py)); + }; cout << "Python eval test " << time(el, 5, 10000) << " ms" << endl; - releaseScript(content(script), py); + releaseScript(script, py); return true; } #ifdef WANT_THREADS -struct testReadEvalAddLoop { - PythonRuntime& py; - testReadEvalAddLoop(PythonRuntime& py) : py(py) { - } - const bool operator()() const { +const list<future<bool> > submitReadEvals(worker& w, const int max, const int i, PythonRuntime& py) { + if (i == max) + return list<future<bool> >(); + const blambda func = [&py]() -> const bool { for (int i = 0; i < 100; i++) { istringstream is(testPythonAdd); - failable<PyObject*> script = readScript("script6", "script6.py", is, py); + const failable<PyObject*> script = readScript("script6", "script6.py", is, py); assert(hasContent(script)); const value exp = mklist<value>("add", 2, 3); @@ -192,15 +177,14 @@ struct testReadEvalAddLoop { releaseScript(content(script), py); } return true; - } -}; - -struct testEvalAddLoop { - PyObject* script; - PythonRuntime& py; - testEvalAddLoop(PyObject* script, PythonRuntime& py) : script(script), py(py) { - } - const bool operator()() const { + }; + return cons(submit(w, func), submitReadEvals(w, max, i + 1, py)); +} + +const list<future<bool> > submitEvals(worker& w, const int max, const int i, PyObject* const script, PythonRuntime& py) { + if (i == max) + return list<future<bool> >(); + const blambda func = [script, &py]() -> const bool { for (int i = 0; i < 100; i++) { const value exp = mklist<value>("add", 2, 3); const failable<value> r = evalScript(exp, script, py); @@ -208,75 +192,44 @@ struct testEvalAddLoop { assert(content(r) == value(5)); } return true; - } -}; - -const list<future<bool> > submitReadEvals(worker& w, const int max, const int i, PythonRuntime& py) { - if (i == max) - return list<future<bool> >(); - const lambda<bool()> func = lambda<bool()>(testReadEvalAddLoop(py)); - return cons(submit(w, func), submitReadEvals(w, max, i + 1, py)); -} - -const list<future<bool> > submitEvals(worker& w, const int max, const int i, PyObject* script, PythonRuntime& py) { - if (i == max) - return list<future<bool> >(); - const lambda<bool()> func = lambda<bool()>(testEvalAddLoop(script, py)); + }; return cons(submit(w, func), submitEvals(w, max, i + 1, script, py)); } -bool checkEvalResults(const list<future<bool> > r) { +const bool checkEvalResults(const list<future<bool> > r) { if (isNil(r)) return true; assert(car(r) == true); return checkEvalResults(cdr(r)); } -struct testReadEvalThreads { - worker& w; - const int max; - PythonRuntime& py; - testReadEvalThreads(worker& w, const int max, PythonRuntime& py) : w(w), max(max), py(py) { - } - const bool operator()() const { - const list<future<bool> > r(submitReadEvals(w, max, 0, py)); - checkEvalResults(r); - return true; - } -}; - -struct testEvalThreads { - worker& w; - const int max; - PyObject* script; - PythonRuntime& py; - testEvalThreads(worker& w, const int max, PyObject* script, PythonRuntime& py) : w(w), max(max), script(script), py(py) { - } - const bool operator()() const { - const list<future<bool> > r(submitEvals(w, max, 0, script, py)); - checkEvalResults(r); - return true; - } -}; - -bool testThreads() { - gc_scoped_pool pool; +const bool testThreads() { + const gc_scoped_pool pool; PythonRuntime py; const int max = 100; worker w(max); - const lambda<bool()> elr = lambda<bool()>(testReadEvalThreads(w, max, py)); + const blambda elr = [&w, max, &py]() -> const bool { + const list<future<bool> > r(submitReadEvals(w, max, 0, py)); + checkEvalResults(r); + return true; + }; cout << "Python eval + read thread test " << time(elr, 1, 1) / 10000.0 << " ms" << endl; istringstream is(testPythonAdd); - failable<PyObject*> script = readScript("script7", "script7.py", is, py); - assert(hasContent(script)); + const failable<PyObject*> fscript = readScript("script7", "script7.py", is, py); + assert(hasContent(fscript)); - const lambda<bool()> el = lambda<bool()>(testEvalThreads(w, max, content(script), py)); + PyObject* const script = content(fscript); + const blambda el = [&w, max, script, &py]() -> const bool { + const list<future<bool> > r(submitEvals(w, max, 0, script, py)); + checkEvalResults(r); + return true; + }; cout << "Python eval thread test " << time(el, 1, 1) / 10000.0 << " ms" << endl; - releaseScript(content(script), py); + releaseScript(script, py); return true; } @@ -286,7 +239,7 @@ bool testThreads() { } int main() { - tuscany::gc_scoped_pool p; + const tuscany::gc_scoped_pool p; tuscany::cout << "Testing..." << tuscany::endl; tuscany::python::testEvalExpr(); |