From db8be03ceea6c9a607973d2b5bcf5fb8e6484391 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 26 Mar 2014 07:26:23 -0600 Subject: [PATCH 01/13] Add tests for returning of arithmetic types with conversions --- unittests/arithmetic_conversions_test.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/unittests/arithmetic_conversions_test.cpp b/unittests/arithmetic_conversions_test.cpp index 255a02a..ba72591 100644 --- a/unittests/arithmetic_conversions_test.cpp +++ b/unittests/arithmetic_conversions_test.cpp @@ -18,6 +18,11 @@ void f3(double) { } +void f_func_return(const boost::function &f) +{ + // test the ability to return an unsigned with auto conversion + f(4); +} int main() { @@ -29,6 +34,8 @@ int main() chai.add(chaiscript::fun(&f1), "f3"); chai.add(chaiscript::fun(&f4), "f3"); + chai.add(chaiscript::fun(&f_func_return), "func_return"); + // no overloads chai.eval("f1(0)"); chai.eval("f1(0l)"); @@ -46,7 +53,12 @@ int main() // 1 non-arithmetic overload chai.eval("f2(1.0)"); - // this is the one call we expect to fail + // various options for returning with conversions from chaiscript + chai.eval("func_return(fun(x) { return 5u; })"); + chai.eval("func_return(fun(x) { return 5; })"); + chai.eval("func_return(fun(x) { return 5.0f; })"); + + // this is the one call we expect to fail, ambiguous overloads try { chai.eval("f2(1.0l)"); } catch (const std::exception &) { From 7fade8e841c4b280072210e7eef33db9a38a5380 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 26 Mar 2014 08:11:37 -0600 Subject: [PATCH 02/13] Allow for automatic conversion of arithmetic types for returns from chaiscript function wrappers --- .../dispatchkit/function_call_detail.hpp | 21 +++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/include/chaiscript/dispatchkit/function_call_detail.hpp b/include/chaiscript/dispatchkit/function_call_detail.hpp index b739281..ab21684 100644 --- a/include/chaiscript/dispatchkit/function_call_detail.hpp +++ b/include/chaiscript/dispatchkit/function_call_detail.hpp @@ -27,12 +27,11 @@ namespace chaiscript { namespace detail { - /** * Internal helper class for handling the return * value of a build_function_caller */ - template + template struct Function_Caller_Ret { static Ret call(const std::vector &t_funcs, @@ -42,11 +41,25 @@ namespace chaiscript } }; + /** + * Specialization for arithmetic return types + */ + template + struct Function_Caller_Ret + { + static Ret call(const std::vector &t_funcs, + const std::vector ¶ms, const Dynamic_Cast_Conversions &t_conversions) + { + return Boxed_Number(dispatch::dispatch(t_funcs, params, t_conversions)).get_as(); + } + }; + + /** * Specialization for void return types */ template<> - struct Function_Caller_Ret + struct Function_Caller_Ret { static void call(const std::vector &t_funcs, const std::vector ¶ms, const Dynamic_Cast_Conversions &t_conversions) @@ -83,7 +96,7 @@ namespace chaiscript BOOST_PP_REPEAT(n, addparam, ~); - return Function_Caller_Ret::call(funcs, params, t_conversions); + return Function_Caller_Ret::value>::call(funcs, params, t_conversions); } /** From 56b036052f11912f1cd92d77a9a3447f758e9bee Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 26 Mar 2014 09:14:06 -0600 Subject: [PATCH 03/13] Add test for automatic casting down in inheritance --- .../chaiscript/dispatchkit/dynamic_cast_conversion.hpp | 2 -- src/test_module.cpp | 10 ++++++++++ unittests/inheritance.chai | 9 +++++++++ 3 files changed, 19 insertions(+), 2 deletions(-) diff --git a/include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp b/include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp index 91e0a88..93d435c 100644 --- a/include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp +++ b/include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp @@ -242,8 +242,6 @@ namespace chaiscript /// chai.add(chaiscript::base_class()); /// \endcode /// - /// \todo Move share static type registration code into a mechanism that allows it to be properly - /// shared by all modules template Dynamic_Cast_Conversion base_class() { diff --git a/src/test_module.cpp b/src/test_module.cpp index 796f5ff..83cbc12 100644 --- a/src/test_module.cpp +++ b/src/test_module.cpp @@ -35,11 +35,17 @@ class TestDerivedType : public TestBaseType public: virtual ~TestDerivedType() {} virtual int func() { return 1; } + int derived_only_func() { return 19; } private: TestDerivedType &operator=(const TestDerivedType &); }; +boost::shared_ptr derived_type_factory() +{ + return boost::shared_ptr(new TestDerivedType()); +} + std::string hello_world() { return "Hello World"; @@ -81,6 +87,10 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo m->add(chaiscript::base_class()); + m->add(chaiscript::fun(&TestDerivedType::derived_only_func), "derived_only_func"); + + m->add(chaiscript::fun(&derived_type_factory), "derived_type_factory"); + m->add(chaiscript::fun(&TestBaseType::func), "func"); m->add(chaiscript::fun(&TestBaseType::val), "val"); m->add(chaiscript::fun(&TestBaseType::const_val), "const_val"); diff --git a/unittests/inheritance.chai b/unittests/inheritance.chai index 0231a50..0105c68 100644 --- a/unittests/inheritance.chai +++ b/unittests/inheritance.chai @@ -15,3 +15,12 @@ assert_equal(15, t.const_val); t.val = 23; assert_equal(23, t.val) +// test_derived_factory returns a TestDerivedType contained +// in a shared_ptr. This is testing our ability +// to detect that and do the down casting for the user automatically +// at runtime +var d := derived_type_factory(); + +assert_equal(t.derived_only_func(), 19); +assert_equal(d.derived_only_func(), 19); + From 656b438002e630da4ebf6b2148506445ef6a94f5 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 26 Mar 2014 10:52:56 -0600 Subject: [PATCH 04/13] First cast up chain, if that fails, cast down --- include/chaiscript/dispatchkit/boxed_cast.hpp | 11 +- .../dispatchkit/dynamic_cast_conversion.hpp | 115 +++++++++++------- unittests/inheritance.chai | 3 +- 3 files changed, 83 insertions(+), 46 deletions(-) diff --git a/include/chaiscript/dispatchkit/boxed_cast.hpp b/include/chaiscript/dispatchkit/boxed_cast.hpp index 345e89a..e3164d4 100644 --- a/include/chaiscript/dispatchkit/boxed_cast.hpp +++ b/include/chaiscript/dispatchkit/boxed_cast.hpp @@ -84,11 +84,18 @@ namespace chaiscript if (boost::is_polymorphic::type>::value && t_conversions) { try { + std::cout << "trying an up conversion " << typeid(Type).name() << std::endl; // 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 return detail::Cast_Helper::cast(t_conversions->boxed_dynamic_cast(bv), t_conversions); - } catch (const boost::bad_any_cast &) { - throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type)); + } catch (...) { + try { + std::cout << "trying a down conversion " << typeid(Type).name() << std::endl; + // try going the other way - down the inheritance graph + return detail::Cast_Helper::cast(t_conversions->boxed_dynamic_down_cast(bv), t_conversions); + } catch (const boost::bad_any_cast &) { + throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type)); + } } } else { // If it's not polymorphic, just throw the error, don't waste the time on the diff --git a/include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp b/include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp index 93d435c..a43ce77 100644 --- a/include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp +++ b/include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp @@ -48,6 +48,7 @@ namespace chaiscript { public: virtual Boxed_Value convert(const Boxed_Value &derived) const = 0; + virtual Boxed_Value convert_down(const Boxed_Value &base) const = 0; const Type_Info &base() { @@ -72,6 +73,57 @@ namespace chaiscript }; + template + class Dynamic_Caster + { + public: + static Boxed_Value cast(const Boxed_Value &t_from) + { + if (t_from.get_type_info().bare_equal(user_type())) + { + if (t_from.is_pointer()) + { + // Dynamic cast out the contained boxed value, which we know is the type we want + if (t_from.is_const()) + { + boost::shared_ptr data + = boost::dynamic_pointer_cast(detail::Cast_Helper >::cast(t_from, 0)); + if (!data) + { + throw std::bad_cast(); + } + + return Boxed_Value(data); + } else { + boost::shared_ptr data + = boost::dynamic_pointer_cast(detail::Cast_Helper >::cast(t_from, 0)); + + if (!data) + { + throw std::bad_cast(); + } + + return Boxed_Value(data); + } + } else { + // Pull the reference out of the contained boxed value, which we know is the type we want + if (t_from.is_const()) + { + const From &d = detail::Cast_Helper::cast(t_from, 0); + const To &data = dynamic_cast(d); + return Boxed_Value(boost::cref(data)); + } else { + From &d = detail::Cast_Helper::cast(t_from, 0); + To &data = dynamic_cast(d); + return Boxed_Value(boost::ref(data)); + } + } + } else { + throw exception::bad_boxed_dynamic_cast(t_from.get_type_info(), typeid(To), "Unknown dynamic_cast_conversion"); + } + } + }; + template class Dynamic_Conversion_Impl : public Dynamic_Conversion { @@ -81,50 +133,14 @@ namespace chaiscript { } + virtual Boxed_Value convert_down(const Boxed_Value &t_base) const + { + return Dynamic_Caster::cast(t_base); + } + virtual Boxed_Value convert(const Boxed_Value &t_derived) const { - if (t_derived.get_type_info().bare_equal(user_type())) - { - if (t_derived.is_pointer()) - { - // Dynamic cast out the contained boxed value, which we know is the type we want - if (t_derived.is_const()) - { - boost::shared_ptr data - = boost::dynamic_pointer_cast(detail::Cast_Helper >::cast(t_derived, 0)); - if (!data) - { - throw std::bad_cast(); - } - - return Boxed_Value(data); - } else { - boost::shared_ptr data - = boost::dynamic_pointer_cast(detail::Cast_Helper >::cast(t_derived, 0)); - - if (!data) - { - throw std::bad_cast(); - } - - return Boxed_Value(data); - } - } else { - // Pull the reference out of the contained boxed value, which we know is the type we want - if (t_derived.is_const()) - { - const Derived &d = detail::Cast_Helper::cast(t_derived, 0); - const Base &data = dynamic_cast(d); - return Boxed_Value(boost::cref(data)); - } else { - Derived &d = detail::Cast_Helper::cast(t_derived, 0); - Base &data = dynamic_cast(d); - return Boxed_Value(boost::ref(data)); - } - } - } else { - throw exception::bad_boxed_dynamic_cast(t_derived.get_type_info(), typeid(Base), "Unknown dynamic_cast_conversion"); - } + return Dynamic_Caster::cast(t_derived); } }; } @@ -155,7 +171,7 @@ namespace chaiscript bool dynamic_cast_converts(const Type_Info &base, const Type_Info &derived) const { - return has_conversion(base, derived); + return has_conversion(base, derived) || has_conversion(derived, base); } template @@ -170,6 +186,19 @@ namespace chaiscript } } + template + Boxed_Value boxed_dynamic_down_cast(const Boxed_Value &base) const + { + try { + return get_conversion(base.get_type_info(), user_type())->convert_down(base); + } catch (const std::out_of_range &) { + throw exception::bad_boxed_dynamic_cast(base.get_type_info(), typeid(Derived), "No known conversion"); + } catch (const std::bad_cast &) { + throw exception::bad_boxed_dynamic_cast(base.get_type_info(), typeid(Derived), "Unable to perform dynamic_cast operation"); + } + } + + bool has_conversion(const Type_Info &base, const Type_Info &derived) const { chaiscript::detail::threading::shared_lock l(m_mutex); diff --git a/unittests/inheritance.chai b/unittests/inheritance.chai index 0105c68..99cf7c0 100644 --- a/unittests/inheritance.chai +++ b/unittests/inheritance.chai @@ -19,8 +19,9 @@ assert_equal(23, t.val) // in a shared_ptr. This is testing our ability // to detect that and do the down casting for the user automatically // at runtime -var d := derived_type_factory(); assert_equal(t.derived_only_func(), 19); + +var d := derived_type_factory(); assert_equal(d.derived_only_func(), 19); From 96acf5e8333ae23c3cb345b2406b7377fd8f53d7 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 26 Mar 2014 11:37:37 -0600 Subject: [PATCH 05/13] Update travis in 4.x branch for coveralls support --- .travis.yml | 11 +++++---- CMakeLists.txt | 60 ++++++++++++++++++++++++++++++-------------------- 2 files changed, 43 insertions(+), 28 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0fcfba3..651b562 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,12 +4,15 @@ compiler: - clang before_install: - sudo apt-get install libboost-dev libboost-all-dev + - sudo pip install cpp-coveralls script: - - mkdir build - - cd build - - cmake ../ - - make + - cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug . + - make -j2 - make test + - mkdir gcov + - find CMakeFiles/ -name "*.gc*" -exec mv {} gcov/ \; + - $GCOV -d -o gcov gcov/*.gcda + - coveralls -n -E ".*\.cpp" notifications: recipients: - jason@emptycrate.com diff --git a/CMakeLists.txt b/CMakeLists.txt index 394c1ea..7a46223 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,6 +6,18 @@ option(MULTITHREAD_SUPPORT_ENABLED "Multithreaded Support Enabled" TRUE) option(BUILD_MODULES "Build Extra Modules (stl, reflection)" TRUE) option(BUILD_SAMPLES "Build Samples Folder" FALSE) +set(EXTRA_LINKER_FLAGS "") + +if (CMAKE_COMPILER_IS_GNUCC) + option(ENABLE_COVERAGE "Enable Coverage Reporting in GCC" FALSE) + + if (ENABLE_COVERAGE) + add_definitions(--coverage -O0) + SET(EXTRA_LINKER_FLAGS ${EXTRA_LINKER_FLAGS} "--coverage") + endif() + +endif() + list(APPEND CPACK_SOURCE_IGNORE_FILES "${CMAKE_CURRENT_BINARY_DIR}") list(APPEND CPACK_SOURCE_IGNORE_FILES "\\\\.svn") list(APPEND CPACK_SOURCE_IGNORE_FILES "\\\\.git") @@ -114,22 +126,22 @@ endif() include_directories(${Boost_INCLUDE_DIRS}) include_directories(${Boost_INCLUDE_DIR}) add_executable(chai src/main.cpp ${Chai_INCLUDES}) -target_link_libraries(chai ${LIBS}) +target_link_libraries(chai ${LIBS} ${EXTRA_LINKER_FLAGS}) if (BUILD_SAMPLES) add_executable(example samples/example.cpp) - target_link_libraries(example ${LIBS}) + target_link_libraries(example ${LIBS} ${EXTRA_LINKER_FLAGS}) add_executable(memory_leak_test samples/memory_leak_test.cpp) - target_link_libraries(memory_leak_test ${LIBS}) + target_link_libraries(memory_leak_test ${LIBS} ${EXTRA_LINKER_FLAGS}) endif() if (BUILD_MODULES) add_library(stl_extra MODULE src/stl_extra.cpp) - target_link_libraries(stl_extra ${LIBS}) + target_link_libraries(stl_extra ${LIBS} ${EXTRA_LINKER_FLAGS}) add_library(reflection MODULE src/reflection.cpp) - target_link_libraries(reflection ${LIBS}) + target_link_libraries(reflection ${LIBS} ${EXTRA_LINKER_FLAGS}) set(MODULES stl_extra reflection) endif() @@ -153,72 +165,72 @@ if(BUILD_TESTING) if (NOT UNIT_TEST_LIGHT) add_executable(utility_test unittests/utility_test.cpp) - target_link_libraries(utility_test ${LIBS}) + target_link_libraries(utility_test ${LIBS} ${EXTRA_LINKER_FLAGS}) add_test(NAME Utility_Test COMMAND utility_test) add_executable(dynamic_object_test unittests/dynamic_object_test.cpp) - target_link_libraries(dynamic_object_test ${LIBS}) + target_link_libraries(dynamic_object_test ${LIBS} ${EXTRA_LINKER_FLAGS}) add_test(NAME Dynamic_Object_Test COMMAND dynamic_object_test) add_executable(functor_creation_test unittests/functor_creation_test.cpp) - target_link_libraries(functor_creation_test ${LIBS}) + target_link_libraries(functor_creation_test ${LIBS} ${EXTRA_LINKER_FLAGS}) add_test(NAME Functor_Creation_Test COMMAND functor_creation_test) add_executable(functor_cast_test unittests/functor_cast_test.cpp) - target_link_libraries(functor_cast_test ${LIBS}) + target_link_libraries(functor_cast_test ${LIBS} ${EXTRA_LINKER_FLAGS}) add_test(NAME Functor_Cast_Test COMMAND functor_cast_test) add_executable(boxed_cast_test unittests/boxed_cast_test.cpp) - target_link_libraries(boxed_cast_test ${LIBS}) + target_link_libraries(boxed_cast_test ${LIBS} ${EXTRA_LINKER_FLAGS}) add_test(NAME Boxed_Cast_Test COMMAND boxed_cast_test) add_executable(object_lifetime_test unittests/object_lifetime_test.cpp) - target_link_libraries(object_lifetime_test ${LIBS}) + target_link_libraries(object_lifetime_test ${LIBS} ${EXTRA_LINKER_FLAGS}) add_test(NAME Object_Lifetime_Test COMMAND object_lifetime_test) add_executable(function_ordering_test unittests/function_ordering_test.cpp) - target_link_libraries(function_ordering_test ${LIBS}) + target_link_libraries(function_ordering_test ${LIBS} ${EXTRA_LINKER_FLAGS}) add_test(NAME Function_Ordering_Test COMMAND function_ordering_test) add_executable(type_info_test unittests/type_info_test.cpp) - target_link_libraries(type_info_test ${LIBS}) + target_link_libraries(type_info_test ${LIBS} ${EXTRA_LINKER_FLAGS}) add_test(NAME Type_Info_Test COMMAND type_info_test) add_executable(eval_catch_exception_test unittests/eval_catch_exception_test.cpp) - target_link_libraries(eval_catch_exception_test ${LIBS}) + target_link_libraries(eval_catch_exception_test ${LIBS} ${EXTRA_LINKER_FLAGS}) add_test(NAME Eval_Catch_Exception_Test COMMAND eval_catch_exception_test) add_executable(short_comparison_test unittests/short_comparison_test.cpp) - target_link_libraries(short_comparison_test ${LIBS}) + target_link_libraries(short_comparison_test ${LIBS} ${EXTRA_LINKER_FLAGS}) add_test(NAME Short_Comparison_Test COMMAND short_comparison_test) add_executable(expected_eval_errors_test unittests/expected_eval_errors_test.cpp) - target_link_libraries(expected_eval_errors_test ${LIBS}) + target_link_libraries(expected_eval_errors_test ${LIBS} ${EXTRA_LINKER_FLAGS}) add_test(NAME Expected_Eval_Errors_Test COMMAND expected_eval_errors_test) add_executable(set_state_test unittests/set_state_test.cpp) - target_link_libraries(set_state_test ${LIBS}) + target_link_libraries(set_state_test ${LIBS} ${EXTRA_LINKER_FLAGS}) add_test(NAME Set_State_Test COMMAND set_state_test) add_executable(simultaneous_chaiscript_test unittests/simultaneous_chaiscript_test.cpp) - target_link_libraries(simultaneous_chaiscript_test ${LIBS}) + target_link_libraries(simultaneous_chaiscript_test ${LIBS} ${EXTRA_LINKER_FLAGS}) add_test(NAME Simultaneous_Chaiscript_Test COMMAND simultaneous_chaiscript_test) add_executable(c_linkage_test unittests/c_linkage_test.cpp) - target_link_libraries(c_linkage_test ${LIBS}) + target_link_libraries(c_linkage_test ${LIBS} ${EXTRA_LINKER_FLAGS}) add_test(NAME C_Linkage_Test COMMAND c_linkage_test) add_executable(integer_literal_test unittests/integer_literal_test.cpp) - target_link_libraries(integer_literal_test ${LIBS}) + target_link_libraries(integer_literal_test ${LIBS} ${EXTRA_LINKER_FLAGS}) add_test(NAME Integer_Literal_Test COMMAND integer_literal_test) add_executable(arithmetic_conversions_test unittests/arithmetic_conversions_test.cpp) - target_link_libraries(arithmetic_conversions_test ${LIBS}) + target_link_libraries(arithmetic_conversions_test ${LIBS} ${EXTRA_LINKER_FLAGS}) add_test(NAME Arithmetic_Conversions_Test COMMAND arithmetic_conversions_test) if (MULTITHREAD_SUPPORT_ENABLED) add_executable(multithreaded_test unittests/multithreaded_test.cpp) - target_link_libraries(multithreaded_test ${LIBS}) + target_link_libraries(multithreaded_test ${LIBS} ${EXTRA_LINKER_FLAGS}) add_test(NAME Multithreaded_Test COMMAND multithreaded_test) set_property(TEST Multithreaded_Test PROPERTY ENVIRONMENT @@ -231,11 +243,11 @@ if(BUILD_TESTING) add_executable(multifile_test unittests/multifile_test_main.cpp unittests/multifile_test_chai.cpp unittests/multifile_test_module.cpp) - target_link_libraries(multifile_test ${LIBS}) + target_link_libraries(multifile_test ${LIBS} ${EXTRA_LINKER_FLAGS}) add_test(NAME MultiFile_Test COMMAND multifile_test) add_library(test_module MODULE src/test_module.cpp) - target_link_libraries(test_module ${LIBS}) + target_link_libraries(test_module ${LIBS} ${EXTRA_LINKER_FLAGS}) install(TARGETS test_module RUNTIME DESTINATION bin LIBRARY DESTINATION lib/chaiscript) endif() From 611692646fc172de4ff81ce9121896e6b1a63afe Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 26 Mar 2014 13:32:25 -0600 Subject: [PATCH 06/13] Add travis support for testing with cppcheck --- .travis.yml | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/.travis.yml b/.travis.yml index 651b562..fadcf76 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,22 +1,34 @@ language: cpp compiler: - - gcc - - clang +- gcc before_install: - - sudo apt-get install libboost-dev libboost-all-dev - - sudo pip install cpp-coveralls -script: - - cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug . - - make -j2 - - make test - - mkdir gcov - - find CMakeFiles/ -name "*.gc*" -exec mv {} gcov/ \; - - $GCOV -d -o gcov gcov/*.gcda - - coveralls -n -E ".*\.cpp" +- sudo apt-get install libboost-dev libboost-all-dev +- sudo pip install cpp-coveralls +script: +- cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug . +- make -j2 +- make test +- mkdir gcov +- find CMakeFiles/ -name "*.gc*" -exec mv {} gcov/ \; +- gcov -d -o gcov gcov/*.gcda +- coveralls -n -E ".*\.cpp" +after_script: +- pushd .. +- wget http://sourceforge.net/projects/cppcheck/files/cppcheck/1.64/cppcheck-1.64.tar.bz2 +- tar -xvf cppcheck-1.64.tar.bz2 +- cd cppcheck-1.64 +- make -j2 +- popd +- ../cppcheck-1.64/cppcheck --enable=all --inconclusive -I include --inline-suppr --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 && echo -n '{ "body": " ' > output.json +- echo -n `awk '{printf "%s\\\\n", $0;}' output` >> output.json && echo -n '"}' >> output.json +- curl -H "Authorization: token ${TOKEN}" --request POST --data @output.json https://api.github.com/repos/ChaiScript/ChaiScript/commits/${TRAVIS_COMMIT}/comments notifications: recipients: - - jason@emptycrate.com + - jason@emptycrate.com email: on_success: always on_failure: always - +env: + global: + secure: LCUAKUCRtFp2ak81nVLR+jx0C9+Drwx1OR4VzuvH+HNGWFdUZmAIV3R84euDqFC5cUhYYipaeMbiSOJUHE4MNlL58eQZryED6KSL7k7SgxOLpFSspMvuMjIYZLlBWpBneCR/EMDilu+zXEnASfVUMPuLmtY1GAyfSoZboqFProc= From a652a7e56438ff3a7db41c7ef82a693d31f041b2 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 26 Mar 2014 13:37:51 -0600 Subject: [PATCH 07/13] Only post comment if this is a pull request --- .travis.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index fadcf76..34155ed 100644 --- a/.travis.yml +++ b/.travis.yml @@ -20,9 +20,11 @@ after_script: - make -j2 - popd - ../cppcheck-1.64/cppcheck --enable=all --inconclusive -I include --inline-suppr --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 && echo -n '{ "body": " ' > output.json -- echo -n `awk '{printf "%s\\\\n", $0;}' output` >> output.json && echo -n '"}' >> output.json -- curl -H "Authorization: token ${TOKEN}" --request POST --data @output.json https://api.github.com/repos/ChaiScript/ChaiScript/commits/${TRAVIS_COMMIT}/comments +- sed -i "s/TRAVIS_COMMIT/${TRAVIS_COMMIT}/g" output +- echo -n '{ "body": " ' > output.json +- echo -n `awk '{printf "%s\\\\n", $0;}' output` >> output.json +- echo -n '"}' >> output.json +- if [ "${TRAVIS_PULL_REQUEST}" = "true" ]; then curl -H "Authorization: token ${TOKEN}" --request POST --data @output.json https://api.github.com/repos/ChaiScript/ChaiScript/commits/${TRAVIS_COMMIT}/comments; fi notifications: recipients: - jason@emptycrate.com From 12de955a4790c1d0a125e327d148ad278154f8f6 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 26 Mar 2014 13:56:02 -0600 Subject: [PATCH 08/13] Post cppcheck results to pull request --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 34155ed..088697f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -24,7 +24,7 @@ after_script: - echo -n '{ "body": " ' > output.json - echo -n `awk '{printf "%s\\\\n", $0;}' output` >> output.json - echo -n '"}' >> output.json -- if [ "${TRAVIS_PULL_REQUEST}" = "true" ]; then curl -H "Authorization: token ${TOKEN}" --request POST --data @output.json https://api.github.com/repos/ChaiScript/ChaiScript/commits/${TRAVIS_COMMIT}/comments; fi +- if [ "${TRAVIS_PULL_REQUEST}" = "false" ]; then curl -H "Authorization: token ${TOKEN}" --request POST --data @output.json https://api.github.com/repos/ChaiScript/ChaiScript/commits/${TRAVIS_COMMIT}/comments; else curl -H "Authorization: token ${TOKEN}" --request POST --data @output.json https://api.github.com/repos/ChaiScript/ChaiScript/issues/${TRAVIS_PULL_REQUEST}/comments; fi notifications: recipients: - jason@emptycrate.com From d9bdad714fe892b996b3e68af371eb0bc35b2f03 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 26 Mar 2014 14:45:01 -0600 Subject: [PATCH 09/13] Fix syntax problem with .travis.yml --- .travis.yml | 37 ++++++++++------------------- contrib/codeanalysis/runcppcheck.sh | 16 +++++++++++++ 2 files changed, 29 insertions(+), 24 deletions(-) create mode 100755 contrib/codeanalysis/runcppcheck.sh diff --git a/.travis.yml b/.travis.yml index 088697f..657c7bc 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,34 +1,23 @@ language: cpp compiler: -- gcc + - gcc before_install: -- sudo apt-get install libboost-dev libboost-all-dev -- sudo pip install cpp-coveralls + - sudo apt-get install libboost-dev libboost-all-dev + - sudo pip install cpp-coveralls script: -- cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug . -- make -j2 -- make test -- mkdir gcov -- find CMakeFiles/ -name "*.gc*" -exec mv {} gcov/ \; -- gcov -d -o gcov gcov/*.gcda -- coveralls -n -E ".*\.cpp" + - cmake -D ENABLE_COVERAGE:BOOL=TRUE -D CMAKE_BUILD_TYPE:STRING=Debug . + - make -j2 + - make test + - mkdir gcov + - find CMakeFiles/ -name "*.gc*" -exec mv {} gcov/ \; + - gcov -d -o gcov gcov/*.gcda + - coveralls -n -E ".*\.cpp" after_script: -- pushd .. -- wget http://sourceforge.net/projects/cppcheck/files/cppcheck/1.64/cppcheck-1.64.tar.bz2 -- tar -xvf cppcheck-1.64.tar.bz2 -- cd cppcheck-1.64 -- make -j2 -- popd -- ../cppcheck-1.64/cppcheck --enable=all --inconclusive -I include --inline-suppr --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 -- echo -n '{ "body": " ' > output.json -- echo -n `awk '{printf "%s\\\\n", $0;}' output` >> output.json -- echo -n '"}' >> output.json -- if [ "${TRAVIS_PULL_REQUEST}" = "false" ]; then curl -H "Authorization: token ${TOKEN}" --request POST --data @output.json https://api.github.com/repos/ChaiScript/ChaiScript/commits/${TRAVIS_COMMIT}/comments; else curl -H "Authorization: token ${TOKEN}" --request POST --data @output.json https://api.github.com/repos/ChaiScript/ChaiScript/issues/${TRAVIS_PULL_REQUEST}/comments; fi + - contrib/codeanalysis/runcppcheck.sh notifications: - recipients: - - jason@emptycrate.com email: + recipients: + - jason@emptycrate.com on_success: always on_failure: always env: diff --git a/contrib/codeanalysis/runcppcheck.sh b/contrib/codeanalysis/runcppcheck.sh new file mode 100755 index 0000000..e4d3946 --- /dev/null +++ b/contrib/codeanalysis/runcppcheck.sh @@ -0,0 +1,16 @@ +#!/bin/sh + +pushd .. +wget http://sourceforge.net/projects/cppcheck/files/cppcheck/1.64/cppcheck-1.64.tar.bz2 +tar -xvf cppcheck-1.64.tar.bz2 +cd cppcheck-1.64 +make -j2 +popd +../cppcheck-1.64/cppcheck --enable=all --inconclusive -I include --inline-suppr --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 +echo -n '{ "body": " ' > output.json +echo -n `awk '{printf "%s\\\\n", $0;}' output` >> output.json +echo -n '"}' >> output.json +if [ "${TRAVIS_PULL_REQUEST}" = "false" ]; then curl -H "Authorization: token ${TOKEN}" --request POST --data @output.json https://api.github.com/repos/ChaiScript/ChaiScript/commits/${TRAVIS_COMMIT}/comments; else curl -H "Authorization: token ${TOKEN}" --request POST --data @output.json https://api.github.com/repos/ChaiScript/ChaiScript/issues/${TRAVIS_PULL_REQUEST}/comments; fi + + From 296769ee24bdb542d06347a4154029aa98e5b516 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 26 Mar 2014 15:20:06 -0600 Subject: [PATCH 10/13] Version number bump, cppcheck fix --- CMakeLists.txt | 2 +- contrib/codeanalysis/runcppcheck.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7a46223..baa12d0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -30,7 +30,7 @@ set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/description.txt" set(CPACK_PACKAGE_VERSION_MAJOR 4) set(CPACK_PACKAGE_VERSION_MINOR 3) -set(CPACK_PACKAGE_VERSION_PATCH 0) +set(CPACK_PACKAGE_VERSION_PATCH 1) set(CPACK_PACKAGE_EXECUTABLES "chai;ChaiScript Eval") set(CPACK_PACKAGE_VENDOR "ChaiScript.com") set(CPACK_PACKAGE_CONTACT "contact@chaiscript.com") diff --git a/contrib/codeanalysis/runcppcheck.sh b/contrib/codeanalysis/runcppcheck.sh index e4d3946..a7eacd8 100755 --- a/contrib/codeanalysis/runcppcheck.sh +++ b/contrib/codeanalysis/runcppcheck.sh @@ -1,4 +1,4 @@ -#!/bin/sh +#!/bin/bash pushd .. wget http://sourceforge.net/projects/cppcheck/files/cppcheck/1.64/cppcheck-1.64.tar.bz2 From 65b0846e419f1a4e9dd3f61395ee28817401c31a Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 26 Mar 2014 16:59:41 -0600 Subject: [PATCH 11/13] Address some of the issues found by cppcheck --- include/chaiscript/dispatchkit/bootstrap.hpp | 6 ------ include/chaiscript/dispatchkit/boxed_number.hpp | 4 ++-- .../dispatchkit/dynamic_cast_conversion.hpp | 4 ++-- include/chaiscript/dispatchkit/dynamic_object.hpp | 2 +- include/chaiscript/dispatchkit/proxy_functions.hpp | 2 +- include/chaiscript/language/chaiscript_common.hpp | 4 ++-- include/chaiscript/language/chaiscript_engine.hpp | 10 +++++----- include/chaiscript/language/chaiscript_parser.hpp | 12 ++++++------ 8 files changed, 19 insertions(+), 25 deletions(-) diff --git a/include/chaiscript/dispatchkit/bootstrap.hpp b/include/chaiscript/dispatchkit/bootstrap.hpp index af2a148..8417e8e 100644 --- a/include/chaiscript/dispatchkit/bootstrap.hpp +++ b/include/chaiscript/dispatchkit/bootstrap.hpp @@ -308,12 +308,6 @@ namespace chaiscript static void throw_exception(const Boxed_Value &bv) { throw bv; } - - static boost::shared_ptr bootstrap2(boost::shared_ptr e = boost::shared_ptr (new chaiscript::detail::Dispatch_Engine())) - { - e->add(user_type(), "void"); - return e; - } static std::string what(const std::exception &e) { diff --git a/include/chaiscript/dispatchkit/boxed_number.hpp b/include/chaiscript/dispatchkit/boxed_number.hpp index 29c6c8d..4ad7ffa 100644 --- a/include/chaiscript/dispatchkit/boxed_number.hpp +++ b/include/chaiscript/dispatchkit/boxed_number.hpp @@ -307,7 +307,7 @@ namespace chaiscript } template - std::string to_string_aux(const Boxed_Value &v) const + static std::string to_string_aux(const Boxed_Value &v) { std::ostringstream oss; oss << *static_cast(v.get_const_ptr()); @@ -520,7 +520,7 @@ namespace chaiscript return oper(Operators::assign_bitwise_and, this->bv, t_rhs.bv); } - void validate_boxed_number(const Boxed_Value &v) + static void validate_boxed_number(const Boxed_Value &v) { const Type_Info &inp_ = v.get_type_info(); if (inp_ == typeid(bool)) diff --git a/include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp b/include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp index a43ce77..84c1bc7 100644 --- a/include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp +++ b/include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp @@ -50,11 +50,11 @@ namespace chaiscript virtual Boxed_Value convert(const Boxed_Value &derived) const = 0; virtual Boxed_Value convert_down(const Boxed_Value &base) const = 0; - const Type_Info &base() + const Type_Info &base() const { return m_base; } - const Type_Info &derived() + const Type_Info &derived() const { return m_derived; } diff --git a/include/chaiscript/dispatchkit/dynamic_object.hpp b/include/chaiscript/dispatchkit/dynamic_object.hpp index 8952a4a..440b085 100644 --- a/include/chaiscript/dispatchkit/dynamic_object.hpp +++ b/include/chaiscript/dispatchkit/dynamic_object.hpp @@ -31,7 +31,7 @@ namespace chaiscript return m_attrs[t_attr_name]; } - std::map get_attrs() + std::map get_attrs() const { return m_attrs; } diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index 2b4aff7..551825b 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -23,7 +23,7 @@ namespace chaiscript class Boxed_Number; struct AST_Node; - typedef boost::shared_ptr AST_NodePtr; + typedef boost::shared_ptr AST_NodePtr; namespace dispatch { diff --git a/include/chaiscript/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index 2f7e0c1..fea4668 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -54,7 +54,7 @@ namespace chaiscript }; /// \brief Typedef for pointers to AST_Node objects. Used in building of the AST_Node tree - typedef boost::shared_ptr AST_NodePtr; + typedef boost::shared_ptr AST_NodePtr; /// \brief Classes which may be thrown during error cases when ChaiScript is executing. @@ -435,7 +435,7 @@ namespace chaiscript return eval_internal(t_e); } catch (exception::eval_error &ee) { ee.call_stack.push_back(shared_from_this()); - throw ee; + throw; } } diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index 0b74d7b..05e468c 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -681,7 +681,7 @@ namespace chaiscript if (t_handler) { t_handler->handle(bv, m_engine); } - throw bv; + throw; } } @@ -707,7 +707,7 @@ namespace chaiscript if (t_handler) { t_handler->handle(bv, m_engine); } - throw bv; + throw; } } @@ -737,7 +737,7 @@ namespace chaiscript if (t_handler) { t_handler->handle(bv, m_engine); } - throw bv; + throw; } } @@ -753,7 +753,7 @@ namespace chaiscript if (t_handler) { t_handler->handle(bv, m_engine); } - throw bv; + throw; } } @@ -773,7 +773,7 @@ namespace chaiscript if (t_handler) { t_handler->handle(bv, m_engine); } - throw bv; + throw; } } }; diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 888c982..4111bea 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -56,7 +56,8 @@ namespace chaiscript public: ChaiScript_Parser() - : m_multiline_comment_begin("/*"), + : m_line(-1), m_col(-1), + m_multiline_comment_begin("/*"), m_multiline_comment_end("*/"), m_singleline_comment("//") { @@ -804,10 +805,9 @@ namespace chaiscript */ bool Quoted_String_() { bool retval = false; - char prev_char = 0; if (has_more_input() && (*m_input_pos == '\"')) { retval = true; - prev_char = *m_input_pos; + char prev_char = *m_input_pos; ++m_input_pos; ++m_col; @@ -981,10 +981,9 @@ namespace chaiscript */ bool Single_Quoted_String_() { bool retval = false; - char prev_char = 0; if (has_more_input() && (*m_input_pos == '\'')) { retval = true; - prev_char = *m_input_pos; + char prev_char = *m_input_pos; ++m_input_pos; ++m_col; @@ -1350,7 +1349,6 @@ namespace chaiscript bool Def() { bool retval = false; bool is_annotated = false; - bool is_method = false; AST_NodePtr annotation; if (Annotation()) { @@ -1369,6 +1367,8 @@ namespace chaiscript throw exception::eval_error("Missing function name in definition", File_Position(m_line, m_col), *m_filename); } + bool is_method = false; + if (Symbol("::", false)) { //We're now a method is_method = true; From 6b0e0dc7ae68502473f9eb76daafb76617e943ab Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 28 Mar 2014 07:04:51 -0600 Subject: [PATCH 12/13] Removed erroneously kept debug output --- include/chaiscript/dispatchkit/boxed_cast.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/chaiscript/dispatchkit/boxed_cast.hpp b/include/chaiscript/dispatchkit/boxed_cast.hpp index e3164d4..c27ffa3 100644 --- a/include/chaiscript/dispatchkit/boxed_cast.hpp +++ b/include/chaiscript/dispatchkit/boxed_cast.hpp @@ -84,13 +84,13 @@ namespace chaiscript if (boost::is_polymorphic::type>::value && t_conversions) { try { - std::cout << "trying an up conversion " << typeid(Type).name() << std::endl; + // std::cout << "trying an up conversion " << typeid(Type).name() << std::endl; // 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 return detail::Cast_Helper::cast(t_conversions->boxed_dynamic_cast(bv), t_conversions); } catch (...) { try { - std::cout << "trying a down conversion " << typeid(Type).name() << std::endl; + // std::cout << "trying a down conversion " << typeid(Type).name() << std::endl; // try going the other way - down the inheritance graph return detail::Cast_Helper::cast(t_conversions->boxed_dynamic_down_cast(bv), t_conversions); } catch (const boost::bad_any_cast &) { From caf4495cff0b7c12106338a19c32ab0b20341cd0 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 29 Mar 2014 06:16:21 -0600 Subject: [PATCH 13/13] Add unit tests for inheritance with multiple layers --- src/test_module.cpp | 22 ++++++++++++++++++++++ unittests/inheritance.chai | 8 ++++++++ 2 files changed, 30 insertions(+) diff --git a/src/test_module.cpp b/src/test_module.cpp index 83cbc12..13298c8 100644 --- a/src/test_module.cpp +++ b/src/test_module.cpp @@ -11,6 +11,8 @@ class TestBaseType virtual ~TestBaseType() {} virtual int func() { return 0; } + int base_only_func() { return -9; } + const TestBaseType &constMe() const { return *this; } int val; @@ -41,11 +43,22 @@ class TestDerivedType : public TestBaseType TestDerivedType &operator=(const TestDerivedType &); }; +class TestMoreDerivedType : public TestDerivedType +{ + public: + virtual ~TestMoreDerivedType() {} +}; + boost::shared_ptr derived_type_factory() { return boost::shared_ptr(new TestDerivedType()); } +boost::shared_ptr more_derived_type_factory() +{ + return boost::shared_ptr(new TestMoreDerivedType()); +} + std::string hello_world() { return "Hello World"; @@ -76,6 +89,7 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo m->add(chaiscript::user_type(), "TestBaseType"); m->add(chaiscript::user_type(), "TestDerivedType"); + m->add(chaiscript::user_type(), "TestMoreDerivedType"); m->add(chaiscript::constructor(), "TestBaseType"); // m->add(chaiscript::constructor(), "TestBaseType"); @@ -85,15 +99,23 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo m->add(chaiscript::constructor(), "TestDerivedType"); m->add(chaiscript::constructor(), "TestDerivedType"); + m->add(chaiscript::constructor(), "TestMoreDerivedType"); + m->add(chaiscript::constructor(), "TestMoreDerivedType"); + + /// \todo automatic chaining of base classes? m->add(chaiscript::base_class()); + m->add(chaiscript::base_class()); + m->add(chaiscript::base_class()); m->add(chaiscript::fun(&TestDerivedType::derived_only_func), "derived_only_func"); m->add(chaiscript::fun(&derived_type_factory), "derived_type_factory"); + m->add(chaiscript::fun(&more_derived_type_factory), "more_derived_type_factory"); m->add(chaiscript::fun(&TestBaseType::func), "func"); m->add(chaiscript::fun(&TestBaseType::val), "val"); m->add(chaiscript::fun(&TestBaseType::const_val), "const_val"); + m->add(chaiscript::fun(&TestBaseType::base_only_func), "base_only_func"); m->add(chaiscript::fun(&get_new_int), "get_new_int"); diff --git a/unittests/inheritance.chai b/unittests/inheritance.chai index 99cf7c0..34df9d9 100644 --- a/unittests/inheritance.chai +++ b/unittests/inheritance.chai @@ -25,3 +25,11 @@ assert_equal(t.derived_only_func(), 19); var d := derived_type_factory(); assert_equal(d.derived_only_func(), 19); +var t2 = TestMoreDerivedType(); +assert_equal(t2.derived_only_func(), 19); +assert_equal(t2.base_only_func(), -9); + +var md := more_derived_type_factory(); +assert_equal(md.derived_only_func(), 19); +assert_equal(md.base_only_func(), -9); +