diff --git a/include/chaiscript/dispatchkit/exception_specification.hpp b/include/chaiscript/dispatchkit/exception_specification.hpp index 0947b9ac..79607fe2 100644 --- a/include/chaiscript/dispatchkit/exception_specification.hpp +++ b/include/chaiscript/dispatchkit/exception_specification.hpp @@ -25,36 +25,26 @@ class bad_boxed_cast; namespace chaiscript { - namespace detail { - struct Exception_Handler + struct Exception_Handler_Base { - virtual void operator()(const Boxed_Value &, const detail::Dispatch_Engine &) const - { - } + virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) = 0; - Exception_Handler() = default; - Exception_Handler(Exception_Handler &&) = default; - Exception_Handler &operator=(Exception_Handler &&) = default; - virtual ~Exception_Handler() noexcept = default; + virtual ~Exception_Handler_Base() = default; protected: - Exception_Handler(const Exception_Handler &) = default; - Exception_Handler &operator=(const Exception_Handler &) = default; - - }; - - template - struct Exception_Handler_Impl final : Exception_Handler - { - template + template static void throw_type(const Boxed_Value &bv, const Dispatch_Engine &t_engine) { - try { throw t_engine.boxed_cast(bv); } catch (const chaiscript::exception::bad_boxed_cast &) {} + try { T t = t_engine.boxed_cast(bv); throw t; } catch (const chaiscript::exception::bad_boxed_cast &) {} } + }; - void operator()(const Boxed_Value &bv, const Dispatch_Engine &t_engine) const final + template + struct Exception_Handler_Impl : Exception_Handler_Base + { + void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) override { (void)std::initializer_list{(throw_type(bv, t_engine), 0)...}; } @@ -111,13 +101,14 @@ namespace chaiscript /// /// \sa chaiscript::exception_specification for creation of chaiscript::Exception_Handler objects /// \sa \ref exceptions + typedef std::shared_ptr Exception_Handler; /// \brief creates a chaiscript::Exception_Handler which handles one type of exception unboxing /// \sa \ref exceptions template - auto exception_specification() noexcept + Exception_Handler exception_specification() { - return detail::Exception_Handler_Impl(); + return std::make_shared>(); } } diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index c88fe10e..11506f58 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -623,12 +623,12 @@ explicit ChaiScript_Basic(std::unique_ptr &&pars /// \brief Evaluates a string. Equivalent to ChaiScript::eval. /// /// \param[in] t_script Script to execute - /// \param[in] t_handler Optional detail::Exception_Handler used for automatic unboxing of script thrown exceptions + /// \param[in] t_handler Optional Exception_Handler used for automatic unboxing of script thrown exceptions /// /// \return result of the script execution /// /// \throw chaiscript::exception::eval_error In the case that evaluation fails. - Boxed_Value operator()(const std::string &t_script, const detail::Exception_Handler &t_handler = detail::Exception_Handler()) + Boxed_Value operator()(const std::string &t_script, const Exception_Handler &t_handler = Exception_Handler()) { return eval(t_script, t_handler); } @@ -637,7 +637,7 @@ explicit ChaiScript_Basic(std::unique_ptr &&pars /// /// \tparam T Type to extract from the result value of the script execution /// \param[in] t_input Script to execute - /// \param[in] t_handler Optional detail::Exception_Handler used for automatic unboxing of script thrown exceptions + /// \param[in] t_handler Optional Exception_Handler used for automatic unboxing of script thrown exceptions /// \param[in] t_filename Optional filename to report to the user for where the error occured. Useful /// in special cases where you are loading a file internally instead of using eval_file /// @@ -647,7 +647,7 @@ explicit ChaiScript_Basic(std::unique_ptr &&pars /// \throw chaiscript::exception::bad_boxed_cast In the case that evaluation succeeds but the result value cannot be converted /// to the requested type. template - T eval(const std::string &t_input, const detail::Exception_Handler &t_handler = detail::Exception_Handler(), const std::string &t_filename="__EVAL__") + T eval(const std::string &t_input, const Exception_Handler &t_handler = Exception_Handler(), const std::string &t_filename="__EVAL__") { return m_engine.boxed_cast(eval(t_input, t_handler, t_filename)); } @@ -663,42 +663,44 @@ explicit ChaiScript_Basic(std::unique_ptr &&pars /// \brief Evaluates a string. /// /// \param[in] t_input Script to execute - /// \param[in] t_handler Optional detail::Exception_Handler used for automatic unboxing of script thrown exceptions + /// \param[in] t_handler Optional Exception_Handler used for automatic unboxing of script thrown exceptions /// \param[in] t_filename Optional filename to report to the user for where the error occurred. Useful /// in special cases where you are loading a file internally instead of using eval_file /// /// \return result of the script execution /// /// \throw exception::eval_error In the case that evaluation fails. - Boxed_Value eval(const std::string &t_input, const detail::Exception_Handler &t_handler = detail::Exception_Handler(), const std::string &t_filename="__EVAL__") + Boxed_Value eval(const std::string &t_input, const Exception_Handler &t_handler = Exception_Handler(), const std::string &t_filename="__EVAL__") { try { return do_eval(t_input, t_filename); } catch (Boxed_Value &bv) { - t_handler(bv, m_engine); + if (t_handler) { + t_handler->handle(bv, m_engine); + } throw; } } /// \brief Loads the file specified by filename, evaluates it, and returns the result. /// \param[in] t_filename File to load and parse. - /// \param[in] t_handler Optional detail::Exception_Handler used for automatic unboxing of script thrown exceptions + /// \param[in] t_handler Optional Exception_Handler used for automatic unboxing of script thrown exceptions /// \return result of the script execution /// \throw chaiscript::exception::eval_error In the case that evaluation fails. - Boxed_Value eval_file(const std::string &t_filename, const detail::Exception_Handler &t_handler = detail::Exception_Handler()) { + Boxed_Value eval_file(const std::string &t_filename, const Exception_Handler &t_handler = Exception_Handler()) { return eval(load_file(t_filename), t_handler, t_filename); } /// \brief Loads the file specified by filename, evaluates it, and returns the type safe result. /// \tparam T Type to extract from the result value of the script execution /// \param[in] t_filename File to load and parse. - /// \param[in] t_handler Optional detail::Exception_Handler used for automatic unboxing of script thrown exceptions + /// \param[in] t_handler Optional Exception_Handler used for automatic unboxing of script thrown exceptions /// \return result of the script execution /// \throw chaiscript::exception::eval_error In the case that evaluation fails. /// \throw chaiscript::exception::bad_boxed_cast In the case that evaluation succeeds but the result value cannot be converted /// to the requested type. template - T eval_file(const std::string &t_filename, const detail::Exception_Handler &t_handler = detail::Exception_Handler()) { + T eval_file(const std::string &t_filename, const Exception_Handler &t_handler = Exception_Handler()) { return m_engine.boxed_cast(eval_file(t_filename, t_handler)); } };