From 8d36b66c89f7c13ecc6b27b384ebf9700c40fe9b Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 5 Sep 2014 07:45:36 -0600 Subject: [PATCH 01/63] Fix call to cppcheck --- contrib/codeanalysis/runcppcheck.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/codeanalysis/runcppcheck.sh b/contrib/codeanalysis/runcppcheck.sh index 5e79737..05a492d 100755 --- a/contrib/codeanalysis/runcppcheck.sh +++ b/contrib/codeanalysis/runcppcheck.sh @@ -6,7 +6,7 @@ tar -xvf cppcheck-1.66.tar.bz2 cd cppcheck-1.66 make -j2 popd -../cppcheck-1.65/cppcheck --enable=all -I include --inline-suppr --std=c++11 --platform=unix64 src/main.cpp src/chai*.cpp --template ' - __{severity}__: [{file}:{line}](../blob/TRAVIS_COMMIT/{file}#L{line}) {message} ({id})' 2>output +../cppcheck-1.66/cppcheck --enable=all -I include --inline-suppr --std=c++11 --platform=unix64 src/main.cpp src/chai*.cpp --template ' - __{severity}__: [{file}:{line}](../blob/TRAVIS_COMMIT/{file}#L{line}) {message} ({id})' 2>output sed -i "s/TRAVIS_COMMIT/${TRAVIS_COMMIT}/g" output echo -n '{ "body": " ' > output.json echo -n `awk '{printf "%s\\\\n", $0;}' output` >> output.json From 29b1fca76c512c730825d4e0a57070cedab406d2 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 5 Sep 2014 08:09:22 -0600 Subject: [PATCH 02/63] Use g++-4.8 for cppcheck building --- contrib/codeanalysis/runcppcheck.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/codeanalysis/runcppcheck.sh b/contrib/codeanalysis/runcppcheck.sh index 05a492d..79e6313 100755 --- a/contrib/codeanalysis/runcppcheck.sh +++ b/contrib/codeanalysis/runcppcheck.sh @@ -4,7 +4,7 @@ pushd .. wget http://sourceforge.net/projects/cppcheck/files/cppcheck/1.66/cppcheck-1.66.tar.bz2 tar -xvf cppcheck-1.66.tar.bz2 cd cppcheck-1.66 -make -j2 +CXX=g++-4.8 make -j2 popd ../cppcheck-1.66/cppcheck --enable=all -I include --inline-suppr --std=c++11 --platform=unix64 src/main.cpp src/chai*.cpp --template ' - __{severity}__: [{file}:{line}](../blob/TRAVIS_COMMIT/{file}#L{line}) {message} ({id})' 2>output sed -i "s/TRAVIS_COMMIT/${TRAVIS_COMMIT}/g" output From 166f3501c3fa0bc54413097073e207db1e73234f Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 5 Sep 2014 08:41:58 -0600 Subject: [PATCH 03/63] Ignore missing system include files --- contrib/codeanalysis/runcppcheck.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contrib/codeanalysis/runcppcheck.sh b/contrib/codeanalysis/runcppcheck.sh index 79e6313..54e9a82 100755 --- a/contrib/codeanalysis/runcppcheck.sh +++ b/contrib/codeanalysis/runcppcheck.sh @@ -6,7 +6,7 @@ tar -xvf cppcheck-1.66.tar.bz2 cd cppcheck-1.66 CXX=g++-4.8 make -j2 popd -../cppcheck-1.66/cppcheck --enable=all -I include --inline-suppr --std=c++11 --platform=unix64 src/main.cpp src/chai*.cpp --template ' - __{severity}__: [{file}:{line}](../blob/TRAVIS_COMMIT/{file}#L{line}) {message} ({id})' 2>output +../cppcheck-1.66/cppcheck --enable=all -I include --inline-suppr --suppress=missingIncludeSystem --std=c++11 --platform=unix64 src/main.cpp src/chai*.cpp --template ' - __{severity}__: [{file}:{line}](../blob/TRAVIS_COMMIT/{file}#L{line}) {message} ({id})' 2>output sed -i "s/TRAVIS_COMMIT/${TRAVIS_COMMIT}/g" output echo -n '{ "body": " ' > output.json echo -n `awk '{printf "%s\\\\n", $0;}' output` >> output.json From eed90b521d4da597f91976be04c1c855e9471302 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Mon, 8 Sep 2014 11:10:53 -0600 Subject: [PATCH 04/63] Spelling corrections and comment fixes --- include/chaiscript/chaiscript.hpp | 6 +++--- include/chaiscript/dispatchkit/any.hpp | 2 +- include/chaiscript/dispatchkit/bad_boxed_cast.hpp | 2 +- include/chaiscript/dispatchkit/dispatchkit.hpp | 2 +- .../chaiscript/dispatchkit/dynamic_cast_conversion.hpp | 2 +- .../chaiscript/dispatchkit/exception_specification.hpp | 1 + include/chaiscript/dispatchkit/proxy_functions.hpp | 4 ++-- .../chaiscript/dispatchkit/proxy_functions_detail.hpp | 4 ++-- include/chaiscript/language/chaiscript_engine.hpp | 4 ++-- .../chaiscript/language/chaiscript_prelude_docs.hpp | 10 +++++----- include/chaiscript/utility/utility.hpp | 2 -- samples/memory_leak_test.cpp | 8 ++++---- 12 files changed, 23 insertions(+), 24 deletions(-) diff --git a/include/chaiscript/chaiscript.hpp b/include/chaiscript/chaiscript.hpp index 903eb38..c8e9e9a 100644 --- a/include/chaiscript/chaiscript.hpp +++ b/include/chaiscript/chaiscript.hpp @@ -75,7 +75,7 @@ /// /// @subsection compiling Compiling ChaiScript Applications /// -/// ChaiScript is a header only library with only one dependecy: The +/// ChaiScript is a header only library with only one dependency: The /// operating system provided dynamic library loader, which has to be specified on some platforms. /// /// @subsubsection compilinggcc Compiling with GCC @@ -112,7 +112,7 @@ /// /// @subsubsection evalmethod Method 'eval' /// -/// The eval method is somewhat more verbose and can be used to get typesafely return values +/// The eval method is somewhat more verbose and can be used to get type safely return values /// from the script. /// /// ~~~~~~~~{.cpp} @@ -311,7 +311,7 @@ /// As much as possible, ChaiScript attempts to convert between &, *, const &, const *, std::shared_ptr, /// std::shared_ptr, std::reference_wrapper, std::reference_wrapper and value types automatically. /// -/// If a chaiscript::var object was created in C++ from a pointer, it cannot be convered to a shared_ptr (this would add invalid reference counting). +/// If a chaiscript::var object was created in C++ from a pointer, it cannot be converted to a shared_ptr (this would add invalid reference counting). /// Const may be added, but never removed. /// /// The take away is that you can pretty much expect function calls to Just Work when you need them to. diff --git a/include/chaiscript/dispatchkit/any.hpp b/include/chaiscript/dispatchkit/any.hpp index ce76175..39ff2fa 100644 --- a/include/chaiscript/dispatchkit/any.hpp +++ b/include/chaiscript/dispatchkit/any.hpp @@ -28,7 +28,7 @@ namespace chaiscript { virtual ~bad_any_cast() CHAISCRIPT_NOEXCEPT {} - /// \brief Description of what error occured + /// \brief Description of what error occurred virtual const char * what() const CHAISCRIPT_NOEXCEPT CHAISCRIPT_OVERRIDE { return m_what.c_str(); diff --git a/include/chaiscript/dispatchkit/bad_boxed_cast.hpp b/include/chaiscript/dispatchkit/bad_boxed_cast.hpp index 3040b71..b22bde6 100644 --- a/include/chaiscript/dispatchkit/bad_boxed_cast.hpp +++ b/include/chaiscript/dispatchkit/bad_boxed_cast.hpp @@ -46,7 +46,7 @@ namespace chaiscript virtual ~bad_boxed_cast() CHAISCRIPT_NOEXCEPT {} - /// \brief Description of what error occured + /// \brief Description of what error occurred virtual const char * what() const CHAISCRIPT_NOEXCEPT CHAISCRIPT_OVERRIDE { return m_what.c_str(); diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index 8c4a7f5..fd539de 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -173,7 +173,7 @@ namespace chaiscript } - //Add a bit of chaiscript to eval during module implementation + //Add a bit of ChaiScript to eval during module implementation Module &eval(const std::string &str) { m_evals.push_back(str); diff --git a/include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp b/include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp index 7c46542..359d0a5 100644 --- a/include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp +++ b/include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp @@ -258,7 +258,7 @@ namespace chaiscript /// \brief Used to register a base / parent class relationship with ChaiScript. Necessary if you /// want automatic conversions up your inheritance hierarchy. /// - /// Create a new base class registration for applying to a module or to the chaiscript engine + /// Create a new base class registration for applying to a module or to the ChaiScript engine /// Currently, due to limitations in module loading on Windows, and for the sake of portability, /// if you have a type that is introduced in a loadable module and is used by multiple modules /// (through a tertiary dll that is shared between the modules, static linking the new type diff --git a/include/chaiscript/dispatchkit/exception_specification.hpp b/include/chaiscript/dispatchkit/exception_specification.hpp index 4645c75..e323484 100644 --- a/include/chaiscript/dispatchkit/exception_specification.hpp +++ b/include/chaiscript/dispatchkit/exception_specification.hpp @@ -23,6 +23,7 @@ namespace chaiscript { namespace detail { + /// \todo make this a variadic template struct Exception_Handler_Base { virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) = 0; diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index 4f9f471..16ceaf8 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -63,7 +63,7 @@ namespace chaiscript /// Returns a vector containing all of the types of the parameters the function returns/takes /// if the function is variadic or takes no arguments (arity of 0 or -1), the returned - /// value containes exactly 1 Type_Info object: the return type + /// value contains exactly 1 Type_Info object: the return type /// \returns the types of all parameters. const std::vector &get_param_types() const { return m_types; } @@ -182,7 +182,7 @@ namespace chaiscript /// \brief Common typedef used for passing of any registered function in ChaiScript typedef std::shared_ptr Proxy_Function; - /// \brief Const version of Proxy_Function chaiscript. Points to a const Proxy_Function. This is how most registered functions + /// \brief Const version of Proxy_Function. Points to a const Proxy_Function. This is how most registered functions /// are handled internally. typedef std::shared_ptr Const_Proxy_Function; diff --git a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp index 1660a27..fa725f8 100644 --- a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp @@ -118,7 +118,7 @@ namespace chaiscript /** * Used by Proxy_Function_Impl to determine if it is equivalent to another - * Proxy_Function_Impl object. This function is primarly used to prevent + * Proxy_Function_Impl object. This function is primarily used to prevent * registration of two functions with the exact same signatures */ template @@ -166,7 +166,7 @@ namespace chaiscript /** * Used by Proxy_Function_Impl to perform typesafe execution of a function. - * The function attempts to unbox each paramter to the expected type. + * The function attempts to unbox each parameter to the expected type. * if any unboxing fails the execution of the function fails and * the bad_boxed_cast is passed up to the caller. */ diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index 0513194..af01ce3 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -845,7 +845,7 @@ namespace chaiscript /// /// \param[in] t_input Script to execute /// \param[in] t_handler Optional Exception_Handler used for automatic unboxing of script thrown exceptions - /// \param[in] t_filename Optional filename to report to the user for where the error occured. Useful + /// \param[in] t_filename Optional filename to report to the user for where the error occurred. Useful /// in special cases where you are loading a file internally instead of using eval_file /// /// \return result of the script execution @@ -879,7 +879,7 @@ namespace chaiscript } } - /// \brief Loads the file specified by filename, evaluates it, and returns the typesafe result. + /// \brief Loads the file specified by filename, evaluates it, and returns the type safe result. /// \tparam T Type to extract from the result value of the script execution /// \param[in] t_filename File to load and parse. /// \param[in] t_handler Optional Exception_Handler used for automatic unboxing of script thrown exceptions diff --git a/include/chaiscript/language/chaiscript_prelude_docs.hpp b/include/chaiscript/language/chaiscript_prelude_docs.hpp index e817420..eb02f3b 100644 --- a/include/chaiscript/language/chaiscript_prelude_docs.hpp +++ b/include/chaiscript/language/chaiscript_prelude_docs.hpp @@ -112,7 +112,7 @@ class Map }; -/// \brief A concept implemented by string, Vector and Map. It is convertable to Range, default constructable and back_insertable +/// \brief A concept implemented by string, Vector and Map. It is convertible to Range, default constructable and back_insertable class Container { public: @@ -153,10 +153,10 @@ void print(Object o); /// \brief ChaiScript representation of std::string. It is an std::string but only some member are exposed to ChaiScript. /// -/// Because the ChaiScript string object is an std::string, it is directly convertable to and from std::string +/// Because the ChaiScript string object is an std::string, it is directly convertible to and from std::string /// using the chaiscript::boxed_cast and chaiscript::var functions. /// -/// With the exception of string::trim, string::rtrim, string::ltrim, all members are direct passthroughs to the +/// With the exception of string::trim, string::rtrim, string::ltrim, all members are direct pass-throughs to the /// std::string of the same name. /// /// \note Object and function notations are equivalent in ChaiScript. This means that @@ -519,7 +519,7 @@ class Function /// \brief Returns a vector of Type_Info objects that represent the param types for this function. /// The first value in the list is the return type. /// - /// If this function is a conglomeration of several functions (get_contained_values().size() > 0) + /// If this function is a conglomerate of several functions (get_contained_values().size() > 0) /// then the function returns as many Type_Info objects as it can. If the functions contained all have /// the same arity, then it represents the arity. If they have different arities, it returns only /// one value - the return type. @@ -534,7 +534,7 @@ class Function /// \endcode Vector get_param_types() const; - /// \brief Returns true if the function has a guard to it. Always returns falls for a conglomerate function + /// \brief Returns true if the function has a guard to it. Always returns false for a conglomerate function bool has_guard() const; /// \brief Calls the function with the given set of parameters and returns the value; diff --git a/include/chaiscript/utility/utility.hpp b/include/chaiscript/utility/utility.hpp index bd60ef0..3efb525 100644 --- a/include/chaiscript/utility/utility.hpp +++ b/include/chaiscript/utility/utility.hpp @@ -21,8 +21,6 @@ namespace chaiscript namespace utility { - /// \todo Use of this utility, and uniform initializer lists, is causing memory errors in MSVC - template void add_class(ModuleType &t_module, const std::string &t_class_name, diff --git a/samples/memory_leak_test.cpp b/samples/memory_leak_test.cpp index 23a7455..fb58003 100644 --- a/samples/memory_leak_test.cpp +++ b/samples/memory_leak_test.cpp @@ -70,12 +70,12 @@ int main(int /*argc*/, char * /*argv*/[]) { std::string command = ""; // - // this loop increases memoryusage, if RunFile is not called (just hitting enter) + // this loop increases memory usage, if RunFile is not called (just hitting enter) // as soon RunFile gets called, memory will be freed. // - // scenario1 - RunFile gets called every Loop: memoryusage does not change - // scenario2 - RunFile gets never called (just hitting enter): memoryusage increases every loop - // scenario3 - RunFile gets in changing intervals: memoryusage goes up and down, but never as + // scenario1 - RunFile gets called every Loop: memory usage does not change + // scenario2 - RunFile gets never called (just hitting enter): memory usage increases every loop + // scenario3 - RunFile gets in changing intervals: memory usage goes up and down, but never as // low as in case 1 scenario3 : while(command != "quit") From 4a70ffe599214af43067548dff9b65074711f1d0 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Mon, 8 Sep 2014 18:23:53 -0600 Subject: [PATCH 05/63] Add failing unit test for accessing member of null object --- src/test_module.cpp | 10 ++++++++-- unittests/null_object_access.chai | 13 +++++++++++++ 2 files changed, 21 insertions(+), 2 deletions(-) create mode 100644 unittests/null_object_access.chai diff --git a/src/test_module.cpp b/src/test_module.cpp index 7c65dc8..9ac98ee 100644 --- a/src/test_module.cpp +++ b/src/test_module.cpp @@ -51,12 +51,17 @@ class TestMoreDerivedType : public TestDerivedType std::shared_ptr derived_type_factory() { - return std::shared_ptr(new TestDerivedType()); + return std::make_shared(); } std::shared_ptr more_derived_type_factory() { - return std::shared_ptr(new TestMoreDerivedType()); + return std::make_shared(); +} + +std::shared_ptr null_factory() +{ + return std::shared_ptr(); } std::string hello_world() @@ -111,6 +116,7 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo m->add(chaiscript::fun(&derived_type_factory), "derived_type_factory"); m->add(chaiscript::fun(&more_derived_type_factory), "more_derived_type_factory"); + m->add(chaiscript::fun(&null_factory), "null_factory"); m->add(chaiscript::fun(&TestDerivedType::func), "func"); diff --git a/unittests/null_object_access.chai b/unittests/null_object_access.chai new file mode 100644 index 0000000..3ee1c9a --- /dev/null +++ b/unittests/null_object_access.chai @@ -0,0 +1,13 @@ +load_module("test_module") + +auto o = null_factory(); + +try { + o.func(); +} catch (e) { + exit(0); +} + +assert_true(false); + + From 308eb34d050343ceeaa7d921e1f92366be804896 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Mon, 8 Sep 2014 21:15:02 -0600 Subject: [PATCH 06/63] Correct test_module changes --- src/test_module.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/test_module.cpp b/src/test_module.cpp index 9ac98ee..7b6ff75 100644 --- a/src/test_module.cpp +++ b/src/test_module.cpp @@ -56,7 +56,7 @@ std::shared_ptr derived_type_factory() std::shared_ptr more_derived_type_factory() { - return std::make_shared(); + return std::make_shared(); } std::shared_ptr null_factory() From fde90ad980aaf6a06fae1c80bafe6a73432a83b0 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 9 Sep 2014 13:43:05 -0600 Subject: [PATCH 07/63] Throw exception if user attempts to use null Boxed_Value --- .../dispatchkit/boxed_cast_helper.hpp | 74 +++++++++++++------ unittests/null_object_access.chai | 2 +- 2 files changed, 52 insertions(+), 24 deletions(-) diff --git a/include/chaiscript/dispatchkit/boxed_cast_helper.hpp b/include/chaiscript/dispatchkit/boxed_cast_helper.hpp index a9c3c84..222fd90 100644 --- a/include/chaiscript/dispatchkit/boxed_cast_helper.hpp +++ b/include/chaiscript/dispatchkit/boxed_cast_helper.hpp @@ -23,6 +23,13 @@ namespace chaiscript { // Cast_Helper_Inner helper classes + template + T* throw_if_null(T *t) + { + if (t) return t; + throw std::runtime_error("Attempted to dereference null Boxed_Value"); + } + /** * Generic Cast_Helper_Inner, for casting to any type */ @@ -33,21 +40,11 @@ namespace chaiscript static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *) { - if (ob.is_ref()) + if (ob.get_type_info().bare_equal_type_info(typeid(Result))) { - if (!ob.get_type_info().is_const()) - { - return std::cref((ob.get().cast >()).get()); - } else { - return ob.get().cast >(); - } + return *(static_cast(throw_if_null(ob.get_const_ptr()))); } else { - if (!ob.get_type_info().is_const()) - { - return std::cref(*(ob.get().cast >())); - } else { - return std::cref(*(ob.get().cast >())); - } + throw chaiscript::detail::exception::bad_any_cast(); } } }; @@ -65,14 +62,46 @@ namespace chaiscript { }; - /** - * Cast_Helper_Inner for casting to a const * type - */ + /* + /// Cast_Helper_Inner for casting to a const * type template struct Cast_Helper_Inner { typedef const Result * Result_Type; + static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *) + { + if (ob.get_type_info().bare_equal_type_info(typeid(Result))) + { + return static_cast(ob.get_const_ptr()); + } else { + throw chaiscript::detail::exception::bad_any_cast(); + } + } + }; + + /// Cast_Helper_Inner for casting to a * type + template + struct Cast_Helper_Inner + { + typedef Result * Result_Type; + + static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *) + { + if (!ob.get_type_info().is_const() && ob.get_type_info().bare_equal_type_info(typeid(Result))) + { + return static_cast(ob.get_ptr()); + } else { + throw chaiscript::detail::exception::bad_any_cast(); + } + } + }; +*/ + + template + struct Cast_Helper_Inner + { + typedef const Result * Result_Type; static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *) { if (ob.is_ref()) @@ -95,13 +124,12 @@ namespace chaiscript }; /** - * Cast_Helper_Inner for casting to a * type - */ + * * Cast_Helper_Inner for casting to a * type + * */ template struct Cast_Helper_Inner { typedef Result * Result_Type; - static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *) { if (ob.is_ref()) @@ -113,6 +141,7 @@ namespace chaiscript } }; + /** * Cast_Helper_Inner for casting to a & type */ @@ -123,12 +152,11 @@ namespace chaiscript static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *) { - if (ob.is_ref()) + if (!ob.get_type_info().is_const() && ob.get_type_info().bare_equal_type_info(typeid(Result))) { - return ob.get().cast >(); + return *(static_cast(throw_if_null(ob.get_ptr()))); } else { - Result &r = *(ob.get().cast >()); - return r; + throw chaiscript::detail::exception::bad_any_cast(); } } }; diff --git a/unittests/null_object_access.chai b/unittests/null_object_access.chai index 3ee1c9a..2a4a06c 100644 --- a/unittests/null_object_access.chai +++ b/unittests/null_object_access.chai @@ -1,6 +1,6 @@ load_module("test_module") -auto o = null_factory(); +auto o := null_factory(); try { o.func(); From 3bd2a9c00d6ab4fb6020d4f62fc4b4b5e81d991e Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 10 Sep 2014 07:40:16 -0600 Subject: [PATCH 08/63] Clean up bind_first implementation --- include/chaiscript/dispatchkit/bind_first.hpp | 71 +------------------ 1 file changed, 3 insertions(+), 68 deletions(-) diff --git a/include/chaiscript/dispatchkit/bind_first.hpp b/include/chaiscript/dispatchkit/bind_first.hpp index 16f95b0..6030e98 100644 --- a/include/chaiscript/dispatchkit/bind_first.hpp +++ b/include/chaiscript/dispatchkit/bind_first.hpp @@ -13,80 +13,15 @@ namespace chaiscript { namespace detail { - - template - struct Placeholder - { - }; - - template<> - struct Placeholder<1> - { - static decltype(std::placeholders::_1) value() { return std::placeholders::_1; } - }; - - template<> - struct Placeholder<2> - { - static decltype(std::placeholders::_2) value() { return std::placeholders::_2; } - }; - - template<> - struct Placeholder<3> - { - static decltype(std::placeholders::_3) value() { return std::placeholders::_3; } - }; - - template<> - struct Placeholder<4> - { - static decltype(std::placeholders::_4) value() { return std::placeholders::_4; } - }; - - template<> - struct Placeholder<5> - { - static decltype(std::placeholders::_5) value() { return std::placeholders::_5; } - }; - - template<> - struct Placeholder<6> - { - static decltype(std::placeholders::_6) value() { return std::placeholders::_6; } - }; - - template<> - struct Placeholder<7> - { - static decltype(std::placeholders::_7) value() { return std::placeholders::_7; } - }; - - template<> - struct Placeholder<8> - { - static decltype(std::placeholders::_8) value() { return std::placeholders::_8; } - }; - - template<> - struct Placeholder<9> - { - static decltype(std::placeholders::_9) value() { return std::placeholders::_9; } - }; - - template<> - struct Placeholder<10> - { - static decltype(std::placeholders::_10) value() { return std::placeholders::_10; } - }; - - template struct Bind_First { template static std::function bind(F f, InnerParams ... innerparams) { - return Bind_First::bind(f, innerparams..., Placeholder::value()); + static auto placeholder = std::make_tuple(std::placeholders::_1,std::placeholders::_2,std::placeholders::_3,std::placeholders::_4,std::placeholders::_5,std::placeholders::_6,std::placeholders::_7,std::placeholders::_8,std::placeholders::_9,std::placeholders::_10); + + return Bind_First::bind(f, innerparams..., std::get(placeholder)); } }; From 243f4001d198480284b13248e018370ac16d590d Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 12 Sep 2014 15:16:24 -0600 Subject: [PATCH 09/63] Code cleanups --- include/chaiscript/dispatchkit/bind_first.hpp | 72 +--- include/chaiscript/dispatchkit/bootstrap.hpp | 32 +- .../dispatchkit/boxed_cast_helper.hpp | 87 +--- include/chaiscript/dispatchkit/operators.hpp | 403 +++++++++--------- 4 files changed, 235 insertions(+), 359 deletions(-) diff --git a/include/chaiscript/dispatchkit/bind_first.hpp b/include/chaiscript/dispatchkit/bind_first.hpp index 16f95b0..83ff560 100644 --- a/include/chaiscript/dispatchkit/bind_first.hpp +++ b/include/chaiscript/dispatchkit/bind_first.hpp @@ -14,71 +14,13 @@ namespace chaiscript namespace detail { - template - struct Placeholder - { + struct Placeholder + { + static const std::tuple& placeholder() { + static const std::tuple d(std::placeholders::_1,std::placeholders::_2,std::placeholders::_3,std::placeholders::_4,std::placeholders::_5,std::placeholders::_6,std::placeholders::_7,std::placeholders::_8,std::placeholders::_9,std::placeholders::_10); + return d; }; - - template<> - struct Placeholder<1> - { - static decltype(std::placeholders::_1) value() { return std::placeholders::_1; } - }; - - template<> - struct Placeholder<2> - { - static decltype(std::placeholders::_2) value() { return std::placeholders::_2; } - }; - - template<> - struct Placeholder<3> - { - static decltype(std::placeholders::_3) value() { return std::placeholders::_3; } - }; - - template<> - struct Placeholder<4> - { - static decltype(std::placeholders::_4) value() { return std::placeholders::_4; } - }; - - template<> - struct Placeholder<5> - { - static decltype(std::placeholders::_5) value() { return std::placeholders::_5; } - }; - - template<> - struct Placeholder<6> - { - static decltype(std::placeholders::_6) value() { return std::placeholders::_6; } - }; - - template<> - struct Placeholder<7> - { - static decltype(std::placeholders::_7) value() { return std::placeholders::_7; } - }; - - template<> - struct Placeholder<8> - { - static decltype(std::placeholders::_8) value() { return std::placeholders::_8; } - }; - - template<> - struct Placeholder<9> - { - static decltype(std::placeholders::_9) value() { return std::placeholders::_9; } - }; - - template<> - struct Placeholder<10> - { - static decltype(std::placeholders::_10) value() { return std::placeholders::_10; } - }; - + }; template struct Bind_First @@ -86,7 +28,7 @@ namespace chaiscript template static std::function bind(F f, InnerParams ... innerparams) { - return Bind_First::bind(f, innerparams..., Placeholder::value()); + return Bind_First::bind(f, innerparams..., std::get(Placeholder::placeholder())); } }; diff --git a/include/chaiscript/dispatchkit/bootstrap.hpp b/include/chaiscript/dispatchkit/bootstrap.hpp index 32aa939..870d506 100644 --- a/include/chaiscript/dispatchkit/bootstrap.hpp +++ b/include/chaiscript/dispatchkit/bootstrap.hpp @@ -113,9 +113,7 @@ namespace chaiscript } - /** - * to_string function for internal use. Uses ostream operator<< - */ + /// to_string function for internal use. Uses ostream operator<< template std::string to_string(Input i) { @@ -124,10 +122,8 @@ namespace chaiscript return ss.str(); } - /** - * Internal function for converting from a string to a value - * uses ostream operator >> to perform the conversion - */ + /// Internal function for converting from a string to a value + /// uses ostream operator >> to perform the conversion template Input parse_string(const std::string &i) { @@ -136,12 +132,10 @@ namespace chaiscript ss >> t; return t; } - - - /** - * Add all common functions for a POD type. All operators, and - * common conversions - */ + + + /// Add all common functions for a POD type. All operators, and + /// common conversions template ModulePtr bootstrap_pod_type(const std::string &name, ModulePtr m = ModulePtr(new Module())) { @@ -155,13 +149,11 @@ namespace chaiscript } - /** - * "clone" function for a shared_ptr type. This is used in the case - * where you do not want to make a deep copy of an object during cloning - * but want to instead maintain the shared_ptr. It is needed internally - * for handling of Proxy_Function object (that is, - * function variables. - */ + /// "clone" function for a shared_ptr type. This is used in the case + /// where you do not want to make a deep copy of an object during cloning + /// but want to instead maintain the shared_ptr. It is needed internally + /// for handling of Proxy_Function object (that is, + /// function variables. template std::shared_ptr shared_ptr_clone(const std::shared_ptr &p) { diff --git a/include/chaiscript/dispatchkit/boxed_cast_helper.hpp b/include/chaiscript/dispatchkit/boxed_cast_helper.hpp index 222fd90..8ae7552 100644 --- a/include/chaiscript/dispatchkit/boxed_cast_helper.hpp +++ b/include/chaiscript/dispatchkit/boxed_cast_helper.hpp @@ -30,9 +30,7 @@ namespace chaiscript throw std::runtime_error("Attempted to dereference null Boxed_Value"); } - /** - * Generic Cast_Helper_Inner, for casting to any type - */ + /// Generic Cast_Helper_Inner, for casting to any type template struct Cast_Helper_Inner { @@ -54,50 +52,13 @@ namespace chaiscript { }; - /** - * Cast_Helper_Inner for casting to a const & type - */ + /// Cast_Helper_Inner for casting to a const & type template struct Cast_Helper_Inner : Cast_Helper_Inner { }; - /* /// Cast_Helper_Inner for casting to a const * type - template - struct Cast_Helper_Inner - { - typedef const Result * Result_Type; - - static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *) - { - if (ob.get_type_info().bare_equal_type_info(typeid(Result))) - { - return static_cast(ob.get_const_ptr()); - } else { - throw chaiscript::detail::exception::bad_any_cast(); - } - } - }; - - /// Cast_Helper_Inner for casting to a * type - template - struct Cast_Helper_Inner - { - typedef Result * Result_Type; - - static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *) - { - if (!ob.get_type_info().is_const() && ob.get_type_info().bare_equal_type_info(typeid(Result))) - { - return static_cast(ob.get_ptr()); - } else { - throw chaiscript::detail::exception::bad_any_cast(); - } - } - }; -*/ - template struct Cast_Helper_Inner { @@ -123,9 +84,7 @@ namespace chaiscript } }; - /** - * * Cast_Helper_Inner for casting to a * type - * */ + /// Cast_Helper_Inner for casting to a * type template struct Cast_Helper_Inner { @@ -142,9 +101,7 @@ namespace chaiscript }; - /** - * Cast_Helper_Inner for casting to a & type - */ + /// Cast_Helper_Inner for casting to a & type template struct Cast_Helper_Inner { @@ -161,9 +118,7 @@ namespace chaiscript } }; - /** - * Cast_Helper_Inner for casting to a std::shared_ptr<> type - */ + /// Cast_Helper_Inner for casting to a std::shared_ptr<> type template struct Cast_Helper_Inner > { @@ -175,9 +130,7 @@ namespace chaiscript } }; - /** - * Cast_Helper_Inner for casting to a std::shared_ptr type - */ + /// Cast_Helper_Inner for casting to a std::shared_ptr type template struct Cast_Helper_Inner > { @@ -194,9 +147,7 @@ namespace chaiscript } }; - /** - * Cast_Helper_Inner for casting to a const std::shared_ptr<> & type - */ + /// Cast_Helper_Inner for casting to a const std::shared_ptr<> & type template struct Cast_Helper_Inner > : Cast_Helper_Inner > { @@ -208,9 +159,7 @@ namespace chaiscript }; - /** - * Cast_Helper_Inner for casting to a const std::shared_ptr & type - */ + /// Cast_Helper_Inner for casting to a const std::shared_ptr & type template struct Cast_Helper_Inner > : Cast_Helper_Inner > { @@ -223,9 +172,7 @@ namespace chaiscript - /** - * Cast_Helper_Inner for casting to a Boxed_Value type - */ + /// Cast_Helper_Inner for casting to a Boxed_Value type template<> struct Cast_Helper_Inner { @@ -237,9 +184,7 @@ namespace chaiscript } }; - /** - * Cast_Helper_Inner for casting to a Boxed_Value & type - */ + /// Cast_Helper_Inner for casting to a Boxed_Value & type template<> struct Cast_Helper_Inner { @@ -252,9 +197,7 @@ namespace chaiscript }; - /** - * Cast_Helper_Inner for casting to a const Boxed_Value & type - */ + /// Cast_Helper_Inner for casting to a const Boxed_Value & type template<> struct Cast_Helper_Inner : Cast_Helper_Inner { @@ -266,9 +209,7 @@ namespace chaiscript }; - /** - * Cast_Helper_Inner for casting to a std::reference_wrapper type - */ + /// Cast_Helper_Inner for casting to a std::reference_wrapper type template struct Cast_Helper_Inner > : Cast_Helper_Inner { @@ -299,9 +240,7 @@ namespace chaiscript { }; - /** - * The exposed Cast_Helper object that by default just calls the Cast_Helper_Inner - */ + /// The exposed Cast_Helper object that by default just calls the Cast_Helper_Inner template struct Cast_Helper { diff --git a/include/chaiscript/dispatchkit/operators.hpp b/include/chaiscript/dispatchkit/operators.hpp index ed64b2c..4c2369f 100644 --- a/include/chaiscript/dispatchkit/operators.hpp +++ b/include/chaiscript/dispatchkit/operators.hpp @@ -8,6 +8,7 @@ #define CHAISCRIPT_OPERATORS_HPP_ #include "../chaiscript_defines.hpp" +#include "register_function.hpp" namespace chaiscript { @@ -15,442 +16,444 @@ namespace chaiscript { namespace operators { - template - Ret assign(L l, R r) - { - return (l = r); - } + namespace detail + { + template + auto assign(L l, R r) -> decltype((l = r)) + { + return (l = r); + } - template - Ret assign_bitwise_and(L l, R r) - { - return (l &= r); - } + template + auto assign_bitwise_and(L l, R r) -> decltype((l &r)) + { + return (l &= r); + } - template - Ret assign_xor(L l, R r) - { - return (l ^= r); - } + template + auto assign_xor(L l, R r) -> decltype((l^=r)) + { + return (l ^= r); + } - template - Ret assign_bitwise_or(L l, R r) - { - return (l |= r); - } + template + auto assign_bitwise_or(L l, R r) -> decltype((l |= r)) + { + return (l |= r); + } - template - Ret assign_difference(L l, R r) - { - return (l -= r); - } + template + auto assign_difference(L l, R r) -> decltype(( l -= r)) + { + return (l -= r); + } - template - Ret assign_left_shift(L l, R r) - { - return (l <<= r); - } + template + auto assign_left_shift(L l, R r) -> decltype(( l <<= r)) + { + return (l <<= r); + } - template - Ret assign_product(L l, R r) - { - return (l *= r); - } + template + auto assign_product(L l, R r) -> decltype(( l *= r )) + { + return (l *= r); + } - template - Ret assign_quotient(L l, R r) - { - return (l /= r); - } + template + auto assign_quotient(L l, R r) -> decltype(( l /= r )) + { + return (l /= r); + } - template - Ret assign_remainder(L l, R r) - { - return (l %= r); - } + template + auto assign_remainder(L l, R r) -> decltype(( l %= r )) + { + return (l %= r); + } - template - Ret assign_right_shift(L l, R r) - { - return (l >>= r); - } + template + auto assign_right_shift(L l, R r) -> decltype(( l >>= r)) + { + return (l >>= r); + } - template - Ret assign_sum(L l, R r) - { - return (l += r); - } + template + auto assign_sum(L l, R r) -> decltype(( l += r)) + { + return (l += r); + } - template - Ret prefix_decrement(L l) - { - return (--l); - } + template + auto prefix_decrement(L l) -> decltype(( --l )) + { + return (--l); + } - template - Ret prefix_increment(L l) - { - return (++l); - } + template + auto prefix_increment(L l) -> decltype(( ++l )) + { + return (++l); + } - template - Ret equal(L l, R r) - { - return (l == r); - } + template + auto equal(L l, R r) -> decltype(( l == r )) + { + return (l == r); + } - template - Ret greater_than(L l, R r) - { - return (l > r); - } + template + auto greater_than(L l, R r) -> decltype(( l > r )) + { + return (l > r); + } - template - Ret greater_than_equal(L l, R r) - { - return (l >= r); - } + template + auto greater_than_equal(L l, R r) -> decltype(( l >= r )) + { + return (l >= r); + } - template - Ret less_than(L l, R r) - { - return (l < r); - } + template + auto less_than(L l, R r) -> decltype(( l < r )) + { + return (l < r); + } - template - Ret less_than_equal(L l, R r) - { - return (l <= r); - } + template + auto less_than_equal(L l, R r) -> decltype(( l <= r )) + { + return (l <= r); + } - template - Ret logical_compliment(L l) - { - return (!l); - } + template + auto logical_compliment(L l) -> decltype(( !l )) + { + return (!l); + } - template - Ret not_equal(L l, R r) - { - return (l != r); - } + template + auto not_equal(L l, R r) -> decltype(( l != r )) + { + return (l != r); + } - template - Ret addition(L l, R r) - { - return (l + r); - } + template + auto addition(L l, R r) -> decltype(( l + r )) + { + return (l + r); + } - template - Ret unary_plus(L l) - { - return (+l); - } + template + auto unary_plus(L l) -> decltype(( +l )) + { + return (+l); + } - template - Ret subtraction(L l, R r) - { - return (l - r); - } + template + auto subtraction(L l, R r) -> decltype(( l - r )) + { + return (l - r); + } - template - Ret unary_minus(L l) - { + template + auto unary_minus(L l) -> decltype(( -l )) + { #ifdef CHAISCRIPT_MSVC #pragma warning(push) #pragma warning(disable : 4146) - return (-l); + return (-l); #pragma warning(pop) #else - return (-l); + return (-l); #endif - } + } - template - Ret bitwise_and(L l, R r) - { - return (l & r); - } + template + auto bitwise_and(L l, R r) -> decltype(( l & r )) + { + return (l & r); + } - template - Ret bitwise_compliment(L l) - { - return (~l); - } + template + auto bitwise_compliment(L l) -> decltype(( ~l )) + { + return (~l); + } - template - Ret bitwise_xor(L l, R r) - { - return (l ^ r); - } + template + auto bitwise_xor(L l, R r) -> decltype(( l ^ r )) + { + return (l ^ r); + } - template - Ret bitwise_or(L l, R r) - { - return (l | r); - } + template + auto bitwise_or(L l, R r) -> decltype(( l | r )) + { + return (l | r); + } - template - Ret division(L l, R r) - { - return (l / r); - } + template + auto division(L l, R r) -> decltype(( l / r )) + { + return (l / r); + } - template - Ret left_shift(L l, R r) - { - return l << r; - } + template + auto left_shift(L l, R r) -> decltype(( l << r )) + { + return l << r; + } - template - Ret multiplication(L l, R r) - { - return l * r; - } + template + auto multiplication(L l, R r) -> decltype(( l * r )) + { + return l * r; + } - template - Ret remainder(L l, R r) - { - return (l % r); - } - - template - Ret right_shift(L l, R r) - { - return (l >> r); - } + template + auto remainder(L l, R r) -> decltype(( l % r )) + { + return (l % r); + } + template + auto right_shift(L l, R r) -> decltype(( l >> r )) + { + return (l >> r); + } + } template ModulePtr assign(ModulePtr m = ModulePtr(new Module())) { - m->add(fun(&assign), "="); + m->add(chaiscript::fun(&detail::assign), "="); return m; } template ModulePtr assign_bitwise_and(ModulePtr m = ModulePtr(new Module())) { - m->add(fun(&assign_bitwise_and), "&="); + m->add(chaiscript::fun(&detail::assign_bitwise_and), "&="); return m; } template ModulePtr assign_xor(ModulePtr m = ModulePtr(new Module())) { - m->add(fun(&assign_xor), "^="); + m->add(chaiscript::fun(&detail::assign_xor), "^="); return m; } template ModulePtr assign_bitwise_or(ModulePtr m = ModulePtr(new Module())) { - m->add(fun(&assign_bitwise_or), "|="); + m->add(chaiscript::fun(&detail::assign_bitwise_or), "|="); return m; } template ModulePtr assign_difference(ModulePtr m = ModulePtr(new Module())) { - m->add(fun(&assign_difference), "-="); + m->add(chaiscript::fun(&detail::assign_difference), "-="); return m; } template ModulePtr assign_left_shift(ModulePtr m = ModulePtr(new Module())) { - m->add(fun(&assign_left_shift), "<<="); + m->add(chaiscript::fun(&detail::assign_left_shift), "<<="); return m; } template ModulePtr assign_product(ModulePtr m = ModulePtr(new Module())) { - m->add(fun(&assign_product), "*="); + m->add(chaiscript::fun(&detail::assign_product), "*="); return m; } template ModulePtr assign_quotient(ModulePtr m = ModulePtr(new Module())) { - m->add(fun(&assign_quotient), "/="); + m->add(chaiscript::fun(&detail::assign_quotient), "/="); return m; } template ModulePtr assign_remainder(ModulePtr m = ModulePtr(new Module())) { - m->add(fun(&assign_remainder), "%="); + m->add(chaiscript::fun(&detail::assign_remainder), "%="); return m; } template ModulePtr assign_right_shift(ModulePtr m = ModulePtr(new Module())) { - m->add(fun(&assign_right_shift), ">>="); + m->add(chaiscript::fun(&detail::assign_right_shift), ">>="); return m; } template ModulePtr assign_sum(ModulePtr m = ModulePtr(new Module())) { - m->add(fun(&assign_sum), "+="); + m->add(chaiscript::fun(&detail::assign_sum), "+="); return m; } template ModulePtr prefix_decrement(ModulePtr m = ModulePtr(new Module())) { - m->add(fun(&prefix_decrement), "--"); + m->add(chaiscript::fun(&detail::prefix_decrement), "--"); return m; } template ModulePtr prefix_increment(ModulePtr m = ModulePtr(new Module())) { - m->add(fun(&prefix_increment), "++"); + m->add(chaiscript::fun(&detail::prefix_increment), "++"); return m; } template ModulePtr equal(ModulePtr m = ModulePtr(new Module())) { - m->add(fun(&equal), "=="); + m->add(chaiscript::fun(&detail::equal), "=="); return m; } template ModulePtr greater_than(ModulePtr m = ModulePtr(new Module())) { - m->add(fun(&greater_than), ">"); + m->add(chaiscript::fun(&detail::greater_than), ">"); return m; } template ModulePtr greater_than_equal(ModulePtr m = ModulePtr(new Module())) { - m->add(fun(&greater_than_equal), ">="); + m->add(chaiscript::fun(&detail::greater_than_equal), ">="); return m; } template ModulePtr less_than(ModulePtr m = ModulePtr(new Module())) { - m->add(fun(&less_than), "<"); + m->add(chaiscript::fun(&detail::less_than), "<"); return m; } template ModulePtr less_than_equal(ModulePtr m = ModulePtr(new Module())) { - m->add(fun(&less_than_equal), "<="); + m->add(chaiscript::fun(&detail::less_than_equal), "<="); return m; } template ModulePtr logical_compliment(ModulePtr m = ModulePtr(new Module())) { - m->add(fun(&logical_compliment), "!"); + m->add(chaiscript::fun(&detail::logical_compliment), "!"); return m; } template ModulePtr not_equal(ModulePtr m = ModulePtr(new Module())) { - m->add(fun(¬_equal), "!="); + m->add(chaiscript::fun(&detail::not_equal), "!="); return m; } template ModulePtr addition(ModulePtr m = ModulePtr(new Module())) { - m->add(fun(&addition), "+"); + m->add(chaiscript::fun(&detail::addition), "+"); return m; } template ModulePtr unary_plus(ModulePtr m = ModulePtr(new Module())) { - m->add(fun(&unary_plus), "+"); + m->add(chaiscript::fun(&detail::unary_plus), "+"); return m; } template ModulePtr subtraction(ModulePtr m = ModulePtr(new Module())) { - m->add(fun(&subtraction), "-"); + m->add(chaiscript::fun(&detail::subtraction), "-"); return m; } template ModulePtr unary_minus(ModulePtr m = ModulePtr(new Module())) { - m->add(fun(&unary_minus), "-"); + m->add(chaiscript::fun(&detail::unary_minus), "-"); return m; } template ModulePtr bitwise_and(ModulePtr m = ModulePtr(new Module())) { - m->add(fun(&bitwise_and), "&"); + m->add(chaiscript::fun(&detail::bitwise_and), "&"); return m; } template ModulePtr bitwise_compliment(ModulePtr m = ModulePtr(new Module())) { - m->add(fun(&bitwise_compliment), "~"); + m->add(chaiscript::fun(&detail::bitwise_compliment), "~"); return m; } template ModulePtr bitwise_xor(ModulePtr m = ModulePtr(new Module())) { - m->add(fun(&bitwise_xor), "^"); + m->add(chaiscript::fun(&detail::bitwise_xor), "^"); return m; } template ModulePtr bitwise_or(ModulePtr m = ModulePtr(new Module())) { - m->add(fun(&bitwise_or), "|"); + m->add(chaiscript::fun(&detail::bitwise_or), "|"); return m; } template ModulePtr division(ModulePtr m = ModulePtr(new Module())) { - m->add(fun(&division), "/"); + m->add(chaiscript::fun(&detail::division), "/"); return m; } template ModulePtr left_shift(ModulePtr m = ModulePtr(new Module())) { - m->add(fun(&left_shift), "<<"); + m->add(chaiscript::fun(&detail::left_shift), "<<"); return m; } template ModulePtr multiplication(ModulePtr m = ModulePtr(new Module())) { - m->add(fun(&multiplication), "*"); + m->add(chaiscript::fun(&detail::multiplication), "*"); return m; } template ModulePtr remainder(ModulePtr m = ModulePtr(new Module())) { - m->add(fun(&remainder), "%"); + m->add(chaiscript::fun(&detail::remainder), "%"); return m; } template ModulePtr right_shift(ModulePtr m = ModulePtr(new Module())) { - m->add(fun(&right_shift), ">>"); + m->add(chaiscript::fun(&detail::right_shift), ">>"); return m; } } From bd8a78eccc954dbfc4812b1db543085ad9399014 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 13 Sep 2014 21:53:12 -0600 Subject: [PATCH 10/63] Initial decent_ci files --- .decent_ci-Linux.yaml | 7 +++++++ .decent_ci-MacOS.yaml | 7 +++++++ .decent_ci-Windows.yaml | 10 ++++++++++ .decent_ci.yaml | 4 ++++ 4 files changed, 28 insertions(+) create mode 100644 .decent_ci-Linux.yaml create mode 100644 .decent_ci-MacOS.yaml create mode 100644 .decent_ci-Windows.yaml create mode 100644 .decent_ci.yaml diff --git a/.decent_ci-Linux.yaml b/.decent_ci-Linux.yaml new file mode 100644 index 0000000..1c26267 --- /dev/null +++ b/.decent_ci-Linux.yaml @@ -0,0 +1,7 @@ +compilers: + - name: "gcc" + version: "4.8" + cmake_extra_flags: -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=$COMMIT_SHA + - name: cppcheck + compiler_extra_flags: --enable=all + diff --git a/.decent_ci-MacOS.yaml b/.decent_ci-MacOS.yaml new file mode 100644 index 0000000..7e8c6cf --- /dev/null +++ b/.decent_ci-MacOS.yaml @@ -0,0 +1,7 @@ +compilers: + - name: clang + cmake_extra_flags: -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=$COMMIT_SHA + - name: clang + build_type: Debug + cmake_extra_flags: -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=$COMMIT_SHA + diff --git a/.decent_ci-Windows.yaml b/.decent_ci-Windows.yaml new file mode 100644 index 0000000..717c269 --- /dev/null +++ b/.decent_ci-Windows.yaml @@ -0,0 +1,10 @@ +compilers: + - name: Visual Studio + version: 12 + cmake_extra_flags: -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA% + - name: Visual Studio + version: 12 + architecture: Win64 + cmake_extra_flags: -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA% + + diff --git a/.decent_ci.yaml b/.decent_ci.yaml new file mode 100644 index 0000000..26d16a9 --- /dev/null +++ b/.decent_ci.yaml @@ -0,0 +1,4 @@ +results_repository : NREL/ChaiScript-BuildResults +results_path : _posts +results_base_url : https://chaiscript.github.io/ChaiScript-BuildResults +aging_pull_requests_notification: true From 7b28f9ef57091c7a442f98d946f279231d5e7323 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 13 Sep 2014 23:11:17 -0600 Subject: [PATCH 11/63] Fix results location --- .decent_ci.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.decent_ci.yaml b/.decent_ci.yaml index 26d16a9..e917c17 100644 --- a/.decent_ci.yaml +++ b/.decent_ci.yaml @@ -1,4 +1,4 @@ -results_repository : NREL/ChaiScript-BuildResults +results_repository : ChaiScript/ChaiScript-BuildResults results_path : _posts results_base_url : https://chaiscript.github.io/ChaiScript-BuildResults aging_pull_requests_notification: true From 0036ebfe5d8fe0292e45910777656fb46dfe9cc2 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sun, 14 Sep 2014 12:44:20 -0600 Subject: [PATCH 12/63] Update .decent_ci-Windows.yaml --- .decent_ci-Windows.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.decent_ci-Windows.yaml b/.decent_ci-Windows.yaml index 717c269..6a93f1a 100644 --- a/.decent_ci-Windows.yaml +++ b/.decent_ci-Windows.yaml @@ -2,9 +2,11 @@ compilers: - name: Visual Studio version: 12 cmake_extra_flags: -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA% + compiler_extra_flags: /ANALYZE - name: Visual Studio version: 12 architecture: Win64 cmake_extra_flags: -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA% + compiler_extra_flags: /ANALYZE From 6c2ccf3869fb7a5bebf9a010afc0785d3cabba43 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sun, 14 Sep 2014 21:53:11 -0600 Subject: [PATCH 13/63] Various cleanups prefering lambda to bind --- include/chaiscript/dispatchkit/bootstrap.hpp | 3 +- .../dispatchkit/proxy_functions_detail.hpp | 31 ++----------------- .../chaiscript/language/chaiscript_engine.hpp | 6 ++-- .../chaiscript/language/chaiscript_eval.hpp | 28 +++++++++++------ 4 files changed, 25 insertions(+), 43 deletions(-) diff --git a/include/chaiscript/dispatchkit/bootstrap.hpp b/include/chaiscript/dispatchkit/bootstrap.hpp index 870d506..76058d4 100644 --- a/include/chaiscript/dispatchkit/bootstrap.hpp +++ b/include/chaiscript/dispatchkit/bootstrap.hpp @@ -496,8 +496,7 @@ namespace chaiscript m->add(fun(&print), "print_string"); m->add(fun(&println), "println_string"); - m->add(Proxy_Function(new dispatch::Dynamic_Proxy_Function(std::bind(&bind_function, std::placeholders::_1))), - "bind"); + m->add(Proxy_Function(new dispatch::Dynamic_Proxy_Function(&bind_function)), "bind"); m->add(fun(&shared_ptr_unconst_clone), "clone"); m->add(fun(&ptr_assign::type>), "="); diff --git a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp index fa725f8..b908d1f 100644 --- a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp @@ -53,29 +53,6 @@ namespace chaiscript { namespace detail { - template - struct Build_Param_Type_List; - - template - struct Build_Param_Type_List - { - static void build(std::vector &t_params) - { - t_params.push_back(chaiscript::detail::Get_Type_Info::get()); - Build_Param_Type_List::build(t_params); - } - }; - - // 0th case - template<> - struct Build_Param_Type_List<> - { - static void build(std::vector &) - { - } - }; - - /** * Used by Proxy_Function_Impl to return a list of all param types * it contains. @@ -83,12 +60,8 @@ namespace chaiscript template std::vector build_param_type_list(Ret (*)(Params...)) { - /// \todo this code was previously using { chaiscript::detail::Get_Type_Info::get()... } - /// but this seems to indicate another bug with MSVC's uniform initializer lists - std::vector params; - params.push_back(chaiscript::detail::Get_Type_Info::get()); - Build_Param_Type_List::build(params); - return params; + /// \note somehow this is responsible for a large part of the code generation + return { user_type(), user_type()... }; } diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index af01ce3..8b96ef5 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -345,8 +345,10 @@ namespace chaiscript m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::function_exists, std::ref(m_engine)), "function_exists"); m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_function_objects, std::ref(m_engine)), "get_functions"); m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_scripting_objects, std::ref(m_engine)), "get_objects"); - m_engine.add(Proxy_Function(new dispatch::Dynamic_Proxy_Function(std::bind(&chaiscript::detail::Dispatch_Engine::call_exists, std::ref(m_engine), std::placeholders::_1))), - "call_exists"); + m_engine.add(Proxy_Function(new dispatch::Dynamic_Proxy_Function( + [this](const std::vector &t_params) { + return m_engine.call_exists(t_params); + })), "call_exists"); m_engine.add(fun &)>(std::bind(&chaiscript::dispatch::Proxy_Function_Base::operator(), std::placeholders::_1, std::placeholders::_2, std::ref(m_engine.conversions()))), "call"); m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_type_name, std::ref(m_engine)), "name"); diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index f40a9fc..b1ee795 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -732,9 +732,14 @@ namespace chaiscript numparams = 0; } - return Boxed_Value(Proxy_Function(new dispatch::Dynamic_Proxy_Function - (std::bind(chaiscript::eval::detail::eval_function, std::ref(t_ss), this->children.back(), t_param_names, std::placeholders::_1), - static_cast(numparams), this->children.back()))); + const auto &lambda_node = this->children.back(); + + return Boxed_Value(Proxy_Function(new dispatch::Dynamic_Proxy_Function( + [&t_ss, lambda_node, t_param_names](const std::vector &t_params) + { + return detail::eval_function(t_ss, lambda_node, t_param_names, t_params); + }, + static_cast(numparams), lambda_node))); } }; @@ -800,19 +805,22 @@ namespace chaiscript std::shared_ptr guard; if (guardnode) { guard = std::shared_ptr - (new dispatch::Dynamic_Proxy_Function(std::bind(chaiscript::eval::detail::eval_function, - std::ref(t_ss), guardnode, - t_param_names, std::placeholders::_1), static_cast(numparams), guardnode)); + (new dispatch::Dynamic_Proxy_Function([&t_ss, guardnode, t_param_names](const std::vector &t_params) + { + return detail::eval_function(t_ss, guardnode, t_param_names, t_params); + }, static_cast(numparams), guardnode)); } try { const std::string & l_function_name = this->children[0]->text; const std::string & l_annotation = this->annotation?this->annotation->text:""; + const auto & func_node = this->children.back(); t_ss.add(Proxy_Function - (new dispatch::Dynamic_Proxy_Function(std::bind(chaiscript::eval::detail::eval_function, - std::ref(t_ss), this->children.back(), - t_param_names, std::placeholders::_1), static_cast(numparams), this->children.back(), - l_annotation, guard)), l_function_name); + (new dispatch::Dynamic_Proxy_Function([&t_ss, guardnode, func_node, t_param_names](const std::vector &t_params) + { + return detail::eval_function(t_ss, func_node, t_param_names, t_params); + }, static_cast(numparams), this->children.back(), + l_annotation, guard)), l_function_name); } catch (const exception::reserved_word_error &e) { throw exception::eval_error("Reserved word used as function name '" + e.word() + "'"); From 3ccb1553580541a25520ceb9852ddb547601cb1d Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sun, 14 Sep 2014 21:57:07 -0600 Subject: [PATCH 14/63] Fix up usage of cppcheck, enable samples build --- .decent_ci-Linux.yaml | 4 ++-- .decent_ci-MacOS.yaml | 4 ++-- .decent_ci-Windows.yaml | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.decent_ci-Linux.yaml b/.decent_ci-Linux.yaml index 1c26267..9fefee7 100644 --- a/.decent_ci-Linux.yaml +++ b/.decent_ci-Linux.yaml @@ -1,7 +1,7 @@ compilers: - name: "gcc" version: "4.8" - cmake_extra_flags: -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=$COMMIT_SHA + cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=$COMMIT_SHA - name: cppcheck - compiler_extra_flags: --enable=all + compiler_extra_flags: --enable=all -I ../include --inline-suppr diff --git a/.decent_ci-MacOS.yaml b/.decent_ci-MacOS.yaml index 7e8c6cf..b68ed8e 100644 --- a/.decent_ci-MacOS.yaml +++ b/.decent_ci-MacOS.yaml @@ -1,7 +1,7 @@ compilers: - name: clang - cmake_extra_flags: -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=$COMMIT_SHA + cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=$COMMIT_SHA - name: clang build_type: Debug - cmake_extra_flags: -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=$COMMIT_SHA + cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=$COMMIT_SHA diff --git a/.decent_ci-Windows.yaml b/.decent_ci-Windows.yaml index 6a93f1a..f6d9dc4 100644 --- a/.decent_ci-Windows.yaml +++ b/.decent_ci-Windows.yaml @@ -1,12 +1,12 @@ compilers: - name: Visual Studio version: 12 - cmake_extra_flags: -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA% + cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA% compiler_extra_flags: /ANALYZE - name: Visual Studio version: 12 architecture: Win64 - cmake_extra_flags: -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA% + cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA% compiler_extra_flags: /ANALYZE From d62a452a9d73be5955b61d453053e4bec6e3ceb4 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Mon, 15 Sep 2014 07:12:19 -0600 Subject: [PATCH 15/63] Correct -I path for cppcheck run --- .decent_ci-Linux.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.decent_ci-Linux.yaml b/.decent_ci-Linux.yaml index 9fefee7..7488d49 100644 --- a/.decent_ci-Linux.yaml +++ b/.decent_ci-Linux.yaml @@ -3,5 +3,5 @@ compilers: version: "4.8" cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=$COMMIT_SHA - name: cppcheck - compiler_extra_flags: --enable=all -I ../include --inline-suppr + compiler_extra_flags: --enable=all -I include --inline-suppr From 5861c45fc1ae4346877db24eda6098019765f4d0 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Mon, 15 Sep 2014 21:16:44 -0600 Subject: [PATCH 16/63] C++11 related cleanup and improvments --- include/chaiscript/dispatchkit/bootstrap.hpp | 8 ++--- .../chaiscript/dispatchkit/boxed_number.hpp | 4 +-- .../chaiscript/dispatchkit/boxed_value.hpp | 2 +- .../chaiscript/dispatchkit/dispatchkit.hpp | 36 +++++++------------ .../dispatchkit/proxy_constructors.hpp | 2 +- 5 files changed, 18 insertions(+), 34 deletions(-) diff --git a/include/chaiscript/dispatchkit/bootstrap.hpp b/include/chaiscript/dispatchkit/bootstrap.hpp index 76058d4..9384920 100644 --- a/include/chaiscript/dispatchkit/bootstrap.hpp +++ b/include/chaiscript/dispatchkit/bootstrap.hpp @@ -46,13 +46,9 @@ namespace chaiscript /// \param[in] v Boxed_Number to copy into the new object /// \returns The newly created object. template - std::shared_ptr construct_pod(Boxed_Number v) + std::shared_ptr construct_pod(const Boxed_Number &v) { - std::shared_ptr p(new P1()); - Boxed_Value bv(p); - Boxed_Number nb(bv); - nb = v; - return p; + return std::make_shared(v.get_as()); } } diff --git a/include/chaiscript/dispatchkit/boxed_number.hpp b/include/chaiscript/dispatchkit/boxed_number.hpp index f3d2838..3541bfb 100644 --- a/include/chaiscript/dispatchkit/boxed_number.hpp +++ b/include/chaiscript/dispatchkit/boxed_number.hpp @@ -334,8 +334,8 @@ namespace chaiscript { } - Boxed_Number(const Boxed_Value &v) - : bv(v) + Boxed_Number(Boxed_Value v) + : bv(std::move(v)) { validate_boxed_number(v); } diff --git a/include/chaiscript/dispatchkit/boxed_value.hpp b/include/chaiscript/dispatchkit/boxed_value.hpp index 861a2f7..3fe48b0 100644 --- a/include/chaiscript/dispatchkit/boxed_value.hpp +++ b/include/chaiscript/dispatchkit/boxed_value.hpp @@ -297,7 +297,7 @@ namespace chaiscript template Boxed_Value const_var_impl(const T &t) { - return Boxed_Value(std::shared_ptr::type >(new T(t))); + return Boxed_Value(std::make_shared::type >(t)); } /// \brief Takes a pointer to a value, adds const to the pointed to type and returns an immutable Boxed_Value. diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index fd539de..0b1e165 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -430,7 +430,7 @@ namespace chaiscript Dispatch_Engine() : m_stack_holder(this), - m_place_holder(std::shared_ptr(new dispatch::Placeholder_Object())) + m_place_holder(std::make_shared()) { } @@ -549,8 +549,7 @@ namespace chaiscript */ void new_scope() { - StackData &stack = get_stack_data(); - stack.push_back(Scope()); + get_stack_data().emplace_back(); } /** @@ -571,9 +570,8 @@ namespace chaiscript /// Pushes a new stack on to the list of stacks void new_stack() { - Stack s(new Stack::element_type()); - s->push_back(Scope()); - m_stack_holder->stacks.push_back(s); + // add a new Stack with 1 element + m_stack_holder->stacks.emplace_back(std::make_shared(1)); } void pop_stack() @@ -836,7 +834,7 @@ namespace chaiscript { for (const auto & internal_func : function.second) { - rets.push_back(std::make_pair(function.first, internal_func)); + rets.emplace_back(function.first, internal_func); } } @@ -867,19 +865,14 @@ namespace chaiscript return call_function(t_name, std::vector()); } - Boxed_Value call_function(const std::string &t_name, const Boxed_Value &p1) const + Boxed_Value call_function(const std::string &t_name, Boxed_Value p1) const { - std::vector params; - params.push_back(p1); - return call_function(t_name, params); + return call_function(t_name, std::vector({std::move(p1)})); } - Boxed_Value call_function(const std::string &t_name, const Boxed_Value &p1, const Boxed_Value &p2) const + Boxed_Value call_function(const std::string &t_name, Boxed_Value p1, Boxed_Value p2) const { - std::vector params; - params.push_back(p1); - params.push_back(p2); - return call_function(t_name, params); + return call_function(t_name, std::vector({std::move(p1), std::move(p2)})); } /** @@ -1219,14 +1212,11 @@ namespace chaiscript // if the function is the only function but it also contains // arithmetic operators, we must wrap it in a dispatch function // to allow for automatic arithmetic type conversions - std::vector vec; - vec.push_back(t_f); + std::vector vec({t_f}); funcs.insert(std::make_pair(t_name, vec)); func_objs[t_name] = Proxy_Function(new Dispatch_Function(vec)); } else { - std::vector vec; - vec.push_back(t_f); - funcs.insert(std::make_pair(t_name, vec)); + funcs.insert(std::make_pair(t_name, std::vector({t_f}))); func_objs[t_name] = t_f; } @@ -1241,9 +1231,7 @@ namespace chaiscript Stack_Holder() : call_depth(0) { - Stack s(new StackData()); - s->push_back(Scope()); - stacks.push_back(s); + stacks.emplace_back(std::make_shared(1)); } std::deque stacks; diff --git a/include/chaiscript/dispatchkit/proxy_constructors.hpp b/include/chaiscript/dispatchkit/proxy_constructors.hpp index 0c56f95..64d2a93 100644 --- a/include/chaiscript/dispatchkit/proxy_constructors.hpp +++ b/include/chaiscript/dispatchkit/proxy_constructors.hpp @@ -21,7 +21,7 @@ namespace chaiscript template std::shared_ptr constructor_(Params ... params) { - return std::shared_ptr(new Class(params...)); + return std::make_shared(params...); } template From 04782b6a33652cfbfe921934d599aaaae3e49216 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 16 Sep 2014 08:02:12 -0600 Subject: [PATCH 17/63] Add gcc-4.6 to test configuration --- .decent_ci-Linux.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.decent_ci-Linux.yaml b/.decent_ci-Linux.yaml index 1c26267..f7a4d1c 100644 --- a/.decent_ci-Linux.yaml +++ b/.decent_ci-Linux.yaml @@ -2,6 +2,9 @@ compilers: - name: "gcc" version: "4.8" cmake_extra_flags: -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=$COMMIT_SHA + - name: "gcc" + version: "4.6" + cmake_extra_flags: -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=$COMMIT_SHA - name: cppcheck compiler_extra_flags: --enable=all From cfd4a73a895ff01c04c6dc63b20bda222cf1ec66 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 16 Sep 2014 13:30:47 -0600 Subject: [PATCH 18/63] Add VS 2014 CI Support --- .decent_ci-Windows.yaml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.decent_ci-Windows.yaml b/.decent_ci-Windows.yaml index f6d9dc4..1f6c033 100644 --- a/.decent_ci-Windows.yaml +++ b/.decent_ci-Windows.yaml @@ -1,4 +1,13 @@ compilers: + - name: Visual Studio + version: 14 + cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA% + compiler_extra_flags: /ANALYZE + - name: Visual Studio + version: 14 + architecture: Win64 + cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA% + compiler_extra_flags: /ANALYZE - name: Visual Studio version: 12 cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA% @@ -9,4 +18,3 @@ compilers: cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA% compiler_extra_flags: /ANALYZE - From 2321f1d7097b088b2162f98b113444d1ab62b334 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Thu, 18 Sep 2014 20:07:15 -0600 Subject: [PATCH 19/63] Enable clang linux builds --- .decent_ci-Linux.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.decent_ci-Linux.yaml b/.decent_ci-Linux.yaml index 7488d49..23a2ab1 100644 --- a/.decent_ci-Linux.yaml +++ b/.decent_ci-Linux.yaml @@ -1,4 +1,7 @@ compilers: + - name: "clang" + version: "3.5" + cmake_extra_flags: -DUSE_LIB_CXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=$COMMIT_SHA - name: "gcc" version: "4.8" cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=$COMMIT_SHA From 93c1cfde99fbdee99a1b429e19eb6b31329d86c5 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Thu, 18 Sep 2014 20:48:34 -0600 Subject: [PATCH 20/63] Try out some alias templates for cleanup --- include/chaiscript/dispatchkit/boxed_cast.hpp | 2 +- include/chaiscript/dispatchkit/type_info.hpp | 25 ++++++------------- 2 files changed, 8 insertions(+), 19 deletions(-) diff --git a/include/chaiscript/dispatchkit/boxed_cast.hpp b/include/chaiscript/dispatchkit/boxed_cast.hpp index c055ac4..c86b4e1 100644 --- a/include/chaiscript/dispatchkit/boxed_cast.hpp +++ b/include/chaiscript/dispatchkit/boxed_cast.hpp @@ -86,7 +86,7 @@ namespace chaiscript #pragma warning(disable : 4127) #endif - if (std::is_polymorphic::type>::value && t_conversions) + if (std::is_polymorphic>::value && t_conversions) { try { // std::cout << "trying an up conversion " << typeid(Type).name() << std::endl; diff --git a/include/chaiscript/dispatchkit/type_info.hpp b/include/chaiscript/dispatchkit/type_info.hpp index 4944e80..afa9e9e 100644 --- a/include/chaiscript/dispatchkit/type_info.hpp +++ b/include/chaiscript/dispatchkit/type_info.hpp @@ -16,14 +16,8 @@ namespace chaiscript { - namespace detail - { - template - struct Bare_Type - { - typedef typename std::remove_cv::type>::type>::type type; - }; - } + template + using Bare_Type = typename std::remove_cv::type>::type>::type; /// \brief Compile time deduced information about a type class Type_Info @@ -151,7 +145,7 @@ namespace chaiscript std::is_void::value, std::is_arithmetic::value && !std::is_same::type, bool>::value, &typeid(T), - &typeid(typename Bare_Type::type)); + &typeid(Bare_Type)); } }; @@ -166,7 +160,7 @@ namespace chaiscript std::is_void::value, std::is_arithmetic::value && !std::is_same::type, bool>::value, &typeid(std::shared_ptr ), - &typeid(typename Bare_Type::type)); + &typeid(Bare_Type)); } }; @@ -181,7 +175,7 @@ namespace chaiscript std::is_void::value, std::is_arithmetic::value && !std::is_same::type, bool>::value, &typeid(const std::shared_ptr &), - &typeid(typename Bare_Type::type)); + &typeid(Bare_Type)); } }; @@ -196,7 +190,7 @@ namespace chaiscript std::is_void::value, std::is_arithmetic::value && !std::is_same::type, bool>::value, &typeid(std::reference_wrapper ), - &typeid(typename Bare_Type::type)); + &typeid(Bare_Type)); } }; @@ -211,15 +205,10 @@ namespace chaiscript std::is_void::value, std::is_arithmetic::value && !std::is_same::type, bool>::value, &typeid(const std::reference_wrapper &), - &typeid(typename Bare_Type::type)); + &typeid(Bare_Type)); } }; - template - struct Stripped_Type - { - typedef typename Bare_Type::type>::type type; - }; } /// \brief Creates a Type_Info object representing the type passed in From ae1897e2ea0fc7bdfa9a9404e9341d5cf02a068a Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 19 Sep 2014 10:25:04 -0600 Subject: [PATCH 21/63] Update to force CI rebuild --- .decent_ci-Linux.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.decent_ci-Linux.yaml b/.decent_ci-Linux.yaml index 23a2ab1..6226d07 100644 --- a/.decent_ci-Linux.yaml +++ b/.decent_ci-Linux.yaml @@ -1,7 +1,7 @@ compilers: - name: "clang" version: "3.5" - cmake_extra_flags: -DUSE_LIB_CXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=$COMMIT_SHA + cmake_extra_flags: -DUSE_LIB_CXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=$COMMIT_SHA - name: "gcc" version: "4.8" cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=$COMMIT_SHA From c00c38bc22d6deeb09bee0307e7df6b353dbedbf Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 19 Sep 2014 10:34:51 -0600 Subject: [PATCH 22/63] Fix spelling of "USE_LIBCXX" flag --- .decent_ci-Linux.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.decent_ci-Linux.yaml b/.decent_ci-Linux.yaml index 6226d07..7e48bc9 100644 --- a/.decent_ci-Linux.yaml +++ b/.decent_ci-Linux.yaml @@ -1,7 +1,7 @@ compilers: - name: "clang" version: "3.5" - cmake_extra_flags: -DUSE_LIB_CXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=$COMMIT_SHA + cmake_extra_flags: -DUSE_LIBCXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=$COMMIT_SHA - name: "gcc" version: "4.8" cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=$COMMIT_SHA From 81184cbbd7ce166368a971254f35cfa29869f98b Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 19 Sep 2014 21:46:52 -0600 Subject: [PATCH 23/63] Rollback template alias, not supported in gcc 4.6 --- include/chaiscript/dispatchkit/boxed_cast.hpp | 2 +- include/chaiscript/dispatchkit/type_info.hpp | 21 ++++++++++++------- 2 files changed, 15 insertions(+), 8 deletions(-) diff --git a/include/chaiscript/dispatchkit/boxed_cast.hpp b/include/chaiscript/dispatchkit/boxed_cast.hpp index c86b4e1..31d9386 100644 --- a/include/chaiscript/dispatchkit/boxed_cast.hpp +++ b/include/chaiscript/dispatchkit/boxed_cast.hpp @@ -86,7 +86,7 @@ namespace chaiscript #pragma warning(disable : 4127) #endif - if (std::is_polymorphic>::value && t_conversions) + if (std::is_polymorphic::type>::value && t_conversions) { try { // std::cout << "trying an up conversion " << typeid(Type).name() << std::endl; diff --git a/include/chaiscript/dispatchkit/type_info.hpp b/include/chaiscript/dispatchkit/type_info.hpp index afa9e9e..628b4bb 100644 --- a/include/chaiscript/dispatchkit/type_info.hpp +++ b/include/chaiscript/dispatchkit/type_info.hpp @@ -16,8 +16,15 @@ namespace chaiscript { - template - using Bare_Type = typename std::remove_cv::type>::type>::type; + namespace detail + { + template + struct Bare_Type + { + typedef typename std::remove_cv::type>::type>::type type; + }; + } + /// \brief Compile time deduced information about a type class Type_Info @@ -145,7 +152,7 @@ namespace chaiscript std::is_void::value, std::is_arithmetic::value && !std::is_same::type, bool>::value, &typeid(T), - &typeid(Bare_Type)); + &typeid(typename Bare_Type::type)); } }; @@ -160,7 +167,7 @@ namespace chaiscript std::is_void::value, std::is_arithmetic::value && !std::is_same::type, bool>::value, &typeid(std::shared_ptr ), - &typeid(Bare_Type)); + &typeid(typename Bare_Type::type)); } }; @@ -175,7 +182,7 @@ namespace chaiscript std::is_void::value, std::is_arithmetic::value && !std::is_same::type, bool>::value, &typeid(const std::shared_ptr &), - &typeid(Bare_Type)); + &typeid(typename Bare_Type::type)); } }; @@ -190,7 +197,7 @@ namespace chaiscript std::is_void::value, std::is_arithmetic::value && !std::is_same::type, bool>::value, &typeid(std::reference_wrapper ), - &typeid(Bare_Type)); + &typeid(typename Bare_Type::type)); } }; @@ -205,7 +212,7 @@ namespace chaiscript std::is_void::value, std::is_arithmetic::value && !std::is_same::type, bool>::value, &typeid(const std::reference_wrapper &), - &typeid(Bare_Type)); + &typeid(typename Bare_Type::type)); } }; From e55700b86bfdc3d41161d559f1ccbe99e9892d39 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 19 Sep 2014 21:52:18 -0600 Subject: [PATCH 24/63] Remove static in bind_first - VS12 warns on it --- include/chaiscript/dispatchkit/bind_first.hpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/include/chaiscript/dispatchkit/bind_first.hpp b/include/chaiscript/dispatchkit/bind_first.hpp index 83ff560..e29ffb0 100644 --- a/include/chaiscript/dispatchkit/bind_first.hpp +++ b/include/chaiscript/dispatchkit/bind_first.hpp @@ -16,9 +16,8 @@ namespace chaiscript struct Placeholder { - static const std::tuple& placeholder() { - static const std::tuple d(std::placeholders::_1,std::placeholders::_2,std::placeholders::_3,std::placeholders::_4,std::placeholders::_5,std::placeholders::_6,std::placeholders::_7,std::placeholders::_8,std::placeholders::_9,std::placeholders::_10); - return d; + CHAISCRIPT_CONSTEXPR static std::tuple placeholder() { + return std::tuple(std::placeholders::_1,std::placeholders::_2,std::placeholders::_3,std::placeholders::_4,std::placeholders::_5,std::placeholders::_6,std::placeholders::_7,std::placeholders::_8,std::placeholders::_9,std::placeholders::_10); }; }; From 01cf906e187198cdce0257ff528cfcc2982cb340 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Fri, 19 Sep 2014 21:58:28 -0600 Subject: [PATCH 25/63] Clean up 32bit windows warnings --- include/chaiscript/language/chaiscript_eval.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index b1ee795..a8ebaf7 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -1420,26 +1420,26 @@ namespace chaiscript auto d = t_ss.get_parent_locals(); auto itr = d.find("_current_class_name"); - int class_offset = 0; + ssize_t class_offset = 0; if (itr != d.end()) class_offset = -1; const std::string & class_name = (itr != d.end())?std::string(boxed_cast(itr->second)):this->children[0]->text; //The first param of a method is always the implied this ptr. t_param_names.push_back("this"); - if ((this->children.size() > (3 + class_offset)) && (this->children[(2 + class_offset)]->identifier == AST_Node_Type::Arg_List)) { + if ((this->children.size() > static_cast(3 + class_offset)) && (this->children[(2 + class_offset)]->identifier == AST_Node_Type::Arg_List)) { for (size_t i = 0; i < this->children[(2 + class_offset)]->children.size(); ++i) { t_param_names.push_back(this->children[(2 + class_offset)]->children[i]->text); } - if (this->children.size() > (4 + class_offset)) { + if (this->children.size() > static_cast(4 + class_offset)) { guardnode = this->children[(3 + class_offset)]; } } else { //no parameters - if (this->children.size() > (3 + class_offset)) { + if (this->children.size() > static_cast(3 + class_offset)) { guardnode = this->children[(2 + class_offset)]; } } From 8c312550121348c6a425b3778a191b94bdd8c216 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 20 Sep 2014 07:21:30 -0600 Subject: [PATCH 26/63] Windows and GCC 4.6 error cleanups --- include/chaiscript/dispatchkit/bind_first.hpp | 2 +- include/chaiscript/dispatchkit/bootstrap.hpp | 4 ++-- include/chaiscript/language/chaiscript_eval.hpp | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/include/chaiscript/dispatchkit/bind_first.hpp b/include/chaiscript/dispatchkit/bind_first.hpp index e29ffb0..1f913c4 100644 --- a/include/chaiscript/dispatchkit/bind_first.hpp +++ b/include/chaiscript/dispatchkit/bind_first.hpp @@ -16,7 +16,7 @@ namespace chaiscript struct Placeholder { - CHAISCRIPT_CONSTEXPR static std::tuple placeholder() { + static std::tuple placeholder() { return std::tuple(std::placeholders::_1,std::placeholders::_2,std::placeholders::_3,std::placeholders::_4,std::placeholders::_5,std::placeholders::_6,std::placeholders::_7,std::placeholders::_8,std::placeholders::_9,std::placeholders::_10); }; }; diff --git a/include/chaiscript/dispatchkit/bootstrap.hpp b/include/chaiscript/dispatchkit/bootstrap.hpp index 9384920..fc39a11 100644 --- a/include/chaiscript/dispatchkit/bootstrap.hpp +++ b/include/chaiscript/dispatchkit/bootstrap.hpp @@ -513,7 +513,7 @@ namespace chaiscript "eval_error", { }, { {fun(&chaiscript::exception::eval_error::reason), "reason"}, - {fun(std::function (const chaiscript::exception::eval_error &t_eval_error)>([](const chaiscript::exception::eval_error &t_eval_error) { + {fun(std::function (const chaiscript::exception::eval_error &t_eval_error)>([](const chaiscript::exception::eval_error &t_eval_error) -> std::vector { std::vector retval; std::transform(t_eval_error.call_stack.begin(), t_eval_error.call_stack.end(), std::back_inserter(retval), @@ -541,7 +541,7 @@ namespace chaiscript {fun(&AST_Node::start), "start"}, {fun(&AST_Node::end), "end"}, {fun(&AST_Node::to_string), "to_string"}, - {fun(std::function (const chaiscript::AST_Node &t_node)>([](const chaiscript::AST_Node &t_node) { + {fun(std::function (const chaiscript::AST_Node &t_node)>([](const chaiscript::AST_Node &t_node) -> std::vector { std::vector retval; std::transform(t_node.children.begin(), t_node.children.end(), std::back_inserter(retval), diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index a8ebaf7..16a25f6 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -1420,7 +1420,7 @@ namespace chaiscript auto d = t_ss.get_parent_locals(); auto itr = d.find("_current_class_name"); - ssize_t class_offset = 0; + int class_offset = 0; if (itr != d.end()) class_offset = -1; const std::string & class_name = (itr != d.end())?std::string(boxed_cast(itr->second)):this->children[0]->text; From 0e381e333ed14273138a5f57c4c60b7ca29c5ecd Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 20 Sep 2014 08:31:18 -0600 Subject: [PATCH 27/63] Attempt to satisfy G++4.6 and decltype usage --- include/chaiscript/dispatchkit/operators.hpp | 8 ++++---- unittests/type_info_test.cpp | 3 +++ 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/include/chaiscript/dispatchkit/operators.hpp b/include/chaiscript/dispatchkit/operators.hpp index 4c2369f..562e3c0 100644 --- a/include/chaiscript/dispatchkit/operators.hpp +++ b/include/chaiscript/dispatchkit/operators.hpp @@ -19,13 +19,13 @@ namespace chaiscript namespace detail { template - auto assign(L l, R r) -> decltype((l = r)) + auto assign(L l, R r) -> decltype((l = r)) { return (l = r); } template - auto assign_bitwise_and(L l, R r) -> decltype((l &r)) + auto assign_bitwise_and(L l, R r) -> decltype((l &= r)) { return (l &= r); } @@ -229,7 +229,7 @@ namespace chaiscript template ModulePtr assign(ModulePtr m = ModulePtr(new Module())) { - m->add(chaiscript::fun(&detail::assign), "="); + m->add(chaiscript::fun(static_cast(&detail::assign)), "="); return m; } @@ -299,7 +299,7 @@ namespace chaiscript template ModulePtr assign_sum(ModulePtr m = ModulePtr(new Module())) { - m->add(chaiscript::fun(&detail::assign_sum), "+="); + m->add(chaiscript::fun(static_cast(&detail::assign_sum)), "+="); return m; } diff --git a/unittests/type_info_test.cpp b/unittests/type_info_test.cpp index 56f2681..e41f111 100644 --- a/unittests/type_info_test.cpp +++ b/unittests/type_info_test.cpp @@ -2,6 +2,7 @@ #include #include +#include #include void test_type(const chaiscript::Type_Info &ti, bool t_is_const, bool t_is_pointer, bool t_is_reference, bool t_is_void, @@ -30,5 +31,7 @@ int main() test_type(chaiscript::user_type(), true, true, false, false, false); test_type(chaiscript::Type_Info(), false, false, false, false, true); + std::cout << "Size of Type_Info " << sizeof(chaiscript::Type_Info) << std::endl; + return EXIT_SUCCESS; } From b6e8605aee7015015ef5777c57ce7558dd6cf877 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 20 Sep 2014 14:17:41 -0600 Subject: [PATCH 28/63] Attempt again to satisfy gcc 4.6 --- include/chaiscript/dispatchkit/operators.hpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/include/chaiscript/dispatchkit/operators.hpp b/include/chaiscript/dispatchkit/operators.hpp index 562e3c0..12719a3 100644 --- a/include/chaiscript/dispatchkit/operators.hpp +++ b/include/chaiscript/dispatchkit/operators.hpp @@ -19,7 +19,7 @@ namespace chaiscript namespace detail { template - auto assign(L l, R r) -> decltype((l = r)) + auto assign(L l, R r) -> L& { return (l = r); } @@ -79,7 +79,7 @@ namespace chaiscript } template - auto assign_sum(L l, R r) -> decltype(( l += r)) + auto assign_sum(L l, R r) -> L& { return (l += r); } @@ -229,7 +229,7 @@ namespace chaiscript template ModulePtr assign(ModulePtr m = ModulePtr(new Module())) { - m->add(chaiscript::fun(static_cast(&detail::assign)), "="); + m->add(chaiscript::fun(&detail::assign), "="); return m; } @@ -299,7 +299,7 @@ namespace chaiscript template ModulePtr assign_sum(ModulePtr m = ModulePtr(new Module())) { - m->add(chaiscript::fun(static_cast(&detail::assign_sum)), "+="); + m->add(chaiscript::fun(&detail::assign_sum), "+="); return m; } From e1b80abac47f618d81479d9120231985140d83cf Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 20 Sep 2014 14:20:37 -0600 Subject: [PATCH 29/63] Update documenation to-dos regarding gcc 4.6 --- include/chaiscript/dispatchkit/operators.hpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/chaiscript/dispatchkit/operators.hpp b/include/chaiscript/dispatchkit/operators.hpp index 12719a3..353035e 100644 --- a/include/chaiscript/dispatchkit/operators.hpp +++ b/include/chaiscript/dispatchkit/operators.hpp @@ -18,6 +18,7 @@ namespace chaiscript { namespace detail { + /// \todo make this return a decltype once we drop gcc 4.6 template auto assign(L l, R r) -> L& { @@ -78,6 +79,7 @@ namespace chaiscript return (l >>= r); } + /// \todo make this return a decltype once we drop gcc 4.6 template auto assign_sum(L l, R r) -> L& { From 4f5a6da2805a2777612cae44e0ac7a20ef114f17 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sun, 21 Sep 2014 14:19:41 -0600 Subject: [PATCH 30/63] Move constructor and noexcept correctness --- .../chaiscript/dispatchkit/boxed_number.hpp | 2 +- .../chaiscript/dispatchkit/boxed_value.hpp | 48 ++++++----------- include/chaiscript/dispatchkit/type_info.hpp | 52 +++++++------------ 3 files changed, 36 insertions(+), 66 deletions(-) diff --git a/include/chaiscript/dispatchkit/boxed_number.hpp b/include/chaiscript/dispatchkit/boxed_number.hpp index 3541bfb..e1a5ca7 100644 --- a/include/chaiscript/dispatchkit/boxed_number.hpp +++ b/include/chaiscript/dispatchkit/boxed_number.hpp @@ -337,7 +337,7 @@ namespace chaiscript Boxed_Number(Boxed_Value v) : bv(std::move(v)) { - validate_boxed_number(v); + validate_boxed_number(bv); } template explicit Boxed_Number(T t) diff --git a/include/chaiscript/dispatchkit/boxed_value.hpp b/include/chaiscript/dispatchkit/boxed_value.hpp index 3fe48b0..374036b 100644 --- a/include/chaiscript/dispatchkit/boxed_value.hpp +++ b/include/chaiscript/dispatchkit/boxed_value.hpp @@ -61,9 +61,6 @@ namespace chaiscript Data(const Data &) = delete; - ~Data() - { - } Type_Info m_type_info; chaiscript::detail::Any m_obj; @@ -151,21 +148,18 @@ namespace chaiscript { } - /// Copy constructor - each copy shares the same data pointer - Boxed_Value(const Boxed_Value &t_so) - : m_data(t_so.m_data) - { - } - /// Unknown-type constructor Boxed_Value() : m_data(Object_Data::get()) { } - ~Boxed_Value() - { - } + + Boxed_Value(Boxed_Value&&) = default; + Boxed_Value& operator=(Boxed_Value&&) = default; + + Boxed_Value(const Boxed_Value&) = default; + Boxed_Value& operator=(const Boxed_Value&) = default; void swap(Boxed_Value &rhs) { @@ -180,61 +174,53 @@ namespace chaiscript return *this; } - /// shared data assignment, same as copy construction - Boxed_Value &operator=(const Boxed_Value &rhs) - { - Boxed_Value temp(rhs); - swap(temp); - return *this; - } - - const Type_Info &get_type_info() const + const Type_Info &get_type_info() const CHAISCRIPT_NOEXCEPT { return m_data->m_type_info; } /// return true if the object is uninitialized - bool is_undef() const + bool is_undef() const CHAISCRIPT_NOEXCEPT { return m_data->m_type_info.is_undef(); } - bool is_const() const + bool is_const() const CHAISCRIPT_NOEXCEPT { return m_data->m_type_info.is_const(); } - bool is_type(const Type_Info &ti) const + bool is_type(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT { return m_data->m_type_info.bare_equal(ti); } - bool is_null() const + bool is_null() const CHAISCRIPT_NOEXCEPT { return (m_data->m_data_ptr == nullptr && m_data->m_const_data_ptr == nullptr); } - const chaiscript::detail::Any & get() const + const chaiscript::detail::Any & get() const CHAISCRIPT_NOEXCEPT { return m_data->m_obj; } - bool is_ref() const + bool is_ref() const CHAISCRIPT_NOEXCEPT { return m_data->m_is_ref; } - bool is_pointer() const + bool is_pointer() const CHAISCRIPT_NOEXCEPT { return !is_ref(); } - void *get_ptr() const + void *get_ptr() const CHAISCRIPT_NOEXCEPT { return m_data->m_data_ptr; } - const void *get_const_ptr() const + const void *get_const_ptr() const CHAISCRIPT_NOEXCEPT { return m_data->m_const_data_ptr; } @@ -260,7 +246,7 @@ namespace chaiscript /// \returns true if the two Boxed_Values share the same internal type - static bool type_match(Boxed_Value l, Boxed_Value r) + static bool type_match(const Boxed_Value &l, const Boxed_Value &r) CHAISCRIPT_NOEXCEPT { return l.get_type_info() == r.get_type_info(); } diff --git a/include/chaiscript/dispatchkit/type_info.hpp b/include/chaiscript/dispatchkit/type_info.hpp index 628b4bb..f287033 100644 --- a/include/chaiscript/dispatchkit/type_info.hpp +++ b/include/chaiscript/dispatchkit/type_info.hpp @@ -39,7 +39,7 @@ namespace chaiscript { } - Type_Info() + CHAISCRIPT_CONSTEXPR Type_Info() : m_type_info(nullptr), m_bare_type_info(nullptr), m_is_const(false), m_is_reference(false), m_is_pointer(false), m_is_void(false), m_is_arithmetic(false), @@ -47,63 +47,47 @@ namespace chaiscript { } - Type_Info(const Type_Info &ti) - : m_type_info(ti.m_type_info), - m_bare_type_info(ti.m_bare_type_info), - m_is_const(ti.m_is_const), m_is_reference(ti.m_is_reference), - m_is_pointer(ti.m_is_pointer), - m_is_void(ti.m_is_void), m_is_arithmetic(ti.m_is_arithmetic), - m_is_undef(ti.m_is_undef) - { - } + Type_Info(Type_Info&&) = default; + Type_Info& operator=(Type_Info&&) = default; - Type_Info &operator=(const Type_Info &ti) - { - m_type_info = ti.m_type_info; - m_bare_type_info = ti.m_bare_type_info; - m_is_const = ti.m_is_const; - m_is_reference = ti.m_is_reference; - m_is_pointer = ti.m_is_pointer; - m_is_void = ti.m_is_void; - m_is_arithmetic = ti.m_is_arithmetic; - m_is_undef = ti.m_is_undef; - return *this; - } + Type_Info(const Type_Info&) = default; + Type_Info& operator=(const Type_Info&) = default; - bool operator<(const Type_Info &ti) const + + CHAISCRIPT_CONSTEXPR bool operator<(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT { return m_type_info < ti.m_type_info; } - bool operator==(const Type_Info &ti) const + CHAISCRIPT_CONSTEXPR bool operator==(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT { return ti.m_type_info == m_type_info || (ti.m_type_info && m_type_info && *ti.m_type_info == *m_type_info); } - bool operator==(const std::type_info &ti) const + CHAISCRIPT_CONSTEXPR bool operator==(const std::type_info &ti) const CHAISCRIPT_NOEXCEPT { return m_type_info != nullptr && (*m_type_info) == ti; } - bool bare_equal(const Type_Info &ti) const + CHAISCRIPT_CONSTEXPR bool bare_equal(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT { return ti.m_bare_type_info == m_bare_type_info || (ti.m_bare_type_info && m_bare_type_info && *ti.m_bare_type_info == *m_bare_type_info); } - bool bare_equal_type_info(const std::type_info &ti) const + CHAISCRIPT_CONSTEXPR bool bare_equal_type_info(const std::type_info &ti) const CHAISCRIPT_NOEXCEPT { return m_bare_type_info != nullptr && (*m_bare_type_info) == ti; } - bool is_const() const { return m_is_const; } - bool is_reference() const { return m_is_reference; } - bool is_void() const { return m_is_void; } - bool is_arithmetic() const { return m_is_arithmetic; } - bool is_undef() const { return m_is_undef || m_bare_type_info == nullptr; } - bool is_pointer() const { return m_is_pointer; } + CHAISCRIPT_CONSTEXPR bool is_const() const CHAISCRIPT_NOEXCEPT { return m_is_const; } + CHAISCRIPT_CONSTEXPR bool is_reference() const CHAISCRIPT_NOEXCEPT { return m_is_reference; } + CHAISCRIPT_CONSTEXPR bool is_void() const CHAISCRIPT_NOEXCEPT { return m_is_void; } + CHAISCRIPT_CONSTEXPR bool is_arithmetic() const CHAISCRIPT_NOEXCEPT { return m_is_arithmetic; } + CHAISCRIPT_CONSTEXPR bool is_undef() const CHAISCRIPT_NOEXCEPT { return m_is_undef || m_bare_type_info == nullptr; } + CHAISCRIPT_CONSTEXPR bool is_pointer() const CHAISCRIPT_NOEXCEPT { return m_is_pointer; } std::string name() const { @@ -115,7 +99,7 @@ namespace chaiscript } } - std::string bare_name() const + std::string bare_name() const { if (m_bare_type_info) { From 9a7d03df05ab4fe6632330be5d59f833c63a82d6 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 4 Oct 2014 09:37:33 -0600 Subject: [PATCH 31/63] Modernization of chaiscript_parser --- .../chaiscript/language/chaiscript_parser.hpp | 3143 ++++++++--------- include/chaiscript/utility/utility.hpp | 27 +- 2 files changed, 1477 insertions(+), 1693 deletions(-) diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index e50a5d0..29ee4b9 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -57,94 +57,63 @@ namespace chaiscript std::vector m_match_stack; bool m_alphabet[detail::max_alphabet][detail::lengthof_alphabet]; - std::vector > m_operator_matches; + std::vector> m_operator_matches; std::vector m_operators; public: ChaiScript_Parser() : m_line(-1), m_col(-1), - m_multiline_comment_begin("/*"), + m_multiline_comment_begin("/*"), m_multiline_comment_end("*/"), m_singleline_comment("//") { setup_operators(); } - ChaiScript_Parser(const ChaiScript_Parser &); // explicitly unimplemented copy constructor - ChaiScript_Parser &operator=(const ChaiScript_Parser &); // explicitly unimplemented assignment operator + ChaiScript_Parser(const ChaiScript_Parser &) = delete; + ChaiScript_Parser &operator=(const ChaiScript_Parser &) = delete; void setup_operators() { - m_operators.push_back(AST_Node_Type::Ternary_Cond); - std::vector ternary_cond; - ternary_cond.push_back("?"); - m_operator_matches.push_back(ternary_cond); + m_operators.emplace_back(AST_Node_Type::Ternary_Cond); + m_operator_matches.emplace_back(std::initializer_list({"?"})); - m_operators.push_back(AST_Node_Type::Logical_Or); - std::vector logical_or; - logical_or.push_back("||"); - m_operator_matches.push_back(logical_or); + m_operators.emplace_back(AST_Node_Type::Logical_Or); + m_operator_matches.emplace_back(std::initializer_list({"||"})); - m_operators.push_back(AST_Node_Type::Logical_And); - std::vector logical_and; - logical_and.push_back("&&"); - m_operator_matches.push_back(logical_and); + m_operators.emplace_back(AST_Node_Type::Logical_And); + m_operator_matches.emplace_back(std::initializer_list({"&&"})); - m_operators.push_back(AST_Node_Type::Bitwise_Or); - std::vector bitwise_or; - bitwise_or.push_back("|"); - m_operator_matches.push_back(bitwise_or); + m_operators.emplace_back(AST_Node_Type::Bitwise_Or); + m_operator_matches.emplace_back(std::initializer_list({"|"})); - m_operators.push_back(AST_Node_Type::Bitwise_Xor); - std::vector bitwise_xor; - bitwise_xor.push_back("^"); - m_operator_matches.push_back(bitwise_xor); + m_operators.emplace_back(AST_Node_Type::Bitwise_Xor); + m_operator_matches.emplace_back(std::initializer_list({"^"})); - m_operators.push_back(AST_Node_Type::Bitwise_And); - std::vector bitwise_and; - bitwise_and.push_back("&"); - m_operator_matches.push_back(bitwise_and); + m_operators.emplace_back(AST_Node_Type::Bitwise_And); + m_operator_matches.emplace_back(std::initializer_list({"&"})); - m_operators.push_back(AST_Node_Type::Equality); - std::vector equality; - equality.push_back("=="); - equality.push_back("!="); - m_operator_matches.push_back(equality); + m_operators.emplace_back(AST_Node_Type::Equality); + m_operator_matches.emplace_back(std::initializer_list({"==", "!="})); - m_operators.push_back(AST_Node_Type::Comparison); - std::vector comparison; - comparison.push_back("<"); - comparison.push_back("<="); - comparison.push_back(">"); - comparison.push_back(">="); - m_operator_matches.push_back(comparison); + m_operators.emplace_back(AST_Node_Type::Comparison); + m_operator_matches.emplace_back(std::initializer_list({"<", "<=", ">", ">="})); - m_operators.push_back(AST_Node_Type::Shift); - std::vector shift; - shift.push_back("<<"); - shift.push_back(">>"); - m_operator_matches.push_back(shift); + m_operators.emplace_back(AST_Node_Type::Shift); + m_operator_matches.emplace_back(std::initializer_list({"<<", ">>"})); //We share precedence here but then separate them later - m_operators.push_back(AST_Node_Type::Addition); - std::vector addition; - addition.push_back("+"); - addition.push_back("-"); - m_operator_matches.push_back(addition); + m_operators.emplace_back(AST_Node_Type::Addition); + m_operator_matches.emplace_back(std::initializer_list({"+", "-"})); //We share precedence here but then separate them later - m_operators.push_back(AST_Node_Type::Multiplication); - std::vector multiplication; - multiplication.push_back("*"); - multiplication.push_back("/"); - multiplication.push_back("%"); - m_operator_matches.push_back(multiplication); + m_operators.emplace_back(AST_Node_Type::Multiplication); + m_operator_matches.emplace_back(std::initializer_list({"*", "/", "%"})); - for ( int c = 0 ; c < detail::lengthof_alphabet ; ++c ) { - for (auto & elem : m_alphabet) { - elem[c]=false; - } + for (auto & elem : m_alphabet) { + std::fill(std::begin(elem), std::end(elem), false); } + m_alphabet[detail::symbol_alphabet][static_cast('?')]=true; m_alphabet[detail::symbol_alphabet][static_cast('+')]=true; m_alphabet[detail::symbol_alphabet][static_cast('-')]=true; @@ -194,17 +163,12 @@ namespace chaiscript m_alphabet[detail::float_suffix_alphabet][static_cast('L')] = true; m_alphabet[detail::float_suffix_alphabet][static_cast('f')] = true; m_alphabet[detail::float_suffix_alphabet][static_cast('F')] = true; - } - /** - * test a char in an m_alphabet - */ - bool char_in_alphabet(char c, detail::Alphabet a) { return m_alphabet[a][static_cast(c)]; } + /// test a char in an m_alphabet + 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 - */ + /// Prints the parsed ast_nodes as a tree /* void debug_print(AST_NodePtr t, std::string prepend = "") { std::cout << prepend << "(" << ast_node_type_to_string(t->identifier) << ") " << t->text << " : " << t->start.line << ", " << t->start.column << std::endl; @@ -214,9 +178,7 @@ namespace chaiscript } */ - /** - * Shows the current stack of matched ast_nodes - */ + /// Shows the current stack of matched ast_nodes void show_match_stack() const { for (auto & elem : m_match_stack) { //debug_print(match_stack[i]); @@ -224,26 +186,20 @@ namespace chaiscript } } - /** - * Clears the stack of matched ast_nodes - */ + /// Clears the stack of matched ast_nodes void clear_match_stack() { m_match_stack.clear(); } - /** - * Returns the front-most AST node - */ - AST_NodePtr ast() { + /// Returns the front-most AST node + AST_NodePtr ast() const { return m_match_stack.front(); } - /** - * Helper function that collects ast_nodes from a starting position to the top of the stack into a new AST node - */ + /// Helper function that collects ast_nodes from a starting position to the top of the stack into a new AST node void build_match(AST_NodePtr t_t, size_t t_match_start) { int pos_line_start, pos_col_start, pos_line_stop, pos_col_stop; - int is_deep = false; + bool is_deep = false; //so we want to take everything to the right of this and make them children if (t_match_start != m_match_stack.size()) { @@ -269,72 +225,57 @@ namespace chaiscript if (is_deep) { t_t->children.assign(m_match_stack.begin() + t_match_start, m_match_stack.end()); m_match_stack.erase(m_match_stack.begin() + t_match_start, m_match_stack.end()); - m_match_stack.push_back(t_t); - } - else { - /// \todo fix the fact that a successful match that captured no ast_nodes doesn't have any real start position - m_match_stack.push_back(t_t); } + + /// \todo fix the fact that a successful match that captured no ast_nodes doesn't have any real start position + m_match_stack.push_back(std::move(t_t)); } - /** - * Check to see if there is more text parse - */ + /// Check to see if there is more text parse inline bool has_more_input() const { return (m_input_pos != m_input_end); } - /** - * Skips any multi-line or single-line comment - */ + /// Skips any multi-line or single-line comment bool SkipComment() { - bool retval = false; - if (Symbol_(m_multiline_comment_begin.c_str())) { while (m_input_pos != m_input_end) { if (Symbol_(m_multiline_comment_end.c_str())) { break; - } - else if (!Eol_()) { + } else if (!Eol_()) { ++m_col; ++m_input_pos; } } - retval = true; - } - else if (Symbol_(m_singleline_comment.c_str())) { + return true; + } else if (Symbol_(m_singleline_comment.c_str())) { while (m_input_pos != m_input_end) { if (Symbol_("\r\n")) { m_input_pos -= 2; break; - } - else if (Char_('\n')) { + } else if (Char_('\n')) { --m_input_pos; break; - } - else { + } else { ++m_col; ++m_input_pos; } } - retval = true; + return true; } - return retval; + return false; } - /** - * Skips ChaiScript whitespace, which means space and tab, but not cr/lf - * jespada: Modified SkipWS to skip optionally CR ('\n') - */ - bool SkipWS(bool skip_cr=false) { + /// Skips ChaiScript whitespace, which means space and tab, but not cr/lf + /// jespada: Modified SkipWS to skip optionally CR ('\n') + bool SkipWS(const bool skip_cr=false) { bool retval = false; while (has_more_input()) { if ( char_in_alphabet(*m_input_pos,detail::white_alphabet) || (skip_cr && (*m_input_pos == '\n'))) { if(*m_input_pos == '\n') { m_col = 1; ++m_line; - } - else { + } else { ++m_col; } ++m_input_pos; @@ -351,22 +292,18 @@ namespace chaiscript return retval; } - /** - * Reads a floating point value from input, without skipping initial whitespace - */ + /// Reads a floating point value from input, without skipping initial whitespace bool Float_() { - bool retval = false; - if (has_more_input() && char_in_alphabet(*m_input_pos,detail::float_alphabet) ) { while (has_more_input() && char_in_alphabet(*m_input_pos,detail::int_alphabet) ) { ++m_input_pos; ++m_col; } + if (has_more_input() && (*m_input_pos == '.')) { ++m_input_pos; ++m_col; if (has_more_input() && char_in_alphabet(*m_input_pos,detail::int_alphabet)) { - retval = true; while (has_more_input() && char_in_alphabet(*m_input_pos,detail::int_alphabet) ) { ++m_input_pos; ++m_col; @@ -377,21 +314,19 @@ namespace chaiscript ++m_input_pos; ++m_col; } - } - else { + + return true; + } else { --m_input_pos; --m_col; } } } - return retval; + return false; } - /** - * Reads a hex value from input, without skipping initial whitespace - */ + /// Reads a hex value from input, without skipping initial whitespace bool Hex_() { - bool retval = false; if (has_more_input() && (*m_input_pos == '0')) { ++m_input_pos; ++m_col; @@ -400,7 +335,6 @@ namespace chaiscript ++m_input_pos; ++m_col; if (has_more_input() && char_in_alphabet(*m_input_pos, detail::hex_alphabet)) { - retval = true; while (has_more_input() && char_in_alphabet(*m_input_pos, detail::hex_alphabet) ) { ++m_input_pos; ++m_col; @@ -410,6 +344,8 @@ namespace chaiscript ++m_input_pos; ++m_col; } + + return true; } else { --m_input_pos; @@ -422,9 +358,10 @@ namespace chaiscript } } - return retval; + return false; } + /// Reads an integer suffix void IntSuffix_() { while (has_more_input() && char_in_alphabet(*m_input_pos, detail::int_suffix_alphabet)) { @@ -433,11 +370,8 @@ namespace chaiscript } } - /** - * Reads a binary value from input, without skipping initial whitespace - */ + /// Reads a binary value from input, without skipping initial whitespace bool Binary_() { - bool retval = false; if (has_more_input() && (*m_input_pos == '0')) { ++m_input_pos; ++m_col; @@ -446,32 +380,31 @@ namespace chaiscript ++m_input_pos; ++m_col; if (has_more_input() && char_in_alphabet(*m_input_pos, detail::bin_alphabet) ) { - retval = true; while (has_more_input() && char_in_alphabet(*m_input_pos, detail::bin_alphabet) ) { ++m_input_pos; ++m_col; } - } - else { + return true; + } else { --m_input_pos; --m_col; } - } - else { + } else { --m_input_pos; --m_col; } } - return retval; + return false; } + /// Parses a floating point value and returns a Boxed_Value representation of it static Boxed_Value buildFloat(const std::string &t_val) { bool float_ = false; bool long_ = false; - size_t i = t_val.size(); + auto i = t_val.size(); for (; i > 0; --i) { @@ -492,16 +425,16 @@ namespace chaiscript if (float_) { float f; - ss >> f; - return Boxed_Value(const_var(f)); + ss >> f; + return const_var(f); } else if (long_) { long double f; - ss >> f; - return Boxed_Value(const_var(f)); + ss >> f; + return const_var(f); } else { double f; - ss >> f; - return Boxed_Value(const_var(f)); + ss >> f; + return const_var(f); } } @@ -514,11 +447,11 @@ namespace chaiscript bool long_ = false; bool longlong_ = false; - size_t i = t_val.size(); + auto i = t_val.size(); for (; i > 0; --i) { - char val = t_val[i-1]; + const char val = t_val[i-1]; if (val == 'u' || val == 'U') { @@ -543,7 +476,6 @@ namespace chaiscript testu >> t_type >> u; bool unsignedrequired = false; - size_t size = sizeof(int) * 8; if ((u >> (sizeof(int) * 8)) > 0) { @@ -561,6 +493,8 @@ namespace chaiscript } + size_t size = sizeof(int) * 8; + if (longlong_) { size = sizeof(int64_t) * 8; @@ -595,60 +529,57 @@ namespace chaiscript if (longlong_) { uint64_t val; - ss >> val; - return Boxed_Value(const_var(val)); + ss >> val; + return const_var(val); } else if (long_) { unsigned long val; ss >> val; - return Boxed_Value(const_var(val)); + return const_var(val); } else { unsigned int val; ss >> val; - return Boxed_Value(const_var(val)); + return const_var(val); } } else { if (longlong_) { int64_t val; - ss >> val; - return Boxed_Value(const_var(val)); + ss >> val; + return const_var(val); } else if (long_) { long val; ss >> val; - return Boxed_Value(const_var(val)); + return const_var(val); } else { int val; ss >> val; - return Boxed_Value(const_var(val)); + return const_var(val); } } } - /** - * Reads a number from the input, detecting if it's an integer or floating point - */ - bool Num(bool t_capture = false) { + /// Reads a number from the input, detecting if it's an integer or floating point + bool Num(const bool t_capture = false) { SkipWS(); if (!t_capture) { return Hex_() || Float_(); - } - else { - std::string::const_iterator start = m_input_pos; - int prev_col = m_col; - int prev_line = m_line; + } else { + const auto start = m_input_pos; + const auto prev_col = m_col; + const auto prev_line = m_line; if (has_more_input() && char_in_alphabet(*m_input_pos, detail::float_alphabet) ) { if (Hex_()) { std::string match(start, m_input_pos); - Boxed_Value i = buildInt(std::hex, match); - AST_NodePtr t(new eval::Int_AST_Node(match, i, m_filename, prev_line, prev_col, m_line, m_col)); - m_match_stack.push_back(t); + m_match_stack.emplace_back(std::make_shared(std::move(match), buildInt(std::hex, match), m_filename, prev_line, prev_col, m_line, m_col)); return true; } + if (Binary_()) { std::string match(start, m_input_pos); int64_t temp_int = 0; - size_t pos = 0, end = match.length(); + size_t pos = 0; + const auto end = match.length(); while ((pos < end) && (pos < (2 + sizeof(int) * 8))) { temp_int <<= 1; @@ -661,34 +592,27 @@ namespace chaiscript Boxed_Value i; if (match.length() <= sizeof(int) * 8) { - i = Boxed_Value(const_var(int(temp_int))); + i = const_var(static_cast(temp_int)); } else { - i = Boxed_Value(const_var(temp_int)); + i = const_var(temp_int); } - AST_NodePtr t(new eval::Int_AST_Node(match, i, m_filename, prev_line, prev_col, m_line, m_col)); - m_match_stack.push_back(t); + m_match_stack.push_back(std::make_shared(std::move(match), std::move(i), m_filename, prev_line, prev_col, m_line, m_col)); return true; } if (Float_()) { std::string match(start, m_input_pos); - Boxed_Value f = buildFloat(match); - AST_NodePtr t(new eval::Float_AST_Node(match, f, m_filename, prev_line, prev_col, m_line, m_col)); - m_match_stack.push_back(t); + m_match_stack.push_back(std::make_shared(std::move(match), buildFloat(match), m_filename, prev_line, prev_col, m_line, m_col)); return true; } else { IntSuffix_(); std::string match(start, m_input_pos); - if ((match.size() > 0) && (match[0] == '0')) { - Boxed_Value i = buildInt(std::oct, match); - AST_NodePtr t(new eval::Int_AST_Node(match, i, m_filename, prev_line, prev_col, m_line, m_col)); - m_match_stack.push_back(t); + if (!match.empty() && (match[0] == '0')) { + m_match_stack.push_back(std::make_shared(std::move(match), buildInt(std::oct, match), m_filename, prev_line, prev_col, m_line, m_col)); } else { - Boxed_Value i = buildInt(std::dec, match); - AST_NodePtr t(new eval::Int_AST_Node(match, i, m_filename, prev_line, prev_col, m_line, m_col)); - m_match_stack.push_back(t); + m_match_stack.push_back(std::make_shared(std::move(match), buildInt(std::dec, match), m_filename, prev_line, prev_col, m_line, m_col)); } return true; } @@ -699,23 +623,19 @@ namespace chaiscript } } - /** - * Reads an identifier from input which conforms to C's identifier naming conventions, without skipping initial whitespace - */ + /// Reads an identifier from input which conforms to C's identifier naming conventions, without skipping initial whitespace bool Id_() { - bool retval = false; if (has_more_input() && char_in_alphabet(*m_input_pos, detail::id_alphabet)) { - retval = true; while (has_more_input() && char_in_alphabet(*m_input_pos, detail::keyword_alphabet) ) { ++m_input_pos; ++m_col; } - } - else if (has_more_input() && (*m_input_pos == '`')) { - retval = true; + + return true; + } else if (has_more_input() && (*m_input_pos == '`')) { ++m_col; ++m_input_pos; - std::string::const_iterator start = m_input_pos; + const auto start = m_input_pos; while (has_more_input() && (*m_input_pos != '`')) { if (Eol()) { @@ -736,52 +656,44 @@ namespace chaiscript ++m_col; ++m_input_pos; + + return true; } - return retval; + return false; } - /** - * Reads (and potentially captures) an identifier from input - */ - bool Id(bool t_capture = false) { + /// Reads (and potentially captures) an identifier from input + bool Id(const bool t_capture = false) { SkipWS(); if (!t_capture) { return Id_(); - } - else { - std::string::const_iterator start = m_input_pos; - int prev_col = m_col; - int prev_line = m_line; + } else { + const auto start = m_input_pos; + const int prev_col = m_col; + const int prev_line = m_line; if (Id_()) { + std::string match; if (*start == '`') { //Id Literal - std::string match(start+1, m_input_pos-1); - AST_NodePtr t(new eval::Id_AST_Node(match, m_filename, prev_line, prev_col, m_line, m_col)); - m_match_stack.push_back(t); - return true; + match = std::string(start+1, m_input_pos-1); + } else { + match = std::string(start, m_input_pos); } - else { - std::string match(start, m_input_pos); - AST_NodePtr t(new eval::Id_AST_Node(match, m_filename, prev_line, prev_col, m_line, m_col)); - m_match_stack.push_back(t); - return true; - } - } - else { + m_match_stack.push_back(std::make_shared(std::move(match), m_filename, prev_line, prev_col, m_line, m_col)); + return true; + } else { return false; } } } - /** - * Checks for a node annotation of the form "#" - */ + /// Checks for a node annotation of the form "#" bool Annotation() { SkipWS(); - std::string::const_iterator start = m_input_pos; - int prev_col = m_col; - int prev_line = m_line; + const auto start = m_input_pos; + const auto prev_col = m_col; + const auto prev_line = m_line; if (Symbol_("#")) { do { while (m_input_pos != m_input_end) { @@ -796,8 +708,7 @@ namespace chaiscript } while (Symbol("#")); std::string match(start, m_input_pos); - AST_NodePtr t(new eval::Annotation_AST_Node(match, m_filename, prev_line, prev_col, m_line, m_col)); - m_match_stack.push_back(t); + m_match_stack.push_back(std::make_shared(std::move(match), m_filename, prev_line, prev_col, m_line, m_col)); return true; } else { @@ -805,13 +716,9 @@ namespace chaiscript } } - /** - * Reads a quoted string from input, without skipping initial whitespace - */ + /// Reads a quoted string from input, without skipping initial whitespace bool Quoted_String_() { - bool retval = false; if (has_more_input() && (*m_input_pos == '\"')) { - retval = true; char prev_char = *m_input_pos; ++m_input_pos; ++m_col; @@ -820,8 +727,7 @@ namespace chaiscript if (!Eol_()) { if (prev_char == '\\') { prev_char = 0; - } - else { + } else { prev_char = *m_input_pos; } ++m_input_pos; @@ -832,33 +738,32 @@ namespace chaiscript if (has_more_input()) { ++m_input_pos; ++m_col; - } - else { + } else { throw exception::eval_error("Unclosed quoted string", File_Position(m_line, m_col), *m_filename); } + + return true; } - return retval; + return false; } - /** - * Reads (and potentially captures) a quoted string from input. Translates escaped sequences. - */ - bool Quoted_String(bool t_capture = false) { + /// Reads (and potentially captures) a quoted string from input. Translates escaped sequences. + bool Quoted_String(const bool t_capture = false) { SkipWS(); if (!t_capture) { return Quoted_String_(); - } - else { - std::string::const_iterator start = m_input_pos; - int prev_col = m_col; - int prev_line = m_line; + } else { + const auto start = m_input_pos; + const auto prev_col = m_col; + const auto prev_line = m_line; + if (Quoted_String_()) { std::string match; bool is_escaped = false; bool is_interpolated = false; bool saw_interpolation_marker = false; - size_t prev_stack_top = m_match_stack.size(); + const auto prev_stack_top = m_match_stack.size(); std::string::const_iterator s = start + 1, end = m_input_pos - 1; @@ -869,76 +774,62 @@ namespace chaiscript if (is_interpolated) { //If we've seen previous interpolation, add on instead of making a new one + m_match_stack.push_back(std::make_shared(match, m_filename, prev_line, prev_col, m_line, m_col)); - AST_NodePtr t(new eval::Quoted_String_AST_Node(match, m_filename, prev_line, prev_col, m_line, m_col)); - m_match_stack.push_back(t); - - build_match(AST_NodePtr(new eval::Addition_AST_Node()), prev_stack_top); - } - else { - AST_NodePtr t(new eval::Quoted_String_AST_Node(match, m_filename, prev_line, prev_col, m_line, m_col)); - m_match_stack.push_back(t); + build_match(std::make_shared(), prev_stack_top); + } else { + m_match_stack.push_back(std::make_shared(match, m_filename, prev_line, prev_col, m_line, m_col)); } //We've finished with the part of the string up to this point, so clear it - match = ""; + match.clear(); std::string eval_match; ++s; - while ((*s != '}') && (s != end)) { + while ((s != end) && (*s != '}')) { eval_match.push_back(*s); ++s; } + if (*s == '}') { is_interpolated = true; ++s; - size_t tostr_stack_top = m_match_stack.size(); + const auto tostr_stack_top = m_match_stack.size(); - AST_NodePtr tostr(new eval::Id_AST_Node("to_string", m_filename, prev_line, prev_col, m_line, m_col)); - m_match_stack.push_back(tostr); + m_match_stack.push_back(std::make_shared("to_string", m_filename, prev_line, prev_col, m_line, m_col)); - size_t ev_stack_top = m_match_stack.size(); + const auto ev_stack_top = m_match_stack.size(); - AST_NodePtr ev(new eval::Id_AST_Node("eval", m_filename, prev_line, prev_col, m_line, m_col)); - m_match_stack.push_back(ev); + /// \todo can we evaluate this in place and save the runtime cost of evaluating with each execution of the node? + m_match_stack.push_back(std::make_shared("eval", m_filename, prev_line, prev_col, m_line, m_col)); - size_t arg_stack_top = m_match_stack.size(); + const auto arg_stack_top = m_match_stack.size(); - AST_NodePtr t(new eval::Quoted_String_AST_Node(eval_match, m_filename, prev_line, prev_col, m_line, m_col)); - m_match_stack.push_back(t); + m_match_stack.push_back(std::make_shared(eval_match, m_filename, prev_line, prev_col, m_line, m_col)); - build_match(AST_NodePtr(new eval::Arg_List_AST_Node()), arg_stack_top); - - build_match(AST_NodePtr(new eval::Inplace_Fun_Call_AST_Node()), ev_stack_top); - - build_match(AST_NodePtr(new eval::Arg_List_AST_Node()), ev_stack_top); - - build_match(AST_NodePtr(new eval::Fun_Call_AST_Node()), tostr_stack_top); - - build_match(AST_NodePtr(new eval::Addition_AST_Node()), prev_stack_top); - } - else { + build_match(std::make_shared(), arg_stack_top); + build_match(std::make_shared(), ev_stack_top); + build_match(std::make_shared(), ev_stack_top); + build_match(std::make_shared(), tostr_stack_top); + build_match(std::make_shared(), prev_stack_top); + } else { throw exception::eval_error("Unclosed in-string eval", File_Position(prev_line, prev_col), *m_filename); } - } - else { + } else { match.push_back('$'); } saw_interpolation_marker = false; - } - else { + } else { if (*s == '\\') { if (is_escaped) { match.push_back('\\'); is_escaped = false; - } - else { + } else { is_escaped = true; } - } - else { + } else { if (is_escaped) { switch (*s) { case ('b') : match.push_back('\b'); break; @@ -947,15 +838,13 @@ namespace chaiscript case ('r') : match.push_back('\r'); break; case ('t') : match.push_back('\t'); break; case ('\'') : match.push_back('\''); break; - case ('\"') : match.push_back('\"'); break; + case ('\"') : match.push_back('\"'); break; case ('$') : match.push_back('$'); break; default: throw exception::eval_error("Unknown escaped sequence in string", File_Position(prev_line, prev_col), *m_filename); } - } - else if (*s == '$') { + } else if (*s == '$') { saw_interpolation_marker = true; - } - else { + } else { match.push_back(*s); } is_escaped = false; @@ -963,1551 +852,1425 @@ namespace chaiscript ++s; } } - if (is_interpolated) { - AST_NodePtr t(new eval::Quoted_String_AST_Node(match, m_filename, prev_line, prev_col, m_line, m_col)); - m_match_stack.push_back(t); - build_match(AST_NodePtr(new eval::Addition_AST_Node()), prev_stack_top); + if (is_interpolated) { + m_match_stack.push_back(std::make_shared(match, m_filename, prev_line, prev_col, m_line, m_col)); + + build_match(std::make_shared(), prev_stack_top); + } else { + m_match_stack.push_back(std::make_shared(match, m_filename, prev_line, prev_col, m_line, m_col)); } - else { - AST_NodePtr t(new eval::Quoted_String_AST_Node(match, m_filename, prev_line, prev_col, m_line, m_col)); - m_match_stack.push_back(t); + return true; + } else { + return false; + } + } + } + + /// Reads a character group from input, without skipping initial whitespace + bool Single_Quoted_String_() { + bool retval = false; + if (has_more_input() && (*m_input_pos == '\'')) { + retval = true; + char prev_char = *m_input_pos; + ++m_input_pos; + ++m_col; + + while (has_more_input() && ((*m_input_pos != '\'') || ((*m_input_pos == '\'') && (prev_char == '\\')))) { + if (!Eol_()) { + if (prev_char == '\\') { + prev_char = 0; + } else { + prev_char = *m_input_pos; + } + ++m_input_pos; + ++m_col; } + } + + if (m_input_pos != m_input_end) { + ++m_input_pos; + ++m_col; + } else { + throw exception::eval_error("Unclosed single-quoted string", File_Position(m_line, m_col), *m_filename); + } + } + return retval; + } + + /// Reads (and potentially captures) a char group from input. Translates escaped sequences. + bool Single_Quoted_String(const bool t_capture = false) { + SkipWS(); + + if (!t_capture) { + return Single_Quoted_String_(); + } else { + const auto start = m_input_pos; + const auto prev_col = m_col; + const auto prev_line = m_line; + if (Single_Quoted_String_()) { + std::string match; + bool is_escaped = false; + for (auto s = start + 1, end = m_input_pos - 1; s != end; ++s) { + if (*s == '\\') { + if (is_escaped) { + match.push_back('\\'); + is_escaped = false; + } else { + is_escaped = true; + } + } else { + if (is_escaped) { + switch (*s) { + case ('b') : match.push_back('\b'); break; + case ('f') : match.push_back('\f'); break; + case ('n') : match.push_back('\n'); break; + case ('r') : match.push_back('\r'); break; + case ('t') : match.push_back('\t'); break; + case ('\'') : match.push_back('\''); break; + case ('\"') : match.push_back('\"'); break; + default: throw exception::eval_error("Unknown escaped sequence in string", File_Position(prev_line, prev_col), *m_filename); + } + } else { + match.push_back(*s); + } + is_escaped = false; + } + } + m_match_stack.push_back(std::make_shared(match, m_filename, prev_line, prev_col, m_line, m_col)); return true; } else { return false; } - } } + } - /** - * Reads a character group from input, without skipping initial whitespace - */ - bool Single_Quoted_String_() { - bool retval = false; - if (has_more_input() && (*m_input_pos == '\'')) { - retval = true; - char prev_char = *m_input_pos; - ++m_input_pos; - ++m_col; - - while (has_more_input() && ((*m_input_pos != '\'') || ((*m_input_pos == '\'') && (prev_char == '\\')))) { - if (!Eol_()) { - if (prev_char == '\\') { - prev_char = 0; - } - else { - prev_char = *m_input_pos; - } - ++m_input_pos; - ++m_col; - } - } - - if (m_input_pos != m_input_end) { - ++m_input_pos; - ++m_col; - } - else { - throw exception::eval_error("Unclosed single-quoted string", File_Position(m_line, m_col), *m_filename); - } - } - return retval; + /// Reads a char from input if it matches the parameter, without skipping initial whitespace + bool Char_(const char c) { + if (has_more_input() && (*m_input_pos == c)) { + ++m_input_pos; + ++m_col; + return true; + } else { + return false; } + } - /** - * Reads (and potentially captures) a char group from input. Translates escaped sequences. - */ - bool Single_Quoted_String(bool t_capture = false) { - SkipWS(); + /// Reads (and potentially captures) a char from input if it matches the parameter + bool Char(const char t_c, bool t_capture = false) { + SkipWS(); - if (!t_capture) { - return Single_Quoted_String_(); - } - else { - std::string::const_iterator start = m_input_pos; - int prev_col = m_col; - int prev_line = m_line; - if (Single_Quoted_String_()) { - std::string match; - bool is_escaped = false; - for (std::string::const_iterator s = start + 1, end = m_input_pos - 1; s != end; ++s) { - if (*s == '\\') { - if (is_escaped) { - match.push_back('\\'); - is_escaped = false; - } - else { - is_escaped = true; - } - } - else { - if (is_escaped) { - switch (*s) { - case ('b') : match.push_back('\b'); break; - case ('f') : match.push_back('\f'); break; - case ('n') : match.push_back('\n'); break; - case ('r') : match.push_back('\r'); break; - case ('t') : match.push_back('\t'); break; - case ('\'') : match.push_back('\''); break; - case ('\"') : match.push_back('\"'); break; - default: throw exception::eval_error("Unknown escaped sequence in string", File_Position(prev_line, prev_col), *m_filename); - } - } - else { - match.push_back(*s); - } - is_escaped = false; - } - } - AST_NodePtr t(new eval::Single_Quoted_String_AST_Node(match, m_filename, prev_line, prev_col, m_line, m_col)); - m_match_stack.push_back(t); - return true; - } - else { - return false; - } - } - } - - /** - * Reads a char from input if it matches the parameter, without skipping initial whitespace - */ - bool Char_(char c) { - bool retval = false; - if (has_more_input() && (*m_input_pos == c)) { - ++m_input_pos; - ++m_col; - retval = true; - } - - return retval; - } - - /** - * Reads (and potentially captures) a char from input if it matches the parameter - */ - bool Char(char t_c, bool t_capture = false) { - SkipWS(); - - if (!t_capture) { - return Char_(t_c); - } - else { - std::string::const_iterator start = m_input_pos; - int prev_col = m_col; - int prev_line = m_line; - if (Char_(t_c)) { - std::string match(start, m_input_pos); - AST_NodePtr t(new eval::Char_AST_Node(match, m_filename, prev_line, prev_col, m_line, m_col)); - m_match_stack.push_back(t); - return true; - } - else { - return false; - } - } - } - - /** - * Reads a string from input if it matches the parameter, without skipping initial whitespace - */ - bool Keyword_(const char *t_s) { - bool retval = false; - size_t len = strlen(t_s); - - if ((m_input_end - m_input_pos) >= static_cast::type>(len)) { - std::string::const_iterator tmp = m_input_pos; - for (size_t i = 0; i < len; ++i) { - if (*tmp != t_s[i]) { - return false; - } - ++tmp; - } - retval = true; - m_input_pos = tmp; - m_col += static_cast(len); - } - - return retval; - } - - /** - * Reads (and potentially captures) a string from input if it matches the parameter - */ - bool Keyword(const char *t_s, bool t_capture = false) { - SkipWS(); - std::string::const_iterator start = m_input_pos; - int prev_col = m_col; - int prev_line = m_line; - bool retval = Keyword_(t_s); - // ignore substring matches - if ( retval && has_more_input() && char_in_alphabet(*m_input_pos, detail::keyword_alphabet) ) { - m_input_pos = start; - m_col = prev_col; - m_line = prev_line; - retval = false; - } - - if ( t_capture && retval ) { + if (!t_capture) { + return Char_(t_c); + } else { + const auto start = m_input_pos; + const auto prev_col = m_col; + const auto prev_line = m_line; + if (Char_(t_c)) { std::string match(start, m_input_pos); - AST_NodePtr t(new eval::Str_AST_Node(match, m_filename, prev_line, prev_col, m_line, m_col)); - m_match_stack.push_back(t); + m_match_stack.push_back(std::make_shared(std::move(match), m_filename, prev_line, prev_col, m_line, m_col)); + return true; + } else { + return false; } - return retval; } + } - /** - * Reads a symbol group from input if it matches the parameter, without skipping initial whitespace - */ - bool Symbol_(const char *t_s) { - bool retval = false; - size_t len = strlen(t_s); + /// Reads a string from input if it matches the parameter, without skipping initial whitespace + bool Keyword_(const char *t_s) { + const auto len = strlen(t_s); - if ((m_input_end - m_input_pos) >= static_cast::type>(len)) { - std::string::const_iterator tmp = m_input_pos; - for (size_t i = 0; i < len; ++i) { - if (*tmp != t_s[i]) { - return false; - } - ++tmp; - } - retval = true; - m_input_pos = tmp; - m_col += static_cast(len); - } - - return retval; - } - - /** - * Reads (and potentially captures) a symbol group from input if it matches the parameter - */ - bool Symbol(const char *t_s, bool t_capture = false, bool t_disallow_prevention=false) { - SkipWS(); - std::string::const_iterator start = m_input_pos; - int prev_col = m_col; - int prev_line = m_line; - bool retval = Symbol_(t_s); - // ignore substring matches - if (retval && has_more_input() && (t_disallow_prevention == false) && char_in_alphabet(*m_input_pos,detail::symbol_alphabet)) { - m_input_pos = start; - m_col = prev_col; - m_line = prev_line; - retval = false; - } - - if ( t_capture && retval ) { - std::string match(start, m_input_pos); - AST_NodePtr t(new eval::Str_AST_Node(match, m_filename, prev_line, prev_col, m_line, m_col)); - m_match_stack.push_back(t); - } - - return retval; - } - - /** - * Reads an end-of-line group from input, without skipping initial whitespace - */ - bool Eol_() { - bool retval = false; - - if (has_more_input() && (Symbol_("\r\n") || Char_('\n'))) { - retval = true; - ++m_line; - m_col = 1; - } - else if (has_more_input() && Char_(';')) { - retval = true; - } - - return retval; - } - - /** - * Reads (and potentially captures) an end-of-line group from input - */ - bool Eol(bool t_capture = false) { - SkipWS(); - - if (!t_capture) { - return Eol_(); - } - else { - std::string::const_iterator start = m_input_pos; - int prev_col = m_col; - int prev_line = m_line; - if (Eol_()) { - std::string match(start, m_input_pos); - AST_NodePtr t(new eval::Eol_AST_Node(match, m_filename, prev_line, prev_col, m_line, m_col)); - m_match_stack.push_back(t); - return true; - } - else { + if ((m_input_end - m_input_pos) >= static_cast::type>(len)) { + auto tmp = m_input_pos; + for (size_t i = 0; i < len; ++i) { + if (*tmp != t_s[i]) { return false; } + ++tmp; } + m_input_pos = tmp; + m_col += static_cast(len); + return true; } - /** - * Reads a comma-separated list of values from input - */ - bool Arg_List() { + return false; + } - SkipWS(true); - bool retval = false; - - size_t prev_stack_top = m_match_stack.size(); - - if (Equation()) { - retval = true; - while (Eol()) {} - if (Char(',')) { - do { - while (Eol()) {} - if (!Equation()) { - throw exception::eval_error("Unexpected value in parameter list", File_Position(m_line, m_col), *m_filename); - } - } while (retval && Char(',')); - } - build_match(AST_NodePtr(new eval::Arg_List_AST_Node()), prev_stack_top); - } - - SkipWS(true); - - return retval; + /// Reads (and potentially captures) a string from input if it matches the parameter + bool Keyword(const char *t_s, bool t_capture = false) { + SkipWS(); + const auto start = m_input_pos; + const auto prev_col = m_col; + const auto prev_line = m_line; + bool retval = Keyword_(t_s); + // ignore substring matches + if ( retval && has_more_input() && char_in_alphabet(*m_input_pos, detail::keyword_alphabet) ) { + m_input_pos = start; + m_col = prev_col; + m_line = prev_line; + retval = false; } - /** - * Reads possible special container values, including ranges and map_pairs - */ - bool Container_Arg_List() { - bool retval = false; - SkipWS(true); + if ( t_capture && retval ) { + std::string match(start, m_input_pos); + m_match_stack.push_back(std::make_shared(std::move(match), m_filename, prev_line, prev_col, m_line, m_col)); + } + return retval; + } - size_t prev_stack_top = m_match_stack.size(); + /// Reads a symbol group from input if it matches the parameter, without skipping initial whitespace + bool Symbol_(const char *t_s) { + const auto len = strlen(t_s); - if (Value_Range()) { - retval = true; - build_match(AST_NodePtr(new eval::Arg_List_AST_Node()), prev_stack_top); - } - else if (Map_Pair()) { - retval = true; - while (Eol()) {} - if (Char(',')) { - do { - while (Eol()) {} - if (!Map_Pair()) { - throw exception::eval_error("Unexpected value in container", File_Position(m_line, m_col), *m_filename); - } - } while (retval && Char(',')); + if ((m_input_end - m_input_pos) >= static_cast::type>(len)) { + auto tmp = m_input_pos; + for (size_t i = 0; i < len; ++i) { + if (*tmp != t_s[i]) { + return false; } - build_match(AST_NodePtr(new eval::Arg_List_AST_Node()), prev_stack_top); + ++tmp; } - else if (Operator()) { - retval = true; - while (Eol()) {} - if (Char(',')) { - do { - while (Eol()) {} - if (!Operator()) { - throw exception::eval_error("Unexpected value in container", File_Position(m_line, m_col), *m_filename); - } - } while (retval && Char(',')); - } - build_match(AST_NodePtr(new eval::Arg_List_AST_Node()), prev_stack_top); - } - - SkipWS(true); - - return retval; - + m_input_pos = tmp; + m_col += static_cast(len); + return true; } - /** - * Reads a lambda (anonymous function) from input - */ - bool Lambda() { - bool retval = false; + return false; + } - size_t prev_stack_top = m_match_stack.size(); + /// Reads (and potentially captures) a symbol group from input if it matches the parameter + bool Symbol(const char *t_s, const bool t_capture = false, const bool t_disallow_prevention=false) { + SkipWS(); + const auto start = m_input_pos; + const auto prev_col = m_col; + const auto prev_line = m_line; + bool retval = Symbol_(t_s); - if (Keyword("fun")) { - retval = true; + // ignore substring matches + if (retval && has_more_input() && (t_disallow_prevention == false) && char_in_alphabet(*m_input_pos,detail::symbol_alphabet)) { + m_input_pos = start; + m_col = prev_col; + m_line = prev_line; + retval = false; + } - if (Char('(')) { - Arg_List(); - if (!Char(')')) { - throw exception::eval_error("Incomplete anonymous function", File_Position(m_line, m_col), *m_filename); + if ( t_capture && retval ) { + std::string match(start, m_input_pos); + m_match_stack.push_back(std::make_shared(std::move(match), m_filename, prev_line, prev_col, m_line, m_col)); + } + + return retval; + } + + /// Reads an end-of-line group from input, without skipping initial whitespace + bool Eol_() { + bool retval = false; + + if (has_more_input() && (Symbol_("\r\n") || Char_('\n'))) { + retval = true; + ++m_line; + m_col = 1; + } else if (has_more_input() && Char_(';')) { + retval = true; + } + + return retval; + } + + /// Reads (and potentially captures) an end-of-line group from input + bool Eol(const bool t_capture = false) { + SkipWS(); + + if (!t_capture) { + return Eol_(); + } else { + const auto start = m_input_pos; + const auto prev_col = m_col; + const auto prev_line = m_line; + if (Eol_()) { + std::string match(start, m_input_pos); + m_match_stack.push_back(std::make_shared(std::move(match), m_filename, prev_line, prev_col, m_line, m_col)); + return true; + } else { + return false; + } + } + } + + /// Reads a comma-separated list of values from input + bool Arg_List() { + SkipWS(true); + bool retval = false; + + const auto prev_stack_top = m_match_stack.size(); + + if (Equation()) { + retval = true; + while (Eol()) {} + if (Char(',')) { + do { + while (Eol()) {} + if (!Equation()) { + throw exception::eval_error("Unexpected value in parameter list", File_Position(m_line, m_col), *m_filename); } - } + } while (Char(',')); + } + build_match(std::make_shared(), prev_stack_top); + } - while (Eol()) {} + SkipWS(true); - if (!Block()) { + return retval; + } + + /// Reads possible special container values, including ranges and map_pairs + bool Container_Arg_List() { + bool retval = false; + SkipWS(true); + + const auto prev_stack_top = m_match_stack.size(); + + if (Value_Range()) { + retval = true; + build_match(std::make_shared(), prev_stack_top); + } else if (Map_Pair()) { + retval = true; + while (Eol()) {} + if (Char(',')) { + do { + while (Eol()) {} + if (!Map_Pair()) { + throw exception::eval_error("Unexpected value in container", File_Position(m_line, m_col), *m_filename); + } + } while (Char(',')); + } + build_match(std::make_shared(), prev_stack_top); + } else if (Operator()) { + retval = true; + while (Eol()) {} + if (Char(',')) { + do { + while (Eol()) {} + if (!Operator()) { + throw exception::eval_error("Unexpected value in container", File_Position(m_line, m_col), *m_filename); + } + } while (Char(',')); + } + build_match(std::make_shared(), prev_stack_top); + } + + SkipWS(true); + + return retval; + } + + /// Reads a lambda (anonymous function) from input + bool Lambda() { + bool retval = false; + + const auto prev_stack_top = m_match_stack.size(); + + if (Keyword("fun")) { + retval = true; + + if (Char('(')) { + Arg_List(); + if (!Char(')')) { throw exception::eval_error("Incomplete anonymous function", File_Position(m_line, m_col), *m_filename); } - - build_match(AST_NodePtr(new eval::Lambda_AST_Node()), prev_stack_top); } - return retval; + while (Eol()) {} + + if (!Block()) { + throw exception::eval_error("Incomplete anonymous function", File_Position(m_line, m_col), *m_filename); + } + + build_match(std::make_shared(), prev_stack_top); } - /** - * Reads a function definition from input - */ - bool Def(bool t_class_context = false) { - bool retval = false; - bool is_annotated = false; - AST_NodePtr annotation; + return retval; + } - if (Annotation()) { - while (Eol_()) {} - annotation = m_match_stack.back(); - m_match_stack.pop_back(); - is_annotated = true; + /// Reads a function definition from input + bool Def(const bool t_class_context = false) { + bool retval = false; + AST_NodePtr annotation; + + if (Annotation()) { + while (Eol_()) {} + annotation = m_match_stack.back(); + m_match_stack.pop_back(); + } + + const auto prev_stack_top = m_match_stack.size(); + + if (Keyword("def")) { + retval = true; + + if (!Id(true)) { + throw exception::eval_error("Missing function name in definition", File_Position(m_line, m_col), *m_filename); } - size_t prev_stack_top = m_match_stack.size(); + bool is_method = false; - if (Keyword("def")) { - retval = true; + if (Symbol("::", false)) { + //We're now a method + is_method = true; if (!Id(true)) { - throw exception::eval_error("Missing function name in definition", File_Position(m_line, m_col), *m_filename); - } - - bool is_method = false; - - if (Symbol("::", false)) { - //We're now a method - is_method = true; - - if (!Id(true)) { - throw exception::eval_error("Missing method name in definition", File_Position(m_line, m_col), *m_filename); - } - } - - if (Char('(')) { - Arg_List(); - if (!Char(')')) { - throw exception::eval_error("Incomplete function definition", File_Position(m_line, m_col), *m_filename); - } - } - - while (Eol()) {} - - if (Char(':')) { - if (!Operator()) { - throw exception::eval_error("Missing guard expression for function", File_Position(m_line, m_col), *m_filename); - } - } - - while (Eol()) {} - if (!Block()) { - throw exception::eval_error("Incomplete function definition", File_Position(m_line, m_col), *m_filename); - } - - if (is_method || t_class_context) { - build_match(AST_NodePtr(new eval::Method_AST_Node()), prev_stack_top); - } - else { - build_match(AST_NodePtr(new eval::Def_AST_Node()), prev_stack_top); - } - - if (is_annotated) { - m_match_stack.back()->annotation = annotation; + throw exception::eval_error("Missing method name in definition", File_Position(m_line, m_col), *m_filename); } } - return retval; + if (Char('(')) { + Arg_List(); + if (!Char(')')) { + throw exception::eval_error("Incomplete function definition", File_Position(m_line, m_col), *m_filename); + } + } + + while (Eol()) {} + + if (Char(':')) { + if (!Operator()) { + throw exception::eval_error("Missing guard expression for function", File_Position(m_line, m_col), *m_filename); + } + } + + while (Eol()) {} + if (!Block()) { + throw exception::eval_error("Incomplete function definition", File_Position(m_line, m_col), *m_filename); + } + + if (is_method || t_class_context) { + build_match(std::make_shared(), prev_stack_top); + } else { + build_match(std::make_shared(), prev_stack_top); + } + + if (annotation) { + m_match_stack.back()->annotation = std::move(annotation); + } } - /** - * Reads a function definition from input - */ - bool Try() { - bool retval = false; + return retval; + } - size_t prev_stack_top = m_match_stack.size(); + /// Reads a function definition from input + bool Try() { + bool retval = false; - if (Keyword("try")) { - retval = true; + const auto prev_stack_top = m_match_stack.size(); + + if (Keyword("try")) { + retval = true; + + while (Eol()) {} + + if (!Block()) { + throw exception::eval_error("Incomplete 'try' block", File_Position(m_line, m_col), *m_filename); + } + + bool has_matches = true; + while (has_matches) { + while (Eol()) {} + has_matches = false; + if (Keyword("catch", false)) { + const auto catch_stack_top = m_match_stack.size(); + if (Char('(')) { + if (!(Id(true) && Char(')'))) { + throw exception::eval_error("Incomplete 'catch' expression", File_Position(m_line, m_col), *m_filename); + } + if (Char(':')) { + if (!Operator()) { + throw exception::eval_error("Missing guard expression for catch", File_Position(m_line, m_col), *m_filename); + } + } + } + + while (Eol()) {} + + if (!Block()) { + throw exception::eval_error("Incomplete 'catch' block", File_Position(m_line, m_col), *m_filename); + } + build_match(std::make_shared(), catch_stack_top); + has_matches = true; + } + } + while (Eol()) {} + if (Keyword("finally", false)) { + const auto finally_stack_top = m_match_stack.size(); while (Eol()) {} if (!Block()) { - throw exception::eval_error("Incomplete 'try' block", File_Position(m_line, m_col), *m_filename); + throw exception::eval_error("Incomplete 'finally' block", File_Position(m_line, m_col), *m_filename); } + build_match(std::make_shared(), finally_stack_top); + } - bool has_matches = true; - while (has_matches) { - while (Eol()) {} - has_matches = false; - if (Keyword("catch", false)) { - size_t catch_stack_top = m_match_stack.size(); - if (Char('(')) { - if (!(Id(true) && Char(')'))) { - throw exception::eval_error("Incomplete 'catch' expression", File_Position(m_line, m_col), *m_filename); - } - if (Char(':')) { - if (!Operator()) { - throw exception::eval_error("Missing guard expression for catch", File_Position(m_line, m_col), *m_filename); - } - } + build_match(std::make_shared(), prev_stack_top); + } + + return retval; + } + + /// Reads an if/else if/else block from input + bool If() { + bool retval = false; + + const auto prev_stack_top = m_match_stack.size(); + + if (Keyword("if")) { + retval = true; + + if (!Char('(')) { + throw exception::eval_error("Incomplete 'if' expression", File_Position(m_line, m_col), *m_filename); + } + + if (!(Operator() && Char(')'))) { + throw exception::eval_error("Incomplete 'if' expression", File_Position(m_line, m_col), *m_filename); + } + + while (Eol()) {} + + if (!Block()) { + throw exception::eval_error("Incomplete 'if' block", File_Position(m_line, m_col), *m_filename); + } + + bool has_matches = true; + while (has_matches) { + while (Eol()) {} + has_matches = false; + if (Keyword("else", true)) { + if (Keyword("if")) { + const AST_NodePtr back(m_match_stack.back()); + m_match_stack.back() = std::make_shared("else if"); + m_match_stack.back()->start = back->start; + m_match_stack.back()->end = back->end; + m_match_stack.back()->children = back->children; + m_match_stack.back()->annotation = back->annotation; + if (!Char('(')) { + throw exception::eval_error("Incomplete 'else if' expression", File_Position(m_line, m_col), *m_filename); + } + + if (!(Operator() && Char(')'))) { + throw exception::eval_error("Incomplete 'else if' expression", File_Position(m_line, m_col), *m_filename); } while (Eol()) {} if (!Block()) { - throw exception::eval_error("Incomplete 'catch' block", File_Position(m_line, m_col), *m_filename); + throw exception::eval_error("Incomplete 'else if' block", File_Position(m_line, m_col), *m_filename); + } + has_matches = true; + } else { + while (Eol()) {} + + if (!Block()) { + throw exception::eval_error("Incomplete 'else' block", File_Position(m_line, m_col), *m_filename); } - build_match(AST_NodePtr(new eval::Catch_AST_Node()), catch_stack_top); has_matches = true; } } - while (Eol()) {} - if (Keyword("finally", false)) { - size_t finally_stack_top = m_match_stack.size(); - - while (Eol()) {} - - if (!Block()) { - throw exception::eval_error("Incomplete 'finally' block", File_Position(m_line, m_col), *m_filename); - } - build_match(AST_NodePtr(new eval::Finally_AST_Node()), finally_stack_top); - } - - build_match(AST_NodePtr(new eval::Try_AST_Node()), prev_stack_top); } - return retval; + build_match(std::make_shared(), prev_stack_top); } - /** - * Reads an if/else if/else block from input - */ - bool If() { - bool retval = false; + return retval; + } - size_t prev_stack_top = m_match_stack.size(); + /// Reads a class block from input + bool Class() { + bool retval = false; - if (Keyword("if")) { - retval = true; + size_t prev_stack_top = m_match_stack.size(); - if (!Char('(')) { - throw exception::eval_error("Incomplete 'if' expression", File_Position(m_line, m_col), *m_filename); - } + if (Keyword("class")) { + retval = true; - if (!(Operator() && Char(')'))) { - throw exception::eval_error("Incomplete 'if' expression", File_Position(m_line, m_col), *m_filename); - } - - while (Eol()) {} - - if (!Block()) { - throw exception::eval_error("Incomplete 'if' block", File_Position(m_line, m_col), *m_filename); - } - - bool has_matches = true; - while (has_matches) { - while (Eol()) {} - has_matches = false; - if (Keyword("else", true)) { - if (Keyword("if")) { - AST_NodePtr back(m_match_stack.back()); - m_match_stack.back() = AST_NodePtr(new eval::If_AST_Node("else if")); - m_match_stack.back()->start = back->start; - m_match_stack.back()->end = back->end; - m_match_stack.back()->children = back->children; - m_match_stack.back()->annotation = back->annotation; - if (!Char('(')) { - throw exception::eval_error("Incomplete 'else if' expression", File_Position(m_line, m_col), *m_filename); - } - - if (!(Operator() && Char(')'))) { - throw exception::eval_error("Incomplete 'else if' expression", File_Position(m_line, m_col), *m_filename); - } - - while (Eol()) {} - - if (!Block()) { - throw exception::eval_error("Incomplete 'else if' block", File_Position(m_line, m_col), *m_filename); - } - has_matches = true; - } - else { - while (Eol()) {} - - if (!Block()) { - throw exception::eval_error("Incomplete 'else' block", File_Position(m_line, m_col), *m_filename); - } - has_matches = true; - } - } - } - - build_match(AST_NodePtr(new eval::If_AST_Node()), prev_stack_top); + if (!Id(true)) { + throw exception::eval_error("Missing class name in definition", File_Position(m_line, m_col), *m_filename); } - return retval; - } - /** - * Reads a class block from input - */ - bool Class() { - bool retval = false; + while (Eol()) {} - size_t prev_stack_top = m_match_stack.size(); - - if (Keyword("class")) { - retval = true; - - if (!Id(true)) { - throw exception::eval_error("Missing class name in definition", File_Position(m_line, m_col), *m_filename); - } - - - while (Eol()) {} - - if (!Class_Block()) { - throw exception::eval_error("Incomplete 'class' block", File_Position(m_line, m_col), *m_filename); - } - - build_match(AST_NodePtr(new eval::Class_AST_Node()), prev_stack_top); + if (!Class_Block()) { + throw exception::eval_error("Incomplete 'class' block", File_Position(m_line, m_col), *m_filename); } - return retval; + build_match(std::make_shared(), prev_stack_top); } + return retval; + } - /** - * Reads a while block from input - */ - bool While() { - bool retval = false; - size_t prev_stack_top = m_match_stack.size(); + /// Reads a while block from input + bool While() { + bool retval = false; - if (Keyword("while")) { - retval = true; + const auto prev_stack_top = m_match_stack.size(); - if (!Char('(')) { - throw exception::eval_error("Incomplete 'while' expression", File_Position(m_line, m_col), *m_filename); - } + if (Keyword("while")) { + retval = true; - if (!(Operator() && Char(')'))) { - throw exception::eval_error("Incomplete 'while' expression", File_Position(m_line, m_col), *m_filename); - } - - while (Eol()) {} - - if (!Block()) { - throw exception::eval_error("Incomplete 'while' block", File_Position(m_line, m_col), *m_filename); - } - - build_match(AST_NodePtr(new eval::While_AST_Node()), prev_stack_top); + if (!Char('(')) { + throw exception::eval_error("Incomplete 'while' expression", File_Position(m_line, m_col), *m_filename); } - return retval; + if (!(Operator() && Char(')'))) { + throw exception::eval_error("Incomplete 'while' expression", File_Position(m_line, m_col), *m_filename); + } + + while (Eol()) {} + + if (!Block()) { + throw exception::eval_error("Incomplete 'while' block", File_Position(m_line, m_col), *m_filename); + } + + build_match(std::make_shared(), prev_stack_top); } + return retval; + } - /** - * Reads the C-style for conditions from input - */ - bool For_Guards() { - if (!(Equation() && Eol())) + + /// Reads the C-style for conditions from input + bool For_Guards() { + if (!(Equation() && Eol())) + { + if (!Eol()) { - if (!Eol()) - { - throw exception::eval_error("'for' loop initial statment missing", File_Position(m_line, m_col), *m_filename); - } else { - AST_NodePtr t(new eval::Noop_AST_Node()); - m_match_stack.push_back(t); - } - } - - if (!(Equation() && Eol())) - { - if (!Eol()) - { - throw exception::eval_error("'for' loop condition missing", File_Position(m_line, m_col), *m_filename); - } else { - AST_NodePtr t(new eval::Noop_AST_Node()); - m_match_stack.push_back(t); - } - } - - if (!Equation()) - { - AST_NodePtr t(new eval::Noop_AST_Node()); - m_match_stack.push_back(t); - } - - return true; - } - - /** - * Reads a for block from input - */ - bool For() { - bool retval = false; - - size_t prev_stack_top = m_match_stack.size(); - - if (Keyword("for")) { - retval = true; - - if (!Char('(')) { - throw exception::eval_error("Incomplete 'for' expression", File_Position(m_line, m_col), *m_filename); - } - - if (!(For_Guards() && Char(')'))) { - throw exception::eval_error("Incomplete 'for' expression", File_Position(m_line, m_col), *m_filename); - } - - while (Eol()) {} - - if (!Block()) { - throw exception::eval_error("Incomplete 'for' block", File_Position(m_line, m_col), *m_filename); - } - - build_match(AST_NodePtr(new eval::For_AST_Node()), prev_stack_top); - } - - return retval; - } - - /** - * Reads a case block from input - */ - bool Case() { - bool retval = false; - - size_t prev_stack_top = m_match_stack.size(); - - if (Keyword("case")) { - retval = true; - - if (!Char('(')) { - throw exception::eval_error("Incomplete 'case' expression", File_Position(m_line, m_col), *m_filename); - } - - if (!(Operator() && Char(')'))) { - throw exception::eval_error("Incomplete 'case' expression", File_Position(m_line, m_col), *m_filename); - } - - while (Eol()) {} - - if (!Block()) { - throw exception::eval_error("Incomplete 'case' block", File_Position(m_line, m_col), *m_filename); - } - - build_match(AST_NodePtr(new eval::Case_AST_Node()), prev_stack_top); - } - else if (Keyword("default")) { - while (Eol()) {} - - if (!Block()) { - throw exception::eval_error("Incomplete 'default' block", File_Position(m_line, m_col), *m_filename); - } - - build_match(AST_NodePtr(new eval::Default_AST_Node()), prev_stack_top); - } - - return retval; - } - - /** - * Reads a switch statement from input - */ - bool Switch() { - size_t prev_stack_top = m_match_stack.size(); - - if (Keyword("switch")) { - - if (!Char('(')) { - throw exception::eval_error("Incomplete 'switch' expression", File_Position(m_line, m_col), *m_filename); - } - - if (!(Operator() && Char(')'))) { - throw exception::eval_error("Incomplete 'switch' expression", File_Position(m_line, m_col), *m_filename); - } - - while (Eol()) {} - - if (Char('{')) { - while (Eol()) {} - - while (Case()) { - while (Eol()) { } // eat - } - - while (Eol()) { } // eat - - if (!Char('}')) { - throw exception::eval_error("Incomplete block", File_Position(m_line, m_col), *m_filename); - } - } - else { - throw exception::eval_error("Incomplete block", File_Position(m_line, m_col), *m_filename); - } - - build_match(AST_NodePtr(new eval::Switch_AST_Node()), prev_stack_top); - return true; - + throw exception::eval_error("'for' loop initial statment missing", File_Position(m_line, m_col), *m_filename); } else { - return false; + m_match_stack.push_back(std::make_shared()); } - } - /** - * Reads a curly-brace C-style class block from input - */ - bool Class_Block() { - bool retval = false; + if (!(Equation() && Eol())) + { + if (!Eol()) + { + throw exception::eval_error("'for' loop condition missing", File_Position(m_line, m_col), *m_filename); + } else { + m_match_stack.push_back(std::make_shared()); + } + } - size_t prev_stack_top = m_match_stack.size(); + if (!Equation()) + { + m_match_stack.push_back(std::make_shared()); + } + + return true; + } + + /** + * Reads a for block from input + */ + bool For() { + bool retval = false; + + const auto prev_stack_top = m_match_stack.size(); + + if (Keyword("for")) { + retval = true; + + if (!Char('(')) { + throw exception::eval_error("Incomplete 'for' expression", File_Position(m_line, m_col), *m_filename); + } + + if (!(For_Guards() && Char(')'))) { + throw exception::eval_error("Incomplete 'for' expression", File_Position(m_line, m_col), *m_filename); + } + + while (Eol()) {} + + if (!Block()) { + throw exception::eval_error("Incomplete 'for' block", File_Position(m_line, m_col), *m_filename); + } + + build_match(std::make_shared(), prev_stack_top); + } + + return retval; + } + + /// Reads a case block from input + bool Case() { + bool retval = false; + + const auto prev_stack_top = m_match_stack.size(); + + if (Keyword("case")) { + retval = true; + + if (!Char('(')) { + throw exception::eval_error("Incomplete 'case' expression", File_Position(m_line, m_col), *m_filename); + } + + if (!(Operator() && Char(')'))) { + throw exception::eval_error("Incomplete 'case' expression", File_Position(m_line, m_col), *m_filename); + } + + while (Eol()) {} + + if (!Block()) { + throw exception::eval_error("Incomplete 'case' block", File_Position(m_line, m_col), *m_filename); + } + + build_match(std::make_shared(), prev_stack_top); + } else if (Keyword("default")) { + while (Eol()) {} + + if (!Block()) { + throw exception::eval_error("Incomplete 'default' block", File_Position(m_line, m_col), *m_filename); + } + + build_match(std::make_shared(), prev_stack_top); + } + + return retval; + } + + + /// Reads a switch statement from input + bool Switch() { + const auto prev_stack_top = m_match_stack.size(); + + if (Keyword("switch")) { + + if (!Char('(')) { + throw exception::eval_error("Incomplete 'switch' expression", File_Position(m_line, m_col), *m_filename); + } + + if (!(Operator() && Char(')'))) { + throw exception::eval_error("Incomplete 'switch' expression", File_Position(m_line, m_col), *m_filename); + } + + while (Eol()) {} if (Char('{')) { - retval = true; + while (Eol()) {} - Class_Statements(); - if (!Char('}')) { - throw exception::eval_error("Incomplete class block", File_Position(m_line, m_col), *m_filename); + while (Case()) { + while (Eol()) { } // eat } - build_match(AST_NodePtr(new eval::Block_AST_Node()), prev_stack_top); - } + while (Eol()) { } // eat - return retval; - } - - /** - * Reads a curly-brace C-style block from input - */ - bool Block() { - bool retval = false; - - size_t prev_stack_top = m_match_stack.size(); - - if (Char('{')) { - retval = true; - - Statements(); if (!Char('}')) { throw exception::eval_error("Incomplete block", File_Position(m_line, m_col), *m_filename); } - - build_match(AST_NodePtr(new eval::Block_AST_Node()), prev_stack_top); - } - - return retval; - } - - /** - * Reads a return statement from input - */ - bool Return() { - bool retval = false; - - size_t prev_stack_top = m_match_stack.size(); - - if (Keyword("return")) { - retval = true; - - Operator(); - build_match(AST_NodePtr(new eval::Return_AST_Node()), prev_stack_top); - } - - return retval; - } - - /** - * Reads a break statement from input - */ - bool Break() { - bool retval = false; - - size_t prev_stack_top = m_match_stack.size(); - - if (Keyword("break")) { - retval = true; - - build_match(AST_NodePtr(new eval::Break_AST_Node()), prev_stack_top); - } - - return retval; - } - - /** - * Reads a continue statement from input - */ - bool Continue() { - bool retval = false; - - size_t prev_stack_top = m_match_stack.size(); - - if (Keyword("continue")) { - retval = true; - - build_match(AST_NodePtr(new eval::Continue_AST_Node()), prev_stack_top); - } - - return retval; - } - - /** - * Reads a dot expression(member access), then proceeds to check if it's a function or array call - */ - bool Dot_Fun_Array() { - bool retval = false; - - size_t prev_stack_top = m_match_stack.size(); - if (Lambda() || Num(true) || Quoted_String(true) || Single_Quoted_String(true) || - Paren_Expression() || Inline_Container() || Id(true)) { - retval = true; - bool has_more = true; - - while (has_more) { - has_more = false; - - if (Char('(')) { - has_more = true; - - Arg_List(); - if (!Char(')')) { - throw exception::eval_error("Incomplete function call", File_Position(m_line, m_col), *m_filename); - } - - build_match(AST_NodePtr(new eval::Fun_Call_AST_Node()), prev_stack_top); - /// \todo Work around for method calls until we have a better solution - if (!m_match_stack.back()->children.empty()) { - if (m_match_stack.back()->children[0]->identifier == AST_Node_Type::Dot_Access) { - AST_NodePtr dot_access = m_match_stack.back()->children[0]; - AST_NodePtr func_call = m_match_stack.back(); - m_match_stack.pop_back(); - func_call->children.erase(func_call->children.begin()); - func_call->children.insert(func_call->children.begin(), dot_access->children.back()); - dot_access->children.pop_back(); - dot_access->children.push_back(func_call); - m_match_stack.push_back(dot_access); - } - } - } - else if (Char('[')) { - has_more = true; - - if (!(Operator() && Char(']'))) { - throw exception::eval_error("Incomplete array access", File_Position(m_line, m_col), *m_filename); - } - - build_match(AST_NodePtr(new eval::Array_Call_AST_Node()), prev_stack_top); - } - else if (Symbol(".", true)) { - has_more = true; - if (!(Id(true))) { - throw exception::eval_error("Incomplete array access", File_Position(m_line, m_col), *m_filename); - } - - build_match(AST_NodePtr(new eval::Dot_Access_AST_Node()), prev_stack_top); - } - } - } - - return retval; - } - - /** - * Reads a variable declaration from input - */ - bool Var_Decl(bool t_class_context = false) { - bool retval = false; - - size_t prev_stack_top = m_match_stack.size(); - - if (t_class_context && (Keyword("attr") || Keyword("auto") || Keyword("var"))) { - retval = true; - - if (!Id(true)) { - throw exception::eval_error("Incomplete attribute declaration", File_Position(m_line, m_col), *m_filename); - } - - build_match(AST_NodePtr(new eval::Attr_Decl_AST_Node()), prev_stack_top); - } else if (Keyword("auto") || Keyword("var")) { - retval = true; - - if (!(Reference() || Id(true))) { - throw exception::eval_error("Incomplete variable declaration", File_Position(m_line, m_col), *m_filename); - } - - build_match(AST_NodePtr(new eval::Var_Decl_AST_Node()), prev_stack_top); - } else if (Keyword("attr")) { - retval = true; - - if (!Id(true)) { - throw exception::eval_error("Incomplete attribute declaration", File_Position(m_line, m_col), *m_filename); - } - if (!Symbol("::", false)) { - throw exception::eval_error("Incomplete attribute declaration", File_Position(m_line, m_col), *m_filename); - } - if (!Id(true)) { - throw exception::eval_error("Missing attribute name in definition", File_Position(m_line, m_col), *m_filename); - } - - - build_match(AST_NodePtr(new eval::Attr_Decl_AST_Node()), prev_stack_top); - } - - return retval; - } - - /** - * Reads an expression surrounded by parentheses from input - */ - bool Paren_Expression() { - bool retval = false; - - if (Char('(')) { - retval = true; - if (!Operator()) { - throw exception::eval_error("Incomplete expression", File_Position(m_line, m_col), *m_filename); - } - if (!Char(')')) { - throw exception::eval_error("Missing closing parenthesis ')'", File_Position(m_line, m_col), *m_filename); - } - } - return retval; - } - - /** - * Reads, and identifies, a short-form container initialization from input - */ - bool Inline_Container() { - bool retval = false; - - size_t prev_stack_top = m_match_stack.size(); - - if (Char('[')) { - retval = true; - Container_Arg_List(); - - if (!Char(']')) { - throw exception::eval_error("Missing closing square bracket ']' in container initializer", File_Position(m_line, m_col), *m_filename); - } - if ((prev_stack_top != m_match_stack.size()) && (m_match_stack.back()->children.size() > 0)) { - if (m_match_stack.back()->children[0]->identifier == AST_Node_Type::Value_Range) { - build_match(AST_NodePtr(new eval::Inline_Range_AST_Node()), prev_stack_top); - } - else if (m_match_stack.back()->children[0]->identifier == AST_Node_Type::Map_Pair) { - build_match(AST_NodePtr(new eval::Inline_Map_AST_Node()), prev_stack_top); - } - else { - build_match(AST_NodePtr(new eval::Inline_Array_AST_Node()), prev_stack_top); - } - } - else { - build_match(AST_NodePtr(new eval::Inline_Array_AST_Node()), prev_stack_top); - } - } - - return retval; - } - - bool Reference() { - bool retval = false; - - size_t prev_stack_top = m_match_stack.size(); - - if (Symbol("&", false)) { - retval = true; - - if (!Id(true)) { - throw exception::eval_error("Incomplete '&' expression", File_Position(m_line, m_col), *m_filename); - } - - build_match(AST_NodePtr( - new eval::Reference_AST_Node()), prev_stack_top); - } - - return retval; - } - - /** - * Reads a unary prefixed expression from input - */ - bool Prefix() { - bool retval = false; - - size_t prev_stack_top = m_match_stack.size(); - - if (Symbol("++", true)) { - retval = true; - - if (!Operator(m_operators.size()-1)) { - throw exception::eval_error("Incomplete '++' expression", File_Position(m_line, m_col), *m_filename); - } - - build_match(AST_NodePtr(new eval::Prefix_AST_Node()), prev_stack_top); - } - else if (Symbol("--", true)) { - retval = true; - - if (!Operator(m_operators.size()-1)) { - throw exception::eval_error("Incomplete '--' expression", File_Position(m_line, m_col), *m_filename); - } - - build_match(AST_NodePtr(new eval::Prefix_AST_Node()), prev_stack_top); - } - else if (Char('-', true)) { - retval = true; - - if (!Operator(m_operators.size()-1)) { - throw exception::eval_error("Incomplete unary '-' expression", File_Position(m_line, m_col), *m_filename); - } - - build_match(AST_NodePtr(new eval::Prefix_AST_Node()), prev_stack_top); - } - else if (Char('+', true)) { - retval = true; - - if (!Operator(m_operators.size()-1)) { - throw exception::eval_error("Incomplete unary '+' expression", File_Position(m_line, m_col), *m_filename); - } - - build_match(AST_NodePtr(new eval::Prefix_AST_Node()), prev_stack_top); - } - else if (Char('!', true)) { - retval = true; - - if (!Operator(m_operators.size()-1)) { - throw exception::eval_error("Incomplete '!' expression", File_Position(m_line, m_col), *m_filename); - } - - build_match(AST_NodePtr(new eval::Prefix_AST_Node()), prev_stack_top); - } - else if (Char('~', true)) { - retval = true; - - if (!Operator(m_operators.size()-1)) { - throw exception::eval_error("Incomplete '~' expression", File_Position(m_line, m_col), *m_filename); - } - - build_match(AST_NodePtr(new eval::Prefix_AST_Node()), prev_stack_top); - } - else if (Char('&', true)) { - retval = true; - - if (!Operator(m_operators.size()-1)) { - throw exception::eval_error("Incomplete '~' expression", File_Position(m_line, m_col), *m_filename); - } - - build_match(AST_NodePtr(new eval::Prefix_AST_Node()), prev_stack_top); - } - - return retval; - } - - /** - * Parses any of a group of 'value' style ast_node groups from input - */ - bool Value() { - if (Var_Decl() || Dot_Fun_Array() || Prefix()) { - return true; } else { - return false; + throw exception::eval_error("Incomplete block", File_Position(m_line, m_col), *m_filename); } - } - bool Operator_Helper(size_t t_precedence) { - for (auto & elem : m_operator_matches[t_precedence]) { - if (Symbol(elem.c_str(), true)) { - return true; - } - } + build_match(std::make_shared(), prev_stack_top); + return true; + + } else { return false; } - bool Operator(size_t t_precedence = 0) { - bool retval = false; - AST_NodePtr oper; - size_t prev_stack_top = m_match_stack.size(); + } - if (t_precedence < m_operators.size()) { - if (Operator(t_precedence+1)) { - retval = true; - if (Operator_Helper(t_precedence)) { - do { - while (Eol()) {} - if (!Operator(t_precedence+1)) { - throw exception::eval_error("Incomplete " - + std::string(ast_node_type_to_string(m_operators[t_precedence])) + " expression", - File_Position(m_line, m_col), *m_filename); - } - switch (m_operators[t_precedence]) { - case(AST_Node_Type::Comparison) : - build_match(AST_NodePtr(new eval::Comparison_AST_Node()), prev_stack_top); - break; - case(AST_Node_Type::Ternary_Cond) : - m_match_stack.erase(m_match_stack.begin() + m_match_stack.size() - 2, - m_match_stack.begin() + m_match_stack.size() - 1); - if (Symbol(":")) { - if (!Operator(t_precedence+1)) { - throw exception::eval_error("Incomplete " - + std::string(ast_node_type_to_string(m_operators[t_precedence])) + " expression", - File_Position(m_line, m_col), *m_filename); - } - build_match(AST_NodePtr(new eval::Ternary_Cond_AST_Node()), prev_stack_top); - } - else { + /// Reads a curly-brace C-style class block from input + bool Class_Block() { + bool retval = false; + + const auto prev_stack_top = m_match_stack.size(); + + if (Char('{')) { + retval = true; + + Class_Statements(); + if (!Char('}')) { + throw exception::eval_error("Incomplete class block", File_Position(m_line, m_col), *m_filename); + } + + build_match(std::make_shared(), prev_stack_top); + } + + return retval; + } + + /// Reads a curly-brace C-style block from input + bool Block() { + bool retval = false; + + const auto prev_stack_top = m_match_stack.size(); + + if (Char('{')) { + retval = true; + + Statements(); + if (!Char('}')) { + throw exception::eval_error("Incomplete block", File_Position(m_line, m_col), *m_filename); + } + + build_match(std::make_shared(), prev_stack_top); + } + + return retval; + } + + /// Reads a return statement from input + bool Return() { + const auto prev_stack_top = m_match_stack.size(); + + if (Keyword("return")) { + Operator(); + build_match(std::make_shared(), prev_stack_top); + return true; + } else { + return false; + } + } + + /// Reads a break statement from input + bool Break() { + const auto prev_stack_top = m_match_stack.size(); + + if (Keyword("break")) { + build_match(std::make_shared(), prev_stack_top); + return true; + } else { + return false; + } + } + + /// Reads a continue statement from input + bool Continue() { + const auto prev_stack_top = m_match_stack.size(); + + if (Keyword("continue")) { + build_match(std::make_shared(), prev_stack_top); + return true; + } else { + return false; + } + } + + /// Reads a dot expression(member access), then proceeds to check if it's a function or array call + bool Dot_Fun_Array() { + bool retval = false; + + const auto prev_stack_top = m_match_stack.size(); + if (Lambda() || Num(true) || Quoted_String(true) || Single_Quoted_String(true) || + Paren_Expression() || Inline_Container() || Id(true)) + { + retval = true; + bool has_more = true; + + while (has_more) { + has_more = false; + + if (Char('(')) { + has_more = true; + + Arg_List(); + if (!Char(')')) { + throw exception::eval_error("Incomplete function call", File_Position(m_line, m_col), *m_filename); + } + + build_match(std::make_shared(), prev_stack_top); + /// \todo Work around for method calls until we have a better solution + if (!m_match_stack.back()->children.empty()) { + if (m_match_stack.back()->children[0]->identifier == AST_Node_Type::Dot_Access) { + AST_NodePtr dot_access = m_match_stack.back()->children[0]; + AST_NodePtr func_call = m_match_stack.back(); + m_match_stack.pop_back(); + func_call->children.erase(func_call->children.begin()); + func_call->children.insert(func_call->children.begin(), dot_access->children.back()); + dot_access->children.pop_back(); + dot_access->children.push_back(std::move(func_call)); + m_match_stack.push_back(std::move(dot_access)); + } + } + } else if (Char('[')) { + has_more = true; + + if (!(Operator() && Char(']'))) { + throw exception::eval_error("Incomplete array access", File_Position(m_line, m_col), *m_filename); + } + + build_match(std::make_shared(), prev_stack_top); + } + else if (Symbol(".", true)) { + has_more = true; + if (!(Id(true))) { + throw exception::eval_error("Incomplete array access", File_Position(m_line, m_col), *m_filename); + } + + build_match(std::make_shared(), prev_stack_top); + } + } + } + + return retval; + } + + /// Reads a variable declaration from input + bool Var_Decl(const bool t_class_context = false) { + bool retval = false; + + const auto prev_stack_top = m_match_stack.size(); + + if (t_class_context && (Keyword("attr") || Keyword("auto") || Keyword("var"))) { + retval = true; + + if (!Id(true)) { + throw exception::eval_error("Incomplete attribute declaration", File_Position(m_line, m_col), *m_filename); + } + + build_match(std::make_shared(), prev_stack_top); + } else if (Keyword("auto") || Keyword("var")) { + retval = true; + + if (!(Reference() || Id(true))) { + throw exception::eval_error("Incomplete variable declaration", File_Position(m_line, m_col), *m_filename); + } + + build_match(std::make_shared(), prev_stack_top); + } else if (Keyword("attr")) { + retval = true; + + if (!Id(true)) { + throw exception::eval_error("Incomplete attribute declaration", File_Position(m_line, m_col), *m_filename); + } + if (!Symbol("::", false)) { + throw exception::eval_error("Incomplete attribute declaration", File_Position(m_line, m_col), *m_filename); + } + if (!Id(true)) { + throw exception::eval_error("Missing attribute name in definition", File_Position(m_line, m_col), *m_filename); + } + + + build_match(std::make_shared(), prev_stack_top); + } + + return retval; + } + + /// Reads an expression surrounded by parentheses from input + bool Paren_Expression() { + if (Char('(')) { + if (!Operator()) { + throw exception::eval_error("Incomplete expression", File_Position(m_line, m_col), *m_filename); + } + if (!Char(')')) { + throw exception::eval_error("Missing closing parenthesis ')'", File_Position(m_line, m_col), *m_filename); + } + return true; + } else { + return false; + } + } + + /// Reads, and identifies, a short-form container initialization from input + bool Inline_Container() { + const auto prev_stack_top = m_match_stack.size(); + + if (Char('[')) { + Container_Arg_List(); + + if (!Char(']')) { + throw exception::eval_error("Missing closing square bracket ']' in container initializer", File_Position(m_line, m_col), *m_filename); + } + if ((prev_stack_top != m_match_stack.size()) && (m_match_stack.back()->children.size() > 0)) { + if (m_match_stack.back()->children[0]->identifier == AST_Node_Type::Value_Range) { + build_match(std::make_shared(), prev_stack_top); + } + else if (m_match_stack.back()->children[0]->identifier == AST_Node_Type::Map_Pair) { + build_match(std::make_shared(), prev_stack_top); + } + else { + build_match(std::make_shared(), prev_stack_top); + } + } + else { + build_match(std::make_shared(), prev_stack_top); + } + + return true; + } else { + return false; + } + } + + /// Parses a variable specified with a & aka reference + bool Reference() { + const auto prev_stack_top = m_match_stack.size(); + + if (Symbol("&", false)) { + if (!Id(true)) { + throw exception::eval_error("Incomplete '&' expression", File_Position(m_line, m_col), *m_filename); + } + + build_match(std::make_shared(), prev_stack_top); + return true; + } else { + return false; + } + } + + /// Reads a unary prefixed expression from input + bool Prefix() { + bool retval = false; + + const auto prev_stack_top = m_match_stack.size(); + + if (Symbol("++", true)) { + retval = true; + + if (!Operator(m_operators.size()-1)) { + throw exception::eval_error("Incomplete '++' expression", File_Position(m_line, m_col), *m_filename); + } + + build_match(std::make_shared(), prev_stack_top); + } else if (Symbol("--", true)) { + retval = true; + + if (!Operator(m_operators.size()-1)) { + throw exception::eval_error("Incomplete '--' expression", File_Position(m_line, m_col), *m_filename); + } + + build_match(std::make_shared(), prev_stack_top); + } else if (Char('-', true)) { + retval = true; + + if (!Operator(m_operators.size()-1)) { + throw exception::eval_error("Incomplete unary '-' expression", File_Position(m_line, m_col), *m_filename); + } + + build_match(std::make_shared(), prev_stack_top); + } else if (Char('+', true)) { + retval = true; + + if (!Operator(m_operators.size()-1)) { + throw exception::eval_error("Incomplete unary '+' expression", File_Position(m_line, m_col), *m_filename); + } + + build_match(std::make_shared(), prev_stack_top); + } + else if (Char('!', true)) { + retval = true; + + if (!Operator(m_operators.size()-1)) { + throw exception::eval_error("Incomplete '!' expression", File_Position(m_line, m_col), *m_filename); + } + + build_match(std::make_shared(), prev_stack_top); + } + else if (Char('~', true)) { + retval = true; + + if (!Operator(m_operators.size()-1)) { + throw exception::eval_error("Incomplete '~' expression", File_Position(m_line, m_col), *m_filename); + } + + build_match(std::make_shared(), prev_stack_top); + } + else if (Char('&', true)) { + retval = true; + + if (!Operator(m_operators.size()-1)) { + throw exception::eval_error("Incomplete '~' expression", File_Position(m_line, m_col), *m_filename); + } + + build_match(std::make_shared(), prev_stack_top); + } + + return retval; + } + + /// Parses any of a group of 'value' style ast_node groups from input + bool Value() { + if (Var_Decl() || Dot_Fun_Array() || Prefix()) { + return true; + } else { + return false; + } + } + + bool Operator_Helper(const size_t t_precedence) { + for (auto & elem : m_operator_matches[t_precedence]) { + if (Symbol(elem.c_str(), true)) { + return true; + } + } + return false; + } + + bool Operator(const size_t t_precedence = 0) { + bool retval = false; + AST_NodePtr oper; + const auto prev_stack_top = m_match_stack.size(); + + if (t_precedence < m_operators.size()) { + if (Operator(t_precedence+1)) { + retval = true; + if (Operator_Helper(t_precedence)) { + do { + while (Eol()) {} + if (!Operator(t_precedence+1)) { + throw exception::eval_error("Incomplete " + + std::string(ast_node_type_to_string(m_operators[t_precedence])) + " expression", + File_Position(m_line, m_col), *m_filename); + } + + switch (m_operators[t_precedence]) { + case(AST_Node_Type::Comparison) : + build_match(std::make_shared(), prev_stack_top); + break; + case(AST_Node_Type::Ternary_Cond) : + m_match_stack.erase(m_match_stack.begin() + m_match_stack.size() - 2, + m_match_stack.begin() + m_match_stack.size() - 1); + if (Symbol(":")) { + if (!Operator(t_precedence+1)) { throw exception::eval_error("Incomplete " + std::string(ast_node_type_to_string(m_operators[t_precedence])) + " expression", File_Position(m_line, m_col), *m_filename); } - break; - case(AST_Node_Type::Addition) : - oper = m_match_stack.at(m_match_stack.size()-2); - m_match_stack.erase(m_match_stack.begin() + m_match_stack.size() - 2, - m_match_stack.begin() + m_match_stack.size() - 1); - if (oper->text == "+") { - build_match(AST_NodePtr(new eval::Addition_AST_Node()), prev_stack_top); - } - else if (oper->text == "-") { - build_match(AST_NodePtr(new eval::Subtraction_AST_Node()), prev_stack_top); - } - break; - case(AST_Node_Type::Multiplication) : - oper = m_match_stack.at(m_match_stack.size()-2); - m_match_stack.erase(m_match_stack.begin() + m_match_stack.size() - 2, - m_match_stack.begin() + m_match_stack.size() - 1); - if (oper->text == "*") { - build_match(AST_NodePtr(new eval::Multiplication_AST_Node()), prev_stack_top); - } - else if (oper->text == "/") { - build_match(AST_NodePtr(new eval::Division_AST_Node()), prev_stack_top); - } - else if (oper->text == "%") { - build_match(AST_NodePtr(new eval::Modulus_AST_Node()), prev_stack_top); - } - break; - case(AST_Node_Type::Shift) : - build_match(AST_NodePtr(new eval::Shift_AST_Node()), prev_stack_top); - break; - case(AST_Node_Type::Equality) : - build_match(AST_NodePtr(new eval::Equality_AST_Node()), prev_stack_top); - break; - case(AST_Node_Type::Bitwise_And) : - build_match(AST_NodePtr(new eval::Bitwise_And_AST_Node()), prev_stack_top); - break; - case(AST_Node_Type::Bitwise_Xor) : - build_match(AST_NodePtr(new eval::Bitwise_Xor_AST_Node()), prev_stack_top); - break; - case(AST_Node_Type::Bitwise_Or) : - build_match(AST_NodePtr(new eval::Bitwise_Or_AST_Node()), prev_stack_top); - break; - case(AST_Node_Type::Logical_And) : - build_match(AST_NodePtr(new eval::Logical_And_AST_Node()), prev_stack_top); - break; - case(AST_Node_Type::Logical_Or) : - build_match(AST_NodePtr(new eval::Logical_Or_AST_Node()), prev_stack_top); - break; - default: - throw exception::eval_error("Internal error: unhandled ast_node", File_Position(m_line, m_col), *m_filename); - } - } while (Operator_Helper(t_precedence)); - } + build_match(std::make_shared(), prev_stack_top); + } + else { + throw exception::eval_error("Incomplete " + + std::string(ast_node_type_to_string(m_operators[t_precedence])) + " expression", + File_Position(m_line, m_col), *m_filename); + } + break; + case(AST_Node_Type::Addition) : + oper = m_match_stack.at(m_match_stack.size()-2); + m_match_stack.erase(m_match_stack.begin() + m_match_stack.size() - 2, + m_match_stack.begin() + m_match_stack.size() - 1); + if (oper->text == "+") { + build_match(std::make_shared(), prev_stack_top); + } + else if (oper->text == "-") { + build_match(std::make_shared(), prev_stack_top); + } + break; + case(AST_Node_Type::Multiplication) : + oper = m_match_stack.at(m_match_stack.size()-2); + m_match_stack.erase(m_match_stack.begin() + m_match_stack.size() - 2, + m_match_stack.begin() + m_match_stack.size() - 1); + if (oper->text == "*") { + build_match(std::make_shared(), prev_stack_top); + } + else if (oper->text == "/") { + build_match(std::make_shared(), prev_stack_top); + } + else if (oper->text == "%") { + build_match(std::make_shared(), prev_stack_top); + } + break; + case(AST_Node_Type::Shift) : + build_match(std::make_shared(), prev_stack_top); + break; + case(AST_Node_Type::Equality) : + build_match(std::make_shared(), prev_stack_top); + break; + case(AST_Node_Type::Bitwise_And) : + build_match(std::make_shared(), prev_stack_top); + break; + case(AST_Node_Type::Bitwise_Xor) : + build_match(std::make_shared(), prev_stack_top); + break; + case(AST_Node_Type::Bitwise_Or) : + build_match(std::make_shared(), prev_stack_top); + break; + case(AST_Node_Type::Logical_And) : + build_match(std::make_shared(), prev_stack_top); + break; + case(AST_Node_Type::Logical_Or) : + build_match(std::make_shared(), prev_stack_top); + break; + default: + throw exception::eval_error("Internal error: unhandled ast_node", File_Position(m_line, m_col), *m_filename); + } + } while (Operator_Helper(t_precedence)); } } - else { - return Value(); - } - - return retval; + } + else { + return Value(); } - /** - * Reads a pair of values used to create a map initialization from input - */ - bool Map_Pair() { - bool retval = false; + return retval; + } - size_t prev_stack_top = m_match_stack.size(); - std::string::const_iterator prev_pos = m_input_pos; - int prev_col = m_col; + /// Reads a pair of values used to create a map initialization from input + bool Map_Pair() { + bool retval = false; - if (Operator()) { - if (Symbol(":")) { - retval = true; - if (!Operator()) { - throw exception::eval_error("Incomplete map pair", File_Position(m_line, m_col), *m_filename); - } + const auto prev_stack_top = m_match_stack.size(); + const auto prev_pos = m_input_pos; + const auto prev_col = m_col; - build_match(AST_NodePtr(new eval::Map_Pair_AST_Node()), prev_stack_top); - } - else { - m_input_pos = prev_pos; - m_col = prev_col; - while (prev_stack_top != m_match_stack.size()) { - m_match_stack.pop_back(); - } - } - } - - return retval; - } - - /** - * Reads a pair of values used to create a range initialization from input - */ - bool Value_Range() { - bool retval = false; - - size_t prev_stack_top = m_match_stack.size(); - std::string::const_iterator prev_pos = m_input_pos; - int prev_col = m_col; - - if (Operator()) { - if (Symbol("..")) { - retval = true; - if (!Operator()) { - throw exception::eval_error("Incomplete value range", File_Position(m_line, m_col), *m_filename); - } - - build_match(AST_NodePtr(new eval::Value_Range_AST_Node()), prev_stack_top); - } - else { - m_input_pos = prev_pos; - m_col = prev_col; - while (prev_stack_top != m_match_stack.size()) { - m_match_stack.pop_back(); - } - } - } - - return retval; - } - - /** - * Parses a string of binary equation operators - */ - bool Equation() { - bool retval = false; - - size_t prev_stack_top = m_match_stack.size(); - - if (Operator()) { + if (Operator()) { + if (Symbol(":")) { retval = true; - if (Symbol("=", true, true) || Symbol(":=", true, true) || Symbol("+=", true, true) || - Symbol("-=", true, true) || Symbol("*=", true, true) || Symbol("/=", true, true) || - Symbol("%=", true, true) || Symbol("<<=", true, true) || Symbol(">>=", true, true) || - Symbol("&=", true, true) || Symbol("^=", true, true) || Symbol("|=", true, true)) { - SkipWS(true); - if (!Equation()) { - throw exception::eval_error("Incomplete equation", File_Position(m_line, m_col), *m_filename); - } + if (!Operator()) { + throw exception::eval_error("Incomplete map pair", File_Position(m_line, m_col), *m_filename); + } - build_match(AST_NodePtr(new eval::Equation_AST_Node()), prev_stack_top); - } - } - - return retval; - } - - /** - * Parses statements allowed inside of a class block - */ - bool Class_Statements() { - bool retval = false; - - bool has_more = true; - bool saw_eol = true; - - while (has_more) { - int prev_line = m_line; - int prev_col = m_col; - if (Def(true)) { - if (!saw_eol) { - throw exception::eval_error("Two function definitions missing line separator", File_Position(prev_line, prev_col), *m_filename); - } - has_more = true; - retval = true; - saw_eol = true; - } else if (Var_Decl(true)) { - if (!saw_eol) { - throw exception::eval_error("Two function definitions missing line separator", File_Position(prev_line, prev_col), *m_filename); - } - has_more = true; - retval = true; - saw_eol = true; - } else if (Eol()) { - has_more = true; - retval = true; - saw_eol = true; - } else { - has_more = false; - } - } - - return retval; - } - - /** - * Top level parser, starts parsing of all known parses - */ - bool Statements() { - bool retval = false; - - bool has_more = true; - bool saw_eol = true; - - while (has_more) { - int prev_line = m_line; - int prev_col = m_col; - if (Def()) { - if (!saw_eol) { - throw exception::eval_error("Two function definitions missing line separator", File_Position(prev_line, prev_col), *m_filename); - } - has_more = true; - retval = true; - saw_eol = true; - } - else if (Try()) { - if (!saw_eol) { - throw exception::eval_error("Two function definitions missing line separator", File_Position(prev_line, prev_col), *m_filename); - } - has_more = true; - retval = true; - saw_eol = true; - } - else if (If()) { - if (!saw_eol) { - throw exception::eval_error("Two function definitions missing line separator", File_Position(prev_line, prev_col), *m_filename); - } - has_more = true; - retval = true; - saw_eol = true; - } - else if (While()) { - if (!saw_eol) { - throw exception::eval_error("Two function definitions missing line separator", File_Position(prev_line, prev_col), *m_filename); - } - has_more = true; - retval = true; - saw_eol = true; - } - else if (Class()) { - if (!saw_eol) { - throw exception::eval_error("Two function definitions missing line separator", File_Position(prev_line, prev_col), *m_filename); - } - has_more = true; - retval = true; - saw_eol = true; - } - else if (For()) { - if (!saw_eol) { - throw exception::eval_error("Two function definitions missing line separator", File_Position(prev_line, prev_col), *m_filename); - } - has_more = true; - retval = true; - saw_eol = true; - } - else if (Switch()) { - if (!saw_eol) { - throw exception::eval_error("Two function definitions missing line separator", File_Position(prev_line, prev_col), *m_filename); - } - has_more = true; - retval = true; - saw_eol = true; - } - else if (Return()) { - if (!saw_eol) { - throw exception::eval_error("Two expressions missing line separator", File_Position(prev_line, prev_col), *m_filename); - } - has_more = true; - retval = true; - saw_eol = false; - } - else if (Break()) { - if (!saw_eol) { - throw exception::eval_error("Two expressions missing line separator", File_Position(prev_line, prev_col), *m_filename); - } - has_more = true; - retval = true; - saw_eol = false; - } - else if (Continue()) { - if (!saw_eol) { - throw exception::eval_error("Two expressions missing line separator", File_Position(prev_line, prev_col), *m_filename); - } - has_more = true; - retval = true; - saw_eol = false; - } - else if (Block()) { - has_more = true; - retval = true; - saw_eol = true; - } - else if (Equation()) { - if (!saw_eol) { - throw exception::eval_error("Two expressions missing line separator", File_Position(prev_line, prev_col), *m_filename); - } - has_more = true; - retval = true; - saw_eol = false; - } - else if (Eol()) { - has_more = true; - retval = true; - saw_eol = true; - } - else { - has_more = false; - } - } - - return retval; - } - - /** - * Parses the given input string, tagging parsed ast_nodes with the given m_filename. - */ - bool parse(const std::string &t_input, const std::string &t_fname) { - m_input_pos = t_input.begin(); - m_input_end = t_input.end(); - m_line = 1; - m_col = 1; - m_filename = std::shared_ptr(new std::string(t_fname)); - - if ((t_input.size() > 1) && (t_input[0] == '#') && (t_input[1] == '!')) { - while ((m_input_pos != m_input_end) && (!Eol())) { - ++m_input_pos; - } - /// \todo respect // -*- coding: utf-8 -*- on line 1 or 2 see: http://evanjones.ca/python-utf8.html) - } - - if (Statements()) { - if (m_input_pos != m_input_end) { - throw exception::eval_error("Unparsed input", File_Position(m_line, m_col), t_fname); - } - else { - build_match(AST_NodePtr(new eval::File_AST_Node()), 0); - return true; - } + build_match(std::make_shared(), prev_stack_top); } else { - return false; + m_input_pos = prev_pos; + m_col = prev_col; + while (prev_stack_top != m_match_stack.size()) { + m_match_stack.pop_back(); + } } } - }; + + return retval; + } + + /// Reads a pair of values used to create a range initialization from input + bool Value_Range() { + bool retval = false; + + const auto prev_stack_top = m_match_stack.size(); + const auto prev_pos = m_input_pos; + const auto prev_col = m_col; + + if (Operator()) { + if (Symbol("..")) { + retval = true; + if (!Operator()) { + throw exception::eval_error("Incomplete value range", File_Position(m_line, m_col), *m_filename); + } + + build_match(std::make_shared(), prev_stack_top); + } + else { + m_input_pos = prev_pos; + m_col = prev_col; + while (prev_stack_top != m_match_stack.size()) { + m_match_stack.pop_back(); + } + } + } + + return retval; + } + + /// Parses a string of binary equation operators + bool Equation() { + bool retval = false; + + const auto prev_stack_top = m_match_stack.size(); + + if (Operator()) { + retval = true; + if (Symbol("=", true, true) || Symbol(":=", true, true) || Symbol("+=", true, true) || + Symbol("-=", true, true) || Symbol("*=", true, true) || Symbol("/=", true, true) || + Symbol("%=", true, true) || Symbol("<<=", true, true) || Symbol(">>=", true, true) || + Symbol("&=", true, true) || Symbol("^=", true, true) || Symbol("|=", true, true)) { + SkipWS(true); + if (!Equation()) { + throw exception::eval_error("Incomplete equation", File_Position(m_line, m_col), *m_filename); + } + + build_match(std::make_shared(), prev_stack_top); + } + } + + return retval; + } + + /// Parses statements allowed inside of a class block + bool Class_Statements() { + bool retval = false; + + bool has_more = true; + bool saw_eol = true; + + while (has_more) { + const auto prev_line = m_line; + const auto prev_col = m_col; + if (Def(true)) { + if (!saw_eol) { + throw exception::eval_error("Two function definitions missing line separator", File_Position(prev_line, prev_col), *m_filename); + } + has_more = true; + retval = true; + saw_eol = true; + } else if (Var_Decl(true)) { + if (!saw_eol) { + throw exception::eval_error("Two function definitions missing line separator", File_Position(prev_line, prev_col), *m_filename); + } + has_more = true; + retval = true; + saw_eol = true; + } else if (Eol()) { + has_more = true; + retval = true; + saw_eol = true; + } else { + has_more = false; + } + } + + return retval; + } + + /// Top level parser, starts parsing of all known parses + bool Statements() { + bool retval = false; + + bool has_more = true; + bool saw_eol = true; + + while (has_more) { + int prev_line = m_line; + int prev_col = m_col; + if (Def()) { + if (!saw_eol) { + throw exception::eval_error("Two function definitions missing line separator", File_Position(prev_line, prev_col), *m_filename); + } + has_more = true; + retval = true; + saw_eol = true; + } + else if (Try()) { + if (!saw_eol) { + throw exception::eval_error("Two function definitions missing line separator", File_Position(prev_line, prev_col), *m_filename); + } + has_more = true; + retval = true; + saw_eol = true; + } + else if (If()) { + if (!saw_eol) { + throw exception::eval_error("Two function definitions missing line separator", File_Position(prev_line, prev_col), *m_filename); + } + has_more = true; + retval = true; + saw_eol = true; + } + else if (While()) { + if (!saw_eol) { + throw exception::eval_error("Two function definitions missing line separator", File_Position(prev_line, prev_col), *m_filename); + } + has_more = true; + retval = true; + saw_eol = true; + } + else if (Class()) { + if (!saw_eol) { + throw exception::eval_error("Two function definitions missing line separator", File_Position(prev_line, prev_col), *m_filename); + } + has_more = true; + retval = true; + saw_eol = true; + } + else if (For()) { + if (!saw_eol) { + throw exception::eval_error("Two function definitions missing line separator", File_Position(prev_line, prev_col), *m_filename); + } + has_more = true; + retval = true; + saw_eol = true; + } + else if (Switch()) { + if (!saw_eol) { + throw exception::eval_error("Two function definitions missing line separator", File_Position(prev_line, prev_col), *m_filename); + } + has_more = true; + retval = true; + saw_eol = true; + } + else if (Return()) { + if (!saw_eol) { + throw exception::eval_error("Two expressions missing line separator", File_Position(prev_line, prev_col), *m_filename); + } + has_more = true; + retval = true; + saw_eol = false; + } + else if (Break()) { + if (!saw_eol) { + throw exception::eval_error("Two expressions missing line separator", File_Position(prev_line, prev_col), *m_filename); + } + has_more = true; + retval = true; + saw_eol = false; + } + else if (Continue()) { + if (!saw_eol) { + throw exception::eval_error("Two expressions missing line separator", File_Position(prev_line, prev_col), *m_filename); + } + has_more = true; + retval = true; + saw_eol = false; + } + else if (Block()) { + has_more = true; + retval = true; + saw_eol = true; + } + else if (Equation()) { + if (!saw_eol) { + throw exception::eval_error("Two expressions missing line separator", File_Position(prev_line, prev_col), *m_filename); + } + has_more = true; + retval = true; + saw_eol = false; + } + else if (Eol()) { + has_more = true; + retval = true; + saw_eol = true; + } + else { + has_more = false; + } + } + + return retval; + } + + /// Parses the given input string, tagging parsed ast_nodes with the given m_filename. + bool parse(const std::string &t_input, std::string t_fname) { + m_input_pos = t_input.begin(); + m_input_end = t_input.end(); + m_line = 1; + m_col = 1; + m_filename = std::make_shared(std::move(t_fname)); + + if ((t_input.size() > 1) && (t_input[0] == '#') && (t_input[1] == '!')) { + while ((m_input_pos != m_input_end) && (!Eol())) { + ++m_input_pos; + } + /// \todo respect // -*- coding: utf-8 -*- on line 1 or 2 see: http://evanjones.ca/python-utf8.html) + } + + if (Statements()) { + if (m_input_pos != m_input_end) { + throw exception::eval_error("Unparsed input", File_Position(m_line, m_col), t_fname); + } else { + build_match(std::make_shared(), 0); + return true; + } + } else { + return false; + } + } + }; } } #endif /* CHAISCRIPT_PARSER_HPP_ */ + diff --git a/include/chaiscript/utility/utility.hpp b/include/chaiscript/utility/utility.hpp index 3efb525..07fdff4 100644 --- a/include/chaiscript/utility/utility.hpp +++ b/include/chaiscript/utility/utility.hpp @@ -21,6 +21,29 @@ namespace chaiscript namespace utility { + /// Single step command for registering a class with ChaiScript + /// + /// \param[in,out] t_module Model to add class to + /// \param[in] t_class_name Name of the class being registered + /// \param[in] t_constructors Vector of constructors to add + /// \param[in] t_funcs Vector of methods to add + /// + /// \example Adding a basic class to ChaiScript in one step + /// + /// \code + /// chaiscript::utility::add_class(*m, + /// "test", + /// { constructor(), + /// constructor() }, + /// { {fun(&test::function), "function"}, + /// {fun(&test::function2), "function2"}, + /// {fun(&test::function3), "function3"}, + /// {fun(static_cast(&test::functionoverload)), "functionoverload" }, + /// {fun(static_cast(&test::functionoverload)), "functionoverload" }, + /// {fun(static_cast(&test::operator=)), "=" } + /// } + /// ); + /// template void add_class(ModuleType &t_module, const std::string &t_class_name, @@ -34,13 +57,11 @@ namespace chaiscript t_module.add(ctor, t_class_name); } - for(auto fun: t_funcs) + for(const auto &fun: t_funcs) { t_module.add(fun.first, fun.second); } - } - } } From 81dc4949d2fd8a4ec5429a833c60e7c81f025da4 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 4 Oct 2014 15:34:32 -0600 Subject: [PATCH 32/63] 1/4 through modernization of chaiscript_eval.hpp --- include/chaiscript/dispatchkit/bootstrap.hpp | 2 +- .../chaiscript/language/chaiscript_common.hpp | 9 +- .../chaiscript/language/chaiscript_eval.hpp | 221 ++++++++---------- 3 files changed, 106 insertions(+), 126 deletions(-) diff --git a/include/chaiscript/dispatchkit/bootstrap.hpp b/include/chaiscript/dispatchkit/bootstrap.hpp index fc39a11..22a439c 100644 --- a/include/chaiscript/dispatchkit/bootstrap.hpp +++ b/include/chaiscript/dispatchkit/bootstrap.hpp @@ -517,7 +517,7 @@ namespace chaiscript std::vector retval; std::transform(t_eval_error.call_stack.begin(), t_eval_error.call_stack.end(), std::back_inserter(retval), - &chaiscript::var>); + &chaiscript::var>); return retval; })), "call_stack"} } ); diff --git a/include/chaiscript/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index 09987fa..1339f86 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -69,6 +69,7 @@ namespace chaiscript /// \brief Typedef for pointers to AST_Node objects. Used in building of the AST_Node tree typedef std::shared_ptr AST_NodePtr; + typedef std::shared_ptr AST_NodePtr_Const; /// \brief Classes which may be thrown during error cases when ChaiScript is executing. @@ -82,7 +83,7 @@ namespace chaiscript File_Position end_position; std::string filename; std::string detail; - std::vector call_stack; + std::vector call_stack; eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname, const std::vector &t_parameters, const std::vector &t_functions, @@ -425,7 +426,7 @@ namespace chaiscript /// Prints the contents of an AST node, including its children, recursively - std::string to_string(const std::string &t_prepend = "") { + std::string to_string(const std::string &t_prepend = "") const { std::ostringstream oss; oss << t_prepend << "(" << ast_node_type_to_string(this->identifier) << ") " @@ -437,7 +438,7 @@ namespace chaiscript return oss.str(); } - Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_e) + Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_e) const { try { return eval_internal(t_e); @@ -466,7 +467,7 @@ namespace chaiscript virtual ~AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &) + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &) const { throw std::runtime_error("Undispatched ast_node (internal error)"); } diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 16a25f6..46f072d 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -45,19 +45,17 @@ namespace chaiscript { namespace detail { - /** - * Helper function that will set up the scope around a function call, including handling the named function parameters - */ - static const Boxed_Value eval_function(chaiscript::detail::Dispatch_Engine &t_ss, const AST_NodePtr &t_node, const std::vector &t_param_names, const std::vector &t_vals) { + /// Helper function that will set up the scope around a function call, including handling the named function parameters + static Boxed_Value eval_function(chaiscript::detail::Dispatch_Engine &t_ss, const AST_NodePtr &t_node, const std::vector &t_param_names, const std::vector &t_vals) { chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); - for (unsigned int i = 0; i < t_param_names.size(); ++i) { + for (size_t i = 0; i < t_param_names.size(); ++i) { t_ss.add_object(t_param_names[i], t_vals[i]); } try { return t_node->eval(t_ss); - } catch (const detail::Return_Value &rv) { + } catch (detail::Return_Value &rv) { return rv.retval; } } @@ -65,12 +63,12 @@ namespace chaiscript struct Binary_Operator_AST_Node : public AST_Node { public: - Binary_Operator_AST_Node(const std::string &t_ast_node_text, int t_id, const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : - AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) + Binary_Operator_AST_Node(std::string t_ast_node_text, int t_id, const std::shared_ptr &t_fname, int t_start_line, int t_start_col, int t_end_line, int t_end_col) : + AST_Node(std::move(t_ast_node_text), t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Binary_Operator_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE { + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE { return do_oper(t_ss, Operators::to_operator(children[1]->text), children[1]->text, this->children[0]->eval(t_ss), this->children[2]->eval(t_ss)); @@ -88,15 +86,12 @@ namespace chaiscript protected: Boxed_Value do_oper(chaiscript::detail::Dispatch_Engine &t_ss, - Operators::Opers t_oper, const std::string &t_oper_string, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs) + Operators::Opers t_oper, const std::string &t_oper_string, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs) const { try { chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); - std::vector params(2); - params.push_back(t_lhs); - params.push_back(t_rhs); - fpp.save_params(params); - + fpp.save_params({t_lhs, t_rhs}); + if (t_oper != Operators::invalid && t_lhs.get_type_info().is_arithmetic() && t_rhs.get_type_info().is_arithmetic()) { // If it's an arithmetic operation we want to short circuit dispatch @@ -117,24 +112,13 @@ namespace chaiscript } }; - struct Error_AST_Node : public AST_Node { - public: - Error_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : - AST_Node(t_ast_node_text, AST_Node_Type::Error, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } - - virtual ~Error_AST_Node() {} - }; - struct Int_AST_Node : public AST_Node { public: - Int_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : - AST_Node(t_ast_node_text, AST_Node_Type::Int, t_fname, t_start_line, t_start_col, t_end_line, t_end_col), - m_value(const_var(int(atoi(t_ast_node_text.c_str())))) { } - Int_AST_Node(const std::string &t_ast_node_text, const Boxed_Value &t_bv, const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : - AST_Node(t_ast_node_text, AST_Node_Type::Int, t_fname, t_start_line, t_start_col, t_end_line, t_end_col), - m_value(t_bv) { } + Int_AST_Node(std::string t_ast_node_text, Boxed_Value t_bv, const std::shared_ptr &t_fname, int t_start_line, int t_start_col, int t_end_line, int t_end_col) : + AST_Node(std::move(t_ast_node_text), AST_Node_Type::Int, t_fname, t_start_line, t_start_col, t_end_line, t_end_col), + m_value(std::move(t_bv)) { } virtual ~Int_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &) CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &) const CHAISCRIPT_OVERRIDE{ return m_value; } @@ -145,14 +129,11 @@ namespace chaiscript struct Float_AST_Node : public AST_Node { public: - Float_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : - AST_Node(t_ast_node_text, AST_Node_Type::Float, t_fname, t_start_line, t_start_col, t_end_line, t_end_col), - m_value(const_var(double(atof(t_ast_node_text.c_str())))) { } - Float_AST_Node(const std::string &t_ast_node_text, const Boxed_Value &t_bv, const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : - AST_Node(t_ast_node_text, AST_Node_Type::Float, t_fname, t_start_line, t_start_col, t_end_line, t_end_col), - m_value(t_bv) { } + Float_AST_Node(std::string t_ast_node_text, Boxed_Value t_bv, const std::shared_ptr &t_fname, int t_start_line, int t_start_col, int t_end_line, int t_end_col) : + AST_Node(std::move(t_ast_node_text), AST_Node_Type::Float, t_fname, t_start_line, t_start_col, t_end_line, t_end_col), + m_value(std::move(t_bv)) { } virtual ~Float_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &) CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &) const CHAISCRIPT_OVERRIDE{ return m_value; } @@ -163,13 +144,13 @@ namespace chaiscript struct Id_AST_Node : public AST_Node { public: - Id_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : + Id_AST_Node(const std::string &t_ast_node_text, const std::shared_ptr &t_fname, int t_start_line, int t_start_col, int t_end_line, int t_end_col) : AST_Node(t_ast_node_text, AST_Node_Type::Id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col), m_value(get_value(t_ast_node_text)) { } virtual ~Id_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE { + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE { if (!m_value.is_undef()) { return m_value; @@ -207,22 +188,22 @@ namespace chaiscript struct Char_AST_Node : public AST_Node { public: - Char_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : - AST_Node(t_ast_node_text, AST_Node_Type::Char, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } + Char_AST_Node(std::string t_ast_node_text, const std::shared_ptr &t_fname, int t_start_line, int t_start_col, int t_end_line, int t_end_col) : + AST_Node(std::move(t_ast_node_text), AST_Node_Type::Char, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Char_AST_Node() {} }; struct Str_AST_Node : public AST_Node { public: - Str_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : - AST_Node(t_ast_node_text, AST_Node_Type::Str, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } + Str_AST_Node(std::string t_ast_node_text, const std::shared_ptr &t_fname, int t_start_line, int t_start_col, int t_end_line, int t_end_col) : + AST_Node(std::move(t_ast_node_text), AST_Node_Type::Str, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Str_AST_Node() {} }; struct Eol_AST_Node : public AST_Node { public: - Eol_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : - AST_Node(t_ast_node_text, AST_Node_Type::Eol, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } + Eol_AST_Node(std::string t_ast_node_text, const std::shared_ptr &t_fname, int t_start_line, int t_start_col, int t_end_line, int t_end_col) : + AST_Node(std::move(t_ast_node_text), AST_Node_Type::Eol, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Eol_AST_Node() {} virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE @@ -236,24 +217,27 @@ namespace chaiscript Fun_Call_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : AST_Node(t_ast_node_text, AST_Node_Type::Fun_Call, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Fun_Call_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); + std::vector params; - if ((this->children.size() > 1) && (this->children[1]->identifier == AST_Node_Type::Arg_List)) { - for (size_t i = 0; i < this->children[1]->children.size(); ++i) { - params.push_back(this->children[1]->children[i]->eval(t_ss)); + if ((this->children.size() > 1)) { + const AST_Node &first_child(*(this->children[1])); + if (first_child.identifier == AST_Node_Type::Arg_List) { + for (const auto &child : first_child.children) { + params.push_back(child->eval(t_ss)); + } } } fpp.save_params(params); + Boxed_Value fn(this->children[0]->eval(t_ss)); - Boxed_Value fn = this->children[0]->eval(t_ss); try { chaiscript::eval::detail::Stack_Push_Pop spp(t_ss); - const Boxed_Value &retval = (*t_ss.boxed_cast(fn))(params, t_ss.conversions()); - return retval; + 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); @@ -262,9 +246,7 @@ namespace chaiscript try { Const_Proxy_Function f = t_ss.boxed_cast(fn); // handle the case where there is only 1 function to try to call and dispatch fails on it - std::vector funcs; - funcs.push_back(f); - throw exception::eval_error("Error calling function '" + this->children[0]->text + "'", params, funcs, false, t_ss); + throw exception::eval_error("Error calling function '" + this->children[0]->text + "'", params, {f}, false, t_ss); } catch (const exception::bad_boxed_cast &) { throw exception::eval_error("'" + this->children[0]->pretty_print() + "' does not evaluate to a function."); } @@ -284,13 +266,15 @@ namespace chaiscript { std::ostringstream oss; - for (size_t j = 0; j < this->children.size(); ++j) { - oss << this->children[j]->pretty_print(); + int count = 0; + for (const auto &child : this->children) { + oss << child->pretty_print(); - if (j == 0) + if (count == 0) { oss << "("; } + ++count; } oss << ")"; @@ -300,25 +284,25 @@ namespace chaiscript }; + /// Used in the context of in-string ${} evals, so that no new scope is created struct Inplace_Fun_Call_AST_Node : public AST_Node { public: Inplace_Fun_Call_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : AST_Node(t_ast_node_text, AST_Node_Type::Inplace_Fun_Call, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Inplace_Fun_Call_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ std::vector params; if ((this->children.size() > 1) && (this->children[1]->identifier == AST_Node_Type::Arg_List)) { - for (size_t i = 0; i < this->children[1]->children.size(); ++i) { - params.push_back(this->children[1]->children[i]->eval(t_ss)); + for (const auto &child : this->children[1]->children) { + params.push_back(child->eval(t_ss)); } } - Boxed_Value bv; Const_Proxy_Function fn; try { - bv = this->children[0]->eval(t_ss); + Boxed_Value bv = this->children[0]->eval(t_ss); try { fn = t_ss.boxed_cast(bv); } catch (const exception::bad_boxed_cast &) { @@ -333,7 +317,7 @@ namespace chaiscript // handle the case where there is only 1 function to try to call and dispatch fails on it std::vector funcs; funcs.push_back(fn); - throw exception::eval_error("Error calling function '" + this->children[0]->text + "'", params, funcs, false, t_ss); + throw exception::eval_error("Error calling function '" + this->children[0]->text + "'", params, {fn}, false, t_ss); } catch(const exception::arity_error &e){ throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'"); @@ -349,13 +333,15 @@ namespace chaiscript virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE { std::ostringstream oss; - for (size_t j = 0; j < this->children.size(); ++j) { - oss << this->children[j]->pretty_print(); + int count = 0; + for (const auto &child : this->children) { + oss << child->pretty_print(); - if (j == 0) + if (count == 0) { oss << "("; } + ++count; } oss << ")"; @@ -367,14 +353,14 @@ namespace chaiscript struct Arg_List_AST_Node : public AST_Node { public: - Arg_List_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : - AST_Node(t_ast_node_text, AST_Node_Type::Arg_List, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } + Arg_List_AST_Node(std::string t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : + AST_Node(std::move(t_ast_node_text), AST_Node_Type::Arg_List, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Arg_List_AST_Node() {} virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE { std::ostringstream oss; - for (unsigned int j = 0; j < this->children.size(); ++j) { + for (size_t j = 0; j < this->children.size(); ++j) { if (j != 0) { oss << ", "; @@ -387,21 +373,14 @@ namespace chaiscript } }; - struct Variable_AST_Node : public AST_Node { - public: - Variable_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : - AST_Node(t_ast_node_text, AST_Node_Type::Variable, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } - virtual ~Variable_AST_Node() {} - }; - struct Equation_AST_Node : public AST_Node { public: - Equation_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : - AST_Node(t_ast_node_text, AST_Node_Type::Equation, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) + Equation_AST_Node(std::string t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : + AST_Node(std::move(t_ast_node_text), AST_Node_Type::Equation, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) {} virtual ~Equation_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE { + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE { Boxed_Value retval = this->children.back()->eval(t_ss); @@ -435,7 +414,7 @@ namespace chaiscript } try { - retval = t_ss.call_function(this->children[1]->text, lhs, retval); + retval = t_ss.call_function(this->children[1]->text, std::move(lhs), retval); } 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); @@ -454,9 +433,9 @@ namespace chaiscript } else { try { - retval = t_ss.call_function(this->children[1]->text, lhs, retval); + retval = t_ss.call_function(this->children[1]->text, std::move(lhs), retval); } 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); + throw exception::eval_error("Unable to find appropriate'" + this->children[1]->text + "' operator.", e.parameters, e.functions, false, t_ss); } } } @@ -466,10 +445,10 @@ namespace chaiscript struct Var_Decl_AST_Node : public AST_Node { public: - Var_Decl_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : - AST_Node(t_ast_node_text, AST_Node_Type::Var_Decl, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } + Var_Decl_AST_Node(std::string t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : + AST_Node(std::move(t_ast_node_text), AST_Node_Type::Var_Decl, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Var_Decl_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE { if (this->children[0]->identifier == AST_Node_Type::Reference) { return this->children[0]->eval(t_ss); @@ -510,7 +489,7 @@ namespace chaiscript int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : Binary_Operator_AST_Node(t_ast_node_text, AST_Node_Type::Addition, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Addition_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE { + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE { return do_oper(t_ss, Operators::sum, "+", this->children[0]->eval(t_ss), this->children[1]->eval(t_ss)); } }; @@ -522,7 +501,7 @@ namespace chaiscript int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : Binary_Operator_AST_Node(t_ast_node_text, AST_Node_Type::Subtraction, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Subtraction_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE { + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE { return do_oper(t_ss, Operators::difference, "-", this->children[0]->eval(t_ss), this->children[1]->eval(t_ss)); } }; @@ -534,7 +513,7 @@ namespace chaiscript int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : Binary_Operator_AST_Node(t_ast_node_text, AST_Node_Type::Multiplication, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Multiplication_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE { + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE { return do_oper(t_ss, Operators::product, "*", this->children[0]->eval(t_ss), this->children[1]->eval(t_ss)); } }; @@ -546,7 +525,7 @@ namespace chaiscript int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : Binary_Operator_AST_Node(t_ast_node_text, AST_Node_Type::Division, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Division_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE { + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE { return do_oper(t_ss, Operators::quotient, "/", this->children[0]->eval(t_ss), this->children[1]->eval(t_ss)); } }; @@ -558,7 +537,7 @@ namespace chaiscript int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : Binary_Operator_AST_Node(t_ast_node_text, AST_Node_Type::Modulus, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Modulus_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE { + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE { return do_oper(t_ss, Operators::remainder, "%", this->children[0]->eval(t_ss), this->children[1]->eval(t_ss)); } }; @@ -568,7 +547,7 @@ namespace chaiscript Array_Call_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : AST_Node(t_ast_node_text, AST_Node_Type::Array_Call, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Array_Call_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); Boxed_Value retval = this->children[0]->eval(t_ss); std::vector params; @@ -613,7 +592,7 @@ namespace chaiscript Dot_Access_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : AST_Node(t_ast_node_text, AST_Node_Type::Dot_Access, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Dot_Access_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ Boxed_Value retval = this->children[0]->eval(t_ss); if (this->children.size() > 1) { @@ -678,7 +657,7 @@ namespace chaiscript AST_Node(t_ast_node_text, AST_Node_Type::Quoted_String, t_fname, t_start_line, t_start_col, t_end_line, t_end_col), m_value(const_var(t_ast_node_text)) { } virtual ~Quoted_String_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &) CHAISCRIPT_OVERRIDE { + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &) const CHAISCRIPT_OVERRIDE { return m_value; } @@ -698,7 +677,7 @@ namespace chaiscript AST_Node(t_ast_node_text, AST_Node_Type::Single_Quoted_String, t_fname, t_start_line, t_start_col, t_end_line, t_end_col), m_value(const_var(char(t_ast_node_text.at(0)))) { } virtual ~Single_Quoted_String_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &) CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &) const CHAISCRIPT_OVERRIDE{ return m_value; } @@ -716,7 +695,7 @@ namespace chaiscript Lambda_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Lambda, const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Lambda_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ std::vector t_param_names; size_t numparams = 0; @@ -749,7 +728,7 @@ namespace chaiscript Block_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : AST_Node(t_ast_node_text, AST_Node_Type::Block, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Block_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ const size_t num_children = this->children.size(); chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); @@ -778,7 +757,7 @@ namespace chaiscript Def_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : AST_Node(t_ast_node_text, AST_Node_Type::Def, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Def_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ std::vector t_param_names; size_t numparams = 0; AST_NodePtr guardnode; @@ -837,7 +816,7 @@ namespace chaiscript While_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : AST_Node(t_ast_node_text, AST_Node_Type::While, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~While_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE { + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE { chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); try { @@ -865,7 +844,7 @@ namespace chaiscript Class_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : AST_Node(t_ast_node_text, AST_Node_Type::Class, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Class_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE { + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE { chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); // put class name in current scope so it can be looked up by the attrs and methods @@ -882,7 +861,7 @@ namespace chaiscript Ternary_Cond_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : AST_Node(t_ast_node_text, AST_Node_Type::If, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Ternary_Cond_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ bool cond; try { cond = boxed_cast(this->children[0]->eval(t_ss)); @@ -905,7 +884,7 @@ namespace chaiscript If_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : AST_Node(t_ast_node_text, AST_Node_Type::If, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~If_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ bool cond; try { cond = boxed_cast(this->children[0]->eval(t_ss)); @@ -950,7 +929,7 @@ namespace chaiscript For_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : AST_Node(t_ast_node_text, AST_Node_Type::For, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~For_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); // initial expression @@ -989,7 +968,7 @@ namespace chaiscript Switch_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : AST_Node(t_ast_node_text, AST_Node_Type::Switch, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Switch_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE { + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE { Boxed_Value match_value; bool breaking = false; size_t currentCase = 1; @@ -1032,7 +1011,7 @@ namespace chaiscript Case_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : AST_Node(t_ast_node_text, AST_Node_Type::Case, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Case_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE { + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE { chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); this->children[1]->eval(t_ss); @@ -1046,7 +1025,7 @@ namespace chaiscript Default_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : AST_Node(t_ast_node_text, AST_Node_Type::Default, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Default_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE { + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE { chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); this->children[0]->eval(t_ss); @@ -1061,7 +1040,7 @@ namespace chaiscript Inline_Array_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : AST_Node(t_ast_node_text, AST_Node_Type::Inline_Array, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Inline_Array_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ try { std::vector vec; if (this->children.size() > 0) { @@ -1089,7 +1068,7 @@ namespace chaiscript Inline_Map_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : AST_Node(t_ast_node_text, AST_Node_Type::Inline_Map, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Inline_Map_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ try { std::map retval; for (size_t i = 0; i < this->children[0]->children.size(); ++i) { @@ -1111,7 +1090,7 @@ namespace chaiscript Return_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : AST_Node(t_ast_node_text, AST_Node_Type::Return, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Return_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ if (this->children.size() > 0) { throw detail::Return_Value(this->children[0]->eval(t_ss)); } @@ -1127,7 +1106,7 @@ namespace chaiscript File_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : AST_Node(t_ast_node_text, AST_Node_Type::File, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~File_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE { + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE { const size_t size = this->children.size(); for (size_t i = 0; i < size; ++i) { const Boxed_Value &retval = this->children[i]->eval(t_ss); @@ -1145,7 +1124,7 @@ namespace chaiscript AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ try { t_ss.add_object(this->children[0]->text, Boxed_Value()); } @@ -1165,7 +1144,7 @@ namespace chaiscript { } virtual ~Prefix_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); Boxed_Value bv(this->children[1]->eval(t_ss)); @@ -1194,7 +1173,7 @@ namespace chaiscript Break_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : AST_Node(t_ast_node_text, AST_Node_Type::Break, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Break_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &) CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &) const CHAISCRIPT_OVERRIDE{ throw detail::Break_Loop(); } }; @@ -1204,7 +1183,7 @@ namespace chaiscript Continue_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : AST_Node(t_ast_node_text, AST_Node_Type::Continue, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Continue_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &) CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &) const CHAISCRIPT_OVERRIDE{ throw detail::Continue_Loop(); } }; @@ -1217,7 +1196,7 @@ namespace chaiscript { } virtual ~Noop_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &) CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &) const CHAISCRIPT_OVERRIDE{ // It's a no-op, that evaluates to "true" return m_value; } @@ -1245,7 +1224,7 @@ namespace chaiscript Inline_Range_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : AST_Node(t_ast_node_text, AST_Node_Type::Inline_Range, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Inline_Range_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ try { return t_ss.call_function("generate_range", this->children[0]->children[0]->children[0]->eval(t_ss), @@ -1270,7 +1249,7 @@ namespace chaiscript Try_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : AST_Node(t_ast_node_text, AST_Node_Type::Try, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Try_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ Boxed_Value retval; chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); @@ -1413,7 +1392,7 @@ namespace chaiscript Method_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : AST_Node(t_ast_node_text, AST_Node_Type::Method, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Method_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ std::vector t_param_names; AST_NodePtr guardnode; @@ -1503,7 +1482,7 @@ namespace chaiscript Attr_Decl_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : AST_Node(t_ast_node_text, AST_Node_Type::Attr_Decl, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Attr_Decl_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE { const auto &d = t_ss.get_parent_locals(); const auto itr = d.find("_current_class_name"); @@ -1573,7 +1552,7 @@ namespace chaiscript Logical_And_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : AST_Node(t_ast_node_text, AST_Node_Type::Logical_And, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Logical_And_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ Boxed_Value retval = this->children[0]->eval(t_ss); if (this->children.size() > 1) { @@ -1607,7 +1586,7 @@ namespace chaiscript Logical_Or_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : AST_Node(t_ast_node_text, AST_Node_Type::Logical_Or, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Logical_Or_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ Boxed_Value retval; retval = this->children[0]->eval(t_ss); From 8ecc11c27545f74adf4771e3ffb56a7fa2ce585b Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 4 Oct 2014 18:31:08 -0600 Subject: [PATCH 33/63] First pass of modernization of chaiscript_eval.hpp done --- .../chaiscript/language/chaiscript_eval.hpp | 237 +++++++++--------- 1 file changed, 118 insertions(+), 119 deletions(-) diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 46f072d..c095c23 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -455,15 +455,16 @@ namespace chaiscript } else { std::string idname = this->children[0]->text; + Boxed_Value bv; try { - t_ss.add_object(idname, Boxed_Value()); + t_ss.add_object(idname, bv); } catch (const exception::reserved_word_error &) { throw exception::eval_error("Reserved word used as variable '" + idname + "'"); } catch (const exception::name_conflict_error &e) { throw exception::eval_error("Variable redefined '" + e.name() + "'"); } - return t_ss.get_object(idname); + return bv; } } @@ -477,17 +478,17 @@ namespace chaiscript struct Comparison_AST_Node : public Binary_Operator_AST_Node { public: - Comparison_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : - Binary_Operator_AST_Node(t_ast_node_text, AST_Node_Type::Comparison, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } + Comparison_AST_Node(std::string t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : + Binary_Operator_AST_Node(std::move(t_ast_node_text), AST_Node_Type::Comparison, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Comparison_AST_Node() {} }; struct Addition_AST_Node : public Binary_Operator_AST_Node { public: - Addition_AST_Node(const std::string &t_ast_node_text = "+", + Addition_AST_Node(std::string t_ast_node_text = "+", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : - Binary_Operator_AST_Node(t_ast_node_text, AST_Node_Type::Addition, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } + Binary_Operator_AST_Node(std::move(t_ast_node_text), AST_Node_Type::Addition, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Addition_AST_Node() {} virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE { return do_oper(t_ss, Operators::sum, "+", this->children[0]->eval(t_ss), this->children[1]->eval(t_ss)); @@ -496,10 +497,10 @@ namespace chaiscript struct Subtraction_AST_Node : public Binary_Operator_AST_Node { public: - Subtraction_AST_Node(const std::string &t_ast_node_text = "-", + Subtraction_AST_Node(std::string t_ast_node_text = "-", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : - Binary_Operator_AST_Node(t_ast_node_text, AST_Node_Type::Subtraction, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } + Binary_Operator_AST_Node(std::move(t_ast_node_text), AST_Node_Type::Subtraction, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Subtraction_AST_Node() {} virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE { return do_oper(t_ss, Operators::difference, "-", this->children[0]->eval(t_ss), this->children[1]->eval(t_ss)); @@ -508,10 +509,10 @@ namespace chaiscript struct Multiplication_AST_Node : public Binary_Operator_AST_Node { public: - Multiplication_AST_Node(const std::string &t_ast_node_text = "*", + Multiplication_AST_Node(std::string t_ast_node_text = "*", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : - Binary_Operator_AST_Node(t_ast_node_text, AST_Node_Type::Multiplication, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } + Binary_Operator_AST_Node(std::move(t_ast_node_text), AST_Node_Type::Multiplication, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Multiplication_AST_Node() {} virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE { return do_oper(t_ss, Operators::product, "*", this->children[0]->eval(t_ss), this->children[1]->eval(t_ss)); @@ -520,10 +521,10 @@ namespace chaiscript struct Division_AST_Node : public Binary_Operator_AST_Node { public: - Division_AST_Node(const std::string &t_ast_node_text = "/", + Division_AST_Node(std::string t_ast_node_text = "/", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : - Binary_Operator_AST_Node(t_ast_node_text, AST_Node_Type::Division, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } + Binary_Operator_AST_Node(std::move(t_ast_node_text), AST_Node_Type::Division, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Division_AST_Node() {} virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE { return do_oper(t_ss, Operators::quotient, "/", this->children[0]->eval(t_ss), this->children[1]->eval(t_ss)); @@ -532,10 +533,10 @@ namespace chaiscript struct Modulus_AST_Node : public Binary_Operator_AST_Node { public: - Modulus_AST_Node(const std::string &t_ast_node_text = "%", + Modulus_AST_Node(std::string t_ast_node_text = "%", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : - Binary_Operator_AST_Node(t_ast_node_text, AST_Node_Type::Modulus, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } + Binary_Operator_AST_Node(std::move(t_ast_node_text), AST_Node_Type::Modulus, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Modulus_AST_Node() {} virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE { return do_oper(t_ss, Operators::remainder, "%", this->children[0]->eval(t_ss), this->children[1]->eval(t_ss)); @@ -549,9 +550,9 @@ namespace chaiscript virtual ~Array_Call_AST_Node() {} virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); - Boxed_Value retval = this->children[0]->eval(t_ss); - std::vector params; - params.push_back(retval); + + Boxed_Value retval(this->children[0]->eval(t_ss)); + std::vector params{retval}; for (size_t i = 1; i < this->children.size(); ++i) { try { @@ -561,7 +562,7 @@ namespace chaiscript params.push_back(p1); fpp.save_params(params); params.clear(); - retval = t_ss.call_function("[]", retval, p1); + retval = t_ss.call_function("[]", retval, std::move(p1)); } catch(const exception::dispatch_error &e){ throw exception::eval_error("Can not find appropriate array lookup operator '[]'.", e.parameters, e.functions, false, t_ss ); @@ -598,12 +599,11 @@ namespace chaiscript if (this->children.size() > 1) { for (size_t i = 2; i < this->children.size(); i+=2) { chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); - std::vector params; - params.push_back(retval); + std::vector params{retval}; if (this->children[i]->children.size() > 1) { - for (size_t j = 0; j < this->children[i]->children[1]->children.size(); ++j) { - params.push_back(this->children[i]->children[1]->children[j]->eval(t_ss)); + for (const auto &child : this->children[i]->children[1]->children) { + params.push_back(child->eval(t_ss)); } } @@ -619,7 +619,7 @@ namespace chaiscript try { chaiscript::eval::detail::Stack_Push_Pop spp(t_ss); - retval = t_ss.call_function(fun_name, params); + retval = t_ss.call_function(fun_name, std::move(params)); } catch(const exception::dispatch_error &e){ if (e.functions.empty()) @@ -657,6 +657,7 @@ namespace chaiscript AST_Node(t_ast_node_text, AST_Node_Type::Quoted_String, t_fname, t_start_line, t_start_col, t_end_line, t_end_col), m_value(const_var(t_ast_node_text)) { } virtual ~Quoted_String_AST_Node() {} + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &) const CHAISCRIPT_OVERRIDE { return m_value; } @@ -676,6 +677,7 @@ namespace chaiscript Single_Quoted_String_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : AST_Node(t_ast_node_text, AST_Node_Type::Single_Quoted_String, t_fname, t_start_line, t_start_col, t_end_line, t_end_col), m_value(const_var(char(t_ast_node_text.at(0)))) { } + virtual ~Single_Quoted_String_AST_Node() {} virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &) const CHAISCRIPT_OVERRIDE{ return m_value; @@ -695,20 +697,19 @@ namespace chaiscript Lambda_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Lambda, const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Lambda_AST_Node() {} + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ std::vector t_param_names; + size_t numparams = 0; - if ((this->children.size() > 0) && (this->children[0]->identifier == AST_Node_Type::Arg_List)) { + if (!this->children.empty() && (this->children[0]->identifier == AST_Node_Type::Arg_List)) { numparams = this->children[0]->children.size(); - for (size_t i = 0; i < numparams; ++i) { - t_param_names.push_back(this->children[0]->children[i]->text); - } - } - else { - //no parameters - numparams = 0; + for (const auto &child : this->children[0]->children) + { + t_param_names.push_back(child->text); + } } const auto &lambda_node = this->children.back(); @@ -725,21 +726,22 @@ namespace chaiscript struct Block_AST_Node : public AST_Node { public: - Block_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : - AST_Node(t_ast_node_text, AST_Node_Type::Block, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } + Block_AST_Node(std::string t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : + AST_Node(std::move(t_ast_node_text), AST_Node_Type::Block, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Block_AST_Node() {} + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ - const size_t num_children = this->children.size(); + const auto num_children = this->children.size(); chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); for (size_t i = 0; i < num_children; ++i) { try { - const Boxed_Value &retval = this->children[i]->eval(t_ss); - - if (i + 1 == num_children) + if (i + 1 < num_children) { - return retval; + this->children[i]->eval(t_ss); + } else { + return this->children[i]->eval(t_ss); } } catch (const chaiscript::eval::detail::Return_Value &) { @@ -749,7 +751,6 @@ namespace chaiscript return Boxed_Value(); } - }; struct Def_AST_Node : public AST_Node { @@ -764,8 +765,10 @@ namespace chaiscript if ((this->children.size() > 2) && (this->children[1]->identifier == AST_Node_Type::Arg_List)) { numparams = this->children[1]->children.size(); - for (size_t i = 0; i < numparams; ++i) { - t_param_names.push_back(this->children[1]->children[i]->text); + + for (const auto &child : this->children[1]->children) + { + t_param_names.push_back(child->text); } if (this->children.size() > 3) { @@ -813,8 +816,8 @@ namespace chaiscript struct While_AST_Node : public AST_Node { public: - While_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : - AST_Node(t_ast_node_text, AST_Node_Type::While, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } + While_AST_Node(std::string t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : + AST_Node(std::move(t_ast_node_text), AST_Node_Type::While, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~While_AST_Node() {} virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE { chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); @@ -862,7 +865,7 @@ namespace chaiscript AST_Node(t_ast_node_text, AST_Node_Type::If, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Ternary_Cond_AST_Node() {} virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ - bool cond; + bool cond = false; try { cond = boxed_cast(this->children[0]->eval(t_ss)); } @@ -885,7 +888,7 @@ namespace chaiscript AST_Node(t_ast_node_text, AST_Node_Type::If, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~If_AST_Node() {} virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ - bool cond; + bool cond = false; try { cond = boxed_cast(this->children[0]->eval(t_ss)); } @@ -914,21 +917,22 @@ namespace chaiscript return this->children[i+2]->eval(t_ss); } } - i = i + 3; + i += 3; } } } - return Boxed_Value(false); + return const_var(false); } }; struct For_AST_Node : public AST_Node { public: - For_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : - AST_Node(t_ast_node_text, AST_Node_Type::For, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } + For_AST_Node(std::string t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : + AST_Node(std::move(t_ast_node_text), AST_Node_Type::For, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~For_AST_Node() {} + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); @@ -965,18 +969,17 @@ namespace chaiscript struct Switch_AST_Node : public AST_Node { public: - Switch_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : - AST_Node(t_ast_node_text, AST_Node_Type::Switch, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } + Switch_AST_Node(std::string t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : + AST_Node(std::move(t_ast_node_text), AST_Node_Type::Switch, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Switch_AST_Node() {} virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE { - Boxed_Value match_value; bool breaking = false; size_t currentCase = 1; bool hasMatched = false; chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); - match_value = this->children[0]->eval(t_ss); + Boxed_Value match_value(this->children[0]->eval(t_ss)); while (!breaking && (currentCase < this->children.size())) { try { @@ -1008,22 +1011,22 @@ namespace chaiscript struct Case_AST_Node : public AST_Node { public: - Case_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : - AST_Node(t_ast_node_text, AST_Node_Type::Case, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } + Case_AST_Node(std::string t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : + AST_Node(std::move(t_ast_node_text), AST_Node_Type::Case, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Case_AST_Node() {} virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE { chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); this->children[1]->eval(t_ss); - + return Boxed_Value(); } }; struct Default_AST_Node : public AST_Node { public: - Default_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : - AST_Node(t_ast_node_text, AST_Node_Type::Default, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } + Default_AST_Node(std::string t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : + AST_Node(std::move(t_ast_node_text), AST_Node_Type::Default, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Default_AST_Node() {} virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE { chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); @@ -1037,19 +1040,18 @@ namespace chaiscript struct Inline_Array_AST_Node : public AST_Node { public: - Inline_Array_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : - AST_Node(t_ast_node_text, AST_Node_Type::Inline_Array, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } + Inline_Array_AST_Node(std::string t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : + AST_Node(std::move(t_ast_node_text), AST_Node_Type::Inline_Array, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Inline_Array_AST_Node() {} - virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ + virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE { try { std::vector vec; - if (this->children.size() > 0) { - for (size_t i = 0; i < this->children[0]->children.size(); ++i) { - Boxed_Value bv = t_ss.call_function("clone", this->children[0]->children[i]->eval(t_ss)); - vec.push_back(bv); + if (!this->children.empty()) { + for (const auto &child : this->children[0]->children) { + vec.push_back(t_ss.call_function("clone", child->eval(t_ss))); } } - return const_var(vec); + return const_var(std::move(vec)); } catch (const exception::dispatch_error &) { throw exception::eval_error("Can not find appropriate 'clone' or copy constructor for vector elements"); @@ -1065,17 +1067,18 @@ namespace chaiscript struct Inline_Map_AST_Node : public AST_Node { public: - Inline_Map_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : - AST_Node(t_ast_node_text, AST_Node_Type::Inline_Map, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } + Inline_Map_AST_Node(std::string t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : + AST_Node(std::move(t_ast_node_text), AST_Node_Type::Inline_Map, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Inline_Map_AST_Node() {} virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ try { std::map retval; - for (size_t i = 0; i < this->children[0]->children.size(); ++i) { - Boxed_Value bv = t_ss.call_function("clone", this->children[0]->children[i]->children[1]->eval(t_ss)); - retval[t_ss.boxed_cast(this->children[0]->children[i]->children[0]->eval(t_ss))] - = bv; + + for (const auto &child : this->children[0]->children) { + Boxed_Value bv = t_ss.call_function("clone", child->children[1]->eval(t_ss)); + retval[t_ss.boxed_cast(child->children[0]->eval(t_ss))] = std::move(bv); } + return const_var(retval); } catch (const exception::dispatch_error &e) { @@ -1087,11 +1090,11 @@ namespace chaiscript struct Return_AST_Node : public AST_Node { public: - Return_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : - AST_Node(t_ast_node_text, AST_Node_Type::Return, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } + Return_AST_Node(std::string t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : + AST_Node(std::move(t_ast_node_text), AST_Node_Type::Return, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Return_AST_Node() {} virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ - if (this->children.size() > 0) { + if (!this->children.empty()) { throw detail::Return_Value(this->children[0]->eval(t_ss)); } else { @@ -1103,13 +1106,13 @@ namespace chaiscript struct File_AST_Node : public AST_Node { public: - File_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : - AST_Node(t_ast_node_text, AST_Node_Type::File, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } + File_AST_Node(std::string t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : + AST_Node(std::move(t_ast_node_text), AST_Node_Type::File, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~File_AST_Node() {} virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE { const size_t size = this->children.size(); for (size_t i = 0; i < size; ++i) { - const Boxed_Value &retval = this->children[i]->eval(t_ss); + Boxed_Value retval(this->children[i]->eval(t_ss)); if (i + 1 == size) { return retval; } @@ -1120,18 +1123,19 @@ namespace chaiscript struct Reference_AST_Node : public AST_Node { public: - Reference_AST_Node(const std::string &t_ast_node_text = "", int t_id = AST_Node_Type::Reference, const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : - AST_Node(t_ast_node_text, t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) + Reference_AST_Node(std::string t_ast_node_text = "", int t_id = AST_Node_Type::Reference, const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : + AST_Node(std::move(t_ast_node_text), t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ try { - t_ss.add_object(this->children[0]->text, Boxed_Value()); + Boxed_Value bv; + t_ss.add_object(this->children[0]->text, bv); + return bv; } catch (const exception::reserved_word_error &) { throw exception::eval_error("Reserved word used as variable '" + this->children[0]->text + "'"); } - return t_ss.get_object(this->children[0]->text); } virtual ~Reference_AST_Node() {} @@ -1139,8 +1143,8 @@ namespace chaiscript struct Prefix_AST_Node : public AST_Node { public: - Prefix_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : - AST_Node(t_ast_node_text, AST_Node_Type::Prefix, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) + Prefix_AST_Node(std::string t_ast_node_text = "", const std::shared_ptr &t_fname=std::shared_ptr(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) : + AST_Node(std::move(t_ast_node_text), AST_Node_Type::Prefix, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Prefix_AST_Node() {} @@ -1153,13 +1157,11 @@ namespace chaiscript // short circuit arithmetic operations if (bv.get_type_info().is_arithmetic() && oper != Operators::invalid) { - return Boxed_Number::do_oper(oper, bv); + return Boxed_Number::do_oper(oper, std::move(bv)); } else { chaiscript::eval::detail::Stack_Push_Pop spp(t_ss); - std::vector params; - params.push_back(bv); - fpp.save_params(params); - return t_ss.call_function(this->children[0]->text, bv); + fpp.save_params({bv}); + return t_ss.call_function(this->children[0]->text, std::move(bv)); } } 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); @@ -1250,7 +1252,7 @@ namespace chaiscript AST_Node(t_ast_node_text, AST_Node_Type::Try, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { } virtual ~Try_AST_Node() {} virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ - Boxed_Value retval; + Boxed_Value retval; chaiscript::eval::detail::Scope_Push_Pop spp(t_ss); @@ -1264,7 +1266,7 @@ namespace chaiscript throw; } catch (const std::exception &e) { - Boxed_Value except = Boxed_Value(std::ref(e)); + Boxed_Value except(std::ref(e)); size_t end_point = this->children.size(); if (this->children.back()->identifier == AST_Node_Type::Finally) { @@ -1291,7 +1293,7 @@ namespace chaiscript //Variable capture, no guards t_ss.add_object(catch_block->children[0]->text, except); - bool guard; + bool guard = false; try { guard = boxed_cast(catch_block->children[1]->eval(t_ss)); } catch (const exception::bad_boxed_cast &) { @@ -1316,7 +1318,7 @@ namespace chaiscript catch (Boxed_Value &except) { for (size_t i = 1; i < this->children.size(); ++i) { chaiscript::eval::detail::Scope_Push_Pop catchscope(t_ss); - AST_NodePtr catch_block = this->children[i]; + const auto &catch_block = this->children[i]; if (catch_block->children.size() == 1) { //No variable capture, no guards @@ -1394,7 +1396,6 @@ namespace chaiscript virtual ~Method_AST_Node() {} virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ - std::vector t_param_names; AST_NodePtr guardnode; auto d = t_ss.get_parent_locals(); @@ -1404,11 +1405,11 @@ namespace chaiscript const std::string & class_name = (itr != d.end())?std::string(boxed_cast(itr->second)):this->children[0]->text; //The first param of a method is always the implied this ptr. - t_param_names.push_back("this"); + std::vector t_param_names{"this"}; if ((this->children.size() > static_cast(3 + class_offset)) && (this->children[(2 + class_offset)]->identifier == AST_Node_Type::Arg_List)) { - for (size_t i = 0; i < this->children[(2 + class_offset)]->children.size(); ++i) { - t_param_names.push_back(this->children[(2 + class_offset)]->children[i]->text); + for (const auto &child : this->children[(2 + class_offset)]->children) { + t_param_names.push_back(child->text); } if (this->children.size() > static_cast(4 + class_offset)) { @@ -1423,14 +1424,14 @@ namespace chaiscript } } - size_t numparams = t_param_names.size(); + const size_t numparams = t_param_names.size(); std::shared_ptr guard; if (guardnode) { - guard = std::shared_ptr - (new dispatch::Dynamic_Proxy_Function(std::bind(chaiscript::eval::detail::eval_function, - std::ref(t_ss), guardnode, - t_param_names, std::placeholders::_1), static_cast(numparams), guardnode)); + guard = std::make_shared + (std::bind(chaiscript::eval::detail::eval_function, + std::ref(t_ss), guardnode, + t_param_names, std::placeholders::_1), static_cast(numparams), guardnode); } try { @@ -1439,31 +1440,29 @@ namespace chaiscript const std::string & function_name = this->children[(1 + class_offset)]->text; if (function_name == class_name) { - t_ss.add(Proxy_Function - (new dispatch::detail::Dynamic_Object_Constructor(class_name, Proxy_Function - (new dispatch::Dynamic_Proxy_Function(std::bind(chaiscript::eval::detail::eval_function, - std::ref(t_ss), this->children.back(), - t_param_names, std::placeholders::_1), static_cast(numparams), this->children.back(), - l_annotation, guard)))), function_name); + t_ss.add(std::make_shared(class_name, std::make_shared(std::bind(chaiscript::eval::detail::eval_function, + std::ref(t_ss), this->children.back(), t_param_names, std::placeholders::_1), + static_cast(numparams), this->children.back(), l_annotation, guard)), + function_name); } else { try { // Do know type name - t_ss.add(Proxy_Function - (new dispatch::detail::Dynamic_Object_Function(class_name, Proxy_Function - (new dispatch::Dynamic_Proxy_Function(std::bind(chaiscript::eval::detail::eval_function, + t_ss.add( + std::make_shared(class_name, + std::make_shared(std::bind(chaiscript::eval::detail::eval_function, std::ref(t_ss), this->children.back(), t_param_names, std::placeholders::_1), static_cast(numparams), this->children.back(), - l_annotation, guard)), t_ss.get_type(class_name))), function_name); + l_annotation, guard), t_ss.get_type(class_name)), function_name); } catch (const std::range_error &) { // Do not know type name - t_ss.add(Proxy_Function - (new dispatch::detail::Dynamic_Object_Function(class_name, Proxy_Function - (new dispatch::Dynamic_Proxy_Function(std::bind(chaiscript::eval::detail::eval_function, + t_ss.add( + std::make_shared(class_name, + std::make_shared(std::bind(chaiscript::eval::detail::eval_function, std::ref(t_ss), this->children.back(), t_param_names, std::placeholders::_1), static_cast(numparams), this->children.back(), - l_annotation, guard)))), function_name); + l_annotation, guard)), function_name); } } } @@ -1491,13 +1490,13 @@ namespace chaiscript std::string class_name = (itr != d.end())?std::string(boxed_cast(itr->second)):this->children[0]->text; try { - t_ss.add(Proxy_Function - (new dispatch::detail::Dynamic_Object_Function( + t_ss.add( + std::make_shared( class_name, fun(std::function(std::bind(&dispatch::Dynamic_Object::get_attr, std::placeholders::_1, this->children[(1 + class_offset)]->text - ))) + )) ) ), this->children[(1 + class_offset)]->text); From 5986531bbaff1f12f7a0a6eaea7bc0c67f7efbea Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 4 Oct 2014 22:59:52 -0600 Subject: [PATCH 34/63] dispatchkit modernization --- .../chaiscript/dispatchkit/dispatchkit.hpp | 346 +++++++----------- .../chaiscript/language/chaiscript_engine.hpp | 38 +- 2 files changed, 146 insertions(+), 238 deletions(-) diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index 0b1e165..5ab3b11 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -53,9 +53,7 @@ namespace chaiscript { namespace exception { - /** - * Exception thrown in the case that an object name is invalid because it is a reserved word - */ + /// Exception thrown in the case that an object name is invalid because it is a reserved word class reserved_word_error : public std::runtime_error { public: @@ -75,18 +73,16 @@ namespace chaiscript std::string m_word; }; - /** - * Exception thrown in the case that an object name is invalid because it contains illegal characters - */ + /// Exception thrown in the case that an object name is invalid because it contains illegal characters class illegal_name_error : public std::runtime_error { public: - illegal_name_error(const std::string &t_name) throw() + illegal_name_error(const std::string &t_name) CHAISCRIPT_NOEXCEPT : std::runtime_error("Reserved name not allowed in object name: " + t_name), m_name(t_name) { } - virtual ~illegal_name_error() throw() {} + virtual ~illegal_name_error() CHAISCRIPT_NOEXCEPT {} std::string name() const { @@ -98,18 +94,16 @@ namespace chaiscript }; - /** - * Exception thrown in the case that an object name is invalid because it already exists in current context - */ + /// Exception thrown in the case that an object name is invalid because it already exists in current context class name_conflict_error : public std::runtime_error { public: - name_conflict_error(const std::string &t_name) throw() + name_conflict_error(const std::string &t_name) CHAISCRIPT_NOEXCEPT : std::runtime_error("Name already exists in current context " + t_name), m_name(t_name) { } - virtual ~name_conflict_error() throw() {} + virtual ~name_conflict_error() CHAISCRIPT_NOEXCEPT {} std::string name() const { @@ -122,9 +116,7 @@ namespace chaiscript }; - /** - * Exception thrown in the case that a non-const object was added as a shared object - */ + /// Exception thrown in the case that a non-const object was added as a shared object class global_non_const : public std::runtime_error { public: @@ -143,40 +135,40 @@ namespace chaiscript class Module { public: - Module &add(const Type_Info &ti, const std::string &name) + Module &add(Type_Info ti, std::string name) { - m_typeinfos.push_back(std::make_pair(ti, name)); + m_typeinfos.emplace_back(std::move(ti), std::move(name)); return *this; } - Module &add(const Dynamic_Cast_Conversion &d) + Module &add(Dynamic_Cast_Conversion d) { - m_conversions.push_back(d); + m_conversions.push_back(std::move(d)); return *this; } - Module &add(const Proxy_Function &f, const std::string &name) + Module &add(Proxy_Function f, std::string name) { - m_funcs.push_back(std::make_pair(f, name)); + m_funcs.emplace_back(std::move(f), std::move(name)); return *this; } - Module &add_global_const(const Boxed_Value &t_bv, const std::string &t_name) + Module &add_global_const(Boxed_Value t_bv, std::string t_name) { if (!t_bv.is_const()) { throw chaiscript::exception::global_non_const(); } - m_globals.push_back(std::make_pair(t_bv, t_name)); + m_globals.emplace_back(std::move(t_bv), std::move(t_name)); return *this; } //Add a bit of ChaiScript to eval during module implementation - Module &eval(const std::string &str) + Module &eval(std::string str) { - m_evals.push_back(str); + m_evals.push_back(std::move(str)); return *this; } @@ -208,18 +200,18 @@ namespace chaiscript std::vector m_conversions; template - static void apply(InItr begin, InItr end, T &t) + static void apply(InItr begin, const InItr end, T &t) { - while (begin != end) - { - try { - t.add(begin->first, begin->second); - } catch (const chaiscript::exception::name_conflict_error &) { - /// \todo Should we throw an error if there's a name conflict - /// while applying a module? - } - ++begin; - } + for_each(begin, end, [&t](typename std::iterator_traits::reference obj) + { + try { + t.add(obj.first, obj.second); + } catch (const chaiscript::exception::name_conflict_error &) { + /// \todo Should we throw an error if there's a name conflict + /// while applying a module? + } + } + ); } template @@ -258,17 +250,15 @@ namespace chaiscript namespace detail { - /** - * A Proxy_Function implementation that is able to take - * a vector of Proxy_Functions and perform a dispatch on them. It is - * used specifically in the case of dealing with Function object variables - */ + /// A Proxy_Function implementation that is able to take + /// a vector of Proxy_Functions and perform a dispatch on them. It is + /// used specifically in the case of dealing with Function object variables class Dispatch_Function : public dispatch::Proxy_Function_Base { public: - Dispatch_Function(const std::vector &t_funcs) + Dispatch_Function(std::vector t_funcs) : Proxy_Function_Base(build_type_infos(t_funcs)), - m_funcs(t_funcs) + m_funcs(std::move(t_funcs)) { } @@ -282,7 +272,7 @@ namespace chaiscript } } - virtual ~Dispatch_Function() {} + virtual ~Dispatch_Function() = default; virtual std::vector get_contained_functions() const CHAISCRIPT_OVERRIDE { @@ -292,46 +282,31 @@ namespace chaiscript virtual int get_arity() const CHAISCRIPT_OVERRIDE { - typedef std::vector function_vec; - - auto begin = m_funcs.begin(); - const function_vec::const_iterator end = m_funcs.end(); - - if (begin != end) - { - int arity = (*begin)->get_arity(); - - ++begin; - - while (begin != end) - { - if (arity != (*begin)->get_arity()) - { - // The arities in the list do not match, so it's unspecified - return -1; - } - - ++begin; - } - - return arity; + if (m_funcs.empty()) { + return -1; } - return -1; // unknown arity + const int arity = m_funcs.front()->get_arity(); + + for (const auto &func : m_funcs) + { + if (arity != func->get_arity()) + { + // The arities in the list do not match, so it's unspecified + return -1; + } + } + + return arity; } virtual bool call_match(const std::vector &vals, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE { - auto begin = m_funcs.begin(); - auto end = m_funcs.end(); - - while (begin != end) + for (const auto &func : m_funcs) { - if ((*begin)->call_match(vals, t_conversions)) + if (func->call_match(vals, t_conversions)) { return true; - } else { - ++begin; } } @@ -399,7 +374,7 @@ namespace chaiscript return std::vector(); } - }; + }; } @@ -431,7 +406,6 @@ namespace chaiscript Dispatch_Engine() : m_stack_holder(this), m_place_holder(std::make_shared()) - { } @@ -446,27 +420,21 @@ namespace chaiscript return chaiscript::boxed_cast(bv, &m_conversions); } - /** - * Add a new conversion for upcasting to a base class - */ + /// Add a new conversion for upcasting to a base class void add(const Dynamic_Cast_Conversion &d) { m_conversions.add_conversion(d); } - /** - * Add a new named Proxy_Function to the system - */ + /// Add a new named Proxy_Function to the system void add(const Proxy_Function &f, const std::string &name) { validate_object_name(name); add_function(f, name); } - /** - * Set the value of an object, by name. If the object - * is not available in the current scope it is created - */ + /// Set the value of an object, by name. If the object + /// is not available in the current scope it is created void add(const Boxed_Value &obj, const std::string &name) { validate_object_name(name); @@ -474,39 +442,34 @@ namespace chaiscript for (int i = static_cast(stack.size())-1; i >= 0; --i) { - std::map::const_iterator itr = stack[i].find(name); + const auto itr = stack[i].find(name); if (itr != stack[i].end()) { - stack[i][name] = obj; + itr->second = std::move(obj); return; } } - add_object(name, obj); + add_object(name, std::move(obj)); } - /** - * Adds a named object to the current scope - */ + /// Adds a named object to the current scope void add_object(const std::string &name, const Boxed_Value &obj) const { StackData &stack = get_stack_data(); validate_object_name(name); - Scope &scope = stack.back(); - auto itr = scope.find(name); - if (itr != stack.back().end()) + const Scope &scope = stack.back(); + if (scope.find(name) != scope.end()) { throw chaiscript::exception::name_conflict_error(name); } else { - stack.back().insert(std::make_pair(name, obj)); + stack.back().emplace(name, std::move(obj)); } } - /** - * Adds a new global shared object, between all the threads - */ + /// Adds a new global shared object, between all the threads void add_global_const(const Boxed_Value &obj, const std::string &name) { validate_object_name(name); @@ -521,14 +484,12 @@ namespace chaiscript { throw chaiscript::exception::name_conflict_error(name); } else { - m_state.m_global_objects.insert(std::make_pair(name, obj)); + m_state.m_global_objects.emplace(name, obj); } } - /** - * Adds a new global (non-const) shared object, between all the threads - */ + /// Adds a new global (non-const) shared object, between all the threads void add_global(const Boxed_Value &obj, const std::string &name) { validate_object_name(name); @@ -539,22 +500,18 @@ namespace chaiscript { throw chaiscript::exception::name_conflict_error(name); } else { - m_state.m_global_objects.insert(std::make_pair(name, obj)); + m_state.m_global_objects.emplace(name, obj); } } - /** - * Adds a new scope to the stack - */ + /// Adds a new scope to the stack void new_scope() { get_stack_data().emplace_back(); } - /** - * Pops the current scope from the stack - */ + /// Pops the current scope from the stack void pop_scope() { StackData &stack = get_stack_data(); @@ -585,11 +542,9 @@ namespace chaiscript return m_stack_holder->stacks.back(); } - /** - * Searches the current stack for an object of the given name - * includes a special overload for the _ place holder object to - * ensure that it is always in scope. - */ + /// Searches the current stack for an object of the given name + /// includes a special overload for the _ place holder object to + /// ensure that it is always in scope. Boxed_Value get_object(const std::string &name) const { // Is it a placeholder object? @@ -603,7 +558,7 @@ namespace chaiscript // Is it in the stack? for (int i = static_cast(stack.size())-1; i >= 0; --i) { - std::map::const_iterator stackitr = stack[i].find(name); + const auto stackitr = stack[i].find(name); if (stackitr != stack[i].end()) { return stackitr->second; @@ -614,7 +569,7 @@ namespace chaiscript { chaiscript::detail::threading::shared_lock l(m_global_object_mutex); - auto itr = m_state.m_global_objects.find(name); + const auto itr = m_state.m_global_objects.find(name); if (itr != m_state.m_global_objects.end()) { return itr->second; @@ -625,26 +580,22 @@ namespace chaiscript return get_function_object(name); } - /** - * Registers a new named type - */ + /// Registers a new named type void add(const Type_Info &ti, const std::string &name) { add_global_const(const_var(ti), name + "_type"); chaiscript::detail::threading::unique_lock l(m_mutex); - m_state.m_types.insert(std::make_pair(name, ti)); + m_state.m_types.emplace(name, ti); } - /** - * Returns the type info for a named type - */ + /// Returns the type info for a named type Type_Info get_type(const std::string &name) const { chaiscript::detail::threading::shared_lock l(m_mutex); - auto itr = m_state.m_types.find(name); + const auto itr = m_state.m_types.find(name); if (itr != m_state.m_types.end()) { @@ -654,11 +605,9 @@ namespace chaiscript throw std::range_error("Type Not Known"); } - /** - * Returns the registered name of a known type_info object - * compares the "bare_type_info" for the broadest possible - * match - */ + /// Returns the registered name of a known type_info object + /// compares the "bare_type_info" for the broadest possible + /// match std::string get_type_name(const Type_Info &ti) const { chaiscript::detail::threading::shared_lock l(m_mutex); @@ -674,9 +623,7 @@ namespace chaiscript return ti.bare_name(); } - /** - * Return all registered types - */ + /// Return all registered types std::vector > get_types() const { chaiscript::detail::threading::shared_lock l(m_mutex); @@ -684,26 +631,22 @@ namespace chaiscript return std::vector >(m_state.m_types.begin(), m_state.m_types.end()); } - /** - * Return a function by name - */ - std::vector< Proxy_Function > - get_function(const std::string &t_name) const + /// Return a function by name + std::vector< Proxy_Function > get_function(const std::string &t_name) const + { + chaiscript::detail::threading::shared_lock l(m_mutex); + + const auto &funs = get_functions_int(); + + auto itr = funs.find(t_name); + + if (itr != funs.end()) { - chaiscript::detail::threading::shared_lock l(m_mutex); - - const std::map > &funs = get_functions_int(); - - auto itr - = funs.find(t_name); - - if (itr != funs.end()) - { - return itr->second; - } else { - return std::vector(); - } + return itr->second; + } else { + return std::vector(); } + } /// \returns a function object (Boxed_Value wrapper) if it exists /// \throws std::range_error if it does not @@ -711,7 +654,7 @@ namespace chaiscript { chaiscript::detail::threading::shared_lock l(m_mutex); - const std::map &funs = get_function_objects_int(); + const auto &funs = get_function_objects_int(); auto itr = funs.find(t_name); @@ -723,14 +666,12 @@ namespace chaiscript } } - /** - * Return true if a function exists - */ + /// Return true if a function exists bool function_exists(const std::string &name) const { chaiscript::detail::threading::shared_lock l(m_mutex); - const std::map > &functions = get_functions_int(); + const auto &functions = get_functions_int(); return functions.find(name) != functions.end(); } @@ -782,7 +723,6 @@ namespace chaiscript std::map retval; // note: map insert doesn't overwrite existing values, which is why this works - for (auto itr = stack.rbegin(); itr != stack.rend(); ++itr) { retval.insert(itr->begin(), itr->end()); @@ -806,29 +746,27 @@ namespace chaiscript { chaiscript::detail::threading::shared_lock l(m_mutex); - const std::map &funs = get_function_objects_int(); + const auto &funs = get_function_objects_int(); std::map objs; for (const auto & fun : funs) { - objs.insert(std::make_pair(fun.first, const_var(fun.second))); + objs.emplace(fun.first, const_var(fun.second)); } return objs; } - /** - * Get a vector of all registered functions - */ + /// Get a vector of all registered functions std::vector > get_functions() const { chaiscript::detail::threading::shared_lock l(m_mutex); std::vector > rets; - const std::map > &functions = get_functions_int(); + const auto &functions = get_functions_int(); for (const auto & function : functions) { @@ -875,25 +813,19 @@ namespace chaiscript return call_function(t_name, std::vector({std::move(p1), std::move(p2)})); } - /** - * Dump object info to stdout - */ + /// Dump object info to stdout void dump_object(const Boxed_Value &o) const { std::cout << (o.is_const()?"const ":"") << type_name(o) << std::endl; } - /** - * Dump type info to stdout - */ + /// Dump type info to stdout void dump_type(const Type_Info &type) const { std::cout << (type.is_const()?"const ":"") << get_type_name(type); } - /** - * Dump function to stdout - */ + /// Dump function to stdout void dump_function(const std::pair &f) const { std::vector params = f.second->get_param_types(); @@ -921,10 +853,8 @@ namespace chaiscript std::cout << ") " << std::endl; } - /** - * Returns true if a call can be made that consists of the first parameter - * (the function) with the remaining parameters as its arguments. - */ + /// 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) { if (params.size() < 1) @@ -932,14 +862,12 @@ namespace chaiscript throw chaiscript::exception::arity_error(static_cast(params.size()), 1); } - Const_Proxy_Function f = this->boxed_cast(params[0]); + const Const_Proxy_Function &f = this->boxed_cast(params[0]); return Boxed_Value(f->call_match(std::vector(params.begin() + 1, params.end()), m_conversions)); } - /** - * Dump all system info to stdout - */ + /// Dump all system info to stdout void dump_system() const { std::cout << "Registered Types: " << std::endl; @@ -966,9 +894,7 @@ namespace chaiscript std::cout << std::endl; } - /** - * return true if the Boxed_Value matches the registered type by name - */ + /// return true if the Boxed_Value matches the registered type by name bool is_type(const Boxed_Value &r, const std::string &user_typename) const { try { @@ -1036,10 +962,8 @@ namespace chaiscript } private: - /** - * Returns the current stack - * make const/non const versions - */ + /// Returns the current stack + /// make const/non const versions StackData &get_stack_data() const { return *(m_stack_holder->stacks.back()); @@ -1067,8 +991,8 @@ namespace chaiscript static bool function_less_than(const Proxy_Function &lhs, const Proxy_Function &rhs) { - const std::vector lhsparamtypes = lhs->get_param_types(); - const std::vector rhsparamtypes = rhs->get_param_types(); + const std::vector &lhsparamtypes = lhs->get_param_types(); + const std::vector &rhsparamtypes = rhs->get_param_types(); const size_t lhssize = lhsparamtypes.size(); const size_t rhssize = rhsparamtypes.size(); @@ -1105,11 +1029,10 @@ namespace chaiscript } - for (size_t i = 1; i < lhssize && i < rhssize; ++i) { - const Type_Info lt = lhsparamtypes[i]; - const Type_Info rt = rhsparamtypes[i]; + const Type_Info < = lhsparamtypes[i]; + const Type_Info &rt = rhsparamtypes[i]; if (lt.bare_equal(rt) && lt.is_const() == rt.is_const()) { @@ -1160,9 +1083,7 @@ namespace chaiscript } - /** - * Throw a reserved_word exception if the name is not allowed - */ + /// Throw a reserved_word exception if the name is not allowed void validate_object_name(const std::string &name) const { if (name.find("::") != std::string::npos) { @@ -1177,29 +1098,24 @@ namespace chaiscript } } - /** - * Implementation detail for adding a function. - * \throws exception::name_conflict_error if there's a function matching the given one being added - */ + /// Implementation detail for adding a function. + /// \throws exception::name_conflict_error if there's a function matching the given one being added void add_function(const Proxy_Function &t_f, const std::string &t_name) { chaiscript::detail::threading::unique_lock l(m_mutex); - std::map > &funcs = get_functions_int(); + auto &funcs = get_functions_int(); - auto itr - = funcs.find(t_name); + auto itr = funcs.find(t_name); - std::map &func_objs = get_function_objects_int(); + auto &func_objs = get_function_objects_int(); if (itr != funcs.end()) { - std::vector &vec = itr->second; - for (std::vector::const_iterator itr2 = vec.begin(); - itr2 != vec.end(); - ++itr2) + auto &vec = itr->second; + for (const auto &func : vec) { - if ((*t_f) == *(*itr2)) + if ((*t_f) == *(func)) { throw chaiscript::exception::name_conflict_error(t_name); } @@ -1207,16 +1123,16 @@ namespace chaiscript vec.push_back(t_f); std::stable_sort(vec.begin(), vec.end(), &function_less_than); - func_objs[t_name] = Proxy_Function(new Dispatch_Function(vec)); + func_objs[t_name] = std::make_shared(vec); } else if (t_f->has_arithmetic_param()) { // if the function is the only function but it also contains // arithmetic operators, we must wrap it in a dispatch function // to allow for automatic arithmetic type conversions std::vector vec({t_f}); - funcs.insert(std::make_pair(t_name, vec)); - func_objs[t_name] = Proxy_Function(new Dispatch_Function(vec)); + funcs.emplace(t_name, vec); + func_objs[t_name] = std::make_shared(std::move(vec)); } else { - funcs.insert(std::make_pair(t_name, std::vector({t_f}))); + funcs.emplace(t_name, std::vector{t_f}); func_objs[t_name] = t_f; } @@ -1238,7 +1154,7 @@ namespace chaiscript std::list call_params; int call_depth; - }; + }; Dynamic_Cast_Conversions m_conversions; chaiscript::detail::threading::Thread_Storage m_stack_holder; diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index 8b96ef5..539157c 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -282,7 +282,7 @@ namespace chaiscript return Boxed_Value(); } } - catch (const chaiscript::eval::detail::Return_Value &rv) { + catch (chaiscript::eval::detail::Return_Value &rv) { return rv.retval; } } @@ -384,7 +384,7 @@ namespace chaiscript throw chaiscript::exception::file_not_found_error(t_filename); } - std::streampos size = infile.tellg(); + const auto size = infile.tellg(); infile.seekg(0, std::ios::beg); assert(size >= 0); @@ -393,7 +393,7 @@ namespace chaiscript { return std::string(); } else { - std::vector v(static_cast(size)); + std::vector v(static_cast(size)); infile.read(&v[0], size); return std::string(v.begin(), v.end()); } @@ -459,7 +459,7 @@ namespace chaiscript u.in_ptr = &ChaiScript::use; if ( dladdr((void*)(u.out_ptr), &rInfo) && rInfo.dli_fname ) { std::string dllpath(rInfo.dli_fname); - size_t lastslash = dllpath.rfind('/'); + const size_t lastslash = dllpath.rfind('/'); if (lastslash != std::string::npos) { dllpath.erase(lastslash); @@ -467,15 +467,15 @@ namespace chaiscript // Let's see if this is a link that we should expand std::vector buf(2048); - size_t pathlen = readlink(dllpath.c_str(), &buf.front(), buf.size()); + const size_t pathlen = readlink(dllpath.c_str(), &buf.front(), buf.size()); if (pathlen > 0 && pathlen < buf.size()) { dllpath = std::string(&buf.front(), pathlen); } m_modulepaths.insert(m_modulepaths.begin(), dllpath+"/"); - } -#endif + } +#endif // attempt to load the stdlib @@ -525,10 +525,10 @@ namespace chaiscript /// \param[in] t_filename Filename to load and evaluate void use(const std::string &t_filename) { - for (size_t i = 0; i < m_usepaths.size(); ++i) + for (const auto &path : m_usepaths) { try { - const std::string appendedpath = m_usepaths[i] + t_filename; + const auto appendedpath = path + t_filename; chaiscript::detail::threading::unique_lock l(m_use_mutex); chaiscript::detail::threading::unique_lock l2(m_mutex); @@ -543,14 +543,12 @@ namespace chaiscript return; // return, we loaded it, or it was already loaded } catch (const exception::file_not_found_error &) { - if (i == m_usepaths.size() - 1) - { - throw exception::file_not_found_error(t_filename); - } - // failed to load, try the next path } } + + // failed to load by any name + throw exception::file_not_found_error(t_filename); } /// \brief Adds a constant object that is available in all contexts and to all threads @@ -718,15 +716,9 @@ namespace chaiscript version_stripped_name.erase(version_pos); } - std::vector prefixes; - prefixes.push_back("lib"); - prefixes.push_back("cyg"); - prefixes.push_back(""); + std::vector prefixes{"lib", "cyg", ""}; - std::vector postfixes; - postfixes.push_back(".dll"); - postfixes.push_back(".so"); - postfixes.push_back(""); + std::vector postfixes{".dll", ".so", ""}; for (auto & elem : m_modulepaths) { @@ -735,7 +727,7 @@ namespace chaiscript for (auto & postfix : postfixes) { try { - std::string name = elem + prefix + t_module_name + postfix; + const auto name = elem + prefix + t_module_name + postfix; // std::cerr << "trying location: " << name << std::endl; load_module(version_stripped_name, name); return name; From 5619f2602ddfd919d7b6e302a04aaf09def91b43 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sun, 5 Oct 2014 08:58:29 -0600 Subject: [PATCH 35/63] Eliminate extra dynamic allocation in the Stack --- .../chaiscript/dispatchkit/dispatchkit.hpp | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index 5ab3b11..c4299fc 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -389,8 +389,7 @@ namespace chaiscript public: typedef std::map Type_Name_Map; typedef std::map Scope; - typedef std::deque StackData; - typedef std::shared_ptr Stack; + typedef std::vector StackData; struct State { @@ -528,7 +527,7 @@ namespace chaiscript void new_stack() { // add a new Stack with 1 element - m_stack_holder->stacks.emplace_back(std::make_shared(1)); + m_stack_holder->stacks.emplace_back(1); } void pop_stack() @@ -536,12 +535,6 @@ namespace chaiscript m_stack_holder->stacks.pop_back(); } - /// \returns the current stack - Stack get_stack() const - { - return m_stack_holder->stacks.back(); - } - /// Searches the current stack for an object of the given name /// includes a special overload for the _ place holder object to /// ensure that it is always in scope. @@ -718,7 +711,7 @@ namespace chaiscript Stack_Holder &s = *m_stack_holder; // We don't want the current context, but one up if it exists - StackData &stack = (s.stacks.size()==1)?(*(s.stacks.back())):(*s.stacks[s.stacks.size()-2]); + StackData &stack = (s.stacks.size()==1)?(s.stacks.back()):(s.stacks[s.stacks.size()-2]); std::map retval; @@ -966,7 +959,7 @@ namespace chaiscript /// make const/non const versions StackData &get_stack_data() const { - return *(m_stack_holder->stacks.back()); + return m_stack_holder->stacks.back(); } const std::map &get_function_objects_int() const @@ -1147,10 +1140,10 @@ namespace chaiscript Stack_Holder() : call_depth(0) { - stacks.emplace_back(std::make_shared(1)); + stacks.emplace_back(1); } - std::deque stacks; + std::deque stacks; std::list call_params; int call_depth; From 87e40237d3f63c3821fa09d725a0eade13130e0e Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sun, 5 Oct 2014 11:47:50 -0600 Subject: [PATCH 36/63] Enable moving of Any objects --- include/chaiscript/dispatchkit/any.hpp | 25 +++++++++---------- .../chaiscript/dispatchkit/boxed_value.hpp | 24 +++++++++++++++--- 2 files changed, 32 insertions(+), 17 deletions(-) diff --git a/include/chaiscript/dispatchkit/any.hpp b/include/chaiscript/dispatchkit/any.hpp index 39ff2fa..89d8d8a 100644 --- a/include/chaiscript/dispatchkit/any.hpp +++ b/include/chaiscript/dispatchkit/any.hpp @@ -51,7 +51,8 @@ namespace chaiscript { Data &operator=(const Data &) = delete; - virtual ~Data() {} + virtual ~Data() = default; + virtual void *data() = 0; const std::type_info &type() const { @@ -65,13 +66,13 @@ namespace chaiscript { template struct Data_Impl : Data { - Data_Impl(T t_type) + explicit Data_Impl(T t_type) : Data(typeid(T)), m_data(std::move(t_type)) { } - virtual ~Data_Impl() {} + virtual ~Data_Impl() = default; virtual void *data() CHAISCRIPT_OVERRIDE { @@ -104,12 +105,17 @@ namespace chaiscript { } } - template - Any(const ValueType &t_value) - : m_data(std::unique_ptr(new Data_Impl(t_value))) + Any(Any &&) = default; + Any &operator=(Any &&t_any) = default; + + template::type>::value>::type> + explicit Any(ValueType &&t_value) + : m_data(std::unique_ptr(new Data_Impl::type>(std::forward(t_value)))) { } + Any & operator=(const Any &t_any) { Any copy(t_any); @@ -117,13 +123,6 @@ namespace chaiscript { return *this; } - template - Any & operator=(const ValueType &t_value) - { - m_data = std::unique_ptr(new Data_Impl(t_value)); - return *this; - } - template ToType &cast() const { diff --git a/include/chaiscript/dispatchkit/boxed_value.hpp b/include/chaiscript/dispatchkit/boxed_value.hpp index 374036b..8d272cb 100644 --- a/include/chaiscript/dispatchkit/boxed_value.hpp +++ b/include/chaiscript/dispatchkit/boxed_value.hpp @@ -35,10 +35,10 @@ namespace chaiscript struct Data { Data(const Type_Info &ti, - const chaiscript::detail::Any &to, + chaiscript::detail::Any to, bool tr, const void *t_void_ptr) - : m_type_info(ti), m_obj(to), m_data_ptr(ti.is_const()?nullptr:const_cast(t_void_ptr)), m_const_data_ptr(t_void_ptr), + : m_type_info(ti), m_obj(std::move(to)), m_data_ptr(ti.is_const()?nullptr:const_cast(t_void_ptr)), m_const_data_ptr(t_void_ptr), m_is_ref(tr) { } @@ -61,6 +61,9 @@ namespace chaiscript Data(const Data &) = delete; + Data(Data &&) = default; + Data &operator=(Data &&rhs) = default; + Type_Info m_type_info; chaiscript::detail::Any m_obj; @@ -99,6 +102,18 @@ namespace chaiscript ); } + template + static std::shared_ptr get(std::shared_ptr &&obj) + { + auto ptr = obj.get(); + return std::make_shared( + detail::Get_Type_Info::get(), + chaiscript::detail::Any(std::move(obj)), + false, + ptr + ); + } + template static std::shared_ptr get(T *t) { @@ -120,11 +135,12 @@ namespace chaiscript static std::shared_ptr get(const T& t) { auto p = std::make_shared(t); + auto ptr = p.get(); return std::make_shared( detail::Get_Type_Info::get(), - chaiscript::detail::Any(p), + chaiscript::detail::Any(std::move(p)), false, - p.get() + ptr ); } From f547b4bb1021cfb2f93d2c2bc5dd2a773d87727d Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sun, 5 Oct 2014 12:11:46 -0600 Subject: [PATCH 37/63] Enable moving of data into Boxed_Values when possible --- include/chaiscript/dispatchkit/boxed_value.hpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/include/chaiscript/dispatchkit/boxed_value.hpp b/include/chaiscript/dispatchkit/boxed_value.hpp index 8d272cb..dd8c210 100644 --- a/include/chaiscript/dispatchkit/boxed_value.hpp +++ b/include/chaiscript/dispatchkit/boxed_value.hpp @@ -132,9 +132,9 @@ namespace chaiscript } template - static std::shared_ptr get(const T& t) + static std::shared_ptr get(T t) { - auto p = std::make_shared(t); + auto p = std::make_shared(std::move(t)); auto ptr = p.get(); return std::make_shared( detail::Get_Type_Info::get(), @@ -158,9 +158,10 @@ namespace chaiscript public: /// Basic Boxed_Value constructor - template - explicit Boxed_Value(T t) - : m_data(Object_Data::get(t)) + template::type>::value>::type> + explicit Boxed_Value(T &&t) + : m_data(Object_Data::get(std::forward(t))) { } From 935e9de19effab00049c7bd04b3b63b049fc7834 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sun, 5 Oct 2014 14:58:27 -0600 Subject: [PATCH 38/63] GCC 4.6 fixes to cleanups --- include/chaiscript/dispatchkit/any.hpp | 4 ++-- include/chaiscript/dispatchkit/boxed_value.hpp | 5 +++-- include/chaiscript/dispatchkit/dispatchkit.hpp | 16 ++++++++-------- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/include/chaiscript/dispatchkit/any.hpp b/include/chaiscript/dispatchkit/any.hpp index 89d8d8a..0abfa37 100644 --- a/include/chaiscript/dispatchkit/any.hpp +++ b/include/chaiscript/dispatchkit/any.hpp @@ -51,7 +51,7 @@ namespace chaiscript { Data &operator=(const Data &) = delete; - virtual ~Data() = default; + virtual ~Data() {} virtual void *data() = 0; const std::type_info &type() const @@ -72,7 +72,7 @@ namespace chaiscript { { } - virtual ~Data_Impl() = default; + virtual ~Data_Impl() {} virtual void *data() CHAISCRIPT_OVERRIDE { diff --git a/include/chaiscript/dispatchkit/boxed_value.hpp b/include/chaiscript/dispatchkit/boxed_value.hpp index dd8c210..6ff5763 100644 --- a/include/chaiscript/dispatchkit/boxed_value.hpp +++ b/include/chaiscript/dispatchkit/boxed_value.hpp @@ -123,11 +123,12 @@ namespace chaiscript template static std::shared_ptr get(std::reference_wrapper obj) { + auto p = &obj.get(); return std::make_shared( detail::Get_Type_Info::get(), - chaiscript::detail::Any(obj), + chaiscript::detail::Any(std::move(obj)), true, - &obj.get() + p ); } diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index c4299fc..63a0038 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -272,7 +272,7 @@ namespace chaiscript } } - virtual ~Dispatch_Function() = default; + virtual ~Dispatch_Function() {} virtual std::vector get_contained_functions() const CHAISCRIPT_OVERRIDE { @@ -464,7 +464,7 @@ namespace chaiscript { throw chaiscript::exception::name_conflict_error(name); } else { - stack.back().emplace(name, std::move(obj)); + stack.back().insert(std::make_pair(name, std::move(obj))); } } @@ -483,7 +483,7 @@ namespace chaiscript { throw chaiscript::exception::name_conflict_error(name); } else { - m_state.m_global_objects.emplace(name, obj); + m_state.m_global_objects.insert(std::make_pair(name, obj)); } } @@ -499,7 +499,7 @@ namespace chaiscript { throw chaiscript::exception::name_conflict_error(name); } else { - m_state.m_global_objects.emplace(name, obj); + m_state.m_global_objects.insert(std::make_pair(name, obj)); } } @@ -580,7 +580,7 @@ namespace chaiscript chaiscript::detail::threading::unique_lock l(m_mutex); - m_state.m_types.emplace(name, ti); + m_state.m_types.insert(std::make_pair(name, ti)); } /// Returns the type info for a named type @@ -745,7 +745,7 @@ namespace chaiscript for (const auto & fun : funs) { - objs.emplace(fun.first, const_var(fun.second)); + objs.insert(std::make_pair(fun.first, const_var(fun.second))); } return objs; @@ -1122,10 +1122,10 @@ namespace chaiscript // arithmetic operators, we must wrap it in a dispatch function // to allow for automatic arithmetic type conversions std::vector vec({t_f}); - funcs.emplace(t_name, vec); + funcs.insert(std::make_pair(t_name, vec)); func_objs[t_name] = std::make_shared(std::move(vec)); } else { - funcs.emplace(t_name, std::vector{t_f}); + funcs.insert(std::make_pair(t_name, std::vector{t_f})); func_objs[t_name] = t_f; } From 58d9e69479bf0a7f7c32c0bd432d1c3e7dc8277c Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sun, 5 Oct 2014 21:53:44 -0600 Subject: [PATCH 39/63] Work around missing move operations in MSVC12 --- include/chaiscript/dispatchkit/any.hpp | 2 ++ include/chaiscript/dispatchkit/boxed_number.hpp | 2 +- include/chaiscript/dispatchkit/boxed_value.hpp | 6 ++++-- include/chaiscript/dispatchkit/type_info.hpp | 2 ++ 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/include/chaiscript/dispatchkit/any.hpp b/include/chaiscript/dispatchkit/any.hpp index 0abfa37..7c403b7 100644 --- a/include/chaiscript/dispatchkit/any.hpp +++ b/include/chaiscript/dispatchkit/any.hpp @@ -105,8 +105,10 @@ namespace chaiscript { } } +#if _MSC_VER != 1800 Any(Any &&) = default; Any &operator=(Any &&t_any) = default; +#endif template::type>::value>::type> diff --git a/include/chaiscript/dispatchkit/boxed_number.hpp b/include/chaiscript/dispatchkit/boxed_number.hpp index e1a5ca7..62eabe9 100644 --- a/include/chaiscript/dispatchkit/boxed_number.hpp +++ b/include/chaiscript/dispatchkit/boxed_number.hpp @@ -233,7 +233,7 @@ namespace chaiscript template static Boxed_Value oper_rhs(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs) { - const Type_Info &inp_ = t_rhs.get_type_info(); + const auto &inp_ = t_rhs.get_type_info(); if (inp_ == typeid(int)) { return Go::go(t_oper, t_lhs, t_rhs); diff --git a/include/chaiscript/dispatchkit/boxed_value.hpp b/include/chaiscript/dispatchkit/boxed_value.hpp index 6ff5763..466035e 100644 --- a/include/chaiscript/dispatchkit/boxed_value.hpp +++ b/include/chaiscript/dispatchkit/boxed_value.hpp @@ -61,9 +61,10 @@ namespace chaiscript Data(const Data &) = delete; +#if !defined(_MSC_VER) || _MSC_VER != 1800 Data(Data &&) = default; Data &operator=(Data &&rhs) = default; - +#endif Type_Info m_type_info; chaiscript::detail::Any m_obj; @@ -172,9 +173,10 @@ namespace chaiscript { } - +#if !defined(_MSC_VER) || _MSC_VER != 1800 Boxed_Value(Boxed_Value&&) = default; Boxed_Value& operator=(Boxed_Value&&) = default; +#endif Boxed_Value(const Boxed_Value&) = default; Boxed_Value& operator=(const Boxed_Value&) = default; diff --git a/include/chaiscript/dispatchkit/type_info.hpp b/include/chaiscript/dispatchkit/type_info.hpp index f287033..3e129e4 100644 --- a/include/chaiscript/dispatchkit/type_info.hpp +++ b/include/chaiscript/dispatchkit/type_info.hpp @@ -47,8 +47,10 @@ namespace chaiscript { } +#if !defined(_MSC_VER) || _MSC_VER != 1800 Type_Info(Type_Info&&) = default; Type_Info& operator=(Type_Info&&) = default; +#endif Type_Info(const Type_Info&) = default; Type_Info& operator=(const Type_Info&) = default; From 78cd980067435de1f8a703d9f8432705a74d967a Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 1 Oct 2014 15:49:11 -0600 Subject: [PATCH 40/63] Work around broken Apple clang implementation This line of code does not cause an error on clang-3.4 or clang-3.5 on Linux. Apple's clang is somewhere between the two, no way to know where. For an unknown reason, specifying default move operations in 'Data' causes the compiler to think that Boxed_Value is an incomplete type. This is highly illogical since Data is only used via a shared_ptr, so the size / type of Boxed_Value should be fully known (and is known on every other compiler/platform combination). --- include/chaiscript/dispatchkit/boxed_value.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/chaiscript/dispatchkit/boxed_value.hpp b/include/chaiscript/dispatchkit/boxed_value.hpp index 466035e..77076f1 100644 --- a/include/chaiscript/dispatchkit/boxed_value.hpp +++ b/include/chaiscript/dispatchkit/boxed_value.hpp @@ -61,7 +61,7 @@ namespace chaiscript Data(const Data &) = delete; -#if !defined(_MSC_VER) || _MSC_VER != 1800 +#if !defined(__APPLE__) && (!defined(_MSC_VER) || _MSC_VER != 1800) Data(Data &&) = default; Data &operator=(Data &&rhs) = default; #endif From 021e2a79496485f50306e5fc9d601f281efe3416 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sun, 12 Oct 2014 22:12:54 -0700 Subject: [PATCH 41/63] Fix returning of boolean values from functors --- include/chaiscript/dispatchkit/function_call_detail.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/chaiscript/dispatchkit/function_call_detail.hpp b/include/chaiscript/dispatchkit/function_call_detail.hpp index e6cd465..e86bb25 100644 --- a/include/chaiscript/dispatchkit/function_call_detail.hpp +++ b/include/chaiscript/dispatchkit/function_call_detail.hpp @@ -81,7 +81,7 @@ namespace chaiscript Ret operator()(Param...param) { - return Function_Caller_Ret::value>::call(m_funcs, { + return Function_Caller_Ret::value && !std::is_same::value>::call(m_funcs, { (std::is_reference::value&&!(std::is_same::type>::type>::value))?Boxed_Value(std::ref(param)):Boxed_Value(param)... }, m_conversions From 48c97bce9c1e98d115433c4c20dad8c58af45b75 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sun, 12 Oct 2014 22:13:40 -0700 Subject: [PATCH 42/63] Add faux-inheritance example --- CMakeLists.txt | 2 + samples/inheritance.cpp | 134 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 136 insertions(+) create mode 100644 samples/inheritance.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index cefe9ec..c8ef4b9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -203,6 +203,8 @@ if(BUILD_SAMPLES) target_link_libraries(example ${LIBS}) add_executable(memory_leak_test samples/memory_leak_test.cpp) target_link_libraries(memory_leak_test ${LIBS}) + add_executable(inheritance samples/inheritance.cpp) + target_link_libraries(inheritance ${LIBS}) endif() diff --git a/samples/inheritance.cpp b/samples/inheritance.cpp new file mode 100644 index 0000000..1e2e02b --- /dev/null +++ b/samples/inheritance.cpp @@ -0,0 +1,134 @@ +#include +#include + +class BaseClass +{ + public: + BaseClass() + { + } + + virtual ~BaseClass() = default; + + virtual std::string doSomething(float, double) const = 0; + + + void setValue(const std::string &t_val) { + if (validateValue(t_val)) + { + m_value = t_val; + } + } + + std::string getValue() const { + return m_value; + } + + protected: + virtual bool validateValue(const std::string &t_val) = 0; + + private: + std::string m_value; +}; + +class ChaiScriptDerived : public BaseClass +{ + public: + ChaiScriptDerived(const std::vector &t_funcs) + { + // using the range-checked .at() methods to give us an exception + // instead of a crash if the user passed in too-few params + tie(t_funcs.at(0), m_doSomethingImpl); + tie(t_funcs.at(1), m_validateValueImpl); + } + + std::string doSomething(float f, double d) const override + { + assert(m_doSomethingImpl); + return m_doSomethingImpl(*this, f, d); + } + + protected: + bool validateValue(const std::string &t_val) override + { + assert(m_validateValueImpl); + return m_validateValueImpl(*this, t_val); + } + + private: + template + void tie(const chaiscript::Boxed_Value &t_func, Param &t_param) + { + t_param = chaiscript::boxed_cast(t_func); + } + + std::function m_doSomethingImpl; + std::function m_validateValueImpl; +}; + +int main() +{ + chaiscript::ChaiScript chai(chaiscript::Std_Lib::library()); + chai.add(chaiscript::fun(&BaseClass::doSomething), "doSomething"); + chai.add(chaiscript::fun(&BaseClass::setValue), "setValue"); + chai.add(chaiscript::fun(&BaseClass::getValue), "getValue"); + chai.add(chaiscript::constructor &)>(), "ChaiScriptDerived"); + chai.add(chaiscript::base_class()); + chai.add(chaiscript::user_type(), "BaseClass"); + chai.add(chaiscript::user_type(), "ChaiScriptDerived"); + + std::string script = R""( + def MakeDerived() { + return ChaiScriptDerived( + // create a dynamically created array and pass it in to the constructor + [ + fun(this, f, d) { + // see here that we are calling back into the 'this' pointer + return "${this.getValue()}${f * d}"; + }, + + fun(this, new_val) { + if (new_val.size() < 5) { + true; + } else { + print("String ${new_val} is too long"); + false; + } + } + ] + ); + } + + var myderived := MakeDerived(); // avoid a copy by using reference assignment := + + )""; + + chai.eval(script); + + BaseClass &myderived = chai.eval("myderived"); + + // at this point in the code myderived is both a ChaiScript variable and a C++ variable. In both cases + // it is a derivation of BaseClass, and the implementation is provided via ChaiScript functors + // assigned in the MakeDerived() factory function + // + // Notice that our validateValue() function has a requirement that the new string be < 5 characters long + + myderived.setValue("1234"); + assert(myderived.getValue() == "1234"); + + // chaiscript defined function will print out an error message and refuse to allow the setting + myderived.setValue("12345"); + assert(myderived.getValue() == "1234"); + + + chai.eval("myderived.setValue(\"new\")"); // set the value via chaiscript + assert(myderived.getValue() == "new"); + + // call the other derived method via chaiscript and return the value to c++ land: + std::string retval = chai.eval("myderived.doSomething(2,4.3)"); + assert(retval == "new8.6"); + + // The whole process is fully orthogonal +} + + From 9e8b833d1155b8fc4bba71535e6a07ce1d605f15 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 18 Oct 2014 16:18:56 -0600 Subject: [PATCH 43/63] Code cleanups --- .../chaiscript/dispatchkit/bad_boxed_cast.hpp | 9 +++--- include/chaiscript/dispatchkit/bind_first.hpp | 31 +++++++++++-------- samples/inheritance.cpp | 6 ++-- 3 files changed, 26 insertions(+), 20 deletions(-) diff --git a/include/chaiscript/dispatchkit/bad_boxed_cast.hpp b/include/chaiscript/dispatchkit/bad_boxed_cast.hpp index b22bde6..648eb41 100644 --- a/include/chaiscript/dispatchkit/bad_boxed_cast.hpp +++ b/include/chaiscript/dispatchkit/bad_boxed_cast.hpp @@ -10,6 +10,7 @@ #include #include +#include "../chaiscript_defines.hpp" #include "type_info.hpp" namespace chaiscript { @@ -28,14 +29,14 @@ namespace chaiscript class bad_boxed_cast : public std::bad_cast { public: - bad_boxed_cast(const Type_Info &t_from, const std::type_info &t_to, + bad_boxed_cast(Type_Info t_from, const std::type_info &t_to, std::string t_what) CHAISCRIPT_NOEXCEPT - : from(t_from), to(&t_to), m_what(std::move(t_what)) + : from(std::move(t_from)), to(&t_to), m_what(std::move(t_what)) { } - bad_boxed_cast(const Type_Info &t_from, const std::type_info &t_to) CHAISCRIPT_NOEXCEPT - : from(t_from), to(&t_to), m_what("Cannot perform boxed_cast") + bad_boxed_cast(Type_Info t_from, const std::type_info &t_to) + : from(std::move(t_from)), to(&t_to), m_what("Cannot perform boxed_cast") { } diff --git a/include/chaiscript/dispatchkit/bind_first.hpp b/include/chaiscript/dispatchkit/bind_first.hpp index 1f913c4..6a3adda 100644 --- a/include/chaiscript/dispatchkit/bind_first.hpp +++ b/include/chaiscript/dispatchkit/bind_first.hpp @@ -18,16 +18,16 @@ namespace chaiscript { static std::tuple placeholder() { return std::tuple(std::placeholders::_1,std::placeholders::_2,std::placeholders::_3,std::placeholders::_4,std::placeholders::_5,std::placeholders::_6,std::placeholders::_7,std::placeholders::_8,std::placeholders::_9,std::placeholders::_10); - }; + } }; template struct Bind_First { template - static std::function bind(F f, InnerParams ... innerparams) + static std::function bind(F&& f, InnerParams ... innerparams) { - return Bind_First::bind(f, innerparams..., std::get(Placeholder::placeholder())); + return Bind_First::bind(std::forward(f), innerparams..., std::get(Placeholder::placeholder())); } }; @@ -35,37 +35,42 @@ namespace chaiscript struct Bind_First<0, maxcount, Sig> { template - static std::function bind(F f, InnerParams ... innerparams) + static std::function bind(F&& f, InnerParams ... innerparams) { - return std::bind(f, innerparams...); + return std::bind(std::forward(f), innerparams...); } }; template - std::function bind_first(Ret (*f)(P1, Param...), O o) + std::function bind_first(Ret (*f)(P1, Param...), O&& o) { - return Bind_First::bind(f, o); + return Bind_First::bind(f, std::forward(o)); } template - std::function bind_first(Ret (Class::*f)(Param...), O o) + std::function bind_first(Ret (Class::*f)(Param...), O&& o) { - return Bind_First::bind(f, o); + return Bind_First::bind(f, std::forward(o)); } template - std::function bind_first(Ret (Class::*f)(Param...) const, O o) + std::function bind_first(Ret (Class::*f)(Param...) const, O&& o) { - return Bind_First::bind(f, o); + return Bind_First::bind(f, std::forward(o)); } template - std::function bind_first(const std::function &f, O o) + std::function bind_first(const std::function &f, O&& o) { - return Bind_First::bind(f, o); + return Bind_First::bind(f, std::forward(o)); } + template + std::function bind_first(std::function &&f, O&& o) + { + return Bind_First::bind(std::move(f), std::forward(o)); + } } } diff --git a/samples/inheritance.cpp b/samples/inheritance.cpp index 1e2e02b..5bd8c86 100644 --- a/samples/inheritance.cpp +++ b/samples/inheritance.cpp @@ -8,7 +8,7 @@ class BaseClass { } - virtual ~BaseClass() = default; + virtual ~BaseClass() {} virtual std::string doSomething(float, double) const = 0; @@ -42,14 +42,14 @@ class ChaiScriptDerived : public BaseClass tie(t_funcs.at(1), m_validateValueImpl); } - std::string doSomething(float f, double d) const override + std::string doSomething(float f, double d) const CHAISCRIPT_OVERRIDE { assert(m_doSomethingImpl); return m_doSomethingImpl(*this, f, d); } protected: - bool validateValue(const std::string &t_val) override + bool validateValue(const std::string &t_val) CHAISCRIPT_OVERRIDE { assert(m_validateValueImpl); return m_validateValueImpl(*this, t_val); From 86e26966c1cb7015fca7fea9f5f37fc0f9afea8e Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 28 Oct 2014 10:53:29 -0600 Subject: [PATCH 44/63] More code cleanups --- include/chaiscript/dispatchkit/bootstrap.hpp | 43 +++------- .../chaiscript/dispatchkit/bootstrap_stl.hpp | 44 +++++----- .../chaiscript/dispatchkit/boxed_number.hpp | 12 +-- .../chaiscript/dispatchkit/boxed_value.hpp | 1 + .../chaiscript/dispatchkit/dispatchkit.hpp | 83 ++++++++----------- .../dispatchkit/dynamic_cast_conversion.hpp | 17 ++-- .../chaiscript/dispatchkit/dynamic_object.hpp | 26 +++--- .../chaiscript/dispatchkit/function_call.hpp | 60 +++++--------- .../dispatchkit/function_call_detail.hpp | 6 +- 9 files changed, 118 insertions(+), 174 deletions(-) diff --git a/include/chaiscript/dispatchkit/bootstrap.hpp b/include/chaiscript/dispatchkit/bootstrap.hpp index 22a439c..c4fd18a 100644 --- a/include/chaiscript/dispatchkit/bootstrap.hpp +++ b/include/chaiscript/dispatchkit/bootstrap.hpp @@ -156,9 +156,7 @@ namespace chaiscript return p; } - /** - * Specific version of shared_ptr_clone just for Proxy_Functions - */ + /// Specific version of shared_ptr_clone just for Proxy_Functions template std::shared_ptr::type> shared_ptr_unconst_clone(const std::shared_ptr::type> &p) @@ -168,11 +166,9 @@ namespace chaiscript - /** - * Assignment function for shared_ptr objects, does not perform a copy of the - * object pointed to, instead maintains the shared_ptr concept. - * Similar to shared_ptr_clone. Used for Proxy_Function. - */ + /// Assignment function for shared_ptr objects, does not perform a copy of the + /// object pointed to, instead maintains the shared_ptr concept. + /// Similar to shared_ptr_clone. Used for Proxy_Function. template Boxed_Value ptr_assign(Boxed_Value lhs, const std::shared_ptr &rhs) { @@ -186,10 +182,8 @@ namespace chaiscript } } - /** - * Class consisting of only static functions. All default bootstrapping occurs - * from this class. - */ + /// Class consisting of only static functions. All default bootstrapping occurs + /// from this class. class Bootstrap { private: @@ -217,9 +211,7 @@ namespace chaiscript } - /** - * Add all arithmetic operators for PODs - */ + /// Add all arithmetic operators for PODs static void opers_arithmetic_pod(ModulePtr m = ModulePtr(new Module())) { m->add(fun(&Boxed_Number::equals), "=="); @@ -259,11 +251,8 @@ namespace chaiscript } - /** - * Create a bound function object. The first param is the function to bind - * the remaining parameters are the args to bind into the - * result - */ + /// Create a bound function object. The first param is the function to bind + /// the remaining parameters are the args to bind into the result static Boxed_Value bind_function(const std::vector ¶ms) { if (params.size() < 2) @@ -273,7 +262,7 @@ namespace chaiscript Const_Proxy_Function f = boxed_cast(params[0]); - return Boxed_Value(Const_Proxy_Function(new dispatch::Bound_Function(f, + return Boxed_Value(Const_Proxy_Function(std::make_shared(f, std::vector(params.begin() + 1, params.end())))); } @@ -318,9 +307,7 @@ namespace chaiscript return e.what(); } - /** - * Boolean specialization of internal to_string function - */ + /// Boolean specialization of internal to_string function static std::string bool_to_string(bool b) { if (b) @@ -350,9 +337,7 @@ namespace chaiscript static bool has_parse_tree(const chaiscript::Const_Proxy_Function &t_pf) { - std::shared_ptr pf - = std::dynamic_pointer_cast(t_pf); - if (pf) + if (auto pf = std::dynamic_pointer_cast(t_pf)) { if (pf->get_parse_tree()) { @@ -367,9 +352,7 @@ namespace chaiscript static chaiscript::AST_NodePtr get_parse_tree(const chaiscript::Const_Proxy_Function &t_pf) { - std::shared_ptr pf - = std::dynamic_pointer_cast(t_pf); - if (pf) + if (auto pf = std::dynamic_pointer_cast(t_pf)) { if (pf->get_parse_tree()) { diff --git a/include/chaiscript/dispatchkit/bootstrap_stl.hpp b/include/chaiscript/dispatchkit/bootstrap_stl.hpp index 6797e5d..acb8344 100644 --- a/include/chaiscript/dispatchkit/bootstrap_stl.hpp +++ b/include/chaiscript/dispatchkit/bootstrap_stl.hpp @@ -278,9 +278,9 @@ namespace chaiscript template ModulePtr container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module())) { - m->add(fun( std::function( [](const ContainerType *a) { return a->size(); } ) ), "size"); - m->add(fun( std::function( [](const ContainerType *a) { return a->empty(); } ) ), "empty"); - m->add(fun( std::function( [](ContainerType *a) { a->clear(); } ) ), "clear"); + m->add(fun([](const ContainerType *a) { return a->size(); } ), "size"); + m->add(fun([](const ContainerType *a) { return a->empty(); } ), "empty"); + m->add(fun([](ContainerType *a) { a->clear(); } ), "clear"); return m; } @@ -493,24 +493,26 @@ namespace chaiscript if (typeid(VectorType) == typeid(std::vector)) { - m->eval("def Vector::`==`(rhs) : type_match(rhs, this) { \ - if ( rhs.size() != this.size() ) { \ - return false; \ - } else { \ - auto r1 = range(this); \ - auto r2 = range(rhs); \ - while (!r1.empty()) \ - { \ - if (!eq(r1.front(), r2.front())) \ - { \ - return false; \ - } \ - r1.pop_front(); \ - r2.pop_front(); \ - } \ - return true; \ - } \ - }"); + m->eval(R"( + def Vector::`==`(rhs) : type_match(rhs, this) { + if ( rhs.size() != this.size() ) { + return false; + } else { + auto r1 = range(this); + auto r2 = range(rhs); + while (!r1.empty()) + { + if (!eq(r1.front(), r2.front())) + { + return false; + } + r1.pop_front(); + r2.pop_front(); + } + true; + } + } )" + ); } return m; diff --git a/include/chaiscript/dispatchkit/boxed_number.hpp b/include/chaiscript/dispatchkit/boxed_number.hpp index 62eabe9..f54cd13 100644 --- a/include/chaiscript/dispatchkit/boxed_number.hpp +++ b/include/chaiscript/dispatchkit/boxed_number.hpp @@ -826,9 +826,7 @@ namespace chaiscript namespace detail { - /** - * Cast_Helper for converting from Boxed_Value to Boxed_Number - */ + /// Cast_Helper for converting from Boxed_Value to Boxed_Number template<> struct Cast_Helper { @@ -840,17 +838,13 @@ namespace chaiscript } }; - /** - * Cast_Helper for converting from Boxed_Value to Boxed_Number - */ + /// Cast_Helper for converting from Boxed_Value to Boxed_Number template<> struct Cast_Helper : Cast_Helper { }; - /** - * Cast_Helper for converting from Boxed_Value to Boxed_Number - */ + /// Cast_Helper for converting from Boxed_Value to Boxed_Number template<> struct Cast_Helper : Cast_Helper { diff --git a/include/chaiscript/dispatchkit/boxed_value.hpp b/include/chaiscript/dispatchkit/boxed_value.hpp index 77076f1..b525281 100644 --- a/include/chaiscript/dispatchkit/boxed_value.hpp +++ b/include/chaiscript/dispatchkit/boxed_value.hpp @@ -13,6 +13,7 @@ #include #include "../chaiscript_threading.hpp" +#include "../chaiscript_defines.hpp" #include "any.hpp" #include "type_info.hpp" diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index 63a0038..b49d14c 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -166,9 +166,9 @@ namespace chaiscript //Add a bit of ChaiScript to eval during module implementation - Module &eval(std::string str) + Module &eval(const std::string &str) { - m_evals.push_back(std::move(str)); + m_evals.push_back(str); return *this; } @@ -265,7 +265,7 @@ namespace chaiscript virtual bool operator==(const dispatch::Proxy_Function_Base &rhs) const CHAISCRIPT_OVERRIDE { try { - const Dispatch_Function &dispatchfun = dynamic_cast(rhs); + const auto &dispatchfun = dynamic_cast(rhs); return m_funcs == dispatchfun.m_funcs; } catch (const std::bad_cast &) { return false; @@ -286,7 +286,7 @@ namespace chaiscript return -1; } - const int arity = m_funcs.front()->get_arity(); + const auto arity = m_funcs.front()->get_arity(); for (const auto &func : m_funcs) { @@ -302,15 +302,8 @@ namespace chaiscript virtual bool call_match(const std::vector &vals, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE { - for (const auto &func : m_funcs) - { - if (func->call_match(vals, t_conversions)) - { - return true; - } - } - - return false; + return std::any_of(m_funcs.cbegin(), m_funcs.cend(), + [&vals, &t_conversions](const Proxy_Function &f){ return f->call_match(vals, t_conversions); }); } virtual std::string annotation() const CHAISCRIPT_OVERRIDE @@ -321,7 +314,7 @@ namespace chaiscript protected: virtual Boxed_Value do_call(const std::vector ¶ms, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE { - return dispatch::dispatch(m_funcs.begin(), m_funcs.end(), params, t_conversions); + return dispatch::dispatch(m_funcs.cbegin(), m_funcs.cend(), params, t_conversions); } private: @@ -329,10 +322,8 @@ namespace chaiscript static std::vector build_type_infos(const std::vector &t_funcs) { - typedef std::vector function_vec; - - auto begin = t_funcs.begin(); - const function_vec::const_iterator end = t_funcs.end(); + auto begin = t_funcs.cbegin(); + const auto &end = t_funcs.cend(); if (begin != end) { @@ -380,10 +371,8 @@ namespace chaiscript namespace detail { - /** - * Main class for the dispatchkit. Handles management - * of the object stack, functions and registered types. - */ + /// Main class for the dispatchkit. Handles management + /// of the object stack, functions and registered types. class Dispatch_Engine { public: @@ -437,12 +426,12 @@ namespace chaiscript void add(const Boxed_Value &obj, const std::string &name) { validate_object_name(name); - StackData &stack = get_stack_data(); + auto &stack = get_stack_data(); - for (int i = static_cast(stack.size())-1; i >= 0; --i) + for (auto stack_elem = stack.rbegin(); stack_elem != stack.rend(); ++stack_elem) { - const auto itr = stack[i].find(name); - if (itr != stack[i].end()) + auto itr = stack_elem->find(name); + if (itr != stack_elem->end()) { itr->second = std::move(obj); return; @@ -456,15 +445,15 @@ namespace chaiscript /// Adds a named object to the current scope void add_object(const std::string &name, const Boxed_Value &obj) const { - StackData &stack = get_stack_data(); + auto &stack = get_stack_data(); validate_object_name(name); - const Scope &scope = stack.back(); + auto &scope = stack.back(); if (scope.find(name) != scope.end()) { throw chaiscript::exception::name_conflict_error(name); } else { - stack.back().insert(std::make_pair(name, std::move(obj))); + scope.insert(std::make_pair(name, obj)); } } @@ -546,13 +535,13 @@ namespace chaiscript return m_place_holder; } - StackData &stack = get_stack_data(); + auto &stack = get_stack_data(); // Is it in the stack? - for (int i = static_cast(stack.size())-1; i >= 0; --i) + for (auto stack_elem = stack.rbegin(); stack_elem != stack.rend(); ++stack_elem) { - const auto stackitr = stack[i].find(name); - if (stackitr != stack[i].end()) + const auto stackitr = stack_elem->find(name); + if (stackitr != stack_elem->end()) { return stackitr->second; } @@ -672,7 +661,7 @@ namespace chaiscript /// the current scope. std::map get_parent_locals() const { - StackData &stack = get_stack_data(); + auto &stack = get_stack_data(); if (stack.size() > 1) { return stack[1]; @@ -684,8 +673,8 @@ namespace chaiscript /// \returns All values in the local thread state, added through the add() function std::map get_locals() const { - StackData &stack = get_stack_data(); - Scope &scope = stack.front(); + auto &stack = get_stack_data(); + auto &scope = stack.front(); return scope; } @@ -696,8 +685,8 @@ namespace chaiscript /// Any existing locals are removed and the given set of variables is added void set_locals(const std::map &t_locals) { - StackData &stack = get_stack_data(); - Scope &scope = stack.front(); + auto &stack = get_stack_data(); + auto &scope = stack.front(); scope = t_locals; } @@ -850,7 +839,7 @@ namespace chaiscript /// (the function) with the remaining parameters as its arguments. Boxed_Value call_exists(const std::vector ¶ms) { - if (params.size() < 1) + if (params.empty()) { throw chaiscript::exception::arity_error(static_cast(params.size()), 1); } @@ -984,17 +973,17 @@ namespace chaiscript static bool function_less_than(const Proxy_Function &lhs, const Proxy_Function &rhs) { - const std::vector &lhsparamtypes = lhs->get_param_types(); - const std::vector &rhsparamtypes = rhs->get_param_types(); + const auto &lhsparamtypes = lhs->get_param_types(); + const auto &rhsparamtypes = rhs->get_param_types(); - const size_t lhssize = lhsparamtypes.size(); - const size_t rhssize = rhsparamtypes.size(); + const auto lhssize = lhsparamtypes.size(); + const auto rhssize = rhsparamtypes.size(); - const Type_Info boxed_type = user_type(); - const Type_Info boxed_pod_type = user_type(); + CHAISCRIPT_CONSTEXPR auto boxed_type = user_type(); + CHAISCRIPT_CONSTEXPR auto boxed_pod_type = user_type(); - std::shared_ptr dynamic_lhs(std::dynamic_pointer_cast(lhs)); - std::shared_ptr dynamic_rhs(std::dynamic_pointer_cast(rhs)); + auto dynamic_lhs(std::dynamic_pointer_cast(lhs)); + auto dynamic_rhs(std::dynamic_pointer_cast(rhs)); if (dynamic_lhs && dynamic_rhs) { diff --git a/include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp b/include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp index 359d0a5..184246e 100644 --- a/include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp +++ b/include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp @@ -229,17 +229,12 @@ namespace chaiscript std::set >::const_iterator find( const Type_Info &base, const Type_Info &derived) const { - for (auto itr = m_conversions.begin(); - itr != m_conversions.end(); - ++itr) - { - if ((*itr)->base().bare_equal(base) && (*itr)->derived().bare_equal(derived)) - { - return itr; - } - } - - return m_conversions.end(); + return std::find_if(m_conversions.begin(), m_conversions.end(), + [&base, &derived](const std::shared_ptr &conversion) + { + return conversion->base().bare_equal(base) && conversion->derived().bare_equal(derived); + } + ); } std::set > get_conversions() const diff --git a/include/chaiscript/dispatchkit/dynamic_object.hpp b/include/chaiscript/dispatchkit/dynamic_object.hpp index beb1c8e..5c93240 100644 --- a/include/chaiscript/dispatchkit/dynamic_object.hpp +++ b/include/chaiscript/dispatchkit/dynamic_object.hpp @@ -64,11 +64,9 @@ namespace chaiscript namespace detail { - /** - * A Proxy_Function implementation designed for calling a function - * that is automatically guarded based on the first param based on the - * param's type name - */ + /// A Proxy_Function implementation designed for calling a function + /// that is automatically guarded based on the first param based on the + /// param's type name class Dynamic_Object_Function : public Proxy_Function_Base { public: @@ -96,11 +94,11 @@ namespace chaiscript virtual ~Dynamic_Object_Function() {} Dynamic_Object_Function &operator=(const Dynamic_Object_Function) = delete; + Dynamic_Object_Function(Dynamic_Object_Function &) = delete; virtual bool operator==(const Proxy_Function_Base &f) const CHAISCRIPT_OVERRIDE { - const Dynamic_Object_Function *df = dynamic_cast(&f); - if (df) + if (const auto *df = dynamic_cast(&f)) { return df->m_type_name == m_type_name && (*df->m_func) == (*m_func); } else { @@ -164,7 +162,7 @@ namespace chaiscript } bool dynamic_object_typename_match(const Boxed_Value &bv, const std::string &name, - const std::shared_ptr &ti, const Dynamic_Cast_Conversions &t_conversions) const + const std::unique_ptr &ti, const Dynamic_Cast_Conversions &t_conversions) const { if (bv.get_type_info().bare_equal(m_doti)) { @@ -186,7 +184,7 @@ namespace chaiscript } bool dynamic_object_typename_match(const std::vector &bvs, const std::string &name, - const std::shared_ptr &ti, const Dynamic_Cast_Conversions &t_conversions) const + const std::unique_ptr &ti, const Dynamic_Cast_Conversions &t_conversions) const { if (bvs.size() > 0) { @@ -198,7 +196,7 @@ namespace chaiscript std::string m_type_name; Proxy_Function m_func; - std::shared_ptr m_ti; + std::unique_ptr m_ti; const Type_Info m_doti; @@ -252,8 +250,7 @@ namespace chaiscript virtual bool call_match(const std::vector &vals, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE { - std::vector new_vals; - new_vals.push_back(Boxed_Value(Dynamic_Object(m_type_name))); + std::vector new_vals{Boxed_Value(Dynamic_Object(m_type_name))}; new_vals.insert(new_vals.end(), vals.begin(), vals.end()); return m_func->call_match(new_vals, t_conversions); @@ -274,9 +271,8 @@ namespace chaiscript protected: virtual Boxed_Value do_call(const std::vector ¶ms, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE { - std::vector new_params; - chaiscript::Boxed_Value bv = var(Dynamic_Object(m_type_name)); - new_params.push_back(bv); + auto bv = var(Dynamic_Object(m_type_name)); + std::vector new_params{bv}; new_params.insert(new_params.end(), params.begin(), params.end()); (*m_func)(new_params, t_conversions); diff --git a/include/chaiscript/dispatchkit/function_call.hpp b/include/chaiscript/dispatchkit/function_call.hpp index 8b6c9ff..66ce0d6 100644 --- a/include/chaiscript/dispatchkit/function_call.hpp +++ b/include/chaiscript/dispatchkit/function_call.hpp @@ -28,14 +28,12 @@ namespace chaiscript { namespace dispatch { - /** - * Build a function caller that knows how to dispatch on a set of functions - * example: - * std::function f = - * build_function_caller(dispatchkit.get_function("print")); - * \returns A std::function object for dispatching - * \param[in] funcs the set of functions to dispatch on. - */ + /// Build a function caller that knows how to dispatch on a set of functions + /// example: + /// std::function f = + /// build_function_caller(dispatchkit.get_function("print")); + /// \returns A std::function object for dispatching + /// \param[in] funcs the set of functions to dispatch on. template std::function functor(const std::vector &funcs, const Dynamic_Cast_Conversions *t_conversions) @@ -44,32 +42,26 @@ namespace chaiscript return detail::build_function_caller_helper(p, funcs, t_conversions); } - /** - * Build a function caller for a particular Proxy_Function object - * useful in the case that a function is being pass out from scripting back - * into code - * example: - * void my_function(Proxy_Function f) - * { - * std::function local_f = - * build_function_caller(f); - * } - * \returns A std::function object for dispatching - * \param[in] func A function to execute. - */ + /// Build a function caller for a particular Proxy_Function object + /// useful in the case that a function is being pass out from scripting back + /// into code + /// example: + /// void my_function(Proxy_Function f) + /// { + /// std::function local_f = + /// build_function_caller(f); + /// } + /// \returns A std::function object for dispatching + /// \param[in] func A function to execute. template std::function functor(Const_Proxy_Function func, const Dynamic_Cast_Conversions *t_conversions) { - std::vector funcs; - funcs.push_back(func); - return functor(funcs, t_conversions); + return functor(std::vector({func}), t_conversions); } - /** - * Helper for automatically unboxing a Boxed_Value that contains a function object - * and creating a typesafe C++ function caller from it. - */ + /// Helper for automatically unboxing a Boxed_Value that contains a function object + /// and creating a typesafe C++ function caller from it. template std::function functor(const Boxed_Value &bv, const Dynamic_Cast_Conversions *t_conversions) @@ -79,9 +71,7 @@ namespace chaiscript } namespace detail{ - /** - * Cast helper to handle automatic casting to const std::function & - */ + /// Cast helper to handle automatic casting to const std::function & template struct Cast_Helper &> { @@ -98,9 +88,7 @@ namespace chaiscript } }; - /** - * Cast helper to handle automatic casting to std::function - */ + /// Cast helper to handle automatic casting to std::function template struct Cast_Helper > { @@ -117,9 +105,7 @@ namespace chaiscript } }; - /** - * Cast helper to handle automatic casting to const std::function - */ + /// Cast helper to handle automatic casting to const std::function template struct Cast_Helper > { diff --git a/include/chaiscript/dispatchkit/function_call_detail.hpp b/include/chaiscript/dispatchkit/function_call_detail.hpp index e86bb25..f3c012b 100644 --- a/include/chaiscript/dispatchkit/function_call_detail.hpp +++ b/include/chaiscript/dispatchkit/function_call_detail.hpp @@ -26,10 +26,8 @@ namespace chaiscript { namespace detail { - /** - * Internal helper class for handling the return - * value of a build_function_caller - */ + /// Internal helper class for handling the return + /// value of a build_function_caller template struct Function_Caller_Ret { From 43d6f0cf164fac76549c9f79105da02de693152d Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 28 Oct 2014 12:43:30 -0600 Subject: [PATCH 45/63] Rename dynamic_cast into type_conversion Prep work for getting user defined type conversions implemented --- include/chaiscript/dispatchkit/boxed_cast.hpp | 8 +- .../dispatchkit/boxed_cast_helper.hpp | 20 +-- .../chaiscript/dispatchkit/boxed_number.hpp | 4 +- .../chaiscript/dispatchkit/dispatchkit.hpp | 14 +- .../dispatchkit/dynamic_cast_conversion.hpp | 132 +++++++++++------- .../chaiscript/dispatchkit/dynamic_object.hpp | 16 +-- .../chaiscript/dispatchkit/function_call.hpp | 14 +- .../dispatchkit/function_call_detail.hpp | 14 +- .../dispatchkit/proxy_functions.hpp | 46 +++--- .../dispatchkit/proxy_functions_detail.hpp | 18 +-- .../chaiscript/language/chaiscript_engine.hpp | 2 +- 11 files changed, 157 insertions(+), 131 deletions(-) diff --git a/include/chaiscript/dispatchkit/boxed_cast.hpp b/include/chaiscript/dispatchkit/boxed_cast.hpp index 31d9386..b33d659 100644 --- a/include/chaiscript/dispatchkit/boxed_cast.hpp +++ b/include/chaiscript/dispatchkit/boxed_cast.hpp @@ -18,7 +18,7 @@ #include "type_info.hpp" namespace chaiscript { -class Dynamic_Cast_Conversions; +class Type_Conversions; namespace detail { namespace exception { class bad_any_cast; @@ -72,7 +72,7 @@ namespace chaiscript /// assert(i == 5); /// \endcode template - typename detail::Cast_Helper::Result_Type boxed_cast(const Boxed_Value &bv, const Dynamic_Cast_Conversions *t_conversions = nullptr) + typename detail::Cast_Helper::Result_Type boxed_cast(const Boxed_Value &bv, const Type_Conversions *t_conversions = nullptr) { try { return detail::Cast_Helper::cast(bv, t_conversions); @@ -92,12 +92,12 @@ namespace chaiscript // std::cout << "trying an up conversion " << typeid(Type).name() << std::endl; // We will not catch any bad_boxed_dynamic_cast that is thrown, let the user get it // either way, we are not responsible if it doesn't work - return detail::Cast_Helper::cast(t_conversions->boxed_dynamic_cast(bv), t_conversions); + return detail::Cast_Helper::cast(t_conversions->boxed_type_conversion(bv), t_conversions); } catch (...) { try { // std::cout << "trying a down conversion " << typeid(Type).name() << std::endl; // try going the other way - down the inheritance graph - return detail::Cast_Helper::cast(t_conversions->boxed_dynamic_down_cast(bv), t_conversions); + return detail::Cast_Helper::cast(t_conversions->boxed_type_down_conversion(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 8ae7552..3222fd1 100644 --- a/include/chaiscript/dispatchkit/boxed_cast_helper.hpp +++ b/include/chaiscript/dispatchkit/boxed_cast_helper.hpp @@ -17,7 +17,7 @@ namespace chaiscript { - class Dynamic_Cast_Conversions; + class Type_Conversions; namespace detail { @@ -36,7 +36,7 @@ namespace chaiscript { typedef typename std::reference_wrapper::type > Result_Type; - static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *) + static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *) { if (ob.get_type_info().bare_equal_type_info(typeid(Result))) { @@ -63,7 +63,7 @@ namespace chaiscript struct Cast_Helper_Inner { typedef const Result * Result_Type; - static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *) + static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *) { if (ob.is_ref()) { @@ -89,7 +89,7 @@ namespace chaiscript struct Cast_Helper_Inner { typedef Result * Result_Type; - static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *) + static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *) { if (ob.is_ref()) { @@ -107,7 +107,7 @@ namespace chaiscript { typedef Result& Result_Type; - static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *) + static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *) { if (!ob.get_type_info().is_const() && ob.get_type_info().bare_equal_type_info(typeid(Result))) { @@ -124,7 +124,7 @@ namespace chaiscript { typedef typename std::shared_ptr Result_Type; - static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *) + static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *) { return ob.get().cast >(); } @@ -136,7 +136,7 @@ namespace chaiscript { typedef typename std::shared_ptr Result_Type; - static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *) + static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *) { if (!ob.get_type_info().is_const()) { @@ -178,7 +178,7 @@ namespace chaiscript { typedef const Boxed_Value & Result_Type; - static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *) + static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *) { return ob; } @@ -190,7 +190,7 @@ namespace chaiscript { typedef Boxed_Value& Result_Type; - static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *) + static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *) { return const_cast(ob); } @@ -246,7 +246,7 @@ namespace chaiscript { typedef typename Cast_Helper_Inner::Result_Type Result_Type; - static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *t_conversions) + static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *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 f54cd13..557a20a 100644 --- a/include/chaiscript/dispatchkit/boxed_number.hpp +++ b/include/chaiscript/dispatchkit/boxed_number.hpp @@ -19,7 +19,7 @@ #include "type_info.hpp" namespace chaiscript { -class Dynamic_Cast_Conversions; +class Type_Conversions; } // namespace chaiscript namespace chaiscript @@ -832,7 +832,7 @@ namespace chaiscript { typedef Boxed_Number Result_Type; - static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *) + static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *) { return Boxed_Number(ob); } diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index b49d14c..b8d4e19 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -141,7 +141,7 @@ namespace chaiscript return *this; } - Module &add(Dynamic_Cast_Conversion d) + Module &add(Type_Conversion d) { m_conversions.push_back(std::move(d)); return *this; @@ -197,7 +197,7 @@ namespace chaiscript std::vector > m_funcs; std::vector > m_globals; std::vector m_evals; - std::vector m_conversions; + std::vector m_conversions; template static void apply(InItr begin, const InItr end, T &t) @@ -300,7 +300,7 @@ namespace chaiscript return arity; } - virtual bool call_match(const std::vector &vals, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE + virtual bool call_match(const std::vector &vals, const Type_Conversions &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); }); @@ -312,7 +312,7 @@ namespace chaiscript } protected: - virtual Boxed_Value do_call(const std::vector ¶ms, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE + virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE { return dispatch::dispatch(m_funcs.cbegin(), m_funcs.cend(), params, t_conversions); } @@ -409,7 +409,7 @@ namespace chaiscript } /// Add a new conversion for upcasting to a base class - void add(const Dynamic_Cast_Conversion &d) + void add(const Type_Conversion &d) { m_conversions.add_conversion(d); } @@ -768,7 +768,7 @@ namespace chaiscript m_state.m_reserved_words.insert(name); } - const Dynamic_Cast_Conversions &conversions() const + const Type_Conversions &conversions() const { return m_conversions; } @@ -1138,7 +1138,7 @@ namespace chaiscript int call_depth; }; - Dynamic_Cast_Conversions m_conversions; + Type_Conversions m_conversions; chaiscript::detail::threading::Thread_Storage m_stack_holder; diff --git a/include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp b/include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp index 184246e..9a90e7c 100644 --- a/include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp +++ b/include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp @@ -47,34 +47,60 @@ namespace chaiscript }; } - namespace detail + namespace exception { - class Dynamic_Conversion + class bad_boxed_type_cast : public bad_boxed_cast { public: - virtual Boxed_Value convert(const Boxed_Value &derived) const = 0; - virtual Boxed_Value convert_down(const Boxed_Value &base) const = 0; - - const Type_Info &base() const + bad_boxed_type_cast(const Type_Info &t_from, const std::type_info &t_to, + const std::string &t_what) CHAISCRIPT_NOEXCEPT + : bad_boxed_cast(t_from, t_to, t_what) { - return m_base; } - const Type_Info &derived() const + + bad_boxed_type_cast(const Type_Info &t_from, const std::type_info &t_to) CHAISCRIPT_NOEXCEPT + : bad_boxed_cast(t_from, t_to) { - return m_derived; + } + + bad_boxed_type_cast(const std::string &w) CHAISCRIPT_NOEXCEPT + : bad_boxed_cast(w) + { + } + + virtual ~bad_boxed_type_cast() CHAISCRIPT_NOEXCEPT {} + }; + } + + + namespace detail + { + class Type_Conversion_Base + { + public: + virtual Boxed_Value convert(const Boxed_Value &from) const = 0; + virtual Boxed_Value convert_down(const Boxed_Value &to) const = 0; + + const Type_Info &to() const + { + return m_to; + } + const Type_Info &from() const + { + return m_from; } protected: - Dynamic_Conversion(const Type_Info &t_base, const Type_Info &t_derived) - : m_base(t_base), m_derived(t_derived) + Type_Conversion_Base(const Type_Info &t_to, const Type_Info &t_from) + : m_to(t_to), m_from(t_from) { } - virtual ~Dynamic_Conversion() {} + virtual ~Type_Conversion_Base() {} private: - Type_Info m_base; - Type_Info m_derived; + Type_Info m_to; + Type_Info m_from; }; @@ -130,11 +156,11 @@ namespace chaiscript }; template - class Dynamic_Conversion_Impl : public Dynamic_Conversion + class Dynamic_Conversion_Impl : public Type_Conversion_Base { public: Dynamic_Conversion_Impl() - : Dynamic_Conversion(user_type(), user_type()) + : Type_Conversion_Base(user_type(), user_type()) { } @@ -150,94 +176,94 @@ namespace chaiscript }; } - class Dynamic_Cast_Conversions + class Type_Conversions { public: - Dynamic_Cast_Conversions() + Type_Conversions() { } - Dynamic_Cast_Conversions(const Dynamic_Cast_Conversions &t_other) + Type_Conversions(const Type_Conversions &t_other) : m_conversions(t_other.get_conversions()) { } - void add_conversion(const std::shared_ptr &conversion) + void add_conversion(const std::shared_ptr &conversion) { chaiscript::detail::threading::unique_lock l(m_mutex); m_conversions.insert(conversion); } - template - bool dynamic_cast_converts() const + template + bool converts() const { - return dynamic_cast_converts(user_type(), user_type()); + return converts(user_type(), user_type()); } - bool dynamic_cast_converts(const Type_Info &base, const Type_Info &derived) const + bool converts(const Type_Info &to, const Type_Info &from) const { - return has_conversion(base, derived) || has_conversion(derived, base); + return has_conversion(to, from) || has_conversion(from, to); } - template - Boxed_Value boxed_dynamic_cast(const Boxed_Value &derived) const + template + Boxed_Value boxed_type_conversion(const Boxed_Value &from) const { try { - return get_conversion(user_type(), derived.get_type_info())->convert(derived); + return get_conversion(user_type(), from.get_type_info())->convert(from); } catch (const std::out_of_range &) { - throw exception::bad_boxed_dynamic_cast(derived.get_type_info(), typeid(Base), "No known conversion"); + throw exception::bad_boxed_dynamic_cast(from.get_type_info(), typeid(To), "No known conversion"); } catch (const std::bad_cast &) { - throw exception::bad_boxed_dynamic_cast(derived.get_type_info(), typeid(Base), "Unable to perform dynamic_cast operation"); + throw exception::bad_boxed_dynamic_cast(from.get_type_info(), typeid(To), "Unable to perform dynamic_cast operation"); } } - template - Boxed_Value boxed_dynamic_down_cast(const Boxed_Value &base) const + template + Boxed_Value boxed_type_down_conversion(const Boxed_Value &to) const { try { - return get_conversion(base.get_type_info(), user_type())->convert_down(base); + return get_conversion(to.get_type_info(), user_type())->convert_down(to); } catch (const std::out_of_range &) { - throw exception::bad_boxed_dynamic_cast(base.get_type_info(), typeid(Derived), "No known conversion"); + throw exception::bad_boxed_dynamic_cast(to.get_type_info(), typeid(From), "No known conversion"); } catch (const std::bad_cast &) { - throw exception::bad_boxed_dynamic_cast(base.get_type_info(), typeid(Derived), "Unable to perform dynamic_cast operation"); + throw exception::bad_boxed_dynamic_cast(to.get_type_info(), typeid(From), "Unable to perform dynamic_cast operation"); } } - bool has_conversion(const Type_Info &base, const Type_Info &derived) const + bool has_conversion(const Type_Info &to, const Type_Info &from) const { chaiscript::detail::threading::shared_lock l(m_mutex); - return find(base, derived) != m_conversions.end(); + return find(to, from) != m_conversions.end(); } - std::shared_ptr get_conversion(const Type_Info &base, const Type_Info &derived) const + std::shared_ptr get_conversion(const Type_Info &to, const Type_Info &from) const { chaiscript::detail::threading::shared_lock l(m_mutex); auto itr = - find(base, derived); + find(to, from); if (itr != m_conversions.end()) { return *itr; } else { - throw std::out_of_range("No such conversion exists from " + derived.bare_name() + " to " + base.bare_name()); + throw std::out_of_range("No such conversion exists from " + from.bare_name() + " to " + to.bare_name()); } } private: - std::set >::const_iterator find( - const Type_Info &base, const Type_Info &derived) const + std::set >::const_iterator find( + const Type_Info &to, const Type_Info &from) const { return std::find_if(m_conversions.begin(), m_conversions.end(), - [&base, &derived](const std::shared_ptr &conversion) + [&to, &from](const std::shared_ptr &conversion) { - return conversion->base().bare_equal(base) && conversion->derived().bare_equal(derived); + return conversion->to().bare_equal(to) && conversion->from().bare_equal(from); } ); } - std::set > get_conversions() const + std::set> get_conversions() const { chaiscript::detail::threading::shared_lock l(m_mutex); @@ -245,19 +271,19 @@ namespace chaiscript } mutable chaiscript::detail::threading::shared_mutex m_mutex; - std::set > m_conversions; + std::set> m_conversions; }; - typedef std::shared_ptr Dynamic_Cast_Conversion; + typedef std::shared_ptr Type_Conversion; - /// \brief Used to register a base / parent class relationship with ChaiScript. Necessary if you + /// \brief Used to register a to / parent class relationship with ChaiScript. Necessary if you /// want automatic conversions up your inheritance hierarchy. /// - /// Create a new base class registration for applying to a module or to the ChaiScript engine + /// Create a new to class registration for applying to a module or to the ChaiScript engine /// Currently, due to limitations in module loading on Windows, and for the sake of portability, /// if you have a type that is introduced in a loadable module and is used by multiple modules /// (through a tertiary dll that is shared between the modules, static linking the new type - /// into both loadable modules would not be portable), you need to register the base type + /// into both loadable modules would not be portable), you need to register the to type /// relationship in all modules that use the newly added type in a polymorphic way. /// /// Example: @@ -268,11 +294,11 @@ namespace chaiscript /// {}; /// /// chaiscript::ChaiScript chai; - /// chai.add(chaiscript::base_class()); + /// chai.add(chaiscript::to_class()); /// \endcode /// template - Dynamic_Cast_Conversion base_class() + Type_Conversion base_class() { //Can only be used with related polymorphic types //may be expanded some day to support conversions other than child -> parent @@ -280,7 +306,7 @@ namespace chaiscript static_assert(std::is_polymorphic::value, "Base class must be polymorphic"); static_assert(std::is_polymorphic::value, "Derived class must be polymorphic"); - return std::shared_ptr(new detail::Dynamic_Conversion_Impl()); + return std::shared_ptr(new detail::Dynamic_Conversion_Impl()); } } diff --git a/include/chaiscript/dispatchkit/dynamic_object.hpp b/include/chaiscript/dispatchkit/dynamic_object.hpp index 5c93240..93ffd26 100644 --- a/include/chaiscript/dispatchkit/dynamic_object.hpp +++ b/include/chaiscript/dispatchkit/dynamic_object.hpp @@ -23,7 +23,7 @@ #include "type_info.hpp" namespace chaiscript { -class Dynamic_Cast_Conversions; +class Type_Conversions; namespace dispatch { class Proxy_Function_Base; } // namespace dispatch @@ -106,7 +106,7 @@ namespace chaiscript } } - virtual bool call_match(const std::vector &vals, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE + virtual bool call_match(const std::vector &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE { if (dynamic_object_typename_match(vals, m_type_name, m_ti, t_conversions)) { @@ -134,7 +134,7 @@ namespace chaiscript protected: - virtual Boxed_Value do_call(const std::vector ¶ms, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE + virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE { if (dynamic_object_typename_match(params, m_type_name, m_ti, t_conversions)) { @@ -144,7 +144,7 @@ namespace chaiscript } } - virtual bool compare_first_type(const Boxed_Value &bv, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE + virtual bool compare_first_type(const Boxed_Value &bv, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE { return dynamic_object_typename_match(bv, m_type_name, m_ti, t_conversions); } @@ -162,7 +162,7 @@ namespace chaiscript } bool dynamic_object_typename_match(const Boxed_Value &bv, const std::string &name, - const std::unique_ptr &ti, const Dynamic_Cast_Conversions &t_conversions) const + const std::unique_ptr &ti, const Type_Conversions &t_conversions) const { if (bv.get_type_info().bare_equal(m_doti)) { @@ -184,7 +184,7 @@ namespace chaiscript } bool dynamic_object_typename_match(const std::vector &bvs, const std::string &name, - const std::unique_ptr &ti, const Dynamic_Cast_Conversions &t_conversions) const + const std::unique_ptr &ti, const Type_Conversions &t_conversions) const { if (bvs.size() > 0) { @@ -248,7 +248,7 @@ namespace chaiscript } } - virtual bool call_match(const std::vector &vals, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE + virtual bool call_match(const std::vector &vals, const Type_Conversions &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()); @@ -269,7 +269,7 @@ namespace chaiscript } protected: - virtual Boxed_Value do_call(const std::vector ¶ms, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE + virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE { auto bv = var(Dynamic_Object(m_type_name)); std::vector new_params{bv}; diff --git a/include/chaiscript/dispatchkit/function_call.hpp b/include/chaiscript/dispatchkit/function_call.hpp index 66ce0d6..a434f07 100644 --- a/include/chaiscript/dispatchkit/function_call.hpp +++ b/include/chaiscript/dispatchkit/function_call.hpp @@ -18,7 +18,7 @@ namespace chaiscript { class Boxed_Value; -class Dynamic_Cast_Conversions; +class Type_Conversions; 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 Dynamic_Cast_Conversions *t_conversions) + functor(const std::vector &funcs, const Type_Conversions *t_conversions) { FunctionType *p=nullptr; return detail::build_function_caller_helper(p, funcs, t_conversions); @@ -55,7 +55,7 @@ namespace chaiscript /// \param[in] func A function to execute. template std::function - functor(Const_Proxy_Function func, const Dynamic_Cast_Conversions *t_conversions) + functor(Const_Proxy_Function func, const Type_Conversions *t_conversions) { return functor(std::vector({func}), t_conversions); } @@ -64,7 +64,7 @@ namespace chaiscript /// and creating a typesafe C++ function caller from it. template std::function - functor(const Boxed_Value &bv, const Dynamic_Cast_Conversions *t_conversions) + functor(const Boxed_Value &bv, const Type_Conversions *t_conversions) { return functor(boxed_cast(bv, t_conversions), t_conversions); } @@ -77,7 +77,7 @@ namespace chaiscript { typedef std::function Result_Type; - static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *t_conversions) + static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *t_conversions) { if (ob.get_type_info().bare_equal(user_type())) { @@ -94,7 +94,7 @@ namespace chaiscript { typedef std::function Result_Type; - static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *t_conversions) + static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *t_conversions) { if (ob.get_type_info().bare_equal(user_type())) { @@ -111,7 +111,7 @@ namespace chaiscript { typedef std::function Result_Type; - static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *t_conversions) + static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *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 f3c012b..2da9b7b 100644 --- a/include/chaiscript/dispatchkit/function_call_detail.hpp +++ b/include/chaiscript/dispatchkit/function_call_detail.hpp @@ -32,7 +32,7 @@ namespace chaiscript struct Function_Caller_Ret { static Ret call(const std::vector &t_funcs, - const std::vector ¶ms, const Dynamic_Cast_Conversions &t_conversions) + const std::vector ¶ms, const Type_Conversions &t_conversions) { return boxed_cast(dispatch::dispatch(t_funcs, params, t_conversions)); } @@ -45,7 +45,7 @@ namespace chaiscript struct Function_Caller_Ret { static Ret call(const std::vector &t_funcs, - const std::vector ¶ms, const Dynamic_Cast_Conversions &t_conversions) + const std::vector ¶ms, const Type_Conversions &t_conversions) { return Boxed_Number(dispatch::dispatch(t_funcs, params, t_conversions)).get_as(); } @@ -59,7 +59,7 @@ namespace chaiscript struct Function_Caller_Ret { static void call(const std::vector &t_funcs, - const std::vector ¶ms, const Dynamic_Cast_Conversions &t_conversions) + const std::vector ¶ms, const Type_Conversions &t_conversions) { dispatch::dispatch(t_funcs, params, t_conversions); } @@ -71,7 +71,7 @@ namespace chaiscript template struct Build_Function_Caller_Helper { - Build_Function_Caller_Helper(std::vector t_funcs, const Dynamic_Cast_Conversions &t_conversions) + Build_Function_Caller_Helper(std::vector t_funcs, const Type_Conversions &t_conversions) : m_funcs(std::move(t_funcs)), m_conversions(t_conversions) { @@ -88,13 +88,13 @@ namespace chaiscript } std::vector m_funcs; - Dynamic_Cast_Conversions m_conversions; + Type_Conversions m_conversions; }; template - std::function build_function_caller_helper(Ret (Params...), const std::vector &funcs, const Dynamic_Cast_Conversions *t_conversions) + std::function build_function_caller_helper(Ret (Params...), const std::vector &funcs, const Type_Conversions *t_conversions) { if (funcs.size() == 1) { @@ -110,7 +110,7 @@ namespace chaiscript // we cannot make any other guesses or assumptions really, so continuing } - return std::function(Build_Function_Caller_Helper(funcs, t_conversions?*t_conversions:Dynamic_Cast_Conversions())); + return std::function(Build_Function_Caller_Helper(funcs, t_conversions?*t_conversions:Type_Conversions())); } } } diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index 16ceaf8..a0cd4b8 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -26,7 +26,7 @@ #include "type_info.hpp" namespace chaiscript { -class Dynamic_Cast_Conversions; +class Type_Conversions; namespace exception { class bad_boxed_cast; struct arity_error; @@ -55,7 +55,7 @@ namespace chaiscript public: virtual ~Proxy_Function_Base() {} - Boxed_Value operator()(const std::vector ¶ms, const chaiscript::Dynamic_Cast_Conversions &t_conversions) const + Boxed_Value operator()(const std::vector ¶ms, const chaiscript::Type_Conversions &t_conversions) const { Boxed_Value bv = do_call(params, t_conversions); return bv; @@ -68,7 +68,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 Dynamic_Cast_Conversions &t_conversions) const = 0; + virtual bool call_match(const std::vector &vals, const Type_Conversions &t_conversions) const = 0; bool has_arithmetic_param() const { @@ -82,7 +82,7 @@ namespace chaiscript //! Return true if the function is a possible match //! to the passed in values - bool filter(const std::vector &vals, const Dynamic_Cast_Conversions &t_conversions) const + bool filter(const std::vector &vals, const Type_Conversions &t_conversions) const { int arity = get_arity(); @@ -106,7 +106,7 @@ namespace chaiscript virtual std::string annotation() const = 0; - static bool compare_type_to_param(const Type_Info &ti, const Boxed_Value &bv, const Dynamic_Cast_Conversions &t_conversions) + static bool compare_type_to_param(const Type_Info &ti, const Boxed_Value &bv, const Type_Conversions &t_conversions) { if (ti.is_undef() || ti.bare_equal(user_type()) @@ -114,7 +114,7 @@ namespace chaiscript && (ti.bare_equal(user_type()) || ti.bare_equal(bv.get_type_info()) || bv.get_type_info().bare_equal(user_type >()) - || t_conversions.dynamic_cast_converts(ti, bv.get_type_info()) + || t_conversions.converts(ti, bv.get_type_info()) ) ) ) @@ -125,7 +125,7 @@ namespace chaiscript } } protected: - virtual Boxed_Value do_call(const std::vector ¶ms, const Dynamic_Cast_Conversions &t_conversions) const = 0; + virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions &t_conversions) const = 0; Proxy_Function_Base(std::vector t_types) : m_types(std::move(t_types)), m_has_arithmetic_param(false) @@ -141,7 +141,7 @@ namespace chaiscript } - virtual bool compare_first_type(const Boxed_Value &bv, const Dynamic_Cast_Conversions &t_conversions) const + virtual bool compare_first_type(const Boxed_Value &bv, const Type_Conversions &t_conversions) const { const std::vector &types = get_param_types(); @@ -233,7 +233,7 @@ namespace chaiscript && !this->m_guard && !prhs->m_guard); } - virtual bool call_match(const std::vector &vals, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE + virtual bool call_match(const std::vector &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE { return (m_arity < 0 || vals.size() == size_t(m_arity)) && test_guard(vals, t_conversions); @@ -260,7 +260,7 @@ namespace chaiscript } protected: - virtual Boxed_Value do_call(const std::vector ¶ms, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE + virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE { if (m_arity < 0 || params.size() == size_t(m_arity)) { @@ -278,7 +278,7 @@ namespace chaiscript } private: - bool test_guard(const std::vector ¶ms, const Dynamic_Cast_Conversions &t_conversions) const + bool test_guard(const std::vector ¶ms, const Type_Conversions &t_conversions) const { if (m_guard) { @@ -351,7 +351,7 @@ namespace chaiscript virtual ~Bound_Function() {} - virtual bool call_match(const std::vector &vals, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE + virtual bool call_match(const std::vector &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE { return m_f->call_match(build_param_list(vals), t_conversions); } @@ -429,7 +429,7 @@ namespace chaiscript return retval; } - virtual Boxed_Value do_call(const std::vector ¶ms, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE + virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE { return (*m_f)(build_param_list(params), t_conversions); } @@ -460,7 +460,7 @@ namespace chaiscript return ""; } - virtual bool call_match(const std::vector &vals, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE + virtual bool call_match(const std::vector &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE { if (int(vals.size()) != get_arity()) { @@ -470,7 +470,7 @@ namespace chaiscript return compare_types(m_types, vals) || compare_types_with_cast(vals, t_conversions); } - virtual bool compare_types_with_cast(const std::vector &vals, const Dynamic_Cast_Conversions &t_conversions) const = 0; + virtual bool compare_types_with_cast(const std::vector &vals, const Type_Conversions &t_conversions) const = 0; }; /** @@ -490,7 +490,7 @@ namespace chaiscript virtual ~Proxy_Function_Impl() {} - virtual bool compare_types_with_cast(const std::vector &vals, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE + virtual bool compare_types_with_cast(const std::vector &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE { return detail::compare_types_cast(m_dummy_func, vals, t_conversions); } @@ -506,7 +506,7 @@ namespace chaiscript } protected: - virtual Boxed_Value do_call(const std::vector ¶ms, const Dynamic_Cast_Conversions &t_conversions) const + virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions &t_conversions) const { return detail::Do_Call::result_type>::go(m_f, params, t_conversions); } @@ -549,7 +549,7 @@ namespace chaiscript return 1; } - virtual bool call_match(const std::vector &vals, const Dynamic_Cast_Conversions &) const CHAISCRIPT_OVERRIDE + virtual bool call_match(const std::vector &vals, const Type_Conversions &) const CHAISCRIPT_OVERRIDE { if (vals.size() != 1) { @@ -565,7 +565,7 @@ namespace chaiscript } protected: - virtual Boxed_Value do_call(const std::vector ¶ms, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE + virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE { if (params.size() == 1) { @@ -622,7 +622,7 @@ namespace chaiscript { template bool types_match_except_for_arithmetic(const FuncType &t_func, const std::vector &plist, - const Dynamic_Cast_Conversions &t_conversions) + const Type_Conversions &t_conversions) { if (t_func->get_arity() != static_cast(plist.size())) { @@ -650,7 +650,7 @@ namespace chaiscript template Boxed_Value dispatch_with_conversions(InItr begin, const InItr &end, const std::vector &plist, - const Dynamic_Cast_Conversions &t_conversions) + const Type_Conversions &t_conversions) { InItr orig(begin); @@ -714,7 +714,7 @@ namespace chaiscript */ template Boxed_Value dispatch(InItr begin, const InItr &end, - const std::vector &plist, const Dynamic_Cast_Conversions &t_conversions) + const std::vector &plist, const Type_Conversions &t_conversions) { InItr orig(begin); while (begin != end) @@ -745,7 +745,7 @@ namespace chaiscript */ template Boxed_Value dispatch(const Funcs &funcs, - const std::vector &plist, const Dynamic_Cast_Conversions &t_conversions) + const std::vector &plist, const Type_Conversions &t_conversions) { return dispatch::dispatch(funcs.begin(), funcs.end(), plist, t_conversions); } diff --git a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp index b908d1f..744d40b 100644 --- a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp @@ -20,7 +20,7 @@ #include "type_info.hpp" namespace chaiscript { -class Dynamic_Cast_Conversions; +class Type_Conversions; namespace exception { class bad_boxed_cast; } // namespace exception @@ -72,7 +72,7 @@ namespace chaiscript template struct Try_Cast { - static void do_try(const std::vector ¶ms, int generation, const Dynamic_Cast_Conversions &t_conversions) + static void do_try(const std::vector ¶ms, int generation, const Type_Conversions &t_conversions) { boxed_cast(params[generation], &t_conversions); Try_Cast::do_try(params, generation+1, t_conversions); @@ -83,7 +83,7 @@ namespace chaiscript template<> struct Try_Cast<> { - static void do_try(const std::vector &, int, const Dynamic_Cast_Conversions &) + static void do_try(const std::vector &, int, const Type_Conversions &) { } }; @@ -96,7 +96,7 @@ namespace chaiscript */ template bool compare_types_cast(Ret (*)(Params...), - const std::vector ¶ms, const Dynamic_Cast_Conversions &t_conversions) + const std::vector ¶ms, const Type_Conversions &t_conversions) { try { Try_Cast::do_try(params, 0, t_conversions); @@ -113,7 +113,7 @@ namespace chaiscript template static Ret do_call(const std::function &f, - const std::vector ¶ms, const Dynamic_Cast_Conversions &t_conversions, InnerParams &&... innerparams) + const std::vector ¶ms, const Type_Conversions &t_conversions, InnerParams &&... innerparams) { return Call_Func::do_call(f, params, t_conversions, std::forward(innerparams)..., params[sizeof...(Params) - count]); } @@ -128,7 +128,7 @@ namespace chaiscript #endif template static Ret do_call(const std::function &f, - const std::vector &, const Dynamic_Cast_Conversions &t_conversions, InnerParams &&... innerparams) + const std::vector &, const Type_Conversions &t_conversions, InnerParams &&... innerparams) { return f(boxed_cast(std::forward(innerparams), &t_conversions)...); } @@ -145,7 +145,7 @@ namespace chaiscript */ template Ret call_func(const std::function &f, - const std::vector ¶ms, const Dynamic_Cast_Conversions &t_conversions) + const std::vector ¶ms, const Type_Conversions &t_conversions) { if (params.size() == sizeof...(Params)) { @@ -171,7 +171,7 @@ namespace chaiscript struct Do_Call { template - static Boxed_Value go(const std::function &fun, const std::vector ¶ms, const Dynamic_Cast_Conversions &t_conversions) + static Boxed_Value go(const std::function &fun, const std::vector ¶ms, const Type_Conversions &t_conversions) { return Handle_Return::handle(call_func(fun, params, t_conversions)); } @@ -181,7 +181,7 @@ namespace chaiscript struct Do_Call { template - static Boxed_Value go(const std::function &fun, const std::vector ¶ms, const Dynamic_Cast_Conversions &t_conversions) + static Boxed_Value go(const std::function &fun, const std::vector ¶ms, const Type_Conversions &t_conversions) { call_func(fun, params, t_conversions); return Handle_Return::handle(); diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index 539157c..b476d29 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -679,7 +679,7 @@ namespace chaiscript /// chaiscript::ChaiScript chai; /// chai.add(chaiscript::base_class()); /// \endcode - ChaiScript &add(const Dynamic_Cast_Conversion &d) + ChaiScript &add(const Type_Conversion &d) { m_engine.add(d); return *this; From 7b42d5307a08f230f53a8524ea4f29cc3a9f6734 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 28 Oct 2014 14:52:24 -0600 Subject: [PATCH 46/63] Add ability to register a user defined type conversion Currently this adds a fair bit of overhead. It will need to be evaluated further before it's merged. --- CMakeLists.txt | 2 +- include/chaiscript/dispatchkit/bootstrap.hpp | 2 +- include/chaiscript/dispatchkit/boxed_cast.hpp | 4 +- .../chaiscript/dispatchkit/dispatchkit.hpp | 2 +- .../dispatchkit/function_call_detail.hpp | 2 +- ...st_conversion.hpp => type_conversions.hpp} | 43 ++++++++++++++++--- .../chaiscript/language/chaiscript_engine.hpp | 9 +++- unittests/user_defined_conversions.chai | 11 +++++ 8 files changed, 62 insertions(+), 13 deletions(-) rename include/chaiscript/dispatchkit/{dynamic_cast_conversion.hpp => type_conversions.hpp} (89%) create mode 100644 unittests/user_defined_conversions.chai diff --git a/CMakeLists.txt b/CMakeLists.txt index c8ef4b9..720cb73 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -154,7 +154,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/dynamic_cast_conversion.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) set_source_files_properties(${Chai_INCLUDES} PROPERTIES HEADER_FILE_ONLY TRUE) diff --git a/include/chaiscript/dispatchkit/bootstrap.hpp b/include/chaiscript/dispatchkit/bootstrap.hpp index c4fd18a..98648da 100644 --- a/include/chaiscript/dispatchkit/bootstrap.hpp +++ b/include/chaiscript/dispatchkit/bootstrap.hpp @@ -24,7 +24,7 @@ #include "boxed_number.hpp" #include "boxed_value.hpp" #include "dispatchkit.hpp" -#include "dynamic_cast_conversion.hpp" +#include "type_conversions.hpp" #include "dynamic_object.hpp" #include "operators.hpp" #include "proxy_constructors.hpp" diff --git a/include/chaiscript/dispatchkit/boxed_cast.hpp b/include/chaiscript/dispatchkit/boxed_cast.hpp index b33d659..f2074d9 100644 --- a/include/chaiscript/dispatchkit/boxed_cast.hpp +++ b/include/chaiscript/dispatchkit/boxed_cast.hpp @@ -14,7 +14,7 @@ #include "bad_boxed_cast.hpp" #include "boxed_cast_helper.hpp" #include "boxed_value.hpp" -#include "dynamic_cast_conversion.hpp" +#include "type_conversions.hpp" #include "type_info.hpp" namespace chaiscript { @@ -86,7 +86,7 @@ namespace chaiscript #pragma warning(disable : 4127) #endif - if (std::is_polymorphic::type>::value && t_conversions) + if ( /*std::is_polymorphic::type>::value && */ t_conversions) { try { // std::cout << "trying an up conversion " << typeid(Type).name() << std::endl; diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index b8d4e19..910987e 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -27,7 +27,7 @@ #include "boxed_cast.hpp" #include "boxed_cast_helper.hpp" #include "boxed_value.hpp" -#include "dynamic_cast_conversion.hpp" +#include "type_conversions.hpp" #include "dynamic_object.hpp" #include "proxy_constructors.hpp" #include "proxy_functions.hpp" diff --git a/include/chaiscript/dispatchkit/function_call_detail.hpp b/include/chaiscript/dispatchkit/function_call_detail.hpp index 2da9b7b..ee1d1bd 100644 --- a/include/chaiscript/dispatchkit/function_call_detail.hpp +++ b/include/chaiscript/dispatchkit/function_call_detail.hpp @@ -17,7 +17,7 @@ #include "boxed_cast.hpp" #include "boxed_number.hpp" #include "boxed_value.hpp" -#include "dynamic_cast_conversion.hpp" +#include "type_conversions.hpp" #include "proxy_functions.hpp" namespace chaiscript diff --git a/include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp b/include/chaiscript/dispatchkit/type_conversions.hpp similarity index 89% rename from include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp rename to include/chaiscript/dispatchkit/type_conversions.hpp index 9a90e7c..7036fe5 100644 --- a/include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp +++ b/include/chaiscript/dispatchkit/type_conversions.hpp @@ -45,10 +45,7 @@ namespace chaiscript virtual ~bad_boxed_dynamic_cast() CHAISCRIPT_NOEXCEPT {} }; - } - namespace exception - { class bad_boxed_type_cast : public bad_boxed_cast { public: @@ -174,6 +171,32 @@ namespace chaiscript return Dynamic_Caster::cast(t_derived); } }; + + + class Type_Conversion_Impl : public Type_Conversion_Base + { + public: + Type_Conversion_Impl(Type_Info t_from, Type_Info t_to, std::function t_func) + : Type_Conversion_Base(std::move(t_to), std::move(t_from)), + m_func(std::move(t_func)) + { + } + + virtual Boxed_Value convert_down(const Boxed_Value &) const CHAISCRIPT_OVERRIDE + { + throw chaiscript::exception::bad_boxed_type_cast("No conversion exists"); + } + + virtual Boxed_Value convert(const Boxed_Value &t_from) const CHAISCRIPT_OVERRIDE + { + /// \todo better handling of errors from the conversion function + return m_func(t_from); + } + + private: + std::function m_func; + }; + } class Type_Conversions @@ -191,6 +214,7 @@ namespace chaiscript void add_conversion(const std::shared_ptr &conversion) { chaiscript::detail::threading::unique_lock l(m_mutex); + /// \todo error if a conversion already exists m_conversions.insert(conversion); } @@ -240,8 +264,7 @@ namespace chaiscript { chaiscript::detail::threading::shared_lock l(m_mutex); - auto itr = - find(to, from); + auto itr = find(to, from); if (itr != m_conversions.end()) { @@ -283,7 +306,7 @@ namespace chaiscript /// Currently, due to limitations in module loading on Windows, and for the sake of portability, /// if you have a type that is introduced in a loadable module and is used by multiple modules /// (through a tertiary dll that is shared between the modules, static linking the new type - /// into both loadable modules would not be portable), you need to register the to type + /// into both loadable modules would not be portable), you need to register the type /// relationship in all modules that use the newly added type in a polymorphic way. /// /// Example: @@ -309,6 +332,14 @@ namespace chaiscript return std::shared_ptr(new detail::Dynamic_Conversion_Impl()); } + namespace { + Type_Conversion type_conversion(const Type_Info &t_from, const Type_Info &t_to, + const std::function &t_func) + { + return std::shared_ptr(new detail::Type_Conversion_Impl(t_from, t_to, t_func)); + } + } + } diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index b476d29..95c4932 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -26,7 +26,7 @@ #include "../dispatchkit/boxed_cast_helper.hpp" #include "../dispatchkit/boxed_value.hpp" #include "../dispatchkit/dispatchkit.hpp" -#include "../dispatchkit/dynamic_cast_conversion.hpp" +#include "../dispatchkit/type_conversions.hpp" #include "../dispatchkit/proxy_functions.hpp" #include "chaiscript_common.hpp" @@ -353,6 +353,13 @@ namespace chaiscript m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_type_name, std::ref(m_engine)), "name"); + m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_type, std::ref(m_engine)), "type"); + m_engine.add(fun &)> ( + [=](const Type_Info &t_from, const Type_Info &t_to, const std::function &t_func) { + m_engine.add(chaiscript::type_conversion(t_from, t_to, t_func)); + } + ), "add_type_conversion"); + typedef std::string (ChaiScript::*load_mod_1)(const std::string&); typedef void (ChaiScript::*load_mod_2)(const std::string&, const std::string&); diff --git a/unittests/user_defined_conversions.chai b/unittests/user_defined_conversions.chai new file mode 100644 index 0000000..e73e92a --- /dev/null +++ b/unittests/user_defined_conversions.chai @@ -0,0 +1,11 @@ + +add_type_conversion(type("string"), type("Type_Info"), fun(s) { return type(s); }); + +// This looks simple, but it takes the string "string" and using the registered +// conversion above, automatically converts that into a Type_Info object, which then +// allows the Type_Info.name() function to be called + +assert_equal("string".name(), "string"); + + + From e85be6eb3d02aec5e7160ec435f5ec8c697e600b Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 28 Oct 2014 20:23:19 -0600 Subject: [PATCH 47/63] Add C++ test for user defined conversion --- .../dispatchkit/type_conversions.hpp | 29 +++++++++++++------ .../chaiscript/language/chaiscript_engine.hpp | 2 +- src/test_module.cpp | 22 ++++++++++++++ unittests/user_defined_conversions_2.chai | 9 ++++++ 4 files changed, 52 insertions(+), 10 deletions(-) create mode 100644 unittests/user_defined_conversions_2.chai diff --git a/include/chaiscript/dispatchkit/type_conversions.hpp b/include/chaiscript/dispatchkit/type_conversions.hpp index 7036fe5..3d6da1b 100644 --- a/include/chaiscript/dispatchkit/type_conversions.hpp +++ b/include/chaiscript/dispatchkit/type_conversions.hpp @@ -107,7 +107,7 @@ namespace chaiscript public: static Boxed_Value cast(const Boxed_Value &t_from) { - if (t_from.get_type_info().bare_equal(user_type())) + if (t_from.get_type_info().bare_equal(chaiscript::user_type())) { if (t_from.is_pointer()) { @@ -157,7 +157,7 @@ namespace chaiscript { public: Dynamic_Conversion_Impl() - : Type_Conversion_Base(user_type(), user_type()) + : Type_Conversion_Base(chaiscript::user_type(), chaiscript::user_type()) { } @@ -173,10 +173,11 @@ namespace chaiscript }; + template class Type_Conversion_Impl : public Type_Conversion_Base { public: - Type_Conversion_Impl(Type_Info t_from, Type_Info t_to, std::function t_func) + Type_Conversion_Impl(Type_Info t_from, Type_Info t_to, Callable t_func) : Type_Conversion_Base(std::move(t_to), std::move(t_from)), m_func(std::move(t_func)) { @@ -194,7 +195,7 @@ namespace chaiscript } private: - std::function m_func; + Callable m_func; }; } @@ -329,16 +330,26 @@ namespace chaiscript static_assert(std::is_polymorphic::value, "Base class must be polymorphic"); static_assert(std::is_polymorphic::value, "Derived class must be polymorphic"); - return std::shared_ptr(new detail::Dynamic_Conversion_Impl()); + return std::make_shared>(); } - namespace { + template Type_Conversion type_conversion(const Type_Info &t_from, const Type_Info &t_to, - const std::function &t_func) + const Callable &t_func) { - return std::shared_ptr(new detail::Type_Conversion_Impl(t_from, t_to, t_func)); + return std::make_shared>(t_from, t_to, t_func); + } + + template + Type_Conversion type_conversion(const Callable &t_function) + { + auto func = [t_function](const Boxed_Value &t_bv) -> Boxed_Value { + // not even attempting to call boxed_cast so that we don't get caught in some call recursion + return chaiscript::Boxed_Value(t_function(detail::Cast_Helper::cast(t_bv, nullptr))); + }; + + return std::make_shared>(user_type(), user_type(), func); } - } } diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index 95c4932..b5393c5 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -359,7 +359,7 @@ namespace chaiscript m_engine.add(chaiscript::type_conversion(t_from, t_to, t_func)); } ), "add_type_conversion"); - + typedef std::string (ChaiScript::*load_mod_1)(const std::string&); typedef void (ChaiScript::*load_mod_2)(const std::string&, const std::string&); diff --git a/src/test_module.cpp b/src/test_module.cpp index 7b6ff75..5dac6f4 100644 --- a/src/test_module.cpp +++ b/src/test_module.cpp @@ -2,6 +2,8 @@ #include #include + + class TestBaseType { public: @@ -22,6 +24,23 @@ class TestBaseType TestBaseType &operator=(const TestBaseType &); }; +class Type2 +{ + public: + Type2(TestBaseType t_bt) + : m_bt(std::move(t_bt)) + { + } + + int get_val() const + { + return m_bt.val; + } + + private: + TestBaseType m_bt; +}; + enum TestEnum { TestValue1 = 1 @@ -95,6 +114,7 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo m->add(chaiscript::user_type(), "TestBaseType"); m->add(chaiscript::user_type(), "TestDerivedType"); m->add(chaiscript::user_type(), "TestMoreDerivedType"); + m->add(chaiscript::user_type(), "Type2"); m->add(chaiscript::constructor(), "TestBaseType"); // m->add(chaiscript::constructor(), "TestBaseType"); @@ -135,7 +155,9 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo m->add(chaiscript::fun(&to_int), "to_int"); m->add(chaiscript::fun(&TestBaseType::constMe), "constMe"); + m->add(chaiscript::type_conversion([](const TestBaseType &t_bt) { return Type2(t_bt); })); + m->add(chaiscript::fun(&Type2::get_val), "get_val"); return m; } diff --git a/unittests/user_defined_conversions_2.chai b/unittests/user_defined_conversions_2.chai new file mode 100644 index 0000000..8a349e1 --- /dev/null +++ b/unittests/user_defined_conversions_2.chai @@ -0,0 +1,9 @@ +load_module("test_module") + +auto t := TestBaseType(); + +// This uses the TestBaseType to Type2 user type +// conversion which was added in the module and then calls +// "get_val()" which exists on the Type2 type +assert_equal(t.get_val(), 10); + From 7c766f87a4b48b8c066e0a0a6f250c6f3aa57f8c Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 28 Oct 2014 22:12:03 -0600 Subject: [PATCH 48/63] Add thread specific cache of type info Reduces the number of locks necessary to check of a user defined type conversion should be scanned for / applied. --- include/chaiscript/dispatchkit/boxed_cast.hpp | 2 +- .../dispatchkit/type_conversions.hpp | 47 ++++++++++++++++++- include/chaiscript/dispatchkit/type_info.hpp | 5 ++ 3 files changed, 51 insertions(+), 3 deletions(-) diff --git a/include/chaiscript/dispatchkit/boxed_cast.hpp b/include/chaiscript/dispatchkit/boxed_cast.hpp index f2074d9..1fc5755 100644 --- a/include/chaiscript/dispatchkit/boxed_cast.hpp +++ b/include/chaiscript/dispatchkit/boxed_cast.hpp @@ -86,7 +86,7 @@ namespace chaiscript #pragma warning(disable : 4127) #endif - if ( /*std::is_polymorphic::type>::value && */ t_conversions) + if (t_conversions && t_conversions->convertable_type()) { try { // std::cout << "trying an up conversion " << typeid(Type).name() << std::endl; diff --git a/include/chaiscript/dispatchkit/type_conversions.hpp b/include/chaiscript/dispatchkit/type_conversions.hpp index 3d6da1b..574f80c 100644 --- a/include/chaiscript/dispatchkit/type_conversions.hpp +++ b/include/chaiscript/dispatchkit/type_conversions.hpp @@ -7,6 +7,7 @@ #ifndef CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_ #define CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_ +#include #include #include #include @@ -203,22 +204,53 @@ namespace chaiscript class Type_Conversions { public: + struct Less_Than + { + bool operator()(const std::type_info *t_lhs, const std::type_info *t_rhs) const + { + return *t_lhs != *t_rhs && t_lhs->before(*t_rhs); + } + }; + Type_Conversions() + : m_num_types(0), + m_thread_cache(this) { } Type_Conversions(const Type_Conversions &t_other) - : m_conversions(t_other.get_conversions()) + : m_conversions(t_other.get_conversions()), m_num_types(m_conversions.size()), + m_thread_cache(this) { } + const std::set &thread_cache() const + { + auto &cache = *m_thread_cache; + if (cache.size() != m_num_types) + { + chaiscript::detail::threading::shared_lock l(m_mutex); + cache = m_convertableTypes; + } + + return cache; + } + void add_conversion(const std::shared_ptr &conversion) { chaiscript::detail::threading::unique_lock l(m_mutex); /// \todo error if a conversion already exists m_conversions.insert(conversion); + m_convertableTypes.insert({conversion->to().bare_type_info(), conversion->from().bare_type_info()}); + m_num_types = m_convertableTypes.size(); } + template + bool convertable_type() const + { + return thread_cache().count(user_type().bare_type_info()) != 0; + } + template bool converts() const { @@ -227,7 +259,14 @@ namespace chaiscript bool converts(const Type_Info &to, const Type_Info &from) const { - return has_conversion(to, from) || has_conversion(from, to); + const auto &types = thread_cache(); + if (types.count(to.bare_type_info()) != 0 && types.count(to.bare_type_info()) != 0) + { + return has_conversion(to, from) || has_conversion(from, to); + } else { + return false; + } + } template @@ -294,8 +333,12 @@ namespace chaiscript return m_conversions; } + mutable chaiscript::detail::threading::shared_mutex m_mutex; std::set> m_conversions; + std::set m_convertableTypes; + std::atomic_size_t m_num_types; + chaiscript::detail::threading::Thread_Storage> m_thread_cache; }; typedef std::shared_ptr Type_Conversion; diff --git a/include/chaiscript/dispatchkit/type_info.hpp b/include/chaiscript/dispatchkit/type_info.hpp index 3e129e4..2cf6455 100644 --- a/include/chaiscript/dispatchkit/type_info.hpp +++ b/include/chaiscript/dispatchkit/type_info.hpp @@ -111,6 +111,11 @@ namespace chaiscript } } + CHAISCRIPT_CONSTEXPR const std::type_info *bare_type_info() const + { + return m_bare_type_info; + } + private: const std::type_info *m_type_info; const std::type_info *m_bare_type_info; From e2cf8a48bec583592e9c5f613b77a914bc7e4881 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Wed, 29 Oct 2014 07:07:12 -0600 Subject: [PATCH 49/63] Correct check for which types might have conversions --- include/chaiscript/dispatchkit/type_conversions.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/chaiscript/dispatchkit/type_conversions.hpp b/include/chaiscript/dispatchkit/type_conversions.hpp index 574f80c..2580fb1 100644 --- a/include/chaiscript/dispatchkit/type_conversions.hpp +++ b/include/chaiscript/dispatchkit/type_conversions.hpp @@ -260,7 +260,7 @@ namespace chaiscript bool converts(const Type_Info &to, const Type_Info &from) const { const auto &types = thread_cache(); - if (types.count(to.bare_type_info()) != 0 && types.count(to.bare_type_info()) != 0) + if (types.count(to.bare_type_info()) != 0 && types.count(from.bare_type_info()) != 0) { return has_conversion(to, from) || has_conversion(from, to); } else { From 87cee688a83ffd5e7042facf411446bc217bb85b Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 1 Nov 2014 15:52:02 -0600 Subject: [PATCH 50/63] Fix broken type conversion call implementation - We need to properly order the function so that the one with the least number if type differences is the one that is tried first. --- .../chaiscript/dispatchkit/dispatchkit.hpp | 6 +-- .../dispatchkit/proxy_functions.hpp | 52 ++++++++++++------- 2 files changed, 34 insertions(+), 24 deletions(-) diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index 910987e..9b4548d 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -314,7 +314,7 @@ namespace chaiscript protected: virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE { - return dispatch::dispatch(m_funcs.cbegin(), m_funcs.cend(), params, t_conversions); + return dispatch::dispatch(m_funcs, params, t_conversions); } private: @@ -775,9 +775,7 @@ namespace chaiscript Boxed_Value call_function(const std::string &t_name, const std::vector ¶ms) const { - std::vector functions = get_function(t_name); - - return dispatch::dispatch(functions.begin(), functions.end(), params, m_conversions); + return dispatch::dispatch(get_function(t_name), params, m_conversions); } Boxed_Value call_function(const std::string &t_name) const diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index a0cd4b8..df446ad 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -712,17 +712,42 @@ namespace chaiscript * each function against the set of parameters, in order, until a matching * function is found or throw dispatch_error if no matching function is found */ - template - Boxed_Value dispatch(InItr begin, const InItr &end, + template + Boxed_Value dispatch(const Funcs &funcs, const std::vector &plist, const Type_Conversions &t_conversions) { - InItr orig(begin); - while (begin != end) + + std::multimap ordered_funcs; + + for (const auto &func : funcs) + { + int numdiffs = 0; + const auto arity = func->get_arity(); + + if (arity == -1) + { + numdiffs = plist.size(); + } else if (arity == plist.size()) { + for (size_t i = 0; i < plist.size(); ++i) + { + if (!func->get_param_types()[i+1].bare_equal(plist[i].get_type_info())) + { + ++numdiffs; + } + } + } else { + continue; + } + + ordered_funcs.insert(std::make_pair(numdiffs, func.get())); + } + + for (const auto &func : ordered_funcs ) { try { - if ((*begin)->filter(plist, t_conversions)) + if (func.second->filter(plist, t_conversions)) { - return (*(*begin))(plist, t_conversions); + return (*(func.second))(plist, t_conversions); } } catch (const exception::bad_boxed_cast &) { //parameter failed to cast, try again @@ -732,22 +757,9 @@ namespace chaiscript //guard failed to allow the function to execute, //try again } - ++begin; } - return detail::dispatch_with_conversions(orig, end, plist, t_conversions); - } - - /** - * Take a vector of functions and a vector of parameters. Attempt to execute - * each function against the set of parameters, in order, until a matching - * function is found or throw dispatch_error if no matching function is found - */ - template - Boxed_Value dispatch(const Funcs &funcs, - const std::vector &plist, const Type_Conversions &t_conversions) - { - return dispatch::dispatch(funcs.begin(), funcs.end(), plist, t_conversions); + return detail::dispatch_with_conversions(funcs.cbegin(), funcs.cend(), plist, t_conversions); } } } From dd12785b72e550dae9642a0d0834af3d41fd0aa5 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sat, 1 Nov 2014 18:40:42 -0600 Subject: [PATCH 51/63] Reduce virtual calls for get_arity Saves compiled code size and some minor runtime differences --- .../chaiscript/dispatchkit/dispatchkit.hpp | 10 ++-- .../chaiscript/dispatchkit/dynamic_object.hpp | 19 ++----- .../dispatchkit/proxy_functions.hpp | 51 ++++++------------- 3 files changed, 24 insertions(+), 56 deletions(-) diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index 9b4548d..d8a4eed 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -257,7 +257,7 @@ namespace chaiscript { public: Dispatch_Function(std::vector t_funcs) - : Proxy_Function_Base(build_type_infos(t_funcs)), + : Proxy_Function_Base(build_type_infos(t_funcs), calculate_arity(t_funcs)), m_funcs(std::move(t_funcs)) { } @@ -280,15 +280,15 @@ namespace chaiscript } - virtual int get_arity() const CHAISCRIPT_OVERRIDE + static int calculate_arity(const std::vector &t_funcs) { - if (m_funcs.empty()) { + if (t_funcs.empty()) { return -1; } - const auto arity = m_funcs.front()->get_arity(); + const auto arity = t_funcs.front()->get_arity(); - for (const auto &func : m_funcs) + for (const auto &func : t_funcs) { if (arity != func->get_arity()) { diff --git a/include/chaiscript/dispatchkit/dynamic_object.hpp b/include/chaiscript/dispatchkit/dynamic_object.hpp index 93ffd26..69c24d5 100644 --- a/include/chaiscript/dispatchkit/dynamic_object.hpp +++ b/include/chaiscript/dispatchkit/dynamic_object.hpp @@ -73,7 +73,7 @@ namespace chaiscript Dynamic_Object_Function( std::string t_type_name, const Proxy_Function &t_func) - : Proxy_Function_Base(t_func->get_param_types()), + : Proxy_Function_Base(t_func->get_param_types(), t_func->get_arity()), m_type_name(std::move(t_type_name)), m_func(t_func), m_doti(user_type()) { assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0) @@ -84,7 +84,7 @@ namespace chaiscript std::string t_type_name, const Proxy_Function &t_func, const Type_Info &t_ti) - : Proxy_Function_Base(build_param_types(t_func->get_param_types(), t_ti)), + : Proxy_Function_Base(build_param_types(t_func->get_param_types(), t_ti), t_func->get_arity()), m_type_name(std::move(t_type_name)), m_func(t_func), m_ti(new Type_Info(t_ti)), m_doti(user_type()) { assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0) @@ -121,12 +121,6 @@ namespace chaiscript return {m_func}; } - - virtual int get_arity() const CHAISCRIPT_OVERRIDE - { - return m_func->get_arity(); - } - virtual std::string annotation() const CHAISCRIPT_OVERRIDE { return m_func->annotation(); @@ -215,7 +209,7 @@ namespace chaiscript Dynamic_Object_Constructor( std::string t_type_name, const Proxy_Function &t_func) - : Proxy_Function_Base(build_type_list(t_func->get_param_types())), + : Proxy_Function_Base(build_type_list(t_func->get_param_types()), t_func->get_arity() - 1), m_type_name(std::move(t_type_name)), m_func(t_func) { assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0) @@ -256,13 +250,6 @@ namespace chaiscript return m_func->call_match(new_vals, t_conversions); } - - virtual int get_arity() const CHAISCRIPT_OVERRIDE - { - // "this" is not considered part of the arity - return m_func->get_arity() - 1; - } - virtual std::string annotation() const CHAISCRIPT_OVERRIDE { return m_func->annotation(); diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index df446ad..0da241e 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -84,13 +84,11 @@ namespace chaiscript //! to the passed in values bool filter(const std::vector &vals, const Type_Conversions &t_conversions) const { - int arity = get_arity(); - - if (arity < 0) + if (m_arity < 0) { return true; - } else if (size_t(arity) == vals.size()) { - if (arity == 0) + } else if (size_t(m_arity) == vals.size()) { + if (m_arity == 0) { return true; } else { @@ -102,7 +100,10 @@ namespace chaiscript } /// \returns the number of arguments the function takes or -1 if it is variadic - virtual int get_arity() const = 0; + int get_arity() const + { + return m_arity; + } virtual std::string annotation() const = 0; @@ -127,8 +128,8 @@ namespace chaiscript protected: virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions &t_conversions) const = 0; - Proxy_Function_Base(std::vector t_types) - : m_types(std::move(t_types)), m_has_arithmetic_param(false) + Proxy_Function_Base(std::vector t_types, int t_arity) + : m_types(std::move(t_types)), m_has_arithmetic_param(false), m_arity(t_arity) { for (size_t i = 1; i < m_types.size(); ++i) { @@ -175,7 +176,7 @@ namespace chaiscript std::vector m_types; bool m_has_arithmetic_param; - + int m_arity; }; } @@ -216,7 +217,7 @@ namespace chaiscript AST_NodePtr t_parsenode = AST_NodePtr(), std::string t_description = "", Proxy_Function t_guard = Proxy_Function()) - : Proxy_Function_Base(build_param_type_list(t_arity)), + : Proxy_Function_Base(build_param_type_list(t_arity), t_arity), m_f(std::move(t_f)), m_arity(t_arity), m_description(std::move(t_description)), m_guard(std::move(t_guard)), m_parsenode(std::move(t_parsenode)) { } @@ -239,10 +240,6 @@ namespace chaiscript && test_guard(vals, t_conversions); } - virtual int get_arity() const CHAISCRIPT_OVERRIDE - { - return m_arity; - } Proxy_Function get_guard() const { @@ -338,8 +335,8 @@ namespace chaiscript public: Bound_Function(const Const_Proxy_Function &t_f, const std::vector &t_args) - : Proxy_Function_Base(build_param_type_info(t_f, t_args)), - m_f(t_f), m_args(t_args), m_arity(t_f->get_arity()<0?-1:static_cast(get_param_types().size())-1) + : Proxy_Function_Base(build_param_type_info(t_f, t_args), (t_f->get_arity()<0?-1:static_cast(build_param_type_info(t_f, t_args).size())-1)), + m_f(t_f), m_args(t_args) { assert(m_f->get_arity() < 0 || m_f->get_arity() == static_cast(m_args.size())); } @@ -395,11 +392,6 @@ namespace chaiscript return args; } - virtual int get_arity() const CHAISCRIPT_OVERRIDE - { - return m_arity; - } - virtual std::string annotation() const CHAISCRIPT_OVERRIDE { return "Bound: " + m_f->annotation(); @@ -444,17 +436,12 @@ namespace chaiscript { public: Proxy_Function_Impl_Base(std::vector t_types) - : Proxy_Function_Base(std::move(t_types)) + : Proxy_Function_Base(std::move(t_types), t_types.size() - 1) { } virtual ~Proxy_Function_Impl_Base() {} - virtual int get_arity() const CHAISCRIPT_OVERRIDE - { - return static_cast(m_types.size()) - 1; - } - virtual std::string annotation() const CHAISCRIPT_OVERRIDE { return ""; @@ -524,8 +511,8 @@ namespace chaiscript { public: Attribute_Access(T Class::* t_attr) - : Proxy_Function_Base(param_types()), - m_attr(t_attr) + : Proxy_Function_Base(param_types(), 1), + m_attr(t_attr) { } @@ -543,12 +530,6 @@ namespace chaiscript } } - - virtual int get_arity() const CHAISCRIPT_OVERRIDE - { - return 1; - } - virtual bool call_match(const std::vector &vals, const Type_Conversions &) const CHAISCRIPT_OVERRIDE { if (vals.size() != 1) From 20c0e6016e99e2a0051ad48ac42cc6cea3af2aba Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sun, 2 Nov 2014 14:08:57 -0700 Subject: [PATCH 52/63] Add type_conversion helper and failing unit test --- include/chaiscript/dispatchkit/type_conversions.hpp | 13 +++++++++++++ src/test_module.cpp | 12 +++++++++++- unittests/user_defined_conversions_2.chai | 1 + 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/include/chaiscript/dispatchkit/type_conversions.hpp b/include/chaiscript/dispatchkit/type_conversions.hpp index 2580fb1..bc6049a 100644 --- a/include/chaiscript/dispatchkit/type_conversions.hpp +++ b/include/chaiscript/dispatchkit/type_conversions.hpp @@ -394,6 +394,19 @@ namespace chaiscript return std::make_shared>(user_type(), user_type(), func); } + template + Type_Conversion type_conversion() + { + static_assert(std::is_convertible::value, "Types are not automatically convertible"); + auto func = [](const Boxed_Value &t_bv) -> Boxed_Value { + // not even attempting to call boxed_cast so that we don't get caught in some call recursion + auto to = To{detail::Cast_Helper::cast(t_bv, nullptr)}; + return chaiscript::Boxed_Value(std::move(to)); + }; + + return std::make_shared>(user_type(), user_type(), func); + } + } diff --git a/src/test_module.cpp b/src/test_module.cpp index 5dac6f4..9029360 100644 --- a/src/test_module.cpp +++ b/src/test_module.cpp @@ -28,7 +28,8 @@ class Type2 { public: Type2(TestBaseType t_bt) - : m_bt(std::move(t_bt)) + : m_bt(std::move(t_bt)), + m_str("Hello World") { } @@ -37,8 +38,14 @@ class Type2 return m_bt.val; } + const char *get_str() const + { + return m_str.c_str(); + } + private: TestBaseType m_bt; + std::string m_str; }; enum TestEnum @@ -158,6 +165,9 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo m->add(chaiscript::type_conversion([](const TestBaseType &t_bt) { return Type2(t_bt); })); m->add(chaiscript::fun(&Type2::get_val), "get_val"); + m->add(chaiscript::fun(&Type2::get_str), "get_str"); + m->add(chaiscript::type_conversion()); + return m; } diff --git a/unittests/user_defined_conversions_2.chai b/unittests/user_defined_conversions_2.chai index 8a349e1..1226ba1 100644 --- a/unittests/user_defined_conversions_2.chai +++ b/unittests/user_defined_conversions_2.chai @@ -7,3 +7,4 @@ auto t := TestBaseType(); // "get_val()" which exists on the Type2 type assert_equal(t.get_val(), 10); +assert_equal(t.get_str().size(), 11); From c876a890306c27c1687ca880dcdc77e3dcfef0fb Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sun, 2 Nov 2014 21:37:01 -0700 Subject: [PATCH 53/63] Fix crash during user_defined_conversions_2 Temporaries created during user conversion operations were being dropped before the result of the conversion was able to be used. This fixes that by temporarily storing the result of the conversion inside the current Function_Push_Pop context. --- .../chaiscript/dispatchkit/boxed_value.hpp | 8 ++++ .../chaiscript/dispatchkit/dispatchkit.hpp | 25 +++++++++++ .../chaiscript/dispatchkit/handle_return.hpp | 9 ++++ .../dispatchkit/type_conversions.hpp | 42 ++++++++++++++++--- .../chaiscript/language/chaiscript_common.hpp | 5 +++ src/test_module.cpp | 1 + unittests/user_defined_conversions_2.chai | 21 +++++++++- 7 files changed, 103 insertions(+), 8 deletions(-) diff --git a/include/chaiscript/dispatchkit/boxed_value.hpp b/include/chaiscript/dispatchkit/boxed_value.hpp index b525281..c73358c 100644 --- a/include/chaiscript/dispatchkit/boxed_value.hpp +++ b/include/chaiscript/dispatchkit/boxed_value.hpp @@ -67,6 +67,7 @@ namespace chaiscript Data &operator=(Data &&rhs) = default; #endif + Type_Info m_type_info; chaiscript::detail::Any m_obj; void *m_data_ptr; @@ -122,6 +123,13 @@ namespace chaiscript return get(std::ref(*t)); } + template + static std::shared_ptr get(const T *t) + { + return get(std::cref(*t)); + } + + template static std::shared_ptr get(std::reference_wrapper obj) { diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index d8a4eed..9d78507 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -915,6 +915,22 @@ namespace chaiscript m_state = t_state; } + void save_function_params(std::initializer_list t_params) + { + Stack_Holder &s = *m_stack_holder; + s.call_params.insert(s.call_params.begin(), std::move(t_params)); + } + + void save_function_params(std::vector &&t_params) + { + Stack_Holder &s = *m_stack_holder; + + for (auto &¶m : t_params) + { + s.call_params.insert(s.call_params.begin(), std::move(param)); + } + } + void save_function_params(const std::vector &t_params) { Stack_Holder &s = *m_stack_holder; @@ -923,7 +939,15 @@ namespace chaiscript void new_function_call() { + Stack_Holder &s = *m_stack_holder; + if (s.call_depth == 0) + { + m_conversions.enable_conversion_saves(true); + } + ++m_stack_holder->call_depth; + + save_function_params(m_conversions.take_saves()); } void pop_function_call() @@ -938,6 +962,7 @@ namespace chaiscript /// \todo Critical: this needs to be smarter, memory can expand quickly /// in tight loops involving function calls s.call_params.clear(); + m_conversions.enable_conversion_saves(false); } } diff --git a/include/chaiscript/dispatchkit/handle_return.hpp b/include/chaiscript/dispatchkit/handle_return.hpp index cc24fdf..8f2ebfe 100644 --- a/include/chaiscript/dispatchkit/handle_return.hpp +++ b/include/chaiscript/dispatchkit/handle_return.hpp @@ -48,6 +48,15 @@ namespace chaiscript } }; + template + struct Handle_Return + { + static Boxed_Value handle(const Ret *p) + { + return Boxed_Value(p); + } + }; + template struct Handle_Return &> { diff --git a/include/chaiscript/dispatchkit/type_conversions.hpp b/include/chaiscript/dispatchkit/type_conversions.hpp index bc6049a..4f1f84c 100644 --- a/include/chaiscript/dispatchkit/type_conversions.hpp +++ b/include/chaiscript/dispatchkit/type_conversions.hpp @@ -214,13 +214,16 @@ namespace chaiscript Type_Conversions() : m_num_types(0), - m_thread_cache(this) + m_thread_cache(this), + m_conversion_saves(this) { } Type_Conversions(const Type_Conversions &t_other) : m_conversions(t_other.get_conversions()), m_num_types(m_conversions.size()), - m_thread_cache(this) + m_thread_cache(this), + m_conversion_saves(this) + { } @@ -273,7 +276,9 @@ namespace chaiscript Boxed_Value boxed_type_conversion(const Boxed_Value &from) const { try { - return get_conversion(user_type(), from.get_type_info())->convert(from); + 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); + return ret; } catch (const std::out_of_range &) { throw exception::bad_boxed_dynamic_cast(from.get_type_info(), typeid(To), "No known conversion"); } catch (const std::bad_cast &) { @@ -285,7 +290,9 @@ namespace chaiscript Boxed_Value boxed_type_down_conversion(const Boxed_Value &to) const { try { - return get_conversion(to.get_type_info(), user_type())->convert_down(to); + 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); + return ret; } catch (const std::out_of_range &) { throw exception::bad_boxed_dynamic_cast(to.get_type_info(), typeid(From), "No known conversion"); } catch (const std::bad_cast &) { @@ -293,6 +300,17 @@ namespace chaiscript } } + void enable_conversion_saves(bool t_val) + { + m_conversion_saves->enabled = t_val; + } + + std::vector take_saves() + { + std::vector ret; + std::swap(ret, m_conversion_saves->saves); + return ret; + } bool has_conversion(const Type_Info &to, const Type_Info &from) const { @@ -334,11 +352,18 @@ namespace chaiscript } + struct Conversion_Saves + { + bool enabled = false; + std::vector saves; + }; + mutable chaiscript::detail::threading::shared_mutex m_mutex; std::set> m_conversions; std::set m_convertableTypes; std::atomic_size_t m_num_types; chaiscript::detail::threading::Thread_Storage> m_thread_cache; + chaiscript::detail::threading::Thread_Storage m_conversion_saves; }; typedef std::shared_ptr Type_Conversion; @@ -400,8 +425,13 @@ namespace chaiscript static_assert(std::is_convertible::value, "Types are not automatically convertible"); auto func = [](const Boxed_Value &t_bv) -> Boxed_Value { // not even attempting to call boxed_cast so that we don't get caught in some call recursion - auto to = To{detail::Cast_Helper::cast(t_bv, nullptr)}; - return chaiscript::Boxed_Value(std::move(to)); + std::cout << " Type conversion to : " << typeid(To).name() << " from " << typeid(From).name() << std::endl; + auto &&from = detail::Cast_Helper::cast(t_bv, nullptr); + std::cout << "Ptr" << static_cast(from) << std::endl; + std::cout << "Ptr" << from << std::endl; + + To to(from); + return chaiscript::Boxed_Value(to); }; return std::make_shared>(user_type(), user_type(), func); diff --git a/include/chaiscript/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index 1339f86..d15c2d9 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -549,6 +549,11 @@ namespace chaiscript m_de.save_function_params(t_params); } + void save_params(std::initializer_list t_params) + { + m_de.save_function_params(std::move(t_params)); + } + private: diff --git a/src/test_module.cpp b/src/test_module.cpp index 9029360..cb95326 100644 --- a/src/test_module.cpp +++ b/src/test_module.cpp @@ -167,6 +167,7 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo m->add(chaiscript::fun(&Type2::get_val), "get_val"); m->add(chaiscript::fun(&Type2::get_str), "get_str"); m->add(chaiscript::type_conversion()); + m->add(chaiscript::constructor(), "Type2"); return m; } diff --git a/unittests/user_defined_conversions_2.chai b/unittests/user_defined_conversions_2.chai index 1226ba1..fdb601c 100644 --- a/unittests/user_defined_conversions_2.chai +++ b/unittests/user_defined_conversions_2.chai @@ -5,6 +5,23 @@ auto t := TestBaseType(); // This uses the TestBaseType to Type2 user type // conversion which was added in the module and then calls // "get_val()" which exists on the Type2 type -assert_equal(t.get_val(), 10); +//assert_equal(t.get_val(), 10); +//print("Made it past test 1"); + +var t2 := Type2(t); +var str = string(get_str(t2)); + +assert_equal("Hello World", str); +print("Made it past test 2"); + +assert_equal(11, size(get_str(t2))); +print("Made it past test 3"); + + +assert_equal(11, t2.get_str().size()); +print("Made it past test 4"); + +assert_equal(11, t.get_str().size()); +print("Made it past test 5"); + -assert_equal(t.get_str().size(), 11); From 79c5f719752392dabf753305f97acddde1c00bc3 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Sun, 2 Nov 2014 21:47:42 -0700 Subject: [PATCH 54/63] Fix compilation on gcc 4.6 --- include/chaiscript/dispatchkit/type_conversions.hpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/include/chaiscript/dispatchkit/type_conversions.hpp b/include/chaiscript/dispatchkit/type_conversions.hpp index 4f1f84c..b238b97 100644 --- a/include/chaiscript/dispatchkit/type_conversions.hpp +++ b/include/chaiscript/dispatchkit/type_conversions.hpp @@ -354,7 +354,11 @@ namespace chaiscript struct Conversion_Saves { - bool enabled = false; + Conversion_Saves() + : enabled(false) + {} + + bool enabled; std::vector saves; }; From 5515d058bb1fd319a04ea3da34c9fe1e21fd8596 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Mon, 3 Nov 2014 07:33:53 -0700 Subject: [PATCH 55/63] Fix some warnings for clang / 64bit windows --- include/chaiscript/dispatchkit/proxy_functions.hpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index 0da241e..cad677c 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -429,14 +429,13 @@ namespace chaiscript private: Const_Proxy_Function m_f; std::vector m_args; - int m_arity; }; class Proxy_Function_Impl_Base : public Proxy_Function_Base { public: Proxy_Function_Impl_Base(std::vector t_types) - : Proxy_Function_Base(std::move(t_types), t_types.size() - 1) + : Proxy_Function_Base(std::move(t_types), static_cast(t_types.size()) - 1) { } @@ -708,7 +707,7 @@ namespace chaiscript if (arity == -1) { numdiffs = plist.size(); - } else if (arity == plist.size()) { + } else if (arity == static_cast(plist.size())) { for (size_t i = 0; i < plist.size(); ++i) { if (!func->get_param_types()[i+1].bare_equal(plist[i].get_type_info())) From 5d5e88197146368842e485ef0e6b69eba82c3cc1 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Mon, 3 Nov 2014 08:24:02 -0700 Subject: [PATCH 56/63] Fix arity of functions A value was being accessed after it was moved. --- include/chaiscript/dispatchkit/proxy_functions.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index cad677c..e07a864 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -434,8 +434,8 @@ namespace chaiscript class Proxy_Function_Impl_Base : public Proxy_Function_Base { public: - Proxy_Function_Impl_Base(std::vector t_types) - : Proxy_Function_Base(std::move(t_types), static_cast(t_types.size()) - 1) + Proxy_Function_Impl_Base(const std::vector &t_types) + : Proxy_Function_Base(t_types, static_cast(t_types.size()) - 1) { } From 4f972bcf67826591423149c006f80d43a026bd15 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Mon, 3 Nov 2014 09:13:30 -0700 Subject: [PATCH 57/63] Refine lifetime of parameters to functions Fixes crash caused when making function calls in a global context, and probably fixes other things. --- include/chaiscript/language/chaiscript_eval.hpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index c095c23..36978ab 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -292,6 +292,7 @@ namespace chaiscript virtual ~Inplace_Fun_Call_AST_Node() {} virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ std::vector params; + chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); if ((this->children.size() > 1) && (this->children[1]->identifier == AST_Node_Type::Arg_List)) { for (const auto &child : this->children[1]->children) { @@ -595,10 +596,10 @@ namespace chaiscript virtual ~Dot_Access_AST_Node() {} virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{ Boxed_Value retval = this->children[0]->eval(t_ss); + chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); if (this->children.size() > 1) { for (size_t i = 2; i < this->children.size(); i+=2) { - chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); std::vector params{retval}; if (this->children[i]->children.size() > 1) { From 3f460fdd20fc30df8eac348886d796f07f46274d Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Mon, 3 Nov 2014 18:34:33 -0700 Subject: [PATCH 58/63] Fix 64bit msvc warning --- include/chaiscript/dispatchkit/proxy_functions.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index e07a864..fba9b4f 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -697,11 +697,11 @@ namespace chaiscript const std::vector &plist, const Type_Conversions &t_conversions) { - std::multimap ordered_funcs; + std::multimap ordered_funcs; for (const auto &func : funcs) { - int numdiffs = 0; + size_t numdiffs = 0; const auto arity = func->get_arity(); if (arity == -1) From 99396ba05cc8784f5ee034507dd28ca93255dac0 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Mon, 3 Nov 2014 21:37:25 -0700 Subject: [PATCH 59/63] Add \r skipping code from @jespada --- .../chaiscript/language/chaiscript_parser.hpp | 25 +++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 29ee4b9..482d653 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -266,16 +266,27 @@ namespace chaiscript return false; } + /// Skips ChaiScript whitespace, which means space and tab, but not cr/lf - /// jespada: Modified SkipWS to skip optionally CR ('\n') - bool SkipWS(const bool skip_cr=false) { + /// jespada: Modified SkipWS to skip optionally CR ('\n') and/or LF+CR ("\r\n") + bool SkipWS(bool skip_cr=false) { bool retval = false; + while (has_more_input()) { - if ( char_in_alphabet(*m_input_pos,detail::white_alphabet) || (skip_cr && (*m_input_pos == '\n'))) { - if(*m_input_pos == '\n') { + auto end_line = (*m_input_pos != 0) && ((*m_input_pos == '\n') || (*m_input_pos == '\r' && *(m_input_pos+1) == '\n')); + + if ( char_in_alphabet(*m_input_pos,detail::white_alphabet) || (skip_cr && end_line)) { + + if(end_line) { m_col = 1; ++m_line; - } else { + + if(*(m_input_pos) == '\r') { + // discards lf + ++m_input_pos; + } + } + else { ++m_col; } ++m_input_pos; @@ -284,14 +295,14 @@ namespace chaiscript } else if (SkipComment()) { retval = true; - } - else { + } else { break; } } return retval; } + /// Reads a floating point value from input, without skipping initial whitespace bool Float_() { if (has_more_input() && char_in_alphabet(*m_input_pos,detail::float_alphabet) ) { From 5daf837037af0ec36d7ebb33d4b3ff1875cda502 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 4 Nov 2014 09:47:32 -0700 Subject: [PATCH 60/63] Increment version number to 5.5.0 --- CMakeLists.txt | 2 +- include/chaiscript/chaiscript_defines.hpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 720cb73..bbf8fa1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -54,7 +54,7 @@ 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 4) +set(CPACK_PACKAGE_VERSION_MINOR 5) set(CPACK_PACKAGE_VERSION_PATCH 0) set(CPACK_PACKAGE_EXECUTABLES "chai;ChaiScript Eval") diff --git a/include/chaiscript/chaiscript_defines.hpp b/include/chaiscript/chaiscript_defines.hpp index 59e302e..d441224 100644 --- a/include/chaiscript/chaiscript_defines.hpp +++ b/include/chaiscript/chaiscript_defines.hpp @@ -45,7 +45,7 @@ namespace chaiscript { static const int version_major = 5; - static const int version_minor = 4; + static const int version_minor = 5; static const int version_patch = 0; } From f4f2391801a6711f6b723d5a06e757afc5280fe0 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Tue, 4 Nov 2014 15:22:09 -0700 Subject: [PATCH 61/63] Add support for clang/gcc MemorySanitizer --- CMakeLists.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index bbf8fa1..22650a1 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,6 +36,12 @@ if(CMAKE_COMPILER_IS_GNUCC OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") set(LINKER_FLAGS "${LINKER_FLAGS} -fsanitize=address") endif() + option(ENABLE_MEMORY_SANITIZER "Enable memory sanitizer testing in gcc/clang" FALSE) + if(ENABLE_MEMORY_SANITIZER) + add_definitions(-fsanitize=memory -g) + set(LINKER_FLAGS "${LINKER_FLAGS} -fsanitize=memory") + endif() + option(ENABLE_UNDEFINED_SANITIZER "Enable undefined behavior sanitizer testing in gcc/clang" FALSE) if(ENABLE_UNDEFINED_SANITIZER) add_definitions(-fsanitize=undefined -g) From fa5966bd044c4f3a06dae28fca841f9c849d729d Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Thu, 6 Nov 2014 15:12:53 -0700 Subject: [PATCH 62/63] Enable optimizations options for LTO and profile --- CMakeLists.txt | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index c8ef4b9..3917f0c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -41,6 +41,27 @@ if(CMAKE_COMPILER_IS_GNUCC OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") add_definitions(-fsanitize=undefined -g) set(LINKER_FLAGS "${LINKER_FLAGS} -fsanitize=undefined") endif() + + option(ENABLE_LTO "Enable Link Time Optimization" FALSE) + + if (ENABLE_LTO) + add_definitions(-flto) + set(LINKER_FLAGS "${LINKER_FLAGS} -flto") + endif() + + option(PROFILE_GENERATE "Generate profile data" FALSE) + if (PROFILE_GENERATE) + add_definitions(-fprofile-generate) + set(LINKER_FLAGS "${LINKER_FLAGS} -fprofile-generate") + endif() + + option(PROFILE_USE "Use profile data" FALSE) + if (PROFILE_USE) + add_definitions(-fprofile-use) + set(LINKER_FLAGS "${LINKER_FLAGS} -fprofile-use") + endif() + + endif() list(APPEND CPACK_SOURCE_IGNORE_FILES "${CMAKE_CURRENT_BINARY_DIR}") From 8a30581eaff6d83b8ace0f495ac0294a6797eb13 Mon Sep 17 00:00:00 2001 From: Jason Turner Date: Mon, 10 Nov 2014 12:45:49 -0700 Subject: [PATCH 63/63] Update release notes for version 5.5.0 --- releasenotes.md | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/releasenotes.md b/releasenotes.md index 5a2d8bf..9942993 100644 --- a/releasenotes.md +++ b/releasenotes.md @@ -1,6 +1,15 @@ Notes: ======= -Current Version: 5.4.0 +Current Version: 5.5.0 + +### Changes since 5.4.0 +* 2x performance increase +* Significant code cleanups +* Throw exception if user attempts to call function on null object +* Allow user defined type conversions +* Fix object lifetime for nested function calls made at the global scope +* Fix returning of boolean values from function calls + ### Changes since 5.3.1 * Decreased compile time and build size