summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJohn Wiegley <johnw@newartisans.com>2009-11-04 20:40:07 -0500
committerJohn Wiegley <johnw@newartisans.com>2009-11-04 20:40:48 -0500
commit78e6770c4c276db3647952f21a6bf3ea465edb88 (patch)
tree64190d80ea0c3933dffaee3cf0e43cde5ea0e6a6
parent4a14f3224b9063202ca39a67c9aff42ae4274942 (diff)
downloadfork-ledger-78e6770c4c276db3647952f21a6bf3ea465edb88.tar.gz
fork-ledger-78e6770c4c276db3647952f21a6bf3ea465edb88.tar.bz2
fork-ledger-78e6770c4c276db3647952f21a6bf3ea465edb88.zip
Segregated symbols into 5 separate namespaces
The different namespaces are: Function Value expression functions, which receive a "context" Option Command-line options Precommand Commands which are invoked before reading the journal Command Commands which are invoked after reading the journal Directive Directives that occur at column 0 in a data file This greatly eases the ability for Python uses to add intercept hooks to change how the basic Ledger module functions. An example of what should be possible soon: import ledger def my_foo_handler(value): print "--foo received:", value ledger.add_handler(ledger.Option, "foo=", my_foo_handler)
-rw-r--r--src/account.cc6
-rw-r--r--src/account.h3
-rw-r--r--src/global.cc44
-rw-r--r--src/global.h3
-rw-r--r--src/item.cc6
-rw-r--r--src/item.h3
-rw-r--r--src/op.cc14
-rw-r--r--src/option.cc22
-rw-r--r--src/option.h24
-rw-r--r--src/post.cc8
-rw-r--r--src/post.h3
-rw-r--r--src/py_value.cc2
-rw-r--r--src/pyinterp.cc46
-rw-r--r--src/pyinterp.h3
-rw-r--r--src/report.cc562
-rw-r--r--src/report.h6
-rw-r--r--src/scope.cc23
-rw-r--r--src/scope.h93
-rw-r--r--src/session.cc29
-rw-r--r--src/session.h3
-rw-r--r--src/textual.cc14
-rw-r--r--src/xact.cc8
-rw-r--r--src/xact.h3
23 files changed, 507 insertions, 421 deletions
diff --git a/src/account.cc b/src/account.cc
index 23761049..2a75a6ac 100644
--- a/src/account.cc
+++ b/src/account.cc
@@ -241,8 +241,12 @@ namespace {
}
}
-expr_t::ptr_op_t account_t::lookup(const string& name)
+expr_t::ptr_op_t account_t::lookup(const symbol_t::kind_t kind,
+ const string& name)
{
+ if (kind != symbol_t::FUNCTION)
+ return NULL;
+
switch (name[0]) {
case 'a':
if (name == "amount")
diff --git a/src/account.h b/src/account.h
index ac4a4788..7d51a08e 100644
--- a/src/account.h
+++ b/src/account.h
@@ -119,7 +119,8 @@ public:
}
bool remove_post(post_t * post);
- virtual expr_t::ptr_op_t lookup(const string& name);
+ virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
+ const string& name);
bool valid() const;
diff --git a/src/global.cc b/src/global.cc
index d9028dd7..97a46cce 100644
--- a/src/global.cc
+++ b/src/global.cc
@@ -314,28 +314,32 @@ option_t<global_scope_t> * global_scope_t::lookup_option(const char * p)
return NULL;
}
-expr_t::ptr_op_t global_scope_t::lookup(const string& name)
+expr_t::ptr_op_t global_scope_t::lookup(const symbol_t::kind_t kind,
+ const string& name)
{
- const char * p = name.c_str();
- switch (*p) {
- case 'o':
- if (WANT_OPT()) { p += OPT_PREFIX_LEN;
- if (option_t<global_scope_t> * handler = lookup_option(p))
- return MAKE_OPT_HANDLER(global_scope_t, handler);
- }
+ switch (kind) {
+ case symbol_t::FUNCTION:
+ if (option_t<global_scope_t> * handler = lookup_option(name.c_str()))
+ return MAKE_OPT_FUNCTOR(global_scope_t, handler);
break;
- case 'p':
- if (WANT_PRECMD()) { const char * q = p + PRECMD_PREFIX_LEN;
- switch (*q) {
- case 'p':
- if (is_eq(q, "push"))
- return MAKE_FUNCTOR(global_scope_t::push_command);
- else if (is_eq(q, "pop"))
- return MAKE_FUNCTOR(global_scope_t::pop_command);
- break;
- }
+ case symbol_t::OPTION:
+ if (option_t<global_scope_t> * handler = lookup_option(name.c_str()))
+ return MAKE_OPT_HANDLER(global_scope_t, handler);
+ break;
+
+ case symbol_t::PRECOMMAND: {
+ const char * p = name.c_str();
+ switch (*p) {
+ case 'p':
+ if (is_eq(p, "push"))
+ return MAKE_FUNCTOR(global_scope_t::push_command);
+ else if (is_eq(p, "pop"))
+ return MAKE_FUNCTOR(global_scope_t::pop_command);
+ break;
}
+ }
+ default:
break;
}
@@ -396,7 +400,7 @@ void global_scope_t::normalize_session_options()
function_t global_scope_t::look_for_precommand(scope_t& scope,
const string& verb)
{
- if (expr_t::ptr_op_t def = scope.lookup(string(PRECMD_PREFIX) + verb))
+ if (expr_t::ptr_op_t def = scope.lookup(symbol_t::PRECOMMAND, verb))
return def->as_function();
else
return function_t();
@@ -405,7 +409,7 @@ function_t global_scope_t::look_for_precommand(scope_t& scope,
function_t global_scope_t::look_for_command(scope_t& scope,
const string& verb)
{
- if (expr_t::ptr_op_t def = scope.lookup(string(CMD_PREFIX) + verb))
+ if (expr_t::ptr_op_t def = scope.lookup(symbol_t::COMMAND, verb))
return def->as_function();
else
return function_t();
diff --git a/src/global.h b/src/global.h
index df9845d5..34577656 100644
--- a/src/global.h
+++ b/src/global.h
@@ -117,7 +117,8 @@ See LICENSE file included with the distribution for details and disclaimer.");
option_t<global_scope_t> * lookup_option(const char * p);
- virtual expr_t::ptr_op_t lookup(const string& name);
+ virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
+ const string& name);
OPTION(global_scope_t, args_only);
OPTION(global_scope_t, debug_);
diff --git a/src/item.cc b/src/item.cc
index 37e19a82..acef2e44 100644
--- a/src/item.cc
+++ b/src/item.cc
@@ -304,8 +304,12 @@ value_t get_comment(item_t& item)
}
}
-expr_t::ptr_op_t item_t::lookup(const string& name)
+expr_t::ptr_op_t item_t::lookup(const symbol_t::kind_t kind,
+ const string& name)
{
+ if (kind != symbol_t::FUNCTION)
+ return NULL;
+
switch (name[0]) {
case 'a':
if (name == "actual")
diff --git a/src/item.h b/src/item.h
index 98b30c70..ea510a5e 100644
--- a/src/item.h
+++ b/src/item.h
@@ -189,7 +189,8 @@ public:
return _state;
}
- virtual expr_t::ptr_op_t lookup(const string& name);
+ virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
+ const string& name);
bool valid() const;
diff --git a/src/op.cc b/src/op.cc
index 67db5136..c4925143 100644
--- a/src/op.cc
+++ b/src/op.cc
@@ -43,7 +43,7 @@ expr_t::ptr_op_t expr_t::op_t::compile(scope_t& scope, const int depth)
if (is_ident()) {
DEBUG("expr.compile", "lookup: " << as_ident());
- if (ptr_op_t def = scope.lookup(as_ident())) {
+ if (ptr_op_t def = scope.lookup(symbol_t::FUNCTION, as_ident())) {
// Identifier references are first looked up at the point of
// definition, and then at the point of every use if they could
// not be found there.
@@ -65,11 +65,11 @@ expr_t::ptr_op_t expr_t::op_t::compile(scope_t& scope, const int depth)
if (kind == O_DEFINE) {
switch (left()->kind) {
case IDENT:
- scope.define(left()->as_ident(), right());
+ scope.define(symbol_t::FUNCTION, left()->as_ident(), right());
break;
case O_CALL:
if (left()->left()->is_ident())
- scope.define(left()->left()->as_ident(), this);
+ scope.define(symbol_t::FUNCTION, left()->left()->as_ident(), this);
else
throw_(compile_error, _("Invalid function definition"));
break;
@@ -152,9 +152,10 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus, const int depth)
if (! varname->is_ident())
throw_(calc_error, _("Invalid function definition"));
else if (args_index == args_count)
- local_scope.define(varname->as_ident(), wrap_value(false));
+ local_scope.define(symbol_t::FUNCTION, varname->as_ident(),
+ wrap_value(false));
else
- local_scope.define(varname->as_ident(),
+ local_scope.define(symbol_t::FUNCTION, varname->as_ident(),
wrap_value(call_args[args_index++]));
}
@@ -178,7 +179,8 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus, const int depth)
_("Left operand of . operator is NULL"));
} else {
scope_t& objscope(*obj.as_scope());
- if (ptr_op_t member = objscope.lookup(right()->as_ident())) {
+ if (ptr_op_t member =
+ objscope.lookup(symbol_t::FUNCTION, right()->as_ident())) {
result = member->calc(objscope, NULL, depth + 1);
break;
}
diff --git a/src/option.cc b/src/option.cc
index 8da66b36..6d230939 100644
--- a/src/option.cc
+++ b/src/option.cc
@@ -41,8 +41,7 @@ namespace {
op_bool_tuple find_option(scope_t& scope, const string& name)
{
char buf[128];
- std::strcpy(buf, "opt_");
- char * p = &buf[4];
+ char * p = buf;
foreach (char ch, name) {
if (ch == '-')
*p++ = '_';
@@ -52,28 +51,27 @@ namespace {
*p++ = '_';
*p = '\0';
- if (expr_t::ptr_op_t op = scope.lookup(buf))
+ if (expr_t::ptr_op_t op = scope.lookup(symbol_t::OPTION, buf))
return op_bool_tuple(op, true);
*--p = '\0';
- return op_bool_tuple(scope.lookup(buf), false);
+ return op_bool_tuple(scope.lookup(symbol_t::OPTION, buf), false);
}
op_bool_tuple find_option(scope_t& scope, const char letter)
{
- char buf[10];
- std::strcpy(buf, "opt_");
- buf[4] = letter;
- buf[5] = '_';
- buf[6] = '\0';
+ char buf[4];
+ buf[0] = letter;
+ buf[1] = '_';
+ buf[2] = '\0';
- if (expr_t::ptr_op_t op = scope.lookup(buf))
+ if (expr_t::ptr_op_t op = scope.lookup(symbol_t::OPTION, buf))
return op_bool_tuple(op, true);
- buf[5] = '\0';
+ buf[1] = '\0';
- return op_bool_tuple(scope.lookup(buf), false);
+ return op_bool_tuple(scope.lookup(symbol_t::OPTION, buf), false);
}
void process_option(const string& whence, const function_t& opt,
diff --git a/src/option.h b/src/option.h
index 7e2e0629..c9903c03 100644
--- a/src/option.h
+++ b/src/option.h
@@ -283,30 +283,6 @@ inline bool is_eq(const char * p, const char * n) {
} \
END(name)
-#define OPT_PREFIX "opt_"
-#define OPT_PREFIX_LEN 4
-
-#define WANT_OPT() \
- (std::strncmp(p, OPT_PREFIX, OPT_PREFIX_LEN) == 0)
-
-#define PRECMD_PREFIX "precmd_"
-#define PRECMD_PREFIX_LEN 7
-
-#define WANT_PRECMD() \
- (std::strncmp(p, PRECMD_PREFIX, PRECMD_PREFIX_LEN) == 0)
-
-#define CMD_PREFIX "cmd_"
-#define CMD_PREFIX_LEN 4
-
-#define WANT_CMD() \
- (std::strncmp(p, CMD_PREFIX, CMD_PREFIX_LEN) == 0)
-
-#define DIR_PREFIX "dir_"
-#define DIR_PREFIX_LEN 4
-
-#define WANT_DIR() \
- (std::strncmp(p, DIR_PREFIX, DIR_PREFIX_LEN) == 0)
-
bool process_option(const string& whence, const string& name, scope_t& scope,
const char * arg, const string& varname);
diff --git a/src/post.cc b/src/post.cc
index 2a1663cb..d7923866 100644
--- a/src/post.cc
+++ b/src/post.cc
@@ -271,8 +271,12 @@ namespace {
}
}
-expr_t::ptr_op_t post_t::lookup(const string& name)
+expr_t::ptr_op_t post_t::lookup(const symbol_t::kind_t kind,
+ const string& name)
{
+ if (kind != symbol_t::FUNCTION)
+ return item_t::lookup(kind, name);
+
switch (name[0]) {
case 'a':
if (name[1] == '\0' || name == "amount")
@@ -366,7 +370,7 @@ expr_t::ptr_op_t post_t::lookup(const string& name)
break;
}
- return item_t::lookup(name);
+ return item_t::lookup(kind, name);
}
bool post_t::valid() const
diff --git a/src/post.h b/src/post.h
index 5a07299e..42217d60 100644
--- a/src/post.h
+++ b/src/post.h
@@ -119,7 +119,8 @@ public:
return ! has_flags(POST_VIRTUAL) || has_flags(POST_MUST_BALANCE);
}
- virtual expr_t::ptr_op_t lookup(const string& name);
+ virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
+ const string& name);
bool valid() const;
diff --git a/src/py_value.cc b/src/py_value.cc
index 86311736..eec3b833 100644
--- a/src/py_value.cc
+++ b/src/py_value.cc
@@ -51,7 +51,7 @@ namespace {
{
if (value.is_scope()) {
if (scope_t * scope = value.as_scope())
- return expr_t(scope->lookup(name), scope);
+ return expr_t(scope->lookup(symbol_t::FUNCTION, name), scope);
}
throw_(value_error, _("Cannot lookup attributes in %1") << value.label());
return expr_t();
diff --git a/src/pyinterp.cc b/src/pyinterp.cc
index 005fc57a..8c79e9c7 100644
--- a/src/pyinterp.cc
+++ b/src/pyinterp.cc
@@ -285,38 +285,40 @@ python_interpreter_t::lookup_option(const char * p)
return NULL;
}
-expr_t::ptr_op_t python_interpreter_t::lookup(const string& name)
+expr_t::ptr_op_t python_interpreter_t::lookup(const symbol_t::kind_t kind,
+ const string& name)
{
// Give our superclass first dibs on symbol definitions
- if (expr_t::ptr_op_t op = session_t::lookup(name))
+ if (expr_t::ptr_op_t op = session_t::lookup(kind, name))
return op;
- const char * p = name.c_str();
- switch (*p) {
- case 'o':
- if (WANT_OPT()) { const char * q = p + OPT_PREFIX_LEN;
- if (option_t<python_interpreter_t> * handler = lookup_option(q))
- return MAKE_OPT_HANDLER(python_interpreter_t, handler);
+ switch (kind) {
+ case symbol_t::FUNCTION:
+ if (is_initialized && main_nspace.has_key(name.c_str())) {
+ DEBUG("python.interp", "Python lookup: " << name);
+
+ if (python::object obj = main_nspace.get(name.c_str()))
+ return WRAP_FUNCTOR(functor_t(name, obj));
}
break;
- case 'p':
- if (WANT_PRECMD()) { const char * q = p + PRECMD_PREFIX_LEN;
- switch (*q) {
- case 'p':
- if (is_eq(q, "python"))
- return MAKE_FUNCTOR(python_interpreter_t::python_command);
- break;
- }
- }
+ case symbol_t::OPTION:
+ if (option_t<python_interpreter_t> * handler = lookup_option(name.c_str()))
+ return MAKE_OPT_HANDLER(python_interpreter_t, handler);
break;
- }
- if (is_initialized && main_nspace.has_key(name.c_str())) {
- DEBUG("python.interp", "Python lookup: " << name);
+ case symbol_t::PRECOMMAND: {
+ const char * p = name.c_str();
+ switch (*p) {
+ case 'p':
+ if (is_eq(p, "python"))
+ return MAKE_FUNCTOR(python_interpreter_t::python_command);
+ break;
+ }
+ }
- if (python::object obj = main_nspace.get(name.c_str()))
- return WRAP_FUNCTOR(functor_t(name, obj));
+ default:
+ break;
}
return NULL;
diff --git a/src/pyinterp.h b/src/pyinterp.h
index 4943eb2f..002e8af1 100644
--- a/src/pyinterp.h
+++ b/src/pyinterp.h
@@ -103,7 +103,8 @@ public:
option_t<python_interpreter_t> * lookup_option(const char * p);
- virtual expr_t::ptr_op_t lookup(const string& name);
+ virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
+ const string& name);
#if BOOST_VERSION >= 103700
OPTION_(python_interpreter_t, import_, DO_(scope) {
diff --git a/src/report.cc b/src/report.cc
index fe482a2e..883b324a 100644
--- a/src/report.cc
+++ b/src/report.cc
@@ -464,8 +464,8 @@ value_t report_t::echo_command(call_scope_t& scope)
bool report_t::maybe_import(const string& module)
{
- if (lookup(string(OPT_PREFIX) + "import_")) {
- expr_t(string(OPT_PREFIX) + "import_(\"" + module + "\")").calc(*this);
+ if (lookup(symbol_t::OPTION, "import_")) {
+ expr_t(string("import_(\"") + module + "\")").calc(*this);
return true;
}
return false;
@@ -707,304 +707,316 @@ option_t<report_t> * report_t::lookup_option(const char * p)
return NULL;
}
-void report_t::define(const string& name, expr_t::ptr_op_t def)
+void report_t::define(const symbol_t::kind_t kind, const string& name,
+ expr_t::ptr_op_t def)
{
- session.define(name, def);
+ session.define(kind, name, def);
}
-expr_t::ptr_op_t report_t::lookup(const string& name)
+expr_t::ptr_op_t report_t::lookup(const symbol_t::kind_t kind,
+ const string& name)
{
- if (expr_t::ptr_op_t def = session.lookup(name))
+ if (expr_t::ptr_op_t def = session.lookup(kind, name))
return def;
const char * p = name.c_str();
- switch (*p) {
- case 'a':
- if (is_eq(p, "amount_expr"))
- return MAKE_FUNCTOR(report_t::fn_amount_expr);
- else if (is_eq(p, "ansify_if"))
- return MAKE_FUNCTOR(report_t::fn_ansify_if);
- else if (is_eq(p, "abs"))
- return MAKE_FUNCTOR(report_t::fn_abs);
- break;
-
- case 'b':
- if (is_eq(p, "black"))
- return WRAP_FUNCTOR(fn_black);
- else if (is_eq(p, "blink"))
- return WRAP_FUNCTOR(fn_blink);
- else if (is_eq(p, "blue"))
- return WRAP_FUNCTOR(fn_blue);
- else if (is_eq(p, "bold"))
- return WRAP_FUNCTOR(fn_bold);
- break;
-
- case 'c':
- if (WANT_CMD()) { const char * q = p + CMD_PREFIX_LEN;
- switch (*q) {
- case 'b':
- if (*(q + 1) == '\0' || is_eq(q, "bal") || is_eq(q, "balance")) {
- return expr_t::op_t::wrap_functor
- (reporter<account_t, acct_handler_ptr, &report_t::accounts_report>
- (new format_accounts(*this, report_format(HANDLER(balance_format_))),
- *this, "#balance"));
- }
- else if (is_eq(q, "budget")) {
- HANDLER(amount_).set_expr(string("#budget"), "(amount, 0)");
-
- budget_flags |= BUDGET_WRAP_VALUES;
- if (! (budget_flags & ~BUDGET_WRAP_VALUES))
- budget_flags |= BUDGET_BUDGETED;
- return expr_t::op_t::wrap_functor
- (reporter<account_t, acct_handler_ptr, &report_t::accounts_report>
- (new format_accounts(*this, report_format(HANDLER(budget_format_))),
- *this, "#budget"));
- }
- break;
-
- case 'c':
- if (is_eq(q, "csv")) {
- return WRAP_FUNCTOR
- (reporter<>
- (new format_posts(*this, report_format(HANDLER(csv_format_))),
- *this, "#csv"));
- }
- else if (is_eq(q, "cleared")) {
- HANDLER(amount_).set_expr(string("#cleared"),
- "(amount, cleared ? amount : 0)");
-
- return expr_t::op_t::wrap_functor
- (reporter<account_t, acct_handler_ptr, &report_t::accounts_report>
- (new format_accounts(*this, report_format(HANDLER(cleared_format_))),
- *this, "#cleared"));
- }
- break;
-
- case 'e':
- if (is_eq(q, "equity"))
- return WRAP_FUNCTOR
- (reporter<>
- (new format_posts(*this, report_format(HANDLER(print_format_))),
- *this, "#equity"));
- else if (is_eq(q, "entry"))
- return WRAP_FUNCTOR(xact_command);
- else if (is_eq(q, "emacs"))
- return WRAP_FUNCTOR
- (reporter<>(new format_emacs_posts(output_stream), *this, "#emacs"));
- else if (is_eq(q, "echo"))
- return MAKE_FUNCTOR(report_t::echo_command);
- break;
-
- case 'p':
- if (*(q + 1) == '\0' || is_eq(q, "print"))
- return WRAP_FUNCTOR
- (reporter<>
- (new format_posts(*this, report_format(HANDLER(print_format_)),
- HANDLED(raw)), *this, "#print"));
- else if (is_eq(q, "prices"))
- return expr_t::op_t::wrap_functor
- (reporter<post_t, post_handler_ptr, &report_t::commodities_report>
- (new format_posts(*this, report_format(HANDLER(prices_format_))),
- *this, "#prices"));
- else if (is_eq(q, "pricesdb"))
- return expr_t::op_t::wrap_functor
- (reporter<post_t, post_handler_ptr, &report_t::commodities_report>
- (new format_posts(*this, report_format(HANDLER(pricesdb_format_))),
- *this, "#pricesdb"));
- else if (is_eq(q, "python") && maybe_import("ledger.interp"))
- return session.lookup(string(CMD_PREFIX) + "python");
- break;
-
- case 'r':
- if (*(q + 1) == '\0' || is_eq(q, "reg") || is_eq(q, "register"))
- return WRAP_FUNCTOR
- (reporter<>
- (new format_posts(*this, report_format(HANDLER(register_format_))),
- *this, "#register"));
- else if (is_eq(q, "reload"))
- return MAKE_FUNCTOR(report_t::reload_command);
- break;
-
- case 's':
- if (is_eq(q, "stats") || is_eq(q, "stat"))
- return WRAP_FUNCTOR(report_statistics);
- else
- if (is_eq(q, "server") && maybe_import("ledger.server"))
- return session.lookup(string(CMD_PREFIX) + "server");
- break;
-
- case 'x':
- if (is_eq(q, "xact"))
- return WRAP_FUNCTOR(xact_command);
- break;
- }
+ switch (kind) {
+ case symbol_t::FUNCTION:
+ switch (*p) {
+ case 'a':
+ if (is_eq(p, "amount_expr"))
+ return MAKE_FUNCTOR(report_t::fn_amount_expr);
+ else if (is_eq(p, "ansify_if"))
+ return MAKE_FUNCTOR(report_t::fn_ansify_if);
+ else if (is_eq(p, "abs"))
+ return MAKE_FUNCTOR(report_t::fn_abs);
+ break;
+
+ case 'b':
+ if (is_eq(p, "black"))
+ return WRAP_FUNCTOR(fn_black);
+ else if (is_eq(p, "blink"))
+ return WRAP_FUNCTOR(fn_blink);
+ else if (is_eq(p, "blue"))
+ return WRAP_FUNCTOR(fn_blue);
+ else if (is_eq(p, "bold"))
+ return WRAP_FUNCTOR(fn_bold);
+ break;
+
+ case 'c':
+ if (is_eq(p, "cyan"))
+ return WRAP_FUNCTOR(fn_cyan);
+ break;
+
+ case 'd':
+ if (is_eq(p, "display_amount"))
+ return MAKE_FUNCTOR(report_t::fn_display_amount);
+ else if (is_eq(p, "display_total"))
+ return MAKE_FUNCTOR(report_t::fn_display_total);
+ else if (is_eq(p, "date"))
+ return MAKE_FUNCTOR(report_t::fn_now);
+ break;
+
+ case 'f':
+ if (is_eq(p, "format_date"))
+ return MAKE_FUNCTOR(report_t::fn_format_date);
+ break;
+
+ case 'g':
+ if (is_eq(p, "get_at"))
+ return MAKE_FUNCTOR(report_t::fn_get_at);
+ else if (is_eq(p, "green"))
+ return WRAP_FUNCTOR(fn_green);
+ break;
+
+ case 'i':
+ if (is_eq(p, "is_seq"))
+ return MAKE_FUNCTOR(report_t::fn_is_seq);
+ break;
+
+ case 'j':
+ if (is_eq(p, "justify"))
+ return MAKE_FUNCTOR(report_t::fn_justify);
+ else if (is_eq(p, "join"))
+ return MAKE_FUNCTOR(report_t::fn_join);
+ break;
+
+ case 'm':
+ if (is_eq(p, "market"))
+ return MAKE_FUNCTOR(report_t::fn_market);
+ else if (is_eq(p, "magenta"))
+ return WRAP_FUNCTOR(fn_magenta);
+ break;
+
+ case 'n':
+ if (is_eq(p, "null"))
+ return WRAP_FUNCTOR(fn_null);
+ else if (is_eq(p, "now"))
+ return MAKE_FUNCTOR(report_t::fn_now);
+ break;
+
+ case 'o':
+ if (is_eq(p, "options"))
+ return MAKE_FUNCTOR(report_t::fn_options);
+ break;
+
+ case 'p':
+ if (is_eq(p, "post"))
+ return WRAP_FUNCTOR(fn_false);
+ else if (is_eq(p, "percent"))
+ return MAKE_FUNCTOR(report_t::fn_percent);
+ else if (is_eq(p, "price"))
+ return MAKE_FUNCTOR(report_t::fn_price);
+ break;
+
+ case 'q':
+ if (is_eq(p, "quoted"))
+ return MAKE_FUNCTOR(report_t::fn_quoted);
+ else if (is_eq(p, "quantity"))
+ return MAKE_FUNCTOR(report_t::fn_quantity);
+ break;
+
+ case 'r':
+ if (is_eq(p, "rounded"))
+ return MAKE_FUNCTOR(report_t::fn_rounded);
+ else if (is_eq(p, "red"))
+ return WRAP_FUNCTOR(fn_red);
+ break;
+
+ case 's':
+ if (is_eq(p, "scrub"))
+ return MAKE_FUNCTOR(report_t::fn_scrub);
+ else if (is_eq(p, "strip"))
+ return MAKE_FUNCTOR(report_t::fn_strip);
+ break;
+
+ case 't':
+ if (is_eq(p, "truncated"))
+ return MAKE_FUNCTOR(report_t::fn_truncated);
+ else if (is_eq(p, "total_expr"))
+ return MAKE_FUNCTOR(report_t::fn_total_expr);
+ else if (is_eq(p, "today"))
+ return MAKE_FUNCTOR(report_t::fn_today);
+ else if (is_eq(p, "t"))
+ return MAKE_FUNCTOR(report_t::fn_display_amount);
+ break;
+
+ case 'T':
+ if (is_eq(p, "T"))
+ return MAKE_FUNCTOR(report_t::fn_display_total);
+ break;
+
+ case 'u':
+ if (is_eq(p, "underline"))
+ return WRAP_FUNCTOR(fn_underline);
+ else if (is_eq(p, "unrounded"))
+ return MAKE_FUNCTOR(report_t::fn_unrounded);
+ break;
+
+ case 'w':
+ if (is_eq(p, "white"))
+ return WRAP_FUNCTOR(fn_white);
+ break;
+
+ case 'y':
+ if (is_eq(p, "yellow"))
+ return WRAP_FUNCTOR(fn_yellow);
+ break;
}
- else if (is_eq(p, "cyan"))
- return WRAP_FUNCTOR(fn_cyan);
- break;
- case 'd':
- if (is_eq(p, "display_amount"))
- return MAKE_FUNCTOR(report_t::fn_display_amount);
- else if (is_eq(p, "display_total"))
- return MAKE_FUNCTOR(report_t::fn_display_total);
- else if (is_eq(p, "date"))
- return MAKE_FUNCTOR(report_t::fn_now);
+ // Check if they are trying to access an option's setting or value.
+ if (option_t<report_t> * handler = lookup_option(p))
+ return MAKE_OPT_FUNCTOR(report_t, handler);
break;
- case 'f':
- if (is_eq(p, "format_date"))
- return MAKE_FUNCTOR(report_t::fn_format_date);
- break;
-
- case 'g':
- if (is_eq(p, "get_at"))
- return MAKE_FUNCTOR(report_t::fn_get_at);
- else if (is_eq(p, "green"))
- return WRAP_FUNCTOR(fn_green);
+ case symbol_t::OPTION:
+ if (option_t<report_t> * handler = lookup_option(p))
+ return MAKE_OPT_HANDLER(report_t, handler);
break;
- case 'i':
- if (is_eq(p, "is_seq"))
- return MAKE_FUNCTOR(report_t::fn_is_seq);
- break;
-
- case 'j':
- if (is_eq(p, "justify"))
- return MAKE_FUNCTOR(report_t::fn_justify);
- else if (is_eq(p, "join"))
- return MAKE_FUNCTOR(report_t::fn_join);
- break;
-
- case 'm':
- if (is_eq(p, "market"))
- return MAKE_FUNCTOR(report_t::fn_market);
- else if (is_eq(p, "magenta"))
- return WRAP_FUNCTOR(fn_magenta);
- break;
-
- case 'n':
- if (is_eq(p, "null"))
- return WRAP_FUNCTOR(fn_null);
- else if (is_eq(p, "now"))
- return MAKE_FUNCTOR(report_t::fn_now);
- break;
+ case symbol_t::COMMAND:
+ switch (*p) {
+ case 'b':
+ if (*(p + 1) == '\0' || is_eq(p, "bal") || is_eq(p, "balance")) {
+ return expr_t::op_t::wrap_functor
+ (reporter<account_t, acct_handler_ptr, &report_t::accounts_report>
+ (new format_accounts(*this, report_format(HANDLER(balance_format_))),
+ *this, "#balance"));
+ }
+ else if (is_eq(p, "budget")) {
+ HANDLER(amount_).set_expr(string("#budget"), "(amount, 0)");
- case 'o':
- if (WANT_OPT()) { const char * q = p + OPT_PREFIX_LEN;
- if (option_t<report_t> * handler = lookup_option(q))
- return MAKE_OPT_HANDLER(report_t, handler);
- }
- else if (is_eq(p, "options")) {
- return MAKE_FUNCTOR(report_t::fn_options);
- }
- break;
+ budget_flags |= BUDGET_WRAP_VALUES;
+ if (! (budget_flags & ~BUDGET_WRAP_VALUES))
+ budget_flags |= BUDGET_BUDGETED;
- case 'p':
- if (WANT_PRECMD()) { const char * q = p + PRECMD_PREFIX_LEN;
- switch (*q) {
- case 'a':
- if (is_eq(q, "args"))
- return WRAP_FUNCTOR(args_command);
- break;
- case 'e':
- if (is_eq(q, "eval"))
- return WRAP_FUNCTOR(eval_command);
- break;
- case 'f':
- if (is_eq(q, "format"))
- return WRAP_FUNCTOR(format_command);
- break;
- case 'g':
- if (is_eq(q, "generate"))
- return expr_t::op_t::wrap_functor
- (reporter<post_t, post_handler_ptr, &report_t::generate_report>
- (new format_posts(*this, report_format(HANDLER(print_format_)),
- false), *this, "#generate"));
- case 'h':
- if (is_eq(q, "hello") && maybe_import("ledger.hello"))
- return session.lookup(string(PRECMD_PREFIX) + "hello");
- break;
- case 'p':
- if (is_eq(q, "parse"))
- return WRAP_FUNCTOR(parse_command);
- else if (is_eq(q, "period"))
- return WRAP_FUNCTOR(period_command);
- break;
- case 't':
- if (is_eq(q, "template"))
- return WRAP_FUNCTOR(template_command);
- break;
+ return expr_t::op_t::wrap_functor
+ (reporter<account_t, acct_handler_ptr, &report_t::accounts_report>
+ (new format_accounts(*this, report_format(HANDLER(budget_format_))),
+ *this, "#budget"));
+ }
+ break;
+
+ case 'c':
+ if (is_eq(p, "csv")) {
+ return WRAP_FUNCTOR
+ (reporter<>
+ (new format_posts(*this, report_format(HANDLER(csv_format_))),
+ *this, "#csv"));
+ }
+ else if (is_eq(p, "cleared")) {
+ HANDLER(amount_).set_expr(string("#cleared"),
+ "(amount, cleared ? amount : 0)");
+
+ return expr_t::op_t::wrap_functor
+ (reporter<account_t, acct_handler_ptr, &report_t::accounts_report>
+ (new format_accounts(*this, report_format(HANDLER(cleared_format_))),
+ *this, "#cleared"));
}
+ break;
+
+ case 'e':
+ if (is_eq(p, "equity"))
+ return WRAP_FUNCTOR
+ (reporter<>
+ (new format_posts(*this, report_format(HANDLER(print_format_))),
+ *this, "#equity"));
+ else if (is_eq(p, "entry"))
+ return WRAP_FUNCTOR(xact_command);
+ else if (is_eq(p, "emacs"))
+ return WRAP_FUNCTOR
+ (reporter<>(new format_emacs_posts(output_stream), *this, "#emacs"));
+ else if (is_eq(p, "echo"))
+ return MAKE_FUNCTOR(report_t::echo_command);
+ break;
+
+ case 'p':
+ if (*(p + 1) == '\0' || is_eq(p, "print"))
+ return WRAP_FUNCTOR
+ (reporter<>
+ (new format_posts(*this, report_format(HANDLER(print_format_)),
+ HANDLED(raw)), *this, "#print"));
+ else if (is_eq(p, "prices"))
+ return expr_t::op_t::wrap_functor
+ (reporter<post_t, post_handler_ptr, &report_t::commodities_report>
+ (new format_posts(*this, report_format(HANDLER(prices_format_))),
+ *this, "#prices"));
+ else if (is_eq(p, "pricesdb"))
+ return expr_t::op_t::wrap_functor
+ (reporter<post_t, post_handler_ptr, &report_t::commodities_report>
+ (new format_posts(*this, report_format(HANDLER(pricesdb_format_))),
+ *this, "#pricesdb"));
+ else if (is_eq(p, "python") && maybe_import("ledger.interp"))
+ return session.lookup(symbol_t::COMMAND, "python");
+ break;
+
+ case 'r':
+ if (*(p + 1) == '\0' || is_eq(p, "reg") || is_eq(p, "register"))
+ return WRAP_FUNCTOR
+ (reporter<>
+ (new format_posts(*this, report_format(HANDLER(register_format_))),
+ *this, "#register"));
+ else if (is_eq(p, "reload"))
+ return MAKE_FUNCTOR(report_t::reload_command);
+ break;
+
+ case 's':
+ if (is_eq(p, "stats") || is_eq(p, "stat"))
+ return WRAP_FUNCTOR(report_statistics);
+ else
+ if (is_eq(p, "server") && maybe_import("ledger.server"))
+ return session.lookup(symbol_t::COMMAND, "server");
+ break;
+
+ case 'x':
+ if (is_eq(p, "xact"))
+ return WRAP_FUNCTOR(xact_command);
+ break;
}
- else if (is_eq(p, "post"))
- return WRAP_FUNCTOR(fn_false);
- else if (is_eq(p, "percent"))
- return MAKE_FUNCTOR(report_t::fn_percent);
- else if (is_eq(p, "price"))
- return MAKE_FUNCTOR(report_t::fn_price);
- break;
-
- case 'q':
- if (is_eq(p, "quoted"))
- return MAKE_FUNCTOR(report_t::fn_quoted);
- else if (is_eq(p, "quantity"))
- return MAKE_FUNCTOR(report_t::fn_quantity);
- break;
-
- case 'r':
- if (is_eq(p, "rounded"))
- return MAKE_FUNCTOR(report_t::fn_rounded);
- else if (is_eq(p, "red"))
- return WRAP_FUNCTOR(fn_red);
- break;
-
- case 's':
- if (is_eq(p, "scrub"))
- return MAKE_FUNCTOR(report_t::fn_scrub);
- else if (is_eq(p, "strip"))
- return MAKE_FUNCTOR(report_t::fn_strip);
- break;
-
- case 't':
- if (is_eq(p, "truncated"))
- return MAKE_FUNCTOR(report_t::fn_truncated);
- else if (is_eq(p, "total_expr"))
- return MAKE_FUNCTOR(report_t::fn_total_expr);
- else if (is_eq(p, "today"))
- return MAKE_FUNCTOR(report_t::fn_today);
- else if (is_eq(p, "t"))
- return MAKE_FUNCTOR(report_t::fn_display_amount);
- break;
-
- case 'T':
- if (is_eq(p, "T"))
- return MAKE_FUNCTOR(report_t::fn_display_total);
break;
- case 'u':
- if (is_eq(p, "underline"))
- return WRAP_FUNCTOR(fn_underline);
- else if (is_eq(p, "unrounded"))
- return MAKE_FUNCTOR(report_t::fn_unrounded);
- break;
-
- case 'w':
- if (is_eq(p, "white"))
- return WRAP_FUNCTOR(fn_white);
+ case symbol_t::PRECOMMAND:
+ switch (*p) {
+ case 'a':
+ if (is_eq(p, "args"))
+ return WRAP_FUNCTOR(args_command);
+ break;
+ case 'e':
+ if (is_eq(p, "eval"))
+ return WRAP_FUNCTOR(eval_command);
+ break;
+ case 'f':
+ if (is_eq(p, "format"))
+ return WRAP_FUNCTOR(format_command);
+ break;
+ case 'g':
+ if (is_eq(p, "generate"))
+ return expr_t::op_t::wrap_functor
+ (reporter<post_t, post_handler_ptr, &report_t::generate_report>
+ (new format_posts(*this, report_format(HANDLER(print_format_)),
+ false), *this, "#generate"));
+ case 'h':
+ if (is_eq(p, "hello") && maybe_import("ledger.hello"))
+ return session.lookup(symbol_t::PRECOMMAND, "hello");
+ break;
+ case 'p':
+ if (is_eq(p, "parse"))
+ return WRAP_FUNCTOR(parse_command);
+ else if (is_eq(p, "period"))
+ return WRAP_FUNCTOR(period_command);
+ break;
+ case 't':
+ if (is_eq(p, "template"))
+ return WRAP_FUNCTOR(template_command);
+ break;
+ }
break;
- case 'y':
- if (is_eq(p, "yellow"))
- return WRAP_FUNCTOR(fn_yellow);
+ default:
break;
}
- // Check if they are trying to access an option's setting or value.
- if (option_t<report_t> * handler = lookup_option(p))
- return MAKE_OPT_FUNCTOR(report_t, handler);
-
return NULL;
}
diff --git a/src/report.h b/src/report.h
index e00c6460..32648648 100644
--- a/src/report.h
+++ b/src/report.h
@@ -311,9 +311,11 @@ public:
option_t<report_t> * lookup_option(const char * p);
- virtual void define(const string& name, expr_t::ptr_op_t def);
+ virtual void define(const symbol_t::kind_t kind, const string& name,
+ expr_t::ptr_op_t def);
- virtual expr_t::ptr_op_t lookup(const string& name);
+ virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
+ const string& name);
/**
* Option handlers
diff --git a/src/scope.cc b/src/scope.cc
index 92d123ee..998eac64 100644
--- a/src/scope.cc
+++ b/src/scope.cc
@@ -35,31 +35,34 @@
namespace ledger {
-void symbol_scope_t::define(const string& name, expr_t::ptr_op_t def)
+void symbol_scope_t::define(const symbol_t::kind_t kind,
+ const string& name, expr_t::ptr_op_t def)
{
DEBUG("scope.symbols", "Defining '" << name << "' = " << def);
std::pair<symbol_map::iterator, bool> result
- = symbols.insert(symbol_map::value_type(name, def));
+ = symbols.insert(symbol_map::value_type(symbol_t(kind, name, def), def));
if (! result.second) {
- symbol_map::iterator i = symbols.find(name);
+ symbol_map::iterator i = symbols.find(symbol_t(kind, name));
assert(i != symbols.end());
symbols.erase(i);
- std::pair<symbol_map::iterator, bool> result2
- = symbols.insert(symbol_map::value_type(name, def));
- if (! result2.second)
- throw_(compile_error, _("Redefinition of '%1' in same scope") << name);
+ result = symbols.insert(symbol_map::value_type(symbol_t(kind, name, def),
+ def));
+ if (! result.second)
+ throw_(compile_error,
+ _("Redefinition of '%1' in the same scope") << name);
}
}
-expr_t::ptr_op_t symbol_scope_t::lookup(const string& name)
+expr_t::ptr_op_t symbol_scope_t::lookup(const symbol_t::kind_t kind,
+ const string& name)
{
- symbol_map::const_iterator i = symbols.find(name);
+ symbol_map::const_iterator i = symbols.find(symbol_t(kind, name));
if (i != symbols.end())
return (*i).second;
- return child_scope_t::lookup(name);
+ return child_scope_t::lookup(kind, name);
}
} // namespace ledger
diff --git a/src/scope.h b/src/scope.h
index 36eb54f1..7cf89c3e 100644
--- a/src/scope.h
+++ b/src/scope.h
@@ -55,6 +55,61 @@ namespace ledger {
*
* Long.
*/
+struct symbol_t
+{
+ enum kind_t {
+ UNKNOWN,
+ FUNCTION,
+ OPTION,
+ PRECOMMAND,
+ COMMAND,
+ DIRECTIVE
+ };
+
+ kind_t kind;
+ string name;
+ expr_t::ptr_op_t definition;
+
+ symbol_t() : kind(UNKNOWN), name(""), definition(NULL) {
+ TRACE_CTOR(symbol_t, "");
+ }
+ symbol_t(kind_t _kind, string _name, expr_t::ptr_op_t _definition = NULL)
+ : kind(_kind), name(_name), definition(_definition) {
+ TRACE_CTOR(symbol_t, "symbol_t::kind_t, string");
+ }
+ symbol_t(const symbol_t& sym)
+ : kind(sym.kind), name(sym.name),
+ definition(sym.definition) {
+ TRACE_CTOR(symbol_t, "copy");
+ }
+ ~symbol_t() throw() {
+ TRACE_DTOR(symbol_t);
+ }
+
+ bool operator<(const symbol_t& sym) const {
+ return kind < sym.kind || name < sym.name;
+ }
+
+#if defined(HAVE_BOOST_SERIALIZATION)
+private:
+ /** Serialization. */
+
+ friend class boost::serialization::access;
+
+ template<class Archive>
+ void serialize(Archive& ar, const unsigned int /* version */) {
+ ar & kind;
+ ar & name;
+ ar & definition;
+ }
+#endif // HAVE_BOOST_SERIALIZATION
+};
+
+/**
+ * @brief Brief
+ *
+ * Long.
+ */
class scope_t
{
public:
@@ -65,8 +120,10 @@ public:
TRACE_DTOR(scope_t);
}
- virtual void define(const string&, expr_t::ptr_op_t) {}
- virtual expr_t::ptr_op_t lookup(const string& name) = 0;
+ virtual void define(const symbol_t::kind_t, const string&,
+ expr_t::ptr_op_t) {}
+ virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
+ const string& name) = 0;
#if defined(HAVE_BOOST_SERIALIZATION)
private:
@@ -100,14 +157,16 @@ public:
TRACE_DTOR(child_scope_t);
}
- virtual void define(const string& name, expr_t::ptr_op_t def) {
+ virtual void define(const symbol_t::kind_t kind,
+ const string& name, expr_t::ptr_op_t def) {
if (parent)
- parent->define(name, def);
+ parent->define(kind, name, def);
}
- virtual expr_t::ptr_op_t lookup(const string& name) {
+ virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
+ const string& name) {
if (parent)
- return parent->lookup(name);
+ return parent->lookup(kind, name);
return NULL;
}
@@ -132,7 +191,7 @@ private:
*/
class symbol_scope_t : public child_scope_t
{
- typedef std::map<const string, expr_t::ptr_op_t> symbol_map;
+ typedef std::map<symbol_t, expr_t::ptr_op_t> symbol_map;
symbol_map symbols;
@@ -147,9 +206,11 @@ public:
TRACE_DTOR(symbol_scope_t);
}
- virtual void define(const string& name, expr_t::ptr_op_t def);
+ virtual void define(const symbol_t::kind_t kind, const string& name,
+ expr_t::ptr_op_t def);
- virtual expr_t::ptr_op_t lookup(const string& name);
+ virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
+ const string& name);
#if defined(HAVE_BOOST_SERIALIZATION)
private:
@@ -259,15 +320,17 @@ public:
TRACE_DTOR(bind_scope_t);
}
- virtual void define(const string& name, expr_t::ptr_op_t def) {
- parent->define(name, def);
- grandchild.define(name, def);
+ virtual void define(const symbol_t::kind_t kind, const string& name,
+ expr_t::ptr_op_t def) {
+ parent->define(kind, name, def);
+ grandchild.define(kind, name, def);
}
- virtual expr_t::ptr_op_t lookup(const string& name) {
- if (expr_t::ptr_op_t def = grandchild.lookup(name))
+ virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
+ const string& name) {
+ if (expr_t::ptr_op_t def = grandchild.lookup(kind, name))
return def;
- return child_scope_t::lookup(name);
+ return child_scope_t::lookup(kind, name);
}
#if defined(HAVE_BOOST_SERIALIZATION)
diff --git a/src/session.cc b/src/session.cc
index 2b8d8d58..67f19ca9 100644
--- a/src/session.cc
+++ b/src/session.cc
@@ -284,23 +284,26 @@ option_t<session_t> * session_t::lookup_option(const char * p)
return NULL;
}
-expr_t::ptr_op_t session_t::lookup(const string& name)
+expr_t::ptr_op_t session_t::lookup(const symbol_t::kind_t kind,
+ const string& name)
{
- const char * p = name.c_str();
- switch (*p) {
- case 'o':
- if (WANT_OPT()) { p += OPT_PREFIX_LEN;
- if (option_t<session_t> * handler = lookup_option(p))
- return MAKE_OPT_HANDLER(session_t, handler);
- }
+ switch (kind) {
+ case symbol_t::FUNCTION:
+ // Check if they are trying to access an option's setting or value.
+ if (option_t<session_t> * handler = lookup_option(name.c_str()))
+ return MAKE_OPT_FUNCTOR(session_t, handler);
break;
- }
- // Check if they are trying to access an option's setting or value.
- if (option_t<session_t> * handler = lookup_option(p))
- return MAKE_OPT_FUNCTOR(session_t, handler);
+ case symbol_t::OPTION:
+ if (option_t<session_t> * handler = lookup_option(name.c_str()))
+ return MAKE_OPT_HANDLER(session_t, handler);
+ break;
+
+ default:
+ break;
+ }
- return symbol_scope_t::lookup(name);
+ return symbol_scope_t::lookup(kind, name);
}
} // namespace ledger
diff --git a/src/session.h b/src/session.h
index 58e33f6b..972a97ba 100644
--- a/src/session.h
+++ b/src/session.h
@@ -116,7 +116,8 @@ public:
option_t<session_t> * lookup_option(const char * p);
- virtual expr_t::ptr_op_t lookup(const string& name);
+ virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
+ const string& name);
/**
* Option handlers
diff --git a/src/textual.cc b/src/textual.cc
index c2976ee1..6e2c919f 100644
--- a/src/textual.cc
+++ b/src/textual.cc
@@ -140,7 +140,8 @@ namespace {
std::streamsize len,
account_t * account);
- virtual expr_t::ptr_op_t lookup(const string& name);
+ virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
+ const string& name);
};
void parse_amount_expr(scope_t& scope,
@@ -749,11 +750,7 @@ void instance_t::general_directive(char * line)
break;
}
- scoped_array<char> directive(new char[std::strlen(p) + DIR_PREFIX_LEN + 1]);
- std::strcpy(directive.get(), DIR_PREFIX);
- std::strcpy(directive.get() + DIR_PREFIX_LEN, p);
-
- if (expr_t::ptr_op_t op = lookup(directive.get())) {
+ if (expr_t::ptr_op_t op = lookup(symbol_t::DIRECTIVE, p)) {
call_scope_t args(*this);
args.push_back(string_value(p));
op->as_function()(args);
@@ -1233,9 +1230,10 @@ xact_t * instance_t::parse_xact(char * line,
}
}
-expr_t::ptr_op_t instance_t::lookup(const string& name)
+expr_t::ptr_op_t instance_t::lookup(const symbol_t::kind_t kind,
+ const string& name)
{
- return scope.lookup(name);
+ return scope.lookup(kind, name);
}
std::size_t journal_t::parse(std::istream& in,
diff --git a/src/xact.cc b/src/xact.cc
index 3291c5be..473837b6 100644
--- a/src/xact.cc
+++ b/src/xact.cc
@@ -422,8 +422,12 @@ namespace {
}
}
-expr_t::ptr_op_t xact_t::lookup(const string& name)
+expr_t::ptr_op_t xact_t::lookup(const symbol_t::kind_t kind,
+ const string& name)
{
+ if (kind != symbol_t::FUNCTION)
+ return item_t::lookup(kind, name);
+
switch (name[0]) {
case 'c':
if (name == "code")
@@ -448,7 +452,7 @@ expr_t::ptr_op_t xact_t::lookup(const string& name)
break;
}
- return item_t::lookup(name);
+ return item_t::lookup(kind, name);
}
bool xact_t::valid() const
diff --git a/src/xact.h b/src/xact.h
index 781b073e..07fc68f5 100644
--- a/src/xact.h
+++ b/src/xact.h
@@ -123,7 +123,8 @@ public:
string idstring() const;
string id() const;
- virtual expr_t::ptr_op_t lookup(const string& name);
+ virtual expr_t::ptr_op_t lookup(const symbol_t::kind_t kind,
+ const string& name);
virtual bool valid() const;