summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68>2009-12-26 03:25:25 +0000
committerjsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68>2009-12-26 03:25:25 +0000
commitbd4c1d47aeaf1d4bca76d5713e705b0869d3f2f7 (patch)
tree475d0385e678c5e7007df571bea9c5cc8b1417bb
parentf453584ae0a3ec04f1781fc35b7abe5d139c6679 (diff)
Added missing const qualifiers, macros and util functions to help debugging, and a simple balanced tree implementation for use in lookup tables.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@893938 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--sca-cpp/trunk/kernel/debug.hpp9
-rw-r--r--sca-cpp/trunk/kernel/dynlib-test.cpp4
-rw-r--r--sca-cpp/trunk/kernel/element.hpp2
-rw-r--r--sca-cpp/trunk/kernel/function.hpp6
-rw-r--r--sca-cpp/trunk/kernel/gc.hpp7
-rw-r--r--sca-cpp/trunk/kernel/kernel-test.cpp313
-rw-r--r--sca-cpp/trunk/kernel/list.hpp127
-rw-r--r--sca-cpp/trunk/kernel/monad.hpp26
-rw-r--r--sca-cpp/trunk/kernel/parallel.hpp2
-rw-r--r--sca-cpp/trunk/kernel/tree.hpp125
-rw-r--r--sca-cpp/trunk/kernel/value.hpp226
-rw-r--r--sca-cpp/trunk/kernel/xml.hpp6
-rw-r--r--sca-cpp/trunk/modules/atom/atom.hpp4
-rw-r--r--sca-cpp/trunk/modules/http/curl.hpp18
-rw-r--r--sca-cpp/trunk/modules/json/json.hpp6
15 files changed, 515 insertions, 366 deletions
diff --git a/sca-cpp/trunk/kernel/debug.hpp b/sca-cpp/trunk/kernel/debug.hpp
index 8dad5fdd3c..c06fe55f4a 100644
--- a/sca-cpp/trunk/kernel/debug.hpp
+++ b/sca-cpp/trunk/kernel/debug.hpp
@@ -26,6 +26,9 @@
* Functions to help log and debug.
*/
+#include <string>
+#include <ostream>
+
namespace tuscany
{
@@ -35,7 +38,7 @@ namespace tuscany
* Debug log.
*/
template<typename V> const bool debug(const V& v, const std::string& msg) {
- std::cerr<< msg << ": " << v << std::endl;
+ std::cerr << msg << ": " << v << std::endl;
return true;
}
@@ -52,6 +55,9 @@ bool debug_dec(long int& c) {
return true;
}
+/**
+ * Attribute used to mark unused parameters.
+ */
#define unused __attribute__ ((unused))
#else
@@ -60,6 +66,7 @@ bool debug_dec(long int& c) {
#define debug_inc(c)
#define debug_dec(c)
+
#define unused
#endif
diff --git a/sca-cpp/trunk/kernel/dynlib-test.cpp b/sca-cpp/trunk/kernel/dynlib-test.cpp
index 3cc666df1a..9d0e6a2186 100644
--- a/sca-cpp/trunk/kernel/dynlib-test.cpp
+++ b/sca-cpp/trunk/kernel/dynlib-test.cpp
@@ -42,8 +42,8 @@ extern "C" {
return tuscany::test::cppsquare(x);
}
- const tuscany::lambda<int(int)> csquarel() {
- return tuscany::lambda<int(int)>(tuscany::test::cppsquare);
+ const tuscany::lambda<int(const int)> csquarel() {
+ return tuscany::lambda<int(const int)>(tuscany::test::cppsquare);
}
}
diff --git a/sca-cpp/trunk/kernel/element.hpp b/sca-cpp/trunk/kernel/element.hpp
index 2b5336ba5c..612752d1df 100644
--- a/sca-cpp/trunk/kernel/element.hpp
+++ b/sca-cpp/trunk/kernel/element.hpp
@@ -247,7 +247,7 @@ struct selectorLambda {
}
};
-const lambda<bool(value)> selector(const list<value> s) {
+const lambda<bool(const value&)> selector(const list<value> s) {
return selectorLambda(s);
}
diff --git a/sca-cpp/trunk/kernel/function.hpp b/sca-cpp/trunk/kernel/function.hpp
index fb2ad296d7..54784b5549 100644
--- a/sca-cpp/trunk/kernel/function.hpp
+++ b/sca-cpp/trunk/kernel/function.hpp
@@ -140,11 +140,11 @@ public:
debug_inc(countELambdas);
}
- template<typename F> lambda(const F f) : callable(0) {
- typedef typename CallableType::template Proxy<F> ProxyType;
-
+ template<typename F> lambda(const F f) {
debug_inc(countLambdas);
debug_inc(countFLambdas);
+
+ typedef typename CallableType::template Proxy<F> ProxyType;
callable = gc_counting_ptr<CallableType>(new ProxyType(f));
}
diff --git a/sca-cpp/trunk/kernel/gc.hpp b/sca-cpp/trunk/kernel/gc.hpp
index bb5bbccb24..c9a1a35756 100644
--- a/sca-cpp/trunk/kernel/gc.hpp
+++ b/sca-cpp/trunk/kernel/gc.hpp
@@ -35,11 +35,10 @@ namespace tuscany
/**
* Macros used to add or subtract values to reference counters.
- * In a multithreaded environment, define MTHREAD_GC to use
- * the GCC __sync_add_and_fetch and __sync_sub_and_fetch built
- * in functions.
+ * In a multithreaded environment, use the GCC __sync_add_and_fetch
+ * and __sync_sub_and_fetch built in functions.
*/
-#ifdef MTHREAD_GC
+#ifdef _REENTRANT
#define gc_add_and_fetch(t, v) __sync_add_and_fetch(&(t), v)
#define gc_sub_and_fetch(t, v) __sync_sub_and_fetch(&(t), v)
diff --git a/sca-cpp/trunk/kernel/kernel-test.cpp b/sca-cpp/trunk/kernel/kernel-test.cpp
index 388fbf7436..8a5e4a704d 100644
--- a/sca-cpp/trunk/kernel/kernel-test.cpp
+++ b/sca-cpp/trunk/kernel/kernel-test.cpp
@@ -20,24 +20,21 @@
/* $Rev$ $Date$ */
/**
- * Test core utils.
+ * Test kernel functions.
*/
#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 "tree.hpp"
#include "value.hpp"
-#include "element.hpp"
-#include "xml.hpp"
#include "monad.hpp"
#include "dynlib.hpp"
+#include "perf.hpp"
namespace tuscany {
@@ -55,22 +52,22 @@ const int square(const int x) {
return x * x;
}
-int mapLambda(lambda<int(int)> f, int v) {
+int mapLambda(lambda<int(const int)> f, int v) {
return f(v);
}
bool testLambda() {
- const lambda<int(int)> sq(square);
+ const lambda<int(const int)> sq(square);
assert(sq(2) == 4);
assert(mapLambda(sq, 2) == 4);
assert(mapLambda(square, 2) == 4);
- const lambda<int(int)> incf(inc(10));
+ const lambda<int(const int)> incf(inc(10));
assert(incf(1) == 11);
assert(mapLambda(incf, 1) == 11);
assert(mapLambda(inc(10), 1) == 11);
- lambda<int(int)> l;
+ lambda<int(const int)> l;
l = incf;
assert(l(1) == 11);
l = square;
@@ -113,6 +110,10 @@ struct Element {
return o.i == i;
}
};
+std::ostream& operator<<(std::ostream& out, const Element& v) {
+ out << v.i ;
+ return out;
+}
bool testCons() {
assert(car(cons(2, mklist(3))) == 2);
@@ -195,6 +196,10 @@ struct Complex {
x(x), y(y) {
}
};
+std::ostream& operator<<(std::ostream& out, const Complex& v) {
+ out << "[" << v.x << ":" << v.y << "]";
+ return out;
+}
bool testComplex() {
const list<Complex> p = mklist(Complex(1, 2), Complex(3, 4));
@@ -219,12 +224,12 @@ const int add(const int x, const int y) {
}
bool testReduce() {
- const lambda<int(int, int)> r(add);
+ const lambda<int(const int, const int)> r(add);
assert(reduce(r, 0, mklist(1, 2, 3)) == 6);
return true;
}
-bool isPositive(int x) {
+bool isPositive(const int x) {
if(x >= 0)
return true;
else
@@ -306,8 +311,6 @@ bool testSeq() {
list<double> s = seq(0.0, 1000.0);
assert(1001 == length(s));
- //printLambdaCounters();
- //printListCounters();
assert(1001 == length(map<double, double>(testSeqMap, s)));
@@ -315,9 +318,6 @@ bool testSeq() {
assert(201 == length(member(200.0, reverse(s))));
assert(1001 == (reduce<double, double>(testSeqReduce, 0.0, s)));
- //printLambdaCounters();
- //printListCounters();
-
return true;
}
@@ -329,7 +329,7 @@ bool testValue() {
assert(value(true) == value(true));
assert(value(1) == value(1));
assert(value("abcd") == value("abcd"));
- lambda<value(list<value>&)> vl(valueSquare);
+ lambda<value(const list<value>&)> vl(valueSquare);
assert(value(vl) == value(vl));
assert(value(mklist<value>(1, 2)) == value(mklist<value>(1, 2)));
@@ -357,6 +357,40 @@ bool testValueGC() {
return true;
}
+bool testTree() {
+ const list<value> t = mktree<value>("a", list<value>(), list<value>());
+ const list<value> ct = constree<value>("d", constree<value>("f", constree<value>("c", constree<value>("e", constree<value>("b", t)))));
+ const list<value> mt = mktree(mklist<value>("d", "f", "c", "e", "b", "a"));
+ assert(mt == ct);
+ const list<value> l = flatten<value>(mt);
+ assert(length(l) == 6);
+ assert(car(l) == "a");
+ assert(car(reverse(l)) == "f");
+ const list<value> bt = mkbtree<value>(l);
+ assert(car(bt) == "c");
+ return true;
+}
+
+const list<value> lta(const std::string& x) {
+ return mklist<value>(x.c_str(), (x + x).c_str());
+}
+
+bool testTreeAssoc() {
+ const list<value> t = mktree<value>(lta("a"), list<value>(), list<value>());
+ const list<value> at = constree<value>(lta("d"), constree<value>(lta("f"), constree<value>(lta("c"), constree<value>(lta("e"), constree<value>(lta("b"), t)))));
+ const list<value> l = flatten<value>(at);
+ assert(length(l) == 6);
+ assert(car(l) == mklist<value>("a", "aa"));
+ assert(car(reverse(l)) == mklist<value>("f", "ff"));
+ const list<value> bt = mkbtree<value>(l);
+ assert(car(bt) == mklist<value>("c", "cc"));
+ assert(assoctree<value>("a", bt) == mklist<value>("a", "aa"));
+ assert(assoctree<value>("b", bt) == mklist<value>("b", "bb"));
+ assert(assoctree<value>("f", bt) == mklist<value>("f", "ff"));
+ assert(isNil(assoctree<value>("x", bt)));
+ return true;
+}
+
double fib_aux(double n, double a, double b) {
if(n == 0.0)
return a;
@@ -367,19 +401,31 @@ double fib(double n) {
return fib_aux(n, 0.0, 1.0);
}
-bool testCppPerf() {
- struct timeval start;
- struct timeval end;
- {
- gettimeofday(&start, NULL);
+struct fibMapPerf {
+ const bool operator()() const {
+ list<double> s = seq(0.0, 999.0);
+ list<double> r = map<double, double>(fib, s);
+ assert(1000 == length(r));
+ return true;
+ }
+};
+struct nestedFibMapPerf {
+ const lambda<double(const double)> fib;
+ nestedFibMapPerf(const lambda<double(const double)>& fib) : fib(fib) {
+ }
+ const bool operator()() const {
list<double> s = seq(0.0, 999.0);
list<double> r = map<double, double>(fib, s);
assert(1000 == length(r));
+ return true;
+ }
+};
- 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;
+bool testCppPerf() {
+ {
+ const lambda<bool()> fml = fibMapPerf();
+ std::cout << "Fibonacci map test " << (time(fml, 1, 1) / 1000) << " ms" << std::endl;
}
{
@@ -396,197 +442,8 @@ bool testCppPerf() {
}
};
- 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);
+ const lambda<bool()> nfml = nestedFibMapPerf(lambda<double(const double)>(nested::fib));
+ std::cout << "Nested Fibonacci map test " << (time(nfml, 1, 1) / 1000) << " ms" << std::endl;
}
return true;
}
@@ -651,8 +508,9 @@ bool testFailableMonad() {
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");
+ std::cout << "Failable monad test... ";
+ failable<int, std::string> ooops = mkfailure<int, std::string>("test");
+ assert(reason(ooops) == "test");
assert(ooops >> failableF >> failableG == ooops);
return true;
}
@@ -683,7 +541,7 @@ const state<int, double> stateH(const double v) {
}
bool testStateMonad() {
- const lambda<state<int, double>(double)> r(result<int, double>);
+ const lambda<state<int, double>(const double)> r(result<int, double>);
state<int, double> m = result<int, double>(2.0);
assert((m >> stateF)(0) == stateF(2.0)(0));
@@ -697,14 +555,14 @@ bool testStateMonad() {
bool testDynLib() {
const failable<lib, std::string> dl(dynlib(".libs/libdynlib-test" + dynlibExt));
assert(hasContent(dl));
- const failable<lambda<int(int)>, std::string> sq(dynlambda<int(int)>("csquare", content(dl)));
+ const failable<lambda<int(const int)>, std::string> sq(dynlambda<int(const int)>("csquare", content(dl)));
assert(hasContent(sq));
- lambda<int(int)> l(content(sq));
+ lambda<int(const int)> l(content(sq));
assert(l(2) == 4);
- const failable<lambda<lambda<int(int)>()>, std::string> sql(dynlambda<lambda<int(int)>()>("csquarel", content(dl)));
+ const failable<lambda<lambda<int(const int)>()>, std::string> sql(dynlambda<lambda<int(const int)>()>("csquarel", content(dl)));
assert(hasContent(sql));
- lambda<lambda<int(int)>()> ll(content(sql));
+ lambda<lambda<int(const int)>()> ll(content(sql));
assert(ll()(3) == 9);
return true;
}
@@ -736,12 +594,9 @@ int main() {
tuscany::testSeq();
tuscany::testValue();
tuscany::testValueGC();
- tuscany::testElement();
+ tuscany::testTree();
+ tuscany::testTreeAssoc();
tuscany::testCppPerf();
- tuscany::testAtomicPerf();
- tuscany::testWorker();
- tuscany::testReadXML();
- tuscany::testWriteXML();
tuscany::testIdMonad();
tuscany::testMaybeMonad();
tuscany::testFailableMonad();
diff --git a/sca-cpp/trunk/kernel/list.hpp b/sca-cpp/trunk/kernel/list.hpp
index da00a5a40d..88163e63d2 100644
--- a/sca-cpp/trunk/kernel/list.hpp
+++ b/sca-cpp/trunk/kernel/list.hpp
@@ -26,6 +26,8 @@
* Simple list functions.
*/
+#include <string>
+#include <sstream>
#include <iostream>
#include "function.hpp"
#include "debug.hpp"
@@ -35,7 +37,9 @@ namespace tuscany {
#ifdef _DEBUG
/**
- * Debug counters.
+ * Debug utilities. Counters used to track instances of lists, and
+ * macro used to write the contents of a list in a string, easier to
+ * watch in a debugger than the list itself.
*/
long countLists = 0;
long countILists = 0;
@@ -59,12 +63,18 @@ bool printListCounters() {
return true;
}
+#define debug_watchList() do { \
+ this->watch = watchList(*this); \
+ } while (0)
+
#else
#define resetListCounters()
#define checkListCounters() true
#define printListCounters()
+#define debug_watchList();
+
#endif
@@ -78,18 +88,23 @@ public:
list() {
debug_inc(countLists);
debug_inc(countELists);
+ debug_watchList();
}
- list(const T car, const lambda<list<T> ()>& cdr) :
+ list(const T car, const lambda<list<T>()>& cdr) :
car(car), cdr(cdr) {
debug_inc(countLists);
debug_inc(countILists);
+ debug_watchList();
}
list(const list& p) :
car(p.car), cdr(p.cdr) {
debug_inc(countLists);
debug_inc(countCLists);
+#ifdef _DEBUG
+ watch = p.watch;
+#endif
}
const list& operator=(const list<T>& p) {
@@ -97,6 +112,9 @@ public:
return *this;
car = p.car;
cdr = p.cdr;
+#ifdef _DEBUG
+ watch = p.watch;
+#endif
return *this;
}
@@ -118,6 +136,34 @@ public:
return cdr() == p.cdr();
}
+ const bool operator<(const list<T>& p) const {
+ if(this == &p)
+ return false;
+ if (isNil(cdr))
+ return !isNil(p.cdr);
+ if (isNil(p.cdr))
+ return false;
+ if (car < p.car)
+ return true;
+ if (car != p.car)
+ return false;
+ return cdr() < p.cdr();
+ }
+
+ const bool operator>(const list<T>& p) const {
+ if(this == &p)
+ return false;
+ if (isNil(cdr))
+ return false;
+ if (isNil(p.cdr))
+ return true;
+ if (car > p.car)
+ return true;
+ if (car != p.car)
+ return false;
+ return cdr() > p.cdr();
+ }
+
const bool operator!=(const list<T>& p) const {
return !this->operator==(p);
}
@@ -136,13 +182,33 @@ public:
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);
+ template<typename X> friend const bool setCdr(list<X>& p, const lambda<list<X>()>& cdr);
private:
+#ifdef _DEBUG
+ template<typename X> friend const std::string watchList(const list<X>& p);
+ std::string watch;
+#endif
+
T car;
- lambda<list<T> ()> cdr;
+ lambda<list<T>()> cdr;
};
+#ifdef _DEBUG
+
+/**
+ * Debug utility used to write the contents of a list to a string, easier
+ * to watch than the list itself in a debugger.
+ */
+template<typename T> const std::string watchList(const list<T>& p) {
+ if(isNil(p))
+ return "()";
+ std::ostringstream os;
+ os << "(" << car(p) << " ...)";
+ return os.str();
+}
+#endif
+
/**
* Returns true if the given list is nil.
*/
@@ -153,25 +219,25 @@ template<typename T> const bool isNil(const list<T>& p) {
/**
* Write a list to an output stream.
*/
+template<typename T> std::ostream& writeHelper(std::ostream& out, const list<T>& l) {
+ if (isNil(l))
+ return out;
+ out << " " << car(l);
+ return writeHelper(out, cdr(l));
+}
+
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 << " ";
- }
+ out << "(" << car(l);
+ writeHelper<T>(out, cdr(l));
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) {
+template<typename T> const list<T> cons(const T& car, const lambda<list<T>()>& cdr) {
return list<T> (car, cdr);
}
@@ -268,7 +334,7 @@ template<typename T> const bool setCdr(list<T>& p, const list<T>& c) {
/**
* Sets the cdr of a list to a lambda function.
*/
-template<typename T> const bool setCdr(list<T>& p, const lambda<list<T> ()>& cdr) {
+template<typename T> const bool setCdr(list<T>& p, const lambda<list<T>()>& cdr) {
p.cdr = cdr;
return true;
}
@@ -289,6 +355,13 @@ template<typename T> const T caddr(const list<T>& p) {
}
/**
+ * Returns the car of the cdr of the cdr of the cdr of a list.
+ */
+template<typename T> const T cadddr(const list<T>& p) {
+ return car(cdr(cdr(cdr(p))));
+}
+
+/**
* Returns the cdr of a cdr of a list.
*/
template<typename T> const list<T> cddr(const list<T>& p) {
@@ -322,8 +395,8 @@ template<typename T> const int length(const list<T>& p) {
*/
template<typename T> struct appendCdr {
const list<T> a;
- const lambda<list<T> ()> fb;
- appendCdr(const list<T>& a, const lambda<list<T> ()>& fb) :
+ const lambda<list<T>()> fb;
+ appendCdr(const list<T>& a, const lambda<list<T>()>& fb) :
a(a), fb(fb) {
}
const list<T> operator()() const {
@@ -331,7 +404,7 @@ template<typename T> struct appendCdr {
}
};
-template<typename T> const list<T> append(const list<T>&a, const lambda<list<T> ()>& fb) {
+template<typename T> const list<T> append(const list<T>&a, const lambda<list<T>()>& fb) {
if(isNil(a))
return fb();
@@ -348,7 +421,7 @@ template<typename T> const list<T> append(const list<T>&a, const list<T>& 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) {
+template<typename T, typename R> const list<R> map(const lambda<R(const T)>& f, const list<T>& p) {
if(isNil(p))
return list<R> ();
return cons(f(car(p)), map(f, cdr(p)));
@@ -358,8 +431,8 @@ template<typename T, typename R> const list<R> map(const lambda<R(T)>& f, const
* 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) :
+ const lambda<R(const R&, const T&)> f;
+ reduceAccumulate(const lambda<R(const R, const T)>& f) :
f(f) {
}
R operator()(const R& acc, const list<T>& p) const {
@@ -369,13 +442,13 @@ template<typename T, typename R> struct reduceAccumulate {
}
};
-template<typename T, typename R> const R reduce(const lambda<R(R, T)>& f, const R& initial, const list<T>& p) {
+template<typename T, typename R> const R reduce(const lambda<R(const R, const 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) :
+ const lambda<R(const T&, const R&)> f;
+ reduceRightAccumulate(const lambda<R(const T, const R)>& f) :
f(f) {
}
R operator()(const list<T>& p, const R& acc) const {
@@ -385,18 +458,18 @@ template<typename T, typename R> struct reduceRightAccumulate {
}
};
-template<typename T, typename R> const R reduceRight(const lambda<R(T, R)>& f, const R& initial, const list<T>& p) {
+template<typename T, typename R> const R reduceRight(const lambda<R(const T, const 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) {
+template<typename T> const list<T> filter(const lambda<bool(const 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> );
+ const lambda<list<T>(const lambda<bool(const T)>, const list<T>)> ff(filter<T>);
return cons(car(p), curry(ff, f, cdr(p)));
}
return filter(f, cdr(p));
diff --git a/sca-cpp/trunk/kernel/monad.hpp b/sca-cpp/trunk/kernel/monad.hpp
index 31eb390f1c..5449aa38fd 100644
--- a/sca-cpp/trunk/kernel/monad.hpp
+++ b/sca-cpp/trunk/kernel/monad.hpp
@@ -89,14 +89,14 @@ template<typename V> const id<V> mkunit(const V& v) {
return id<V>(v);
}
-template<typename V> const lambda<id<V>(V)> unit() {
+template<typename V> const lambda<id<V>(const 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) {
+template<typename R, typename V> const id<R> operator>>(const id<V>& m, const lambda<id<R>(const V)>& f) {
return f(content(m));
}
@@ -164,7 +164,7 @@ template<typename V> const maybe<V> mkjust(const V& v) {
return maybe<V>(v);
}
-template<typename V> const lambda<maybe<V>(V)> just() {
+template<typename V> const lambda<maybe<V>(const V)> just() {
return mkjust<V>;
}
@@ -186,7 +186,7 @@ template<typename V> const V content(const maybe<V>& m) {
* 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) {
+template<typename R, typename V> const maybe<R> operator>>(const maybe<V>& m, const lambda<maybe<R>(const V)>& f) {
if (!hasContent(m))
return m;
return f(content(m));
@@ -274,7 +274,7 @@ 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() {
+template<typename V, typename F> const lambda<failable<V, F>(const V)> success() {
return mksuccess<V, F>;
}
@@ -286,7 +286,7 @@ 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() {
+template<typename V, typename F> const lambda<failable<V, F>(const V)> failure() {
return mkfailure<V, F>;
}
@@ -316,7 +316,7 @@ template<typename V, typename F> const F reason(const failable<V, F>& m) {
* 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) {
+const failable<R, FR> operator>>(const failable<V, FV>& m, const lambda<failable<R, FR>(const V)>& f) {
if (!hasContent(m))
return m;
return f(content(m));
@@ -390,7 +390,7 @@ template<typename S, typename V> const S content(const scp<S, V>& m) {
*/
template<typename S, typename V> class state {
public:
- state(const lambda<scp<S, V>(S)>& f) : f(f) {
+ state(const lambda<scp<S, V>(const S)>& f) : f(f) {
}
const scp<S, V> operator()(const S& s) const {
@@ -415,7 +415,7 @@ public:
}
private:
- const lambda<scp<S, V>(S)> f;
+ const lambda<scp<S, V>(const S)> f;
};
/**
@@ -449,7 +449,7 @@ template<typename S, typename V> const state<S, V> result(const V& v) {
* A transformer function takes a state and returns an scp pair carrying a content and a
* new (transformed) state.
*/
-template<typename S, typename V> const state<S, V> transformer(const lambda<scp<S, V>(S)>& f) {
+template<typename S, typename V> const state<S, V> transformer(const lambda<scp<S, V>(const S)>& f) {
return state<S, V>(f);
}
@@ -459,9 +459,9 @@ template<typename S, typename V> const state<S, V> transformer(const lambda<scp<
*/
template<typename S, typename A, typename B> struct stateBind {
const state<S, A> st;
- const lambda<state<S, B>(A)>f;
+ const lambda<state<S, B>(const A)>f;
- stateBind(const state<S, A>& st, const lambda<state<S, B>(A)>& f) : st(st), f(f) {
+ stateBind(const state<S, A>& st, const lambda<state<S, B>(const A)>& f) : st(st), f(f) {
}
const scp<S, B> operator()(const S& is) const {
@@ -472,7 +472,7 @@ template<typename S, typename A, typename B> struct stateBind {
};
template<typename S, typename A, typename B>
-const state<S, B> operator>>(const state<S, A>& st, const lambda<state<S, B>(A)>& f) {
+const state<S, B> operator>>(const state<S, A>& st, const lambda<state<S, B>(const A)>& f) {
return state<S, B>(stateBind<S, A , B>(st, f));
}
diff --git a/sca-cpp/trunk/kernel/parallel.hpp b/sca-cpp/trunk/kernel/parallel.hpp
index 987d662e23..a94764763a 100644
--- a/sca-cpp/trunk/kernel/parallel.hpp
+++ b/sca-cpp/trunk/kernel/parallel.hpp
@@ -246,7 +246,7 @@ template<typename R> bool submitFunc(const lambda<R()>& func, const future<R>& f
*/
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);
+ const lambda<bool()> f = curry(lambda<bool(const lambda<R()>, future<R>)>(submitFunc<R>), func, fut);
enqueue(w.work, f);
return fut;
}
diff --git a/sca-cpp/trunk/kernel/tree.hpp b/sca-cpp/trunk/kernel/tree.hpp
new file mode 100644
index 0000000000..f0c85ff403
--- /dev/null
+++ b/sca-cpp/trunk/kernel/tree.hpp
@@ -0,0 +1,125 @@
+/*
+ * 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_tree_hpp
+#define tuscany_tree_hpp
+
+/**
+ * Functions to work with trees.
+ */
+
+#include <iostream>
+#include <string>
+#include "function.hpp"
+#include "list.hpp"
+#include "monad.hpp"
+#include "value.hpp"
+
+namespace tuscany {
+
+/**
+ * Make a tree from a leaf and two branches.
+ */
+template<typename T> const list<T> mktree(const T& e, const list<T>& left, const list<T>& right) {
+ return mklist<T>(e, left, right);
+}
+
+/**
+ * Find a leaf with the given key in a tree.
+ */
+template<typename T> const list<T> assoctree(const T& k, const list<T>& tree) {
+ if (isNil(tree))
+ return tree;
+ if (k == car<T>(car(tree)))
+ return car(tree);
+ if (k < car<T>(car(tree)))
+ return assoctree<T>(k, cadr(tree));
+ return assoctree<T>(k, caddr(tree));
+}
+
+/**
+ * Construct a new tree from a leaf and a tree.
+ */
+template<typename T> const list<T> constree(const T& e, const list<T>& tree) {
+ if (isNil(tree))
+ return mktree(e, list<T>(), list<T>());
+ if (e == car(tree))
+ return tree;
+ if (e < car(tree))
+ return mktree<T>(car(tree), constree<T>(e, cadr(tree)), caddr(tree));
+ return mktree<T>(car(tree), cadr(tree), constree<T>(e, caddr(tree)));
+}
+
+/**
+ * Make a tree from an unordered list of leaves.
+ */
+template<typename T> const list<T> mktree(const list<T>& l) {
+ if (isNil(l))
+ return l;
+ return constree(car(l), mktree(cdr(l)));
+}
+
+/**
+ * Convert a tree to an ordered list of leaves.
+ */
+template<typename T> const list<T> flatten(const list<T>& tree) {
+ if (isNil(tree))
+ return tree;
+ return append<T>(flatten<T>(cadr(tree)), cons<T>(car(tree), flatten<T>(caddr(tree))));
+}
+
+/**
+ * Sort a list.
+ */
+template<typename T> const list<T> sort(const list<T>& l) {
+ return flatten(mktree(l));
+}
+
+/**
+ * Make a balanced tree from an ordered list of leaves.
+ */
+template<typename T> const list<T> btreeHelper(const list<T>& elements, const int n) {
+ if (n == 0)
+ return cons<T>(list<T>(), elements);
+ const int leftSize = (n - 1) / 2; {
+ const list<T> leftResult = btreeHelper<T>(elements, leftSize); {
+ const list<T> leftTree = car(leftResult);
+ const list<T> nonLeftElements = cdr(leftResult);
+ const int rightSize = n - (leftSize + 1); {
+ const T thisEntry = car(nonLeftElements);
+ const list<T> rightResult = btreeHelper<T>(cdr(nonLeftElements), rightSize); {
+ const list<T> rightTree = car(rightResult);
+ const list<T> remainingElements = cdr(rightResult); {
+ return cons<T>(mktree<T>(thisEntry, leftTree, rightTree), remainingElements);
+ }
+ }
+ }
+ }
+ }
+}
+
+template<typename T> const list<T> mkbtree(const list<T>& elements) {
+ return car(btreeHelper<T>(elements, length(elements)));
+}
+
+}
+
+#endif /* tuscany_tree_hpp */
diff --git a/sca-cpp/trunk/kernel/value.hpp b/sca-cpp/trunk/kernel/value.hpp
index a99309869f..e767ead74b 100644
--- a/sca-cpp/trunk/kernel/value.hpp
+++ b/sca-cpp/trunk/kernel/value.hpp
@@ -32,6 +32,7 @@
#include "gc.hpp"
#include "function.hpp"
#include "list.hpp"
+#include "monad.hpp"
#include "debug.hpp"
namespace tuscany
@@ -40,7 +41,9 @@ namespace tuscany
#ifdef _DEBUG
/**
- * Debug counters.
+ * Debug utilities. Counters used to track instances of values, and
+ * macro used to write the contents of a value in a string, easier to
+ * watch in a debugger than the value itself.
*/
long int countValues = 0;
long int countEValues = 0;
@@ -64,12 +67,18 @@ bool printValueCounters() {
return true;
}
+#define debug_watchValue() do { \
+ this->watch = watchValue(*this); \
+ } while (0)
+
#else
#define resetValueCounters()
#define checkValueCounters() true
#define printValueCounters()
+#define debug_watchValue()
+
#endif
class value;
@@ -85,6 +94,7 @@ public:
type(value::Undefined) {
debug_inc(countValues);
debug_inc(countEValues);
+ debug_watchValue();
}
value(const value& v) {
@@ -113,6 +123,9 @@ public:
default:
break;
}
+#ifdef _DEBUG
+ watch = v.watch;
+#endif
}
const value& operator=(const value& v) {
@@ -141,6 +154,9 @@ public:
default:
break;
}
+#ifdef _DEBUG
+ watch = v.watch;
+#endif
return *this;
}
@@ -148,70 +164,84 @@ public:
debug_dec(countValues);
}
- value(const lambda<value(list<value>&)>& func) :
- type(value::Lambda), data(vdata(func)) {
+ value(const lambda<value(const list<value>&)>& func) : type(value::Lambda), data(vdata(func)) {
debug_inc(countValues);
debug_inc(countVValues);
+ debug_watchValue();
}
- value(const std::string& str) :
- type(value::String), data(vdata(result(str))) {
+ value(const std::string& str) : type(value::String), data(vdata(result(str))) {
debug_inc(countValues);
debug_inc(countVValues);
+ debug_watchValue();
}
- value(const char* str) :
- type(value::Symbol), data(vdata(result(std::string(str)))) {
+ value(const char* str) : type(value::Symbol), data(vdata(result(std::string(str)))) {
debug_inc(countValues);
debug_inc(countVValues);
+ debug_watchValue();
}
- value(const list<value>& lst) :
- type(value::List), data(vdata(result(lst))) {
+ value(const list<value>& lst) : type(value::List), data(vdata(result(lst))) {
debug_inc(countValues);
debug_inc(countVValues);
+ debug_watchValue();
}
- value(const list<list<value> >& l) :
- type(value::List), data(vdata(result(listOfValues(l)))) {
+ value(const list<list<value> >& l) : type(value::List), data(vdata(result(listOfValues(l)))) {
debug_inc(countValues);
debug_inc(countVValues);
+ debug_watchValue();
}
- value(const double num) :
- type(value::Number), data(vdata(result(num))) {
+ value(const double num) : type(value::Number), data(vdata(result(num))) {
debug_inc(countValues);
debug_inc(countVValues);
+ debug_watchValue();
}
- value(const int num) :
- type(value::Number), data(vdata(result((double)num))) {
+ value(const int num) : type(value::Number), data(vdata(result((double)num))) {
debug_inc(countValues);
debug_inc(countVValues);
+ debug_watchValue();
}
- value(const bool boo) :
- type(value::Bool), data(vdata(result(boo))) {
+ value(const bool boo) : type(value::Bool), data(vdata(result(boo))) {
debug_inc(countValues);
debug_inc(countVValues);
+ debug_watchValue();
}
- value(const char chr) :
- type(value::Char), data(vdata(result(chr))) {
+ value(const char chr) : type(value::Char), data(vdata(result(chr))) {
debug_inc(countValues);
debug_inc(countVValues);
+ debug_watchValue();
}
- value(const gc_ptr<value> ptr) :
- type(value::Ptr), data(vdata(result(ptr))) {
+ value(const gc_ptr<value> ptr) : type(value::Ptr), data(vdata(result(ptr))) {
debug_inc(countValues);
debug_inc(countVValues);
+ debug_watchValue();
}
- value(const gc_pool_ptr<value> ptr) :
- type(value::PoolPtr), data(vdata(result(ptr))) {
+ value(const gc_pool_ptr<value> ptr) : type(value::PoolPtr), data(vdata(result(ptr))) {
debug_inc(countValues);
debug_inc(countVValues);
+ debug_watchValue();
+ }
+
+ value(const failable<value, std::string>& m) : type(value::List),
+ data(vdata(result(hasContent(m)? mklist<value>(content(m)) : mklist<value>(value(), reason(m))))) {
+ debug_inc(countValues);
+ debug_inc(countVValues);
+ debug_watchValue();
+ }
+
+ value(const maybe<value>& m) : type(value::List),
+ data(vdata(result(hasContent(m)? mklist<value>(content(m)) : list<value>()))) {
+ debug_inc(countValues);
+ debug_inc(countVValues);
+ debug_watchValue();
}
const bool operator!=(const value& v) const {
@@ -221,35 +251,75 @@ public:
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()();
+ return v.type == value::List && lst()() == v.lst()();
case value::Lambda:
- return func() == v.func();
+ return v.type == value::Lambda && func() == v.func();
case value::Symbol:
- return str()() == v.str()();
+ return str()() == (std::string)v;
case value::String:
- return str()() == v.str()();
+ return str()() == (std::string)v;
case value::Number:
- return num()() == v.num()();
+ return num()() == (double)v;
case value::Bool:
- return boo()() == v.boo()();
+ return boo()() == (bool)v;
case value::Char:
- return chr()() == v.chr()();
+ return chr()() == (char)v;
case value::Ptr:
- return ptr()() == v.ptr()();
+ return v.type == value::Ptr && ptr()() == v.ptr()();
case value::PoolPtr:
- return poolptr()() == v.poolptr()();
+ return v.type == value::PoolPtr && poolptr()() == v.poolptr()();
+ default:
+ return false;
+ }
+ }
+
+ const bool operator<(const value& v) const {
+ if(this == &v)
+ return false;
+ switch(type) {
+ case value::List:
+ return v.type == value::List && lst()() < v.lst()();
+ case value::Symbol:
+ case value::String:
+ return str()() < (std::string)v;
+ return str()() < (std::string)v;
+ case value::Bool:
+ return boo()() < (bool)v;
+ case value::Number:
+ return num()() < (double)v;
+ case value::Char:
+ return chr()() < (char)v;
+ default:
+ return false;
+ }
+ }
+
+ const bool operator>(const value& v) const {
+ if(this == &v)
+ return false;
+ switch(type) {
+ case value::List:
+ return v.type == value::List && lst()() > v.lst()();
+ case value::Symbol:
+ case value::String:
+ return str()() > (std::string)v;
+ return str()() > (std::string)v;
+ case value::Bool:
+ return boo()() > (bool)v;
+ case value::Number:
+ return num()() > (double)v;
+ case value::Char:
+ return chr()() > (char)v;
default:
return false;
}
}
- const value operator()(list<value>& args) const {
+ const value operator()(const list<value>& args) const {
return func()(args);
}
@@ -355,17 +425,12 @@ public:
return listOfListOfValues(lst()());
}
- operator const lambda<value(list<value>&)>() const {
+ operator const lambda<value(const 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 {
+ template<typename T> lambda<T>& vdata() const {
return *reinterpret_cast<lambda<T> *> (const_cast<lambda<char()> *> (&data));
}
@@ -401,8 +466,8 @@ private:
return vdata<list<value>()> ();
}
- lambda<value(list<value>&)>& func() const {
- return vdata<value(list<value>&)> ();
+ lambda<value(const list<value>&)>& func() const {
+ return vdata<value(const list<value>&)> ();
}
const list<value> listOfValues(const list<list<value> >& l) const {
@@ -417,8 +482,33 @@ private:
return cons<list<value> >(list<value>(car(l)), listOfListOfValues(cdr(l)));
}
+ friend std::ostream& operator<<(std::ostream&, const value&);
+ friend const value::ValueType type(const value& v);
+
+#ifdef _DEBUG
+ friend const std::string watchValue(const value& v);
+ std::string watch;
+#endif
+
+ ValueType type;
+ lambda<char()> data;
};
+#ifdef _DEBUG
+
+/**
+ * Debug utility used to write the contents of a value to a string, easier
+ * to watch than the value itself in a debugger.
+ */
+const std::string watchValue(const value& v) {
+ if (v.type == value::List)
+ return watchList<value>(v);
+ std::ostringstream os;
+ os << v;
+ return os.str();
+}
+#endif
+
/**
* Write a value to a stream.
*/
@@ -444,14 +534,14 @@ std::ostream& operator<<(std::ostream& out, const value& v) {
case value::Ptr: {
const gc_ptr<value> p = v.ptr()();
if (p == gc_ptr<value>(NULL))
- return out << "pointer::null";
- return out << "pointer::" << *p;
+ return out << "gc_ptr::null";
+ return out << "gc_ptr::" << 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;
+ return out << "pool_ptr::null";
+ return out << "pool_ptr::" << p;
}
default:
return out << "undefined";
@@ -468,71 +558,71 @@ const value::ValueType type(const value& v) {
/**
* Returns true if a value is nil.
*/
-const bool isNil(const value& value) {
- return value.type == value::Undefined;
+const bool isNil(const value& v) {
+ return type(v) == value::Undefined;
}
/**
* Returns true if a value is a lambda.
*/
-const bool isLambda(const value& value) {
- return value.type == value::Lambda;
+const bool isLambda(const value& v) {
+ return type(v) == value::Lambda;
}
/**
* Returns true if a value is a string.
*/
-const bool isString(const value& value) {
- return value.type == value::String;
+const bool isString(const value& v) {
+ return type(v) == value::String;
}
/**
* Returns true if a value is a symbol.
*/
-const bool isSymbol(const value& value) {
- return value.type == value::Symbol;
+const bool isSymbol(const value& v) {
+ return type(v) == value::Symbol;
}
/**
* Returns true if a value is a list.
*/
-const bool isList(const value& value) {
- return value.type == value::List;
+const bool isList(const value& v) {
+ return type(v) == value::List;
}
/**
* Returns true if a value is a number.
*/
-const bool isNumber(const value& value) {
- return value.type == value::Number;
+const bool isNumber(const value& v) {
+ return type(v) == value::Number;
}
/**
* Returns true if a value is a boolean.
*/
-const bool isBool(const value& value) {
- return value.type == value::Bool;
+const bool isBool(const value& v) {
+ return type(v) == value::Bool;
}
/**
* Returns true if a value is a character.
*/
-const bool isChar(const value& value) {
- return value.type == value::Char;
+const bool isChar(const value& v) {
+ return type(v) == value::Char;
}
/**
* Returns true if a value is a pointer.
*/
-const bool isPtr(const value& value) {
- return value.type == value::Ptr;
+const bool isPtr(const value& v) {
+ return type(v) == value::Ptr;
}
/**
* Returns true if a value is a pooled pointer.
*/
-const bool isPoolPtr(const value& value) {
- return value.type == value::PoolPtr;
+const bool isPoolPtr(const value& v) {
+ return type(v) == value::PoolPtr;
}
/**
diff --git a/sca-cpp/trunk/kernel/xml.hpp b/sca-cpp/trunk/kernel/xml.hpp
index 4b4bcd098e..eee6e290d8 100644
--- a/sca-cpp/trunk/kernel/xml.hpp
+++ b/sca-cpp/trunk/kernel/xml.hpp
@@ -315,9 +315,9 @@ const failable<bool, std::string> write(const list<value>& l, const xmlTextWrite
*/
template<typename R> class XMLWriteContext {
public:
- XMLWriteContext(const lambda<R(std::string, R)>& reduce, const R& accum) : reduce(reduce), accum(accum) {
+ XMLWriteContext(const lambda<R(const std::string&, const R)>& reduce, const R& accum) : reduce(reduce), accum(accum) {
}
- const lambda<R(std::string, R)> reduce;
+ const lambda<R(const std::string&, const R)> reduce;
R accum;
};
@@ -333,7 +333,7 @@ template<typename R> int writeCallback(void *context, const char* buffer, int le
/**
* 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) {
+template<typename R> const failable<R, std::string> writeXML(const lambda<R(const std::string&, const 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)
diff --git a/sca-cpp/trunk/modules/atom/atom.hpp b/sca-cpp/trunk/modules/atom/atom.hpp
index 22489fd1d1..7e2eb66cd2 100644
--- a/sca-cpp/trunk/modules/atom/atom.hpp
+++ b/sca-cpp/trunk/modules/atom/atom.hpp
@@ -115,7 +115,7 @@ const list<value> entriesElements(const list<value>& l) {
* Convert a list of values representing an ATOM entry to an ATOM entry.
* The first two values in the list are the entry id and title.
*/
-template<typename R> const failable<R, std::string> writeATOMEntry(const lambda<R(std::string, R)>& reduce, const R& initial, const list<value>& l) {
+template<typename R> const failable<R, std::string> writeATOMEntry(const lambda<R(const std::string&, const R)>& reduce, const R& initial, const list<value>& l) {
return writeXML<R>(reduce, initial, mklist<value>(entryElement(l)));
}
@@ -130,7 +130,7 @@ const failable<list<std::string>, std::string> writeATOMEntry(const list<value>&
* Convert a list of values representing an ATOM feed to an ATOM feed.
* The first two values in the list are the feed id and title.
*/
-template<typename R> const failable<R, std::string> writeATOMFeed(const lambda<R(std::string, R)>& reduce, const R& initial, const list<value>& l) {
+template<typename R> const failable<R, std::string> writeATOMFeed(const lambda<R(const std::string&, const R)>& reduce, const R& initial, const list<value>& l) {
const list<value> f = list<value>()
<< element << "feed" << (list<value>() << attribute << "xmlns" << "http://www.w3.org/2005/Atom")
<< (list<value>() << element << "title" << (list<value>() << attribute << "type" << "text") << car(l))
diff --git a/sca-cpp/trunk/modules/http/curl.hpp b/sca-cpp/trunk/modules/http/curl.hpp
index fd2e9857d1..85665c2785 100644
--- a/sca-cpp/trunk/modules/http/curl.hpp
+++ b/sca-cpp/trunk/modules/http/curl.hpp
@@ -35,6 +35,7 @@
#include "value.hpp"
#include "element.hpp"
#include "monad.hpp"
+#include "parallel.hpp"
#include "../atom/atom.hpp"
#include "../json/json.hpp"
@@ -126,9 +127,9 @@ size_t readCallback(void *ptr, size_t size, size_t nmemb, void *data) {
*/
template<typename R> class CURLWriteContext {
public:
- CURLWriteContext(const lambda<R(std::string, R)>& reduce, const R& accum) : reduce(reduce), accum(accum) {
+ CURLWriteContext(const lambda<R(const std::string&, const R)>& reduce, const R& accum) : reduce(reduce), accum(accum) {
}
- const lambda<R(std::string, R)> reduce;
+ const lambda<R(const std::string&, const R)> reduce;
R accum;
};
@@ -162,7 +163,7 @@ curl_slist* headers(curl_slist* cl, const list<std::string>& h) {
return headers(curl_slist_append(cl, std::string(car(h)).c_str()), cdr(h));
}
-template<typename R> const failable<list<R>, std::string> apply(const list<list<std::string> >& req, const lambda<R(std::string, R)>& reduce, const R& initial, const std::string& url, const std::string& verb, const CURLSession& cs) {
+template<typename R> const failable<list<R>, std::string> apply(const list<list<std::string> >& req, const lambda<R(const std::string&, const R)>& reduce, const R& initial, const std::string& url, const std::string& verb, const CURLSession& cs) {
// Init the curl session
CURL* ch = handle(cs);
@@ -174,8 +175,6 @@ template<typename R> const failable<list<R>, std::string> apply(const list<list<
write(cadr(req), os);
const std::string s = os.str();
const int sz = s.length();
- if (sz < 1400)
- curl_easy_setopt(ch, CURLOPT_TCP_NODELAY, true);
// Setup the read, header and write callbacks
CURLReadContext rcx(mklist(s));
@@ -187,6 +186,7 @@ template<typename R> const failable<list<R>, std::string> apply(const list<list<
CURLWriteContext<R> wcx(reduce, initial);
curl_easy_setopt(ch, CURLOPT_WRITEFUNCTION, (size_t (*)(void*, size_t, size_t, void*))writeCallback<R>);
curl_easy_setopt(ch, CURLOPT_WRITEDATA, &wcx);
+ curl_easy_setopt(ch, CURLOPT_TCP_NODELAY, true);
// Set the request headers
curl_slist* hl = headers(NULL, car(req));
@@ -291,7 +291,7 @@ const failable<std::string, std::string> contentType(const list<std::string>& h)
/**
* HTTP GET, return the resource at the given URL.
*/
-template<typename R> const failable<list<R>, std::string> get(const lambda<R(std::string, R)>& reduce, const R& initial, const std::string& url, const CURLSession& ch) {
+template<typename R> const failable<list<R>, std::string> get(const lambda<R(const std::string&, const R)>& reduce, const R& initial, const std::string& url, const CURLSession& ch) {
debug(url, "http::get::url");
const list<list<std::string> > req = mklist(list<std::string>(), list<std::string>());
return apply(req, reduce, initial, url, "GET", ch);
@@ -391,18 +391,18 @@ const failable<value, std::string> del(const std::string& url, const CURLSession
* HTTP client proxy function.
*/
struct proxy {
- proxy(const std::string& url, const CURLSession& ch) : url(url), ch(ch) {
+ proxy(const std::string& url) : url(url) {
}
const value operator()(const list<value>& args) const {
- failable<value, std::string> val = evalExpr(args, url, ch);
+ CURLSession cs;
+ failable<value, std::string> val = evalExpr(args, url, cs);
if (!hasContent(val))
return value();
return content(val);
}
const std::string url;
- const CURLSession ch;
};
}
diff --git a/sca-cpp/trunk/modules/json/json.hpp b/sca-cpp/trunk/modules/json/json.hpp
index 7d9bba564e..6ce4e3a9a1 100644
--- a/sca-cpp/trunk/modules/json/json.hpp
+++ b/sca-cpp/trunk/modules/json/json.hpp
@@ -332,10 +332,10 @@ const failable<bool, std::string> writeList(const list<value>& l, JSObject* o, c
*/
template<typename R> class WriteContext {
public:
- WriteContext(const lambda<R(std::string, R)>& reduce, const R& accum, const JSONContext& cx) : cx(cx), reduce(reduce), accum(accum) {
+ WriteContext(const lambda<R(const std::string&, const R)>& reduce, const R& accum, const JSONContext& cx) : cx(cx), reduce(reduce), accum(accum) {
}
const JSONContext& cx;
- const lambda<R(std::string, R)> reduce;
+ const lambda<R(const std::string&, const R)> reduce;
R accum;
};
@@ -352,7 +352,7 @@ template<typename R> JSBool writeCallback(const jschar *buf, uint32 len, void *d
/**
* Convert a list of values to a JSON document.
*/
-template<typename R> const failable<R, std::string> writeJSON(const lambda<R(std::string, R)>& reduce, const R& initial, const list<value>& l, const JSONContext& cx) {
+template<typename R> const failable<R, std::string> writeJSON(const lambda<R(const std::string&, const R)>& reduce, const R& initial, const list<value>& l, const JSONContext& cx) {
JSObject* o = JS_NewObject(cx, NULL, NULL, NULL);
jsval val = OBJECT_TO_JSVAL(o);
const failable<bool, std::string> w = writeList(l, o, cx);