Merge branch 'develop' of github.com:ChaiScript/ChaiScript into develop

This commit is contained in:
Jason Turner 2018-02-02 20:22:19 -07:00
commit de4b497de1
8 changed files with 10700 additions and 8478 deletions

View File

@ -170,6 +170,12 @@ endif()
if(MSVC) if(MSVC)
add_definitions(/W4 /w14545 /w34242 /w34254 /w34287 /w44263 /w44265 /w44296 /w44311 /w44826 /we4289 /w14546 /w14547 /w14549 /w14555 /w14619 /w14905 /w14906 /w14928) add_definitions(/W4 /w14545 /w34242 /w34254 /w34287 /w44263 /w44265 /w44296 /w44311 /w44826 /we4289 /w14546 /w14547 /w14549 /w14555 /w14619 /w14905 /w14906 /w14928)
if (BUILD_IN_CPP17_MODE)
add_definitions(/std:c++17)
endif()
if (MSVC_VERSION STREQUAL "1800") if (MSVC_VERSION STREQUAL "1800")
# VS2013 doesn't have magic statics # VS2013 doesn't have magic statics
add_definitions(/w44640) add_definitions(/w44640)
@ -178,7 +184,7 @@ if(MSVC)
add_definitions(/w34062) add_definitions(/w34062)
endif() endif()
add_definitions(/bigobj) add_definitions(/bigobj /permissive-)
# Note on MSVC compiler flags. # Note on MSVC compiler flags.
# The code base selective disables warnings as necessary when the compiler is complaining too much # The code base selective disables warnings as necessary when the compiler is complaining too much
# about something that is perfectly valid, or there is simply no technical way around it # about something that is perfectly valid, or there is simply no technical way around it

View File

