From ce62706fea8ed88519f021c60eb09d75adeb7ef6 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 6 Dec 2016 10:31:36 -0700 Subject: [PATCH 01/84] Clean up warnings * msvc * pvs-studio --- include/chaiscript/dispatchkit/boxed_value.hpp | 5 +++-- .../language/chaiscript_algebraic.hpp | 9 +++++++++ .../chaiscript/language/chaiscript_eval.hpp | 4 ++-- .../chaiscript/language/chaiscript_parser.hpp | 10 ++++++++++ include/chaiscript/utility/fnv1a.hpp | 18 ++++++++++++++++++ 5 files changed, 42 insertions(+), 4 deletions(-) diff --git a/include/chaiscript/dispatchkit/boxed_value.hpp b/include/chaiscript/dispatchkit/boxed_value.hpp index e6c669bd..c2cd20e3 100644 --- a/include/chaiscript/dispatchkit/boxed_value.hpp +++ b/include/chaiscript/dispatchkit/boxed_value.hpp @@ -251,8 +251,9 @@ namespace chaiscript ~Sentinel() { // save new pointer data - m_data.get().m_data_ptr = m_ptr.get().get(); - m_data.get().m_const_data_ptr = m_ptr.get().get(); + const auto ptr = m_ptr.get().get(); + m_data.get().m_data_ptr = ptr; + m_data.get().m_const_data_ptr = ptr; } Sentinel& operator=(Sentinel&&s) = default; diff --git a/include/chaiscript/language/chaiscript_algebraic.hpp b/include/chaiscript/language/chaiscript_algebraic.hpp index 36516dda..022a295c 100644 --- a/include/chaiscript/language/chaiscript_algebraic.hpp +++ b/include/chaiscript/language/chaiscript_algebraic.hpp @@ -53,6 +53,11 @@ namespace chaiscript static Opers to_operator(const std::string &t_str, bool t_is_unary = false) { +#ifdef CHAISCRIPT_MSVC +#pragma warning(push) +#pragma warning(disable : 4307) +#endif + const auto op_hash = utility::fnv1a_32(t_str.c_str()); switch (op_hash) { case utility::fnv1a_32("=="): { return Opers::equals; } @@ -86,6 +91,10 @@ namespace chaiscript case utility::fnv1a_32("*"): { return Opers::product; } default: { return Opers::invalid; } } +#ifdef CHAISCRIPT_MSVC +#pragma warning(pop) +#endif + } }; diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index adc86ed4..20325a5f 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -433,13 +433,13 @@ namespace chaiscript try { if (lhs.is_undef()) { - if ((!this->children.empty() + if (!this->children.empty() && ((this->children[0]->identifier == AST_Node_Type::Reference) || (!this->children[0]->children.empty() && this->children[0]->children[0]->identifier == AST_Node_Type::Reference) ) - ) ) + { /// \todo This does not handle the case of an unassigned reference variable /// being assigned outside of its declaration diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index a4199a35..18c42200 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -884,6 +884,11 @@ namespace chaiscript validate_object_name(text); } +#ifdef CHAISCRIPT_MSVC +#pragma warning(push) +#pragma warning(disable : 4307) +#endif + switch (text_hash) { case utility::fnv1a_32("true"): { m_match_stack.push_back(make_node>(std::move(text), start.line, start.col, const_var(true))); @@ -948,6 +953,11 @@ namespace chaiscript } break; } +#ifdef CHAISCRIPT_MSVC +#pragma warning(pop) +#endif + + return true; } else { return false; diff --git a/include/chaiscript/utility/fnv1a.hpp b/include/chaiscript/utility/fnv1a.hpp index fcf9b1e9..54378cd1 100644 --- a/include/chaiscript/utility/fnv1a.hpp +++ b/include/chaiscript/utility/fnv1a.hpp @@ -7,16 +7,34 @@ #ifndef CHAISCRIPT_UTILITY_FNV1A_HPP_ #define CHAISCRIPT_UTILITY_FNV1A_HPP_ + #include +#include "../chaiscript_defines.hpp" + namespace chaiscript { + + namespace utility { + + static constexpr std::uint32_t fnv1a_32(const char *s, std::uint32_t h = 0x811c9dc5) { +#ifdef CHAISCRIPT_MSVC +#pragma warning(push) +#pragma warning(disable : 4307) +#endif return (*s == 0) ? h : fnv1a_32(s+1, ((h ^ (*s)) * 0x01000193)); +#ifdef CHAISCRIPT_MSVC +#pragma warning(pop) +#endif } + + } + + } #endif From cee57f998a44d3c833b3c7bde66f42ed5b8b5f78 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 6 Dec 2016 13:05:17 -0700 Subject: [PATCH 02/84] Allow conversions while calling chaiscript funcs * This puts ChaiScript funcs more on even footings with C++ defined funcs * Minor performance hit (0.5%) --- .../dispatchkit/proxy_functions.hpp | 98 ++++++++++++++++--- .../dispatchkit/type_conversions.hpp | 35 ++++--- .../chaiscript/language/chaiscript_eval.hpp | 2 +- 3 files changed, 110 insertions(+), 25 deletions(-) diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index 3b1b9fd1..218ba807 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -72,10 +72,51 @@ namespace chaiscript return m_types == t_rhs.m_types; } - bool match(const std::vector &vals, const Type_Conversions_State &t_conversions) const + std::vector convert(std::vector vals, const Type_Conversions_State &t_conversions) const { - if (!m_has_types) { return true; } - if (vals.size() != m_types.size()) { return false; } + for (size_t i = 0; i < vals.size(); ++i) + { + const auto &name = m_types[i].first; + if (!name.empty()) { + const auto &bv = vals[i]; + + if (!bv.get_type_info().bare_equal(m_doti)) + { + const auto &ti = m_types[i].second; + if (!ti.is_undef()) + { + if (!bv.get_type_info().bare_equal(ti)) { + if (t_conversions->converts(ti, bv.get_type_info())) { + try { + // We will not catch any bad_boxed_dynamic_cast that is thrown, let the user get it + // either way, we are not responsible if it doesn't work + vals[i] = t_conversions->boxed_type_conversion(m_types[i].second, t_conversions.saves(), vals[i]); + } catch (...) { + try { + // try going the other way + vals[i] = t_conversions->boxed_type_down_conversion(m_types[i].second, t_conversions.saves(), vals[i]); + } catch (const chaiscript::detail::exception::bad_any_cast &) { + throw exception::bad_boxed_cast(bv.get_type_info(), *m_types[i].second.bare_type_info()); + } + } + } + } + } + } + } + } + + return vals; + } + + // first result: is a match + // second result: needs conversions + std::pair match(const std::vector &vals, const Type_Conversions_State &t_conversions) const + { + bool needs_conversion = false; + + if (!m_has_types) { return std::make_pair(true, needs_conversion); } + if (vals.size() != m_types.size()) { return std::make_pair(false, needs_conversion); } for (size_t i = 0; i < vals.size(); ++i) { @@ -87,25 +128,31 @@ namespace chaiscript { try { const Dynamic_Object &d = boxed_cast(bv, &t_conversions); - return name == "Dynamic_Object" || d.get_type_name() == name; + if (!(name == "Dynamic_Object" || d.get_type_name() == name)) { + return std::make_pair(false, false); + } } catch (const std::bad_cast &) { - return false; + return std::make_pair(false, false); } } else { const auto &ti = m_types[i].second; if (!ti.is_undef()) { if (!bv.get_type_info().bare_equal(ti)) { - return false; + if (!t_conversions->converts(ti, bv.get_type_info())) { + return std::make_pair(false, false); + } else { + needs_conversion = true; + } } } else { - return false; + return std::make_pair(false, false); } } } } - return true; + return std::make_pair(true, needs_conversion); } const std::vector> &types() const @@ -320,8 +367,7 @@ namespace chaiscript bool call_match(const std::vector &vals, const Type_Conversions_State &t_conversions) const override { - return (m_arity < 0 || (vals.size() == size_t(m_arity) && m_param_types.match(vals, t_conversions))) - && test_guard(vals, t_conversions); + return call_match_internal(vals, t_conversions).first; } @@ -353,6 +399,26 @@ namespace chaiscript } } + // first result: is a match + // second result: needs conversions + std::pair call_match_internal(const std::vector &vals, const Type_Conversions_State &t_conversions) const + { + const auto comparison_result = [&](){ + if (m_arity < 0) { + return std::make_pair(true, false); + } else if (vals.size() == size_t(m_arity)) { + return m_param_types.match(vals, t_conversions); + } else { + return std::make_pair(false, false); + } + }(); + + return std::make_pair( + comparison_result.first && test_guard(vals, t_conversions), + comparison_result.second + ); + } + private: static std::vector build_param_type_list(const Param_Types &t_types) { @@ -371,7 +437,10 @@ namespace chaiscript return types; } + protected: Param_Types m_param_types; + + private: Proxy_Function m_guard; AST_NodePtr m_parsenode; }; @@ -402,9 +471,14 @@ namespace chaiscript protected: Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override { - if (call_match(params, t_conversions) && test_guard(params, t_conversions)) + const auto match_results = call_match_internal(params, t_conversions); + if (match_results.first) { - return m_f(params); + if (match_results.second) { + return m_f(m_param_types.convert(params, t_conversions)); + } else { + return m_f(params); + } } else { throw exception::guard_error(); } diff --git a/include/chaiscript/dispatchkit/type_conversions.hpp b/include/chaiscript/dispatchkit/type_conversions.hpp index 273544f2..3a546c67 100644 --- a/include/chaiscript/dispatchkit/type_conversions.hpp +++ b/include/chaiscript/dispatchkit/type_conversions.hpp @@ -397,28 +397,39 @@ namespace chaiscript template Boxed_Value boxed_type_conversion(Conversion_Saves &t_saves, const Boxed_Value &from) const { - try { - Boxed_Value ret = get_conversion(user_type(), from.get_type_info())->convert(from); - if (t_saves.enabled) { t_saves.saves.push_back(ret); } - return ret; - } catch (const std::out_of_range &) { - throw exception::bad_boxed_dynamic_cast(from.get_type_info(), typeid(To), "No known conversion"); - } catch (const std::bad_cast &) { - throw exception::bad_boxed_dynamic_cast(from.get_type_info(), typeid(To), "Unable to perform dynamic_cast operation"); - } + return boxed_type_conversion(user_type(), t_saves, from); } template Boxed_Value boxed_type_down_conversion(Conversion_Saves &t_saves, const Boxed_Value &to) const + { + return boxed_type_down_conversion(user_type(), t_saves, to); + } + + + Boxed_Value boxed_type_conversion(const Type_Info &to, Conversion_Saves &t_saves, const Boxed_Value &from) const { try { - Boxed_Value ret = get_conversion(to.get_type_info(), user_type())->convert_down(to); + Boxed_Value ret = get_conversion(to, from.get_type_info())->convert(from); if (t_saves.enabled) { t_saves.saves.push_back(ret); } return ret; } catch (const std::out_of_range &) { - throw exception::bad_boxed_dynamic_cast(to.get_type_info(), typeid(From), "No known conversion"); + throw exception::bad_boxed_dynamic_cast(from.get_type_info(), *to.bare_type_info(), "No known conversion"); } catch (const std::bad_cast &) { - throw exception::bad_boxed_dynamic_cast(to.get_type_info(), typeid(From), "Unable to perform dynamic_cast operation"); + throw exception::bad_boxed_dynamic_cast(from.get_type_info(), *to.bare_type_info(), "Unable to perform dynamic_cast operation"); + } + } + + Boxed_Value boxed_type_down_conversion(const Type_Info &from, Conversion_Saves &t_saves, const Boxed_Value &to) const + { + try { + Boxed_Value ret = get_conversion(to.get_type_info(), from)->convert_down(to); + if (t_saves.enabled) { t_saves.saves.push_back(ret); } + return ret; + } catch (const std::out_of_range &) { + throw exception::bad_boxed_dynamic_cast(to.get_type_info(), *from.bare_type_info(), "No known conversion"); + } catch (const std::bad_cast &) { + throw exception::bad_boxed_dynamic_cast(to.get_type_info(), *from.bare_type_info(), "Unable to perform dynamic_cast operation"); } } diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index adc86ed4..8116c835 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -1226,7 +1226,7 @@ namespace chaiscript if (dispatch::Param_Types( std::vector>{Arg_List_AST_Node::get_arg_type(catch_block->children[0], t_ss)} - ).match(std::vector{t_except}, t_ss.conversions())) + ).match(std::vector{t_except}, t_ss.conversions()).first) { t_ss.add_object(name, t_except); From f79de06e0b774a723195d8c3e3910ef0c7325393 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 6 Dec 2016 13:42:58 -0700 Subject: [PATCH 03/84] Change comment format --- include/chaiscript/dispatchkit/proxy_functions.hpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index 218ba807..67b94c06 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -917,11 +917,9 @@ namespace chaiscript } } - /** - * Take a vector of functions and a vector of parameters. Attempt to execute - * each function against the set of parameters, in order, until a matching - * function is found or throw dispatch_error if no matching function is found - */ + /// Take a vector of functions and a vector of parameters. Attempt to execute + /// each function against the set of parameters, in order, until a matching + /// function is found or throw dispatch_error if no matching function is found template Boxed_Value dispatch(const Funcs &funcs, const std::vector &plist, const Type_Conversions_State &t_conversions) From cf89bdd804b3f416d6b3164d62d95011e8662525 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 6 Dec 2016 14:15:39 -0700 Subject: [PATCH 04/84] Update release notes, add chai type fun conversion test --- releasenotes.md | 1 + unittests/compiled_tests.cpp | 57 ++++++++++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/releasenotes.md b/releasenotes.md index 4300bd12..5f4f3eb1 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -31,6 +31,7 @@ Current Version: 6.0.0 * Support for passing r-value references to functions * Support for containing unique_ptr * Add helpers for exposing enum classes to ChaiScript +* Allow typed ChaiScript defined functions to perform conversions on call #303 #### Improvements diff --git a/unittests/compiled_tests.cpp b/unittests/compiled_tests.cpp index 39ee06e4..86227dbc 100644 --- a/unittests/compiled_tests.cpp +++ b/unittests/compiled_tests.cpp @@ -1129,3 +1129,60 @@ TEST_CASE("Use unique_ptr") } +class A +{ + public: + A() = default; + A(const A&) = default; + A(A &&) = default; + A &operator=(const A&) = default; + A &operator=(A&&) = default; + virtual ~A() = default; +}; + +class B : public A +{ + public: + B() = default; +}; + +TEST_CASE("Test typed chaiscript functions to perform conversions") +{ + chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser()); + + //------------------------------------------------------------------------- + + chai.add(chaiscript::user_type(), "A"); + + chai.add(chaiscript::user_type(), "B"); + chai.add(chaiscript::base_class()); + + chai.add(chaiscript::fun([](const B &) + { + }), "CppFunctWithBArg"); + + chai.add(chaiscript::fun([]() -> std::shared_ptr + { + return (std::shared_ptr(new B())); + }), "Create"); + + chai.eval(R"( + var inst = Create() // A* + + // it prints "A" + inst.type_name().print() + + // Ok it is casted using conversion + CppFunctWithBArg(inst) + + // Define a function with B as argument + def ChaiFuncWithBArg(B inst) + { + print("ok") + } + + // don't work + ChaiFuncWithBArg(inst) + )"); +} + From 624c7c435b46581661df9902cf742774f0713e65 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 6 Dec 2016 14:22:12 -0700 Subject: [PATCH 05/84] Add unit test for #302 --- unittests/compiled_tests.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/unittests/compiled_tests.cpp b/unittests/compiled_tests.cpp index 86227dbc..74868140 100644 --- a/unittests/compiled_tests.cpp +++ b/unittests/compiled_tests.cpp @@ -1186,3 +1186,16 @@ TEST_CASE("Test typed chaiscript functions to perform conversions") )"); } +struct Reference_MyClass +{ + Reference_MyClass(double& t_x) : x(t_x) {} + double& x; +}; + +TEST_CASE("Test reference member being registered") +{ + chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser()); + chai.add(chaiscript::fun(&Reference_MyClass::x) , "x"); +} + + From 51663df1bae3552032f71dc5fa268b6f3ae72f87 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 6 Dec 2016 14:51:00 -0700 Subject: [PATCH 06/84] Demonstrate workaround for pointer to ref member closes #302 --- unittests/compiled_tests.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/unittests/compiled_tests.cpp b/unittests/compiled_tests.cpp index 74868140..9d75519e 100644 --- a/unittests/compiled_tests.cpp +++ b/unittests/compiled_tests.cpp @@ -1195,7 +1195,14 @@ struct Reference_MyClass TEST_CASE("Test reference member being registered") { chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser()); - chai.add(chaiscript::fun(&Reference_MyClass::x) , "x"); + // Note, C++ will not allow us to do this: + // chai.add(chaiscript::fun(&Reference_MyClass::x) , "x"); + chai.add(chaiscript::fun([](Reference_MyClass &r) -> decltype(auto) { return (r.x); }), "x"); + chai.add(chaiscript::fun([](const Reference_MyClass &r) -> decltype(auto) { return (r.x); }), "x"); + double d; + chai.add(chaiscript::var(Reference_MyClass(d)), "ref"); + chai.eval("ref.x = 2.3"); + CHECK(d == 2.3); } From 9c59600b9fa39699c754ca94ead28732d36ba87c Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 27 Dec 2016 15:23:58 -0700 Subject: [PATCH 07/84] Add OSX to OS matrix --- .travis.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.travis.yml b/.travis.yml index f3db01df..3f815249 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,4 +1,9 @@ language: cpp + +os: + - linux + - osx + compiler: - gcc env: From 2431362e542a42b101425cd21fd3f3e43596027b Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 27 Dec 2016 15:50:53 -0700 Subject: [PATCH 08/84] Simplify OS types for travis --- .travis.yml | 50 +++++++++++++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/.travis.yml b/.travis.yml index 3f815249..fec0442b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,16 +1,33 @@ language: cpp -os: - - linux - - osx - -compiler: - - gcc -env: - matrix: - - GCC_VER="4.9" - - GCC_VER="5" +addons: + apt: + sources: + - ubuntu-toolchain-r-test + packages: + - g++-4.9 + - g++-5 + +matrix: + include: + - os: linux + sudo: required + env: GCC_VER="4.9" + compiler: gcc + - os: linux + sudo: required + env: + - GCC_VER="5" + - CPPCHECK=1 + - COVERAGE=1 + - FUZZY_CMD="-D RUN_FUZZY_TESTS:BOOL=TRUE" + compiler: gcc + - os: osx + compiler: clang + + +env: global: - secure: eiaR6pXiiEpyB8+LLQ1NvZdl0Yylru1BLy9lMoHl+IpUNGGQGywmW/2WAn77rFfmR1OPA2qWQLfgPwgK0HxUA9HHlot9tre5QhiN2Lw8NOT8tCZ6tTm2+QntDBjBGJyal/knRvQkn/6qs6GxlXRerz4ArnnuPL1vESt3zwB0YtU= # The next declaration is the encrypted COVERITY_SCAN_TOKEN, created @@ -18,17 +35,12 @@ env: before_install: - export CXX="g++-$GCC_VER" CC="gcc-$GCC_VER" GCOV="gcov-$GCC_VER" - - if [ "$GCC_VER" = "5" ]; then export COVERAGE=1 CPPCHECK=1; fi - - if [ ${COVERAGE} = 1 ]; then export FUZZY_CMD="-D RUN_FUZZY_TESTS:BOOL=TRUE"; fi - - sudo pip install cpp-coveralls - - sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y - - sudo apt-get update - - sudo apt-get install -qq g++-$GCC_VER + - pip install --user cpp-coveralls script: - - if [ ${COVERITY_SCAN_BRANCH} != 1 ]; then cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug $FUZZY_CMD . ; fi - - if [ ${COVERITY_SCAN_BRANCH} != 1 ]; then make -j2 ; fi - - make test + - cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug $FUZZY_CMD . + - cmake --build . -- -j2 + - ctest - if [ ${COVERAGE} = 1 ]; then bash <(curl -s https://raw.githubusercontent.com/codecov/codecov-bash/master/codecov) -x $GCOV -a "-s `pwd`" ; fi after_script: From 037335a0eaec65a9b977f3e0140a9e6ef977b0f7 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 27 Dec 2016 16:02:55 -0700 Subject: [PATCH 09/84] Don't require sudu on linux for travis.yml --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index fec0442b..797d91dd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -12,11 +12,11 @@ addons: matrix: include: - os: linux - sudo: required + sudo: false env: GCC_VER="4.9" compiler: gcc - os: linux - sudo: required + sudo: false env: - GCC_VER="5" - CPPCHECK=1 @@ -34,7 +34,7 @@ env: - secure: "LfolGjP8tWm3yAwthfu3yp8Zn40aueFae580UUR34gusG87cyglq2tQDtxdy+63gWEeNfArbv9n5rZv+bDW3ggHyPjuCKKc1PlZAy07lfXUXf1uz+SFhNvNoYTn3mQG3VZ08o116p4Le2p8yqu4bylJ8wckEq7PrTwvSGVQWTWM=" before_install: - - export CXX="g++-$GCC_VER" CC="gcc-$GCC_VER" GCOV="gcov-$GCC_VER" + - if [ "${GCC_VER}" != "" ]; then export CXX="g++-$GCC_VER" CC="gcc-$GCC_VER" GCOV="gcov-$GCC_VER" ; fi - pip install --user cpp-coveralls script: From 89f373d21c3c09c97db9a8341f3c32a724043421 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 27 Dec 2016 16:10:08 -0700 Subject: [PATCH 10/84] Clean up ENV and addons --- .travis.yml | 27 ++++++++++----------------- 1 file changed, 10 insertions(+), 17 deletions(-) diff --git a/.travis.yml b/.travis.yml index 797d91dd..58edb5f1 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,6 +8,14 @@ addons: packages: - g++-4.9 - g++-5 + coverity_scan: + project: + name: "ChaiScript/ChaiScript" + description: "Build submitted via Travis CI" + notification_email: jason@emptycrate.com + build_command_prepend: "cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug . " + build_command: "cmake --build . -- -j2" + branch_pattern: coverity_scan matrix: include: @@ -17,11 +25,7 @@ matrix: compiler: gcc - os: linux sudo: false - env: - - GCC_VER="5" - - CPPCHECK=1 - - COVERAGE=1 - - FUZZY_CMD="-D RUN_FUZZY_TESTS:BOOL=TRUE" + env: GCC_VER="5" compiler: gcc - os: osx compiler: clang @@ -35,6 +39,7 @@ env: before_install: - if [ "${GCC_VER}" != "" ]; then export CXX="g++-$GCC_VER" CC="gcc-$GCC_VER" GCOV="gcov-$GCC_VER" ; fi + - if [ "${GCC_VER}" == "5" ]; then export CPPCHECK=1 COVERAGE=1 FUZZY_CMD="-D RUN_FUZZY_TESTS:BOOL=TRUE" ; fi - pip install --user cpp-coveralls script: @@ -59,15 +64,3 @@ notifications: on_success: change # options: [always|never|change] default: always on_failure: always # options: [always|never|change] default: always on_start: false # default: false - -addons: - coverity_scan: - project: - name: "ChaiScript/ChaiScript" - description: "Build submitted via Travis CI" - notification_email: jason@emptycrate.com - build_command_prepend: "cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug . " - build_command: "cmake --build . -- -j2" - branch_pattern: coverity_scan - - From 7a588ed5cf54bc3890497111c99bab128dbf4178 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 27 Dec 2016 17:56:10 -0700 Subject: [PATCH 11/84] Disable cppcheck runs --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 58edb5f1..5aee8f05 100644 --- a/.travis.yml +++ b/.travis.yml @@ -48,8 +48,8 @@ script: - ctest - if [ ${COVERAGE} = 1 ]; then bash <(curl -s https://raw.githubusercontent.com/codecov/codecov-bash/master/codecov) -x $GCOV -a "-s `pwd`" ; fi -after_script: - - if [ ${CPPCHECK} = 1 ]; then contrib/codeanalysis/runcppcheck.sh ; fi +#after_script: +# - if [ ${CPPCHECK} = 1 ]; then contrib/codeanalysis/runcppcheck.sh ; fi notifications: From 574f4a9664a1c599d7c1e59f4d94563012e8604e Mon Sep 17 00:00:00 2001 From: Sam Twidale Date: Mon, 9 Jan 2017 18:38:19 +0000 Subject: [PATCH 12/84] Add double stringize trick so _MSC_FULL_VER macro gets expanded This fixes CHAISCRIPT_COMPILER_VERSION, so it gets the compiler version number instead of the string "_MSC_FULL_VER". This means, for example, build ids read like msvc-190023918-Debug, not msvc-_MSC_FULL_VER-Debug. --- include/chaiscript/chaiscript_defines.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/chaiscript/chaiscript_defines.hpp b/include/chaiscript/chaiscript_defines.hpp index 0a76a822..7e016990 100644 --- a/include/chaiscript/chaiscript_defines.hpp +++ b/include/chaiscript/chaiscript_defines.hpp @@ -9,7 +9,8 @@ #ifdef _MSC_VER #define CHAISCRIPT_STRINGIZE(x) "" #x -#define CHAISCRIPT_COMPILER_VERSION CHAISCRIPT_STRINGIZE(_MSC_FULL_VER) +#define CHAISCRIPT_STRINGIZE_EXPANDED(x) CHAISCRIPT_STRINGIZE(x) +#define CHAISCRIPT_COMPILER_VERSION CHAISCRIPT_STRINGIZE_EXPANDED(_MSC_FULL_VER) #define CHAISCRIPT_MSVC _MSC_VER #define CHAISCRIPT_HAS_DECLSPEC From c54d84fae69a8e87c66247dc9850b3e69f8deff6 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 31 Jan 2017 10:11:28 -0800 Subject: [PATCH 13/84] Don't force compiler when building cppcheck --- contrib/codeanalysis/runcppcheck.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/codeanalysis/runcppcheck.sh b/contrib/codeanalysis/runcppcheck.sh index 54e9a823..999118e1 100755 --- a/contrib/codeanalysis/runcppcheck.sh +++ b/contrib/codeanalysis/runcppcheck.sh @@ -4,7 +4,7 @@ pushd .. wget http://sourceforge.net/projects/cppcheck/files/cppcheck/1.66/cppcheck-1.66.tar.bz2 tar -xvf cppcheck-1.66.tar.bz2 cd cppcheck-1.66 -CXX=g++-4.8 make -j2 +make -j2 popd ../cppcheck-1.66/cppcheck --enable=all -I include --inline-suppr --suppress=missingIncludeSystem --std=c++11 --platform=unix64 src/main.cpp src/chai*.cpp --template ' - __{severity}__: [{file}:{line}](../blob/TRAVIS_COMMIT/{file}#L{line}) {message} ({id})' 2>output sed -i "s/TRAVIS_COMMIT/${TRAVIS_COMMIT}/g" output From 94fb7c2453dd48aedddacede7211b8537b29eb3e Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 31 Jan 2017 13:24:53 -0800 Subject: [PATCH 14/84] Add test for explicitly capturing "this" --- unittests/explicit_this_capture.chai | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 unittests/explicit_this_capture.chai diff --git a/unittests/explicit_this_capture.chai b/unittests/explicit_this_capture.chai new file mode 100644 index 00000000..ca46a075 --- /dev/null +++ b/unittests/explicit_this_capture.chai @@ -0,0 +1,26 @@ +class Test +{ + def Test() + {} + + def a(Function f) + { + f("test"); +// f(); + } + + def b() + { + var l = fun [this](x) { this.thing(); } + this.a(l) + } + + def thing() + { + print("hello world"); + } +} +var t = Test() +t.b() + + From ca87c05cd46a93c4f1aed1fbc40b609bcc0eeb37 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 31 Jan 2017 13:25:26 -0800 Subject: [PATCH 15/84] Don't add 'this' if it was explicitly captured --- .../chaiscript/language/chaiscript_eval.hpp | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index a0441559..f2ab7918 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -49,7 +49,7 @@ namespace chaiscript { /// Helper function that will set up the scope around a function call, including handling the named function parameters template - static Boxed_Value eval_function(chaiscript::detail::Dispatch_Engine &t_ss, const AST_Node_Impl_Ptr &t_node, const std::vector &t_param_names, const std::vector &t_vals, const std::map *t_locals=nullptr) { + static Boxed_Value eval_function(chaiscript::detail::Dispatch_Engine &t_ss, const AST_Node_Impl_Ptr &t_node, const std::vector &t_param_names, const std::vector &t_vals, const std::map *t_locals=nullptr, bool has_this_capture = false) { chaiscript::detail::Dispatch_State state(t_ss); const Boxed_Value *thisobj = [&]() -> const Boxed_Value *{ @@ -64,7 +64,7 @@ namespace chaiscript }(); chaiscript::eval::detail::Stack_Push_Pop tpp(state); - if (thisobj) { state.add_object("this", *thisobj); } + if (thisobj && !has_this_capture) { state.add_object("this", *thisobj); } if (t_locals) { for (const auto &local : *t_locals) { @@ -618,7 +618,9 @@ namespace chaiscript struct Lambda_AST_Node final : AST_Node_Impl { Lambda_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : AST_Node_Impl(t_ast_node_text, AST_Node_Type::Lambda, std::move(t_loc), std::move(t_children)), - m_param_names(Arg_List_AST_Node::get_arg_names(this->children[1])) { } + m_param_names(Arg_List_AST_Node::get_arg_names(this->children[1])), + m_this_capture(has_this_capture(this->children[0]->children)) + { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { @@ -638,17 +640,26 @@ namespace chaiscript return Boxed_Value( dispatch::make_dynamic_proxy_function( - [engine, lambda_node, param_names = this->m_param_names, captures](const std::vector &t_params) + [engine, lambda_node, param_names = this->m_param_names, captures, this_capture = this->m_this_capture](const std::vector &t_params) { - return detail::eval_function(engine, lambda_node, param_names, t_params, &captures); + return detail::eval_function(engine, lambda_node, param_names, t_params, &captures, this_capture); }, static_cast(numparams), lambda_node, param_types ) ); } + static bool has_this_capture(const std::vector> &children) { + return std::any_of(begin(children), end(children), + [](const auto &child){ + return child->children[0]->text == "this"; + } + ); + } + private: const std::vector m_param_names; + const bool m_this_capture = false; }; From 8efba903c3a6afc2851f6a3cdb7fd7d0d2b307f3 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 31 Jan 2017 13:28:40 -0800 Subject: [PATCH 16/84] use std::end instead of end because of MSVC --- include/chaiscript/language/chaiscript_eval.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index f2ab7918..c6143f15 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -650,7 +650,7 @@ namespace chaiscript } static bool has_this_capture(const std::vector> &children) { - return std::any_of(begin(children), end(children), + return std::any_of(std::begin(children), std::end(children), [](const auto &child){ return child->children[0]->text == "this"; } From 0a18f0a809a2fcb06757426902bb3e1208a201de Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 31 Jan 2017 13:40:16 -0800 Subject: [PATCH 17/84] Remove unnecessary params --- .../chaiscript/language/chaiscript_parser.hpp | 266 +++++++++--------- 1 file changed, 127 insertions(+), 139 deletions(-) diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 18c42200..3e7315b7 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -781,58 +781,54 @@ namespace chaiscript } /// Reads a number from the input, detecting if it's an integer or floating point - bool Num(const bool t_capture = false) { + bool Num() { SkipWS(); - if (!t_capture) { - return Hex_() || Float_(); - } else { - const auto start = m_position; - if (m_position.has_more() && char_in_alphabet(*m_position, detail::float_alphabet) ) { - try { - if (Hex_()) { - auto match = Position::str(start, m_position); - auto bv = buildInt(16, match, true); - m_match_stack.emplace_back(make_node>(std::move(match), start.line, start.col, std::move(bv))); - return true; - } - - if (Binary_()) { - auto match = Position::str(start, m_position); - auto bv = buildInt(2, match, true); - m_match_stack.push_back(make_node>(std::move(match), start.line, start.col, std::move(bv))); - return true; - } - if (Float_()) { - auto match = Position::str(start, m_position); - auto bv = buildFloat(match); - m_match_stack.push_back(make_node>(std::move(match), start.line, start.col, std::move(bv))); - return true; - } - else { - IntSuffix_(); - auto match = Position::str(start, m_position); - if (!match.empty() && (match[0] == '0')) { - auto bv = buildInt(8, match, false); - m_match_stack.push_back(make_node>(std::move(match), start.line, start.col, std::move(bv))); - } - else if (!match.empty()) { - auto bv = buildInt(10, match, false); - m_match_stack.push_back(make_node>(std::move(match), start.line, start.col, std::move(bv))); - } else { - return false; - } - return true; - } - } catch (const std::invalid_argument &) { - // error parsing number passed in to buildFloat/buildInt - return false; + const auto start = m_position; + if (m_position.has_more() && char_in_alphabet(*m_position, detail::float_alphabet) ) { + try { + if (Hex_()) { + auto match = Position::str(start, m_position); + auto bv = buildInt(16, match, true); + m_match_stack.emplace_back(make_node>(std::move(match), start.line, start.col, std::move(bv))); + return true; } - } - else { + + if (Binary_()) { + auto match = Position::str(start, m_position); + auto bv = buildInt(2, match, true); + m_match_stack.push_back(make_node>(std::move(match), start.line, start.col, std::move(bv))); + return true; + } + if (Float_()) { + auto match = Position::str(start, m_position); + auto bv = buildFloat(match); + m_match_stack.push_back(make_node>(std::move(match), start.line, start.col, std::move(bv))); + return true; + } + else { + IntSuffix_(); + auto match = Position::str(start, m_position); + if (!match.empty() && (match[0] == '0')) { + auto bv = buildInt(8, match, false); + m_match_stack.push_back(make_node>(std::move(match), start.line, start.col, std::move(bv))); + } + else if (!match.empty()) { + auto bv = buildInt(10, match, false); + m_match_stack.push_back(make_node>(std::move(match), start.line, start.col, std::move(bv))); + } else { + return false; + } + return true; + } + } catch (const std::invalid_argument &) { + // error parsing number passed in to buildFloat/buildInt return false; } } + else { + return false; + } } /// Reads an identifier from input which conforms to C's identifier naming conventions, without skipping initial whitespace @@ -1188,92 +1184,88 @@ namespace chaiscript /// Reads (and potentially captures) a quoted string from input. Translates escaped sequences. - bool Quoted_String(const bool t_capture = false) { + bool Quoted_String() { SkipWS(); - if (!t_capture) { - return Quoted_String_(); - } else { - const auto start = m_position; + const auto start = m_position; - if (Quoted_String_()) { - std::string match; - const auto prev_stack_top = m_match_stack.size(); + if (Quoted_String_()) { + std::string match; + const auto prev_stack_top = m_match_stack.size(); - bool is_interpolated = [&]()->bool { - Char_Parser cparser(match, true); + bool is_interpolated = [&]()->bool { + Char_Parser cparser(match, true); - auto s = start + 1, end = m_position - 1; + auto s = start + 1, end = m_position - 1; - while (s != end) { - if (cparser.saw_interpolation_marker) { - if (*s == '{') { - //We've found an interpolation point + while (s != end) { + if (cparser.saw_interpolation_marker) { + if (*s == '{') { + //We've found an interpolation point - m_match_stack.push_back(make_node>(match, start.line, start.col, const_var(match))); + m_match_stack.push_back(make_node>(match, start.line, start.col, const_var(match))); - if (cparser.is_interpolated) { - //If we've seen previous interpolation, add on instead of making a new one - build_match>(prev_stack_top, "+"); - } - - //We've finished with the part of the string up to this point, so clear it - match.clear(); - - std::string eval_match; - - ++s; - while ((s != end) && (*s != '}')) { - eval_match.push_back(*s); - ++s; - } - - if (*s == '}') { - cparser.is_interpolated = true; - ++s; - - const auto tostr_stack_top = m_match_stack.size(); - - m_match_stack.push_back(make_node>("to_string", start.line, start.col)); - - const auto ev_stack_top = m_match_stack.size(); - - try { - m_match_stack.push_back(parse_instr_eval(eval_match)); - } catch (const exception::eval_error &e) { - throw exception::eval_error(e.what(), File_Position(start.line, start.col), *m_filename); - } - - build_match>(ev_stack_top); - build_match>(tostr_stack_top); - build_match>(prev_stack_top, "+"); - } else { - throw exception::eval_error("Unclosed in-string eval", File_Position(start.line, start.col), *m_filename); - } - } else { - match.push_back('$'); + if (cparser.is_interpolated) { + //If we've seen previous interpolation, add on instead of making a new one + build_match>(prev_stack_top, "+"); } - cparser.saw_interpolation_marker = false; - } else { - cparser.parse(*s, start.line, start.col, *m_filename); + + //We've finished with the part of the string up to this point, so clear it + match.clear(); + + std::string eval_match; + ++s; + while ((s != end) && (*s != '}')) { + eval_match.push_back(*s); + ++s; + } + + if (*s == '}') { + cparser.is_interpolated = true; + ++s; + + const auto tostr_stack_top = m_match_stack.size(); + + m_match_stack.push_back(make_node>("to_string", start.line, start.col)); + + const auto ev_stack_top = m_match_stack.size(); + + try { + m_match_stack.push_back(parse_instr_eval(eval_match)); + } catch (const exception::eval_error &e) { + throw exception::eval_error(e.what(), File_Position(start.line, start.col), *m_filename); + } + + build_match>(ev_stack_top); + build_match>(tostr_stack_top); + build_match>(prev_stack_top, "+"); + } else { + throw exception::eval_error("Unclosed in-string eval", File_Position(start.line, start.col), *m_filename); + } + } else { + match.push_back('$'); } + cparser.saw_interpolation_marker = false; + } else { + cparser.parse(*s, start.line, start.col, *m_filename); + ++s; } - - return cparser.is_interpolated; - }(); - - m_match_stack.push_back(make_node>(match, start.line, start.col, const_var(match))); - - if (is_interpolated) { - build_match>(prev_stack_top, "+"); } - return true; - } else { - return false; + return cparser.is_interpolated; + }(); + + m_match_stack.push_back(make_node>(match, start.line, start.col, const_var(match))); + + if (is_interpolated) { + build_match>(prev_stack_top, "+"); } + + return true; + } else { + return false; } } @@ -1306,35 +1298,31 @@ namespace chaiscript } /// Reads (and potentially captures) a char group from input. Translates escaped sequences. - bool Single_Quoted_String(const bool t_capture = false) { + bool Single_Quoted_String() { SkipWS(); - if (!t_capture) { - return Single_Quoted_String_(); - } else { - const auto start = m_position; - if (Single_Quoted_String_()) { - std::string match; + const auto start = m_position; + if (Single_Quoted_String_()) { + std::string match; - { - // scope for cparser destructor - Char_Parser cparser(match, false); + { + // scope for cparser destructor + Char_Parser cparser(match, false); - for (auto s = start + 1, end = m_position - 1; s != end; ++s) { - cparser.parse(*s, start.line, start.col, *m_filename); - } + for (auto s = start + 1, end = m_position - 1; s != end; ++s) { + cparser.parse(*s, start.line, start.col, *m_filename); } - - if (match.size() != 1) { - throw exception::eval_error("Single-quoted strings must be 1 character long", File_Position(m_position.line, m_position.col), *m_filename); - } - - m_match_stack.push_back(make_node>(match, start.line, start.col, const_var(char(match.at(0))))); - return true; } - else { - return false; + + if (match.size() != 1) { + throw exception::eval_error("Single-quoted strings must be 1 character long", File_Position(m_position.line, m_position.col), *m_filename); } + + m_match_stack.push_back(make_node>(match, start.line, start.col, const_var(char(match.at(0))))); + return true; + } + else { + return false; } } @@ -2088,7 +2076,7 @@ namespace chaiscript bool retval = false; const auto prev_stack_top = m_match_stack.size(); - if (Lambda() || Num(true) || Quoted_String(true) || Single_Quoted_String(true) || + if (Lambda() || Num() || Quoted_String() || Single_Quoted_String() || Paren_Expression() || Inline_Container() || Id(false)) { retval = true; From e7a6b2306ce82ae50c7a7d71744d00829cadb59c Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 31 Jan 2017 15:30:38 -0800 Subject: [PATCH 18/84] Add tests for parsing of neg numbers --- unittests/integer_literal_test.cpp | 251 ++++++++++++++++++----------- unittests/negative_numbers.chai | 8 + 2 files changed, 165 insertions(+), 94 deletions(-) create mode 100644 unittests/negative_numbers.chai diff --git a/unittests/integer_literal_test.cpp b/unittests/integer_literal_test.cpp index 0cb41c37..e5cfbfdb 100644 --- a/unittests/integer_literal_test.cpp +++ b/unittests/integer_literal_test.cpp @@ -8,110 +8,173 @@ template bool test_literal(T val, const std::string &str) { - std::cout << "Comparing : " << val; + std::cout << '(' << str << ") Comparing : C++ '" << val; chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser()); T val2 = chai.eval(str); - std::cout << " " << val2 << '\n'; + std::cout << "' chai '" << val2 << "'\n"; return val == val2; } int main() { - if( TEST_LITERAL(0xF) - && TEST_LITERAL(0xFF) - && TEST_LITERAL(0xFFF) - && TEST_LITERAL(0xFFFF) - && TEST_LITERAL(0xFFFFF) - && TEST_LITERAL(0xFFFFFF) - && TEST_LITERAL(0xFFFFFFF) - && TEST_LITERAL(0xFFFFFFFF) - && TEST_LITERAL(0xFFFFFFFFF) - && TEST_LITERAL(0xFFFFFFFFFF) - && TEST_LITERAL(0xFFFFFFFFFFF) - && TEST_LITERAL(0xFFFFFFFFFFFF) - && TEST_LITERAL(0xFFFFFFFFFFFFF) - && TEST_LITERAL(0xFFFFFFFFFFFFFF) - && TEST_LITERAL(0xFFFFFFFFFFFFFFF) - && TEST_LITERAL(0xFFFFFFFFFFFFFFFF) - - - && TEST_LITERAL(01) - && TEST_LITERAL(017) - && TEST_LITERAL(0177) - && TEST_LITERAL(01777) - && TEST_LITERAL(017777) - && TEST_LITERAL(0177777) - && TEST_LITERAL(01777777) - && TEST_LITERAL(017777777) - && TEST_LITERAL(0177777777) - && TEST_LITERAL(01777777777) - && TEST_LITERAL(017777777777) - && TEST_LITERAL(0177777777777) - && TEST_LITERAL(01777777777777) - && TEST_LITERAL(017777777777777) - && TEST_LITERAL(0177777777777777) - && TEST_LITERAL(01777777777777777) - && TEST_LITERAL(017777777777777777) - && TEST_LITERAL(0177777777777777777) - && TEST_LITERAL(01777777777777777777) - && TEST_LITERAL(017777777777777777777) - && TEST_LITERAL(0177777777777777777777) - && TEST_LITERAL(01777777777777777777777) + if( + TEST_LITERAL(0xF) + && TEST_LITERAL(0xFF) + && TEST_LITERAL(0xFFF) + && TEST_LITERAL(0xFFFF) + && TEST_LITERAL(0xFFFFF) + && TEST_LITERAL(0xFFFFFF) + && TEST_LITERAL(0xFFFFFFF) + && TEST_LITERAL(0xFFFFFFFF) + && TEST_LITERAL(0xFFFFFFFFF) + && TEST_LITERAL(0xFFFFFFFFFF) + && TEST_LITERAL(0xFFFFFFFFFFF) + && TEST_LITERAL(0xFFFFFFFFFFFF) + && TEST_LITERAL(0xFFFFFFFFFFFFF) + && TEST_LITERAL(0xFFFFFFFFFFFFFF) + && TEST_LITERAL(0xFFFFFFFFFFFFFFF) + && TEST_LITERAL(0xFFFFFFFFFFFFFFFF) - && TEST_LITERAL(1) - && TEST_LITERAL(17) - && TEST_LITERAL(177) - && TEST_LITERAL(1777) - && TEST_LITERAL(17777) - && TEST_LITERAL(177777) - && TEST_LITERAL(1777777) - && TEST_LITERAL(17777777) - && TEST_LITERAL(177777777) - && TEST_LITERAL(1777777777) - && TEST_LITERAL(17777777777) - && TEST_LITERAL(177777777777) - && TEST_LITERAL(1777777777777) - && TEST_LITERAL(17777777777777) - && TEST_LITERAL(177777777777777) - && TEST_LITERAL(1777777777777777) - && TEST_LITERAL(17777777777777777) - && TEST_LITERAL(177777777777777777) - && TEST_LITERAL(1777777777777777777) - && test_literal(0xF, "0b1111") - && test_literal(0xFF, "0b11111111") - && test_literal(0xFFF, "0b111111111111") - && test_literal(0xFFFF, "0b1111111111111111") - && test_literal(0xFFFFF, "0b11111111111111111111") - && test_literal(0xFFFFFF, "0b111111111111111111111111") - && test_literal(0xFFFFFFF, "0b1111111111111111111111111111") - && test_literal(0xFFFFFFFF, "0b11111111111111111111111111111111") - && test_literal(0xFFFFFFFFF, "0b111111111111111111111111111111111111") - && test_literal(0xFFFFFFFFFF, "0b1111111111111111111111111111111111111111") - && test_literal(0xFFFFFFFFFFF, "0b11111111111111111111111111111111111111111111") - && test_literal(0xFFFFFFFFFFFF, "0b111111111111111111111111111111111111111111111111") - && test_literal(0xFFFFFFFFFFFFF, "0b1111111111111111111111111111111111111111111111111111") - && test_literal(0xFFFFFFFFFFFFFF, "0b11111111111111111111111111111111111111111111111111111111") - && test_literal(0xFFFFFFFFFFFFFFF, "0b111111111111111111111111111111111111111111111111111111111111") - && test_literal(0xFFFFFFFFFFFFFFFF, "0b1111111111111111111111111111111111111111111111111111111111111111") + && TEST_LITERAL(01) + && TEST_LITERAL(017) + && TEST_LITERAL(0177) + && TEST_LITERAL(01777) + && TEST_LITERAL(017777) + && TEST_LITERAL(0177777) + && TEST_LITERAL(01777777) + && TEST_LITERAL(017777777) + && TEST_LITERAL(0177777777) + && TEST_LITERAL(01777777777) + && TEST_LITERAL(017777777777) + && TEST_LITERAL(0177777777777) + && TEST_LITERAL(01777777777777) + && TEST_LITERAL(017777777777777) + && TEST_LITERAL(0177777777777777) + && TEST_LITERAL(01777777777777777) + && TEST_LITERAL(017777777777777777) + && TEST_LITERAL(0177777777777777777) + && TEST_LITERAL(01777777777777777777) + && TEST_LITERAL(017777777777777777777) + && TEST_LITERAL(0177777777777777777777) + && TEST_LITERAL(01777777777777777777777) - && test_literal(0x7, "0b111") - && test_literal(0x7F, "0b1111111") - && test_literal(0x7FF, "0b11111111111") - && test_literal(0x7FFF, "0b111111111111111") - && test_literal(0x7FFFF, "0b1111111111111111111") - && test_literal(0x7FFFFF, "0b11111111111111111111111") - && test_literal(0x7FFFFFF, "0b111111111111111111111111111") - && test_literal(0x7FFFFFFF, "0b1111111111111111111111111111111") - && test_literal(0x7FFFFFFFF, "0b11111111111111111111111111111111111") - && test_literal(0x7FFFFFFFFF, "0b111111111111111111111111111111111111111") - && test_literal(0x7FFFFFFFFFF, "0b1111111111111111111111111111111111111111111") - && test_literal(0x7FFFFFFFFFFF, "0b11111111111111111111111111111111111111111111111") - && test_literal(0x7FFFFFFFFFFFF, "0b111111111111111111111111111111111111111111111111111") - && test_literal(0x7FFFFFFFFFFFFF, "0b1111111111111111111111111111111111111111111111111111111") - && test_literal(0x7FFFFFFFFFFFFFF, "0b11111111111111111111111111111111111111111111111111111111111") - && test_literal(0x7FFFFFFFFFFFFFFF, "0b111111111111111111111111111111111111111111111111111111111111111") -) + && TEST_LITERAL(1) + && TEST_LITERAL(17) + && TEST_LITERAL(177) + && TEST_LITERAL(1777) + && TEST_LITERAL(17777) + && TEST_LITERAL(177777) + && TEST_LITERAL(1777777) + && TEST_LITERAL(17777777) + && TEST_LITERAL(177777777) + && TEST_LITERAL(1777777777) + && TEST_LITERAL(17777777777) + && TEST_LITERAL(177777777777) + && TEST_LITERAL(1777777777777) + && TEST_LITERAL(17777777777777) + && TEST_LITERAL(177777777777777) + && TEST_LITERAL(1777777777777777) + && TEST_LITERAL(17777777777777777) + && TEST_LITERAL(177777777777777777) + && TEST_LITERAL(1777777777777777777) + + && test_literal(0xF, "0b1111") + && test_literal(0xFF, "0b11111111") + && test_literal(0xFFF, "0b111111111111") + && test_literal(0xFFFF, "0b1111111111111111") + && test_literal(0xFFFFF, "0b11111111111111111111") + && test_literal(0xFFFFFF, "0b111111111111111111111111") + && test_literal(0xFFFFFFF, "0b1111111111111111111111111111") + && test_literal(0xFFFFFFFF, "0b11111111111111111111111111111111") + && test_literal(0xFFFFFFFFF, "0b111111111111111111111111111111111111") + && test_literal(0xFFFFFFFFFF, "0b1111111111111111111111111111111111111111") + && test_literal(0xFFFFFFFFFFF, "0b11111111111111111111111111111111111111111111") + && test_literal(0xFFFFFFFFFFFF, "0b111111111111111111111111111111111111111111111111") + && test_literal(0xFFFFFFFFFFFFF, "0b1111111111111111111111111111111111111111111111111111") + && test_literal(0xFFFFFFFFFFFFFF, "0b11111111111111111111111111111111111111111111111111111111") + && test_literal(0xFFFFFFFFFFFFFFF, "0b111111111111111111111111111111111111111111111111111111111111") + && test_literal(0xFFFFFFFFFFFFFFFF, "0b1111111111111111111111111111111111111111111111111111111111111111") + + && test_literal(0x7, "0b111") + && test_literal(0x7F, "0b1111111") + && test_literal(0x7FF, "0b11111111111") + && test_literal(0x7FFF, "0b111111111111111") + && test_literal(0x7FFFF, "0b1111111111111111111") + && test_literal(0x7FFFFF, "0b11111111111111111111111") + && test_literal(0x7FFFFFF, "0b111111111111111111111111111") + && test_literal(0x7FFFFFFF, "0b1111111111111111111111111111111") + && test_literal(0x7FFFFFFFF, "0b11111111111111111111111111111111111") + && test_literal(0x7FFFFFFFFF, "0b111111111111111111111111111111111111111") + && test_literal(0x7FFFFFFFFFF, "0b1111111111111111111111111111111111111111111") + && test_literal(0x7FFFFFFFFFFF, "0b11111111111111111111111111111111111111111111111") + && test_literal(0x7FFFFFFFFFFFF, "0b111111111111111111111111111111111111111111111111111") + && test_literal(0x7FFFFFFFFFFFFF, "0b1111111111111111111111111111111111111111111111111111111") + && test_literal(0x7FFFFFFFFFFFFFF, "0b11111111111111111111111111111111111111111111111111111111111") + && test_literal(0x7FFFFFFFFFFFFFFF, "0b111111111111111111111111111111111111111111111111111111111111111") + + + && TEST_LITERAL(-0xF) + && TEST_LITERAL(-0xFF) + && TEST_LITERAL(-0xFFF) + && TEST_LITERAL(-0xFFFF) + && TEST_LITERAL(-0xFFFFF) + && TEST_LITERAL(-0xFFFFFF) + && TEST_LITERAL(-0xFFFFFFF) + && TEST_LITERAL(-0xFFFFFFFF) + && TEST_LITERAL(-0xFFFFFFFFF) + && TEST_LITERAL(-0xFFFFFFFFFF) + && TEST_LITERAL(-0xFFFFFFFFFFF) + && TEST_LITERAL(-0xFFFFFFFFFFFF) + && TEST_LITERAL(-0xFFFFFFFFFFFFF) + && TEST_LITERAL(-0xFFFFFFFFFFFFFF) + && TEST_LITERAL(-0xFFFFFFFFFFFFFFF) + && TEST_LITERAL(-0xFFFFFFFFFFFFFFFF) + + + && TEST_LITERAL(-01) + && TEST_LITERAL(-017) + && TEST_LITERAL(-0177) + && TEST_LITERAL(-01777) + && TEST_LITERAL(-017777) + && TEST_LITERAL(-0177777) + && TEST_LITERAL(-01777777) + && TEST_LITERAL(-017777777) + && TEST_LITERAL(-0177777777) + && TEST_LITERAL(-01777777777) + && TEST_LITERAL(-017777777777) + && TEST_LITERAL(-0177777777777) + && TEST_LITERAL(-01777777777777) + && TEST_LITERAL(-017777777777777) + && TEST_LITERAL(-0177777777777777) + && TEST_LITERAL(-01777777777777777) + && TEST_LITERAL(-017777777777777777) + && TEST_LITERAL(-0177777777777777777) + && TEST_LITERAL(-01777777777777777777) + && TEST_LITERAL(-017777777777777777777) + && TEST_LITERAL(-0177777777777777777777) + && TEST_LITERAL(-01777777777777777777777) + + && TEST_LITERAL(-1) + && TEST_LITERAL(-17) + && TEST_LITERAL(-177) + && TEST_LITERAL(-1777) + && TEST_LITERAL(-17777) + && TEST_LITERAL(-177777) + && TEST_LITERAL(-1777777) + && TEST_LITERAL(-17777777) + && TEST_LITERAL(-177777777) + && TEST_LITERAL(-1777777777) + && TEST_LITERAL(-17777777777) + && TEST_LITERAL(-177777777777) + && TEST_LITERAL(-1777777777777) + && TEST_LITERAL(-17777777777777) + && TEST_LITERAL(-177777777777777) + && TEST_LITERAL(-1777777777777777) + && TEST_LITERAL(-17777777777777777) + && TEST_LITERAL(-177777777777777777) + && TEST_LITERAL(-1777777777777777777) + ) { return EXIT_SUCCESS; } else { diff --git a/unittests/negative_numbers.chai b/unittests/negative_numbers.chai new file mode 100644 index 00000000..5fdb1db9 --- /dev/null +++ b/unittests/negative_numbers.chai @@ -0,0 +1,8 @@ +def numFunc(x) +{ + return x + 10; +} + + +assert_true(-5.numFunc() == 5); + From 83b7973cb885af928e36195a7cbc6ab8f04a93b6 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 31 Jan 2017 15:41:21 -0800 Subject: [PATCH 19/84] Fix parsing of negative numbers --- include/chaiscript/chaiscript_defines.hpp | 27 ++++++++----------- .../chaiscript/language/chaiscript_parser.hpp | 27 +++++++++++-------- include/chaiscript/utility/json.hpp | 6 ++--- 3 files changed, 30 insertions(+), 30 deletions(-) diff --git a/include/chaiscript/chaiscript_defines.hpp b/include/chaiscript/chaiscript_defines.hpp index 0a76a822..97f969f7 100644 --- a/include/chaiscript/chaiscript_defines.hpp +++ b/include/chaiscript/chaiscript_defines.hpp @@ -144,21 +144,6 @@ namespace chaiscript { }; - template - auto parse_num(const char *t_str) -> typename std::enable_if::value, T>::type - { - T t = 0; - for (char c = *t_str; (c = *t_str) != 0; ++t_str) { - if (c < '0' || c > '9') { - return t; - } - t *= 10; - t += c - '0'; - } - return t; - } - - template auto parse_num(const char *t_str) -> typename std::enable_if::value, T>::type { @@ -176,6 +161,16 @@ namespace chaiscript { } }; + const bool neg = [&](){ + if (t_str[0] == '-') { + ++t_str; + return true; + } else { + return false; + } + }(); + + for(; *t_str != '\0'; ++t_str) { char c = *t_str; if (c == '.') { @@ -200,7 +195,7 @@ namespace chaiscript { } } - return final_value(t, base, exponent, neg_exponent); + return final_value(t, base, exponent, neg_exponent) * (neg?-1:1); } template diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 3e7315b7..fe275ec0 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -722,7 +722,10 @@ namespace chaiscript } } - const auto val = prefixed?std::string(t_val.begin()+2,t_val.end()):t_val; + + const bool neg = t_val[0] == '-'; + const auto pref = neg?std::string(t_val.begin()+1,t_val.end()):t_val; + const auto val = prefixed?std::string(pref.begin() + 2, pref.end()):pref; #ifdef __GNUC__ #pragma GCC diagnostic push @@ -739,17 +742,17 @@ namespace chaiscript if (!unsigned_ && !long_ && u >= std::numeric_limits::min() && u <= std::numeric_limits::max()) { - return const_var(static_cast(u)); + return const_var(static_cast(u) * (neg?-1:1)); } else if ((unsigned_ || base != 10) && !long_ && u >= std::numeric_limits::min() && u <= std::numeric_limits::max()) { - return const_var(static_cast(u)); + return const_var(static_cast(u) * (neg?-1:1)); } else if (!unsigned_ && !longlong_ && u >= std::numeric_limits::min() && u <= std::numeric_limits::max()) { - return const_var(static_cast(u)); + return const_var(static_cast(u) * (neg?-1:1)); } else if ((unsigned_ || base != 10) && !longlong_ && u >= std::numeric_limits::min() && u <= std::numeric_limits::max()) { - return const_var(static_cast(u)); + return const_var(static_cast(u) * (neg?-1:1)); } else if (!unsigned_ && u >= std::numeric_limits::min() && u <= std::numeric_limits::max()) { - return const_var(static_cast(u)); + return const_var(static_cast(u) * (neg?-1:1)); } else { - return const_var(static_cast(u)); + return const_var(static_cast(u) * (neg?-1:1)); } } catch (const std::out_of_range &) { @@ -758,13 +761,13 @@ namespace chaiscript auto u = std::stoull(val,nullptr,base); if (u >= std::numeric_limits::min() && u <= std::numeric_limits::max()) { - return const_var(static_cast(u)); + return const_var(static_cast(u) * (neg?-1:1)); } else { - return const_var(static_cast(u)); + return const_var(static_cast(u) * (neg?-1:1)); } } catch (const std::out_of_range &) { // it's just simply too big - return const_var(std::numeric_limits::max()); + return const_var(neg?std::numeric_limits::min():std::numeric_limits::max()); } } @@ -785,6 +788,7 @@ namespace chaiscript SkipWS(); const auto start = m_position; + const bool neg = Char_('-'); if (m_position.has_more() && char_in_alphabet(*m_position, detail::float_alphabet) ) { try { if (Hex_()) { @@ -809,7 +813,7 @@ namespace chaiscript else { IntSuffix_(); auto match = Position::str(start, m_position); - if (!match.empty() && (match[0] == '0')) { + if (!match.empty() && (match[neg?1:0] == '0')) { auto bv = buildInt(8, match, false); m_match_stack.push_back(make_node>(std::move(match), start.line, start.col, std::move(bv))); } @@ -827,6 +831,7 @@ namespace chaiscript } } else { + if (neg) { --m_position; } return false; } } diff --git a/include/chaiscript/utility/json.hpp b/include/chaiscript/utility/json.hpp index 96decc09..73a0c981 100644 --- a/include/chaiscript/utility/json.hpp +++ b/include/chaiscript/utility/json.hpp @@ -600,7 +600,7 @@ struct JSONParser { break; } } - exp = chaiscript::parse_num( exp_str ); + exp = std::stol( exp_str ); } else if( offset < str.size() && (!isspace( c ) && c != ',' && c != ']' && c != '}' )) { throw std::runtime_error(std::string("JSON ERROR: Number: unexpected character '") + c + "'"); @@ -611,9 +611,9 @@ struct JSONParser { return JSON(chaiscript::parse_num( val ) * std::pow( 10, exp )); } else { if( !exp_str.empty() ) { - return JSON(static_cast(chaiscript::parse_num( val )) * std::pow( 10, exp )); + return JSON(static_cast(std::stol( val )) * std::pow( 10, exp )); } else { - return JSON(chaiscript::parse_num( val )); + return JSON(std::stol( val )); } } } From efd37a70711f0b6f7bc90a8d39092fd148fd15ca Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 31 Jan 2017 17:05:53 -0800 Subject: [PATCH 20/84] Add some more integer literal tests --- unittests/integer_literal_test.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/unittests/integer_literal_test.cpp b/unittests/integer_literal_test.cpp index e5cfbfdb..5cc91f20 100644 --- a/unittests/integer_literal_test.cpp +++ b/unittests/integer_literal_test.cpp @@ -174,6 +174,17 @@ int main() && TEST_LITERAL(-17777777777777777) && TEST_LITERAL(-177777777777777777) && TEST_LITERAL(-1777777777777777777) + + + && TEST_LITERAL(255) + && TEST_LITERAL(65535) + && TEST_LITERAL(16777215) + && TEST_LITERAL(4294967295) + + && TEST_LITERAL(-255) + && TEST_LITERAL(-65535) + && TEST_LITERAL(-16777215) + && TEST_LITERAL(-4294967295) ) { return EXIT_SUCCESS; From c82c9ccb6e05906fb97e28fffc051e5bfbffca73 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 1 Feb 2017 06:18:14 -0800 Subject: [PATCH 21/84] Revert "Fix parsing of negative numbers" This reverts commit 83b7973cb885af928e36195a7cbc6ab8f04a93b6. --- include/chaiscript/chaiscript_defines.hpp | 27 +++++++++++-------- .../chaiscript/language/chaiscript_parser.hpp | 27 ++++++++----------- include/chaiscript/utility/json.hpp | 6 ++--- 3 files changed, 30 insertions(+), 30 deletions(-) diff --git a/include/chaiscript/chaiscript_defines.hpp b/include/chaiscript/chaiscript_defines.hpp index 97f969f7..0a76a822 100644 --- a/include/chaiscript/chaiscript_defines.hpp +++ b/include/chaiscript/chaiscript_defines.hpp @@ -144,6 +144,21 @@ namespace chaiscript { }; + template + auto parse_num(const char *t_str) -> typename std::enable_if::value, T>::type + { + T t = 0; + for (char c = *t_str; (c = *t_str) != 0; ++t_str) { + if (c < '0' || c > '9') { + return t; + } + t *= 10; + t += c - '0'; + } + return t; + } + + template auto parse_num(const char *t_str) -> typename std::enable_if::value, T>::type { @@ -161,16 +176,6 @@ namespace chaiscript { } }; - const bool neg = [&](){ - if (t_str[0] == '-') { - ++t_str; - return true; - } else { - return false; - } - }(); - - for(; *t_str != '\0'; ++t_str) { char c = *t_str; if (c == '.') { @@ -195,7 +200,7 @@ namespace chaiscript { } } - return final_value(t, base, exponent, neg_exponent) * (neg?-1:1); + return final_value(t, base, exponent, neg_exponent); } template diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index fe275ec0..3e7315b7 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -722,10 +722,7 @@ namespace chaiscript } } - - const bool neg = t_val[0] == '-'; - const auto pref = neg?std::string(t_val.begin()+1,t_val.end()):t_val; - const auto val = prefixed?std::string(pref.begin() + 2, pref.end()):pref; + const auto val = prefixed?std::string(t_val.begin()+2,t_val.end()):t_val; #ifdef __GNUC__ #pragma GCC diagnostic push @@ -742,17 +739,17 @@ namespace chaiscript if (!unsigned_ && !long_ && u >= std::numeric_limits::min() && u <= std::numeric_limits::max()) { - return const_var(static_cast(u) * (neg?-1:1)); + return const_var(static_cast(u)); } else if ((unsigned_ || base != 10) && !long_ && u >= std::numeric_limits::min() && u <= std::numeric_limits::max()) { - return const_var(static_cast(u) * (neg?-1:1)); + return const_var(static_cast(u)); } else if (!unsigned_ && !longlong_ && u >= std::numeric_limits::min() && u <= std::numeric_limits::max()) { - return const_var(static_cast(u) * (neg?-1:1)); + return const_var(static_cast(u)); } else if ((unsigned_ || base != 10) && !longlong_ && u >= std::numeric_limits::min() && u <= std::numeric_limits::max()) { - return const_var(static_cast(u) * (neg?-1:1)); + return const_var(static_cast(u)); } else if (!unsigned_ && u >= std::numeric_limits::min() && u <= std::numeric_limits::max()) { - return const_var(static_cast(u) * (neg?-1:1)); + return const_var(static_cast(u)); } else { - return const_var(static_cast(u) * (neg?-1:1)); + return const_var(static_cast(u)); } } catch (const std::out_of_range &) { @@ -761,13 +758,13 @@ namespace chaiscript auto u = std::stoull(val,nullptr,base); if (u >= std::numeric_limits::min() && u <= std::numeric_limits::max()) { - return const_var(static_cast(u) * (neg?-1:1)); + return const_var(static_cast(u)); } else { - return const_var(static_cast(u) * (neg?-1:1)); + return const_var(static_cast(u)); } } catch (const std::out_of_range &) { // it's just simply too big - return const_var(neg?std::numeric_limits::min():std::numeric_limits::max()); + return const_var(std::numeric_limits::max()); } } @@ -788,7 +785,6 @@ namespace chaiscript SkipWS(); const auto start = m_position; - const bool neg = Char_('-'); if (m_position.has_more() && char_in_alphabet(*m_position, detail::float_alphabet) ) { try { if (Hex_()) { @@ -813,7 +809,7 @@ namespace chaiscript else { IntSuffix_(); auto match = Position::str(start, m_position); - if (!match.empty() && (match[neg?1:0] == '0')) { + if (!match.empty() && (match[0] == '0')) { auto bv = buildInt(8, match, false); m_match_stack.push_back(make_node>(std::move(match), start.line, start.col, std::move(bv))); } @@ -831,7 +827,6 @@ namespace chaiscript } } else { - if (neg) { --m_position; } return false; } } diff --git a/include/chaiscript/utility/json.hpp b/include/chaiscript/utility/json.hpp index 73a0c981..96decc09 100644 --- a/include/chaiscript/utility/json.hpp +++ b/include/chaiscript/utility/json.hpp @@ -600,7 +600,7 @@ struct JSONParser { break; } } - exp = std::stol( exp_str ); + exp = chaiscript::parse_num( exp_str ); } else if( offset < str.size() && (!isspace( c ) && c != ',' && c != ']' && c != '}' )) { throw std::runtime_error(std::string("JSON ERROR: Number: unexpected character '") + c + "'"); @@ -611,9 +611,9 @@ struct JSONParser { return JSON(chaiscript::parse_num( val ) * std::pow( 10, exp )); } else { if( !exp_str.empty() ) { - return JSON(static_cast(std::stol( val )) * std::pow( 10, exp )); + return JSON(static_cast(chaiscript::parse_num( val )) * std::pow( 10, exp )); } else { - return JSON(std::stol( val )); + return JSON(chaiscript::parse_num( val )); } } } From 3e042100275ad8b5a34c5e67a902a4aa49bb2624 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 1 Feb 2017 07:02:18 -0800 Subject: [PATCH 22/84] Add more integer literal tests / fix neg test Addresses #322 --- .../chaiscript/language/chaiscript_common.hpp | 2 +- unittests/integer_literal_test.cpp | 53 +++++++++++++++++++ unittests/negative_numbers.chai | 6 ++- 3 files changed, 59 insertions(+), 2 deletions(-) diff --git a/include/chaiscript/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index 1b16b31c..abcfe5bf 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -77,7 +77,7 @@ namespace chaiscript "Array_Call", "Dot_Access", "Lambda", "Block", "Scopeless_Block", "Def", "While", "If", "For", "Ranged_For", "Inline_Array", "Inline_Map", "Return", "File", "Prefix", "Break", "Continue", "Map_Pair", "Value_Range", "Inline_Range", "Try", "Catch", "Finally", "Method", "Attr_Decl", - "Logical_And", "Logical_Or", "Reference", "Switch", "Case", "Default", "Ternary Condition", "Noop", "Class", "Binary", "Arg", "Global_Decl", "Constant", "Compiled"}; + "Logical_And", "Logical_Or", "Reference", "Switch", "Case", "Default", "Noop", "Class", "Binary", "Arg", "Global_Decl", "Constant", "Compiled"}; return ast_node_types[static_cast(ast_node_type)]; } diff --git a/unittests/integer_literal_test.cpp b/unittests/integer_literal_test.cpp index 5cc91f20..9403a1d4 100644 --- a/unittests/integer_literal_test.cpp +++ b/unittests/integer_literal_test.cpp @@ -175,6 +175,7 @@ int main() && TEST_LITERAL(-177777777777777777) && TEST_LITERAL(-1777777777777777777) + // Test 8/16/24/32 bit boundaries for various types && TEST_LITERAL(255) && TEST_LITERAL(65535) @@ -185,6 +186,58 @@ int main() && TEST_LITERAL(-65535) && TEST_LITERAL(-16777215) && TEST_LITERAL(-4294967295) + + && TEST_LITERAL(255u) + && TEST_LITERAL(65535u) + && TEST_LITERAL(16777215u) + && TEST_LITERAL(4294967295u) + + && TEST_LITERAL(-255u) + && TEST_LITERAL(-65535u) + && TEST_LITERAL(-16777215u) + && TEST_LITERAL(-4294967295u) + + && TEST_LITERAL(255l) + && TEST_LITERAL(65535l) + && TEST_LITERAL(16777215l) + && TEST_LITERAL(4294967295l) + + && TEST_LITERAL(-255l) + && TEST_LITERAL(-65535l) + && TEST_LITERAL(-16777215l) + && TEST_LITERAL(-4294967295l) + + && TEST_LITERAL(255ul) + && TEST_LITERAL(65535ul) + && TEST_LITERAL(16777215ul) + && TEST_LITERAL(4294967295ul) + + && TEST_LITERAL(-255ul) + && TEST_LITERAL(-65535ul) + && TEST_LITERAL(-16777215ul) + && TEST_LITERAL(-4294967295ul) + + && TEST_LITERAL(255ull) + && TEST_LITERAL(65535ull) + && TEST_LITERAL(16777215ull) + && TEST_LITERAL(4294967295ull) + + && TEST_LITERAL(-255ull) + && TEST_LITERAL(-65535ull) + && TEST_LITERAL(-16777215ull) + && TEST_LITERAL(-4294967295ull) + + && TEST_LITERAL(255ll) + && TEST_LITERAL(65535ll) + && TEST_LITERAL(16777215ll) + && TEST_LITERAL(4294967295ll) + + && TEST_LITERAL(-255ll) + && TEST_LITERAL(-65535ll) + && TEST_LITERAL(-16777215ll) + && TEST_LITERAL(-4294967295ll) + + ) { return EXIT_SUCCESS; diff --git a/unittests/negative_numbers.chai b/unittests/negative_numbers.chai index 5fdb1db9..80a617b5 100644 --- a/unittests/negative_numbers.chai +++ b/unittests/negative_numbers.chai @@ -4,5 +4,9 @@ def numFunc(x) } -assert_true(-5.numFunc() == 5); +// Note that unary prefix `-` has lower precedence than `.` +// this is why these values are correct, even if counterintuitive + +assert_true(-5.numFunc() == -15); +assert_true((-5).numFunc() == 5); From d8d7bc79b74c7f53018390dd1e19bcc2aafe4c82 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 1 Feb 2017 09:07:40 -0800 Subject: [PATCH 23/84] Enhance number parsing tests --- .../chaiscript/language/chaiscript_parser.hpp | 2 +- unittests/integer_literal_test.cpp | 32 +++++++++++++------ 2 files changed, 23 insertions(+), 11 deletions(-) diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 3e7315b7..f0b57f06 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -757,7 +757,7 @@ namespace chaiscript try { auto u = std::stoull(val,nullptr,base); - if (u >= std::numeric_limits::min() && u <= std::numeric_limits::max()) { + if (!longlong_ && u >= std::numeric_limits::min() && u <= std::numeric_limits::max()) { return const_var(static_cast(u)); } else { return const_var(static_cast(u)); diff --git a/unittests/integer_literal_test.cpp b/unittests/integer_literal_test.cpp index 9403a1d4..bd5ef101 100644 --- a/unittests/integer_literal_test.cpp +++ b/unittests/integer_literal_test.cpp @@ -4,13 +4,25 @@ #define TEST_LITERAL(v) test_literal(v, #v) +#define TEST_LITERAL_SIGNED(v) test_literal(v, #v, true) template -bool test_literal(T val, const std::string &str) +bool test_literal(T val, const std::string &str, bool use_boxed_number = false) { std::cout << '(' << str << ") Comparing : C++ '" << val; chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser()); - T val2 = chai.eval(str); + + // Note, after applying the `-` it's possible that chaiscript has internally converted + // between two equivalently sized types (ie, unsigned long and unsigned long long on a 64bit system) + // so we're going to allow some leeway with the signed tests + T val2 = [&](){ + if (!use_boxed_number) { + return chai.eval(str); + } else { + return chai.eval(str).get_as(); + } + }(); + std::cout << "' chai '" << val2 << "'\n"; return val == val2; } @@ -222,20 +234,20 @@ int main() && TEST_LITERAL(16777215ull) && TEST_LITERAL(4294967295ull) - && TEST_LITERAL(-255ull) - && TEST_LITERAL(-65535ull) - && TEST_LITERAL(-16777215ull) - && TEST_LITERAL(-4294967295ull) + && TEST_LITERAL_SIGNED(-255ull) + && TEST_LITERAL_SIGNED(-65535ull) + && TEST_LITERAL_SIGNED(-16777215ull) + && TEST_LITERAL_SIGNED(-4294967295ull) && TEST_LITERAL(255ll) && TEST_LITERAL(65535ll) && TEST_LITERAL(16777215ll) && TEST_LITERAL(4294967295ll) - && TEST_LITERAL(-255ll) - && TEST_LITERAL(-65535ll) - && TEST_LITERAL(-16777215ll) - && TEST_LITERAL(-4294967295ll) + && TEST_LITERAL_SIGNED(-255ll) + && TEST_LITERAL_SIGNED(-65535ll) + && TEST_LITERAL_SIGNED(-16777215ll) + && TEST_LITERAL_SIGNED(-4294967295ll) ) From 2782cdd33bb1a696ecc8acf2e7263161a3675d28 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 1 Feb 2017 15:42:32 -0800 Subject: [PATCH 24/84] Remove 2-value bind in favor of lambdas closes #320 --- .../dispatchkit/register_function.hpp | 25 ------------------- samples/example.cpp | 4 +-- 2 files changed, 2 insertions(+), 27 deletions(-) diff --git a/include/chaiscript/dispatchkit/register_function.hpp b/include/chaiscript/dispatchkit/register_function.hpp index 8334b7b6..1c58840a 100644 --- a/include/chaiscript/dispatchkit/register_function.hpp +++ b/include/chaiscript/dispatchkit/register_function.hpp @@ -107,31 +107,6 @@ namespace chaiscript return fun(detail::bind_first(std::forward(t), q)); } - /// \brief Creates a new Proxy_Function object from a free function or member function and binds the first and second parameters of it - /// \param[in] t Function / member to expose - /// \param[in] q Value to bind to first parameter - /// \param[in] r Value to bind to second parameter - /// - /// \b Example: - /// \code - /// struct MyClass - /// { - /// void memberfunction(int); - /// }; - /// - /// MyClass obj; - /// chaiscript::ChaiScript chai; - /// // Add function taking only no arguments, and permanently bound to "obj" and "1" - /// // memberfunction() will be equivalent to obj.memberfunction(1) - /// chai.add(fun(&MyClass::memberfunction, std::ref(obj), 1), "memberfunction"); - /// \endcode - /// - /// \sa \ref adding_functions - template - Proxy_Function fun(T &&t, Q &&q, R &&r) - { - return fun(detail::bind_first(detail::bind_first(std::forward(t), std::forward(q)), std::forward(r))); - } } diff --git a/samples/example.cpp b/samples/example.cpp index 0316ebf6..9a0f0070 100644 --- a/samples/example.cpp +++ b/samples/example.cpp @@ -108,9 +108,9 @@ int main(int /*argc*/, char * /*argv*/[]) { // A shortcut to using eval is just to use the chai operator() chai("log(\"Test Module\", \"Test Message\");"); - //Finally, it is possible to register any std::function as a system function, in this + //Finally, it is possible to register a lambda as a system function, in this //way, we can, for instance add a bound member function to the system - chai.add(fun(&System::do_callbacks, std::ref(system), std::string("Bound Test")), "do_callbacks"); + chai.add(fun([&system](){ return system.do_callbacks("Bound Test"); }), "do_callbacks"); //Call bound version of do_callbacks chai("do_callbacks()"); From 396d43a13f6f1b368a09339bb6d846e474b05428 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 1 Feb 2017 20:01:30 -0800 Subject: [PATCH 25/84] sublime now at ChaiScript/sublimetext-chaiscript --- .../sublimetext/ChaiScript.YAML-tmLanguage | 93 ----- contrib/sublimetext/ChaiScript.tmLanguage | 333 ------------------ 2 files changed, 426 deletions(-) delete mode 100644 contrib/sublimetext/ChaiScript.YAML-tmLanguage delete mode 100644 contrib/sublimetext/ChaiScript.tmLanguage diff --git a/contrib/sublimetext/ChaiScript.YAML-tmLanguage b/contrib/sublimetext/ChaiScript.YAML-tmLanguage deleted file mode 100644 index 7596d472..00000000 --- a/contrib/sublimetext/ChaiScript.YAML-tmLanguage +++ /dev/null @@ -1,93 +0,0 @@ -# [PackageDev] target_format: plist, ext: tmLanguage ---- -comment: 'ChaiScript Syntax: version 2.0' -fileTypes: [chai] -firstLineMatch: ^#!/usr/bin/env node -foldingStartMarker: ^.*\bdef\s*(\w+\s*)?\([^\)]*\)(\s*\{[^\}]*)?\s*$ -foldingStopMarker: ^\s*\} -keyEquivalent: ^~J -name: ChaiScript -patterns: -- {comment: chaiscript shebang, match: ^#, name: comment.line.chai} -- {match: '\b((0(x|X)[0-9a-fA-F]+)|([0-9]+(\.[0-9]+)?))\b', name: constant.numeric.chai} -- begin: '''' - beginCaptures: - '0': {name: punctuation.definition.string.begin.chai} - end: '''' - endCaptures: - '0': {name: punctuation.definition.string.end.chai} - name: string.quoted.single.chai - patterns: - - {match: '\\(x\h{2}|[0-2][0-7]{,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.)', name: constant.character.escape.chai} -- begin: '"' - beginCaptures: - '0': {name: punctuation.definition.string.begin.chai} - end: '"' - endCaptures: - '0': {name: punctuation.definition.string.end.chai} - name: string.quoted.double.chai - patterns: - - {match: '\\(x\h{2}|[0-2][0-7]{,2}|3[0-6][0-7]|37[0-7]?|[4-7][0-7]?|.)', name: constant.character.escape.chai} -- begin: /\*\*(?!/) - captures: - '0': {name: punctuation.definition.comment.chai} - end: \*/ - name: comment.block.documentation.chai -- begin: /\* - captures: - '0': {name: punctuation.definition.comment.chai} - end: \*/ - name: comment.block.chai -- captures: - '1': {name: punctuation.definition.comment.chai} - match: (//).*$\n? - name: comment.line.double-slash.chai -- captures: - '0': {name: punctuation.definition.comment.html.chai} - '2': {name: punctuation.definition.comment.html.chai} - match: () - name: comment.block.html.chai -- {match: \b(boolean|byte|char|class|double|enum|float|fun|def|int|interface|long|short|var|auto|attr)\b, - name: storage.type.chai} -- {match: \b(break|case|catch|continue|default|do|else|finally|else if|for|goto|if|return|switch|throw|try|while)\b, - name: keyword.control.chai} -- {match: \b(delete|in|instanceof|new|typeof|with)\b, name: keyword.operator.chai} -- {match: \btrue\b, name: constant.language.boolean.true.chai} -- {match: \bfalse\b, name: constant.language.boolean.false.chai} -- {match: \bnull\b, name: constant.language.null.chai} -- {match: \b(Anchor|Applet|Area|Array|Boolean|Button|Checkbox|Date|document|event|FileUpload|Form|Frame|Function|Hidden|History|Image|JavaArray|JavaClass|JavaObject|JavaPackage|java|Layer|Link|Location|Math|MimeType|Number|navigator|netscape|Object|Option|Packages|Password|Plugin|Radio|RegExp|Reset|Select|String|Style|Submit|screen|sun|Text|Textarea|window|XMLHttpRequest)\b, - name: support.class.chai} -- {match: '\b(s(h(ift|ow(Mod(elessDialog|alDialog)|Help))|croll(X|By(Pages|Lines)?|Y|To)?|t(op|rike)|i(n|zeToContent|debar|gnText)|ort|u(p|b(str(ing)?)?)|pli(ce|t)|e(nd|t(Re(sizable|questHeader)|M(i(nutes|lliseconds)|onth)|Seconds|Ho(tKeys|urs)|Year|Cursor|Time(out)?|Interval|ZOptions|Date|UTC(M(i(nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(ome|andleEvent)|navigate|c(har(CodeAt|At)|o(s|n(cat|textual|firm)|mpile)|eil|lear(Timeout|Interval)?|a(ptureEvents|ll)|reate(StyleSheet|Popup|EventObject))|t(o(GMTString|S(tring|ource)|U(TCString|pperCase)|Lo(caleString|werCase))|est|a(n|int(Enabled)?))|i(s(NaN|Finite)|ndexOf|talics)|d(isableExternalCapture|ump|etachEvent)|u(n(shift|taint|escape|watch)|pdateCommands)|j(oin|avaEnabled)|p(o(p|w)|ush|lugins.refresh|a(ddings|rse(Int|Float)?)|r(int|ompt|eference))|e(scape|nableExternalCapture|val|lementFromPoint|x(p|ec(Script|Command)?))|valueOf|UTC|queryCommand(State|Indeterm|Enabled|Value)|f(i(nd|le(ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(nt(size|color)|rward)|loor|romCharCode)|watch|l(ink|o(ad|g)|astIndexOf)|a(sin|nchor|cos|t(tachEvent|ob|an(2)?)|pply|lert|b(s|ort))|r(ou(nd|teEvents)|e(size(By|To)|calc|turnValue|place|verse|l(oad|ease(Capture|Events)))|andom)|g(o|et(ResponseHeader|M(i(nutes|lliseconds)|onth)|Se(conds|lection)|Hours|Year|Time(zoneOffset)?|Da(y|te)|UTC(M(i(nutes|lliseconds)|onth)|Seconds|Hours|Da(y|te)|FullYear)|FullYear|A(ttention|llResponseHeaders)))|m(in|ove(B(y|elow)|To(Absolute)?|Above)|ergeAttributes|a(tch|rgins|x))|b(toa|ig|o(ld|rderWidths)|link|ack))\b(?=\()', - name: support.function.chai} -- {match: '\b(s(ub(stringData|mit)|plitText|e(t(NamedItem|Attribute(Node)?)|lect))|has(ChildNodes|Feature)|namedItem|c(l(ick|o(se|neNode))|reate(C(omment|DATASection|aption)|T(Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(ntityReference|lement)|Attribute))|tabIndex|i(nsert(Row|Before|Cell|Data)|tem)|open|delete(Row|C(ell|aption)|T(Head|Foot)|Data)|focus|write(ln)?|a(dd|ppend(Child|Data))|re(set|place(Child|Data)|move(NamedItem|Child|Attribute(Node)?)?)|get(NamedItem|Element(sBy(Name|TagName)|ById)|Attribute(Node)?)|blur)\b(?=\()', - name: support.function.dom.chai} -- {match: '(?<=\.)(s(ystemLanguage|cr(ipts|ollbars|een(X|Y|Top|Left))|t(yle(Sheets)?|atus(Text|bar)?)|ibling(Below|Above)|ource|uffixes|e(curity(Policy)?|l(ection|f)))|h(istory|ost(name)?|as(h|Focus))|y|X(MLDocument|SLDocument)|n(ext|ame(space(s|URI)|Prop))|M(IN_VALUE|AX_VALUE)|c(haracterSet|o(n(structor|trollers)|okieEnabled|lorDepth|mp(onents|lete))|urrent|puClass|l(i(p(boardData)?|entInformation)|osed|asses)|alle(e|r)|rypto)|t(o(olbar|p)|ext(Transform|Indent|Decoration|Align)|ags)|SQRT(1_2|2)|i(n(ner(Height|Width)|put)|ds|gnoreCase)|zIndex|o(scpu|n(readystatechange|Line)|uter(Height|Width)|p(sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(i(splay|alog(Height|Top|Width|Left|Arguments)|rectories)|e(scription|fault(Status|Ch(ecked|arset)|View)))|u(ser(Profile|Language|Agent)|n(iqueID|defined)|pdateInterval)|_content|p(ixelDepth|ort|ersonalbar|kcs11|l(ugins|atform)|a(thname|dding(Right|Bottom|Top|Left)|rent(Window|Layer)?|ge(X(Offset)?|Y(Offset)?))|r(o(to(col|type)|duct(Sub)?|mpter)|e(vious|fix)))|e(n(coding|abledPlugin)|x(ternal|pando)|mbeds)|v(isibility|endor(Sub)?|Linkcolor)|URLUnencoded|P(I|OSITIVE_INFINITY)|f(ilename|o(nt(Size|Family|Weight)|rmName)|rame(s|Element)|gColor)|E|whiteSpace|l(i(stStyleType|n(eHeight|kColor))|o(ca(tion(bar)?|lName)|wsrc)|e(ngth|ft(Context)?)|a(st(M(odified|atch)|Index|Paren)|yer(s|X)|nguage))|a(pp(MinorVersion|Name|Co(deName|re)|Version)|vail(Height|Top|Width|Left)|ll|r(ity|guments)|Linkcolor|bove)|r(ight(Context)?|e(sponse(XML|Text)|adyState))|global|x|m(imeTypes|ultiline|enubar|argin(Right|Bottom|Top|Left))|L(N(10|2)|OG(10E|2E))|b(o(ttom|rder(Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(Color|Image)))\b', - name: support.constant.chai} -- {match: '(?<=\.)(s(hape|ystemId|c(heme|ope|rolling)|ta(ndby|rt)|ize|ummary|pecified|e(ctionRowIndex|lected(Index)?)|rc)|h(space|t(tpEquiv|mlFor)|e(ight|aders)|ref(lang)?)|n(o(Resize|tation(s|Name)|Shade|Href|de(Name|Type|Value)|Wrap)|extSibling|ame)|c(h(ildNodes|Off|ecked|arset)?|ite|o(ntent|o(kie|rds)|de(Base|Type)?|l(s|Span|or)|mpact)|ell(s|Spacing|Padding)|l(ear|assName)|aption)|t(ype|Bodies|itle|Head|ext|a(rget|gName)|Foot)|i(sMap|ndex|d|m(plementation|ages))|o(ptions|wnerDocument|bject)|d(i(sabled|r)|o(c(type|umentElement)|main)|e(clare|f(er|ault(Selected|Checked|Value)))|at(eTime|a))|useMap|p(ublicId|arentNode|r(o(file|mpt)|eviousSibling))|e(n(ctype|tities)|vent|lements)|v(space|ersion|alue(Type)?|Link|Align)|URL|f(irstChild|orm(s)?|ace|rame(Border)?)|width|l(ink(s)?|o(ngDesc|wSrc)|a(stChild|ng|bel))|a(nchors|c(ce(ssKey|pt(Charset)?)|tion)|ttributes|pplets|l(t|ign)|r(chive|eas)|xis|Link|bbr)|r(ow(s|Span|Index)|ules|e(v|ferrer|l|adOnly))|m(ultiple|e(thod|dia)|a(rgin(Height|Width)|xLength))|b(o(dy|rder)|ackground|gColor))\b', - name: support.constant.dom.chai} -- {match: \b(ELEMENT_NODE|ATTRIBUTE_NODE|TEXT_NODE|CDATA_SECTION_NODE|ENTITY_REFERENCE_NODE|ENTITY_NODE|PROCESSING_INSTRUCTION_NODE|COMMENT_NODE|DOCUMENT_NODE|DOCUMENT_TYPE_NODE|DOCUMENT_FRAGMENT_NODE|NOTATION_NODE|INDEX_SIZE_ERR|DOMSTRING_SIZE_ERR|HIERARCHY_REQUEST_ERR|WRONG_DOCUMENT_ERR|INVALID_CHARACTER_ERR|NO_DATA_ALLOWED_ERR|NO_MODIFICATION_ALLOWED_ERR|NOT_FOUND_ERR|NOT_SUPPORTED_ERR|INUSE_ATTRIBUTE_ERR)\b, - name: support.constant.dom.chai} -- {match: '\bon(R(ow(s(inserted|delete)|e(nter|xit))|e(s(ize(start|end)?|et)|adystatechange))|Mouse(o(ut|ver)|down|up|move)|B(efore(cut|deactivate|u(nload|pdate)|p(aste|rint)|editfocus|activate)|lur)|S(croll|top|ubmit|elect(start|ionchange)?)|H(over|elp)|C(hange|ont(extmenu|rolselect)|ut|ellchange|l(ick|ose))|D(eactivate|ata(setc(hanged|omplete)|available)|r(op|ag(start|over|drop|en(ter|d)|leave)?)|blclick)|Unload|P(aste|ropertychange)|Error(update)?|Key(down|up|press)|Focus|Load|A(ctivate|fter(update|print)|bort))\b', - name: support.function.event-handler.chai} -- {match: '!|\$|%|&|\*|\-\-|\-|\+\+|\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|\*=|(? - - - - comment - ChaiScript Syntax: version 2.0 - fileTypes - - chai - - firstLineMatch - ^#!/usr/bin/env node - foldingStartMarker - ^.*\bdef\s*(\w+\s*)?\([^\)]*\)(\s*\{[^\}]*)?\s*$ - foldingStopMarker - ^\s*\} - keyEquivalent - ^~J - name - ChaiScript - patterns - - - comment - chaiscript shebang - match - ^# - name - comment.line.chai - - - match - \b((0(x|X)[0-9a-fA-F]+)|([0-9]+(\.[0-9]+)?))\b - name - constant.numeric.chai - - - begin - ' - beginCaptures - - 0 - - name - punctuation.definition.string.begin.chai - - - end - ' - endCaptures - - 0 - - name - punctuation.definition.string.end.chai - - - name - string.quoted.single.chai - patterns - - - match - \\(x\h{2}|[0-2][0-7]{,2}|3[0-6][0-7]?|37[0-7]?|[4-7][0-7]?|.) - name - constant.character.escape.chai - - - - - begin - " - beginCaptures - - 0 - - name - punctuation.definition.string.begin.chai - - - end - " - endCaptures - - 0 - - name - punctuation.definition.string.end.chai - - - name - string.quoted.double.chai - patterns - - - match - \\(x\h{2}|[0-2][0-7]{,2}|3[0-6][0-7]|37[0-7]?|[4-7][0-7]?|.) - name - constant.character.escape.chai - - - - - begin - /\*\*(?!/) - captures - - 0 - - name - punctuation.definition.comment.chai - - - end - \*/ - name - comment.block.documentation.chai - - - begin - /\* - captures - - 0 - - name - punctuation.definition.comment.chai - - - end - \*/ - name - comment.block.chai - - - captures - - 1 - - name - punctuation.definition.comment.chai - - - match - (//).*$\n? - name - comment.line.double-slash.chai - - - captures - - 0 - - name - punctuation.definition.comment.html.chai - - 2 - - name - punctuation.definition.comment.html.chai - - - match - (<!--|-->) - name - comment.block.html.chai - - - match - \b(boolean|byte|char|class|double|enum|float|fun|def|int|interface|long|short|var|auto|attr)\b - name - storage.type.chai - - - match - \b(break|case|catch|continue|default|do|else|finally|else if|for|goto|if|return|switch|throw|try|while)\b - name - keyword.control.chai - - - match - \b(delete|in|instanceof|new|typeof|with)\b - name - keyword.operator.chai - - - match - \btrue\b - name - constant.language.boolean.true.chai - - - match - \bfalse\b - name - constant.language.boolean.false.chai - - - match - \bnull\b - name - constant.language.null.chai - - - match - \b(Anchor|Applet|Area|Array|Boolean|Button|Checkbox|Date|document|event|FileUpload|Form|Frame|Function|Hidden|History|Image|JavaArray|JavaClass|JavaObject|JavaPackage|java|Layer|Link|Location|Math|MimeType|Number|navigator|netscape|Object|Option|Packages|Password|Plugin|Radio|RegExp|Reset|Select|String|Style|Submit|screen|sun|Text|Textarea|window|XMLHttpRequest)\b - name - support.class.chai - - - match - \b(s(h(ift|ow(Mod(elessDialog|alDialog)|Help))|croll(X|By(Pages|Lines)?|Y|To)?|t(op|rike)|i(n|zeToContent|debar|gnText)|ort|u(p|b(str(ing)?)?)|pli(ce|t)|e(nd|t(Re(sizable|questHeader)|M(i(nutes|lliseconds)|onth)|Seconds|Ho(tKeys|urs)|Year|Cursor|Time(out)?|Interval|ZOptions|Date|UTC(M(i(nutes|lliseconds)|onth)|Seconds|Hours|Date|FullYear)|FullYear|Active)|arch)|qrt|lice|avePreferences|mall)|h(ome|andleEvent)|navigate|c(har(CodeAt|At)|o(s|n(cat|textual|firm)|mpile)|eil|lear(Timeout|Interval)?|a(ptureEvents|ll)|reate(StyleSheet|Popup|EventObject))|t(o(GMTString|S(tring|ource)|U(TCString|pperCase)|Lo(caleString|werCase))|est|a(n|int(Enabled)?))|i(s(NaN|Finite)|ndexOf|talics)|d(isableExternalCapture|ump|etachEvent)|u(n(shift|taint|escape|watch)|pdateCommands)|j(oin|avaEnabled)|p(o(p|w)|ush|lugins.refresh|a(ddings|rse(Int|Float)?)|r(int|ompt|eference))|e(scape|nableExternalCapture|val|lementFromPoint|x(p|ec(Script|Command)?))|valueOf|UTC|queryCommand(State|Indeterm|Enabled|Value)|f(i(nd|le(ModifiedDate|Size|CreatedDate|UpdatedDate)|xed)|o(nt(size|color)|rward)|loor|romCharCode)|watch|l(ink|o(ad|g)|astIndexOf)|a(sin|nchor|cos|t(tachEvent|ob|an(2)?)|pply|lert|b(s|ort))|r(ou(nd|teEvents)|e(size(By|To)|calc|turnValue|place|verse|l(oad|ease(Capture|Events)))|andom)|g(o|et(ResponseHeader|M(i(nutes|lliseconds)|onth)|Se(conds|lection)|Hours|Year|Time(zoneOffset)?|Da(y|te)|UTC(M(i(nutes|lliseconds)|onth)|Seconds|Hours|Da(y|te)|FullYear)|FullYear|A(ttention|llResponseHeaders)))|m(in|ove(B(y|elow)|To(Absolute)?|Above)|ergeAttributes|a(tch|rgins|x))|b(toa|ig|o(ld|rderWidths)|link|ack))\b(?=\() - name - support.function.chai - - - match - \b(s(ub(stringData|mit)|plitText|e(t(NamedItem|Attribute(Node)?)|lect))|has(ChildNodes|Feature)|namedItem|c(l(ick|o(se|neNode))|reate(C(omment|DATASection|aption)|T(Head|extNode|Foot)|DocumentFragment|ProcessingInstruction|E(ntityReference|lement)|Attribute))|tabIndex|i(nsert(Row|Before|Cell|Data)|tem)|open|delete(Row|C(ell|aption)|T(Head|Foot)|Data)|focus|write(ln)?|a(dd|ppend(Child|Data))|re(set|place(Child|Data)|move(NamedItem|Child|Attribute(Node)?)?)|get(NamedItem|Element(sBy(Name|TagName)|ById)|Attribute(Node)?)|blur)\b(?=\() - name - support.function.dom.chai - - - match - (?<=\.)(s(ystemLanguage|cr(ipts|ollbars|een(X|Y|Top|Left))|t(yle(Sheets)?|atus(Text|bar)?)|ibling(Below|Above)|ource|uffixes|e(curity(Policy)?|l(ection|f)))|h(istory|ost(name)?|as(h|Focus))|y|X(MLDocument|SLDocument)|n(ext|ame(space(s|URI)|Prop))|M(IN_VALUE|AX_VALUE)|c(haracterSet|o(n(structor|trollers)|okieEnabled|lorDepth|mp(onents|lete))|urrent|puClass|l(i(p(boardData)?|entInformation)|osed|asses)|alle(e|r)|rypto)|t(o(olbar|p)|ext(Transform|Indent|Decoration|Align)|ags)|SQRT(1_2|2)|i(n(ner(Height|Width)|put)|ds|gnoreCase)|zIndex|o(scpu|n(readystatechange|Line)|uter(Height|Width)|p(sProfile|ener)|ffscreenBuffering)|NEGATIVE_INFINITY|d(i(splay|alog(Height|Top|Width|Left|Arguments)|rectories)|e(scription|fault(Status|Ch(ecked|arset)|View)))|u(ser(Profile|Language|Agent)|n(iqueID|defined)|pdateInterval)|_content|p(ixelDepth|ort|ersonalbar|kcs11|l(ugins|atform)|a(thname|dding(Right|Bottom|Top|Left)|rent(Window|Layer)?|ge(X(Offset)?|Y(Offset)?))|r(o(to(col|type)|duct(Sub)?|mpter)|e(vious|fix)))|e(n(coding|abledPlugin)|x(ternal|pando)|mbeds)|v(isibility|endor(Sub)?|Linkcolor)|URLUnencoded|P(I|OSITIVE_INFINITY)|f(ilename|o(nt(Size|Family|Weight)|rmName)|rame(s|Element)|gColor)|E|whiteSpace|l(i(stStyleType|n(eHeight|kColor))|o(ca(tion(bar)?|lName)|wsrc)|e(ngth|ft(Context)?)|a(st(M(odified|atch)|Index|Paren)|yer(s|X)|nguage))|a(pp(MinorVersion|Name|Co(deName|re)|Version)|vail(Height|Top|Width|Left)|ll|r(ity|guments)|Linkcolor|bove)|r(ight(Context)?|e(sponse(XML|Text)|adyState))|global|x|m(imeTypes|ultiline|enubar|argin(Right|Bottom|Top|Left))|L(N(10|2)|OG(10E|2E))|b(o(ttom|rder(Width|RightWidth|BottomWidth|Style|Color|TopWidth|LeftWidth))|ufferDepth|elow|ackground(Color|Image)))\b - name - support.constant.chai - - - match - (?<=\.)(s(hape|ystemId|c(heme|ope|rolling)|ta(ndby|rt)|ize|ummary|pecified|e(ctionRowIndex|lected(Index)?)|rc)|h(space|t(tpEquiv|mlFor)|e(ight|aders)|ref(lang)?)|n(o(Resize|tation(s|Name)|Shade|Href|de(Name|Type|Value)|Wrap)|extSibling|ame)|c(h(ildNodes|Off|ecked|arset)?|ite|o(ntent|o(kie|rds)|de(Base|Type)?|l(s|Span|or)|mpact)|ell(s|Spacing|Padding)|l(ear|assName)|aption)|t(ype|Bodies|itle|Head|ext|a(rget|gName)|Foot)|i(sMap|ndex|d|m(plementation|ages))|o(ptions|wnerDocument|bject)|d(i(sabled|r)|o(c(type|umentElement)|main)|e(clare|f(er|ault(Selected|Checked|Value)))|at(eTime|a))|useMap|p(ublicId|arentNode|r(o(file|mpt)|eviousSibling))|e(n(ctype|tities)|vent|lements)|v(space|ersion|alue(Type)?|Link|Align)|URL|f(irstChild|orm(s)?|ace|rame(Border)?)|width|l(ink(s)?|o(ngDesc|wSrc)|a(stChild|ng|bel))|a(nchors|c(ce(ssKey|pt(Charset)?)|tion)|ttributes|pplets|l(t|ign)|r(chive|eas)|xis|Link|bbr)|r(ow(s|Span|Index)|ules|e(v|ferrer|l|adOnly))|m(ultiple|e(thod|dia)|a(rgin(Height|Width)|xLength))|b(o(dy|rder)|ackground|gColor))\b - name - support.constant.dom.chai - - - match - \b(ELEMENT_NODE|ATTRIBUTE_NODE|TEXT_NODE|CDATA_SECTION_NODE|ENTITY_REFERENCE_NODE|ENTITY_NODE|PROCESSING_INSTRUCTION_NODE|COMMENT_NODE|DOCUMENT_NODE|DOCUMENT_TYPE_NODE|DOCUMENT_FRAGMENT_NODE|NOTATION_NODE|INDEX_SIZE_ERR|DOMSTRING_SIZE_ERR|HIERARCHY_REQUEST_ERR|WRONG_DOCUMENT_ERR|INVALID_CHARACTER_ERR|NO_DATA_ALLOWED_ERR|NO_MODIFICATION_ALLOWED_ERR|NOT_FOUND_ERR|NOT_SUPPORTED_ERR|INUSE_ATTRIBUTE_ERR)\b - name - support.constant.dom.chai - - - match - \bon(R(ow(s(inserted|delete)|e(nter|xit))|e(s(ize(start|end)?|et)|adystatechange))|Mouse(o(ut|ver)|down|up|move)|B(efore(cut|deactivate|u(nload|pdate)|p(aste|rint)|editfocus|activate)|lur)|S(croll|top|ubmit|elect(start|ionchange)?)|H(over|elp)|C(hange|ont(extmenu|rolselect)|ut|ellchange|l(ick|ose))|D(eactivate|ata(setc(hanged|omplete)|available)|r(op|ag(start|over|drop|en(ter|d)|leave)?)|blclick)|Unload|P(aste|ropertychange)|Error(update)?|Key(down|up|press)|Focus|Load|A(ctivate|fter(update|print)|bort))\b - name - support.function.event-handler.chai - - - match - !|\$|%|&|\*|\-\-|\-|\+\+|\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|\*=|(?<!\()/=|%=|\+=|\-=|&=|\^=|\b(in|instanceof|new|delete|typeof|void)\b - name - keyword.operator.chai - - - match - \b(Infinity|NaN|undefined)\b - name - constant.language.chai - - - begin - (?<=[=(:]|^|return|&&|\|\||!)\s*(/)(?![/*+{}?]) - beginCaptures - - 1 - - name - punctuation.definition.string.begin.chai - - - end - (/)[igm]* - endCaptures - - 1 - - name - punctuation.definition.string.end.chai - - - name - string.regexp.chai - patterns - - - match - \\. - name - constant.character.escape.chai - - - - - match - \; - name - punctuation.terminator.statement.chai - - - match - ,[ |\t]* - name - meta.delimiter.object.comma.chai - - - match - \. - name - meta.delimiter.method.period.chai - - - match - \{|\} - name - meta.brace.curly.chai - - - match - \(|\) - name - meta.brace.round.chai - - - match - \[|\] - name - meta.brace.square.chai - - - scopeName - source.chai - uuid - 93E017CC-6F27-11D9-90EB-000D93589AF6 - - From 24352c62e8869ac56564cba0a14d4a79811de885 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Thu, 2 Feb 2017 08:00:57 -0800 Subject: [PATCH 26/84] Some clang specific fixes / warnings --- .../chaiscript/dispatchkit/boxed_value.hpp | 6 ++--- .../chaiscript/language/chaiscript_parser.hpp | 18 +++++++------- include/chaiscript/utility/fnv1a.hpp | 10 ++++++++ unittests/compiled_tests.cpp | 2 +- unittests/integer_literal_test.cpp | 24 +++++++++---------- 5 files changed, 35 insertions(+), 25 deletions(-) diff --git a/include/chaiscript/dispatchkit/boxed_value.hpp b/include/chaiscript/dispatchkit/boxed_value.hpp index c2cd20e3..8b3d763b 100644 --- a/include/chaiscript/dispatchkit/boxed_value.hpp +++ b/include/chaiscript/dispatchkit/boxed_value.hpp @@ -251,9 +251,9 @@ namespace chaiscript ~Sentinel() { // save new pointer data - const auto ptr = m_ptr.get().get(); - m_data.get().m_data_ptr = ptr; - m_data.get().m_const_data_ptr = ptr; + const auto ptr_ = m_ptr.get().get(); + m_data.get().m_data_ptr = ptr_; + m_data.get().m_const_data_ptr = ptr_; } Sentinel& operator=(Sentinel&&s) = default; diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index f0b57f06..c703fb43 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -2261,14 +2261,14 @@ namespace chaiscript /// Reads a unary prefixed expression from input bool Prefix() { const auto prev_stack_top = m_match_stack.size(); - using SS = utility::Static_String; - constexpr const std::array prefix_opers{ - SS{"++"}, - SS{"--"}, - SS{"-"}, - SS{"+"}, - SS{"!"}, - SS{"~"}}; + constexpr const std::array prefix_opers{{ + "++", + "--", + "-", + "+", + "!", + "~" + }}; for (const auto &oper : prefix_opers) { @@ -2426,7 +2426,7 @@ namespace chaiscript using SS = utility::Static_String; if (Operator()) { - for (const auto sym : {SS{"="}, SS{":="}, SS{"+="}, SS{"-="}, SS{"*="}, SS{"/="}, SS{"%="}, SS{"<<="}, SS{">>="}, SS{"&="}, SS{"^="}, SS{"|="}}) + for (const auto &sym : {SS{"="}, SS{":="}, SS{"+="}, SS{"-="}, SS{"*="}, SS{"/="}, SS{"%="}, SS{"<<="}, SS{">>="}, SS{"&="}, SS{"^="}, SS{"|="}}) { if (Symbol(sym, true)) { SkipWS(true); diff --git a/include/chaiscript/utility/fnv1a.hpp b/include/chaiscript/utility/fnv1a.hpp index 54378cd1..b8c01874 100644 --- a/include/chaiscript/utility/fnv1a.hpp +++ b/include/chaiscript/utility/fnv1a.hpp @@ -21,6 +21,11 @@ namespace chaiscript static constexpr std::uint32_t fnv1a_32(const char *s, std::uint32_t h = 0x811c9dc5) { +#ifdef __GNUC__ +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wsign-conversion" +#endif + #ifdef CHAISCRIPT_MSVC #pragma warning(push) #pragma warning(disable : 4307) @@ -29,6 +34,11 @@ namespace chaiscript #ifdef CHAISCRIPT_MSVC #pragma warning(pop) #endif + +#ifdef __GNUC__ +#pragma GCC diagnostic pop +#endif + } diff --git a/unittests/compiled_tests.cpp b/unittests/compiled_tests.cpp index 9d75519e..8bebc928 100644 --- a/unittests/compiled_tests.cpp +++ b/unittests/compiled_tests.cpp @@ -1202,7 +1202,7 @@ TEST_CASE("Test reference member being registered") double d; chai.add(chaiscript::var(Reference_MyClass(d)), "ref"); chai.eval("ref.x = 2.3"); - CHECK(d == 2.3); + CHECK(d == Approx(2.3)); } diff --git a/unittests/integer_literal_test.cpp b/unittests/integer_literal_test.cpp index bd5ef101..4c20f286 100644 --- a/unittests/integer_literal_test.cpp +++ b/unittests/integer_literal_test.cpp @@ -204,30 +204,30 @@ int main() && TEST_LITERAL(16777215u) && TEST_LITERAL(4294967295u) - && TEST_LITERAL(-255u) - && TEST_LITERAL(-65535u) - && TEST_LITERAL(-16777215u) - && TEST_LITERAL(-4294967295u) + && TEST_LITERAL_SIGNED(-255u) + && TEST_LITERAL_SIGNED(-65535u) + && TEST_LITERAL_SIGNED(-16777215u) + && TEST_LITERAL_SIGNED(-4294967295u) && TEST_LITERAL(255l) && TEST_LITERAL(65535l) && TEST_LITERAL(16777215l) && TEST_LITERAL(4294967295l) - && TEST_LITERAL(-255l) - && TEST_LITERAL(-65535l) - && TEST_LITERAL(-16777215l) - && TEST_LITERAL(-4294967295l) + && TEST_LITERAL_SIGNED(-255l) + && TEST_LITERAL_SIGNED(-65535l) + && TEST_LITERAL_SIGNED(-16777215l) + && TEST_LITERAL_SIGNED(-4294967295l) && TEST_LITERAL(255ul) && TEST_LITERAL(65535ul) && TEST_LITERAL(16777215ul) && TEST_LITERAL(4294967295ul) - && TEST_LITERAL(-255ul) - && TEST_LITERAL(-65535ul) - && TEST_LITERAL(-16777215ul) - && TEST_LITERAL(-4294967295ul) + && TEST_LITERAL_SIGNED(-255ul) + && TEST_LITERAL_SIGNED(-65535ul) + && TEST_LITERAL_SIGNED(-16777215ul) + && TEST_LITERAL_SIGNED(-4294967295ul) && TEST_LITERAL(255ull) && TEST_LITERAL(65535ull) From 1499061f864bb2e82338d80105390fb724f667f7 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Thu, 2 Feb 2017 08:06:41 -0800 Subject: [PATCH 27/84] Add check for negate conversion to bool Check for #321 --- unittests/conversion_to_bool.chai | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/unittests/conversion_to_bool.chai b/unittests/conversion_to_bool.chai index d5512bf1..955b68ec 100644 --- a/unittests/conversion_to_bool.chai +++ b/unittests/conversion_to_bool.chai @@ -7,6 +7,12 @@ if (0) { assert_true(false); } +if (!0) { + assert_true(true); +} else { + assert_true(false); +} + while (0) { assert_true(false); } From f5ced799cfd985b720004568d5e9830bdfefa9d1 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Thu, 2 Feb 2017 08:10:47 -0800 Subject: [PATCH 28/84] Hopefully find balance with gcc/clang for static_string --- include/chaiscript/language/chaiscript_parser.hpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index c703fb43..913b995a 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -2261,13 +2261,14 @@ namespace chaiscript /// Reads a unary prefixed expression from input bool Prefix() { const auto prev_stack_top = m_match_stack.size(); + using SS = utility::Static_String; constexpr const std::array prefix_opers{{ - "++", - "--", - "-", - "+", - "!", - "~" + SS{"++"}, + SS{"--"}, + SS{"-"}, + SS{"+"}, + SS{"!"}, + SS{"~"} }}; for (const auto &oper : prefix_opers) From ca7d4ab734c90e0fe2231cce12c2415a5aed657b Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Thu, 2 Feb 2017 13:17:59 -0800 Subject: [PATCH 29/84] Add test for calling method of unique_ptr var --- unittests/compiled_tests.cpp | 27 ++++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/unittests/compiled_tests.cpp b/unittests/compiled_tests.cpp index 8bebc928..062cd13e 100644 --- a/unittests/compiled_tests.cpp +++ b/unittests/compiled_tests.cpp @@ -1123,12 +1123,33 @@ TEST_CASE("Use unique_ptr") CHECK(chai.eval("iptr") == 2); chai.eval("derefi(iptr)"); CHECK(chai.eval("iptr") == 3); - - - } +class Unique_Ptr_Test_Class +{ + public: + Unique_Ptr_Test_Class() = default; + Unique_Ptr_Test_Class(const Unique_Ptr_Test_Class&) = default; + Unique_Ptr_Test_Class(Unique_Ptr_Test_Class &&) = default; + Unique_Ptr_Test_Class &operator=(const Unique_Ptr_Test_Class&) = default; + Unique_Ptr_Test_Class &operator=(Unique_Ptr_Test_Class&&) = default; + virtual ~Unique_Ptr_Test_Class() = default; + + int getI() const {return 5;} +}; + +TEST_CASE("Call methods through unique_ptr") +{ + chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser()); + + chai.add(chaiscript::var(std::make_unique()), "uptr"); + chai.add(chaiscript::fun(&Unique_Ptr_Test_Class::getI), "getI"); + CHECK(chai.eval("uptr.getI()") == 5); +} + + + class A { public: From dca3ce4ea6396c67d5c91600bd1f08b62a05d554 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Thu, 2 Feb 2017 15:07:37 -0700 Subject: [PATCH 30/84] Enhance testing of integer literals * enable the ability to check a boxed_number conversion * fix integer_literal_test to pass on MacOS --- .../chaiscript/dispatchkit/boxed_number.hpp | 53 ++++++++ unittests/integer_literal_test.cpp | 124 +++++++++--------- 2 files changed, 115 insertions(+), 62 deletions(-) diff --git a/include/chaiscript/dispatchkit/boxed_number.hpp b/include/chaiscript/dispatchkit/boxed_number.hpp index 7a7c875a..68b2f0b8 100644 --- a/include/chaiscript/dispatchkit/boxed_number.hpp +++ b/include/chaiscript/dispatchkit/boxed_number.hpp @@ -585,6 +585,59 @@ namespace chaiscript } + template + static void check_type() + { + if (sizeof(Source) != sizeof(Target) + || std::is_signed() != std::is_signed() + || std::is_floating_point() != std::is_floating_point()) + { + throw chaiscript::detail::exception::bad_any_cast(); + } + } + + template Target get_as_checked() const + { + switch (get_common_type(bv)) { + case Common_Types::t_int32: + check_type(); + return get_as_aux(bv); + case Common_Types::t_uint8: + check_type(); + return get_as_aux(bv); + case Common_Types::t_int8: + check_type(); + return get_as_aux(bv); + case Common_Types::t_uint16: + check_type(); + return get_as_aux(bv); + case Common_Types::t_int16: + check_type(); + return get_as_aux(bv); + case Common_Types::t_uint32: + check_type(); + return get_as_aux(bv); + case Common_Types::t_uint64: + check_type(); + return get_as_aux(bv); + case Common_Types::t_int64: + check_type(); + return get_as_aux(bv); + case Common_Types::t_double: + check_type(); + return get_as_aux(bv); + case Common_Types::t_float: + check_type(); + return get_as_aux(bv); + case Common_Types::t_long_double: + check_type(); + return get_as_aux(bv); + } + + throw chaiscript::detail::exception::bad_any_cast(); + } + + template Target get_as() const { switch (get_common_type(bv)) { diff --git a/unittests/integer_literal_test.cpp b/unittests/integer_literal_test.cpp index 4c20f286..9ac88081 100644 --- a/unittests/integer_literal_test.cpp +++ b/unittests/integer_literal_test.cpp @@ -19,7 +19,7 @@ bool test_literal(T val, const std::string &str, bool use_boxed_number = false) if (!use_boxed_number) { return chai.eval(str); } else { - return chai.eval(str).get_as(); + return chai.eval(str).get_as_checked(); } }(); @@ -126,66 +126,66 @@ int main() && test_literal(0x7FFFFFFFFFFFFFFF, "0b111111111111111111111111111111111111111111111111111111111111111") - && TEST_LITERAL(-0xF) - && TEST_LITERAL(-0xFF) - && TEST_LITERAL(-0xFFF) - && TEST_LITERAL(-0xFFFF) - && TEST_LITERAL(-0xFFFFF) - && TEST_LITERAL(-0xFFFFFF) - && TEST_LITERAL(-0xFFFFFFF) - && TEST_LITERAL(-0xFFFFFFFF) - && TEST_LITERAL(-0xFFFFFFFFF) - && TEST_LITERAL(-0xFFFFFFFFFF) - && TEST_LITERAL(-0xFFFFFFFFFFF) - && TEST_LITERAL(-0xFFFFFFFFFFFF) - && TEST_LITERAL(-0xFFFFFFFFFFFFF) - && TEST_LITERAL(-0xFFFFFFFFFFFFFF) - && TEST_LITERAL(-0xFFFFFFFFFFFFFFF) - && TEST_LITERAL(-0xFFFFFFFFFFFFFFFF) + && TEST_LITERAL_SIGNED(-0xF) + && TEST_LITERAL_SIGNED(-0xFF) + && TEST_LITERAL_SIGNED(-0xFFF) + && TEST_LITERAL_SIGNED(-0xFFFF) + && TEST_LITERAL_SIGNED(-0xFFFFF) + && TEST_LITERAL_SIGNED(-0xFFFFFF) + && TEST_LITERAL_SIGNED(-0xFFFFFFF) + && TEST_LITERAL_SIGNED(-0xFFFFFFFF) + && TEST_LITERAL_SIGNED(-0xFFFFFFFFF) + && TEST_LITERAL_SIGNED(-0xFFFFFFFFFF) + && TEST_LITERAL_SIGNED(-0xFFFFFFFFFFF) + && TEST_LITERAL_SIGNED(-0xFFFFFFFFFFFF) + && TEST_LITERAL_SIGNED(-0xFFFFFFFFFFFFF) + && TEST_LITERAL_SIGNED(-0xFFFFFFFFFFFFFF) + && TEST_LITERAL_SIGNED(-0xFFFFFFFFFFFFFFF) + && TEST_LITERAL_SIGNED(-0xFFFFFFFFFFFFFFFF) - && TEST_LITERAL(-01) - && TEST_LITERAL(-017) - && TEST_LITERAL(-0177) - && TEST_LITERAL(-01777) - && TEST_LITERAL(-017777) - && TEST_LITERAL(-0177777) - && TEST_LITERAL(-01777777) - && TEST_LITERAL(-017777777) - && TEST_LITERAL(-0177777777) - && TEST_LITERAL(-01777777777) - && TEST_LITERAL(-017777777777) - && TEST_LITERAL(-0177777777777) - && TEST_LITERAL(-01777777777777) - && TEST_LITERAL(-017777777777777) - && TEST_LITERAL(-0177777777777777) - && TEST_LITERAL(-01777777777777777) - && TEST_LITERAL(-017777777777777777) - && TEST_LITERAL(-0177777777777777777) - && TEST_LITERAL(-01777777777777777777) - && TEST_LITERAL(-017777777777777777777) - && TEST_LITERAL(-0177777777777777777777) - && TEST_LITERAL(-01777777777777777777777) + && TEST_LITERAL_SIGNED(-01) + && TEST_LITERAL_SIGNED(-017) + && TEST_LITERAL_SIGNED(-0177) + && TEST_LITERAL_SIGNED(-01777) + && TEST_LITERAL_SIGNED(-017777) + && TEST_LITERAL_SIGNED(-0177777) + && TEST_LITERAL_SIGNED(-01777777) + && TEST_LITERAL_SIGNED(-017777777) + && TEST_LITERAL_SIGNED(-0177777777) + && TEST_LITERAL_SIGNED(-01777777777) + && TEST_LITERAL_SIGNED(-017777777777) + && TEST_LITERAL_SIGNED(-0177777777777) + && TEST_LITERAL_SIGNED(-01777777777777) + && TEST_LITERAL_SIGNED(-017777777777777) + && TEST_LITERAL_SIGNED(-0177777777777777) + && TEST_LITERAL_SIGNED(-01777777777777777) + && TEST_LITERAL_SIGNED(-017777777777777777) + && TEST_LITERAL_SIGNED(-0177777777777777777) + && TEST_LITERAL_SIGNED(-01777777777777777777) + && TEST_LITERAL_SIGNED(-017777777777777777777) + && TEST_LITERAL_SIGNED(-0177777777777777777777) + && TEST_LITERAL_SIGNED(-01777777777777777777777) - && TEST_LITERAL(-1) - && TEST_LITERAL(-17) - && TEST_LITERAL(-177) - && TEST_LITERAL(-1777) - && TEST_LITERAL(-17777) - && TEST_LITERAL(-177777) - && TEST_LITERAL(-1777777) - && TEST_LITERAL(-17777777) - && TEST_LITERAL(-177777777) - && TEST_LITERAL(-1777777777) - && TEST_LITERAL(-17777777777) - && TEST_LITERAL(-177777777777) - && TEST_LITERAL(-1777777777777) - && TEST_LITERAL(-17777777777777) - && TEST_LITERAL(-177777777777777) - && TEST_LITERAL(-1777777777777777) - && TEST_LITERAL(-17777777777777777) - && TEST_LITERAL(-177777777777777777) - && TEST_LITERAL(-1777777777777777777) + && TEST_LITERAL_SIGNED(-1) + && TEST_LITERAL_SIGNED(-17) + && TEST_LITERAL_SIGNED(-177) + && TEST_LITERAL_SIGNED(-1777) + && TEST_LITERAL_SIGNED(-17777) + && TEST_LITERAL_SIGNED(-177777) + && TEST_LITERAL_SIGNED(-1777777) + && TEST_LITERAL_SIGNED(-17777777) + && TEST_LITERAL_SIGNED(-177777777) + && TEST_LITERAL_SIGNED(-1777777777) + && TEST_LITERAL_SIGNED(-17777777777) + && TEST_LITERAL_SIGNED(-177777777777) + && TEST_LITERAL_SIGNED(-1777777777777) + && TEST_LITERAL_SIGNED(-17777777777777) + && TEST_LITERAL_SIGNED(-177777777777777) + && TEST_LITERAL_SIGNED(-1777777777777777) + && TEST_LITERAL_SIGNED(-17777777777777777) + && TEST_LITERAL_SIGNED(-177777777777777777) + && TEST_LITERAL_SIGNED(-1777777777777777777) // Test 8/16/24/32 bit boundaries for various types @@ -194,10 +194,10 @@ int main() && TEST_LITERAL(16777215) && TEST_LITERAL(4294967295) - && TEST_LITERAL(-255) - && TEST_LITERAL(-65535) - && TEST_LITERAL(-16777215) - && TEST_LITERAL(-4294967295) + && TEST_LITERAL_SIGNED(-255) + && TEST_LITERAL_SIGNED(-65535) + && TEST_LITERAL_SIGNED(-16777215) + && TEST_LITERAL_SIGNED(-4294967295) && TEST_LITERAL(255u) && TEST_LITERAL(65535u) From 2ce155237df607b6efbd41e6f05216093cc88378 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 3 Feb 2017 18:55:58 -0800 Subject: [PATCH 31/84] Add test for unique_ptr returned from function --- unittests/compiled_tests.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/unittests/compiled_tests.cpp b/unittests/compiled_tests.cpp index 062cd13e..dc256ea5 100644 --- a/unittests/compiled_tests.cpp +++ b/unittests/compiled_tests.cpp @@ -1139,15 +1139,23 @@ class Unique_Ptr_Test_Class int getI() const {return 5;} }; + +std::unique_ptr make_Unique_Ptr_Test_Class() +{ + return std::make_unique(); +} + TEST_CASE("Call methods through unique_ptr") { chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser()); chai.add(chaiscript::var(std::make_unique()), "uptr"); + chai.add(chaiscript::fun(make_Unique_Ptr_Test_Class), "make_Unique_Ptr_Test_Class"); chai.add(chaiscript::fun(&Unique_Ptr_Test_Class::getI), "getI"); CHECK(chai.eval("uptr.getI()") == 5); -} + CHECK(chai.eval("var uptr2 = make_Unique_Ptr_Test_Class(); uptr2.getI()") == 5); +} class A From 1cb15d8b226818464495399d57ac95edc8bb3012 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 3 Feb 2017 19:34:12 -0800 Subject: [PATCH 32/84] Handle return of std::unique_ptr objects --- include/chaiscript/dispatchkit/handle_return.hpp | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/include/chaiscript/dispatchkit/handle_return.hpp b/include/chaiscript/dispatchkit/handle_return.hpp index 2b770ac5..4d0930e1 100644 --- a/include/chaiscript/dispatchkit/handle_return.hpp +++ b/include/chaiscript/dispatchkit/handle_return.hpp @@ -27,9 +27,7 @@ namespace chaiscript namespace detail { - /** - * Used internally for handling a return value from a Proxy_Function call - */ + /// Used internally for handling a return value from a Proxy_Function call template struct Handle_Return { @@ -155,6 +153,18 @@ namespace chaiscript { }; + + template + struct Handle_Return> : Handle_Return &> + { + static Boxed_Value handle(std::unique_ptr &&r) + { + return Boxed_Value(std::move(r), true); + } + }; + + + template struct Handle_Return { From 2549b4e9839924c1c132e150c4c0dc280a418d8f Mon Sep 17 00:00:00 2001 From: Gabriel Aubut-Lussier Date: Fri, 3 Feb 2017 23:19:25 -0500 Subject: [PATCH 33/84] Add test to call base class methods through std::unique_ptr. --- unittests/compiled_tests.cpp | 38 ++++++++++++++++++++++++++++++------ 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/unittests/compiled_tests.cpp b/unittests/compiled_tests.cpp index dc256ea5..44f23bdf 100644 --- a/unittests/compiled_tests.cpp +++ b/unittests/compiled_tests.cpp @@ -1147,14 +1147,40 @@ std::unique_ptr make_Unique_Ptr_Test_Class() TEST_CASE("Call methods through unique_ptr") { - chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser()); + chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser()); - chai.add(chaiscript::var(std::make_unique()), "uptr"); - chai.add(chaiscript::fun(make_Unique_Ptr_Test_Class), "make_Unique_Ptr_Test_Class"); - chai.add(chaiscript::fun(&Unique_Ptr_Test_Class::getI), "getI"); - CHECK(chai.eval("uptr.getI()") == 5); - CHECK(chai.eval("var uptr2 = make_Unique_Ptr_Test_Class(); uptr2.getI()") == 5); + chai.add(chaiscript::var(std::make_unique()), "uptr"); + chai.add(chaiscript::fun(make_Unique_Ptr_Test_Class), "make_Unique_Ptr_Test_Class"); + chai.add(chaiscript::fun(&Unique_Ptr_Test_Class::getI), "getI"); + CHECK(chai.eval("uptr.getI()") == 5); + CHECK(chai.eval("var uptr2 = make_Unique_Ptr_Test_Class(); uptr2.getI()") == 5); +} + +class Unique_Ptr_Test_Base_Class +{ + public: + int getI() const {return 5;} +}; + +class Unique_Ptr_Test_Derived_Class : public Unique_Ptr_Test_Base_Class +{}; + +std::unique_ptr make_Unique_Ptr_Test_Derived_Class() +{ + return std::make_unique(); +} + +TEST_CASE("Call methods on base class through unique_ptr") +{ + chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser()); + + chai.add(chaiscript::var(std::make_unique()), "uptr"); + chai.add(chaiscript::fun(make_Unique_Ptr_Test_Derived_Class), "make_Unique_Ptr_Test_Derived_Class"); + chai.add(chaiscript::fun(&Unique_Ptr_Test_Base_Class::getI), "getI"); + chai.add(chaiscript::base_class()); + CHECK(chai.eval("uptr.getI()") == 5); + CHECK(chai.eval("var uptr2 = make_Unique_Ptr_Test_Derived_Class(); uptr2.getI()") == 5); } From 077c93ab27a0d8292546de549397fbfd15772386 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 4 Feb 2017 09:14:07 -0800 Subject: [PATCH 34/84] Fix/enhance unique_ptr support --- include/chaiscript/dispatchkit/boxed_cast_helper.hpp | 11 +++++++++++ include/chaiscript/dispatchkit/boxed_value.hpp | 6 +++--- unittests/compiled_tests.cpp | 9 +++++++++ 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/include/chaiscript/dispatchkit/boxed_cast_helper.hpp b/include/chaiscript/dispatchkit/boxed_cast_helper.hpp index 4a0c3081..c8dce2e1 100644 --- a/include/chaiscript/dispatchkit/boxed_cast_helper.hpp +++ b/include/chaiscript/dispatchkit/boxed_cast_helper.hpp @@ -167,6 +167,17 @@ namespace chaiscript } }; + /// Cast_Helper_Inner for casting to a std::unique_ptr<> & type + /// \todo Fix the fact that this has to be in a shared_ptr for now + template + struct Cast_Helper_Inner &> + { + static std::unique_ptr &cast(const Boxed_Value &ob, const Type_Conversions_State *) + { + return *(ob.get().cast>>()); + } + }; + /// Cast_Helper_Inner for casting to a std::shared_ptr<> type template diff --git a/include/chaiscript/dispatchkit/boxed_value.hpp b/include/chaiscript/dispatchkit/boxed_value.hpp index 8b3d763b..938aab00 100644 --- a/include/chaiscript/dispatchkit/boxed_value.hpp +++ b/include/chaiscript/dispatchkit/boxed_value.hpp @@ -35,11 +35,11 @@ namespace chaiscript { Data(const Type_Info &ti, chaiscript::detail::Any to, - bool tr, + bool is_ref, const void *t_void_ptr, bool t_return_value) : m_type_info(ti), m_obj(std::move(to)), m_data_ptr(ti.is_const()?nullptr:const_cast(t_void_ptr)), m_const_data_ptr(t_void_ptr), - m_is_ref(tr), m_return_value(t_return_value) + m_is_ref(is_ref), m_return_value(t_return_value) { } @@ -154,7 +154,7 @@ namespace chaiscript return std::make_shared( detail::Get_Type_Info::get(), chaiscript::detail::Any(std::make_shared>(std::move(obj))), - false, + true, ptr, t_return_value ); diff --git a/unittests/compiled_tests.cpp b/unittests/compiled_tests.cpp index 44f23bdf..1a94c738 100644 --- a/unittests/compiled_tests.cpp +++ b/unittests/compiled_tests.cpp @@ -1113,6 +1113,9 @@ TEST_CASE("Use unique_ptr") chai.add(chaiscript::fun([](int &i){ ++i; }), "inci"); chai.add(chaiscript::fun([](int i){ ++i; }), "copyi"); chai.add(chaiscript::fun([](int *i){ ++(*i); }), "derefi"); + chai.add(chaiscript::fun([](const std::unique_ptr &i){ ++(*i); }), "constrefuniqptri"); + chai.add(chaiscript::fun([](std::unique_ptr &i){ ++(*i); }), "refuniqptri"); + chai.add(chaiscript::fun([](std::unique_ptr &&i){ ++(*i); }), "rvaluniqptri"); chai.add(chaiscript::var(std::make_unique(1)), "iptr"); @@ -1123,6 +1126,12 @@ TEST_CASE("Use unique_ptr") CHECK(chai.eval("iptr") == 2); chai.eval("derefi(iptr)"); CHECK(chai.eval("iptr") == 3); + chai.eval("constrefuniqptri(iptr)"); + CHECK(chai.eval("iptr") == 4); + chai.eval("refuniqptri(iptr)"); + CHECK(chai.eval("iptr") == 5); + chai.eval("rvaluniqptri(iptr)"); + CHECK(chai.eval("iptr") == 6); } From faba0f1317bc53173b10482815e4840b42144b38 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 15 Feb 2017 15:38:44 -0700 Subject: [PATCH 35/84] Require thread_local support, move to xcode8 --- .travis.yml | 1 + include/chaiscript/chaiscript_defines.hpp | 4 -- include/chaiscript/chaiscript_threading.hpp | 64 --------------------- 3 files changed, 1 insertion(+), 68 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5aee8f05..c7a33cf2 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,6 +29,7 @@ matrix: compiler: gcc - os: osx compiler: clang + osx_image: xcode8 env: diff --git a/include/chaiscript/chaiscript_defines.hpp b/include/chaiscript/chaiscript_defines.hpp index 7e016990..cf60a799 100644 --- a/include/chaiscript/chaiscript_defines.hpp +++ b/include/chaiscript/chaiscript_defines.hpp @@ -48,10 +48,6 @@ static_assert(_MSC_FULL_VER >= 190024210, "Visual C++ 2015 Update 3 or later req #endif #endif -#if defined(CHAISCRIPT_MSVC) || (defined(__GNUC__) && __GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) || (defined(__llvm__) && !defined(CHAISCRIPT_LIBCPP)) -/// \todo Make this support other compilers when possible -#define CHAISCRIPT_HAS_THREAD_LOCAL -#endif #if defined(__llvm__) #define CHAISCRIPT_CLANG diff --git a/include/chaiscript/chaiscript_threading.hpp b/include/chaiscript/chaiscript_threading.hpp index 0d2825f7..e8f097fd 100644 --- a/include/chaiscript/chaiscript_threading.hpp +++ b/include/chaiscript/chaiscript_threading.hpp @@ -57,7 +57,6 @@ namespace chaiscript using std::recursive_mutex; -#ifdef CHAISCRIPT_HAS_THREAD_LOCAL /// Typesafe thread specific storage. If threading is enabled, this class uses a mutex protected map. If /// threading is not enabled, the class always returns the same data, regardless of which thread it is called from. template @@ -106,69 +105,6 @@ namespace chaiscript } }; -#else - -#pragma message ("Threading without thread_local support is not well supported.") - - - /// Typesafe thread specific storage. If threading is enabled, this class uses a mutex protected map. If - /// threading is not enabled, the class always returns the same data, regardless of which thread it is called from. - /// - /// This version is used if the compiler does not support thread_local - template - class Thread_Storage - { - public: - - explicit Thread_Storage(void *) - { - } - - inline const T *operator->() const - { - return get_tls().get(); - } - - inline const T &operator*() const - { - return *get_tls(); - } - - inline T *operator->() - { - return get_tls().get(); - } - - inline T &operator*() - { - return *get_tls(); - } - - - private: - /// \todo this leaks thread instances. It needs to be culled from time to time - std::shared_ptr get_tls() const - { - unique_lock lock(m_mutex); - - const auto id = std::this_thread::get_id(); - auto itr = m_instances.find(id); - - if (itr != m_instances.end()) { return itr->second; } - - std::shared_ptr new_instance(std::make_shared()); - - m_instances.insert(std::make_pair(id, new_instance)); - - return new_instance; - } - - - mutable mutex m_mutex; - mutable std::unordered_map > m_instances; - }; -#endif // threading enabled but no tls - #else // threading disabled template class unique_lock From 87f1242ed421816ff11ae99cff2a6cec82f18a98 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 15 Feb 2017 15:55:40 -0700 Subject: [PATCH 36/84] Update copyrights to 2017 --- include/chaiscript/chaiscript.hpp | 2 +- include/chaiscript/chaiscript_basic.hpp | 2 +- include/chaiscript/chaiscript_defines.hpp | 2 +- include/chaiscript/chaiscript_threading.hpp | 2 +- include/chaiscript/dispatchkit/bad_boxed_cast.hpp | 2 +- include/chaiscript/dispatchkit/bind_first.hpp | 2 +- include/chaiscript/dispatchkit/bootstrap.hpp | 2 +- include/chaiscript/dispatchkit/bootstrap_stl.hpp | 2 +- include/chaiscript/dispatchkit/boxed_cast.hpp | 2 +- include/chaiscript/dispatchkit/boxed_cast_helper.hpp | 2 +- include/chaiscript/dispatchkit/boxed_number.hpp | 2 +- include/chaiscript/dispatchkit/boxed_value.hpp | 2 +- include/chaiscript/dispatchkit/callable_traits.hpp | 2 +- include/chaiscript/dispatchkit/dispatchkit.hpp | 2 +- include/chaiscript/dispatchkit/dynamic_object.hpp | 2 +- include/chaiscript/dispatchkit/dynamic_object_detail.hpp | 2 +- include/chaiscript/dispatchkit/exception_specification.hpp | 2 +- include/chaiscript/dispatchkit/function_call.hpp | 2 +- include/chaiscript/dispatchkit/function_call_detail.hpp | 2 +- include/chaiscript/dispatchkit/handle_return.hpp | 2 +- include/chaiscript/dispatchkit/operators.hpp | 2 +- include/chaiscript/dispatchkit/proxy_constructors.hpp | 2 +- include/chaiscript/dispatchkit/proxy_functions.hpp | 2 +- include/chaiscript/dispatchkit/proxy_functions_detail.hpp | 2 +- include/chaiscript/dispatchkit/register_function.hpp | 2 +- include/chaiscript/dispatchkit/type_conversions.hpp | 2 +- include/chaiscript/dispatchkit/type_info.hpp | 2 +- include/chaiscript/language/chaiscript_algebraic.hpp | 2 +- include/chaiscript/language/chaiscript_common.hpp | 2 +- include/chaiscript/language/chaiscript_engine.hpp | 2 +- include/chaiscript/language/chaiscript_eval.hpp | 2 +- include/chaiscript/language/chaiscript_optimizer.hpp | 2 +- include/chaiscript/language/chaiscript_parser.hpp | 2 +- include/chaiscript/language/chaiscript_posix.hpp | 2 +- include/chaiscript/language/chaiscript_prelude.hpp | 2 +- include/chaiscript/language/chaiscript_tracer.hpp | 2 +- include/chaiscript/language/chaiscript_unknown.hpp | 2 +- include/chaiscript/language/chaiscript_windows.hpp | 2 +- include/chaiscript/utility/fnv1a.hpp | 2 +- include/chaiscript/utility/static_string.hpp | 2 +- include/chaiscript/utility/utility.hpp | 2 +- readme.md | 2 +- samples/fun_call_performance.cpp | 2 +- src/main.cpp | 2 +- src/stl_extra.cpp | 2 +- 45 files changed, 45 insertions(+), 45 deletions(-) diff --git a/include/chaiscript/chaiscript.hpp b/include/chaiscript/chaiscript.hpp index b3fefc9e..a6fed122 100644 --- a/include/chaiscript/chaiscript.hpp +++ b/include/chaiscript/chaiscript.hpp @@ -1,7 +1,7 @@ // This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) -// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2017, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_HPP_ diff --git a/include/chaiscript/chaiscript_basic.hpp b/include/chaiscript/chaiscript_basic.hpp index 28f26d79..b770b1b7 100644 --- a/include/chaiscript/chaiscript_basic.hpp +++ b/include/chaiscript/chaiscript_basic.hpp @@ -1,7 +1,7 @@ // This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) -// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2017, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_BASIC_HPP_ diff --git a/include/chaiscript/chaiscript_defines.hpp b/include/chaiscript/chaiscript_defines.hpp index cf60a799..cc349a0b 100644 --- a/include/chaiscript/chaiscript_defines.hpp +++ b/include/chaiscript/chaiscript_defines.hpp @@ -1,7 +1,7 @@ // This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) -// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2017, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_DEFINES_HPP_ diff --git a/include/chaiscript/chaiscript_threading.hpp b/include/chaiscript/chaiscript_threading.hpp index e8f097fd..fb958879 100644 --- a/include/chaiscript/chaiscript_threading.hpp +++ b/include/chaiscript/chaiscript_threading.hpp @@ -1,7 +1,7 @@ // This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) -// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2017, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_THREADING_HPP_ diff --git a/include/chaiscript/dispatchkit/bad_boxed_cast.hpp b/include/chaiscript/dispatchkit/bad_boxed_cast.hpp index 8547b977..c9fec769 100644 --- a/include/chaiscript/dispatchkit/bad_boxed_cast.hpp +++ b/include/chaiscript/dispatchkit/bad_boxed_cast.hpp @@ -1,7 +1,7 @@ // This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) -// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2017, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_BAD_BOXED_CAST_HPP_ diff --git a/include/chaiscript/dispatchkit/bind_first.hpp b/include/chaiscript/dispatchkit/bind_first.hpp index 98da1deb..5d1ae057 100644 --- a/include/chaiscript/dispatchkit/bind_first.hpp +++ b/include/chaiscript/dispatchkit/bind_first.hpp @@ -1,7 +1,7 @@ // This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) -// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2017, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_BIND_FIRST_HPP_ diff --git a/include/chaiscript/dispatchkit/bootstrap.hpp b/include/chaiscript/dispatchkit/bootstrap.hpp index 45143636..279fbc08 100644 --- a/include/chaiscript/dispatchkit/bootstrap.hpp +++ b/include/chaiscript/dispatchkit/bootstrap.hpp @@ -1,7 +1,7 @@ // This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) -// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2017, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_BOOTSTRAP_HPP_ diff --git a/include/chaiscript/dispatchkit/bootstrap_stl.hpp b/include/chaiscript/dispatchkit/bootstrap_stl.hpp index e2ec267f..863e990a 100644 --- a/include/chaiscript/dispatchkit/bootstrap_stl.hpp +++ b/include/chaiscript/dispatchkit/bootstrap_stl.hpp @@ -1,7 +1,7 @@ // This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) -// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2017, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com /// \file diff --git a/include/chaiscript/dispatchkit/boxed_cast.hpp b/include/chaiscript/dispatchkit/boxed_cast.hpp index 7fbe78d3..935cebdd 100644 --- a/include/chaiscript/dispatchkit/boxed_cast.hpp +++ b/include/chaiscript/dispatchkit/boxed_cast.hpp @@ -1,7 +1,7 @@ // This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) -// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2017, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_BOXED_CAST_HPP_ diff --git a/include/chaiscript/dispatchkit/boxed_cast_helper.hpp b/include/chaiscript/dispatchkit/boxed_cast_helper.hpp index c8dce2e1..02728d32 100644 --- a/include/chaiscript/dispatchkit/boxed_cast_helper.hpp +++ b/include/chaiscript/dispatchkit/boxed_cast_helper.hpp @@ -1,7 +1,7 @@ // This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) -// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2017, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_BOXED_CAST_HELPER_HPP_ diff --git a/include/chaiscript/dispatchkit/boxed_number.hpp b/include/chaiscript/dispatchkit/boxed_number.hpp index 68b2f0b8..0eb68304 100644 --- a/include/chaiscript/dispatchkit/boxed_number.hpp +++ b/include/chaiscript/dispatchkit/boxed_number.hpp @@ -1,7 +1,7 @@ // This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) -// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2017, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_BOXED_NUMERIC_HPP_ diff --git a/include/chaiscript/dispatchkit/boxed_value.hpp b/include/chaiscript/dispatchkit/boxed_value.hpp index 938aab00..6032ac11 100644 --- a/include/chaiscript/dispatchkit/boxed_value.hpp +++ b/include/chaiscript/dispatchkit/boxed_value.hpp @@ -1,7 +1,7 @@ // This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) -// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2017, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_BOXED_VALUE_HPP_ diff --git a/include/chaiscript/dispatchkit/callable_traits.hpp b/include/chaiscript/dispatchkit/callable_traits.hpp index 7bbfbd0b..4b61b088 100644 --- a/include/chaiscript/dispatchkit/callable_traits.hpp +++ b/include/chaiscript/dispatchkit/callable_traits.hpp @@ -1,7 +1,7 @@ // This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) -// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2017, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_CALLABLE_TRAITS_HPP_ diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index a83747e2..2d6b2155 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -1,7 +1,7 @@ // This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) -// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2017, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_DISPATCHKIT_HPP_ diff --git a/include/chaiscript/dispatchkit/dynamic_object.hpp b/include/chaiscript/dispatchkit/dynamic_object.hpp index ee972320..2821f2e6 100644 --- a/include/chaiscript/dispatchkit/dynamic_object.hpp +++ b/include/chaiscript/dispatchkit/dynamic_object.hpp @@ -1,7 +1,7 @@ // This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) -// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2017, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_DYNAMIC_OBJECT_HPP_ diff --git a/include/chaiscript/dispatchkit/dynamic_object_detail.hpp b/include/chaiscript/dispatchkit/dynamic_object_detail.hpp index 8fbc373d..df90ab66 100644 --- a/include/chaiscript/dispatchkit/dynamic_object_detail.hpp +++ b/include/chaiscript/dispatchkit/dynamic_object_detail.hpp @@ -1,7 +1,7 @@ // This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) -// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2017, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_DYNAMIC_OBJECT_DETAIL_HPP_ diff --git a/include/chaiscript/dispatchkit/exception_specification.hpp b/include/chaiscript/dispatchkit/exception_specification.hpp index 0c9b40f9..8dbee03e 100644 --- a/include/chaiscript/dispatchkit/exception_specification.hpp +++ b/include/chaiscript/dispatchkit/exception_specification.hpp @@ -1,7 +1,7 @@ // This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) -// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2017, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_EXCEPTION_SPECIFICATION_HPP_ diff --git a/include/chaiscript/dispatchkit/function_call.hpp b/include/chaiscript/dispatchkit/function_call.hpp index 3efb7031..dfb6f370 100644 --- a/include/chaiscript/dispatchkit/function_call.hpp +++ b/include/chaiscript/dispatchkit/function_call.hpp @@ -1,7 +1,7 @@ // This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) -// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2017, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_FUNCTION_CALL_HPP_ diff --git a/include/chaiscript/dispatchkit/function_call_detail.hpp b/include/chaiscript/dispatchkit/function_call_detail.hpp index 93e3e61c..a66194da 100644 --- a/include/chaiscript/dispatchkit/function_call_detail.hpp +++ b/include/chaiscript/dispatchkit/function_call_detail.hpp @@ -1,7 +1,7 @@ // This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) -// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2017, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_FUNCTION_CALL_DETAIL_HPP_ diff --git a/include/chaiscript/dispatchkit/handle_return.hpp b/include/chaiscript/dispatchkit/handle_return.hpp index 4d0930e1..6ca37823 100644 --- a/include/chaiscript/dispatchkit/handle_return.hpp +++ b/include/chaiscript/dispatchkit/handle_return.hpp @@ -1,7 +1,7 @@ // This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) -// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2017, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_HANDLE_RETURN_HPP_ diff --git a/include/chaiscript/dispatchkit/operators.hpp b/include/chaiscript/dispatchkit/operators.hpp index 4ebaec55..1c123f37 100644 --- a/include/chaiscript/dispatchkit/operators.hpp +++ b/include/chaiscript/dispatchkit/operators.hpp @@ -1,7 +1,7 @@ // This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) -// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2017, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_OPERATORS_HPP_ diff --git a/include/chaiscript/dispatchkit/proxy_constructors.hpp b/include/chaiscript/dispatchkit/proxy_constructors.hpp index a5ad41ec..14e0a134 100644 --- a/include/chaiscript/dispatchkit/proxy_constructors.hpp +++ b/include/chaiscript/dispatchkit/proxy_constructors.hpp @@ -1,7 +1,7 @@ // This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) -// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2017, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index 67b94c06..6ad5dae2 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -1,7 +1,7 @@ // This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) -// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2017, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com diff --git a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp index f00eeef5..496ccb9a 100644 --- a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp @@ -1,7 +1,7 @@ // This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) -// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2017, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_ diff --git a/include/chaiscript/dispatchkit/register_function.hpp b/include/chaiscript/dispatchkit/register_function.hpp index 1c58840a..b1e5da0e 100644 --- a/include/chaiscript/dispatchkit/register_function.hpp +++ b/include/chaiscript/dispatchkit/register_function.hpp @@ -1,7 +1,7 @@ // This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) -// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2017, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_REGISTER_FUNCTION_HPP_ diff --git a/include/chaiscript/dispatchkit/type_conversions.hpp b/include/chaiscript/dispatchkit/type_conversions.hpp index 3a546c67..4c2f596f 100644 --- a/include/chaiscript/dispatchkit/type_conversions.hpp +++ b/include/chaiscript/dispatchkit/type_conversions.hpp @@ -1,7 +1,7 @@ // This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) -// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2017, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_ diff --git a/include/chaiscript/dispatchkit/type_info.hpp b/include/chaiscript/dispatchkit/type_info.hpp index 592271a8..034fe844 100644 --- a/include/chaiscript/dispatchkit/type_info.hpp +++ b/include/chaiscript/dispatchkit/type_info.hpp @@ -1,7 +1,7 @@ // This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) -// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2017, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_TYPE_INFO_HPP_ diff --git a/include/chaiscript/language/chaiscript_algebraic.hpp b/include/chaiscript/language/chaiscript_algebraic.hpp index 022a295c..99b361ee 100644 --- a/include/chaiscript/language/chaiscript_algebraic.hpp +++ b/include/chaiscript/language/chaiscript_algebraic.hpp @@ -1,7 +1,7 @@ // This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) -// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2017, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_ALGEBRAIC_HPP_ diff --git a/include/chaiscript/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index abcfe5bf..32f5c946 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -1,7 +1,7 @@ // This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) -// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2017, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_COMMON_HPP_ diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index f4550e8a..e4376bed 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -1,7 +1,7 @@ // This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) -// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2017, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_ENGINE_HPP_ diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index c6143f15..36814d69 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -1,7 +1,7 @@ // This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) -// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2017, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_EVAL_HPP_ diff --git a/include/chaiscript/language/chaiscript_optimizer.hpp b/include/chaiscript/language/chaiscript_optimizer.hpp index 54e1fdbc..996b6971 100644 --- a/include/chaiscript/language/chaiscript_optimizer.hpp +++ b/include/chaiscript/language/chaiscript_optimizer.hpp @@ -1,7 +1,7 @@ // This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) -// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2017, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_OPTIMIZER_HPP_ diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 913b995a..ce5ddcf2 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -1,7 +1,7 @@ // This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) -// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2017, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_PARSER_HPP_ diff --git a/include/chaiscript/language/chaiscript_posix.hpp b/include/chaiscript/language/chaiscript_posix.hpp index 2ffcff70..62f1c117 100644 --- a/include/chaiscript/language/chaiscript_posix.hpp +++ b/include/chaiscript/language/chaiscript_posix.hpp @@ -1,7 +1,7 @@ // This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) -// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2017, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_POSIX_HPP_ diff --git a/include/chaiscript/language/chaiscript_prelude.hpp b/include/chaiscript/language/chaiscript_prelude.hpp index 98e09026..a4deb874 100644 --- a/include/chaiscript/language/chaiscript_prelude.hpp +++ b/include/chaiscript/language/chaiscript_prelude.hpp @@ -1,7 +1,7 @@ // This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) -// and 2009-2016, Jason Turner (jason@emptycrate.com) +// and 2009-2017, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_PRELUDE_HPP_ diff --git a/include/chaiscript/language/chaiscript_tracer.hpp b/include/chaiscript/language/chaiscript_tracer.hpp index 4b27d2bf..9d111815 100644 --- a/include/chaiscript/language/chaiscript_tracer.hpp +++ b/include/chaiscript/language/chaiscript_tracer.hpp @@ -1,7 +1,7 @@ // This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) -// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2017, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_TRACER_HPP_ diff --git a/include/chaiscript/language/chaiscript_unknown.hpp b/include/chaiscript/language/chaiscript_unknown.hpp index 2e5c2283..9e1d7afc 100644 --- a/include/chaiscript/language/chaiscript_unknown.hpp +++ b/include/chaiscript/language/chaiscript_unknown.hpp @@ -1,7 +1,7 @@ // This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) -// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2017, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_UNKNOWN_HPP_ diff --git a/include/chaiscript/language/chaiscript_windows.hpp b/include/chaiscript/language/chaiscript_windows.hpp index 55f9af92..493572c2 100644 --- a/include/chaiscript/language/chaiscript_windows.hpp +++ b/include/chaiscript/language/chaiscript_windows.hpp @@ -1,7 +1,7 @@ // This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) -// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2017, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_WINDOWS_HPP_ diff --git a/include/chaiscript/utility/fnv1a.hpp b/include/chaiscript/utility/fnv1a.hpp index b8c01874..9e549928 100644 --- a/include/chaiscript/utility/fnv1a.hpp +++ b/include/chaiscript/utility/fnv1a.hpp @@ -1,7 +1,7 @@ // This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) -// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2017, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_UTILITY_FNV1A_HPP_ diff --git a/include/chaiscript/utility/static_string.hpp b/include/chaiscript/utility/static_string.hpp index 5a570041..49edfbd8 100644 --- a/include/chaiscript/utility/static_string.hpp +++ b/include/chaiscript/utility/static_string.hpp @@ -1,7 +1,7 @@ // This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) -// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2017, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_UTILITY_STATIC_STRING_HPP_ diff --git a/include/chaiscript/utility/utility.hpp b/include/chaiscript/utility/utility.hpp index 11262ff0..37438f73 100644 --- a/include/chaiscript/utility/utility.hpp +++ b/include/chaiscript/utility/utility.hpp @@ -1,7 +1,7 @@ // This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) -// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2017, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_UTILITY_UTILITY_HPP_ diff --git a/readme.md b/readme.md index ddb0ed3d..26efc9a7 100644 --- a/readme.md +++ b/readme.md @@ -17,7 +17,7 @@ ChaiScript http://www.chaiscript.com (c) 2009-2012 Jonathan Turner -(c) 2009-2016 Jason Turner +(c) 2009-2017 Jason Turner Release under the BSD license, see "license.txt" for details. diff --git a/samples/fun_call_performance.cpp b/samples/fun_call_performance.cpp index 90fd7d94..68a122f8 100644 --- a/samples/fun_call_performance.cpp +++ b/samples/fun_call_performance.cpp @@ -1,7 +1,7 @@ // This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) -// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2017, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #include diff --git a/src/main.cpp b/src/main.cpp index ae2d4907..eb9a245b 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,7 +1,7 @@ // This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) -// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2017, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #include diff --git a/src/stl_extra.cpp b/src/stl_extra.cpp index 07bc0609..4442df92 100644 --- a/src/stl_extra.cpp +++ b/src/stl_extra.cpp @@ -1,7 +1,7 @@ // This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) -// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2017, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #include From f5f6ddf219c9adbbb369cd4def3d559d5601ea03 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Mon, 20 Feb 2017 13:28:31 -0700 Subject: [PATCH 37/84] Disable tests on MSVC for broken literal handling --- unittests/integer_literal_test.cpp | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/unittests/integer_literal_test.cpp b/unittests/integer_literal_test.cpp index 9ac88081..114883c4 100644 --- a/unittests/integer_literal_test.cpp +++ b/unittests/integer_literal_test.cpp @@ -192,12 +192,18 @@ int main() && TEST_LITERAL(255) && TEST_LITERAL(65535) && TEST_LITERAL(16777215) - && TEST_LITERAL(4294967295) +#ifndef CHAISCRIPT_MSVC + // bug in cl.exe causes this to be incorrectly parsed as an unsigned + && TEST_LITERAL(4294967295) +#endif && TEST_LITERAL_SIGNED(-255) && TEST_LITERAL_SIGNED(-65535) && TEST_LITERAL_SIGNED(-16777215) - && TEST_LITERAL_SIGNED(-4294967295) +#ifndef CHAISCRIPT_MSVC + // bug in cl.exe causes this to be incorrectly parsed as an unsigned + && TEST_LITERAL_SIGNED(-4294967295) +#endif && TEST_LITERAL(255u) && TEST_LITERAL(65535u) @@ -212,12 +218,18 @@ int main() && TEST_LITERAL(255l) && TEST_LITERAL(65535l) && TEST_LITERAL(16777215l) - && TEST_LITERAL(4294967295l) +#ifndef CHAISCRIPT_MSVC + // bug in cl.exe causes this to be incorrectly parsed as an unsigned + && TEST_LITERAL(4294967295l) +#endif && TEST_LITERAL_SIGNED(-255l) && TEST_LITERAL_SIGNED(-65535l) && TEST_LITERAL_SIGNED(-16777215l) - && TEST_LITERAL_SIGNED(-4294967295l) +#ifndef CHAISCRIPT_MSVC + // bug in cl.exe causes this to be incorrectly parsed as an unsigned + && TEST_LITERAL_SIGNED(-4294967295l) +#endif && TEST_LITERAL(255ul) && TEST_LITERAL(65535ul) From 40fb8d257e7ebb49cc0aa0ad4f3898dbcd10bcbe Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 22 Feb 2017 13:55:02 -0700 Subject: [PATCH 38/84] Fix warnings from MSVC --- include/chaiscript/dispatchkit/boxed_number.hpp | 7 +++++++ include/chaiscript/language/chaiscript_engine.hpp | 3 --- unittests/integer_literal_test.cpp | 15 +++++++++++---- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/include/chaiscript/dispatchkit/boxed_number.hpp b/include/chaiscript/dispatchkit/boxed_number.hpp index 68b2f0b8..2d44b7ea 100644 --- a/include/chaiscript/dispatchkit/boxed_number.hpp +++ b/include/chaiscript/dispatchkit/boxed_number.hpp @@ -588,12 +588,19 @@ namespace chaiscript template static void check_type() { +#ifdef CHAISCRIPT_MSVC +#pragma warning(push) +#pragma warning(disable : 4127) +#endif if (sizeof(Source) != sizeof(Target) || std::is_signed() != std::is_signed() || std::is_floating_point() != std::is_floating_point()) { throw chaiscript::detail::exception::bad_any_cast(); } +#ifdef CHAISCRIPT_MSVC +#pragma warning(pop) +#endif } template Target get_as_checked() const diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index f4550e8a..828fc409 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -145,9 +145,6 @@ namespace chaiscript }) , "call_exists"); -// m_engine.add(fun &)>(std::bind(&chaiscript::dispatch::Proxy_Function_Base::operator(), std::placeholders::_1, std::placeholders::_2, std::ref(m_engine.conversions()))), "call"); -// -// m_engine.add(fun( [=](const dispatch::Proxy_Function_Base &t_fun, const std::vector &t_params) -> Boxed_Value { diff --git a/unittests/integer_literal_test.cpp b/unittests/integer_literal_test.cpp index 114883c4..9112374b 100644 --- a/unittests/integer_literal_test.cpp +++ b/unittests/integer_literal_test.cpp @@ -3,6 +3,12 @@ #include "../static_libs/chaiscript_stdlib.hpp" +#ifdef CHAISCRIPT_MSVC +#pragma warning(push) +#pragma warning(disable : 4146) +#endif + + #define TEST_LITERAL(v) test_literal(v, #v) #define TEST_LITERAL_SIGNED(v) test_literal(v, #v, true) @@ -269,8 +275,9 @@ int main() return EXIT_FAILURE; } - - - - } + + +#ifdef CHAISCRIPT_MSVC +#pragma warning(pop) +#endif From c0c0bd3172c7f70a01653c955a5d9bc76b9befee Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 22 Feb 2017 14:04:56 -0700 Subject: [PATCH 39/84] Address warning from MSVC /analyze --- unittests/integer_literal_test.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/unittests/integer_literal_test.cpp b/unittests/integer_literal_test.cpp index 9112374b..3187b65d 100644 --- a/unittests/integer_literal_test.cpp +++ b/unittests/integer_literal_test.cpp @@ -4,6 +4,7 @@ #ifdef CHAISCRIPT_MSVC +// ignore errors about negative unsigned integer literals #pragma warning(push) #pragma warning(disable : 4146) #endif From 283785faaff2c7287e95fc5b1459b8aada3154cb Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 22 Feb 2017 15:18:56 -0700 Subject: [PATCH 40/84] Add PVS Studio and address some issues it found --- include/chaiscript/chaiscript.hpp | 4 ++++ include/chaiscript/chaiscript_threading.hpp | 4 ++++ .../chaiscript/dispatchkit/bad_boxed_cast.hpp | 4 ++++ include/chaiscript/dispatchkit/bind_first.hpp | 4 ++++ include/chaiscript/dispatchkit/bootstrap.hpp | 4 ++++ .../chaiscript/dispatchkit/bootstrap_stl.hpp | 4 ++++ include/chaiscript/dispatchkit/boxed_cast.hpp | 4 ++++ .../dispatchkit/boxed_cast_helper.hpp | 4 ++++ .../chaiscript/dispatchkit/boxed_number.hpp | 6 +++++- include/chaiscript/dispatchkit/boxed_value.hpp | 4 ++++ include/chaiscript/dispatchkit/dispatchkit.hpp | 4 ++++ .../chaiscript/dispatchkit/dynamic_object.hpp | 4 ++++ .../dispatchkit/exception_specification.hpp | 4 ++++ .../chaiscript/dispatchkit/function_call.hpp | 4 ++++ .../dispatchkit/function_call_detail.hpp | 4 ++++ .../chaiscript/dispatchkit/handle_return.hpp | 4 ++++ include/chaiscript/dispatchkit/operators.hpp | 4 ++++ .../dispatchkit/proxy_constructors.hpp | 3 +++ .../chaiscript/dispatchkit/proxy_functions.hpp | 3 +++ .../dispatchkit/proxy_functions_detail.hpp | 4 ++++ .../dispatchkit/register_function.hpp | 4 ++++ .../dispatchkit/type_conversions.hpp | 18 +++++++++--------- include/chaiscript/dispatchkit/type_info.hpp | 4 ++++ .../language/chaiscript_algebraic.hpp | 4 ++++ .../chaiscript/language/chaiscript_common.hpp | 4 ++++ .../chaiscript/language/chaiscript_engine.hpp | 4 ++++ .../chaiscript/language/chaiscript_eval.hpp | 4 ++++ .../chaiscript/language/chaiscript_parser.hpp | 4 ++++ include/chaiscript/utility/utility.hpp | 4 ++++ samples/fun_call_performance.cpp | 4 ++++ src/main.cpp | 4 ++++ src/stl_extra.cpp | 4 ++++ unittests/compiled_tests.cpp | 2 +- 33 files changed, 133 insertions(+), 11 deletions(-) diff --git a/include/chaiscript/chaiscript.hpp b/include/chaiscript/chaiscript.hpp index b3fefc9e..632aa300 100644 --- a/include/chaiscript/chaiscript.hpp +++ b/include/chaiscript/chaiscript.hpp @@ -4,6 +4,10 @@ // Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + + #ifndef CHAISCRIPT_HPP_ #define CHAISCRIPT_HPP_ diff --git a/include/chaiscript/chaiscript_threading.hpp b/include/chaiscript/chaiscript_threading.hpp index e8f097fd..5c3e0b4f 100644 --- a/include/chaiscript/chaiscript_threading.hpp +++ b/include/chaiscript/chaiscript_threading.hpp @@ -4,6 +4,10 @@ // Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + + #ifndef CHAISCRIPT_THREADING_HPP_ #define CHAISCRIPT_THREADING_HPP_ diff --git a/include/chaiscript/dispatchkit/bad_boxed_cast.hpp b/include/chaiscript/dispatchkit/bad_boxed_cast.hpp index 8547b977..3529578c 100644 --- a/include/chaiscript/dispatchkit/bad_boxed_cast.hpp +++ b/include/chaiscript/dispatchkit/bad_boxed_cast.hpp @@ -4,6 +4,10 @@ // Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + + #ifndef CHAISCRIPT_BAD_BOXED_CAST_HPP_ #define CHAISCRIPT_BAD_BOXED_CAST_HPP_ diff --git a/include/chaiscript/dispatchkit/bind_first.hpp b/include/chaiscript/dispatchkit/bind_first.hpp index 98da1deb..edd365cb 100644 --- a/include/chaiscript/dispatchkit/bind_first.hpp +++ b/include/chaiscript/dispatchkit/bind_first.hpp @@ -4,6 +4,10 @@ // Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + + #ifndef CHAISCRIPT_BIND_FIRST_HPP_ #define CHAISCRIPT_BIND_FIRST_HPP_ diff --git a/include/chaiscript/dispatchkit/bootstrap.hpp b/include/chaiscript/dispatchkit/bootstrap.hpp index 45143636..3cef9f05 100644 --- a/include/chaiscript/dispatchkit/bootstrap.hpp +++ b/include/chaiscript/dispatchkit/bootstrap.hpp @@ -4,6 +4,10 @@ // Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + + #ifndef CHAISCRIPT_BOOTSTRAP_HPP_ #define CHAISCRIPT_BOOTSTRAP_HPP_ diff --git a/include/chaiscript/dispatchkit/bootstrap_stl.hpp b/include/chaiscript/dispatchkit/bootstrap_stl.hpp index e2ec267f..b0297a88 100644 --- a/include/chaiscript/dispatchkit/bootstrap_stl.hpp +++ b/include/chaiscript/dispatchkit/bootstrap_stl.hpp @@ -4,6 +4,10 @@ // Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + + /// \file /// This file contains utility functions for registration of STL container /// classes. The methodology used is based on the SGI STL concepts. diff --git a/include/chaiscript/dispatchkit/boxed_cast.hpp b/include/chaiscript/dispatchkit/boxed_cast.hpp index 7fbe78d3..d7c52fc2 100644 --- a/include/chaiscript/dispatchkit/boxed_cast.hpp +++ b/include/chaiscript/dispatchkit/boxed_cast.hpp @@ -4,6 +4,10 @@ // Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + + #ifndef CHAISCRIPT_BOXED_CAST_HPP_ #define CHAISCRIPT_BOXED_CAST_HPP_ diff --git a/include/chaiscript/dispatchkit/boxed_cast_helper.hpp b/include/chaiscript/dispatchkit/boxed_cast_helper.hpp index c8dce2e1..01e8936d 100644 --- a/include/chaiscript/dispatchkit/boxed_cast_helper.hpp +++ b/include/chaiscript/dispatchkit/boxed_cast_helper.hpp @@ -4,6 +4,10 @@ // Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + + #ifndef CHAISCRIPT_BOXED_CAST_HELPER_HPP_ #define CHAISCRIPT_BOXED_CAST_HELPER_HPP_ diff --git a/include/chaiscript/dispatchkit/boxed_number.hpp b/include/chaiscript/dispatchkit/boxed_number.hpp index 2d44b7ea..2ab65091 100644 --- a/include/chaiscript/dispatchkit/boxed_number.hpp +++ b/include/chaiscript/dispatchkit/boxed_number.hpp @@ -4,6 +4,9 @@ // Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #ifndef CHAISCRIPT_BOXED_NUMERIC_HPP_ #define CHAISCRIPT_BOXED_NUMERIC_HPP_ @@ -589,8 +592,9 @@ namespace chaiscript static void check_type() { #ifdef CHAISCRIPT_MSVC +// MSVC complains about this being redundant / tautologica l #pragma warning(push) -#pragma warning(disable : 4127) +#pragma warning(disable : 4127 6287) #endif if (sizeof(Source) != sizeof(Target) || std::is_signed() != std::is_signed() diff --git a/include/chaiscript/dispatchkit/boxed_value.hpp b/include/chaiscript/dispatchkit/boxed_value.hpp index 938aab00..138311e6 100644 --- a/include/chaiscript/dispatchkit/boxed_value.hpp +++ b/include/chaiscript/dispatchkit/boxed_value.hpp @@ -4,6 +4,10 @@ // Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + + #ifndef CHAISCRIPT_BOXED_VALUE_HPP_ #define CHAISCRIPT_BOXED_VALUE_HPP_ diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index a83747e2..85227f7d 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -4,6 +4,10 @@ // Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + + #ifndef CHAISCRIPT_DISPATCHKIT_HPP_ #define CHAISCRIPT_DISPATCHKIT_HPP_ diff --git a/include/chaiscript/dispatchkit/dynamic_object.hpp b/include/chaiscript/dispatchkit/dynamic_object.hpp index ee972320..7aa63524 100644 --- a/include/chaiscript/dispatchkit/dynamic_object.hpp +++ b/include/chaiscript/dispatchkit/dynamic_object.hpp @@ -4,6 +4,10 @@ // Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + + #ifndef CHAISCRIPT_DYNAMIC_OBJECT_HPP_ #define CHAISCRIPT_DYNAMIC_OBJECT_HPP_ diff --git a/include/chaiscript/dispatchkit/exception_specification.hpp b/include/chaiscript/dispatchkit/exception_specification.hpp index 0c9b40f9..17bca6b9 100644 --- a/include/chaiscript/dispatchkit/exception_specification.hpp +++ b/include/chaiscript/dispatchkit/exception_specification.hpp @@ -4,6 +4,10 @@ // Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + + #ifndef CHAISCRIPT_EXCEPTION_SPECIFICATION_HPP_ #define CHAISCRIPT_EXCEPTION_SPECIFICATION_HPP_ diff --git a/include/chaiscript/dispatchkit/function_call.hpp b/include/chaiscript/dispatchkit/function_call.hpp index 3efb7031..b9b0384a 100644 --- a/include/chaiscript/dispatchkit/function_call.hpp +++ b/include/chaiscript/dispatchkit/function_call.hpp @@ -4,6 +4,10 @@ // Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + + #ifndef CHAISCRIPT_FUNCTION_CALL_HPP_ #define CHAISCRIPT_FUNCTION_CALL_HPP_ diff --git a/include/chaiscript/dispatchkit/function_call_detail.hpp b/include/chaiscript/dispatchkit/function_call_detail.hpp index 93e3e61c..c9cdaad1 100644 --- a/include/chaiscript/dispatchkit/function_call_detail.hpp +++ b/include/chaiscript/dispatchkit/function_call_detail.hpp @@ -4,6 +4,10 @@ // Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + + #ifndef CHAISCRIPT_FUNCTION_CALL_DETAIL_HPP_ #define CHAISCRIPT_FUNCTION_CALL_DETAIL_HPP_ diff --git a/include/chaiscript/dispatchkit/handle_return.hpp b/include/chaiscript/dispatchkit/handle_return.hpp index 4d0930e1..1c70bcb2 100644 --- a/include/chaiscript/dispatchkit/handle_return.hpp +++ b/include/chaiscript/dispatchkit/handle_return.hpp @@ -4,6 +4,10 @@ // Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + + #ifndef CHAISCRIPT_HANDLE_RETURN_HPP_ #define CHAISCRIPT_HANDLE_RETURN_HPP_ diff --git a/include/chaiscript/dispatchkit/operators.hpp b/include/chaiscript/dispatchkit/operators.hpp index 4ebaec55..0563fbfc 100644 --- a/include/chaiscript/dispatchkit/operators.hpp +++ b/include/chaiscript/dispatchkit/operators.hpp @@ -4,6 +4,10 @@ // Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + + #ifndef CHAISCRIPT_OPERATORS_HPP_ #define CHAISCRIPT_OPERATORS_HPP_ diff --git a/include/chaiscript/dispatchkit/proxy_constructors.hpp b/include/chaiscript/dispatchkit/proxy_constructors.hpp index a5ad41ec..1d733071 100644 --- a/include/chaiscript/dispatchkit/proxy_constructors.hpp +++ b/include/chaiscript/dispatchkit/proxy_constructors.hpp @@ -4,6 +4,9 @@ // Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #ifndef CHAISCRIPT_PROXY_CONSTRUCTORS_HPP_ #define CHAISCRIPT_PROXY_CONSTRUCTORS_HPP_ diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index 67b94c06..cc861a28 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -4,6 +4,9 @@ // Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + #ifndef CHAISCRIPT_PROXY_FUNCTIONS_HPP_ #define CHAISCRIPT_PROXY_FUNCTIONS_HPP_ diff --git a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp index f00eeef5..48c039d9 100644 --- a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp @@ -4,6 +4,10 @@ // Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + + #ifndef CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_ #define CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_ diff --git a/include/chaiscript/dispatchkit/register_function.hpp b/include/chaiscript/dispatchkit/register_function.hpp index 1c58840a..4193ad8b 100644 --- a/include/chaiscript/dispatchkit/register_function.hpp +++ b/include/chaiscript/dispatchkit/register_function.hpp @@ -4,6 +4,10 @@ // Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + + #ifndef CHAISCRIPT_REGISTER_FUNCTION_HPP_ #define CHAISCRIPT_REGISTER_FUNCTION_HPP_ diff --git a/include/chaiscript/dispatchkit/type_conversions.hpp b/include/chaiscript/dispatchkit/type_conversions.hpp index 3a546c67..df229bd7 100644 --- a/include/chaiscript/dispatchkit/type_conversions.hpp +++ b/include/chaiscript/dispatchkit/type_conversions.hpp @@ -4,6 +4,10 @@ // Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + + #ifndef CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_ #define CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_ @@ -340,15 +344,11 @@ namespace chaiscript { } - Type_Conversions(const Type_Conversions &t_other) - : m_mutex(), - m_conversions(t_other.get_conversions()), - m_convertableTypes(t_other.m_convertableTypes), - m_num_types(m_conversions.size()), - m_thread_cache(this), - m_conversion_saves(this) - { - } + Type_Conversions(const Type_Conversions &t_other) = delete; + Type_Conversions(Type_Conversions &&) = default; + + Type_Conversions &operator=(const Type_Conversions &) = delete; + Type_Conversions &operator=(Type_Conversions &&) = default; const std::set &thread_cache() const { diff --git a/include/chaiscript/dispatchkit/type_info.hpp b/include/chaiscript/dispatchkit/type_info.hpp index 592271a8..47f10c50 100644 --- a/include/chaiscript/dispatchkit/type_info.hpp +++ b/include/chaiscript/dispatchkit/type_info.hpp @@ -4,6 +4,10 @@ // Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + + #ifndef CHAISCRIPT_TYPE_INFO_HPP_ #define CHAISCRIPT_TYPE_INFO_HPP_ diff --git a/include/chaiscript/language/chaiscript_algebraic.hpp b/include/chaiscript/language/chaiscript_algebraic.hpp index 022a295c..ad55a38d 100644 --- a/include/chaiscript/language/chaiscript_algebraic.hpp +++ b/include/chaiscript/language/chaiscript_algebraic.hpp @@ -4,6 +4,10 @@ // Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + + #ifndef CHAISCRIPT_ALGEBRAIC_HPP_ #define CHAISCRIPT_ALGEBRAIC_HPP_ diff --git a/include/chaiscript/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index abcfe5bf..8983f196 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -4,6 +4,10 @@ // Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + + #ifndef CHAISCRIPT_COMMON_HPP_ #define CHAISCRIPT_COMMON_HPP_ diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index 828fc409..33cb00f0 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -4,6 +4,10 @@ // Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + + #ifndef CHAISCRIPT_ENGINE_HPP_ #define CHAISCRIPT_ENGINE_HPP_ diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index c6143f15..0373dccc 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -4,6 +4,10 @@ // Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + + #ifndef CHAISCRIPT_EVAL_HPP_ #define CHAISCRIPT_EVAL_HPP_ diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 913b995a..5536b000 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -4,6 +4,10 @@ // Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + + #ifndef CHAISCRIPT_PARSER_HPP_ #define CHAISCRIPT_PARSER_HPP_ diff --git a/include/chaiscript/utility/utility.hpp b/include/chaiscript/utility/utility.hpp index 11262ff0..1cfb3eb9 100644 --- a/include/chaiscript/utility/utility.hpp +++ b/include/chaiscript/utility/utility.hpp @@ -4,6 +4,10 @@ // Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + + #ifndef CHAISCRIPT_UTILITY_UTILITY_HPP_ #define CHAISCRIPT_UTILITY_UTILITY_HPP_ diff --git a/samples/fun_call_performance.cpp b/samples/fun_call_performance.cpp index 90fd7d94..d18c6369 100644 --- a/samples/fun_call_performance.cpp +++ b/samples/fun_call_performance.cpp @@ -4,6 +4,10 @@ // Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + + #include #include #include diff --git a/src/main.cpp b/src/main.cpp index ae2d4907..a32e6474 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -4,6 +4,10 @@ // Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + + #include #include #include diff --git a/src/stl_extra.cpp b/src/stl_extra.cpp index 07bc0609..807dbac0 100644 --- a/src/stl_extra.cpp +++ b/src/stl_extra.cpp @@ -4,6 +4,10 @@ // Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + + #include #include #include diff --git a/unittests/compiled_tests.cpp b/unittests/compiled_tests.cpp index 1a94c738..c1716ec9 100644 --- a/unittests/compiled_tests.cpp +++ b/unittests/compiled_tests.cpp @@ -198,7 +198,7 @@ TEST_CASE("Throw int or double") chai.eval("throw(1.0)", chaiscript::exception_specification()); REQUIRE(false); } catch (const double e) { - CHECK(e == 1.0); + CHECK(e == Approx(1.0)); } } From e342243193da0fa34c212b783dd13f9e1ee8973f Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 22 Feb 2017 15:33:42 -0700 Subject: [PATCH 41/84] Update release notes for 6.0.0 --- releasenotes.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/releasenotes.md b/releasenotes.md index 5f4f3eb1..9951e753 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -26,7 +26,7 @@ Current Version: 6.0.0 * Modular optimization system; this can be accessed via the ChaiScript_Basic interface * Execution tracing capability; also accessed via ChaiScript_Basic interface -* range-based for loops `for( id : container ) { }` +* range-based for loops `for( id : container ) { }` (much better performance than other loop types) * If-init expressions (ala C++17) * Support for passing r-value references to functions * Support for containing unique_ptr @@ -39,6 +39,7 @@ Current Version: 6.0.0 * Compile size improvements * Significant runtime improvements (see "Modular optimization system") * Significant parser improvements, both with parse-time and parser initialization time (Thanks @niXman) +* Fix type conversion to bool in conditionals #### Improvements Still Need To Be Made From fac5a3906681ad92be9cd775ebffc0dde60cd460 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Thu, 23 Feb 2017 17:54:59 -0700 Subject: [PATCH 42/84] Update readme.md for 6.0.0 --- readme.md | 23 ----------------------- 1 file changed, 23 deletions(-) diff --git a/readme.md b/readme.md index 26efc9a7..58cd1bd1 100644 --- a/readme.md +++ b/readme.md @@ -105,26 +105,3 @@ The shortest complete example possible follows: } - -Or, if you want to compile the std lib into your code, which reduces -runtime requirements. - - /// main.cpp - - #include - #include - - double function(int i, double j) - { - return i * j; - } - - int main() - { - chaiscript::ChaiScript chai(chaiscript::Std_Lib::library()); - chai.add(chaiscript::fun(&function), "function"); - - double d = chai.eval("function(3, 4.75);"); - } - - From 534897d8358bd61be8452852a04b00919a77310d Mon Sep 17 00:00:00 2001 From: Ionoclast Laboratories Date: Thu, 2 Mar 2017 11:27:10 -0800 Subject: [PATCH 43/84] Fixes path reference and code formatting in readme. Changes Example.cpp's directory "src" => "samples" to match repo. Change code example from indented quote to highlighted code block. --- readme.md | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/readme.md b/readme.md index 58cd1bd1..8bf4deec 100644 --- a/readme.md +++ b/readme.md @@ -79,7 +79,7 @@ directory, and for more in-depth look at the language, the unit tests in the "unittests" directory cover the most ground. For examples of how to register parts of your C++ application, see -"example.cpp" in the "src" directory. Example.cpp is verbose and shows every +"example.cpp" in the "samples" directory. Example.cpp is verbose and shows every possible way of working with the library. For further documentation generate the doxygen documentation in the build folder or see the website http://www.chaiscript.com. @@ -87,21 +87,21 @@ http://www.chaiscript.com. The shortest complete example possible follows: - /// main.cpp +```C++ +/// main.cpp - #include +#include - double function(int i, double j) - { - return i * j; - } - - int main() - { - chaiscript::ChaiScript chai; - chai.add(chaiscript::fun(&function), "function"); - - double d = chai.eval("function(3, 4.75);"); - } +double function(int i, double j) +{ + return i * j; +} +int main() +{ + chaiscript::ChaiScript chai; + chai.add(chaiscript::fun(&function), "function"); + double d = chai.eval("function(3, 4.75);"); +} +``` From 698dfb06db216630d3fa2f54a85b7c658059c9e5 Mon Sep 17 00:00:00 2001 From: ftk Date: Sun, 5 Mar 2017 20:54:01 +0300 Subject: [PATCH 44/84] Loadable module support can be disabled by defining CHAISCRIPT_NO_DYNLOAD --- include/chaiscript/language/chaiscript_engine.hpp | 7 ++++--- include/chaiscript/language/chaiscript_unknown.hpp | 4 ++++ 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index 5d8b6f0d..27b46981 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -36,12 +36,13 @@ #include #endif -#if defined(_POSIX_VERSION) && !defined(__CYGWIN__) +#if !defined(CHAISCRIPT_NO_DYNLOAD) && defined(_POSIX_VERSION) && !defined(__CYGWIN__) #include #endif - -#ifdef CHAISCRIPT_WINDOWS +#if defined(CHAISCRIPT_NO_DYNLOAD) +#include "chaiscript_unknown.hpp" +#elif defined(CHAISCRIPT_WINDOWS) #include "chaiscript_windows.hpp" #elif _POSIX_VERSION #include "chaiscript_posix.hpp" diff --git a/include/chaiscript/language/chaiscript_unknown.hpp b/include/chaiscript/language/chaiscript_unknown.hpp index 9e1d7afc..8fc1d494 100644 --- a/include/chaiscript/language/chaiscript_unknown.hpp +++ b/include/chaiscript/language/chaiscript_unknown.hpp @@ -16,7 +16,11 @@ namespace chaiscript { Loadable_Module(const std::string &, const std::string &) { +#ifdef CHAISCRIPT_NO_DYNLOAD + throw chaiscript::exception::load_module_error("Loadable module support was disabled (CHAISCRIPT_NO_DYNLOAD)"); +#else throw chaiscript::exception::load_module_error("Loadable module support not available for your platform"); +#endif } ModulePtr m_moduleptr; From 84f9c44ab628b9445e2bf62c95609f7625ce244b Mon Sep 17 00:00:00 2001 From: ftk Date: Sun, 5 Mar 2017 21:23:05 +0300 Subject: [PATCH 45/84] Do not register load_module by default when dynamic loading is disabled --- include/chaiscript/chaiscript_defines.hpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/chaiscript/chaiscript_defines.hpp b/include/chaiscript/chaiscript_defines.hpp index cc349a0b..be837c26 100644 --- a/include/chaiscript/chaiscript_defines.hpp +++ b/include/chaiscript/chaiscript_defines.hpp @@ -216,7 +216,11 @@ namespace chaiscript { static inline std::vector default_options() { +#ifdef CHAISCRIPT_NO_DYNLOAD + return {Options::No_Load_Modules, Options::External_Scripts}; +#else return {Options::Load_Modules, Options::External_Scripts}; +#endif } } #endif From 72cb9bd940530dbb56ebb68b5fedb14cfe48c05c Mon Sep 17 00:00:00 2001 From: ftk Date: Sun, 5 Mar 2017 21:26:01 +0300 Subject: [PATCH 46/84] Compile out module path search code when module support is disabled --- include/chaiscript/language/chaiscript_engine.hpp | 2 +- samples/fun_call_performance.cpp | 2 ++ src/main.cpp | 2 ++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index 27b46981..16110f00 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -243,7 +243,7 @@ namespace chaiscript m_parser(std::move(parser)), m_engine(*m_parser) { -#if defined(_POSIX_VERSION) && !defined(__CYGWIN__) +#if !defined(CHAISCRIPT_NO_DYNLOAD) && defined(_POSIX_VERSION) && !defined(__CYGWIN__) // If on Unix, add the path of the current executable to the module search path // as windows would do diff --git a/samples/fun_call_performance.cpp b/samples/fun_call_performance.cpp index a519052e..b8bda5ae 100644 --- a/samples/fun_call_performance.cpp +++ b/samples/fun_call_performance.cpp @@ -68,6 +68,7 @@ std::vector default_search_paths() { std::vector paths; +#ifndef CHAISCRIPT_NO_DYNLOAD #ifdef CHAISCRIPT_WINDOWS // force no unicode CHAR path[4096]; int size = GetModuleFileNameA(0, path, sizeof(path) - 1); @@ -137,6 +138,7 @@ std::vector default_search_paths() paths.push_back(exepath.substr(0, secondtolastslash) + "/lib/chaiscript/"); } #endif +#endif // ifndef CHAISCRIPT_NO_DYNLOAD return paths; } diff --git a/src/main.cpp b/src/main.cpp index 4179a6bf..78044e06 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -71,6 +71,7 @@ std::vector default_search_paths() { std::vector paths; +#ifndef CHAISCRIPT_NO_DYNLOAD #ifdef CHAISCRIPT_WINDOWS // force no unicode CHAR path[4096]; int size = GetModuleFileNameA(nullptr, path, sizeof(path)-1); @@ -140,6 +141,7 @@ std::vector default_search_paths() paths.push_back(exepath.substr(0, secondtolastslash) + "/lib/chaiscript/"); } #endif +#endif // ifndef CHAISCRIPT_NO_DYNLOAD return paths; } From c2f7ca3aa220911eb6dde46560c71c0dec9177e2 Mon Sep 17 00:00:00 2001 From: ftk Date: Sun, 5 Mar 2017 21:48:59 +0300 Subject: [PATCH 47/84] Using runtime stdlib constructor will result in compilation error --- include/chaiscript/language/chaiscript_engine.hpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index 16110f00..b2df16bd 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -279,6 +279,7 @@ namespace chaiscript build_eval_system(t_lib, t_opts); } +#ifndef CHAISCRIPT_NO_DYNLOAD /// \brief Constructor for ChaiScript. /// /// This version of the ChaiScript constructor attempts to find the stdlib module to load @@ -308,6 +309,12 @@ namespace chaiscript throw; } } +#else // CHAISCRIPT_NO_DYNLOAD +explicit ChaiScript_Basic(std::unique_ptr &&parser, + std::vector t_module_paths = {}, + std::vector t_use_paths = {}, + const std::vector &t_opts = chaiscript::default_options()) = delete; +#endif parser::ChaiScript_Parser_Base &get_parser() { From 60c43233c68ba52dd4363d8bc92262e5a7c385b6 Mon Sep 17 00:00:00 2001 From: ftk Date: Sun, 5 Mar 2017 21:55:01 +0300 Subject: [PATCH 48/84] More clear error message in load_module --- include/chaiscript/language/chaiscript_engine.hpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index b2df16bd..37131773 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -556,6 +556,10 @@ explicit ChaiScript_Basic(std::unique_ptr &&pars /// \throw chaiscript::exception::load_module_error In the event that no matching module can be found. std::string load_module(const std::string &t_module_name) { +#ifdef CHAISCRIPT_NO_DYNLOAD + (void)t_module_name; // -Wunused-parameter + throw chaiscript::exception::load_module_error("Loadable module support was disabled (CHAISCRIPT_NO_DYNLOAD)"); +#else std::vector errors; std::string version_stripped_name = t_module_name; size_t version_pos = version_stripped_name.find("-" + Build_Info::version()); @@ -589,6 +593,7 @@ explicit ChaiScript_Basic(std::unique_ptr &&pars } throw chaiscript::exception::load_module_error(t_module_name, errors); +#endif } /// \brief Load a binary module from a dynamic library. Works on platforms that support From d22c27b62791584e6a5f910be98b223e7041414c Mon Sep 17 00:00:00 2001 From: ftk Date: Wed, 8 Mar 2017 12:31:30 +0300 Subject: [PATCH 49/84] Added option to disable dynload in cmakelists.txt --- CMakeLists.txt | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index fbba252b..6409ea51 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -14,6 +14,7 @@ ELSE() project(chaiscript) option(MULTITHREAD_SUPPORT_ENABLED "Multithreaded Support Enabled" TRUE) +option(DYNLOAD_ENABLED "Dynamic Loading Support Enabled" TRUE) option(BUILD_MODULES "Build Extra Modules (stl)" TRUE) @@ -221,9 +222,15 @@ if(NOT MULTITHREAD_SUPPORT_ENABLED) add_definitions(-DCHAISCRIPT_NO_THREADS) endif() +if(NOT DYNLOAD_ENABLED) + add_definitions(-DCHAISCRIPT_NO_DYNLOAD) +endif() + if(CMAKE_HOST_UNIX) - if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD" AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "Haiku") - list(APPEND LIBS "dl") + if(DYNLOAD_ENABLED) + if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD" AND NOT ${CMAKE_SYSTEM_NAME} MATCHES "Haiku") + list(APPEND LIBS "dl") + endif() endif() if(MULTITHREAD_SUPPORT_ENABLED) From bd4a458c319dbc160d49e38afb4d7ad11ae65b41 Mon Sep 17 00:00:00 2001 From: njlr Date: Wed, 8 Mar 2017 19:47:07 +0000 Subject: [PATCH 50/84] * Added Buck build --- .buckconfig | 0 .gitignore | 5 +++++ BUCK | 14 ++++++++++++++ buckaroo.json | 4 ++++ samples/BUCK | 12 ++++++++++++ 5 files changed, 35 insertions(+) create mode 100644 .buckconfig create mode 100644 .gitignore create mode 100644 BUCK create mode 100644 buckaroo.json create mode 100644 samples/BUCK diff --git a/.buckconfig b/.buckconfig new file mode 100644 index 00000000..e69de29b diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..9e6e4429 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +/buck-out/ +/.buckd/ +/buckaroo/ +.buckconfig.local +BUCKAROO_DEPS diff --git a/BUCK b/BUCK new file mode 100644 index 00000000..e01db658 --- /dev/null +++ b/BUCK @@ -0,0 +1,14 @@ +include_defs('//BUCKAROO_DEPS') + +prebuilt_cxx_library( + name = 'chaiscript', + header_only = True, + header_namespace = 'chaiscript', + exported_headers = subdir_glob([ + ('include/chaiscript', '**/*.hpp'), + ]), + visibility = [ + 'PUBLIC', + ], + deps = BUCKAROO_DEPS, +) diff --git a/buckaroo.json b/buckaroo.json new file mode 100644 index 00000000..afc50314 --- /dev/null +++ b/buckaroo.json @@ -0,0 +1,4 @@ +{ + "name": "chaiscript", + "dependencies": {} +} diff --git a/samples/BUCK b/samples/BUCK new file mode 100644 index 00000000..7dd4982c --- /dev/null +++ b/samples/BUCK @@ -0,0 +1,12 @@ +cxx_binary( + name = 'example', + srcs = [ + 'example.cpp', + ], + compiler_flags = [ + '-std=c++14', + ], + deps = [ + '//:chaiscript', + ], +) From 12100cce99e9807d553c2764abb58de55dcf1e95 Mon Sep 17 00:00:00 2001 From: ftk Date: Wed, 8 Mar 2017 12:37:04 +0300 Subject: [PATCH 51/84] Updated travis.yml --- .travis.yml | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index c7a33cf2..1d6e283e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,6 +23,10 @@ matrix: sudo: false env: GCC_VER="4.9" compiler: gcc + - os: linux + sudo: false + env: GCC_VER="4.9" CMAKE_OPTIONS="-D DYNLOAD_ENABLED:BOOL=FALSE -D MULTITHREAD_SUPPORT_ENABLED:BOOL=FALSE -D USE_STD_MAKE_SHARED:BOOL=TRUE" BUILD_ONLY=1 + compiler: gcc - os: linux sudo: false env: GCC_VER="5" @@ -30,7 +34,10 @@ matrix: - os: osx compiler: clang osx_image: xcode8 - + - os: osx + compiler: clang + osx_image: xcode8 + env: CMAKE_OPTIONS="-D DYNLOAD_ENABLED:BOOL=FALSE -D MULTITHREAD_SUPPORT_ENABLED:BOOL=FALSE -D USE_STD_MAKE_SHARED:BOOL=TRUE" BUILD_ONLY=1 env: global: @@ -40,14 +47,14 @@ env: before_install: - if [ "${GCC_VER}" != "" ]; then export CXX="g++-$GCC_VER" CC="gcc-$GCC_VER" GCOV="gcov-$GCC_VER" ; fi - - if [ "${GCC_VER}" == "5" ]; then export CPPCHECK=1 COVERAGE=1 FUZZY_CMD="-D RUN_FUZZY_TESTS:BOOL=TRUE" ; fi + - if [ "${GCC_VER}" == "5" && "${BUILD_ONLY}" != "1"]; then export CPPCHECK=1 COVERAGE=1 CMAKE_OPTIONS+=" -D RUN_FUZZY_TESTS:BOOL=TRUE" ; fi - pip install --user cpp-coveralls script: - - cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug $FUZZY_CMD . + - cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug $CMAKE_OPTIONS . - cmake --build . -- -j2 - - ctest - - if [ ${COVERAGE} = 1 ]; then bash <(curl -s https://raw.githubusercontent.com/codecov/codecov-bash/master/codecov) -x $GCOV -a "-s `pwd`" ; fi + - if [ "${BUILD_ONLY}" != "1" ]; then ctest; fi + - if [ "${COVERAGE}" = "1" ]; then bash <(curl -s https://raw.githubusercontent.com/codecov/codecov-bash/master/codecov) -x $GCOV -a "-s `pwd`" ; fi #after_script: # - if [ ${CPPCHECK} = 1 ]; then contrib/codeanalysis/runcppcheck.sh ; fi From f53a1ed9513615d15a676062dcd516ae8b5ba7f9 Mon Sep 17 00:00:00 2001 From: ftk Date: Wed, 8 Mar 2017 13:00:34 +0300 Subject: [PATCH 52/84] Fix compilation of multithreaded_test --- unittests/multithreaded_test.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/unittests/multithreaded_test.cpp b/unittests/multithreaded_test.cpp index ff06620a..e2d0240b 100644 --- a/unittests/multithreaded_test.cpp +++ b/unittests/multithreaded_test.cpp @@ -2,6 +2,9 @@ #include +#ifdef CHAISCRIPT_NO_DYNLOAD +#include +#endif #include #include @@ -57,18 +60,22 @@ int main() } std::vector modulepaths; + +#ifdef CHAISCRIPT_NO_DYNLOAD + chaiscript::ChaiScript chai(/* unused */modulepaths, usepaths); +#else modulepaths.push_back(""); if (modulepath) { modulepaths.push_back(modulepath); } - // For this test we are going to load the dynamic stdlib // to make sure it continues to work chaiscript::ChaiScript_Basic chai( std::make_unique>(), modulepaths,usepaths); +#endif std::vector > threads; From 12829ee5d24bbbd7a91910ee002819af0b02a0df Mon Sep 17 00:00:00 2001 From: ftk Date: Sat, 11 Mar 2017 15:42:24 +0300 Subject: [PATCH 53/84] Simplified travis.yml --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 1d6e283e..01ab0ea8 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,7 +29,7 @@ matrix: compiler: gcc - os: linux sudo: false - env: GCC_VER="5" + env: GCC_VER="5" CPPCHECK=1 COVERAGE=1 CMAKE_OPTIONS="-D RUN_FUZZY_TESTS:BOOL=TRUE" compiler: gcc - os: osx compiler: clang @@ -47,7 +47,6 @@ env: before_install: - if [ "${GCC_VER}" != "" ]; then export CXX="g++-$GCC_VER" CC="gcc-$GCC_VER" GCOV="gcov-$GCC_VER" ; fi - - if [ "${GCC_VER}" == "5" && "${BUILD_ONLY}" != "1"]; then export CPPCHECK=1 COVERAGE=1 CMAKE_OPTIONS+=" -D RUN_FUZZY_TESTS:BOOL=TRUE" ; fi - pip install --user cpp-coveralls script: From 561c5bc981ead1fd8f38e5949696382691ea2c2a Mon Sep 17 00:00:00 2001 From: Glen Fraser Date: Tue, 14 Mar 2017 12:01:51 +0100 Subject: [PATCH 54/84] Handle negative numbers in JSONParse::parse_number - fix issue #334, where negative numbers loaded from JSON were being parsed as 0. - add unit tests to cover these cases. --- include/chaiscript/utility/json.hpp | 11 +++++++---- unittests/json_3.chai | 1 + unittests/json_4.chai | 1 + unittests/json_9.chai | 2 +- 4 files changed, 10 insertions(+), 5 deletions(-) diff --git a/include/chaiscript/utility/json.hpp b/include/chaiscript/utility/json.hpp index 96decc09..6fe2e584 100644 --- a/include/chaiscript/utility/json.hpp +++ b/include/chaiscript/utility/json.hpp @@ -567,10 +567,13 @@ struct JSONParser { std::string val, exp_str; char c = '\0'; bool isDouble = false; + bool isNegative = false; long exp = 0; for (; offset < str.size() ;) { c = str[offset++]; - if( (c == '-') || (c >= '0' && c <= '9') ) { + if( c == '-' ) { + isNegative = true; + } else if( c >= '0' && c <= '9' ) { val += c; } else if( c == '.' ) { val += c; @@ -608,12 +611,12 @@ struct JSONParser { --offset; if( isDouble ) { - return JSON(chaiscript::parse_num( val ) * std::pow( 10, exp )); + return JSON((isNegative?-1:1) * chaiscript::parse_num( val ) * std::pow( 10, exp )); } else { if( !exp_str.empty() ) { - return JSON(static_cast(chaiscript::parse_num( val )) * std::pow( 10, exp )); + return JSON((isNegative?-1:1) * static_cast(chaiscript::parse_num( val )) * std::pow( 10, exp )); } else { - return JSON(chaiscript::parse_num( val )); + return JSON((isNegative?-1:1) * chaiscript::parse_num( val )); } } } diff --git a/unittests/json_3.chai b/unittests/json_3.chai index d3f222e4..11ce7dcb 100644 --- a/unittests/json_3.chai +++ b/unittests/json_3.chai @@ -1 +1,2 @@ assert_equal(from_json("100"), 100) +assert_equal(from_json("-100"), -100) diff --git a/unittests/json_4.chai b/unittests/json_4.chai index 22d388c7..34ecfa9d 100644 --- a/unittests/json_4.chai +++ b/unittests/json_4.chai @@ -1 +1,2 @@ assert_equal(from_json("1.234"), 1.234) +assert_equal(from_json("-1.234"), -1.234) diff --git a/unittests/json_9.chai b/unittests/json_9.chai index 15127387..d8c64239 100644 --- a/unittests/json_9.chai +++ b/unittests/json_9.chai @@ -1,2 +1,2 @@ -assert_equal(from_json("[1,2,3]"), [1,2,3]) +assert_equal(from_json("[1,-2,3]"), [1,-2,3]) From 491b95099dba0aae2c95d373aea6fc99a77ce3be Mon Sep 17 00:00:00 2001 From: Glen Fraser Date: Tue, 14 Mar 2017 13:01:09 +0100 Subject: [PATCH 55/84] In JSONParser::parse_number(), only allow a single '-' at start - also, don't allow multiple '.' decimal points. Add unit tests to cover these cases. --- include/chaiscript/utility/json.hpp | 10 ++++++---- unittests/json_4.chai | 20 ++++++++++++++++++++ 2 files changed, 26 insertions(+), 4 deletions(-) diff --git a/include/chaiscript/utility/json.hpp b/include/chaiscript/utility/json.hpp index 6fe2e584..676b4699 100644 --- a/include/chaiscript/utility/json.hpp +++ b/include/chaiscript/utility/json.hpp @@ -569,13 +569,15 @@ struct JSONParser { bool isDouble = false; bool isNegative = false; long exp = 0; + if( offset < str.size() && str[offset] == '-' ) { + isNegative = true; + ++offset; + } for (; offset < str.size() ;) { c = str[offset++]; - if( c == '-' ) { - isNegative = true; - } else if( c >= '0' && c <= '9' ) { + if( c >= '0' && c <= '9' ) { val += c; - } else if( c == '.' ) { + } else if( c == '.' && !isDouble ) { val += c; isDouble = true; } else { diff --git a/unittests/json_4.chai b/unittests/json_4.chai index 34ecfa9d..ae070241 100644 --- a/unittests/json_4.chai +++ b/unittests/json_4.chai @@ -1,2 +1,22 @@ assert_equal(from_json("1.234"), 1.234) assert_equal(from_json("-1.234"), -1.234) + +auto caught = false; +try { + from_json("-1-5.3"); +} +catch(e) { + assert_equal("JSON ERROR: Number: unexpected character '-'", e.what()); + caught = true; +} +assert_equal(caught, true); + +caught = false; +try { + from_json("-15.3.2"); +} +catch(e) { + assert_equal("JSON ERROR: Number: unexpected character '.'", e.what()); + caught = true; +} +assert_equal(caught, true); From be2fec02d9ee3669975affd157b3773782d0fb60 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 21 Mar 2017 10:10:25 -0700 Subject: [PATCH 56/84] Simplify usage of Thread_Specific object --- include/chaiscript/chaiscript_threading.hpp | 24 +++++++++---------- .../chaiscript/dispatchkit/dispatchkit.hpp | 2 +- .../dispatchkit/type_conversions.hpp | 4 +--- 3 files changed, 14 insertions(+), 16 deletions(-) diff --git a/include/chaiscript/chaiscript_threading.hpp b/include/chaiscript/chaiscript_threading.hpp index cb5e129c..01bda2bb 100644 --- a/include/chaiscript/chaiscript_threading.hpp +++ b/include/chaiscript/chaiscript_threading.hpp @@ -67,44 +67,44 @@ namespace chaiscript class Thread_Storage { public: - - explicit Thread_Storage(void *t_key) - : m_key(t_key) - { - } + Thread_Storage() = default; + Thread_Storage(const Thread_Storage &) = delete; + Thread_Storage(Thread_Storage &&) = delete; + Thread_Storage &operator=(const Thread_Storage &) = delete; + Thread_Storage &operator=(Thread_Storage &&) = delete; ~Thread_Storage() { - t().erase(m_key); + t().erase(this); } inline const T *operator->() const { - return &(t()[m_key]); + return &(t()[this]); } inline const T &operator*() const { - return t()[m_key]; + return t()[this]; } inline T *operator->() { - return &(t()[m_key]); + return &(t()[this]); } inline T &operator*() { - return t()[m_key]; + return t()[this]; } void *m_key; private: - static std::unordered_map &t() + static std::unordered_map &t() { - thread_local static std::unordered_map my_t; + thread_local std::unordered_map my_t; return my_t; } }; diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index c4e61983..d8bfb25b 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -452,7 +452,7 @@ namespace chaiscript }; explicit Dispatch_Engine(chaiscript::parser::ChaiScript_Parser_Base &parser) - : m_stack_holder(this), + : m_stack_holder(), m_parser(parser) { } diff --git a/include/chaiscript/dispatchkit/type_conversions.hpp b/include/chaiscript/dispatchkit/type_conversions.hpp index e16693a5..d9d2f374 100644 --- a/include/chaiscript/dispatchkit/type_conversions.hpp +++ b/include/chaiscript/dispatchkit/type_conversions.hpp @@ -338,9 +338,7 @@ namespace chaiscript : m_mutex(), m_conversions(), m_convertableTypes(), - m_num_types(0), - m_thread_cache(this), - m_conversion_saves(this) + m_num_types(0) { } From 204faa82c188cb9444b5ecdc79ef3d3199f44566 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 21 Mar 2017 11:58:21 -0700 Subject: [PATCH 57/84] Add failing static chaiscript test --- CMakeLists.txt | 3 +++ unittests/static_chaiscript.cpp | 5 +++++ 2 files changed, 8 insertions(+) create mode 100644 unittests/static_chaiscript.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index fbba252b..5e57c177 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -427,6 +427,9 @@ if(BUILD_TESTING) target_link_libraries(compiled_tests ${LIBS} ${CHAISCRIPT_LIBS}) ADD_CATCH_TESTS(compiled_tests) + add_executable(static_chaiscript unittests/static_chaiscript.cpp) + target_link_libraries(static_chaiscript_test ${LIBS}) + add_test(NAME Static_ChaiScript_Test COMMAND static_chaiscript_test) add_executable(boxed_cast_test unittests/boxed_cast_test.cpp) target_link_libraries(boxed_cast_test ${LIBS}) diff --git a/unittests/static_chaiscript.cpp b/unittests/static_chaiscript.cpp new file mode 100644 index 00000000..fb003044 --- /dev/null +++ b/unittests/static_chaiscript.cpp @@ -0,0 +1,5 @@ +#include + +static chaiscript::ChaiScript chai; + +int main() {} From a281d9571e00788784a10bdae054f92cb3e3fb1a Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 21 Mar 2017 11:58:33 -0700 Subject: [PATCH 58/84] Add workaround for chaiscript used as static closes #338 --- include/chaiscript/chaiscript_threading.hpp | 35 +++++++++++++++------ 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/include/chaiscript/chaiscript_threading.hpp b/include/chaiscript/chaiscript_threading.hpp index 01bda2bb..4a255735 100644 --- a/include/chaiscript/chaiscript_threading.hpp +++ b/include/chaiscript/chaiscript_threading.hpp @@ -75,17 +75,19 @@ namespace chaiscript ~Thread_Storage() { - t().erase(this); + if (!destroyed) { + t().erase(this); + } } inline const T *operator->() const { - return &(t()[this]); + return &(t()[const_cast(this)]); } inline const T &operator*() const { - return t()[this]; + return t()[const_cast(this)]; } inline T *operator->() @@ -98,15 +100,30 @@ namespace chaiscript return t()[this]; } - - void *m_key; - private: - static std::unordered_map &t() + struct Map_Holder { + std::unordered_map *, T> map; + + Map_Holder() = default; + Map_Holder(const Map_Holder &) = delete; + Map_Holder(Map_Holder &&) = delete; + Map_Holder& operator=(Map_Holder &&) = delete; + Map_Holder& operator=(const Map_Holder &&) = delete; + ~Map_Holder() { + // here is the theory: + // * If the Map_Holder is destroyed before the Thread_Storage, a flag will get set + // * If destroyed after the Thread_Storage, the * will have been removed from `map` and nothing will happen + for(auto &elem : map) { elem.first->destroyed = true; } + } + }; + + static std::unordered_map *, T> &t() { - thread_local std::unordered_map my_t; - return my_t; + thread_local Map_Holder my_map; + return my_map.map; } + + bool destroyed{false}; }; #else // threading disabled From 9847618cf379c5156d7c0a75c519efa2a1ce2f58 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 21 Mar 2017 12:17:30 -0700 Subject: [PATCH 59/84] Fix use after move during parsing closes #337 --- CMakeLists.txt | 2 +- include/chaiscript/language/chaiscript_parser.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5e57c177..c5e2a82b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -427,7 +427,7 @@ if(BUILD_TESTING) target_link_libraries(compiled_tests ${LIBS} ${CHAISCRIPT_LIBS}) ADD_CATCH_TESTS(compiled_tests) - add_executable(static_chaiscript unittests/static_chaiscript.cpp) + add_executable(static_chaiscript_test unittests/static_chaiscript.cpp) target_link_libraries(static_chaiscript_test ${LIBS}) add_test(NAME Static_ChaiScript_Test COMMAND static_chaiscript_test) diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 163d2bb3..f60fc959 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -2551,7 +2551,7 @@ namespace chaiscript if (Statements(true)) { if (m_position.has_more()) { - throw exception::eval_error("Unparsed input", File_Position(m_position.line, m_position.col), t_fname); + throw exception::eval_error("Unparsed input", File_Position(m_position.line, m_position.col), *m_filename); } else { build_match>(0); } From 252ea8072ded9067b8b7af4c53aced817395c35a Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 30 May 2017 08:29:43 -0600 Subject: [PATCH 60/84] Add failing test for const return type #340 --- unittests/compiled_tests.cpp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/unittests/compiled_tests.cpp b/unittests/compiled_tests.cpp index c1716ec9..86dcc092 100644 --- a/unittests/compiled_tests.cpp +++ b/unittests/compiled_tests.cpp @@ -12,6 +12,8 @@ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wunknown-pragmas" #pragma GCC diagnostic ignored "-Wparentheses" +// This one is necessary for the const return non-reference test +#pragma GCC diagnostic ignored "-Wignored-qualifiers" #endif @@ -1270,3 +1272,20 @@ TEST_CASE("Test reference member being registered") } +const int add_3(const int &i) +{ + return i + 3; +} + +TEST_CASE("Test returning by const non-reference") +{ + chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser()); + // Note, C++ will not allow us to do this: + // chai.add(chaiscript::fun(&Reference_MyClass::x) , "x"); + chai.add(chaiscript::fun(&add_3), "add_3"); + auto v = chai.eval("add_3(12)"); + CHECK(v == 15); +} + + + From 5c9b16bdced1b6bc5cae34a326dcbf23fe50f7fd Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 30 May 2017 08:34:17 -0600 Subject: [PATCH 61/84] Fix handling of const return types #430 --- include/chaiscript/dispatchkit/handle_return.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/chaiscript/dispatchkit/handle_return.hpp b/include/chaiscript/dispatchkit/handle_return.hpp index 8243333b..8570c8d0 100644 --- a/include/chaiscript/dispatchkit/handle_return.hpp +++ b/include/chaiscript/dispatchkit/handle_return.hpp @@ -181,9 +181,9 @@ namespace chaiscript template struct Handle_Return { - static Boxed_Value handle(const Ret &r) + static Boxed_Value handle(Ret r) { - return Boxed_Value(std::cref(r)); + return Boxed_Value(std::move(r)); } }; From a999ea3692d43650956ed5dd8c26716121ea0aef Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 30 May 2017 08:34:17 -0600 Subject: [PATCH 62/84] Fix handling of const return types #430 --- include/chaiscript/dispatchkit/handle_return.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/chaiscript/dispatchkit/handle_return.hpp b/include/chaiscript/dispatchkit/handle_return.hpp index 8243333b..8570c8d0 100644 --- a/include/chaiscript/dispatchkit/handle_return.hpp +++ b/include/chaiscript/dispatchkit/handle_return.hpp @@ -181,9 +181,9 @@ namespace chaiscript template struct Handle_Return { - static Boxed_Value handle(const Ret &r) + static Boxed_Value handle(Ret r) { - return Boxed_Value(std::cref(r)); + return Boxed_Value(std::move(r)); } }; From 9f8b57c145da9251e343750f416880092a90e6b5 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 30 May 2017 09:16:20 -0600 Subject: [PATCH 63/84] Enable ChaiScript compilation for C++17 Closes #348 This works by taking into account the fact that `noexcept` is now part of the type system in C++17. However, this would conflict with pre-C++17 compilers, so I have added a feature macro around it --- .../dispatchkit/register_function.hpp | 35 ++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/include/chaiscript/dispatchkit/register_function.hpp b/include/chaiscript/dispatchkit/register_function.hpp index ef17fb86..e660790d 100644 --- a/include/chaiscript/dispatchkit/register_function.hpp +++ b/include/chaiscript/dispatchkit/register_function.hpp @@ -48,6 +48,7 @@ namespace chaiscript chaiscript::make_shared>(t)); } + template Proxy_Function fun(Ret (*func)(Param...)) { @@ -77,13 +78,45 @@ namespace chaiscript } - template::value>::type*/> Proxy_Function fun(T Class::* m /*, typename std::enable_if::value>::type* = 0*/ ) { return Proxy_Function(chaiscript::make_shared>(m)); } +// only compile this bit if noexcept is part of the type system +// +#if __cpp_noexcept_function_type >= 201510 + template + Proxy_Function fun(Ret (*func)(Param...) noexcept) + { + auto fun_call = dispatch::detail::Fun_Caller(func); + + return Proxy_Function( + chaiscript::make_shared>(fun_call)); + + } + + template + Proxy_Function fun(Ret (Class::*t_func)(Param...) const noexcept) + { + auto call = dispatch::detail::Const_Caller(t_func); + + return Proxy_Function( + chaiscript::make_shared>(call)); + } + + template + Proxy_Function fun(Ret (Class::*t_func)(Param...) noexcept) + { + auto call = dispatch::detail::Caller(t_func); + + return Proxy_Function( + chaiscript::make_shared>(call)); + + } +#endif + From bd736eddec762e6708663607048d1b2b80e65077 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 30 May 2017 11:33:12 -0600 Subject: [PATCH 64/84] Deprecate GLOBAL #247 --- include/chaiscript/language/chaiscript_parser.hpp | 2 +- unittests/global.chai | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index f60fc959..93e69343 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -2172,7 +2172,7 @@ namespace chaiscript throw exception::eval_error("Incomplete variable declaration", File_Position(m_position.line, m_position.col), *m_filename); } - } else if (Keyword("GLOBAL") || Keyword("global")) { + } else if (Keyword("global")) { retval = true; if (!(Reference() || Id(true))) { diff --git a/unittests/global.chai b/unittests/global.chai index 0374e6d3..7f8959a6 100644 --- a/unittests/global.chai +++ b/unittests/global.chai @@ -1,12 +1,12 @@ // Test global -GLOBAL g = 3; +global g = 3; assert_true(g == 3); var v := g; assert_true(v == 3); -GLOBAL g = 2; +global g = 2; assert_true(g == 2); assert_true(v == 2); From 3b48983bc25299896052801b7c3f9608dcdbdb8b Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 31 May 2017 13:54:45 -0600 Subject: [PATCH 65/84] Revert "Add workaround for chaiscript used as static" This reverts commit a281d9571e00788784a10bdae054f92cb3e3fb1a. --- include/chaiscript/chaiscript_threading.hpp | 35 ++++++--------------- 1 file changed, 9 insertions(+), 26 deletions(-) diff --git a/include/chaiscript/chaiscript_threading.hpp b/include/chaiscript/chaiscript_threading.hpp index 4a255735..01bda2bb 100644 --- a/include/chaiscript/chaiscript_threading.hpp +++ b/include/chaiscript/chaiscript_threading.hpp @@ -75,19 +75,17 @@ namespace chaiscript ~Thread_Storage() { - if (!destroyed) { - t().erase(this); - } + t().erase(this); } inline const T *operator->() const { - return &(t()[const_cast(this)]); + return &(t()[this]); } inline const T &operator*() const { - return t()[const_cast(this)]; + return t()[this]; } inline T *operator->() @@ -100,30 +98,15 @@ namespace chaiscript return t()[this]; } + + void *m_key; + private: - struct Map_Holder { - std::unordered_map *, T> map; - - Map_Holder() = default; - Map_Holder(const Map_Holder &) = delete; - Map_Holder(Map_Holder &&) = delete; - Map_Holder& operator=(Map_Holder &&) = delete; - Map_Holder& operator=(const Map_Holder &&) = delete; - ~Map_Holder() { - // here is the theory: - // * If the Map_Holder is destroyed before the Thread_Storage, a flag will get set - // * If destroyed after the Thread_Storage, the * will have been removed from `map` and nothing will happen - for(auto &elem : map) { elem.first->destroyed = true; } - } - }; - - static std::unordered_map *, T> &t() + static std::unordered_map &t() { - thread_local Map_Holder my_map; - return my_map.map; + thread_local std::unordered_map my_t; + return my_t; } - - bool destroyed{false}; }; #else // threading disabled From bdd0a12bb71cd5dd3ac47152e9ec5ffb44f1dca4 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 31 May 2017 14:09:07 -0600 Subject: [PATCH 66/84] ChaiScript can only support static in non-threading mode --- cheatsheet.md | 3 +++ include/chaiscript/chaiscript_threading.hpp | 2 +- unittests/static_chaiscript.cpp | 6 ++++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/cheatsheet.md b/cheatsheet.md index 2e2c218f..8cf3d3f4 100644 --- a/cheatsheet.md +++ b/cheatsheet.md @@ -15,6 +15,9 @@ chaiscript::ChaiScript chai; // loads stdlib from loadable module on file system chaiscript::ChaiScript chai(chaiscript::Std_Lib::library()); // compiles in stdlib ``` +Note that ChaiScript cannot be used as a global / static object unless it is being compiled with `CHAISCRIPT_NO_THREADS`. + + # Adding Things To The Engine ## Adding a Function / Method / Member diff --git a/include/chaiscript/chaiscript_threading.hpp b/include/chaiscript/chaiscript_threading.hpp index 01bda2bb..79feaa1e 100644 --- a/include/chaiscript/chaiscript_threading.hpp +++ b/include/chaiscript/chaiscript_threading.hpp @@ -144,7 +144,7 @@ namespace chaiscript class Thread_Storage { public: - explicit Thread_Storage(void *) + explicit Thread_Storage() { } diff --git a/unittests/static_chaiscript.cpp b/unittests/static_chaiscript.cpp index fb003044..beeac2d1 100644 --- a/unittests/static_chaiscript.cpp +++ b/unittests/static_chaiscript.cpp @@ -1,3 +1,9 @@ + +#define CHAISCRIPT_NO_THREADS + +/// ChaiScript as a static is unsupported with thread support enabled +/// + #include static chaiscript::ChaiScript chai; From ab90c6171063ed0e6d145c8cb35e74161e1ad380 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 31 May 2017 14:36:09 -0600 Subject: [PATCH 67/84] Add gcc6/7 to travis --- .travis.yml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/.travis.yml b/.travis.yml index 01ab0ea8..4a1202bf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,6 +8,8 @@ addons: packages: - g++-4.9 - g++-5 + - g++-6 + - g++-7 coverity_scan: project: name: "ChaiScript/ChaiScript" @@ -31,6 +33,14 @@ matrix: sudo: false env: GCC_VER="5" CPPCHECK=1 COVERAGE=1 CMAKE_OPTIONS="-D RUN_FUZZY_TESTS:BOOL=TRUE" compiler: gcc + - os: linux + sudo: false + env: GCC_VER="6" CPPCHECK=1 COVERAGE=1 CMAKE_OPTIONS="-D RUN_FUZZY_TESTS:BOOL=TRUE" + compiler: gcc + - os: linux + sudo: false + env: GCC_VER="7" CPPCHECK=1 COVERAGE=1 CMAKE_OPTIONS="-D RUN_FUZZY_TESTS:BOOL=TRUE" + compiler: gcc - os: osx compiler: clang osx_image: xcode8 From 562ca5aee6f21703e37012648a870156e6c0178e Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 31 May 2017 14:44:14 -0600 Subject: [PATCH 68/84] gcc-6 only, not 7 yet --- .travis.yml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4a1202bf..0aadff1e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -37,10 +37,6 @@ matrix: sudo: false env: GCC_VER="6" CPPCHECK=1 COVERAGE=1 CMAKE_OPTIONS="-D RUN_FUZZY_TESTS:BOOL=TRUE" compiler: gcc - - os: linux - sudo: false - env: GCC_VER="7" CPPCHECK=1 COVERAGE=1 CMAKE_OPTIONS="-D RUN_FUZZY_TESTS:BOOL=TRUE" - compiler: gcc - os: osx compiler: clang osx_image: xcode8 From 94f7bfec2b7a09a1e3fda8afbcfa057ecb084c9b Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 31 May 2017 14:46:20 -0600 Subject: [PATCH 69/84] Remove gcc-7 from package list for travis --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 0aadff1e..7471e1ee 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,6 @@ addons: - g++-4.9 - g++-5 - g++-6 - - g++-7 coverity_scan: project: name: "ChaiScript/ChaiScript" From d720d069ca3f6656c5d9779925915031e44e3422 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 31 May 2017 14:56:51 -0600 Subject: [PATCH 70/84] Attempt to add visual studio 2017 to appveyor --- appveyor.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 50c59211..042e1e59 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,15 +1,17 @@ version: 5.8.x.{build} -os: Visual Studio 2015 +image: + - Visual Studio 2017 environment: matrix: - - {} + - VS_VERSION: "Visual Studio 14" + - VS_VERSION: "Visual Studio 15" build_script: - cmd: >- mkdir build cd build - cmake c:\Projects\chaiscript -G "Visual Studio 14" + cmake c:\Projects\chaiscript -G "%VS_VERSION%" cmake --build . --config Debug test_script: From 76c7712507109d6e2a512d7090d9aacf86e18fe4 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Mon, 5 Jun 2017 19:36:40 -0600 Subject: [PATCH 71/84] Test custom exception handling #351 --- unittests/compiled_tests.cpp | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/unittests/compiled_tests.cpp b/unittests/compiled_tests.cpp index 86dcc092..4cb09da7 100644 --- a/unittests/compiled_tests.cpp +++ b/unittests/compiled_tests.cpp @@ -1288,4 +1288,32 @@ TEST_CASE("Test returning by const non-reference") } +struct MyException : std::runtime_error +{ + using std::runtime_error::runtime_error; + int value = 5; +}; + +void throws_a_thing() +{ + throw MyException("Hello World"); +} + +TEST_CASE("Test throwing and catching custom exception") +{ + chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser()); + chai.add(chaiscript::user_type(), "MyException"); + chai.add(chaiscript::base_class()); // be sure to register base class relationship + chai.add(chaiscript::fun(&throws_a_thing), "throws_a_thing"); + chai.add(chaiscript::fun(&MyException::value), "value"); + + const auto s = chai.eval("fun(){ try { throws_a_thing(); } catch (MyException ex) { return ex.what(); } }()"); + CHECK(s == "Hello World"); + + // this has an explicit clone to prevent returning a pointer to the `value` from inside of MyException + const auto i = chai.eval("fun(){ try { throws_a_thing(); } catch (MyException ex) { var v = clone(ex.value); print(v); return v; } }()"); + CHECK(i == 5); +} + + From 36e61dec0a1412ba2a09e15c6f45785f24915daf Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 6 Jun 2017 14:59:05 -0600 Subject: [PATCH 72/84] Fix defaults for dynload options --- include/chaiscript/chaiscript.hpp | 2 +- unittests/compiled_tests.cpp | 6 ++++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/include/chaiscript/chaiscript.hpp b/include/chaiscript/chaiscript.hpp index 2d28c962..dbf6d73b 100644 --- a/include/chaiscript/chaiscript.hpp +++ b/include/chaiscript/chaiscript.hpp @@ -832,7 +832,7 @@ namespace chaiscript public: ChaiScript(std::vector t_modulepaths = {}, std::vector t_usepaths = {}, - const std::vector &t_opts = {}) + const std::vector &t_opts = chaiscript::default_options()) : ChaiScript_Basic( chaiscript::Std_Lib::library(), std::make_unique>(), diff --git a/unittests/compiled_tests.cpp b/unittests/compiled_tests.cpp index 4cb09da7..6e241572 100644 --- a/unittests/compiled_tests.cpp +++ b/unittests/compiled_tests.cpp @@ -1316,4 +1316,10 @@ TEST_CASE("Test throwing and catching custom exception") } +TEST_CASE("Test ability to get 'use' function from default construction") +{ + chaiscript::ChaiScript chai; + const auto use_function = chai.eval>("use"); +} + From 700a6205521f81105f19c30618664e7b93add5a1 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 6 Jun 2017 16:47:23 -0600 Subject: [PATCH 73/84] Add option to compile in C++17 mode for testing --- CMakeLists.txt | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 9e152d71..048c2e54 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -22,6 +22,7 @@ option(BUILD_SAMPLES "Build Samples Folder" FALSE) option(RUN_FUZZY_TESTS "Run tests generated by AFL" FALSE) option(USE_STD_MAKE_SHARED "Use std::make_shared instead of chaiscript::make_shared" FALSE) option(RUN_PERFORMANCE_TESTS "Run Performance Tests" FALSE) +option(BUILD_IN_CPP17_MODE "Build with C++17 flags" FALSE) mark_as_advanced(USE_STD_MAKE_SHARED) @@ -150,12 +151,20 @@ if(CMAKE_COMPILER_IS_GNUCC) execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION) if(GCC_VERSION VERSION_LESS 4.9) - set(CPP11_FLAG "-std=c++1y") + set(CPP14_FLAG "-std=c++1y") else() - set(CPP11_FLAG "-std=c++14") + if (BUILD_IN_CPP17_MODE) + set(CPP14_FLAG "-std=c++1z") + else() + set(CPP14_FLAG "-std=c++14") + endif() endif() else() - set(CPP11_FLAG "-std=c++14") + if (BUILD_IN_CPP17_MODE) + set(CPP14_FLAG "-std=c++1z") + else() + set(CPP14_FLAG "-std=c++14") + endif() endif() if(MSVC) @@ -179,7 +188,7 @@ if(MSVC) # how to workaround or fix the error. So I'm disabling it globally. add_definitions(/wd4503) else() - add_definitions(-Wall -Wextra -Wconversion -Wshadow -Wnon-virtual-dtor -Wold-style-cast -Wcast-align -Wcast-qual -Wunused -Woverloaded-virtual -pedantic ${CPP11_FLAG}) + add_definitions(-Wall -Wextra -Wconversion -Wshadow -Wnon-virtual-dtor -Wold-style-cast -Wcast-align -Wcast-qual -Wunused -Woverloaded-virtual -pedantic ${CPP14_FLAG}) if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") add_definitions(-Weverything -Wno-c++98-compat-pedantic -Wno-c++98-compat -Wno-documentation -Wno-switch-enum -Wno-weak-vtables -Wno-missing-prototypes -Wno-padded -Wno-missing-noreturn -Wno-exit-time-destructors -Wno-documentation-unknown-command) @@ -197,12 +206,12 @@ if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") if(USE_LIBCXX) add_definitions(-stdlib=libc++) - set(LINKER_FLAGS "${LINKER_FLAGS} ${CPP11_FLAG} -stdlib=libc++") + set(LINKER_FLAGS "${LINKER_FLAGS} ${CPP14_FLAG} -stdlib=libc++") else() - set(LINKER_FLAGS "${LINKER_FLAGS} ${CPP11_FLAG}") + set(LINKER_FLAGS "${LINKER_FLAGS} ${CPP14_FLAG}") endif() elseif(CMAKE_COMPILER_IS_GNUCC) - set(LINKER_FLAGS "${LINKER_FLAGS} ${CPP11_FLAG}") + set(LINKER_FLAGS "${LINKER_FLAGS} ${CPP14_FLAG}") endif() # limitations in MinGW require us to make an optimized build From 5a5600914c47a8c8cadb7c19d1b2f600a9a4aa55 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 21 Jun 2017 21:27:48 -0600 Subject: [PATCH 74/84] Move away from shared_ptr for parse nodes --- include/chaiscript/chaiscript_defines.hpp | 10 + include/chaiscript/dispatchkit/bootstrap.hpp | 10 +- .../dispatchkit/proxy_functions.hpp | 14 +- .../chaiscript/language/chaiscript_common.hpp | 93 ++++++-- .../chaiscript/language/chaiscript_engine.hpp | 4 +- .../chaiscript/language/chaiscript_eval.hpp | 224 ++++++++++-------- .../language/chaiscript_optimizer.hpp | 188 ++++++++------- .../chaiscript/language/chaiscript_parser.hpp | 54 ++--- src/main.cpp | 2 +- 9 files changed, 357 insertions(+), 242 deletions(-) diff --git a/include/chaiscript/chaiscript_defines.hpp b/include/chaiscript/chaiscript_defines.hpp index be837c26..5b2e84f4 100644 --- a/include/chaiscript/chaiscript_defines.hpp +++ b/include/chaiscript/chaiscript_defines.hpp @@ -93,6 +93,16 @@ namespace chaiscript { #endif } + template + inline std::unique_ptr make_unique(Arg && ... arg) + { +#ifdef CHAISCRIPT_USE_STD_MAKE_SHARED + return std::make_unique(std::forward(arg)...); +#else + return std::unique_ptr(static_cast(new D(std::forward(arg)...))); +#endif + } + struct Build_Info { static int version_major() { diff --git a/include/chaiscript/dispatchkit/bootstrap.hpp b/include/chaiscript/dispatchkit/bootstrap.hpp index cbb91a51..8aedb353 100644 --- a/include/chaiscript/dispatchkit/bootstrap.hpp +++ b/include/chaiscript/dispatchkit/bootstrap.hpp @@ -305,13 +305,13 @@ namespace chaiscript static bool has_parse_tree(const chaiscript::Const_Proxy_Function &t_pf) { const auto pf = std::dynamic_pointer_cast(t_pf); - return pf && pf->get_parse_tree(); + return bool(pf); } - static chaiscript::AST_NodePtr get_parse_tree(const chaiscript::Const_Proxy_Function &t_pf) + static const chaiscript::AST_Node &get_parse_tree(const chaiscript::Const_Proxy_Function &t_pf) { const auto pf = std::dynamic_pointer_cast(t_pf); - if (pf && pf->get_parse_tree()) + if (pf) { return pf->get_parse_tree(); } else { @@ -545,7 +545,7 @@ namespace chaiscript std::vector retval; std::transform(t_eval_error.call_stack.begin(), t_eval_error.call_stack.end(), std::back_inserter(retval), - &chaiscript::var &>); + &chaiscript::var); return retval; }), "call_stack"} } ); @@ -574,7 +574,7 @@ namespace chaiscript const auto children = t_node.get_children(); std::transform(children.begin(), children.end(), std::back_inserter(retval), - &chaiscript::var &>); + &chaiscript::var &>); return retval; }), "children"} } diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index bb57c698..2afda8dd 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -41,7 +41,7 @@ namespace chaiscript class Boxed_Number; struct AST_Node; - typedef std::shared_ptr AST_NodePtr; + typedef std::unique_ptr AST_NodePtr; namespace dispatch { @@ -346,8 +346,8 @@ namespace chaiscript { public: Dynamic_Proxy_Function( - int t_arity=-1, - AST_NodePtr t_parsenode = AST_NodePtr(), + const int t_arity, + std::shared_ptr t_parsenode, Param_Types t_param_types = Param_Types(), Proxy_Function t_guard = Proxy_Function()) : Proxy_Function_Base(build_param_type_list(t_param_types), t_arity), @@ -379,9 +379,9 @@ namespace chaiscript return m_guard; } - AST_NodePtr get_parse_tree() const + const AST_Node &get_parse_tree() const { - return m_parsenode; + return *m_parsenode; } @@ -445,7 +445,7 @@ namespace chaiscript private: Proxy_Function m_guard; - AST_NodePtr m_parsenode; + std::shared_ptr m_parsenode; }; @@ -457,7 +457,7 @@ namespace chaiscript Dynamic_Proxy_Function_Impl( Callable t_f, int t_arity=-1, - AST_NodePtr t_parsenode = AST_NodePtr(), + std::shared_ptr t_parsenode = AST_NodePtr(), Param_Types t_param_types = Param_Types(), Proxy_Function t_guard = Proxy_Function()) : Dynamic_Proxy_Function( diff --git a/include/chaiscript/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index 602efd54..5fe377c4 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -124,8 +124,10 @@ namespace chaiscript /// \brief Typedef for pointers to AST_Node objects. Used in building of the AST_Node tree - typedef std::shared_ptr AST_NodePtr; - typedef std::shared_ptr AST_NodePtr_Const; + typedef std::unique_ptr AST_NodePtr; + typedef std::unique_ptr AST_NodePtr_Const; + + struct AST_Node_Trace; /// \brief Classes which may be thrown during error cases when ChaiScript is executing. @@ -168,7 +170,7 @@ namespace chaiscript File_Position start_position; std::string filename; std::string detail; - std::vector call_stack; + std::vector call_stack; eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname, const std::vector &t_parameters, const std::vector &t_functions, @@ -228,26 +230,26 @@ namespace chaiscript template static AST_Node_Type id(const T& t) { - return t->identifier; + return t.identifier; } template static std::string pretty(const T& t) { - return t->pretty_print(); + return t.pretty_print(); } template static const std::string &fname(const T& t) { - return t->filename(); + return t.filename(); } template static std::string startpos(const T& t) { std::ostringstream oss; - oss << t->start().line << ", " << t->start().column; + oss << t.start().line << ", " << t.start().column; return oss.str(); } @@ -321,7 +323,7 @@ namespace chaiscript } } - retval += "\n Defined at " + format_location(dynfun->get_parse_tree()); + retval += "\n Defined at " + format_location(dynfun->get_parse_tree()); } return retval; @@ -330,20 +332,15 @@ namespace chaiscript template static std::string format_guard(const T &t) { - return t->pretty_print(); + return t.pretty_print(); } template static std::string format_location(const T &t) { - if (t) { - std::ostringstream oss; - oss << "(" << t->filename() << " " << t->start().line << ", " << t->start().column << ")"; - return oss.str(); - } else { - return "(internal)"; - } - + std::ostringstream oss; + oss << "(" << t.filename() << " " << t.start().line << ", " << t.start().column << ")"; + return oss.str(); } static std::string format_detail(const std::vector &t_functions, @@ -492,7 +489,7 @@ namespace chaiscript /// \brief Struct that doubles as both a parser ast_node and an AST node. - struct AST_Node : std::enable_shared_from_this { + struct AST_Node { public: const AST_Node_Type identifier; const std::string text; @@ -516,14 +513,14 @@ namespace chaiscript oss << text; - for (auto & elem : this->get_children()) { - oss << elem->pretty_print() << ' '; + for (auto & elem : get_children()) { + oss << elem.get().pretty_print() << ' '; } return oss.str(); } - virtual std::vector get_children() const = 0; + virtual std::vector> get_children() const = 0; virtual Boxed_Value eval(const chaiscript::detail::Dispatch_State &t_e) const = 0; @@ -534,8 +531,8 @@ namespace chaiscript oss << t_prepend << "(" << ast_node_type_to_string(this->identifier) << ") " << this->text << " : " << this->location.start.line << ", " << this->location.start.column << '\n'; - for (auto & elem : this->get_children()) { - oss << elem->to_string(t_prepend + " "); + for (auto & elem : get_children()) { + oss << elem.get().to_string(t_prepend + " "); } return oss.str(); } @@ -568,12 +565,60 @@ namespace chaiscript }; + struct AST_Node_Trace + { + const AST_Node_Type identifier; + const std::string text; + Parse_Location location; + + const std::string &filename() const { + return *location.filename; + } + + const File_Position &start() const { + return location.start; + } + + const File_Position &end() const { + return location.end; + } + + std::string pretty_print() const + { + std::ostringstream oss; + + oss << text; + + for (const auto & elem : children) { + oss << elem.pretty_print() << ' '; + } + + return oss.str(); + } + + std::vector get_children(const AST_Node &node) + { + const auto node_children = node.get_children(); + return std::vector(node_children.begin(), node_children.end()); + } + + AST_Node_Trace(const AST_Node &node) + : identifier(node.identifier), text(node.text), + location(node.location), children(get_children(node)) + { + } + + + std::vector children; + + }; + namespace parser { class ChaiScript_Parser_Base { public: virtual AST_NodePtr parse(const std::string &t_input, const std::string &t_fname) = 0; - virtual void debug_print(AST_NodePtr t, std::string prepend = "") const = 0; + virtual void debug_print(const AST_Node &t, std::string prepend = "") const = 0; virtual void *get_tracer_ptr() = 0; virtual ~ChaiScript_Parser_Base() = default; ChaiScript_Parser_Base() = default; diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index 37131773..dc0b8536 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -332,9 +332,9 @@ explicit ChaiScript_Basic(std::unique_ptr &&pars AST_NodePtr parse(const std::string &t_input, const bool t_debug_print = false) { - const auto ast = m_parser->parse(t_input, "PARSE"); + auto ast = m_parser->parse(t_input, "PARSE"); if (t_debug_print) { - m_parser->debug_print(ast); + m_parser->debug_print(*ast); } return ast; } diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 95e2218e..4388649d 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -47,13 +47,13 @@ namespace chaiscript { template struct AST_Node_Impl; - template using AST_Node_Impl_Ptr = typename std::shared_ptr>; + template using AST_Node_Impl_Ptr = typename std::unique_ptr>; namespace detail { /// Helper function that will set up the scope around a function call, including handling the named function parameters template - static Boxed_Value eval_function(chaiscript::detail::Dispatch_Engine &t_ss, const AST_Node_Impl_Ptr &t_node, const std::vector &t_param_names, const std::vector &t_vals, const std::map *t_locals=nullptr, bool has_this_capture = false) { + static Boxed_Value eval_function(chaiscript::detail::Dispatch_Engine &t_ss, const AST_Node_Impl &t_node, const std::vector &t_param_names, const std::vector &t_vals, const std::map *t_locals=nullptr, bool has_this_capture = false) { chaiscript::detail::Dispatch_State state(t_ss); const Boxed_Value *thisobj = [&]() -> const Boxed_Value *{ @@ -83,7 +83,7 @@ namespace chaiscript } try { - return t_node->eval(state); + return t_node.eval(state); } catch (detail::Return_Value &rv) { return std::move(rv.retval); } @@ -106,8 +106,14 @@ namespace chaiscript } - std::vector get_children() const final { - return {children.begin(), children.end()}; + std::vector> get_children() const final { + std::vector> retval; + retval.reserve(children.size()); + for (auto &&child : children) { + retval.emplace_back(*child); + } + + return retval; } Boxed_Value eval(const chaiscript::detail::Dispatch_State &t_e) const final @@ -116,7 +122,7 @@ namespace chaiscript T::trace(t_e, this); return eval_internal(t_e); } catch (exception::eval_error &ee) { - ee.call_stack.push_back(shared_from_this()); + ee.call_stack.push_back(*this); throw; } } @@ -364,44 +370,44 @@ namespace chaiscript AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Arg_List, std::move(t_loc), std::move(t_children)) { } - static std::string get_arg_name(const AST_Node_Impl_Ptr &t_node) { - if (t_node->children.empty()) + static std::string get_arg_name(const AST_Node_Impl &t_node) { + if (t_node.children.empty()) { - return t_node->text; - } else if (t_node->children.size() == 1) { - return t_node->children[0]->text; + return t_node.text; + } else if (t_node.children.size() == 1) { + return t_node.children[0]->text; } else { - return t_node->children[1]->text; + return t_node.children[1]->text; } } - static std::vector get_arg_names(const AST_Node_Impl_Ptr &t_node) { + static std::vector get_arg_names(const AST_Node_Impl &t_node) { std::vector retval; - for (const auto &node : t_node->children) + for (const auto &node : t_node.children) { - retval.push_back(get_arg_name(node)); + retval.push_back(get_arg_name(*node)); } return retval; } - static std::pair get_arg_type(const AST_Node_Impl_Ptr &t_node, const chaiscript::detail::Dispatch_State &t_ss) + static std::pair get_arg_type(const AST_Node_Impl &t_node, const chaiscript::detail::Dispatch_State &t_ss) { - if (t_node->children.size() < 2) + if (t_node.children.size() < 2) { return {}; } else { - return {t_node->children[0]->text, t_ss->get_type(t_node->children[0]->text, false)}; + return {t_node.children[0]->text, t_ss->get_type(t_node.children[0]->text, false)}; } } - static dispatch::Param_Types get_arg_types(const AST_Node_Impl_Ptr &t_node, const chaiscript::detail::Dispatch_State &t_ss) { + static dispatch::Param_Types get_arg_types(const AST_Node_Impl &t_node, const chaiscript::detail::Dispatch_State &t_ss) { std::vector> retval; - for (const auto &child : t_node->children) + for (const auto &child : t_node.children) { - retval.push_back(get_arg_type(child, t_ss)); + retval.push_back(get_arg_type(*child, t_ss)); } return dispatch::Param_Types(std::move(retval)); @@ -621,9 +627,15 @@ namespace chaiscript template struct Lambda_AST_Node final : AST_Node_Impl { Lambda_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : - AST_Node_Impl(t_ast_node_text, AST_Node_Type::Lambda, std::move(t_loc), std::move(t_children)), - m_param_names(Arg_List_AST_Node::get_arg_names(this->children[1])), - m_this_capture(has_this_capture(this->children[0]->children)) + AST_Node_Impl(t_ast_node_text, + AST_Node_Type::Lambda, + std::move(t_loc), + std::vector>(std::make_move_iterator(t_children.begin()), + std::make_move_iterator(std::prev(t_children.end()))) + ), + m_param_names(Arg_List_AST_Node::get_arg_names(*this->children[1])), + m_this_capture(has_this_capture(this->children[0]->children)), + m_lambda_node(std::move(t_children.back())) { } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { @@ -637,18 +649,18 @@ namespace chaiscript }(); const auto numparams = this->children[1]->children.size(); - const auto param_types = Arg_List_AST_Node::get_arg_types(this->children[1], t_ss); + const auto param_types = Arg_List_AST_Node::get_arg_types(*this->children[1], t_ss); - const auto &lambda_node = this->children.back(); std::reference_wrapper engine(*t_ss); return Boxed_Value( dispatch::make_dynamic_proxy_function( - [engine, lambda_node, param_names = this->m_param_names, captures, this_capture = this->m_this_capture](const std::vector &t_params) + [engine, lambda_node = this->m_lambda_node, param_names = this->m_param_names, captures, + this_capture = this->m_this_capture] (const std::vector &t_params) { - return detail::eval_function(engine, lambda_node, param_names, t_params, &captures, this_capture); + return detail::eval_function(engine, *lambda_node, param_names, t_params, &captures, this_capture); }, - static_cast(numparams), lambda_node, param_types + static_cast(numparams), m_lambda_node, param_types ) ); } @@ -664,7 +676,7 @@ namespace chaiscript private: const std::vector m_param_names; const bool m_this_capture = false; - + const std::shared_ptr> m_lambda_node; }; template @@ -699,55 +711,81 @@ namespace chaiscript template struct Def_AST_Node final : AST_Node_Impl { + + std::shared_ptr> m_body_node; + std::shared_ptr> m_guard_node; + Def_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : - AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Def, std::move(t_loc), std::move(t_children)) { } + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Def, std::move(t_loc), + std::vector>(std::make_move_iterator(t_children.begin()), + std::make_move_iterator(std::prev(t_children.end(), has_guard(t_children)?2:1))) + ), + 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)) + + { } + + static std::shared_ptr> get_guard_node(std::vector> &&vec, bool has_guard) + { + if (has_guard) { + return std::move(*std::prev(vec.end(), 2)); + } else { + return {}; + } + } + + static std::shared_ptr> get_body_node(std::vector> &&vec) + { + return std::move(vec.back()); + } + + static bool has_guard(const std::vector> &t_children) + { + if ((t_children.size() > 2) && (t_children[1]->identifier == AST_Node_Type::Arg_List)) { + if (t_children.size() > 3) { + return true; + } + } + else { + if (t_children.size() > 2) { + return true; + } + } + return false; + } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ std::vector t_param_names; size_t numparams = 0; - AST_Node_Impl_Ptr guardnode; dispatch::Param_Types param_types; - if ((this->children.size() > 2) && (this->children[1]->identifier == AST_Node_Type::Arg_List)) { + if ((this->children.size() > 1) && (this->children[1]->identifier == AST_Node_Type::Arg_List)) { numparams = this->children[1]->children.size(); - t_param_names = Arg_List_AST_Node::get_arg_names(this->children[1]); - param_types = Arg_List_AST_Node::get_arg_types(this->children[1], t_ss); - - if (this->children.size() > 3) { - guardnode = this->children[2]; - } - } - else { - //no parameters - numparams = 0; - - if (this->children.size() > 2) { - guardnode = this->children[1]; - } + t_param_names = Arg_List_AST_Node::get_arg_names(*this->children[1]); + param_types = Arg_List_AST_Node::get_arg_types(*this->children[1], t_ss); } std::reference_wrapper engine(*t_ss); std::shared_ptr guard; - if (guardnode) { + if (m_guard_node) { guard = dispatch::make_dynamic_proxy_function( - [engine, guardnode, t_param_names](const std::vector &t_params) + [engine, guardnode = m_guard_node, t_param_names](const std::vector &t_params) { - return detail::eval_function(engine, guardnode, t_param_names, t_params); + return detail::eval_function(engine, *guardnode, t_param_names, t_params); }, - static_cast(numparams), guardnode); + static_cast(numparams), m_guard_node); } try { const std::string & l_function_name = this->children[0]->text; - const auto & func_node = this->children.back(); t_ss->add( dispatch::make_dynamic_proxy_function( - [engine, guardnode, func_node, t_param_names](const std::vector &t_params) + [engine, func_node = m_body_node, t_param_names](const std::vector &t_params) { - return detail::eval_function(engine, func_node, t_param_names, t_params); + return detail::eval_function(engine, *func_node, t_param_names, t_params); }, - static_cast(numparams), this->children.back(), + static_cast(numparams), m_body_node, param_types, guard), l_function_name); } catch (const exception::name_conflict_error &e) { throw exception::eval_error("Function redefined '" + e.name() + "'"); @@ -1230,32 +1268,32 @@ namespace chaiscript } for (size_t i = 1; i < end_point; ++i) { chaiscript::eval::detail::Scope_Push_Pop catch_scope(t_ss); - AST_Node_Impl_Ptr catch_block = this->children[i]; + auto &catch_block = *this->children[i]; - if (catch_block->children.size() == 1) { + if (catch_block.children.size() == 1) { //No variable capture, no guards - retval = catch_block->children[0]->eval(t_ss); + retval = catch_block.children[0]->eval(t_ss); break; - } else if (catch_block->children.size() == 2 || catch_block->children.size() == 3) { - const auto name = Arg_List_AST_Node::get_arg_name(catch_block->children[0]); + } else if (catch_block.children.size() == 2 || catch_block.children.size() == 3) { + const auto name = Arg_List_AST_Node::get_arg_name(*catch_block.children[0]); if (dispatch::Param_Types( - std::vector>{Arg_List_AST_Node::get_arg_type(catch_block->children[0], t_ss)} + std::vector>{Arg_List_AST_Node::get_arg_type(*catch_block.children[0], t_ss)} ).match(std::vector{t_except}, t_ss.conversions()).first) { t_ss.add_object(name, t_except); - if (catch_block->children.size() == 2) { + if (catch_block.children.size() == 2) { //Variable capture, no guards - retval = catch_block->children[1]->eval(t_ss); + retval = catch_block.children[1]->eval(t_ss); break; } - else if (catch_block->children.size() == 3) { + else if (catch_block.children.size() == 3) { //Variable capture, guards bool guard = false; try { - guard = boxed_cast(catch_block->children[1]->eval(t_ss)); + guard = boxed_cast(catch_block.children[1]->eval(t_ss)); } catch (const exception::bad_boxed_cast &) { if (this->children.back()->identifier == AST_Node_Type::Finally) { this->children.back()->children[0]->eval(t_ss); @@ -1263,7 +1301,7 @@ namespace chaiscript throw exception::eval_error("Guard condition not boolean"); } if (guard) { - retval = catch_block->children[2]->eval(t_ss); + retval = catch_block.children[2]->eval(t_ss); break; } } @@ -1335,8 +1373,18 @@ namespace chaiscript template struct Method_AST_Node final : AST_Node_Impl { + std::shared_ptr> m_body_node; + std::shared_ptr> m_guard_node; + Method_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : - AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Method, std::move(t_loc), std::move(t_children)) { } + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Method, std::move(t_loc), + std::vector>(std::make_move_iterator(t_children.begin()), + std::make_move_iterator(std::prev(t_children.end(), Def_AST_Node::has_guard(t_children)?2:1))) + ), + m_body_node(Def_AST_Node::get_body_node(std::move(t_children))), + m_guard_node(Def_AST_Node::get_guard_node(std::move(t_children), t_children.size()-this->children.size()==2)) + { + } Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ @@ -1348,39 +1396,27 @@ namespace chaiscript std::vector t_param_names{"this"}; dispatch::Param_Types param_types; - if ((this->children.size() > 3) + if ((this->children.size() > 2) && (this->children[2]->identifier == AST_Node_Type::Arg_List)) { - auto args = Arg_List_AST_Node::get_arg_names(this->children[2]); + auto args = Arg_List_AST_Node::get_arg_names(*this->children[2]); t_param_names.insert(t_param_names.end(), args.begin(), args.end()); - param_types = Arg_List_AST_Node::get_arg_types(this->children[2], t_ss); - - if (this->children.size() > 4) { - guardnode = this->children[3]; - } - } - else { - //no parameters - - if (this->children.size() > 3) { - guardnode = this->children[2]; - } + param_types = Arg_List_AST_Node::get_arg_types(*this->children[2], t_ss); } const size_t numparams = t_param_names.size(); std::shared_ptr guard; std::reference_wrapper engine(*t_ss); - if (guardnode) { + if (m_guard_node) { guard = dispatch::make_dynamic_proxy_function( - [engine, t_param_names, guardnode](const std::vector &t_params) { - return chaiscript::eval::detail::eval_function(engine, guardnode, t_param_names, t_params); + [engine, t_param_names, guardnode = m_guard_node](const std::vector &t_params) { + return chaiscript::eval::detail::eval_function(engine, *guardnode, t_param_names, t_params); }, - static_cast(numparams), guardnode); + static_cast(numparams), m_guard_node); } try { const std::string & function_name = this->children[1]->text; - auto node = this->children.back(); if (function_name == class_name) { param_types.push_front(class_name, Type_Info()); @@ -1388,10 +1424,10 @@ namespace chaiscript t_ss->add( std::make_shared(class_name, dispatch::make_dynamic_proxy_function( - [engine, t_param_names, node](const std::vector &t_params) { - return chaiscript::eval::detail::eval_function(engine, node, t_param_names, t_params); + [engine, t_param_names, node = m_body_node](const std::vector &t_params) { + return chaiscript::eval::detail::eval_function(engine, *node, t_param_names, t_params); }, - static_cast(numparams), node, param_types, guard + static_cast(numparams), m_body_node, param_types, guard ) ), function_name); @@ -1402,15 +1438,17 @@ namespace chaiscript auto type = t_ss->get_type(class_name, false); param_types.push_front(class_name, type); - t_ss->add(std::make_shared(class_name, + t_ss->add( + std::make_shared(class_name, dispatch::make_dynamic_proxy_function( - [engine, t_param_names, node](const std::vector &t_params) { - return chaiscript::eval::detail::eval_function(engine, node, t_param_names, t_params); + [engine, t_param_names, node = m_body_node](const std::vector &t_params) { + return chaiscript::eval::detail::eval_function(engine, *node, t_param_names, t_params); }, - static_cast(numparams), node, param_types, guard), type), + static_cast(numparams), m_body_node, param_types, guard), type), function_name); } } catch (const exception::name_conflict_error &e) { + std::cout << "Method!!" << std::endl; throw exception::eval_error("Method redefined '" + e.name() + "'"); } return void_var(); diff --git a/include/chaiscript/language/chaiscript_optimizer.hpp b/include/chaiscript/language/chaiscript_optimizer.hpp index 996b6971..675d092c 100644 --- a/include/chaiscript/language/chaiscript_optimizer.hpp +++ b/include/chaiscript/language/chaiscript_optimizer.hpp @@ -24,17 +24,26 @@ namespace chaiscript { template auto optimize(eval::AST_Node_Impl_Ptr p) { - (void)std::initializer_list{ (p = static_cast(*this).optimize(p), 0)... }; + (void)std::initializer_list{ (p = static_cast(*this).optimize(std::move(p)), 0)... }; return p; } }; template - auto child_at(const eval::AST_Node_Impl_Ptr &node, const size_t offset) { - if (node->children[offset]->identifier == AST_Node_Type::Compiled) { - return dynamic_cast&>(*node->children[offset]).m_original_node; + eval::AST_Node_Impl &child_at(eval::AST_Node_Impl &node, const size_t offset) { + if (node.children[offset]->identifier == AST_Node_Type::Compiled) { + return *(dynamic_cast &>(*node.children[offset]).m_original_node); } else { - return node->children[offset]; + return *node.children[offset]; + } + } + + template + const eval::AST_Node_Impl &child_at(const eval::AST_Node_Impl &node, const size_t offset) { + if (node.children[offset]->identifier == AST_Node_Type::Compiled) { + return *(dynamic_cast &>(*node.children[offset]).m_original_node); + } else { + return *node.children[offset]; } @@ -48,24 +57,24 @@ namespace chaiscript { } template - auto child_count(const eval::AST_Node_Impl_Ptr &node) { - if (node->identifier == AST_Node_Type::Compiled) { - return dynamic_cast&>(*node).m_original_node->children.size(); + auto child_count(const eval::AST_Node_Impl &node) { + if (node.identifier == AST_Node_Type::Compiled) { + return dynamic_cast&>(node).m_original_node->children.size(); } else { - return node->children.size(); + return node.children.size(); } } template - auto make_compiled_node(const eval::AST_Node_Impl_Ptr &original_node, std::vector> children, Callable callable) + auto make_compiled_node(eval::AST_Node_Impl_Ptr original_node, std::vector> children, Callable callable) { - return chaiscript::make_shared, eval::Compiled_AST_Node>(original_node, std::move(children), std::move(callable)); + return chaiscript::make_unique, eval::Compiled_AST_Node>(std::move(original_node), std::move(children), std::move(callable)); } struct Return { template - auto optimize(const eval::AST_Node_Impl_Ptr &p) + auto optimize(eval::AST_Node_Impl_Ptr p) { if ( (p->identifier == AST_Node_Type::Def || p->identifier == AST_Node_Type::Lambda) && !p->children.empty()) @@ -75,7 +84,7 @@ namespace chaiscript { auto &block_last_child = last_child->children.back(); if (block_last_child->identifier == AST_Node_Type::Return) { if (block_last_child->children.size() == 1) { - last_child->children.back() = block_last_child->children[0]; + last_child->children.back() = std::move(block_last_child->children[0]); } } } @@ -86,9 +95,9 @@ namespace chaiscript { }; template - bool contains_var_decl_in_scope(const T &node) + bool contains_var_decl_in_scope(const eval::AST_Node_Impl &node) { - if (node->identifier == AST_Node_Type::Var_Decl) { + if (node.identifier == AST_Node_Type::Var_Decl) { return true; } @@ -96,8 +105,8 @@ namespace chaiscript { for (size_t i = 0; i < num; ++i) { const auto &child = child_at(node, i); - if (child->identifier != AST_Node_Type::Block - && child->identifier != AST_Node_Type::For + if (child.identifier != AST_Node_Type::Block + && child.identifier != AST_Node_Type::For && contains_var_decl_in_scope(child)) { return true; } @@ -108,15 +117,16 @@ namespace chaiscript { struct Block { template - auto optimize(const eval::AST_Node_Impl_Ptr &node) { + auto optimize(eval::AST_Node_Impl_Ptr node) { if (node->identifier == AST_Node_Type::Block) { - if (!contains_var_decl_in_scope(node)) + if (!contains_var_decl_in_scope(*node)) { if (node->children.size() == 1) { - return node->children[0]; + return std::move(node->children[0]); } else { - return chaiscript::make_shared, eval::Scopeless_Block_AST_Node>(node->text, node->location, node->children); + return chaiscript::make_unique, eval::Scopeless_Block_AST_Node>(node->text, node->location, + std::move(node->children)); } } } @@ -127,7 +137,7 @@ namespace chaiscript { struct Dead_Code { template - auto optimize(const eval::AST_Node_Impl_Ptr &node) { + auto optimize(eval::AST_Node_Impl_Ptr node) { if (node->identifier == AST_Node_Type::Block) { std::vector keepers; @@ -135,10 +145,10 @@ namespace chaiscript { keepers.reserve(num_children); for (size_t i = 0; i < num_children; ++i) { - auto child = node->children[i]; - if ( (child->identifier != AST_Node_Type::Id - && child->identifier != AST_Node_Type::Constant - && child->identifier != AST_Node_Type::Noop) + const auto &child = *node->children[i]; + if ( (child.identifier != AST_Node_Type::Id + && child.identifier != AST_Node_Type::Constant + && child.identifier != AST_Node_Type::Noop) || i == num_children - 1) { keepers.push_back(i); } @@ -147,12 +157,16 @@ namespace chaiscript { if (keepers.size() == num_children) { return node; } else { - std::vector> new_children; - for (const auto x : keepers) - { - new_children.push_back(node->children[x]); - } - return chaiscript::make_shared, eval::Block_AST_Node>(node->text, node->location, new_children); + const auto new_children = [&](){ + std::vector> retval; + for (const auto x : keepers) + { + retval.push_back(std::move(node->children[x])); + } + return retval; + }; + + return chaiscript::make_unique, eval::Block_AST_Node>(node->text, node->location, new_children()); } } else { return node; @@ -162,29 +176,30 @@ namespace chaiscript { struct Unused_Return { template - auto optimize(const eval::AST_Node_Impl_Ptr &node) { + auto optimize(eval::AST_Node_Impl_Ptr node) { if ((node->identifier == AST_Node_Type::Block || node->identifier == AST_Node_Type::Scopeless_Block) && !node->children.empty()) { for (size_t i = 0; i < node->children.size()-1; ++i) { - auto child = node->children[i]; + auto child = node->children[i].get(); if (child->identifier == AST_Node_Type::Fun_Call) { - node->children[i] = chaiscript::make_shared, eval::Unused_Return_Fun_Call_AST_Node>(child->text, child->location, std::move(child->children)); + node->children[i] = chaiscript::make_unique, eval::Unused_Return_Fun_Call_AST_Node>(child->text, child->location, + std::move(child->children)); } } } else if ((node->identifier == AST_Node_Type::For || node->identifier == AST_Node_Type::While) - && child_count(node) > 0) { - auto child = child_at(node, child_count(node) - 1); - if (child->identifier == AST_Node_Type::Block - || child->identifier == AST_Node_Type::Scopeless_Block) + && child_count(*node) > 0) { + auto &child = child_at(*node, child_count(*node) - 1); + if (child.identifier == AST_Node_Type::Block + || child.identifier == AST_Node_Type::Scopeless_Block) { auto num_sub_children = child_count(child); for (size_t i = 0; i < num_sub_children; ++i) { - auto sub_child = child_at(child, i); - if (sub_child->identifier == AST_Node_Type::Fun_Call) { - child->children[i] = chaiscript::make_shared, eval::Unused_Return_Fun_Call_AST_Node>(sub_child->text, sub_child->location, std::move(sub_child->children)); + auto &sub_child = child_at(child, i); + if (sub_child.identifier == AST_Node_Type::Fun_Call) { + child.children[i] = chaiscript::make_unique, eval::Unused_Return_Fun_Call_AST_Node>(sub_child.text, sub_child.location, std::move(sub_child.children)); } } } @@ -195,17 +210,17 @@ namespace chaiscript { struct If { template - auto optimize(const eval::AST_Node_Impl_Ptr &node) { + auto optimize(eval::AST_Node_Impl_Ptr node) { if ((node->identifier == AST_Node_Type::If) && node->children.size() >= 2 && node->children[0]->identifier == AST_Node_Type::Constant) { - const auto condition = std::dynamic_pointer_cast>(node->children[0])->m_value; + const auto condition = dynamic_cast *>(node->children[0].get())->m_value; if (condition.get_type_info().bare_equal_type_info(typeid(bool))) { if (boxed_cast(condition)) { - return node->children[1]; + return std::move(node->children[1]); } else if (node->children.size() == 3) { - return node->children[2]; + return std::move(node->children[2]); } } } @@ -216,7 +231,7 @@ namespace chaiscript { struct Partial_Fold { template - auto optimize(const eval::AST_Node_Impl_Ptr &node) { + auto optimize(eval::AST_Node_Impl_Ptr node) { // Fold right side if (node->identifier == AST_Node_Type::Binary @@ -228,9 +243,10 @@ namespace chaiscript { const auto &oper = node->text; const auto parsed = Operators::to_operator(oper); if (parsed != Operators::Opers::invalid) { - const auto rhs = std::dynamic_pointer_cast>(node->children[1])->m_value; + const auto rhs = dynamic_cast *>(node->children[1].get())->m_value; if (rhs.get_type_info().is_arithmetic()) { - return chaiscript::make_shared, eval::Fold_Right_Binary_Operator_AST_Node>(node->text, node->location, node->children, rhs); + return chaiscript::make_unique, eval::Fold_Right_Binary_Operator_AST_Node>(node->text, node->location, + std::move(node->children), rhs); } } } catch (const std::exception &) { @@ -244,7 +260,7 @@ namespace chaiscript { struct Constant_Fold { template - auto optimize(const eval::AST_Node_Impl_Ptr &node) { + auto optimize(eval::AST_Node_Impl_Ptr node) { if (node->identifier == AST_Node_Type::Prefix && node->children.size() == 1 @@ -253,14 +269,14 @@ namespace chaiscript { try { const auto &oper = node->text; const auto parsed = Operators::to_operator(oper, true); - const auto lhs = std::dynamic_pointer_cast>(node->children[0])->m_value; + const auto lhs = dynamic_cast *>(node->children[0].get())->m_value; const auto match = oper + node->children[0]->text; if (parsed != Operators::Opers::invalid && parsed != Operators::Opers::bitwise_and && lhs.get_type_info().is_arithmetic()) { const auto val = Boxed_Number::do_oper(parsed, lhs); - return chaiscript::make_shared, eval::Constant_AST_Node>(std::move(match), node->location, std::move(val)); + return chaiscript::make_unique, eval::Constant_AST_Node>(std::move(match), node->location, std::move(val)); } else if (lhs.get_type_info().bare_equal_type_info(typeid(bool)) && oper == "!") { - return chaiscript::make_shared, eval::Constant_AST_Node>(std::move(match), node->location, Boxed_Value(!boxed_cast(lhs))); + return chaiscript::make_unique, eval::Constant_AST_Node>(std::move(match), node->location, Boxed_Value(!boxed_cast(lhs))); } } catch (const std::exception &) { //failure to fold, that's OK @@ -271,8 +287,8 @@ namespace chaiscript { && node->children[1]->identifier == AST_Node_Type::Constant) { try { - const auto lhs = std::dynamic_pointer_cast>(node->children[0])->m_value; - const auto rhs = std::dynamic_pointer_cast>(node->children[1])->m_value; + const auto lhs = dynamic_cast &>(*node->children[0]).m_value; + const auto rhs = dynamic_cast &>(*node->children[1]).m_value; if (lhs.get_type_info().bare_equal_type_info(typeid(bool)) && rhs.get_type_info().bare_equal_type_info(typeid(bool))) { const auto match = node->children[0]->text + " " + node->text + " " + node->children[1]->text; const auto val = [lhs_val = boxed_cast(lhs), rhs_val = boxed_cast(rhs), id = node->identifier] { @@ -280,7 +296,7 @@ namespace chaiscript { else { return Boxed_Value(lhs_val || rhs_val); } }(); - return chaiscript::make_shared, eval::Constant_AST_Node>(std::move(match), node->location, std::move(val)); + return chaiscript::make_unique, eval::Constant_AST_Node>(std::move(match), node->location, std::move(val)); } } catch (const std::exception &) { //failure to fold, that's OK @@ -294,12 +310,12 @@ namespace chaiscript { const auto &oper = node->text; const auto parsed = Operators::to_operator(oper); if (parsed != Operators::Opers::invalid) { - const auto lhs = std::dynamic_pointer_cast>(node->children[0])->m_value; - const auto rhs = std::dynamic_pointer_cast>(node->children[1])->m_value; + const auto lhs = dynamic_cast &>(*node->children[0]).m_value; + const auto rhs = dynamic_cast &>(*node->children[1]).m_value; if (lhs.get_type_info().is_arithmetic() && rhs.get_type_info().is_arithmetic()) { const auto val = Boxed_Number::do_oper(parsed, lhs, rhs); const auto match = node->children[0]->text + " " + oper + " " + node->children[1]->text; - return chaiscript::make_shared, eval::Constant_AST_Node>(std::move(match), node->location, std::move(val)); + return chaiscript::make_unique, eval::Constant_AST_Node>(std::move(match), node->location, std::move(val)); } } } catch (const std::exception &) { @@ -312,13 +328,13 @@ namespace chaiscript { && node->children[1]->children.size() == 1 && node->children[1]->children[0]->identifier == AST_Node_Type::Constant) { - const auto arg = std::dynamic_pointer_cast>(node->children[1]->children[0])->m_value; + const auto arg = dynamic_cast &>(*node->children[1]->children[0]).m_value; if (arg.get_type_info().is_arithmetic()) { const auto &fun_name = node->children[0]->text; const auto make_constant = [&node, &fun_name](auto val){ const auto match = fun_name + "(" + node->children[1]->children[0]->text + ")"; - return chaiscript::make_shared, eval::Constant_AST_Node>(std::move(match), node->location, Boxed_Value(val)); + return chaiscript::make_unique, eval::Constant_AST_Node>(std::move(match), node->location, Boxed_Value(val)); }; if (fun_name == "double") { @@ -344,35 +360,36 @@ namespace chaiscript { struct For_Loop { template - auto optimize(const eval::AST_Node_Impl_Ptr &for_node) { + auto optimize(eval::AST_Node_Impl_Ptr for_node) { if (for_node->identifier != AST_Node_Type::For) { return for_node; } - const auto eq_node = child_at(for_node, 0); - const auto binary_node = child_at(for_node, 1); - const auto prefix_node = child_at(for_node, 2); + const auto &eq_node = child_at(*for_node, 0); + const auto &binary_node = child_at(*for_node, 1); + const auto &prefix_node = child_at(*for_node, 2); - if (eq_node->identifier == AST_Node_Type::Equation + if (child_count(*for_node) == 4 + && eq_node.identifier == AST_Node_Type::Equation && child_count(eq_node) == 2 - && child_at(eq_node, 0)->identifier == AST_Node_Type::Var_Decl - && child_at(eq_node, 1)->identifier == AST_Node_Type::Constant - && binary_node->identifier == AST_Node_Type::Binary - && binary_node->text == "<" + && child_at(eq_node, 0).identifier == AST_Node_Type::Var_Decl + && child_at(eq_node, 1).identifier == AST_Node_Type::Constant + && binary_node.identifier == AST_Node_Type::Binary + && binary_node.text == "<" && child_count(binary_node) == 2 - && child_at(binary_node, 0)->identifier == AST_Node_Type::Id - && child_at(binary_node, 0)->text == child_at(child_at(eq_node,0), 0)->text - && child_at(binary_node, 1)->identifier == AST_Node_Type::Constant - && prefix_node->identifier == AST_Node_Type::Prefix - && prefix_node->text == "++" + && child_at(binary_node, 0).identifier == AST_Node_Type::Id + && child_at(binary_node, 0).text == child_at(child_at(eq_node,0), 0).text + && child_at(binary_node, 1).identifier == AST_Node_Type::Constant + && prefix_node.identifier == AST_Node_Type::Prefix + && prefix_node.text == "++" && child_count(prefix_node) == 1 - && child_at(prefix_node, 0)->identifier == AST_Node_Type::Id - && child_at(prefix_node, 0)->text == child_at(child_at(eq_node,0), 0)->text) + && child_at(prefix_node, 0).identifier == AST_Node_Type::Id + && child_at(prefix_node, 0).text == child_at(child_at(eq_node,0), 0).text) { - const Boxed_Value &begin = std::dynamic_pointer_cast>(child_at(eq_node, 1))->m_value; - const Boxed_Value &end = std::dynamic_pointer_cast>(child_at(binary_node, 1))->m_value; - const std::string &id = child_at(prefix_node, 0)->text; + const Boxed_Value &begin = dynamic_cast &>(child_at(eq_node, 1)).m_value; + const Boxed_Value &end = dynamic_cast &>(child_at(binary_node, 1)).m_value; + const std::string &id = child_at(prefix_node, 0).text; if (begin.get_type_info().bare_equal(user_type()) && end.get_type_info().bare_equal(user_type())) { @@ -380,9 +397,14 @@ namespace chaiscript { const auto start_int = boxed_cast(begin); const auto end_int = boxed_cast(end); - const auto body = child_at(for_node, 3); - - return make_compiled_node(for_node, {body}, + // note that we are moving the last element out, then popping the empty shared_ptr + // from the vector + std::vector> body_vector; + auto body_child = std::move(for_node->children[3]); + for_node->children.pop_back(); + body_vector.emplace_back(std::move(body_child)); + + return make_compiled_node(std::move(for_node), std::move(body_vector), [id, start_int, end_int](const std::vector> &children, const chaiscript::detail::Dispatch_State &t_ss) { assert(children.size() == 1); chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 93e69343..73575ef5 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -397,7 +397,7 @@ namespace chaiscript return m_optimizer; } - ChaiScript_Parser(const ChaiScript_Parser &) = default; + ChaiScript_Parser(const ChaiScript_Parser &) = delete; ChaiScript_Parser &operator=(const ChaiScript_Parser &) = delete; ChaiScript_Parser(ChaiScript_Parser &&) = default; ChaiScript_Parser &operator=(ChaiScript_Parser &&) = delete; @@ -406,10 +406,10 @@ namespace chaiscript bool char_in_alphabet(char c, detail::Alphabet a) const { return m_alphabet[a][static_cast(c)]; } /// Prints the parsed ast_nodes as a tree - void debug_print(AST_NodePtr t, std::string prepend = "") const override { - std::cout << prepend << "(" << ast_node_type_to_string(t->identifier) << ") " << t->text << " : " << t->start().line << ", " << t->start().column << '\n'; - for (const auto &node : t->get_children()) { - debug_print(node, prepend + " "); + void debug_print(const AST_Node &t, std::string prepend = "") const override { + std::cout << prepend << "(" << ast_node_type_to_string(t.identifier) << ") " << t.text << " : " << t.start().line << ", " << t.start().column << '\n'; + for (const auto &node : t.get_children()) { + debug_print(node.get(), prepend + " "); } } @@ -452,7 +452,7 @@ namespace chaiscript /// \todo fix the fact that a successful match that captured no ast_nodes doesn't have any real start position m_match_stack.push_back( m_optimizer.optimize( - chaiscript::make_shared, NodeType>( + chaiscript::make_unique, NodeType>( std::move(t_text), std::move(filepos), std::move(new_children))) @@ -779,9 +779,9 @@ namespace chaiscript } template - std::shared_ptr> make_node(std::string t_match, const int t_prev_line, const int t_prev_col, Param && ...param) + std::unique_ptr> make_node(std::string t_match, const int t_prev_line, const int t_prev_col, Param && ...param) { - return chaiscript::make_shared, T>(std::move(t_match), Parse_Location(m_filename, t_prev_line, t_prev_col, m_position.line, m_position.col), std::forward(param)...); + return chaiscript::make_unique, T>(std::move(t_match), Parse_Location(m_filename, t_prev_line, t_prev_col, m_position.line, m_position.col), std::forward(param)...); } /// Reads a number from the input, detecting if it's an integer or floating point @@ -1759,7 +1759,7 @@ namespace chaiscript if ((is_if_init && num_children == 3) || (!is_if_init && num_children == 2)) { - m_match_stack.push_back(chaiscript::make_shared, eval::Noop_AST_Node>()); + m_match_stack.push_back(chaiscript::make_unique, eval::Noop_AST_Node>()); } if (!is_if_init) { @@ -1849,7 +1849,7 @@ namespace chaiscript { return false; } else { - m_match_stack.push_back(chaiscript::make_shared, eval::Noop_AST_Node>()); + m_match_stack.push_back(chaiscript::make_unique, eval::Noop_AST_Node>()); } } @@ -1859,13 +1859,13 @@ namespace chaiscript { return false; } else { - m_match_stack.push_back(chaiscript::make_shared, eval::Constant_AST_Node>(Boxed_Value(true))); + m_match_stack.push_back(chaiscript::make_unique, eval::Constant_AST_Node>(Boxed_Value(true))); } } if (!Equation()) { - m_match_stack.push_back(chaiscript::make_shared, eval::Noop_AST_Node>()); + m_match_stack.push_back(chaiscript::make_unique, eval::Noop_AST_Node>()); } return true; @@ -2005,7 +2005,7 @@ namespace chaiscript } if (m_match_stack.size() == prev_stack_top) { - m_match_stack.push_back(chaiscript::make_shared, eval::Noop_AST_Node>()); + m_match_stack.push_back(chaiscript::make_unique, eval::Noop_AST_Node>()); } build_match>(prev_stack_top); @@ -2029,7 +2029,7 @@ namespace chaiscript } if (m_match_stack.size() == prev_stack_top) { - m_match_stack.push_back(chaiscript::make_shared, eval::Noop_AST_Node>()); + m_match_stack.push_back(chaiscript::make_unique, eval::Noop_AST_Node>()); } build_match>(prev_stack_top); @@ -2105,13 +2105,13 @@ namespace chaiscript } if (m_match_stack.back()->children.empty()) { throw exception::eval_error("Incomplete dot access fun call", File_Position(m_position.line, m_position.col), *m_filename); } - auto dot_access = m_match_stack.back()->children[0]; - auto func_call = m_match_stack.back(); + auto dot_access = std::move(m_match_stack.back()->children[0]); + auto func_call = std::move(m_match_stack.back()); m_match_stack.pop_back(); func_call->children.erase(func_call->children.begin()); if (dot_access->children.empty()) { throw exception::eval_error("Incomplete dot access fun call", File_Position(m_position.line, m_position.col), *m_filename); } - func_call->children.insert(func_call->children.begin(), dot_access->children.back()); + func_call->children.insert(func_call->children.begin(), std::move(dot_access->children.back())); dot_access->children.pop_back(); dot_access->children.push_back(std::move(func_call)); if (dot_access->children.size() != 2) { throw exception::eval_error("Incomplete dot access fun call", File_Position(m_position.line, m_position.col), *m_filename); @@ -2517,24 +2517,23 @@ namespace chaiscript AST_NodePtr parse(const std::string &t_input, const std::string &t_fname) override { - ChaiScript_Parser parser(*this); - parser.m_match_stack.clear(); + ChaiScript_Parser parser(m_tracer, m_optimizer); return parser.parse_internal(t_input, t_fname); } eval::AST_Node_Impl_Ptr parse_instr_eval(const std::string &t_input) { - const auto last_position = m_position; - const auto last_filename = m_filename; - const auto last_match_stack = std::exchange(m_match_stack, decltype(m_match_stack){}); + auto last_position = m_position; + auto last_filename = m_filename; + auto last_match_stack = std::exchange(m_match_stack, decltype(m_match_stack){}); - const auto retval = parse_internal(t_input, "instr eval"); + auto retval = parse_internal(t_input, "instr eval"); m_position = std::move(last_position); m_filename = std::move(last_filename); m_match_stack = std::move(last_match_stack); - return std::dynamic_pointer_cast>(retval); + return eval::AST_Node_Impl_Ptr(dynamic_cast*>(retval.release())); } /// Parses the given input string, tagging parsed ast_nodes with the given m_filename. @@ -2546,7 +2545,6 @@ namespace chaiscript while (m_position.has_more() && (!Eol())) { ++m_position; } - /// \todo respect // -*- coding: utf-8 -*- on line 1 or 2 see: http://evanjones.ca/python-utf8.html) } if (Statements(true)) { @@ -2556,10 +2554,12 @@ namespace chaiscript build_match>(0); } } else { - m_match_stack.push_back(chaiscript::make_shared, eval::Noop_AST_Node>()); + m_match_stack.push_back(chaiscript::make_unique, eval::Noop_AST_Node>()); } - return m_match_stack.front(); + AST_NodePtr retval(std::move(m_match_stack.front())); + m_match_stack.clear(); + return retval; } }; } diff --git a/src/main.cpp b/src/main.cpp index 78044e06..e826def0 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -247,7 +247,7 @@ void interactive(chaiscript::ChaiScript_Basic& chai) catch (const chaiscript::exception::eval_error &ee) { std::cout << ee.what(); if ( !ee.call_stack.empty() ) { - std::cout << "during evaluation at (" << ee.call_stack[0]->start().line << ", " << ee.call_stack[0]->start().column << ")"; + std::cout << "during evaluation at (" << ee.call_stack[0].start().line << ", " << ee.call_stack[0].start().column << ")"; } std::cout << '\n'; } From 77315ae4b9cc71a7d1d9512cfdf641491b5cdd81 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Thu, 22 Jun 2017 09:32:49 -0600 Subject: [PATCH 75/84] Fix non-shared_ptr tree code --- include/chaiscript/language/chaiscript_eval.hpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 4388649d..3b9c7837 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -718,7 +718,7 @@ namespace chaiscript Def_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Def, std::move(t_loc), std::vector>(std::make_move_iterator(t_children.begin()), - std::make_move_iterator(std::prev(t_children.end(), has_guard(t_children)?2:1))) + std::make_move_iterator(std::prev(t_children.end(), has_guard(t_children, 1)?2:1))) ), 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)) @@ -739,15 +739,15 @@ namespace chaiscript return std::move(vec.back()); } - static bool has_guard(const std::vector> &t_children) + static bool has_guard(const std::vector> &t_children, const std::size_t offset) { - if ((t_children.size() > 2) && (t_children[1]->identifier == AST_Node_Type::Arg_List)) { - if (t_children.size() > 3) { + if ((t_children.size() > 2 + offset) && (t_children[1+offset]->identifier == AST_Node_Type::Arg_List)) { + if (t_children.size() > 3 + offset) { return true; } } else { - if (t_children.size() > 2) { + if (t_children.size() > 2 + offset) { return true; } } @@ -1379,7 +1379,7 @@ namespace chaiscript Method_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Method, std::move(t_loc), std::vector>(std::make_move_iterator(t_children.begin()), - std::make_move_iterator(std::prev(t_children.end(), Def_AST_Node::has_guard(t_children)?2:1))) + std::make_move_iterator(std::prev(t_children.end(), Def_AST_Node::has_guard(t_children, 1)?2:1))) ), m_body_node(Def_AST_Node::get_body_node(std::move(t_children))), m_guard_node(Def_AST_Node::get_guard_node(std::move(t_children), t_children.size()-this->children.size()==2)) From ea03a5462f0a9edfc07c536d540ba9c1e66307e9 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 18 Jul 2017 16:58:09 -0600 Subject: [PATCH 76/84] Wrap up build issues for dropping of shared_ptr --- include/chaiscript/language/chaiscript_engine.hpp | 6 +++--- samples/fun_call_performance.cpp | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index dc0b8536..0e07f4ce 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -186,7 +186,7 @@ namespace chaiscript } m_engine.add(fun([this](const std::string &t_str){ return internal_eval(t_str); }), "eval"); - m_engine.add(fun([this](const AST_NodePtr &t_ast){ return eval(t_ast); }), "eval"); + m_engine.add(fun([this](const AST_Node &t_ast){ return eval(t_ast); }), "eval"); m_engine.add(fun([this](const std::string &t_str, const bool t_dump){ return parse(t_str, t_dump); }), "parse"); m_engine.add(fun([this](const std::string &t_str){ return parse(t_str); }), "parse"); @@ -321,10 +321,10 @@ explicit ChaiScript_Basic(std::unique_ptr &&pars return *m_parser; } - const Boxed_Value eval(const AST_NodePtr &t_ast) + const Boxed_Value eval(const AST_Node &t_ast) { try { - return t_ast->eval(chaiscript::detail::Dispatch_State(m_engine)); + return t_ast.eval(chaiscript::detail::Dispatch_State(m_engine)); } catch (const exception::eval_error &t_ee) { throw Boxed_Value(t_ee); } diff --git a/samples/fun_call_performance.cpp b/samples/fun_call_performance.cpp index b8bda5ae..31fa606c 100644 --- a/samples/fun_call_performance.cpp +++ b/samples/fun_call_performance.cpp @@ -252,7 +252,7 @@ void interactive(chaiscript::ChaiScript& chai) catch (const chaiscript::exception::eval_error &ee) { std::cout << ee.what(); if (ee.call_stack.size() > 0) { - std::cout << "during evaluation at (" << ee.call_stack[0]->start().line << ", " << ee.call_stack[0]->start().column << ")"; + std::cout << "during evaluation at (" << ee.call_stack[0].start().line << ", " << ee.call_stack[0].start().column << ")"; } std::cout << std::endl; } From cfb2e663d36d84130aacd1abd6807e73452c3f6a Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 19 Jul 2017 10:09:44 -0600 Subject: [PATCH 77/84] Fix unhandled exception found via libfuzzer --- .../chaiscript/language/chaiscript_parser.hpp | 42 ++++++++++++------- 1 file changed, 27 insertions(+), 15 deletions(-) diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 73575ef5..d6cf7402 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -1051,23 +1051,30 @@ namespace chaiscript Char_Parser &operator=(const Char_Parser &) = delete; ~Char_Parser(){ - if (is_octal) { - process_octal(); - } + try { + if (is_octal) { + process_octal(); + } - if (is_hex) { - process_hex(); - } + if (is_hex) { + process_hex(); + } - if (is_unicode) { - process_unicode(); + if (is_unicode) { + process_unicode(); + } + } catch (const std::invalid_argument &) { + // escape sequence was invalid somehow, we'll pick this + // up in the next part of parsing } } void process_hex() { - auto val = stoll(hex_matches, nullptr, 16); - match.push_back(char_type(val)); + if (!hex_matches.empty()) { + auto val = stoll(hex_matches, nullptr, 16); + match.push_back(char_type(val)); + } hex_matches.clear(); is_escaped = false; is_hex = false; @@ -1076,8 +1083,10 @@ namespace chaiscript void process_octal() { - auto val = stoll(octal_matches, nullptr, 8); - match.push_back(char_type(val)); + if (!octal_matches.empty()) { + auto val = stoll(octal_matches, nullptr, 8); + match.push_back(char_type(val)); + } octal_matches.clear(); is_escaped = false; is_octal = false; @@ -1086,9 +1095,11 @@ namespace chaiscript void process_unicode() { - auto val = stoll(hex_matches, nullptr, 16); - hex_matches.clear(); - match += detail::Char_Parser_Helper::str_from_ll(val); + if (!hex_matches.empty()) { + auto val = stoll(hex_matches, nullptr, 16); + hex_matches.clear(); + match += detail::Char_Parser_Helper::str_from_ll(val); + } is_escaped = false; is_unicode = false; } @@ -1254,6 +1265,7 @@ namespace chaiscript cparser.saw_interpolation_marker = false; } else { cparser.parse(*s, start.line, start.col, *m_filename); + ++s; } } From d8da295e40aeb171b4bf1c612c1186f2d4b392fc Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 19 Jul 2017 10:47:17 -0600 Subject: [PATCH 78/84] Check string accesses during JSON parsing --- include/chaiscript/utility/json.hpp | 38 ++++++++++++------------ include/chaiscript/utility/json_wrap.hpp | 6 +++- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/include/chaiscript/utility/json.hpp b/include/chaiscript/utility/json.hpp index 676b4699..693f19da 100644 --- a/include/chaiscript/utility/json.hpp +++ b/include/chaiscript/utility/json.hpp @@ -463,7 +463,7 @@ struct JSONParser { } static void consume_ws( const std::string &str, size_t &offset ) { - while( isspace( str[offset] ) && offset <= str.size() ) { ++offset; } + while( isspace( str.at(offset) ) && offset <= str.size() ) { ++offset; } } static JSON parse_object( const std::string &str, size_t &offset ) { @@ -471,29 +471,29 @@ struct JSONParser { ++offset; consume_ws( str, offset ); - if( str[offset] == '}' ) { + if( str.at(offset) == '}' ) { ++offset; return Object; } for (;offset= '0' && c <= '9') || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F') ) { val += c; } else { @@ -569,12 +569,12 @@ struct JSONParser { bool isDouble = false; bool isNegative = false; long exp = 0; - if( offset < str.size() && str[offset] == '-' ) { + if( offset < str.size() && str.at(offset) == '-' ) { isNegative = true; ++offset; } for (; offset < str.size() ;) { - c = str[offset++]; + c = str.at(offset++); if( c >= '0' && c <= '9' ) { val += c; } else if( c == '.' && !isDouble ) { @@ -585,7 +585,7 @@ struct JSONParser { } } if( offset < str.size() && (c == 'E' || c == 'e' )) { - c = str[ offset++ ]; + c = str.at(offset++); if( c == '-' ) { exp_str += '-'; } else if( c == '+' ) { @@ -595,7 +595,7 @@ struct JSONParser { } for (; offset < str.size() ;) { - c = str[ offset++ ]; + c = str.at(offset++); if( c >= '0' && c <= '9' ) { exp_str += c; } else if( !isspace( c ) && c != ',' && c != ']' && c != '}' ) { @@ -646,7 +646,7 @@ struct JSONParser { static JSON parse_next( const std::string &str, size_t &offset ) { char value; consume_ws( str, offset ); - value = str[offset]; + value = str.at(offset); switch( value ) { case '[' : return parse_array( str, offset ); case '{' : return parse_object( str, offset ); diff --git a/include/chaiscript/utility/json_wrap.hpp b/include/chaiscript/utility/json_wrap.hpp index c0af1cd8..6a6ccd02 100644 --- a/include/chaiscript/utility/json_wrap.hpp +++ b/include/chaiscript/utility/json_wrap.hpp @@ -63,7 +63,11 @@ namespace chaiscript static Boxed_Value from_json(const std::string &t_json) { - return from_json( json::JSON::Load(t_json) ); + try { + return from_json( json::JSON::Load(t_json) ); + } catch (...) { + throw std::runtime_error("Unparsed JSON input"); + } } static std::string to_json(const Boxed_Value &t_bv) From b42316a27581c5cef8a4b825d78bf7836703ce0f Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 19 Jul 2017 13:19:17 -0600 Subject: [PATCH 79/84] More careful with json errors --- include/chaiscript/utility/json_wrap.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/chaiscript/utility/json_wrap.hpp b/include/chaiscript/utility/json_wrap.hpp index 6a6ccd02..2aa81f34 100644 --- a/include/chaiscript/utility/json_wrap.hpp +++ b/include/chaiscript/utility/json_wrap.hpp @@ -65,7 +65,7 @@ namespace chaiscript { try { return from_json( json::JSON::Load(t_json) ); - } catch (...) { + } catch (const std::out_of_range& ) { throw std::runtime_error("Unparsed JSON input"); } } From f03659c8656301b4b304542e6276a7834d3f6f5b Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 19 Jul 2017 13:19:36 -0600 Subject: [PATCH 80/84] More careful testing of 'for' parses --- include/chaiscript/language/chaiscript_parser.hpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index d6cf7402..06a51dfa 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -1908,9 +1908,17 @@ namespace chaiscript throw exception::eval_error("Incomplete 'for' block", File_Position(m_position.line, m_position.col), *m_filename); } + const auto num_children = m_match_stack.size() - prev_stack_top; + if (classic_for) { + if (num_children != 4) { + throw exception::eval_error("Incomplete 'for' expression", File_Position(m_position.line, m_position.col), *m_filename); + } build_match>(prev_stack_top); } else { + if (num_children != 3) { + throw exception::eval_error("Incomplete ranged-for expression", File_Position(m_position.line, m_position.col), *m_filename); + } build_match>(prev_stack_top); } } From 14eaefdceba3be88265a6992b677292ba8dcbf4c Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 19 Jul 2017 15:52:34 -0600 Subject: [PATCH 81/84] Make `front()` `back()` checked --- .../chaiscript/dispatchkit/bootstrap_stl.hpp | 69 ++++++++++++++++--- 1 file changed, 58 insertions(+), 11 deletions(-) diff --git a/include/chaiscript/dispatchkit/bootstrap_stl.hpp b/include/chaiscript/dispatchkit/bootstrap_stl.hpp index 6710ed00..7f409a3a 100644 --- a/include/chaiscript/dispatchkit/bootstrap_stl.hpp +++ b/include/chaiscript/dispatchkit/bootstrap_stl.hpp @@ -335,9 +335,24 @@ namespace chaiscript template void back_insertion_sequence_type(const std::string &type, Module& m) { - typedef typename ContainerType::reference (ContainerType::*backptr)(); - - m.add(fun(static_cast(&ContainerType::back)), "back"); + m.add(fun([](ContainerType &container)->decltype(auto){ + if (container.empty()) { + throw std::range_error("Container empty"); + } else { + return (container.back()); + } + } + ) + , "back"); + m.add(fun([](const ContainerType &container)->decltype(auto){ + if (container.empty()) { + throw std::range_error("Container empty"); + } else { + return (container.back()); + } + } + ) + , "back"); typedef void (ContainerType::*push_back)(const typename ContainerType::value_type &); @@ -380,13 +395,29 @@ namespace chaiscript template void front_insertion_sequence_type(const std::string &type, Module& m) { - typedef typename ContainerType::reference (ContainerType::*front_ptr)(); - typedef typename ContainerType::const_reference (ContainerType::*const_front_ptr)() const; typedef void (ContainerType::*push_ptr)(typename ContainerType::const_reference); typedef void (ContainerType::*pop_ptr)(); - m.add(fun(static_cast(&ContainerType::front)), "front"); - m.add(fun(static_cast(&ContainerType::front)), "front"); + m.add(fun([](ContainerType &container)->decltype(auto){ + if (container.empty()) { + throw std::range_error("Container empty"); + } else { + return (container.front()); + } + } + ) + , "front"); + + m.add(fun([](const ContainerType &container)->decltype(auto){ + if (container.empty()) { + throw std::range_error("Container empty"); + } else { + return (container.front()); + } + } + ) + , "front"); + m.add(fun(static_cast(&ContainerType::push_front)), [&]()->std::string{ @@ -577,11 +608,27 @@ namespace chaiscript { m.add(user_type(), type); - typedef typename VectorType::reference (VectorType::*frontptr)(); - typedef typename VectorType::const_reference (VectorType::*constfrontptr)() const; + m.add(fun([](VectorType &container)->decltype(auto){ + if (container.empty()) { + throw std::range_error("Container empty"); + } else { + return (container.front()); + } + } + ) + , "front"); + + m.add(fun([](const VectorType &container)->decltype(auto){ + if (container.empty()) { + throw std::range_error("Container empty"); + } else { + return (container.front()); + } + } + ) + , "front"); + - m.add(fun(static_cast(&VectorType::front)), "front"); - m.add(fun(static_cast(&VectorType::front)), "front"); back_insertion_sequence_type(type, m); From f465d2cecaab97b3e765e0072596ea8e136254fb Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Thu, 20 Jul 2017 06:10:31 -0600 Subject: [PATCH 82/84] Make sure to not deref null parse node --- include/chaiscript/dispatchkit/proxy_functions.hpp | 11 ++++++++++- include/chaiscript/language/chaiscript_common.hpp | 6 ++++-- include/chaiscript/language/chaiscript_eval.hpp | 4 +++- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index 2afda8dd..0c60315f 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -354,6 +354,7 @@ namespace chaiscript m_param_types(std::move(t_param_types)), m_guard(std::move(t_guard)), m_parsenode(std::move(t_parsenode)) { + // assert(t_parsenode); } @@ -379,9 +380,17 @@ namespace chaiscript return m_guard; } + bool has_parse_tree() const { + return static_cast(m_parsenode); + } + const AST_Node &get_parse_tree() const { - return *m_parsenode; + if (m_parsenode) { + return *m_parsenode; + } else { + throw std::runtime_error("Dynamic_Proxy_Function does not have parse_tree"); + } } diff --git a/include/chaiscript/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index 5fe377c4..b157cac2 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -262,6 +262,7 @@ namespace chaiscript bool t_dot_notation, const chaiscript::detail::Dispatch_Engine &t_ss) { + assert(t_func); int arity = t_func->get_arity(); std::vector types = t_func->get_param_types(); @@ -310,14 +311,14 @@ namespace chaiscript std::shared_ptr dynfun = std::dynamic_pointer_cast(t_func); - if (dynfun) + if (dynfun && dynfun->has_parse_tree()) { Proxy_Function f = dynfun->get_guard(); if (f) { auto dynfunguard = std::dynamic_pointer_cast(f); - if (dynfunguard) + if (dynfunguard && dynfunguard->has_parse_tree()) { retval += " : " + format_guard(dynfunguard->get_parse_tree()); } @@ -350,6 +351,7 @@ namespace chaiscript std::stringstream ss; if (t_functions.size() == 1) { + assert(t_functions[0]); ss << " Expected: " << format_types(t_functions[0], t_dot_notation, t_ss) << '\n'; } else { ss << " " << t_functions.size() << " overloads available:\n"; diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 3b9c7837..a9819440 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -288,7 +288,9 @@ namespace chaiscript template struct Fun_Call_AST_Node : AST_Node_Impl { Fun_Call_AST_Node(std::string t_ast_node_text, Parse_Location t_loc, std::vector> t_children) : - AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Fun_Call, std::move(t_loc), std::move(t_children)) { } + AST_Node_Impl(std::move(t_ast_node_text), AST_Node_Type::Fun_Call, std::move(t_loc), std::move(t_children)) { + assert(!this->children.empty()); + } template Boxed_Value do_eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const From 0f74597139d6ec8bb519b460e425c461ec839fc7 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Thu, 20 Jul 2017 15:08:53 -0600 Subject: [PATCH 83/84] Limit when coverage happens to only one build target --- .travis.yml | 2 +- CMakeLists.txt | 25 +- src/libfuzzer_client.cpp | 342 +++++++++++++++++++++++ src/main.cpp | 21 +- unittests/fuzz_unit_test.inc | 53 ++++ unittests/fuzzy_tests-2016-06-29.tar.bz2 | Bin 84871 -> 0 bytes unittests/fuzzy_tests-2017-07-20.tar.bz2 | Bin 0 -> 129965 bytes 7 files changed, 417 insertions(+), 26 deletions(-) create mode 100644 src/libfuzzer_client.cpp create mode 100644 unittests/fuzz_unit_test.inc delete mode 100644 unittests/fuzzy_tests-2016-06-29.tar.bz2 create mode 100644 unittests/fuzzy_tests-2017-07-20.tar.bz2 diff --git a/.travis.yml b/.travis.yml index 7471e1ee..888922b7 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,7 +30,7 @@ matrix: compiler: gcc - os: linux sudo: false - env: GCC_VER="5" CPPCHECK=1 COVERAGE=1 CMAKE_OPTIONS="-D RUN_FUZZY_TESTS:BOOL=TRUE" + env: GCC_VER="5" CPPCHECK=1 CMAKE_OPTIONS="-D RUN_FUZZY_TESTS:BOOL=TRUE" compiler: gcc - os: linux sudo: false diff --git a/CMakeLists.txt b/CMakeLists.txt index 048c2e54..effc7aed 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -314,32 +314,17 @@ if (RUN_FUZZY_TESTS) file(MAKE_DIRECTORY "${CMAKE_BINARY_DIR}/unittests") execute_process( - COMMAND ${CMAKE_COMMAND} -E tar xjf ${CMAKE_CURRENT_SOURCE_DIR}/unittests/fuzzy_tests-2016-06-29.tar.bz2 + COMMAND ${CMAKE_COMMAND} -E tar xjf ${CMAKE_CURRENT_SOURCE_DIR}/unittests/fuzzy_tests-2017-07-20.tar.bz2 WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/unittests ) - file(GLOB FUZZY_CRASH_TESTS RELATIVE ${CMAKE_BINARY_DIR}/unittests/ ${CMAKE_BINARY_DIR}/unittests/fuzzy_tests/crashes/id*) - list(SORT FUZZY_CRASH_TESTS) + file(GLOB FUZZY_TESTS RELATIVE ${CMAKE_BINARY_DIR}/unittests/ ${CMAKE_BINARY_DIR}/unittests/MINIMIZED/*) + list(SORT FUZZY_TESTS) - file(GLOB FUZZY_EXCEPTION_TESTS RELATIVE ${CMAKE_BINARY_DIR}/unittests/ ${CMAKE_BINARY_DIR}/unittests/fuzzy_tests/exceptions/id*) - list(SORT FUZZY_EXCEPTION_TESTS) - - - foreach(filename ${FUZZY_CRASH_TESTS}) + foreach(filename ${FUZZY_TESTS}) message(STATUS "Adding test ${filename}") - add_test(${filename} chai "-e" ${CMAKE_BINARY_DIR}/unittests/fuzzy_tests/crashes/unit_test.inc ${CMAKE_BINARY_DIR}/unittests/${filename}) - endforeach() - - set_property(TEST ${FUZZY_CRASH_TESTS} - PROPERTY ENVIRONMENT - "CHAI_USE_PATH=${CMAKE_BINARY_DIR}/unittests/" - "CHAI_MODULE_PATH=${CMAKE_CURRENT_BINARY_DIR}/" - ) - - foreach(filename ${FUZZY_EXCEPTION_TESTS}) - message(STATUS "Adding test ${filename}") - add_test(${filename} chai "--exception" ${CMAKE_BINARY_DIR}/unittests/fuzzy_tests/exceptions/unit_test.inc ${CMAKE_BINARY_DIR}/unittests/${filename}) + add_test(fuzz.${filename} chai "-e" "--exception" "--any-exception" ${CMAKE_CURRENT_SOURCE_DIR}/unittests/fuzz_unit_test.inc ${CMAKE_BINARY_DIR}/unittests/${filename}) endforeach() set_property(TEST ${FUZZY_EXCEPTION_TESTS} diff --git a/src/libfuzzer_client.cpp b/src/libfuzzer_client.cpp new file mode 100644 index 00000000..1c90d0ba --- /dev/null +++ b/src/libfuzzer_client.cpp @@ -0,0 +1,342 @@ +// This file is distributed under the BSD License. +// See "license.txt" for details. +// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) +// Copyright 2009-2017, Jason Turner (jason@emptycrate.com) +// http://www.chaiscript.com + +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + + +#include +#include +#include + +#ifdef _MSC_VER +#define _CRT_SECURE_NO_WARNINGS +#endif + +#include +#include "../static_libs/chaiscript_parser.hpp" +#include "../static_libs/chaiscript_stdlib.hpp" + + +#ifdef READLINE_AVAILABLE +#include +#include +#else + +char *mystrdup (const char *s) { + size_t len = strlen(s); // Space for length plus nul + char *d = static_cast(malloc (len+1)); + if (d == nullptr) { return nullptr; } // No memory +#ifdef CHAISCRIPT_MSVC + strcpy_s(d, len+1, s); // Copy the characters +#else + strncpy(d,s,len); // Copy the characters +#endif + d[len] = '\0'; + return d; // Return the new string +} + +char* readline(const char* p) +{ + std::string retval; + std::cout << p ; + std::getline(std::cin, retval); + return std::cin.eof() ? nullptr : mystrdup(retval.c_str()); +} + + +void add_history(const char* /*unused*/){} +void using_history(){} +#endif + + + +void *cast_module_symbol(std::vector (*t_path)()) +{ + union cast_union + { + std::vector (*in_ptr)(); + void *out_ptr; + }; + + cast_union c; + c.in_ptr = t_path; + return c.out_ptr; +} + +std::vector default_search_paths() +{ + std::vector paths; + +#ifndef CHAISCRIPT_NO_DYNLOAD +#ifdef CHAISCRIPT_WINDOWS // force no unicode + CHAR path[4096]; + int size = GetModuleFileNameA(nullptr, path, sizeof(path)-1); + + std::string exepath(path, size); + + size_t lastslash = exepath.rfind('\\'); + size_t secondtolastslash = exepath.rfind('\\', lastslash - 1); + if (lastslash != std::string::npos) + { + paths.push_back(exepath.substr(0, lastslash)); + } + + if (secondtolastslash != std::string::npos) + { + return {exepath.substr(0, secondtolastslash) + "\\lib\\chaiscript\\"}; + } +#else + + std::string exepath; + + std::vector buf(2048); + ssize_t size = -1; + + if ((size = readlink("/proc/self/exe", &buf.front(), buf.size())) >= 0) + { + exepath = std::string(&buf.front(), static_cast(size)); + } + + if (exepath.empty()) + { + if ((size = readlink("/proc/curproc/file", &buf.front(), buf.size())) >= 0) + { + exepath = std::string(&buf.front(), static_cast(size)); + } + } + + if (exepath.empty()) + { + if ((size = readlink("/proc/self/path/a.out", &buf.front(), buf.size())) >= 0) + { + exepath = std::string(&buf.front(), static_cast(size)); + } + } + + if (exepath.empty()) + { + Dl_info rInfo; + memset( &rInfo, 0, sizeof(rInfo) ); + if ( dladdr(cast_module_symbol(&default_search_paths), &rInfo) == 0 || rInfo.dli_fname == nullptr ) { + return paths; + } + + exepath = std::string(rInfo.dli_fname); + } + + size_t lastslash = exepath.rfind('/'); + + size_t secondtolastslash = exepath.rfind('/', lastslash - 1); + if (lastslash != std::string::npos) + { + paths.push_back(exepath.substr(0, lastslash+1)); + } + + if (secondtolastslash != std::string::npos) + { + paths.push_back(exepath.substr(0, secondtolastslash) + "/lib/chaiscript/"); + } +#endif +#endif // ifndef CHAISCRIPT_NO_DYNLOAD + + return paths; +} + +void help(int n) { + if ( n >= 0 ) { + std::cout << "ChaiScript evaluator. To evaluate an expression, type it and press .\n"; + std::cout << "Additionally, you can inspect the runtime system using:\n"; + std::cout << " dump_system() - outputs all functions registered to the system\n"; + std::cout << " dump_object(x) - dumps information about the given symbol\n"; + } else { + std::cout << "usage : chai [option]+\n"; + std::cout << "option:" << '\n'; + std::cout << " -h | --help" << '\n'; + std::cout << " -i | --interactive" << '\n'; + std::cout << " -c | --command cmd" << '\n'; + std::cout << " -v | --version" << '\n'; + std::cout << " - --stdin" << '\n'; + std::cout << " filepath" << '\n'; + } +} + +bool throws_exception(const std::function &f) +{ + try { + f(); + } catch (...) { + return true; + } + + return false; +} + +chaiscript::exception::eval_error get_eval_error(const std::function &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 retval("quit"); + if ( ! std::cin.eof() ) { + char *input_raw = readline("eval> "); + if ( input_raw != nullptr ) { + add_history(input_raw); + + std::string val(input_raw); + size_t pos = val.find_first_not_of("\t \n"); + if (pos != std::string::npos) + { + val.erase(0, pos); + } + pos = val.find_last_not_of("\t \n"); + if (pos != std::string::npos) + { + val.erase(pos+1, std::string::npos); + } + + retval = val; + + ::free(input_raw); + } + } + if( retval == "quit" + || retval == "exit" + || retval == "help" + || retval == "version") + { + retval += "(0)"; + } + return retval; +} + +// We have to wrap exit with our own because Clang has a hard time with +// function pointers to functions with special attributes (system exit being marked NORETURN) +void myexit(int return_val) { + exit(return_val); +} + +void interactive(chaiscript::ChaiScript_Basic& chai) +{ + using_history(); + + for (;;) { + std::string input = get_next_command(); + try { + // evaluate input + chaiscript::Boxed_Value val = chai.eval(input); + + //Then, we try to print the result of the evaluation to the user + if (!val.get_type_info().bare_equal(chaiscript::user_type())) { + try { + std::cout << chai.eval >("to_string")(val) << '\n'; + } + catch (...) {} //If we can't, do nothing + } + } + catch (const chaiscript::exception::eval_error &ee) { + std::cout << ee.what(); + if ( !ee.call_stack.empty() ) { + std::cout << "during evaluation at (" << ee.call_stack[0].start().line << ", " << ee.call_stack[0].start().column << ")"; + } + std::cout << '\n'; + } + catch (const std::exception &e) { + std::cout << e.what(); + std::cout << '\n'; + } + } +} + +double now() +{ + using namespace std::chrono; + auto now = high_resolution_clock::now(); + return duration_cast>(now.time_since_epoch()).count(); +} + +extern "C" int LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) { + chaiscript::ChaiScript chai; + + chai.eval( R"chaiscript( +def assert_equal(x, y) +{ + if (x == y) + { + // Passes + } else { + // Fails + print("assert_equal failure: got '" + to_string(y) + "' expected '" + to_string(x) + "'"); +// exit(-1); + } +} + +def assert_false(f) +{ + if (f) + { + print("assert_false failure"); +// exit(-1); + } +} + +def assert_true(f) +{ + if (!f) + { + print("assert_true failure"); +// exit(-1); + } +} + +def assert_not_equal(x, y) +{ + if (!(x == y)) + { + // Passes + } else { + // Fails + print("assert_not_equal failure: got " + to_string(y) + " which was not expected."); +// exit(-1); + } +} + +def assert_throws(desc, x) +{ + if (throws_exception(x)) + { + // Passes + } else { + // Fails + print("assert_throws failure, function did not throw exception: " + to_string(desc)); +// exit(-1); + } +})chaiscript"); + + try { + chai.eval(std::string(reinterpret_cast(data), size)); + } catch (const chaiscript::exception::eval_error &ee) { + std::cout << ee.pretty_print(); + std::cout << '\n'; + } catch (const chaiscript::Boxed_Value &e) { + std::cout << "Unhandled exception thrown of type " << e.get_type_info().name() << '\n'; + } catch (const chaiscript::exception::load_module_error &e) { + std::cout << "Unhandled module load error\n" << e.what() << '\n'; + } catch (const std::exception &e) { + std::cout << "unhandled unknown exception: " << e.what() << '\n'; + } + + return 0; +} + + diff --git a/src/main.cpp b/src/main.cpp index e826def0..f3bd2d82 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -308,6 +308,7 @@ int main(int argc, char *argv[]) bool eval_error_ok = false; bool boxed_exception_ok = false; + bool any_exception_ok = false; for (int i = 0; i < argc; ++i) { if ( i == 0 && argc > 1 ) { @@ -344,6 +345,9 @@ int main(int argc, char *argv[]) } else if ( arg == "--exception" ) { boxed_exception_ok = true; continue; + } else if ( arg == "--any-exception" ) { + any_exception_ok = true; + continue; } else if ( arg == "-i" || arg == "--interactive" ) { mode = eInteractive ; } else if ( arg.find('-') == 0 ) { @@ -383,11 +387,18 @@ int main(int argc, char *argv[]) catch (const chaiscript::exception::load_module_error &e) { std::cout << "Unhandled module load error\n" << e.what() << '\n'; } - -// catch (std::exception &e) { -// std::cout << e.what() << '\n'; -// return EXIT_FAILURE; -// } + catch (std::exception &e) { + std::cout << "Unhandled standard exception: " << e.what() << '\n'; + if (!any_exception_ok) { + throw; + } + } + catch (...) { + std::cout << "Unhandled unknown exception" << '\n'; + if (!any_exception_ok) { + throw; + } + } } return EXIT_SUCCESS; diff --git a/unittests/fuzz_unit_test.inc b/unittests/fuzz_unit_test.inc new file mode 100644 index 00000000..87b8e518 --- /dev/null +++ b/unittests/fuzz_unit_test.inc @@ -0,0 +1,53 @@ +def assert_equal(x, y) +{ + if (x == y) + { + // Passes + } else { + // Fails + print("assert_equal failure: got '" + to_string(y) + "' expected '" + to_string(x) + "'"); +// exit(-1); + } +} + +def assert_false(f) +{ + if (f) + { + print("assert_false failure"); +// exit(-1); + } +} + +def assert_true(f) +{ + if (!f) + { + print("assert_true failure"); +// exit(-1); + } +} + +def assert_not_equal(x, y) +{ + if (!(x == y)) + { + // Passes + } else { + // Fails + print("assert_not_equal failure: got " + to_string(y) + " which was not expected."); +// exit(-1); + } +} + +def assert_throws(desc, x) +{ + if (throws_exception(x)) + { + // Passes + } else { + // Fails + print("assert_throws failure, function did not throw exception: " + to_string(desc)); +// exit(-1); + } +} diff --git a/unittests/fuzzy_tests-2016-06-29.tar.bz2 b/unittests/fuzzy_tests-2016-06-29.tar.bz2 deleted file mode 100644 index 95fd20ae03b75b4446c7d9108652d70ab788a428..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 84871 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 a#n@+c`R7lYuI!Khi@744C`d3a_(K4rF{6V3 diff --git a/unittests/fuzzy_tests-2017-07-20.tar.bz2 b/unittests/fuzzy_tests-2017-07-20.tar.bz2 new file mode 100644 index 0000000000000000000000000000000000000000..35df734fc0c5c0ac4cd4a4afe63ff27f485c0684 GIT binary patch literal 129965 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 Date: Fri, 21 Jul 2017 11:09:53 +0100 Subject: [PATCH 84/84] * Added Buckaroo.pm package --- BUCK | 5 +---- buckaroo.json | 3 +-- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/BUCK b/BUCK index e01db658..0bf9e3ad 100644 --- a/BUCK +++ b/BUCK @@ -1,7 +1,5 @@ -include_defs('//BUCKAROO_DEPS') - prebuilt_cxx_library( - name = 'chaiscript', + name = 'chaiscript', header_only = True, header_namespace = 'chaiscript', exported_headers = subdir_glob([ @@ -10,5 +8,4 @@ prebuilt_cxx_library( visibility = [ 'PUBLIC', ], - deps = BUCKAROO_DEPS, ) diff --git a/buckaroo.json b/buckaroo.json index afc50314..95db1764 100644 --- a/buckaroo.json +++ b/buckaroo.json @@ -1,4 +1,3 @@ { - "name": "chaiscript", - "dependencies": {} + "name": "ChaiScript" }