From c7689f18ec8043caef89f93374145a8e2c9c2ad5 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 20 Jun 2015 10:28:27 -0600 Subject: [PATCH] Save local variable location after first pass --- .../chaiscript/dispatchkit/dispatchkit.hpp | 36 +++++++++++++++---- .../chaiscript/language/chaiscript_eval.hpp | 6 ++-- 2 files changed, 33 insertions(+), 9 deletions(-) diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index 676b5f1..c451515 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -569,19 +569,41 @@ namespace chaiscript /// Searches the current stack for an object of the given name /// includes a special overload for the _ place holder object to /// ensure that it is always in scope. - Boxed_Value get_object(const std::string &name) const + Boxed_Value get_object(const std::string &name, uint32_t &t_loc) const { - auto &stack = get_stack_data(); + enum class Loc : uint32_t { + located = 0x80000000, + is_local = 0x40000000, + stack_mask = 0x0FFF0000, + loc_mask = 0x0000FFFF + }; - // Is it in the stack? - for (auto stack_elem = stack.rbegin(); stack_elem != stack.rend(); ++stack_elem) + unsigned int loc = t_loc; + + if (loc == 0) { - for (auto &s : (*stack_elem) ) + auto &stack = get_stack_data(); + + // Is it in the stack? + for (auto stack_elem = stack.rbegin(); stack_elem != stack.rend(); ++stack_elem) { - if (s.first == name) { - return s.second; + for (auto s = stack_elem->begin(); s != stack_elem->end(); ++s ) + { + if (s->first == name) { + t_loc = static_cast(std::distance(stack.rbegin(), stack_elem) << 16) + | static_cast(std::distance(stack_elem->begin(), s)) + | static_cast(Loc::located) + | static_cast(Loc::is_local); + return s->second; + } } } + + t_loc = static_cast(Loc::located); + } else if (loc & static_cast(Loc::is_local)) { + auto &stack = get_stack_data(); + + return stack[stack.size() - 1 - ((loc & static_cast(Loc::stack_mask)) >> 16)][loc & static_cast(Loc::loc_mask)].second; } // Is the value we are looking for a global? diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 2b8b601..53deb6a 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -147,7 +147,7 @@ namespace chaiscript public: Id_AST_Node(const std::string &t_ast_node_text, Parse_Location t_loc) : AST_Node(t_ast_node_text, AST_Node_Type::Id, std::move(t_loc)), - m_value(get_value(t_ast_node_text)) + m_value(get_value(t_ast_node_text)), m_loc(0) { } virtual ~Id_AST_Node() {} @@ -157,7 +157,7 @@ namespace chaiscript return m_value; } else { try { - return t_ss.get_object(this->text); + return t_ss.get_object(this->text, m_loc); } catch (std::exception &) { throw exception::eval_error("Can not find object: " + this->text); @@ -184,6 +184,8 @@ namespace chaiscript } Boxed_Value m_value; + + mutable uint32_t m_loc; }; struct Char_AST_Node : public AST_Node {