From 42e1d725aa9deb41396ba4c73c8499c7c3798508 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Tue, 29 Jul 2008 21:05:08 -0400 Subject: [PATCH] The next value expression scheme is working, but the individual accessor functions for each of the journal objects has yet to be ported. --- entry.cc | 36 ++++++++++++++++++++++++++++++++++++ entry.h | 8 +++++--- format.cc | 51 ++++++++++++++++++++++++++------------------------- format.h | 2 +- main.cc | 2 ++ op.cc | 12 +++++++----- textual.cc | 5 ++++- value.cc | 1 - xact.cc | 51 ++++++++++++++++++++++++++++++++++++++++++++++----- 9 files changed, 127 insertions(+), 41 deletions(-) diff --git a/entry.cc b/entry.cc index 06e2a131..2feaa761 100644 --- a/entry.cc +++ b/entry.cc @@ -363,6 +363,42 @@ void entry_t::add_xact(xact_t * xact) entry_base_t::add_xact(xact); } +namespace { + value_t get_date(call_scope_t& scope) + { + entry_t& entry(downcast(*scope.parent)); + return entry.date(); + } + + value_t get_payee(call_scope_t& scope) + { + entry_t& entry(downcast(*scope.parent)); + return value_t(entry.payee, true); + } +} + +expr_t::ptr_op_t entry_t::lookup(const string& name) +{ + switch (name[0]) { + case 'd': + if (name[1] == '\0' || name == "date") + return WRAP_FUNCTOR(bind(get_date, _1)); + break; + case 'p': + if (name[1] == '\0' || name == "payee") + return WRAP_FUNCTOR(bind(get_payee, _1)); + break; + } + +#if 0 + // jww (2008-07-29): Should it go to the containing journal next, or to the + // session? + return entry->lookup(name); +#else + return expr_t::ptr_op_t(); +#endif +} + bool entry_t::valid() const { if (! is_valid(_date) || ! journal) { diff --git a/entry.h b/entry.h index 860fc7a5..84802b60 100644 --- a/entry.h +++ b/entry.h @@ -76,7 +76,7 @@ class entry_base_t virtual bool valid() const = 0; }; -class entry_t : public entry_base_t +class entry_t : public entry_base_t, public scope_t { public: datetime_t _date; @@ -108,11 +108,13 @@ public: return actual_date(); } + bool get_state(xact_t::state_t * state) const; + virtual void add_xact(xact_t * xact); - virtual bool valid() const; + virtual expr_t::ptr_op_t lookup(const string& name); - bool get_state(xact_t::state_t * state) const; + virtual bool valid() const; }; struct entry_finalizer_t { diff --git a/format.cc b/format.cc index cf37a9a2..b1e5a8e2 100644 --- a/format.cc +++ b/format.cc @@ -320,7 +320,7 @@ namespace { } } -void format_t::format(std::ostream& out_str, const scope_t& scope) const +void format_t::format(std::ostream& out_str, scope_t& scope) const { for (const element_t * elem = elements; elem; elem = elem->next) { std::ostringstream out; @@ -340,9 +340,23 @@ void format_t::format(std::ostream& out_str, const scope_t& scope) const out << elem->chars; break; -#if 0 case element_t::AMOUNT: + out << scope.resolve("amount"); + break; + + case element_t::ACCOUNT_FULLNAME: + scope.resolve("account").dump(out, elem->min_width); + break; + case element_t::ACCOUNT_NAME: + scope.resolve("account_base").dump(out, elem->min_width); + break; + case element_t::TOTAL: + out << "T"; + //out << scope.resolve("total"); + break; + +#if 0 case element_t::VALUE_EXPR: { expr_t * calc; switch (elem->type) { @@ -569,23 +583,13 @@ void format_t::format(std::ostream& out_str, const scope_t& scope) const if (details.xact) out << details.xact->end_line; break; +#endif - case element_t::DATE_STRING: { - datetime_t date; - if (details.xact) - date = details.xact->date(); - else if (details.entry) - date = details.entry->date(); + case element_t::DATE_STRING: + out << format_datetime(scope.resolve("date").as_datetime()); + break; #if 0 - // jww (2008-04-20): This needs to be rewritten - char buf[256]; - std::strftime(buf, 255, elem->chars.c_str(), date.localtime()); - out << (elem->max_width == 0 ? buf : truncate(buf, elem->max_width)); -#endif - break; - } - case element_t::COMPLETE_DATE_STRING: { datetime_t actual_date; datetime_t effective_date; @@ -670,14 +674,13 @@ void format_t::format(std::ostream& out_str, const scope_t& scope) const out << temp; break; } +#endif case element_t::PAYEE: - if (details.entry) - out << (elem->max_width == 0 ? - details.entry->payee : truncate(details.entry->payee, - elem->max_width)); + scope.resolve("payee").dump(out, elem->min_width); break; +#if 0 case element_t::OPT_NOTE: if (details.xact && details.xact->note) out << " ; "; @@ -781,24 +784,22 @@ format_xacts::format_xacts(std::ostream& _output_stream, void format_xacts::operator()(xact_t& xact) { -#if 0 if (! xact_has_xdata(xact) || ! (xact_xdata_(xact).dflags & XACT_DISPLAYED)) { if (last_entry != xact.entry) { - first_line_format.format(output_stream, details_t(xact)); + first_line_format.format(output_stream, xact); last_entry = xact.entry; } else if (last_xact && last_xact->date() != xact.date()) { - first_line_format.format(output_stream, details_t(xact)); + first_line_format.format(output_stream, xact); } else { - next_lines_format.format(output_stream, details_t(xact)); + next_lines_format.format(output_stream, xact); } xact_xdata(xact).dflags |= XACT_DISPLAYED; last_xact = &xact; } -#endif } void format_entries::format_last_entry() diff --git a/format.h b/format.h index e28b6964..6c9d2e5f 100644 --- a/format.h +++ b/format.h @@ -110,7 +110,7 @@ struct format_t : public noncopyable static string truncate(const string& str, unsigned int width, const bool is_account = false); - void format(std::ostream& out, const scope_t& scope) const; + void format(std::ostream& out, scope_t& scope) const; }; class format_xacts : public item_handler diff --git a/main.cc b/main.cc index 6dfe4004..c998b20c 100644 --- a/main.cc +++ b/main.cc @@ -51,6 +51,8 @@ namespace ledger { var_t report(args, 0); var_t ostream(args, 1); + std::cout << "Hello, world!" << std::endl; + report->xacts_report (xact_handler_ptr(new format_xacts (*ostream, report->session.register_format))); diff --git a/op.cc b/op.cc index c8f38a38..6fcd77f1 100644 --- a/op.cc +++ b/op.cc @@ -682,11 +682,13 @@ value_t expr_t::op_t::calc(scope_t& scope) } throw_(calc_error, "Unknown identifier '" << as_ident() << "'"); - case FUNCTION: - // This should never be evaluated directly; it only appears as the - // left node of an O_CALL operator. - assert(false); - break; + case FUNCTION: { + // Evaluating a FUNCTION is the same as calling it directly; this happens + // when certain functions-that-look-like-variables (such as "amount") are + // resolved. + call_scope_t call_args(scope); + return as_function()(call_args); + } case O_CALL: { call_scope_t call_args(scope); diff --git a/textual.cc b/textual.cc index 61fe66db..37c03c06 100644 --- a/textual.cc +++ b/textual.cc @@ -291,7 +291,10 @@ xact_t * parse_xact(char * line, account_t * account, account_xdata_t& xdata(account_xdata(*xact->account)); if (xact->amount) { - xdata.value += xact->amount; + if (xdata.value.is_null()) + xdata.value = xact->amount; + else + xdata.value += xact->amount; DEBUG("ledger.textual.parse", "line " << linenum << ": " << "XACT assign: account total = " << xdata.value); } diff --git a/value.cc b/value.cc index 70f229cd..730ef2e6 100644 --- a/value.cc +++ b/value.cc @@ -448,7 +448,6 @@ value_t& value_t::operator+=(const value_t& val) } throw_(value_error, "Cannot add " << val.label() << " to " << label()); - return *this; } diff --git a/xact.cc b/xact.cc index d5c16517..7e363333 100644 --- a/xact.cc +++ b/xact.cc @@ -31,6 +31,7 @@ #include "xact.h" #include "journal.h" +#include "account.h" namespace ledger { @@ -61,6 +62,39 @@ namespace { xact_t& xact(downcast(*scope.parent)); return xact.amount; } + + value_t get_date(call_scope_t& scope) + { + xact_t& xact(downcast(*scope.parent)); + return xact.entry->date(); + } + + value_t get_payee(call_scope_t& scope) + { + xact_t& xact(downcast(*scope.parent)); + return value_t(xact.entry->payee, true); + } + + value_t get_account(call_scope_t& scope) + { + xact_t& xact(downcast(*scope.parent)); + + string name = xact.account->fullname(); + + if (xact.has_flags(XACT_VIRTUAL)) { + if (xact.must_balance()) + name = string("[") + name + "]"; + else + name = string("(") + name + ")"; + } + return value_t(name, true); + } + + value_t get_account_base(call_scope_t& scope) + { + assert(false); + return NULL_VALUE; + } } expr_t::ptr_op_t xact_t::lookup(const string& name) @@ -69,14 +103,21 @@ expr_t::ptr_op_t xact_t::lookup(const string& name) case 'a': if (name[1] == '\0' || name == "amount") return WRAP_FUNCTOR(bind(get_amount, _1)); + else if (name == "account") + return WRAP_FUNCTOR(bind(get_account, _1)); + else if (name == "account_base") + return WRAP_FUNCTOR(bind(get_account_base, _1)); + break; + case 'd': + if (name[1] == '\0' || name == "date") + return WRAP_FUNCTOR(bind(get_date, _1)); + break; + case 'p': + if (name[1] == '\0' || name == "payee") + return WRAP_FUNCTOR(bind(get_payee, _1)); break; } - -#if 0 return entry->lookup(name); -#else - return expr_t::ptr_op_t(); -#endif } bool xact_t::valid() const