From bc9ff7095fbfa1812e4f47dbf8531dec76cd0d00 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Mon, 20 Feb 2012 17:20:16 -0600 Subject: [PATCH 1/2] Introduced a new SCOPE expression terminal --- src/compare.cc | 2 +- src/format.cc | 2 +- src/op.cc | 93 +++++++++++++++++++++++++++++++------------------- src/op.h | 51 +++++++++++++++++++++------ src/parser.cc | 33 +++++++++--------- src/value.cc | 2 +- 6 files changed, 118 insertions(+), 65 deletions(-) diff --git a/src/compare.cc b/src/compare.cc index 12114c7d..cdc96a86 100644 --- a/src/compare.cc +++ b/src/compare.cc @@ -44,7 +44,7 @@ void push_sort_value(std::list& sort_values, if (node->kind == expr_t::op_t::O_CONS) { while (node && node->kind == expr_t::op_t::O_CONS) { push_sort_value(sort_values, node->left(), scope); - node = node->right(); + node = node->has_right() ? node->right() : NULL; } } else { bool inverted = false; diff --git a/src/format.cc b/src/format.cc index 93e7ea08..65c06488 100644 --- a/src/format.cc +++ b/src/format.cc @@ -225,7 +225,7 @@ format_t::element_t * format_t::parse_elements(const string& fmt, expr_t::ptr_op_t colorize_op; if (op->kind == expr_t::op_t::O_CONS) { amount_op = op->left(); - colorize_op = op->right(); + colorize_op = op->has_right() ? op->right() : NULL; } else { amount_op = op; } diff --git a/src/op.cc b/src/op.cc index 537f5371..d5a589c8 100644 --- a/src/op.cc +++ b/src/op.cc @@ -50,7 +50,7 @@ namespace { expr_t::ptr_op_t value_op; if (next->kind == expr_t::op_t::O_CONS) { value_op = next->left(); - next = next->right(); + next = next->has_right() ? next->right() : NULL; } else { value_op = next; next = NULL; @@ -78,10 +78,12 @@ namespace { expr_t::ptr_op_t expr_t::op_t::compile(scope_t& scope, const int depth) { + scope_t * scope_ptr = &scope; + if (is_ident()) { DEBUG("expr.compile", "lookup: " << as_ident()); - if (ptr_op_t def = scope.lookup(symbol_t::FUNCTION, as_ident())) { + if (ptr_op_t def = scope_ptr->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. @@ -91,21 +93,26 @@ expr_t::ptr_op_t expr_t::op_t::compile(scope_t& scope, const int depth) def->dump(*_log_stream, 0); } #endif // defined(DEBUG_ON) - return copy(def); + return copy(def); } else if (left()) { return copy(); } return this; } - - if (kind < TERMINALS) + else if (is_scope()) { + shared_ptr subscope(new symbol_scope_t(scope)); + DEBUG("expr.compile", "creating scope"); + set_scope(subscope); + scope_ptr = subscope.get(); + } + else if (kind < TERMINALS) { return this; - - if (kind == O_DEFINE) { + } + else if (kind == O_DEFINE) { switch (left()->kind) { case IDENT: - scope.define(symbol_t::FUNCTION, left()->as_ident(), right()); + scope_ptr->define(symbol_t::FUNCTION, left()->as_ident(), right()); break; case O_CALL: if (left()->left()->is_ident()) { @@ -113,7 +120,8 @@ expr_t::ptr_op_t expr_t::op_t::compile(scope_t& scope, const int depth) node->set_left(left()->right()); node->set_right(right()); - scope.define(symbol_t::FUNCTION, left()->left()->as_ident(), node); + scope_ptr->define(symbol_t::FUNCTION, left()->left()->as_ident(), + node); } else { throw_(compile_error, _("Invalid function definition")); } @@ -121,13 +129,13 @@ expr_t::ptr_op_t expr_t::op_t::compile(scope_t& scope, const int depth) default: throw_(compile_error, _("Invalid function definition")); } - return wrap_value(value_t()); + return wrap_value(NULL_VALUE); } - ptr_op_t lhs(left()->compile(scope, depth)); + ptr_op_t lhs(left()->compile(*scope_ptr, depth)); ptr_op_t rhs(kind > UNARY_OPERATORS && has_right() ? (kind == O_LOOKUP ? right() : - right()->compile(scope, depth)) : NULL); + right()->compile(*scope_ptr, depth)) : NULL); if (lhs == left() && (! rhs || rhs == right())) return this; @@ -136,22 +144,19 @@ expr_t::ptr_op_t expr_t::op_t::compile(scope_t& scope, const int depth) // Reduce constants immediately if possible if ((! lhs || lhs->is_value()) && (! rhs || rhs->is_value())) - return wrap_value(intermediate->calc(scope, NULL, depth)); + return wrap_value(intermediate->calc(*scope_ptr, NULL, depth)); return intermediate; } value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus, const int depth) { -#if defined(DEBUG_ON) - bool skip_debug = false; -#endif try { value_t result; #if defined(DEBUG_ON) - if (! skip_debug && SHOW_DEBUG("expr.calc")) { + if (SHOW_DEBUG("expr.calc")) { for (int i = 0; i < depth; i++) ledger::_log_buffer << '.'; ledger::_log_buffer << op_context(this) << " => ..."; @@ -196,12 +201,18 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus, const int depth) call_scope_t call_args(scope, locus, depth); result = as_function()(call_args); check_type_context(scope, result); -#if defined(DEBUG_ON) - skip_debug = true; -#endif break; } + case SCOPE: + if (is_scope_unset()) { + symbol_scope_t subscope(scope); + result = left()->calc(subscope, locus, depth + 1); + } else { + result = left()->calc(*as_scope(), locus, depth + 1); + } + break; + case O_LAMBDA: { call_scope_t& call_args(downcast(scope)); std::size_t args_count(call_args.size()); @@ -267,7 +278,7 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus, const int depth) throw_(calc_error, _("Calling unknown function '%1'") << name); #if defined(DEBUG_ON) - if (! skip_debug && SHOW_DEBUG("expr.calc")) { + if (SHOW_DEBUG("expr.calc")) { for (int i = 0; i < depth; i++) ledger::_log_buffer << '.'; ledger::_log_buffer << " args: "; @@ -382,7 +393,7 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus, const int depth) ptr_op_t value_op; if (next->kind == O_CONS) { value_op = next->left(); - next = next->right(); + next = next->has_right() ? next->right() : NULL; } else { value_op = next; next = NULL; @@ -395,14 +406,13 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus, const int depth) break; case O_SEQ: { - symbol_scope_t seq_scope(scope); - - // An O_SEQ is very similar to an O_CONS except that only the last result - // value in the series is kept. O_CONS builds up a list. + // An O_SEQ is very similar to an O_CONS except that only the last + // result value in the series is kept. O_CONS builds up a list. // - // Another feature of O_SEQ is that it pushes a new symbol scope onto the - // stack. - result = left()->calc(seq_scope, locus, depth + 1); + // Another feature of O_SEQ is that it pushes a new symbol scope + // onto the stack. We evaluate the left side here to catch any + // side-effects, such as definitions in the case of 'x = 1; x'. + result = left()->calc(scope, locus, depth + 1); if (has_right()) { ptr_op_t next = right(); @@ -415,7 +425,7 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus, const int depth) value_op = next; next = NULL; } - result = value_op->calc(seq_scope, locus, depth + 1); + result = value_op->calc(scope, locus, depth + 1); } } break; @@ -426,7 +436,7 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus, const int depth) } #if defined(DEBUG_ON) - if (! skip_debug && SHOW_DEBUG("expr.calc")) { + if (SHOW_DEBUG("expr.calc")) { for (int i = 0; i < depth; i++) ledger::_log_buffer << '.'; ledger::_log_buffer << op_context(this) << " => "; @@ -476,9 +486,8 @@ namespace { if (op->has_right()) { out << "; "; - - if (op->right()->kind == expr_t::op_t::O_CONS) - found = print_cons(out, op->right(), context); + if (op->right()->kind == expr_t::op_t::O_SEQ) + found = print_seq(out, op->right(), context); else if (op->right()->print(out, context)) found = true; } @@ -515,6 +524,11 @@ bool expr_t::op_t::print(std::ostream& out, const context_t& context) const out << ""; break; + case SCOPE: + if (left() && left()->print(out, context)) + found = true; + break; + case O_NOT: out << "! "; if (left() && left()->print(out, context)) @@ -625,7 +639,6 @@ bool expr_t::op_t::print(std::ostream& out, const context_t& context) const case O_CONS: found = print_cons(out, this, context); break; - case O_SEQ: found = print_seq(out, this, context); break; @@ -726,6 +739,14 @@ void expr_t::op_t::dump(std::ostream& out, const int depth) const out << "FUNCTION"; break; + case SCOPE: + out << "SCOPE: "; + if (is_scope_unset()) + out << "null"; + else + out << as_scope().get(); + break; + case O_DEFINE: out << "O_DEFINE"; break; case O_LOOKUP: out << "O_LOOKUP"; break; case O_LAMBDA: out << "O_LAMBDA"; break; @@ -765,7 +786,7 @@ void expr_t::op_t::dump(std::ostream& out, const int depth) const // An identifier is a special non-terminal, in that its left() can // hold the compiled definition of the identifier. - if (kind > TERMINALS || is_ident()) { + if (kind > TERMINALS || is_ident() || is_scope()) { if (left()) { left()->dump(out, depth + 1); if (kind > UNARY_OPERATORS && has_right()) diff --git a/src/op.h b/src/op.h index 6f7d7904..c4d353dc 100644 --- a/src/op.h +++ b/src/op.h @@ -58,10 +58,12 @@ private: mutable short refc; ptr_op_t left_; - variant // used by terminal SCOPE > data; public: @@ -73,6 +75,7 @@ public: CONSTANTS, FUNCTION, + SCOPE, TERMINALS, @@ -173,7 +176,7 @@ public: return kind == FUNCTION; } expr_t::func_t& as_function_lval() { - assert(kind == FUNCTION); + assert(is_function()); return boost::get(data); } const expr_t::func_t& as_function() const { @@ -183,21 +186,41 @@ public: data = val; } + bool is_scope() const { + return kind == SCOPE; + } + bool is_scope_unset() const { + return data.which() == 0; + } + shared_ptr as_scope_lval() { + assert(is_scope()); + return boost::get >(data); + } + const shared_ptr as_scope() const { + return const_cast(this)->as_scope_lval(); + } + void set_scope(shared_ptr val) { + data = val; + } + + // These three functions must use 'kind == IDENT' rather than + // 'is_ident()', because they are called before the `data' member gets + // set, which is_ident() tests. ptr_op_t& left() { - assert(kind > TERMINALS || kind == IDENT); + assert(kind > TERMINALS || kind == IDENT || is_scope()); return left_; } const ptr_op_t& left() const { - assert(kind > TERMINALS || kind == IDENT); + assert(kind > TERMINALS || kind == IDENT || is_scope()); return left_; } void set_left(const ptr_op_t& expr) { - assert(kind > TERMINALS || kind == IDENT); + assert(kind > TERMINALS || kind == IDENT || is_scope()); left_ = expr; } ptr_op_t& as_op_lval() { - assert(kind > TERMINALS || kind == IDENT); + assert(kind > TERMINALS || is_ident()); return boost::get(data); } const ptr_op_t& as_op() const { @@ -219,7 +242,7 @@ public: bool has_right() const { if (kind < TERMINALS) return false; - return as_op(); + return data.which() != 0 && as_op(); } private: @@ -284,6 +307,7 @@ public: static ptr_op_t wrap_value(const value_t& val); static ptr_op_t wrap_functor(expr_t::func_t fobj); + static ptr_op_t wrap_scope(shared_ptr sobj); #if defined(HAVE_BOOST_SERIALIZATION) private: @@ -295,13 +319,13 @@ private: void serialize(Archive& ar, const unsigned int /* version */) { ar & refc; ar & kind; - if (Archive::is_loading::value || ! left_ || left_->kind != FUNCTION) { + if (Archive::is_loading::value || ! left_ || ! left_->is_function()) { ar & left_; } else { ptr_op_t temp_op; ar & temp_op; } - if (Archive::is_loading::value || kind == VALUE || kind == IDENT || + if (Archive::is_loading::value || is_value() || is_ident() || (kind > UNARY_OPERATORS && (! has_right() || ! right()->is_function()))) { ar & data; @@ -335,6 +359,13 @@ expr_t::op_t::wrap_functor(expr_t::func_t fobj) { return temp; } +inline expr_t::ptr_op_t +expr_t::op_t::wrap_scope(shared_ptr sobj) { + ptr_op_t temp(new op_t(op_t::SCOPE)); + temp->set_scope(sobj); + return temp; +} + #define MAKE_FUNCTOR(x) expr_t::op_t::wrap_functor(bind(&x, this, _1)) #define WRAP_FUNCTOR(x) expr_t::op_t::wrap_functor(x) diff --git a/src/parser.cc b/src/parser.cc index a18fa552..ad621106 100644 --- a/src/parser.cc +++ b/src/parser.cc @@ -434,7 +434,6 @@ expr_t::parser_t::parse_comma_expr(std::istream& in, ptr_op_t prev(node); node = new op_t(op_t::O_CONS); node->set_left(prev); - next = node; } @@ -493,7 +492,9 @@ expr_t::parser_t::parse_assign_expr(std::istream& in, ptr_op_t prev(node); node = new op_t(op_t::O_DEFINE); node->set_left(prev); - node->set_right(parse_lambda_expr(in, tflags)); + ptr_op_t scope(new op_t(op_t::SCOPE)); + scope->set_left(parse_lambda_expr(in, tflags)); + node->set_right(scope); } else { push_token(tok); } @@ -509,24 +510,24 @@ expr_t::parser_t::parse_value_expr(std::istream& in, ptr_op_t node(parse_assign_expr(in, tflags)); if (node && ! tflags.has_flags(PARSE_SINGLE)) { - ptr_op_t next; + ptr_op_t chain; while (true) { token_t& tok = next_token(in, tflags.plus_flags(PARSE_OP_CONTEXT)); - if (tok.kind == token_t::SEMI) { - if (! next) { - ptr_op_t prev(node); - node = new op_t(op_t::O_SEQ); - node->set_left(prev); - - next = node; + ptr_op_t seq(new op_t(op_t::O_SEQ)); + if (! chain) { + seq->set_left(node); + ptr_op_t scope(new op_t(op_t::SCOPE)); + scope->set_left(seq); + node = scope; + } else { + seq->set_left(chain->right()); + ptr_op_t scope(new op_t(op_t::SCOPE)); + scope->set_left(seq); + chain->set_right(scope); } - - ptr_op_t chain(new op_t(op_t::O_SEQ)); - chain->set_left(parse_assign_expr(in, tflags)); - - next->set_right(chain); - next = chain; + seq->set_right(parse_assign_expr(in, tflags)); + chain = seq; } else { push_token(tok); break; diff --git a/src/value.cc b/src/value.cc index c62e6f32..f54c06a5 100644 --- a/src/value.cc +++ b/src/value.cc @@ -1727,7 +1727,7 @@ void value_t::print(std::ostream& _out, switch (type()) { case VOID: - out << ""; + out << "(null)"; break; case BOOLEAN: From 1837e323916c7479623bb61e479407b85edee562 Mon Sep 17 00:00:00 2001 From: John Wiegley Date: Tue, 21 Feb 2012 01:45:26 -0600 Subject: [PATCH 2/2] The new SCOPE mechanism is working --- src/op.cc | 151 +++++++++++++++++++++------------------------------ src/scope.cc | 8 ++- src/scope.h | 2 + 3 files changed, 71 insertions(+), 90 deletions(-) diff --git a/src/op.cc b/src/op.cc index d5a589c8..bf6fa543 100644 --- a/src/op.cc +++ b/src/op.cc @@ -81,7 +81,7 @@ expr_t::ptr_op_t expr_t::op_t::compile(scope_t& scope, const int depth) scope_t * scope_ptr = &scope; if (is_ident()) { - DEBUG("expr.compile", "lookup: " << as_ident()); + DEBUG("expr.compile", "Lookup: " << as_ident()); if (ptr_op_t def = scope_ptr->lookup(symbol_t::FUNCTION, as_ident())) { // Identifier references are first looked up at the point of @@ -93,7 +93,7 @@ expr_t::ptr_op_t expr_t::op_t::compile(scope_t& scope, const int depth) def->dump(*_log_stream, 0); } #endif // defined(DEBUG_ON) - return copy(def); + return copy(def); } else if (left()) { return copy(); @@ -102,7 +102,6 @@ expr_t::ptr_op_t expr_t::op_t::compile(scope_t& scope, const int depth) } else if (is_scope()) { shared_ptr subscope(new symbol_scope_t(scope)); - DEBUG("expr.compile", "creating scope"); set_scope(subscope); scope_ptr = subscope.get(); } @@ -114,22 +113,21 @@ expr_t::ptr_op_t expr_t::op_t::compile(scope_t& scope, const int depth) case IDENT: scope_ptr->define(symbol_t::FUNCTION, left()->as_ident(), right()); break; + case O_CALL: if (left()->left()->is_ident()) { ptr_op_t node(new op_t(op_t::O_LAMBDA)); node->set_left(left()->right()); node->set_right(right()); - scope_ptr->define(symbol_t::FUNCTION, left()->left()->as_ident(), node); - } else { - throw_(compile_error, _("Invalid function definition")); + break; } - break; + // fall through... + default: throw_(compile_error, _("Invalid function definition")); } - return wrap_value(NULL_VALUE); } ptr_op_t lhs(left()->compile(*scope_ptr, depth)); @@ -144,7 +142,7 @@ expr_t::ptr_op_t expr_t::op_t::compile(scope_t& scope, const int depth) // Reduce constants immediately if possible if ((! lhs || lhs->is_value()) && (! rhs || rhs->is_value())) - return wrap_value(intermediate->calc(*scope_ptr, NULL, depth)); + return wrap_value(intermediate->calc(*scope_ptr, NULL, depth + 1)); return intermediate; } @@ -159,7 +157,7 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus, const int depth) if (SHOW_DEBUG("expr.calc")) { for (int i = 0; i < depth; i++) ledger::_log_buffer << '.'; - ledger::_log_buffer << op_context(this) << " => ..."; + ledger::_log_buffer << op_context(this) << " => ..."; DEBUG("expr.calc", ""); } #endif @@ -170,61 +168,96 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus, const int depth) break; case O_DEFINE: - //result = left()->calc(scope, locus, depth + 1); result = NULL_VALUE; break; case IDENT: { ptr_op_t definition = left(); + // If no definition was pre-compiled for this identifier, look it up + // in the current scope. if (! definition) { - // If no definition was pre-compiled for this identifier, look it - // up in the current scope. + DEBUG("scope.symbols", "Looking for IDENT '" << as_ident() << "'"); 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 = definition->compile(call_args, depth + 1) - ->calc(call_args, locus, depth + 1); + // directly + result = definition->calc(scope, locus, depth + 1); check_type_context(scope, result); break; } case FUNCTION: { - // Evaluating a FUNCTION is the same as calling it directly; this happens - // when certain functions-that-look-like-variables (such as "amount") are - // resolved. - call_scope_t call_args(scope, locus, depth); + // Evaluating a FUNCTION is the same as calling it directly; this + // happens when certain functions-that-look-like-variables (such as + // "amount") are resolved. + call_scope_t call_args(scope, locus, depth + 1); result = as_function()(call_args); check_type_context(scope, result); break; } case SCOPE: + assert(! is_scope_unset()); if (is_scope_unset()) { symbol_scope_t subscope(scope); result = left()->calc(subscope, locus, depth + 1); } else { - result = left()->calc(*as_scope(), locus, depth + 1); + bind_scope_t bound_scope(scope, *as_scope()); + result = left()->calc(bound_scope, locus, depth + 1); } break; + case O_LOOKUP: { + context_scope_t context_scope(scope, value_t::SCOPE); + bool scope_error = true; + if (value_t obj = left()->calc(context_scope, locus, depth + 1)) { + if (obj.is_scope() && obj.as_scope() != NULL) { + bind_scope_t bound_scope(scope, *obj.as_scope()); + result = right()->calc(bound_scope, locus, depth + 1); + scope_error = false; + } + } + if (scope_error) + throw_(calc_error, _("Left operand does not evaluate to an object")); + break; + } + + case O_CALL: { + ptr_op_t func = left(); + 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); + + call_scope_t call_args(scope, locus, depth + 1); + if (has_right()) + call_args.set_args(split_cons_expr(right())); + + if (func->is_function()) + result = func->as_function()(call_args); + else + result = func->calc(call_args, locus, depth + 1); + + check_type_context(scope, result); + break; + } + case O_LAMBDA: { call_scope_t& call_args(downcast(scope)); std::size_t args_count(call_args.size()); std::size_t args_index(0); symbol_scope_t call_scope(call_args); - ptr_op_t sym(left()); - - for (; sym; sym = sym->has_right() ? sym->right() : NULL) { - ptr_op_t varname = sym; - if (sym->kind == O_CONS) - varname = sym->left(); + for (ptr_op_t sym = left(); + sym; + sym = sym->has_right() ? sym->right() : NULL) { + ptr_op_t varname = sym->kind == O_CONS ? sym->left() : sym; if (! varname->is_ident()) { throw_(calc_error, _("Invalid function definition")); } @@ -248,59 +281,6 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus, const int depth) break; } - case O_LOOKUP: { - context_scope_t context_scope(scope, value_t::SCOPE); - bool scope_error = true; - if (value_t obj = left()->calc(context_scope, locus, depth + 1)) { - if (obj.is_scope() && obj.as_scope() != NULL) { - bind_scope_t bound_scope(scope, *obj.as_scope()); - result = right()->calc(bound_scope, locus, depth + 1); - scope_error = false; - } - } - if (scope_error) - throw_(calc_error, _("Left operand does not evaluate to an object")); - break; - } - - case O_CALL: { - call_scope_t call_args(scope, locus, depth); - if (has_right()) - call_args.set_args(split_cons_expr(right())); - - ptr_op_t func = left(); - 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); - -#if defined(DEBUG_ON) - if (SHOW_DEBUG("expr.calc")) { - for (int i = 0; i < depth; i++) - ledger::_log_buffer << '.'; - ledger::_log_buffer << " args: "; - if (call_args.args.is_sequence()) { - foreach (value_t& arg, call_args) - ledger::_log_buffer << arg << " "; - } else { - ledger::_log_buffer << call_args.args[0] << " "; - } - DEBUG("expr.calc", ""); - } -#endif - - if (func->is_function()) - result = func->as_function()(call_args); - else - result = func->calc(call_args, locus, depth + 1); - - check_type_context(scope, result); - break; - } - case O_MATCH: result = (right()->calc(scope, locus, depth + 1).as_mask() .match(left()->calc(scope, locus, depth + 1).to_string())); @@ -369,7 +349,6 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus, const int depth) case O_QUERY: assert(right()); assert(right()->kind == O_COLON); - if (value_t temp = left()->calc(scope, locus, depth + 1)) result = right()->left()->calc(scope, locus, depth + 1); else @@ -382,8 +361,6 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus, const int depth) case O_CONS: result = left()->calc(scope, locus, depth + 1); - DEBUG("op.cons", "car = " << result); - if (has_right()) { value_t temp; temp.push_back(result); @@ -399,7 +376,6 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus, const int depth) next = NULL; } temp.push_back(value_op->calc(scope, locus, depth + 1)); - DEBUG("op.cons", "temp now = " << temp); } result = temp; } @@ -413,7 +389,6 @@ value_t expr_t::op_t::calc(scope_t& scope, ptr_op_t * locus, const int depth) // onto the stack. We evaluate the left side here to catch any // side-effects, such as definitions in the case of 'x = 1; x'. result = left()->calc(scope, locus, depth + 1); - if (has_right()) { ptr_op_t next = right(); while (next) { @@ -786,7 +761,7 @@ void expr_t::op_t::dump(std::ostream& out, const int depth) const // An identifier is a special non-terminal, in that its left() can // hold the compiled definition of the identifier. - if (kind > TERMINALS || is_ident() || is_scope()) { + if (kind > TERMINALS || is_scope()) { if (left()) { left()->dump(out, depth + 1); if (kind > UNARY_OPERATORS && has_right()) diff --git a/src/scope.cc b/src/scope.cc index e18b5a0a..95347c8d 100644 --- a/src/scope.cc +++ b/src/scope.cc @@ -40,7 +40,8 @@ scope_t * scope_t::default_scope = NULL; 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); + DEBUG("scope.symbols", + "Defining '" << name << "' = " << def << " in " << this); if (! symbols) symbols = symbol_map(); @@ -64,9 +65,12 @@ expr_t::ptr_op_t symbol_scope_t::lookup(const symbol_t::kind_t kind, const string& name) { if (symbols) { + DEBUG("scope.symbols", "Looking for '" << name << "' in " << this); symbol_map::const_iterator i = symbols->find(symbol_t(kind, name)); - if (i != symbols->end()) + if (i != symbols->end()) { + DEBUG("scope.symbols", "Found '" << name << "' in " << this); return (*i).second; + } } return child_scope_t::lookup(kind, name); } diff --git a/src/scope.h b/src/scope.h index a7b3c5cb..fbc1a889 100644 --- a/src/scope.h +++ b/src/scope.h @@ -188,6 +188,8 @@ public: scope_t& _grandchild) : child_scope_t(_parent), grandchild(_grandchild) { TRACE_CTOR(bind_scope_t, "scope_t&, scope_t&"); + DEBUG("scope.symbols", + "Binding scope " << &_parent << " with " << &_grandchild); } virtual ~bind_scope_t() { TRACE_DTOR(bind_scope_t);