Re-enabled almost all of the old reporting code, which means it compiles now

within the new scheme.
This commit is contained in:
John Wiegley 2008-08-02 23:34:28 -04:00
parent 5a90fe7357
commit dfc14dfff3
6 changed files with 313 additions and 244 deletions

1
expr.h
View file

@ -39,6 +39,7 @@ namespace ledger {
DECLARE_EXCEPTION(parse_error, std::runtime_error); DECLARE_EXCEPTION(parse_error, std::runtime_error);
DECLARE_EXCEPTION(compile_error, std::runtime_error); DECLARE_EXCEPTION(compile_error, std::runtime_error);
DECLARE_EXCEPTION(calc_error, std::runtime_error); DECLARE_EXCEPTION(calc_error, std::runtime_error);
DECLARE_EXCEPTION(usage_error, std::runtime_error);
class scope_t; class scope_t;
class call_scope_t; class call_scope_t;

View file

@ -61,6 +61,7 @@ class format_t : public noncopyable
string format_string; string format_string;
scoped_ptr<element_t> elements; scoped_ptr<element_t> elements;
public:
enum elision_style_t { enum elision_style_t {
TRUNCATE_TRAILING, TRUNCATE_TRAILING,
TRUNCATE_MIDDLE, TRUNCATE_MIDDLE,
@ -68,6 +69,8 @@ class format_t : public noncopyable
ABBREVIATE ABBREVIATE
}; };
private:
// jww (2008-08-02): Should these four be here, or in session_t?
static elision_style_t elision_style; static elision_style_t elision_style;
static int abbrev_length; static int abbrev_length;

413
report.cc
View file

@ -34,6 +34,185 @@
namespace ledger { namespace ledger {
#if 0
void
report_t::regexps_to_predicate(const std::string& command,
std::list<std::string>::const_iterator begin,
std::list<std::string>::const_iterator end,
const bool account_regexp,
const bool add_account_short_masks,
const bool logical_and)
{
std::string regexps[2];
assert(begin != end);
// Treat the remaining command-line arguments as regular
// expressions, used for refining report results.
for (std::list<std::string>::const_iterator i = begin;
i != end;
i++)
if ((*i)[0] == '-') {
if (! regexps[1].empty())
regexps[1] += "|";
regexps[1] += (*i).substr(1);
}
else if ((*i)[0] == '+') {
if (! regexps[0].empty())
regexps[0] += "|";
regexps[0] += (*i).substr(1);
}
else {
if (! regexps[0].empty())
regexps[0] += "|";
regexps[0] += *i;
}
for (int i = 0; i < 2; i++) {
if (regexps[i].empty())
continue;
if (! predicate.empty())
predicate += logical_and ? "&" : "|";
int add_predicate = 0; // 1 adds /.../, 2 adds ///.../
if (i == 1) {
predicate += "!";
}
else if (add_account_short_masks) {
if (regexps[i].find(':') != std::string::npos ||
regexps[i].find('.') != std::string::npos ||
regexps[i].find('*') != std::string::npos ||
regexps[i].find('+') != std::string::npos ||
regexps[i].find('[') != std::string::npos ||
regexps[i].find('(') != std::string::npos) {
show_subtotal = true;
add_predicate = 1;
} else {
add_predicate = 2;
}
}
else {
add_predicate = 1;
}
if (i != 1 && command == "b" && account_regexp) {
if (! show_related && ! show_all_related) {
if (! display_predicate.empty())
display_predicate += "&";
if (! show_empty)
display_predicate += "T&";
if (add_predicate == 2)
display_predicate += "//";
display_predicate += "/(?:";
display_predicate += regexps[i];
display_predicate += ")/";
}
else if (! show_empty) {
if (! display_predicate.empty())
display_predicate += "&";
display_predicate += "T";
}
}
if (! account_regexp)
predicate += "/";
predicate += "/(?:";
predicate += regexps[i];
predicate += ")/";
}
}
void report_t::process_options(const std::string& command,
strings_list::iterator arg,
strings_list::iterator args_end)
{
// Configure some other options depending on report type
if (command == "p" || command == "e" || command == "w") {
show_related =
show_all_related = true;
}
else if (command == "E") {
show_subtotal = true;
}
else if (show_related) {
if (command == "r") {
show_inverted = true;
} else {
show_subtotal = true;
show_all_related = true;
}
}
if (command != "b" && command != "r")
amount_t::keep_base = true;
// Process remaining command-line arguments
if (command != "e") {
// Treat the remaining command-line arguments as regular
// expressions, used for refining report results.
std::list<std::string>::iterator i = arg;
for (; i != args_end; i++)
if (*i == "--")
break;
if (i != arg)
regexps_to_predicate(command, arg, i, true,
(command == "b" && ! show_subtotal &&
display_predicate.empty()));
if (i != args_end && ++i != args_end)
regexps_to_predicate(command, i, args_end);
}
// Setup the default value for the display predicate
if (display_predicate.empty()) {
if (command == "b") {
if (! show_empty)
display_predicate = "T";
if (! show_subtotal) {
if (! display_predicate.empty())
display_predicate += "&";
display_predicate += "l<=1";
}
}
else if (command == "E") {
display_predicate = "t";
}
else if (command == "r" && ! show_empty) {
display_predicate = "a";
}
}
DEBUG_PRINT("ledger.config.predicates", "Predicate: " << predicate);
DEBUG_PRINT("ledger.config.predicates", "Display P: " << display_predicate);
// Setup the values of %t and %T, used in format strings
if (! amount_expr.empty())
ledger::amount_expr = amount_expr;
if (! total_expr.empty())
ledger::total_expr = total_expr;
// Now setup the various formatting strings
if (! date_output_format.empty())
date_t::output_format = date_output_format;
amount_t::keep_price = keep_price;
amount_t::keep_date = keep_date;
amount_t::keep_tag = keep_tag;
if (! report_period.empty() && ! sort_all)
entry_sort = true;
}
#endif
xact_handler_ptr xact_handler_ptr
report_t::chain_xact_handlers(xact_handler_ptr base_handler, report_t::chain_xact_handlers(xact_handler_ptr base_handler,
const bool handle_individual_xacts) const bool handle_individual_xacts)
@ -179,7 +358,7 @@ report_t::chain_xact_handlers(xact_handler_ptr base_handler,
budget_xacts * budget_handler budget_xacts * budget_handler
= new budget_xacts(handler, budget_flags); = new budget_xacts(handler, budget_flags);
budget_handler->add_period_entries(journal->period_entries); budget_handler->add_period_entries(journal->period_entries);
handler.reset(budget_handler; handler.reset(budget_handler);
// Apply this before the budget handler, so that only matching // Apply this before the budget handler, so that only matching
// xacts are calculated toward the budget. The use of // xacts are calculated toward the budget. The use of
@ -239,8 +418,9 @@ void report_t::sum_all_accounts()
sum_accounts(*session.master); sum_accounts(*session.master);
} }
void report_t::accounts_report(acct_handler_ptr handler, void report_t::accounts_report(acct_handler_ptr handler,
const bool print_final_total) const bool print_final_total,
optional<std::ostream&> ostream)
{ {
sum_all_accounts(); sum_all_accounts();
@ -253,16 +433,21 @@ void report_t::accounts_report(acct_handler_ptr handler,
} }
handler->flush(); handler->flush();
if (print_final_total && account_has_xdata(*session.master)) {
account_xdata_t& xdata = account_xdata(*session.master);
if (! show_collapsed && xdata.total) {
#if 0 #if 0
*out << "--------------------\n"; // jww (2008-08-02): I need access to the output formatter before this is
// going to work.
if (print_final_total) {
assert(ostream);
assert(account_has_xdata(*session.master));
account_xdata_t& xdata(account_xdata(*session.master));
if (! show_collapsed && xdata.total) {
*ostream << "--------------------\n";
xdata.value = xdata.total; xdata.value = xdata.total;
handler->format.format(*out, details_t(*journal->master)); handler->format.format(*ostream, *session.master);
#endif
} }
} }
#endif
if (DO_VERIFY()) { if (DO_VERIFY()) {
session.clean_xacts(); session.clean_xacts();
@ -278,30 +463,24 @@ void report_t::entry_report(const entry_t& entry, const string& format)
{ {
} }
#if 0
value_t report_t::abbrev(call_scope_t& args) value_t report_t::abbrev(call_scope_t& args)
{ {
if (args.size() < 2) if (args.size() < 2)
throw_(std::logic_error, "usage: abbrev(STRING, WIDTH [, STYLE, ABBREV_LEN])"); throw_(usage_error, "usage: abbrev(STRING, WIDTH [, STYLE, ABBREV_LEN])");
string str = args[0].as_string(); const var_t<string> str(args, 0);
#if 0 const var_t<long> wid(args, 1);
long wid = args[1]; const var_t<long> style(args, 2);
const var_t<long> abbrev_len(args, 3);
elision_style_t style = session.elision_style; return value_t(abbreviate(*str, *wid,
if (args.size() == 3) (style ?
style = static_cast<elision_style_t>(args[2].as_long()); static_cast<format_t::elision_style_t>(*style) :
#endif session.elision_style),
true,
long abbrev_len = session.abbrev_length; abbrev_len ? *abbrev_len : session.abbrev_len),
if (args.size() == 4) true);
abbrev_len = args[3].as_long();
#if 0
return value_t(abbreviate(str, wid, style, true,
static_cast<int>(abbrev_len)), true);
#else
return NULL_VALUE;
#endif
} }
value_t report_t::ftime(call_scope_t& args) value_t report_t::ftime(call_scope_t& args)
@ -314,36 +493,10 @@ value_t report_t::ftime(call_scope_t& args)
string date_format; string date_format;
if (args.size() == 2) if (args.size() == 2)
date_format = args[1].as_string(); date_format = args[1].as_string();
#if 0
// jww (2007-04-18): Need to setup an output facet here
else else
date_format = moment_t::output_format; date_format = moment_t::output_format;
return string_value(date.as_string(date_format)); return string_value(date.as_string(date_format));
#else
return NULL_VALUE;
#endif
}
#if 0
optional<value_t>
report_t::resolve(const string& name, call_scope_t& args)
{
const char * p = name.c_str();
switch (*p) {
case 'a':
if (name == "abbrev") {
return abbrev(args);
}
break;
case 'f':
if (name == "ftime") {
return ftime(args);
}
break;
}
return scope_t::resolve(name, args);
} }
#endif #endif
@ -356,13 +509,8 @@ expr_t::ptr_op_t report_t::lookup(const string& name)
p = p + 4; p = p + 4;
switch (*p) { switch (*p) {
case 'a': case 'a':
#if 0 if (std::strcmp(p, "amount") == 0)
if (std::strcmp(p, "accounts") == 0) return MAKE_FUNCTOR(report_t::option_amount);
return MAKE_FUNCTOR(report_t::option_accounts);
else
#endif
if (std::strcmp(p, "amount") == 0)
return MAKE_FUNCTOR(report_t::option_amount);
break; break;
case 'b': case 'b':
@ -370,73 +518,11 @@ expr_t::ptr_op_t report_t::lookup(const string& name)
return MAKE_FUNCTOR(report_t::option_bar); return MAKE_FUNCTOR(report_t::option_bar);
break; break;
#if 0
case 'c':
if (std::strcmp(p, "clean") == 0)
return MAKE_FUNCTOR(report_t::option_clean);
else if (std::strcmp(p, "compact") == 0)
return MAKE_FUNCTOR(report_t::option_compact);
break;
#endif
case 'e':
#if 0
if (std::strcmp(p, "entries") == 0)
return MAKE_FUNCTOR(report_t::option_entries);
else if (std::strcmp(p, "eval") == 0)
return MAKE_FUNCTOR(report_t::option_eval);
else if (std::strcmp(p, "exclude") == 0)
return MAKE_FUNCTOR(report_t::option_remove);
#endif
break;
case 'f': case 'f':
#if 0 if (std::strcmp(p, "format") == 0)
if (std::strcmp(p, "foo") == 0)
return MAKE_FUNCTOR(report_t::option_foo);
else
#endif
if (std::strcmp(p, "format") == 0)
return MAKE_FUNCTOR(report_t::option_format); return MAKE_FUNCTOR(report_t::option_format);
break; break;
case 'i':
#if 0
if (std::strcmp(p, "include") == 0)
return MAKE_FUNCTOR(report_t::option_select);
#endif
break;
case 'l':
#if 0
if (! *(p + 1) || std::strcmp(p, "limit") == 0)
return MAKE_FUNCTOR(report_t::option_limit);
#endif
break;
#if 0
case 'm':
if (std::strcmp(p, "merge") == 0)
return MAKE_FUNCTOR(report_t::option_merge);
break;
#endif
case 'r':
#if 0
if (std::strcmp(p, "remove") == 0)
return MAKE_FUNCTOR(report_t::option_remove);
#endif
break;
#if 0
case 's':
if (std::strcmp(p, "select") == 0)
return MAKE_FUNCTOR(report_t::option_select);
else if (std::strcmp(p, "split") == 0)
return MAKE_FUNCTOR(report_t::option_split);
break;
#endif
case 't': case 't':
if (! *(p + 1)) if (! *(p + 1))
return MAKE_FUNCTOR(report_t::option_amount); return MAKE_FUNCTOR(report_t::option_amount);
@ -496,21 +582,20 @@ void format_xacts::operator()(xact_t& xact)
void format_entries::format_last_entry() void format_entries::format_last_entry()
{ {
#if 0
bool first = true; bool first = true;
foreach (const transaction_t * xact, last_entry->xacts) {
if (xact_has_xdata(*xact) && foreach (xact_t * xact, last_entry->xacts) {
xact_xdata_(*xact).dflags & XACT_TO_DISPLAY) { if (xact->has_xdata() &&
xact->xdata().has_flags(XACT_EXT_TO_DISPLAY)) {
if (first) { if (first) {
first_line_format.format(output_stream, details_t(*xact)); first_line_format.format(output_stream, *xact);
first = false; first = false;
} else { } else {
next_lines_format.format(output_stream, details_t(*xact)); next_lines_format.format(output_stream, *xact);
} }
xact_xdata_(*xact).dflags |= XACT_DISPLAYED; xact->xdata().add_flags(XACT_EXT_DISPLAYED);
} }
} }
#endif
} }
void format_entries::operator()(xact_t& xact) void format_entries::operator()(xact_t& xact)
@ -557,29 +642,30 @@ void print_entry(std::ostream& out, const entry_base_t& entry_base,
#endif #endif
} }
bool disp_subaccounts_p(const account_t& account, bool disp_subaccounts_p(account_t& account,
item_predicate<account_t>& disp_pred, item_predicate<account_t>& disp_pred,
const account_t *& to_show) account_t *& to_show)
{ {
bool display = false; bool display = false;
#if 0
unsigned int counted = 0; unsigned int counted = 0;
bool matches = disp_pred ? (*disp_pred)(account) : true; bool matches = disp_pred(account);
bool computed = false; bool computed = false;
#endif
value_t acct_total; value_t acct_total;
value_t result; value_t result;
to_show = NULL; to_show = NULL;
#if 0 foreach (accounts_map::value_type pair, account.accounts) {
for (accounts_map::value_type pair, account.accounts) { if (! disp_pred(*pair.second))
if (disp_pred && ! (*disp_pred)(*pair.second))
continue; continue;
compute_total(result, details_t(*pair.second)); #if 0
compute_total(result, *pair.second);
#endif
if (! computed) { if (! computed) {
compute_total(acct_total, details_t(account)); #if 0
compute_total(acct_total, account);
#endif
computed = true; computed = true;
} }
@ -590,13 +676,11 @@ bool disp_subaccounts_p(const account_t& account,
to_show = pair.second; to_show = pair.second;
counted++; counted++;
} }
#endif
return display; return display;
} }
bool display_account(const account_t& account, bool display_account(account_t& account, item_predicate<account_t>& disp_pred)
item_predicate<account_t>& disp_pred)
{ {
// Never display an account that has already been displayed. // Never display an account that has already been displayed.
if (account_has_xdata(account) && if (account_has_xdata(account) &&
@ -610,26 +694,23 @@ bool display_account(const account_t& account,
// determine if it is a parent that must be displayed regardless of // determine if it is a parent that must be displayed regardless of
// the predicate. // the predicate.
const account_t * account_to_show = NULL; account_t * account_to_show = NULL;
if (disp_subaccounts_p(account, disp_pred, account_to_show)) if (disp_subaccounts_p(account, disp_pred, account_to_show))
return true; return true;
return (! account_to_show && return ! account_to_show && disp_pred(account);
disp_pred(const_cast<account_t&>(account)));
} }
void format_accounts::operator()(account_t& account) void format_accounts::operator()(account_t& account)
{ {
#if 0
if (display_account(account, disp_pred)) { if (display_account(account, disp_pred)) {
if (! account.parent) { if (! account.parent) {
account_xdata(account).dflags |= ACCOUNT_TO_DISPLAY; account_xdata(account).dflags |= ACCOUNT_TO_DISPLAY;
} else { } else {
format.format(output_stream, details_t(account)); format.format(output_stream, account);
account_xdata(account).dflags |= ACCOUNT_DISPLAYED; account_xdata(account).dflags |= ACCOUNT_DISPLAYED;
} }
} }
#endif
} }
format_equity::format_equity(std::ostream& _output_stream, format_equity::format_equity(std::ostream& _output_stream,
@ -637,26 +718,23 @@ format_equity::format_equity(std::ostream& _output_stream,
const string& display_predicate) const string& display_predicate)
: output_stream(_output_stream), disp_pred(display_predicate) : output_stream(_output_stream), disp_pred(display_predicate)
{ {
#if 0
const char * f = _format.c_str(); const char * f = _format.c_str();
if (const char * p = std::strstr(f, "%/")) { if (const char * p = std::strstr(f, "%/")) {
first_line_format.reset(string(f, 0, p - f)); first_line_format.parse(string(f, 0, p - f));
next_lines_format.reset(string(p + 2)); next_lines_format.parse(string(p + 2));
} else { } else {
first_line_format.reset(_format); first_line_format.parse(_format);
next_lines_format.reset(_format); next_lines_format.parse(_format);
} }
entry_t header_entry; entry_t header_entry;
header_entry.payee = "Opening Balances"; header_entry.payee = "Opening Balances";
header_entry._date = current_moment; header_entry._date = current_date;
first_line_format.format(output_stream, details_t(header_entry)); first_line_format.format(output_stream, header_entry);
#endif
} }
void format_equity::flush() void format_equity::flush()
{ {
#if 0
account_xdata_t xdata; account_xdata_t xdata;
xdata.value = total; xdata.value = total;
xdata.value.negate(); xdata.value.negate();
@ -672,21 +750,19 @@ void format_equity::flush()
else else
assert(false); assert(false);
for (balance_t::amounts_map::value_type pair, bal->amounts) { foreach (balance_t::amounts_map::value_type pair, bal->amounts) {
xdata.value = pair.second; xdata.value = pair.second;
xdata.value.negate(); xdata.value.negate();
next_lines_format.format(output_stream, details_t(summary)); next_lines_format.format(output_stream, summary);
} }
} else { } else {
next_lines_format.format(output_stream, details_t(summary)); next_lines_format.format(output_stream, summary);
} }
output_stream.flush(); output_stream.flush();
#endif
} }
void format_equity::operator()(account_t& account) void format_equity::operator()(account_t& account)
{ {
#if 0
if (display_account(account, disp_pred)) { if (display_account(account, disp_pred)) {
if (account_has_xdata(account)) { if (account_has_xdata(account)) {
value_t val = account_xdata_(account).value; value_t val = account_xdata_(account).value;
@ -700,19 +776,18 @@ void format_equity::operator()(account_t& account)
else else
assert(false); assert(false);
for (balance_t::amounts_map::value_type pair, bal->amounts) { foreach (balance_t::amounts_map::value_type pair, bal->amounts) {
account_xdata_(account).value = pair.second; account_xdata_(account).value = pair.second;
next_lines_format.format(output_stream, details_t(account)); next_lines_format.format(output_stream, account);
} }
account_xdata_(account).value = val; account_xdata_(account).value = val;
} else { } else {
next_lines_format.format(output_stream, details_t(account)); next_lines_format.format(output_stream, account);
} }
total += val; total += val;
} }
account_xdata(account).dflags |= ACCOUNT_DISPLAYED; account_xdata(account).dflags |= ACCOUNT_DISPLAYED;
} }
#endif
} }
} // namespace ledger } // namespace ledger

View file

@ -88,9 +88,8 @@ class report_t : public noncopyable, public scope_t
public: public:
optional<path> output_file; optional<path> output_file;
string format_string; string format_string;
string amount_expr;
string total_expr;
string date_output_format; string date_output_format;
string predicate; string predicate;
string secondary_predicate; string secondary_predicate;
@ -103,6 +102,9 @@ public:
string reconcile_balance; string reconcile_balance;
string reconcile_date; string reconcile_date;
expr_t amount_expr;
expr_t total_expr;
unsigned long budget_flags; unsigned long budget_flags;
int head_entries; int head_entries;
@ -135,7 +137,10 @@ public:
session_t& session; session_t& session;
explicit report_t(session_t& _session) explicit report_t(session_t& _session)
: head_entries(0), : amount_expr("amount"),
total_expr("total"),
head_entries(0),
tail_entries(0), tail_entries(0),
show_collapsed(false), show_collapsed(false),
@ -162,13 +167,6 @@ public:
session(_session) session(_session)
{ {
TRACE_CTOR(report_t, "session_t&"); TRACE_CTOR(report_t, "session_t&");
#if 0
eval("t=total,TOT=0,T()=(TOT=TOT+t,TOT)");
value_expr_t::amount_expr.reset(new value_expr("a"));
value_expr_t::total_expr.reset(new value_expr("O"));
#endif
} }
virtual ~report_t() { virtual ~report_t() {
@ -189,8 +187,9 @@ public:
void sum_all_accounts(); void sum_all_accounts();
void accounts_report(acct_handler_ptr handler, void accounts_report(acct_handler_ptr handler,
const bool print_final_total = true); const bool print_final_total = true,
optional<std::ostream&> ostream = none);
void commodities_report(const string& format); void commodities_report(const string& format);
@ -243,54 +242,6 @@ public:
return args[0]; return args[0];
} }
//
// Transform options
//
#if 0
value_t option_select(call_scope_t& args) {
transforms.push_back(new select_transform(args[0].as_string()));
return NULL_VALUE;
}
value_t option_limit(call_scope_t& args) {
string expr = (string("//xact[") +
args[0].as_string() + "]");
transforms.push_back(new select_transform(expr));
return NULL_VALUE;
}
value_t option_remove(call_scope_t& args) {
transforms.push_back(new remove_transform(args[0].as_string()));
return NULL_VALUE;
}
value_t option_accounts(call_scope_t& args) {
transforms.push_back(new accounts_transform);
return NULL_VALUE;
}
value_t option_compact(call_scope_t& args) {
transforms.push_back(new compact_transform);
return NULL_VALUE;
}
value_t option_clean(call_scope_t& args) {
transforms.push_back(new clean_transform);
return NULL_VALUE;
}
value_t option_entries(call_scope_t& args) {
transforms.push_back(new entries_transform);
return NULL_VALUE;
}
value_t option_split(call_scope_t& args) {
transforms.push_back(new split_transform);
return NULL_VALUE;
}
value_t option_merge(call_scope_t& args) {
transforms.push_back(new merge_transform);
return NULL_VALUE;
}
#endif
// //
// Scope members // Scope members
// //
@ -348,15 +299,15 @@ class format_entries : public format_xacts
virtual void operator()(xact_t& xact); virtual void operator()(xact_t& xact);
}; };
void print_entry(std::ostream& out, const entry_base_t& entry, void print_entry(std::ostream& out,
const string& prefix = ""); const entry_base_t& entry,
const string& prefix = "");
bool disp_subaccounts_p(const account_t& account, bool disp_subaccounts_p(account_t& account,
item_predicate<account_t>& disp_pred, item_predicate<account_t>& disp_pred,
const account_t *& to_show); account_t *& to_show);
bool display_account(const account_t& account, bool display_account(account_t& account, item_predicate<account_t>& disp_pred);
item_predicate<account_t>& disp_pred);
class format_accounts : public item_handler<account_t> class format_accounts : public item_handler<account_t>
{ {

52
scope.h
View file

@ -209,27 +209,67 @@ public:
template <typename T> template <typename T>
class var_t : public noncopyable class var_t : public noncopyable
{ {
value_t value; optional<value_t> value;
var_t(); var_t();
public: public:
var_t(scope_t& scope, const string& name) : value(scope.resolve(name)) { var_t(scope_t& scope, const string& name)
{
TRACE_CTOR(var_t, "scope_t&, const string&"); TRACE_CTOR(var_t, "scope_t&, const string&");
try {
value = scope.resolve(name);
}
catch (...) {
DEBUG("scope.var_t", "Failed lookup var_t(\"" << name << "\")");
value = none;
}
} }
var_t(call_scope_t& scope, const unsigned int idx) : value(scope[idx]) {
var_t(call_scope_t& scope, const unsigned int idx)
{
TRACE_CTOR(var_t, "call_scope_t&, const unsigned int"); TRACE_CTOR(var_t, "call_scope_t&, const unsigned int");
if (idx < scope.size())
value = scope[idx];
else
value = none;
} }
~var_t() throw() { ~var_t() throw() {
TRACE_DTOR(var_t); TRACE_DTOR(var_t);
} }
operator T() { assert(false); } operator bool() { return value; }
T& operator *();
const T& operator *() const;
T * operator->() {
return &**this;
}
const T * operator->() const {
return &**this;
}
}; };
template <> template <>
inline var_t<long>::operator long() { inline long& var_t<long>::operator *() {
return value.to_long(); return value->as_long_lval();
}
template <>
inline const long& var_t<long>::operator *() const {
return value->as_long();
}
template <>
inline string& var_t<string>::operator *() {
return value->as_string_lval();
}
template <>
inline const string& var_t<string>::operator *() const {
return value->as_string();
} }
} // namespace ledger } // namespace ledger

View file

@ -35,6 +35,7 @@
#include "scope.h" #include "scope.h"
#include "journal.h" #include "journal.h"
#include "account.h" #include "account.h"
#include "format.h"
namespace ledger { namespace ledger {
@ -75,9 +76,7 @@ public:
datetime_t now; datetime_t now;
date_t today; date_t today;
#if 0 format_t::elision_style_t elision_style;
elision_style_t elision_style;
#endif
int abbrev_length; int abbrev_length;
bool ansi_codes; bool ansi_codes;