summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--balance.h38
-rw-r--r--binary.cc4
-rw-r--r--textual.cc2
-rw-r--r--valexpr.cc13
-rw-r--r--valexpr.h20
-rw-r--r--value.cc3
6 files changed, 45 insertions, 35 deletions
diff --git a/balance.h b/balance.h
index 3863e68e..47647a39 100644
--- a/balance.h
+++ b/balance.h
@@ -144,9 +144,12 @@ class balance_t
// multiplication and divide
balance_t& operator*=(const balance_t& bal) {
- if (amounts.size() == 1 && bal.amounts.size() == 1)
+ if (! *this || ! bal)
+ return (*this = 0L);
+ else if (amounts.size() == 1 && bal.amounts.size() == 1)
return *this *= (*bal.amounts.begin()).second;
- throw amount_error("It makes no sense to multiply two balances");
+ else
+ throw amount_error("It makes no sense to multiply two balances");
}
balance_t& operator*=(const amount_t& amt) {
// Multiplying by the null commodity causes all amounts to be
@@ -173,9 +176,14 @@ class balance_t
}
balance_t& operator/=(const balance_t& bal) {
- if (amounts.size() == 1 && bal.amounts.size() == 1)
+ if (! *this)
+ return (*this = 0L);
+ else if (! bal)
+ throw amount_error("Attempt to divide by zero");
+ else if (amounts.size() == 1 && bal.amounts.size() == 1)
return *this /= (*bal.amounts.begin()).second;
- throw amount_error("It makes no sense to divide two balances");
+ else
+ throw amount_error("It makes no sense to divide two balances");
}
balance_t& operator/=(const amount_t& amt) {
// Dividing by the null commodity causes all amounts to be
@@ -428,9 +436,8 @@ class balance_t
balance_t value(const std::time_t moment) const;
balance_t price() const;
- void write(std::ostream& out,
- const int first_width,
- const int latter_width = -1) const;
+ void write(std::ostream& out, const int first_width,
+ const int latter_width = -1) const;
void abs() {
for (amounts_map::iterator i = amounts.begin();
@@ -563,7 +570,6 @@ class balance_pair_t
else
cost = new balance_t(*bal_pair.cost);
}
-
return *this;
}
balance_pair_t& operator+=(const balance_t& bal) {
@@ -594,7 +600,6 @@ class balance_pair_t
else
cost = new balance_t(- *bal_pair.cost);
}
-
return *this;
}
balance_pair_t& operator-=(const balance_t& bal) {
@@ -677,7 +682,6 @@ class balance_pair_t
cost = NULL;
}
}
-
return *this;
}
balance_pair_t& operator*=(const balance_t& bal) {
@@ -694,21 +698,19 @@ class balance_pair_t
}
balance_pair_t& operator/=(const balance_pair_t& bal_pair) {
- quantity /= bal_pair.quantity;
+ if (bal_pair.quantity)
+ quantity /= bal_pair.quantity;
+ else
+ throw amount_error("Attempt to divide by zero");
if (bal_pair.price) {
if (price)
*price /= *bal_pair.price;
- } else {
- throw amount_error("Attempt to divide by zero");
}
if (bal_pair.cost) {
if (cost)
*cost /= *bal_pair.cost;
- } else {
- throw amount_error("Attempt to divide by zero");
}
-
return *this;
}
balance_pair_t& operator/=(const balance_t& bal) {
@@ -899,8 +901,7 @@ class balance_pair_t
balance_pair_t& add(const amount_t& amount,
const amount_t * a_price = NULL,
- const amount_t * a_cost = NULL)
- {
+ const amount_t * a_cost = NULL) {
quantity += amount;
if (a_price) {
@@ -915,7 +916,6 @@ class balance_pair_t
else
cost = new balance_t(*a_cost);
}
-
return *this;
}
diff --git a/binary.cc b/binary.cc
index 7b283d97..958c0a79 100644
--- a/binary.cc
+++ b/binary.cc
@@ -343,9 +343,9 @@ inline void read_binary_transaction(char *& data, transaction_t * xact)
xact->data = NULL;
if (xact->amount_expr)
- compute_amount(xact->amount_expr, xact->amount, *xact);
+ compute_amount(xact->amount_expr, xact->amount, xact);
if (xact->cost_expr)
- compute_amount(xact->cost_expr, *xact->cost, *xact);
+ compute_amount(xact->cost_expr, *xact->cost, xact);
}
inline void read_binary_entry_base(char *& data, entry_base_t * entry,
diff --git a/textual.cc b/textual.cc
index 258157c3..1857ddbf 100644
--- a/textual.cc
+++ b/textual.cc
@@ -164,7 +164,7 @@ value_expr_t * parse_amount(const char * text, amount_t& amt,
if (altbuf)
delete[] altbuf;
- if (! compute_amount(expr, amt, xact))
+ if (! compute_amount(expr, amt, &xact))
throw parse_error(path, linenum, "Value expression yields a balance");
}
diff --git a/valexpr.cc b/valexpr.cc
index bc247fce..41dd9b25 100644
--- a/valexpr.cc
+++ b/valexpr.cc
@@ -19,10 +19,11 @@ details_t::details_t(const transaction_t& _xact)
DEBUG_PRINT("ledger.memory.ctors", "ctor details_t");
}
-bool compute_amount(value_expr_t * expr, amount_t& amt, transaction_t& xact)
+bool compute_amount(value_expr_t * expr, amount_t& amt,
+ const transaction_t * xact, value_expr_t * context)
{
value_t result;
- expr->compute(result, details_t(xact));
+ expr->compute(result, xact ? details_t(*xact) : details_t(), context);
switch (result.type) {
case value_t::BOOLEAN:
amt = *((bool *) result.data);
@@ -537,11 +538,10 @@ void value_expr_t::compute(value_t& result, const details_t& details,
index = 0;
expr = find_leaf(context, 1, index);
- value_t temp;
- expr->compute(temp, details, context);
- if (expr->kind == CONSTANT_T)
- result = result.value(expr->constant_t);
+ amount_t moment;
+ if (compute_amount(expr, moment, details.xact, context))
+ result = result.value((long)moment);
else
throw compute_error("Invalid date passed to P(value,date)");
@@ -1279,6 +1279,7 @@ void init_value_expr()
globals->define("P", node);
globals->define("val", node);
globals->define("value", node);
+ parse_boolean_expr("current_value(x)=P(x,m)", globals);
// Macros
node = parse_value_expr("P(a,d)");
diff --git a/valexpr.h b/valexpr.h
index 3faadd58..a9a02854 100644
--- a/valexpr.h
+++ b/valexpr.h
@@ -215,10 +215,18 @@ struct scope_t
DEBUG_PRINT("ledger.valexpr.syms",
"Defining '" << name << "' = " << def);
std::pair<symbol_map::iterator, bool> result
- = symbols.insert(symbol_pair(name, def->acquire()));
- if (! result.second)
- throw value_expr_error(std::string("Redefinition of '") +
- name + "' in same scope");
+ = symbols.insert(symbol_pair(name, def));
+ if (! result.second) {
+ symbols.erase(name);
+ std::pair<symbol_map::iterator, bool> result
+ = symbols.insert(symbol_pair(name, def));
+ if (! result.second) {
+ def->release();
+ throw value_expr_error(std::string("Redefinition of '") +
+ name + "' in same scope");
+ }
+ }
+ def->acquire();
}
value_expr_t * lookup(const std::string& name) {
symbol_map::const_iterator i = symbols.find(name);
@@ -237,7 +245,9 @@ extern bool initialized;
void init_value_expr();
-bool compute_amount(value_expr_t * expr, amount_t& amt, transaction_t& xact);
+bool compute_amount(value_expr_t * expr, amount_t& amt,
+ const transaction_t * xact,
+ value_expr_t * context = NULL);
struct scope_t;
value_expr_t * parse_boolean_expr(std::istream& in, scope_t * scope);
diff --git a/value.cc b/value.cc
index 6038ca9e..1ec5b219 100644
--- a/value.cc
+++ b/value.cc
@@ -733,11 +733,10 @@ value_t value_t::price() const
return *this;
case BALANCE_PAIR:
- assert(((balance_pair_t *) data)->price);
if (((balance_pair_t *) data)->price)
return *(((balance_pair_t *) data)->price);
else
- return ((balance_pair_t *) data)->quantity;
+ return 0L;
default:
assert(0);