Use RAII for scope management

Possibly fixes a few bugs where scope pops where missed.
This commit is contained in:
Jason Turner
2011-03-27 10:03:37 -06:00
parent d6b8e32373
commit de5822873b
2 changed files with 34 additions and 53 deletions

View File

@@ -90,7 +90,6 @@ namespace chaiscript
virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &) virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &)
{ {
Boxed_Value bv;
throw std::runtime_error("Undispatched ast_node (internal error)"); throw std::runtime_error("Undispatched ast_node (internal error)");
} }
@@ -175,6 +174,26 @@ namespace chaiscript
struct Break_Loop { struct Break_Loop {
Break_Loop() { } Break_Loop() { }
}; };
/// Creates a new scope then pops it on destruction
struct Scope_Push_Pop
{
Scope_Push_Pop(chaiscript::detail::Dispatch_Engine &t_de)
: m_de(t_de)
{
m_de.new_scope();
}
~Scope_Push_Pop()
{
m_de.pop_scope();
}
private:
chaiscript::detail::Dispatch_Engine &m_de;
};
} }
} }

View File

@@ -18,25 +18,18 @@ namespace chaiscript
*/ */
template <typename Eval_System> template <typename Eval_System>
const Boxed_Value eval_function (Eval_System &t_ss, const AST_NodePtr &t_node, const std::vector<std::string> &t_param_names, const std::vector<Boxed_Value> &t_vals) { const Boxed_Value eval_function (Eval_System &t_ss, const AST_NodePtr &t_node, const std::vector<std::string> &t_param_names, const std::vector<Boxed_Value> &t_vals) {
t_ss.new_scope(); detail::Scope_Push_Pop spp(t_ss);
for (unsigned int i = 0; i < t_param_names.size(); ++i) { for (unsigned int i = 0; i < t_param_names.size(); ++i) {
t_ss.add_object(t_param_names[i], t_vals[i]); t_ss.add_object(t_param_names[i], t_vals[i]);
} }
try { try {
Boxed_Value retval(t_node->eval(t_ss)); return t_node->eval(t_ss);
t_ss.pop_scope();
return retval;
} catch (const detail::Return_Value &rv) { } catch (const detail::Return_Value &rv) {
t_ss.pop_scope();
return rv.retval; return rv.retval;
} catch (exception::eval_error &ee) { } catch (exception::eval_error &ee) {
ee.call_stack.push_back(t_node); ee.call_stack.push_back(t_node);
t_ss.pop_scope();
throw;
} catch (...) {
t_ss.pop_scope();
throw; throw;
} }
} }
@@ -89,7 +82,8 @@ namespace chaiscript
struct Int_AST_Node : public AST_Node { struct Int_AST_Node : public AST_Node {
public: public:
Int_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Int, const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : Int_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Int, const boost::shared_ptr<std::string> &t_fname=boost::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col), m_value(const_var(int(atoi(this->text.c_str())))) { } AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col),
m_value(const_var(int(atoi(this->text.c_str())))) { }
virtual ~Int_AST_Node() {} virtual ~Int_AST_Node() {}
virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &){ virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &){
return m_value; return m_value;
@@ -577,35 +571,28 @@ namespace chaiscript
AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Block_AST_Node() {} virtual ~Block_AST_Node() {}
virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_ss){ virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_ss){
size_t num_children = this->children.size(); const size_t num_children = this->children.size();
detail::Scope_Push_Pop spp(t_ss);
t_ss.new_scope();
for (size_t i = 0; i < num_children; ++i) { for (size_t i = 0; i < num_children; ++i) {
try { try {
const Boxed_Value &retval = this->children[i]->eval(t_ss); const Boxed_Value &retval = this->children[i]->eval(t_ss);
if (i + 1 == num_children) if (i + 1 == num_children)
{ {
t_ss.pop_scope();
return retval; return retval;
} }
} }
catch (const chaiscript::detail::Return_Value &) { catch (const chaiscript::detail::Return_Value &) {
t_ss.pop_scope();
throw; throw;
} }
catch (exception::eval_error &ee) { catch (exception::eval_error &ee) {
ee.call_stack.push_back(this->children[i]); ee.call_stack.push_back(this->children[i]);
t_ss.pop_scope();
throw;
}
catch (...) {
t_ss.pop_scope();
throw; throw;
} }
} }
t_ss.pop_scope();
return Boxed_Value(); return Boxed_Value();
} }
@@ -673,18 +660,16 @@ namespace chaiscript
virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_ss) { virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_ss) {
bool cond; bool cond;
t_ss.new_scope(); detail::Scope_Push_Pop spp(t_ss);
try { try {
cond = boxed_cast<bool>(this->children[0]->eval(t_ss)); cond = boxed_cast<bool>(this->children[0]->eval(t_ss));
} }
catch (const exception::bad_boxed_cast &) { catch (const exception::bad_boxed_cast &) {
t_ss.pop_scope();
throw exception::eval_error("While condition not boolean"); throw exception::eval_error("While condition not boolean");
} }
catch (exception::eval_error &ee) { catch (exception::eval_error &ee) {
ee.call_stack.push_back(this->children[0]); ee.call_stack.push_back(this->children[0]);
t_ss.pop_scope();
throw; throw;
} }
while (cond) { while (cond) {
@@ -701,12 +686,10 @@ namespace chaiscript
cond = boxed_cast<bool>(this->children[0]->eval(t_ss)); cond = boxed_cast<bool>(this->children[0]->eval(t_ss));
} }
catch (const exception::bad_boxed_cast &) { catch (const exception::bad_boxed_cast &) {
t_ss.pop_scope();
throw exception::eval_error("While condition not boolean"); throw exception::eval_error("While condition not boolean");
} }
catch (exception::eval_error &ee) { catch (exception::eval_error &ee) {
ee.call_stack.push_back(this->children[0]); ee.call_stack.push_back(this->children[0]);
t_ss.pop_scope();
throw; throw;
} }
} }
@@ -714,10 +697,9 @@ namespace chaiscript
cond = false; cond = false;
} }
} }
t_ss.pop_scope();
return Boxed_Value(); return Boxed_Value();
} }
;
}; };
struct If_AST_Node : public AST_Node { struct If_AST_Node : public AST_Node {
@@ -799,7 +781,7 @@ namespace chaiscript
virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_ss){ virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_ss){
bool cond; bool cond;
t_ss.new_scope(); detail::Scope_Push_Pop spp(t_ss);
try { try {
if (this->children.size() == 4) { if (this->children.size() == 4) {
@@ -825,13 +807,11 @@ namespace chaiscript
} }
catch (exception::eval_error &ee) { catch (exception::eval_error &ee) {
ee.call_stack.push_back(this->children[0]); ee.call_stack.push_back(this->children[0]);
t_ss.pop_scope();
throw; throw;
} }
} }
} }
catch (const exception::bad_boxed_cast &) { catch (const exception::bad_boxed_cast &) {
t_ss.pop_scope();
throw exception::eval_error("For condition not boolean"); throw exception::eval_error("For condition not boolean");
} }
while (cond) { while (cond) {
@@ -883,20 +863,17 @@ namespace chaiscript
} }
catch (exception::eval_error &ee) { catch (exception::eval_error &ee) {
ee.call_stack.push_back(this->children[0]); ee.call_stack.push_back(this->children[0]);
t_ss.pop_scope();
throw; throw;
} }
} }
} }
catch (const exception::bad_boxed_cast &) { catch (const exception::bad_boxed_cast &) {
t_ss.pop_scope();
throw exception::eval_error("For condition not boolean"); throw exception::eval_error("For condition not boolean");
} }
catch (detail::Break_Loop &) { catch (detail::Break_Loop &) {
cond = false; cond = false;
} }
} }
t_ss.pop_scope();
return Boxed_Value(); return Boxed_Value();
} }
@@ -1075,7 +1052,8 @@ namespace chaiscript
virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_ss){ virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_ss){
Boxed_Value retval; Boxed_Value retval;
t_ss.new_scope(); detail::Scope_Push_Pop spp(t_ss);
try { try {
retval = this->children[0]->eval(t_ss); retval = this->children[0]->eval(t_ss);
} }
@@ -1087,11 +1065,9 @@ namespace chaiscript
} }
catch (exception::eval_error &ee2) { catch (exception::eval_error &ee2) {
ee2.call_stack.push_back(this->children.back()->children[0]); ee2.call_stack.push_back(this->children.back()->children[0]);
t_ss.pop_scope();
throw; throw;
} }
} }
t_ss.pop_scope();
throw; throw;
} }
catch (const std::exception &e) { catch (const std::exception &e) {
@@ -1143,11 +1119,9 @@ namespace chaiscript
} }
catch (exception::eval_error &ee) { catch (exception::eval_error &ee) {
ee.call_stack.push_back(this->children.back()->children[0]); ee.call_stack.push_back(this->children.back()->children[0]);
t_ss.pop_scope();
throw; throw;
} }
} }
t_ss.pop_scope();
throw exception::eval_error("Guard condition not boolean"); throw exception::eval_error("Guard condition not boolean");
} }
if (guard) { if (guard) {
@@ -1169,17 +1143,14 @@ namespace chaiscript
} }
catch (exception::eval_error &ee) { catch (exception::eval_error &ee) {
ee.call_stack.push_back(this->children.back()->children[0]); ee.call_stack.push_back(this->children.back()->children[0]);
t_ss.pop_scope();
throw; throw;
} }
} }
t_ss.pop_scope();
throw exception::eval_error("Internal error: catch block size unrecognized"); throw exception::eval_error("Internal error: catch block size unrecognized");
} }
} }
} }
catch (Boxed_Value &bv) { catch (Boxed_Value &except) {
Boxed_Value except = bv;
for (size_t i = 1; i < this->children.size(); ++i) { for (size_t i = 1; i < this->children.size(); ++i) {
AST_NodePtr catch_block = this->children[i]; AST_NodePtr catch_block = this->children[i];
@@ -1223,12 +1194,10 @@ namespace chaiscript
} }
catch (exception::eval_error &ee) { catch (exception::eval_error &ee) {
ee.call_stack.push_back(this->children.back()->children[0]); ee.call_stack.push_back(this->children.back()->children[0]);
t_ss.pop_scope();
throw; throw;
} }
} }
t_ss.pop_scope();
throw exception::eval_error("Guard condition not boolean"); throw exception::eval_error("Guard condition not boolean");
} }
catch (exception::eval_error &ee) { catch (exception::eval_error &ee) {
@@ -1253,11 +1222,9 @@ namespace chaiscript
} }
catch (exception::eval_error &ee) { catch (exception::eval_error &ee) {
ee.call_stack.push_back(this->children.back()->children[0]); ee.call_stack.push_back(this->children.back()->children[0]);
t_ss.pop_scope();
throw; throw;
} }
} }
t_ss.pop_scope();
throw exception::eval_error("Internal error: catch block size unrecognized"); throw exception::eval_error("Internal error: catch block size unrecognized");
} }
} }
@@ -1269,11 +1236,9 @@ namespace chaiscript
} }
catch (exception::eval_error &ee) { catch (exception::eval_error &ee) {
ee.call_stack.push_back(this->children.back()->children[0]); ee.call_stack.push_back(this->children.back()->children[0]);
t_ss.pop_scope();
throw; throw;
} }
} }
t_ss.pop_scope();
throw; throw;
} }
@@ -1283,13 +1248,10 @@ namespace chaiscript
} }
catch (exception::eval_error &ee) { catch (exception::eval_error &ee) {
ee.call_stack.push_back(this->children.back()->children[0]); ee.call_stack.push_back(this->children.back()->children[0]);
t_ss.pop_scope();
throw; throw;
} }
} }
t_ss.pop_scope();
return retval; return retval;
} }