summaryrefslogtreecommitdiffstats
path: root/sca-cpp/branches/lightweight-sca/kernel/value.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'sca-cpp/branches/lightweight-sca/kernel/value.hpp')
-rw-r--r--sca-cpp/branches/lightweight-sca/kernel/value.hpp656
1 files changed, 656 insertions, 0 deletions
diff --git a/sca-cpp/branches/lightweight-sca/kernel/value.hpp b/sca-cpp/branches/lightweight-sca/kernel/value.hpp
new file mode 100644
index 0000000000..206fe8b32b
--- /dev/null
+++ b/sca-cpp/branches/lightweight-sca/kernel/value.hpp
@@ -0,0 +1,656 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+/* $Rev$ $Date$ */
+
+#ifndef tuscany_value_hpp
+#define tuscany_value_hpp
+
+/**
+ * Generic value type.
+ */
+
+#include <stdlib.h>
+#include <apr_uuid.h>
+#include <apr_time.h>
+
+#include "string.hpp"
+#include "sstream.hpp"
+#include "gc.hpp"
+#include "function.hpp"
+#include "list.hpp"
+#include "monad.hpp"
+
+namespace tuscany
+{
+
+#ifdef WANT_MAINTAINER_COUNTERS
+
+/**
+ * Debug utilities. Counters used to track instances of values
+ */
+long int countValues = 0;
+long int countEValues = 0;
+long int countCValues = 0;
+long int countVValues = 0;
+
+bool resetValueCounters() {
+ countValues = countEValues = countCValues = countVValues = 0;
+ return true;
+}
+
+bool checkValueCounters() {
+ return countValues == 0;
+}
+
+bool printValueCounters() {
+ cout << "countValues " << countValues << endl;
+ cout << "countEValues " << countEValues << endl;
+ cout << "countCValues " << countCValues << endl;
+ cout << "countVValues " << countVValues << endl;
+ return true;
+}
+
+#else
+
+#define resetValueCounters()
+#define checkValueCounters() true
+#define printValueCounters()
+
+#endif
+
+#ifdef WANT_MAINTAINER_WATCH
+
+/**
+ * Debug utilities. Macro used to write the contents of a value to
+ * a string, easier to watch in a debugger than the value itself.
+ */
+
+#define debug_watchValue() do { \
+ this->watch = watchValue(*this); \
+ } while (0)
+
+#else
+
+#define debug_watchValue()
+
+#endif
+
+class value;
+
+class value {
+public:
+
+ enum ValueType {
+ Nil, Symbol, String, List, Number, Bool, Lambda, Ptr
+ };
+
+ value() : type(value::Nil) {
+ debug_inc(countValues);
+ debug_inc(countEValues);
+ debug_watchValue();
+ }
+
+ value(const value& v) {
+ debug_inc(countValues);
+ debug_inc(countCValues);
+ type = v.type;
+ switch(type) {
+ case value::List:
+ lst() = v.lst();
+ case value::Lambda:
+ func() = v.func();
+ case value::Symbol:
+ str() = v.str();
+ case value::String:
+ str() = v.str();
+ case value::Number:
+ num() = v.num();
+ case value::Bool:
+ boo() = v.boo();
+ case value::Ptr:
+ ptr() = v.ptr();
+ default:
+ break;
+ }
+#ifdef WANT_MAINTAINER_WATCH
+ watch = v.watch;
+#endif
+ }
+
+ virtual ~value() {
+ debug_dec(countValues);
+ }
+
+ value(const lambda<value(const list<value>&)>& func) : type(value::Lambda), data(vdata(func)) {
+ debug_inc(countValues);
+ debug_inc(countVValues);
+ debug_watchValue();
+ }
+
+ value(const string& str) : type(value::String), data(vdata(result(str))) {
+ debug_inc(countValues);
+ debug_inc(countVValues);
+ debug_watchValue();
+ }
+
+ value(const char* str) : type(value::Symbol), data(vdata(result(string(str)))) {
+ debug_inc(countValues);
+ debug_inc(countVValues);
+ debug_watchValue();
+ }
+
+ value(const list<value>& lst) : type(value::List), data(vdata(result(lst))) {
+ debug_inc(countValues);
+ debug_inc(countVValues);
+ debug_watchValue();
+ }
+
+ value(const list<list<value> >& l) : type(value::List), data(vdata(result(listOfValues(l)))) {
+ debug_inc(countValues);
+ debug_inc(countVValues);
+ debug_watchValue();
+ }
+
+ value(const double num) : type(value::Number), data(vdata(result(num))) {
+ debug_inc(countValues);
+ debug_inc(countVValues);
+ debug_watchValue();
+ }
+
+ value(const int num) : type(value::Number), data(vdata(result((double)num))) {
+ debug_inc(countValues);
+ debug_inc(countVValues);
+ debug_watchValue();
+ }
+
+ value(const bool boo) : type(value::Bool), data(vdata(result(boo))) {
+ debug_inc(countValues);
+ debug_inc(countVValues);
+ debug_watchValue();
+ }
+
+ value(const gc_ptr<value> ptr) : type(value::Ptr), data(vdata(result(ptr))) {
+ debug_inc(countValues);
+ debug_inc(countVValues);
+ debug_watchValue();
+ }
+
+ value(const failable<value>& m) : type(value::List),
+ data(vdata(result(hasContent(m)? mklist<value>(content(m)) : rcode(m) == 1? mklist<value>(value(), reason(m)) : mklist<value>(value(), reason(m), rcode(m))))) {
+ debug_inc(countValues);
+ debug_inc(countVValues);
+ debug_watchValue();
+ }
+
+ value(const maybe<value>& m) : type(value::List),
+ data(vdata(result(hasContent(m)? mklist<value>(content(m)) : list<value>()))) {
+ debug_inc(countValues);
+ debug_inc(countVValues);
+ debug_watchValue();
+ }
+
+ const value& operator=(const value& v) {
+ if(this == &v)
+ return *this;
+ type = v.type;
+ switch(type) {
+ case value::List:
+ lst() = v.lst();
+ case value::Lambda:
+ func() = v.func();
+ case value::Symbol:
+ str() = v.str();
+ case value::String:
+ str() = v.str();
+ case value::Number:
+ num() = v.num();
+ case value::Bool:
+ boo() = v.boo();
+ case value::Ptr:
+ ptr() = v.ptr();
+ default:
+ break;
+ }
+#ifdef WANT_MAINTAINER_WATCH
+ watch = v.watch;
+#endif
+ return *this;
+ }
+
+ const bool operator!=(const value& v) const {
+ return !this->operator==(v);
+ }
+
+ const bool operator==(const value& v) const {
+ if(this == &v)
+ return true;
+ switch(type) {
+ case value::Nil:
+ return v.type == value::Nil;
+ case value::List:
+ return v.type == value::List && lst()() == v.lst()();
+ case value::Lambda:
+ return v.type == value::Lambda && func() == v.func();
+ case value::Symbol:
+ case value::String:
+ return str()() == (string)v;
+ case value::Number:
+ return num()() == (double)v;
+ case value::Bool:
+ return boo()() == (bool)v;
+ case value::Ptr:
+ return v.type == value::Ptr && ptr()() == v.ptr()();
+ default:
+ return false;
+ }
+ }
+
+ const bool operator<(const value& v) const {
+ if(this == &v)
+ return false;
+ switch(type) {
+ case value::List:
+ return v.type == value::List && lst()() < v.lst()();
+ case value::Symbol:
+ case value::String:
+ return str()() < (string)v;
+ case value::Bool:
+ return boo()() < (bool)v;
+ case value::Number:
+ return num()() < (double)v;
+ default:
+ return false;
+ }
+ }
+
+ const bool operator>(const value& v) const {
+ if(this == &v)
+ return false;
+ switch(type) {
+ case value::List:
+ return v.type == value::List && lst()() > v.lst()();
+ case value::Symbol:
+ case value::String:
+ return str()() > (string)v;
+ case value::Bool:
+ return boo()() > (bool)v;
+ case value::Number:
+ return num()() > (double)v;
+ default:
+ return false;
+ }
+ }
+
+ const value operator()(const list<value>& args) const {
+ return func()(args);
+ }
+
+ operator const string() const {
+ switch(type) {
+ case value::Symbol:
+ case value::String:
+ return str()();
+ case value::Number: {
+ ostringstream os;
+ os << num()();
+ return tuscany::str(os);
+ }
+ case value::Bool:
+ return boo()()? trueString : falseString;
+ default:
+ return emptyString;
+ }
+ }
+
+ operator const double() const {
+ switch(type) {
+ case value::Symbol:
+ case value::String:
+ return atof(c_str(str()()));
+ case value::Number:
+ return (double)num()();
+ case value::Bool:
+ return boo()()? 1.0 : 0.0;
+ default:
+ return 0.0;
+ }
+ }
+
+ operator const int() const {
+ switch(type) {
+ case value::Symbol:
+ case value::String:
+ return atoi(c_str(str()()));
+ case value::Number:
+ return (int)num()();
+ case value::Bool:
+ return boo()()? 1 : 0;
+ default:
+ return 0;
+ }
+ }
+
+ operator const bool() const {
+ switch(type) {
+ case value::Symbol:
+ case value::String:
+ return str()() == string("true");
+ case value::Number:
+ return (int)num()() != 0;
+ case value::Bool:
+ return boo()();
+ default:
+ return 0;
+ }
+ }
+
+ operator const gc_ptr<value>() const {
+ return ptr()();
+ }
+
+ operator const list<value>() const {
+ return lst()();
+ }
+
+ operator const list<list<value> >() const {
+ return listOfListOfValues(lst()());
+ }
+
+ operator const lambda<value(const list<value>&)>() const {
+ return func();
+ }
+
+private:
+ template<typename T> lambda<T>& vdata() const {
+ return *reinterpret_cast<lambda<T> *> (const_cast<lambda<char()> *> (&data));
+ }
+
+ template<typename T> const lambda<char()>& vdata(const T& v) const {
+ return *reinterpret_cast<const lambda<char()> *> (&v);
+ }
+
+ lambda<double()>& num() const {
+ return vdata<double()> ();
+ }
+
+ lambda<bool()>& boo() const {
+ return vdata<bool()> ();
+ }
+
+ lambda<gc_ptr<value>()>& ptr() const {
+ return vdata<gc_ptr<value>()> ();
+ }
+
+ lambda<string()>& str() const {
+ return vdata<string()> ();
+ }
+
+ lambda<list<value>()>& lst() const {
+ return vdata<list<value>()> ();
+ }
+
+ lambda<value(const list<value>&)>& func() const {
+ return vdata<value(const list<value>&)> ();
+ }
+
+ const list<value> listOfValues(const list<list<value> >& l) const {
+ if (isNil(l))
+ return list<value>();
+ return cons<value>(car(l), listOfValues(cdr(l)));
+ }
+
+ const list<list<value> > listOfListOfValues(const list<value>& l) const {
+ if (isNil(l))
+ return list<list<value> >();
+ return cons<list<value> >(list<value>(car(l)), listOfListOfValues(cdr(l)));
+ }
+
+ friend ostream& operator<<(ostream&, const value&);
+ friend const value::ValueType type(const value& v);
+
+#ifdef WANT_MAINTAINER_WATCH
+ friend const string watchValue(const value& v);
+ string watch;
+#endif
+
+ ValueType type;
+ lambda<char()> data;
+};
+
+#ifdef WANT_MAINTAINER_WATCH
+
+/**
+ * Debug utility used to write the contents of a value to a string, easier
+ * to watch than the value itself in a debugger.
+ */
+const string watchValue(const value& v) {
+ if (v.type == value::List)
+ return watchList<value>(v);
+ odebugstream os;
+ os << v;
+ return str(os);
+}
+
+#endif
+
+/**
+ * Write an escape string to a buffer.
+ */
+const char* escapestr(const char* s, char* buf) {
+ if (*s == '\0') {
+ *buf = '\0';
+ return buf;
+ }
+ if (*s == '\\' || *s == '"') {
+ *buf = '\\';
+ *(buf + 1) = *s;
+ return escapestr(s + 1, buf + 2);
+ }
+ *buf = *s;
+ return escapestr(s + 1, buf + 1);
+}
+
+/**
+ * Write an escaped string value to a stream.
+ */
+ostream& escvwrite(const string& str, ostream& out) {
+ char* buf = gc_cnew(length(str) * 2 + 1);
+ escapestr(c_str(str), buf);
+ out << buf;
+ return out;
+}
+
+/**
+ * Write a value to a stream.
+ */
+ostream& operator<<(ostream& out, const value& v) {
+ switch(v.type) {
+ case value::List:
+ return out << v.lst()();
+ case value::Lambda:
+ return out << "lambda::" << v.func();
+ case value::Symbol:
+ return out << v.str()();
+ case value::String:
+ out << '\"';
+ escvwrite(v.str()(), out);
+ return out << '\"';
+ case value::Number:
+ return out << v.num()();
+ case value::Bool:
+ if(v.boo()())
+ return out << "true";
+ else
+ return out << "false";
+ case value::Ptr: {
+ const gc_ptr<value> p = v.ptr()();
+ if (p == gc_ptr<value>(NULL))
+ return out << "gc_ptr::null";
+ return out << "gc_ptr::" << p;
+ }
+ default:
+ return out << "nil";
+ }
+}
+
+/**
+ * Returns the type of a value.
+ */
+const value::ValueType type(const value& v) {
+ return v.type;
+}
+
+/**
+ * Returns true if a value is nil.
+ */
+const bool isNil(const value& v) {
+ return type(v) == value::Nil;
+}
+
+/**
+ * Returns true if a value is a lambda.
+ */
+const bool isLambda(const value& v) {
+ return type(v) == value::Lambda;
+}
+
+/**
+ * Returns true if a value is a string.
+ */
+const bool isString(const value& v) {
+ return type(v) == value::String;
+}
+
+/**
+ * Returns true if a value is a symbol.
+ */
+const bool isSymbol(const value& v) {
+ return type(v) == value::Symbol;
+}
+
+/**
+ * Returns true if a value is a list.
+ */
+const bool isList(const value& v) {
+ return type(v) == value::List;
+}
+
+/**
+ * Returns true if a value is a number.
+ */
+const bool isNumber(const value& v) {
+ return type(v) == value::Number;
+}
+
+/**
+ * Returns true if a value is a boolean.
+ */
+const bool isBool(const value& v) {
+ return type(v) == value::Bool;
+}
+
+/**
+ * Returns true if a value is a pointer.
+ */
+const bool isPtr(const value& v) {
+ return type(v) == value::Ptr;
+}
+
+/**
+ * Returns true if a value is a tagged list.
+ */
+const bool isTaggedList(const value& exp, value tag) {
+ if(isList(exp) && !isNil((list<value>)exp))
+ return car((list<value>)exp) == tag;
+ return false;
+}
+
+/**
+ * Make a list of values from a list of other things.
+ */
+template<typename T> const list<value> mkvalues(const list<T>& l) {
+ if (isNil(l))
+ return list<value>();
+ return cons<value>(car(l), mkvalues(cdr(l)));
+}
+
+/**
+ * Convert a list of values to a list of other things.
+ */
+template<typename T> const list<T> convertValues(const list<value>& l) {
+ if (isNil(l))
+ return list<T>();
+ return cons<T>(car(l), convertValues<T>(cdr(l)));
+}
+
+/**
+ * Convert a path string value to a list of values.
+ */
+const list<string> pathTokens(const char* p) {
+ if (p == NULL || p[0] == '\0')
+ return list<string>();
+ if (p[0] == '/')
+ return tokenize("/", p + 1);
+ return tokenize("/", p);
+}
+
+const list<value> pathValues(const value& p) {
+ return mkvalues(pathTokens(c_str(p)));
+}
+
+/**
+ * Convert a path represented as a list of values to a string value.
+ */
+const value path(const list<value>& p) {
+ if (isNil(p))
+ return "";
+ return string("/") + car(p) + path(cdr(p));
+}
+
+/**
+ * Make a uuid value.
+ */
+const value mkuuid() {
+ apr_uuid_t id;
+ apr_uuid_get(&id);
+ char buf[APR_UUID_FORMATTED_LENGTH];
+ apr_uuid_format(buf, &id);
+ return value(string(buf, APR_UUID_FORMATTED_LENGTH));
+}
+
+/**
+ * Make a random alphanumeric value.
+ */
+const int intrand() {
+ const apr_uint64_t now = apr_time_now();
+ srand((unsigned int)(((now >> 32) ^ now) & 0xffffffff));
+ return rand() & 0x0FFFF;
+}
+
+const value mkrand() {
+ char buf[32];
+ const char* an = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
+ for (int i =0; i < 32; i++)
+ buf[i] = an[intrand() % 62];
+ return value(string(buf, 32));
+}
+
+}
+#endif /* tuscany_value_hpp */