From 024fb4f3e0f659fca5aa3770d5d70ac5827797f7 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Thu, 24 Jun 2010 20:22:11 -0400 Subject: Fixed how valexpr function defs and calls work --- src/op.cc | 47 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 32 insertions(+), 15 deletions(-) (limited to 'src/op.cc') diff --git a/src/op.cc b/src/op.cc index 95ad5abd..e9df7e63 100644 --- a/src/op.cc +++ b/src/op.cc @@ -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; } @@ -244,6 +259,8 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus, const int depth) const string& name(func->as_ident()); func = func->left(); + if (! func) + func = scope.lookup(symbol_t::FUNCTION, name); if (! func) throw_(calc_error, _("Calling unknown function '%1'") << name); -- cgit v1.2.3