diff --git a/.decent_ci-Linux.yaml b/.decent_ci-Linux.yaml index e8ecf732..dfb50567 100644 --- a/.decent_ci-Linux.yaml +++ b/.decent_ci-Linux.yaml @@ -19,6 +19,11 @@ compilers: version: "3.6" skip_packaging: true cmake_extra_flags: -DUSE_LIBCXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DENABLE_THREAD_SANITIZER:BOOL=ON + - name: "gcc" + version: "4.8" + build_tag: "NoThreads" + cmake_extra_flags: -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DBUILD_TESTING:BOOL=ON -DRUN_PERFORMANCE_TESTS:BOOL=ON -DMULTITHREAD_SUPPORT_ENABLED:BOOL=OFF + collect_performance_results: true - name: "gcc" version: "4.8" cmake_extra_flags: -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DBUILD_TESTING:BOOL=ON -DRUN_PERFORMANCE_TESTS:BOOL=ON @@ -29,7 +34,7 @@ compilers: cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DRUN_PERFORMANCE_TESTS:BOOL=ON collect_performance_results: true - name: cppcheck - compiler_extra_flags: --enable=all -I include --inline-suppr -Umax --suppress="*:cmake*" --suppress="*:unittests/catch.hpp" --force + compiler_extra_flags: --enable=all -I include --inline-suppr -Umax --suppress="*:unittests/catch.hpp" --force --suppress="unusedFunction:*" - name: custom_check commands: - ./contrib/check_for_tabs.rb diff --git a/CMakeLists.txt b/CMakeLists.txt index 471784c8..50b5e3e0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -102,8 +102,8 @@ set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/readme.md") set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/description.txt") set(CPACK_PACKAGE_VERSION_MAJOR 5) -set(CPACK_PACKAGE_VERSION_MINOR 7) -set(CPACK_PACKAGE_VERSION_PATCH 2) +set(CPACK_PACKAGE_VERSION_MINOR 8) +set(CPACK_PACKAGE_VERSION_PATCH 0) set(CPACK_PACKAGE_EXECUTABLES "chai;ChaiScript Eval") set(CPACK_PACKAGE_VENDOR "ChaiScript.com") @@ -178,7 +178,7 @@ else() add_definitions(-Wall -Wextra -Wshadow -Wnon-virtual-dtor -Wold-style-cast -Wcast-align -Wcast-qual -Wunused -Woverloaded-virtual -pedantic ${CPP11_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-sign-conversion -Wno-missing-prototypes -Wno-padded -Wno-missing-noreturn -Wno-exit-time-destructors) + add_definitions(-Weverything -Wno-c++98-compat-pedantic -Wno-c++98-compat -Wno-documentation -Wno-switch-enum -Wno-weak-vtables -Wno-sign-conversion -Wno-missing-prototypes -Wno-padded -Wno-missing-noreturn -Wno-exit-time-destructors -Wno-documentation-unknown-command) else() add_definitions(-Wnoexcept) endif() @@ -210,7 +210,7 @@ endif() include_directories(include) -set(Chai_INCLUDES include/chaiscript/chaiscript.hpp include/chaiscript/chaiscript_threading.hpp include/chaiscript/dispatchkit/bad_boxed_cast.hpp include/chaiscript/dispatchkit/bind_first.hpp include/chaiscript/dispatchkit/bootstrap.hpp include/chaiscript/dispatchkit/bootstrap_stl.hpp include/chaiscript/dispatchkit/boxed_cast.hpp include/chaiscript/dispatchkit/boxed_cast_helper.hpp include/chaiscript/dispatchkit/boxed_number.hpp include/chaiscript/dispatchkit/boxed_value.hpp include/chaiscript/dispatchkit/dispatchkit.hpp include/chaiscript/dispatchkit/type_conversions.hpp include/chaiscript/dispatchkit/dynamic_object.hpp include/chaiscript/dispatchkit/exception_specification.hpp include/chaiscript/dispatchkit/function_call.hpp include/chaiscript/dispatchkit/function_call_detail.hpp include/chaiscript/dispatchkit/handle_return.hpp include/chaiscript/dispatchkit/operators.hpp include/chaiscript/dispatchkit/proxy_constructors.hpp include/chaiscript/dispatchkit/proxy_functions.hpp include/chaiscript/dispatchkit/proxy_functions_detail.hpp include/chaiscript/dispatchkit/register_function.hpp include/chaiscript/dispatchkit/type_info.hpp include/chaiscript/language/chaiscript_algebraic.hpp include/chaiscript/language/chaiscript_common.hpp include/chaiscript/language/chaiscript_engine.hpp include/chaiscript/language/chaiscript_eval.hpp include/chaiscript/language/chaiscript_parser.hpp include/chaiscript/language/chaiscript_prelude.chai include/chaiscript/language/chaiscript_prelude_docs.hpp include/chaiscript/utility/utility.hpp) +set(Chai_INCLUDES include/chaiscript/chaiscript.hpp include/chaiscript/chaiscript_threading.hpp include/chaiscript/dispatchkit/bad_boxed_cast.hpp include/chaiscript/dispatchkit/bind_first.hpp include/chaiscript/dispatchkit/bootstrap.hpp include/chaiscript/dispatchkit/bootstrap_stl.hpp include/chaiscript/dispatchkit/boxed_cast.hpp include/chaiscript/dispatchkit/boxed_cast_helper.hpp include/chaiscript/dispatchkit/boxed_number.hpp include/chaiscript/dispatchkit/boxed_value.hpp include/chaiscript/dispatchkit/dispatchkit.hpp include/chaiscript/dispatchkit/type_conversions.hpp include/chaiscript/dispatchkit/dynamic_object.hpp include/chaiscript/dispatchkit/exception_specification.hpp include/chaiscript/dispatchkit/function_call.hpp include/chaiscript/dispatchkit/function_call_detail.hpp include/chaiscript/dispatchkit/handle_return.hpp include/chaiscript/dispatchkit/operators.hpp include/chaiscript/dispatchkit/proxy_constructors.hpp include/chaiscript/dispatchkit/proxy_functions.hpp include/chaiscript/dispatchkit/proxy_functions_detail.hpp include/chaiscript/dispatchkit/register_function.hpp include/chaiscript/dispatchkit/type_info.hpp include/chaiscript/language/chaiscript_algebraic.hpp include/chaiscript/language/chaiscript_common.hpp include/chaiscript/language/chaiscript_engine.hpp include/chaiscript/language/chaiscript_eval.hpp include/chaiscript/language/chaiscript_parser.hpp include/chaiscript/language/chaiscript_prelude.chai include/chaiscript/language/chaiscript_prelude_docs.hpp include/chaiscript/utility/utility.hpp include/chaiscript/utility/json.hpp include/chaiscript/utility/json_wrap.hpp) set_source_files_properties(${Chai_INCLUDES} PROPERTIES HEADER_FILE_ONLY TRUE) @@ -397,6 +397,14 @@ if(BUILD_TESTING) add_test(NAME performance.${filename} COMMAND ${VALGRIND} --tool=callgrind --callgrind-out-file=callgrind.performance.${filename} $ ${CMAKE_CURRENT_SOURCE_DIR}/performance_tests/${filename}) list(APPEND TESTS performance.${filename}) endforeach() + + add_executable(profile_cpp_calls_2 performance_tests/profile_cpp_calls_2.cpp) + target_link_libraries(profile_cpp_calls_2 ${LIBS}) + add_test(NAME performance.profile_cpp_calls_2 COMMAND ${VALGRIND} --tool=callgrind --callgrind-out-file=callgrind.performance.profile_cpp_calls_2 $) + + add_executable(profile_fun_wrappers performance_tests/profile_fun_wrappers.cpp) + target_link_libraries(profile_fun_wrappers ${LIBS}) + add_test(NAME performance.profile_fun_wrappers COMMAND ${VALGRIND} --tool=callgrind --callgrind-out-file=callgrind.performance.profile_fun_wrappers $) endif() set_property(TEST ${TESTS} diff --git a/LICENSE b/LICENSE index 48f52923..105662d9 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright 2009-2015 Jason Turner +Copyright 2009-2016 Jason Turner Copyright 2009-2012 Jonathan Turner. All Rights Reserved. diff --git a/appveyor.yml b/appveyor.yml new file mode 100644 index 00000000..c402efee --- /dev/null +++ b/appveyor.yml @@ -0,0 +1,16 @@ +version: 5.7.2.{build} +os: Visual Studio 2015 +environment: + matrix: + - {} +build_script: +- cmd: >- + mkdir build + + cd build + + cmake c:\Projects\chaiscript -G "Visual Studio 14" + + cmake --build . --config Debug +test_script: +- cmd: ctest -C Debug diff --git a/cheatsheet.md b/cheatsheet.md index eca67f0e..ce8e04a0 100644 --- a/cheatsheet.md +++ b/cheatsheet.md @@ -90,6 +90,13 @@ A helper function exists for strongly typed and ChaiScript `Vector` function con chai.add(chaiscript::vector_conversion>()); ``` +A helper function also exists for strongly typed and ChaiScript `Map` function conversion definition: + +``` +chai.add(chaiscript::map_conversion>()); +``` + + This allows you to pass a ChaiScript function to a function requiring `std::vector` ## Adding Objects @@ -100,8 +107,9 @@ chai.add(chaiscript::var(std::ref(somevar), "somevar"); // by reference, shared auto shareddouble = std::make_shared(4.3); chai.add(chaiscript::var(shareddouble), "shareddouble"); // by shared_ptr, shared between c++ and chai chai.add(chaiscript::const_var(somevar), "somevar"); // copied in and made const -chai.add_global_const(chaiscript::const_var(somevar), "somevar"); // global const. Throws if value is non-const -chai.add_global(chaiscript::var(somevar), "somevar"); // global non-const +chai.add_global_const(chaiscript::const_var(somevar), "somevar"); // global const. Throws if value is non-const, throws if object exists +chai.add_global(chaiscript::var(somevar), "somevar"); // global non-const, throws if object exists +chai.set_global(chaiscript::var(somevar), "somevar"); // global non-const, overwrites existing object ``` # Using STL ChaiScript recognize many types from STL, but you have to add specific instantiation yourself. @@ -221,11 +229,13 @@ var k = 5; // initialized to 5 (integer) var l := k; // reference to k auto &m = k; // reference to k -GLOBAL g = 5; // creates a global variable. If global already exists, it is not re-added -GLOBAL g = 2; // global 'g' now equals 2 +global g = 5; // creates a global variable. If global already exists, it is not re-added +global g = 2; // global 'g' now equals 2 -GLOBAL g2; -if (g2.is_var_undef()) { g2 = 4; } // only initialize g2 once, if GLOBAL decl hit more than once +global g2; +if (g2.is_var_undef()) { g2 = 4; } // only initialize g2 once, if global decl hit more than once + +GLOBAL g3; // all upper case version also accepted ``` ## Built in Types diff --git a/include/chaiscript/chaiscript.hpp b/include/chaiscript/chaiscript.hpp index 1b37e9b8..79ef8cf4 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-2015, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_HPP_ diff --git a/include/chaiscript/chaiscript_defines.hpp b/include/chaiscript/chaiscript_defines.hpp index c2ba4ae6..8d250ebf 100644 --- a/include/chaiscript/chaiscript_defines.hpp +++ b/include/chaiscript/chaiscript_defines.hpp @@ -1,18 +1,22 @@ // This file is distributed under the BSD License. // See "license.txt" for details. // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) -// Copyright 2009-2015, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_DEFINES_HPP_ #define CHAISCRIPT_DEFINES_HPP_ #ifdef _MSC_VER +#define CHAISCRIPT_STRINGIZE(x) "" #x +#define CHAISCRIPT_COMPILER_VERSION CHAISCRIPT_STRINGIZE(_MSC_FULL_VER) #define CHAISCRIPT_MSVC _MSC_VER #define CHAISCRIPT_HAS_DECLSPEC #if _MSC_VER <= 1800 #define CHAISCRIPT_MSVC_12 #endif +#else +#define CHAISCRIPT_COMPILER_VERSION __VERSION__ #endif #ifndef CHAISCRIPT_MSVC_12 @@ -29,7 +33,25 @@ #define CHAISCRIPT_WINDOWS #endif -#if (defined(__GNUC__) && __GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) || (defined(__llvm__) && !defined(CHAISCRIPT_LIBCPP)) +#if defined(_WIN32) +#if defined(__llvm__) +#define CHAISCRIPT_COMPILER_NAME "clang(windows)" +#elif defined(__GNUC__) +#define CHAISCRIPT_COMPILER_NAME "gcc(mingw)" +#else +#define CHAISCRIPT_COMPILER_NAME "msvc" +#endif +#else +#if defined(__llvm__) +#define CHAISCRIPT_COMPILER_NAME "clang" +#elif defined(__GNUC__) +#define CHAISCRIPT_COMPILER_NAME "gcc" +#else +#define CHAISCRIPT_COMPILER_NAME "unknown" +#endif +#endif + +#if (defined(CHAISCRIPT_MSVC) && !defined(CHAISCRIPT_MSVC_12)) || (defined(__GNUC__) && __GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) || (defined(__llvm__) && !defined(CHAISCRIPT_LIBCPP)) /// Currently only g++>=4.8 supports this natively /// \todo Make this support other compilers when possible #define CHAISCRIPT_HAS_THREAD_LOCAL @@ -64,12 +86,22 @@ #define CHAISCRIPT_CONSTEXPR constexpr #endif +#ifdef _DEBUG +#define CHAISCRIPT_DEBUG true +#else +#define CHAISCRIPT_DEBUG false +#endif + #include namespace chaiscript { static const int version_major = 5; - static const int version_minor = 7; - static const int version_patch = 2; + static const int version_minor = 8; + static const int version_patch = 0; + + static const char *compiler_version = CHAISCRIPT_COMPILER_VERSION; + static const char *compiler_name = CHAISCRIPT_COMPILER_NAME; + static const bool debug_build = CHAISCRIPT_DEBUG; template inline std::shared_ptr make_shared(Arg && ... arg) diff --git a/include/chaiscript/chaiscript_threading.hpp b/include/chaiscript/chaiscript_threading.hpp index 09fc617d..2a0e63c3 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-2015, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_THREADING_HPP_ @@ -45,14 +45,14 @@ namespace chaiscript class unique_lock : public std::unique_lock { public: - unique_lock(T &t) : std::unique_lock(t) {} + explicit unique_lock(T &t) : std::unique_lock(t) {} }; template class shared_lock : public std::unique_lock { public: - shared_lock(T &t) : std::unique_lock(t) {} + explicit shared_lock(T &t) : std::unique_lock(t) {} void unlock() {} }; @@ -60,7 +60,7 @@ namespace chaiscript class lock_guard : public std::lock_guard { public: - lock_guard(T &t) : std::lock_guard(t) {} + explicit lock_guard(T &t) : std::lock_guard(t) {} }; class shared_mutex : public std::mutex { }; @@ -77,7 +77,7 @@ namespace chaiscript { public: - Thread_Storage(void *t_key) + explicit Thread_Storage(void *t_key) : m_key(t_key) { } @@ -129,7 +129,7 @@ namespace chaiscript { public: - Thread_Storage(void *) + explicit Thread_Storage(void *) { } @@ -160,13 +160,14 @@ namespace chaiscript { unique_lock lock(m_mutex); - auto itr = m_instances.find(std::this_thread::get_id()); + 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(std::this_thread::get_id(), new_instance)); + m_instances.insert(std::make_pair(id, new_instance)); return new_instance; } @@ -182,7 +183,7 @@ namespace chaiscript class unique_lock { public: - unique_lock(T &) {} + explicit unique_lock(T &) {} void lock() {} void unlock() {} }; @@ -191,7 +192,7 @@ namespace chaiscript class shared_lock { public: - shared_lock(T &) {} + explicit shared_lock(T &) {} void lock() {} void unlock() {} }; @@ -200,7 +201,7 @@ namespace chaiscript class lock_guard { public: - lock_guard(T &) {} + explicit lock_guard(T &) {} }; class shared_mutex { }; @@ -212,7 +213,7 @@ namespace chaiscript class Thread_Storage { public: - Thread_Storage(void *) + explicit Thread_Storage(void *) { } diff --git a/include/chaiscript/dispatchkit/any.hpp b/include/chaiscript/dispatchkit/any.hpp index 8a624b1e..e86ba0ed 100644 --- a/include/chaiscript/dispatchkit/any.hpp +++ b/include/chaiscript/dispatchkit/any.hpp @@ -46,7 +46,7 @@ namespace chaiscript { private: struct Data { - Data(const std::type_info &t_type) + explicit Data(const std::type_info &t_type) : m_type(t_type) { } diff --git a/include/chaiscript/dispatchkit/bad_boxed_cast.hpp b/include/chaiscript/dispatchkit/bad_boxed_cast.hpp index c2be40fc..0716749d 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-2015, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_BAD_BOXED_CAST_HPP_ @@ -40,7 +40,7 @@ namespace chaiscript { } - bad_boxed_cast(std::string t_what) CHAISCRIPT_NOEXCEPT + explicit bad_boxed_cast(std::string t_what) CHAISCRIPT_NOEXCEPT : to(nullptr), m_what(std::move(t_what)) { } diff --git a/include/chaiscript/dispatchkit/bind_first.hpp b/include/chaiscript/dispatchkit/bind_first.hpp index 5cd61dac..fcba5348 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-2015, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2016, 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 7e3a3015..ef9f032c 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-2015, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2016, 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 8b559811..8c225c3b 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-2015, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2016, 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 1ddaacc1..44450a0f 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-2015, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_BOXED_CAST_HPP_ @@ -69,9 +69,9 @@ namespace chaiscript /// assert(i == 5); /// \endcode template - typename detail::Cast_Helper::Result_Type boxed_cast(const Boxed_Value &bv, const Type_Conversions *t_conversions = nullptr) + typename detail::Cast_Helper::Result_Type boxed_cast(const Boxed_Value &bv, const Type_Conversions_State *t_conversions = nullptr) { - if (!t_conversions || bv.get_type_info().bare_equal(user_type()) || (t_conversions && !t_conversions->convertable_type())) { + if (!t_conversions || bv.get_type_info().bare_equal(user_type()) || (t_conversions && !(*t_conversions)->convertable_type())) { try { return detail::Cast_Helper::cast(bv, t_conversions); } catch (const chaiscript::detail::exception::bad_any_cast &) { @@ -79,18 +79,18 @@ namespace chaiscript } - if (t_conversions && t_conversions->convertable_type()) + if (t_conversions && (*t_conversions)->convertable_type()) { try { // std::cout << "trying an up conversion " << typeid(Type).name() << '\n'; // 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_type_conversion(bv), t_conversions); + return detail::Cast_Helper::cast((*t_conversions)->boxed_type_conversion(t_conversions->saves(), bv), t_conversions); } catch (...) { try { // std::cout << "trying a down conversion " << typeid(Type).name() << '\n'; // try going the other way - down the inheritance graph - return detail::Cast_Helper::cast(t_conversions->boxed_type_down_conversion(bv), t_conversions); + return detail::Cast_Helper::cast((*t_conversions)->boxed_type_down_conversion(t_conversions->saves(), bv), t_conversions); } catch (const chaiscript::detail::exception::bad_any_cast &) { throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type)); } diff --git a/include/chaiscript/dispatchkit/boxed_cast_helper.hpp b/include/chaiscript/dispatchkit/boxed_cast_helper.hpp index 2e087776..505b1e1f 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-2015, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_BOXED_CAST_HELPER_HPP_ @@ -16,7 +16,7 @@ namespace chaiscript { - class Type_Conversions; + class Type_Conversions_State; namespace detail { @@ -35,7 +35,7 @@ namespace chaiscript { typedef typename std::add_const::type Result_Type; - static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *) + static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *) { if (ob.get_type_info().bare_equal_type_info(typeid(Result))) { @@ -58,7 +58,7 @@ namespace chaiscript struct Cast_Helper_Inner { typedef const Result * Result_Type; - static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *) + static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *) { if (ob.get_type_info().bare_equal_type_info(typeid(Result))) { @@ -74,7 +74,7 @@ namespace chaiscript struct Cast_Helper_Inner { typedef Result * Result_Type; - static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *) + static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *) { if (!ob.get_type_info().is_const() && ob.get_type_info() == typeid(Result)) { @@ -102,7 +102,7 @@ namespace chaiscript { typedef const Result& Result_Type; - static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *) + static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *) { if (ob.get_type_info().bare_equal_type_info(typeid(Result))) { @@ -122,7 +122,7 @@ namespace chaiscript { typedef Result& Result_Type; - static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *) + static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *) { if (!ob.get_type_info().is_const() && ob.get_type_info().bare_equal_type_info(typeid(Result))) { @@ -139,7 +139,7 @@ namespace chaiscript { typedef std::shared_ptr Result_Type; - static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *) + static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *) { return ob.get().cast >(); } @@ -151,7 +151,7 @@ namespace chaiscript { typedef std::shared_ptr Result_Type; - static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *) + static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *) { if (!ob.get_type_info().is_const()) { @@ -191,7 +191,7 @@ namespace chaiscript { typedef Boxed_Value Result_Type; - static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *) + static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *) { return ob; } @@ -203,7 +203,7 @@ namespace chaiscript { typedef std::reference_wrapper Result_Type; - static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *) + static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *) { return std::ref(const_cast(ob)); } @@ -259,7 +259,7 @@ namespace chaiscript { typedef typename Cast_Helper_Inner::Result_Type Result_Type; - static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *t_conversions) + static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions) { return Cast_Helper_Inner::cast(ob, t_conversions); } diff --git a/include/chaiscript/dispatchkit/boxed_number.hpp b/include/chaiscript/dispatchkit/boxed_number.hpp index dd5bf8c9..604d0d03 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-2015, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_BOXED_NUMERIC_HPP_ @@ -1011,7 +1011,7 @@ namespace chaiscript { typedef Boxed_Number Result_Type; - static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *) + static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *) { return Boxed_Number(ob); } diff --git a/include/chaiscript/dispatchkit/boxed_value.hpp b/include/chaiscript/dispatchkit/boxed_value.hpp index 1c2ebe72..5a49119f 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-2015, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2016, 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 cc1b2e70..765e6d67 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-2015, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2016, 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 cd97f0e8..09b90f7c 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-2015, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_DISPATCHKIT_HPP_ @@ -314,7 +314,7 @@ namespace chaiscript return arity; } - virtual bool call_match(const std::vector &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE + virtual bool call_match(const std::vector &vals, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE { return std::any_of(m_funcs.cbegin(), m_funcs.cend(), [&vals, &t_conversions](const Proxy_Function &f){ return f->call_match(vals, t_conversions); }); @@ -326,7 +326,7 @@ namespace chaiscript } protected: - virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE + virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE { return dispatch::dispatch(m_funcs, params, t_conversions); } @@ -442,7 +442,8 @@ namespace chaiscript template typename detail::Cast_Helper::Result_Type boxed_cast(const Boxed_Value &bv) const { - return chaiscript::boxed_cast(bv, &m_conversions); + Type_Conversions_State state(m_conversions, m_conversions.conversion_saves()); + return chaiscript::boxed_cast(bv, &state); } /// Add a new conversion for upcasting to a base class @@ -561,6 +562,21 @@ namespace chaiscript } } + /// Updates an existing global shared object or adds a new global shared object if not found + void set_global(const Boxed_Value &obj, const std::string &name) + { + validate_object_name(name); + + chaiscript::detail::threading::unique_lock l(m_mutex); + + const auto itr = m_state.m_global_objects.find(name); + if (itr != m_state.m_global_objects.end()) + { + itr->second.assign(obj); + } else { + m_state.m_global_objects.insert(std::make_pair(name, obj)); + } + } /// Adds a new scope to the stack void new_scope() @@ -596,13 +612,13 @@ namespace chaiscript /// Pushes a new stack on to the list of stacks - void new_stack(Stack_Holder &t_holder) + static void new_stack(Stack_Holder &t_holder) { // add a new Stack with 1 element t_holder.stacks.emplace_back(1); } - void pop_stack(Stack_Holder &t_holder) + static void pop_stack(Stack_Holder &t_holder) { t_holder.stacks.pop_back(); } @@ -896,7 +912,7 @@ namespace chaiscript } bool is_attribute_call(const std::vector &t_funs, const std::vector &t_params, - bool t_has_params) const + bool t_has_params, const Type_Conversions_State &t_conversions) const { if (!t_has_params || t_params.empty()) { return false; @@ -904,7 +920,7 @@ namespace chaiscript for (const auto &fun : t_funs) { if (fun->is_attribute_function()) { - if (fun->compare_first_type(t_params[0], m_conversions)) { + if (fun->compare_first_type(t_params[0], t_conversions)) { return true; } } @@ -919,14 +935,15 @@ namespace chaiscript #pragma warning(push) #pragma warning(disable : 4715) #endif - Boxed_Value call_member(const std::string &t_name, std::atomic_uint_fast32_t &t_loc, const std::vector ¶ms, bool t_has_params) + Boxed_Value call_member(const std::string &t_name, std::atomic_uint_fast32_t &t_loc, const std::vector ¶ms, bool t_has_params, + const Type_Conversions_State &t_conversions) { uint_fast32_t loc = t_loc.load(std::memory_order_relaxed); const auto funs = get_function(t_name, loc); if (funs.first != loc) t_loc.store(uint_fast32_t(funs.first), std::memory_order_relaxed); const auto do_attribute_call = - [this](int l_num_params, const std::vector &l_params, const std::vector &l_funs, const Type_Conversions &l_conversions)->Boxed_Value + [this](int l_num_params, const std::vector &l_params, const std::vector &l_funs, const Type_Conversions_State &l_conversions)->Boxed_Value { std::vector attr_params{l_params.begin(), l_params.begin() + l_num_params}; Boxed_Value bv = dispatch::dispatch(l_funs, attr_params, l_conversions); @@ -959,14 +976,14 @@ namespace chaiscript } }; - if (is_attribute_call(*funs.second, params, t_has_params)) { - return do_attribute_call(1, params, *funs.second, m_conversions); + if (is_attribute_call(*funs.second, params, t_has_params, t_conversions)) { + return do_attribute_call(1, params, *funs.second, t_conversions); } else { std::exception_ptr except; if (!funs.second->empty()) { try { - return dispatch::dispatch(*funs.second, params, m_conversions); + return dispatch::dispatch(*funs.second, params, t_conversions); } catch(chaiscript::exception::dispatch_error&) { except = std::current_exception(); } @@ -982,7 +999,7 @@ namespace chaiscript for (const auto &f : *method_missing_funs) { - if(f->compare_first_type(params[0], m_conversions)) { + if(f->compare_first_type(params[0], t_conversions)) { fs.push_back(f); } } @@ -1006,9 +1023,9 @@ namespace chaiscript if (is_no_param) { std::vector tmp_params(params); tmp_params.insert(tmp_params.begin() + 1, var(t_name)); - return do_attribute_call(2, tmp_params, functions, m_conversions); + return do_attribute_call(2, tmp_params, functions, t_conversions); } else { - return dispatch::dispatch(functions, {params[0], var(t_name), var(std::vector(params.begin()+1, params.end()))}, m_conversions); + return dispatch::dispatch(functions, {params[0], var(t_name), var(std::vector(params.begin()+1, params.end()))}, t_conversions); } } catch (const dispatch::option_explicit_set &e) { throw chaiscript::exception::dispatch_error(params, std::vector(funs.second->begin(), funs.second->end()), @@ -1031,12 +1048,13 @@ namespace chaiscript - Boxed_Value call_function(const std::string &t_name, std::atomic_uint_fast32_t &t_loc, const std::vector ¶ms) const + Boxed_Value call_function(const std::string &t_name, std::atomic_uint_fast32_t &t_loc, const std::vector ¶ms, + const Type_Conversions_State &t_conversions) const { uint_fast32_t loc = t_loc.load(std::memory_order_relaxed); const auto funs = get_function(t_name, loc); if (funs.first != loc) t_loc.store(uint_fast32_t(funs.first), std::memory_order_relaxed); - return dispatch::dispatch(*funs.second, params, m_conversions); + return dispatch::dispatch(*funs.second, params, t_conversions); } @@ -1090,7 +1108,7 @@ namespace chaiscript /// Returns true if a call can be made that consists of the first parameter /// (the function) with the remaining parameters as its arguments. - Boxed_Value call_exists(const std::vector ¶ms) + Boxed_Value call_exists(const std::vector ¶ms) const { if (params.empty()) { @@ -1098,8 +1116,9 @@ namespace chaiscript } const Const_Proxy_Function &f = this->boxed_cast(params[0]); + const Type_Conversions_State convs(m_conversions, m_conversions.conversion_saves()); - return Boxed_Value(f->call_match(std::vector(params.begin() + 1, params.end()), m_conversions)); + return Boxed_Value(f->call_match(std::vector(params.begin() + 1, params.end()), convs)); } /// Dump all system info to stdout @@ -1168,12 +1187,12 @@ namespace chaiscript m_state = t_state; } - void save_function_params(Stack_Holder &t_s, std::initializer_list t_params) + static void save_function_params(Stack_Holder &t_s, std::initializer_list t_params) { t_s.call_params.back().insert(t_s.call_params.back().begin(), std::move(t_params)); } - void save_function_params(Stack_Holder &t_s, std::vector &&t_params) + static void save_function_params(Stack_Holder &t_s, std::vector &&t_params) { for (auto &¶m : t_params) { @@ -1181,7 +1200,7 @@ namespace chaiscript } } - void save_function_params(Stack_Holder &t_s, const std::vector &t_params) + static void save_function_params(Stack_Holder &t_s, const std::vector &t_params) { t_s.call_params.back().insert(t_s.call_params.back().begin(), t_params.begin(), t_params.end()); } @@ -1201,19 +1220,19 @@ namespace chaiscript save_function_params(*m_stack_holder, t_params); } - void new_function_call(Stack_Holder &t_s) + void new_function_call(Stack_Holder &t_s, Type_Conversions::Conversion_Saves &t_saves) { if (t_s.call_depth == 0) { - m_conversions.enable_conversion_saves(true); + m_conversions.enable_conversion_saves(t_saves, true); } ++t_s.call_depth; - save_function_params(m_conversions.take_saves()); + save_function_params(m_conversions.take_saves(t_saves)); } - void pop_function_call(Stack_Holder &t_s) + void pop_function_call(Stack_Holder &t_s, Type_Conversions::Conversion_Saves &t_saves) { --t_s.call_depth; @@ -1222,18 +1241,18 @@ namespace chaiscript if (t_s.call_depth == 0) { t_s.call_params.back().clear(); - m_conversions.enable_conversion_saves(false); + m_conversions.enable_conversion_saves(t_saves, false); } } void new_function_call() { - new_function_call(*m_stack_holder); + new_function_call(*m_stack_holder, m_conversions.conversion_saves()); } void pop_function_call() { - pop_function_call(*m_stack_holder); + pop_function_call(*m_stack_holder, m_conversions.conversion_saves()); } Stack_Holder &get_stack_holder() @@ -1248,7 +1267,7 @@ namespace chaiscript return m_stack_holder->stacks.back(); } - StackData &get_stack_data(Stack_Holder &t_holder) + static StackData &get_stack_data(Stack_Holder &t_holder) { return t_holder.stacks.back(); } @@ -1572,7 +1591,8 @@ namespace chaiscript public: Dispatch_State(Dispatch_Engine &t_engine) : m_engine(t_engine), - m_stack_holder(t_engine.get_stack_holder()) + m_stack_holder(t_engine.get_stack_holder()), + m_conversions(t_engine.conversions(), t_engine.conversions().conversion_saves()) { } @@ -1588,6 +1608,14 @@ namespace chaiscript return m_stack_holder.get(); } + const Type_Conversions_State &conversions() const { + return m_conversions; + } + + Type_Conversions::Conversion_Saves &conversion_saves() const { + return m_conversions.saves(); + } + void add_object(const std::string &t_name, Boxed_Value obj) const { m_engine.get().add_object(t_name, std::move(obj), m_stack_holder.get()); } @@ -1595,6 +1623,7 @@ namespace chaiscript private: std::reference_wrapper m_engine; std::reference_wrapper m_stack_holder; + Type_Conversions_State m_conversions; }; } } diff --git a/include/chaiscript/dispatchkit/dynamic_object.hpp b/include/chaiscript/dispatchkit/dynamic_object.hpp index 1e79eeab..05fc0697 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-2015, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2016, 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 710c927f..1b66d34b 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-2015, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_DYNAMIC_OBJECT_DETAIL_HPP_ @@ -96,7 +96,7 @@ namespace chaiscript virtual bool is_attribute_function() const CHAISCRIPT_OVERRIDE { return m_is_attribute; } - virtual bool call_match(const std::vector &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE + virtual bool call_match(const std::vector &vals, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE { if (dynamic_object_typename_match(vals, m_type_name, m_ti, t_conversions)) { @@ -118,7 +118,7 @@ namespace chaiscript protected: - virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE + virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE { if (dynamic_object_typename_match(params, m_type_name, m_ti, t_conversions)) { @@ -128,7 +128,7 @@ namespace chaiscript } } - virtual bool compare_first_type(const Boxed_Value &bv, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE + virtual bool compare_first_type(const Boxed_Value &bv, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE { return dynamic_object_typename_match(bv, m_type_name, m_ti, t_conversions); } @@ -146,7 +146,7 @@ namespace chaiscript } bool dynamic_object_typename_match(const Boxed_Value &bv, const std::string &name, - const std::unique_ptr &ti, const Type_Conversions &t_conversions) const + const std::unique_ptr &ti, const Type_Conversions_State &t_conversions) const { if (bv.get_type_info().bare_equal(m_doti)) { @@ -168,7 +168,7 @@ namespace chaiscript } bool dynamic_object_typename_match(const std::vector &bvs, const std::string &name, - const std::unique_ptr &ti, const Type_Conversions &t_conversions) const + const std::unique_ptr &ti, const Type_Conversions_State &t_conversions) const { if (bvs.size() > 0) { @@ -240,7 +240,7 @@ namespace chaiscript return dc && dc->m_type_name == m_type_name && (*dc->m_func) == (*m_func); } - virtual bool call_match(const std::vector &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE + virtual bool call_match(const std::vector &vals, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE { std::vector new_vals{Boxed_Value(Dynamic_Object(m_type_name))}; new_vals.insert(new_vals.end(), vals.begin(), vals.end()); @@ -254,7 +254,7 @@ namespace chaiscript } protected: - virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE + virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE { auto bv = Boxed_Value(Dynamic_Object(m_type_name), true); std::vector new_params{bv}; diff --git a/include/chaiscript/dispatchkit/exception_specification.hpp b/include/chaiscript/dispatchkit/exception_specification.hpp index 54f19c4d..55398f7d 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-2015, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_EXCEPTION_SPECIFICATION_HPP_ @@ -32,7 +32,7 @@ namespace chaiscript protected: template - void throw_type(const Boxed_Value &bv, const Dispatch_Engine &t_engine) + static void throw_type(const Boxed_Value &bv, const Dispatch_Engine &t_engine) { try { T t = t_engine.boxed_cast(bv); throw t; } catch (const chaiscript::exception::bad_boxed_cast &) {} } diff --git a/include/chaiscript/dispatchkit/function_call.hpp b/include/chaiscript/dispatchkit/function_call.hpp index c5b950a1..ea0a61e2 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-2015, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_FUNCTION_CALL_HPP_ @@ -18,7 +18,7 @@ namespace chaiscript { class Boxed_Value; -class Type_Conversions; +class Type_Conversions_State; namespace detail { template struct Cast_Helper; } // namespace detail @@ -36,7 +36,7 @@ namespace chaiscript /// \param[in] funcs the set of functions to dispatch on. template std::function - functor(const std::vector &funcs, const Type_Conversions *t_conversions) + functor(const std::vector &funcs, const Type_Conversions_State *t_conversions) { const bool has_arity_match = std::any_of(funcs.begin(), funcs.end(), [](const Const_Proxy_Function &f) { @@ -64,7 +64,7 @@ namespace chaiscript /// \param[in] func A function to execute. template std::function - functor(Const_Proxy_Function func, const Type_Conversions *t_conversions) + functor(Const_Proxy_Function func, const Type_Conversions_State *t_conversions) { return functor(std::vector({std::move(func)}), t_conversions); } @@ -73,7 +73,7 @@ namespace chaiscript /// and creating a typesafe C++ function caller from it. template std::function - functor(const Boxed_Value &bv, const Type_Conversions *t_conversions) + functor(const Boxed_Value &bv, const Type_Conversions_State *t_conversions) { return functor(boxed_cast(bv, t_conversions), t_conversions); } @@ -86,7 +86,7 @@ namespace chaiscript { typedef std::function Result_Type; - static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *t_conversions) + static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions) { if (ob.get_type_info().bare_equal(user_type())) { @@ -103,7 +103,7 @@ namespace chaiscript { typedef std::function Result_Type; - static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *t_conversions) + static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions) { if (ob.get_type_info().bare_equal(user_type())) { @@ -120,7 +120,7 @@ namespace chaiscript { typedef std::function Result_Type; - static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *t_conversions) + static Result_Type cast(const Boxed_Value &ob, const Type_Conversions_State *t_conversions) { if (ob.get_type_info().bare_equal(user_type())) { diff --git a/include/chaiscript/dispatchkit/function_call_detail.hpp b/include/chaiscript/dispatchkit/function_call_detail.hpp index 4054b591..8ed6115c 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-2015, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_FUNCTION_CALL_DETAIL_HPP_ @@ -31,9 +31,15 @@ namespace chaiscript struct Function_Caller_Ret { static Ret call(const std::vector &t_funcs, - const std::vector ¶ms, const Type_Conversions *t_conversions) + const std::vector ¶ms, const Type_Conversions_State *t_conversions) { - return boxed_cast(dispatch::dispatch(t_funcs, params, t_conversions?*t_conversions:Type_Conversions()), t_conversions); + if (t_conversions) { + return boxed_cast(dispatch::dispatch(t_funcs, params, *t_conversions), t_conversions); + } else { + Type_Conversions conv; + Type_Conversions_State state(conv, conv.conversion_saves()); + return boxed_cast(dispatch::dispatch(t_funcs, params, state), t_conversions); + } } }; @@ -44,9 +50,15 @@ namespace chaiscript struct Function_Caller_Ret { static Ret call(const std::vector &t_funcs, - const std::vector ¶ms, const Type_Conversions *t_conversions) + const std::vector ¶ms, const Type_Conversions_State *t_conversions) { - return Boxed_Number(dispatch::dispatch(t_funcs, params, t_conversions?*t_conversions:Type_Conversions())).get_as(); + if (t_conversions) { + return Boxed_Number(dispatch::dispatch(t_funcs, params, *t_conversions)).get_as(); + } else { + Type_Conversions conv; + Type_Conversions_State state(conv, conv.conversion_saves()); + return Boxed_Number(dispatch::dispatch(t_funcs, params, state)).get_as(); + } } }; @@ -58,9 +70,15 @@ namespace chaiscript struct Function_Caller_Ret { static void call(const std::vector &t_funcs, - const std::vector ¶ms, const Type_Conversions *t_conversions) + const std::vector ¶ms, const Type_Conversions_State *t_conversions) { - dispatch::dispatch(t_funcs, params, t_conversions?*t_conversions:Type_Conversions()); + if (t_conversions) { + dispatch::dispatch(t_funcs, params, *t_conversions); + } else { + Type_Conversions conv; + Type_Conversions_State state(conv, conv.conversion_saves()); + dispatch::dispatch(t_funcs, params, state); + } } }; @@ -79,11 +97,18 @@ namespace chaiscript template Ret operator()(P&& ... param) { - return Function_Caller_Ret::value && !std::is_same::value>::call(m_funcs, { - box

(std::forward

(param))... - }, m_conversions - - ); + if (m_conversions) { + Type_Conversions_State state(*m_conversions, m_conversions->conversion_saves()); + return Function_Caller_Ret::value && !std::is_same::value>::call(m_funcs, { + box

(std::forward

(param))... + }, &state + ); + } else { + return Function_Caller_Ret::value && !std::is_same::value>::call(m_funcs, { + box

(std::forward

(param))... + }, nullptr + ); + } } @@ -114,7 +139,7 @@ namespace chaiscript /// \todo what happens if t_conversions is deleted out from under us?! template - std::function build_function_caller_helper(Ret (Params...), const std::vector &funcs, const Type_Conversions *t_conversions) + std::function build_function_caller_helper(Ret (Params...), const std::vector &funcs, const Type_Conversions_State *t_conversions) { /* if (funcs.size() == 1) @@ -132,7 +157,7 @@ namespace chaiscript } */ - return std::function(Build_Function_Caller_Helper(funcs, t_conversions)); + return std::function(Build_Function_Caller_Helper(funcs, t_conversions?t_conversions->get():nullptr)); } } } diff --git a/include/chaiscript/dispatchkit/handle_return.hpp b/include/chaiscript/dispatchkit/handle_return.hpp index e3a82545..2650e3b7 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-2015, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2016, 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 a04cba43..2d4401ee 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-2015, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2016, 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 063c5579..a5ad41ec 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-2015, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2016, 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 b8464ed4..078486f0 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-2015, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com @@ -43,7 +43,7 @@ namespace chaiscript namespace dispatch { template - std::function functor(std::shared_ptr func, const Type_Conversions *t_conversions); + std::function functor(std::shared_ptr func, const Type_Conversions_State *t_conversions); class Param_Types { @@ -91,7 +91,7 @@ namespace chaiscript return m_types == t_rhs.m_types; } - bool match(const std::vector &vals, const Type_Conversions &t_conversions) const + bool match(const std::vector &vals, const Type_Conversions_State &t_conversions) const { if (!m_has_types) return true; if (vals.size() != m_types.size()) return false; @@ -166,7 +166,7 @@ namespace chaiscript public: virtual ~Proxy_Function_Base() {} - Boxed_Value operator()(const std::vector ¶ms, const chaiscript::Type_Conversions &t_conversions) const + Boxed_Value operator()(const std::vector ¶ms, const chaiscript::Type_Conversions_State &t_conversions) const { if (m_arity < 0 || size_t(m_arity) == params.size()) { return do_call(params, t_conversions); @@ -182,7 +182,7 @@ namespace chaiscript const std::vector &get_param_types() const { return m_types; } virtual bool operator==(const Proxy_Function_Base &) const = 0; - virtual bool call_match(const std::vector &vals, const Type_Conversions &t_conversions) const = 0; + virtual bool call_match(const std::vector &vals, const Type_Conversions_State &t_conversions) const = 0; virtual bool is_attribute_function() const { return false; } @@ -198,7 +198,7 @@ namespace chaiscript //! Return true if the function is a possible match //! to the passed in values - bool filter(const std::vector &vals, const Type_Conversions &t_conversions) const + bool filter(const std::vector &vals, const Type_Conversions_State &t_conversions) const { if (m_arity < 0) { @@ -225,7 +225,7 @@ namespace chaiscript virtual std::string annotation() const = 0; - static bool compare_type_to_param(const Type_Info &ti, const Boxed_Value &bv, const Type_Conversions &t_conversions) + static bool compare_type_to_param(const Type_Info &ti, const Boxed_Value &bv, const Type_Conversions_State &t_conversions) { if (ti.is_undef() || ti.bare_equal(user_type()) @@ -233,7 +233,7 @@ namespace chaiscript && ( (ti.bare_equal(user_type()) && bv.get_type_info().is_arithmetic()) || ti.bare_equal(bv.get_type_info()) || bv.get_type_info().bare_equal(user_type >()) - || t_conversions.converts(ti, bv.get_type_info()) + || t_conversions->converts(ti, bv.get_type_info()) ) ) ) @@ -244,13 +244,13 @@ namespace chaiscript } } - virtual bool compare_first_type(const Boxed_Value &bv, const Type_Conversions &t_conversions) const + virtual bool compare_first_type(const Boxed_Value &bv, const Type_Conversions_State &t_conversions) const { return compare_type_to_param(m_types[1], bv, t_conversions); } protected: - virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions &t_conversions) const = 0; + virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const = 0; Proxy_Function_Base(std::vector t_types, int t_arity) : m_types(std::move(t_types)), m_arity(t_arity), m_has_arithmetic_param(false) @@ -267,7 +267,7 @@ namespace chaiscript } - static bool compare_types(const std::vector &tis, const std::vector &bvs, const Type_Conversions &t_conversions) + static bool compare_types(const std::vector &tis, const std::vector &bvs, const Type_Conversions_State &t_conversions) { if (tis.size() - 1 != bvs.size()) { @@ -353,7 +353,7 @@ namespace chaiscript && this->m_param_types == prhs->m_param_types); } - virtual bool call_match(const std::vector &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE + virtual bool call_match(const std::vector &vals, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE { return (m_arity < 0 || (vals.size() == size_t(m_arity) && m_param_types.match(vals, t_conversions))) && test_guard(vals, t_conversions); @@ -380,7 +380,7 @@ namespace chaiscript } protected: - bool test_guard(const std::vector ¶ms, const Type_Conversions &t_conversions) const + bool test_guard(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const { if (m_guard) { @@ -450,7 +450,7 @@ namespace chaiscript protected: - virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE + virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE { if (call_match(params, t_conversions) && test_guard(params, t_conversions)) { @@ -500,7 +500,7 @@ namespace chaiscript virtual ~Bound_Function() {} - virtual bool call_match(const std::vector &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE + virtual bool call_match(const std::vector &vals, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE { return m_f->call_match(build_param_list(vals), t_conversions); } @@ -579,7 +579,7 @@ namespace chaiscript return retval; } - virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE + virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE { return (*m_f)(build_param_list(params), t_conversions); } @@ -604,12 +604,12 @@ namespace chaiscript return ""; } - virtual bool call_match(const std::vector &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE + virtual bool call_match(const std::vector &vals, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE { return static_cast(vals.size()) == get_arity() && (compare_types(m_types, vals, t_conversions) && compare_types_with_cast(vals, t_conversions)); } - virtual bool compare_types_with_cast(const std::vector &vals, const Type_Conversions &t_conversions) const = 0; + virtual bool compare_types_with_cast(const std::vector &vals, const Type_Conversions_State &t_conversions) const = 0; }; @@ -627,7 +627,7 @@ namespace chaiscript virtual ~Proxy_Function_Callable_Impl() {} - virtual bool compare_types_with_cast(const std::vector &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE + virtual bool compare_types_with_cast(const std::vector &vals, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE { return detail::compare_types_cast(static_cast(nullptr), vals, t_conversions); } @@ -639,7 +639,7 @@ namespace chaiscript protected: - virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE + virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE { typedef typename detail::Function_Signature::Return_Type Return_Type; return detail::Do_Call::template go(m_f, params, t_conversions); @@ -679,7 +679,7 @@ namespace chaiscript virtual ~Assignable_Proxy_Function_Impl() {} - virtual bool compare_types_with_cast(const std::vector &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE + virtual bool compare_types_with_cast(const std::vector &vals, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE { return detail::compare_types_cast(static_cast(nullptr), vals, t_conversions); } @@ -699,7 +699,7 @@ namespace chaiscript } protected: - virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE + virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE { return detail::Do_Call::result_type>::template go(m_f.get(), params, t_conversions); } @@ -738,7 +738,7 @@ namespace chaiscript } } - virtual bool call_match(const std::vector &vals, const Type_Conversions &) const CHAISCRIPT_OVERRIDE + virtual bool call_match(const std::vector &vals, const Type_Conversions_State &) const CHAISCRIPT_OVERRIDE { if (vals.size() != 1) { @@ -754,7 +754,7 @@ namespace chaiscript } protected: - virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE + virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const CHAISCRIPT_OVERRIDE { const Boxed_Value &bv = params[0]; if (bv.is_const()) @@ -815,7 +815,7 @@ namespace chaiscript { template bool types_match_except_for_arithmetic(const FuncType &t_func, const std::vector &plist, - const Type_Conversions &t_conversions) + const Type_Conversions_State &t_conversions) { const std::vector &types = t_func->get_param_types(); @@ -834,7 +834,7 @@ namespace chaiscript template Boxed_Value dispatch_with_conversions(InItr begin, const InItr &end, const std::vector &plist, - const Type_Conversions &t_conversions, const Funcs &t_funcs) + const Type_Conversions_State &t_conversions, const Funcs &t_funcs) { InItr matching_func(end); @@ -911,7 +911,7 @@ namespace chaiscript */ template Boxed_Value dispatch(const Funcs &funcs, - const std::vector &plist, const Type_Conversions &t_conversions) + const std::vector &plist, const Type_Conversions_State &t_conversions) { std::vector> ordered_funcs; ordered_funcs.reserve(funcs.size()); diff --git a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp index 130d3c1e..452a999b 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-2015, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_PROXY_FUNCTIONS_DETAIL_HPP_ @@ -19,7 +19,7 @@ #include "callable_traits.hpp" namespace chaiscript { -class Type_Conversions; +class Type_Conversions_State; namespace exception { class bad_boxed_cast; } // namespace exception @@ -77,7 +77,7 @@ namespace chaiscript template struct Try_Cast { - static void do_try(const std::vector ¶ms, size_t generation, const Type_Conversions &t_conversions) + static void do_try(const std::vector ¶ms, size_t generation, const Type_Conversions_State &t_conversions) { boxed_cast(params[generation], &t_conversions); Try_Cast::do_try(params, generation+1, t_conversions); @@ -88,7 +88,7 @@ namespace chaiscript template<> struct Try_Cast<> { - static void do_try(const std::vector &, size_t, const Type_Conversions &) + static void do_try(const std::vector &, size_t, const Type_Conversions_State &) { } }; @@ -101,7 +101,7 @@ namespace chaiscript */ template bool compare_types_cast(Ret (*)(Params...), - const std::vector ¶ms, const Type_Conversions &t_conversions) + const std::vector ¶ms, const Type_Conversions_State &t_conversions) { try { Try_Cast::do_try(params, 0, t_conversions); @@ -118,7 +118,7 @@ namespace chaiscript template static Ret do_call(const Callable &f, - const std::vector ¶ms, const Type_Conversions &t_conversions, InnerParams &&... innerparams) + const std::vector ¶ms, const Type_Conversions_State &t_conversions, InnerParams &&... innerparams) { return Call_Func::do_call(f, params, t_conversions, std::forward(innerparams)..., params[sizeof...(Params) - count]); } @@ -133,7 +133,7 @@ namespace chaiscript #endif template static Ret do_call(const Callable &f, - const std::vector &, const Type_Conversions &t_conversions, InnerParams &&... innerparams) + const std::vector &, const Type_Conversions_State &t_conversions, InnerParams &&... innerparams) { return f(boxed_cast(std::forward(innerparams), &t_conversions)...); } @@ -150,7 +150,7 @@ namespace chaiscript */ template Ret call_func(const chaiscript::dispatch::detail::Function_Signature &, const Callable &f, - const std::vector ¶ms, const Type_Conversions &t_conversions) + const std::vector ¶ms, const Type_Conversions_State &t_conversions) { if (params.size() == sizeof...(Params)) { @@ -190,7 +190,7 @@ namespace chaiscript */ template bool compare_types_cast(Indexes, Ret (*)(Params...), - const std::vector ¶ms, const Type_Conversions &t_conversions) + const std::vector ¶ms, const Type_Conversions_State &t_conversions) { try { (void)params; (void)t_conversions; @@ -204,7 +204,7 @@ namespace chaiscript template bool compare_types_cast(Ret (*f)(Params...), - const std::vector ¶ms, const Type_Conversions &t_conversions) + const std::vector ¶ms, const Type_Conversions_State &t_conversions) { typedef typename Make_Indexes::indexes indexes; return compare_types_cast(indexes(), f, params, t_conversions); @@ -213,7 +213,7 @@ namespace chaiscript template Ret call_func(const chaiscript::dispatch::detail::Function_Signature &, Indexes, const Callable &f, - const std::vector ¶ms, const Type_Conversions &t_conversions) + const std::vector ¶ms, const Type_Conversions_State &t_conversions) { (void)params; (void)t_conversions; return f(boxed_cast(params[I], &t_conversions)...); @@ -228,7 +228,7 @@ namespace chaiscript */ template Ret call_func(const chaiscript::dispatch::detail::Function_Signature &sig, const Callable &f, - const std::vector ¶ms, const Type_Conversions &t_conversions) + const std::vector ¶ms, const Type_Conversions_State &t_conversions) { typedef typename Make_Indexes::indexes indexes; return call_func(sig, indexes(), f, params, t_conversions); @@ -252,7 +252,7 @@ namespace chaiscript struct Do_Call { template - static Boxed_Value go(const Callable &fun, const std::vector ¶ms, const Type_Conversions &t_conversions) + static Boxed_Value go(const Callable &fun, const std::vector ¶ms, const Type_Conversions_State &t_conversions) { return Handle_Return::handle(call_func(Function_Signature(), fun, params, t_conversions)); } @@ -262,7 +262,7 @@ namespace chaiscript struct Do_Call { template - static Boxed_Value go(const Callable &fun, const std::vector ¶ms, const Type_Conversions &t_conversions) + static Boxed_Value go(const Callable &fun, const std::vector ¶ms, const Type_Conversions_State &t_conversions) { call_func(Function_Signature(), fun, params, t_conversions); return Handle_Return::handle(); diff --git a/include/chaiscript/dispatchkit/register_function.hpp b/include/chaiscript/dispatchkit/register_function.hpp index 598dd8b0..8334b7b6 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-2015, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2016, 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 602d4d9b..3a4d2392 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-2015, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_ @@ -310,12 +310,21 @@ namespace chaiscript private: Callable m_func; }; - } class Type_Conversions { public: + struct Conversion_Saves + { + Conversion_Saves() + : enabled(false) + {} + + bool enabled; + std::vector saves; + }; + struct Less_Than { bool operator()(const std::type_info *t_lhs, const std::type_info *t_rhs) const @@ -387,15 +396,14 @@ namespace chaiscript } else { return false; } - } template - Boxed_Value boxed_type_conversion(const Boxed_Value &from) const + 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 (m_conversion_saves->enabled) m_conversion_saves->saves.push_back(ret); + 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"); @@ -405,11 +413,11 @@ namespace chaiscript } template - Boxed_Value boxed_type_down_conversion(const Boxed_Value &to) const + Boxed_Value boxed_type_down_conversion(Conversion_Saves &t_saves, const Boxed_Value &to) const { try { Boxed_Value ret = get_conversion(to.get_type_info(), user_type())->convert_down(to); - if (m_conversion_saves->enabled) m_conversion_saves->saves.push_back(ret); + 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"); @@ -418,15 +426,15 @@ namespace chaiscript } } - void enable_conversion_saves(bool t_val) + static void enable_conversion_saves(Conversion_Saves &t_saves, bool t_val) { - m_conversion_saves->enabled = t_val; + t_saves.enabled = t_val; } - std::vector take_saves() + std::vector take_saves(Conversion_Saves &t_saves) { std::vector ret; - std::swap(ret, m_conversion_saves->saves); + std::swap(ret, t_saves.saves); return ret; } @@ -450,6 +458,10 @@ namespace chaiscript } } + Conversion_Saves &conversion_saves() const { + return *m_conversion_saves; + } + private: std::set >::const_iterator find_bidir( const Type_Info &to, const Type_Info &from) const @@ -459,7 +471,6 @@ namespace chaiscript { return (conversion->to().bare_equal(to) && conversion->from().bare_equal(from)) || (conversion->bidir() && conversion->from().bare_equal(to) && conversion->to().bare_equal(from)); -; } ); } @@ -483,15 +494,6 @@ namespace chaiscript } - struct Conversion_Saves - { - Conversion_Saves() - : enabled(false) - {} - - bool enabled; - std::vector saves; - }; mutable chaiscript::detail::threading::shared_mutex m_mutex; std::set> m_conversions; @@ -501,6 +503,33 @@ namespace chaiscript mutable chaiscript::detail::threading::Thread_Storage m_conversion_saves; }; + class Type_Conversions_State + { + public: + Type_Conversions_State(const Type_Conversions &t_conversions, + Type_Conversions::Conversion_Saves &t_saves) + : m_conversions(t_conversions), + m_saves(t_saves) + { + } + + const Type_Conversions *operator->() const { + return &m_conversions.get(); + } + + const Type_Conversions *get() const { + return &m_conversions.get(); + } + + Type_Conversions::Conversion_Saves &saves() const { + return m_saves; + } + + private: + std::reference_wrapper m_conversions; + std::reference_wrapper m_saves; + }; + typedef std::shared_ptr Type_Conversion; /// \brief Used to register a to / parent class relationship with ChaiScript. Necessary if you @@ -582,7 +611,7 @@ namespace chaiscript const std::vector &from_vec = detail::Cast_Helper &>::cast(t_bv, nullptr); To vec; - + vec.reserve(from_vec.size()); for (const Boxed_Value &bv : from_vec) { vec.push_back(detail::Cast_Helper::cast(bv, nullptr)); } @@ -593,6 +622,22 @@ namespace chaiscript return chaiscript::make_shared>(user_type>(), user_type(), func); } + template + Type_Conversion map_conversion() + { + auto func = [](const Boxed_Value &t_bv) -> Boxed_Value { + const std::map &from_map = detail::Cast_Helper &>::cast(t_bv, nullptr); + + To map; + for (const std::pair &p : from_map) { + map.insert(std::make_pair(p.first, detail::Cast_Helper::cast(p.second, nullptr))); + } + + return Boxed_Value(std::move(map)); + }; + + return chaiscript::make_shared>(user_type>(), user_type(), func); + } } diff --git a/include/chaiscript/dispatchkit/type_info.hpp b/include/chaiscript/dispatchkit/type_info.hpp index 96145976..14260857 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-2015, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2016, 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 151a94b3..52441e8f 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-2015, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2016, 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 259946f1..b44a5a3b 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-2015, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_COMMON_HPP_ @@ -582,12 +582,12 @@ namespace chaiscript Function_Push_Pop(const chaiscript::detail::Dispatch_State &t_ds) : m_ds(t_ds) { - m_ds.get()->new_function_call(m_ds.get().stack_holder()); + m_ds.get()->new_function_call(m_ds.get().stack_holder(), m_ds.get().conversion_saves()); } ~Function_Push_Pop() { - m_ds.get()->pop_function_call(m_ds.get().stack_holder()); + m_ds.get()->pop_function_call(m_ds.get().stack_holder(), m_ds.get().conversion_saves()); } void save_params(const std::vector &t_params) diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index 4764c671..f3aa0693 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-2015, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_ENGINE_HPP_ @@ -177,11 +177,11 @@ namespace chaiscript FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, - NULL, + nullptr, t_err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), reinterpret_cast(&lpMsgBuf), - 0, NULL ) != 0 && lpMsgBuf) + 0, nullptr ) != 0 && lpMsgBuf) { retval = lpMsgBuf; LocalFree(lpMsgBuf); @@ -342,6 +342,7 @@ namespace chaiscript m_engine.add_reserved_word("class"); m_engine.add_reserved_word("attr"); m_engine.add_reserved_word("var"); + m_engine.add_reserved_word("global"); m_engine.add_reserved_word("GLOBAL"); m_engine.add_reserved_word("_"); @@ -367,11 +368,15 @@ namespace chaiscript // 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) { - return t_fun(t_params, this->m_engine.conversions()); + [=](const dispatch::Proxy_Function_Base &t_fun, const std::vector &t_params) -> Boxed_Value { + Type_Conversions_State s(this->m_engine.conversions(), this->m_engine.conversions().conversion_saves()); + return t_fun(t_params, s); }), "call"); + m_engine.add(fun([this](const Type_Info &t_ti){ return m_engine.get_type_name(t_ti); }), "name"); m_engine.add(fun([this](const std::string &t_type_name, bool t_throw){ return m_engine.get_type(t_type_name, t_throw); }), "type"); @@ -398,10 +403,14 @@ namespace chaiscript m_engine.add(fun(&ChaiScript::version_minor), "version_minor"); m_engine.add(fun(&ChaiScript::version_patch), "version_patch"); m_engine.add(fun(&ChaiScript::version), "version"); + m_engine.add(fun(&ChaiScript::compiler_version), "compiler_version"); + m_engine.add(fun(&ChaiScript::compiler_name), "compiler_name"); + m_engine.add(fun(&ChaiScript::compiler_id), "compiler_id"); + m_engine.add(fun(&ChaiScript::debug_build), "debug_build"); m_engine.add(fun([this](const Boxed_Value &t_bv, const std::string &t_name){ add_global_const(t_bv, t_name); }), "add_global_const"); m_engine.add(fun([this](const Boxed_Value &t_bv, const std::string &t_name){ add_global(t_bv, t_name); }), "add_global"); - + m_engine.add(fun([this](const Boxed_Value &t_bv, const std::string &t_name){ set_global(t_bv, t_name); }), "set_global"); } @@ -552,11 +561,36 @@ namespace chaiscript static std::string version() { - std::stringstream ss; - ss << version_major() << "." << version_minor() << "." << version_patch(); - return ss.str(); + return std::to_string(version_major()) + '.' + std::to_string(version_minor()) + '.' + std::to_string(version_patch()); } + static std::string compiler_id() + { + return compiler_name() + '-' + compiler_version(); + } + + static std::string build_id() + { + return compiler_id() + (debug_build()?"-Debug":"-Release"); + } + + static std::string compiler_version() + { + return chaiscript::compiler_version; + } + + static std::string compiler_name() + { + return chaiscript::compiler_name; + } + + static bool debug_build() + { + return chaiscript::debug_build; + } + + + std::string get_type_name(const Type_Info &ti) const { return m_engine.get_type_name(ti); @@ -626,6 +660,12 @@ namespace chaiscript return *this; } + ChaiScript &set_global(const Boxed_Value &t_bv, const std::string &t_name) + { + m_engine.set_global(t_bv, t_name); + return *this; + } + /// \brief Represents the current state of the ChaiScript system. State and be saved and restored /// \warning State object does not contain the user defined type conversions of the engine. They /// are left out due to performance considerations involved in tracking the state diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index aa01de96..60474b4a 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-2015, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_EVAL_HPP_ @@ -118,7 +118,7 @@ namespace chaiscript } else { chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); fpp.save_params({t_lhs, t_rhs}); - return t_ss->call_function(t_oper_string, m_loc, {t_lhs, t_rhs}); + return t_ss->call_function(t_oper_string, m_loc, {t_lhs, t_rhs}, t_ss.conversions()); } } catch(const exception::dispatch_error &e){ @@ -253,7 +253,7 @@ namespace chaiscript Boxed_Value fn(this->children[0]->eval(t_ss)); try { - return (*t_ss->boxed_cast(fn))(params, t_ss->conversions()); + return (*t_ss->boxed_cast(fn))(params, t_ss.conversions()); } catch(const exception::dispatch_error &e){ throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'", e.parameters, e.functions, false, *t_ss); @@ -434,14 +434,14 @@ namespace chaiscript } else { if (!rhs.is_return_value()) { - rhs = t_ss->call_function("clone", m_clone_loc, {rhs}); + rhs = t_ss->call_function("clone", m_clone_loc, {rhs}, t_ss.conversions()); } rhs.reset_return_value(); } } try { - return t_ss->call_function(this->children[1]->text, m_loc, {std::move(lhs), rhs}); + return t_ss->call_function(this->children[1]->text, m_loc, {std::move(lhs), rhs}, t_ss.conversions()); } catch(const exception::dispatch_error &e){ throw exception::eval_error("Unable to find appropriate'" + this->children[1]->text + "' operator.", e.parameters, e.functions, false, *t_ss); @@ -461,7 +461,7 @@ namespace chaiscript } else { try { - return t_ss->call_function(this->children[1]->text, m_loc, {std::move(lhs), rhs}); + return t_ss->call_function(this->children[1]->text, m_loc, {std::move(lhs), rhs}, t_ss.conversions()); } catch(const exception::dispatch_error &e){ throw exception::eval_error("Unable to find appropriate'" + this->children[1]->text + "' operator.", e.parameters, e.functions, false, *t_ss); } @@ -544,7 +544,7 @@ namespace chaiscript try { fpp.save_params(params); - return t_ss->call_function("[]", m_loc, params); + return t_ss->call_function("[]", m_loc, params, t_ss.conversions()); } catch(const exception::dispatch_error &e){ throw exception::eval_error("Can not find appropriate array lookup operator '[]'.", e.parameters, e.functions, false, *t_ss ); @@ -597,7 +597,7 @@ namespace chaiscript fpp.save_params(params); try { - retval = t_ss->call_member(m_fun_name, m_loc, std::move(params), has_function_params); + retval = t_ss->call_member(m_fun_name, m_loc, std::move(params), has_function_params, t_ss.conversions()); } catch(const exception::dispatch_error &e){ if (e.functions.empty()) @@ -613,7 +613,7 @@ namespace chaiscript if (this->children[2]->identifier == AST_Node_Type::Array_Call) { try { - retval = t_ss->call_function("[]", m_array_loc, {retval, this->children[2]->children[1]->eval(t_ss)}); + retval = t_ss->call_function("[]", m_array_loc, {retval, this->children[2]->children[1]->eval(t_ss)}, t_ss.conversions()); } catch(const exception::dispatch_error &e){ throw exception::eval_error("Can not find appropriate array lookup operator '[]'.", e.parameters, e.functions, true, *t_ss); @@ -939,7 +939,7 @@ namespace chaiscript if (this->children[currentCase]->identifier == AST_Node_Type::Case) { //This is a little odd, but because want to see both the switch and the case simultaneously, I do a downcast here. try { - if (hasMatched || boxed_cast(t_ss->call_function("==", m_loc, {match_value, this->children[currentCase]->children[0]->eval(t_ss)}))) { + if (hasMatched || boxed_cast(t_ss->call_function("==", m_loc, {match_value, this->children[currentCase]->children[0]->eval(t_ss)}, t_ss.conversions()))) { this->children[currentCase]->eval(t_ss); hasMatched = true; } @@ -1005,10 +1005,11 @@ namespace chaiscript try { std::vector vec; if (!children.empty()) { + vec.reserve(children[0]->children.size()); for (const auto &child : children[0]->children) { auto obj = child->eval(t_ss); if (!obj.is_return_value()) { - vec.push_back(t_ss->call_function("clone", m_loc, {obj})); + vec.push_back(t_ss->call_function("clone", m_loc, {obj}, t_ss.conversions())); } else { vec.push_back(std::move(obj)); } @@ -1041,7 +1042,7 @@ namespace chaiscript for (const auto &child : children[0]->children) { auto obj = child->children[1]->eval(t_ss); if (!obj.is_return_value()) { - obj = t_ss->call_function("clone", m_loc, {obj}); + obj = t_ss->call_function("clone", m_loc, {obj}, t_ss.conversions()); } retval[t_ss->boxed_cast(child->children[0]->eval(t_ss))] = std::move(obj); @@ -1137,7 +1138,7 @@ namespace chaiscript } else { chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); fpp.save_params({bv}); - return t_ss->call_function(children[0]->text, m_loc, {std::move(bv)}); + return t_ss->call_function(children[0]->text, m_loc, {std::move(bv)}, t_ss.conversions()); } } catch (const exception::dispatch_error &e) { throw exception::eval_error("Error with prefix operator evaluation: '" + children[0]->text + "'", e.parameters, e.functions, false, *t_ss); @@ -1209,7 +1210,7 @@ namespace chaiscript try { auto oper1 = children[0]->children[0]->children[0]->eval(t_ss); auto oper2 = children[0]->children[0]->children[1]->eval(t_ss); - return t_ss->call_function("generate_range", m_loc, {oper1, oper2}); + return t_ss->call_function("generate_range", m_loc, {oper1, oper2}, t_ss.conversions()); } catch (const exception::dispatch_error &e) { throw exception::eval_error("Unable to generate range vector, while calling 'generate_range'", e.parameters, e.functions, false, *t_ss); @@ -1254,7 +1255,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())) { t_ss.add_object(name, t_except); diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 6548521d..0bfabe56 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-2015, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_PARSER_HPP_ @@ -278,7 +278,7 @@ 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 = "") { + void debug_print(AST_NodePtr t, std::string prepend = "") const { std::cout << prepend << "(" << ast_node_type_to_string(t->identifier) << ") " << t->text << " : " << t->start().line << ", " << t->start().column << '\n'; for (unsigned int j = 0; j < t->children.size(); ++j) { debug_print(t->children[j], prepend + " "); @@ -881,8 +881,20 @@ namespace chaiscript char prev_char = *m_position; ++m_position; - while (m_position.has_more() && ((*m_position != '\"') || ((*m_position == '\"') && (prev_char == '\\')))) { + int in_interpolation = 0; + bool in_quote = false; + + while (m_position.has_more() && ((*m_position != '\"') || ((*m_position == '\"') && (in_interpolation > 0)) || ((*m_position == '\"') && (prev_char == '\\')))) { + if (!Eol_()) { + if (prev_char == '$' && *m_position == '{') { + ++in_interpolation; + } else if (prev_char != '\\' && *m_position == '"') { + in_quote = !in_quote; + } else if (*m_position == '}' && !in_quote) { + --in_interpolation; + } + if (prev_char == '\\') { prev_char = 0; } else { @@ -929,7 +941,7 @@ namespace chaiscript { } - Char_Parser &operator=(const Char_Parser &) = delete; + Char_Parser &operator=(const Char_Parser &) = delete; ~Char_Parser(){ if (is_octal) { @@ -2055,7 +2067,7 @@ namespace chaiscript } build_match(prev_stack_top); - } else if (Keyword("GLOBAL")) { + } else if (Keyword("GLOBAL") || Keyword("global")) { retval = true; if (!(Reference() || Id())) { diff --git a/include/chaiscript/utility/json.hpp b/include/chaiscript/utility/json.hpp index c023c2bf..56f28e75 100644 --- a/include/chaiscript/utility/json.hpp +++ b/include/chaiscript/utility/json.hpp @@ -19,6 +19,7 @@ #include #include #include +#include "../chaiscript_defines.hpp" namespace json { @@ -48,6 +49,21 @@ namespace { } return output; } + + bool isspace(const char c) + { +#ifdef CHAISCRIPT_MSVC + // MSVC warns on these line in some circumstances +#pragma warning(push) +#pragma warning(disable : 6330) +#endif + return ::isspace(c) != 0; +#ifdef CHAISCRIPT_MSVC +#pragma warning(pop) +#endif + + + } } class JSON diff --git a/include/chaiscript/utility/utility.hpp b/include/chaiscript/utility/utility.hpp index 381afda2..22ab8e96 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-2015, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #ifndef CHAISCRIPT_UTILITY_UTILITY_HPP_ @@ -69,21 +69,31 @@ namespace chaiscript typename std::enable_if::value, void>::type add_class(ModuleType &t_module, const std::string &t_class_name, - const std::vector::type, std::string>> &t_constants) +#ifdef CHAISCRIPT_GCC_4_6 + const std::vector> &t_constants +#else + const std::vector::type, std::string>> &t_constants +#endif + ) { t_module.add(chaiscript::user_type(), t_class_name); t_module.add(chaiscript::constructor(), t_class_name); t_module.add(chaiscript::constructor(), t_class_name); + using namespace chaiscript::bootstrap::operators; t_module.add([](){ // add some comparison and assignment operators - using namespace chaiscript::bootstrap::operators; return assign(not_equal(equal())); }()); +#ifdef CHAISCRIPT_GCC_4_6 + t_module.add(chaiscript::fun([](const Enum &e, const int &i) { return e == i; }), "=="); + t_module.add(chaiscript::fun([](const int &i, const Enum &e) { return i == e; }), "=="); +#else t_module.add(chaiscript::fun([](const Enum &e, const typename std::underlying_type::type &i) { return e == i; }), "=="); t_module.add(chaiscript::fun([](const typename std::underlying_type::type &i, const Enum &e) { return i == e; }), "=="); +#endif for (const auto &constant : t_constants) { diff --git a/license.txt b/license.txt index 48f52923..105662d9 100644 --- a/license.txt +++ b/license.txt @@ -1,4 +1,4 @@ -Copyright 2009-2015 Jason Turner +Copyright 2009-2016 Jason Turner Copyright 2009-2012 Jonathan Turner. All Rights Reserved. diff --git a/performance_tests/profile_cpp_calls_2.cpp b/performance_tests/profile_cpp_calls_2.cpp new file mode 100644 index 00000000..0424654b --- /dev/null +++ b/performance_tests/profile_cpp_calls_2.cpp @@ -0,0 +1,20 @@ +#include +#include + +double f(const std::string &, double, bool) noexcept { + return .0; +} + +int main() +{ + chaiscript::ChaiScript chai(chaiscript::Std_Lib::library()); + + chai.add(chaiscript::fun(&f), "f"); + + chai.eval(R"( + for (var i = 0; i < 100000; ++i) { + f("str", 1.2, false); + } + )"); + +} diff --git a/performance_tests/profile_fun_wrappers.cpp b/performance_tests/profile_fun_wrappers.cpp new file mode 100644 index 00000000..fb96f483 --- /dev/null +++ b/performance_tests/profile_fun_wrappers.cpp @@ -0,0 +1,20 @@ +#include +#include + +double f(const std::string &, double, bool) noexcept { + return .0; +} + +int main() +{ + chaiscript::ChaiScript chai(chaiscript::Std_Lib::library()); + + chai.add(chaiscript::fun(&f), "f"); + + const auto f = chai.eval>(R"(fun(){ f("str", 1.2, false); })"); + + for (int i = 0; i < 100000; ++i) { + f(); + } + +} diff --git a/readme.md b/readme.md index 75e470a9..160662a5 100644 --- a/readme.md +++ b/readme.md @@ -12,7 +12,7 @@ ChaiScript http://www.chaiscript.com (c) 2009-2012 Jonathan Turner -(c) 2009-2015 Jason Turner +(c) 2009-2016 Jason Turner Release under the BSD license, see "license.txt" for details. diff --git a/releasenotes.md b/releasenotes.md index c78376d8..993f93d1 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -1,6 +1,29 @@ Notes: ======= -Current Version: 5.7.1 +Current Version: 5.8.0 + +### Changes since 5.7.1 +* Make all parser iterator operations range checked +* Parse in-string eval statements once, not once for each execution +* Fix parsing of operators (ie 1<-1 now parses) +* Fix variable scoping for functors +* Exception reduction +* Various object lifetime fixes +* Add JSON support for load / save #207 +* Numeric overload resolution fixes #209 +* Fix long long #208 +* Add octal escapes in strings #211 +* Fixed sizing of binary literals #213 +* Added support for != with bool values #217 +* Various value assignment vector fixes +* Fixed broken hex escape sequences from @ChristianKaeser +* Multiply defined symbols fixes #232 @RaptorFactor +* Add add_class helper #233 @vrennert +* Cheatsheet fixes #235 @mlamby +* Fix parsing of strings inside of in-string eval statements +* Allow lower-case global keyword +* Enable thread-local on MSVC (should be significant performance boost) + ### Changes since 5.7.0 * Build time reduction diff --git a/samples/fun_call_performance.cpp b/samples/fun_call_performance.cpp index a416cc2a..0ccc08dd 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-2015, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #include @@ -316,7 +316,7 @@ int main(int argc, char *argv[]) ////for (int i = 0; i < 1000; i++) ////{ - //// chai.eval("puts(helloWorld(\"Bob12345\"));"); + //// chai.eval("puts(helloWorld(\"Bob12345\"));"); ////} //chai.eval_file("E:\\C++\\ChaiScript - 5.4.0\\samples\forx.chai"); diff --git a/samples/test_num_exceptions.cpp b/samples/test_num_exceptions.cpp index 36bbb756..3a35fb7c 100644 --- a/samples/test_num_exceptions.cpp +++ b/samples/test_num_exceptions.cpp @@ -7,20 +7,22 @@ int main( int /*argc*/ , char * /*argv*/[] ) { chaiscript::ChaiScript ch( chaiscript::Std_Lib::library( ) ); - static const char script[ ] = - R""( + + try + { + static const char script[ ] = + R""( class Rectangle { def Rectangle() { } } - var rect = Rectangle( ); + var rect = Rectangle( ); )""; - try - { + ch.eval( script ); } catch ( const std::exception &e ) diff --git a/src/main.cpp b/src/main.cpp index 372adf74..7f203cdd 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-2015, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #include @@ -66,7 +66,7 @@ std::vector default_search_paths() #ifdef CHAISCRIPT_WINDOWS // force no unicode CHAR path[4096]; - int size = GetModuleFileNameA(0, path, sizeof(path)-1); + int size = GetModuleFileNameA(nullptr, path, sizeof(path)-1); std::string exepath(path, size); @@ -344,17 +344,16 @@ int main(int argc, char *argv[]) mode = eFile; } - chaiscript::Boxed_Value val ; try { switch ( mode ) { case eInteractive: interactive(chai); break; case eCommand: - val = chai.eval(arg); + chai.eval(arg); break; case eFile: - val = chai.eval_file(arg); + chai.eval_file(arg); } } catch (const chaiscript::exception::eval_error &ee) { diff --git a/src/stl_extra.cpp b/src/stl_extra.cpp index e391b180..ec38db77 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-2015, Jason Turner (jason@emptycrate.com) +// Copyright 2009-2016, Jason Turner (jason@emptycrate.com) // http://www.chaiscript.com #include diff --git a/unittests/array_access.chai b/unittests/array_access.chai new file mode 100644 index 00000000..76004923 --- /dev/null +++ b/unittests/array_access.chai @@ -0,0 +1,3 @@ +var v = [[[15]]] + +assert_true(v[0][0][0] == 15) diff --git a/unittests/compiled_tests.cpp b/unittests/compiled_tests.cpp index de37aafb..9ee60f10 100644 --- a/unittests/compiled_tests.cpp +++ b/unittests/compiled_tests.cpp @@ -399,7 +399,7 @@ class Short_Comparison_Test { public: Short_Comparison_Test() : value_(5) {} - short get_value() { return value_; } + short get_value() const { return value_; } short value_; }; @@ -874,6 +874,7 @@ struct Returned_Converted_Config }; + TEST_CASE("Return of converted type from script") { chaiscript::ChaiScript chai; @@ -915,3 +916,28 @@ TEST_CASE("Return of converted type from script") chai.add(chaiscript::user_type(), "Returned_Converted_Config"); } + +int get_value_a(const std::map &t_m) +{ + return t_m.at("a"); +} + + +TEST_CASE("Map conversions") +{ + chaiscript::ChaiScript chai; + chai.add(chaiscript::map_conversion>()); + chai.add(chaiscript::fun(&get_value_a), "get_value_a"); + + const auto c = chai.eval(R"( + var m = ["a": 42]; + get_value_a(m); + )"); + + CHECK(c == 42); + +} + + + + diff --git a/unittests/global_in_script.chai b/unittests/global_in_script.chai index 951a9107..3d94c7a5 100644 --- a/unittests/global_in_script.chai +++ b/unittests/global_in_script.chai @@ -8,3 +8,17 @@ def myFun() } myFun(); + + +def myFun2() +{ + assert_equal(j, 7) +} + +set_global(7, "j") + +myFun2(); + +set_global(5, "j") + +myFun(); diff --git a/unittests/global_lcase.chai b/unittests/global_lcase.chai new file mode 100644 index 00000000..7f8959a6 --- /dev/null +++ b/unittests/global_lcase.chai @@ -0,0 +1,18 @@ +// Test global + +global g = 3; +assert_true(g == 3); + +var v := g; +assert_true(v == 3); + +global g = 2; +assert_true(g == 2); +assert_true(v == 2); + +def f() { + assert_true(g == 2); +} + +f(); + diff --git a/unittests/instring_eval_with_string.chai b/unittests/instring_eval_with_string.chai new file mode 100644 index 00000000..9cb1091a --- /dev/null +++ b/unittests/instring_eval_with_string.chai @@ -0,0 +1 @@ +assert_equal("a string", "${"a string"}") diff --git a/unittests/list_push_back.chai b/unittests/list_push_back.chai index 5a058fc8..35b8fa68 100644 --- a/unittests/list_push_back.chai +++ b/unittests/list_push_back.chai @@ -8,7 +8,5 @@ assert_equal(3, x.front()); assert_equal("A", x.back()); -// push_back newly constructed return value that's non-copyable -x.push_back(async(fun(){})) diff --git a/unittests/move_async.chai b/unittests/move_async.chai new file mode 100644 index 00000000..7975a7c4 --- /dev/null +++ b/unittests/move_async.chai @@ -0,0 +1,17 @@ +load_module("stl_extra") + +auto x = List() +// push_back newly constructed return value that's non-copyable +x.push_front(async(fun(){})) + +// push_front newly constructed return value that's non-copyable +x.push_front(async(fun(){})) + + + +// push_back newly constructed return value that's non-copyable + +var v = [] +v.push_back(async(fun(){})) + + diff --git a/unittests/return_value_assignment.chai b/unittests/return_value_assignment.chai new file mode 100644 index 00000000..e6906e61 --- /dev/null +++ b/unittests/return_value_assignment.chai @@ -0,0 +1,16 @@ + +try { + eval("to_string(5) = \"some string\"") + assert_true(false) +} catch (e) { + print("Caught Error: " + e.what()); +} + + + +try { + eval("var v = [1,2,3]; v.size() = 3") + assert_true(false) +} catch (e) { + print("Caught Error: " + e.what()); +} diff --git a/unittests/vector_push_back.chai b/unittests/vector_push_back.chai index 176e1cec..148e7ff6 100644 --- a/unittests/vector_push_back.chai +++ b/unittests/vector_push_back.chai @@ -12,9 +12,6 @@ uint16v.push_back(1u); assert_equal(1, uint16v.front()); -// push_back newly constructed return value that's non-copyable - -var v = [] -v.push_back(async(fun(){})) +