diff --git a/include/chaiscript/chaiscript_defines.hpp b/include/chaiscript/chaiscript_defines.hpp index 9754913f..6c8ee78d 100644 --- a/include/chaiscript/chaiscript_defines.hpp +++ b/include/chaiscript/chaiscript_defines.hpp @@ -105,47 +105,47 @@ namespace chaiscript { } struct Build_Info { - constexpr static int version_major() noexcept + [[nodiscard]] constexpr static int version_major() noexcept { return chaiscript::version_major; } - constexpr static int version_minor() noexcept + [[nodiscard]] constexpr static int version_minor() noexcept { return chaiscript::version_minor; } - constexpr static int version_patch() noexcept + [[nodiscard]] constexpr static int version_patch() noexcept { return chaiscript::version_patch; } - static std::string version() + [[nodiscard]] static std::string version() { return std::to_string(version_major()) + '.' + std::to_string(version_minor()) + '.' + std::to_string(version_patch()); } - static std::string compiler_id() + [[nodiscard]] static std::string compiler_id() { return compiler_name() + '-' + compiler_version(); } - static std::string build_id() + [[nodiscard]] static std::string build_id() { return compiler_id() + (debug_build()?"-Debug":"-Release"); } - static std::string compiler_version() + [[nodiscard]] static std::string compiler_version() { return chaiscript::compiler_version; } - static std::string compiler_name() + [[nodiscard]] static std::string compiler_name() { return chaiscript::compiler_name; } - constexpr static bool debug_build() noexcept + [[nodiscard]] constexpr static bool debug_build() noexcept { return chaiscript::debug_build; } @@ -153,7 +153,8 @@ namespace chaiscript { template - constexpr auto parse_num(const std::string_view &t_str) noexcept -> typename std::enable_if::value, T>::type + [[nodiscard]] constexpr auto parse_num(const std::string_view &t_str) noexcept + -> typename std::enable_if::value, T>::type { T t = 0; for (const auto c : t_str) { @@ -168,7 +169,8 @@ namespace chaiscript { template - auto parse_num(const std::string_view &t_str) noexcept -> typename std::enable_if::value, T>::type + [[nodiscard]] auto parse_num(const std::string_view &t_str) noexcept + -> typename std::enable_if::value, T>::type { T t = 0; T base = 0; @@ -211,11 +213,11 @@ namespace chaiscript { } struct str_less { - bool operator()(const std::string &t_lhs, const std::string &t_rhs) const noexcept { + [[nodiscard]] bool operator()(const std::string &t_lhs, const std::string &t_rhs) const noexcept { return t_lhs < t_rhs; } template - constexpr bool operator()(const LHS &t_lhs, const RHS &t_rhs) const noexcept { + [[nodiscard]] constexpr bool operator()(const LHS &t_lhs, const RHS &t_rhs) const noexcept { return std::lexicographical_compare(t_lhs.begin(), t_lhs.end(), t_rhs.begin(), t_rhs.end()); } struct is_transparent{}; @@ -229,6 +231,37 @@ namespace chaiscript { External_Scripts }; + template + struct is_nothrow_forward_constructible + : std::bool_constant()})> + { + }; + + template< class From, class To > + inline constexpr bool is_nothrow_forward_constructible_v + = is_nothrow_forward_constructible::value; + + template + [[nodiscard]] constexpr auto make_container(T && ... t) + { + Container c; + c.reserve(sizeof...(t)); + (c.push_back(std::forward(t)), ...); + return c; + } + + + template + [[nodiscard]] auto make_vector(T && ... t) + { + using container_type = + std::vector...>>; + + return make_container(std::forward(t)...); + } + + + static inline std::vector default_options() { #ifdef CHAISCRIPT_NO_DYNLOAD diff --git a/include/chaiscript/chaiscript_stdlib.hpp b/include/chaiscript/chaiscript_stdlib.hpp index ed56b234..2407fcf0 100644 --- a/include/chaiscript/chaiscript_stdlib.hpp +++ b/include/chaiscript/chaiscript_stdlib.hpp @@ -42,7 +42,7 @@ namespace chaiscript { public: - static ModulePtr library() + [[nodiscard]] static ModulePtr library() { auto lib = std::make_shared(); bootstrap::Bootstrap::bootstrap(*lib); diff --git a/include/chaiscript/dispatchkit/any.hpp b/include/chaiscript/dispatchkit/any.hpp index d13b653f..a9e31594 100644 --- a/include/chaiscript/dispatchkit/any.hpp +++ b/include/chaiscript/dispatchkit/any.hpp @@ -83,8 +83,8 @@ namespace chaiscript { public: // construct/copy/destruct constexpr Any() noexcept = default; - Any(Any &&) = default; - Any &operator=(Any &&t_any) = default; + Any(Any &&) noexcept = default; + Any &operator=(Any &&t_any) noexcept = default; Any(const Any &t_any) : m_data(t_any.empty() ? nullptr : t_any.m_data->clone()) @@ -93,7 +93,7 @@ namespace chaiscript { template>>> - explicit Any(ValueType &&t_value) + explicit Any(ValueType &&t_value) noexcept(is_nothrow_forward_constructible_v>) : m_data(std::make_unique>>(std::forward(t_value))) { } @@ -128,7 +128,7 @@ namespace chaiscript { // queries bool empty() const noexcept { - return !bool(m_data); + return !static_cast(m_data); } const std::type_info & type() const noexcept diff --git a/include/chaiscript/dispatchkit/bootstrap.hpp b/include/chaiscript/dispatchkit/bootstrap.hpp index 67116da6..9a94d104 100644 --- a/include/chaiscript/dispatchkit/bootstrap.hpp +++ b/include/chaiscript/dispatchkit/bootstrap.hpp @@ -241,7 +241,7 @@ 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 - static Boxed_Value bind_function(const std::vector ¶ms) + static Boxed_Value bind_function(const Function_Params ¶ms) { if (params.empty()) { throw exception::arity_error(0, 1); diff --git a/include/chaiscript/dispatchkit/dispatchkit.hpp b/include/chaiscript/dispatchkit/dispatchkit.hpp index f8217ea4..4f338cee 100644 --- a/include/chaiscript/dispatchkit/dispatchkit.hpp +++ b/include/chaiscript/dispatchkit/dispatchkit.hpp @@ -313,14 +313,14 @@ namespace chaiscript return arity; } - bool call_match(const std::vector &vals, const Type_Conversions_State &t_conversions) const noexcept override + bool call_match(const Function_Params &vals, const Type_Conversions_State &t_conversions) const noexcept override { return std::any_of(std::begin(m_funcs), std::end(m_funcs), [&vals, &t_conversions](const Proxy_Function &f){ return f->call_match(vals, t_conversions); }); } protected: - Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override + Boxed_Value do_call(const Function_Params ¶ms, const Type_Conversions_State &t_conversions) const override { return dispatch::dispatch(m_funcs, params, t_conversions); } @@ -935,7 +935,7 @@ namespace chaiscript return m_conversions; } - static bool is_attribute_call(const std::vector &t_funs, const std::vector &t_params, + static bool is_attribute_call(const std::vector &t_funs, const Function_Params &t_params, bool t_has_params, const Type_Conversions_State &t_conversions) noexcept { if (!t_has_params || t_params.empty()) { @@ -956,7 +956,7 @@ namespace chaiscript #pragma warning(push) #pragma warning(disable : 4715) #endif - Boxed_Value call_member(const std::string &t_name, std::atomic_uint_fast32_t &t_loc, const std::vector ¶ms, bool t_has_params, + Boxed_Value call_member(const std::string &t_name, std::atomic_uint_fast32_t &t_loc, const Function_Params ¶ms, bool t_has_params, const Type_Conversions_State &t_conversions) { uint_fast32_t loc = t_loc; @@ -964,9 +964,9 @@ namespace chaiscript if (funs.first != loc) { t_loc = uint_fast32_t(funs.first); } const auto do_attribute_call = - [this](int l_num_params, const std::vector &l_params, const std::vector &l_funs, const Type_Conversions_State &l_conversions)->Boxed_Value + [this](int l_num_params, Function_Params l_params, const std::vector &l_funs, const Type_Conversions_State &l_conversions)->Boxed_Value { - std::vector attr_params{l_params.begin(), l_params.begin() + l_num_params}; + Function_Params attr_params(l_params.begin(), l_params.begin() + l_num_params); Boxed_Value bv = dispatch::dispatch(l_funs, attr_params, l_conversions); if (l_num_params < int(l_params.size()) || bv.get_type_info().bare_equal(user_type())) { struct This_Foist { @@ -1049,14 +1049,15 @@ namespace chaiscript if (!functions.empty()) { try { if (is_no_param) { - auto tmp_params(params); + auto tmp_params = params.to_vector(); tmp_params.insert(tmp_params.begin() + 1, var(t_name)); - return do_attribute_call(2, tmp_params, functions, t_conversions); + return do_attribute_call(2, Function_Params(tmp_params), functions, t_conversions); } else { - return dispatch::dispatch(functions, {params[0], var(t_name), var(std::vector(params.begin()+1, params.end()))}, t_conversions); + std::array p{params[0], var(t_name), var(std::vector(params.begin()+1, params.end()))}; + return dispatch::dispatch(functions, Function_Params{p}, t_conversions); } } catch (const dispatch::option_explicit_set &e) { - throw chaiscript::exception::dispatch_error(params, std::vector(funs.second->begin(), funs.second->end()), + throw chaiscript::exception::dispatch_error(params, std::vector(funs.second->begin(), funs.second->end()), e.what()); } } @@ -1076,7 +1077,7 @@ namespace chaiscript - Boxed_Value call_function(const std::string_view &t_name, std::atomic_uint_fast32_t &t_loc, const std::vector ¶ms, + Boxed_Value call_function(const std::string_view &t_name, std::atomic_uint_fast32_t &t_loc, Function_Params params, const Type_Conversions_State &t_conversions) const { uint_fast32_t loc = t_loc; @@ -1132,7 +1133,7 @@ namespace chaiscript /// Returns true if a call can be made that consists of the first parameter /// (the function) with the remaining parameters as its arguments. - Boxed_Value call_exists(const std::vector ¶ms) const + Boxed_Value call_exists(const Function_Params ¶ms) const { if (params.empty()) { @@ -1142,7 +1143,7 @@ namespace chaiscript const auto &f = this->boxed_cast(params[0]); const Type_Conversions_State convs(m_conversions, m_conversions.conversion_saves()); - return const_var(f->call_match(std::vector(params.begin() + 1, params.end()), convs)); + return const_var(f->call_match(Function_Params(params.begin() + 1, params.end()), convs)); } /// Dump all system info to stdout @@ -1203,11 +1204,6 @@ namespace chaiscript m_state = t_state; } - static void save_function_params(Stack_Holder &t_s, std::initializer_list t_params) - { - t_s.call_params.back().insert(t_s.call_params.back().begin(), t_params); - } - static void save_function_params(Stack_Holder &t_s, std::vector &&t_params) { for (auto &¶m : t_params) @@ -1216,22 +1212,17 @@ namespace chaiscript } } - static void save_function_params(Stack_Holder &t_s, const std::vector &t_params) + static void save_function_params(Stack_Holder &t_s, const Function_Params &t_params) { t_s.call_params.back().insert(t_s.call_params.back().begin(), t_params.begin(), t_params.end()); } - void save_function_params(std::initializer_list t_params) - { - save_function_params(*m_stack_holder, t_params); - } - void save_function_params(std::vector &&t_params) { save_function_params(*m_stack_holder, std::move(t_params)); } - void save_function_params(const std::vector &t_params) + void save_function_params(const Function_Params &t_params) { save_function_params(*m_stack_holder, t_params); } diff --git a/include/chaiscript/dispatchkit/dynamic_object_detail.hpp b/include/chaiscript/dispatchkit/dynamic_object_detail.hpp index eacfb51a..7c0364d8 100644 --- a/include/chaiscript/dispatchkit/dynamic_object_detail.hpp +++ b/include/chaiscript/dispatchkit/dynamic_object_detail.hpp @@ -94,7 +94,7 @@ namespace chaiscript bool is_attribute_function() const noexcept override { return m_is_attribute; } - bool call_match(const std::vector &vals, const Type_Conversions_State &t_conversions) const noexcept override + bool call_match(const Function_Params &vals, const Type_Conversions_State &t_conversions) const noexcept override { if (dynamic_object_typename_match(vals, m_type_name, m_ti, t_conversions)) { @@ -110,7 +110,7 @@ namespace chaiscript } protected: - Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override + Boxed_Value do_call(const Function_Params ¶ms, const Type_Conversions_State &t_conversions) const override { if (dynamic_object_typename_match(params, m_type_name, m_ti, t_conversions)) { @@ -159,7 +159,7 @@ namespace chaiscript } - bool dynamic_object_typename_match(const std::vector &bvs, const std::string &name, + bool dynamic_object_typename_match(const Function_Params &bvs, const std::string &name, const std::unique_ptr &ti, const Type_Conversions_State &t_conversions) const noexcept { if (!bvs.empty()) @@ -228,22 +228,22 @@ namespace chaiscript return (dc != nullptr) && dc->m_type_name == m_type_name && (*dc->m_func) == (*m_func); } - bool call_match(const std::vector &vals, const Type_Conversions_State &t_conversions) const override + bool call_match(const Function_Params &vals, const Type_Conversions_State &t_conversions) const override { 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); + return m_func->call_match(Function_Params{new_vals}, t_conversions); } protected: - Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override + Boxed_Value do_call(const Function_Params ¶ms, const Type_Conversions_State &t_conversions) const override { auto bv = Boxed_Value(Dynamic_Object(m_type_name), true); std::vector new_params{bv}; new_params.insert(new_params.end(), params.begin(), params.end()); - (*m_func)(new_params, t_conversions); + (*m_func)(Function_Params{new_params}, t_conversions); return bv; } diff --git a/include/chaiscript/dispatchkit/function_call_detail.hpp b/include/chaiscript/dispatchkit/function_call_detail.hpp index 7d8b3d5e..5cd1932e 100644 --- a/include/chaiscript/dispatchkit/function_call_detail.hpp +++ b/include/chaiscript/dispatchkit/function_call_detail.hpp @@ -35,7 +35,7 @@ namespace chaiscript struct Function_Caller_Ret { static Ret call(const std::vector &t_funcs, - const std::vector ¶ms, const Type_Conversions_State *t_conversions) + const Function_Params ¶ms, const Type_Conversions_State *t_conversions) { if (t_conversions != nullptr) { return boxed_cast(dispatch::dispatch(t_funcs, params, *t_conversions), t_conversions); @@ -54,7 +54,7 @@ namespace chaiscript struct Function_Caller_Ret { static Ret call(const std::vector &t_funcs, - const std::vector ¶ms, const Type_Conversions_State *t_conversions) + const Function_Params ¶ms, const Type_Conversions_State *t_conversions) { if (t_conversions != nullptr) { return Boxed_Number(dispatch::dispatch(t_funcs, params, *t_conversions)).get_as(); @@ -74,7 +74,7 @@ namespace chaiscript struct Function_Caller_Ret { static void call(const std::vector &t_funcs, - const std::vector ¶ms, const Type_Conversions_State *t_conversions) + const Function_Params ¶ms, const Type_Conversions_State *t_conversions) { if (t_conversions != nullptr) { dispatch::dispatch(t_funcs, params, *t_conversions); @@ -101,16 +101,14 @@ namespace chaiscript template Ret operator()(P&& ... param) { + std::array params{box

(std::forward

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

(std::forward

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

(std::forward

(param))... - }, nullptr + return Function_Caller_Ret::value && !std::is_same::value>::call(m_funcs, Function_Params{params}, nullptr ); } diff --git a/include/chaiscript/dispatchkit/function_params.hpp b/include/chaiscript/dispatchkit/function_params.hpp new file mode 100644 index 00000000..090f7004 --- /dev/null +++ b/include/chaiscript/dispatchkit/function_params.hpp @@ -0,0 +1,81 @@ +// This file is distributed under the BSD License. +// See "license.txt" for details. +// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) +// Copyright 2009-2017, Jason Turner (jason@emptycrate.com) +// http://www.chaiscript.com + +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + + +#ifndef CHAISCRIPT_FUNCTION_PARAMS_HPP +#define CHAISCRIPT_FUNCTION_PARAMS_HPP + + +#include "boxed_value.hpp" + +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.front()), m_end(&vec.front() + vec.size()) + { + } + + template + constexpr explicit Function_Params(const std::array &a) + : m_begin(std::begin(a)), m_end(std::end(a)) + { + } + + [[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 *end() const noexcept { + return m_end; + } + + [[nodiscard]] constexpr std::size_t size() const noexcept { + return m_end - m_begin; + } + + 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; + + }; + +} + + +#endif + diff --git a/include/chaiscript/dispatchkit/proxy_functions.hpp b/include/chaiscript/dispatchkit/proxy_functions.hpp index f1797417..0f97edbf 100644 --- a/include/chaiscript/dispatchkit/proxy_functions.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions.hpp @@ -27,6 +27,7 @@ #include "proxy_functions_detail.hpp" #include "type_info.hpp" #include "dynamic_object.hpp" +#include "function_params.hpp" namespace chaiscript { class Type_Conversions; @@ -91,8 +92,9 @@ namespace chaiscript return m_types == t_rhs.m_types; } - std::vector convert(std::vector vals, const Type_Conversions_State &t_conversions) const + std::vector convert(Function_Params t_params, const Type_Conversions_State &t_conversions) const { + auto vals = t_params.to_vector(); constexpr auto dynamic_object_type_info = user_type(); for (size_t i = 0; i < vals.size(); ++i) { @@ -131,7 +133,7 @@ namespace chaiscript // first result: is a match // second result: needs conversions - std::pair match(const std::vector &vals, const Type_Conversions_State &t_conversions) const noexcept + std::pair match(const Function_Params &vals, const Type_Conversions_State &t_conversions) const noexcept { constexpr auto dynamic_object_type_info = user_type(); bool needs_conversion = false; @@ -154,7 +156,7 @@ namespace chaiscript } } catch (const std::bad_cast &) { return std::make_pair(false, false); - } + } } else { const auto &ti = m_types[i].second; if (!ti.is_undef()) @@ -214,7 +216,7 @@ namespace chaiscript public: virtual ~Proxy_Function_Base() = default; - Boxed_Value operator()(const std::vector ¶ms, const chaiscript::Type_Conversions_State &t_conversions) const + Boxed_Value operator()(const Function_Params ¶ms, const chaiscript::Type_Conversions_State &t_conversions) const { if (m_arity < 0 || size_t(m_arity) == params.size()) { return do_call(params, t_conversions); @@ -226,11 +228,11 @@ 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 contains exactly 1 Type_Info object: the return type - /// \returns the types of all parameters. + /// \returns the types of all parameters. const std::vector &get_param_types() const noexcept { return m_types; } virtual bool operator==(const Proxy_Function_Base &) const noexcept = 0; - virtual bool call_match(const std::vector &vals, const Type_Conversions_State &t_conversions) const = 0; + virtual bool call_match(const Function_Params &vals, const Type_Conversions_State &t_conversions) const = 0; virtual bool is_attribute_function() const noexcept { return false; } @@ -246,7 +248,7 @@ namespace chaiscript //! Return true if the function is a possible match //! to the passed in values - bool filter(const std::vector &vals, const Type_Conversions_State &t_conversions) const noexcept + bool filter(const Function_Params &vals, const Type_Conversions_State &t_conversions) const noexcept { assert(m_arity == -1 || (m_arity > 0 && static_cast(vals.size()) == m_arity)); @@ -272,13 +274,13 @@ namespace chaiscript constexpr auto boxed_number_ti = user_type(); constexpr auto function_ti = user_type>(); - if (ti.is_undef() + if (ti.is_undef() || ti.bare_equal(boxed_value_ti) || (!bv.get_type_info().is_undef() && ( (ti.bare_equal(boxed_number_ti) && bv.get_type_info().is_arithmetic()) || ti.bare_equal(bv.get_type_info()) || bv.get_type_info().bare_equal(function_ti) - || t_conversions->converts(ti, bv.get_type_info()) + || t_conversions->converts(ti, bv.get_type_info()) ) ) ) @@ -296,7 +298,7 @@ namespace chaiscript } protected: - virtual Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const = 0; + virtual Boxed_Value do_call(const Function_Params ¶ms, const Type_Conversions_State &t_conversions) const = 0; Proxy_Function_Base(std::vector t_types, int t_arity) : m_types(std::move(t_types)), m_arity(t_arity), m_has_arithmetic_param(false) @@ -313,7 +315,7 @@ namespace chaiscript } - static bool compare_types(const std::vector &tis, const std::vector &bvs, + static bool compare_types(const std::vector &tis, const Function_Params &bvs, const Type_Conversions_State &t_conversions) noexcept { if (tis.size() - 1 != bvs.size()) @@ -367,10 +369,8 @@ namespace chaiscript virtual Param_Types get_dynamic_param_types() const = 0; }; - /** - * A Proxy_Function implementation that is not type safe, the called function - * is expecting a vector that it works with how it chooses. - */ + /// A Proxy_Function implementation that is not type safe, the called function + /// is expecting a vector that it works with how it chooses. class Dynamic_Proxy_Function : public Proxy_Function_Base, public Dynamic_Function_Interface { public: @@ -398,7 +398,7 @@ namespace chaiscript && this->m_param_types == prhs->m_param_types); } - bool call_match(const std::vector &vals, const Type_Conversions_State &t_conversions) const override + bool call_match(const Function_Params &vals, const Type_Conversions_State &t_conversions) const override { return call_match_internal(vals, t_conversions).first; } @@ -431,7 +431,7 @@ namespace chaiscript } protected: - bool test_guard(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const + bool test_guard(const Function_Params ¶ms, const Type_Conversions_State &t_conversions) const { if (m_guard) { @@ -449,7 +449,7 @@ namespace chaiscript // first result: is a match // second result: needs conversions - std::pair call_match_internal(const std::vector &vals, const Type_Conversions_State &t_conversions) const + std::pair call_match_internal(const Function_Params &vals, const Type_Conversions_State &t_conversions) const { const auto comparison_result = [&](){ if (m_arity < 0) { @@ -462,7 +462,7 @@ namespace chaiscript }(); return std::make_pair( - comparison_result.first && test_guard(vals, t_conversions), + comparison_result.first && test_guard(vals, t_conversions), comparison_result.second ); } @@ -500,7 +500,7 @@ namespace chaiscript { public: Dynamic_Proxy_Function_Impl( - Callable t_f, + Callable t_f, int t_arity=-1, std::shared_ptr t_parsenode = AST_NodePtr(), Param_Types t_param_types = Param_Types(), @@ -517,13 +517,13 @@ namespace chaiscript protected: - Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override + Boxed_Value do_call(const Function_Params ¶ms, const Type_Conversions_State &t_conversions) const override { - const auto match_results = call_match_internal(params, t_conversions); - if (match_results.first) + const auto [is_a_match, needs_conversions] = call_match_internal(params, t_conversions); + if (is_a_match) { - if (match_results.second) { - return m_f(m_param_types.convert(params, t_conversions)); + if (needs_conversions) { + return m_f(Function_Params{m_param_types.convert(params, t_conversions)}); } else { return m_f(params); } @@ -556,7 +556,7 @@ namespace chaiscript class Bound_Function final : public Proxy_Function_Base { public: - Bound_Function(const Const_Proxy_Function &t_f, + Bound_Function(const Const_Proxy_Function &t_f, const std::vector &t_args) : 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) @@ -570,9 +570,9 @@ namespace chaiscript } - bool call_match(const std::vector &vals, const Type_Conversions_State &t_conversions) const override + bool call_match(const Function_Params &vals, const Type_Conversions_State &t_conversions) const override { - return m_f->call_match(build_param_list(vals), t_conversions); + return m_f->call_match(Function_Params(build_param_list(vals)), t_conversions); } std::vector get_contained_functions() const override @@ -581,7 +581,7 @@ namespace chaiscript } - std::vector build_param_list(const std::vector ¶ms) const + std::vector build_param_list(const Function_Params ¶ms) const { auto parg = params.begin(); auto barg = m_args.begin(); @@ -590,7 +590,7 @@ namespace chaiscript while (!(parg == params.end() && barg == m_args.end())) { - while (barg != m_args.end() + while (barg != m_args.end() && !(barg->get_type_info() == chaiscript::detail::Get_Type_Info::get())) { args.push_back(*barg); @@ -603,18 +603,18 @@ namespace chaiscript ++parg; } - if (barg != m_args.end() + if (barg != m_args.end() && barg->get_type_info() == chaiscript::detail::Get_Type_Info::get()) { ++barg; - } + } } return args; } protected: - static std::vector build_param_type_info(const Const_Proxy_Function &t_f, + static std::vector build_param_type_info(const Const_Proxy_Function &t_f, const std::vector &t_args) { assert(t_f->get_arity() < 0 || t_f->get_arity() == static_cast(t_args.size())); @@ -638,9 +638,9 @@ namespace chaiscript return retval; } - Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override + Boxed_Value do_call(const Function_Params ¶ms, const Type_Conversions_State &t_conversions) const override { - return (*m_f)(build_param_list(params), t_conversions); + return (*m_f)(Function_Params{build_param_list(params)}, t_conversions); } private: @@ -656,13 +656,13 @@ namespace chaiscript { } - bool call_match(const std::vector &vals, const Type_Conversions_State &t_conversions) const noexcept override + bool call_match(const Function_Params &vals, const Type_Conversions_State &t_conversions) const noexcept override { - return static_cast(vals.size()) == get_arity() + return static_cast(vals.size()) == get_arity() && (compare_types(m_types, vals, t_conversions) && compare_types_with_cast(vals, t_conversions)); } - virtual bool compare_types_with_cast(const std::vector &vals, const Type_Conversions_State &t_conversions) const noexcept = 0; + virtual bool compare_types_with_cast(const Function_Params &vals, const Type_Conversions_State &t_conversions) const noexcept = 0; }; @@ -678,7 +678,7 @@ namespace chaiscript { } - bool compare_types_with_cast(const std::vector &vals, const Type_Conversions_State &t_conversions) const noexcept override + bool compare_types_with_cast(const Function_Params &vals, const Type_Conversions_State &t_conversions) const noexcept override { return detail::compare_types_cast(static_cast(nullptr), vals, t_conversions); } @@ -690,7 +690,7 @@ namespace chaiscript protected: - Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override + Boxed_Value do_call(const Function_Params ¶ms, const Type_Conversions_State &t_conversions) const override { return detail::call_func(static_cast(nullptr), m_f, params, t_conversions); } @@ -722,7 +722,7 @@ namespace chaiscript assert(!m_shared_ptr_holder || m_shared_ptr_holder.get() == &m_f.get()); } - bool compare_types_with_cast(const std::vector &vals, const Type_Conversions_State &t_conversions) const noexcept override + bool compare_types_with_cast(const Function_Params &vals, const Type_Conversions_State &t_conversions) const noexcept override { return detail::compare_types_cast(static_cast(nullptr), vals, t_conversions); } @@ -742,7 +742,7 @@ namespace chaiscript } protected: - Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override + Boxed_Value do_call(const Function_Params ¶ms, const Type_Conversions_State &t_conversions) const override { return detail::call_func(static_cast(nullptr), m_f.get(), params, t_conversions); } @@ -765,11 +765,11 @@ namespace chaiscript { } - bool is_attribute_function() const noexcept override { return true; } + bool is_attribute_function() const noexcept override { return true; } bool operator==(const Proxy_Function_Base &t_func) const noexcept override { - const Attribute_Access * aa + const Attribute_Access * aa = dynamic_cast *>(&t_func); if (aa) { @@ -779,7 +779,7 @@ namespace chaiscript } } - bool call_match(const std::vector &vals, const Type_Conversions_State &) const noexcept override + bool call_match(const Function_Params &vals, const Type_Conversions_State &) const noexcept override { if (vals.size() != 1) { @@ -790,7 +790,7 @@ namespace chaiscript } protected: - Boxed_Value do_call(const std::vector ¶ms, const Type_Conversions_State &t_conversions) const override + Boxed_Value do_call(const Function_Params ¶ms, const Type_Conversions_State &t_conversions) const override { const Boxed_Value &bv = params[0]; if (bv.is_const()) @@ -839,22 +839,22 @@ namespace chaiscript { /// \brief Exception thrown in the case that a method dispatch fails /// because no matching function was found - /// + /// /// May be thrown due to an arity_error, a guard_error or a bad_boxed_cast /// exception class dispatch_error : public std::runtime_error { public: - dispatch_error(std::vector t_parameters, + dispatch_error(const Function_Params &t_parameters, std::vector t_functions) - : std::runtime_error("Error with function dispatch"), parameters(std::move(t_parameters)), functions(std::move(t_functions)) + : std::runtime_error("Error with function dispatch"), parameters(t_parameters.to_vector()), functions(std::move(t_functions)) { } - dispatch_error(std::vector t_parameters, + dispatch_error(const Function_Params &t_parameters, std::vector t_functions, const std::string &t_desc) - : std::runtime_error(t_desc), parameters(std::move(t_parameters)), functions(std::move(t_functions)) + : std::runtime_error(t_desc), parameters(t_parameters.to_vector()), functions(std::move(t_functions)) { } @@ -865,14 +865,14 @@ namespace chaiscript std::vector parameters; std::vector functions; }; - } + } namespace dispatch { - namespace detail + namespace detail { template - bool types_match_except_for_arithmetic(const FuncType &t_func, const std::vector &plist, + bool types_match_except_for_arithmetic(const FuncType &t_func, const Function_Params &plist, const Type_Conversions_State &t_conversions) noexcept { const std::vector &types = t_func->get_param_types(); @@ -891,7 +891,7 @@ namespace chaiscript } template - Boxed_Value dispatch_with_conversions(InItr begin, const InItr &end, const std::vector &plist, + Boxed_Value dispatch_with_conversions(InItr begin, const InItr &end, const Function_Params &plist, const Type_Conversions_State &t_conversions, const Funcs &t_funcs) { InItr matching_func(end); @@ -947,7 +947,7 @@ namespace chaiscript ); try { - return (*(matching_func->second))(newplist, t_conversions); + return (*(matching_func->second))(Function_Params{newplist}, t_conversions); } catch (const exception::bad_boxed_cast &) { //parameter failed to cast } catch (const exception::arity_error &) { @@ -966,7 +966,7 @@ namespace chaiscript /// 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_State &t_conversions) + const Function_Params &plist, const Type_Conversions_State &t_conversions) { std::vector> ordered_funcs; ordered_funcs.reserve(funcs.size()); diff --git a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp index ed71663f..3799363f 100644 --- a/include/chaiscript/dispatchkit/proxy_functions_detail.hpp +++ b/include/chaiscript/dispatchkit/proxy_functions_detail.hpp @@ -21,6 +21,7 @@ #include "boxed_value.hpp" #include "handle_return.hpp" #include "type_info.hpp" +#include "function_params.hpp" namespace chaiscript { class Type_Conversions_State; @@ -77,7 +78,7 @@ namespace chaiscript */ template bool compare_types_cast(Ret (*)(Params...), - const std::vector ¶ms, const Type_Conversions_State &t_conversions) noexcept + const Function_Params ¶ms, const Type_Conversions_State &t_conversions) noexcept { try { std::vector::size_type i = 0; @@ -92,7 +93,7 @@ namespace chaiscript template Ret call_func(Ret (*)(Params...), std::index_sequence, const Callable &f, - [[maybe_unused]] const std::vector ¶ms, + [[maybe_unused]] const Function_Params ¶ms, [[maybe_unused]] const Type_Conversions_State &t_conversions) { return f(boxed_cast(params[I], &t_conversions)...); @@ -105,7 +106,7 @@ namespace chaiscript /// the bad_boxed_cast is passed up to the caller. template Boxed_Value call_func(Ret (*sig)(Params...), const Callable &f, - const std::vector ¶ms, const Type_Conversions_State &t_conversions) + const Function_Params ¶ms, const Type_Conversions_State &t_conversions) { if constexpr (std::is_same_v) { call_func(sig, std::index_sequence_for{}, f, params, t_conversions); diff --git a/include/chaiscript/language/chaiscript_common.hpp b/include/chaiscript/language/chaiscript_common.hpp index dbbfc744..0527bb0c 100644 --- a/include/chaiscript/language/chaiscript_common.hpp +++ b/include/chaiscript/language/chaiscript_common.hpp @@ -95,7 +95,7 @@ namespace chaiscript Logical_And, Logical_Or, Reference, Switch, Case, Default, Noop, Class, Binary, Arg, Global_Decl, Constant, Compiled }; - enum class Operator_Precidence { Ternary_Cond, Logical_Or, + enum class Operator_Precedence { Ternary_Cond, Logical_Or, Logical_And, Bitwise_Or, Bitwise_Xor, Bitwise_And, Equality, Comparison, Shift, Addition, Multiplication, Prefix }; @@ -732,12 +732,7 @@ namespace chaiscript m_ds->pop_function_call(m_ds.stack_holder(), m_ds.conversion_saves()); } - void save_params(const std::vector &t_params) - { - m_ds->save_function_params(t_params); - } - - void save_params(std::initializer_list t_params) + void save_params(const Function_Params &t_params) { m_ds->save_function_params(t_params); } diff --git a/include/chaiscript/language/chaiscript_engine.hpp b/include/chaiscript/language/chaiscript_engine.hpp index 47cf43a3..6cf22a1d 100644 --- a/include/chaiscript/language/chaiscript_engine.hpp +++ b/include/chaiscript/language/chaiscript_engine.hpp @@ -145,7 +145,7 @@ namespace chaiscript m_engine.add( dispatch::make_dynamic_proxy_function( - [this](const std::vector &t_params) { + [this](const Function_Params &t_params) { return m_engine.call_exists(t_params); }) , "call_exists"); @@ -154,7 +154,7 @@ namespace chaiscript m_engine.add(fun( [=](const dispatch::Proxy_Function_Base &t_fun, const std::vector &t_params) -> Boxed_Value { Type_Conversions_State s(this->m_engine.conversions(), this->m_engine.conversions().conversion_saves()); - return t_fun(t_params, s); + return t_fun(Function_Params{t_params}, s); }), "call"); diff --git a/include/chaiscript/language/chaiscript_eval.hpp b/include/chaiscript/language/chaiscript_eval.hpp index 42c18790..dcdf073e 100644 --- a/include/chaiscript/language/chaiscript_eval.hpp +++ b/include/chaiscript/language/chaiscript_eval.hpp @@ -51,7 +51,7 @@ namespace chaiscript { /// Helper function that will set up the scope around a function call, including handling the named function parameters template - static Boxed_Value eval_function(chaiscript::detail::Dispatch_Engine &t_ss, const AST_Node_Impl &t_node, const std::vector &t_param_names, const std::vector &t_vals, const std::map *t_locals=nullptr, bool has_this_capture = false) { + static Boxed_Value eval_function(chaiscript::detail::Dispatch_Engine &t_ss, const AST_Node_Impl &t_node, const std::vector &t_param_names, const Function_Params &t_vals, const std::map *t_locals=nullptr, bool has_this_capture = false) { chaiscript::detail::Dispatch_State state(t_ss); const Boxed_Value *thisobj = [&]() -> const Boxed_Value *{ @@ -183,8 +183,9 @@ namespace chaiscript } } else { chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); - fpp.save_params({t_lhs, m_rhs}); - return t_ss->call_function(t_oper_string, m_loc, {t_lhs, m_rhs}, t_ss.conversions()); + std::array params{t_lhs, m_rhs}; + fpp.save_params(Function_Params{params}); + return t_ss->call_function(t_oper_string, m_loc, Function_Params{params}, t_ss.conversions()); } } catch(const exception::dispatch_error &e){ @@ -229,8 +230,9 @@ namespace chaiscript } } else { chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); - fpp.save_params({t_lhs, t_rhs}); - return t_ss->call_function(t_oper_string, m_loc, {t_lhs, t_rhs}, t_ss.conversions()); + std::array params{t_lhs, t_rhs}; + fpp.save_params(Function_Params(params)); + return t_ss->call_function(t_oper_string, m_loc, Function_Params(params), t_ss.conversions()); } } catch(const exception::dispatch_error &e){ @@ -304,13 +306,13 @@ namespace chaiscript } if (Save_Params) { - fpp.save_params(params); + fpp.save_params(Function_Params{params}); } Boxed_Value fn(this->children[0]->eval(t_ss)); try { - return (*t_ss->boxed_cast(fn))(params, t_ss.conversions()); + return (*t_ss->boxed_cast(fn))(Function_Params{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); @@ -319,7 +321,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 - throw exception::eval_error("Error calling function '" + this->children[0]->text + "'", params, {f}, false, *t_ss); + throw exception::eval_error("Error calling function '" + this->children[0]->text + "'", params, make_vector(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."); } @@ -425,25 +427,25 @@ namespace chaiscript Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); - Boxed_Value rhs = this->children[1]->eval(t_ss); - Boxed_Value lhs = this->children[0]->eval(t_ss); - if (m_oper != Operators::Opers::invalid && lhs.get_type_info().is_arithmetic() && - rhs.get_type_info().is_arithmetic()) + std::array params{this->children[0]->eval(t_ss), this->children[1]->eval(t_ss)}; + + if (m_oper != Operators::Opers::invalid && params[0].get_type_info().is_arithmetic() && + params[0].get_type_info().is_arithmetic()) { try { - return Boxed_Number::do_oper(m_oper, lhs, rhs); + return Boxed_Number::do_oper(m_oper, params[0], params[1]); } catch (const std::exception &) { throw exception::eval_error("Error with unsupported arithmetic assignment operation"); } } else if (m_oper == Operators::Opers::assign) { - if (lhs.is_return_value()) { + if (params[0].is_return_value()) { throw exception::eval_error("Error, cannot assign to temporary value."); } try { - if (lhs.is_undef()) { + if (params[0].is_undef()) { if (!this->children.empty() && ((this->children[0]->identifier == AST_Node_Type::Reference) || (!this->children[0]->children.empty() @@ -454,20 +456,20 @@ namespace chaiscript { /// \todo This does not handle the case of an unassigned reference variable /// being assigned outside of its declaration - lhs.assign(rhs); - lhs.reset_return_value(); - return rhs; + params[0].assign(params[1]); + params[0].reset_return_value(); + return params[1]; } else { - if (!rhs.is_return_value()) + if (!params[1].is_return_value()) { - rhs = t_ss->call_function("clone", m_clone_loc, {rhs}, t_ss.conversions()); + params[1] = t_ss->call_function("clone", m_clone_loc, Function_Params{¶ms[0], std::end(params)}, t_ss.conversions()); } - rhs.reset_return_value(); + params[1].reset_return_value(); } } try { - return t_ss->call_function(this->text, m_loc, {std::move(lhs), rhs}, t_ss.conversions()); + return t_ss->call_function(this->text, m_loc, Function_Params{params}, t_ss.conversions()); } catch(const exception::dispatch_error &e){ throw exception::eval_error("Unable to find appropriate'" + this->text + "' operator.", e.parameters, e.functions, false, *t_ss); @@ -478,22 +480,22 @@ namespace chaiscript } } else if (this->text == ":=") { - if (lhs.is_undef() || Boxed_Value::type_match(lhs, rhs)) { - lhs.assign(rhs); - lhs.reset_return_value(); + if (params[0].is_undef() || Boxed_Value::type_match(params[0], params[1])) { + params[0].assign(params[1]); + params[0].reset_return_value(); } else { throw exception::eval_error("Mismatched types in equation"); } } else { try { - return t_ss->call_function(this->text, m_loc, {std::move(lhs), rhs}, t_ss.conversions()); + return t_ss->call_function(this->text, m_loc, Function_Params{params}, t_ss.conversions()); } catch(const exception::dispatch_error &e){ throw exception::eval_error("Unable to find appropriate'" + this->text + "' operator.", e.parameters, e.functions, false, *t_ss); } } - return rhs; + return params[1]; } private: @@ -550,11 +552,11 @@ namespace chaiscript Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override { chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); - const std::vector params{this->children[0]->eval(t_ss), this->children[1]->eval(t_ss)}; + std::array params{this->children[0]->eval(t_ss), this->children[1]->eval(t_ss)}; try { - fpp.save_params(params); - return t_ss->call_function("[]", m_loc, params, t_ss.conversions()); + fpp.save_params(Function_Params{params}); + return t_ss->call_function("[]", m_loc, Function_Params{params}, t_ss.conversions()); } catch(const exception::dispatch_error &e){ throw exception::eval_error("Can not find appropriate array lookup operator '[]'.", e.parameters, e.functions, false, *t_ss ); @@ -579,7 +581,7 @@ namespace chaiscript Boxed_Value retval = this->children[0]->eval(t_ss); - std::vector params{retval}; + auto params = make_vector(retval); bool has_function_params = false; if (this->children[1]->children.size() > 1) { @@ -589,10 +591,10 @@ namespace chaiscript } } - fpp.save_params(params); + fpp.save_params(Function_Params{params}); try { - retval = t_ss->call_member(m_fun_name, m_loc, std::move(params), has_function_params, t_ss.conversions()); + retval = t_ss->call_member(m_fun_name, m_loc, Function_Params{params}, has_function_params, t_ss.conversions()); } catch(const exception::dispatch_error &e){ if (e.functions.empty()) @@ -608,7 +610,8 @@ namespace chaiscript if (this->children[1]->identifier == AST_Node_Type::Array_Call) { try { - retval = t_ss->call_function("[]", m_array_loc, {retval, this->children[1]->children[1]->eval(t_ss)}, t_ss.conversions()); + std::array p{retval, this->children[1]->children[1]->eval(t_ss)}; + retval = t_ss->call_function("[]", m_array_loc, Function_Params{p}, t_ss.conversions()); } catch(const exception::dispatch_error &e){ throw exception::eval_error("Can not find appropriate array lookup operator '[]'.", e.parameters, e.functions, true, *t_ss); @@ -657,7 +660,7 @@ namespace chaiscript return Boxed_Value( dispatch::make_dynamic_proxy_function( [engine, lambda_node = this->m_lambda_node, param_names = this->m_param_names, captures, - this_capture = this->m_this_capture] (const std::vector &t_params) + this_capture = this->m_this_capture] (const Function_Params &t_params) { return detail::eval_function(engine, *lambda_node, param_names, t_params, &captures, this_capture); }, @@ -771,7 +774,7 @@ namespace chaiscript std::shared_ptr guard; if (m_guard_node) { guard = dispatch::make_dynamic_proxy_function( - [engine, guardnode = m_guard_node, t_param_names](const std::vector &t_params) + [engine, guardnode = m_guard_node, t_param_names](const Function_Params &t_params) { return detail::eval_function(engine, *guardnode, t_param_names, t_params); }, @@ -782,7 +785,7 @@ namespace chaiscript const std::string & l_function_name = this->children[0]->text; t_ss->add( dispatch::make_dynamic_proxy_function( - [engine, func_node = m_body_node, t_param_names](const std::vector &t_params) + [engine, func_node = m_body_node, t_param_names](const Function_Params &t_params) { return detail::eval_function(engine, *func_node, t_param_names, t_params); }, @@ -873,7 +876,7 @@ namespace chaiscript }; const auto call_function = [&t_ss](const auto &t_funcs, const Boxed_Value &t_param) { - return dispatch::dispatch(*t_funcs, {t_param}, t_ss.conversions()); + return dispatch::dispatch(*t_funcs, Function_Params{t_param}, t_ss.conversions()); }; @@ -988,7 +991,8 @@ namespace chaiscript if (this->children[currentCase]->identifier == AST_Node_Type::Case) { //This is a little odd, but because want to see both the switch and the case simultaneously, I do a downcast here. try { - if (hasMatched || boxed_cast(t_ss->call_function("==", m_loc, {match_value, this->children[currentCase]->children[0]->eval(t_ss)}, t_ss.conversions()))) { + std::array p{match_value, this->children[currentCase]->children[0]->eval(t_ss)}; + if (hasMatched || boxed_cast(t_ss->call_function("==", m_loc, Function_Params{p}, t_ss.conversions()))) { this->children[currentCase]->eval(t_ss); hasMatched = true; } @@ -1057,7 +1061,7 @@ namespace chaiscript for (const auto &child : this->children[0]->children) { if (auto obj = child->eval(t_ss); !obj.is_return_value()) { - vec.push_back(t_ss->call_function("clone", m_loc, {obj}, t_ss.conversions())); + vec.push_back(t_ss->call_function("clone", m_loc, Function_Params{obj}, t_ss.conversions())); } else { vec.push_back(std::move(obj)); } @@ -1087,7 +1091,7 @@ namespace chaiscript for (const auto &child : this->children[0]->children) { auto obj = child->children[1]->eval(t_ss); if (!obj.is_return_value()) { - obj = t_ss->call_function("clone", m_loc, {obj}, t_ss.conversions()); + obj = t_ss->call_function("clone", m_loc, Function_Params{obj}, t_ss.conversions()); } retval[t_ss->boxed_cast(child->children[0]->eval(t_ss))] = std::move(obj); @@ -1174,8 +1178,8 @@ namespace chaiscript return Boxed_Number::do_oper(m_oper, bv); } else { chaiscript::eval::detail::Function_Push_Pop fpp(t_ss); - fpp.save_params({bv}); - return t_ss->call_function(this->text, m_loc, {std::move(bv)}, t_ss.conversions()); + fpp.save_params(Function_Params{bv}); + return t_ss->call_function(this->text, m_loc, Function_Params{bv}, 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); @@ -1240,9 +1244,12 @@ namespace chaiscript Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{ try { - auto oper1 = this->children[0]->children[0]->children[0]->eval(t_ss); - auto oper2 = this->children[0]->children[0]->children[1]->eval(t_ss); - return t_ss->call_function("generate_range", m_loc, {oper1, oper2}, t_ss.conversions()); + std::array params{ + this->children[0]->children[0]->children[0]->eval(t_ss), + this->children[0]->children[0]->children[1]->eval(t_ss) + }; + + return t_ss->call_function("generate_range", m_loc, Function_Params{params}, t_ss.conversions()); } catch (const exception::dispatch_error &e) { throw exception::eval_error("Unable to generate range vector, while calling 'generate_range'", e.parameters, e.functions, false, *t_ss); @@ -1280,7 +1287,7 @@ namespace chaiscript if (dispatch::Param_Types( std::vector>{Arg_List_AST_Node::get_arg_type(*catch_block.children[0], t_ss)} - ).match(std::vector{t_except}, t_ss.conversions()).first) + ).match(Function_Params{t_except}, t_ss.conversions()).first) { t_ss.add_object(name, t_except); @@ -1410,7 +1417,7 @@ namespace chaiscript std::reference_wrapper engine(*t_ss); if (m_guard_node) { guard = dispatch::make_dynamic_proxy_function( - [engine, t_param_names, guardnode = m_guard_node](const std::vector &t_params) { + [engine, t_param_names, guardnode = m_guard_node](const Function_Params &t_params) { return chaiscript::eval::detail::eval_function(engine, *guardnode, t_param_names, t_params); }, static_cast(numparams), m_guard_node); @@ -1425,7 +1432,7 @@ namespace chaiscript t_ss->add( std::make_shared(class_name, dispatch::make_dynamic_proxy_function( - [engine, t_param_names, node = m_body_node](const std::vector &t_params) { + [engine, t_param_names, node = m_body_node](const Function_Params &t_params) { return chaiscript::eval::detail::eval_function(engine, *node, t_param_names, t_params); }, static_cast(numparams), m_body_node, param_types, guard @@ -1442,7 +1449,7 @@ namespace chaiscript t_ss->add( std::make_shared(class_name, dispatch::make_dynamic_proxy_function( - [engine, t_param_names, node = m_body_node](const std::vector &t_params) { + [engine, t_param_names, node = m_body_node](const Function_Params &t_params) { return chaiscript::eval::detail::eval_function(engine, *node, t_param_names, t_params); }, static_cast(numparams), m_body_node, param_types, guard), type), diff --git a/include/chaiscript/language/chaiscript_parser.hpp b/include/chaiscript/language/chaiscript_parser.hpp index ebcef83f..749ac9d3 100644 --- a/include/chaiscript/language/chaiscript_parser.hpp +++ b/include/chaiscript/language/chaiscript_parser.hpp @@ -263,20 +263,20 @@ namespace chaiscript }; - constexpr static std::array create_operators() noexcept { - std::array operators = { { - Operator_Precidence::Ternary_Cond, - Operator_Precidence::Logical_Or, - Operator_Precidence::Logical_And, - Operator_Precidence::Bitwise_Or, - Operator_Precidence::Bitwise_Xor, - Operator_Precidence::Bitwise_And, - Operator_Precidence::Equality, - Operator_Precidence::Comparison, - Operator_Precidence::Shift, - Operator_Precidence::Addition, - Operator_Precidence::Multiplication, - Operator_Precidence::Prefix + constexpr static std::array create_operators() noexcept { + std::array operators = { { + Operator_Precedence::Ternary_Cond, + Operator_Precedence::Logical_Or, + Operator_Precedence::Logical_And, + Operator_Precedence::Bitwise_Or, + Operator_Precedence::Bitwise_Xor, + Operator_Precedence::Bitwise_And, + Operator_Precedence::Equality, + Operator_Precedence::Comparison, + Operator_Precedence::Shift, + Operator_Precedence::Addition, + Operator_Precedence::Multiplication, + Operator_Precedence::Prefix } }; return operators; } @@ -2363,7 +2363,7 @@ namespace chaiscript bool retval = false; const auto prev_stack_top = m_match_stack.size(); - if (m_operators[t_precedence] != Operator_Precidence::Prefix) { + if (m_operators[t_precedence] != Operator_Precedence::Prefix) { if (Operator(t_precedence+1)) { retval = true; std::string oper; @@ -2375,7 +2375,7 @@ namespace chaiscript } switch (m_operators[t_precedence]) { - case(Operator_Precidence::Ternary_Cond) : + case(Operator_Precedence::Ternary_Cond) : if (Symbol(":")) { if (!Operator(t_precedence+1)) { throw exception::eval_error("Incomplete '" + oper + "' expression", @@ -2389,24 +2389,24 @@ namespace chaiscript } break; - case(Operator_Precidence::Addition) : - case(Operator_Precidence::Multiplication) : - case(Operator_Precidence::Shift) : - case(Operator_Precidence::Equality) : - case(Operator_Precidence::Bitwise_And) : - case(Operator_Precidence::Bitwise_Xor) : - case(Operator_Precidence::Bitwise_Or) : - case(Operator_Precidence::Comparison) : + case(Operator_Precedence::Addition) : + case(Operator_Precedence::Multiplication) : + case(Operator_Precedence::Shift) : + case(Operator_Precedence::Equality) : + case(Operator_Precedence::Bitwise_And) : + case(Operator_Precedence::Bitwise_Xor) : + case(Operator_Precedence::Bitwise_Or) : + case(Operator_Precedence::Comparison) : build_match>(prev_stack_top, oper); break; - case(Operator_Precidence::Logical_And) : + case(Operator_Precedence::Logical_And) : build_match>(prev_stack_top, oper); break; - case(Operator_Precidence::Logical_Or) : + case(Operator_Precedence::Logical_Or) : build_match>(prev_stack_top, oper); break; - case(Operator_Precidence::Prefix) : + case(Operator_Precedence::Prefix) : assert(false); // cannot reach here because of if() statement at the top break; diff --git a/include/chaiscript/utility/stack_vector.hpp b/include/chaiscript/utility/stack_vector.hpp new file mode 100644 index 00000000..706d276a --- /dev/null +++ b/include/chaiscript/utility/stack_vector.hpp @@ -0,0 +1,63 @@ +// This file is distributed under the BSD License. +// See "license.txt" for details. +// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) +// Copyright 2009-2017, Jason Turner (jason@emptycrate.com) +// http://www.chaiscript.com + +// This is an open source non-commercial project. Dear PVS-Studio, please check it. +// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + + +#ifndef CHAISCRIPT_STACK_VECTOR_HPP_ +#define CHAISCRIPT_STACK_VECTOR_HPP_ + +#include +#include +#include + + + +template +struct Stack_Vector +{ + constexpr static auto aligned_size = sizeof(T) + (sizeof(T) & std::alignment_of_v) > 0 ? std::alignment_of_v : 0; + + alignas(std::alignment_of_v) char data[aligned_size * MaxSize]; + + [[nodiscard]] T & operator[](const std::size_t idx) noexcept { + return *reinterpret_cast(&data + aligned_size * idx); + } + + [[nodiscard]] const T & operator[](const std::size_t idx) const noexcept { + return *reinterpret_cast(&data + aligned_size * idx); + } + + template + T& emplace_back(Param && ... param) { + auto *p = new(&(*this)[m_size++]) T(std::forward(param)...); + return *p; + }; + + auto size() const noexcept { + return m_size; + }; + + void pop_back() noexcept(std::is_nothrow_destructible_v) { + (*this)[m_size--].~T(); + } + + ~Stack_Vector() noexcept(std::is_nothrow_destructible_v) + { + auto loc = m_size - 1; + for (std::size_t pos = 0; pos < m_size; ++pos) { + (*this)[loc--].~T(); + } + } + + std::size_t m_size{0}; + +}; + +#endif CHAISCRIPT_STACK_VECTOR_HPP_ + +