diff options
Diffstat (limited to 'src/value.cc')
-rw-r--r-- | src/value.cc | 580 |
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; |