diff options
author | John Wiegley <johnw@newartisans.com> | 2010-06-24 20:22:11 -0400 |
---|---|---|
committer | John Wiegley <johnw@newartisans.com> | 2010-06-24 20:22:11 -0400 |
commit | 024fb4f3e0f659fca5aa3770d5d70ac5827797f7 (patch) | |
tree | 27106ddac062192223520f9b4e03d9a493e4ecbb /src/op.cc | |
parent | 2f50e30b89a06e2f3c439f4a8440e4d35b4ebb27 (diff) | |
download | fork-ledger-024fb4f3e0f659fca5aa3770d5d70ac5827797f7.tar.gz fork-ledger-024fb4f3e0f659fca5aa3770d5d70ac5827797f7.tar.bz2 fork-ledger-024fb4f3e0f659fca5aa3770d5d70ac5827797f7.zip |
Fixed how valexpr function defs and calls work
Diffstat (limited to 'src/op.cc')
-rw-r--r-- | src/op.cc | 47 |
1 files changed, 32 insertions, 15 deletions
@@ -151,15 +151,21 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus, const int depth) break; case IDENT: { - if (! left()) + ptr_op_t definition = left(); + if (! definition) { + // If no definition was pre-compiled for this identifier, look it + // up in the current scope. + definition = scope.lookup(symbol_t::FUNCTION, as_ident()); + } + if (! definition) throw_(calc_error, _("Unknown identifier '%1'") << as_ident()); // Evaluating an identifier is the same as calling its definition // directly, so we create an empty call_scope_t to reflect the scope for // this implicit call. call_scope_t call_args(scope, locus, depth); - result = left()->compile(call_args, depth + 1) - ->calc(call_args, locus, depth + 1); + result = definition->compile(call_args, depth + 1) + ->calc(call_args, locus, depth + 1); check_type_context(scope, result); break; } @@ -184,28 +190,37 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus, const int depth) assert(left()->kind == O_CALL); - for (ptr_op_t sym = left()->right(); - sym; - sym = sym->has_right() ? sym->right() : NULL) { + ptr_op_t sym = left()->right(); + if (sym->kind == O_SEQ) + sym = sym->left(); + + symbol_scope_t call_scope(call_args); + + for (; sym; sym = sym->has_right() ? sym->right() : NULL) { ptr_op_t varname = sym; if (sym->kind == O_CONS) varname = sym->left(); - if (! varname->is_ident()) + if (! varname->is_ident()) { throw_(calc_error, _("Invalid function definition")); - else if (args_index == args_count) - scope.define(symbol_t::FUNCTION, varname->as_ident(), - wrap_value(false)); - else - scope.define(symbol_t::FUNCTION, varname->as_ident(), - wrap_value(call_args[args_index++])); + } + else if (args_index == args_count) { + call_scope.define(symbol_t::FUNCTION, varname->as_ident(), + wrap_value(NULL_VALUE)); + } + else { + DEBUG("expr.compile", + "Defining function parameter " << varname->as_ident()); + call_scope.define(symbol_t::FUNCTION, varname->as_ident(), + wrap_value(call_args[args_index++])); + } } if (args_index < args_count) throw_(calc_error, - _("Too many arguments in function call (saw %1)") << args_count); + _("Too few arguments in function call (saw %1)") << args_count); - result = right()->calc(scope, locus, depth + 1); + result = right()->calc(call_scope, locus, depth + 1); break; } @@ -245,6 +260,8 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus, const int depth) func = func->left(); if (! func) + func = scope.lookup(symbol_t::FUNCTION, name); + if (! func) throw_(calc_error, _("Calling unknown function '%1'") << name); if (func->is_function()) |