diff options
-rw-r--r-- | sca-cpp/trunk/configure.ac | 21 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/python/Makefile.am | 31 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/python/driver.hpp | 85 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/python/eval.hpp | 286 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/python/io.hpp | 167 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/python/python-shell.cpp | 40 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/python/python-test.cpp | 135 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/python/tuscany-sca-1.1-implementation-python.xsd | 43 |
8 files changed, 806 insertions, 2 deletions
diff --git a/sca-cpp/trunk/configure.ac b/sca-cpp/trunk/configure.ac index 99650734c3..95d984396c 100644 --- a/sca-cpp/trunk/configure.ac +++ b/sca-cpp/trunk/configure.ac @@ -124,6 +124,20 @@ AC_ARG_WITH([httpd], [AC_HELP_STRING([--with-httpd=PATH], [path to installed htt ]) AC_SUBST(HTTPD_INCLUDE) +# Configure PYTHON_INCLUDE and PYTHON_LIB +AC_MSG_CHECKING([for python]) +AC_ARG_WITH([curl], [AC_HELP_STRING([--with-python=PATH], [path to installed python 2.6 [default=/usr]])], [ + PYTHON_INCLUDE="${withval}/include" + PYTHON_LIB="${withval}/lib" + AC_MSG_RESULT("${withval}") +], [ + PYTHON_INCLUDE="/usr/include" + PYTHON_LIB="/usr/lib" + AC_MSG_RESULT(/usr) +]) +AC_SUBST(PYTHON_INCLUDE) +AC_SUBST(PYTHON_LIB) + # Checks for libraries. original_LIBS="${LIBS}" AC_MSG_NOTICE([checking for libraries]) @@ -138,6 +152,8 @@ AC_CHECK_LIB([xml2], [xmlInitParser], [], [AC_MSG_ERROR([couldn't find a suitabl LIBS="-L${APR_LIB} ${original_LIBS}" AC_CHECK_LIB([apr-1], [apr_pool_initialize], [], [AC_MSG_ERROR([couldn't find a suitable libapr-1, use --with-apr=PATH])]) AC_CHECK_LIB([aprutil-1], [apr_memcache_replace], [], [AC_MSG_ERROR([couldn't find a suitable libaprutil-1, use --with-apr=PATH])]) +LIBS="-L${PYTHON_LIB} ${original_LIBS}" +AC_CHECK_LIB([python2.6], [Py_Initialize], [], [AC_MSG_ERROR([couldn't find a suitable libpython2.6, use --with-python=PATH])]) LIBS="${original_LIBS}" # Checks for header files. @@ -175,7 +191,7 @@ AC_ARG_ENABLE(maintainer-mode, [AS_HELP_STRING([--enable-maintainer-mode], [comp esac ], [ AC_MSG_RESULT(no)]) if test "${want_maintainer_mode}" = "true"; then - cxxflags="${cxxflags} -D_DEBUG -O0 -g3 -Werror -Wall -Wextra -Wno-ignored-qualifiers -Winit-self -Wmissing-include-dirs -Wcast-qual -Wcast-align -Wwrite-strings -Wpointer-arith -Wconversion -Waddress -Wlogical-op -Wredundant-decls -std=c++0x -fmessage-length=0" + cxxflags="${cxxflags} -D_DEBUG -O0 -ggdb -g3 -Werror -Wall -Wextra -Wno-ignored-qualifiers -Winit-self -Wmissing-include-dirs -Wcast-qual -Wcast-align -Wwrite-strings -Wpointer-arith -Wconversion -Waddress -Wlogical-op -Wredundant-decls -std=c++0x -fmessage-length=0" ldflags="${ldflags} -pg" else cxxflags="${cxxflags} -O3 -std=c++0x -fmessage-length=0" @@ -256,9 +272,10 @@ AC_CONFIG_FILES([Makefile kernel/Makefile modules/Makefile modules/atom/Makefile - modules/eval/Makefile + modules/scheme/Makefile modules/http/Makefile modules/json/Makefile + modules/python/Makefile modules/scdl/Makefile modules/server/Makefile components/Makefile diff --git a/sca-cpp/trunk/modules/python/Makefile.am b/sca-cpp/trunk/modules/python/Makefile.am new file mode 100644 index 0000000000..d61ca5bed3 --- /dev/null +++ b/sca-cpp/trunk/modules/python/Makefile.am @@ -0,0 +1,31 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +noinst_PROGRAMS = python-test python-shell + +datadir=$(prefix)/modules/python +nobase_data_DATA = *.xsd + +INCLUDES = -I. -I$(top_builddir)/kernel -I${LIBXML2_INCLUDE} -I${APR_INCLUDE} -I${PYTHON_INCLUDE} + +python_test_SOURCES = python-test.cpp +python_test_LDADD = -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1 -L${PYTHON_LIB} -lpython2.6 + +python_shell_SOURCES = python-shell.cpp +python_shell_LDADD = -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1 -L${PYTHON_LIB} -lpython2.6 + +TESTS = python-test diff --git a/sca-cpp/trunk/modules/python/driver.hpp b/sca-cpp/trunk/modules/python/driver.hpp new file mode 100644 index 0000000000..a7139889b9 --- /dev/null +++ b/sca-cpp/trunk/modules/python/driver.hpp @@ -0,0 +1,85 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/* $Rev$ $Date$ */ + +#ifndef tuscany_python_pydriver_hpp +#define tuscany_python_pydriver_hpp + +/** + * Python evaluator main driver loop. + */ + +#include "string.hpp" +#include "stream.hpp" +#include "monad.hpp" +#include "eval.hpp" + +namespace tuscany { +namespace python { + +const string evalOutputPrompt("; "); +const string evalInputPrompt("=> "); + +const bool promptForInput(const string& str, ostream& out) { + out << endl << endl << str; + return true; +} + +const bool announceOutput(const string str, ostream& out) { + out << endl << str; + return true; +} + +const bool userPrint(const value val, ostream& out) { + writeValue(val, out); + return true; +} + +const value evalDriverLoop(PyObject* script, istream& in, ostream& out, const gc_pool& pool) { + promptForInput(evalInputPrompt, out); + value input = readValue(in); + if (isNil(input)) + return input; + const value output = evalScript(input, script, pool); + announceOutput(evalOutputPrompt, out); + userPrint(output, out); + return evalDriverLoop(script, in, out, pool); +} + +const bool evalDriverRun(istream& in, ostream& out, const gc_pool& pool) { + setupDisplay(out); + evalDriverLoop(builtin(pythonRuntime), in, out, pool); + return true; +} + +const bool evalDriverRun(const char* path, istream& in, ostream& out, const gc_pool& pool) { + setupDisplay(out); + ifstream is(path); + failable<PyObject*> script = readScript(path, is); + if (!hasContent(script)) + return true; + evalDriverLoop(content(script), in, out, pool); + Py_DECREF(content(script)); + return true; +} + +} +} +#endif /* tuscany_scheme_pydriver_hpp */ diff --git a/sca-cpp/trunk/modules/python/eval.hpp b/sca-cpp/trunk/modules/python/eval.hpp new file mode 100644 index 0000000000..8d709731a6 --- /dev/null +++ b/sca-cpp/trunk/modules/python/eval.hpp @@ -0,0 +1,286 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/* $Rev$ $Date$ */ + +#ifndef tuscany_python_pyeval_hpp +#define tuscany_python_pyeval_hpp + +/** + * Python script evaluation logic. + */ +#include <python2.6/Python.h> + +#include "list.hpp" +#include "value.hpp" +#include "io.hpp" + +namespace tuscany { +namespace python { + +/** + * Initialize the Python runtime. + */ +class PythonRuntime { +public: + PythonRuntime() { + Py_Initialize(); + + // Import the builtin module + PyObject* p = PyString_FromString("__builtin__"); + builtin = PyImport_Import(p); + Py_DECREF(p); + + setupIO(); + } + + ~PythonRuntime() { + Py_DECREF(builtin); + } + +private: + friend PyObject* builtin(const PythonRuntime& r); + + PyObject* builtin; + +} pythonRuntime; + +PyObject* builtin(const PythonRuntime& r) { + return r.builtin; +} + +/** + * Declare conversion functions. + */ +PyObject* valueToPyObject(const value& v); +const value pyObjectToValue(PyObject *o); +PyObject* valuesToPyTuple(const list<value>& v); +const list<value> pyTupleToValues(PyObject* o); + +/** + * Callable python type used to represent a lambda expression. + */ +typedef struct { + PyObject_HEAD + lambda<value(const list<value>&)> func; +} pyLambda; + +void pyLambda_dealloc(PyObject* self) { + PyMem_DEL(self); +} + +PyObject* pyLambda_call(PyObject* self, PyObject* args, unused PyObject* kwds) { + const pyLambda* pyl = (pyLambda*)self; + const value result = pyl->func(pyTupleToValues(args)); + Py_DECREF(args); + PyObject *pyr = valueToPyObject(result); + return pyr; +} + +PyTypeObject pyLambda_type = { + PyObject_HEAD_INIT(0) + 0, + "lambda", + sizeof(pyLambda), + 0, + (destructor)pyLambda_dealloc, + 0, 0, 0, 0, 0, 0, 0, 0, 0, + (ternaryfunc)pyLambda_call, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0 +}; + +/** + * Create a new python object representing a lambda expression. + */ +PyObject *mkPyLambda(const lambda<value(const list<value>&)> l) { + pyLambda* pyl = NULL; + pyl = PyObject_NEW(pyLambda, &pyLambda_type); + if (pyl != NULL) + pyl->func = l; + return (PyObject *)pyl; +} + +/** + * Convert a list of values to a python list. + */ + +PyObject* valuesToPyListHelper(PyObject* l, const list<value>& v) { + if (isNil(v)) + return l; + PyList_Append(l, valueToPyObject(car(v))); + return valuesToPyListHelper(l, cdr(v)); +} + +PyObject* valuesToPyTuple(const list<value>& v) { + return PyList_AsTuple(valuesToPyListHelper(PyList_New(0), v)); +} + +/** + * Convert a value to a python object. + */ +PyObject* valueToPyObject(const value& v) { + switch (type(v)) { + case value::List: + return valuesToPyTuple(v); + case value::Lambda: + return mkPyLambda(v); + case value::Symbol: + case value::String: + return PyString_FromString(c_str(v)); + case value::Number: + return PyFloat_FromDouble((double)v); + case value::Bool: + return (bool)v? Py_True : Py_False; + case value::Char: + return PyInt_FromLong((long)((char)v)); + case value::Ptr: + return NULL; + default: + return NULL; + } +} + +/** + * Convert a python tuple to a list of values. + */ + +const list<value> pyTupleToValuesHelper(PyObject* o, int i, int size) { + if (i == size) + return list<value>(); + return cons(pyObjectToValue(PyTuple_GetItem(o, i)), pyTupleToValuesHelper(o, i + 1, size)); +} + +const list<value> pyTupleToValues(PyObject* o) { + return pyTupleToValuesHelper(o, 0, PyTuple_Size(o)); +} + +/** + * Lambda function used to represent a python callable object. + */ +struct pyCallable { + PyObject* func; + + pyCallable(PyObject* func) : func(func) { + Py_INCREF(func); + } + + ~pyCallable() { + Py_DECREF(func); + } + + const value operator()(const list<value>& args) const { + PyObject* pyargs = valuesToPyTuple(args); + PyObject* result = PyObject_CallObject(func, pyargs); + Py_DECREF(pyargs); + const value v = pyObjectToValue(result); + Py_DECREF(result); + return v; + } +}; + +/** + * Convert a python object to a value. + */ +const value pyObjectToValue(PyObject *o) { + if (PyString_Check(o)) + return value(string(PyString_AsString(o))); + if (PyBool_Check(o)) + return value(o == Py_True); + if (PyInt_Check(o)) + return value((double)PyInt_AsLong(o)); + if (PyLong_Check(o)) + return value((double)PyLong_AsLong(o)); + if (PyFloat_Check(o)) + return value((double)PyFloat_AsDouble(o)); + if (PyTuple_Check(o)) + return pyTupleToValues(o); + if (PyCallable_Check(o)) + return lambda<value(const list<value>&)>(pyCallable(o)); + return value(); +} + +/** + * Read a python script from an input stream. + */ +const failable<PyObject*> readScript(const string& path, istream& is) { + 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); + if (code == NULL) + return mkfailure<PyObject*>(string("Couldn't compile script: ") + path + " : " + lastError()); + PyObject* mod = PyImport_ExecCodeModule(const_cast<char*>(c_str(path)), code); + if (mod == NULL) + return mkfailure<PyObject*>(string("Couldn't import module: ") + path + " : " + lastError()); + return mod; +} + +/** + * Evaluate an expression against a script provided as a python object. + */ +const failable<value> evalScript(const value& expr, PyObject* script, unused const gc_pool& pool) { + + // Get the requested function + PyObject* func = PyObject_GetAttrString(script, c_str(car<value>(expr))); + if (func == NULL) + return mkfailure<value>(string("Couldn't find function: ") + car<value>(expr) + " : " + lastError()); + if (!PyCallable_Check(func)) { + Py_DECREF(func); + return mkfailure<value>(string("Couldn't find callable function: ") + car<value>(expr)); + } + + // Convert args to python objects + PyObject* args = valuesToPyTuple(cdr<value>(expr)); + + // Call the function + PyObject* result = PyObject_CallObject(func, args); + Py_DECREF(args); + Py_DECREF(func); + if (result == NULL) + return mkfailure<value>(string("Function call failed: ") + car<value>(expr) + " : " + lastError()); + + // Convert python result to a value + const value v = pyObjectToValue(result); + Py_DECREF(result); + return v; +} + +/** + * Evaluate an expression against a script provided as an input stream. + */ +const failable<value> evalScript(const value& expr, istream& is, unused const gc_pool& pool) { + failable<PyObject*> script = readScript("script", is); + if (!hasContent(script)) + return mkfailure<value>(reason(script)); + return evalScript(expr, content(script), pool); +} + +/** + * Evaluate an expression against the python builtin module, no script is provided. + */ +const failable<value> evalExpr(const value& expr, const gc_pool& pool) { + return evalScript(expr, builtin(pythonRuntime), pool); +} + +} +} +#endif /* tuscany_python_pyeval_hpp */ diff --git a/sca-cpp/trunk/modules/python/io.hpp b/sca-cpp/trunk/modules/python/io.hpp new file mode 100644 index 0000000000..4292c32c34 --- /dev/null +++ b/sca-cpp/trunk/modules/python/io.hpp @@ -0,0 +1,167 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/* $Rev$ $Date$ */ + +#ifndef tuscany_python_pyio_hpp +#define tuscany_python_pyio_hpp + +/** + * Hooks used to capture python stdout and stderr. + */ +#include <python2.6/Python.h> + +#include "stream.hpp" +#include "../scheme/io.hpp" + +namespace tuscany { +namespace python { + +#ifdef _REENTRANT +__thread +#endif +ostream* displayOutStream = NULL; + +#ifdef _REENTRANT +__thread +#endif +ostream* logOutStream = NULL; + +/** + * Setup the display stream. + */ +const bool setupDisplay(ostream& out) { + scheme::setupDisplay(out); + displayOutStream = &out; + return true; +} + +ostream& displayStream() { + if (displayOutStream == NULL) + return cout; + return *displayOutStream; +} + +/** + * Setup the log stream. + */ +const bool setupLog(ostream& out) { + scheme::setupLog(out); + logOutStream = &out; + return true; +} + +ostream& logStream() { + if (logOutStream == NULL) + return cerr; + return *logOutStream; +} + +/** + * Hook method used to redirect python output to a stream. + */ +PyObject* display(unused PyObject* self, PyObject* args) { + char* s = NULL; + if (!PyArg_ParseTuple(args, "s", &s)) + return NULL; + + displayStream() << s; + + Py_INCREF(Py_None); + return Py_None; +} + +PyMethodDef displayHookMethods[] = { + {"display", display, METH_VARARGS, "Redirects stdout"}, + {NULL, NULL, 0, NULL}}; + +/** + * Hook method used to redirect python errors to a stream. + */ +PyObject* log(unused PyObject* self, PyObject* args) { + char* s = NULL; + if (!PyArg_ParseTuple(args, "s", &s)) + return NULL; + + logStream() << s; + + Py_INCREF(Py_None); + return Py_None; +} + +PyMethodDef logHookMethods[] = { + {"log", log, METH_VARARGS, "Redirects stdout"}, + {NULL, NULL, 0, NULL}}; + +/** + * Setup the display and log hooks. + */ +bool setupIO() { + Py_InitModule("displayhook", displayHookMethods); + PyRun_SimpleString( + "import sys\n" + "import displayhook\n" + "\n" + "class DisplayHook:\n" + " def write(self, text):\n" + " displayhook.display(text)\n" + "\n" + "sys.stdout = DisplayHook()\n"); + + Py_InitModule("loghook", logHookMethods); + PyRun_SimpleString( + "import sys\n" + "import loghook\n" + "\n" + "class LogHook:\n" + " def write(self, text):\n" + " loghook.log(text)\n" + "\n" + "sys.stderr = LogHook()\n"); + return true; +} + +/** + * Return the last python error. + */ +const string lastError() { + ostream* pos = logOutStream; + ostringstream eos; + logOutStream = &eos; + if (PyErr_Occurred()) + PyErr_Print(); + logOutStream = pos; + return str(eos); +} + +/** + * Read and write values (using the scheme representation as it's the canonical + * representation used throughout the runtime.) + */ +const value readValue(istream& in) { + return scheme::readValue(in); +} + +const bool writeValue(const value& val, ostream& out) { + return scheme::writeValue(val, out); +} + +} +} +#endif /* tuscany_python_pyio_hpp */ diff --git a/sca-cpp/trunk/modules/python/python-shell.cpp b/sca-cpp/trunk/modules/python/python-shell.cpp new file mode 100644 index 0000000000..0525ea2f2c --- /dev/null +++ b/sca-cpp/trunk/modules/python/python-shell.cpp @@ -0,0 +1,40 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/* $Rev$ $Date$ */ + +/** + * Python script evaluator shell, used for interactive testing of scripts. + */ + +#include <assert.h> +#include "gc.hpp" +#include "stream.hpp" +#include "string.hpp" +#include "driver.hpp" + +int main(const int argc, char** argv) { + tuscany::gc_scoped_pool pool; + if (argc == 1) { + tuscany::python::evalDriverRun(tuscany::cin, tuscany::cout, pool); + return 0; + } + tuscany::python::evalDriverRun(argv[1], tuscany::cin, tuscany::cout, pool); + return 0; +} diff --git a/sca-cpp/trunk/modules/python/python-test.cpp b/sca-cpp/trunk/modules/python/python-test.cpp new file mode 100644 index 0000000000..612dc5b79d --- /dev/null +++ b/sca-cpp/trunk/modules/python/python-test.cpp @@ -0,0 +1,135 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/* $Rev$ $Date$ */ + +/** + * Test Python script evaluator. + */ + +#include <assert.h> +#include "stream.hpp" +#include "string.hpp" +#include "driver.hpp" + +namespace tuscany { +namespace python { + +const value evalBuiltin(const string& py, const gc_pool& pool) { + istringstream is(py); + ostringstream os; + evalDriverRun(is, os, pool); + return str(os); +} + +const string testPythonPrint( + "(print \"testPrint ok\")"); + +bool testEval() { + gc_scoped_pool pool; + assert(contains(evalBuiltin(testPythonPrint, pool), "testPrint ok")); + return true; +} + +const string testPythonAdd = + "def add(x, y):\n" + " return x + y\n"; + +bool testEvalExpr() { + gc_scoped_pool pool; + { + const value exp = mklist<value>("abs", -5); + const failable<value> r = evalExpr(exp, pool); + assert(hasContent(r)); + assert(content(r) == value(5)); + } + { + istringstream is(testPythonAdd); + failable<PyObject*> script = readScript("script", is); + assert(hasContent(script)); + const value exp = mklist<value>("add", 2, 3); + const failable<value> r = evalScript(exp, content(script), pool); + assert(hasContent(r)); + assert(content(r) == value(5)); + } + return true; +} + +bool testEvalRun() { + gc_scoped_pool pool; + evalDriverRun(cin, cout, pool); + return true; +} + +const value mult(const list<value>& args) { + const double x = car(args); + const double y = cadr(args); + return x * y; +} + +const string testReturnLambda( + "def mul(x, y):\n" + " return x * y\n" + "\n" + "def testReturnLambda():\n" + " return mul\n"); + +const string testCallLambda( + "def testCallLambda(l, x, y):\n" + " return l(x, y)\n"); + +bool testEvalLambda() { + gc_scoped_pool pool; + + const value trl = mklist<value>("testReturnLambda"); + istringstream trlis(testReturnLambda); + const failable<value> trlv = evalScript(trl, trlis, pool); + + assert(hasContent(trlv)); + assert(isLambda(content(trlv))); + const lambda<value(const list<value>&)> trll(content(trlv)); + assert(trll(mklist<value>(2, 3)) == value(6)); + + istringstream tclis(testCallLambda); + const value tcl = mklist<value>("testCallLambda", content(trlv), 2, 3); + const failable<value> tclv = evalScript(tcl, tclis, pool); + assert(hasContent(tclv)); + assert(content(tclv) == value(6)); + + istringstream tcelis(testCallLambda); + const value tcel = mklist<value>("testCallLambda", lambda<value(const list<value>&)>(mult), 3, 4); + const failable<value> tcelv = evalScript(tcel, tcelis, pool); + assert(hasContent(tcelv)); + assert(content(tcelv) == value(12)); + return true; +} + +} +} + +int main() { + tuscany::cout << "Testing..." << tuscany::endl; + + tuscany::python::testEval(); + tuscany::python::testEvalExpr(); + tuscany::python::testEvalLambda(); + + tuscany::cout << "OK" << tuscany::endl; + return 0; +} diff --git a/sca-cpp/trunk/modules/python/tuscany-sca-1.1-implementation-python.xsd b/sca-cpp/trunk/modules/python/tuscany-sca-1.1-implementation-python.xsd new file mode 100644 index 0000000000..95ffc4f743 --- /dev/null +++ b/sca-cpp/trunk/modules/python/tuscany-sca-1.1-implementation-python.xsd @@ -0,0 +1,43 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. +--> +<schema xmlns="http://www.w3.org/2001/XMLSchema" + targetNamespace="http://tuscany.apache.org/xmlns/sca/1.1" + xmlns:sca="http://docs.oasis-open.org/ns/opencsa/sca/200903" + xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1" + elementFormDefault="qualified"> + + <import namespace="http://docs.oasis-open.org/ns/opencsa/sca/200903" schemaLocation="sca-1.1-cd04.xsd"/> + + <element name="implementation.python" type="t:PythonImplementation" substitutionGroup="sca:implementation"/> + + <complexType name="PythonImplementation"> + <complexContent> + <extension base="sca:Implementation"> + <sequence> + <any namespace="##targetNamespace" processContents="lax" + minOccurs="0" maxOccurs="unbounded"/> + </sequence> + <attribute name="location" type="anyURI" use="required"/> + <anyAttribute namespace="##any" processContents="lax"/> + </extension> + </complexContent> + </complexType> + +</schema> |