From 0870cb5a3a1ad21573c318acaf476014a998433f Mon Sep 17 00:00:00 2001 From: FellowTraveler Date: Sun, 18 Jun 2023 06:42:51 -0500 Subject: [PATCH] Add C++20 support ChaiScript now successfully builds on my Mac with C++20, and passes 100% of the unit tests. --- CMakeLists.txt | 4 +- .../chaiscript/language/chaiscript_common.hpp | 197 +++++++++--------- unittests/compiled_tests.cpp | 2 +- unittests/static_chaiscript.cpp | 8 +- 4 files changed, 111 insertions(+), 100 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7eef73e3..878749ad 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,7 @@ cmake_minimum_required(VERSION 3.12) cmake_policy(SET CMP0054 NEW) -set(CMAKE_CXX_STANDARD 17) +set(CMAKE_CXX_STANDARD 20) set(CMAKE_CXX_STANDARD_REQUIRED ON) # required since cmake 3.4 at least for libc++ @@ -167,7 +167,7 @@ if(MSVC) else() add_definitions(-Wall -Wextra -Wconversion -Wshadow -Wnon-virtual-dtor -Wold-style-cast -Wcast-align -Wcast-qual -Wunused -Woverloaded-virtual -Wno-noexcept-type -Wpedantic -Werror=return-type) - if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") + if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang") add_definitions(-Weverything -Wno-c++98-compat-pedantic -Wno-c++98-compat -Wno-documentation -Wno-switch-enum -Wno-weak-vtables -Wno-missing-prototypes -Wno-padded -Wno-missing-noreturn -Wno-exit-time-destructors -Wno-documentation-unknown-command -Wno-unused-template -Wno-undef -Wno-double-promotion) else() add_definitions(-Wnoexcept) diff --git a/include/chaiscript/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index f4d51a19..3b020c84 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -26,6 +26,10 @@ namespace chaiscript { struct AST_Node; + struct AST_Node_Trace; + namespace exception { + struct eval_error; + } } // namespace chaiscript namespace chaiscript { @@ -166,11 +170,104 @@ namespace chaiscript { std::shared_ptr filename; }; + /// \brief Struct that doubles as both a parser ast_node and an AST node. + struct AST_Node { + public: + const AST_Node_Type identifier; + const std::string text; + Parse_Location location; + + const std::string &filename() const noexcept { return *location.filename; } + + const File_Position &start() const noexcept { return location.start; } + + const File_Position &end() const noexcept { return location.end; } + + std::string pretty_print() const { + std::ostringstream oss; + + oss << text; + + for (auto &elem : get_children()) { + oss << elem.get().pretty_print() << ' '; + } + + return oss.str(); + } + + virtual std::vector> get_children() const = 0; + virtual Boxed_Value eval(const chaiscript::detail::Dispatch_State &t_e) const = 0; + + /// Prints the contents of an AST node, including its children, recursively + std::string to_string(const std::string &t_prepend = "") const { + std::ostringstream oss; + + oss << t_prepend << "(" << ast_node_type_to_string(this->identifier) << ") " << this->text << " : " << this->location.start.line + << ", " << this->location.start.column << '\n'; + + for (auto &elem : get_children()) { + oss << elem.get().to_string(t_prepend + " "); + } + return oss.str(); + } + + static inline bool get_bool_condition(const Boxed_Value &t_bv, const chaiscript::detail::Dispatch_State &t_ss); + + virtual ~AST_Node() noexcept = default; + AST_Node(AST_Node &&) = default; + AST_Node &operator=(AST_Node &&) = delete; + AST_Node(const AST_Node &) = delete; + AST_Node &operator=(const AST_Node &) = delete; + + protected: + AST_Node(std::string t_ast_node_text, AST_Node_Type t_id, Parse_Location t_loc) + : identifier(t_id) + , text(std::move(t_ast_node_text)) + , location(std::move(t_loc)) { + } + }; + /// \brief Typedef for pointers to AST_Node objects. Used in building of the AST_Node tree using AST_NodePtr = std::unique_ptr; using AST_NodePtr_Const = std::unique_ptr; - struct AST_Node_Trace; + struct AST_Node_Trace { + const AST_Node_Type identifier; + const std::string text; + Parse_Location location; + + const std::string &filename() const noexcept { return *location.filename; } + + const File_Position &start() const noexcept { return location.start; } + + const File_Position &end() const noexcept { return location.end; } + + std::string pretty_print() const { + std::ostringstream oss; + + oss << text; + + for (const auto &elem : children) { + oss << elem.pretty_print() << ' '; + } + + return oss.str(); + } + + std::vector get_children(const AST_Node &node) { + const auto node_children = node.get_children(); + return std::vector(node_children.begin(), node_children.end()); + } + + AST_Node_Trace(const AST_Node &node) + : identifier(node.identifier) + , text(node.text) + , location(node.location) + , children(get_children(node)) { + } + + std::vector children; + }; /// \brief Classes which may be thrown during error cases when ChaiScript is executing. namespace exception { @@ -495,106 +592,14 @@ namespace chaiscript { } // namespace exception - /// \brief Struct that doubles as both a parser ast_node and an AST node. - struct AST_Node { - public: - const AST_Node_Type identifier; - const std::string text; - Parse_Location location; - - const std::string &filename() const noexcept { return *location.filename; } - - const File_Position &start() const noexcept { return location.start; } - - const File_Position &end() const noexcept { return location.end; } - - std::string pretty_print() const { - std::ostringstream oss; - - oss << text; - - for (auto &elem : get_children()) { - oss << elem.get().pretty_print() << ' '; - } - - return oss.str(); - } - - virtual std::vector> get_children() const = 0; - virtual Boxed_Value eval(const chaiscript::detail::Dispatch_State &t_e) const = 0; - - /// Prints the contents of an AST node, including its children, recursively - std::string to_string(const std::string &t_prepend = "") const { - std::ostringstream oss; - - oss << t_prepend << "(" << ast_node_type_to_string(this->identifier) << ") " << this->text << " : " << this->location.start.line - << ", " << this->location.start.column << '\n'; - - for (auto &elem : get_children()) { - oss << elem.get().to_string(t_prepend + " "); - } - return oss.str(); - } - - static bool get_bool_condition(const Boxed_Value &t_bv, const chaiscript::detail::Dispatch_State &t_ss) { + //static + bool AST_Node::get_bool_condition(const Boxed_Value &t_bv, const chaiscript::detail::Dispatch_State &t_ss) { try { return t_ss->boxed_cast(t_bv); } catch (const exception::bad_boxed_cast &) { throw exception::eval_error("Condition not boolean"); } - } - - virtual ~AST_Node() noexcept = default; - AST_Node(AST_Node &&) = default; - AST_Node &operator=(AST_Node &&) = delete; - AST_Node(const AST_Node &) = delete; - AST_Node &operator=(const AST_Node &) = delete; - - protected: - AST_Node(std::string t_ast_node_text, AST_Node_Type t_id, Parse_Location t_loc) - : identifier(t_id) - , text(std::move(t_ast_node_text)) - , location(std::move(t_loc)) { - } - }; - - struct AST_Node_Trace { - const AST_Node_Type identifier; - const std::string text; - Parse_Location location; - - const std::string &filename() const noexcept { return *location.filename; } - - const File_Position &start() const noexcept { return location.start; } - - const File_Position &end() const noexcept { return location.end; } - - std::string pretty_print() const { - std::ostringstream oss; - - oss << text; - - for (const auto &elem : children) { - oss << elem.pretty_print() << ' '; - } - - return oss.str(); - } - - std::vector get_children(const AST_Node &node) { - const auto node_children = node.get_children(); - return std::vector(node_children.begin(), node_children.end()); - } - - AST_Node_Trace(const AST_Node &node) - : identifier(node.identifier) - , text(node.text) - , location(node.location) - , children(get_children(node)) { - } - - std::vector children; - }; + } namespace parser { class ChaiScript_Parser_Base { diff --git a/unittests/compiled_tests.cpp b/unittests/compiled_tests.cpp index f8873df8..1462c203 100644 --- a/unittests/compiled_tests.cpp +++ b/unittests/compiled_tests.cpp @@ -1032,7 +1032,7 @@ TEST_CASE("Use unique_ptr") { chaiscript::ChaiScript_Basic chai(create_chaiscript_stdlib(), create_chaiscript_parser()); chai.add(chaiscript::fun([](int &i) { ++i; }), "inci"); - chai.add(chaiscript::fun([](int i) { ++i; }), "copyi"); + chai.add(chaiscript::fun([]([[maybe_unused]] int i) { ++i; }), "copyi"); chai.add(chaiscript::fun([](int *i) { ++(*i); }), "derefi"); chai.add(chaiscript::fun([](const std::unique_ptr &i) { ++(*i); }), "constrefuniqptri"); chai.add(chaiscript::fun([](std::unique_ptr &i) { ++(*i); }), "refuniqptri"); diff --git a/unittests/static_chaiscript.cpp b/unittests/static_chaiscript.cpp index 7819d9eb..61aa3ac7 100644 --- a/unittests/static_chaiscript.cpp +++ b/unittests/static_chaiscript.cpp @@ -6,8 +6,14 @@ /// ChaiScript as a static is unsupported with thread support enabled /// +#if defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wexit-time-destructors" +#pragma clang diagnostic ignored "-Wglobal-constructors" +#endif + #include -static chaiscript::ChaiScript chai; +static chaiscript::ChaiScript chai{}; int main() {}