summaryrefslogtreecommitdiffstats
path: root/cpp/sca/modules
diff options
context:
space:
mode:
authorjsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68>2009-10-26 05:13:06 +0000
committerjsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68>2009-10-26 05:13:06 +0000
commitf61164c77c5c21a32b58ad61c868bd8ff6a4a79e (patch)
tree951cc581d22bac8ad615697b19e879e22578d10c /cpp/sca/modules
parent0969cc21d093f9450c36e7f63cddc4f5aa44b238 (diff)
Minor refactoring, given each module its own namespace. Added utility functions to convert between values elements/attributes and fixed XML, ATOM and JSON serialization of lists.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@829699 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to '')
-rw-r--r--cpp/sca/modules/atom/atom-test.cpp72
-rw-r--r--cpp/sca/modules/atom/atom.hpp50
-rw-r--r--cpp/sca/modules/eval/Makefile.am3
-rw-r--r--cpp/sca/modules/eval/driver.hpp4
-rw-r--r--cpp/sca/modules/eval/environment.hpp42
-rw-r--r--cpp/sca/modules/eval/eval-shell.cpp2
-rw-r--r--cpp/sca/modules/eval/eval-test.cpp22
-rw-r--r--cpp/sca/modules/eval/eval.hpp31
-rw-r--r--cpp/sca/modules/eval/primitive.hpp5
-rw-r--r--cpp/sca/modules/eval/read.hpp5
-rw-r--r--cpp/sca/modules/json/json-test.cpp57
-rw-r--r--cpp/sca/modules/json/json.hpp62
12 files changed, 245 insertions, 110 deletions
diff --git a/cpp/sca/modules/atom/atom-test.cpp b/cpp/sca/modules/atom/atom-test.cpp
index 0cef6b3b60..618f534001 100644
--- a/cpp/sca/modules/atom/atom-test.cpp
+++ b/cpp/sca/modules/atom/atom-test.cpp
@@ -31,8 +31,9 @@
#include "atom.hpp"
namespace tuscany {
+namespace atom {
-std::ostringstream* atomWriter(std::ostringstream* os, const std::string& s) {
+std::ostringstream* writer(std::ostringstream* os, const std::string& s) {
(*os) << s;
return os;
}
@@ -49,22 +50,49 @@ std::string itemEntry("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"<link href=\"cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b\"/>"
"</entry>\n");
-bool testATOMEntry() {
+std::string incompleteEntry("<entry xmlns=\"http://www.w3.org/2005/Atom\">"
+ "<title>item</title><content type=\"text/xml\">"
+ "<Item xmlns=\"http://services/\">"
+ "<name xmlns=\"\">Orange</name>"
+ "<price xmlns=\"\">3.55</price>"
+ "</Item>"
+ "</content>"
+ "</entry>");
+
+std::string completedEntry("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
+ "<entry xmlns=\"http://www.w3.org/2005/Atom\">"
+ "<title type=\"text\">item</title>"
+ "<id></id>"
+ "<content type=\"application/xml\">"
+ "<Item xmlns=\"http://services/\">"
+ "<name xmlns=\"\">Orange</name>"
+ "<price xmlns=\"\">3.55</price>"
+ "</Item>"
+ "</content><link href=\"\"/>"
+ "</entry>\n");
+
+bool testEntry() {
{
const list<value> i = list<value>() << element << "item"
<< (list<value>() << element << "name" << std::string("Apple"))
<< (list<value>() << element << "price" << std::string("$2.99"));
const list<value> a = mklist<value>(std::string("item"), std::string("cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"), i);
std::ostringstream os;
- writeATOMEntry<std::ostringstream*>(atomWriter, &os, a);
+ writeEntry<std::ostringstream*>(writer, &os, a);
assert(os.str() == itemEntry);
}
{
- const list<value> a = readATOMEntry(mklist(itemEntry));
+ const list<value> a = readEntry(mklist(itemEntry));
std::ostringstream os;
- writeATOMEntry<std::ostringstream*>(atomWriter, &os, a);
+ writeEntry<std::ostringstream*>(writer, &os, a);
assert(os.str() == itemEntry);
}
+ {
+ const list<value> a = readEntry(mklist(incompleteEntry));
+ std::ostringstream os;
+ writeEntry<std::ostringstream*>(writer, &os, a);
+ assert(os.str() == completedEntry);
+ }
return true;
}
@@ -100,16 +128,16 @@ std::string itemFeed("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
"</entry>"
"</feed>\n");
-bool testATOMFeed() {
+bool testFeed() {
{
std::ostringstream os;
- writeATOMFeed<std::ostringstream*>(atomWriter, &os, mklist<value>("Feed", "1234"));
+ writeFeed<std::ostringstream*>(writer, &os, mklist<value>("Feed", "1234"));
assert(os.str() == emptyFeed);
}
{
- const list<value> a = readATOMFeed(mklist(emptyFeed));
+ const list<value> a = readFeed(mklist(emptyFeed));
std::ostringstream os;
- writeATOMFeed<std::ostringstream*>(atomWriter, &os, a);
+ writeFeed<std::ostringstream*>(writer, &os, a);
assert(os.str() == emptyFeed);
}
{
@@ -124,25 +152,41 @@ bool testATOMFeed() {
<< (list<value>() << element << "price" << "$3.55")));
const list<value> a = cons<value>("Feed", cons<value>("1234", i));
std::ostringstream os;
- writeATOMFeed<std::ostringstream*>(atomWriter, &os, a);
+ writeFeed<std::ostringstream*>(writer, &os, a);
assert(os.str() == itemFeed);
}
{
- const list<value> a = readATOMFeed(mklist(itemFeed));
+ const list<value> i = list<value>()
+ << (list<value>() << "item" << "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83b"
+ << valueToElement(list<value>() << "item"
+ << (list<value>() << "name" << "Apple")
+ << (list<value>() << "price" << "$2.99")))
+ << (list<value>() << "item" << "cart-53d67a61-aa5e-4e5e-8401-39edeba8b83c"
+ << valueToElement(list<value>() << "item"
+ << (list<value>() << "name" << "Orange")
+ << (list<value>() << "price" << "$3.55")));
+ const list<value> a = cons<value>("Feed", cons<value>("1234", i));
std::ostringstream os;
- writeATOMFeed<std::ostringstream*>(atomWriter, &os, a);
+ writeFeed<std::ostringstream*>(writer, &os, a);
+ assert(os.str() == itemFeed);
+ }
+ {
+ const list<value> a = readFeed(mklist(itemFeed));
+ std::ostringstream os;
+ writeFeed<std::ostringstream*>(writer, &os, a);
assert(os.str() == itemFeed);
}
return true;
}
}
+}
int main() {
std::cout << "Testing..." << std::endl;
- tuscany::testATOMEntry();
- tuscany::testATOMFeed();
+ tuscany::atom::testEntry();
+ tuscany::atom::testFeed();
std::cout << "OK" << std::endl;
diff --git a/cpp/sca/modules/atom/atom.hpp b/cpp/sca/modules/atom/atom.hpp
index 5bb8d45e38..78b60da70f 100644
--- a/cpp/sca/modules/atom/atom.hpp
+++ b/cpp/sca/modules/atom/atom.hpp
@@ -33,40 +33,43 @@
#include "xml.hpp"
namespace tuscany {
+namespace atom {
/**
* Convert a list of elements to a list of values representing an ATOM entry.
*/
-const list<value> atomEntry(const list<value>& e) {
- const list<value> t = filter<value>(selector(mklist<value>(element, "title")), e);
- const list<value> i = filter<value>(selector(mklist<value>(element, "id")), e);
- const list<value> c = filter<value>(selector(mklist<value>(element, "content")), e);
- return mklist<value>(elementValue(car(t)), elementValue(car(i)), cadr(elementChildren(car(c))));
+const list<value> entry(const list<value>& e) {
+ const list<value> lt = filter<value>(selector(mklist<value>(element, "title")), e);
+ const value t = isNil(lt)? value(std::string("")) : elementValue(car(lt));
+ const list<value> li = filter<value>(selector(mklist<value>(element, "id")), e);
+ const value i = isNil(li)? value(std::string("")) : elementValue(car(li));
+ const list<value> lc = filter<value>(selector(mklist<value>(element, "content")), e);
+ return mklist<value>(t, i, cadr(elementChildren(car(lc))));
}
/**
* Convert a list of elements to a list of values representing ATOM entries.
*/
-const list<value> atomEntries(const list<value>& e) {
+const list<value> entries(const list<value>& e) {
if (isNil(e))
return list<value>();
- return cons<value>(atomEntry(car(e)), atomEntries(cdr(e)));
+ return cons<value>(entry(car(e)), entries(cdr(e)));
}
/**
* Convert a list of strings to a list of values representing an ATOM entry.
*/
-const failable<list<value>, std::string> readATOMEntry(const list<std::string>& ilist) {
+const failable<list<value>, std::string> readEntry(const list<std::string>& ilist) {
const list<value> e = readXML(ilist);
if (isNil(e))
return std::string("Empty entry");
- return atomEntry(car(e));
+ return entry(car(e));
}
/**
* Convert a list of strings to a list of values representing an ATOM feed.
*/
-const failable<list<value>, std::string> readATOMFeed(const list<std::string>& ilist) {
+const failable<list<value>, std::string> readFeed(const list<std::string>& ilist) {
const list<value> f = readXML(ilist);
if (isNil(f))
return std::string("Empty feed");
@@ -75,14 +78,14 @@ const failable<list<value>, std::string> readATOMFeed(const list<std::string>& i
const list<value> e = filter<value>(selector(mklist<value>(element, "entry")), car(f));
if (isNil(e))
return mklist<value>(elementValue(car(t)), elementValue(car(i)));
- return cons<value>(elementValue(car(t)), cons(elementValue(car(i)), atomEntries(e)));
+ return cons<value>(elementValue(car(t)), cons(elementValue(car(i)), entries(e)));
}
/**
* Convert a list of values representing an ATOM entry to a list of elements.
* The first two values in the list are the entry title and id.
*/
-const list<value> atomEntryElement(const list<value>& l) {
+const list<value> entryElement(const list<value>& l) {
return list<value>()
<< element << "entry" << (list<value>() << attribute << "xmlns" << "http://www.w3.org/2005/Atom")
<< (list<value>() << element << "title" << (list<value>() << attribute << "type" << "text") << car(l))
@@ -94,30 +97,30 @@ const list<value> atomEntryElement(const list<value>& l) {
/**
* Convert a list of values representing ATOM entries to a list of elements.
*/
-const list<value> atomEntriesElements(const list<value>& l) {
+const list<value> entriesElements(const list<value>& l) {
if (isNil(l))
return list<value>();
- return cons<value>(atomEntryElement(car(l)), atomEntriesElements(cdr(l)));
+ return cons<value>(entryElement(car(l)), entriesElements(cdr(l)));
}
/**
* Convert a list of values representing an ATOM entry to an ATOM entry.
* The first two values in the list are the entry id and title.
*/
-template<typename R> const failable<R, std::string> writeATOMEntry(const lambda<R(R, std::string)>& reduce, const R& initial, const list<value>& l) {
- return writeXML<R>(reduce, initial, mklist<value>(atomEntryElement(l)));
+template<typename R> const failable<R, std::string> writeEntry(const lambda<R(R, std::string)>& reduce, const R& initial, const list<value>& l) {
+ return writeXML<R>(reduce, initial, mklist<value>(entryElement(l)));
}
/**
* Convert a list of values representing an ATOM entry to a list of strings.
* The first two values in the list are the entry id and title.
*/
-const list<std::string> writeATOMList(const list<std::string>& listSoFar, const std::string& s) {
+const list<std::string> writeStrings(const list<std::string>& listSoFar, const std::string& s) {
return cons(s, listSoFar);
}
-const failable<list<std::string>, std::string> writeATOMEntry(const list<value>& l) {
- const failable<list<std::string>, std::string> ls = writeATOMEntry<list<std::string> >(writeATOMList, list<std::string>(), l);
+const failable<list<std::string>, std::string> writeEntry(const list<value>& l) {
+ const failable<list<std::string>, std::string> ls = writeEntry<list<std::string> >(writeStrings, list<std::string>(), l);
if (!hasValue(ls))
return ls;
return reverse(list<std::string>(ls));
@@ -127,14 +130,14 @@ const failable<list<std::string>, std::string> writeATOMEntry(const list<value>&
* Convert a list of values representing an ATOM feed to an ATOM feed.
* The first two values in the list are the feed id and title.
*/
-template<typename R> const failable<R, std::string> writeATOMFeed(const lambda<R(R, std::string)>& reduce, const R& initial, const list<value>& l) {
+template<typename R> const failable<R, std::string> writeFeed(const lambda<R(R, std::string)>& reduce, const R& initial, const list<value>& l) {
const list<value> f = list<value>()
<< element << "feed" << (list<value>() << attribute << "xmlns" << "http://www.w3.org/2005/Atom")
<< (list<value>() << element << "title" << (list<value>() << attribute << "type" << "text") << car(l))
<< (list<value>() << element << "id" << cadr(l));
if (isNil(cddr(l)))
return writeXML<R>(reduce, initial, mklist<value>(f));
- const list<value> fe = append(f, atomEntriesElements(cddr(l)));
+ const list<value> fe = append(f, entriesElements(cddr(l)));
return writeXML<R>(reduce, initial, mklist<value>(fe));
}
@@ -142,13 +145,14 @@ template<typename R> const failable<R, std::string> writeATOMFeed(const lambda<R
* Convert a list of values representing an ATOM feed to a list of strings.
* The first two values in the list are the feed id and title.
*/
-const failable<list<std::string>, std::string> writeATOMFeed(const list<value>& l) {
- const failable<list<std::string>, std::string> ls = writeATOMFeed<list<std::string> >(writeATOMList, list<std::string>(), l);
+const failable<list<std::string>, std::string> writeFeed(const list<value>& l) {
+ const failable<list<std::string>, std::string> ls = writeFeed<list<std::string> >(writeStrings, list<std::string>(), l);
if (!hasValue(ls))
return ls;
return reverse(list<std::string>(ls));
}
}
+}
#endif /* tuscany_atom_hpp */
diff --git a/cpp/sca/modules/eval/Makefile.am b/cpp/sca/modules/eval/Makefile.am
index 552e0f99c7..b9fa9f8f56 100644
--- a/cpp/sca/modules/eval/Makefile.am
+++ b/cpp/sca/modules/eval/Makefile.am
@@ -27,3 +27,6 @@ eval_test_LDADD = -lpthread -L${LIBXML2_LIB} -lxml2
eval_shell_SOURCES = eval-shell.cpp
eval_shell_LDADD = -lpthread -L${LIBXML2_LIB} -lxml2
+
+TESTS = eval-test
+
diff --git a/cpp/sca/modules/eval/driver.hpp b/cpp/sca/modules/eval/driver.hpp
index 7a0645781f..064213706c 100644
--- a/cpp/sca/modules/eval/driver.hpp
+++ b/cpp/sca/modules/eval/driver.hpp
@@ -31,6 +31,7 @@
#include "eval.hpp"
namespace tuscany {
+namespace eval {
const std::string evalOutputPrompt("; ");
const std::string evalInputPrompt("=> ");
@@ -57,7 +58,7 @@ const value evalDriverLoop(std::istream& in, std::ostream& out, Env& globalEnv)
value input = read(in);
if (isNil(input))
return input;
- const value output = eval(input, globalEnv);
+ const value output = evalApply(input, globalEnv);
announceOutput(out, evalOutputPrompt);
userPrint(out, output);
return evalDriverLoop(in, out, globalEnv);
@@ -71,4 +72,5 @@ const bool evalDriverRun(std::istream& in, std::ostream& out) {
}
}
+}
#endif /* tuscany_eval_driver_hpp */
diff --git a/cpp/sca/modules/eval/environment.hpp b/cpp/sca/modules/eval/environment.hpp
index 834563069e..e0da9096fe 100644
--- a/cpp/sca/modules/eval/environment.hpp
+++ b/cpp/sca/modules/eval/environment.hpp
@@ -31,10 +31,10 @@
#include "value.hpp"
#include "primitive.hpp"
-namespace tuscany
-{
+namespace tuscany {
+namespace eval {
-typedef value Frame;
+typedef list<value> Frame;
typedef list<value> Env;
const value trueSymbol("true");
@@ -130,28 +130,37 @@ const value assignmentValue(const value& exp) {
return car(cdr(cdr((list<value> )exp)));
}
-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 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 Env defineVariable(const value& var, const value& val, Env& env) {
- return cons(addBindingToFrame(var, val, firstFrame(env)), cdr(env));
+const bool defineVariable(const value& var, const value& val, Env& env) {
+ Frame frame = firstFrame(env);
+ addBindingToFrame(var, val, frame);
+ setCar(env, value(frame));
+ 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) {
-// if(length(vars) == length(vals))
-// else if(length(vars) < length(vals))
-// std::cout << "Too many arguments supplied " << vars << " " << vals << "\n";
-// else
-// std::cout << "Too few arguments supplied " << vars << " " << vals << "\n";
-// return baseEnv;
- return cons(makeFrame(vars, vals), baseEnv);
+ return cons(value(makeFrame(vars, vals)), lambda<list<value>()>(environmentReference(baseEnv)));
}
const Env setupEnvironment() {
Env env = extendEnvironment(primitiveProcedureNames(), primitiveProcedureObjects(), theEmptyEnvironment());
- env = defineVariable(trueSymbol, true, env);
- env = defineVariable(falseSymbol, false, env);
+ defineVariable(trueSymbol, true, env);
+ defineVariable(falseSymbol, false, env);
return env;
}
@@ -178,4 +187,5 @@ const value lookupVariableValue(const value& var, const Env& env) {
}
}
+}
#endif /* tuscany_eval_environment_hpp */
diff --git a/cpp/sca/modules/eval/eval-shell.cpp b/cpp/sca/modules/eval/eval-shell.cpp
index 46710b8354..e1c90101da 100644
--- a/cpp/sca/modules/eval/eval-shell.cpp
+++ b/cpp/sca/modules/eval/eval-shell.cpp
@@ -30,6 +30,6 @@
#include "driver.hpp"
int main() {
- tuscany::evalDriverRun(std::cin, std::cout);
+ tuscany::eval::evalDriverRun(std::cin, std::cout);
return 0;
}
diff --git a/cpp/sca/modules/eval/eval-test.cpp b/cpp/sca/modules/eval/eval-test.cpp
index c536ed51a4..95a286ade0 100644
--- a/cpp/sca/modules/eval/eval-test.cpp
+++ b/cpp/sca/modules/eval/eval-test.cpp
@@ -30,6 +30,7 @@
#include "driver.hpp"
namespace tuscany {
+namespace eval {
bool testEnv() {
Env globalEnv = list<value>();
@@ -109,6 +110,11 @@ const std::string testSchemeLambda(
"(define (testLambda) (if (= 4 (sqrt 2)) (display \"testLambda ok\") (error \"testLambda\"))) "
"(testLambda)");
+const std::string testSchemeForward(
+ "(define (testLambda) (if (= 4 (sqrt 2)) (display \"testForward ok\") (error \"testForward\"))) "
+ "(define sqrt (lambda (x) (* x x))) "
+ "(testLambda)");
+
bool contains(const std::string& str, const std::string& pattern) {
return str.find(pattern) != str.npos;
}
@@ -129,13 +135,14 @@ 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"));
return true;
}
bool testEvalExpr() {
const value exp = mklist<value>("+", 2, 3);
Env env = setupEnvironment();
- const value r = eval(exp, env);
+ const value r = evalApply(exp, env);
assert(r == value(5));
return true;
}
@@ -160,16 +167,17 @@ bool testEvalRun() {
}
}
+}
int main() {
std::cout << "Testing..." << std::endl;
- tuscany::testEnv();
- tuscany::testEnvGC();
- tuscany::testRead();
- tuscany::testEval();
- tuscany::testEvalExpr();
- tuscany::testEvalGC();
+ tuscany::eval::testEnv();
+ tuscany::eval::testEnvGC();
+ tuscany::eval::testRead();
+ tuscany::eval::testEval();
+ tuscany::eval::testEvalExpr();
+ tuscany::eval::testEvalGC();
std::cout << "OK" << std::endl;
return 0;
diff --git a/cpp/sca/modules/eval/eval.hpp b/cpp/sca/modules/eval/eval.hpp
index 2be2894bf3..1496c3bd09 100644
--- a/cpp/sca/modules/eval/eval.hpp
+++ b/cpp/sca/modules/eval/eval.hpp
@@ -33,10 +33,10 @@
#include "read.hpp"
#include "environment.hpp"
-namespace tuscany
-{
+namespace tuscany {
+namespace eval {
-const value eval(const value& exp, Env& env);
+const value evalApply(const value& exp, Env& env);
const value compoundProcedureSymbol("compound-procedure");
const value procedureSymbol("procedure");
@@ -89,7 +89,7 @@ const list<value> operands(const value& exp) {
const list<value> listOfValues(const list<value> exps, Env& env) {
if(isNil(exps))
return list<value> ();
- return cons(eval(car(exps), env), listOfValues(cdr(exps), env));
+ return cons(evalApply(car(exps), env), listOfValues(cdr(exps), env));
}
const value applyOperat(const value& exp) {
@@ -134,8 +134,8 @@ const value makeBegin(const list<value> seq) {
const value evalSequence(const list<value>& exps, Env& env) {
if(isLastExp(exps))
- return eval(firstExp(exps), env);
- eval(firstExp(exps), env);
+ return evalApply(firstExp(exps), env);
+ evalApply(firstExp(exps), env);
return evalSequence(restExp(exps), env);
}
@@ -219,17 +219,17 @@ value condToIf(const value& exp) {
}
value evalIf(const value& exp, Env& env) {
- if(isTrue(eval(ifPredicate(exp), env)))
- return eval(ifConsequent(exp), env);
- return eval(ifAlternative(exp), env);
+ if(isTrue(evalApply(ifPredicate(exp), env)))
+ return evalApply(ifConsequent(exp), env);
+ return evalApply(ifAlternative(exp), env);
}
const value evalDefinition(const value& exp, Env& env) {
- env = defineVariable(definitionVariable(exp), eval(definitionValue(exp), env), env);
+ defineVariable(definitionVariable(exp), evalApply(definitionValue(exp), env), env);
return definitionVariable(exp);
}
-const value eval(const value& exp, Env& env) {
+const value evalApply(const value& exp, Env& env) {
if(isSelfEvaluating(exp))
return exp;
if(isQuoted(exp))
@@ -241,22 +241,23 @@ const value eval(const value& exp, Env& env) {
if(isBegin(exp))
return evalSequence(beginActions(exp), env);
if(isCond(exp))
- return eval(condToIf(exp), env);
+ return evalApply(condToIf(exp), env);
if(isLambda(exp))
return makeProcedure(lambdaParameters(exp), lambdaBody(exp), env);
if(isVariable(exp))
return lookupVariableValue(exp, env);
if(isApply(exp)) {
- list<value> applyOperandValues = eval(applyOperand(exp), env);
- return applyProcedure(eval(applyOperat(exp), env), applyOperandValues);
+ list<value> applyOperandValues = evalApply(applyOperand(exp), env);
+ return applyProcedure(evalApply(applyOperat(exp), env), applyOperandValues);
}
if(isApplication(exp)) {
list<value> operandValues = listOfValues(operands(exp), env);
- return applyProcedure(eval(operat(exp), env), operandValues);
+ return applyProcedure(evalApply(operat(exp), env), operandValues);
}
std::cout << "Unknown expression type " << exp << "\n";
return value();
}
}
+}
#endif /* tuscany_eval_eval_hpp */
diff --git a/cpp/sca/modules/eval/primitive.hpp b/cpp/sca/modules/eval/primitive.hpp
index 0d738d1392..4ca6ea900a 100644
--- a/cpp/sca/modules/eval/primitive.hpp
+++ b/cpp/sca/modules/eval/primitive.hpp
@@ -31,8 +31,8 @@
#include "list.hpp"
#include "value.hpp"
-namespace tuscany
-{
+namespace tuscany {
+namespace eval {
const value primitiveSymbol("primitive");
const value quoteSymbol("'");
@@ -190,4 +190,5 @@ const value makeLambda(const list<value>& parameters, const list<value>& body) {
}
}
+}
#endif /* tuscany_eval_primitive_hpp */
diff --git a/cpp/sca/modules/eval/read.hpp b/cpp/sca/modules/eval/read.hpp
index 189075ded9..994462f145 100644
--- a/cpp/sca/modules/eval/read.hpp
+++ b/cpp/sca/modules/eval/read.hpp
@@ -35,8 +35,8 @@
#include "value.hpp"
#include "primitive.hpp"
-namespace tuscany
-{
+namespace tuscany {
+namespace eval {
const value rightParenthesis(mklist<value>(")"));
const value leftParenthesis(mklist<value>("("));
@@ -180,4 +180,5 @@ const value read(std::istream& in) {
}
}
+}
#endif /* tuscany_eval_read_hpp */
diff --git a/cpp/sca/modules/json/json-test.cpp b/cpp/sca/modules/json/json-test.cpp
index b7cc4e4eeb..bf0ecab1f4 100644
--- a/cpp/sca/modules/json/json-test.cpp
+++ b/cpp/sca/modules/json/json-test.cpp
@@ -31,6 +31,7 @@
#include "json.hpp"
namespace tuscany {
+namespace json {
bool testJSEval() {
JSONContext cx;
@@ -56,49 +57,75 @@ bool testJSON() {
const list<value> cr = mklist<value>(mklist<value> (attribute, "name", std::string("jdoe")), cons<value>(element, cons<value>("address", ad)), cons<value>(element, cons<value>("account", ac)));
const list<value> c = mklist<value>(cons<value>(element, cons<value>("customer", cr)));
std::ostringstream os;
- writeJSON<std::ostringstream*>(cx, jsonWriter, &os, c);
+ write<std::ostringstream*>(cx, jsonWriter, &os, c);
assert(os.str() == "{\"customer\":{\"name\":\"jdoe\",\"address\":{\"city\":\"san francisco\",\"state\":\"ca\"},\"account\":{\"id\":\"1234\",\"balance\":1000}}}");
}
{
const list<value> phones = mklist<value> (std::string("408-1234"), std::string("650-1234"));
- const list<value> l = mklist<value> (mklist<value> (element, "phones", phones), mklist<value> (attribute, "lastName", std::string("test\ttab")), mklist<value> (attribute, "firstName", std::string("test1")));
+ const list<value> l = mklist<value> (mklist<value> (element, "phones", phones), mklist<value> (element, "lastName", std::string("test\ttab")), mklist<value> (element, "firstName", std::string("test1")));
std::ostringstream os;
- writeJSON<std::ostringstream*>(cx, jsonWriter, &os, l);
+ write<std::ostringstream*>(cx, jsonWriter, &os, l);
assert(os.str() == "{\"phones\":[\"408-1234\",\"650-1234\"],\"lastName\":\"test\\u0009tab\",\"firstName\":\"test1\"}");
std::istringstream is(os.str());
const list<std::string> il = streamList(is);
- const list<value> r = readJSON(cx, il);
+ const list<value> r = read(cx, il);
assert(r == l);
std::ostringstream wos;
- write(writeJSON(cx, r), wos);
+ write(write(cx, r), wos);
assert(wos.str() == os.str());
}
return true;
}
bool testJSONRPC() {
- const std::string lm("{\"id\": 1, \"method\": \"system.listMethods\", \"params\": []}");
JSONContext cx;
- const list<value> e = readJSON(cx, mklist(lm));
- const list<value> v = elementsToValues(e);
-
- assert(assoc<value>("id", v) == mklist<value>("id", 1));
- assert(assoc<value>("method", v) == mklist<value>("method", std::string("system.listMethods")));
- assert(assoc<value>("params", v) == mklist<value>("params", list<value>()));
+ {
+ const std::string lm("{\"id\": 1, \"method\": \"system.listMethods\", \"params\": []}");
+ const list<value> e = read(cx, mklist(lm));
+ const list<value> v = elementsToValues(e);
+ assert(assoc<value>("id", v) == mklist<value>("id", 1));
+ assert(assoc<value>("method", v) == mklist<value>("method", std::string("system.listMethods")));
+ assert(assoc<value>("params", v) == mklist<value>("params", list<value>()));
+ }
+ {
+ const std::string i("{\"id\":3,\"result\":[{\"price\":\"$2.99\",\"name\":\"Apple\"},{\"price\":\"$3.55\",\"name\":\"Orange\"},{\"price\":\"$1.55\",\"name\":\"Pear\"}]}");
+ const list<value> e = read(cx, mklist(i));
+ const std::string i2("{\"id\":3,\"result\":{\"0\":{\"price\":\"$2.99\",\"name\":\"Apple\"},\"1\":{\"price\":\"$3.55\",\"name\":\"Orange\"},\"2\":{\"price\":\"$1.55\",\"name\":\"Pear\"}}}");
+ const list<value> e2 = read(cx, mklist(i));
+ assert(e == e2);
+ }
+ {
+ const std::string i("{\"id\":3,\"result\":[{\"price\":\"$2.99\",\"name\":\"Apple\"},{\"price\":\"$3.55\",\"name\":\"Orange\"},{\"price\":\"$1.55\",\"name\":\"Pear\"}]}");
+ const list<value> e = read(cx, mklist(i));
+ std::ostringstream os;
+ write(write(cx, e), os);
+ assert(os.str() == i);
+ const list<value> v = elementsToValues(e);
+ const list<value> r = valuesToElements(v);
+ assert(r == e);
+ }
+ {
+ const list<value> r = mklist<value>(mklist<value>("id", 1), mklist<value>("result", mklist<value>(std::string("Service.get"), std::string("Service.getTotal"))));
+ const list<value> e = valuesToElements(r);
+ std::ostringstream os;
+ write(write(cx, e), os);
+ assert(os.str() == "{\"id\":1,\"result\":[\"Service.get\",\"Service.getTotal\"]}");
+ }
return true;
}
}
+}
int main() {
std::cout << "Testing..." << std::endl;
- tuscany::testJSEval();
- tuscany::testJSON();
- tuscany::testJSONRPC();
+ tuscany::json::testJSEval();
+ tuscany::json::testJSON();
+ tuscany::json::testJSONRPC();
std::cout << "OK" << std::endl;
diff --git a/cpp/sca/modules/json/json.hpp b/cpp/sca/modules/json/json.hpp
index 5f3d8c21e0..8e4666196e 100644
--- a/cpp/sca/modules/json/json.hpp
+++ b/cpp/sca/modules/json/json.hpp
@@ -35,6 +35,7 @@
#include "monad.hpp"
namespace tuscany {
+namespace json {
/**
* Report JSON errors.
@@ -155,7 +156,7 @@ const list<value> jsPropertiesToValues(const JSONContext& cx, const list<value>&
jsval idv;
JS_IdToValue(cx, id, &idv);
if(JSVAL_IS_STRING(idv)) {
- const value type = isList(val)? element : attribute;
+ const value type = isList(val)? element : element;
return jsPropertiesToValues(cx, cons<value> (mklist<value> (type, JS_GetStringBytes(JSVAL_TO_STRING(idv)), val), propertiesSoFar), o, i);
}
return jsPropertiesToValues(cx, cons(val, propertiesSoFar), o, i);
@@ -194,25 +195,25 @@ const value jsValToValue(const JSONContext& cx, const jsval& jsv) {
/**
* Consumes JSON strings and populates a JS object.
*/
-failable<bool, std::string> consumeJSON(const JSONContext& cx, JSONParser* parser, const list<std::string>& ilist) {
+failable<bool, std::string> consume(const JSONContext& cx, JSONParser* parser, const list<std::string>& ilist) {
if (isNil(ilist))
return true;
JSString* jstr = JS_NewStringCopyZ(cx, car(ilist).c_str());
if(!JS_ConsumeJSONText(cx, parser, JS_GetStringChars(jstr), JS_GetStringLength(jstr)))
return "JS_ConsumeJSONText failed";
- return consumeJSON(cx, parser, cdr(ilist));
+ return consume(cx, parser, cdr(ilist));
}
/**
* Convert a list of strings representing a JSON document to a list of values.
*/
-const failable<list<value>, std::string> readJSON(const JSONContext& cx, const list<std::string>& ilist) {
+const failable<list<value>, std::string> read(const JSONContext& cx, const list<std::string>& ilist) {
jsval val;
JSONParser* parser = JS_BeginJSONParse(cx, &val);
if(parser == NULL)
return std::string("JS_BeginJSONParse failed");
- const failable<bool, std::string> consumed = consumeJSON(cx, parser, ilist);
+ const failable<bool, std::string> consumed = consume(cx, parser, ilist);
if(!JS_FinishJSONParse(cx, parser, JSVAL_NULL))
return std::string("JS_FinishJSONParse failed");
@@ -235,6 +236,36 @@ JSObject* valuesToJSElements(const JSONContext& cx, JSObject* a, const list<valu
}
/**
+ * Returns true if a list represents a JS array.
+ */
+const bool isJSArray(const list<value>& l) {
+ if(isNil(l))
+ return false;
+ const value v = car(l);
+ if(isList(v)) {
+ const list<value> p = v;
+ if(isSymbol(car(p)))
+ return false;
+ }
+ return true;
+}
+
+
+
+/**
+ * Converts a list of values to JS properties.
+ */
+JSObject* valuesToJSProperties(const JSONContext& cx, JSObject* o, const list<value>& l) {
+ const jsval valueToJSVal(const JSONContext& cx, const value& val);
+ if(isNil(l))
+ return o;
+ const list<value> p = car(l);
+ jsval pv = valueToJSVal(cx, caddr(p));
+ JS_SetProperty(cx, o, ((std::string)cadr(p)).c_str(), &pv);
+ return valuesToJSProperties(cx, o, cdr(l));
+}
+
+/**
* Converts a value to a JS val.
*/
const jsval valueToJSVal(const JSONContext& cx, const value& val) {
@@ -250,7 +281,9 @@ const jsval valueToJSVal(const JSONContext& cx, const value& val) {
return DOUBLE_TO_JSVAL(JS_NewDouble(cx, (double)val));
}
case value::List: {
- return OBJECT_TO_JSVAL(valuesToJSElements(cx, JS_NewArrayObject(cx, 0, NULL), val, 0));
+ if (isJSArray(val))
+ return OBJECT_TO_JSVAL(valuesToJSElements(cx, JS_NewArrayObject(cx, 0, NULL), val, 0));
+ return OBJECT_TO_JSVAL(valuesToJSProperties(cx, JS_NewObject(cx, NULL, NULL, NULL), val));
}
default: {
return JSVAL_VOID;
@@ -297,9 +330,9 @@ const failable<bool, std::string> writeList(const JSONContext& cx, const list<va
/**
* Context passed to the JSON write callback function.
*/
-template<typename R> class JSONWriteContext {
+template<typename R> class WriteContext {
public:
- JSONWriteContext(const JSONContext& cx, const lambda<R(R, std::string)>& reduce, const R& accum) : cx(cx), reduce(reduce), accum(accum) {
+ WriteContext(const JSONContext& cx, const lambda<R(R, std::string)>& reduce, const R& accum) : cx(cx), reduce(reduce), accum(accum) {
}
const JSONContext& cx;
const lambda<R(R, std::string)> reduce;
@@ -310,7 +343,7 @@ public:
* Called by JS_Stringify to write JSON out.
*/
template<typename R> JSBool writeCallback(const jschar *buf, uint32 len, void *data) {
- JSONWriteContext<R>& wcx = *(static_cast<JSONWriteContext<R>*> (data));
+ WriteContext<R>& wcx = *(static_cast<WriteContext<R>*> (data));
JSString* jstr = JS_NewUCStringCopyN(wcx.cx, buf, len);
wcx.accum = wcx.reduce(wcx.accum, std::string(JS_GetStringBytes(jstr), JS_GetStringLength(jstr)));
return JS_TRUE;
@@ -319,14 +352,14 @@ template<typename R> JSBool writeCallback(const jschar *buf, uint32 len, void *d
/**
* Convert a list of values to a JSON document.
*/
-template<typename R> const failable<R, std::string> writeJSON(const JSONContext& cx, const lambda<R(R, std::string)>& reduce, const R& initial, const list<value>& l) {
+template<typename R> const failable<R, std::string> write(const JSONContext& cx, const lambda<R(R, std::string)>& reduce, const R& initial, const list<value>& l) {
JSObject* o = JS_NewObject(cx, NULL, NULL, NULL);
jsval val = OBJECT_TO_JSVAL(o);
const failable<bool, std::string> w = writeList(cx, l, o);
if (!hasValue(w))
return std::string(w);
- JSONWriteContext<R> wcx(cx, reduce, initial);
+ WriteContext<R> wcx(cx, reduce, initial);
if (!JS_Stringify(cx, &val, NULL, JSVAL_NULL, writeCallback<R>, &wcx))
return std::string("JS_Stringify failed");
return wcx.accum;
@@ -335,17 +368,18 @@ template<typename R> const failable<R, std::string> writeJSON(const JSONContext&
/**
* Convert a list of values to a list of strings representing a JSON document.
*/
-const list<std::string> writeJSONList(const list<std::string>& listSoFar, const std::string& s) {
+const list<std::string> writeStrings(const list<std::string>& listSoFar, const std::string& s) {
return cons(s, listSoFar);
}
-const failable<list<std::string>, std::string> writeJSON(const JSONContext& cx, const list<value>& l) {
- const failable<list<std::string>, std::string> ls = writeJSON<list<std::string> >(cx, writeJSONList, list<std::string>(), l);
+const failable<list<std::string>, std::string> write(const JSONContext& cx, const list<value>& l) {
+ const failable<list<std::string>, std::string> ls = write<list<std::string> >(cx, writeStrings, list<std::string>(), l);
if (!hasValue(ls))
return ls;
return reverse(list<std::string>(ls));
}
}
+}
#endif /* tuscany_json_hpp */