Add more specific exception types to the dynamic system and handle them properly

This commit is contained in:
Jason Turner 2009-06-25 00:03:23 +00:00
parent d8b5847ff6
commit eb5dbe4975
4 changed files with 75 additions and 38 deletions

View File

@ -110,7 +110,7 @@ namespace chaiscript
try { try {
retval = dispatch(ss.get_function(node->children[i+1]->text), plb); retval = dispatch(ss.get_function(node->children[i+1]->text), plb);
} }
catch(std::exception &e){ catch(const dispatchkit::dispatch_error &e){
throw EvalError("Can not find appropriate '" + node->children[i+1]->text + "'", node->children[i+1]); throw EvalError("Can not find appropriate '" + node->children[i+1]->text + "'", node->children[i+1]);
} }
} }
@ -136,7 +136,7 @@ namespace chaiscript
try { try {
retval = dispatch(ss.get_function(node->children[i]->text), plb); retval = dispatch(ss.get_function(node->children[i]->text), plb);
} }
catch(std::exception &e){ catch(const dispatchkit::dispatch_error &e){
throw EvalError("Can not find appropriate '" + node->children[i]->text + "'", node->children[i]); throw EvalError("Can not find appropriate '" + node->children[i]->text + "'", node->children[i]);
} }
} }
@ -155,7 +155,7 @@ namespace chaiscript
catch(std::out_of_range &oor) { catch(std::out_of_range &oor) {
throw EvalError("Out of bounds exception", node); throw EvalError("Out of bounds exception", node);
} }
catch(std::exception &e){ catch(const dispatchkit::dispatch_error &e){
throw EvalError("Can not find appropriate array lookup '[]'", node->children[i]); throw EvalError("Can not find appropriate array lookup '[]'", node->children[i]);
} }
} }
@ -208,12 +208,12 @@ namespace chaiscript
dispatchkit::Boxed_Value tmp = eval_token(ss, node->children[i]); dispatchkit::Boxed_Value tmp = eval_token(ss, node->children[i]);
dispatch(ss.get_function("push_back"), dispatchkit::Param_List_Builder() << retval << tmp); dispatch(ss.get_function("push_back"), dispatchkit::Param_List_Builder() << retval << tmp);
} }
catch (std::exception inner_e) { catch (const dispatchkit::dispatch_error &inner_e) {
throw EvalError("Can not find appropriate 'push_back'", node->children[i]); throw EvalError("Can not find appropriate 'push_back'", node->children[i]);
} }
} }
} }
catch (std::exception e) { catch (const dispatchkit::dispatch_error &e) {
throw EvalError("Can not find appropriate 'Vector()'", node); throw EvalError("Can not find appropriate 'Vector()'", node);
} }
} }
@ -227,12 +227,12 @@ namespace chaiscript
dispatchkit::Boxed_Value slot = dispatch(ss.get_function("[]"), dispatchkit::Param_List_Builder() << retval << key); dispatchkit::Boxed_Value slot = dispatch(ss.get_function("[]"), dispatchkit::Param_List_Builder() << retval << key);
dispatch(ss.get_function("="), dispatchkit::Param_List_Builder() << slot << eval_token(ss, node->children[i]->children[1])); dispatch(ss.get_function("="), dispatchkit::Param_List_Builder() << slot << eval_token(ss, node->children[i]->children[1]));
} }
catch (std::exception inner_e) { catch (const dispatchkit::dispatch_error &inner_e) {
throw EvalError("Can not find appropriate '=' for map init", node->children[i]); throw EvalError("Can not find appropriate '=' for map init", node->children[i]);
} }
} }
} }
catch (std::exception e) { catch (const dispatchkit::dispatch_error &e) {
throw EvalError("Can not find appropriate 'Vector()'", node); throw EvalError("Can not find appropriate 'Vector()'", node);
} }
} }
@ -259,7 +259,7 @@ namespace chaiscript
ss.set_stack(prev_stack); ss.set_stack(prev_stack);
throw EvalError(ee.reason, node->children[0]); throw EvalError(ee.reason, node->children[0]);
} }
catch(std::exception &e){ catch(const dispatchkit::dispatch_error &e){
ss.set_stack(prev_stack); ss.set_stack(prev_stack);
throw EvalError("Engine error: " + std::string(e.what()) + " on '" + node->children[0]->text + "'", node->children[0]); throw EvalError("Engine error: " + std::string(e.what()) + " on '" + node->children[0]->text + "'", node->children[0]);
} }
@ -304,7 +304,7 @@ namespace chaiscript
ss.set_stack(prev_stack); ss.set_stack(prev_stack);
throw EvalError(ee.reason, node); throw EvalError(ee.reason, node);
} }
catch(std::exception &e){ catch(const dispatchkit::dispatch_error &e){
ss.set_stack(prev_stack); ss.set_stack(prev_stack);
throw EvalError("Can not find appropriate '" + fun_name + "'", node); throw EvalError("Can not find appropriate '" + fun_name + "'", node);
} }

View File

