Enhance eval error stack reporting

Use OOP to avoid code duplication for eval error tracking. This results
in much more robust stack error reporting and 400 LOC less.
This commit is contained in:
Jason Turner
2011-03-27 21:03:24 -06:00
parent de5822873b
commit 79e8af4f6e
6 changed files with 260 additions and 504 deletions

View File

@@ -8,6 +8,7 @@
#define CHAISCRIPT_COMMON_HPP_ #define CHAISCRIPT_COMMON_HPP_
#include <chaiscript/dispatchkit/dispatchkit.hpp> #include <chaiscript/dispatchkit/dispatchkit.hpp>
#include <boost/enable_shared_from_this.hpp>
namespace chaiscript namespace chaiscript
{ {
@@ -57,65 +58,6 @@ namespace chaiscript
typedef boost::shared_ptr<struct AST_Node> AST_NodePtr; typedef boost::shared_ptr<struct AST_Node> AST_NodePtr;
/**
* The struct that doubles as both a parser ast_node and an AST node
*/
struct AST_Node {
public:
const std::string text;
const int identifier;
boost::shared_ptr<const std::string> filename;
File_Position start, end;
std::vector<AST_NodePtr> children;
AST_NodePtr annotation;
/**
* Prints the contents of an AST node, including its children, recursively
*/
std::string to_string(std::string t_prepend = "") {
std::ostringstream oss;
oss << t_prepend << "(" << ast_node_type_to_string(this->identifier) << ") "
<< this->text << " : " << this->start.line << ", " << this->start.column << std::endl;
for (unsigned int j = 0; j < this->children.size(); ++j) {
oss << this->children[j]->to_string(t_prepend + " ");
}
return oss.str();
}
std::string internal_to_string() {
return to_string();
}
virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &)
{
throw std::runtime_error("Undispatched ast_node (internal error)");
}
void replace_child(const AST_NodePtr &t_child, const AST_NodePtr &t_new_child)
{
std::replace(children.begin(), children.end(), t_child, t_new_child);
}
protected:
AST_Node(const std::string &t_ast_node_text, int t_id, const boost::shared_ptr<std::string> &t_fname,
int t_start_line, int t_start_col, int t_end_line, int t_end_col) :
text(t_ast_node_text), identifier(t_id), filename(t_fname),
start(t_start_line, t_start_col), end(t_end_line, t_end_col)
{
}
AST_Node(const std::string &t_ast_node_text, int t_id, const boost::shared_ptr<std::string> &t_fname) :
text(t_ast_node_text), identifier(t_id), filename(t_fname) {}
virtual ~AST_Node() {}
};
namespace exception namespace exception
{ {
/** /**
@@ -157,6 +99,76 @@ namespace chaiscript
} }
/**
* The struct that doubles as both a parser ast_node and an AST node
*/
struct AST_Node : boost::enable_shared_from_this<AST_Node> {
public:
const std::string text;
const int identifier;
boost::shared_ptr<const std::string> filename;
File_Position start, end;
std::vector<AST_NodePtr> children;
AST_NodePtr annotation;
/**
* Prints the contents of an AST node, including its children, recursively
*/
std::string to_string(std::string t_prepend = "") {
std::ostringstream oss;
oss << t_prepend << "(" << ast_node_type_to_string(this->identifier) << ") "
<< this->text << " : " << this->start.line << ", " << this->start.column << std::endl;
for (unsigned int j = 0; j < this->children.size(); ++j) {
oss << this->children[j]->to_string(t_prepend + " ");
}
return oss.str();
}
std::string internal_to_string() {
return to_string();
}
Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_e)
{
try {
return eval_internal(t_e);
} catch (exception::eval_error &ee) {
ee.call_stack.push_back(shared_from_this());
throw ee;
}
}
void replace_child(const AST_NodePtr &t_child, const AST_NodePtr &t_new_child)
{
std::replace(children.begin(), children.end(), t_child, t_new_child);
}
protected:
AST_Node(const std::string &t_ast_node_text, int t_id, const boost::shared_ptr<std::string> &t_fname,
int t_start_line, int t_start_col, int t_end_line, int t_end_col) :
text(t_ast_node_text), identifier(t_id), filename(t_fname),
start(t_start_line, t_start_col), end(t_end_line, t_end_col)
{
}
AST_Node(const std::string &t_ast_node_text, int t_id, const boost::shared_ptr<std::string> &t_fname) :
text(t_ast_node_text), identifier(t_id), filename(t_fname) {}
virtual ~AST_Node() {}
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &)
{
throw std::runtime_error("Undispatched ast_node (internal error)");
}
};
namespace detail namespace detail
{ {
/** /**

View File

@@ -28,9 +28,6 @@ namespace chaiscript
return t_node->eval(t_ss); return t_node->eval(t_ss);
} catch (const detail::Return_Value &rv) { } catch (const detail::Return_Value &rv) {
return rv.retval; return rv.retval;
} catch (exception::eval_error &ee) {
ee.call_stack.push_back(t_node);
throw;
} }
} }
@@ -42,16 +39,10 @@ namespace chaiscript
Binary_Operator_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Bitwise_Xor, 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) : Binary_Operator_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Bitwise_Xor, 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) { } AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Binary_Operator_AST_Node() {} virtual ~Binary_Operator_AST_Node() {}
virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_ss){ virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
Boxed_Value retval; Boxed_Value retval;
try { retval = this->children[0]->eval(t_ss);
retval = this->children[0]->eval(t_ss);
}
catch (exception::eval_error &ee) {
ee.call_stack.push_back(this->children[0]);
throw;
}
for (size_t i = 1; i < this->children.size(); i += 2) { for (size_t i = 1; i < this->children.size(); i += 2) {
try { try {
@@ -60,10 +51,6 @@ namespace chaiscript
catch(const exception::dispatch_error &){ catch(const exception::dispatch_error &){
throw exception::eval_error("Can not find appropriate '" + this->children[i]->text + "'"); throw exception::eval_error("Can not find appropriate '" + this->children[i]->text + "'");
} }
catch(exception::eval_error &ee) {
ee.call_stack.push_back(this->children[i+1]);
throw;
}
} }
return retval; return retval;
@@ -85,7 +72,7 @@ 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),
m_value(const_var(int(atoi(this->text.c_str())))) { } 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_internal(chaiscript::detail::Dispatch_Engine &){
return m_value; return m_value;
} }
@@ -100,7 +87,7 @@ 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),
m_value(const_var(double(atof(this->text.c_str())))) { } m_value(const_var(double(atof(this->text.c_str())))) { }
virtual ~Float_AST_Node() {} virtual ~Float_AST_Node() {}
virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &){ virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &){
return m_value; return m_value;
} }
@@ -114,7 +101,7 @@ namespace chaiscript
Id_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Id, 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) : Id_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Id, 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) { } AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Id_AST_Node() {} virtual ~Id_AST_Node() {}
virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_ss){ virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
if (this->text == "true") { if (this->text == "true") {
return const_var(true); return const_var(true);
} }
@@ -164,18 +151,12 @@ namespace chaiscript
Fun_Call_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Fun_Call, 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) : Fun_Call_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Fun_Call, 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) { } AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Fun_Call_AST_Node() {} virtual ~Fun_Call_AST_Node() {}
virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_ss){ virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
dispatch::Param_List_Builder plb; dispatch::Param_List_Builder plb;
if ((this->children.size() > 1) && (this->children[1]->identifier == AST_Node_Type::Arg_List)) { if ((this->children.size() > 1) && (this->children[1]->identifier == AST_Node_Type::Arg_List)) {
for (size_t i = 0; i < this->children[1]->children.size(); ++i) { for (size_t i = 0; i < this->children[1]->children.size(); ++i) {
try { plb << this->children[1]->children[i]->eval(t_ss);
plb << this->children[1]->children[i]->eval(t_ss);
}
catch(exception::eval_error &ee) {
ee.call_stack.push_back(this->children[1]->children[i]);
throw;
}
} }
} }
@@ -205,9 +186,8 @@ namespace chaiscript
} }
} }
catch(exception::eval_error &ee) { catch(exception::eval_error &ee) {
ee.call_stack.push_back(this->children[0]);
t_ss.set_stack(prev_stack); t_ss.set_stack(prev_stack);
throw exception::eval_error(ee.reason); throw;
} }
} }
@@ -219,42 +199,29 @@ namespace chaiscript
Inplace_Fun_Call_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Inplace_Fun_Call, 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) : Inplace_Fun_Call_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Inplace_Fun_Call, 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) { } AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Inplace_Fun_Call_AST_Node() {} virtual ~Inplace_Fun_Call_AST_Node() {}
virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_ss){ virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
dispatch::Param_List_Builder plb; dispatch::Param_List_Builder plb;
if ((this->children.size() > 1) && (this->children[1]->identifier == AST_Node_Type::Arg_List)) { if ((this->children.size() > 1) && (this->children[1]->identifier == AST_Node_Type::Arg_List)) {
for (size_t i = 0; i < this->children[1]->children.size(); ++i) { for (size_t i = 0; i < this->children[1]->children.size(); ++i) {
try { plb << this->children[1]->children[i]->eval(t_ss);
plb << this->children[1]->children[i]->eval(t_ss);
}
catch (exception::eval_error &ee) {
ee.call_stack.push_back(this->children[1]->children[i]);
throw;
}
} }
} }
Boxed_Value fn = this->children[0]->eval(t_ss);
try { try {
Boxed_Value fn = this->children[0]->eval(t_ss); return (*boxed_cast<Const_Proxy_Function >(fn))(plb);
try {
return (*boxed_cast<Const_Proxy_Function >(fn))(plb);
}
catch(const exception::dispatch_error &e){
throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'");
}
catch(detail::Return_Value &rv) {
return rv.retval;
}
catch(...) {
throw;
}
} }
catch(exception::eval_error &ee) { catch(const exception::dispatch_error &e){
ee.call_stack.push_back(this->children[0]); throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'");
throw exception::eval_error(ee.reason); }
catch(detail::Return_Value &rv) {
return rv.retval;
}
catch(...) {
throw;
} }
} }
}; };
@@ -278,70 +245,45 @@ namespace chaiscript
Equation_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Equation, 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) : Equation_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Equation, 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) { } AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Equation_AST_Node() {} virtual ~Equation_AST_Node() {}
virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_ss){ virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
Boxed_Value retval; Boxed_Value retval = this->children.back()->eval(t_ss);
try {
retval = this->children.back()->eval(t_ss);
}
catch (exception::eval_error &ee) {
ee.call_stack.push_back(this->children.back());
throw;
}
if (this->children.size() > 1) { if (this->children.size() > 1) {
for (int i = static_cast<int>(this->children.size())-3; i >= 0; i -= 2) { for (int i = static_cast<int>(this->children.size())-3; i >= 0; i -= 2) {
if (this->children[i+1]->text == "=") { if (this->children[i+1]->text == "=") {
Boxed_Value lhs = this->children[i]->eval(t_ss);
try { try {
Boxed_Value lhs = this->children[i]->eval(t_ss); if (lhs.is_undef()) {
retval = t_ss.call_function("clone", retval);
retval.clear_dependencies();
}
try { try {
if (lhs.is_undef()) { retval = t_ss.call_function(this->children[i+1]->text, lhs, retval);
retval = t_ss.call_function("clone", retval);
retval.clear_dependencies();
}
try {
retval = t_ss.call_function(this->children[i+1]->text, lhs, retval);
}
catch(const exception::dispatch_error &){
throw exception::eval_error(std::string("Mismatched types in equation") + (lhs.is_const()?", lhs is const.":"."));
}
} }
catch(const exception::dispatch_error &){ catch(const exception::dispatch_error &){
throw exception::eval_error("Can not clone right hand side of equation"); throw exception::eval_error(std::string("Mismatched types in equation") + (lhs.is_const()?", lhs is const.":"."));
} }
} }
catch(exception::eval_error &ee) { catch(const exception::dispatch_error &){
ee.call_stack.push_back(this->children[i]); throw exception::eval_error("Can not clone right hand side of equation");
throw;
} }
} }
else if (this->children[i+1]->text == ":=") { else if (this->children[i+1]->text == ":=") {
try { Boxed_Value lhs = this->children[i]->eval(t_ss);
Boxed_Value lhs = this->children[i]->eval(t_ss); if (lhs.is_undef() || type_match(lhs, retval)) {
if (lhs.is_undef() || type_match(lhs, retval)) { lhs.assign(retval);
lhs.assign(retval); } else {
} throw exception::eval_error("Mismatched types in equation");
else {
throw exception::eval_error("Mismatched types in equation");
}
}
catch (exception::eval_error &ee) {
ee.call_stack.push_back(this->children[i]);
throw;
} }
} }
else { else {
try { try {
retval = t_ss.call_function(this->children[i+1]->text, this->children[i]->eval(t_ss), retval); retval = t_ss.call_function(this->children[i+1]->text, this->children[i]->eval(t_ss), retval);
} } catch(const exception::dispatch_error &){
catch(const exception::dispatch_error &){
throw exception::eval_error("Can not find appropriate '" + this->children[i+1]->text + "'"); throw exception::eval_error("Can not find appropriate '" + this->children[i+1]->text + "'");
} }
catch(exception::eval_error &ee) {
ee.call_stack.push_back(this->children[i]);
throw;
}
} }
} }
} }
@@ -354,7 +296,7 @@ namespace chaiscript
Var_Decl_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Var_Decl, 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) : Var_Decl_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Var_Decl, 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) { } AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Var_Decl_AST_Node() {} virtual ~Var_Decl_AST_Node() {}
virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_ss){ virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
try { try {
t_ss.add_object(this->children[0]->text, Boxed_Value()); t_ss.add_object(this->children[0]->text, Boxed_Value());
} }
@@ -392,16 +334,8 @@ namespace chaiscript
Array_Call_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Array_Call, 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) : Array_Call_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Array_Call, 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) { } AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Array_Call_AST_Node() {} virtual ~Array_Call_AST_Node() {}
virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_ss){ virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
Boxed_Value retval; Boxed_Value retval = this->children[0]->eval(t_ss);
try {
retval = this->children[0]->eval(t_ss);
}
catch (exception::eval_error &ee) {
ee.call_stack.push_back(this->children[0]);
throw;
}
for (size_t i = 1; i < this->children.size(); ++i) { for (size_t i = 1; i < this->children.size(); ++i) {
try { try {
@@ -413,10 +347,6 @@ namespace chaiscript
catch(const exception::dispatch_error &){ catch(const exception::dispatch_error &){
throw exception::eval_error("Can not find appropriate array lookup '[]' "); throw exception::eval_error("Can not find appropriate array lookup '[]' ");
} }
catch(exception::eval_error &ee) {
ee.call_stack.push_back(this->children[i]);
throw;
}
} }
return retval; return retval;
@@ -428,15 +358,8 @@ namespace chaiscript
Dot_Access_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Dot_Access, 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) : Dot_Access_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Dot_Access, 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) { } AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Dot_Access_AST_Node() {} virtual ~Dot_Access_AST_Node() {}
virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_ss){ virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
Boxed_Value retval; Boxed_Value retval = this->children[0]->eval(t_ss);
try {
retval = this->children[0]->eval(t_ss);
}
catch (exception::eval_error &ee) {
ee.call_stack.push_back(this->children[0]);
throw;
}
if (this->children.size() > 1) { if (this->children.size() > 1) {
for (size_t i = 2; i < this->children.size(); i+=2) { for (size_t i = 2; i < this->children.size(); i+=2) {
@@ -445,13 +368,7 @@ namespace chaiscript
if (this->children[i]->children.size() > 1) { if (this->children[i]->children.size() > 1) {
for (size_t j = 0; j < this->children[i]->children[1]->children.size(); ++j) { for (size_t j = 0; j < this->children[i]->children[1]->children.size(); ++j) {
try { plb << this->children[i]->children[1]->children[j]->eval(t_ss);
plb << this->children[i]->children[1]->children[j]->eval(t_ss);
}
catch (exception::eval_error &ee) {
ee.call_stack.push_back(this->children[i]->children[1]->children[j]);
throw;
}
} }
} }
@@ -494,10 +411,6 @@ namespace chaiscript
catch(const exception::dispatch_error &){ catch(const exception::dispatch_error &){
throw exception::eval_error("Can not find appropriate array lookup '[]' "); throw exception::eval_error("Can not find appropriate array lookup '[]' ");
} }
catch(exception::eval_error &ee) {
ee.call_stack.push_back(this->children[i]->children[j]);
throw;
}
} }
} }
} }
@@ -514,7 +427,7 @@ 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),
m_value(const_var(this->text)) { } m_value(const_var(this->text)) { }
virtual ~Quoted_String_AST_Node() {} virtual ~Quoted_String_AST_Node() {}
virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &) { virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &) {
return m_value; return m_value;
} }
@@ -529,7 +442,7 @@ 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),
m_value(const_var(char(this->text[0]))) { } m_value(const_var(char(this->text[0]))) { }
virtual ~Single_Quoted_String_AST_Node() {} virtual ~Single_Quoted_String_AST_Node() {}
virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &){ virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &){
return m_value; return m_value;
} }
@@ -542,7 +455,7 @@ namespace chaiscript
Lambda_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Lambda, 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) : Lambda_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Lambda, 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) { } AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Lambda_AST_Node() {} virtual ~Lambda_AST_Node() {}
virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_ss){ virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
std::vector<std::string> t_param_names; std::vector<std::string> t_param_names;
size_t numparams = 0; size_t numparams = 0;
@@ -570,7 +483,7 @@ namespace chaiscript
Block_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Block, 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) : Block_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Block, 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) { } 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_internal(chaiscript::detail::Dispatch_Engine &t_ss){
const size_t num_children = this->children.size(); const size_t num_children = this->children.size();
detail::Scope_Push_Pop spp(t_ss); detail::Scope_Push_Pop spp(t_ss);
@@ -587,10 +500,6 @@ namespace chaiscript
catch (const chaiscript::detail::Return_Value &) { catch (const chaiscript::detail::Return_Value &) {
throw; throw;
} }
catch (exception::eval_error &ee) {
ee.call_stack.push_back(this->children[i]);
throw;
}
} }
return Boxed_Value(); return Boxed_Value();
@@ -603,7 +512,7 @@ namespace chaiscript
Def_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Def, 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) : Def_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Def, 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) { } AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Def_AST_Node() {} virtual ~Def_AST_Node() {}
virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_ss){ virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
std::vector<std::string> t_param_names; std::vector<std::string> t_param_names;
size_t numparams = 0; size_t numparams = 0;
AST_NodePtr guardnode; AST_NodePtr guardnode;
@@ -657,7 +566,7 @@ namespace chaiscript
While_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::While, 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) : While_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::While, 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) { } AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~While_AST_Node() {} virtual ~While_AST_Node() {}
virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_ss) { virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) {
bool cond; bool cond;
detail::Scope_Push_Pop spp(t_ss); detail::Scope_Push_Pop spp(t_ss);
@@ -668,19 +577,9 @@ namespace chaiscript
catch (const exception::bad_boxed_cast &) { catch (const exception::bad_boxed_cast &) {
throw exception::eval_error("While condition not boolean"); throw exception::eval_error("While condition not boolean");
} }
catch (exception::eval_error &ee) {
ee.call_stack.push_back(this->children[0]);
throw;
}
while (cond) { while (cond) {
try { try {
try { this->children[1]->eval(t_ss);
this->children[1]->eval(t_ss);
}
catch (exception::eval_error &ee) {
ee.call_stack.push_back(this->children[1]);
throw;
}
try { try {
cond = boxed_cast<bool>(this->children[0]->eval(t_ss)); cond = boxed_cast<bool>(this->children[0]->eval(t_ss));
@@ -688,10 +587,6 @@ namespace chaiscript
catch (const exception::bad_boxed_cast &) { catch (const exception::bad_boxed_cast &) {
throw exception::eval_error("While condition not boolean"); throw exception::eval_error("While condition not boolean");
} }
catch (exception::eval_error &ee) {
ee.call_stack.push_back(this->children[0]);
throw;
}
} }
catch (detail::Break_Loop &) { catch (detail::Break_Loop &) {
cond = false; cond = false;
@@ -707,7 +602,7 @@ namespace chaiscript
If_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::If, 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) : If_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::If, 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) { } AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~If_AST_Node() {} virtual ~If_AST_Node() {}
virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_ss){ virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
bool cond; bool cond;
try { try {
cond = boxed_cast<bool>(this->children[0]->eval(t_ss)); cond = boxed_cast<bool>(this->children[0]->eval(t_ss));
@@ -715,32 +610,16 @@ namespace chaiscript
catch (const exception::bad_boxed_cast &) { catch (const exception::bad_boxed_cast &) {
throw exception::eval_error("If condition not boolean"); throw exception::eval_error("If condition not boolean");
} }
catch (exception::eval_error &ee) {
ee.call_stack.push_back(this->children[0]);
throw;
}
if (cond) { if (cond) {
try { return this->children[1]->eval(t_ss);
return this->children[1]->eval(t_ss);
}
catch (exception::eval_error &ee) {
ee.call_stack.push_back(this->children[1]);
throw;
}
} }
else { else {
if (this->children.size() > 2) { if (this->children.size() > 2) {
size_t i = 2; size_t i = 2;
while ((!cond) && (i < this->children.size())) { while ((!cond) && (i < this->children.size())) {
if (this->children[i]->text == "else") { if (this->children[i]->text == "else") {
try { return this->children[i+1]->eval(t_ss);
return this->children[i+1]->eval(t_ss);
}
catch (exception::eval_error &ee) {
ee.call_stack.push_back(this->children[i+1]);
throw;
}
} }
else if (this->children[i]->text == "else if") { else if (this->children[i]->text == "else if") {
try { try {
@@ -749,18 +628,8 @@ namespace chaiscript
catch (const exception::bad_boxed_cast &) { catch (const exception::bad_boxed_cast &) {
throw exception::eval_error("'else if' condition not boolean"); throw exception::eval_error("'else if' condition not boolean");
} }
catch (exception::eval_error &ee) {
ee.call_stack.push_back(this->children[i+1]);
throw;
}
if (cond) { if (cond) {
try { return this->children[i+2]->eval(t_ss);
return this->children[i+2]->eval(t_ss);
}
catch (exception::eval_error &ee) {
ee.call_stack.push_back(this->children[i+2]);
throw;
}
} }
} }
i = i + 3; i = i + 3;
@@ -778,37 +647,18 @@ namespace chaiscript
For_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::For, 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) : For_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::For, 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) { } AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~For_AST_Node() {} virtual ~For_AST_Node() {}
virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_ss){ virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
bool cond; bool cond;
detail::Scope_Push_Pop spp(t_ss); detail::Scope_Push_Pop spp(t_ss);
try { try {
if (this->children.size() == 4) { if (this->children.size() == 4) {
try { this->children[0]->eval(t_ss);
this->children[0]->eval(t_ss);
}
catch (exception::eval_error &ee) {
ee.call_stack.push_back(this->children[0]);
throw;
}
try { cond = boxed_cast<bool>(this->children[1]->eval(t_ss));
cond = boxed_cast<bool>(this->children[1]->eval(t_ss)); } else {
} cond = boxed_cast<bool>(this->children[0]->eval(t_ss));
catch (exception::eval_error &ee) {
ee.call_stack.push_back(this->children[1]);
throw;
}
}
else {
try {
cond = boxed_cast<bool>(this->children[0]->eval(t_ss));
}
catch (exception::eval_error &ee) {
ee.call_stack.push_back(this->children[0]);
throw;
}
} }
} }
catch (const exception::bad_boxed_cast &) { catch (const exception::bad_boxed_cast &) {
@@ -817,54 +667,17 @@ namespace chaiscript
while (cond) { while (cond) {
try { try {
if (this->children.size() == 4) { if (this->children.size() == 4) {
try { this->children[3]->eval(t_ss);
this->children[3]->eval(t_ss); this->children[2]->eval(t_ss);
}
catch (exception::eval_error &ee) {
ee.call_stack.push_back(this->children[3]);
throw;
}
try { cond = boxed_cast<bool>(this->children[1]->eval(t_ss));
this->children[2]->eval(t_ss);
}
catch (exception::eval_error &ee) {
ee.call_stack.push_back(this->children[2]);
throw;
}
try {
cond = boxed_cast<bool>(this->children[1]->eval(t_ss));
}
catch (exception::eval_error &ee) {
ee.call_stack.push_back(this->children[1]);
throw;
}
} }
else { else {
try { this->children[2]->eval(t_ss);
this->children[2]->eval(t_ss);
}
catch (exception::eval_error &ee) {
ee.call_stack.push_back(this->children[2]);
throw;
}
try { this->children[1]->eval(t_ss);
this->children[1]->eval(t_ss);
}
catch (exception::eval_error &ee) {
ee.call_stack.push_back(this->children[1]);
throw;
}
try { cond = boxed_cast<bool>(this->children[0]->eval(t_ss));
cond = boxed_cast<bool>(this->children[0]->eval(t_ss));
}
catch (exception::eval_error &ee) {
ee.call_stack.push_back(this->children[0]);
throw;
}
} }
} }
catch (const exception::bad_boxed_cast &) { catch (const exception::bad_boxed_cast &) {
@@ -884,17 +697,11 @@ namespace chaiscript
Inline_Array_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Inline_Array, 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) : Inline_Array_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Inline_Array, 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) { } AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Inline_Array_AST_Node() {} virtual ~Inline_Array_AST_Node() {}
virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_ss){ virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
std::vector<Boxed_Value> vec; std::vector<Boxed_Value> vec;
if (this->children.size() > 0) { if (this->children.size() > 0) {
for (size_t i = 0; i < this->children[0]->children.size(); ++i) { for (size_t i = 0; i < this->children[0]->children.size(); ++i) {
try { vec.push_back(this->children[0]->children[i]->eval(t_ss));
vec.push_back(this->children[0]->children[i]->eval(t_ss));
}
catch(exception::eval_error &ee) {
ee.call_stack.push_back(this->children[0]->children[i]);
throw;
}
} }
} }
@@ -908,18 +715,12 @@ namespace chaiscript
Inline_Map_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Inline_Map, 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) : Inline_Map_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Inline_Map, 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) { } AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Inline_Map_AST_Node() {} virtual ~Inline_Map_AST_Node() {}
virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_ss){ virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
try { try {
std::map<std::string, Boxed_Value> retval; std::map<std::string, Boxed_Value> retval;
for (size_t i = 0; i < this->children[0]->children.size(); ++i) { for (size_t i = 0; i < this->children[0]->children.size(); ++i) {
try { retval[boxed_cast<std::string>(this->children[0]->children[i]->children[0]->eval(t_ss))]
retval[boxed_cast<std::string>(this->children[0]->children[i]->children[0]->eval(t_ss))] = t_ss.call_function("clone", this->children[0]->children[i]->children[1]->eval(t_ss));
= t_ss.call_function("clone", this->children[0]->children[i]->children[1]->eval(t_ss));
}
catch(exception::eval_error &ee) {
ee.call_stack.push_back(this->children[0]->children[i]);
throw;
}
} }
return const_var(retval); return const_var(retval);
} }
@@ -935,15 +736,9 @@ namespace chaiscript
Return_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Return, 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) : Return_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Return, 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) { } AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Return_AST_Node() {} virtual ~Return_AST_Node() {}
virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_ss){ virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
if (this->children.size() > 0) { if (this->children.size() > 0) {
try { throw detail::Return_Value(this->children[0]->eval(t_ss));
throw detail::Return_Value(this->children[0]->eval(t_ss));
}
catch (exception::eval_error &ee) {
ee.call_stack.push_back(this->children[0]);
throw;
}
} }
else { else {
throw detail::Return_Value(Boxed_Value()); throw detail::Return_Value(Boxed_Value());
@@ -957,18 +752,12 @@ namespace chaiscript
File_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::File, 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) : File_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::File, 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) { } AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~File_AST_Node() {} virtual ~File_AST_Node() {}
virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_ss) { virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) {
const size_t size = this->children.size(); const size_t size = this->children.size();
for (size_t i = 0; i < size; ++i) { for (size_t i = 0; i < size; ++i) {
try { const Boxed_Value &retval = this->children[i]->eval(t_ss);
const Boxed_Value &retval = this->children[i]->eval(t_ss); if (i + 1 == size) {
if (i + 1 == size) { return retval;
return retval;
}
}
catch (exception::eval_error &ee) {
ee.call_stack.push_back(this->children[i]);
throw;
} }
} }
return Boxed_Value(); return Boxed_Value();
@@ -980,13 +769,8 @@ namespace chaiscript
Prefix_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Prefix, 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) : Prefix_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Prefix, 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) { } AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Prefix_AST_Node() {} virtual ~Prefix_AST_Node() {}
virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_ss){ virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
try { return t_ss.call_function(this->children[0]->text, this->children[1]->eval(t_ss));
return t_ss.call_function(this->children[0]->text, this->children[1]->eval(t_ss));
}
catch(std::exception &){
throw exception::eval_error("Can not find appropriate unary '" + this->children[0]->text + "'");
}
} }
}; };
@@ -996,7 +780,7 @@ namespace chaiscript
Break_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Break, 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) : Break_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Break, 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) { } AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Break_AST_Node() {} virtual ~Break_AST_Node() {}
virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &){ virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &){
throw detail::Break_Loop(); throw detail::Break_Loop();
} }
}; };
@@ -1020,7 +804,7 @@ namespace chaiscript
Inline_Range_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Inline_Range, 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) : Inline_Range_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Inline_Range, 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) { } AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Inline_Range_AST_Node() {} virtual ~Inline_Range_AST_Node() {}
virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_ss){ virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
try { try {
return t_ss.call_function("generate_range", return t_ss.call_function("generate_range",
this->children[0]->children[0]->children[0]->eval(t_ss), this->children[0]->children[0]->children[0]->eval(t_ss),
@@ -1029,10 +813,6 @@ namespace chaiscript
catch (const exception::dispatch_error &) { catch (const exception::dispatch_error &) {
throw exception::eval_error("Unable to generate range vector"); throw exception::eval_error("Unable to generate range vector");
} }
catch(exception::eval_error &ee) {
ee.call_stack.push_back(this->children[0]->children[0]);
throw;
}
} }
}; };
@@ -1049,7 +829,7 @@ namespace chaiscript
Try_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Try, 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) : Try_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Try, 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) { } AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Try_AST_Node() {} virtual ~Try_AST_Node() {}
virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_ss){ virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
Boxed_Value retval; Boxed_Value retval;
detail::Scope_Push_Pop spp(t_ss); detail::Scope_Push_Pop spp(t_ss);
@@ -1058,15 +838,8 @@ namespace chaiscript
retval = this->children[0]->eval(t_ss); retval = this->children[0]->eval(t_ss);
} }
catch (exception::eval_error &ee) { catch (exception::eval_error &ee) {
ee.call_stack.push_back(this->children[0]);
if (this->children.back()->identifier == AST_Node_Type::Finally) { if (this->children.back()->identifier == AST_Node_Type::Finally) {
try { this->children.back()->children[0]->eval(t_ss);
this->children.back()->children[0]->eval(t_ss);
}
catch (exception::eval_error &ee2) {
ee2.call_stack.push_back(this->children.back()->children[0]);
throw;
}
} }
throw; throw;
} }
@@ -1083,25 +856,13 @@ namespace chaiscript
if (catch_block->children.size() == 1) { if (catch_block->children.size() == 1) {
//No variable capture, no guards //No variable capture, no guards
try { retval = catch_block->children[0]->eval(t_ss);
retval = catch_block->children[0]->eval(t_ss);
}
catch (exception::eval_error &ee) {
ee.call_stack.push_back(catch_block->children[0]);
throw;
}
break; break;
} }
else if (catch_block->children.size() == 2) { else if (catch_block->children.size() == 2) {
//Variable capture, no guards //Variable capture, no guards
t_ss.add_object(catch_block->children[0]->text, except); t_ss.add_object(catch_block->children[0]->text, except);
try { retval = catch_block->children[1]->eval(t_ss);
retval = catch_block->children[1]->eval(t_ss);
}
catch (exception::eval_error &ee) {
ee.call_stack.push_back(catch_block->children[1]);
throw;
}
break; break;
} }
@@ -1114,37 +875,18 @@ namespace chaiscript
guard = boxed_cast<bool>(catch_block->children[1]->eval(t_ss)); guard = boxed_cast<bool>(catch_block->children[1]->eval(t_ss));
} catch (const exception::bad_boxed_cast &) { } catch (const exception::bad_boxed_cast &) {
if (this->children.back()->identifier == AST_Node_Type::Finally) { if (this->children.back()->identifier == AST_Node_Type::Finally) {
try { this->children.back()->children[0]->eval(t_ss);
this->children.back()->children[0]->eval(t_ss);
}
catch (exception::eval_error &ee) {
ee.call_stack.push_back(this->children.back()->children[0]);
throw;
}
} }
throw exception::eval_error("Guard condition not boolean"); throw exception::eval_error("Guard condition not boolean");
} }
if (guard) { if (guard) {
try { retval = catch_block->children[2]->eval(t_ss);
retval = catch_block->children[2]->eval(t_ss);
}
catch (exception::eval_error &ee) {
ee.call_stack.push_back(catch_block->children[2]);
throw;
}
break; break;
} }
} }
else { else {
if (this->children.back()->identifier == AST_Node_Type::Finally) { if (this->children.back()->identifier == AST_Node_Type::Finally) {
try { this->children.back()->children[0]->eval(t_ss);
this->children.back()->children[0]->eval(t_ss);
}
catch (exception::eval_error &ee) {
ee.call_stack.push_back(this->children.back()->children[0]);
throw;
}
} }
throw exception::eval_error("Internal error: catch block size unrecognized"); throw exception::eval_error("Internal error: catch block size unrecognized");
} }
@@ -1156,27 +898,13 @@ namespace chaiscript
if (catch_block->children.size() == 1) { if (catch_block->children.size() == 1) {
//No variable capture, no guards //No variable capture, no guards
try { retval = catch_block->children[0]->eval(t_ss);
retval = catch_block->children[0]->eval(t_ss);
}
catch (exception::eval_error &ee) {
ee.call_stack.push_back(catch_block->children[0]);
throw;
}
break; break;
} }
else if (catch_block->children.size() == 2) { else if (catch_block->children.size() == 2) {
//Variable capture, no guards //Variable capture, no guards
t_ss.add_object(catch_block->children[0]->text, except); t_ss.add_object(catch_block->children[0]->text, except);
try { retval = catch_block->children[1]->eval(t_ss);
retval = catch_block->children[1]->eval(t_ss);
}
catch (exception::eval_error &ee) {
ee.call_stack.push_back(catch_block->children[1]);
throw;
}
break; break;
} }
else if (catch_block->children.size() == 3) { else if (catch_block->children.size() == 3) {
@@ -1189,41 +917,19 @@ namespace chaiscript
} }
catch (const exception::bad_boxed_cast &) { catch (const exception::bad_boxed_cast &) {
if (this->children.back()->identifier == AST_Node_Type::Finally) { if (this->children.back()->identifier == AST_Node_Type::Finally) {
try { this->children.back()->children[0]->eval(t_ss);
this->children.back()->children[0]->eval(t_ss);
}
catch (exception::eval_error &ee) {
ee.call_stack.push_back(this->children.back()->children[0]);
throw;
}
} }
throw exception::eval_error("Guard condition not boolean"); throw exception::eval_error("Guard condition not boolean");
} }
catch (exception::eval_error &ee) {
ee.call_stack.push_back(catch_block->children[1]);
throw;
}
if (guard) { if (guard) {
try { retval = catch_block->children[2]->eval(t_ss);
retval = catch_block->children[2]->eval(t_ss);
}
catch (exception::eval_error &ee) {
ee.call_stack.push_back(catch_block->children[2]);
throw;
}
break; break;
} }
} }
else { else {
if (this->children.back()->identifier == AST_Node_Type::Finally) { if (this->children.back()->identifier == AST_Node_Type::Finally) {
try { this->children.back()->children[0]->eval(t_ss);
this->children.back()->children[0]->eval(t_ss);
}
catch (exception::eval_error &ee) {
ee.call_stack.push_back(this->children.back()->children[0]);
throw;
}
} }
throw exception::eval_error("Internal error: catch block size unrecognized"); throw exception::eval_error("Internal error: catch block size unrecognized");
} }
@@ -1231,25 +937,13 @@ namespace chaiscript
} }
catch (...) { catch (...) {
if (this->children.back()->identifier == AST_Node_Type::Finally) { if (this->children.back()->identifier == AST_Node_Type::Finally) {
try { this->children.back()->children[0]->eval(t_ss);
this->children.back()->children[0]->eval(t_ss);
}
catch (exception::eval_error &ee) {
ee.call_stack.push_back(this->children.back()->children[0]);
throw;
}
} }
throw; throw;
} }
if (this->children.back()->identifier == AST_Node_Type::Finally) { if (this->children.back()->identifier == AST_Node_Type::Finally) {
try { retval = this->children.back()->children[0]->eval(t_ss);
retval = this->children.back()->children[0]->eval(t_ss);
}
catch (exception::eval_error &ee) {
ee.call_stack.push_back(this->children.back()->children[0]);
throw;
}
} }
return retval; return retval;
@@ -1276,7 +970,7 @@ namespace chaiscript
Method_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Method, 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) : Method_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Method, 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) { } AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Method_AST_Node() {} virtual ~Method_AST_Node() {}
virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_ss){ virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
std::vector<std::string> t_param_names; std::vector<std::string> t_param_names;
AST_NodePtr guardnode; AST_NodePtr guardnode;
@@ -1353,7 +1047,7 @@ namespace chaiscript
Attr_Decl_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Attr_Decl, 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) : Attr_Decl_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Attr_Decl, 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) { } AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Attr_Decl_AST_Node() {} virtual ~Attr_Decl_AST_Node() {}
virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_ss){ virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
try { try {
t_ss.add(fun(boost::function<Boxed_Value (dispatch::Dynamic_Object &)>(boost::bind(&dispatch::detail::Dynamic_Object_Attribute::func, this->children[0]->text, t_ss.add(fun(boost::function<Boxed_Value (dispatch::Dynamic_Object &)>(boost::bind(&dispatch::detail::Dynamic_Object_Attribute::func, this->children[0]->text,
this->children[1]->text, _1))), this->children[1]->text); this->children[1]->text, _1))), this->children[1]->text);
@@ -1407,15 +1101,8 @@ namespace chaiscript
Logical_And_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Logical_And, 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) : Logical_And_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Logical_And, 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) { } AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Logical_And_AST_Node() {} virtual ~Logical_And_AST_Node() {}
virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_ss){ virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
Boxed_Value retval; Boxed_Value retval = this->children[0]->eval(t_ss);
try {
retval = this->children[0]->eval(t_ss);
}
catch (exception::eval_error &ee) {
ee.call_stack.push_back(this->children[0]);
throw;
}
if (this->children.size() > 1) { if (this->children.size() > 1) {
for (size_t i = 1; i < this->children.size(); i += 2) { for (size_t i = 1; i < this->children.size(); i += 2) {
@@ -1427,13 +1114,7 @@ namespace chaiscript
throw exception::eval_error("Condition not boolean"); throw exception::eval_error("Condition not boolean");
} }
if (lhs) { if (lhs) {
try { retval = this->children[i+1]->eval(t_ss);
retval = this->children[i+1]->eval(t_ss);
}
catch (exception::eval_error &ee) {
ee.call_stack.push_back(this->children[i+1]);
throw;
}
} }
else { else {
retval = Boxed_Value(false); retval = Boxed_Value(false);
@@ -1449,37 +1130,20 @@ namespace chaiscript
Logical_Or_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Logical_Or, 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) : Logical_Or_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Logical_Or, 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) { } AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
virtual ~Logical_Or_AST_Node() {} virtual ~Logical_Or_AST_Node() {}
virtual Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_ss){ virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss){
Boxed_Value retval; Boxed_Value retval;
try { retval = this->children[0]->eval(t_ss);
retval = this->children[0]->eval(t_ss);
}
catch (exception::eval_error &ee) {
ee.call_stack.push_back(this->children[0]);
throw;
}
if (this->children.size() > 1) { if (this->children.size() > 1) {
for (size_t i = 1; i < this->children.size(); i += 2) { for (size_t i = 1; i < this->children.size(); i += 2) {
bool lhs; bool lhs = boxed_cast<bool>(retval);
try {
lhs = boxed_cast<bool>(retval);
}
catch (const exception::bad_boxed_cast &) {
throw exception::eval_error("Condition not boolean");
}
if (lhs) { if (lhs) {
retval = Boxed_Value(true); retval = Boxed_Value(true);
} }
else { else {
try { retval = this->children[i+1]->eval(t_ss);
retval = this->children[i+1]->eval(t_ss);
}
catch (exception::eval_error &ee) {
ee.call_stack.push_back(this->children[i+1]);
throw;
}
} }
} }
} }

View File

@@ -63,6 +63,17 @@ bool throws_exception(const boost::function<void ()> &f)
return false; return false;
} }
chaiscript::exception::eval_error get_eval_error(const boost::function<void ()> &f)
{
try {
f();
} catch (const chaiscript::exception::eval_error &e) {
return e;
}
throw std::runtime_error("no exception throw");
}
std::string get_next_command() { std::string get_next_command() {
std::string retval("quit"); std::string retval("quit");
if ( ! std::cin.eof() ) { if ( ! std::cin.eof() ) {
@@ -158,6 +169,7 @@ int main(int argc, char *argv[])
chai.add(chaiscript::fun(&help), "help"); chai.add(chaiscript::fun(&help), "help");
chai.add(chaiscript::fun(&version), "version"); chai.add(chaiscript::fun(&version), "version");
chai.add(chaiscript::fun(&throws_exception), "throws_exception"); chai.add(chaiscript::fun(&throws_exception), "throws_exception");
chai.add(chaiscript::fun(&get_eval_error), "get_eval_error");
for (int i = 0; i < argc; ++i) { for (int i = 0; i < argc; ++i) {
if ( i == 0 && argc > 1 ) { if ( i == 0 && argc > 1 ) {
@@ -209,9 +221,13 @@ int main(int argc, char *argv[])
std::cout << ee.what(); std::cout << ee.what();
if (ee.call_stack.size() > 0) { if (ee.call_stack.size() > 0) {
std::cout << "during evaluation at (" << *(ee.call_stack[0]->filename) << " " << ee.call_stack[0]->start.line << ", " << ee.call_stack[0]->start.column << ")"; std::cout << "during evaluation at (" << *(ee.call_stack[0]->filename) << " " << ee.call_stack[0]->start.line << ", " << ee.call_stack[0]->start.column << ")";
for (unsigned int j = 1; j < ee.call_stack.size(); ++j) { for (size_t j = 1; j < ee.call_stack.size(); ++j) {
std::cout << std::endl; if (ee.call_stack[j]->identifier != chaiscript::AST_Node_Type::Block
std::cout << " from " << *(ee.call_stack[j]->filename) << " (" << ee.call_stack[j]->start.line << ", " << ee.call_stack[j]->start.column << ")"; && ee.call_stack[j]->identifier != chaiscript::AST_Node_Type::File)
{
std::cout << std::endl;
std::cout << " from " << *(ee.call_stack[j]->filename) << " (" << ee.call_stack[j]->start.line << ", " << ee.call_stack[j]->start.column << ")";
}
} }
} }
std::cout << std::endl; std::cout << std::endl;

View File

@@ -52,6 +52,13 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_reflect
chaiscript::bootstrap::standard_library::vector_type<std::vector<boost::shared_ptr<chaiscript::AST_Node> > >("AST_NodeVector", m); chaiscript::bootstrap::standard_library::vector_type<std::vector<boost::shared_ptr<chaiscript::AST_Node> > >("AST_NodeVector", m);
CHAISCRIPT_CLASS( m,
chaiscript::exception::eval_error,
,
((reason))
((call_stack))
);
CHAISCRIPT_CLASS( m, CHAISCRIPT_CLASS( m,
chaiscript::File_Position, chaiscript::File_Position,
(chaiscript::File_Position()) (chaiscript::File_Position())

39
unittests/eval_error.chai Normal file
View File

@@ -0,0 +1,39 @@
load_module("reflection")
def deep()
{
try {
} catch {
} finally {
if (2)
{
}
}
}
def func()
{
deep();
}
def doing()
{
for (var i = 0; i < 10; ++i)
{
func();
}
}
def while_doing()
{
while (true)
{
doing();
}
}
var f = fun() { while_doing(); }
assert_equal(get_eval_error(f).call_stack.size(), 16)

View File

@@ -10,6 +10,24 @@ def assert_equal(x, y)
} }
} }
def assert_false(f)
{
if (f)
{
print("assert_false failure");
exit(-1);
}
}
def assert_true(f)
{
if (!f)
{
print("assert_false failure");
exit(-1);
}
}
def assert_not_equal(x, y) def assert_not_equal(x, y)
{ {
if (!(x == y)) if (!(x == y))