diff options
Diffstat (limited to 'src/post.cc')
-rw-r--r-- | src/post.cc | 271 |
1 files changed, 150 insertions, 121 deletions
diff --git a/src/post.cc b/src/post.cc index 7dc15830..4fc34892 100644 --- a/src/post.cc +++ b/src/post.cc @@ -35,49 +35,57 @@ #include "xact.h" #include "account.h" #include "journal.h" -#include "interactive.h" #include "format.h" namespace ledger { -bool post_t::has_tag(const string& tag) const +bool post_t::has_tag(const string& tag, bool inherit) const { if (item_t::has_tag(tag)) return true; - if (xact) + if (inherit && xact) return xact->has_tag(tag); return false; } bool post_t::has_tag(const mask_t& tag_mask, - const optional<mask_t>& value_mask) const + const optional<mask_t>& value_mask, + bool inherit) const { if (item_t::has_tag(tag_mask, value_mask)) return true; - if (xact) + if (inherit && xact) return xact->has_tag(tag_mask, value_mask); return false; } -optional<string> post_t::get_tag(const string& tag) const +optional<value_t> post_t::get_tag(const string& tag, bool inherit) const { - if (optional<string> value = item_t::get_tag(tag)) + if (optional<value_t> value = item_t::get_tag(tag)) return value; - if (xact) + if (inherit && xact) return xact->get_tag(tag); return none; } -optional<string> post_t::get_tag(const mask_t& tag_mask, - const optional<mask_t>& value_mask) const +optional<value_t> post_t::get_tag(const mask_t& tag_mask, + const optional<mask_t>& value_mask, + bool inherit) const { - if (optional<string> value = item_t::get_tag(tag_mask, value_mask)) + if (optional<value_t> value = item_t::get_tag(tag_mask, value_mask)) return value; - if (xact) + if (inherit && xact) return xact->get_tag(tag_mask, value_mask); return none; } +date_t post_t::value_date() const +{ + if (xdata_ && is_valid(xdata_->value_date)) + return xdata_->value_date; + return date(); +} + date_t post_t::date() const { if (xdata_ && is_valid(xdata_->date)) @@ -117,9 +125,17 @@ optional<date_t> post_t::effective_date() const return date; } +string post_t::payee() const +{ + if (optional<value_t> post_payee = get_tag(_("Payee"))) + return post_payee->as_string(); + else + return xact->payee; +} + namespace { value_t get_this(post_t& post) { - return value_t(static_cast<scope_t *>(&post)); + return scope_value(&post); } value_t get_is_calculated(post_t& post) { @@ -139,7 +155,7 @@ namespace { } value_t get_xact(post_t& post) { - return value_t(static_cast<scope_t *>(post.xact)); + return scope_value(post.xact); } value_t get_xact_id(post_t& post) { @@ -154,7 +170,7 @@ namespace { } value_t get_payee(post_t& post) { - return string_value(post.xact->payee); + return string_value(post.payee()); } value_t get_note(post_t& post) { @@ -190,20 +206,25 @@ namespace { return post.has_xdata() && post.xdata().has_flags(POST_EXT_DIRECT_AMT); } - value_t get_commodity(post_t& post) { - if (post.has_xdata() && - post.xdata().has_flags(POST_EXT_COMPOUND)) - return string_value(post.xdata().compound_value.to_amount() - .commodity().symbol()); - else - return string_value(post.amount.commodity().symbol()); + value_t get_commodity(call_scope_t& args) + { + if (args.has<amount_t>(0)) { + return string_value(args.get<amount_t>(0).commodity().symbol()); + } else { + post_t& post(args.context<post_t>()); + if (post.has_xdata() && post.xdata().has_flags(POST_EXT_COMPOUND)) + return string_value(post.xdata().compound_value.to_amount() + .commodity().symbol()); + else + return string_value(post.amount.commodity().symbol()); + } } value_t get_commodity_is_primary(post_t& post) { if (post.has_xdata() && - post.xdata().has_flags(POST_EXT_COMPOUND)) + post.xdata().has_flags(POST_EXT_COMPOUND)) return post.xdata().compound_value.to_amount() - .commodity().has_flags(COMMODITY_PRIMARY); + .commodity().has_flags(COMMODITY_PRIMARY); else return post.amount.commodity().has_flags(COMMODITY_PRIMARY); } @@ -216,7 +237,7 @@ namespace { if (post.cost) return *post.cost; else if (post.has_xdata() && - post.xdata().has_flags(POST_EXT_COMPOUND)) + post.xdata().has_flags(POST_EXT_COMPOUND)) return post.xdata().compound_value; else if (post.amount.is_null()) return 0L; @@ -240,73 +261,71 @@ namespace { return 1L; } - value_t account_name(call_scope_t& scope) + value_t get_account(call_scope_t& args) { - in_context_t<post_t> env(scope, "&v"); - - string name; - - if (env.has(0)) { - if (env.value_at(0).is_long()) { - if (env.get<long>(0) > 2) - name = format_t::truncate(env->reported_account()->fullname(), - env.get<long>(0) - 2, - 2 /* account_abbrev_length */); - else - name = env->reported_account()->fullname(); + post_t& post(args.context<post_t>()); + account_t& account(*post.reported_account()); + string name; + + if (args.has(0)) { + if (args[0].is_long()) { + if (args.get<long>(0) > 2) + name = format_t::truncate(account.fullname(), + args.get<long>(0) - 2, + 2 /* account_abbrev_length */); + else + name = account.fullname(); } else { - account_t * account = NULL; - account_t * master = env->account; - while (master->parent) - master = master->parent; - - if (env.value_at(0).is_string()) { - name = env.get<string>(0); - account = master->find_account(name, false); - } - else if (env.value_at(0).is_mask()) { - name = env.get<mask_t>(0).str(); - account = master->find_account_re(name); - } - else { - throw_(std::runtime_error, - _("Expected string or mask for argument 1, but received %1") - << env.value_at(0).label()); - } - - if (! account) - throw_(std::runtime_error, - _("Could not find an account matching ") << env.value_at(0)); - else - return value_t(static_cast<scope_t *>(account)); + account_t * acct = NULL; + account_t * master = &account; + while (master->parent) + master = master->parent; + + if (args[0].is_string()) { + name = args.get<string>(0); + acct = master->find_account(name, false); + } + else if (args[0].is_mask()) { + name = args.get<mask_t>(0).str(); + acct = master->find_account_re(name); + } + else { + throw_(std::runtime_error, + _("Expected string or mask for argument 1, but received %1") + << args[0].label()); + } + + if (! acct) + throw_(std::runtime_error, + _("Could not find an account matching ") << args[0]); + else + return value_t(static_cast<scope_t *>(acct)); } - } else { - name = env->reported_account()->fullname(); + } + else if (args.type_context() == value_t::SCOPE) { + return scope_value(&account); + } + else { + name = account.fullname(); } return string_value(name); } - value_t get_display_account(call_scope_t& scope) + value_t get_display_account(call_scope_t& args) { - in_context_t<post_t> env(scope, "&v"); - - value_t acct = account_name(scope); + post_t& post(args.context<post_t>()); + value_t acct = get_account(args); if (acct.is_string()) { - if (env->has_flags(POST_VIRTUAL)) { - if (env->must_balance()) - acct = string_value(string("[") + acct.as_string() + "]"); - else - acct = string_value(string("(") + acct.as_string() + ")"); + if (post.has_flags(POST_VIRTUAL)) { + if (post.must_balance()) + acct = string_value(string("[") + acct.as_string() + "]"); + else + acct = string_value(string("(") + acct.as_string() + ")"); } } return acct; } - value_t get_account(call_scope_t& scope) - { - return account_name(scope); - } - value_t get_account_id(post_t& post) { return static_cast<long>(post.account_id()); } @@ -319,6 +338,14 @@ namespace { return long(post.reported_account()->depth); } + value_t get_value_date(post_t& post) { + if (post.has_xdata()) { + post_t::xdata_t& xdata(post.xdata()); + if (! xdata.value_date.is_not_a_date()) + return xdata.value_date; + } + return post.date(); + } value_t get_datetime(post_t& post) { return post.xdata().datetime; } @@ -328,45 +355,45 @@ namespace { return (*Func)(find_scope<post_t>(scope)); } - value_t fn_any(call_scope_t& scope) + value_t fn_any(call_scope_t& args) { - interactive_t args(scope, "X&X"); - - post_t& post(find_scope<post_t>(scope)); - expr_t& expr(args.get<expr_t&>(0)); + post_t& post(args.context<post_t>()); + expr_t::ptr_op_t expr(args.get<expr_t::ptr_op_t>(0)); foreach (post_t * p, post.xact->posts) { - bind_scope_t bound_scope(scope, *p); - if (p == &post && args.has(1) && - ! args.get<expr_t&>(1).calc(bound_scope).to_boolean()) { - // If the user specifies any(EXPR, false), and the context is a - // posting, then that posting isn't considered by the test. - ; // skip it + bind_scope_t bound_scope(args, *p); + if (p == &post && args.has<expr_t::ptr_op_t>(1) && + ! args.get<expr_t::ptr_op_t>(1) + ->calc(bound_scope, args.locus, args.depth).to_boolean()) { + // If the user specifies any(EXPR, false), and the context is a + // posting, then that posting isn't considered by the test. + ; // skip it } - else if (expr.calc(bound_scope).to_boolean()) { - return true; + else if (expr->calc(bound_scope, args.locus, + args.depth).to_boolean()) { + return true; } } return false; } - value_t fn_all(call_scope_t& scope) + value_t fn_all(call_scope_t& args) { - interactive_t args(scope, "X&X"); - - post_t& post(find_scope<post_t>(scope)); - expr_t& expr(args.get<expr_t&>(0)); + post_t& post(args.context<post_t>()); + expr_t::ptr_op_t expr(args.get<expr_t::ptr_op_t>(0)); foreach (post_t * p, post.xact->posts) { - bind_scope_t bound_scope(scope, *p); - if (p == &post && args.has(1) && - ! args.get<expr_t&>(1).calc(bound_scope).to_boolean()) { - // If the user specifies any(EXPR, false), and the context is a - // posting, then that posting isn't considered by the test. - ; // skip it + bind_scope_t bound_scope(args, *p); + if (p == &post && args.has<expr_t::ptr_op_t>(1) && + ! args.get<expr_t::ptr_op_t>(1) + ->calc(bound_scope, args.locus, args.depth).to_boolean()) { + // If the user specifies any(EXPR, false), and the context is a + // posting, then that posting isn't considered by the test. + ; // skip it } - else if (! expr.calc(bound_scope).to_boolean()) { - return false; + else if (! expr->calc(bound_scope, args.locus, + args.depth).to_boolean()) { + return false; } } return true; @@ -374,7 +401,7 @@ namespace { } expr_t::ptr_op_t post_t::lookup(const symbol_t::kind_t kind, - const string& name) + const string& name) { if (kind != symbol_t::FUNCTION) return item_t::lookup(kind, name); @@ -412,7 +439,7 @@ expr_t::ptr_op_t post_t::lookup(const symbol_t::kind_t kind, else if (name == "calculated") return WRAP_FUNCTOR(get_wrapper<&get_is_calculated>); else if (name == "commodity") - return WRAP_FUNCTOR(get_wrapper<&get_commodity>); + return WRAP_FUNCTOR(&get_commodity); break; case 'd': @@ -479,6 +506,8 @@ expr_t::ptr_op_t post_t::lookup(const symbol_t::kind_t kind, case 'v': if (name == "virtual") return WRAP_FUNCTOR(get_wrapper<&get_virtual>); + else if (name == "value_date") + return WRAP_FUNCTOR(get_wrapper<&get_value_date>); break; case 'x': @@ -516,7 +545,7 @@ amount_t post_t::resolve_expr(scope_t& scope, expr_t& expr) } else { if (! result.is_amount()) throw_(amount_error, - _("Amount expressions must result in a simple amount")); + _("Amount expressions must result in a simple amount")); return result.as_amount(); } } @@ -554,7 +583,7 @@ bool post_t::valid() const posts_list::const_iterator i = std::find(xact->posts.begin(), - xact->posts.end(), this); + xact->posts.end(), this); if (i == xact->posts.end()) { DEBUG("ledger.validate", "post_t: ! found"); return false; @@ -591,7 +620,7 @@ void post_t::add_to_value(value_t& value, const optional<expr_t&>& expr) const } else if (expr) { bind_scope_t bound_scope(*expr->get_context(), - const_cast<post_t&>(*this)); + const_cast<post_t&>(*this)); #if 1 value_t temp(expr->calc(bound_scope)); add_or_set_value(value, temp); @@ -604,7 +633,7 @@ void post_t::add_to_value(value_t& value, const optional<expr_t&>& expr) const #endif } else if (xdata_ && xdata_->has_flags(POST_EXT_VISITED) && - ! xdata_->visited_value.is_null()) { + ! xdata_->visited_value.is_null()) { add_or_set_value(value, xdata_->visited_value); } else { @@ -691,18 +720,18 @@ void to_xml(std::ostream& out, const post_t& post) push_xml y(out, "metadata"); foreach (const item_t::string_map::value_type& pair, *post.metadata) { if (pair.second.first) { - push_xml z(out, "variable"); - { - push_xml z(out, "key"); - out << y.guard(pair.first); - } - { - push_xml z(out, "value"); - out << y.guard(*pair.second.first); - } + push_xml z(out, "variable"); + { + push_xml z(out, "key"); + out << y.guard(pair.first); + } + { + push_xml z(out, "value"); + to_xml(out, *pair.second.first); + } } else { - push_xml z(out, "tag"); - out << y.guard(pair.first); + push_xml z(out, "tag"); + out << y.guard(pair.first); } } } |