@ -170,7 +170,7 @@ namespace chaiscript {
auto parse_num(const char *t_str) -> typename std::enable_if<!std::is_integral<T>::value, T>::type auto parse_num(const char *t_str) -> typename std::enable_if<!std::is_integral<T>::value, T>::type
{ {
T t = 0; T t = 0;
T base; T base{};
T decimal_place = 0; T decimal_place = 0;
int exponent = 0; int exponent = 0;

View File

@ -86,7 +86,7 @@ namespace chaiscript
// only compile this bit if noexcept is part of the type system // only compile this bit if noexcept is part of the type system
// //
#if __cpp_noexcept_function_type >= 201510 #if __cpp_noexcept_function_type >= 201510 || (defined(_NOEXCEPT_TYPES_SUPPORTED) && _MSC_VER >= 1912)
template<typename Ret, typename ... Param> template<typename Ret, typename ... Param>
Proxy_Function fun(Ret (*func)(Param...) noexcept) Proxy_Function fun(Ret (*func)(Param...) noexcept)
{ {

View File

@ -54,8 +54,8 @@
#include "../dispatchkit/exception_specification.hpp" #include "../dispatchkit/exception_specification.hpp"
namespace chaiscript namespace chaiscript
{ {
/// Namespace alias to provide cleaner and more explicit syntax to users. /// Namespace alias to provide cleaner and more explicit syntax to users.
using Namespace = dispatch::Dynamic_Object; using Namespace = dispatch::Dynamic_Object;
namespace detail namespace detail
@ -200,7 +200,7 @@ namespace chaiscript
m_engine.add(fun([this](const Boxed_Value &t_bv, const std::string &t_name){ add_global(t_bv, t_name); }), "add_global"); m_engine.add(fun([this](const Boxed_Value &t_bv, const std::string &t_name){ add_global(t_bv, t_name); }), "add_global");
m_engine.add(fun([this](const Boxed_Value &t_bv, const std::string &t_name){ set_global(t_bv, t_name); }), "set_global"); m_engine.add(fun([this](const Boxed_Value &t_bv, const std::string &t_name){ set_global(t_bv, t_name); }), "set_global");
m_engine.add(fun([this](const std::string& t_namespace_name) { register_namespace([](Namespace& space) {}, t_namespace_name); import(t_namespace_name); }), "namespace"); m_engine.add(fun([this](const std::string& t_namespace_name) { register_namespace([](Namespace& /*space*/) {}, t_namespace_name); import(t_namespace_name); }), "namespace");
m_engine.add(fun([this](const std::string& t_namespace_name) { import(t_namespace_name); }), "import"); m_engine.add(fun([this](const std::string& t_namespace_name) { import(t_namespace_name); }), "import");
} }
@ -711,39 +711,39 @@ explicit ChaiScript_Basic(std::unique_ptr<parser::ChaiScript_Parser_Base> &&pars
return m_engine.boxed_cast<T>(eval_file(t_filename, t_handler)); return m_engine.boxed_cast<T>(eval_file(t_filename, t_handler));
} }
/// \brief Imports a namespace object into the global scope of this ChaiScript instance. /// \brief Imports a namespace object into the global scope of this ChaiScript instance.
/// \param[in] t_namespace_name Name of the namespace to import. /// \param[in] t_namespace_name Name of the namespace to import.
/// \throw std::runtime_error In the case that the namespace name was never registered. /// \throw std::runtime_error In the case that the namespace name was never registered.
void import(const std::string& t_namespace_name) void import(const std::string& t_namespace_name)
{ {
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex); chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex);
if (m_engine.get_scripting_objects().count(t_namespace_name)) { if (m_engine.get_scripting_objects().count(t_namespace_name)) {
throw std::runtime_error("Namespace: " + t_namespace_name + " was already defined"); throw std::runtime_error("Namespace: " + t_namespace_name + " was already defined");
} }
else if (m_namespace_generators.count(t_namespace_name)) { else if (m_namespace_generators.count(t_namespace_name)) {
m_engine.add_global(var(std::ref(m_namespace_generators[t_namespace_name]())), t_namespace_name); m_engine.add_global(var(std::ref(m_namespace_generators[t_namespace_name]())), t_namespace_name);
} }
else { else {
throw std::runtime_error("No registered namespace: " + t_namespace_name); throw std::runtime_error("No registered namespace: " + t_namespace_name);
} }
} }
/// \brief Registers a namespace generator, which delays generation of the namespace until it is imported, saving memory if it is never used. /// \brief Registers a namespace generator, which delays generation of the namespace until it is imported, saving memory if it is never used.
/// \param[in] t_namespace_generator Namespace generator function. /// \param[in] t_namespace_generator Namespace generator function.
/// \param[in] t_namespace_name Name of the Namespace function being registered. /// \param[in] t_namespace_name Name of the Namespace function being registered.
/// \throw std::runtime_error In the case that the namespace name was already registered. /// \throw std::runtime_error In the case that the namespace name was already registered.
void register_namespace(const std::function<void(Namespace&)>& t_namespace_generator, const std::string& t_namespace_name) void register_namespace(const std::function<void(Namespace&)>& t_namespace_generator, const std::string& t_namespace_name)
{ {
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex); chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex);
if (!m_namespace_generators.count(t_namespace_name)) { if (!m_namespace_generators.count(t_namespace_name)) {
// contain the namespace object memory within the m_namespace_generators map // contain the namespace object memory within the m_namespace_generators map
m_namespace_generators.emplace(std::make_pair(t_namespace_name, [=, space = Namespace()]() mutable -> Namespace& { t_namespace_generator(space); return space; })); m_namespace_generators.emplace(std::make_pair(t_namespace_name, [=, space = Namespace()]() mutable -> Namespace& { t_namespace_generator(space); return space; }));
} }
else { else {
throw std::runtime_error("Namespace: " + t_namespace_name + " was already registered."); throw std::runtime_error("Namespace: " + t_namespace_name + " was already registered.");
} }
} }
}; };

View File

