diff options
Diffstat (limited to 'valexpr.cc')
-rw-r--r-- | valexpr.cc | 1085 |
1 files changed, 0 insertions, 1085 deletions
diff --git a/valexpr.cc b/valexpr.cc deleted file mode 100644 index 9091672f..00000000 --- a/valexpr.cc +++ /dev/null @@ -1,1085 +0,0 @@ -#include "valexpr.h" -#include "walk.h" -#include "error.h" -#include "datetime.h" -#include "debug.h" -#include "util.h" -#ifdef USE_BOOST_PYTHON -#include "py_eval.h" -#endif - -namespace ledger { - -std::auto_ptr<value_expr_t> amount_expr; -std::auto_ptr<value_expr_t> total_expr; - -void value_expr_t::compute(value_t& result, const details_t& details) const -{ - switch (kind) { - case CONSTANT_I: - result = constant_i; - break; - case CONSTANT_T: - result = long(constant_t); - break; - - case CONSTANT_A: - result = constant_a; - break; - - case AMOUNT: - if (details.xact) { - if (transaction_has_xdata(*details.xact) && - transaction_xdata_(*details.xact).dflags & TRANSACTION_COMPOSITE) - result = transaction_xdata_(*details.xact).composite_amount; - else - result = details.xact->amount; - } - else if (details.account && account_has_xdata(*details.account)) { - result = account_xdata(*details.account).value; - } - else { - result = 0L; - } - break; - - case COST: - if (details.xact) { - bool set = false; - if (transaction_has_xdata(*details.xact)) { - transaction_xdata_t& xdata(transaction_xdata_(*details.xact)); - if (xdata.dflags & TRANSACTION_COMPOSITE) { - if (xdata.composite_amount.type == value_t::BALANCE_PAIR && - ((balance_pair_t *) xdata.composite_amount.data)->cost) - result = *((balance_pair_t *) xdata.composite_amount.data)->cost; - else - result = xdata.composite_amount; - set = true; - } - } - - if (! set) { - if (details.xact->cost) - result = *details.xact->cost; - else - result = details.xact->amount; - } - } - else if (details.account && account_has_xdata(*details.account)) { - result = account_xdata(*details.account).value.cost(); - } - else { - result = 0L; - } - break; - - case TOTAL: - if (details.xact && transaction_has_xdata(*details.xact)) - result = transaction_xdata_(*details.xact).total; - else if (details.account && account_has_xdata(*details.account)) - result = account_xdata(*details.account).total; - else - result = 0L; - break; - case COST_TOTAL: - if (details.xact && transaction_has_xdata(*details.xact)) - result = transaction_xdata_(*details.xact).total.cost(); - else if (details.account && account_has_xdata(*details.account)) - result = account_xdata(*details.account).total.cost(); - else - result = 0L; - break; - - case VALUE_EXPR: - if (amount_expr.get()) - amount_expr->compute(result, details); - else - result = 0L; - break; - case TOTAL_EXPR: - if (total_expr.get()) - total_expr->compute(result, details); - else - result = 0L; - break; - - case DATE: - if (details.xact && transaction_has_xdata(*details.xact) && - transaction_xdata_(*details.xact).date) - result = long(transaction_xdata_(*details.xact).date); - else if (details.entry) - result = long(details.entry->date); - else - result = long(now); - break; - - case CLEARED: - if (details.entry) - result = details.entry->state == entry_t::CLEARED; - else - result = false; - break; - - case REAL: - if (details.xact) - result = ! (details.xact->flags & TRANSACTION_VIRTUAL); - else - result = true; - break; - - case ACTUAL: - if (details.xact) - result = ! (details.xact->flags & TRANSACTION_AUTO); - else - result = true; - break; - - case INDEX: - if (details.xact && transaction_has_xdata(*details.xact)) - result = long(transaction_xdata_(*details.xact).index + 1); - else if (details.account && account_has_xdata(*details.account)) - result = long(account_xdata(*details.account).count); - else - result = 0L; - break; - - case COUNT: - if (details.xact && transaction_has_xdata(*details.xact)) - result = long(transaction_xdata_(*details.xact).index + 1); - else if (details.account && account_has_xdata(*details.account)) - result = long(account_xdata(*details.account).total_count); - else - result = 0L; - break; - - case DEPTH: - if (details.account) - result = long(details.account->depth); - else - result = 0L; - break; - - case F_ARITH_MEAN: - if (details.xact && transaction_has_xdata(*details.xact)) { - assert(left); - left->compute(result, details); - result /= amount_t(long(transaction_xdata_(*details.xact).index + 1)); - } - else if (details.account && account_has_xdata(*details.account) && - account_xdata(*details.account).total_count) { - assert(left); - left->compute(result, details); - result /= amount_t(long(account_xdata(*details.account).total_count)); - } - else { - result = 0L; - } - break; - - case F_PARENT: - if (details.account && details.account->parent) - left->compute(result, details_t(*details.account->parent)); - break; - - case F_NEG: - assert(left); - left->compute(result, details); - result.negate(); - break; - - case F_ABS: - assert(left); - left->compute(result, details); - result.abs(); - break; - - case F_STRIP: { - assert(left); - left->compute(result, details); - - balance_t * bal = NULL; - switch (result.type) { - case value_t::BALANCE_PAIR: - bal = &((balance_pair_t *) result.data)->quantity; - // fall through... - - case value_t::BALANCE: - if (! bal) - bal = (balance_t *) result.data; - - if (bal->amounts.size() < 2) { - result.cast(value_t::AMOUNT); - } else { - value_t temp; - for (amounts_map::const_iterator i = bal->amounts.begin(); - i != bal->amounts.end(); - i++) { - amount_t x = (*i).second; - x.clear_commodity(); - temp += x; - } - result = temp; - assert(temp.type == value_t::AMOUNT); - } - // fall through... - - case value_t::AMOUNT: - ((amount_t *) result.data)->clear_commodity(); - break; - - default: - break; - } - break; - } - - case F_CODE_MASK: - assert(mask); - if (details.entry) - result = mask->match(details.entry->code); - else - result = false; - break; - - case F_PAYEE_MASK: - assert(mask); - if (details.entry) - result = mask->match(details.entry->payee); - else - result = false; - break; - - case F_NOTE_MASK: - assert(mask); - if (details.xact) - result = mask->match(details.xact->note); - else - result = false; - break; - - case F_ACCOUNT_MASK: - assert(mask); - if (details.account) - result = mask->match(details.account->fullname()); - else - result = false; - break; - - case F_SHORT_ACCOUNT_MASK: - assert(mask); - if (details.account) - result = mask->match(details.account->name); - else - result = false; - break; - - case F_VALUE: { - assert(left); - left->compute(result, details); - - std::time_t moment = now; - if (right) { - switch (right->kind) { - case DATE: - if (details.xact && transaction_has_xdata(*details.xact) && - transaction_xdata_(*details.xact).date) - moment = transaction_xdata_(*details.xact).date; - else if (details.entry) - moment = details.entry->date; - break; - case CONSTANT_T: - moment = right->constant_t; - break; - default: - throw compute_error("Invalid date passed to P(value,date)"); - } - } - - result = result.value(moment); - break; - } - - case F_INTERP_FUNC: { -#ifdef USE_BOOST_PYTHON - if (! python_call(constant_s, right, details, result)) - result = 0L; -#else - result = 0L; -#endif - break; - } - - case O_NOT: - left->compute(result, details); - result.negate(); - break; - - case O_QUES: { - assert(left); - assert(right); - assert(right->kind == O_COL); - left->compute(result, details); - if (result) - right->left->compute(result, details); - else - right->right->compute(result, details); - break; - } - - case O_AND: - assert(left); - assert(right); - left->compute(result, details); - if (result) - right->compute(result, details); - break; - - case O_OR: - assert(left); - assert(right); - left->compute(result, details); - if (! result) - right->compute(result, details); - break; - - case O_EQ: - case O_LT: - case O_LTE: - case O_GT: - case O_GTE: { - assert(left); - assert(right); - value_t temp; - left->compute(temp, details); - right->compute(result, details); - switch (kind) { - case O_EQ: result = temp == result; break; - case O_LT: result = temp < result; break; - case O_LTE: result = temp <= result; break; - case O_GT: result = temp > result; break; - case O_GTE: result = temp >= result; break; - default: assert(0); break; - } - break; - } - - case O_ADD: - case O_SUB: - case O_MUL: - case O_DIV: { - assert(left); - assert(right); - value_t temp; - right->compute(temp, details); - left->compute(result, details); - switch (kind) { - case O_ADD: result += temp; break; - case O_SUB: result -= temp; break; - case O_MUL: result *= temp; break; - case O_DIV: result /= temp; break; - default: assert(0); break; - } - break; - } - - case LAST: - default: - assert(0); - break; - } -} - -static inline void unexpected(char c, char wanted = '\0') { - if ((unsigned char) c == 0xff) { - if (wanted) - throw value_expr_error(std::string("Missing '") + wanted + "'"); - else - throw value_expr_error("Unexpected end"); - } else { - if (wanted) - throw value_expr_error(std::string("Invalid char '") + c + - "' (wanted '" + wanted + "')"); - else - throw value_expr_error(std::string("Invalid char '") + c + "'"); - } -} - -value_expr_t * parse_value_term(std::istream& in); - -inline value_expr_t * parse_value_term(const char * p) { - std::istringstream stream(p); - return parse_value_term(stream); -} - -value_expr_t * parse_value_term(std::istream& in) -{ - std::auto_ptr<value_expr_t> node; - - char buf[256]; - char c = peek_next_nonws(in); - if (std::isdigit(c)) { - READ_INTO(in, buf, 255, c, std::isdigit(c)); - - node.reset(new value_expr_t(value_expr_t::CONSTANT_I)); - node->constant_i = std::atol(buf); - return node.release(); - } - else if (c == '{') { - in.get(c); - READ_INTO(in, buf, 255, c, c != '}'); - if (c == '}') - in.get(c); - else - unexpected(c, '}'); - - node.reset(new value_expr_t(value_expr_t::CONSTANT_A)); - node->constant_a.parse(buf); - return node.release(); - } - - in.get(c); - switch (c) { - // Basic terms - case 'm': - node.reset(new value_expr_t(value_expr_t::CONSTANT_T)); - node->constant_t = now; - break; - - case 'a': node.reset(new value_expr_t(value_expr_t::AMOUNT)); break; - case 'b': node.reset(new value_expr_t(value_expr_t::COST)); break; - case 'd': node.reset(new value_expr_t(value_expr_t::DATE)); break; - case 'X': node.reset(new value_expr_t(value_expr_t::CLEARED)); break; - case 'R': node.reset(new value_expr_t(value_expr_t::REAL)); break; - case 'L': node.reset(new value_expr_t(value_expr_t::ACTUAL)); break; - case 'n': node.reset(new value_expr_t(value_expr_t::INDEX)); break; - case 'N': node.reset(new value_expr_t(value_expr_t::COUNT)); break; - case 'l': node.reset(new value_expr_t(value_expr_t::DEPTH)); break; - case 'O': node.reset(new value_expr_t(value_expr_t::TOTAL)); break; - case 'B': node.reset(new value_expr_t(value_expr_t::COST_TOTAL)); break; - - // Relating to format_t - case 't': node.reset(new value_expr_t(value_expr_t::VALUE_EXPR)); break; - case 'T': node.reset(new value_expr_t(value_expr_t::TOTAL_EXPR)); break; - - // Compound terms - case 'v': node.reset(parse_value_expr("P(a,d)")); break; - case 'V': node.reset(parse_value_term("P(O,d)")); break; - case 'g': node.reset(parse_value_expr("v-b")); break; - case 'G': node.reset(parse_value_expr("V-B")); break; - - // Functions - case '^': - node.reset(new value_expr_t(value_expr_t::F_PARENT)); - node->left = parse_value_term(in); - break; - - case '-': - node.reset(new value_expr_t(value_expr_t::F_NEG)); - node->left = parse_value_term(in); - break; - - case 'U': - node.reset(new value_expr_t(value_expr_t::F_ABS)); - node->left = parse_value_term(in); - break; - - case 'S': - node.reset(new value_expr_t(value_expr_t::F_STRIP)); - node->left = parse_value_term(in); - break; - - case 'A': - node.reset(new value_expr_t(value_expr_t::F_ARITH_MEAN)); - node->left = parse_value_term(in); - break; - - case 'P': - node.reset(new value_expr_t(value_expr_t::F_VALUE)); - if (peek_next_nonws(in) == '(') { - in.get(c); - node->left = parse_value_expr(in, true); - if (peek_next_nonws(in) == ',') { - in.get(c); - node->right = parse_value_expr(in, true); - } - in.get(c); - if (c != ')') - unexpected(c, ')'); - } else { - node->left = parse_value_term(in); - } - break; - - // Other - case 'c': - case 'p': - case 'w': - case 'W': - case 'e': - case '/': { - bool code_mask = c == 'c'; - bool payee_mask = c == 'p'; - bool note_mask = c == 'e'; - bool short_account_mask = c == 'w'; - - if (c == '/') { - c = peek_next_nonws(in); - if (c == '/') { - in.get(c); - c = in.peek(); - if (c == '/') { - in.get(c); - c = in.peek(); - short_account_mask = true; - } else { - payee_mask = true; - } - } - } else { - in.get(c); - } - - // Read in the regexp - READ_INTO(in, buf, 255, c, c != '/'); - if (c != '/') - unexpected(c, '/'); - - value_expr_t::kind_t kind; - - if (short_account_mask) - kind = value_expr_t::F_SHORT_ACCOUNT_MASK; - else if (code_mask) - kind = value_expr_t::F_CODE_MASK; - else if (payee_mask) - kind = value_expr_t::F_PAYEE_MASK; - else if (note_mask) - kind = value_expr_t::F_NOTE_MASK; - else - kind = value_expr_t::F_ACCOUNT_MASK; - - in.get(c); - node.reset(new value_expr_t(kind)); - node->mask = new mask_t(buf); - break; - } - - case '@': { - READ_INTO(in, buf, 255, c, c != '('); - if (c != '(') - unexpected(c, '('); - - node.reset(new value_expr_t(value_expr_t::F_INTERP_FUNC)); - node->constant_s = buf; - - in.get(c); - if (peek_next_nonws(in) == ')') { - in.get(c); - } else { - node->right = new value_expr_t(value_expr_t::O_ARG); - value_expr_t * cur = node->right; - cur->left = parse_value_expr(in, true); - in.get(c); - while (! in.eof() && c == ',') { - cur->right = new value_expr_t(value_expr_t::O_ARG); - cur = cur->right; - cur->left = parse_value_expr(in, true); - in.get(c); - } - if (c != ')') - unexpected(c, ')'); - } - break; - } - - case '(': - node.reset(parse_value_expr(in, true)); - in.get(c); - if (c != ')') - unexpected(c, ')'); - break; - - case '[': { - READ_INTO(in, buf, 255, c, c != ']'); - if (c != ']') - unexpected(c, ']'); - in.get(c); - - node.reset(new value_expr_t(value_expr_t::CONSTANT_T)); - - interval_t timespan(buf); - node->constant_t = timespan.first(); - break; - } - - default: - in.unget(); - break; - } - - return node.release(); -} - -value_expr_t * parse_mul_expr(std::istream& in) -{ - std::auto_ptr<value_expr_t> node(parse_value_term(in)); - - if (node.get() && ! in.eof()) { - char c = peek_next_nonws(in); - while (c == '*' || c == '/') { - in.get(c); - switch (c) { - case '*': { - std::auto_ptr<value_expr_t> prev(node.release()); - node.reset(new value_expr_t(value_expr_t::O_MUL)); - node->left = prev.release(); - node->right = parse_value_term(in); - break; - } - - case '/': { - std::auto_ptr<value_expr_t> prev(node.release()); - node.reset(new value_expr_t(value_expr_t::O_DIV)); - node->left = prev.release(); - node->right = parse_value_term(in); - break; - } - } - c = peek_next_nonws(in); - } - } - - return node.release(); -} - -value_expr_t * parse_add_expr(std::istream& in) -{ - std::auto_ptr<value_expr_t> node(parse_mul_expr(in)); - - if (node.get() && ! in.eof()) { - char c = peek_next_nonws(in); - while (c == '+' || c == '-') { - in.get(c); - switch (c) { - case '+': { - std::auto_ptr<value_expr_t> prev(node.release()); - node.reset(new value_expr_t(value_expr_t::O_ADD)); - node->left = prev.release(); - node->right = parse_mul_expr(in); - break; - } - - case '-': { - std::auto_ptr<value_expr_t> prev(node.release()); - node.reset(new value_expr_t(value_expr_t::O_SUB)); - node->left = prev.release(); - node->right = parse_mul_expr(in); - break; - } - } - c = peek_next_nonws(in); - } - } - - return node.release(); -} - -value_expr_t * parse_logic_expr(std::istream& in) -{ - std::auto_ptr<value_expr_t> node; - - if (peek_next_nonws(in) == '!') { - char c; - in.get(c); - node.reset(new value_expr_t(value_expr_t::O_NOT)); - node->left = parse_logic_expr(in); - return node.release(); - } - - node.reset(parse_add_expr(in)); - - if (node.get() && ! in.eof()) { - char c = peek_next_nonws(in); - if (c == '=' || c == '<' || c == '>') { - in.get(c); - switch (c) { - case '=': { - std::auto_ptr<value_expr_t> prev(node.release()); - node.reset(new value_expr_t(value_expr_t::O_EQ)); - node->left = prev.release(); - node->right = parse_add_expr(in); - break; - } - - case '<': { - std::auto_ptr<value_expr_t> prev(node.release()); - node.reset(new value_expr_t(value_expr_t::O_LT)); - if (peek_next_nonws(in) == '=') { - in.get(c); - node->kind = value_expr_t::O_LTE; - } - node->left = prev.release(); - node->right = parse_add_expr(in); - break; - } - - case '>': { - std::auto_ptr<value_expr_t> prev(node.release()); - node.reset(new value_expr_t(value_expr_t::O_GT)); - if (peek_next_nonws(in) == '=') { - in.get(c); - node->kind = value_expr_t::O_GTE; - } - node->left = prev.release(); - node->right = parse_add_expr(in); - break; - } - - default: - if (! in.eof()) - unexpected(c); - break; - } - } - } - - return node.release(); -} - -value_expr_t * parse_value_expr(std::istream& in, const bool partial) -{ - std::auto_ptr<value_expr_t> node(parse_logic_expr(in)); - - if (node.get() && ! in.eof()) { - char c = peek_next_nonws(in); - while (c == '&' || c == '|' || c == '?') { - in.get(c); - switch (c) { - case '&': { - std::auto_ptr<value_expr_t> prev(node.release()); - node.reset(new value_expr_t(value_expr_t::O_AND)); - node->left = prev.release(); - node->right = parse_logic_expr(in); - break; - } - - case '|': { - std::auto_ptr<value_expr_t> prev(node.release()); - node.reset(new value_expr_t(value_expr_t::O_OR)); - node->left = prev.release(); - node->right = parse_logic_expr(in); - break; - } - - case '?': { - std::auto_ptr<value_expr_t> prev(node.release()); - node.reset(new value_expr_t(value_expr_t::O_QUES)); - node->left = prev.release(); - value_expr_t * choices; - node->right = choices = new value_expr_t(value_expr_t::O_COL); - choices->left = parse_logic_expr(in); - c = peek_next_nonws(in); - if (c != ':') - unexpected(c, ':'); - in.get(c); - choices->right = parse_logic_expr(in); - break; - } - - default: - if (! in.eof()) - unexpected(c); - break; - } - c = peek_next_nonws(in); - } - } - - char c; - if (! node.get()) { - in.get(c); - if (in.eof()) - throw value_expr_error(std::string("Failed to parse value expression")); - else - unexpected(c); - } else if (! partial) { - in.get(c); - if (! in.eof()) - unexpected(c); - else - in.unget(); - } - - return node.release(); -} - -#ifdef DEBUG_ENABLED - -void dump_value_expr(std::ostream& out, const value_expr_t * node) -{ - switch (node->kind) { - case value_expr_t::CONSTANT_I: - out << "UINT[" << node->constant_i << ']'; - break; - case value_expr_t::CONSTANT_T: - out << "DATE/TIME[" << node->constant_t << ']'; - break; - case value_expr_t::CONSTANT_A: - out << "CONST[" << node->constant_a << ']'; - break; - - case value_expr_t::AMOUNT: out << "AMOUNT"; break; - case value_expr_t::COST: out << "COST"; break; - case value_expr_t::DATE: out << "DATE"; break; - case value_expr_t::CLEARED: out << "CLEARED"; break; - case value_expr_t::REAL: out << "REAL"; break; - case value_expr_t::ACTUAL: out << "ACTUAL"; break; - case value_expr_t::INDEX: out << "INDEX"; break; - case value_expr_t::COUNT: out << "COUNT"; break; - case value_expr_t::DEPTH: out << "DEPTH"; break; - case value_expr_t::TOTAL: out << "TOTAL"; break; - case value_expr_t::COST_TOTAL: out << "COST_TOTAL"; break; - - case value_expr_t::F_ARITH_MEAN: - out << "MEAN("; - dump_value_expr(out, node->left); - out << ')'; - break; - - case value_expr_t::F_NEG: - out << "ABS("; - dump_value_expr(out, node->left); - out << ')'; - break; - - case value_expr_t::F_ABS: - out << "ABS("; - dump_value_expr(out, node->left); - out << ')'; - break; - - case value_expr_t::F_STRIP: - out << "STRIP("; - dump_value_expr(out, node->left); - out << ')'; - break; - - case value_expr_t::F_CODE_MASK: - assert(node->mask); - out << "M_CODE(" << node->mask->pattern << ')'; - break; - - case value_expr_t::F_PAYEE_MASK: - assert(node->mask); - out << "M_PAYEE(" << node->mask->pattern << ')'; - break; - - case value_expr_t::F_NOTE_MASK: - assert(node->mask); - out << "M_NOTE(" << node->mask->pattern << ')'; - break; - - case value_expr_t::F_ACCOUNT_MASK: - assert(node->mask); - out << "M_ACCT(" << node->mask->pattern << ')'; - break; - - case value_expr_t::F_SHORT_ACCOUNT_MASK: - assert(node->mask); - out << "M_SACCT(" << node->mask->pattern << ')'; - break; - - case value_expr_t::F_VALUE: - out << "VALUE("; - dump_value_expr(out, node->left); - if (node->right) { - out << ", "; - dump_value_expr(out, node->right); - } - out << ')'; - break; - - case value_expr_t::F_INTERP_FUNC: - out << "F_INTERP[" << node->constant_s << "]("; - dump_value_expr(out, node->right); - out << ')'; - break; - - case value_expr_t::O_NOT: - out << '!'; - dump_value_expr(out, node->left); - break; - - case value_expr_t::O_ARG: - dump_value_expr(out, node->left); - if (node->right) { - out << ','; - dump_value_expr(out, node->right); - } - break; - - case value_expr_t::O_QUES: - dump_value_expr(out, node->left); - out << '?'; - dump_value_expr(out, node->right->left); - out << ':'; - dump_value_expr(out, node->right->right); - break; - - case value_expr_t::O_AND: - case value_expr_t::O_OR: - out << '('; - dump_value_expr(out, node->left); - switch (node->kind) { - case value_expr_t::O_AND: out << " & "; break; - case value_expr_t::O_OR: out << " | "; break; - default: assert(0); break; - } - dump_value_expr(out, node->right); - out << ')'; - break; - - case value_expr_t::O_EQ: - case value_expr_t::O_LT: - case value_expr_t::O_LTE: - case value_expr_t::O_GT: - case value_expr_t::O_GTE: - out << '('; - dump_value_expr(out, node->left); - switch (node->kind) { - case value_expr_t::O_EQ: out << '='; break; - case value_expr_t::O_LT: out << '<'; break; - case value_expr_t::O_LTE: out << "<="; break; - case value_expr_t::O_GT: out << '>'; break; - case value_expr_t::O_GTE: out << ">="; break; - default: assert(0); break; - } - dump_value_expr(out, node->right); - out << ')'; - break; - - case value_expr_t::O_ADD: - case value_expr_t::O_SUB: - case value_expr_t::O_MUL: - case value_expr_t::O_DIV: - out << '('; - dump_value_expr(out, node->left); - switch (node->kind) { - case value_expr_t::O_ADD: out << '+'; break; - case value_expr_t::O_SUB: out << '-'; break; - case value_expr_t::O_MUL: out << '*'; break; - case value_expr_t::O_DIV: out << '/'; break; - default: assert(0); break; - } - dump_value_expr(out, node->right); - out << ')'; - break; - - case value_expr_t::LAST: - default: - assert(0); - break; - } -} - -#endif // DEBUG_ENABLED - -} // namespace ledger - -#ifdef USE_BOOST_PYTHON - -#include <boost/python.hpp> - -using namespace boost::python; -using namespace ledger; - -value_t py_compute_1(value_expr_t& value_expr, const details_t& item) -{ - value_t result; - value_expr.compute(result, item); - return result; -} - -template <typename T> -value_t py_compute(value_expr_t& value_expr, const T& item) -{ - value_t result; - value_expr.compute(result, details_t(item)); - return result; -} - -value_expr_t * py_parse_value_expr_1(const std::string& str) -{ - return parse_value_expr(str); -} - -value_expr_t * py_parse_value_expr_2(const std::string& str, const bool partial) -{ - return parse_value_expr(str, partial); -} - -#define EXC_TRANSLATOR(type) \ - void exc_translate_ ## type(const type& err) { \ - PyErr_SetString(PyExc_RuntimeError, err.what()); \ - } - -EXC_TRANSLATOR(value_expr_error) -EXC_TRANSLATOR(compute_error) -EXC_TRANSLATOR(mask_error) - -void export_valexpr() -{ - class_< details_t > ("Details", init<const entry_t&>()) - .def(init<const transaction_t&>()) - .def(init<const account_t&>()) - .add_property("entry", - make_getter(&details_t::entry, - return_value_policy<reference_existing_object>())) - .add_property("xact", - make_getter(&details_t::xact, - return_value_policy<reference_existing_object>())) - .add_property("account", - make_getter(&details_t::account, - return_value_policy<reference_existing_object>())) - ; - - class_< value_expr_t > ("ValueExpr", init<value_expr_t::kind_t>()) - .def("compute", py_compute_1) - .def("compute", py_compute<account_t>) - .def("compute", py_compute<entry_t>) - .def("compute", py_compute<transaction_t>) - ; - - def("parse_value_expr", py_parse_value_expr_1, - return_value_policy<manage_new_object>()); - def("parse_value_expr", py_parse_value_expr_2, - return_value_policy<manage_new_object>()); - - class_< item_predicate<transaction_t> > - ("TransactionPredicate", init<std::string>()) - .def("__call__", &item_predicate<transaction_t>::operator()) - ; - - class_< item_predicate<account_t> > - ("AccountPredicate", init<std::string>()) - .def("__call__", &item_predicate<account_t>::operator()) - ; - -#define EXC_TRANSLATE(type) \ - register_exception_translator<type>(&exc_translate_ ## type); - - EXC_TRANSLATE(value_expr_error); - EXC_TRANSLATE(compute_error); - EXC_TRANSLATE(mask_error); -} - -#endif // USE_BOOST_PYTHON - -#ifdef TEST - -int main(int argc, char *argv[]) -{ - ledger::dump_value_expr(std::cout, ledger::parse_value_expr(argv[1])); - std::cout << std::endl; -} - -#endif // TEST |