summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorjsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68>2009-11-01 05:24:54 +0000
committerjsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68>2009-11-01 05:24:54 +0000
commit9f187b46ae761e8275362d6c1533e9fe79028c7b (patch)
treee2625f63e0c84f172c877e1fe2cbe75adf678208
parent24021bd09a0d5c9664565a244c24e0bdef0908b8 (diff)
Improved memory management using APR memory pools, changed frame allocation in eval library to support forward references and fixed memory leak in XML parsing code. Also simplified a bit the printing of lists to make them easier to read.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@831639 13f79535-47bb-0310-9956-ffa450edef68
-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;
}