From 5a76d986926a77929408c2c8aa493da2e1b606a6 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sun, 25 Sep 2011 16:46:05 -0600 Subject: [PATCH] Enhance and correct error messages Backported from C++11 branch. Conflicts: include/chaiscript/dispatchkit/proxy_functions.hpp include/chaiscript/language/chaiscript_common.hpp include/chaiscript/language/chaiscript_eval.hpp include/chaiscript/language/chaiscript_parser.hpp --- .../chaiscript/dispatchkit/dispatchkit.hpp | 7 +- .../dispatchkit/proxy_functions.hpp | 13 +- .../chaiscript/language/chaiscript_common.hpp | 144 ++++++++++++++---- .../chaiscript/language/chaiscript_eval.hpp | 42 ++--- .../chaiscript/language/chaiscript_parser.hpp | 4 +- 5 files changed, 142 insertions(+), 68 deletions(-) diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index a805233..89508d1 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -780,10 +780,9 @@ namespace chaiscript /** * Dump object info to stdout */ - void dump_object(Boxed_Value o) const + void dump_object(const Boxed_Value &o) const { - Type_Info ti = o.get_type_info(); - std::cout << (ti.is_const()?"const ":"") << get_type_name(ti) << std::endl; + std::cout << (o.is_const()?"const ":"") << type_name(o) << std::endl; } /** @@ -875,7 +874,7 @@ namespace chaiscript return false; } - std::string type_name(Boxed_Value obj) const + std::string type_name(const Boxed_Value &obj) const { return get_type_name(obj.get_type_info()); } diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index fe47ae5..f28fa60 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -591,17 +591,14 @@ namespace chaiscript class dispatch_error : public std::runtime_error { public: - dispatch_error() throw() - : std::runtime_error("No matching function to dispatch to") + dispatch_error(const std::vector &t_bvs) + : std::runtime_error("Error with function dispatch"), parameters(t_bvs) { } - dispatch_error(bool is_const) throw() - : std::runtime_error(std::string("No matching function to dispatch to") + (is_const?", parameter is const":"")) - { - } - virtual ~dispatch_error() throw() {} + + std::vector parameters; }; } @@ -635,7 +632,7 @@ namespace chaiscript ++begin; } - throw exception::dispatch_error(plist.empty()?false:plist[0].is_const()); + throw exception::dispatch_error(plist); } /** diff --git a/include/chaiscript/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index f45d9f0..fd00c87 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -71,9 +71,22 @@ namespace chaiscript std::string filename; std::vector call_stack; - eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname) throw() - : std::runtime_error(format(t_why, t_where, t_fname)), - reason(t_why), start_position(t_where), end_position(t_where), filename(t_fname) + eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname, + const std::vector &t_parameters, const chaiscript::detail::Dispatch_Engine &t_ss) : + std::runtime_error(format(t_why, t_where, t_fname, t_parameters, t_ss)), + reason(t_why), start_position(t_where), end_position(t_where), filename(t_fname) + {} + + eval_error(const std::string &t_why, + const std::vector &t_parameters, const chaiscript::detail::Dispatch_Engine &t_ss) : + std::runtime_error(format(t_why, t_parameters, t_ss)), + reason(t_why) + {} + + + eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname) : + std::runtime_error(format(t_why, t_where, t_fname)), + reason(t_why), start_position(t_where), end_position(t_where), filename(t_fname) {} eval_error(const std::string &t_why) throw() @@ -84,39 +97,104 @@ namespace chaiscript virtual ~eval_error() throw() {} private: - static std::string format_why(const std::string &t_why) + static std::string format_why(const std::string &t_why) { - return "Error: \"" + t_why + "\""; - } - - static std::string format_filename(const std::string &t_fname) - { - std::stringstream ss; - if (t_fname != "__EVAL__") - { - ss << "in '" << t_fname << "' "; - } else { - ss << "during evaluation "; - } - return ss.str(); - } - - static std::string format_location(const File_Position &t_where) - { - std::stringstream ss; - ss << "at (" << t_where.line << ", " << t_where.column << ")"; - return ss.str(); + return "Error: \"" + t_why + "\""; } - static std::string format(const std::string &t_why, const File_Position &t_where, const std::string &t_fname) - { - std::stringstream ss; - ss << format_why(t_why); - ss << " "; - ss << format_filename(t_fname); - ss << " "; - ss << format_location(t_where); - return ss.str(); + static std::string format_parameters(const std::vector &t_parameters, + const chaiscript::detail::Dispatch_Engine &t_ss) + { + std::stringstream ss; + ss << "With parameters: ("; + + if (!t_parameters.empty()) + { + std::string paramstr; + + for (std::vector::const_iterator itr = t_parameters.begin(); + itr != t_parameters.end(); + ++itr) + { + paramstr += (itr->is_const()?"const ":""); + paramstr += t_ss.type_name(*itr); + paramstr += ", "; + } + + ss << paramstr.substr(0, paramstr.size() - 2); + } + ss << ")"; + + return ss.str(); + } + + static std::string format_filename(const std::string &t_fname) + { + std::stringstream ss; + + if (t_fname != "__EVAL__") + { + ss << "in '" << t_fname << "' "; + } else { + ss << "during evaluation "; + } + + return ss.str(); + } + + static std::string format_location(const File_Position &t_where) + { + std::stringstream ss; + ss << "at (" << t_where.line << ", " << t_where.column << ")"; + return ss.str(); + } + + static std::string format(const std::string &t_why, const File_Position &t_where, const std::string &t_fname, + const std::vector &t_parameters, const chaiscript::detail::Dispatch_Engine &t_ss) + { + std::stringstream ss; + + ss << format_why(t_why); + ss << " "; + + ss << format_parameters(t_parameters, t_ss); + ss << " "; + + ss << format_filename(t_fname); + ss << " "; + + ss << format_location(t_where); + + return ss.str(); + } + + static std::string format(const std::string &t_why, + const std::vector &t_parameters, const chaiscript::detail::Dispatch_Engine &t_ss) + { + std::stringstream ss; + + ss << format_why(t_why); + ss << " "; + + ss << format_parameters(t_parameters, t_ss); + ss << " "; + + return ss.str(); + } + + static std::string format(const std::string &t_why, const File_Position &t_where, const std::string &t_fname) + { + std::stringstream ss; + + ss << format_why(t_why); + ss << " "; + + ss << format_filename(t_fname); + ss << " "; + + ss << format_location(t_where); + + return ss.str(); } }; diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 921ad85..f78b53c 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -74,8 +74,8 @@ namespace chaiscript return t_ss.call_function(t_oper_string, t_lhs, t_rhs); } } - catch(const exception::dispatch_error &){ - throw exception::eval_error("Can not find appropriate '" + t_oper_string + "'"); + catch(const exception::dispatch_error &e){ + throw exception::eval_error("Can not find appropriate '" + t_oper_string + "' operator.", e.parameters, t_ss); } } }; @@ -208,7 +208,7 @@ namespace chaiscript return retval; } catch(const exception::dispatch_error &e){ - throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'"); + throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'", e.parameters, t_ss); } catch(detail::Return_Value &rv) { return rv.retval; @@ -235,7 +235,7 @@ namespace chaiscript return (*boxed_cast(this->children[0]->eval(t_ss)))(plb); } catch(const exception::dispatch_error &e){ - throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'"); + throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'", e.parameters, t_ss); } catch(detail::Return_Value &rv) { return rv.retval; @@ -294,12 +294,12 @@ namespace chaiscript try { retval = t_ss.call_function(this->children[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 &e){ + throw exception::eval_error("Unable to find appropriate'" + this->children[1]->text + "' operator.", e.parameters, t_ss); } } - catch(const exception::dispatch_error &){ - throw exception::eval_error("Can not clone right hand side of equation"); + catch(const exception::dispatch_error &e){ + throw exception::eval_error("Missing clone or copy constructor for right hand side of equation", e.parameters, t_ss); } } else if (this->children[1]->text == ":=") { @@ -312,8 +312,8 @@ namespace chaiscript else { try { retval = t_ss.call_function(this->children[1]->text, lhs, retval); - } catch(const exception::dispatch_error &){ - throw exception::eval_error("Can not find appropriate '" + this->children[1]->text + "'"); + } catch(const exception::dispatch_error &e){ + throw exception::eval_error("Unable to find appropriate'" + this->children[1]->text + "' operator.", e.parameters, t_ss); } } } @@ -431,8 +431,8 @@ namespace chaiscript catch(std::out_of_range &) { throw exception::eval_error("Out of bounds exception"); } - catch(const exception::dispatch_error &){ - throw exception::eval_error("Can not find appropriate array lookup '[]' "); + catch(const exception::dispatch_error &e){ + throw exception::eval_error("Can not find appropriate array lookup operator '[]'.", e.parameters, t_ss ); } } @@ -475,7 +475,7 @@ namespace chaiscript retval = t_ss.call_function(fun_name, plb); } catch(const exception::dispatch_error &e){ - throw exception::eval_error(std::string(e.what()) + " for function: " + fun_name); + throw exception::eval_error(std::string(e.what()) + " for function: " + fun_name, e.parameters, t_ss); } catch(detail::Return_Value &rv) { retval = rv.retval; @@ -489,8 +489,8 @@ namespace chaiscript catch(std::out_of_range &) { throw exception::eval_error("Out of bounds exception"); } - catch(const exception::dispatch_error &){ - throw exception::eval_error("Can not find appropriate array lookup '[]' "); + catch(const exception::dispatch_error &e){ + throw exception::eval_error("Can not find appropriate array lookup operator '[]'.", e.parameters, t_ss); } } } @@ -908,8 +908,8 @@ namespace chaiscript } return const_var(retval); } - catch (const exception::dispatch_error &) { - throw exception::eval_error("Can not find appropriate 'clone' or copy constructor for map elements"); + catch (const exception::dispatch_error &e) { + throw exception::eval_error("Can not find appropriate copy constructor or 'clone' while inserting into Map.", e.parameters, t_ss); } } @@ -971,8 +971,8 @@ namespace chaiscript fpp.save_params(params); return t_ss.call_function(this->children[0]->text, bv); } - } catch (const exception::dispatch_error &) { - throw exception::eval_error("Error with prefix operator evaluation: " + children[0]->text); + } catch (const exception::dispatch_error &e) { + throw exception::eval_error("Error with prefix operator evaluation: '" + children[0]->text + "'", e.parameters, t_ss); } } @@ -1013,8 +1013,8 @@ namespace chaiscript this->children[0]->children[0]->children[0]->eval(t_ss), this->children[0]->children[0]->children[1]->eval(t_ss)); } - catch (const exception::dispatch_error &) { - throw exception::eval_error("Unable to generate range vector"); + catch (const exception::dispatch_error &e) { + throw exception::eval_error("Unable to generate range vector, while calling 'generate_range'", e.parameters, t_ss); } } diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 3003038..b1258e4 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -1672,7 +1672,7 @@ namespace chaiscript throw exception::eval_error("Incomplete expression", File_Position(m_line, m_col), *m_filename); } if (!Char(')')) { - throw exception::eval_error("Missing closing parenthesis", File_Position(m_line, m_col), *m_filename); + throw exception::eval_error("Missing closing parenthesis ')'", File_Position(m_line, m_col), *m_filename); } } return retval; @@ -1690,7 +1690,7 @@ namespace chaiscript retval = true; Container_Arg_List(); if (!Char(']')) { - throw exception::eval_error("Missing closing square bracket", File_Position(m_line, m_col), *m_filename); + throw exception::eval_error("Missing closing square bracket ']' in container initializer", File_Position(m_line, m_col), *m_filename); } if ((prev_stack_top != m_match_stack.size()) && (m_match_stack.back()->children.size() > 0)) { if (m_match_stack.back()->children[0]->identifier == AST_Node_Type::Value_Range) {