summaryrefslogtreecommitdiffstats
path: root/sca-cpp/trunk/kernel
diff options
context:
space:
mode:
authorjsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68>2009-11-16 06:57:41 +0000
committerjsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68>2009-11-16 06:57:41 +0000
commitbd0fdbf902f8ca8e7e352582efe938e1d6743dd1 (patch)
tree4ffc871e04f7e22cad2a6ed1d921718e296dc5fe /sca-cpp/trunk/kernel
parent2cd577564c1e4a37b25f4064b84af15d112b0654 (diff)
Cleaning up SVN structure, moving sca trunk to sca-cpp/trunk.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@880633 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'sca-cpp/trunk/kernel')
-rw-r--r--sca-cpp/trunk/kernel/Makefile.am31
-rw-r--r--sca-cpp/trunk/kernel/element.hpp300
-rw-r--r--sca-cpp/trunk/kernel/function.hpp235
-rw-r--r--sca-cpp/trunk/kernel/gc.hpp404
-rw-r--r--sca-cpp/trunk/kernel/kernel-test.cpp737
-rw-r--r--sca-cpp/trunk/kernel/list.hpp484
-rw-r--r--sca-cpp/trunk/kernel/monad.hpp455
-rw-r--r--sca-cpp/trunk/kernel/parallel.hpp283
-rw-r--r--sca-cpp/trunk/kernel/slist.hpp96
-rw-r--r--sca-cpp/trunk/kernel/value.hpp491
-rw-r--r--sca-cpp/trunk/kernel/xml.hpp364
-rw-r--r--sca-cpp/trunk/kernel/xsd-test.cpp107
12 files changed, 3987 insertions, 0 deletions
diff --git a/sca-cpp/trunk/kernel/Makefile.am b/sca-cpp/trunk/kernel/Makefile.am
new file mode 100644
index 0000000000..0bbfa195c7
--- /dev/null
+++ b/sca-cpp/trunk/kernel/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 = kernel-test xsd-test
+
+nobase_include_HEADERS = *.hpp
+
+INCLUDES = -I. -I$(top_builddir)/kernel -I${LIBXML2_INCLUDE} -I${APR_INCLUDE}
+
+kernel_test_SOURCES = kernel-test.cpp
+kernel_test_LDADD = -lpthread -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1
+
+xsd_test_SOURCES = xsd-test.cpp
+xsd_test_LDADD = -lpthread -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1
+
+TESTS = kernel-test
+
diff --git a/sca-cpp/trunk/kernel/element.hpp b/sca-cpp/trunk/kernel/element.hpp
new file mode 100644
index 0000000000..2b5336ba5c
--- /dev/null
+++ b/sca-cpp/trunk/kernel/element.hpp
@@ -0,0 +1,300 @@
+/*
+ * 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_element_hpp
+#define tuscany_element_hpp
+
+/**
+ * Functions to help represent data as lists of elements and attributes.
+ */
+
+#include "list.hpp"
+#include "value.hpp"
+
+namespace tuscany
+{
+
+/**
+ * Tags used to tag lists of elements and attributes.
+ */
+const value attribute("attribute");
+const value element("element");
+
+/**
+ * Returns true if a value is an element.
+ */
+bool isElement(const value& v) {
+ if (!isList(v) || isNil(v) || element != car<value>(v))
+ return false;
+ return true;
+}
+
+/**
+ * Returns true if a value is an attribute.
+ */
+bool isAttribute(const value& v) {
+ if (!isList(v) || isNil(v) || attribute != car<value>(v))
+ return false;
+ return true;
+}
+
+/**
+ * Returns the name of an attribute.
+ */
+const value attributeName(const list<value>& l) {
+ return cadr(l);
+}
+
+/**
+ * Returns the value of an attribute.
+ */
+const value attributeValue(const list<value>& l) {
+ return caddr(l);
+}
+
+/**
+ * Returns the name of an element.
+ */
+const value elementName(const list<value>& l) {
+ return cadr(l);
+}
+
+/**
+ * Returns true if an element has children.
+ */
+const bool elementHasChildren(const list<value>& l) {
+ return !isNil(cddr(l));
+}
+
+/**
+ * Returns the children of an element.
+ */
+const list<value> elementChildren(const list<value>& l) {
+ return cddr(l);
+}
+
+/**
+ * Returns true if an element has a value.
+ */
+const value elementHasValue(const list<value>& l) {
+ const list<value> r = reverse(l);
+ if (isSymbol(car(r)))
+ return false;
+ if(isList(car(r)) && isSymbol(car<value>(car(r))))
+ return false;
+ return true;
+}
+
+/**
+ * Returns the value of an element.
+ */
+const value elementValue(const list<value>& l) {
+ return car(reverse(l));
+}
+
+/**
+ * Convert an element to a value.
+ */
+const bool elementToValueIsList(const value& v) {
+ if (!isList(v))
+ return false;
+ const list<value> l = v;
+ return (isNil(l) || !isSymbol(car(l)));
+}
+
+const value elementToValue(const value& t) {
+ const list<value> elementsToValues(const list<value>& e);
+
+ // Convert an attribute
+ if (isTaggedList(t, attribute))
+ return mklist(attributeName(t), attributeValue(t));
+
+ // Convert an element
+ if (isTaggedList(t, element)) {
+
+ // Convert an element's value
+ if (elementHasValue(t)) {
+
+ // Convert a single value
+ if (!elementToValueIsList(elementValue(t)))
+ return mklist(elementName(t), elementValue(t));
+
+ // Convert a list value
+ return cons(elementName(t), mklist<value>(elementsToValues(elementValue(t))));
+ }
+
+ // Convert an element's children
+ return cons(elementName(t), elementsToValues(elementChildren(t)));
+ }
+
+ // Convert a value
+ if (!isList(t))
+ return t;
+ return elementsToValues(t);
+}
+
+/**
+ * Convert a list of elements to a list of values.
+ */
+const bool elementToValueIsSymbol(const value& v) {
+ if (!isList(v))
+ return false;
+ const list<value> l = v;
+ if (isNil(l))
+ return false;
+ if (!isSymbol(car(l)))
+ return false;
+ return true;
+}
+
+const list<value> elementToValueGroupValues(const value& v, const list<value>& l) {
+ if (isNil(l) || !elementToValueIsSymbol(v) || !elementToValueIsSymbol(car(l)))
+ return cons(v, l);
+ if (car<value>(car(l)) != car<value>(v))
+ return cons(v, l);
+ if (!elementToValueIsList(cadr<value>(car(l)))) {
+ const value g = mklist<value>(car<value>(v), mklist<value>(cdr<value>(v), cdr<value>(car(l))));
+ return elementToValueGroupValues(g, cdr(l));
+ }
+ const value g = mklist<value>(car<value>(v), cons<value>(cdr<value>(v), (list<value>)cadr<value>(car(l))));
+ return elementToValueGroupValues(g, cdr(l));
+
+}
+
+const list<value> elementsToValues(const list<value>& e) {
+ if (isNil(e))
+ return e;
+ return elementToValueGroupValues(elementToValue(car(e)), elementsToValues(cdr(e)));
+}
+
+/**
+ * Convert a value to an element.
+ */
+const value valueToElement(const value& t) {
+ const list<value> valuesToElements(const list<value>& l);
+
+ // Convert a name value pair
+ if (isList(t) && isSymbol(car<value>(t))) {
+ const value n = car<value>(t);
+ const value v = cadr<value>(t);
+
+ // Convert a single value
+ if (!isList(v))
+ return mklist(element, n, v);
+
+ // Convert a list value
+ if (!isSymbol(car<value>(v)))
+ return cons(element, cons(n, mklist<value>(valuesToElements(v))));
+
+ // Convert a nested name value pair value
+ return cons(element, cons(n, valuesToElements(cdr<value>(t))));
+ }
+
+ // Convert a value
+ if (!isList(t))
+ return t;
+ return valuesToElements(t);
+}
+
+/**
+ * Convert a list of values to a list of elements.
+ */
+const list<value> valuesToElements(const list<value>& l) {
+ if (isNil(l))
+ return l;
+ return cons<value>(valueToElement(car(l)), valuesToElements(cdr(l)));
+}
+
+/**
+ * Returns a selector lambda function which can be used to filter
+ * elements against the given element pattern.
+ */
+struct selectorLambda {
+ const list<value> select;
+ selectorLambda(const list<value>& s) : select(s) {
+ }
+ const bool evalSelect(const list<value>& s, const list<value> v) const {
+ if (isNil(s))
+ return true;
+ if (isNil(v))
+ return false;
+ if (car(s) != car(v))
+ return false;
+ return evalSelect(cdr(s), cdr(v));
+ }
+ const bool operator()(const value& v) const {
+ if (!isList(v))
+ return false;
+ return evalSelect(select, v);
+ }
+};
+
+const lambda<bool(value)> selector(const list<value> s) {
+ return selectorLambda(s);
+}
+
+/**
+ * Returns the value of the attribute with the given name.
+ */
+struct filterAttribute {
+ const value name;
+ filterAttribute(const value& n) : name(n) {
+ }
+ const bool operator()(const value& v) const {
+ return isAttribute(v) && attributeName((list<value>)v) == name;
+ }
+};
+
+const value attributeValue(const value& name, const value& l) {
+ const list<value> f = filter<value>(filterAttribute(name), list<value>(l));
+ if (isNil(f))
+ return value();
+ return caddr<value>(car(f));
+}
+
+/**
+ * Returns child elements with the given name.
+ */
+struct filterElement {
+ const value name;
+ filterElement(const value& n) : name(n) {
+ }
+ const bool operator()(const value& v) const {
+ return isElement(v) && elementName((list<value>)v) == name;
+ }
+};
+
+const value elementChildren(const value& name, const value& l) {
+ return filter<value>(filterElement(name), list<value>(l));
+}
+
+/**
+ * Return the child element with the given name.
+ */
+const value elementChild(const value& name, const value& l) {
+ const list<value> f = elementChildren(name, l);
+ if (isNil(f))
+ return value();
+ return car(f);
+}
+
+}
+#endif /* tuscany_element_hpp */
diff --git a/sca-cpp/trunk/kernel/function.hpp b/sca-cpp/trunk/kernel/function.hpp
new file mode 100644
index 0000000000..c99ee5dbad
--- /dev/null
+++ b/sca-cpp/trunk/kernel/function.hpp
@@ -0,0 +1,235 @@
+/*
+ * 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_function_hpp
+#define tuscany_function_hpp
+
+/**
+ * Lambda function type.
+ */
+
+#include <iostream>
+#include "gc.hpp"
+
+namespace tuscany {
+
+/**
+ * Debug counters.
+ */
+long int countProxies;
+long int countFProxies = 0;
+long int countCProxies = 0;
+long int countLambdas = 0;
+long int countELambdas = 0;
+long int countCLambdas = 0;
+long int countFLambdas = 0;
+
+bool resetLambdaCounters() {
+ countLambdas = countELambdas = countCLambdas = countFLambdas = countProxies = countFProxies = countCProxies = 0;
+ return true;
+}
+
+bool printLambdaCounters() {
+ std::cout << "countLambdas " << countLambdas << std::endl;
+ std::cout << "countELambdas " << countELambdas << std::endl;
+ std::cout << "countFLambdas " << countFLambdas << std::endl;
+ std::cout << "countCLambdas " << countCLambdas << std::endl;
+ std::cout << "countProxies " << countProxies << std::endl;
+ std::cout << "countFProxies " << countFProxies << std::endl;
+ std::cout << "countCProxies " << countCProxies << std::endl;
+ return true;
+}
+
+/**
+ * Lambda function type.
+ */
+
+template<typename R, typename... P> class Callable {
+public:
+ Callable() : refCount(0) {
+ }
+
+ virtual const int size() const = 0;
+
+ virtual const R operator()(P... p) const = 0;
+
+ virtual ~Callable() {
+ }
+
+ template<typename F> class Proxy: public Callable {
+ public:
+ Proxy(const F& f) : function(f) {
+ countProxies++;
+ countFProxies ++;
+ }
+
+ Proxy(const Proxy& p) : function(p.function) {
+ countProxies++;
+ countCProxies ++;
+ }
+
+ ~Proxy() {
+ countProxies--;
+ }
+
+ virtual const R operator() (P... p) const {
+ return function(std::forward<P>(p)...);
+ }
+
+ virtual const int size() const {
+ return sizeof(function);
+ }
+
+ private:
+ const F function;
+ };
+
+private:
+ friend class gc_counting_ptr<Callable>;
+
+ unsigned int refCount;
+
+ unsigned int acquire() {
+ return __sync_add_and_fetch(&refCount, 1);
+ }
+
+ unsigned int release() {
+ return __sync_sub_and_fetch(&refCount, 1);
+ }
+};
+
+template<typename S> class lambda;
+
+template<typename R, typename... P> class lambda<R(P...)> {
+public:
+ lambda() : callable(0) {
+ countLambdas++;
+ countELambdas++;
+ }
+
+ template<typename F> lambda(const F f) : callable(0) {
+ typedef typename CallableType::template Proxy<F> ProxyType;
+
+ countLambdas++;
+ countFLambdas++;
+ callable = gc_counting_ptr<CallableType>(new ProxyType(f));
+ }
+
+ lambda(const lambda& l) {
+ countLambdas++;
+ countCLambdas++;
+ callable = l.callable;
+ }
+
+ const lambda& operator=(const lambda& l) {
+ if (this == &l)
+ return *this;
+ callable = l.callable;
+ return *this;
+ }
+
+ ~lambda() {
+ countLambdas--;
+ }
+
+ const bool operator==(const lambda& l) const {
+ if (this == &l)
+ return true;
+ return callable == l.callable;
+ }
+
+ const bool operator!=(const lambda& l) const {
+ return !this->operator==(l);
+ }
+
+ const R operator()(P... p) const {
+ return (*callable)(std::forward<P>(p)...);
+ }
+
+ template<typename S> friend std::ostream& operator<<(std::ostream&, const lambda<S>&);
+ template<typename S> friend const bool isNil(const lambda<S>& l);
+
+private:
+ typedef Callable<R,P...> CallableType;
+ gc_counting_ptr<CallableType> callable;
+};
+
+template<typename S> std::ostream& operator<<(std::ostream& out, const lambda<S>& l) {
+ return out << "lambda::" << l.callable;
+}
+
+/**
+ * Return true if a lambda is nil.
+ */
+template<typename S> const bool isNil(const lambda<S>& l) {
+ return ((void*)l.callable) == 0;
+}
+
+/**
+ * Curry a lambda function.
+ */
+template<typename R, typename T, typename... P> class curried {
+public:
+ curried(const lambda<R(T, P...)>& f, const T& v): v(v), f(f) {
+ }
+
+ const R operator()(P... p) const {
+ return f(v, std::forward<P>(p)...);
+ }
+
+private:
+ const T v;
+ const lambda<R(T, P...)>f;
+};
+
+template<typename R, typename T, typename... P> const lambda<R(P...)> curry(const lambda<R(T, P...)>& f, const T& t) {
+ return curried<R, T, P...>(f, t);
+}
+
+template<typename R, typename T, typename U, typename... P> const lambda<R(P...)> curry(const lambda<R(T, U, P...)>& f, const T& t, const U& u) {
+ return curry(curry(f, t), u);
+}
+
+template<typename R, typename T, typename U, typename V, typename... P> const lambda<R(P...)> curry(const lambda<R(T, U, P...)>& f, const T& t, const U& u, const V& v) {
+ return curry(curry(curry(f, t), u), v);
+}
+
+/**
+ * A lambda function that returns the given value.
+ */
+template<typename T> class returnResult {
+public:
+ returnResult(const T& v) :
+ v(v) {
+ }
+ const T operator()() const {
+ return v;
+ }
+private:
+ const T v;
+};
+
+template<typename T> const lambda<T()> result(const T& v) {
+ return returnResult<T> (v);
+}
+
+}
+#endif /* tuscany_function_hpp */
diff --git a/sca-cpp/trunk/kernel/gc.hpp b/sca-cpp/trunk/kernel/gc.hpp
new file mode 100644
index 0000000000..7739e714c2
--- /dev/null
+++ b/sca-cpp/trunk/kernel/gc.hpp
@@ -0,0 +1,404 @@
+/*
+ * 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_gc_hpp
+#define tuscany_gc_hpp
+
+/**
+ * Garbage collected pointer.
+ */
+
+#include <apr_general.h>
+#include <apr_pools.h>
+#include <iostream>
+
+namespace tuscany
+{
+
+template<typename T> class gc_ptr {
+public:
+ gc_ptr(T* p = 0) throw() : countingRef(p == 0? 0 : new CountingRef(p)) {
+ }
+
+ ~gc_ptr() throw() {
+ release();
+ }
+
+ gc_ptr(const gc_ptr& r) throw() : countingRef(r.countingRef) {
+ acquire(r.countingRef);
+ }
+
+ gc_ptr& operator=(const gc_ptr& r) throw() {
+ if(this == &r)
+ return *this;
+ acquire(r.countingRef);
+ release();
+ countingRef = r.countingRef;
+ return *this;
+ }
+
+ const bool operator==(const gc_ptr& r) const throw() {
+ if (this == &r)
+ return true;
+ if (countingRef == NULL)
+ return r.countingRef == NULL;
+ if (r.countingRef == NULL)
+ return false;
+ return countingRef-> ptr == r.countingRef->ptr;
+ }
+
+ const bool operator!=(const gc_ptr& r) const throw() {
+ return !this->operator ==(r);
+ }
+
+ T& operator*() const throw() {
+ return *countingRef->ptr;
+ }
+
+ T* operator->() const throw() {
+ return countingRef->ptr;
+ }
+
+ operator T*() const throw() {
+ return countingRef->ptr;
+ }
+
+ template<typename X> friend std::ostream& operator<<(std::ostream&, const gc_ptr<X>&);
+
+private:
+ struct CountingRef {
+ T* ptr;
+ unsigned count;
+
+ CountingRef(T* p) throw() :
+ ptr(p), count(1) {
+ }
+ }* countingRef;
+
+ void acquire(CountingRef* ref) throw() {
+ if(ref)
+ __sync_add_and_fetch(&ref->count, 1);
+ }
+
+ void release() throw() {
+ if(countingRef) {
+ unsigned rc = __sync_sub_and_fetch(&countingRef->count, 1);
+ if(rc == 0) {
+ delete countingRef->ptr;
+ delete countingRef;
+ }
+ }
+ }
+};
+
+template<typename T> std::ostream& operator<<(std::ostream& out, const gc_ptr<T>& p) {
+ return out << p.countingRef->ptr;
+}
+
+/**
+ * Garbage collected pointer to an array.
+ */
+template<typename T> class gc_aptr {
+public:
+ gc_aptr(T* p = 0) throw() : countingRef(p == 0? 0 : new CountingRef(p)) {
+ }
+
+ ~gc_aptr() throw() {
+ release();
+ }
+
+ gc_aptr(const gc_aptr& r) throw() : countingRef(r.countingRef) {
+ acquire(r.countingRef);
+ }
+
+ gc_aptr& operator=(const gc_aptr& r) throw() {
+ if(this == &r)
+ return *this;
+ acquire(r.countingRef);
+ release();
+ countingRef = r.countingRef;
+ return *this;
+ }
+
+ const bool operator==(const gc_aptr& r) const throw() {
+ if (this == &r)
+ return true;
+ if (countingRef == NULL)
+ return r.countingRef == NULL;
+ if (r.countingRef == NULL)
+ return false;
+ return countingRef-> ptr == r.countingRef->ptr;
+ }
+
+ const bool operator!=(const gc_aptr& r) const throw() {
+ return !this->operator ==(r);
+ }
+
+ T& operator*() const throw() {
+ return *countingRef->ptr;
+ }
+
+ T* operator->() const throw() {
+ return countingRef->ptr;
+ }
+
+ operator T*() const throw() {
+ return countingRef->ptr;
+ }
+
+ template<typename X> friend std::ostream& operator<<(std::ostream&, const gc_aptr<X>&);
+
+private:
+ struct CountingRef {
+ T* ptr;
+ unsigned count;
+
+ CountingRef(T* p) throw() :
+ ptr(p), count(1) {
+ }
+ }* countingRef;
+
+ void acquire(CountingRef* ref) throw() {
+ if(ref)
+ __sync_add_and_fetch(&ref->count, 1);
+ }
+
+ void release() throw() {
+ if(countingRef) {
+ unsigned rc = __sync_sub_and_fetch(&countingRef->count, 1);
+ if(rc == 0) {
+ delete[] countingRef->ptr;
+ delete countingRef;
+ }
+ }
+ }
+};
+
+template<typename T> std::ostream& operator<<(std::ostream& out, const gc_aptr<T>& p) {
+ return out << p.countingRef->ptr;
+}
+
+/**
+ * Garbage collected pointer to a reference counting object.
+ */
+template<typename T> class gc_counting_ptr {
+public:
+ gc_counting_ptr(T* p = 0) throw() : ptr(p) {
+ acquire(p);
+ }
+
+ ~gc_counting_ptr() throw() {
+ release();
+ }
+
+ gc_counting_ptr(const gc_counting_ptr& r) throw() : ptr(r.ptr) {
+ acquire(ptr);
+ }
+
+ gc_counting_ptr& operator=(const gc_counting_ptr& r) throw() {
+ if(this == &r)
+ return *this;
+ acquire(r.ptr);
+ release();
+ ptr = r.ptr;
+ return *this;
+ }
+
+ const bool operator==(const gc_counting_ptr& r) const throw() {
+ if (this == &r)
+ return true;
+ return ptr == r.ptr;
+ }
+
+ const bool operator!=(const gc_counting_ptr& r) const throw() {
+ return !this->operator ==(r);
+ }
+
+ T& operator*() const throw() {
+ return *ptr;
+ }
+
+ T* operator->() const throw() {
+ return ptr;
+ }
+
+ operator T*() const throw() {
+ return ptr;
+ }
+
+ template<typename X> friend std::ostream& operator<<(std::ostream&, const gc_counting_ptr<X>&);
+
+private:
+ T* ptr;
+
+ void acquire(T* p) throw() {
+ if(p)
+ p->acquire();
+ }
+
+ void release() throw() {
+ if(ptr) {
+ if(ptr->release() == 0) {
+ delete ptr;
+ }
+ }
+ }
+};
+
+template<typename T> std::ostream& operator<<(std::ostream& out, const gc_counting_ptr<T>& p) {
+ return out << p.ptr;
+}
+
+/**
+ * Apache Portable Runtime library context
+ */
+class APRContext {
+public:
+ APRContext() {
+ apr_initialize();
+ }
+ ~APRContext() {
+ apr_terminate();
+ }
+};
+
+APRContext aprContext;
+
+/**
+ * Garbage collected memory pool, using an APR pool.
+ */
+class gc_pool {
+public:
+ gc_pool() : aprPool(new APRPool) {
+ }
+
+ operator apr_pool_t*() const {
+ return aprPool->p;
+ }
+
+private:
+ class APRPool {
+ friend class gc_pool;
+ friend class gc_counting_ptr<APRPool>;
+
+ unsigned int refCount;
+ apr_pool_t* p;
+
+ APRPool() : refCount(0) {
+ apr_pool_create(&p, NULL);
+ }
+
+ ~APRPool() {
+ apr_pool_destroy(p);
+ }
+
+ unsigned int acquire() {
+ return __sync_add_and_fetch(&refCount, 1);
+ }
+
+ unsigned int release() {
+ return __sync_sub_and_fetch(&refCount, 1);
+ }
+ };
+
+ const gc_counting_ptr<APRPool> aprPool;
+};
+
+/**
+ * Garbage collected pointer to pooled memory.
+ */
+template<typename T> class gc_pool_ptr {
+public:
+ gc_pool_ptr(T* ptr = 0) throw() : ptr(ptr) {
+ }
+
+ ~gc_pool_ptr() throw() {
+ }
+
+ gc_pool_ptr(const gc_pool_ptr& r) throw() : ptr(r.ptr) {
+ }
+
+ gc_pool_ptr& operator=(const gc_pool_ptr& r) throw() {
+ if(this == &r)
+ return *this;
+ ptr = r.ptr;
+ return *this;
+ }
+
+ const bool operator==(const gc_pool_ptr& r) const throw() {
+ if (this == &r)
+ return true;
+ return ptr == r.ptr;
+ }
+
+ const bool operator!=(const gc_pool_ptr& r) const throw() {
+ return !this->operator ==(r);
+ }
+
+ T& operator*() const throw() {
+ return *ptr;
+ }
+
+ T* operator->() const throw() {
+ return ptr;
+ }
+
+ operator T*() const throw() {
+ return ptr;
+ }
+
+ template<typename X> friend std::ostream& operator<<(std::ostream&, const gc_pool_ptr<X>&);
+
+private:
+ T* ptr;
+};
+
+template<typename T> std::ostream& operator<<(std::ostream& out, const gc_pool_ptr<T>& p) {
+ return out << p.ptr;
+}
+
+/**
+ * Cleanup function, called by the APR pool to cleanup registered resources.
+ * Calls the allocated object's destructor.
+ */
+template<typename T> apr_status_t gc_pool_cleanupCallback(void* v) {
+ T* t = static_cast<T*>(v);
+ t->~T();
+ return APR_SUCCESS;
+}
+
+/**
+ * Returns a pointer to an object allocated from a memory pool.
+ */
+template<typename T> gc_pool_ptr<T> gc_pool_new(const gc_pool& mp) {
+
+ // Allocate memory from the pool
+ void* m = apr_palloc(mp, sizeof(T));
+
+ // Register a cleanup callback
+ apr_pool_cleanup_register(mp, m, gc_pool_cleanupCallback<T>, apr_pool_cleanup_null) ;
+
+ // Run the requested type's constructor over the allocated memory
+ return new (m) T();
+}
+
+}
+#endif /* tuscany_gc_hpp */
diff --git a/sca-cpp/trunk/kernel/kernel-test.cpp b/sca-cpp/trunk/kernel/kernel-test.cpp
new file mode 100644
index 0000000000..9346e31b71
--- /dev/null
+++ b/sca-cpp/trunk/kernel/kernel-test.cpp
@@ -0,0 +1,737 @@
+/*
+ * 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 core utils.
+ */
+
+#include <assert.h>
+#include <sys/time.h>
+#include <time.h>
+#include <iostream>
+#include <string>
+#include <sstream>
+#include "function.hpp"
+#include "list.hpp"
+#include "slist.hpp"
+#include "parallel.hpp"
+#include "value.hpp"
+#include "element.hpp"
+#include "xml.hpp"
+#include "monad.hpp"
+
+namespace tuscany {
+
+struct inc {
+ int i;
+ inc(int i) :
+ i(i) {
+ }
+ const int operator()(const int x) const {
+ return x + i;
+ }
+};
+
+const int square(const int x) {
+ return x * x;
+}
+
+int mapLambda(lambda<int(int)> f, int v) {
+ return f(v);
+}
+
+bool testLambda() {
+ const lambda<int(int)> sq(square);
+ assert(sq(2) == 4);
+ assert(mapLambda(sq, 2) == 4);
+ assert(mapLambda(square, 2) == 4);
+
+ const lambda<int(int)> incf(inc(10));
+ assert(incf(1) == 11);
+ assert(mapLambda(incf, 1) == 11);
+ assert(mapLambda(inc(10), 1) == 11);
+
+ lambda<int(int)> l;
+ l = incf;
+ assert(l(1) == 11);
+ l = square;
+ assert(l(2) == 4);
+ return true;
+}
+
+bool testLambdaGC() {
+ resetLambdaCounters();
+ testLambda();
+ assert(countLambdas == 0);
+ return true;
+}
+
+int countElements = 0;
+
+struct Element {
+ int i;
+
+ Element() :
+ i(0) {
+ countElements++;
+ }
+
+ Element(int i) :
+ i(i) {
+ countElements++;
+ }
+
+ Element(const Element& o) :
+ i(o.i) {
+ countElements++;
+ }
+
+ ~Element() {
+ countElements--;
+ }
+
+ const bool operator==(const Element& o) const {
+ return o.i == i;
+ }
+};
+
+bool testCons() {
+ assert(car(cons(2, mklist(3))) == 2);
+ assert(car(cdr(cons(2, mklist(3)))) == 3);
+ assert(isNil(cdr(cdr(cons(2, mklist(3))))));
+
+ assert(cons(Element(1), mklist(Element(2))) == mklist(Element(1), Element(2)));
+ return true;
+}
+
+bool testSet() {
+ list<int> l = mklist(1, 2, 3);
+ setCar(l, 4);
+ setCdr(l, mklist(5, 6));
+ assert(car(l) == 4);
+ assert(cadr(l) == 5);
+ assert(caddr(l) == 6);
+ assert(isNil(cdddr(l)));
+ return true;
+}
+
+bool testListGC() {
+ resetLambdaCounters();
+ resetListCounters();
+ countElements = 0;
+ testCons();
+ testSet();
+ assert(countLambdas == 0);
+ assert(countlists == 0);
+ assert(countElements == 0);
+ return true;
+}
+
+bool testOut() {
+ std::ostringstream os1;
+ os1 << list<int> ();
+ assert(os1.str() == "()");
+
+ std::ostringstream os2;
+ os2 << mklist(1, 2, 3);
+ assert(os2.str() == "(1 2 3)");
+ return true;
+}
+
+bool testEquals() {
+ assert(list<int>() == list<int>());
+ assert(mklist(1, 2) == mklist(1, 2));
+ assert(list<int>() != mklist(1, 2));
+ assert(mklist(1, 2, 3) == mklist(1, 2, 3));
+ assert(mklist(1, 2) != mklist(1, 2, 3));
+ return true;
+}
+
+bool testLength() {
+ assert(0 == length(list<int>()));
+ assert(1 == length(mklist(1)));
+ assert(2 == length(cons(1, mklist(2))));
+ return true;
+}
+
+bool testAppend() {
+ assert(car(append(mklist(1), mklist(2))) == 1);
+ assert(car(cdr(append(mklist(1), mklist(2)))) == 2);
+ assert(car(cdr(cdr(append(mklist(1), mklist(2, 3))))) == 3);
+ assert(isNil(cdr(cdr(cdr(append(mklist(1), mklist(2, 3)))))));
+
+ list<int> l;
+ l << 1 << 2 << 3;
+ assert(l == mklist(1, 2, 3));
+ assert(list<int>() << 1 << 2 << 3 == mklist(1, 2, 3));
+ return true;
+}
+
+struct Complex {
+ int x;
+ int y;
+ Complex() {
+ }
+ Complex(int x, int y) :
+ x(x), y(y) {
+ }
+};
+
+bool testComplex() {
+ const list<Complex> p = mklist(Complex(1, 2), Complex(3, 4));
+ assert(car(p).x == 1);
+ assert(car(cdr(p)).x == 3);
+ assert(isNil(cdr(cdr(p))));
+ return true;
+}
+
+bool testMap() {
+ assert(isNil(map<int, int>(square, list<int>())));
+
+ const list<int> m = map<int, int>(square, mklist(2, 3));
+ assert(car(m) == 4);
+ assert(car(cdr(m)) == 9);
+
+ return true;
+}
+
+const int add(const int x, const int y) {
+ return x + y;
+}
+
+bool testReduce() {
+ const lambda<int(int, int)> r(add);
+ assert(reduce(r, 0, mklist(1, 2, 3)) == 6);
+ return true;
+}
+
+bool isPositive(int x) {
+ if(x >= 0)
+ return true;
+ else
+ return false;
+}
+
+bool testFilter() {
+ assert(car(filter<int>(isPositive, mklist(1, -1, 2, -2))) == 1);
+ assert(cadr(filter<int>(isPositive, mklist(1, -1, 2, -2))) == 2);
+ return true;
+}
+
+bool testMember() {
+ assert(isNil(member(4, mklist(1, 2, 3))));
+ assert(car(member(1, mklist(1, 2, 3))) == 1);
+ assert(car(member(2, mklist(1, 2, 3))) == 2);
+ assert(car(member(3, mklist(1, 2, 3))) == 3);
+ return true;
+}
+
+bool testReverse() {
+ assert(isNil(reverse(list<int>())));
+ assert(car(reverse(mklist(1, 2, 3))) == 3);
+ assert(cadr(reverse(mklist(1, 2, 3))) == 2);
+ return true;
+}
+
+bool testListRef() {
+ assert(listRef(mklist(1), 0) == 1);
+ assert(listRef(mklist(1, 2, 3), 0) == 1);
+ assert(listRef(mklist(1, 2, 3), 1) == 2);
+ assert(listRef(mklist(1, 2, 3), 2) == 3);
+ return true;
+}
+
+bool testAssoc() {
+ const list<list<std::string> > l = mklist(mklist<std::string>("x", "X"), mklist<std::string>("a", "A"), mklist<std::string>("y", "Y"), mklist<std::string>("a", "AA"));
+ assert(assoc<std::string>("a", l) == mklist<std::string>("a", "A"));
+ assert(isNil(assoc<std::string>("z", l)));
+
+ const list<list<value> > u = mklist(mklist<value>("x", "X"), mklist<value>("a", "A"), mklist<value>("y", "Y"), mklist<value>("a", "AA"));
+ assert(assoc<value>("a", u) == mklist<value>("a", "A"));
+
+ const list<value> v = mklist<value>(mklist<value>("x", "X"), mklist<value>("a", "A"), mklist<value>("y", "Y"), mklist<value>("a", "AA"));
+ assert(assoc<value>("a", v) == mklist<value>("a", "A"));
+ return true;
+}
+
+bool testZip() {
+ const list<std::string> k = mklist<std::string>("x", "a", "y", "a");
+ const list<std::string> v = mklist<std::string>("X", "A", "Y", "AA");
+ const list<list<std::string> > z = mklist(k, v);
+ const list<list<std::string> > u = mklist(mklist<std::string>("x", "X"), mklist<std::string>("a", "A"), mklist<std::string>("y", "Y"), mklist<std::string>("a", "AA"));
+ assert(zip(k, v) == u);
+ assert(unzip(u) == z);
+ return true;
+}
+
+bool testTokenize() {
+ assert(tokenize("/", "aaa/bbb/ccc/ddd") == mklist<std::string>("aaa", "bbb", "ccc", "ddd"));
+ assert(tokenize("/", "/bbb/ccc/ddd") == mklist<std::string>("", "bbb", "ccc", "ddd"));
+ assert(tokenize("/", "/bbb/ccc/") == mklist<std::string>("", "bbb", "ccc"));
+ assert(tokenize("/", "/bbb//ccc/") == mklist<std::string>("", "bbb", "", "ccc"));
+ assert(tokenize("/", "abc/def/") == mklist<std::string>("abc", "def"));
+ return true;
+}
+
+double testSeqMap(double x) {
+ return x;
+}
+
+double testSeqReduce(double v, double accum) {
+ return accum + 1.0;
+}
+
+bool testSeq() {
+ resetLambdaCounters();
+ resetListCounters();
+
+ list<double> s = seq(0.0, 1000.0);
+ assert(1001 == length(s));
+ //printLambdaCounters();
+ //printListCounters();
+
+ assert(1001 == length(map<double, double>(testSeqMap, s)));
+
+ assert(801 == length(member(200.0, s)));
+ assert(201 == length(member(200.0, reverse(s))));
+
+ assert(1001 == (reduce<double, double>(testSeqReduce, 0.0, s)));
+ //printLambdaCounters();
+ //printListCounters();
+
+ return true;
+}
+
+value valueSquare(list<value> x) {
+ return (int)car(x) * (int)car(x);
+}
+
+bool testValue() {
+ assert(value(true) == value(true));
+ assert(value(1) == value(1));
+ assert(value("abcd") == value("abcd"));
+ lambda<value(list<value>&)> vl(valueSquare);
+ assert(value(vl) == value(vl));
+ assert(value(mklist<value>(1, 2)) == value(mklist<value>(1, 2)));
+
+ const list<value> v = mklist<value>(mklist<value>("x", "X"), mklist<value>("a", "A"), mklist<value>("y", "Y"));
+ assert(cadr((list<list<value> >)value(v)) == mklist<value>("a", "A"));
+
+ const value pv(gc_ptr<value>(new value(1)));
+ assert(*(gc_ptr<value>)pv == value(1));
+
+ const list<value> lpv = mklist<value>(gc_ptr<value>(new value(1)), gc_ptr<value>(new value(2)));
+ assert(*(gc_ptr<value>)car(lpv) == value(1));
+ *(gc_ptr<value>)cadr(lpv) = value(3);
+ assert(*(gc_ptr<value>)cadr(lpv) == value(3));
+ return true;
+}
+
+bool testValueGC() {
+ resetLambdaCounters();
+ resetListCounters();
+ resetValueCounters();
+ testValue();
+ assert(countValues == 0);
+ assert(countLambdas == 0);
+ assert(countlists == 0);
+ return true;
+}
+
+double fib_aux(double n, double a, double b) {
+ if(n == 0.0)
+ return a;
+ return fib_aux(n - 1.0, b, a + b);
+}
+
+double fib(double n) {
+ return fib_aux(n, 0.0, 1.0);
+}
+
+bool testCppPerf() {
+ struct timeval start;
+ struct timeval end;
+ {
+ gettimeofday(&start, NULL);
+
+ list<double> s = seq(0.0, 999.0);
+ list<double> r = map<double, double>(fib, s);
+ assert(1000 == length(r));
+
+ gettimeofday(&end, NULL);
+ //long t = (end.tv_sec * 1000 + end.tv_usec / 1000) - (start.tv_sec * 1000 + start.tv_usec / 1000);
+ //std::cout << "Fib cpp function map perf test " << t << " ms" << std::endl;
+ }
+
+ {
+ struct nested {
+ static double fib(double n) {
+ struct nested {
+ static double fib_aux(double n, double a, double b) {
+ if(n == 0.0)
+ return a;
+ return fib_aux(n - 1.0, b, a + b);
+ }
+ };
+ return nested::fib_aux(n, 0.0, 1.0);
+ }
+ };
+
+ gettimeofday(&start, NULL);
+
+ list<double> s = seq(0.0, 999.0);
+ list<double> r = map(lambda<double(double)>(nested::fib), s);
+ assert(1000 == length(r));
+
+ gettimeofday(&end, NULL);
+ //long t = (end.tv_sec * 1000 + end.tv_usec / 1000) - (start.tv_sec * 1000 + start.tv_usec / 1000);
+ //std::cout << "Fib cpp nested function map perf test " << t << " ms" << std::endl;
+ }
+ return true;
+}
+
+bool testAtomicPerf() {
+ struct timeval start;
+ struct timeval end;
+ {
+ gettimeofday(&start, NULL);
+ for(int i = 0; i < 10000000;)
+ i = i + 1;
+ gettimeofday(&end, NULL);
+ //long t = (end.tv_sec * 1000 + end.tv_usec / 1000) - (start.tv_sec * 1000 + start.tv_usec / 1000);
+ //std::cout << "Loop test " << t << " ms" << std::endl;
+ }
+ {
+ gettimeofday(&start, NULL);
+ for(int i = 0; i < 10000000;)
+ __sync_add_and_fetch(&i, 1);
+ gettimeofday(&end, NULL);
+ //long t = (end.tv_sec * 1000 + end.tv_usec / 1000) - (start.tv_sec * 1000 + start.tv_usec / 1000);
+ //std::cout << "Loop atomic test " << t << " ms" << std::endl;
+ }
+ {
+ pthread_mutex_t mutex;
+ pthread_mutex_init(&mutex, NULL);
+ gettimeofday(&start, NULL);
+ for(int i = 0; i < 10000000;) {
+ pthread_mutex_lock(&mutex);
+ i = i + 1;
+ pthread_mutex_unlock(&mutex);
+ }
+ gettimeofday(&end, NULL);
+ pthread_mutex_destroy(&mutex);
+ //long t = (end.tv_sec * 1000 + end.tv_usec / 1000) - (start.tv_sec * 1000 + start.tv_usec / 1000);
+ //std::cout << "Loop mutex test " << t << " ms" << std::endl;
+ }
+ return true;
+}
+
+const int mtsquare(const int x) {
+ //std::cout << "thread " << threadId() << " mtsquare(" << x << ")\n";
+ for(int i = 0; i < 10000000; i++)
+ ;
+ return x * x;
+}
+
+bool testWorker() {
+ worker w(10);
+ {
+ const lambda<int()> func = curry(lambda<int(int)> (mtsquare), 2);
+ assert(submit(w, func) == 4);
+ }
+ {
+ const int max = 10;
+
+ list<future<int> > r;
+ for(int i = 0; i < max; i++) {
+ const lambda<int()> func = curry(lambda<int(int)> (mtsquare), i);
+ r = cons(submit(w, func), r);
+ }
+ for(int i = max - 1; i >= 0; i--) {
+ assert(car(r) == i * i);
+ r = cdr(r);
+ }
+ }
+ shutdown(w);
+ return true;
+}
+
+const std::string currencyXML =
+"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+"<composite xmlns=\"http://docs.oasis-open.org/ns/opencsa/sca/200903\" "
+"xmlns:t=\"http://tuscany.apache.org/xmlns/sca/1.1\" "
+"targetNamespace=\"http://services\" "
+"name=\"currency\">"
+"<component name=\"CurrencyConverterWebService\">"
+"<implementation.java class=\"services.CurrencyConverterImpl\"/>"
+"<service name=\"CurrencyConverter\">"
+"<binding.ws/>"
+"</service>"
+"</component>"
+"<component name=\"CurrencyConverterWebService2\">"
+"<implementation.java class=\"services.CurrencyConverterImpl2\"/>"
+"<service name=\"CurrencyConverter2\">"
+"<binding.atom/>"
+"</service>"
+"<property name=\"currency\">US</property>"
+"</component>"
+"</composite>"
+"\n";
+
+const std::string customerXML =
+"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+"<customer>"
+"<name>jdoe</name>"
+"<address><city>san francisco</city><state>ca</state></address>"
+"<account><id>1234</id><balance>1000</balance></account>"
+"<account><id>6789</id><balance>2000</balance></account>"
+"<account><id>4567</id><balance>3000</balance></account>"
+"</customer>"
+"\n";
+
+
+const bool isName(const value& token) {
+ return isTaggedList(token, attribute) && attributeName(token) == "name";
+}
+
+bool testReadXML() {
+ {
+ std::istringstream is(customerXML);
+ const list<value> c = readXML(streamList(is));
+ }
+ {
+ std::istringstream is(currencyXML);
+ const list<value> c = readXML(streamList(is));
+
+ const value composite = car(c);
+ assert(isTaggedList(composite, element));
+ assert(elementName(composite) == "composite");
+ assert(attributeValue(car(filter<value>(isName, elementChildren(composite)))) == std::string("currency"));
+ }
+ return true;
+}
+
+std::ostringstream* xmlWriter(const std::string& s, std::ostringstream* os) {
+ (*os) << s;
+ return os;
+}
+
+bool testWriteXML() {
+ {
+ std::istringstream is(customerXML);
+ const list<value> c = readXML(streamList(is));
+ std::ostringstream os;
+ writeXML<std::ostringstream*>(xmlWriter, &os, c);
+ assert(os.str() == customerXML);
+ }
+ {
+ std::istringstream is(currencyXML);
+ const list<value> c = readXML(streamList(is));
+ std::ostringstream os;
+ writeXML<std::ostringstream*>(xmlWriter, &os, c);
+ assert(os.str() == currencyXML);
+ }
+ return true;
+}
+
+bool testElement() {
+ {
+ const list<value> ad = mklist<value>(mklist<value>("city", std::string("san francisco")), mklist<value>("state", std::string("ca")));
+ const list<value> ac1 = mklist<value>(mklist<value>("id", std::string("1234")), mklist<value>("balance", 1000));
+ const list<value> ac2 = mklist<value>(mklist<value>("id", std::string("6789")), mklist<value>("balance", 2000));
+ const list<value> ac3 = mklist<value>(mklist<value>("id", std::string("4567")), mklist<value>("balance", 3000));
+ {
+ const list<value> c = mklist<value>(mklist<value>("customer", mklist<value>("name", std::string("jdoe")), cons<value>("address", ad), mklist<value>("account", mklist<value>(ac1, ac2, ac3))));
+ const list<value> e = valuesToElements(c);
+ const list<value> v = elementsToValues(e);
+ assert(v == c);
+
+ std::ostringstream os;
+ writeXML<std::ostringstream*>(xmlWriter, &os, e);
+ assert(os.str() == customerXML);
+ }
+ {
+ const list<value> c = mklist<value>(mklist<value>("customer", mklist<value>("name", std::string("jdoe")), cons<value>("address", ad), cons<value>("account", ac1), cons<value>("account", ac2), cons<value>("account", ac3)));
+ const list<value> e = valuesToElements(c);
+ const list<value> v = elementsToValues(e);
+
+ std::ostringstream os;
+ writeXML<std::ostringstream*>(xmlWriter, &os, e);
+ assert(os.str() == customerXML);
+ }
+ }
+ {
+ std::istringstream is(customerXML);
+ const list<value> c = readXML(streamList(is));
+ const list<value> v = elementsToValues(c);
+ const list<value> e = valuesToElements(v);
+ std::ostringstream os;
+ writeXML<std::ostringstream*>(xmlWriter, &os, e);
+ assert(os.str() == customerXML);
+ }
+ return true;
+}
+
+const id<int> idF(const int v) {
+ return v * 2;
+}
+
+const id<int> idG(const int v) {
+ return v * 3;
+}
+
+const id<int> idH(const int v) {
+ return idF(v) >> idG;
+}
+
+bool testIdMonad() {
+ const id<int> m(2);
+ assert(m >> idF == idF(2));
+ assert(m >> unit<int>() == m);
+ assert(m >> idF >> idG == m >> idH);
+ return true;
+}
+
+const maybe<int> maybeF(const int v) {
+ return v * 2;
+}
+
+const maybe<int> maybeG(const int v) {
+ return v * 3;
+}
+
+const maybe<int> maybeH(const int v) {
+ return maybeF(v) >> maybeG;
+}
+
+bool testMaybeMonad() {
+ const maybe<int> m(2);
+ assert(m >> maybeF == maybeF(2));
+ assert((m >> just<int>()) == m);
+ assert(m >> maybeF >> maybeG == m >> maybeH);
+
+ assert(maybe<int>() >> maybeF >> maybeG == maybe<int>());
+ return true;
+}
+
+const failable<int, std::string> failableF(const int v) {
+ return v * 2;
+}
+
+const failable<int, std::string> failableG(const int v) {
+ return v * 3;
+}
+
+const failable<int, std::string> failableH(const int v) {
+ return failableF(v) >> failableG;
+}
+
+bool testFailableMonad() {
+ const failable<int, std::string> m(2);
+ assert(m >> failableF == failableF(2));
+ assert((m >> success<int, std::string>()) == m);
+ assert(m >> failableF >> failableG == m >> failableH);
+
+ failable<int, std::string> ooops = mkfailure<int, std::string>("ooops");
+ assert(reason(ooops) == "ooops");
+ assert(ooops >> failableF >> failableG == ooops);
+ return true;
+}
+
+struct tickInc {
+ const double v;
+ tickInc(const double v) : v(v) {
+ }
+ const svp<int, double> operator()(int s) const {
+ return svp<int, double>(s + 1, v);
+ }
+};
+
+const state<int, double> tick(const double v) {
+ return transformer<int, double>(tickInc(v));
+}
+
+const state<int, double> stateF(const double v) {
+ return result<int, double>(v * 2.0) >> tick;
+}
+
+const state<int, double> stateG(const double v) {
+ return result<int, double>(v + 5);
+}
+
+const state<int, double> stateH(const double v) {
+ return stateF(v) >> stateG;
+}
+
+bool testStateMonad() {
+ const lambda<state<int, double>(double)> r(result<int, double>);
+
+ state<int, double> m = result<int, double>(2.0);
+ assert((m >> stateF)(0) == stateF(2.0)(0));
+ assert(1 == (int)(m >> stateF)(0));
+ assert((m >> r)(0) == m(0));
+ assert((m >> stateF >> stateG)(0) == (m >> stateH)(0));
+
+ return true;
+}
+
+}
+
+int main() {
+ std::cout << "Testing..." << std::endl;
+
+ tuscany::testLambda();
+ tuscany::testLambdaGC();
+ tuscany::testCons();
+ tuscany::testSet();
+ tuscany::testListGC();
+ tuscany::testOut();
+ tuscany::testEquals();
+ tuscany::testLength();
+ tuscany::testAppend();
+ tuscany::testComplex();
+ tuscany::testMap();
+ tuscany::testReduce();
+ tuscany::testFilter();
+ tuscany::testMember();
+ tuscany::testReverse();
+ tuscany::testListRef();
+ tuscany::testAssoc();
+ tuscany::testZip();
+ tuscany::testTokenize();
+ tuscany::testSeq();
+ tuscany::testValue();
+ tuscany::testValueGC();
+ tuscany::testElement();
+ tuscany::testCppPerf();
+ tuscany::testAtomicPerf();
+ tuscany::testWorker();
+ tuscany::testReadXML();
+ tuscany::testWriteXML();
+ tuscany::testIdMonad();
+ tuscany::testMaybeMonad();
+ tuscany::testFailableMonad();
+ tuscany::testStateMonad();
+
+ std::cout << "OK" << std::endl;
+
+ return 0;
+}
diff --git a/sca-cpp/trunk/kernel/list.hpp b/sca-cpp/trunk/kernel/list.hpp
new file mode 100644
index 0000000000..c21efe173b
--- /dev/null
+++ b/sca-cpp/trunk/kernel/list.hpp
@@ -0,0 +1,484 @@
+/*
+ * 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_list_hpp
+#define tuscany_list_hpp
+
+/**
+ * Simple list functions.
+ */
+
+#include <iostream>
+#include "function.hpp"
+
+namespace tuscany {
+
+long countlists = 0;
+long countIlists = 0;
+long countClists = 0;
+long countElists = 0;
+
+bool resetListCounters() {
+ countlists = countIlists = countClists = countElists = 0;
+ return true;
+}
+
+bool printListCounters() {
+ std::cout << "countlists " << countlists << std::endl;
+ std::cout << "countElists " << countElists << std::endl;
+ std::cout << "countIlists " << countIlists << std::endl;
+ std::cout << "countClists " << countClists << std::endl;
+ return true;
+}
+
+/**
+ * A car/cdr lisp-like pair, base structure to construct lists.
+ */
+
+template<typename T> class list {
+public:
+
+ list() {
+ countlists++;
+ countElists++;
+ }
+
+ list(const T car, const lambda<list<T> ()>& cdr) :
+ car(car), cdr(cdr) {
+ countlists++;
+ countIlists++;
+ }
+
+ list(const list& p) :
+ car(p.car), cdr(p.cdr) {
+ countlists++;
+ countClists++;
+ }
+
+ const list& operator=(const list<T>& p) {
+ if(this == &p)
+ return *this;
+ car = p.car;
+ cdr = p.cdr;
+ return *this;
+ }
+
+ ~list() {
+ countlists--;
+ }
+
+ const bool operator==(const list<T>& p) const {
+ if(this == &p)
+ return true;
+ if(isNil(cdr))
+ return isNil(p.cdr);
+ if(isNil(p.cdr))
+ return false;
+ if(!(car == p.car))
+ return false;
+ if(cdr == p.cdr)
+ return true;
+ return cdr() == p.cdr();
+ }
+
+ const bool operator!=(const list<T>& p) const {
+ return !this->operator==(p);
+ }
+
+ operator const list<list<T> >() const {
+ return (list<list<T> >)T(*this);
+ }
+
+ list<T>& operator<<(const T& v) {
+ *this = append(*this, mklist(v));
+ return *this;
+ }
+
+ template<typename X> friend const bool isNil(const list<X>& p);
+ template<typename X> friend const X car(const list<X>& p);
+ template<typename X> friend const list<X> cdr(const list<X>& p);
+ template<typename X> friend const bool setCar(list<X>& p, const X& car);
+ template<typename X> friend const bool setCdr(list<X>& p, const list<X>& cdr);
+ template<typename X> friend const bool setCdr(list<X>& p, const lambda<list<X> ()>& cdr);
+
+private:
+ T car;
+ lambda<list<T> ()> cdr;
+};
+
+/**
+ * Returns true if the given list is nil.
+ */
+template<typename T> const bool isNil(const list<T>& p) {
+ return isNil(p.cdr);
+}
+
+/**
+ * Write a list to an output stream.
+ */
+template<typename T> std::ostream& operator<<(std::ostream& out, const list<T>& l) {
+ if(isNil(l))
+ return out << "()";
+ out << "(";
+ list<T> ml = l;
+ while(true) {
+ out << car(ml);
+ ml = cdr(ml);
+ if (isNil(ml))
+ break;
+ out << " ";
+ }
+ return out << ")";
+}
+
+/**
+ * Construct a (lazy) list from a value and a lambda function that returns the cdr.
+ */
+template<typename T> const list<T> cons(const T& car, const lambda<list<T> ()>& cdr) {
+ return list<T> (car, cdr);
+}
+
+/**
+ * Construct a list from a value and a cdr list.
+ */
+template<typename T> const list<T> cons(const T& car, const list<T>& cdr) {
+ return list<T> (car, result(cdr));
+}
+
+/**
+ * Cons variations for use with the reduce and reduceRight functions.
+ */
+template<typename T> const list<T> lcons(const list<T>& cdr, const T& car) {
+ return cons<T>(car, cdr);
+}
+
+template<typename T> const list<T> rcons(const T& car, const list<T>& cdr) {
+ return cons<T>(car, cdr);
+}
+
+/**
+ * Construct a list of one value.
+ */
+template<typename T> const list<T> mklist(const T& car) {
+ return list<T> (car, result(list<T> ()));
+}
+
+/**
+ * Construct a list of two values.
+ */
+template<typename T> const list<T> mklist(const T& a, const T& b) {
+ return cons(a, mklist(b));
+}
+
+/**
+ * Construct a list of three values.
+ */
+template<typename T> const list<T> mklist(const T& a, const T& b, const T& c) {
+ return cons(a, cons(b, mklist(c)));
+}
+
+/**
+ * Construct a list of four values.
+ */
+template<typename T> const list<T> mklist(const T& a, const T& b, const T& c, const T& d) {
+ return cons(a, cons(b, cons(c, mklist(d))));
+}
+
+/**
+ * Construct a list of five values.
+ */
+template<typename T> const list<T> mklist(const T& a, const T& b, const T& c, const T& d, const T& e) {
+ return cons(a, cons(b, cons(c, cons(d, mklist(e)))));
+}
+
+/**
+ * Construct a list of six values.
+ */
+template<typename T> const list<T> mklist(const T& a, const T& b, const T& c, const T& d, const T& e, const T& f) {
+ return cons(a, cons(b, cons(c, cons(d, cons(e, mklist(f))))));
+}
+
+/**
+ * Returns the car of a list.
+ */
+template<typename T> const T car(const list<T>& p) {
+ return p.car;
+}
+
+/**
+ * Returns the cdr of a list.
+ */
+template<typename T> const list<T> cdr(const list<T>& p) {
+ return p.cdr();
+}
+
+/**
+ * Sets the car of a list.
+ */
+template<typename T> const bool setCar(list<T>& p, const T& car) {
+ p.car = car;
+ return true;
+}
+
+/**
+ * Sets the cdr of a list.
+ */
+template<typename T> const bool setCdr(list<T>& p, const list<T>& c) {
+ p.cdr = result(c);
+ return true;
+}
+
+/**
+ * Sets the cdr of a list to a lambda function.
+ */
+template<typename T> const bool setCdr(list<T>& p, const lambda<list<T> ()>& cdr) {
+ p.cdr = cdr;
+ return true;
+}
+
+
+/**
+ * Returns the car of the cdr of a list.
+ */
+template<typename T> const T cadr(const list<T>& p) {
+ return car(cdr(p));
+}
+
+/**
+ * Returns the car of the cdr of the cdr of a list.
+ */
+template<typename T> const T caddr(const list<T>& p) {
+ return car(cdr(cdr(p)));
+}
+
+/**
+ * Returns the cdr of a cdr of a list.
+ */
+template<typename T> const list<T> cddr(const list<T>& p) {
+ return cdr(cdr(p));
+}
+
+/**
+ * Returns the cdr of a cdr of the cdr of a list.
+ */
+template<typename T> const list<T> cdddr(const list<T>& p) {
+ return cdr(cdr(cdr(p)));
+}
+
+/**
+ * Returns the length of a list.
+ */
+template<typename T> struct lengthRef {
+ const int operator()(const int c, const list<T>& p) {
+ if(isNil(p))
+ return c;
+ return (*this)(c + 1, cdr(p));
+ }
+};
+
+template<typename T> const int length(const list<T>& p) {
+ return lengthRef<T> ()(0, p);
+}
+
+/**
+ * Appends a list and a lambda function returning a list.
+ */
+template<typename T> struct appendCdr {
+ const list<T> a;
+ const lambda<list<T> ()> fb;
+ appendCdr(const list<T>& a, const lambda<list<T> ()>& fb) :
+ a(a), fb(fb) {
+ }
+ const list<T> operator()() const {
+ return append(a, fb);
+ }
+};
+
+template<typename T> const list<T> append(const list<T>&a, const lambda<list<T> ()>& fb) {
+ if(isNil(a))
+ return fb();
+
+ return cons<T>(car(a), appendCdr<T> (cdr(a), fb));
+}
+
+/**
+ * Appends two lists.
+ */
+template<typename T> const list<T> append(const list<T>&a, const list<T>& b) {
+ return append(a, result(b));
+}
+
+/**
+ * Map a lambda function on a list.
+ */
+template<typename T, typename R> const list<R> map(const lambda<R(T)>& f, const list<T>& p) {
+ if(isNil(p))
+ return list<R> ();
+ return cons(f(car(p)), map(f, cdr(p)));
+}
+
+/**
+ * Run a reduce lambda function on a list.
+ */
+template<typename T, typename R> struct reduceAccumulate {
+ const lambda<R(R, T)> f;
+ reduceAccumulate(const lambda<R(R, T)>& f) :
+ f(f) {
+ }
+ R operator()(const R& acc, const list<T>& p) const {
+ if(isNil(p))
+ return acc;
+ return (*this)(f(acc, car(p)), cdr(p));
+ }
+};
+
+template<typename T, typename R> const R reduce(const lambda<R(R, T)>& f, const R& initial, const list<T>& p) {
+ return reduceAccumulate<T, R> (f)(initial, p);
+}
+
+template<typename T, typename R> struct reduceRightAccumulate {
+ const lambda<R(T, R)> f;
+ reduceRightAccumulate(const lambda<R(T, R)>& f) :
+ f(f) {
+ }
+ R operator()(const list<T>& p, const R& acc) const {
+ if(isNil(p))
+ return acc;
+ return (*this)(cdr(p), f(car(p), acc));
+ }
+};
+
+template<typename T, typename R> const R reduceRight(const lambda<R(T, R)>& f, const R& initial, const list<T>& p) {
+ return reduceRightAccumulate<T, R> (f)(p, initial);
+}
+
+/**
+ * Run a filter lambda function on a list.
+ */
+template<typename T> const list<T> filter(const lambda<bool(T)>& f, const list<T>& p) {
+ if(isNil(p))
+ return list<T> ();
+ if(f(car(p))) {
+ const lambda<list<T> (lambda<bool(T)> , list<T> )> ff(filter<T> );
+ return cons(car(p), curry(ff, f, cdr(p)));
+ }
+ return filter(f, cdr(p));
+}
+
+/**
+ * Returns a list pointing to a member of a list.
+ */
+template<typename T> const list<T> member(const T& t, const list<T>& p) {
+ if(isNil(p))
+ return list<T> ();
+ if(t == car(p))
+ return p;
+ return member(t, cdr(p));
+}
+
+/**
+ * Reverse a list.
+ */
+template<typename T> const list<T> reverseIter(const list<T>& acc, const list<T>& p) {
+ if(isNil(p))
+ return acc;
+ return reverseIter(cons(car(p), acc), cdr(p));
+}
+
+template<typename T> const list<T> reverse(const list<T>& p) {
+ return reverseIter(list<T> (), p);
+}
+
+template<typename T> const list<T> seq(const T& start, const T& end);
+
+template<typename T> struct seqGenerate {
+ const T start;
+ const T end;
+ seqGenerate(const T& start, const T&end) :
+ start(start), end(end) {
+ }
+ const list<T> operator()() const {
+ return seq<T> (start, end);
+ }
+};
+
+/**
+ * Returns a sequence of values between the given bounds.
+ */
+template<typename T> const list<T> seq(const T& start, const T& end) {
+ if(start == end)
+ return mklist(start);
+ if(start < end)
+ return cons<T>(start, seqGenerate<T> (start + 1, end));
+ return cons<T>(start, seqGenerate<T> (start - 1, end));
+}
+
+/**
+ * Returns the i-th element of a list.
+ */
+template<typename T> const T listRef(const list<T>& l, const int i) {
+ if (i == 0)
+ return car(l);
+ return listRef(cdr(l), i - 1);
+}
+
+/**
+ * Returns the first pair matching a key from a list of key value pairs.
+ */
+template<typename T> const list<T> assoc(const T& k, const list<list<T> >& p) {
+ if(isNil(p))
+ return list<T> ();
+ if(k == car(car(p)))
+ return car(p);
+ return assoc(k, cdr(p));
+}
+
+/**
+ * Returns a list of lists containing elements from two input lists.
+ */
+template<typename T> const list<list<T> > zip(const list<T>& a, const list<T>& b) {
+ if (isNil(a) || isNil(b))
+ return list<list<T> >();
+ return cons<list<T> >(mklist<T>(car(a), car(b)), zip(cdr(a), cdr(b)));
+}
+
+/**
+ * Converts a list of key value pairs to a list containing the list of keys and the list of values.
+ */
+template<typename T> const list<T> unzipKeys(const list<list<T> >& l) {
+ if (isNil(l))
+ return list<T>();
+ return cons(car(car(l)), unzipKeys(cdr(l)));
+}
+
+template<typename T> const list<T> unzipValues(const list<list<T> >& l) {
+ if (isNil(l))
+ return list<T>();
+ return cons(cadr(car(l)), unzipValues(cdr(l)));
+}
+
+template<typename T> const list<list<T> > unzip(const list<list<T> >& l) {
+ return mklist<list<T> >(unzipKeys(l), unzipValues(l));
+}
+
+}
+
+#endif /* tuscany_list_hpp */
diff --git a/sca-cpp/trunk/kernel/monad.hpp b/sca-cpp/trunk/kernel/monad.hpp
new file mode 100644
index 0000000000..98eb3799c0
--- /dev/null
+++ b/sca-cpp/trunk/kernel/monad.hpp
@@ -0,0 +1,455 @@
+/*
+ * 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_monad_hpp
+#define tuscany_monad_hpp
+
+/**
+ * Simple monad implementations.
+ */
+
+#include <string>
+#include <iostream>
+#include "function.hpp"
+
+namespace tuscany
+{
+
+/**
+ * Identity monad. Just wraps a value.
+ * To get the value in the monad, just cast it to the value type.
+ */
+template<typename V> class id {
+public:
+ id(const V& v) : v(v) {
+ }
+
+ operator const V() const {
+ return v;
+ }
+
+ const id<V>& operator=(const id<V>& m) {
+ if(this == &m)
+ return *this;
+ v = m.v;
+ return *this;
+ }
+
+ const bool operator!=(const id<V>& m) const {
+ return !this->operator==(m);
+ }
+
+ const bool operator==(const id<V>& m) const {
+ if (&m == this)
+ return true;
+ return v == m.v;
+ }
+
+private:
+ const V v;
+};
+
+/**
+ * Write an identity monad to a stream.
+ */
+template<typename V> std::ostream& operator<<(std::ostream& out, const id<V>& m) {
+ out << (V)m;
+ return out;
+}
+
+/**
+ * Return an identity monad from a value.
+ */
+template<typename V> const id<V> mkunit(const V& v) {
+ return id<V>(v);
+}
+
+template<typename V> const lambda<id<V>(V)> unit() {
+ return mkunit<V>;
+}
+
+/**
+ * Bind a function to an identity monad. Pass the value in the monad to the function.
+ */
+template<typename R, typename V> const id<R> operator>>(const id<V>& m, const lambda<id<R>(V)>& f) {
+ return f(m);
+}
+
+template<typename R, typename V> const id<R> operator>>(const id<V>& m, const id<R> (* const f)(const V)) {
+ return f(m);
+}
+
+/**
+ * Maybe monad. Used to represent an optional value, which may be there or not.
+ * To get the value in the monad, just cast it to the value type.
+ */
+template<typename V> class maybe {
+public:
+ maybe(const V& v) : hasv(true), v(v) {
+ }
+
+ maybe() : hasv(false) {
+ }
+
+ operator const V() const {
+ return v;
+ }
+
+ const maybe<V>& operator=(const maybe<V>& m) {
+ if(this == &m)
+ return *this;
+ hasv = m.hasv;
+ if (hasv)
+ v = m.v;
+ return *this;
+ }
+
+ const bool operator!=(const maybe<V>& m) const {
+ return !this->operator==(m);
+ }
+
+ const bool operator==(const maybe<V>& m) const {
+ if (this == &m)
+ return true;
+ if (!hasv)
+ return !m.hasv;
+ return m.hasv && v == m.v;
+ }
+
+private:
+ const bool hasv;
+ V v;
+
+ template<typename A> friend const bool hasValue(const maybe<A>& m);
+};
+
+/**
+ * Write a maybe monad to a stream.
+ */
+template<typename V> std::ostream& operator<<(std::ostream& out, const maybe<V>& m) {
+ if (!hasValue(m)) {
+ out << "nothing";
+ return out;
+ }
+ out << (V)m;
+ return out;
+}
+
+/**
+ * Return a maybe monad with a value in it.
+ */
+template<typename V> const maybe<V> mkjust(const V& v) {
+ return maybe<V>(v);
+}
+
+template<typename V> const lambda<maybe<V>(V)> just() {
+ return mkjust<V>;
+}
+
+/**
+ * Returns true if the monad contains a value.
+ */
+template<typename V> const bool hasValue(const maybe<V>& m) {
+ return m.hasv;
+}
+
+/**
+ * Bind a function to a maybe monad. Passes the value in the monad to the function
+ * if present, or does nothing if there's no value.
+ */
+template<typename R, typename V> const maybe<R> operator>>(const maybe<V>& m, const lambda<maybe<R>(V)>& f) {
+ if (!hasValue(m))
+ return m;
+ return f(m);
+}
+
+template<typename R, typename V> const maybe<R> operator>>(const maybe<V>& m, const maybe<R> (* const f)(const V)) {
+ if (!hasValue(m))
+ return m;
+ return f(m);
+}
+
+/**
+ * Failable monad. Used to represent either a success value or a failure.
+ * To get the value in the monad, just cast it to the value type.
+ * To get the failure in the monad, cast it to the failure type.
+ */
+template<typename V, typename F> class failable {
+public:
+ failable() : hasv(false) {
+ }
+
+ failable(const V& v) : hasv(true), v(v) {
+ }
+
+ failable(const failable<V, F>& m) : hasv(m.hasv) {
+ if (hasv)
+ v = m.v;
+ else
+ f = m.f;
+ }
+
+ operator const V() const {
+ return v;
+ }
+
+ const failable<V, F>& operator=(const failable<V, F>& m) {
+ if(this == &m)
+ return *this;
+ hasv = m.hasv;
+ if (hasv)
+ v = m.v;
+ else
+ f = m.f;
+ return *this;
+ }
+
+ const bool operator!=(const failable<V, F>& m) const {
+ return !this->operator==(m);
+ }
+
+ const bool operator==(const failable<V, F>& m) const {
+ if (this == &m)
+ return true;
+ if (!hasv)
+ return !m.hasv && f == m.f;
+ return m.hasv && v == m.v;
+ }
+
+private:
+ bool hasv;
+ V v;
+ F f;
+
+ failable(const bool hasv, const F& f) : hasv(hasv), f(f) {
+ }
+
+ template<typename A, typename B> friend const bool hasValue(const failable<A, B>& m);
+ template<typename A, typename B> friend const B reason(const failable<A, B>& m);
+ template<typename A, typename B> friend const failable<A, B> mkfailure(const B& f);
+};
+
+/**
+ * Write a failable monad to a stream.
+ */
+template<typename V, typename F> std::ostream& operator<<(std::ostream& out, const failable<V, F>& m) {
+ if (!hasValue(m)) {
+ out << reason(m);
+ return out;
+ }
+ const V v = m;
+ out << v;
+ return out;
+}
+
+/**
+ * Returns a failable monad with a success value in it.
+ */
+template<typename V, typename F> const failable<V, F> mksuccess(const V& v) {
+ return failable<V, F>(v);
+}
+
+template<typename V, typename F> const lambda<failable<V, F>(V)> success() {
+ return mksuccess<V, F>;
+}
+
+/**
+ * Returns a failable monad with a failure in it.
+ */
+template<typename V, typename F> const failable<V, F> mkfailure(const F& f) {
+ return failable<V, F>(false, f);
+}
+
+template<typename V, typename F> const lambda<failable<V, F>(V)> failure() {
+ return mkfailure<V, F>;
+}
+
+/**
+ * Returns true if the monad contains a value.
+ */
+template<typename V, typename F> const bool hasValue(const failable<V, F>& m) {
+ return m.hasv;
+}
+
+/**
+ * Returns the reason for failure of a failable monad.
+ */
+template<typename V, typename F> const F reason(const failable<V, F>& m) {
+ return m.f;
+}
+
+/**
+ * Bind a function to a failable monad. Passes the success value in the monad to the function
+ * if present, or does nothing if there's no value and a failure instead.
+ */
+template<typename R, typename FR, typename V, typename FV>
+const failable<R, FR> operator>>(const failable<V, FV>& m, const lambda<failable<R, FR>(V)>& f) {
+ if (!hasValue(m))
+ return m;
+ return f(m);
+}
+
+template<typename R, typename FR, typename V, typename FV>
+const failable<R, FR> operator>>(const failable<V, FV>& m, const failable<R, FR> (* const f)(const V)) {
+ if (!hasValue(m))
+ return m;
+ return f(m);
+}
+
+/**
+ * State + value pair data type used by the state monad.
+ */
+template<typename S, typename V> class svp {
+public:
+ svp(const S& s, const V& v) : s(s), v(v) {
+ }
+
+ operator const S() const {
+ return s;
+ }
+
+ operator const V() const {
+ return v;
+ }
+
+ const svp<S, V>& operator=(const svp<S, V>& p) {
+ if(this == &p)
+ return *this;
+ s = p.s;
+ v = p.v;
+ return *this;
+ }
+
+ const bool operator!=(const svp<S, V>& p) const {
+ return !this->operator==(p);
+ }
+
+ const bool operator==(const svp<S, V>& p) const {
+ if (this == &p)
+ return true;
+ return s == p.s && v == p.v;
+ }
+
+private:
+ const S s;
+ const V v;
+};
+
+/**
+ * State monad. Used to represent the combination of a state and a value.
+ * To get the state in the monad, just cast it to the state type.
+ * To get the value in the monad, just cast it to the value type.
+ */
+template<typename S, typename V> class state {
+public:
+ state(const lambda<svp<S, V>(S)>& f) : f(f) {
+ }
+
+ const svp<S, V> operator()(const S& s) const {
+ return f(s);
+ }
+
+ const state<S, V>& operator=(const state<S, V>& m) {
+ if(this == &m)
+ return *this;
+ f = m.f;
+ return *this;
+ }
+
+ const bool operator!=(const state<S, V>& m) const {
+ return !this->operator==(m);
+ }
+
+ const bool operator==(const state<S, V>& m) const {
+ if (this == &m)
+ return true;
+ return f == m.f;
+ }
+
+private:
+ const lambda<svp<S, V>(S)> f;
+};
+
+/**
+ * Write a state monad to a stream.
+ */
+template<typename S, typename V> std::ostream& operator<<(std::ostream& out, const state<S, V>& m) {
+ const S s = m;
+ const V v = m;
+ out << '(' << s << ' ' << v << ')';
+ return out;
+}
+
+/**
+ * Return a state monad carrying a result value.
+ */
+template<typename S, typename V> struct returnState {
+ const V v;
+ returnState(const V& v) : v(v) {
+ }
+ const svp<S, V> operator()(const S& s) const {
+ return svp<S, V>(s, v);
+ }
+};
+
+template<typename S, typename V> const state<S, V> result(const V& v) {
+ return state<S, V>(returnState<S, V>(v));
+}
+
+/**
+ * Return a state monad with a transformer function.
+ * A transformer function takes a state and returns an svp pair carrying a value and a
+ * new (transformed) state.
+ */
+template<typename S, typename V> const state<S, V> transformer(const lambda<svp<S, V>(S)>& f) {
+ return state<S, V>(f);
+}
+
+/**
+ * Bind a function to a state monad. The function takes a value and returns a state
+ * monad carrying a return value.
+ */
+template<typename S, typename A, typename B> struct stateBind {
+ const state<S, A> st;
+ const lambda<state<S, B>(A)>f;
+
+ stateBind(const state<S, A>& st, const lambda<state<S, B>(A)>& f) : st(st), f(f) {
+ }
+
+ const svp<S, B> operator()(const S& is) const {
+ const svp<S, A> iscp = st(is);
+ const state<S, B> m = f((A)iscp);
+ return m((S)iscp);
+ }
+};
+
+template<typename S, typename A, typename B>
+const state<S, B> operator>>(const state<S, A>& st, const lambda<state<S, B>(A)>& f) {
+ return state<S, B>(stateBind<S, A , B>(st, f));
+}
+
+template<typename S, typename A, typename B>
+const state<S, B> operator>>(const state<S, A>& st, const state<S, B> (* const f)(const A)) {
+ return state<S, B>(stateBind<S, A , B>(st, f));
+}
+
+}
+#endif /* tuscany_monad_hpp */
diff --git a/sca-cpp/trunk/kernel/parallel.hpp b/sca-cpp/trunk/kernel/parallel.hpp
new file mode 100644
index 0000000000..c2a948bbeb
--- /dev/null
+++ b/sca-cpp/trunk/kernel/parallel.hpp
@@ -0,0 +1,283 @@
+/*
+ * 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_parallel_hpp
+#define tuscany_parallel_hpp
+
+/**
+ * Simple parallel work execution functions.
+ */
+
+#include <pthread.h>
+#include <sys/syscall.h>
+#include "function.hpp"
+
+namespace tuscany {
+
+/**
+ * Returns the current thread id.
+ */
+unsigned int threadId() {
+ return syscall(__NR_gettid);
+}
+
+/**
+ * Represents a value which will be know in the future.
+ */
+template<typename T> class future {
+
+private:
+ template<typename X> class futureValue {
+ public:
+ futureValue() :
+ refCount(0), hasValue(false) {
+ pthread_mutex_init(&valueMutex, NULL);
+ pthread_cond_init(&valueCond, NULL);
+ }
+
+ ~futureValue() {
+ pthread_mutex_destroy(&valueMutex);
+ pthread_cond_destroy(&valueCond);
+ }
+
+ unsigned int acquire() {
+ return __sync_add_and_fetch(&refCount, 1);
+ }
+
+ unsigned int release() {
+ return __sync_sub_and_fetch(&refCount, 1);
+ }
+
+ bool set(const T& v) {
+ pthread_mutex_lock(&valueMutex);
+ if(hasValue) {
+ pthread_mutex_unlock(&valueMutex);
+ return false;
+ }
+ hasValue = true;
+ value = v;
+ pthread_mutex_unlock(&valueMutex);
+ pthread_cond_broadcast(&valueCond);
+ return true;
+ }
+
+ const T get() {
+ pthread_mutex_lock(&valueMutex);
+ while(!hasValue) {
+ pthread_cond_wait(&valueCond, &valueMutex);
+ }
+ const T& v = value;
+ pthread_mutex_unlock(&valueMutex);
+ return v;
+ }
+
+ private:
+ unsigned refCount;
+ pthread_mutex_t valueMutex;
+ pthread_cond_t valueCond;
+ bool hasValue;
+ X value;
+ };
+
+ gc_counting_ptr<futureValue<T> > fvalue;
+
+ template<typename X> friend const X get(const future<X>& f);
+ template<typename X> friend bool set(const future<X>& f, const X& v);
+
+public:
+ future() : fvalue(new futureValue<T>()) {
+ //std::cout << "future() threadId " << threadId() << "\n";
+ }
+
+ ~future() {
+ //std::cout << "~future() threadId " << threadId() << "\n";
+ }
+
+ future(const future& f) : fvalue(f.fvalue) {
+ //std::cout << "future(const future& f) threadId " << threadId() << "\n";
+ }
+
+ const future& operator=(const future& f) {
+ //std::cout << "future::operator=(const future& f) threadId " << threadId() << "\n";
+ if (&f == this)
+ return *this;
+ fvalue = f.fvalue;
+ return *this;
+ }
+
+ const future& operator=(const T& v) const {
+ fvalue->set(v);
+ return *this;
+ }
+
+ operator const T() const {
+ return fvalue->get();
+ }
+
+};
+
+/**
+ * A bounded thread safe queue.
+ */
+template<typename T> class queue {
+public:
+ queue(int max) : max(max), size(0), tail(0), head(0), values(new T[max]) {
+ pthread_mutex_init(&mutex, NULL);
+ pthread_cond_init(&full, NULL);
+ pthread_cond_init(&empty, NULL);
+ }
+
+ ~queue() {
+ pthread_mutex_destroy(&mutex);
+ pthread_cond_destroy(&full);
+ pthread_cond_destroy(&empty);
+ }
+
+private:
+ const int max;
+ int size;
+ int tail;
+ int head;
+ pthread_mutex_t mutex;
+ pthread_cond_t full;
+ pthread_cond_t empty;
+ gc_aptr<T> values;
+
+ template<typename X> friend const int enqueue(queue<X>& q, const X& v);
+ template<typename X> friend const X dequeue(queue<X>& q);
+};
+
+/**
+ * Adds an element to the tail of the queue.
+ */
+template<typename T> const int enqueue(queue<T>&q, const T& v) {
+ pthread_mutex_lock(&q.mutex);
+ while(q.size == q.max)
+ pthread_cond_wait(&q.full, &q.mutex);
+ q.values[q.tail] = v;
+ q.tail = (q.tail + 1) % q.max;
+ q.size++;
+ pthread_mutex_unlock(&q.mutex);
+ pthread_cond_broadcast(&q.empty);
+ return q.size;
+}
+
+/**
+ * Returns the element at the head of the queue.
+ */
+template<typename T> const T dequeue(queue<T>& q) {
+ pthread_mutex_lock(&q.mutex);
+ while(q.size == 0)
+ pthread_cond_wait(&q.empty, &q.mutex);
+ const T v = q.values[q.head];
+ q.head = (q.head + 1) % q.max;
+ q.size--;
+ pthread_mutex_unlock(&q.mutex);
+ pthread_cond_broadcast(&q.full);
+ return v;
+}
+
+/**
+ * The worker thread function.
+ */
+void *workerThreadFunc(void *arg) {
+ queue<lambda<bool()> >* work = reinterpret_cast<queue<lambda<bool()> >*>(arg);
+ while(dequeue(*work)())
+ ;
+ return NULL;
+}
+
+/**
+ * Returns a list of worker threads.
+ */
+const list<pthread_t> workerThreads(queue<lambda<bool()> >& queue, const int count) {
+ if (count == 0)
+ return list<pthread_t>();
+ pthread_t thread;
+ pthread_create(&thread, NULL, workerThreadFunc, &queue);
+ return cons(thread, workerThreads(queue, count - 1));
+}
+
+/**
+ * A worker, implemented with a work queue and a pool of threads.
+ */
+class worker {
+public:
+ worker(int max) : work(queue<lambda<bool()> >(max)), threads(workerThreads(work, max)) {
+ }
+
+private:
+ queue<lambda<bool()> > work;
+ const list<pthread_t> threads;
+
+ template<typename X> friend const future<X> submit(worker& w, const lambda<X()>& func);
+ friend const bool shutdown(worker& w);
+};
+
+/**
+ * Function used to wrap work submitted to a worker.
+ */
+template<typename R> bool submitFunc(const lambda<R()>& func, const future<R>& fut) {
+ fut = func();
+ return true;
+}
+
+/**
+ * Submits work to a worker.
+ */
+template<typename R> const future<R> submit(worker& w, const lambda<R()>& func) {
+ const future<R> fut;
+ const lambda<bool()> f = curry(lambda<bool(lambda<R()>, future<R>)>(submitFunc<R>), func, fut);
+ enqueue(w.work, f);
+ return fut;
+}
+
+/**
+ * Enqueues shutdown requests.
+ */
+const bool shutdownEnqueue(const list<pthread_t>& threads, queue<lambda<bool()> >& work) {
+ if (isNil(threads))
+ return true;
+ enqueue(work, result(false));
+ return shutdownEnqueue(cdr(threads), work);
+}
+
+/**
+ * Waits for shut down threads to terminate.
+ */
+const bool shutdownJoin(const list<pthread_t>& threads) {
+ if (isNil(threads))
+ return true;
+ pthread_join(car(threads), NULL);
+ return shutdownJoin(cdr(threads));
+}
+
+/**
+ * Shutdown a worker.
+ */
+const bool shutdown(worker& w) {
+ shutdownEnqueue(w.threads, w.work);
+ shutdownJoin(w.threads);
+ return true;
+}
+
+}
+#endif /* tuscany_parallel_hpp */
diff --git a/sca-cpp/trunk/kernel/slist.hpp b/sca-cpp/trunk/kernel/slist.hpp
new file mode 100644
index 0000000000..705152cb29
--- /dev/null
+++ b/sca-cpp/trunk/kernel/slist.hpp
@@ -0,0 +1,96 @@
+/*
+ * 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_slist_hpp
+#define tuscany_slist_hpp
+
+/**
+ * Useful functions to work with lists of strings and character streams.
+ */
+
+#include <iostream>
+#include <string>
+#include "function.hpp"
+#include "list.hpp"
+
+namespace tuscany {
+
+/**
+ * Tokenize a string into a list of strings.
+ */
+const list<std::string> tokenize(const std::string& sep, const std::string& str) {
+ struct nested {
+ static const list<std::string> tokenize(const std::string& sep, const std::string& str, const unsigned int start = 0) {
+ if (start >= str.length())
+ return list<std::string>();
+ const unsigned int i = str.find_first_of(sep, start);
+ if (i == std::string::npos)
+ return mklist(str.substr(start));
+ return cons(str.substr(start, i - start), tokenize(sep, str, i + 1));
+ }
+ };
+ return nested::tokenize(sep, str, 0);
+}
+
+/**
+ * Returns a lazy list view of an input stream.
+ */
+struct ilistRead{
+ std::istream &is;
+ ilistRead(std::istream& is) : is(is) {
+ }
+ const list<std::string> operator()() {
+ char buffer[1024];
+ is.read(buffer, 1024);
+ const int n = is.gcount();
+ if (n ==0)
+ return list<std::string>();
+ return cons(std::string(buffer, n), (*this)());
+ }
+};
+
+const list<std::string> streamList(std::istream& is) {
+ return ilistRead(is)();
+}
+
+/**
+ * Fragment the first element of a list of strings to fit the given max length.
+ */
+const list<std::string> fragment(list<std::string> l, unsigned int max) {
+ const std::string s = car(l);
+ if (s.length() <= max)
+ return l;
+ return cons(s.substr(0, max), cons(s.substr(max), cdr(l)));
+}
+
+/**
+ * Write a list of strings to an output stream.
+ */
+std::ostream& write(const list<std::string>& l, std::ostream& os) {
+ if(isNil(l))
+ return os;
+ os << car(l);
+ return write(cdr(l), os);
+}
+
+}
+
+#endif /* tuscany_slist_hpp */
diff --git a/sca-cpp/trunk/kernel/value.hpp b/sca-cpp/trunk/kernel/value.hpp
new file mode 100644
index 0000000000..d602b30623
--- /dev/null
+++ b/sca-cpp/trunk/kernel/value.hpp
@@ -0,0 +1,491 @@
+/*
+ * 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_value_hpp
+#define tuscany_value_hpp
+
+/**
+ * Generic value type.
+ */
+
+#include <string>
+#include <iostream>
+#include <sstream>
+#include "gc.hpp"
+#include "function.hpp"
+#include "list.hpp"
+
+namespace tuscany
+{
+
+long int countValues = 0;
+long int countEValues = 0;
+long int countCValues = 0;
+long int countVValues = 0;
+
+bool resetValueCounters() {
+ countValues = countEValues = countCValues = countVValues = 0;
+ return true;
+}
+
+bool printValueCounters() {
+ std::cout << "countValues " << countValues << std::endl;
+ std::cout << "countEValues " << countEValues << std::endl;
+ std::cout << "countCValues " << countCValues << std::endl;
+ std::cout << "countVValues " << countVValues << std::endl;
+ return true;
+}
+
+class value;
+
+class value {
+public:
+
+ enum ValueType {
+ Undefined, Symbol, String, List, Number, Bool, Char, Lambda, Ptr, PoolPtr
+ };
+
+ value() :
+ type(value::Undefined) {
+ countValues++;
+ countEValues++;
+ }
+
+ value(const value& v) {
+ countValues++;
+ countCValues++;
+ type = v.type;
+ switch(type) {
+ case value::List:
+ lst() = v.lst();
+ case value::Lambda:
+ func() = v.func();
+ case value::Symbol:
+ str() = v.str();
+ case value::String:
+ str() = v.str();
+ case value::Number:
+ num() = v.num();
+ case value::Bool:
+ boo() = v.boo();
+ case value::Char:
+ chr() = v.chr();
+ case value::Ptr:
+ ptr() = v.ptr();
+ case value::PoolPtr:
+ poolptr() = v.poolptr();
+ default:
+ break;
+ }
+ }
+
+ const value& operator=(const value& v) {
+ if(this == &v)
+ return *this;
+ type = v.type;
+ switch(type) {
+ case value::List:
+ lst() = v.lst();
+ case value::Lambda:
+ func() = v.func();
+ case value::Symbol:
+ str() = v.str();
+ case value::String:
+ str() = v.str();
+ case value::Number:
+ num() = v.num();
+ case value::Bool:
+ boo() = v.boo();
+ case value::Char:
+ chr() = v.chr();
+ case value::Ptr:
+ ptr() = v.ptr();
+ case value::PoolPtr:
+ poolptr() = v.poolptr();
+ default:
+ break;
+ }
+ return *this;
+ }
+
+ virtual ~value() {
+ countValues--;
+ }
+
+ value(const lambda<value(list<value>&)>& func) :
+ type(value::Lambda), data(vdata(func)) {
+ countValues++;
+ countVValues++;
+ }
+
+ value(const std::string& str) :
+ type(value::String), data(vdata(result(str))) {
+ countValues++;
+ countVValues++;
+ }
+
+ value(const char* str) :
+ type(value::Symbol), data(vdata(result(std::string(str)))) {
+ countValues++;
+ countVValues++;
+ }
+
+ value(const list<value>& lst) :
+ type(value::List), data(vdata(result(lst))) {
+ countValues++;
+ countVValues++;
+ }
+
+ value(const list<list<value> >& l) :
+ type(value::List), data(vdata(result(listOfValues(l)))) {
+ countValues++;
+ countVValues++;
+ }
+
+ value(const double num) :
+ type(value::Number), data(vdata(result(num))) {
+ countValues++;
+ countVValues++;
+ }
+
+ value(const int num) :
+ type(value::Number), data(vdata(result((double)num))) {
+ countValues++;
+ countVValues++;
+ }
+
+ value(const bool boo) :
+ type(value::Bool), data(vdata(result(boo))) {
+ countValues++;
+ countVValues++;
+ }
+
+ value(const char chr) :
+ type(value::Char), data(vdata(result(chr))) {
+ countValues++;
+ countVValues++;
+ }
+
+ value(const gc_ptr<value> ptr) :
+ type(value::Ptr), data(vdata(result(ptr))) {
+ countValues++;
+ countVValues++;
+ }
+
+ value(const gc_pool_ptr<value> ptr) :
+ type(value::PoolPtr), data(vdata(result(ptr))) {
+ countValues++;
+ countVValues++;
+ }
+
+ const bool operator!=(const value& v) const {
+ return !this->operator==(v);
+ }
+
+ const bool operator==(const value& v) const {
+ if(this == &v)
+ return true;
+ if(type != v.type)
+ return false;
+ switch(type) {
+ case value::Undefined:
+ return true;
+ case value::List:
+ return lst()() == v.lst()();
+ case value::Lambda:
+ return func() == v.func();
+ case value::Symbol:
+ return str()() == v.str()();
+ case value::String:
+ return str()() == v.str()();
+ case value::Number:
+ return num()() == v.num()();
+ case value::Bool:
+ return boo()() == v.boo()();
+ case value::Char:
+ return chr()() == v.chr()();
+ case value::Ptr:
+ return ptr()() == v.ptr()();
+ case value::PoolPtr:
+ return poolptr()() == v.poolptr()();
+ default:
+ return false;
+ }
+ }
+
+ const value operator()(list<value>& args) const {
+ return func()(args);
+ }
+
+ operator const std::string() const {
+ switch(type) {
+ case value::List:
+ case value::Lambda:
+ case value::Ptr:
+ case value::PoolPtr:
+ return "";
+ case value::Symbol:
+ case value::String:
+ return str()();
+ case value::Number: {
+ std::ostringstream sos;
+ sos << num()();
+ return sos.str();
+ }
+ case value::Bool: {
+ if(boo()())
+ return "true";
+ else
+ return "false";
+ }
+ case value::Char: {
+ std::ostringstream sos;
+ sos << chr()();
+ return sos.str();
+ }
+ default:
+ return "";
+ }
+ }
+
+ operator const double() const {
+ return num()();
+ }
+
+ operator const int() const {
+ return num()();
+ }
+
+ operator const bool() const {
+ return boo()();
+ }
+
+ operator const char() const {
+ return chr()();
+ }
+
+ operator const gc_ptr<value>() const {
+ return ptr()();
+ }
+
+ operator const gc_pool_ptr<value>() const {
+ return poolptr()();
+ }
+
+ operator const list<value>() const {
+ return lst()();
+ }
+
+ operator const list<list<value> >() const {
+ return listOfListOfValues(lst()());
+ }
+
+ operator const lambda<value(list<value>&)>() const {
+ return func();
+ }
+
+ friend std::ostream& operator<<(std::ostream&, const value&);
+
+ ValueType type;
+ lambda<char()> data;
+
+private:
+ template<typename T> lambda<T>& vdata() const {
+ return *reinterpret_cast<lambda<T> *> (const_cast<lambda<char()> *> (&data));
+ }
+
+ template<typename T> const lambda<char()>& vdata(const T& v) const {
+ return *reinterpret_cast<const lambda<char()> *> (&v);
+ }
+
+ lambda<double()>& num() const {
+ return vdata<double()> ();
+ }
+
+ lambda<bool()>& boo() const {
+ return vdata<bool()> ();
+ }
+
+ lambda<char()>& chr() const {
+ return vdata<char()> ();
+ }
+
+ lambda<gc_ptr<value>()>& ptr() const {
+ return vdata<gc_ptr<value>()> ();
+ }
+
+ lambda<gc_pool_ptr<value>()>& poolptr() const {
+ return vdata<gc_pool_ptr<value>()> ();
+ }
+
+ lambda<std::string()>& str() const {
+ return vdata<std::string()> ();
+ }
+
+ lambda<list<value>()>& lst() const {
+ return vdata<list<value>()> ();
+ }
+
+ lambda<value(list<value>&)>& func() const {
+ return vdata<value(list<value>&)> ();
+ }
+
+ const list<value> listOfValues(const list<list<value> >& l) const {
+ if (isNil(l))
+ return list<value>();
+ return cons<value>(car(l), listOfValues(cdr(l)));
+ }
+
+ const list<list<value> > listOfListOfValues(const list<value>& l) const {
+ if (isNil(l))
+ return list<list<value> >();
+ return cons<list<value> >(list<value>(car(l)), listOfListOfValues(cdr(l)));
+ }
+
+};
+
+/**
+ * Write a value to a stream.
+ */
+std::ostream& operator<<(std::ostream& out, const value& v) {
+ switch(v.type) {
+ case value::List:
+ return out << v.lst()();
+ case value::Lambda:
+ return out << "lambda::" << v.func();
+ case value::Symbol:
+ return out << v.str()();
+ case value::String:
+ return out << '\"' << v.str()() << '\"';
+ case value::Number:
+ return out << v.num()();
+ case value::Bool:
+ if(v.boo()())
+ return out << "true";
+ else
+ return out << "false";
+ case value::Char:
+ return out << v.chr()();
+ case value::Ptr: {
+ const gc_ptr<value> p = v.ptr()();
+ if (p == gc_ptr<value>(NULL))
+ return out << "pointer::null";
+ return out << "pointer::" << *p;
+ }
+ case value::PoolPtr: {
+ const gc_pool_ptr<value> p = v.poolptr()();
+ if (p == gc_pool_ptr<value>(NULL))
+ return out << "pointer::null";
+ return out << "pointer::" << *p;
+ }
+ default:
+ return out << "undefined";
+ }
+}
+
+/**
+ * Returns the type of a value.
+ */
+const value::ValueType type(const value& v) {
+ return v.type;
+}
+
+/**
+ * Returns true if a value is nil.
+ */
+const bool isNil(const value& value) {
+ return value.type == value::Undefined;
+}
+
+/**
+ * Returns true if a value is a lambda.
+ */
+const bool isLambda(const value& value) {
+ return value.type == value::Lambda;
+}
+
+/**
+ * Returns true if a value is a string.
+ */
+const bool isString(const value& value) {
+ return value.type == value::String;
+}
+
+/**
+ * Returns true if a value is a symbol.
+ */
+const bool isSymbol(const value& value) {
+ return value.type == value::Symbol;
+}
+
+/**
+ * Returns true if a value is a list.
+ */
+const bool isList(const value& value) {
+ return value.type == value::List;
+}
+
+/**
+ * Returns true if a value is a number.
+ */
+const bool isNumber(const value& value) {
+ return value.type == value::Number;
+}
+
+/**
+ * Returns true if a value is a boolean.
+ */
+const bool isBool(const value& value) {
+ return value.type == value::Bool;
+}
+
+/**
+ * Returns true if a value is a character.
+ */
+const bool isChar(const value& value) {
+ return value.type == value::Char;
+}
+
+/**
+ * Returns true if a value is a pointer.
+ */
+const bool isPtr(const value& value) {
+ return value.type == value::Ptr;
+}
+
+/**
+ * Returns true if a value is a pooled pointer.
+ */
+const bool isPoolPtr(const value& value) {
+ return value.type == value::PoolPtr;
+}
+
+/**
+ * Returns true if a value is a tagged list.
+ */
+const bool isTaggedList(const value& exp, value tag) {
+ if(isList(exp) && !isNil((list<value>)exp))
+ return car((list<value>)exp) == tag;
+ return false;
+}
+
+}
+#endif /* tuscany_value_hpp */
diff --git a/sca-cpp/trunk/kernel/xml.hpp b/sca-cpp/trunk/kernel/xml.hpp
new file mode 100644
index 0000000000..8d561557ca
--- /dev/null
+++ b/sca-cpp/trunk/kernel/xml.hpp
@@ -0,0 +1,364 @@
+/*
+ * 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_xml_hpp
+#define tuscany_xml_hpp
+
+/**
+ * XML read/write functions.
+ */
+
+#include <libxml/xmlreader.h>
+#include <libxml/xmlwriter.h>
+#include <libxml/xmlschemas.h>
+#include <libxml/globals.h>
+#include <string>
+#include "list.hpp"
+#include "slist.hpp"
+#include "value.hpp"
+#include "element.hpp"
+#include "monad.hpp"
+
+namespace tuscany {
+
+/**
+ * Initializes the libxml2 library.
+ */
+class XMLParser {
+public:
+ XMLParser() {
+ xmlInitParser();
+ }
+
+ ~XMLParser() {
+ xmlCleanupParser();
+ }
+};
+
+XMLParser xmlParser;
+
+/**
+ * Encapsulates a libxml2 xmlTextReader and its state.
+ */
+class XMLReader {
+public:
+ enum TokenType {
+ None = 0, Element = 1, Attribute = 2, Text = 3, EndElement = 15, Identifier = 100, End = 101
+ };
+
+ XMLReader(xmlTextReaderPtr xml) : xml(xml), tokenType(None), isEmptyElement(false), hasValue(false), hasAttributes(false) {
+ xmlTextReaderSetParserProp(xml, XML_PARSER_DEFAULTATTRS, 1);
+ xmlTextReaderSetParserProp(xml, XML_PARSER_SUBST_ENTITIES, 1);
+ }
+
+ ~XMLReader() {
+ xmlTextReaderClose(xml);
+ xmlFreeTextReader(xml);
+ }
+
+ /**
+ * Read the next XML token and return its type.
+ */
+ int read() {
+ if (tokenType == End)
+ return tokenType;
+ if (tokenType == Element) {
+ isEmptyElement = xmlTextReaderIsEmptyElement(xml);
+ hasAttributes = xmlTextReaderHasAttributes(xml);
+ return tokenType = Identifier;
+ }
+ if (tokenType == Identifier && hasAttributes && xmlTextReaderMoveToFirstAttribute(xml) == 1)
+ return tokenType = Attribute;
+ if (tokenType == Attribute && xmlTextReaderMoveToNextAttribute(xml) == 1)
+ return tokenType = Attribute;
+ if (isEmptyElement && (tokenType == Identifier || tokenType == Attribute))
+ return tokenType = EndElement;
+ if (!xmlTextReaderRead(xml))
+ return tokenType = End;
+ return tokenType = xmlTextReaderNodeType(xml);
+ }
+
+ operator xmlTextReaderPtr() const {
+ return xml;
+ }
+
+private:
+ const xmlTextReaderPtr xml;
+ int tokenType;
+ bool isEmptyElement;
+ bool hasValue;
+ bool hasAttributes;
+};
+
+/**
+ * Constants used to tag XML tokens.
+ */
+const value endElement("<");
+const value startElement(">");
+
+/**
+ * Read an XML identifier.
+ */
+const value readIdentifier(XMLReader& reader) {
+ const char* name = (const char*)xmlTextReaderConstName(reader);
+ return name;
+}
+
+/**
+ * Read XML text.
+ */
+const value readText(XMLReader& reader) {
+ const char *val = (const char*)xmlTextReaderConstValue(reader);
+ return std::string(val);
+}
+
+/**
+ * Read an XML attribute.
+ */
+const value readAttribute(XMLReader& reader) {
+ const char *name = (const char*)xmlTextReaderConstName(reader);
+ const char *val = (const char*)xmlTextReaderConstValue(reader);
+ return mklist<value>(attribute, name, std::string(val));
+}
+
+/**
+ * Read an XML token.
+ */
+const value readToken(XMLReader& reader) {
+ const int tokenType = reader.read();
+ if (tokenType == XMLReader::None || tokenType == XMLReader::End)
+ return value();
+ if (tokenType == XMLReader::Element)
+ return startElement;
+ if (tokenType == XMLReader::Identifier)
+ return readIdentifier(reader);
+ if (tokenType == XMLReader::Attribute)
+ return readAttribute(reader);
+ if (tokenType == XMLReader::Text)
+ return readText(reader);
+ if (tokenType == XMLReader::EndElement)
+ return endElement;
+ return readToken(reader);
+}
+
+/**
+ * Read a list of values from XML tokens.
+ */
+const list<value> readList(const list<value>& listSoFar, XMLReader& reader) {
+ const value token = readToken(reader);
+ if(isNil(token) || endElement == token)
+ return reverse(listSoFar);
+ if(startElement == token)
+ return readList(cons<value>(readList(mklist(element), reader), listSoFar), reader);
+ return readList(cons(token, listSoFar), reader);
+}
+
+/**
+ * Read a list of values from a libxml2 XML reader.
+ */
+const list<value> read(XMLReader& reader) {
+ value nextToken = readToken(reader);
+ if (startElement == nextToken)
+ return mklist<value>(readList(mklist(element), reader));
+ return list<value>();
+}
+
+/**
+ * Context passed to the read callback function.
+ */
+class XMLReadContext {
+public:
+ XMLReadContext(const list<std::string>& ilist) : ilist(ilist) {
+ }
+ list<std::string> ilist;
+};
+
+/**
+ * Callback function called by libxml2 to read XML.
+ */
+int readCallback(void *context, char* buffer, int len) {
+ XMLReadContext& rc = *static_cast<XMLReadContext*>(context);
+ if (isNil(rc.ilist))
+ return 0;
+ rc.ilist = fragment(rc.ilist, len);
+ std::string s = car(rc.ilist);
+ rc.ilist = cdr(rc.ilist);
+ s.copy(buffer, s.length());
+ return s.length();
+}
+
+/**
+ * Read a list values from a list of strings representing an XML document.
+ */
+const list<value> readXML(const list<std::string>& ilist) {
+ XMLReadContext cx(ilist);
+ xmlTextReaderPtr xml = xmlReaderForIO(readCallback, NULL, &cx, NULL, NULL, XML_PARSE_NONET);
+ if (xml == NULL)
+ return list<value>();
+ XMLReader reader(xml);
+ return read(reader);
+}
+
+/**
+ * Default encoding used to write XML documents.
+ */
+const char* encoding = "UTF-8";
+
+
+/**
+ * Write a list of XML element or attribute tokens.
+ */
+const list<value> expandElementValues(const value& n, const list<value>& l) {
+ if (isNil(l))
+ return l;
+ return cons<value>(value(cons<value>(element, cons<value>(n, (list<value>)car(l)))), expandElementValues(n, cdr(l)));
+}
+
+const failable<bool, std::string> writeList(const list<value>& l, const xmlTextWriterPtr xml) {
+ if (isNil(l))
+ return true;
+
+ // Write an attribute
+ const value token(car(l));
+ if (isTaggedList(token, attribute)) {
+ if (xmlTextWriterWriteAttribute(xml, (const xmlChar*)std::string(attributeName(token)).c_str(), (const xmlChar*)std::string(attributeValue(token)).c_str()) < 0)
+ return mkfailure<bool, std::string>("xmlTextWriterWriteAttribute failed");
+
+ } else if (isTaggedList(token, element)) {
+
+ // Write an element containing a value
+ if (elementHasValue(token)) {
+ const value v = elementValue(token);
+ if (isList(v)) {
+
+ // Write an element per entry in a list of values
+ const list<value> e = expandElementValues(elementName(token), v);
+ writeList(e, xml);
+
+ } else {
+
+ // Write an element with a single value
+ if (xmlTextWriterStartElement(xml, (const xmlChar*)std::string(elementName(token)).c_str()) < 0)
+ return mkfailure<bool, std::string>("xmlTextWriterStartElement failed");
+
+ // Write its children
+ const failable<bool, std::string> w = writeList(elementChildren(token), xml);
+ if (!hasValue(w))
+ return w;
+
+ if (xmlTextWriterEndElement(xml) < 0)
+ return mkfailure<bool, std::string>("xmlTextWriterEndElement failed");
+ }
+ }
+ else {
+
+ // Write an element
+ if (xmlTextWriterStartElement(xml, (const xmlChar*)std::string(elementName(token)).c_str()) < 0)
+ return mkfailure<bool, std::string>("xmlTextWriterStartElement failed");
+
+ // Write its children
+ const failable<bool, std::string> w = writeList(elementChildren(token), xml);
+ if (!hasValue(w))
+ return w;
+
+ if (xmlTextWriterEndElement(xml) < 0)
+ return mkfailure<bool, std::string>("xmlTextWriterEndElement failed");
+ }
+ } else {
+
+ // Write XML text
+ if (xmlTextWriterWriteString(xml, (const xmlChar*)std::string(token).c_str()) < 0)
+ return mkfailure<bool, std::string>("xmlTextWriterWriteString failed");
+
+ }
+
+ // Go on
+ return writeList(cdr(l), xml);
+}
+
+/**
+ * Write a list of values to a libxml2 XML writer.
+ */
+const failable<bool, std::string> write(const list<value>& l, const xmlTextWriterPtr xml) {
+ if (xmlTextWriterStartDocument(xml, NULL, encoding, NULL) < 0)
+ return mkfailure<bool, std::string>("xmlTextWriterStartDocument failed");
+
+ const failable<bool, std::string> w = writeList(l, xml);
+ if (!hasValue(w))
+ return w;
+
+ if (xmlTextWriterEndDocument(xml) < 0)
+ return mkfailure<bool, std::string>("xmlTextWriterEndDocument failed");
+ return true;
+}
+
+/**
+ * Context passed to the write callback function.
+ */
+template<typename R> class XMLWriteContext {
+public:
+ XMLWriteContext(const lambda<R(std::string, R)>& reduce, const R& accum) : reduce(reduce), accum(accum) {
+ }
+ const lambda<R(std::string, R)> reduce;
+ R accum;
+};
+
+/**
+ * Callback function called by libxml2 to write XML out.
+ */
+template<typename R> int writeCallback(void *context, const char* buffer, int len) {
+ XMLWriteContext<R>& cx = *static_cast<XMLWriteContext<R>*>(context);
+ cx.accum = cx.reduce(std::string(buffer, len), cx.accum);
+ return len;
+}
+
+/**
+ * Convert a list of values to an XML document.
+ */
+template<typename R> const failable<R, std::string> writeXML(const lambda<R(std::string, R)>& reduce, const R& initial, const list<value>& l) {
+ XMLWriteContext<R> cx(reduce, initial);
+ xmlOutputBufferPtr out = xmlOutputBufferCreateIO(writeCallback<R>, NULL, &cx, NULL);
+ if (out == NULL)
+ return mkfailure<R, std::string>("xmlOutputBufferCreateIO failed");
+ xmlTextWriterPtr xml = xmlNewTextWriter(out);
+ if (xml == NULL)
+ return mkfailure<R, std::string>("xmlNewTextWriter failed");
+
+ const failable<bool, std::string> w = write(l, xml);
+ xmlFreeTextWriter(xml);
+ if (!hasValue(w)) {
+ return mkfailure<R, std::string>(reason(w));
+ }
+ return cx.accum;
+}
+
+/**
+ * Convert a list of values to a list of strings representing an XML document.
+ */
+const failable<list<std::string>, std::string> writeXML(const list<value>& l) {
+ const failable<list<std::string>, std::string> ls = writeXML<list<std::string> >(rcons<std::string>, list<std::string>(), l);
+ if (!hasValue(ls))
+ return ls;
+ return reverse(list<std::string>(ls));
+}
+
+}
+#endif /* tuscany_xml_hpp */
diff --git a/sca-cpp/trunk/kernel/xsd-test.cpp b/sca-cpp/trunk/kernel/xsd-test.cpp
new file mode 100644
index 0000000000..818c03ba68
--- /dev/null
+++ b/sca-cpp/trunk/kernel/xsd-test.cpp
@@ -0,0 +1,107 @@
+/*
+ * 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 validation of a composite file against an SCDL schema.
+ */
+
+#include <iostream>
+#include <string>
+#include <libxml/xmlreader.h>
+#include <libxml/xmlschemas.h>
+
+namespace tuscany {
+
+bool printNode(xmlTextReaderPtr reader) {
+ const xmlChar* name = xmlTextReaderConstName(reader);
+ if(name == NULL)
+ name = (xmlChar *)"<unknown>";
+ const xmlChar* value = xmlTextReaderConstValue(reader);
+ std::cout << xmlTextReaderDepth(reader) << " " << xmlTextReaderNodeType(reader) << " " << name << " "
+ << xmlTextReaderIsEmptyElement(reader) << " " << xmlTextReaderHasValue(reader);
+ if(value == NULL)
+ std::cout << std::endl;
+ else
+ std::cout << value << std::endl;
+ return true;
+}
+
+int xmlRead(void *context, char* buffer, int len) {
+ return fread(buffer, 1, len, (FILE*)context);
+}
+
+int xmlClose(void *context) {
+ fclose((FILE*)context);
+ return 0;
+}
+
+bool readFile(const char*xsdfilename, const char *filename) {
+ std::cout << "Loading schemas...\n";
+ const xmlDocPtr xsddoc = xmlReadFile(xsdfilename, NULL, XML_PARSE_NONET);
+ const xmlSchemaParserCtxtPtr xsdctx = xmlSchemaNewDocParserCtxt(xsddoc);
+ const xmlSchemaPtr xsd = xmlSchemaParse(xsdctx);
+ const xmlSchemaValidCtxtPtr validctx = xmlSchemaNewValidCtxt(xsd);
+
+ std::cout << "Reading file...\n";
+ FILE* file = fopen(filename, "r");
+ if (file != NULL) {
+ const xmlTextReaderPtr reader = xmlReaderForIO(xmlRead, xmlClose, file, filename, NULL, XML_PARSE_NONET);
+ xmlTextReaderSetParserProp(reader, XML_PARSER_DEFAULTATTRS, 1);
+ xmlTextReaderSetParserProp(reader, XML_PARSER_SUBST_ENTITIES, 1);
+
+ if(reader != NULL) {
+ xmlTextReaderSchemaValidateCtxt(reader, validctx, 0);
+
+ int rc;
+ while((rc = xmlTextReaderRead(reader)) == 1) {
+ printNode(reader);
+ }
+ if(xmlTextReaderIsValid(reader) != 1)
+ std::cout << "Could not validate document" << std::endl;
+ xmlFreeTextReader(reader);
+ if(rc != 0)
+ std::cout << "Could not parse document" << std::endl;
+ } else
+ std::cout << "Could not create parser" << std::endl;
+ } else
+ std::cout << "Could not open document" << std::endl;
+
+ xmlSchemaFreeValidCtxt(validctx);
+ xmlSchemaFree(xsd);
+ xmlSchemaFreeParserCtxt(xsdctx);
+
+ return true;
+}
+
+}
+
+int main(int argc, char **argv) {
+ std::cout << "Testing..." << std::endl;
+ if(argc != 3)
+ return 1;
+
+ tuscany::readFile(argv[1], argv[2]);
+
+ xmlCleanupParser();
+
+ std::cout << "OK" << std::endl;
+ return 0;
+}