@ -351,27 +351,6 @@ namespace dispatchkit
} }
class bad_boxed_value_cast : public std::bad_cast
{
public:
bad_boxed_value_cast(const std::string &val) throw()
: m_val(val)
{
}
virtual ~bad_boxed_value_cast() throw()
{
}
virtual const char * what() const throw()
{
return m_val.c_str();
}
private:
std::string m_val;
};
//Built in to_string operator //Built in to_string operator
@ -420,7 +399,7 @@ namespace dispatchkit
{ {
return (lhs.assign(rhs)); return (lhs.assign(rhs));
} else { } else {
throw bad_boxed_value_cast("boxed_value has a set type alread"); throw bad_boxed_cast("boxed_value has a set type already");
} }
} }

View File

@ -356,10 +356,40 @@ namespace dispatchkit
} }
}; };
class bad_boxed_cast : public std::bad_cast
{
public:
bad_boxed_cast(const Type_Info &t_from, const std::type_info &t_to) throw()
: from(t_from.m_type_info), to(&t_to), m_what("Cannot perform boxed_cast")
{
}
bad_boxed_cast(const std::string &w) throw()
: m_what(w)
{
}
virtual ~bad_boxed_cast() throw() {}
virtual const char * what () throw()
{
return m_what.c_str();
}
const std::type_info *from;
const std::type_info *to;
private:
std::string m_what;
};
template<typename Type> template<typename Type>
typename Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv) typename Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv)
{ {
return Cast_Helper<Type>::cast(bv); try {
return Cast_Helper<Type>::cast(bv);
} catch (const boost::bad_any_cast &) {
throw bad_boxed_cast(bv.get_type_info(), typeid(Type));
}
} }
struct Boxed_POD_Value struct Boxed_POD_Value

View File

@ -13,6 +13,8 @@
#include <string> #include <string>
#include <boost/function.hpp> #include <boost/function.hpp>
#include <boost/bind.hpp> #include <boost/bind.hpp>
#include <boost/lexical_cast.hpp>
#include <stdexcept> #include <stdexcept>
#include <vector> #include <vector>
@ -88,6 +90,20 @@ namespace dispatchkit
std::vector<Boxed_Value> objects; std::vector<Boxed_Value> objects;
}; };
struct arity_error : std::range_error
{
arity_error(int t_got, int t_expected)
: std::range_error("Function dispatch arity mismatch"),
got(t_got), expected(t_expected)
{
}
virtual ~arity_error() throw() {}
int got;
int expected;
};
} }
#define BOOST_PP_ITERATION_LIMITS ( 0, 10 ) #define BOOST_PP_ITERATION_LIMITS ( 0, 10 )
@ -96,6 +112,8 @@ namespace dispatchkit
namespace dispatchkit namespace dispatchkit
{ {
class Proxy_Function class Proxy_Function
{ {
public: public:
@ -126,7 +144,7 @@ namespace dispatchkit
{ {
return m_f(params); return m_f(params);
} else { } else {
throw std::range_error("Incorrect number of parameters"); throw arity_error(params.size(), m_arity);
} }
} }
@ -175,6 +193,16 @@ namespace dispatchkit
Func m_f; Func m_f;
}; };
struct dispatch_error : std::runtime_error
{
dispatch_error() throw()
: std::runtime_error("No matching function to dispatch to")
{
}
virtual ~dispatch_error() throw() {}
};
Boxed_Value dispatch(const std::vector<std::pair<std::string, boost::shared_ptr<Proxy_Function> > > &funcs, Boxed_Value dispatch(const std::vector<std::pair<std::string, boost::shared_ptr<Proxy_Function> > > &funcs,
const std::vector<Boxed_Value> &plist) const std::vector<Boxed_Value> &plist)
{ {
@ -184,14 +212,14 @@ namespace dispatchkit
{ {
try { try {
return (*itr->second)(plist); return (*itr->second)(plist);
} catch (const std::bad_cast &) { } catch (const bad_boxed_cast &) {
//try again //try again
} catch (const std::range_error &) { } catch (const arity_error &) {
//invalid num params, try again //invalid num params, try again
} }
} }
throw std::runtime_error("No matching function to dispatch to"); throw dispatch_error();
} }
} }
@ -210,7 +238,7 @@ namespace dispatchkit
BOOST_PP_REPEAT(n, gettypeinfo, ~) BOOST_PP_REPEAT(n, gettypeinfo, ~)
return ti; return ti;
} }
template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)> template<typename Ret BOOST_PP_COMMA_IF(n) BOOST_PP_ENUM_PARAMS(n, typename Param)>
@ -219,7 +247,7 @@ namespace dispatchkit
{ {
if (params.size() != n) if (params.size() != n)
{ {
throw std::range_error("Incorrect number of parameters"); throw arity_error(params.size(), n);
} else { } else {
return Handle_Return<Ret>()(boost::bind(f BOOST_PP_REPEAT(n, casthelper, ~))); return Handle_Return<Ret>()(boost::bind(f BOOST_PP_REPEAT(n, casthelper, ~)));
} }