summaryrefslogtreecommitdiff
path: root/src/value.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/value.cc')
-rw-r--r--src/value.cc580
1 files changed, 310 insertions, 270 deletions
diff --git a/src/value.cc b/src/value.cc
index e9313f0c..c34792b2 100644
--- a/src/value.cc
+++ b/src/value.cc
@@ -35,7 +35,7 @@
#include "commodity.h"
#include "annotate.h"
#include "pool.h"
-#include "unistring.h" // for justify()
+#include "unistring.h" // for justify()
#include "op.h"
namespace ledger {
@@ -65,11 +65,11 @@ value_t::storage_t& value_t::storage_t::operator=(const value_t::storage_t& rhs)
void value_t::initialize()
{
- true_value = new storage_t;
+ true_value = new storage_t;
true_value->type = BOOLEAN;
true_value->data = true;
- false_value = new storage_t;
+ false_value = new storage_t;
false_value->type = BOOLEAN;
false_value->data = false;
}
@@ -103,26 +103,28 @@ value_t::operator bool() const
std::ostringstream out;
out << *this;
throw_(value_error,
- _("Cannot determine truth of %1 (did you mean 'account =~ %2'?)")
- << label() << out.str());
+ _("Cannot determine truth of %1 (did you mean 'account =~ %2'?)")
+ << label() << out.str());
}
case SEQUENCE:
if (! as_sequence().empty()) {
foreach (const value_t& value, as_sequence()) {
- if (value)
- return true;
+ if (value)
+ return true;
}
}
return false;
case SCOPE:
return as_scope() != NULL;
- case EXPR:
- return as_expr();
+ case ANY:
+ return ! as_any().empty();
default:
break;
}
+ add_error_context(_("While taking boolean value of %1:") << *this);
throw_(value_error, _("Cannot determine truth of %1") << label());
+
return false;
}
@@ -143,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()) {
@@ -279,7 +275,7 @@ void value_t::in_place_simplify()
DEBUG_("as an amount it looks like: " << *this);
}
-#ifdef REDUCE_TO_INTEGER // this is off by default
+#ifdef REDUCE_TO_INTEGER // this is off by default
if (is_amount() && ! as_amount().has_commodity() &&
as_amount().fits_in_long()) {
DEBUG_("Reducing amount to integer");
@@ -305,7 +301,7 @@ value_t value_t::number() const
if (! as_sequence().empty()) {
value_t temp;
foreach (const value_t& value, as_sequence())
- temp += value.number();
+ temp += value.number();
return temp;
}
break;
@@ -313,7 +309,9 @@ value_t value_t::number() const
break;
}
+ add_error_context(_("While calling number() on %1:") << *this);
throw_(value_error, _("Cannot determine numeric value of %1") << label());
+
return false;
}
@@ -329,16 +327,17 @@ value_t& value_t::operator+=(const value_t& val)
else if (is_sequence()) {
if (val.is_sequence()) {
if (size() == val.size()) {
- sequence_t::iterator i = begin();
- sequence_t::const_iterator j = val.begin();
+ sequence_t::iterator i = begin();
+ sequence_t::const_iterator j = val.begin();
- for (; i != end(); i++, j++)
- *i += *j;
+ for (; i != end(); i++, j++)
+ *i += *j;
} else {
- throw_(value_error, _("Cannot add sequences of different lengths"));
+ add_error_context(_("While adding %1 to %2:") << *this << val);
+ throw_(value_error, _("Cannot add sequences of different lengths"));
}
} else {
- as_sequence_lval().push_back(val);
+ as_sequence_lval().push_back(new value_t(val));
}
return *this;
}
@@ -348,12 +347,12 @@ value_t& value_t::operator+=(const value_t& val)
switch (val.type()) {
case INTEGER:
as_datetime_lval() +=
- time_duration_t(0, 0, static_cast<time_duration_t::sec_type>(val.as_long()));
+ time_duration_t(0, 0, static_cast<time_duration_t::sec_type>(val.as_long()));
return *this;
case AMOUNT:
as_datetime_lval() +=
- time_duration_t(0, 0, static_cast<time_duration_t::sec_type>
- (val.as_amount().to_long()));
+ time_duration_t(0, 0, static_cast<time_duration_t::sec_type>
+ (val.as_amount().to_long()));
return *this;
default:
break;
@@ -380,8 +379,8 @@ value_t& value_t::operator+=(const value_t& val)
return *this;
case AMOUNT:
if (val.as_amount().has_commodity()) {
- in_place_cast(BALANCE);
- return *this += val;
+ in_place_cast(BALANCE);
+ return *this += val;
}
in_place_cast(AMOUNT);
as_amount_lval() += val.as_amount();
@@ -399,21 +398,21 @@ value_t& value_t::operator+=(const value_t& val)
switch (val.type()) {
case INTEGER:
if (as_amount().has_commodity()) {
- in_place_cast(BALANCE);
- return *this += val;
+ in_place_cast(BALANCE);
+ return *this += val;
} else {
- as_amount_lval() += val.as_long();
- return *this;
+ as_amount_lval() += val.as_long();
+ return *this;
}
break;
case AMOUNT:
if (as_amount().commodity() != val.as_amount().commodity()) {
- in_place_cast(BALANCE);
- return *this += val;
+ in_place_cast(BALANCE);
+ return *this += val;
} else {
- as_amount_lval() += val.as_amount();
- return *this;
+ as_amount_lval() += val.as_amount();
+ return *this;
}
break;
@@ -447,7 +446,9 @@ value_t& value_t::operator+=(const value_t& val)
break;
}
+ add_error_context(_("While adding %1 to %2:") << *this << val);
throw_(value_error, _("Cannot add %1 to %2") << val.label() << label());
+
return *this;
}
@@ -458,18 +459,19 @@ value_t& value_t::operator-=(const value_t& val)
if (val.is_sequence()) {
if (size() == val.size()) {
- sequence_t::iterator i = begin();
- sequence_t::const_iterator j = val.begin();
+ sequence_t::iterator i = begin();
+ sequence_t::const_iterator j = val.begin();
- for (; i != end(); i++, j++)
- *i -= *j;
+ for (; i != end(); i++, j++)
+ *i -= *j;
} else {
- throw_(value_error, _("Cannot subtract sequences of different lengths"));
+ add_error_context(_("While subtracting %1 to %2:") << *this << val);
+ throw_(value_error, _("Cannot subtract sequences of different lengths"));
}
} else {
sequence_t::iterator i = std::find(seq.begin(), seq.end(), val);
if (i != seq.end())
- seq.erase(i);
+ seq.erase(i);
}
return *this;
}
@@ -479,12 +481,12 @@ value_t& value_t::operator-=(const value_t& val)
switch (val.type()) {
case INTEGER:
as_datetime_lval() -=
- time_duration_t(0, 0, static_cast<time_duration_t::sec_type>(val.as_long()));
+ time_duration_t(0, 0, static_cast<time_duration_t::sec_type>(val.as_long()));
return *this;
case AMOUNT:
as_datetime_lval() -=
- time_duration_t(0, 0, static_cast<time_duration_t::sec_type>
- (val.as_amount().to_long()));
+ time_duration_t(0, 0, static_cast<time_duration_t::sec_type>
+ (val.as_amount().to_long()));
return *this;
default:
break;
@@ -528,27 +530,27 @@ value_t& value_t::operator-=(const value_t& val)
switch (val.type()) {
case INTEGER:
if (as_amount().has_commodity()) {
- in_place_cast(BALANCE);
- *this -= val;
- in_place_simplify();
- return *this;
+ in_place_cast(BALANCE);
+ *this -= val;
+ in_place_simplify();
+ return *this;
} else {
- as_amount_lval() -= val.as_long();
- in_place_simplify();
- return *this;
+ as_amount_lval() -= val.as_long();
+ in_place_simplify();
+ return *this;
}
break;
case AMOUNT:
if (as_amount().commodity() != val.as_amount().commodity()) {
- in_place_cast(BALANCE);
- *this -= val;
- in_place_simplify();
- return *this;
+ in_place_cast(BALANCE);
+ *this -= val;
+ in_place_simplify();
+ return *this;
} else {
- as_amount_lval() -= val.as_amount();
- in_place_simplify();
- return *this;
+ as_amount_lval() -= val.as_amount();
+ in_place_simplify();
+ return *this;
}
break;
@@ -586,6 +588,7 @@ value_t& value_t::operator-=(const value_t& val)
break;
}
+ add_error_context(_("While subtracting %1 from %2:") << *this << val);
throw_(value_error, _("Cannot subtract %1 from %2") << val.label() << label());
return *this;
@@ -633,8 +636,8 @@ value_t& value_t::operator*=(const value_t& val)
return *this;
case BALANCE:
if (val.as_balance().single_amount()) {
- as_amount_lval() *= val.simplified().as_amount();
- return *this;
+ as_amount_lval() *= val.simplified().as_amount();
+ return *this;
}
break;
default:
@@ -649,13 +652,13 @@ value_t& value_t::operator*=(const value_t& val)
return *this;
case AMOUNT:
if (as_balance().single_amount()) {
- in_place_simplify();
- as_amount_lval() *= val.as_amount();
- return *this;
+ in_place_simplify();
+ as_amount_lval() *= val.as_amount();
+ return *this;
}
else if (! val.as_amount().has_commodity()) {
- as_balance_lval() *= val.as_amount();
- return *this;
+ as_balance_lval() *= val.as_amount();
+ return *this;
}
break;
default:
@@ -667,9 +670,7 @@ value_t& value_t::operator*=(const value_t& val)
break;
}
- DEBUG("value.multiply.error", "Left: " << *this);
- DEBUG("value.multiply.error", "Right: " << val);
-
+ add_error_context(_("While multiplying %1 with %2:") << *this << val);
throw_(value_error, _("Cannot multiply %1 with %2") << label() << val.label());
return *this;
@@ -702,19 +703,19 @@ value_t& value_t::operator/=(const value_t& val)
return *this;
case BALANCE:
if (val.as_balance().single_amount()) {
- value_t simpler(val.simplified());
- switch (simpler.type()) {
- case INTEGER:
- as_amount_lval() /= simpler.as_long();
- break;
- case AMOUNT:
- as_amount_lval() /= simpler.as_amount();
- break;
- default:
- assert(false);
- break;
- }
- return *this;
+ value_t simpler(val.simplified());
+ switch (simpler.type()) {
+ case INTEGER:
+ as_amount_lval() /= simpler.as_long();
+ break;
+ case AMOUNT:
+ as_amount_lval() /= simpler.as_amount();
+ break;
+ default:
+ assert(false);
+ break;
+ }
+ return *this;
}
break;
default:
@@ -729,13 +730,13 @@ value_t& value_t::operator/=(const value_t& val)
return *this;
case AMOUNT:
if (as_balance().single_amount()) {
- in_place_simplify();
- as_amount_lval() /= val.as_amount();
- return *this;
+ in_place_simplify();
+ as_amount_lval() /= val.as_amount();
+ return *this;
}
else if (! val.as_amount().has_commodity()) {
- as_balance_lval() /= val.as_amount();
- return *this;
+ as_balance_lval() /= val.as_amount();
+ return *this;
}
break;
default:
@@ -747,6 +748,7 @@ value_t& value_t::operator/=(const value_t& val)
break;
}
+ add_error_context(_("While dividing %1 by %2:") << *this << val);
throw_(value_error, _("Cannot divide %1 by %2") << label() << val.label());
return *this;
@@ -832,6 +834,7 @@ bool value_t::is_equal_to(const value_t& val) const
break;
}
+ add_error_context(_("While comparing equality of %1 to %2:") << *this << val);
throw_(value_error, _("Cannot compare %1 to %2") << label() << val.label());
return *this;
@@ -843,16 +846,16 @@ bool value_t::is_less_than(const value_t& val) const
case BOOLEAN:
if (val.is_boolean()) {
if (as_boolean()) {
- if (! val.as_boolean())
- return false;
- else
- return false;
+ if (! val.as_boolean())
+ return false;
+ else
+ return false;
}
else if (! as_boolean()) {
- if (! val.as_boolean())
- return false;
- else
- return true;
+ if (! val.as_boolean())
+ return false;
+ else
+ return true;
}
}
break;
@@ -884,11 +887,11 @@ bool value_t::is_less_than(const value_t& val) const
return as_amount() < val.as_long();
case AMOUNT:
if (as_amount().commodity() == val.as_amount().commodity() ||
- ! as_amount().has_commodity() ||
- ! val.as_amount().has_commodity())
- return as_amount() < val.as_amount();
+ ! as_amount().has_commodity() ||
+ ! val.as_amount().has_commodity())
+ return as_amount() < val.as_amount();
else
- return commodity_t::compare_by_commodity()(&as_amount(), &val.as_amount());
+ return commodity_t::compare_by_commodity()(&as_amount(), &val.as_amount());
default:
break;
}
@@ -898,15 +901,12 @@ bool value_t::is_less_than(const value_t& val) const
switch (val.type()) {
case INTEGER:
case AMOUNT: {
- if (val.is_nonzero())
- break;
-
bool no_amounts = true;
foreach (const balance_t::amounts_map::value_type& pair,
- as_balance().amounts) {
- if (pair.second >= 0L)
- return false;
- no_amounts = false;
+ as_balance().amounts) {
+ if (pair.second >= val)
+ return false;
+ no_amounts = false;
}
return ! no_amounts;
}
@@ -924,14 +924,11 @@ bool value_t::is_less_than(const value_t& val) const
switch (val.type()) {
case INTEGER:
case AMOUNT: {
- if (val.is_nonzero())
- break;
-
bool no_amounts = true;
foreach (const value_t& value, as_sequence()) {
- if (value >= 0L)
- return false;
- no_amounts = false;
+ if (value >= val)
+ return false;
+ no_amounts = false;
}
return ! no_amounts;
}
@@ -939,14 +936,14 @@ bool value_t::is_less_than(const value_t& val) const
sequence_t::const_iterator i = as_sequence().begin();
sequence_t::const_iterator j = val.as_sequence().begin();
for (; (i != as_sequence().end() &&
- j != val.as_sequence().end()); i++, j++) {
- if (! ((*i) < (*j)))
- return false;
+ j != val.as_sequence().end()); i++, j++) {
+ if (! ((*i) < (*j)))
+ return false;
}
if (i == as_sequence().end())
- return true;
+ return true;
else
- return false;
+ return false;
break;
}
default:
@@ -958,6 +955,8 @@ bool value_t::is_less_than(const value_t& val) const
break;
}
+ add_error_context(_("While comparing if %1 is less than %2:")
+ << *this << val);
throw_(value_error, _("Cannot compare %1 to %2") << label() << val.label());
return *this;
@@ -968,16 +967,16 @@ bool value_t::is_greater_than(const value_t& val) const
switch (type()) {
if (val.is_boolean()) {
if (as_boolean()) {
- if (! val.as_boolean())
- return true;
- else
- return false;
+ if (! val.as_boolean())
+ return true;
+ else
+ return false;
}
else if (! as_boolean()) {
- if (! val.as_boolean())
- return false;
- else
- return false;
+ if (! val.as_boolean())
+ return false;
+ else
+ return false;
}
}
break;
@@ -1018,15 +1017,12 @@ bool value_t::is_greater_than(const value_t& val) const
switch (val.type()) {
case INTEGER:
case AMOUNT: {
- if (val.is_nonzero())
- break;
-
bool no_amounts = true;
foreach (const balance_t::amounts_map::value_type& pair,
- as_balance().amounts) {
- if (pair.second <= 0L)
- return false;
- no_amounts = false;
+ as_balance().amounts) {
+ if (pair.second <= val)
+ return false;
+ no_amounts = false;
}
return ! no_amounts;
}
@@ -1044,14 +1040,11 @@ bool value_t::is_greater_than(const value_t& val) const
switch (val.type()) {
case INTEGER:
case AMOUNT: {
- if (val.is_nonzero())
- break;
-
bool no_amounts = true;
foreach (const value_t& value, as_sequence()) {
- if (value <= 0L)
- return false;
- no_amounts = false;
+ if (value <= val)
+ return false;
+ no_amounts = false;
}
return ! no_amounts;
}
@@ -1059,14 +1052,14 @@ bool value_t::is_greater_than(const value_t& val) const
sequence_t::const_iterator i = as_sequence().begin();
sequence_t::const_iterator j = val.as_sequence().begin();
for (; (i != as_sequence().end() &&
- j != val.as_sequence().end()); i++, j++) {
- if (! ((*i) > (*j)))
- return false;
+ j != val.as_sequence().end()); i++, j++) {
+ if (! ((*i) > (*j)))
+ return false;
}
if (i == as_sequence().end())
- return false;
+ return false;
else
- return true;
+ return true;
break;
}
default:
@@ -1078,6 +1071,8 @@ bool value_t::is_greater_than(const value_t& val) const
break;
}
+ add_error_context(_("While comparing if %1 is greater than %2:")
+ << *this << val);
throw_(value_error, _("Cannot compare %1 to %2") << label() << val.label());
return *this;
@@ -1097,7 +1092,7 @@ void value_t::in_place_cast(type_t cast_type)
else if (cast_type == SEQUENCE) {
sequence_t temp;
if (! is_null())
- temp.push_back(*this);
+ temp.push_back(new value_t(*this));
set_sequence(temp);
return;
}
@@ -1181,21 +1176,21 @@ void value_t::in_place_cast(type_t cast_type)
switch (cast_type) {
case INTEGER:
if (amt.is_null())
- set_long(0L);
+ set_long(0L);
else
- set_long(as_amount().to_long());
+ set_long(as_amount().to_long());
return;
case BALANCE:
if (amt.is_null())
- set_balance(balance_t());
+ set_balance(balance_t());
else
- set_balance(as_amount());
+ set_balance(as_amount());
return;
case STRING:
if (amt.is_null())
- set_string("");
+ set_string("");
else
- set_string(as_amount().to_string());
+ set_string(as_amount().to_string());
return;
default:
break;
@@ -1208,27 +1203,28 @@ void value_t::in_place_cast(type_t cast_type)
switch (cast_type) {
case AMOUNT: {
if (bal.amounts.size() == 1) {
- // Because we are changing the current balance value to an amount
- // value, and because set_amount takes a reference (and that memory is
- // about to be repurposed), we must pass in a copy.
- set_amount(amount_t((*bal.amounts.begin()).second));
- return;
+ // Because we are changing the current balance value to an amount
+ // value, and because set_amount takes a reference (and that memory is
+ // about to be repurposed), we must pass in a copy.
+ set_amount(amount_t((*bal.amounts.begin()).second));
+ return;
}
else if (bal.amounts.size() == 0) {
- set_amount(0L);
- return;
+ set_amount(0L);
+ return;
}
else {
- throw_(value_error, _("Cannot convert %1 with multiple commodities to %2")
- << label() << label(cast_type));
+ add_error_context(_("While converting %1 to an amount:") << *this);
+ throw_(value_error, _("Cannot convert %1 with multiple commodities to %2")
+ << label() << label(cast_type));
}
break;
}
case STRING:
if (bal.is_empty())
- set_string("");
+ set_string("");
else
- set_string(as_balance().to_string());
+ set_string(as_balance().to_string());
return;
default:
break;
@@ -1240,8 +1236,8 @@ void value_t::in_place_cast(type_t cast_type)
switch (cast_type) {
case INTEGER: {
if (all(as_string(), is_digit())) {
- set_long(lexical_cast<long>(as_string()));
- return;
+ set_long(lexical_cast<long>(as_string()));
+ return;
}
break;
}
@@ -1266,8 +1262,9 @@ void value_t::in_place_cast(type_t cast_type)
break;
}
+ add_error_context(_("While converting %1:") << *this);
throw_(value_error,
- _("Cannot convert %1 to %2") << label() << label(cast_type));
+ _("Cannot convert %1 to %2") << label() << label(cast_type));
}
void value_t::in_place_negate()
@@ -1289,17 +1286,15 @@ void value_t::in_place_negate()
case BALANCE:
as_balance_lval().in_place_negate();
return;
- case SEQUENCE: {
- value_t temp;
- foreach (const value_t& value, as_sequence())
- temp.push_back(- value);
- *this = temp;
+ case SEQUENCE:
+ foreach (value_t& value, as_sequence_lval())
+ value.in_place_negate();
return;
- }
default:
break;
}
+ add_error_context(_("While negating %1:") << *this);
throw_(value_error, _("Cannot negate %1") << label());
}
@@ -1325,17 +1320,15 @@ void value_t::in_place_not()
case STRING:
set_boolean(as_string().empty());
return;
- case SEQUENCE: {
- value_t temp;
- foreach (const value_t& value, as_sequence())
- temp.push_back(! value);
- *this = temp;
+ case SEQUENCE:
+ foreach (value_t& value, as_sequence_lval())
+ value.in_place_not();
return;
- }
default:
break;
}
+ add_error_context(_("While applying not to %1:") << *this);
throw_(value_error, _("Cannot 'not' %1") << label());
}
@@ -1361,10 +1354,11 @@ 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);
throw_(value_error, _("Cannot determine if %1 is really zero") << label());
}
return false;
@@ -1392,18 +1386,18 @@ 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);
throw_(value_error, _("Cannot determine if %1 is zero") << label());
}
return false;
}
-value_t value_t::value(const bool primary_only,
- const optional<datetime_t>& moment,
- const optional<commodity_t&>& in_terms_of) const
+value_t value_t::value(const optional<datetime_t>& moment,
+ const optional<commodity_t&>& in_terms_of) const
{
switch (type()) {
case INTEGER:
@@ -1411,13 +1405,13 @@ value_t value_t::value(const bool primary_only,
case AMOUNT:
if (optional<amount_t> val =
- as_amount().value(primary_only, moment, in_terms_of))
+ as_amount().value(moment, in_terms_of))
return *val;
return NULL_VALUE;
case BALANCE:
if (optional<balance_t> bal =
- as_balance().value(primary_only, moment, in_terms_of))
+ as_balance().value(moment, in_terms_of))
return *bal;
return NULL_VALUE;
@@ -1425,6 +1419,7 @@ value_t value_t::value(const bool primary_only,
break;
}
+ add_error_context(_("While finding valuation of %1:") << *this);
throw_(value_error, _("Cannot find the value of %1") << label());
return NULL_VALUE;
}
@@ -1441,9 +1436,9 @@ value_t value_t::price() const
}
}
-value_t value_t::exchange_commodities(const std::string& commodities,
- const bool add_prices,
- const optional<datetime_t>& moment)
+value_t value_t::exchange_commodities(const std::string& commodities,
+ const bool add_prices,
+ const optional<datetime_t>& moment)
{
scoped_array<char> buf(new char[commodities.length() + 1]);
@@ -1453,11 +1448,11 @@ value_t value_t::exchange_commodities(const std::string& commodities,
p;
p = std::strtok(NULL, ",")) {
if (commodity_t * commodity =
- commodity_pool_t::current_pool->parse_price_expression(p, add_prices,
- moment)) {
- value_t result = value(false, moment, *commodity);
+ commodity_pool_t::current_pool->parse_price_expression(p, add_prices,
+ moment)) {
+ value_t result = value(moment, *commodity);
if (! result.is_null())
- return result;
+ return result;
}
}
return *this;
@@ -1472,6 +1467,10 @@ void value_t::in_place_reduce()
case BALANCE:
as_balance_lval().in_place_reduce();
return;
+ case SEQUENCE:
+ foreach (value_t& value, as_sequence_lval())
+ value.in_place_reduce();
+ return;
default:
return;
}
@@ -1488,6 +1487,10 @@ void value_t::in_place_unreduce()
case BALANCE:
as_balance_lval().in_place_unreduce();
return;
+ case SEQUENCE:
+ foreach (value_t& value, as_sequence_lval())
+ value.in_place_unreduce();
+ return;
default:
return;
}
@@ -1512,6 +1515,7 @@ value_t value_t::abs() const
break;
}
+ add_error_context(_("While taking abs of %1:") << *this);
throw_(value_error, _("Cannot abs %1") << label());
return NULL_VALUE;
}
@@ -1527,17 +1531,15 @@ void value_t::in_place_round()
case BALANCE:
as_balance_lval().in_place_round();
return;
- case SEQUENCE: {
- value_t temp;
- foreach (const value_t& value, as_sequence())
- temp.push_back(value.rounded());
- *this = temp;
+ case SEQUENCE:
+ foreach (value_t& value, as_sequence_lval())
+ value.in_place_round();
return;
- }
default:
break;
}
+ add_error_context(_("While rounding %1:") << *this);
throw_(value_error, _("Cannot set rounding for %1") << label());
}
@@ -1552,17 +1554,15 @@ void value_t::in_place_truncate()
case BALANCE:
as_balance_lval().in_place_truncate();
return;
- case SEQUENCE: {
- value_t temp;
- foreach (const value_t& value, as_sequence())
- temp.push_back(value.truncated());
- *this = temp;
+ case SEQUENCE:
+ foreach (value_t& value, as_sequence_lval())
+ value.in_place_truncate();
return;
- }
default:
break;
}
+ add_error_context(_("While truncating %1:") << *this);
throw_(value_error, _("Cannot truncate %1") << label());
}
@@ -1577,17 +1577,15 @@ void value_t::in_place_floor()
case BALANCE:
as_balance_lval().in_place_floor();
return;
- case SEQUENCE: {
- value_t temp;
- foreach (const value_t& value, as_sequence())
- temp.push_back(value.floored());
- *this = temp;
+ case SEQUENCE:
+ foreach (value_t& value, as_sequence_lval())
+ value.in_place_floor();
return;
- }
default:
break;
}
+ add_error_context(_("While flooring %1:") << *this);
throw_(value_error, _("Cannot floor %1") << label());
}
@@ -1602,43 +1600,46 @@ void value_t::in_place_unround()
case BALANCE:
as_balance_lval().in_place_unround();
return;
- case SEQUENCE: {
- value_t temp;
- foreach (const value_t& value, as_sequence())
- temp.push_back(value.unrounded());
- *this = temp;
+ case SEQUENCE:
+ foreach (value_t& value, as_sequence_lval())
+ value.in_place_unround();
return;
- }
default:
break;
}
+ add_error_context(_("While unrounding %1:") << *this);
throw_(value_error, _("Cannot unround %1") << label());
}
void value_t::annotate(const annotation_t& details)
{
- if (is_amount())
+ if (is_amount()) {
as_amount_lval().annotate(details);
- else
+ } else {
+ add_error_context(_("While attempting to annotate %1:") << *this);
throw_(value_error, _("Cannot annotate %1") << label());
+ }
}
bool value_t::has_annotation() const
{
- if (is_amount())
+ if (is_amount()) {
return as_amount().has_annotation();
- else
+ } else {
+ add_error_context(_("While checking if %1 has annotations:") << *this);
throw_(value_error,
- _("Cannot determine whether %1 is annotated") << label());
+ _("Cannot determine whether %1 is annotated") << label());
+ }
return false;
}
annotation_t& value_t::annotation()
{
- if (is_amount())
+ if (is_amount()) {
return as_amount_lval().annotation();
- else {
+ } else {
+ add_error_context(_("While requesting the annotations of %1:") << *this);
throw_(value_error, _("Cannot request annotation of %1") << label());
return as_amount_lval().annotation(); // quiet g++ warning
}
@@ -1658,13 +1659,13 @@ 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: {
sequence_t temp;
foreach (const value_t& value, as_sequence())
- temp.push_back(value.strip_annotations(what_to_keep));
+ temp.push_back(new value_t(value.strip_annotations(what_to_keep)));
return temp;
}
@@ -1681,18 +1682,56 @@ value_t value_t::strip_annotations(const keep_details_t& what_to_keep) const
return NULL_VALUE;
}
-void value_t::print(std::ostream& out,
- const int first_width,
- const int latter_width,
- const bool right_justify,
- const bool colorize) const
+string value_t::label(optional<type_t> the_type) const
+{
+ switch (the_type ? *the_type : type()) {
+ case VOID:
+ return _("an uninitialized value");
+ case BOOLEAN:
+ return _("a boolean");
+ case DATETIME:
+ return _("a date/time");
+ case DATE:
+ return _("a date");
+ case INTEGER:
+ return _("an integer");
+ case AMOUNT:
+ return _("an amount");
+ case BALANCE:
+ return _("a balance");
+ case STRING:
+ return _("a string");
+ case MASK:
+ return _("a regexp");
+ case SEQUENCE:
+ return _("a sequence");
+ case SCOPE:
+ return _("a scope");
+ case ANY:
+ if (as_any().type() == typeid(expr_t::ptr_op_t))
+ return _("an expr");
+ else
+ return _("an object");
+ break;
+ default:
+ assert(false);
+ break;
+ }
+ assert(false);
+ return _("<invalid>");
+}
+
+void value_t::print(std::ostream& out,
+ const int first_width,
+ const int latter_width,
+ const uint_least8_t flags) const
{
if (first_width > 0 &&
(! is_amount() || as_amount().is_zero()) &&
! is_balance() && ! is_string()) {
out.width(first_width);
- if (right_justify)
+ if (flags & AMOUNT_PRINT_RIGHT_JUSTIFY)
out << std::right;
else
out << std::left;
@@ -1716,8 +1755,9 @@ void value_t::print(std::ostream& out,
break;
case INTEGER:
- if (colorize && as_long() < 0)
- justify(out, to_string(), first_width, right_justify, true);
+ if (flags & AMOUNT_PRINT_COLORIZE && as_long() < 0)
+ justify(out, to_string(), first_width,
+ flags & AMOUNT_PRINT_RIGHT_JUSTIFY, true);
else
out << as_long();
break;
@@ -1727,21 +1767,20 @@ void value_t::print(std::ostream& out,
out << 0;
} else {
std::ostringstream buf;
- buf << as_amount();
- justify(out, buf.str(), first_width, right_justify,
- colorize && as_amount().sign() < 0);
+ as_amount().print(buf, flags);
+ justify(out, buf.str(), first_width, flags & AMOUNT_PRINT_RIGHT_JUSTIFY,
+ flags & AMOUNT_PRINT_COLORIZE && as_amount().sign() < 0);
}
break;
}
case BALANCE:
- as_balance().print(out, first_width, latter_width, right_justify,
- colorize);
+ as_balance().print(out, first_width, latter_width, flags);
break;
case STRING:
if (first_width > 0)
- justify(out, as_string(), first_width, right_justify);
+ justify(out, as_string(), first_width, flags & AMOUNT_PRINT_RIGHT_JUSTIFY);
else
out << as_string();
break;
@@ -1755,12 +1794,11 @@ void value_t::print(std::ostream& out,
bool first = true;
foreach (const value_t& value, as_sequence()) {
if (first)
- first = false;
+ first = false;
else
- out << ", ";
+ out << ", ";
- value.print(out, first_width, latter_width, right_justify,
- colorize);
+ value.print(out, first_width, latter_width, flags);
}
out << ')';
break;
@@ -1769,16 +1807,18 @@ 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:
+ add_error_context(_("While printing %1:") << *this);
throw_(value_error, _("Cannot print %1") << label());
}
}
@@ -1825,14 +1865,14 @@ void value_t::dump(std::ostream& out, const bool relaxed) const
foreach (const char& ch, as_string()) {
switch (ch) {
case '"':
- out << "\\\"";
- break;
+ out << "\\\"";
+ break;
case '\\':
- out << "\\\\";
- break;
+ out << "\\\\";
+ break;
default:
- out << ch;
- break;
+ out << ch;
+ break;
}
}
out << '"';
@@ -1845,11 +1885,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: {
@@ -1857,9 +1897,9 @@ void value_t::dump(std::ostream& out, const bool relaxed) const
bool first = true;
foreach (const value_t& value, as_sequence()) {
if (first)
- first = false;
+ first = false;
else
- out << ", ";
+ out << ", ";
value.dump(out, relaxed);
}
@@ -1887,7 +1927,7 @@ bool value_t::valid() const
}
bool sort_value_is_less_than(const std::list<sort_value_t>& left_values,
- const std::list<sort_value_t>& right_values)
+ const std::list<sort_value_t>& right_values)
{
std::list<sort_value_t>::const_iterator left_iter = left_values.begin();
std::list<sort_value_t>::const_iterator right_iter = right_values.begin();
@@ -1895,16 +1935,16 @@ bool sort_value_is_less_than(const std::list<sort_value_t>& left_values,
while (left_iter != left_values.end() && right_iter != right_values.end()) {
// Don't even try to sort balance values
if (! (*left_iter).value.is_balance() &&
- ! (*right_iter).value.is_balance()) {
+ ! (*right_iter).value.is_balance()) {
DEBUG("value.sort",
- " Comparing " << (*left_iter).value << " < " << (*right_iter).value);
+ " Comparing " << (*left_iter).value << " < " << (*right_iter).value);
if ((*left_iter).value < (*right_iter).value) {
- DEBUG("value.sort", " is less");
- return ! (*left_iter).inverted;
+ DEBUG("value.sort", " is less");
+ return ! (*left_iter).inverted;
}
else if ((*left_iter).value > (*right_iter).value) {
- DEBUG("value.sort", " is greater");
- return (*left_iter).inverted;
+ DEBUG("value.sort", " is greater");
+ return (*left_iter).inverted;
}
}
left_iter++; right_iter++;
@@ -1963,7 +2003,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;