@ -327,15 +327,17 @@ namespace chaiscript
Boxed_Value fn(this->children[0]->eval(t_ss)); Boxed_Value fn(this->children[0]->eval(t_ss));
using ConstFunctionTypePtr = const dispatch::Proxy_Function_Base *;
try { try {
return (*t_ss->boxed_cast<const dispatch::Proxy_Function_Base *>(fn))(params, t_ss.conversions()); return (*t_ss->boxed_cast<ConstFunctionTypePtr>(fn))(params, t_ss.conversions());
} }
catch(const exception::dispatch_error &e){ catch(const exception::dispatch_error &e){
throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'", e.parameters, e.functions, false, *t_ss); throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'", e.parameters, e.functions, false, *t_ss);
} }
catch(const exception::bad_boxed_cast &){ catch(const exception::bad_boxed_cast &){
try { try {
Const_Proxy_Function f = t_ss->boxed_cast<const Const_Proxy_Function &>(fn); using ConstFunctionTypeRef = const Const_Proxy_Function &;
Const_Proxy_Function f = t_ss->boxed_cast<ConstFunctionTypeRef>(fn);
// handle the case where there is only 1 function to try to call and dispatch fails on it // handle the case where there is only 1 function to try to call and dispatch fails on it
throw exception::eval_error("Error calling function '" + this->children[0]->text + "'", params, {f}, false, *t_ss); throw exception::eval_error("Error calling function '" + this->children[0]->text + "'", params, {f}, false, *t_ss);
} catch (const exception::bad_boxed_cast &) { } catch (const exception::bad_boxed_cast &) {
@ -756,6 +758,8 @@ namespace chaiscript
std::vector<AST_Node_Impl_Ptr<T>>(std::make_move_iterator(t_children.begin()), std::vector<AST_Node_Impl_Ptr<T>>(std::make_move_iterator(t_children.begin()),
std::make_move_iterator(std::prev(t_children.end(), has_guard(t_children, 1)?2:1))) std::make_move_iterator(std::prev(t_children.end(), has_guard(t_children, 1)?2:1)))
), ),
// This apparent use after move is safe because we are only moving out the specific elements we need
// on each operation.
m_body_node(get_body_node(std::move(t_children))), m_body_node(get_body_node(std::move(t_children))),
m_guard_node(get_guard_node(std::move(t_children), t_children.size()-this->children.size()==2)) m_guard_node(get_guard_node(std::move(t_children), t_children.size()-this->children.size()==2))

View File

@ -142,6 +142,8 @@ namespace chaiscript
// not a dynamic object // not a dynamic object
} }
if (t_bv.is_null()) return json::JSON(); // a null value
throw std::runtime_error("Unknown object type to convert to JSON"); throw std::runtime_error("Unknown object type to convert to JSON");
} }

File diff suppressed because it is too large Load Diff

View File

@ -382,7 +382,7 @@ TEST_CASE("Set and restore chai state")
// set state should have reverted the state of the functions and dropped // set state should have reverted the state of the functions and dropped
// the 'myfun' // the 'myfun'
CHECK_THROWS_AS(chai.eval<int>("myfun()"), chaiscript::exception::eval_error &); CHECK_THROWS_AS(chai.eval<int>("myfun()"), chaiscript::exception::eval_error);
// set state should not affect the local variables // set state should not affect the local variables
CHECK(chai.eval<int>("i") == 1); CHECK(chai.eval<int>("i") == 1);
@ -390,7 +390,7 @@ TEST_CASE("Set and restore chai state")
// After resetting the locals we expect the 'i' to be gone // After resetting the locals we expect the 'i' to be gone
chai.set_locals(locals); chai.set_locals(locals);
CHECK_THROWS_AS(chai.eval<int>("i"), chaiscript::exception::eval_error &); CHECK_THROWS_AS(chai.eval<int>("i"), chaiscript::exception::eval_error);
} }
@ -468,8 +468,8 @@ TEST_CASE("Simultaneous ChaiScript tests")
CHECK(chai.eval<int>("do_something(" + std::to_string(i) + ")") == i + 2); CHECK(chai.eval<int>("do_something(" + std::to_string(i) + ")") == i + 2);
CHECK(chai2.eval<int>("do_something_else(" + std::to_string(i) + ")") == i * 2); CHECK(chai2.eval<int>("do_something_else(" + std::to_string(i) + ")") == i * 2);
CHECK_THROWS_AS(chai2.eval("do_something(1)"), chaiscript::exception::eval_error &); CHECK_THROWS_AS(chai2.eval("do_something(1)"), chaiscript::exception::eval_error);
CHECK_THROWS_AS(chai2.eval("i"), chaiscript::exception::eval_error &); CHECK_THROWS_AS(chai2.eval("i"), chaiscript::exception::eval_error);
CHECK_NOTHROW(chai2.eval("do_something_else(1)")); CHECK_NOTHROW(chai2.eval("do_something_else(1)"));
} }
} }