summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2010-06-13 03:55:02 -0400
committerJohn Wiegley <johnw@newartisans.com>2010-06-13 03:55:08 -0400
commit4a44218da15c5d4dfb29fc32dfe5818a5ac27b7a (patch)
treef263cca3ab24cdad7f76c68e32025feb21b09969
parent44a5103e1ce9f968df02ac6e1f86fcf9415a1983 (diff)
downloadfork-ledger-4a44218da15c5d4dfb29fc32dfe5818a5ac27b7a.tar.gz
fork-ledger-4a44218da15c5d4dfb29fc32dfe5818a5ac27b7a.tar.bz2
fork-ledger-4a44218da15c5d4dfb29fc32dfe5818a5ac27b7a.zip
For value_t, use boost::any to refer to objects
-rw-r--r--src/system.hh.in1
-rw-r--r--src/value.cc45
-rw-r--r--src/value.h81
3 files changed, 75 insertions, 52 deletions
diff --git a/src/system.hh.in b/src/system.hh.in
index 34efa424..d9e664e3 100644
--- a/src/system.hh.in
+++ b/src/system.hh.in
@@ -137,6 +137,7 @@ typedef std::ostream::pos_type ostream_pos_type;
#endif
#include <boost/algorithm/string.hpp>
+#include <boost/any.hpp>
#include <boost/bind.hpp>
#include <boost/cast.hpp>
#include <boost/current_function.hpp>
diff --git a/src/value.cc b/src/value.cc
index fd49e85c..99837832 100644
--- a/src/value.cc
+++ b/src/value.cc
@@ -116,8 +116,8 @@ value_t::operator bool() const
return false;
case SCOPE:
return as_scope() != NULL;
- case EXPR:
- return as_expr();
+ case ANY:
+ return ! as_any().empty();
default:
break;
}
@@ -145,12 +145,6 @@ void value_t::set_type(type_t new_type)
}
}
-void value_t::set_expr(const expr_t& val)
-{
- set_type(EXPR);
- storage->data = new expr_t(val);
-}
-
bool value_t::to_boolean() const
{
if (is_boolean()) {
@@ -1372,8 +1366,8 @@ bool value_t::is_realzero() const
case SCOPE:
return as_scope() == NULL;
- case EXPR:
- return ! as_expr();
+ case ANY:
+ return as_any().empty();
default:
add_error_context(_("While applying is_realzero to %1:") << *this);
@@ -1404,8 +1398,8 @@ bool value_t::is_zero() const
case SCOPE:
return as_scope() == NULL;
- case EXPR:
- return ! as_expr();
+ case ANY:
+ return as_any().empty();
default:
add_error_context(_("While applying is_zero to %1:") << *this);
@@ -1677,7 +1671,7 @@ value_t value_t::strip_annotations(const keep_details_t& what_to_keep) const
case STRING:
case MASK:
case SCOPE:
- case EXPR:
+ case ANY:
return *this;
case SEQUENCE: {
@@ -1825,13 +1819,14 @@ void value_t::print(std::ostream& out,
case SCOPE:
out << "<#SCOPE>";
break;
- case EXPR:
- out << "<#EXPR ";
- if (as_expr())
- as_expr().print(out);
- else
- out << "null";
- out << ">";
+ case ANY:
+ if (as_any().type() == typeid(expr_t::ptr_op_t)) {
+ out << "<#EXPR ";
+ as_any<expr_t::ptr_op_t>()->print(out);
+ out << ">";
+ } else {
+ out << "<#OBJECT>";
+ }
break;
default:
@@ -1902,11 +1897,11 @@ void value_t::dump(std::ostream& out, const bool relaxed) const
case SCOPE:
out << as_scope();
break;
- case EXPR:
- if (as_expr())
- as_expr().dump(out);
+ case ANY:
+ if (as_any().type() == typeid(expr_t::ptr_op_t))
+ as_any<expr_t::ptr_op_t>()->dump(out);
else
- out << "null";
+ out << boost::unsafe_any_cast<const void *>(&as_any());
break;
case SEQUENCE: {
@@ -2020,7 +2015,7 @@ void to_xml(std::ostream& out, const value_t& value)
}
case value_t::SCOPE:
- case value_t::EXPR:
+ case value_t::ANY:
default:
assert(false);
break;
diff --git a/src/value.h b/src/value.h
index 7bd09c9a..361282c4 100644
--- a/src/value.h
+++ b/src/value.h
@@ -57,7 +57,6 @@ namespace ledger {
DECLARE_EXCEPTION(value_error, std::runtime_error);
class scope_t;
-class expr_t;
/**
* @class value_t
@@ -110,7 +109,7 @@ public:
MASK, // a regular expression mask
SEQUENCE, // a vector of value_t objects
SCOPE, // a pointer to a scope
- EXPR // a pointer to a value expression
+ ANY // a pointer to an arbitrary object
};
private:
@@ -128,17 +127,17 @@ private:
* The `type' member holds the value_t::type_t value representing
* the type of the object stored.
*/
- variant<bool, // BOOLEAN
- datetime_t, // DATETIME
- date_t, // DATE
- long, // INTEGER
- amount_t, // AMOUNT
- balance_t *, // BALANCE
- string, // STRING
- mask_t, // MASK
- sequence_t *, // SEQUENCE
- scope_t *, // SCOPE
- expr_t * // EXPR
+ variant<bool, // BOOLEAN
+ datetime_t, // DATETIME
+ date_t, // DATE
+ long, // INTEGER
+ amount_t, // AMOUNT
+ balance_t *, // BALANCE
+ string, // STRING
+ mask_t, // MASK
+ sequence_t *, // SEQUENCE
+ scope_t *, // SCOPE
+ boost::any // ANY
> data;
type_t type;
@@ -354,10 +353,13 @@ public:
TRACE_CTOR(value_t, "scope_t *");
set_scope(item);
}
- explicit value_t(const expr_t& item) {
- TRACE_CTOR(value_t, "const expr_t&");
- set_expr(item);
+#if 0
+ template <typename T>
+ explicit value_t(T& item) {
+ TRACE_CTOR(value_t, "T&");
+ set_any(item);
}
+#endif
/**
* Destructor. This does not do anything, because the intrusive_ptr
@@ -530,7 +532,7 @@ public:
* is_string()
* is_mask()
* is_sequence()
- * is_pointer()
+ * is_any()
*
* There are corresponding as_*() methods that represent a value as a
* reference to its underlying type. For example, as_long() returns a
@@ -729,20 +731,45 @@ public:
}
/**
- * Dealing with expr pointers.
+ * Dealing with any type at all is bit involved because we actually
+ * deal with typed object. For example, if you call as_any it returns
+ * a boost::any object, but if you use as_any<type_t>, then it returns
+ * a type_t by value.
*/
- bool is_expr() const {
- return is_type(EXPR);
+ bool is_any() const {
+ return is_type(ANY);
+ }
+ template <typename T>
+ bool is_any() const {
+ return (is_type(ANY) &&
+ boost::get<boost::any>(storage->data).type() == typeid(T));
}
- expr_t& as_expr_lval() const {
- VERIFY(is_expr());
- return *boost::get<expr_t *>(storage->data);
+ boost::any& as_any_lval() {
+ VERIFY(is_any());
+ _dup();
+ return boost::get<boost::any>(storage->data);
+ }
+ template <typename T>
+ T& as_any_lval() {
+ return any_cast<T&>(as_any_lval());
}
- const expr_t& as_expr() const {
- VERIFY(is_expr());
- return *boost::get<expr_t *>(storage->data);
+ const boost::any& as_any() const {
+ VERIFY(is_any());
+ return boost::get<boost::any>(storage->data);
+ }
+ template <typename T>
+ const T& as_any() const {
+ return any_cast<const T&>(as_any());
+ }
+ void set_any(const boost::any& val) {
+ set_type(ANY);
+ storage->data = val;
+ }
+ template <typename T>
+ void set_any(T& val) {
+ set_type(ANY);
+ storage->data = boost::any(val);
}
- void set_expr(const expr_t& val);
/**
* Data conversion methods. These methods convert a value object to