summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rwxr-xr-xcpp/sca/etc/memgrind (renamed from cpp/sca/etc/valgrind.sh)2
-rw-r--r--cpp/sca/kernel/Makefile.am6
-rw-r--r--cpp/sca/kernel/element.hpp6
-rw-r--r--cpp/sca/kernel/function.hpp22
-rw-r--r--cpp/sca/kernel/gc.hpp135
-rw-r--r--cpp/sca/kernel/kernel-test.cpp12
-rw-r--r--cpp/sca/kernel/list.hpp29
-rw-r--r--cpp/sca/kernel/value.hpp108
-rw-r--r--cpp/sca/kernel/xml.hpp38
-rw-r--r--cpp/sca/modules/atom/Makefile.am4
-rw-r--r--cpp/sca/modules/eval/Makefile.am6
-rw-r--r--cpp/sca/modules/eval/driver.hpp12
-rw-r--r--cpp/sca/modules/eval/environment.hpp49
-rw-r--r--cpp/sca/modules/eval/eval-test.cpp13
-rw-r--r--cpp/sca/modules/eval/eval.hpp56
-rw-r--r--cpp/sca/modules/eval/primitive.hpp16
-rw-r--r--cpp/sca/modules/http/Makefile.am6
-rw-r--r--cpp/sca/modules/json/Makefile.am4
-rw-r--r--cpp/sca/test/store-function/Makefile.am4
-rw-r--r--cpp/sca/test/store-object/Makefile.am4
-rw-r--r--cpp/sca/test/store-script/Makefile.am6
-rw-r--r--cpp/sca/test/store-script/store-script-test.cpp34
22 files changed, 424 insertions, 148 deletions
diff --git a/cpp/sca/etc/valgrind.sh b/cpp/sca/etc/memgrind
index 16acd91427..1a220cd5d2 100755
--- a/cpp/sca/etc/valgrind.sh
+++ b/cpp/sca/etc/memgrind
@@ -19,5 +19,5 @@
# Run valgrind to analyze memory usage and track memory leaks
-valgrind --tool=memcheck --leak-check=yes --show-reachable=yes --num-callers=20 --track-fds=yes $* >valgrind.txt 2>&1
+valgrind --tool=memcheck --leak-check=yes --show-reachable=yes --num-callers=20 --track-fds=yes $* 2>&1 | tee memgrind.log
diff --git a/cpp/sca/kernel/Makefile.am b/cpp/sca/kernel/Makefile.am
index d3caa16b3b..0bbfa195c7 100644
--- a/cpp/sca/kernel/Makefile.am
+++ b/cpp/sca/kernel/Makefile.am
@@ -19,13 +19,13 @@ noinst_PROGRAMS = kernel-test xsd-test
nobase_include_HEADERS = *.hpp
-INCLUDES = -I. -I$(top_builddir)/kernel -I${LIBXML2_INCLUDE}
+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
+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
+xsd_test_LDADD = -lpthread -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1
TESTS = kernel-test
diff --git a/cpp/sca/kernel/element.hpp b/cpp/sca/kernel/element.hpp
index af221f849b..d93e90742b 100644
--- a/cpp/sca/kernel/element.hpp
+++ b/cpp/sca/kernel/element.hpp
@@ -219,19 +219,19 @@ struct selectorLambda {
const list<value> select;
selectorLambda(const list<value>& s) : select(s) {
}
- const bool evalApply(const list<value>& s, const list<value> v) const {
+ const bool evalExpr(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 evalApply(cdr(s), cdr(v));
+ return evalExpr(cdr(s), cdr(v));
}
const bool operator()(const value& v) const {
if (!isList(v))
return false;
- return evalApply(select, v);
+ return evalExpr(select, v);
}
};
diff --git a/cpp/sca/kernel/function.hpp b/cpp/sca/kernel/function.hpp
index 9492879e5e..c99ee5dbad 100644
--- a/cpp/sca/kernel/function.hpp
+++ b/cpp/sca/kernel/function.hpp
@@ -64,8 +64,6 @@ bool printLambdaCounters() {
template<typename R, typename... P> class Callable {
public:
- unsigned int refCount;
-
Callable() : refCount(0) {
}
@@ -76,14 +74,6 @@ public:
virtual ~Callable() {
}
- unsigned int acquire() {
- return __sync_add_and_fetch(&refCount, 1);
- }
-
- unsigned int release() {
- return __sync_sub_and_fetch(&refCount, 1);
- }
-
template<typename F> class Proxy: public Callable {
public:
Proxy(const F& f) : function(f) {
@@ -112,6 +102,18 @@ public:
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;
diff --git a/cpp/sca/kernel/gc.hpp b/cpp/sca/kernel/gc.hpp
index 0d292f6194..7739e714c2 100644
--- a/cpp/sca/kernel/gc.hpp
+++ b/cpp/sca/kernel/gc.hpp
@@ -26,6 +26,8 @@
* Garbage collected pointer.
*/
+#include <apr_general.h>
+#include <apr_pools.h>
#include <iostream>
namespace tuscany
@@ -265,5 +267,138 @@ template<typename T> std::ostream& operator<<(std::ostream& out, const gc_counti
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/cpp/sca/kernel/kernel-test.cpp b/cpp/sca/kernel/kernel-test.cpp
index 9f977a64f9..0234f6eb3e 100644
--- a/cpp/sca/kernel/kernel-test.cpp
+++ b/cpp/sca/kernel/kernel-test.cpp
@@ -152,7 +152,7 @@ bool testOut() {
std::ostringstream os2;
os2 << mklist(1, 2, 3);
- assert(os2.str() == "(1, 2, 3)");
+ assert(os2.str() == "(1 2 3)");
return true;
}
@@ -334,6 +334,14 @@ bool testValue() {
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;
}
@@ -521,7 +529,7 @@ bool testReadXML() {
return true;
}
-std::ostringstream* xmlWriter(std::ostringstream* os, const std::string& s) {
+std::ostringstream* xmlWriter(const std::string& s, std::ostringstream* os) {
(*os) << s;
return os;
}
diff --git a/cpp/sca/kernel/list.hpp b/cpp/sca/kernel/list.hpp
index 62c5d91150..deb4414d98 100644
--- a/cpp/sca/kernel/list.hpp
+++ b/cpp/sca/kernel/list.hpp
@@ -144,7 +144,7 @@ template<typename T> std::ostream& operator<<(std::ostream& out, const list<T>&
ml = cdr(ml);
if (isNil(ml))
break;
- out << ", ";
+ out << " ";
}
return out << ")";
}
@@ -164,6 +164,17 @@ template<typename T> const list<T> cons(const T& car, const list<T>& 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 from a single value.
*/
template<typename T> const list<T> cons(const T& car) {
@@ -350,6 +361,22 @@ template<typename T, typename R> const R reduce(const lambda<R(R, T)>& f, const
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.
*/
diff --git a/cpp/sca/kernel/value.hpp b/cpp/sca/kernel/value.hpp
index d57264ff43..618bd7b622 100644
--- a/cpp/sca/kernel/value.hpp
+++ b/cpp/sca/kernel/value.hpp
@@ -60,7 +60,7 @@ class value {
public:
enum ValueType {
- Undefined, Symbol, String, List, Number, Boolean, Character, Lambda
+ Undefined, Symbol, String, List, Number, Bool, Char, Lambda, Ptr, PoolPtr
};
value() :
@@ -84,10 +84,14 @@ public:
str() = v.str();
case value::Number:
num() = v.num();
- case value::Boolean:
+ case value::Bool:
boo() = v.boo();
- case value::Character:
+ case value::Char:
chr() = v.chr();
+ case value::Ptr:
+ ptr() = v.ptr();
+ case value::PoolPtr:
+ poolptr() = v.poolptr();
default:
break;
}
@@ -108,10 +112,14 @@ public:
str() = v.str();
case value::Number:
num() = v.num();
- case value::Boolean:
+ case value::Bool:
boo() = v.boo();
- case value::Character:
+ case value::Char:
chr() = v.chr();
+ case value::Ptr:
+ ptr() = v.ptr();
+ case value::PoolPtr:
+ poolptr() = v.poolptr();
default:
break;
}
@@ -165,13 +173,25 @@ public:
}
value(const bool boo) :
- type(value::Boolean), data(vdata(result(boo))) {
+ type(value::Bool), data(vdata(result(boo))) {
countValues++;
countVValues++;
}
value(const char chr) :
- type(value::Character), data(vdata(result(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++;
}
@@ -198,10 +218,14 @@ public:
return str()() == v.str()();
case value::Number:
return num()() == v.num()();
- case value::Boolean:
+ case value::Bool:
return boo()() == v.boo()();
- case value::Character:
+ case value::Char:
return chr()() == v.chr()();
+ case value::Ptr:
+ return ptr()() == v.ptr()();
+ case value::PoolPtr:
+ return poolptr()() == v.poolptr()();
default:
return false;
}
@@ -215,6 +239,8 @@ public:
switch(type) {
case value::List:
case value::Lambda:
+ case value::Ptr:
+ case value::PoolPtr:
return "";
case value::Symbol:
case value::String:
@@ -224,13 +250,13 @@ public:
sos << num()();
return sos.str();
}
- case value::Boolean: {
+ case value::Bool: {
if(boo()())
return "true";
else
return "false";
}
- case value::Character: {
+ case value::Char: {
std::ostringstream sos;
sos << chr()();
return sos.str();
@@ -256,6 +282,14 @@ public:
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()();
}
@@ -294,6 +328,14 @@ private:
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()> ();
}
@@ -328,18 +370,30 @@ std::ostream& operator<<(std::ostream& out, const value& v) {
case value::Lambda:
return out << "lambda::" << v.func();
case value::Symbol:
- return out << "symbol::" << v.str()();
+ return out << v.str()();
case value::String:
- return out << "string::" << '\"' << v.str()() << '\"';
+ return out << '\"' << v.str()() << '\"';
case value::Number:
- return out << "number::" << v.num()();
- case value::Boolean:
+ return out << v.num()();
+ case value::Bool:
if(v.boo()())
- return out << "bool::" << "true";
+ return out << "true";
else
- return out << "bool::" << "false";
- case value::Character:
- return out << "char::" << v.chr()();
+ 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";
}
@@ -369,12 +423,20 @@ const bool isNumber(const value& value) {
return value.type == value::Number;
}
-const bool isBoolean(const value& value) {
- return value.type == value::Boolean;
+const bool isBool(const value& value) {
+ return value.type == value::Bool;
+}
+
+const bool isChar(const value& value) {
+ return value.type == value::Char;
+}
+
+const bool isPtr(const value& value) {
+ return value.type == value::Ptr;
}
-const bool isCharacter(const value& value) {
- return value.type == value::Character;
+const bool isPoolPtr(const value& value) {
+ return value.type == value::PoolPtr;
}
const bool isTaggedList(const value& exp, value tag) {
diff --git a/cpp/sca/kernel/xml.hpp b/cpp/sca/kernel/xml.hpp
index afc3f5cc38..b7611b8477 100644
--- a/cpp/sca/kernel/xml.hpp
+++ b/cpp/sca/kernel/xml.hpp
@@ -40,6 +40,22 @@
namespace tuscany {
/**
+ * Initializes the libxml2 library.
+ */
+class XMLParser {
+public:
+ XMLParser() {
+ xmlInitParser();
+ }
+
+ ~XMLParser() {
+ xmlCleanupParser();
+ }
+};
+
+XMLParser xmlParser;
+
+/**
* Encapsulates a libxml2 xmlTextReader and its state.
*/
class XMLReader {
@@ -54,6 +70,7 @@ public:
}
~XMLReader() {
+ xmlTextReaderClose(xml);
xmlFreeTextReader(xml);
}
@@ -298,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(R, std::string)>& reduce, const R& accum) : reduce(reduce), accum(accum) {
+ XMLWriteContext(const lambda<R(std::string, R)>& reduce, const R& accum) : reduce(reduce), accum(accum) {
}
- const lambda<R(R, std::string)> reduce;
+ const lambda<R(std::string, R)> reduce;
R accum;
};
@@ -309,36 +326,35 @@ public:
*/
template<typename R> int writeCallback(void *context, const char* buffer, int len) {
XMLWriteContext<R>& cx = *static_cast<XMLWriteContext<R>*>(context);
- cx.accum = cx.reduce(cx.accum, std::string(buffer, len));
+ 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(R, std::string)>& reduce, const R& initial, const list<value>& l) {
+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 std::string("xmlOutputBufferCreateIO failed");
xmlTextWriterPtr xml = xmlNewTextWriter(out);
if (xml == NULL)
return std::string("xmlNewTextWriter failed");
const failable<bool, std::string> w = write(l, xml);
- if (!hasValue(w))
+ xmlFreeTextWriter(xml);
+ if (!hasValue(w)) {
return std::string(w);
-
+ }
return cx.accum;
}
/**
* Convert a list of values to a list of strings representing an XML document.
*/
-const list<std::string> writeXMLList(const list<std::string>& listSoFar, const std::string& s) {
- return cons(s, listSoFar);
-}
-
const failable<list<std::string>, std::string> writeXML(const list<value>& l) {
- const failable<list<std::string>, std::string> ls = writeXML<list<std::string> >(writeXMLList, list<std::string>(), 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));
diff --git a/cpp/sca/modules/atom/Makefile.am b/cpp/sca/modules/atom/Makefile.am
index 5373587c43..2e4eb4b89f 100644
--- a/cpp/sca/modules/atom/Makefile.am
+++ b/cpp/sca/modules/atom/Makefile.am
@@ -17,10 +17,10 @@
noinst_PROGRAMS = atom-test
-INCLUDES = -I. -I$(top_builddir)/kernel -I${LIBXML2_INCLUDE}
+INCLUDES = -I. -I$(top_builddir)/kernel -I${LIBXML2_INCLUDE} -I${APR_INCLUDE}
atom_test_SOURCES = atom-test.cpp
-atom_test_LDADD = -lpthread -L${LIBXML2_LIB} -lxml2
+atom_test_LDADD = -lpthread -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1
TESTS = atom-test
diff --git a/cpp/sca/modules/eval/Makefile.am b/cpp/sca/modules/eval/Makefile.am
index b9fa9f8f56..b6b85c6965 100644
--- a/cpp/sca/modules/eval/Makefile.am
+++ b/cpp/sca/modules/eval/Makefile.am
@@ -20,13 +20,13 @@ noinst_PROGRAMS = eval-test eval-shell
datadir=$(prefix)/modules/eval
nobase_data_DATA = *.xsd
-INCLUDES = -I. -I$(top_builddir)/kernel -I${LIBXML2_INCLUDE}
+INCLUDES = -I. -I$(top_builddir)/kernel -I${LIBXML2_INCLUDE} -I${APR_INCLUDE}
eval_test_SOURCES = eval-test.cpp
-eval_test_LDADD = -lpthread -L${LIBXML2_LIB} -lxml2
+eval_test_LDADD = -lpthread -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1
eval_shell_SOURCES = eval-shell.cpp
-eval_shell_LDADD = -lpthread -L${LIBXML2_LIB} -lxml2
+eval_shell_LDADD = -lpthread -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1
TESTS = eval-test
diff --git a/cpp/sca/modules/eval/driver.hpp b/cpp/sca/modules/eval/driver.hpp
index 064213706c..f777973ebf 100644
--- a/cpp/sca/modules/eval/driver.hpp
+++ b/cpp/sca/modules/eval/driver.hpp
@@ -53,21 +53,23 @@ const bool userPrint(std::ostream& out, const value object) {
return true;
}
-const value evalDriverLoop(std::istream& in, std::ostream& out, Env& globalEnv) {
+const value evalDriverLoop(std::istream& in, std::ostream& out, Env& globalEnv, const gc_pool& pool) {
promptForInput(out, evalInputPrompt);
value input = read(in);
if (isNil(input))
return input;
- const value output = evalApply(input, globalEnv);
+ const value output = evalExpr(input, globalEnv, pool);
announceOutput(out, evalOutputPrompt);
userPrint(out, output);
- return evalDriverLoop(in, out, globalEnv);
+ return evalDriverLoop(in, out, globalEnv, pool);
}
const bool evalDriverRun(std::istream& in, std::ostream& out) {
+ gc_pool pool;
setupEvalOut(out);
- Env globalEnv = setupEnvironment();
- evalDriverLoop(in, out, globalEnv);
+ Env globalEnv = setupEnvironment(pool);
+ evalDriverLoop(in, out, globalEnv, pool);
+ cleanupEnvironment(globalEnv);
return true;
}
diff --git a/cpp/sca/modules/eval/environment.hpp b/cpp/sca/modules/eval/environment.hpp
index e0da9096fe..90a1d88854 100644
--- a/cpp/sca/modules/eval/environment.hpp
+++ b/cpp/sca/modules/eval/environment.hpp
@@ -34,7 +34,7 @@
namespace tuscany {
namespace eval {
-typedef list<value> Frame;
+typedef value Frame;
typedef list<value> Env;
const value trueSymbol("true");
@@ -63,7 +63,7 @@ const Env enclosingEnvironment(const Env& env) {
return cdr(env);
}
-const value firstFrame(const Env& env) {
+const gc_pool_ptr<Frame> firstFrame(const Env& env) {
return car(env);
}
@@ -101,9 +101,10 @@ const Frame makeBinding(const Frame& frameSoFar, const list<value>& variables, c
return makeBinding(newFrame, cdr(variables), cdr(values));
}
-const Frame makeFrame(const list<value>& variables, const list<value> values) {
- const Frame emptyFrame = cons(value(list<value>()), list<value>());
- return makeBinding(emptyFrame, variables, values);
+const gc_pool_ptr<Frame> makeFrame(const list<value>& variables, const list<value> values, const gc_pool& pool) {
+ gc_pool_ptr<Frame> frame = gc_pool_new<Frame>(pool);
+ *frame = value(makeBinding(cons(value(list<value>()), list<value>()), variables, values));
+ return frame;
}
const value definitionVariable(const value& exp) {
@@ -130,40 +131,34 @@ const value assignmentValue(const value& exp) {
return car(cdr(cdr((list<value> )exp)));
}
-const bool addBindingToFrame(const value& var, const value& val, Frame& frame) {
- //frame = cons(value(cons(var, frameVariables(frame))), cons(val, frameValues(frame)));
- setCar(frame, (value)cons(var, frameVariables(frame)));
- setCdr(frame, cons(val, frameValues(frame)));
- return true;
+const Frame addBindingToFrame(const value& var, const value& val, const Frame& frame) {
+ return cons(value(cons(var, frameVariables(frame))), cons(val, frameValues(frame)));
}
const bool defineVariable(const value& var, const value& val, Env& env) {
- Frame frame = firstFrame(env);
- addBindingToFrame(var, val, frame);
- setCar(env, value(frame));
+ *firstFrame(env) = addBindingToFrame(var, val, *firstFrame(env));
return true;
}
-struct environmentReference {
- const Env env;
- environmentReference(const Env& env) : env(env) {
- }
- const Env& operator()() const {
- return env;
- }
-};
-
-const Env extendEnvironment(const list<value>& vars, const list<value>& vals, const Env& baseEnv) {
- return cons(value(makeFrame(vars, vals)), lambda<list<value>()>(environmentReference(baseEnv)));
+const Env extendEnvironment(const list<value>& vars, const list<value>& vals, const Env& baseEnv, const gc_pool& pool) {
+ return cons<value>(makeFrame(vars, vals, pool), baseEnv);
}
-const Env setupEnvironment() {
- Env env = extendEnvironment(primitiveProcedureNames(), primitiveProcedureObjects(), theEmptyEnvironment());
+const Env setupEnvironment(const gc_pool& pool) {
+ Env env = extendEnvironment(primitiveProcedureNames(), primitiveProcedureObjects(), theEmptyEnvironment(), pool);
defineVariable(trueSymbol, true, env);
defineVariable(falseSymbol, false, env);
return env;
}
+const bool cleanupEnvironment(Env& env) {
+ if (isNil(env))
+ return true;
+ *firstFrame(env) = list<value>();
+ Env enclosing = enclosingEnvironment(env);
+ return cleanupEnvironment(enclosing);
+}
+
const value lookupEnvLoop(const value& var, const Env& env);
const value lookupEnvScan(const value& var, const list<value>& vars, const list<value>& vals, const Env& env) {
@@ -179,7 +174,7 @@ const value lookupEnvLoop(const value& var, const Env& env) {
std::cout << "Unbound variable " << var << "\n";
return value();
}
- return lookupEnvScan(var, frameVariables(firstFrame(env)), frameValues(firstFrame(env)), env);
+ return lookupEnvScan(var, frameVariables(*firstFrame(env)), frameValues(*firstFrame(env)), env);
}
const value lookupVariableValue(const value& var, const Env& env) {
diff --git a/cpp/sca/modules/eval/eval-test.cpp b/cpp/sca/modules/eval/eval-test.cpp
index 95a286ade0..584c8470b1 100644
--- a/cpp/sca/modules/eval/eval-test.cpp
+++ b/cpp/sca/modules/eval/eval-test.cpp
@@ -33,11 +33,13 @@ namespace tuscany {
namespace eval {
bool testEnv() {
+ gc_pool pool;
Env globalEnv = list<value>();
- Env env = extendEnvironment(mklist<value>("a"), mklist<value>(1), globalEnv);
+ Env env = extendEnvironment(mklist<value>("a"), mklist<value>(1), globalEnv, pool);
defineVariable("x", env, env);
- //assert(lookupVariableValue(value("x"), env) == env);
+ assert(lookupVariableValue(value("x"), env) == env);
assert(lookupVariableValue("a", env) == value(1));
+ cleanupEnvironment(env);
return true;
}
@@ -135,14 +137,15 @@ bool testEval() {
assert(contains(evalOutput(testSchemeBegin), "testBegin1 ok"));
assert(contains(evalOutput(testSchemeBegin), "testBegin2 ok"));
assert(contains(evalOutput(testSchemeLambda), "testLambda ok"));
- //assert(contains(evalOutput(testSchemeForward), "testForward ok"));
+ assert(contains(evalOutput(testSchemeForward), "testForward ok"));
return true;
}
bool testEvalExpr() {
+ gc_pool pool;
const value exp = mklist<value>("+", 2, 3);
- Env env = setupEnvironment();
- const value r = evalApply(exp, env);
+ Env env = setupEnvironment(pool);
+ const value r = evalExpr(exp, env, pool);
assert(r == value(5));
return true;
}
diff --git a/cpp/sca/modules/eval/eval.hpp b/cpp/sca/modules/eval/eval.hpp
index 1496c3bd09..78051c5a2b 100644
--- a/cpp/sca/modules/eval/eval.hpp
+++ b/cpp/sca/modules/eval/eval.hpp
@@ -36,7 +36,7 @@
namespace tuscany {
namespace eval {
-const value evalApply(const value& exp, Env& env);
+const value evalExpr(const value& exp, Env& env, const gc_pool& pool);
const value compoundProcedureSymbol("compound-procedure");
const value procedureSymbol("procedure");
@@ -86,10 +86,10 @@ const list<value> operands(const value& exp) {
return cdr((list<value> )exp);
}
-const list<value> listOfValues(const list<value> exps, Env& env) {
+const list<value> listOfValues(const list<value> exps, Env& env, const gc_pool& pool) {
if(isNil(exps))
return list<value> ();
- return cons(evalApply(car(exps), env), listOfValues(cdr(exps), env));
+ return cons(evalExpr(car(exps), env, pool), listOfValues(cdr(exps), env, pool));
}
const value applyOperat(const value& exp) {
@@ -132,19 +132,19 @@ const value makeBegin(const list<value> seq) {
return cons(beginSymbol, seq);
}
-const value evalSequence(const list<value>& exps, Env& env) {
+const value evalSequence(const list<value>& exps, Env& env, const gc_pool& pool) {
if(isLastExp(exps))
- return evalApply(firstExp(exps), env);
- evalApply(firstExp(exps), env);
- return evalSequence(restExp(exps), env);
+ return evalExpr(firstExp(exps), env, pool);
+ evalExpr(firstExp(exps), env, pool);
+ return evalSequence(restExp(exps), env, pool);
}
-const value applyProcedure(const value& procedure, list<value>& arguments) {
+const value applyProcedure(const value& procedure, list<value>& arguments, const gc_pool& pool) {
if(isPrimitiveProcedure(procedure))
return applyPrimitiveProcedure(procedure, arguments);
if(isCompoundProcedure(procedure)) {
- Env env = extendEnvironment(procedureParameters(procedure), arguments, procedureEnvironment(procedure));
- return evalSequence(procedureBody(procedure), env);
+ Env env = extendEnvironment(procedureParameters(procedure), arguments, procedureEnvironment(procedure), pool);
+ return evalSequence(procedureBody(procedure), env, pool);
}
std::cout << "Unknown procedure type " << procedure << "\n";
return value();
@@ -218,46 +218,52 @@ value condToIf(const value& exp) {
return expandClauses(condClauses(exp));
}
-value evalIf(const value& exp, Env& env) {
- if(isTrue(evalApply(ifPredicate(exp), env)))
- return evalApply(ifConsequent(exp), env);
- return evalApply(ifAlternative(exp), env);
+value evalIf(const value& exp, Env& env, const gc_pool& pool) {
+ if(isTrue(evalExpr(ifPredicate(exp), env, pool)))
+ return evalExpr(ifConsequent(exp), env, pool);
+ return evalExpr(ifAlternative(exp), env, pool);
}
-const value evalDefinition(const value& exp, Env& env) {
- defineVariable(definitionVariable(exp), evalApply(definitionValue(exp), env), env);
+const value evalDefinition(const value& exp, Env& env, const gc_pool& pool) {
+ defineVariable(definitionVariable(exp), evalExpr(definitionValue(exp), env, pool), env);
return definitionVariable(exp);
}
-const value evalApply(const value& exp, Env& env) {
+const value evalExpr(const value& exp, Env& env, const gc_pool& pool) {
if(isSelfEvaluating(exp))
return exp;
if(isQuoted(exp))
return textOfQuotation(exp);
if(isDefinition(exp))
- return evalDefinition(exp, env);
+ return evalDefinition(exp, env, pool);
if(isIf(exp))
- return evalIf(exp, env);
+ return evalIf(exp, env, pool);
if(isBegin(exp))
- return evalSequence(beginActions(exp), env);
+ return evalSequence(beginActions(exp), env, pool);
if(isCond(exp))
- return evalApply(condToIf(exp), env);
+ return evalExpr(condToIf(exp), env, pool);
if(isLambda(exp))
return makeProcedure(lambdaParameters(exp), lambdaBody(exp), env);
if(isVariable(exp))
return lookupVariableValue(exp, env);
if(isApply(exp)) {
- list<value> applyOperandValues = evalApply(applyOperand(exp), env);
- return applyProcedure(evalApply(applyOperat(exp), env), applyOperandValues);
+ list<value> applyOperandValues = evalExpr(applyOperand(exp), env, pool);
+ return applyProcedure(evalExpr(applyOperat(exp), env, pool), applyOperandValues, pool);
}
if(isApplication(exp)) {
- list<value> operandValues = listOfValues(operands(exp), env);
- return applyProcedure(evalApply(operat(exp), env), operandValues);
+ list<value> operandValues = listOfValues(operands(exp), env, pool);
+ return applyProcedure(evalExpr(operat(exp), env, pool), operandValues, pool);
}
std::cout << "Unknown expression type " << exp << "\n";
return value();
}
+const list<value> quotedParameters(const list<value>& p) {
+ if (isNil(p))
+ return p;
+ return cons<value>(mklist<value>(quoteSymbol, car(p)), quotedParameters(cdr(p)));
+}
+
}
}
#endif /* tuscany_eval_eval_hpp */
diff --git a/cpp/sca/modules/eval/primitive.hpp b/cpp/sca/modules/eval/primitive.hpp
index 4ca6ea900a..423e5af07b 100644
--- a/cpp/sca/modules/eval/primitive.hpp
+++ b/cpp/sca/modules/eval/primitive.hpp
@@ -26,6 +26,8 @@
* Script evaluator primitive functions.
*/
+#include <apr_general.h>
+#include <apr_uuid.h>
#include <iostream>
#include "function.hpp"
#include "list.hpp"
@@ -104,6 +106,14 @@ const value valueError(list<value>& args) {
return true;
}
+const value valueUuid(list<value>& args) {
+ apr_uuid_t uuid;
+ apr_uuid_get(&uuid);
+ char buf[APR_UUID_FORMATTED_LENGTH];
+ apr_uuid_format(buf, &uuid);
+ return std::string(buf, APR_UUID_FORMATTED_LENGTH);
+}
+
const value applyPrimitiveProcedure(const value& proc, list<value>& args) {
const lambda<value(list<value>&)> func(cadr((list<value>)proc));
return func(args);
@@ -120,9 +130,9 @@ const bool isSelfEvaluating(const value& exp) {
return true;
if(isString(exp))
return true;
- if(isBoolean(exp))
+ if(isBool(exp))
return true;
- if(isCharacter(exp))
+ if(isChar(exp))
return true;
return false;
}
@@ -148,6 +158,7 @@ const list<value> primitiveProcedureNames() {
l = cons<value>("/", l);
l = cons<value>("equal?", l);
l = cons<value>("display", l);
+ l = cons<value>("uuid", l);
l = cons<value>(";", l);
return l;
}
@@ -165,6 +176,7 @@ const list<value> primitiveProcedureObjects() {
l = cons(primitiveProcedure(valueDiv), l);
l = cons(primitiveProcedure(valueEqual), l);
l = cons(primitiveProcedure(valueDisplay), l);
+ l = cons(primitiveProcedure(valueUuid), l);
l = cons(primitiveProcedure(valueComment), l);
return l;
}
diff --git a/cpp/sca/modules/http/Makefile.am b/cpp/sca/modules/http/Makefile.am
index d34da0822f..6fe3b944d1 100644
--- a/cpp/sca/modules/http/Makefile.am
+++ b/cpp/sca/modules/http/Makefile.am
@@ -20,13 +20,13 @@ noinst_PROGRAMS = curl-test
libdir=$(prefix)/lib
lib_LTLIBRARIES = libmod_tuscany.la
-INCLUDES = -I. -I$(top_builddir)/kernel -I${HTTPD_INCLUDE} -I${APR_INCLUDE} -I${LIBXML2_INCLUDE} -I${LIBMOZJS_INCLUDE} -I${CURL_INCLUDE}
+INCLUDES = -I. -I$(top_builddir)/kernel -I${LIBXML2_INCLUDE} -I${HTTPD_INCLUDE} -I${APR_INCLUDE} -I${LIBMOZJS_INCLUDE} -I${CURL_INCLUDE}
libmod_tuscany_la_SOURCES = mod.cpp
-libmod_tuscany_la_LIBADD = -lpthread -L${LIBXML2_LIB} -lxml2 -L${LIBMOZJS_LIB} -lmozjs
+libmod_tuscany_la_LIBADD = -lpthread -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1 -L${LIBMOZJS_LIB} -lmozjs
curl_test_SOURCES = curl-test.cpp
-curl_test_LDADD = -lpthread -L${LIBXML2_LIB} -lxml2 -L${CURL_LIB} -lcurl
+curl_test_LDADD = -lpthread -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1 -L${CURL_LIB} -lcurl -L${LIBMOZJS_LIB} -lmozjs
TESTS = httpd-test http-test
diff --git a/cpp/sca/modules/json/Makefile.am b/cpp/sca/modules/json/Makefile.am
index 059eac97a2..1c4222870c 100644
--- a/cpp/sca/modules/json/Makefile.am
+++ b/cpp/sca/modules/json/Makefile.am
@@ -17,10 +17,10 @@
noinst_PROGRAMS = json-test
-INCLUDES = -I. -I$(top_builddir)/kernel -I${LIBXML2_INCLUDE} -I${LIBMOZJS_INCLUDE}
+INCLUDES = -I. -I$(top_builddir)/kernel -I${LIBXML2_INCLUDE} -I${APR_INCLUDE} -I${LIBMOZJS_INCLUDE}
json_test_SOURCES = json-test.cpp
-json_test_LDADD = -lpthread -L${LIBXML2_LIB} -lxml2 -L${LIBMOZJS_LIB} -lmozjs
+json_test_LDADD = -lpthread -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1 -L${LIBMOZJS_LIB} -lmozjs
TESTS = json-test
diff --git a/cpp/sca/test/store-function/Makefile.am b/cpp/sca/test/store-function/Makefile.am
index d969e01f59..57a5c114d3 100644
--- a/cpp/sca/test/store-function/Makefile.am
+++ b/cpp/sca/test/store-function/Makefile.am
@@ -18,10 +18,10 @@
store_function_PROGRAMS = store-function-test
store_functiondir=$(prefix)/test/store-function/deploy
-INCLUDES = -I. -I$(top_builddir)/kernel -I${LIBXML2_INCLUDE}
+INCLUDES = -I. -I$(top_builddir)/kernel -I${LIBXML2_INCLUDE} -I${APR_INCLUDE}
store_function_test_SOURCES = store-function-test.cpp
-store_function_test_LDADD = -L${LIBXML2_LIB} -lxml2 -lpthread
+store_function_test_LDADD = -lpthread -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1
EXTRA_DIST = *.composite
store_function_DATA = *.composite
diff --git a/cpp/sca/test/store-object/Makefile.am b/cpp/sca/test/store-object/Makefile.am
index d4ad4e5fc0..18b4aa8cc7 100644
--- a/cpp/sca/test/store-object/Makefile.am
+++ b/cpp/sca/test/store-object/Makefile.am
@@ -18,10 +18,10 @@
store_object_PROGRAMS = store-object-test
store_objectdir=$(prefix)/test/store-object/deploy
-INCLUDES = -I. -I$(top_builddir)/kernel -I${LIBXML2_INCLUDE}
+INCLUDES = -I. -I$(top_builddir)/kernel -I${LIBXML2_INCLUDE} -I${APR_INCLUDE}
store_object_test_SOURCES = store-object-test.cpp
-store_object_test_LDADD = -L${LIBXML2_LIB} -lxml2 -lpthread
+store_object_test_LDADD = -lpthread -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1
EXTRA_DIST = *.composite
store_object_DATA = *.composite
diff --git a/cpp/sca/test/store-script/Makefile.am b/cpp/sca/test/store-script/Makefile.am
index 2bd969b5ba..d5c4a8c0eb 100644
--- a/cpp/sca/test/store-script/Makefile.am
+++ b/cpp/sca/test/store-script/Makefile.am
@@ -18,13 +18,13 @@
store_script_PROGRAMS = store-script-test
store_scriptdir=$(prefix)/test/store-script/deploy
-INCLUDES = -I. -I$(top_builddir)/kernel -I$(top_builddir)/modules/eval -I${LIBXML2_INCLUDE} -I${LIBMOZJS_INCLUDE}
+INCLUDES = -I. -I$(top_builddir)/kernel -I$(top_builddir)/modules/eval -I${LIBXML2_INCLUDE} -I${APR_INCLUDE} -I${LIBMOZJS_INCLUDE}
store_script_test_SOURCES = store-script-test.cpp
-store_script_test_LDADD = -L${LIBXML2_LIB} -lxml2 -lpthread -L${LIBMOZJS_LIB} -lmozjs
+store_script_test_LDADD = -lpthread -L${LIBXML2_LIB} -lxml2 -L${APR_LIB} -lapr-1 -laprutil-1 -L${LIBMOZJS_LIB} -lmozjs
EXTRA_DIST = *.composite
store_script_DATA = *.composite
-TESTS = store-script-test
+TESTS = store-script-test store-http-test
diff --git a/cpp/sca/test/store-script/store-script-test.cpp b/cpp/sca/test/store-script/store-script-test.cpp
index 2d1891dd14..5808bd889e 100644
--- a/cpp/sca/test/store-script/store-script-test.cpp
+++ b/cpp/sca/test/store-script/store-script-test.cpp
@@ -24,6 +24,7 @@
*/
#include <assert.h>
+#include <regex.h>
#include <iostream>
#include <fstream>
#include <string>
@@ -38,23 +39,27 @@ namespace store {
using namespace tuscany;
bool contains(const std::string& str, const std::string& pattern) {
- return str.find(pattern) != str.npos;
+ return str.find(pattern) != std::string::npos;
}
bool testScript() {
std::ifstream is("store.scm", std::ios_base::in);
std::ostringstream os;
eval::evalDriverRun(is, os);
- assert(contains(os.str(), "(string::\"Sample Feed\", string::\"123\", (string::\"Item\", string::\"123456789\", ((symbol::javaClass, string::\"services.Item\"), (symbol::name, string::\"Orange\"), (symbol::currency, string::\"USD\"), (symbol::symbol, string::\"$\"), (symbol::price, number::3.55))), (string::\"Item\", string::\"123456789\", ((symbol::javaClass, string::\"services.Item\"), (symbol::name, string::\"Apple\"), (symbol::currency, string::\"USD\"), (symbol::symbol, string::\"$\"), (symbol::price, number::2.99))))"));
+
+ assert(contains(os.str(), "(\"Sample Feed\" \""));
+ assert(contains(os.str(), "\" (\"Item\" \""));
+ assert(contains(os.str(), "\" ((javaClass \"services.Item\") (name \"Orange\") (currency \"USD\") (symbol \"$\") (price 3.55))) (\"Item\" \""));
+ assert(contains(os.str(), "\" ((javaClass \"services.Item\") (name \"Apple\") (currency \"USD\") (symbol \"$\") (price 2.99))))"));
return true;
}
-const value evalLoop(std::istream& is, const value& req, eval::Env& globalEnv) {
+const value evalLoop(std::istream& is, const value& req, eval::Env& globalEnv, const gc_pool& pool) {
value in = eval::read(is);
if(isNil(in))
- return eval::evalApply(req, globalEnv);
- eval::evalApply(in, globalEnv);
- return evalLoop(is, req, globalEnv);
+ return eval::evalExpr(req, globalEnv, pool);
+ eval::evalExpr(in, globalEnv, pool);
+ return evalLoop(is, req, globalEnv, pool);
}
bool testEval() {
@@ -62,29 +67,32 @@ bool testEval() {
std::ifstream is("store.scm", std::ios_base::in);
std::ostringstream os;
eval::setupEvalOut(os);
- eval::Env globalEnv = eval::setupEnvironment();
+ gc_pool pool;
+ eval::Env globalEnv = eval::setupEnvironment(pool);
const value req(mklist<value>("storeui_service", std::string("getcatalog")));
- const value val = evalLoop(is, req, globalEnv);
+ const value val = evalLoop(is, req, globalEnv, pool);
+ eval::cleanupEnvironment(globalEnv);
std::ostringstream vs;
vs << val;
- assert(contains(vs.str(),"(((symbol::javaClass, string::\"services.Item\"), (symbol::name, string::\"Apple\"), (symbol::currency, string::\"USD\"), (symbol::symbol, string::\"$\"), (symbol::price, number::2.99)), ((symbol::javaClass, string::\"services.Item\"), (symbol::name, string::\"Orange\"), (symbol::currency, string::\"USD\"), (symbol::symbol, string::\"$\"), (symbol::price, number::3.55)), ((symbol::javaClass, string::\"services.Item\"), (symbol::name, string::\"Pear\"), (symbol::currency, string::\"USD\"), (symbol::symbol, string::\"$\"), (symbol::price, number::1.55)))"));
+ assert(contains(vs.str(), "(((javaClass \"services.Item\") (name \"Apple\") (currency \"USD\") (symbol \"$\") (price 2.99)) ((javaClass \"services.Item\") (name \"Orange\") (currency \"USD\") (symbol \"$\") (price 3.55)) ((javaClass \"services.Item\") (name \"Pear\") (currency \"USD\") (symbol \"$\") (price 1.55)))"));
}
{
std::ifstream is("store.scm", std::ios_base::in);
std::ostringstream os;
-
eval::setupEvalOut(os);
- eval::Env globalEnv = eval::setupEnvironment();
+ gc_pool pool;
+ eval::Env globalEnv = eval::setupEnvironment(pool);
const value req(mklist<value>("storeui_service", std::string("gettotal")));
- const value res = evalLoop(is, req, globalEnv);
+ const value res = evalLoop(is, req, globalEnv, pool);
+ eval::cleanupEnvironment(globalEnv);
std::ostringstream rs;
rs << res;
- assert(contains(rs.str(), "number::10"));
+ assert(contains(rs.str(), "10"));
}
return true;
}