diff --git a/include/chaiscript/dispatchkit/bootstrap_stl.hpp b/include/chaiscript/dispatchkit/bootstrap_stl.hpp index 6ac2939c..ac7984cf 100644 --- a/include/chaiscript/dispatchkit/bootstrap_stl.hpp +++ b/include/chaiscript/dispatchkit/bootstrap_stl.hpp @@ -580,8 +580,37 @@ namespace chaiscript::bootstrap::standard_library { m.add(fun([](const StringView *s, const StringView &f, size_t pos) { return s->find_last_not_of(f, pos); }), "find_last_not_of"); m.add(fun([](const StringView *s, const StringView &f, size_t pos) { return s->find_first_not_of(f, pos); }), "find_first_not_of"); - m.add(fun([](const StringView *s, const StringView &f) { return s->starts_with(f); }), "starts_with"); - m.add(fun([](const StringView *s, const StringView &f) { return s->ends_with(f); }), "ends_with"); + #if __cplusplus >= 202002L + m.add(fun([](const StringView *s, const StringView &f) { return s->starts_with(f); }), "starts_with"); + m.add(fun([](const StringView *s, const StringView &f) { return s->ends_with(f); }), "ends_with"); + #else + m.add(fun([](const StringView *s, const StringView &f) -> bool { + using size_type = typename StringView::size_type; + const size_type fsz = f.size(); + if (fsz == 0) { + return true; + } + if (fsz > s->size()) { + return false; + } + return s->compare(size_type{0}, fsz, f) == 0; + }), + "starts_with"); + + m.add(fun([](const StringView *s, const StringView &f) -> bool { + using size_type = typename StringView::size_type; + const size_type fsz = f.size(); + if (fsz == 0) { + return true; + } + const size_type ssz = s->size(); + if (fsz > ssz) { + return false; + } + return s->compare(ssz - fsz, fsz, f) == 0; + }), + "ends_with"); + #endif m.add(fun([](const StringView *s, size_t pos, size_t len) { return s->substr(pos, len); }), "substr"); diff --git a/include/chaiscript/dispatchkit/function_params.hpp b/include/chaiscript/dispatchkit/function_params.hpp index a1e5aacf..bebca5ff 100644 --- a/include/chaiscript/dispatchkit/function_params.hpp +++ b/include/chaiscript/dispatchkit/function_params.hpp @@ -12,6 +12,9 @@ #include "boxed_value.hpp" +// std::span was introduced in >= C++20, so we implement a small +// wrapper around it if it's not available. +#if __cplusplus >= 202002L #include namespace chaiscript { @@ -20,4 +23,70 @@ namespace chaiscript { } // namespace chaiscript +#else + +namespace chaiscript { + class Function_Params { + public: + constexpr Function_Params(const Boxed_Value *const t_begin, const Boxed_Value *const t_end) + : m_begin(t_begin) + , m_end(t_end) { + } + + explicit Function_Params(const Boxed_Value &bv) + : m_begin(&bv) + , m_end(m_begin + 1) { + } + + explicit Function_Params(const std::vector &vec) + : m_begin(vec.empty() ? nullptr : vec.data()) + , m_end(vec.empty() ? nullptr : vec.data() + vec.size()) { + } + + template + constexpr explicit Function_Params(const std::array &a) + : m_begin(a.data()) + , m_end(a.data() + Size) { + } + + [[nodiscard]] constexpr const Boxed_Value &operator[](const std::size_t t_i) const noexcept { return m_begin[t_i]; } + + [[nodiscard]] constexpr const Boxed_Value *begin() const noexcept { return m_begin; } + + [[nodiscard]] constexpr const Boxed_Value &front() const noexcept { return *m_begin; } + + [[nodiscard]] constexpr const Boxed_Value &first() const noexcept { return *m_begin; } + + [[nodiscard]] constexpr Function_Params first(std::size_t t_count) const noexcept { return Function_Params(m_begin, m_begin + t_count); } + + [[nodiscard]] constexpr Function_Params subspan(std::size_t t_offset, std::size_t t_count = std::size_t(-1)) const noexcept { + const auto *begin = m_begin + t_offset; + const auto *end = (t_count == std::size_t(-1)) ? m_end : begin + t_count; + return Function_Params(begin, end); + } + + [[nodiscard]] constexpr const Boxed_Value *end() const noexcept { return m_end; } + + [[nodiscard]] constexpr std::size_t size() const noexcept { return static_cast(m_end - m_begin); } + + [[nodiscard]] std::vector to_vector() const { return std::vector{m_begin, m_end}; } + + [[nodiscard]] constexpr bool empty() const noexcept { return m_begin == m_end; } + + private: + const Boxed_Value *m_begin = nullptr; + const Boxed_Value *m_end = nullptr; + }; + + // Constructor specialization for array of size 0 + template<> + constexpr Function_Params::Function_Params(const std::array & /* a */) + : m_begin(nullptr) + , m_end(nullptr) { + } + +} // namespace chaiscript + +#endif + #endif diff --git a/include/chaiscript/dispatchkit/register_function.hpp b/include/chaiscript/dispatchkit/register_function.hpp index b8c2b00a..78245eaa 100644 --- a/include/chaiscript/dispatchkit/register_function.hpp +++ b/include/chaiscript/dispatchkit/register_function.hpp @@ -12,6 +12,19 @@ #include +/** + * std::type_identity was introduced in >= C++20 so we put + * together a small shim for it if it doesn't exist. + */ +#if __cplusplus < 202002L +namespace std { + template + struct type_identity { using type = T; }; + template + using type_identity_t = typename type_identity::type; +} +#endif + #include "bind_first.hpp" #include "function_signature.hpp" #include "proxy_functions.hpp" diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 635aac3f..a34a3a2b 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -1246,7 +1246,7 @@ namespace chaiscript { const auto &ns_name = this->children[0]->text; auto ns_name_bv = const_var(ns_name); - t_ss->call_function("namespace", m_ns_loc, Function_Params{&ns_name_bv, 1}, t_ss.conversions()); + t_ss->call_function("namespace", m_ns_loc, Function_Params{&ns_name_bv, &ns_name_bv + 1}, t_ss.conversions()); std::vector parts; { @@ -1350,7 +1350,7 @@ namespace chaiscript { }; const auto call_function = [&t_ss](const auto &t_funcs, const Boxed_Value &t_param) { - return dispatch::dispatch(*t_funcs, Function_Params{&t_param, 1}, t_ss.conversions()); + return dispatch::dispatch(*t_funcs, Function_Params{&t_param, &t_param + 1}, t_ss.conversions()); }; const std::string &loop_var_name = this->children[0]->text; @@ -1646,8 +1646,8 @@ namespace chaiscript { return Boxed_Number::do_oper(m_oper, bv); } else { chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); - fpp.save_params(Function_Params{&bv, 1}); - return t_ss->call_function(this->text, m_loc, Function_Params{&bv, 1}, t_ss.conversions()); + fpp.save_params(Function_Params{&bv, &bv + 1}); + return t_ss->call_function(this->text, m_loc, Function_Params{&bv, &bv + 1}, t_ss.conversions()); } } catch (const exception::dispatch_error &e) { throw exception::eval_error("Error with prefix operator evaluation: '" + this->text + "'", e.parameters, e.functions, false, *t_ss); @@ -1755,7 +1755,7 @@ namespace chaiscript { if (dispatch::Param_Types( std::vector>{Arg_List_AST_Node::get_arg_type(*catch_block.children[0], t_ss)}) - .match(Function_Params{&t_except, 1}, t_ss.conversions()) + .match(Function_Params{&t_except, &t_except + 1}, t_ss.conversions()) .first) { t_ss.add_object(name, t_except); diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index 715f6ffe..dad2f6f5 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -1029,7 +1029,7 @@ namespace chaiscript { template struct Char_Parser { string_type &match; - using char_type = string_type::value_type; + using char_type = typename string_type::value_type; bool is_escaped = false; bool is_interpolated = false; bool saw_interpolation_marker = false; @@ -2941,7 +2941,11 @@ namespace chaiscript { /// Parses the given input string, tagging parsed ast_nodes with the given m_filename. AST_NodePtr parse_internal(const std::string &t_input, std::string t_fname) { const auto begin = t_input.empty() ? nullptr : &t_input.front(); + #if __cplusplus >= 202002L const auto end = begin == nullptr ? nullptr : std::next(begin, std::ssize(t_input)); + #else + const auto end = begin == nullptr ? nullptr : std::next(begin, (int)std::size(t_input)); + #endif m_position = Position(begin, end); m_filename = std::make_shared(std::move(t_fname)); diff --git a/include/chaiscript/utility/json.hpp b/include/chaiscript/utility/json.hpp index cb5fdffe..30a4d36e 100644 --- a/include/chaiscript/utility/json.hpp +++ b/include/chaiscript/utility/json.hpp @@ -128,10 +128,10 @@ namespace chaiscript::json { } JSONWrapper(std::nullptr_t) {} - Container::iterator begin() { return object ? object->begin() : typename Container::iterator(); } - Container::iterator end() { return object ? object->end() : typename Container::iterator(); } - [[nodiscard]] Container::const_iterator begin() const { return object ? object->begin() : typename Container::iterator(); } - [[nodiscard]] Container::const_iterator end() const { return object ? object->end() : typename Container::iterator(); } + typename Container::iterator begin() { return object ? object->begin() : typename Container::iterator(); } + typename Container::iterator end() { return object ? object->end() : typename Container::iterator(); } + [[nodiscard]] typename Container::const_iterator begin() const { return object ? object->begin() : typename Container::const_iterator(); } + [[nodiscard]] typename Container::const_iterator end() const { return object ? object->end() : typename Container::const_iterator(); } }; template @@ -144,10 +144,10 @@ namespace chaiscript::json { } JSONConstWrapper(std::nullptr_t) {} - [[nodiscard]] Container::const_iterator begin() const noexcept { + [[nodiscard]] typename Container::const_iterator begin() const noexcept { return object ? object->begin() : typename Container::const_iterator(); } - [[nodiscard]] Container::const_iterator end() const noexcept { return object ? object->end() : typename Container::const_iterator(); } + [[nodiscard]] typename Container::const_iterator end() const noexcept { return object ? object->end() : typename Container::const_iterator(); } }; JSON() = default; diff --git a/include/chaiscript/utility/static_string.hpp b/include/chaiscript/utility/static_string.hpp index 39ceb5f5..c6b4099c 100644 --- a/include/chaiscript/utility/static_string.hpp +++ b/include/chaiscript/utility/static_string.hpp @@ -33,7 +33,7 @@ namespace chaiscript::utility { return std::string_view(data, m_size) == other; } - constexpr bool operator==(const std::string &t_str) const noexcept { return std::equal(begin(), end(), std::cbegin(t_str), std::cend(t_str)); } + constexpr bool operator==(const std::string &t_str) const noexcept { return std::string_view(data, m_size) == std::string_view(t_str); } const size_t m_size; const char *data = nullptr;