diff options
Diffstat (limited to 'cpp')
-rwxr-xr-x | cpp/sca/etc/memgrind (renamed from cpp/sca/etc/valgrind.sh) | 2 | ||||
-rw-r--r-- | cpp/sca/kernel/Makefile.am | 6 | ||||
-rw-r--r-- | cpp/sca/kernel/element.hpp | 6 | ||||
-rw-r--r-- | cpp/sca/kernel/function.hpp | 22 | ||||
-rw-r--r-- | cpp/sca/kernel/gc.hpp | 135 | ||||
-rw-r--r-- | cpp/sca/kernel/kernel-test.cpp | 12 | ||||
-rw-r--r-- | cpp/sca/kernel/list.hpp | 29 | ||||
-rw-r--r-- | cpp/sca/kernel/value.hpp | 108 | ||||
-rw-r--r-- | cpp/sca/kernel/xml.hpp | 38 | ||||
-rw-r--r-- | cpp/sca/modules/atom/Makefile.am | 4 | ||||
-rw-r--r-- | cpp/sca/modules/eval/Makefile.am | 6 | ||||
-rw-r--r-- | cpp/sca/modules/eval/driver.hpp | 12 | ||||
-rw-r--r-- | cpp/sca/modules/eval/environment.hpp | 49 | ||||
-rw-r--r-- | cpp/sca/modules/eval/eval-test.cpp | 13 | ||||
-rw-r--r-- | cpp/sca/modules/eval/eval.hpp | 56 | ||||
-rw-r--r-- | cpp/sca/modules/eval/primitive.hpp | 16 | ||||
-rw-r--r-- | cpp/sca/modules/http/Makefile.am | 6 | ||||
-rw-r--r-- | cpp/sca/modules/json/Makefile.am | 4 | ||||
-rw-r--r-- | cpp/sca/test/store-function/Makefile.am | 4 | ||||
-rw-r--r-- | cpp/sca/test/store-object/Makefile.am | 4 | ||||
-rw-r--r-- | cpp/sca/test/store-script/Makefile.am | 6 | ||||
-rw-r--r-- | cpp/sca/test/store-script/store-script-test.cpp | 34 |
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; } |