mirror of
https://github.com/ChaiScript/ChaiScript.git
synced 2025-12-07 17:26:55 +08:00
Merge remote-tracking branch 'origin/c++17' into develop
This commit is contained in:
commit
c19705da5d
@ -15,7 +15,6 @@ option(BUILD_SAMPLES "Build Samples Folder" FALSE)
|
||||
option(RUN_FUZZY_TESTS "Run tests generated by AFL" FALSE)
|
||||
option(USE_STD_MAKE_SHARED "Use std::make_shared instead of chaiscript::make_shared" FALSE)
|
||||
option(RUN_PERFORMANCE_TESTS "Run Performance Tests" FALSE)
|
||||
option(BUILD_IN_CPP17_MODE "Build with C++17 flags" FALSE)
|
||||
|
||||
mark_as_advanced(USE_STD_MAKE_SHARED)
|
||||
|
||||
@ -49,8 +48,8 @@ if(CMAKE_COMPILER_IS_GNUCC OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
|
||||
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")
|
||||
add_definitions(-fsanitize=memory -fsanitize-memory-track-origins -g)
|
||||
set(LINKER_FLAGS "${LINKER_FLAGS} -fsanitize=memory -fsanitize-memory-track-origins ")
|
||||
endif()
|
||||
|
||||
option(ENABLE_UNDEFINED_SANITIZER "Enable undefined behavior sanitizer testing in gcc/clang" FALSE)
|
||||
@ -98,8 +97,8 @@ set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/license.txt")
|
||||
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 6)
|
||||
set(CPACK_PACKAGE_VERSION_MINOR 1)
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR 7)
|
||||
set(CPACK_PACKAGE_VERSION_MINOR 0)
|
||||
set(CPACK_PACKAGE_VERSION_PATCH 0)
|
||||
|
||||
set(CPACK_PACKAGE_EXECUTABLES "chai;ChaiScript Eval")
|
||||
@ -149,27 +148,16 @@ if(CMAKE_COMPILER_IS_GNUCC)
|
||||
if(GCC_VERSION VERSION_LESS 4.9)
|
||||
set(CPP14_FLAG "-std=c++1y")
|
||||
else()
|
||||
if (BUILD_IN_CPP17_MODE)
|
||||
set(CPP14_FLAG "-std=c++1z")
|
||||
else()
|
||||
set(CPP14_FLAG "-std=c++14")
|
||||
endif()
|
||||
set(CPP14_FLAG "-std=c++1z")
|
||||
endif()
|
||||
else()
|
||||
if (BUILD_IN_CPP17_MODE)
|
||||
set(CPP14_FLAG "-std=c++1z")
|
||||
else()
|
||||
set(CPP14_FLAG "-std=c++14")
|
||||
endif()
|
||||
set(CPP14_FLAG "-std=c++1z")
|
||||
endif()
|
||||
|
||||
if(MSVC)
|
||||
add_definitions(/W4 /w14545 /w34242 /w34254 /w34287 /w44263 /w44265 /w44296 /w44311 /w44826 /we4289 /w14546 /w14547 /w14549 /w14555 /w14619 /w14905 /w14906 /w14928)
|
||||
|
||||
if (BUILD_IN_CPP17_MODE)
|
||||
add_definitions(/std:c++17)
|
||||
endif()
|
||||
add_definitions(/std:c++latest /W4 /w14545 /w34242 /w34254 /w34287 /w44263 /w44265 /w44296 /w44311 /w44826 /we4289 /w14546 /w14547 /w14549 /w14555 /w14619 /w14905 /w14906 /w14928)
|
||||
|
||||
add_definitions(/std:c++17)
|
||||
|
||||
|
||||
if (MSVC_VERSION STREQUAL "1800")
|
||||
@ -190,10 +178,10 @@ if(MSVC)
|
||||
# how to workaround or fix the error. So I'm disabling it globally.
|
||||
add_definitions(/wd4503)
|
||||
else()
|
||||
add_definitions(-Wall -Wextra -Wconversion -Wshadow -Wnon-virtual-dtor -Wold-style-cast -Wcast-align -Wcast-qual -Wunused -Woverloaded-virtual -pedantic ${CPP14_FLAG})
|
||||
add_definitions(-Wall -Wextra -Wconversion -Wshadow -Wnon-virtual-dtor -Wold-style-cast -Wcast-align -Wcast-qual -Wunused -Woverloaded-virtual -Wno-noexcept-type -Wpedantic ${CPP14_FLAG})
|
||||
|
||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
add_definitions(-Weverything -Wno-c++98-compat-pedantic -Wno-c++98-compat -Wno-documentation -Wno-switch-enum -Wno-weak-vtables -Wno-missing-prototypes -Wno-padded -Wno-missing-noreturn -Wno-exit-time-destructors -Wno-documentation-unknown-command -Wno-unused-template)
|
||||
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 )
|
||||
else()
|
||||
add_definitions(-Wnoexcept)
|
||||
endif()
|
||||
|
||||
@ -21,6 +21,7 @@ static_assert(_MSC_FULL_VER >= 190024210, "Visual C++ 2015 Update 3 or later req
|
||||
#endif
|
||||
|
||||
#include <vector>
|
||||
#include <string_view>
|
||||
|
||||
#if defined( _LIBCPP_VERSION )
|
||||
#define CHAISCRIPT_LIBCPP
|
||||
@ -75,13 +76,13 @@ static_assert(_MSC_FULL_VER >= 190024210, "Visual C++ 2015 Update 3 or later req
|
||||
#include <cmath>
|
||||
|
||||
namespace chaiscript {
|
||||
static const int version_major = 6;
|
||||
static const int version_minor = 1;
|
||||
static const int version_patch = 0;
|
||||
constexpr static const int version_major = 7;
|
||||
constexpr static const int version_minor = 0;
|
||||
constexpr static const int version_patch = 0;
|
||||
|
||||
static const char *compiler_version = CHAISCRIPT_COMPILER_VERSION;
|
||||
static const char *compiler_name = CHAISCRIPT_COMPILER_NAME;
|
||||
static const bool debug_build = CHAISCRIPT_DEBUG;
|
||||
constexpr static const char *compiler_version = CHAISCRIPT_COMPILER_VERSION;
|
||||
constexpr static const char *compiler_name = CHAISCRIPT_COMPILER_NAME;
|
||||
constexpr static const bool debug_build = CHAISCRIPT_DEBUG;
|
||||
|
||||
template<typename B, typename D, typename ...Arg>
|
||||
inline std::shared_ptr<B> make_shared(Arg && ... arg)
|
||||
@ -104,17 +105,17 @@ namespace chaiscript {
|
||||
}
|
||||
|
||||
struct Build_Info {
|
||||
static int version_major()
|
||||
constexpr static int version_major() noexcept
|
||||
{
|
||||
return chaiscript::version_major;
|
||||
}
|
||||
|
||||
static int version_minor()
|
||||
constexpr static int version_minor() noexcept
|
||||
{
|
||||
return chaiscript::version_minor;
|
||||
}
|
||||
|
||||
static int version_patch()
|
||||
constexpr static int version_patch() noexcept
|
||||
{
|
||||
return chaiscript::version_patch;
|
||||
}
|
||||
@ -144,7 +145,7 @@ namespace chaiscript {
|
||||
return chaiscript::compiler_name;
|
||||
}
|
||||
|
||||
static bool debug_build()
|
||||
constexpr static bool debug_build() noexcept
|
||||
{
|
||||
return chaiscript::debug_build;
|
||||
}
|
||||
@ -152,10 +153,10 @@ namespace chaiscript {
|
||||
|
||||
|
||||
template<typename T>
|
||||
auto parse_num(const char *t_str) -> typename std::enable_if<std::is_integral<T>::value, T>::type
|
||||
constexpr auto parse_num(const std::string_view t_str) noexcept -> typename std::enable_if<std::is_integral<T>::value, T>::type
|
||||
{
|
||||
T t = 0;
|
||||
for (char c = *t_str; (c = *t_str) != 0; ++t_str) {
|
||||
for (const auto c : t_str) {
|
||||
if (c < '0' || c > '9') {
|
||||
return t;
|
||||
}
|
||||
@ -167,15 +168,14 @@ namespace chaiscript {
|
||||
|
||||
|
||||
template<typename T>
|
||||
auto parse_num(const char *t_str) -> typename std::enable_if<!std::is_integral<T>::value, T>::type
|
||||
auto parse_num(const std::string_view t_str) -> typename std::enable_if<!std::is_integral<T>::value, T>::type
|
||||
{
|
||||
T t = 0;
|
||||
T base{};
|
||||
T decimal_place = 0;
|
||||
int exponent = 0;
|
||||
|
||||
for (char c;; ++t_str) {
|
||||
c = *t_str;
|
||||
for (const auto c : t_str) {
|
||||
switch (c)
|
||||
{
|
||||
case '.':
|
||||
@ -213,16 +213,24 @@ namespace chaiscript {
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return exponent ? base * std::pow(T(10), t * static_cast<T>(exponent)) : t;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return exponent ? base * std::pow(T(10), t * static_cast<T>(exponent)) : t;
|
||||
|
||||
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T parse_num(const std::string &t_str)
|
||||
{
|
||||
return parse_num<T>(t_str.c_str());
|
||||
struct str_less {
|
||||
bool operator()(const std::string &t_lhs, const std::string &t_rhs) const noexcept {
|
||||
return t_lhs < t_rhs;
|
||||
}
|
||||
template<typename LHS, typename RHS>
|
||||
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{};
|
||||
};
|
||||
|
||||
enum class Options
|
||||
{
|
||||
|
||||
@ -17,6 +17,7 @@
|
||||
#ifndef CHAISCRIPT_NO_THREADS
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <shared_mutex>
|
||||
#else
|
||||
#ifndef CHAISCRIPT_NO_THREADS_WARNING
|
||||
#pragma message ("ChaiScript is compiling without thread safety.")
|
||||
@ -49,13 +50,13 @@ namespace chaiscript
|
||||
using unique_lock = std::unique_lock<T>;
|
||||
|
||||
template<typename T>
|
||||
using shared_lock = std::unique_lock<T>;
|
||||
using shared_lock = std::shared_lock<T>;
|
||||
|
||||
template<typename T>
|
||||
using lock_guard = std::lock_guard<T>;
|
||||
|
||||
|
||||
using shared_mutex = std::mutex;
|
||||
using std::shared_mutex;
|
||||
|
||||
using std::mutex;
|
||||
|
||||
@ -78,22 +79,22 @@ namespace chaiscript
|
||||
t().erase(this);
|
||||
}
|
||||
|
||||
inline const T *operator->() const
|
||||
inline const T *operator->() const noexcept
|
||||
{
|
||||
return &(t()[this]);
|
||||
}
|
||||
|
||||
inline const T &operator*() const
|
||||
inline const T &operator*() const noexcept
|
||||
{
|
||||
return t()[this];
|
||||
}
|
||||
|
||||
inline T *operator->()
|
||||
inline T *operator->() noexcept
|
||||
{
|
||||
return &(t()[this]);
|
||||
}
|
||||
|
||||
inline T &operator*()
|
||||
inline T &operator*() noexcept
|
||||
{
|
||||
return t()[this];
|
||||
}
|
||||
@ -102,7 +103,9 @@ namespace chaiscript
|
||||
void *m_key;
|
||||
|
||||
private:
|
||||
static std::unordered_map<const void*, T> &t()
|
||||
/// todo: is it valid to make this noexcept? The allocation could fail, but if it
|
||||
/// does there is no possible way to recover
|
||||
static std::unordered_map<const void*, T> &t() noexcept
|
||||
{
|
||||
thread_local std::unordered_map<const void *, T> my_t;
|
||||
return my_t;
|
||||
@ -114,25 +117,25 @@ namespace chaiscript
|
||||
class unique_lock
|
||||
{
|
||||
public:
|
||||
explicit unique_lock(T &) {}
|
||||
void lock() {}
|
||||
void unlock() {}
|
||||
constexpr explicit unique_lock(T &) noexcept {}
|
||||
constexpr void lock() noexcept {}
|
||||
constexpr void unlock() noexcept {}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class shared_lock
|
||||
{
|
||||
public:
|
||||
explicit shared_lock(T &) {}
|
||||
void lock() {}
|
||||
void unlock() {}
|
||||
constexpr explicit shared_lock(T &) noexcept {}
|
||||
constexpr void lock() noexcept {}
|
||||
constexpr void unlock() noexcept {}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
class lock_guard
|
||||
{
|
||||
public:
|
||||
explicit lock_guard(T &) {}
|
||||
constexpr explicit lock_guard(T &) noexcept {}
|
||||
};
|
||||
|
||||
class shared_mutex { };
|
||||
@ -144,16 +147,16 @@ namespace chaiscript
|
||||
class Thread_Storage
|
||||
{
|
||||
public:
|
||||
explicit Thread_Storage()
|
||||
constexpr explicit Thread_Storage() noexcept
|
||||
{
|
||||
}
|
||||
|
||||
inline T *operator->() const
|
||||
constexpr inline T *operator->() const noexcept
|
||||
{
|
||||
return &obj;
|
||||
}
|
||||
|
||||
inline T &operator*() const
|
||||
constexpr inline T &operator*() const noexcept
|
||||
{
|
||||
return obj;
|
||||
}
|
||||
|
||||
@ -21,20 +21,11 @@ namespace chaiscript {
|
||||
class bad_any_cast : public std::bad_cast
|
||||
{
|
||||
public:
|
||||
bad_any_cast() = default;
|
||||
|
||||
bad_any_cast(const bad_any_cast &) = default;
|
||||
|
||||
~bad_any_cast() noexcept override = default;
|
||||
|
||||
/// \brief Description of what error occurred
|
||||
const char * what() const noexcept override
|
||||
{
|
||||
return m_what.c_str();
|
||||
return "bad any cast";
|
||||
}
|
||||
|
||||
private:
|
||||
std::string m_what = "bad any cast";
|
||||
};
|
||||
}
|
||||
|
||||
@ -43,18 +34,18 @@ namespace chaiscript {
|
||||
private:
|
||||
struct Data
|
||||
{
|
||||
explicit Data(const std::type_info &t_type)
|
||||
constexpr explicit Data(const std::type_info &t_type) noexcept
|
||||
: m_type(t_type)
|
||||
{
|
||||
}
|
||||
|
||||
Data &operator=(const Data &) = delete;
|
||||
|
||||
virtual ~Data() = default;
|
||||
virtual ~Data() noexcept = default;
|
||||
|
||||
virtual void *data() = 0;
|
||||
virtual void *data() noexcept = 0;
|
||||
|
||||
const std::type_info &type() const
|
||||
const std::type_info &type() const noexcept
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
@ -72,14 +63,14 @@ namespace chaiscript {
|
||||
{
|
||||
}
|
||||
|
||||
void *data() override
|
||||
void *data() noexcept override
|
||||
{
|
||||
return &m_data;
|
||||
}
|
||||
|
||||
std::unique_ptr<Data> clone() const override
|
||||
{
|
||||
return std::unique_ptr<Data>(new Data_Impl<T>(m_data));
|
||||
return std::make_unique<Data_Impl<T>>(m_data);
|
||||
}
|
||||
|
||||
Data_Impl &operator=(const Data_Impl&) = delete;
|
||||
@ -91,25 +82,19 @@ namespace chaiscript {
|
||||
|
||||
public:
|
||||
// construct/copy/destruct
|
||||
Any() = default;
|
||||
constexpr Any() noexcept = default;
|
||||
Any(Any &&) = default;
|
||||
Any &operator=(Any &&t_any) = default;
|
||||
|
||||
Any(const Any &t_any)
|
||||
{
|
||||
if (!t_any.empty())
|
||||
{
|
||||
m_data = t_any.m_data->clone();
|
||||
} else {
|
||||
m_data.reset();
|
||||
}
|
||||
Any(const Any &t_any)
|
||||
: m_data(t_any.empty() ? nullptr : t_any.m_data->clone())
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
template<typename ValueType,
|
||||
typename = typename std::enable_if<!std::is_same<Any, typename std::decay<ValueType>::type>::value>::type>
|
||||
typename = std::enable_if_t<!std::is_same_v<Any, std::decay_t<ValueType>>>>
|
||||
explicit Any(ValueType &&t_value)
|
||||
: m_data(std::unique_ptr<Data>(new Data_Impl<typename std::decay<ValueType>::type>(std::forward<ValueType>(t_value))))
|
||||
: m_data(std::make_unique<Data_Impl<std::decay_t<ValueType>>>(std::forward<ValueType>(t_value)))
|
||||
{
|
||||
}
|
||||
|
||||
@ -141,12 +126,12 @@ namespace chaiscript {
|
||||
}
|
||||
|
||||
// queries
|
||||
bool empty() const
|
||||
bool empty() const noexcept
|
||||
{
|
||||
return !bool(m_data);
|
||||
}
|
||||
|
||||
const std::type_info & type() const
|
||||
const std::type_info & type() const noexcept
|
||||
{
|
||||
if (m_data) {
|
||||
return m_data->type();
|
||||
|
||||
@ -15,6 +15,7 @@
|
||||
#include <typeinfo>
|
||||
|
||||
#include "../chaiscript_defines.hpp"
|
||||
#include "../utility/static_string.hpp"
|
||||
#include "type_info.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
@ -34,22 +35,22 @@ namespace chaiscript
|
||||
{
|
||||
public:
|
||||
bad_boxed_cast(Type_Info t_from, const std::type_info &t_to,
|
||||
std::string t_what) noexcept
|
||||
utility::Static_String t_what) noexcept
|
||||
: from(t_from), to(&t_to), m_what(std::move(t_what))
|
||||
{
|
||||
}
|
||||
|
||||
bad_boxed_cast(Type_Info t_from, const std::type_info &t_to)
|
||||
: from(t_from), to(&t_to), m_what("Cannot perform boxed_cast: " + t_from.name() + " to: " + t_to.name())
|
||||
bad_boxed_cast(Type_Info t_from, const std::type_info &t_to) noexcept
|
||||
: from(t_from), to(&t_to), m_what("Cannot perform boxed_cast")
|
||||
{
|
||||
}
|
||||
|
||||
explicit bad_boxed_cast(std::string t_what) noexcept
|
||||
explicit bad_boxed_cast(utility::Static_String t_what) noexcept
|
||||
: m_what(std::move(t_what))
|
||||
{
|
||||
}
|
||||
|
||||
bad_boxed_cast(const bad_boxed_cast &) = default;
|
||||
bad_boxed_cast(const bad_boxed_cast &) noexcept = default;
|
||||
~bad_boxed_cast() noexcept override = default;
|
||||
|
||||
/// \brief Description of what error occurred
|
||||
@ -62,7 +63,7 @@ namespace chaiscript
|
||||
const std::type_info *to = nullptr; ///< std::type_info of the desired (but failed) result type
|
||||
|
||||
private:
|
||||
std::string m_what;
|
||||
utility::Static_String m_what;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@ -19,37 +19,37 @@ namespace chaiscript
|
||||
{
|
||||
|
||||
template<typename T>
|
||||
T* get_pointer(T *t)
|
||||
constexpr T* get_pointer(T *t) noexcept
|
||||
{
|
||||
return t;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
T* get_pointer(const std::reference_wrapper<T> &t)
|
||||
T* get_pointer(const std::reference_wrapper<T> &t) noexcept
|
||||
{
|
||||
return &t.get();
|
||||
}
|
||||
|
||||
template<typename O, typename Ret, typename P1, typename ... Param>
|
||||
auto bind_first(Ret (*f)(P1, Param...), O&& o)
|
||||
constexpr auto bind_first(Ret (*f)(P1, Param...), O&& o)
|
||||
{
|
||||
return [f, o](Param...param) -> Ret {
|
||||
return f(std::forward<O>(o), std::forward<Param>(param)...);
|
||||
return [f, o = std::forward<O>(o)](Param...param) -> Ret {
|
||||
return f(o, std::forward<Param>(param)...);
|
||||
};
|
||||
}
|
||||
|
||||
template<typename O, typename Ret, typename Class, typename ... Param>
|
||||
auto bind_first(Ret (Class::*f)(Param...), O&& o)
|
||||
constexpr auto bind_first(Ret (Class::*f)(Param...), O&& o)
|
||||
{
|
||||
return [f, o](Param...param) -> Ret {
|
||||
return [f, o = std::forward<O>(o)](Param...param) -> Ret {
|
||||
return (get_pointer(o)->*f)(std::forward<Param>(param)...);
|
||||
};
|
||||
}
|
||||
|
||||
template<typename O, typename Ret, typename Class, typename ... Param>
|
||||
auto bind_first(Ret (Class::*f)(Param...) const, O&& o)
|
||||
constexpr auto bind_first(Ret (Class::*f)(Param...) const, O&& o)
|
||||
{
|
||||
return [f, o](Param...param) -> Ret {
|
||||
return [f, o = std::forward<O>(o)](Param...param) -> Ret {
|
||||
return (get_pointer(o)->*f)(std::forward<Param>(param)...);
|
||||
};
|
||||
|
||||
@ -58,22 +58,22 @@ namespace chaiscript
|
||||
template<typename O, typename Ret, typename P1, typename ... Param>
|
||||
auto bind_first(const std::function<Ret (P1, Param...)> &f, O&& o)
|
||||
{
|
||||
return [f, o](Param...param) -> Ret {
|
||||
return [f, o = std::forward<O>(o)](Param...param) -> Ret {
|
||||
return f(o, std::forward<Param>(param)...);
|
||||
};
|
||||
}
|
||||
|
||||
template<typename F, typename O, typename Ret, typename Class, typename P1, typename ... Param>
|
||||
auto bind_first(const F &fo, O&& o, Ret (Class::*f)(P1, Param...) const)
|
||||
constexpr auto bind_first(const F &fo, O&& o, Ret (Class::*f)(P1, Param...) const)
|
||||
{
|
||||
return [fo, o, f](Param ...param) -> Ret {
|
||||
return [fo, o = std::forward<O>(o), f](Param ...param) -> Ret {
|
||||
return (fo.*f)(o, std::forward<Param>(param)...);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
template<typename F, typename O>
|
||||
auto bind_first(const F &f, O&& o)
|
||||
constexpr auto bind_first(const F &f, O&& o)
|
||||
{
|
||||
return bind_first(f, std::forward<O>(o), &F::operator());
|
||||
}
|
||||
|
||||
@ -22,11 +22,12 @@ namespace chaiscript
|
||||
template<typename T, typename = typename std::enable_if<std::is_array<T>::value>::type >
|
||||
void array(const std::string &type, Module& m)
|
||||
{
|
||||
typedef typename std::remove_extent<T>::type ReturnType;
|
||||
using ReturnType = typename std::remove_extent<T>::type;
|
||||
|
||||
m.add(user_type<T>(), type);
|
||||
m.add(fun(
|
||||
[](T& t, size_t index)->ReturnType &{
|
||||
constexpr auto extent = std::extent<T>::value;
|
||||
constexpr const auto extent = std::extent<T>::value;
|
||||
if (extent > 0 && index >= extent) {
|
||||
throw std::range_error("Array index out of range. Received: " + std::to_string(index) + " expected < " + std::to_string(extent));
|
||||
} else {
|
||||
@ -38,7 +39,7 @@ namespace chaiscript
|
||||
|
||||
m.add(fun(
|
||||
[](const T &t, size_t index)->const ReturnType &{
|
||||
constexpr auto extent = std::extent<T>::value;
|
||||
constexpr const auto extent = std::extent<T>::value;
|
||||
if (extent > 0 && index >= extent) {
|
||||
throw std::range_error("Array index out of range. Received: " + std::to_string(index) + " expected < " + std::to_string(extent));
|
||||
} else {
|
||||
@ -50,8 +51,7 @@ namespace chaiscript
|
||||
|
||||
m.add(fun(
|
||||
[](const T &) {
|
||||
constexpr auto extent = std::extent<T>::value;
|
||||
return extent;
|
||||
return std::extent<T>::value;
|
||||
}), "size");
|
||||
}
|
||||
|
||||
@ -111,31 +111,20 @@ namespace chaiscript
|
||||
/// Internal function for converting from a string to a value
|
||||
/// uses ostream operator >> to perform the conversion
|
||||
template<typename Input>
|
||||
auto parse_string(const std::string &i)
|
||||
-> typename std::enable_if<
|
||||
!std::is_same<Input, wchar_t>::value
|
||||
&& !std::is_same<Input, char16_t>::value
|
||||
&& !std::is_same<Input, char32_t>::value,
|
||||
Input>::type
|
||||
Input parse_string(const std::string &i)
|
||||
{
|
||||
std::stringstream ss(i);
|
||||
Input t;
|
||||
ss >> t;
|
||||
return t;
|
||||
if constexpr (!std::is_same<Input, wchar_t>::value
|
||||
&& !std::is_same<Input, char16_t>::value
|
||||
&& !std::is_same<Input, char32_t>::value) {
|
||||
std::stringstream ss(i);
|
||||
Input t;
|
||||
ss >> t;
|
||||
return t;
|
||||
} else {
|
||||
throw std::runtime_error("Parsing of wide characters is not yet supported");
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Input>
|
||||
auto parse_string(const std::string &)
|
||||
-> typename std::enable_if<
|
||||
std::is_same<Input, wchar_t>::value
|
||||
|| std::is_same<Input, char16_t>::value
|
||||
|| std::is_same<Input, char32_t>::value,
|
||||
Input>::type
|
||||
{
|
||||
throw std::runtime_error("Parsing of wide characters is not yet supported");
|
||||
}
|
||||
|
||||
|
||||
/// Add all common functions for a POD type. All operators, and
|
||||
/// common conversions
|
||||
template<typename T>
|
||||
@ -202,12 +191,12 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
static void print(const std::string &s)
|
||||
static void print(const std::string &s) noexcept
|
||||
{
|
||||
fwrite(s.c_str(), 1, s.size(), stdout);
|
||||
}
|
||||
|
||||
static void println(const std::string &s)
|
||||
static void println(const std::string &s) noexcept
|
||||
{
|
||||
puts(s.c_str());
|
||||
}
|
||||
@ -271,10 +260,10 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
|
||||
static bool has_guard(const Const_Proxy_Function &t_pf)
|
||||
static bool has_guard(const Const_Proxy_Function &t_pf) noexcept
|
||||
{
|
||||
auto pf = std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(t_pf);
|
||||
return pf && pf->get_guard();
|
||||
return pf && pf->has_guard();
|
||||
}
|
||||
|
||||
static Const_Proxy_Function get_guard(const Const_Proxy_Function &t_pf)
|
||||
@ -305,7 +294,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
|
||||
static bool has_parse_tree(const chaiscript::Const_Proxy_Function &t_pf)
|
||||
static bool has_parse_tree(const chaiscript::Const_Proxy_Function &t_pf) noexcept
|
||||
{
|
||||
const auto pf = std::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf);
|
||||
return bool(pf);
|
||||
|
||||
@ -44,19 +44,19 @@ namespace chaiscript
|
||||
template<typename Container, typename IterType>
|
||||
struct Bidir_Range
|
||||
{
|
||||
typedef Container container_type;
|
||||
using container_type = Container;
|
||||
|
||||
Bidir_Range(Container &c)
|
||||
constexpr Bidir_Range(Container &c)
|
||||
: m_begin(c.begin()), m_end(c.end())
|
||||
{
|
||||
}
|
||||
|
||||
bool empty() const
|
||||
constexpr bool empty() const noexcept
|
||||
{
|
||||
return m_begin == m_end;
|
||||
}
|
||||
|
||||
void pop_front()
|
||||
constexpr void pop_front()
|
||||
{
|
||||
if (empty())
|
||||
{
|
||||
@ -65,7 +65,7 @@ namespace chaiscript
|
||||
++m_begin;
|
||||
}
|
||||
|
||||
void pop_back()
|
||||
constexpr void pop_back()
|
||||
{
|
||||
if (empty())
|
||||
{
|
||||
@ -74,7 +74,7 @@ namespace chaiscript
|
||||
--m_end;
|
||||
}
|
||||
|
||||
decltype(auto) front() const
|
||||
constexpr decltype(auto) front() const
|
||||
{
|
||||
if (empty())
|
||||
{
|
||||
@ -83,7 +83,7 @@ namespace chaiscript
|
||||
return (*m_begin);
|
||||
}
|
||||
|
||||
decltype(auto) back() const
|
||||
constexpr decltype(auto) back() const
|
||||
{
|
||||
if (empty())
|
||||
{
|
||||
@ -355,7 +355,7 @@ namespace chaiscript
|
||||
, "back");
|
||||
|
||||
|
||||
typedef void (ContainerType::*push_back)(const typename ContainerType::value_type &);
|
||||
using push_back = void (ContainerType::*)(const typename ContainerType::value_type &);
|
||||
m.add(fun(static_cast<push_back>(&ContainerType::push_back)),
|
||||
[&]()->std::string{
|
||||
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) {
|
||||
@ -395,8 +395,8 @@ namespace chaiscript
|
||||
template<typename ContainerType>
|
||||
void front_insertion_sequence_type(const std::string &type, Module& m)
|
||||
{
|
||||
typedef void (ContainerType::*push_ptr)(typename ContainerType::const_reference);
|
||||
typedef void (ContainerType::*pop_ptr)();
|
||||
using push_ptr = void (ContainerType::*)(typename ContainerType::const_reference);
|
||||
using pop_ptr = void (ContainerType::*)();
|
||||
|
||||
m.add(fun([](ContainerType &container)->decltype(auto){
|
||||
if (container.empty()) {
|
||||
@ -498,7 +498,7 @@ namespace chaiscript
|
||||
{
|
||||
m.add(fun(detail::count<ContainerType>), "count");
|
||||
|
||||
typedef size_t (ContainerType::*erase_ptr)(const typename ContainerType::key_type &);
|
||||
using erase_ptr = size_t (ContainerType::*)(const typename ContainerType::key_type &);
|
||||
|
||||
m.add(fun(static_cast<erase_ptr>(&ContainerType::erase)), "erase");
|
||||
|
||||
@ -529,8 +529,8 @@ namespace chaiscript
|
||||
{
|
||||
m.add(user_type<MapType>(), type);
|
||||
|
||||
typedef typename MapType::mapped_type &(MapType::*elem_access)(const typename MapType::key_type &);
|
||||
typedef const typename MapType::mapped_type &(MapType::*const_elem_access)(const typename MapType::key_type &) const;
|
||||
using elem_access = typename MapType::mapped_type &(MapType::*)(const typename MapType::key_type &);
|
||||
using const_elem_access = const typename MapType::mapped_type &(MapType::*)(const typename MapType::key_type &) const;
|
||||
|
||||
m.add(fun(static_cast<elem_access>(&MapType::operator[])), "[]");
|
||||
|
||||
|
||||
@ -27,7 +27,7 @@ namespace chaiscript
|
||||
// Cast_Helper_Inner helper classes
|
||||
|
||||
template<typename T>
|
||||
T* throw_if_null(T *t)
|
||||
constexpr T* throw_if_null(T *t)
|
||||
{
|
||||
if (t) { return t; }
|
||||
throw std::runtime_error("Attempted to dereference null Boxed_Value");
|
||||
|
||||
@ -59,6 +59,7 @@ namespace chaiscript
|
||||
#pragma GCC diagnostic ignored "-Wconversion"
|
||||
#pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||
#pragma GCC diagnostic ignored "-Wfloat-conversion"
|
||||
#pragma GCC diagnostic ignored "-Wswitch"
|
||||
#endif
|
||||
|
||||
/// \brief Represents any numeric type, generically. Used internally for generic operations between POD values
|
||||
@ -80,21 +81,18 @@ namespace chaiscript
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
static inline void check_divide_by_zero(T t, typename std::enable_if<std::is_integral<T>::value>::type* = nullptr)
|
||||
constexpr static inline void check_divide_by_zero([[maybe_unused]] T t)
|
||||
{
|
||||
#ifndef CHAISCRIPT_NO_PROTECT_DIVIDEBYZERO
|
||||
if (t == 0) {
|
||||
throw chaiscript::exception::arithmetic_error("divide by zero");
|
||||
if constexpr (!std::is_floating_point<T>::value) {
|
||||
if (t == 0) {
|
||||
throw chaiscript::exception::arithmetic_error("divide by zero");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static inline void check_divide_by_zero(T, typename std::enable_if<std::is_floating_point<T>::value>::type* = nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
static constexpr Common_Types get_common_type(size_t t_size, bool t_signed)
|
||||
constexpr static Common_Types get_common_type(size_t t_size, bool t_signed) noexcept
|
||||
{
|
||||
return (t_size == 1 && t_signed)?(Common_Types::t_int8)
|
||||
:(t_size == 1)?(Common_Types::t_uint8)
|
||||
@ -111,378 +109,234 @@ namespace chaiscript
|
||||
{
|
||||
const Type_Info &inp_ = t_bv.get_type_info();
|
||||
|
||||
if (inp_ == typeid(int)) {
|
||||
if (inp_ == user_type<int>()) {
|
||||
return get_common_type(sizeof(int), true);
|
||||
} else if (inp_ == typeid(double)) {
|
||||
} else if (inp_ == user_type<double>()) {
|
||||
return Common_Types::t_double;
|
||||
} else if (inp_ == typeid(long double)) {
|
||||
} else if (inp_ == user_type<long double>()) {
|
||||
return Common_Types::t_long_double;
|
||||
} else if (inp_ == typeid(float)) {
|
||||
} else if (inp_ == user_type<float>()) {
|
||||
return Common_Types::t_float;
|
||||
} else if (inp_ == typeid(char)) {
|
||||
} else if (inp_ == user_type<char>()) {
|
||||
return get_common_type(sizeof(char), std::is_signed<char>::value);
|
||||
} else if (inp_ == typeid(unsigned char)) {
|
||||
} else if (inp_ == user_type<unsigned char>()) {
|
||||
return get_common_type(sizeof(unsigned char), false);
|
||||
} else if (inp_ == typeid(unsigned int)) {
|
||||
} else if (inp_ == user_type<unsigned int>()) {
|
||||
return get_common_type(sizeof(unsigned int), false);
|
||||
} else if (inp_ == typeid(long)) {
|
||||
} else if (inp_ == user_type<long>()) {
|
||||
return get_common_type(sizeof(long), true);
|
||||
} else if (inp_ == typeid(long long)) {
|
||||
} else if (inp_ == user_type<long long>()) {
|
||||
return get_common_type(sizeof(long long), true);
|
||||
} else if (inp_ == typeid(unsigned long)) {
|
||||
} else if (inp_ == user_type<unsigned long>()) {
|
||||
return get_common_type(sizeof(unsigned long), false);
|
||||
} else if (inp_ == typeid(unsigned long long)) {
|
||||
} else if (inp_ == user_type<unsigned long long>()) {
|
||||
return get_common_type(sizeof(unsigned long long), false);
|
||||
} else if (inp_ == typeid(std::int8_t)) {
|
||||
} else if (inp_ == user_type<std::int8_t>()) {
|
||||
return Common_Types::t_int8;
|
||||
} else if (inp_ == typeid(std::int16_t)) {
|
||||
} else if (inp_ == user_type<std::int16_t>()) {
|
||||
return Common_Types::t_int16;
|
||||
} else if (inp_ == typeid(std::int32_t)) {
|
||||
} else if (inp_ == user_type<std::int32_t>()) {
|
||||
return Common_Types::t_int32;
|
||||
} else if (inp_ == typeid(std::int64_t)) {
|
||||
} else if (inp_ == user_type<std::int64_t>()) {
|
||||
return Common_Types::t_int64;
|
||||
} else if (inp_ == typeid(std::uint8_t)) {
|
||||
} else if (inp_ == user_type<std::uint8_t>()) {
|
||||
return Common_Types::t_uint8;
|
||||
} else if (inp_ == typeid(std::uint16_t)) {
|
||||
} else if (inp_ == user_type<std::uint16_t>()) {
|
||||
return Common_Types::t_uint16;
|
||||
} else if (inp_ == typeid(std::uint32_t)) {
|
||||
} else if (inp_ == user_type<std::uint32_t>()) {
|
||||
return Common_Types::t_uint32;
|
||||
} else if (inp_ == typeid(std::uint64_t)) {
|
||||
} else if (inp_ == user_type<std::uint64_t>()) {
|
||||
return Common_Types::t_uint64;
|
||||
} else if (inp_ == typeid(wchar_t)) {
|
||||
} else if (inp_ == user_type<wchar_t>()) {
|
||||
return get_common_type(sizeof(wchar_t), std::is_signed<wchar_t>::value);
|
||||
} else if (inp_ == typeid(char16_t)) {
|
||||
} else if (inp_ == user_type<char16_t>()) {
|
||||
return get_common_type(sizeof(char16_t), std::is_signed<char16_t>::value);
|
||||
} else if (inp_ == typeid(char32_t)) {
|
||||
} else if (inp_ == user_type<char32_t>()) {
|
||||
return get_common_type(sizeof(char32_t), std::is_signed<char32_t>::value);
|
||||
} else {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static Boxed_Value boolean_go(Operators::Opers t_oper, const T &t, const T &u)
|
||||
|
||||
|
||||
template<typename LHS, typename RHS>
|
||||
static auto go(Operators::Opers t_oper, const Boxed_Value &t_bv, LHS *t_lhs, const LHS &c_lhs, const RHS &c_rhs)
|
||||
{
|
||||
switch (t_oper)
|
||||
{
|
||||
switch (t_oper) {
|
||||
case Operators::Opers::equals:
|
||||
return const_var(t == u);
|
||||
return const_var(c_lhs == c_rhs);
|
||||
case Operators::Opers::less_than:
|
||||
return const_var(t < u);
|
||||
return const_var(c_lhs < c_rhs);
|
||||
case Operators::Opers::greater_than:
|
||||
return const_var(t > u);
|
||||
return const_var(c_lhs > c_rhs);
|
||||
case Operators::Opers::less_than_equal:
|
||||
return const_var(t <= u);
|
||||
return const_var(c_lhs <= c_rhs);
|
||||
case Operators::Opers::greater_than_equal:
|
||||
return const_var(t >= u);
|
||||
return const_var(c_lhs >= c_rhs);
|
||||
case Operators::Opers::not_equal:
|
||||
return const_var(t != u);
|
||||
default:
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static Boxed_Value unary_go(Operators::Opers t_oper, T &t, const Boxed_Value &t_lhs)
|
||||
{
|
||||
switch (t_oper)
|
||||
{
|
||||
case Operators::Opers::pre_increment:
|
||||
++t;
|
||||
break;
|
||||
case Operators::Opers::pre_decrement:
|
||||
--t;
|
||||
break;
|
||||
default:
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
|
||||
return t_lhs;
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
static Boxed_Value binary_go(Operators::Opers t_oper, T &t, const U &u, const Boxed_Value &t_lhs)
|
||||
{
|
||||
switch (t_oper)
|
||||
{
|
||||
case Operators::Opers::assign:
|
||||
t = u;
|
||||
break;
|
||||
case Operators::Opers::assign_product:
|
||||
t *= u;
|
||||
break;
|
||||
case Operators::Opers::assign_sum:
|
||||
t += u;
|
||||
break;
|
||||
case Operators::Opers::assign_quotient:
|
||||
check_divide_by_zero(u);
|
||||
t /= u;
|
||||
break;
|
||||
case Operators::Opers::assign_difference:
|
||||
t -= u;
|
||||
break;
|
||||
default:
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
|
||||
return t_lhs;
|
||||
}
|
||||
|
||||
template<typename T, typename U>
|
||||
static Boxed_Value binary_int_go(Operators::Opers t_oper, T &t, const U &u, const Boxed_Value &t_lhs)
|
||||
{
|
||||
switch (t_oper)
|
||||
{
|
||||
case Operators::Opers::assign_bitwise_and:
|
||||
t &= u;
|
||||
break;
|
||||
case Operators::Opers::assign_bitwise_or:
|
||||
t |= u;
|
||||
break;
|
||||
case Operators::Opers::assign_shift_left:
|
||||
t <<= u;
|
||||
break;
|
||||
case Operators::Opers::assign_shift_right:
|
||||
t >>= u;
|
||||
break;
|
||||
case Operators::Opers::assign_remainder:
|
||||
check_divide_by_zero(u);
|
||||
t %= u;
|
||||
break;
|
||||
case Operators::Opers::assign_bitwise_xor:
|
||||
t ^= u;
|
||||
break;
|
||||
default:
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
return t_lhs;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static Boxed_Value const_unary_int_go(Operators::Opers t_oper, const T &t)
|
||||
{
|
||||
switch (t_oper)
|
||||
{
|
||||
case Operators::Opers::bitwise_complement:
|
||||
return const_var(~t);
|
||||
default:
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static Boxed_Value const_binary_int_go(Operators::Opers t_oper, const T &t, const T &u)
|
||||
{
|
||||
switch (t_oper)
|
||||
{
|
||||
case Operators::Opers::shift_left:
|
||||
return const_var(t << u);
|
||||
case Operators::Opers::shift_right:
|
||||
return const_var(t >> u);
|
||||
case Operators::Opers::remainder:
|
||||
check_divide_by_zero(u);
|
||||
return const_var(t % u);
|
||||
case Operators::Opers::bitwise_and:
|
||||
return const_var(t & u);
|
||||
case Operators::Opers::bitwise_or:
|
||||
return const_var(t | u);
|
||||
case Operators::Opers::bitwise_xor:
|
||||
return const_var(t ^ u);
|
||||
default:
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static Boxed_Value const_unary_go(Operators::Opers t_oper, const T &t)
|
||||
{
|
||||
switch (t_oper)
|
||||
{
|
||||
case Operators::Opers::unary_minus:
|
||||
return const_var(-t);
|
||||
case Operators::Opers::unary_plus:
|
||||
return const_var(+t);
|
||||
default:
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static Boxed_Value const_binary_go(Operators::Opers t_oper, const T &t, const T &u)
|
||||
{
|
||||
switch (t_oper)
|
||||
{
|
||||
return const_var(c_lhs != c_rhs);
|
||||
case Operators::Opers::sum:
|
||||
return const_var(t + u);
|
||||
return const_var(c_lhs + c_rhs);
|
||||
case Operators::Opers::quotient:
|
||||
check_divide_by_zero(u);
|
||||
return const_var(t / u);
|
||||
check_divide_by_zero(c_rhs);
|
||||
return const_var(c_lhs / c_rhs);
|
||||
case Operators::Opers::product:
|
||||
return const_var(t * u);
|
||||
return const_var(c_lhs * c_rhs);
|
||||
case Operators::Opers::difference:
|
||||
return const_var(t - u);
|
||||
default:
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
return const_var(c_lhs - c_rhs);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename LHS, typename RHS>
|
||||
static auto go(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs)
|
||||
-> typename std::enable_if<!std::is_floating_point<LHS>::value && !std::is_floating_point<RHS>::value, Boxed_Value>::type
|
||||
{
|
||||
typedef typename std::common_type<LHS, RHS>::type common_type;
|
||||
if (t_oper > Operators::Opers::boolean_flag && t_oper < Operators::Opers::non_const_flag)
|
||||
{
|
||||
return boolean_go(t_oper, get_as_aux<common_type, LHS>(t_lhs), get_as_aux<common_type, RHS>(t_rhs));
|
||||
} else if (t_oper > Operators::Opers::non_const_flag && t_oper < Operators::Opers::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
|
||||
return binary_go(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), get_as_aux<common_type, RHS>(t_rhs), t_lhs);
|
||||
} else if (t_oper > Operators::Opers::non_const_int_flag && t_oper < Operators::Opers::const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
|
||||
return binary_int_go(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), get_as_aux<common_type, RHS>(t_rhs), t_lhs);
|
||||
} else if (t_oper > Operators::Opers::const_int_flag && t_oper < Operators::Opers::const_flag) {
|
||||
return const_binary_int_go(t_oper, get_as_aux<common_type, LHS>(t_lhs), get_as_aux<common_type, RHS>(t_rhs));
|
||||
} else if (t_oper > Operators::Opers::const_flag) {
|
||||
return const_binary_go(t_oper, get_as_aux<common_type, LHS>(t_lhs), get_as_aux<common_type, RHS>(t_rhs));
|
||||
} else {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
|
||||
if constexpr (!std::is_floating_point<LHS>::value && !std::is_floating_point<RHS>::value) {
|
||||
switch (t_oper) {
|
||||
case Operators::Opers::shift_left:
|
||||
return const_var(c_lhs << c_rhs);
|
||||
case Operators::Opers::shift_right:
|
||||
return const_var(c_lhs >> c_rhs);
|
||||
case Operators::Opers::remainder:
|
||||
check_divide_by_zero(c_rhs);
|
||||
return const_var(c_lhs % c_rhs);
|
||||
case Operators::Opers::bitwise_and:
|
||||
return const_var(c_lhs & c_rhs);
|
||||
case Operators::Opers::bitwise_or:
|
||||
return const_var(c_lhs | c_rhs);
|
||||
case Operators::Opers::bitwise_xor:
|
||||
return const_var(c_lhs ^ c_rhs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template<typename LHS, typename RHS>
|
||||
static auto go(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs)
|
||||
-> typename std::enable_if<std::is_floating_point<LHS>::value || std::is_floating_point<RHS>::value, Boxed_Value>::type
|
||||
{
|
||||
typedef typename std::common_type<LHS, RHS>::type common_type;
|
||||
if (t_oper > Operators::Opers::boolean_flag && t_oper < Operators::Opers::non_const_flag)
|
||||
{
|
||||
return boolean_go(t_oper, get_as_aux<common_type, LHS>(t_lhs), get_as_aux<common_type, RHS>(t_rhs));
|
||||
} else if (t_oper > Operators::Opers::non_const_flag && t_oper < Operators::Opers::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
|
||||
return binary_go(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), get_as_aux<common_type, RHS>(t_rhs), t_lhs);
|
||||
} else if (t_oper > Operators::Opers::const_flag) {
|
||||
return const_binary_go(t_oper, get_as_aux<common_type, LHS>(t_lhs), get_as_aux<common_type, RHS>(t_rhs));
|
||||
} else {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
}
|
||||
|
||||
// Unary
|
||||
template<typename LHS>
|
||||
static auto go(Operators::Opers t_oper, const Boxed_Value &t_lhs)
|
||||
-> typename std::enable_if<!std::is_floating_point<LHS>::value, Boxed_Value>::type
|
||||
{
|
||||
if (t_oper > Operators::Opers::non_const_flag && t_oper < Operators::Opers::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
|
||||
return unary_go(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), t_lhs);
|
||||
} else if (t_oper > Operators::Opers::const_int_flag && t_oper < Operators::Opers::const_flag) {
|
||||
return const_unary_int_go(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()));
|
||||
} else if (t_oper > Operators::Opers::const_flag) {
|
||||
return const_unary_go(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()));
|
||||
} else {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename LHS>
|
||||
static auto go(Operators::Opers t_oper, const Boxed_Value &t_lhs)
|
||||
-> typename std::enable_if<std::is_floating_point<LHS>::value, Boxed_Value>::type
|
||||
{
|
||||
if (t_oper > Operators::Opers::non_const_flag && t_oper < Operators::Opers::non_const_int_flag && !t_lhs.is_const() && !t_lhs.is_return_value()) {
|
||||
return unary_go(t_oper, *static_cast<LHS *>(t_lhs.get_ptr()), t_lhs);
|
||||
} else if (t_oper > Operators::Opers::const_flag) {
|
||||
return const_unary_go(t_oper, *static_cast<const LHS *>(t_lhs.get_const_ptr()));
|
||||
} else {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
}
|
||||
|
||||
template<typename LHS>
|
||||
inline static Boxed_Value oper_rhs(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs)
|
||||
{
|
||||
switch (get_common_type(t_rhs)) {
|
||||
case Common_Types::t_int32:
|
||||
return go<LHS, int32_t>(t_oper, t_lhs, t_rhs);
|
||||
case Common_Types::t_uint8:
|
||||
return go<LHS, uint8_t>(t_oper, t_lhs, t_rhs);
|
||||
case Common_Types::t_int8:
|
||||
return go<LHS, int8_t>(t_oper, t_lhs, t_rhs);
|
||||
case Common_Types::t_uint16:
|
||||
return go<LHS, uint16_t>(t_oper, t_lhs, t_rhs);
|
||||
case Common_Types::t_int16:
|
||||
return go<LHS, int16_t>(t_oper, t_lhs, t_rhs);
|
||||
case Common_Types::t_uint32:
|
||||
return go<LHS, uint32_t>(t_oper, t_lhs, t_rhs);
|
||||
case Common_Types::t_uint64:
|
||||
return go<LHS, uint64_t>(t_oper, t_lhs, t_rhs);
|
||||
case Common_Types::t_int64:
|
||||
return go<LHS, int64_t>(t_oper, t_lhs, t_rhs);
|
||||
case Common_Types::t_double:
|
||||
return go<LHS, double>(t_oper, t_lhs, t_rhs);
|
||||
case Common_Types::t_float:
|
||||
return go<LHS, float>(t_oper, t_lhs, t_rhs);
|
||||
case Common_Types::t_long_double:
|
||||
return go<LHS, long double>(t_oper, t_lhs, t_rhs);
|
||||
if (t_lhs) {
|
||||
switch (t_oper) {
|
||||
case Operators::Opers::assign:
|
||||
*t_lhs = c_rhs;
|
||||
return t_bv;
|
||||
case Operators::Opers::assign_product:
|
||||
*t_lhs *= c_rhs;
|
||||
return t_bv;
|
||||
case Operators::Opers::assign_sum:
|
||||
*t_lhs += c_rhs;
|
||||
return t_bv;
|
||||
case Operators::Opers::assign_quotient:
|
||||
check_divide_by_zero(c_rhs);
|
||||
*t_lhs /= c_rhs;
|
||||
return t_bv;
|
||||
case Operators::Opers::assign_difference:
|
||||
*t_lhs -= c_rhs;
|
||||
return t_bv;
|
||||
}
|
||||
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
if constexpr (!std::is_floating_point<LHS>::value && !std::is_floating_point<RHS>::value) {
|
||||
switch (t_oper) {
|
||||
case Operators::Opers::assign_bitwise_and:
|
||||
check_divide_by_zero(c_rhs);
|
||||
*t_lhs &= c_rhs;
|
||||
return t_bv;
|
||||
case Operators::Opers::assign_bitwise_or:
|
||||
*t_lhs |= c_rhs;
|
||||
return t_bv;
|
||||
case Operators::Opers::assign_shift_left:
|
||||
*t_lhs <<= c_rhs;
|
||||
return t_bv;
|
||||
case Operators::Opers::assign_shift_right:
|
||||
*t_lhs >>= c_rhs;
|
||||
return t_bv;
|
||||
case Operators::Opers::assign_remainder:
|
||||
*t_lhs %= c_rhs;
|
||||
return t_bv;
|
||||
case Operators::Opers::assign_bitwise_xor:
|
||||
*t_lhs ^= c_rhs;
|
||||
return t_bv;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
|
||||
template<typename Callable>
|
||||
inline static auto visit(const Boxed_Value &bv, Callable &&callable)
|
||||
{
|
||||
switch (get_common_type(bv)) {
|
||||
case Common_Types::t_int32:
|
||||
return callable(*static_cast<const std::int32_t *>(bv.get_const_ptr()));
|
||||
case Common_Types::t_uint8:
|
||||
return callable(*static_cast<const std::uint8_t *>(bv.get_const_ptr()));
|
||||
case Common_Types::t_int8:
|
||||
return callable(*static_cast<const std::int8_t *>(bv.get_const_ptr()));
|
||||
case Common_Types::t_uint16:
|
||||
return callable(*static_cast<const std::uint16_t *>(bv.get_const_ptr()));
|
||||
case Common_Types::t_int16:
|
||||
return callable(*static_cast<const std::int16_t *>(bv.get_const_ptr()));
|
||||
case Common_Types::t_uint32:
|
||||
return callable(*static_cast<const std::uint32_t *>(bv.get_const_ptr()));
|
||||
case Common_Types::t_uint64:
|
||||
return callable(*static_cast<const std::uint64_t *>(bv.get_const_ptr()));
|
||||
case Common_Types::t_int64:
|
||||
return callable(*static_cast<const std::int64_t *>(bv.get_const_ptr()));
|
||||
case Common_Types::t_double:
|
||||
return callable(*static_cast<const double *>(bv.get_const_ptr()));
|
||||
case Common_Types::t_float:
|
||||
return callable(*static_cast<const float *>(bv.get_const_ptr()));
|
||||
case Common_Types::t_long_double:
|
||||
return callable(*static_cast<const long double *>(bv.get_const_ptr()));
|
||||
default:
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
inline static Boxed_Value oper(Operators::Opers t_oper, const Boxed_Value &t_lhs)
|
||||
{
|
||||
switch (get_common_type(t_lhs)) {
|
||||
case Common_Types::t_int32:
|
||||
return go<int32_t>(t_oper, t_lhs);
|
||||
case Common_Types::t_uint8:
|
||||
return go<uint8_t>(t_oper, t_lhs);
|
||||
case Common_Types::t_int8:
|
||||
return go<int8_t>(t_oper, t_lhs);
|
||||
case Common_Types::t_uint16:
|
||||
return go<uint16_t>(t_oper, t_lhs);
|
||||
case Common_Types::t_int16:
|
||||
return go<int16_t>(t_oper, t_lhs);
|
||||
case Common_Types::t_uint32:
|
||||
return go<uint32_t>(t_oper, t_lhs);
|
||||
case Common_Types::t_uint64:
|
||||
return go<uint64_t>(t_oper, t_lhs);
|
||||
case Common_Types::t_int64:
|
||||
return go<int64_t>(t_oper, t_lhs);
|
||||
case Common_Types::t_double:
|
||||
return go<double>(t_oper, t_lhs);
|
||||
case Common_Types::t_float:
|
||||
return go<float>(t_oper, t_lhs);
|
||||
case Common_Types::t_long_double:
|
||||
return go<long double>(t_oper, t_lhs);
|
||||
}
|
||||
auto unary_operator = [t_oper, &t_lhs](const auto &c_lhs){
|
||||
auto *lhs = static_cast<std::decay_t<decltype(c_lhs)> *>(t_lhs.get_ptr());
|
||||
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
if (lhs) {
|
||||
switch (t_oper) {
|
||||
case Operators::Opers::pre_increment:
|
||||
++(*lhs);
|
||||
return t_lhs;
|
||||
case Operators::Opers::pre_decrement:
|
||||
--(*lhs);
|
||||
return t_lhs;
|
||||
}
|
||||
}
|
||||
|
||||
switch (t_oper) {
|
||||
case Operators::Opers::unary_minus:
|
||||
return const_var(-c_lhs);
|
||||
case Operators::Opers::unary_plus:
|
||||
return const_var(+c_lhs);
|
||||
}
|
||||
|
||||
if constexpr (!std::is_floating_point_v<std::decay_t<decltype(c_lhs)>>) {
|
||||
switch (t_oper) {
|
||||
case Operators::Opers::bitwise_complement:
|
||||
return const_var(~c_lhs);
|
||||
}
|
||||
}
|
||||
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
};
|
||||
|
||||
return visit(t_lhs, unary_operator);
|
||||
}
|
||||
|
||||
|
||||
inline static Boxed_Value oper(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs)
|
||||
{
|
||||
switch (get_common_type(t_lhs)) {
|
||||
case Common_Types::t_int32:
|
||||
return oper_rhs<int32_t>(t_oper, t_lhs, t_rhs);
|
||||
case Common_Types::t_uint8:
|
||||
return oper_rhs<uint8_t>(t_oper, t_lhs, t_rhs);
|
||||
case Common_Types::t_int8:
|
||||
return oper_rhs<int8_t>(t_oper, t_lhs, t_rhs);
|
||||
case Common_Types::t_uint16:
|
||||
return oper_rhs<uint16_t>(t_oper, t_lhs, t_rhs);
|
||||
case Common_Types::t_int16:
|
||||
return oper_rhs<int16_t>(t_oper, t_lhs, t_rhs);
|
||||
case Common_Types::t_uint32:
|
||||
return oper_rhs<uint32_t>(t_oper, t_lhs, t_rhs);
|
||||
case Common_Types::t_uint64:
|
||||
return oper_rhs<uint64_t>(t_oper, t_lhs, t_rhs);
|
||||
case Common_Types::t_int64:
|
||||
return oper_rhs<int64_t>(t_oper, t_lhs, t_rhs);
|
||||
case Common_Types::t_double:
|
||||
return oper_rhs<double>(t_oper, t_lhs, t_rhs);
|
||||
case Common_Types::t_float:
|
||||
return oper_rhs<float>(t_oper, t_lhs, t_rhs);
|
||||
case Common_Types::t_long_double:
|
||||
return oper_rhs<long double>(t_oper, t_lhs, t_rhs);
|
||||
}
|
||||
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
auto lhs_visit = [t_oper, &t_lhs, &t_rhs](const auto &c_lhs){
|
||||
auto *lhs = t_lhs.is_return_value()?nullptr:static_cast<std::decay_t<decltype(c_lhs)> *>(t_lhs.get_ptr());
|
||||
|
||||
auto rhs_visit = [t_oper, &t_lhs, lhs, &c_lhs](const auto &c_rhs) {
|
||||
return go(t_oper, t_lhs, lhs, c_lhs, c_rhs);
|
||||
};
|
||||
|
||||
return visit(t_rhs, rhs_visit);
|
||||
};
|
||||
|
||||
return visit(t_lhs, lhs_visit);
|
||||
}
|
||||
|
||||
template<typename Target, typename Source>
|
||||
@ -529,11 +383,11 @@ namespace chaiscript
|
||||
{
|
||||
const Type_Info &inp_ = t_bv.get_type_info();
|
||||
|
||||
if (inp_ == typeid(double)) {
|
||||
if (inp_ == user_type<double>()) {
|
||||
return true;
|
||||
} else if (inp_ == typeid(long double)) {
|
||||
} else if (inp_ == user_type<long double>()) {
|
||||
return true;
|
||||
} else if (inp_ == typeid(float)) {
|
||||
} else if (inp_ == user_type<float>()) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@ -542,49 +396,49 @@ namespace chaiscript
|
||||
|
||||
Boxed_Number get_as(const Type_Info &inp_) const
|
||||
{
|
||||
if (inp_.bare_equal_type_info(typeid(int))) {
|
||||
if (inp_.bare_equal(user_type<int>())) {
|
||||
return Boxed_Number(get_as<int>());
|
||||
} else if (inp_.bare_equal_type_info(typeid(double))) {
|
||||
} else if (inp_.bare_equal(user_type<double>())) {
|
||||
return Boxed_Number(get_as<double>());
|
||||
} else if (inp_.bare_equal_type_info(typeid(float))) {
|
||||
} else if (inp_.bare_equal(user_type<float>())) {
|
||||
return Boxed_Number(get_as<float>());
|
||||
} else if (inp_.bare_equal_type_info(typeid(long double))) {
|
||||
} else if (inp_.bare_equal(user_type<long double>())) {
|
||||
return Boxed_Number(get_as<long double>());
|
||||
} else if (inp_.bare_equal_type_info(typeid(char))) {
|
||||
} else if (inp_.bare_equal(user_type<char>())) {
|
||||
return Boxed_Number(get_as<char>());
|
||||
} else if (inp_.bare_equal_type_info(typeid(unsigned char))) {
|
||||
} else if (inp_.bare_equal(user_type<unsigned char>())) {
|
||||
return Boxed_Number(get_as<unsigned char>());
|
||||
} else if (inp_.bare_equal_type_info(typeid(wchar_t))) {
|
||||
} else if (inp_.bare_equal(user_type<wchar_t>())) {
|
||||
return Boxed_Number(get_as<wchar_t>());
|
||||
} else if (inp_.bare_equal_type_info(typeid(char16_t))) {
|
||||
} else if (inp_.bare_equal(user_type<char16_t>())) {
|
||||
return Boxed_Number(get_as<char16_t>());
|
||||
} else if (inp_.bare_equal_type_info(typeid(char32_t))) {
|
||||
} else if (inp_.bare_equal(user_type<char32_t>())) {
|
||||
return Boxed_Number(get_as<char32_t>());
|
||||
} else if (inp_.bare_equal_type_info(typeid(unsigned int))) {
|
||||
} else if (inp_.bare_equal(user_type<unsigned int>())) {
|
||||
return Boxed_Number(get_as<unsigned int>());
|
||||
} else if (inp_.bare_equal_type_info(typeid(long))) {
|
||||
} else if (inp_.bare_equal(user_type<long>())) {
|
||||
return Boxed_Number(get_as<long>());
|
||||
} else if (inp_.bare_equal_type_info(typeid(long long))) {
|
||||
} else if (inp_.bare_equal(user_type<long long>())) {
|
||||
return Boxed_Number(get_as<long long>());
|
||||
} else if (inp_.bare_equal_type_info(typeid(unsigned long))) {
|
||||
} else if (inp_.bare_equal(user_type<unsigned long>())) {
|
||||
return Boxed_Number(get_as<unsigned long>());
|
||||
} else if (inp_.bare_equal_type_info(typeid(unsigned long long))) {
|
||||
} else if (inp_.bare_equal(user_type<unsigned long long>())) {
|
||||
return Boxed_Number(get_as<unsigned long long>());
|
||||
} else if (inp_.bare_equal_type_info(typeid(int8_t))) {
|
||||
} else if (inp_.bare_equal(user_type<int8_t>())) {
|
||||
return Boxed_Number(get_as<int8_t>());
|
||||
} else if (inp_.bare_equal_type_info(typeid(int16_t))) {
|
||||
} else if (inp_.bare_equal(user_type<int16_t>())) {
|
||||
return Boxed_Number(get_as<int16_t>());
|
||||
} else if (inp_.bare_equal_type_info(typeid(int32_t))) {
|
||||
} else if (inp_.bare_equal(user_type<int32_t>())) {
|
||||
return Boxed_Number(get_as<int32_t>());
|
||||
} else if (inp_.bare_equal_type_info(typeid(int64_t))) {
|
||||
} else if (inp_.bare_equal(user_type<int64_t>())) {
|
||||
return Boxed_Number(get_as<int64_t>());
|
||||
} else if (inp_.bare_equal_type_info(typeid(uint8_t))) {
|
||||
} else if (inp_.bare_equal(user_type<uint8_t>())) {
|
||||
return Boxed_Number(get_as<uint8_t>());
|
||||
} else if (inp_.bare_equal_type_info(typeid(uint16_t))) {
|
||||
} else if (inp_.bare_equal(user_type<uint16_t>())) {
|
||||
return Boxed_Number(get_as<uint16_t>());
|
||||
} else if (inp_.bare_equal_type_info(typeid(uint32_t))) {
|
||||
} else if (inp_.bare_equal(user_type<uint32_t>())) {
|
||||
return Boxed_Number(get_as<uint32_t>());
|
||||
} else if (inp_.bare_equal_type_info(typeid(uint64_t))) {
|
||||
} else if (inp_.bare_equal(user_type<uint64_t>())) {
|
||||
return Boxed_Number(get_as<uint64_t>());
|
||||
} else {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
@ -716,7 +570,7 @@ namespace chaiscript
|
||||
static void validate_boxed_number(const Boxed_Value &v)
|
||||
{
|
||||
const Type_Info &inp_ = v.get_type_info();
|
||||
if (inp_ == typeid(bool))
|
||||
if (inp_ == user_type<bool>())
|
||||
{
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
|
||||
@ -208,14 +208,14 @@ namespace chaiscript
|
||||
Boxed_Value(const Boxed_Value&) = default;
|
||||
Boxed_Value& operator=(const Boxed_Value&) = default;
|
||||
|
||||
void swap(Boxed_Value &rhs)
|
||||
void swap(Boxed_Value &rhs) noexcept
|
||||
{
|
||||
std::swap(m_data, rhs.m_data);
|
||||
}
|
||||
|
||||
/// Copy the values stored in rhs.m_data to m_data.
|
||||
/// m_data pointers are not shared in this case
|
||||
Boxed_Value assign(const Boxed_Value &rhs)
|
||||
Boxed_Value assign(const Boxed_Value &rhs) noexcept
|
||||
{
|
||||
(*m_data) = (*rhs.m_data);
|
||||
return *this;
|
||||
@ -244,7 +244,7 @@ namespace chaiscript
|
||||
|
||||
|
||||
template<typename T>
|
||||
auto pointer_sentinel(std::shared_ptr<T> &ptr) const
|
||||
auto pointer_sentinel(std::shared_ptr<T> &ptr) const noexcept
|
||||
{
|
||||
struct Sentinel {
|
||||
Sentinel(std::shared_ptr<T> &t_ptr, Data &data)
|
||||
@ -263,7 +263,7 @@ namespace chaiscript
|
||||
Sentinel& operator=(Sentinel&&s) = default;
|
||||
Sentinel(Sentinel &&s) = default;
|
||||
|
||||
operator std::shared_ptr<T>&() const
|
||||
operator std::shared_ptr<T>&() const noexcept
|
||||
{
|
||||
return m_ptr.get();
|
||||
}
|
||||
@ -308,7 +308,7 @@ namespace chaiscript
|
||||
return !is_ref();
|
||||
}
|
||||
|
||||
void *get_ptr() const noexcept
|
||||
void *get_ptr() const noexcept
|
||||
{
|
||||
return m_data->m_data_ptr;
|
||||
}
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
#include <set>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <string_view>
|
||||
#include <typeinfo>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
@ -180,9 +181,9 @@ namespace chaiscript
|
||||
|
||||
|
||||
//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;
|
||||
}
|
||||
|
||||
@ -196,15 +197,15 @@ namespace chaiscript
|
||||
apply_globals(m_globals.begin(), m_globals.end(), t_engine);
|
||||
}
|
||||
|
||||
bool has_function(const Proxy_Function &new_f, const std::string &name)
|
||||
bool has_function(const Proxy_Function &new_f, const std::string_view &name) noexcept
|
||||
{
|
||||
return std::any_of(m_funcs.begin(), m_funcs.end(),
|
||||
return std::any_of(m_funcs.begin(), m_funcs.end(),
|
||||
[&](const std::pair<Proxy_Function, std::string> &existing_f) {
|
||||
return existing_f.second == name && *(existing_f.first) == *(new_f);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private:
|
||||
std::vector<std::pair<Type_Info, std::string>> m_typeinfos;
|
||||
@ -214,14 +215,14 @@ namespace chaiscript
|
||||
std::vector<Type_Conversion> m_conversions;
|
||||
|
||||
template<typename T, typename InItr>
|
||||
static void apply(InItr begin, const InItr end, T &t)
|
||||
static void apply(InItr begin, const InItr end, T &t)
|
||||
{
|
||||
for_each(begin, end,
|
||||
for_each(begin, end,
|
||||
[&t](const auto &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
|
||||
/// \todo Should we throw an error if there's a name conflict
|
||||
/// while applying a module?
|
||||
}
|
||||
}
|
||||
@ -260,12 +261,12 @@ namespace chaiscript
|
||||
};
|
||||
|
||||
/// Convenience typedef for Module objects to be added to the ChaiScript runtime
|
||||
typedef std::shared_ptr<Module> ModulePtr;
|
||||
using ModulePtr = std::shared_ptr<Module>;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
/// A Proxy_Function implementation that is able to take
|
||||
/// a vector of Proxy_Functions and perform a dispatch on them. It is
|
||||
/// 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 final : public dispatch::Proxy_Function_Base
|
||||
{
|
||||
@ -276,7 +277,7 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
bool operator==(const dispatch::Proxy_Function_Base &rhs) const override
|
||||
bool operator==(const dispatch::Proxy_Function_Base &rhs) const noexcept override
|
||||
{
|
||||
try {
|
||||
const auto &dispatch_fun = dynamic_cast<const Dispatch_Function &>(rhs);
|
||||
@ -292,7 +293,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
|
||||
static int calculate_arity(const std::vector<Proxy_Function> &t_funcs)
|
||||
static int calculate_arity(const std::vector<Proxy_Function> &t_funcs) noexcept
|
||||
{
|
||||
if (t_funcs.empty()) {
|
||||
return -1;
|
||||
@ -312,7 +313,7 @@ namespace chaiscript
|
||||
return arity;
|
||||
}
|
||||
|
||||
bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const override
|
||||
bool call_match(const std::vector<Boxed_Value> &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); });
|
||||
@ -385,13 +386,13 @@ namespace chaiscript
|
||||
|
||||
template <class T>
|
||||
using SmallVector = std::vector<T>;
|
||||
|
||||
|
||||
typedef SmallVector<std::pair<std::string, Boxed_Value>> Scope;
|
||||
typedef SmallVector<Scope> StackData;
|
||||
typedef SmallVector<StackData> Stacks;
|
||||
typedef SmallVector<Boxed_Value> Call_Param_List;
|
||||
typedef SmallVector<Call_Param_List> Call_Params;
|
||||
|
||||
using Scope = SmallVector<std::pair<std::string, Boxed_Value>>;
|
||||
using StackData = SmallVector<Scope>;
|
||||
using Stacks = SmallVector<StackData>;
|
||||
using Call_Param_List = SmallVector<Boxed_Value>;
|
||||
using Call_Params = SmallVector<Call_Param_List>;
|
||||
|
||||
Stack_Holder()
|
||||
{
|
||||
@ -438,16 +439,16 @@ namespace chaiscript
|
||||
{
|
||||
|
||||
public:
|
||||
typedef std::map<std::string, chaiscript::Type_Info> Type_Name_Map;
|
||||
typedef std::vector<std::pair<std::string, Boxed_Value>> Scope;
|
||||
typedef Stack_Holder::StackData StackData;
|
||||
using Type_Name_Map = std::map<std::string, chaiscript::Type_Info, str_less>;
|
||||
using Scope = std::vector<std::pair<std::string, Boxed_Value>>;
|
||||
using StackData = Stack_Holder::StackData;
|
||||
|
||||
struct State
|
||||
{
|
||||
std::vector<std::pair<std::string, std::shared_ptr<std::vector<Proxy_Function>>>> m_functions;
|
||||
std::vector<std::pair<std::string, Proxy_Function>> m_function_objects;
|
||||
std::vector<std::pair<std::string, Boxed_Value>> m_boxed_functions;
|
||||
std::map<std::string, Boxed_Value> m_global_objects;
|
||||
std::map<std::string, Boxed_Value, str_less> m_global_objects;
|
||||
Type_Name_Map m_types;
|
||||
};
|
||||
|
||||
@ -515,8 +516,7 @@ namespace chaiscript
|
||||
throw chaiscript::exception::name_conflict_error(t_name);
|
||||
}
|
||||
|
||||
stack_elem.emplace_back(t_name, std::move(obj));
|
||||
return stack_elem.back().second;
|
||||
return stack_elem.emplace_back(t_name, std::move(obj)).second;
|
||||
}
|
||||
|
||||
|
||||
@ -654,7 +654,7 @@ namespace chaiscript
|
||||
/// 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, std::atomic_uint_fast32_t &t_loc, Stack_Holder &t_holder) const
|
||||
Boxed_Value get_object(const std::string_view &name, std::atomic_uint_fast32_t &t_loc, Stack_Holder &t_holder) const
|
||||
{
|
||||
enum class Loc : uint_fast32_t {
|
||||
located = 0x80000000,
|
||||
@ -719,7 +719,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
/// Returns the type info for a named type
|
||||
Type_Info get_type(const std::string &name, bool t_throw = true) const
|
||||
Type_Info get_type(std::string_view name, bool t_throw = true) const
|
||||
{
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
@ -731,7 +731,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
if (t_throw) {
|
||||
throw std::range_error("Type Not Known: " + name);
|
||||
throw std::range_error("Type Not Known: " + std::string(name));
|
||||
} else {
|
||||
return Type_Info();
|
||||
}
|
||||
@ -776,7 +776,7 @@ namespace chaiscript
|
||||
|
||||
|
||||
/// Return a function by name
|
||||
std::pair<size_t, std::shared_ptr<std::vector< Proxy_Function>>> get_function(const std::string &t_name, const size_t t_hint) const
|
||||
std::pair<size_t, std::shared_ptr<std::vector< Proxy_Function>>> get_function(const std::string_view &t_name, const size_t t_hint) const
|
||||
{
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
@ -804,7 +804,7 @@ namespace chaiscript
|
||||
/// \returns a function object (Boxed_Value wrapper) if it exists
|
||||
/// \throws std::range_error if it does not
|
||||
/// \warn does not obtain a mutex lock. \sa get_function_object for public version
|
||||
std::pair<size_t, Boxed_Value> get_function_object_int(const std::string &t_name, const size_t t_hint) const
|
||||
std::pair<size_t, Boxed_Value> get_function_object_int(const std::string_view &t_name, const size_t t_hint) const
|
||||
{
|
||||
const auto &funs = get_boxed_functions_int();
|
||||
|
||||
@ -814,13 +814,13 @@ namespace chaiscript
|
||||
{
|
||||
return std::make_pair(std::distance(funs.begin(), itr), itr->second);
|
||||
} else {
|
||||
throw std::range_error("Object not found: " + t_name);
|
||||
throw std::range_error("Object not found: " + std::string(t_name));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Return true if a function exists
|
||||
bool function_exists(const std::string &name) const
|
||||
bool function_exists(const std::string_view &name) const
|
||||
{
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
@ -930,13 +930,13 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
|
||||
const Type_Conversions &conversions() const
|
||||
const Type_Conversions &conversions() const noexcept
|
||||
{
|
||||
return m_conversions;
|
||||
}
|
||||
|
||||
static bool is_attribute_call(const std::vector<Proxy_Function> &t_funs, const std::vector<Boxed_Value> &t_params,
|
||||
bool t_has_params, const Type_Conversions_State &t_conversions)
|
||||
bool t_has_params, const Type_Conversions_State &t_conversions) noexcept
|
||||
{
|
||||
if (!t_has_params || t_params.empty()) {
|
||||
return false;
|
||||
@ -1049,7 +1049,7 @@ namespace chaiscript
|
||||
if (!functions.empty()) {
|
||||
try {
|
||||
if (is_no_param) {
|
||||
std::vector<Boxed_Value> tmp_params(params);
|
||||
auto tmp_params(params);
|
||||
tmp_params.insert(tmp_params.begin() + 1, var(t_name));
|
||||
return do_attribute_call(2, tmp_params, functions, t_conversions);
|
||||
} else {
|
||||
@ -1076,14 +1076,13 @@ namespace chaiscript
|
||||
|
||||
|
||||
|
||||
Boxed_Value call_function(const std::string &t_name, std::atomic_uint_fast32_t &t_loc, const std::vector<Boxed_Value> ¶ms,
|
||||
Boxed_Value call_function(const std::string_view &t_name, std::atomic_uint_fast32_t &t_loc, const std::vector<Boxed_Value> ¶ms,
|
||||
const Type_Conversions_State &t_conversions) const
|
||||
{
|
||||
uint_fast32_t loc = t_loc;
|
||||
const auto funs = get_function(t_name, loc);
|
||||
if (funs.first != loc) { t_loc = uint_fast32_t(funs.first);
|
||||
}
|
||||
return dispatch::dispatch(*funs.second, params, t_conversions);
|
||||
const auto [func_loc, func] = get_function(t_name, loc);
|
||||
if (func_loc != loc) { t_loc = uint_fast32_t(func_loc); }
|
||||
return dispatch::dispatch(*func, params, t_conversions);
|
||||
}
|
||||
|
||||
|
||||
@ -1102,12 +1101,12 @@ namespace chaiscript
|
||||
/// Dump function to stdout
|
||||
void dump_function(const std::pair<const std::string, Proxy_Function > &f) const
|
||||
{
|
||||
std::vector<Type_Info> params = f.second->get_param_types();
|
||||
const auto params = f.second->get_param_types();
|
||||
|
||||
dump_type(params.front());
|
||||
std::cout << " " << f.first << "(";
|
||||
|
||||
for (std::vector<Type_Info>::const_iterator itr = params.begin() + 1;
|
||||
for (auto itr = params.begin() + 1;
|
||||
itr != params.end();
|
||||
)
|
||||
{
|
||||
@ -1132,7 +1131,7 @@ namespace chaiscript
|
||||
throw chaiscript::exception::arity_error(static_cast<int>(params.size()), 1);
|
||||
}
|
||||
|
||||
const Const_Proxy_Function &f = this->boxed_cast<Const_Proxy_Function>(params[0]);
|
||||
const auto &f = this->boxed_cast<Const_Proxy_Function>(params[0]);
|
||||
const Type_Conversions_State convs(m_conversions, m_conversions.conversion_saves());
|
||||
|
||||
return const_var(f->call_match(std::vector<Boxed_Value>(params.begin() + 1, params.end()), convs));
|
||||
@ -1142,15 +1141,15 @@ namespace chaiscript
|
||||
void dump_system() const
|
||||
{
|
||||
std::cout << "Registered Types: \n";
|
||||
for (auto const &type: get_types())
|
||||
for (const auto &[type_name, type] : get_types() )
|
||||
{
|
||||
std::cout << type.first << ": " << type.second.bare_name() << '\n';
|
||||
std::cout << type_name << ": " << type.bare_name() << '\n';
|
||||
}
|
||||
|
||||
std::cout << '\n';
|
||||
std::cout << '\n';
|
||||
|
||||
std::cout << "Functions: \n";
|
||||
for (auto const &func: get_functions())
|
||||
for (const auto &func : get_functions())
|
||||
{
|
||||
dump_function(func);
|
||||
}
|
||||
@ -1158,7 +1157,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
/// 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
|
||||
bool is_type(const Boxed_Value &r, const std::string_view &user_typename) const noexcept
|
||||
{
|
||||
try {
|
||||
if (get_type(user_typename).bare_equal(r.get_type_info()))
|
||||
@ -1264,66 +1263,66 @@ namespace chaiscript
|
||||
pop_function_call(*m_stack_holder, m_conversions.conversion_saves());
|
||||
}
|
||||
|
||||
Stack_Holder &get_stack_holder()
|
||||
Stack_Holder &get_stack_holder() noexcept
|
||||
{
|
||||
return *m_stack_holder;
|
||||
}
|
||||
|
||||
/// Returns the current stack
|
||||
/// make const/non const versions
|
||||
const StackData &get_stack_data() const
|
||||
const StackData &get_stack_data() const noexcept
|
||||
{
|
||||
return m_stack_holder->stacks.back();
|
||||
}
|
||||
|
||||
static StackData &get_stack_data(Stack_Holder &t_holder)
|
||||
static StackData &get_stack_data(Stack_Holder &t_holder) noexcept
|
||||
{
|
||||
return t_holder.stacks.back();
|
||||
}
|
||||
|
||||
StackData &get_stack_data()
|
||||
StackData &get_stack_data() noexcept
|
||||
{
|
||||
return m_stack_holder->stacks.back();
|
||||
}
|
||||
|
||||
parser::ChaiScript_Parser_Base &get_parser()
|
||||
parser::ChaiScript_Parser_Base &get_parser() noexcept
|
||||
{
|
||||
return m_parser.get();
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
const std::vector<std::pair<std::string, Boxed_Value>> &get_boxed_functions_int() const
|
||||
const std::vector<std::pair<std::string, Boxed_Value>> &get_boxed_functions_int() const noexcept
|
||||
{
|
||||
return m_state.m_boxed_functions;
|
||||
}
|
||||
|
||||
std::vector<std::pair<std::string, Boxed_Value>> &get_boxed_functions_int()
|
||||
std::vector<std::pair<std::string, Boxed_Value>> &get_boxed_functions_int() noexcept
|
||||
{
|
||||
return m_state.m_boxed_functions;
|
||||
}
|
||||
|
||||
const std::vector<std::pair<std::string, Proxy_Function>> &get_function_objects_int() const
|
||||
const std::vector<std::pair<std::string, Proxy_Function>> &get_function_objects_int() const noexcept
|
||||
{
|
||||
return m_state.m_function_objects;
|
||||
}
|
||||
|
||||
std::vector<std::pair<std::string, Proxy_Function>> &get_function_objects_int()
|
||||
std::vector<std::pair<std::string, Proxy_Function>> &get_function_objects_int() noexcept
|
||||
{
|
||||
return m_state.m_function_objects;
|
||||
}
|
||||
|
||||
const std::vector<std::pair<std::string, std::shared_ptr<std::vector<Proxy_Function>>>> &get_functions_int() const
|
||||
const std::vector<std::pair<std::string, std::shared_ptr<std::vector<Proxy_Function>>>> &get_functions_int() const noexcept
|
||||
{
|
||||
return m_state.m_functions;
|
||||
}
|
||||
|
||||
std::vector<std::pair<std::string, std::shared_ptr<std::vector<Proxy_Function>>>> &get_functions_int()
|
||||
std::vector<std::pair<std::string, std::shared_ptr<std::vector<Proxy_Function>>>> &get_functions_int() noexcept
|
||||
{
|
||||
return m_state.m_functions;
|
||||
}
|
||||
|
||||
static bool function_less_than(const Proxy_Function &lhs, const Proxy_Function &rhs)
|
||||
static bool function_less_than(const Proxy_Function &lhs, const Proxy_Function &rhs) noexcept
|
||||
{
|
||||
|
||||
auto dynamic_lhs(std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(lhs));
|
||||
@ -1355,8 +1354,8 @@ namespace chaiscript
|
||||
const auto lhssize = lhsparamtypes.size();
|
||||
const auto rhssize = rhsparamtypes.size();
|
||||
|
||||
static const auto boxed_type = user_type<Boxed_Value>();
|
||||
static const auto boxed_pod_type = user_type<Boxed_Number>();
|
||||
constexpr const auto boxed_type = user_type<Boxed_Value>();
|
||||
constexpr const auto boxed_pod_type = user_type<Boxed_Number>();
|
||||
|
||||
for (size_t i = 1; i < lhssize && i < rhssize; ++i)
|
||||
{
|
||||
@ -1418,13 +1417,13 @@ namespace chaiscript
|
||||
t_c.reserve(t_c.size() + 1); // tightly control growth of memory usage here
|
||||
t_c.emplace_back(t_key, std::forward<Value>(t_value));
|
||||
} else {
|
||||
typedef typename Container::value_type value_type;
|
||||
using value_type = typename Container::value_type;
|
||||
*itr = value_type(t_key, std::forward<Value>(t_value));
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Container, typename Key>
|
||||
static typename Container::iterator find_keyed_value(Container &t_c, const Key &t_key)
|
||||
static typename Container::iterator find_keyed_value(Container &t_c, const Key &t_key) noexcept
|
||||
{
|
||||
return std::find_if(t_c.begin(), t_c.end(),
|
||||
[&t_key](const typename Container::value_type &o) {
|
||||
@ -1433,16 +1432,16 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
template<typename Container, typename Key>
|
||||
static typename Container::const_iterator find_keyed_value(const Container &t_c, const Key &t_key)
|
||||
static typename Container::const_iterator find_keyed_value(const Container &t_c, const Key &t_key) noexcept
|
||||
{
|
||||
return std::find_if(t_c.begin(), t_c.end(),
|
||||
[&t_key](const typename Container::value_type &o) {
|
||||
return o.first == t_key;
|
||||
return std::equal(o.first.begin(), o.first.end(), t_key.begin(), t_key.end());
|
||||
});
|
||||
}
|
||||
|
||||
template<typename Container, typename Key>
|
||||
static typename Container::const_iterator find_keyed_value(const Container &t_c, const Key &t_key, const size_t t_hint)
|
||||
static typename Container::const_iterator find_keyed_value(const Container &t_c, const Key &t_key, const size_t t_hint) noexcept
|
||||
{
|
||||
if (t_c.size() > t_hint && t_c[t_hint].first == t_key) {
|
||||
return std::next(t_c.begin(), static_cast<typename std::iterator_traits<typename Container::const_iterator>::difference_type>(t_hint));
|
||||
@ -1519,23 +1518,23 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
Dispatch_Engine *operator->() const {
|
||||
Dispatch_Engine *operator->() const noexcept {
|
||||
return &m_engine.get();
|
||||
}
|
||||
|
||||
Dispatch_Engine &operator*() const {
|
||||
Dispatch_Engine &operator*() const noexcept {
|
||||
return m_engine.get();
|
||||
}
|
||||
|
||||
Stack_Holder &stack_holder() const {
|
||||
Stack_Holder &stack_holder() const noexcept {
|
||||
return m_stack_holder.get();
|
||||
}
|
||||
|
||||
const Type_Conversions_State &conversions() const {
|
||||
const Type_Conversions_State &conversions() const noexcept {
|
||||
return m_conversions;
|
||||
}
|
||||
|
||||
Type_Conversions::Conversion_Saves &conversion_saves() const {
|
||||
Type_Conversions::Conversion_Saves &conversion_saves() const noexcept {
|
||||
return m_conversions.saves();
|
||||
}
|
||||
|
||||
@ -1547,7 +1546,7 @@ namespace chaiscript
|
||||
return m_engine.get().add_object(t_name, std::move(obj), m_stack_holder.get());
|
||||
}
|
||||
|
||||
Boxed_Value get_object(const std::string &t_name, std::atomic_uint_fast32_t &t_loc) const {
|
||||
Boxed_Value get_object(const std::string_view &t_name, std::atomic_uint_fast32_t &t_loc) const {
|
||||
return m_engine.get().get_object(t_name, t_loc, m_stack_holder.get());
|
||||
}
|
||||
|
||||
|
||||
@ -50,17 +50,17 @@ namespace chaiscript
|
||||
|
||||
Dynamic_Object() = default;
|
||||
|
||||
bool is_explicit() const
|
||||
bool is_explicit() const noexcept
|
||||
{
|
||||
return m_option_explicit;
|
||||
}
|
||||
|
||||
void set_explicit(const bool t_explicit)
|
||||
void set_explicit(const bool t_explicit) noexcept
|
||||
{
|
||||
m_option_explicit = t_explicit;
|
||||
}
|
||||
|
||||
std::string get_type_name() const
|
||||
const std::string &get_type_name() const noexcept
|
||||
{
|
||||
return m_type_name;
|
||||
}
|
||||
|
||||
@ -71,7 +71,7 @@ namespace chaiscript
|
||||
Dynamic_Object_Function &operator=(const Dynamic_Object_Function) = delete;
|
||||
Dynamic_Object_Function(Dynamic_Object_Function &) = delete;
|
||||
|
||||
bool operator==(const Proxy_Function_Base &f) const override
|
||||
bool operator==(const Proxy_Function_Base &f) const noexcept override
|
||||
{
|
||||
if (const auto *df = dynamic_cast<const Dynamic_Object_Function *>(&f))
|
||||
{
|
||||
@ -81,9 +81,9 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
bool is_attribute_function() const override { return m_is_attribute; }
|
||||
bool is_attribute_function() const noexcept override { return m_is_attribute; }
|
||||
|
||||
bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const override
|
||||
bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const noexcept override
|
||||
{
|
||||
if (dynamic_object_typename_match(vals, m_type_name, m_ti, t_conversions))
|
||||
{
|
||||
@ -109,7 +109,7 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
bool compare_first_type(const Boxed_Value &bv, const Type_Conversions_State &t_conversions) const override
|
||||
bool compare_first_type(const Boxed_Value &bv, const Type_Conversions_State &t_conversions) const noexcept override
|
||||
{
|
||||
return dynamic_object_typename_match(bv, m_type_name, m_ti, t_conversions);
|
||||
}
|
||||
@ -127,7 +127,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
bool dynamic_object_typename_match(const Boxed_Value &bv, const std::string &name,
|
||||
const std::unique_ptr<Type_Info> &ti, const Type_Conversions_State &t_conversions) const
|
||||
const std::unique_ptr<Type_Info> &ti, const Type_Conversions_State &t_conversions) const noexcept
|
||||
{
|
||||
if (bv.get_type_info().bare_equal(m_doti))
|
||||
{
|
||||
@ -149,7 +149,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
bool dynamic_object_typename_match(const std::vector<Boxed_Value> &bvs, const std::string &name,
|
||||
const std::unique_ptr<Type_Info> &ti, const Type_Conversions_State &t_conversions) const
|
||||
const std::unique_ptr<Type_Info> &ti, const Type_Conversions_State &t_conversions) const noexcept
|
||||
{
|
||||
if (!bvs.empty())
|
||||
{
|
||||
@ -199,7 +199,7 @@ namespace chaiscript
|
||||
return std::vector<Type_Info>(begin, end);
|
||||
}
|
||||
|
||||
bool operator==(const Proxy_Function_Base &f) const override
|
||||
bool operator==(const Proxy_Function_Base &f) const noexcept override
|
||||
{
|
||||
const Dynamic_Object_Constructor *dc = dynamic_cast<const Dynamic_Object_Constructor*>(&f);
|
||||
return (dc != nullptr) && dc->m_type_name == m_type_name && (*dc->m_func) == (*m_func);
|
||||
|
||||
@ -46,7 +46,7 @@ namespace chaiscript
|
||||
{
|
||||
void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) override
|
||||
{
|
||||
(void)std::initializer_list<int>{(throw_type<T>(bv, t_engine), 0)...};
|
||||
(throw_type<T>(bv, t_engine), ...);
|
||||
}
|
||||
};
|
||||
}
|
||||
@ -101,7 +101,7 @@ namespace chaiscript
|
||||
///
|
||||
/// \sa chaiscript::exception_specification for creation of chaiscript::Exception_Handler objects
|
||||
/// \sa \ref exceptions
|
||||
typedef std::shared_ptr<detail::Exception_Handler_Base> Exception_Handler;
|
||||
using Exception_Handler = std::shared_ptr<detail::Exception_Handler_Base>;
|
||||
|
||||
/// \brief creates a chaiscript::Exception_Handler which handles one type of exception unboxing
|
||||
/// \sa \ref exceptions
|
||||
|
||||
@ -18,7 +18,6 @@
|
||||
#include "boxed_cast.hpp"
|
||||
#include "function_call_detail.hpp"
|
||||
#include "proxy_functions.hpp"
|
||||
#include "callable_traits.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
class Boxed_Value;
|
||||
@ -32,6 +31,15 @@ namespace chaiscript
|
||||
{
|
||||
namespace dispatch
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template<typename Ret, typename ... Param>
|
||||
constexpr auto arity(Ret (*)(Param...)) noexcept
|
||||
{
|
||||
return sizeof...(Param);
|
||||
}
|
||||
}
|
||||
|
||||
/// Build a function caller that knows how to dispatch on a set of functions
|
||||
/// example:
|
||||
/// std::function<void (int)> f =
|
||||
@ -43,7 +51,7 @@ namespace chaiscript
|
||||
{
|
||||
const bool has_arity_match = std::any_of(funcs.begin(), funcs.end(),
|
||||
[](const Const_Proxy_Function &f) {
|
||||
return f->get_arity() == -1 || size_t(f->get_arity()) == chaiscript::dispatch::detail::Arity<FunctionType>::arity;
|
||||
return f->get_arity() == -1 || size_t(f->get_arity()) == detail::arity(static_cast<FunctionType *>(nullptr));
|
||||
});
|
||||
|
||||
if (!has_arity_match) {
|
||||
|
||||
@ -129,7 +129,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
template<typename P>
|
||||
static Boxed_Value box(Boxed_Value bv)
|
||||
static Boxed_Value box(Boxed_Value bv) noexcept
|
||||
{
|
||||
return bv;
|
||||
}
|
||||
|
||||
124
include/chaiscript/dispatchkit/function_signature.hpp
Normal file
124
include/chaiscript/dispatchkit/function_signature.hpp
Normal file
@ -0,0 +1,124 @@
|
||||
#ifndef CHAISCRIPT_FUNCTION_SIGNATURE_HPP
|
||||
#define CHAISCRIPT_FUNCTION_SIGNATURE_HPP
|
||||
|
||||
#include <type_traits>
|
||||
|
||||
namespace chaiscript::dispatch::detail {
|
||||
template<typename ... Param>
|
||||
struct Function_Params
|
||||
{
|
||||
};
|
||||
|
||||
template<typename Ret, typename Params, bool IsNoExcept = false, bool IsMember = false, bool IsMemberObject = false, bool IsObject = false>
|
||||
struct Function_Signature {
|
||||
using Param_Types = Params;
|
||||
using Return_Type = Ret;
|
||||
constexpr static const bool is_object = IsObject;
|
||||
constexpr static const bool is_member_object = IsMemberObject;
|
||||
constexpr static const bool is_noexcept = IsNoExcept;
|
||||
template<typename T>
|
||||
constexpr Function_Signature(T &&) noexcept {}
|
||||
constexpr Function_Signature() noexcept = default;
|
||||
};
|
||||
|
||||
// Free functions
|
||||
|
||||
template<typename Ret, typename ... Param>
|
||||
Function_Signature(Ret (*f)(Param...)) -> Function_Signature<Ret, Function_Params<Param...>>;
|
||||
|
||||
template<typename Ret, typename ... Param>
|
||||
Function_Signature(Ret (*f)(Param...) noexcept) -> Function_Signature<Ret, Function_Params<Param...>, true>;
|
||||
|
||||
// no reference specifier
|
||||
|
||||
template<typename Ret, typename Class, typename ... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param ...) volatile) -> Function_Signature<Ret, Function_Params<volatile Class &, Param...>, false, true>;
|
||||
|
||||
template<typename Ret, typename Class, typename ... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param ...) volatile noexcept) -> Function_Signature<Ret, Function_Params<volatile Class &, Param...>, true, true>;
|
||||
|
||||
template<typename Ret, typename Class, typename ... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param ...) volatile const) -> Function_Signature<Ret, Function_Params<volatile const Class &, Param...>, false, true>;
|
||||
|
||||
template<typename Ret, typename Class, typename ... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param ...) volatile const noexcept) -> Function_Signature<Ret, Function_Params<volatile const Class &, Param...>, true, true>;
|
||||
|
||||
template<typename Ret, typename Class, typename ... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param ...) ) -> Function_Signature<Ret, Function_Params<Class &, Param...>, false, true>;
|
||||
|
||||
template<typename Ret, typename Class, typename ... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param ...) noexcept) -> Function_Signature<Ret, Function_Params<Class &, Param...>, true, true>;
|
||||
|
||||
template<typename Ret, typename Class, typename ... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param ...) const) -> Function_Signature<Ret, Function_Params<const Class &, Param...>, false, true>;
|
||||
|
||||
template<typename Ret, typename Class, typename ... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param ...) const noexcept) -> Function_Signature<Ret, Function_Params<const Class &, Param...>, true, true>;
|
||||
|
||||
// & reference specifier
|
||||
|
||||
template<typename Ret, typename Class, typename ... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param ...) volatile &) -> Function_Signature<Ret, Function_Params<volatile Class &, Param...>, false, true>;
|
||||
|
||||
template<typename Ret, typename Class, typename ... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param ...) volatile & noexcept) -> Function_Signature<Ret, Function_Params<volatile Class &, Param...>, true, true>;
|
||||
|
||||
template<typename Ret, typename Class, typename ... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param ...) volatile const &) -> Function_Signature<Ret, Function_Params<volatile const Class &, Param...>, false, true>;
|
||||
|
||||
template<typename Ret, typename Class, typename ... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param ...) volatile const & noexcept) -> Function_Signature<Ret, Function_Params<volatile const Class &, Param...>, true, true>;
|
||||
|
||||
template<typename Ret, typename Class, typename ... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param ...) & ) -> Function_Signature<Ret, Function_Params<Class &, Param...>, false, true>;
|
||||
|
||||
template<typename Ret, typename Class, typename ... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param ...) & noexcept) -> Function_Signature<Ret, Function_Params<Class &, Param...>, true, true>;
|
||||
|
||||
template<typename Ret, typename Class, typename ... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param ...) const &) -> Function_Signature<Ret, Function_Params<const Class &, Param...>, false, true>;
|
||||
|
||||
template<typename Ret, typename Class, typename ... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param ...) const & noexcept) -> Function_Signature<Ret, Function_Params<const Class &, Param...>, true, true>;
|
||||
|
||||
// && reference specifier
|
||||
|
||||
template<typename Ret, typename Class, typename ... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param ...) volatile &&) -> Function_Signature<Ret, Function_Params<volatile Class &&, Param...>, false, true>;
|
||||
|
||||
template<typename Ret, typename Class, typename ... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param ...) volatile && noexcept) -> Function_Signature<Ret, Function_Params<volatile Class &&, Param...>, true, true>;
|
||||
|
||||
template<typename Ret, typename Class, typename ... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param ...) volatile const &&) -> Function_Signature<Ret, Function_Params<volatile const Class &&, Param...>, false, true>;
|
||||
|
||||
template<typename Ret, typename Class, typename ... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param ...) volatile const && noexcept) -> Function_Signature<Ret, Function_Params<volatile const Class &&, Param...>, true, true>;
|
||||
|
||||
template<typename Ret, typename Class, typename ... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param ...) &&) -> Function_Signature<Ret, Function_Params<Class &&, Param...>, false, true>;
|
||||
|
||||
template<typename Ret, typename Class, typename ... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param ...) && noexcept) -> Function_Signature<Ret, Function_Params<Class &&, Param...>, true, true>;
|
||||
|
||||
template<typename Ret, typename Class, typename ... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param ...) const &&) -> Function_Signature<Ret, Function_Params<const Class &&, Param...>, false, true>;
|
||||
|
||||
template<typename Ret, typename Class, typename ... Param>
|
||||
Function_Signature(Ret (Class::*f)(Param ...) const && noexcept) -> Function_Signature<Ret, Function_Params<const Class &&, Param...>, true, true>;
|
||||
|
||||
template<typename Ret, typename Class>
|
||||
Function_Signature(Ret (Class::*f)) -> Function_Signature<Ret, Function_Params<Class &>, true, true, true>;
|
||||
|
||||
template<typename Func>
|
||||
Function_Signature(Func &&) -> Function_Signature<
|
||||
typename decltype(Function_Signature{&std::decay_t<Func>::operator()})::Return_Type,
|
||||
typename decltype(Function_Signature{&std::decay_t<Func>::operator()})::Param_Types,
|
||||
decltype(Function_Signature{&std::decay_t<Func>::operator()})::is_noexcept,
|
||||
false,
|
||||
false,
|
||||
true
|
||||
>;
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -199,7 +199,7 @@ namespace chaiscript
|
||||
template<>
|
||||
struct Handle_Return<Boxed_Value>
|
||||
{
|
||||
static Boxed_Value handle(const Boxed_Value &r)
|
||||
static Boxed_Value handle(const Boxed_Value &r) noexcept
|
||||
{
|
||||
return r;
|
||||
}
|
||||
@ -226,7 +226,7 @@ namespace chaiscript
|
||||
template<>
|
||||
struct Handle_Return<Boxed_Number>
|
||||
{
|
||||
static Boxed_Value handle(const Boxed_Number &r)
|
||||
static Boxed_Value handle(const Boxed_Number &r) noexcept
|
||||
{
|
||||
return r.bv;
|
||||
}
|
||||
|
||||
@ -19,14 +19,15 @@ namespace chaiscript
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<typename Class, typename ... Params >
|
||||
Proxy_Function build_constructor_(Class (*)(Params...))
|
||||
{
|
||||
auto call = dispatch::detail::Constructor<Class, Params...>();
|
||||
auto call = [](auto && ... param){
|
||||
return Class(std::forward<decltype(param)>(param)...);
|
||||
};
|
||||
|
||||
return Proxy_Function(
|
||||
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<std::shared_ptr<Class> (Params...), decltype(call)>>(call));
|
||||
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Class (Params...), decltype(call)>>(call));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -41,7 +41,7 @@ namespace chaiscript
|
||||
class Boxed_Number;
|
||||
struct AST_Node;
|
||||
|
||||
typedef std::unique_ptr<AST_Node> AST_NodePtr;
|
||||
using AST_NodePtr = std::unique_ptr<AST_Node>;
|
||||
|
||||
namespace dispatch
|
||||
{
|
||||
@ -52,14 +52,12 @@ namespace chaiscript
|
||||
{
|
||||
public:
|
||||
Param_Types()
|
||||
: m_has_types(false),
|
||||
m_doti(user_type<Dynamic_Object>())
|
||||
: m_has_types(false)
|
||||
{}
|
||||
|
||||
explicit Param_Types(std::vector<std::pair<std::string, Type_Info>> t_types)
|
||||
: m_types(std::move(t_types)),
|
||||
m_has_types(false),
|
||||
m_doti(user_type<Dynamic_Object>())
|
||||
m_has_types(false)
|
||||
{
|
||||
update_has_types();
|
||||
}
|
||||
@ -70,20 +68,21 @@ namespace chaiscript
|
||||
update_has_types();
|
||||
}
|
||||
|
||||
bool operator==(const Param_Types &t_rhs) const
|
||||
bool operator==(const Param_Types &t_rhs) const noexcept
|
||||
{
|
||||
return m_types == t_rhs.m_types;
|
||||
}
|
||||
|
||||
std::vector<Boxed_Value> convert(std::vector<Boxed_Value> vals, const Type_Conversions_State &t_conversions) const
|
||||
{
|
||||
constexpr auto dynamic_object_type_info = user_type<Dynamic_Object>();
|
||||
for (size_t i = 0; i < vals.size(); ++i)
|
||||
{
|
||||
const auto &name = m_types[i].first;
|
||||
if (!name.empty()) {
|
||||
const auto &bv = vals[i];
|
||||
|
||||
if (!bv.get_type_info().bare_equal(m_doti))
|
||||
if (!bv.get_type_info().bare_equal(dynamic_object_type_info))
|
||||
{
|
||||
const auto &ti = m_types[i].second;
|
||||
if (!ti.is_undef())
|
||||
@ -114,8 +113,9 @@ namespace chaiscript
|
||||
|
||||
// first result: is a match
|
||||
// second result: needs conversions
|
||||
std::pair<bool, bool> match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const
|
||||
std::pair<bool, bool> match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const noexcept
|
||||
{
|
||||
constexpr auto dynamic_object_type_info = user_type<Dynamic_Object>();
|
||||
bool needs_conversion = false;
|
||||
|
||||
if (!m_has_types) { return std::make_pair(true, needs_conversion); }
|
||||
@ -127,7 +127,7 @@ namespace chaiscript
|
||||
if (!name.empty()) {
|
||||
const auto &bv = vals[i];
|
||||
|
||||
if (bv.get_type_info().bare_equal(m_doti))
|
||||
if (bv.get_type_info().bare_equal(dynamic_object_type_info))
|
||||
{
|
||||
try {
|
||||
const Dynamic_Object &d = boxed_cast<const Dynamic_Object &>(bv, &t_conversions);
|
||||
@ -158,7 +158,7 @@ namespace chaiscript
|
||||
return std::make_pair(true, needs_conversion);
|
||||
}
|
||||
|
||||
const std::vector<std::pair<std::string, Type_Info>> &types() const
|
||||
const std::vector<std::pair<std::string, Type_Info>> &types() const noexcept
|
||||
{
|
||||
return m_types;
|
||||
}
|
||||
@ -180,7 +180,6 @@ namespace chaiscript
|
||||
|
||||
std::vector<std::pair<std::string, Type_Info>> m_types;
|
||||
bool m_has_types;
|
||||
Type_Info m_doti;
|
||||
|
||||
};
|
||||
|
||||
@ -210,14 +209,14 @@ namespace chaiscript
|
||||
/// 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.
|
||||
const std::vector<Type_Info> &get_param_types() const { return m_types; }
|
||||
const std::vector<Type_Info> &get_param_types() const noexcept { return m_types; }
|
||||
|
||||
virtual bool operator==(const Proxy_Function_Base &) const = 0;
|
||||
virtual bool operator==(const Proxy_Function_Base &) const noexcept = 0;
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const = 0;
|
||||
|
||||
virtual bool is_attribute_function() const { return false; }
|
||||
virtual bool is_attribute_function() const noexcept { return false; }
|
||||
|
||||
bool has_arithmetic_param() const
|
||||
bool has_arithmetic_param() const noexcept
|
||||
{
|
||||
return m_has_arithmetic_param;
|
||||
}
|
||||
@ -229,7 +228,7 @@ namespace chaiscript
|
||||
|
||||
//! Return true if the function is a possible match
|
||||
//! to the passed in values
|
||||
bool filter(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const
|
||||
bool filter(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const noexcept
|
||||
{
|
||||
assert(m_arity == -1 || (m_arity > 0 && static_cast<int>(vals.size()) == m_arity));
|
||||
|
||||
@ -244,19 +243,23 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
/// \returns the number of arguments the function takes or -1 if it is variadic
|
||||
int get_arity() const
|
||||
int get_arity() const noexcept
|
||||
{
|
||||
return m_arity;
|
||||
}
|
||||
|
||||
static bool compare_type_to_param(const Type_Info &ti, const Boxed_Value &bv, const Type_Conversions_State &t_conversions)
|
||||
static bool compare_type_to_param(const Type_Info &ti, const Boxed_Value &bv, const Type_Conversions_State &t_conversions) noexcept
|
||||
{
|
||||
constexpr auto boxed_value_ti = user_type<Boxed_Value>();
|
||||
constexpr auto boxed_number_ti = user_type<Boxed_Number>();
|
||||
constexpr auto function_ti = user_type<std::shared_ptr<const Proxy_Function_Base>>();
|
||||
|
||||
if (ti.is_undef()
|
||||
|| ti.bare_equal(user_type<Boxed_Value>())
|
||||
|| ti.bare_equal(boxed_value_ti)
|
||||
|| (!bv.get_type_info().is_undef()
|
||||
&& ( (ti.bare_equal(user_type<Boxed_Number>()) && bv.get_type_info().is_arithmetic())
|
||||
&& ( (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(user_type<std::shared_ptr<const Proxy_Function_Base> >())
|
||||
|| bv.get_type_info().bare_equal(function_ti)
|
||||
|| t_conversions->converts(ti, bv.get_type_info())
|
||||
)
|
||||
)
|
||||
@ -268,8 +271,9 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool compare_first_type(const Boxed_Value &bv, const Type_Conversions_State &t_conversions) const
|
||||
virtual bool compare_first_type(const Boxed_Value &bv, const Type_Conversions_State &t_conversions) const noexcept
|
||||
{
|
||||
/// TODO is m_types guaranteed to be at least 2??
|
||||
return compare_type_to_param(m_types[1], bv, t_conversions);
|
||||
}
|
||||
|
||||
@ -292,7 +296,7 @@ namespace chaiscript
|
||||
|
||||
|
||||
static bool compare_types(const std::vector<Type_Info> &tis, const std::vector<Boxed_Value> &bvs,
|
||||
const Type_Conversions_State &t_conversions)
|
||||
const Type_Conversions_State &t_conversions) noexcept
|
||||
{
|
||||
if (tis.size() - 1 != bvs.size())
|
||||
{
|
||||
@ -314,11 +318,11 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
/// \brief Common typedef used for passing of any registered function in ChaiScript
|
||||
typedef std::shared_ptr<dispatch::Proxy_Function_Base> Proxy_Function;
|
||||
using Proxy_Function = std::shared_ptr<dispatch::Proxy_Function_Base>;
|
||||
|
||||
/// \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 dispatch::Proxy_Function_Base> Const_Proxy_Function;
|
||||
using Const_Proxy_Function = std::shared_ptr<const dispatch::Proxy_Function_Base>;
|
||||
|
||||
namespace exception
|
||||
{
|
||||
@ -358,7 +362,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
|
||||
bool operator==(const Proxy_Function_Base &rhs) const override
|
||||
bool operator==(const Proxy_Function_Base &rhs) const noexcept override
|
||||
{
|
||||
const Dynamic_Proxy_Function *prhs = dynamic_cast<const Dynamic_Proxy_Function *>(&rhs);
|
||||
|
||||
@ -374,13 +378,17 @@ namespace chaiscript
|
||||
return call_match_internal(vals, t_conversions).first;
|
||||
}
|
||||
|
||||
bool has_guard() const noexcept
|
||||
{
|
||||
return bool(m_guard);
|
||||
}
|
||||
|
||||
Proxy_Function get_guard() const
|
||||
Proxy_Function get_guard() const noexcept
|
||||
{
|
||||
return m_guard;
|
||||
}
|
||||
|
||||
bool has_parse_tree() const {
|
||||
bool has_parse_tree() const noexcept {
|
||||
return static_cast<bool>(m_parsenode);
|
||||
}
|
||||
|
||||
@ -528,7 +536,7 @@ namespace chaiscript
|
||||
assert(m_f->get_arity() < 0 || m_f->get_arity() == static_cast<int>(m_args.size()));
|
||||
}
|
||||
|
||||
bool operator==(const Proxy_Function_Base &t_f) const override
|
||||
bool operator==(const Proxy_Function_Base &t_f) const noexcept override
|
||||
{
|
||||
return &t_f == this;
|
||||
}
|
||||
@ -620,13 +628,13 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const override
|
||||
bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const noexcept override
|
||||
{
|
||||
return static_cast<int>(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<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const = 0;
|
||||
virtual bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const noexcept = 0;
|
||||
};
|
||||
|
||||
|
||||
@ -642,12 +650,12 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const override
|
||||
bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const noexcept override
|
||||
{
|
||||
return detail::compare_types_cast(static_cast<Func *>(nullptr), vals, t_conversions);
|
||||
}
|
||||
|
||||
bool operator==(const Proxy_Function_Base &t_func) const override
|
||||
bool operator==(const Proxy_Function_Base &t_func) const noexcept override
|
||||
{
|
||||
return dynamic_cast<const Proxy_Function_Callable_Impl<Func, Callable> *>(&t_func) != nullptr;
|
||||
}
|
||||
@ -656,7 +664,7 @@ namespace chaiscript
|
||||
protected:
|
||||
Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
return detail::call_func(detail::Function_Signature<Func>(), m_f, params, t_conversions);
|
||||
return detail::call_func(static_cast<Func *>(nullptr), m_f, params, t_conversions);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -686,12 +694,12 @@ namespace chaiscript
|
||||
assert(!m_shared_ptr_holder || m_shared_ptr_holder.get() == &m_f.get());
|
||||
}
|
||||
|
||||
bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const override
|
||||
bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const noexcept override
|
||||
{
|
||||
return detail::compare_types_cast(static_cast<Func *>(nullptr), vals, t_conversions);
|
||||
}
|
||||
|
||||
bool operator==(const Proxy_Function_Base &t_func) const override
|
||||
bool operator==(const Proxy_Function_Base &t_func) const noexcept override
|
||||
{
|
||||
return dynamic_cast<const Assignable_Proxy_Function_Impl<Func> *>(&t_func) != nullptr;
|
||||
}
|
||||
@ -708,7 +716,7 @@ namespace chaiscript
|
||||
protected:
|
||||
Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) const override
|
||||
{
|
||||
return detail::call_func(detail::Function_Signature<Func>(), m_f.get(), params, t_conversions);
|
||||
return detail::call_func(static_cast<Func *>(nullptr), m_f.get(), params, t_conversions);
|
||||
}
|
||||
|
||||
|
||||
@ -729,9 +737,9 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
bool is_attribute_function() const override { return true; }
|
||||
bool is_attribute_function() const noexcept override { return true; }
|
||||
|
||||
bool operator==(const Proxy_Function_Base &t_func) const override
|
||||
bool operator==(const Proxy_Function_Base &t_func) const noexcept override
|
||||
{
|
||||
const Attribute_Access<T, Class> * aa
|
||||
= dynamic_cast<const Attribute_Access<T, Class> *>(&t_func);
|
||||
@ -743,14 +751,14 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &) const override
|
||||
bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &) const noexcept override
|
||||
{
|
||||
if (vals.size() != 1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return vals[0].get_type_info().bare_equal(user_type<Class>());
|
||||
constexpr auto class_type_info = user_type<Class>();
|
||||
return vals[0].get_type_info().bare_equal(class_type_info);
|
||||
}
|
||||
|
||||
protected:
|
||||
@ -769,36 +777,32 @@ namespace chaiscript
|
||||
|
||||
private:
|
||||
template<typename Type>
|
||||
auto do_call_impl(Class *o) const -> std::enable_if_t<std::is_pointer<Type>::value, Boxed_Value>
|
||||
auto do_call_impl(Class *o) const
|
||||
{
|
||||
return detail::Handle_Return<Type>::handle(o->*m_attr);
|
||||
if constexpr(std::is_pointer<Type>::value) {
|
||||
return detail::Handle_Return<Type>::handle(o->*m_attr);
|
||||
} else {
|
||||
return detail::Handle_Return<typename std::add_lvalue_reference<Type>::type>::handle(o->*m_attr);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
auto do_call_impl(const Class *o) const -> std::enable_if_t<std::is_pointer<Type>::value, Boxed_Value>
|
||||
auto do_call_impl(const Class *o) const
|
||||
{
|
||||
return detail::Handle_Return<const Type>::handle(o->*m_attr);
|
||||
if constexpr(std::is_pointer<Type>::value) {
|
||||
return detail::Handle_Return<const Type>::handle(o->*m_attr);
|
||||
} else {
|
||||
return detail::Handle_Return<typename std::add_lvalue_reference<typename std::add_const<Type>::type>::type>::handle(o->*m_attr);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
auto do_call_impl(Class *o) const -> std::enable_if_t<!std::is_pointer<Type>::value, Boxed_Value>
|
||||
{
|
||||
return detail::Handle_Return<typename std::add_lvalue_reference<Type>::type>::handle(o->*m_attr);
|
||||
}
|
||||
|
||||
template<typename Type>
|
||||
auto do_call_impl(const Class *o) const -> std::enable_if_t<!std::is_pointer<Type>::value, Boxed_Value>
|
||||
{
|
||||
return detail::Handle_Return<typename std::add_lvalue_reference<typename std::add_const<Type>::type>::type>::handle(o->*m_attr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
static std::vector<Type_Info> param_types()
|
||||
{
|
||||
return {user_type<T>(), user_type<Class>()};
|
||||
}
|
||||
|
||||
std::vector<Type_Info> m_param_types{user_type<T>(), user_type<Class>()};
|
||||
T Class::* m_attr;
|
||||
};
|
||||
}
|
||||
@ -841,7 +845,7 @@ namespace chaiscript
|
||||
{
|
||||
template<typename FuncType>
|
||||
bool types_match_except_for_arithmetic(const FuncType &t_func, const std::vector<Boxed_Value> &plist,
|
||||
const Type_Conversions_State &t_conversions)
|
||||
const Type_Conversions_State &t_conversions) noexcept
|
||||
{
|
||||
const std::vector<Type_Info> &types = t_func->get_param_types();
|
||||
|
||||
|
||||
@ -21,7 +21,6 @@
|
||||
#include "boxed_value.hpp"
|
||||
#include "handle_return.hpp"
|
||||
#include "type_info.hpp"
|
||||
#include "callable_traits.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
class Type_Conversions_State;
|
||||
@ -78,14 +77,11 @@ namespace chaiscript
|
||||
*/
|
||||
template<typename Ret, typename ... Params>
|
||||
bool compare_types_cast(Ret (*)(Params...),
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions)
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions) noexcept
|
||||
{
|
||||
try {
|
||||
std::vector<Boxed_Value>::size_type i = 0;
|
||||
(void)i;
|
||||
(void)params; (void)t_conversions;
|
||||
// this is ok because the order of evaluation of initializer lists is well defined
|
||||
(void)std::initializer_list<int>{(boxed_cast<Params>(params[i++], &t_conversions), 0)...};
|
||||
( boxed_cast<Params>(params[i++], &t_conversions), ... );
|
||||
return true;
|
||||
} catch (const exception::bad_boxed_cast &) {
|
||||
return false;
|
||||
@ -94,11 +90,11 @@ namespace chaiscript
|
||||
|
||||
|
||||
template<typename Callable, typename Ret, typename ... Params, size_t ... I>
|
||||
Ret call_func(const chaiscript::dispatch::detail::Function_Signature<Ret (Params...)> &,
|
||||
Ret call_func(Ret (*)(Params...),
|
||||
std::index_sequence<I...>, const Callable &f,
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions)
|
||||
[[maybe_unused]] const std::vector<Boxed_Value> ¶ms,
|
||||
[[maybe_unused]] const Type_Conversions_State &t_conversions)
|
||||
{
|
||||
(void)params; (void)t_conversions;
|
||||
return f(boxed_cast<Params>(params[I], &t_conversions)...);
|
||||
}
|
||||
|
||||
@ -108,26 +104,15 @@ namespace chaiscript
|
||||
/// if any unboxing fails the execution of the function fails and
|
||||
/// the bad_boxed_cast is passed up to the caller.
|
||||
template<typename Callable, typename Ret, typename ... Params>
|
||||
Boxed_Value call_func(const chaiscript::dispatch::detail::Function_Signature<Ret (Params...)> &sig, const Callable &f,
|
||||
Boxed_Value call_func(Ret (*sig)(Params...), const Callable &f,
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions)
|
||||
{
|
||||
return Handle_Return<Ret>::handle(call_func(sig, std::index_sequence_for<Params...>{}, f, params, t_conversions));
|
||||
}
|
||||
|
||||
template<typename Callable, typename ... Params>
|
||||
Boxed_Value call_func(const chaiscript::dispatch::detail::Function_Signature<void (Params...)> &sig, const Callable &f,
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions_State &t_conversions)
|
||||
{
|
||||
call_func(sig, std::index_sequence_for<Params...>{}, f, params, t_conversions);
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4702)
|
||||
#endif
|
||||
// MSVC is reporting that this is unreachable code - and it's wrong.
|
||||
return Handle_Return<void>::handle();
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
if constexpr (std::is_same_v<Ret, void>) {
|
||||
call_func(sig, std::index_sequence_for<Params...>{}, f, params, t_conversions);
|
||||
return Handle_Return<void>::handle();
|
||||
} else {
|
||||
return Handle_Return<Ret>::handle(call_func(sig, std::index_sequence_for<Params...>{}, f, params, t_conversions));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -15,9 +15,54 @@
|
||||
|
||||
#include "bind_first.hpp"
|
||||
#include "proxy_functions.hpp"
|
||||
#include "function_signature.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace dispatch::detail
|
||||
{
|
||||
template<typename Obj, typename Param1, typename ... Rest>
|
||||
Param1 get_first_param(Function_Params<Param1, Rest...>, Obj &&obj)
|
||||
{
|
||||
return static_cast<Param1>(std::forward<Obj>(obj));
|
||||
}
|
||||
|
||||
template<typename Func, bool Is_Noexcept, bool Is_Member, bool Is_MemberObject, bool Is_Object, typename Ret, typename ... Param>
|
||||
auto make_callable_impl(Func &&func, Function_Signature<Ret, Function_Params<Param...>, Is_Noexcept, Is_Member, Is_MemberObject, Is_Object>)
|
||||
{
|
||||
if constexpr (Is_MemberObject) {
|
||||
// we now that the Param pack will have only one element, so we are safe expanding it here
|
||||
return Proxy_Function(chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Attribute_Access<Ret, std::decay_t<Param>...>>(std::forward<Func>(func)));
|
||||
} else if constexpr (Is_Member) {
|
||||
auto call = [func = std::forward<Func>(func)](auto && obj, auto && ... param) noexcept(Is_Noexcept) -> decltype(auto) {
|
||||
return (( get_first_param(Function_Params<Param...>{}, obj).*func )(std::forward<decltype(param)>(param)...));
|
||||
};
|
||||
return Proxy_Function(
|
||||
chaiscript::make_shared<dispatch::Proxy_Function_Base,
|
||||
dispatch::Proxy_Function_Callable_Impl<Ret (Param...), decltype(call)>>(std::move(call))
|
||||
);
|
||||
} else {
|
||||
return Proxy_Function(
|
||||
chaiscript::make_shared<dispatch::Proxy_Function_Base,
|
||||
dispatch::Proxy_Function_Callable_Impl<Ret (Param...), std::decay_t<Func>>>(std::forward<Func>(func))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// this version peels off the function object itself from the function signature, when used
|
||||
// on a callable object
|
||||
template<typename Func, typename Ret, typename Object, typename ... Param, bool Is_Noexcept>
|
||||
auto make_callable(Func &&func, Function_Signature<Ret, Function_Params<Object, Param...>, Is_Noexcept, false, false, true>)
|
||||
{
|
||||
return make_callable_impl(std::forward<Func>(func), Function_Signature<Ret, Function_Params<Param...>, Is_Noexcept, false, false, true>{});
|
||||
}
|
||||
|
||||
template<typename Func, typename Ret, typename ... Param, bool Is_Noexcept, bool Is_Member, bool Is_MemberObject>
|
||||
auto make_callable(Func &&func, Function_Signature<Ret, Function_Params<Param...>, Is_Noexcept, Is_Member, Is_MemberObject, false> fs)
|
||||
{
|
||||
return make_callable_impl(std::forward<Func>(func), fs);
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Creates a new Proxy_Function object from a free function, member function or data member
|
||||
/// \param[in] t Function / member to expose
|
||||
@ -40,85 +85,12 @@ namespace chaiscript
|
||||
///
|
||||
/// \sa \ref adding_functions
|
||||
template<typename T>
|
||||
Proxy_Function fun(const T &t)
|
||||
Proxy_Function fun(T &&t)
|
||||
{
|
||||
typedef typename dispatch::detail::Callable_Traits<T>::Signature Signature;
|
||||
|
||||
return Proxy_Function(
|
||||
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Signature, T>>(t));
|
||||
return dispatch::detail::make_callable(std::forward<T>(t), dispatch::detail::Function_Signature{t});
|
||||
}
|
||||
|
||||
|
||||
template<typename Ret, typename ... Param>
|
||||
Proxy_Function fun(Ret (*func)(Param...))
|
||||
{
|
||||
auto fun_call = dispatch::detail::Fun_Caller<Ret, Param...>(func);
|
||||
|
||||
return Proxy_Function(
|
||||
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Ret (Param...), decltype(fun_call)>>(fun_call));
|
||||
|
||||
}
|
||||
|
||||
template<typename Ret, typename Class, typename ... Param>
|
||||
Proxy_Function fun(Ret (Class::*t_func)(Param...) const)
|
||||
{
|
||||
auto call = dispatch::detail::Const_Caller<Ret, Class, Param...>(t_func);
|
||||
|
||||
return Proxy_Function(
|
||||
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Ret (const Class &, Param...), decltype(call)>>(call));
|
||||
}
|
||||
|
||||
template<typename Ret, typename Class, typename ... Param>
|
||||
Proxy_Function fun(Ret (Class::*t_func)(Param...))
|
||||
{
|
||||
auto call = dispatch::detail::Caller<Ret, Class, Param...>(t_func);
|
||||
|
||||
return Proxy_Function(
|
||||
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Ret (Class &, Param...), decltype(call)>>(call));
|
||||
|
||||
}
|
||||
|
||||
template<typename T, typename Class /*, typename = typename std::enable_if<std::is_member_object_pointer<T>::value>::type*/>
|
||||
Proxy_Function fun(T Class::* m /*, typename std::enable_if<std::is_member_object_pointer<T>::value>::type* = 0*/ )
|
||||
{
|
||||
return Proxy_Function(chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Attribute_Access<T, Class>>(m));
|
||||
}
|
||||
|
||||
// only compile this bit if noexcept is part of the type system
|
||||
//
|
||||
#if (defined(__cpp_noexcept_function_type) && __cpp_noexcept_function_type >= 201510) || (defined(_NOEXCEPT_TYPES_SUPPORTED) && _MSC_VER >= 1912)
|
||||
template<typename Ret, typename ... Param>
|
||||
Proxy_Function fun(Ret (*func)(Param...) noexcept)
|
||||
{
|
||||
auto fun_call = dispatch::detail::Fun_Caller<Ret, Param...>(func);
|
||||
|
||||
return Proxy_Function(
|
||||
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Ret (Param...), decltype(fun_call)>>(fun_call));
|
||||
|
||||
}
|
||||
|
||||
template<typename Ret, typename Class, typename ... Param>
|
||||
Proxy_Function fun(Ret (Class::*t_func)(Param...) const noexcept)
|
||||
{
|
||||
auto call = dispatch::detail::Const_Caller<Ret, Class, Param...>(t_func);
|
||||
|
||||
return Proxy_Function(
|
||||
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Ret (const Class &, Param...), decltype(call)>>(call));
|
||||
}
|
||||
|
||||
template<typename Ret, typename Class, typename ... Param>
|
||||
Proxy_Function fun(Ret (Class::*t_func)(Param...) noexcept)
|
||||
{
|
||||
auto call = dispatch::detail::Caller<Ret, Class, Param...>(t_func);
|
||||
|
||||
return Proxy_Function(
|
||||
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Ret (Class &, Param...), decltype(call)>>(call));
|
||||
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
|
||||
/// \brief Creates a new Proxy_Function object from a free function, member function or data member and binds the first parameter of it
|
||||
/// \param[in] t Function / member to expose
|
||||
@ -145,6 +117,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -20,6 +20,7 @@
|
||||
#include <typeinfo>
|
||||
|
||||
#include "../chaiscript_threading.hpp"
|
||||
#include "../utility/static_string.hpp"
|
||||
#include "bad_boxed_cast.hpp"
|
||||
#include "boxed_cast_helper.hpp"
|
||||
#include "boxed_value.hpp"
|
||||
@ -33,7 +34,7 @@ namespace chaiscript
|
||||
{
|
||||
public:
|
||||
bad_boxed_dynamic_cast(const Type_Info &t_from, const std::type_info &t_to,
|
||||
const std::string &t_what) noexcept
|
||||
const utility::Static_String &t_what) noexcept
|
||||
: bad_boxed_cast(t_from, t_to, t_what)
|
||||
{
|
||||
}
|
||||
@ -43,7 +44,7 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
explicit bad_boxed_dynamic_cast(const std::string &w) noexcept
|
||||
explicit bad_boxed_dynamic_cast(const utility::Static_String &w) noexcept
|
||||
: bad_boxed_cast(w)
|
||||
{
|
||||
}
|
||||
@ -57,7 +58,7 @@ namespace chaiscript
|
||||
{
|
||||
public:
|
||||
bad_boxed_type_cast(const Type_Info &t_from, const std::type_info &t_to,
|
||||
const std::string &t_what) noexcept
|
||||
const utility::Static_String &t_what) noexcept
|
||||
: bad_boxed_cast(t_from, t_to, t_what)
|
||||
{
|
||||
}
|
||||
@ -67,7 +68,7 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
explicit bad_boxed_type_cast(const std::string &w) noexcept
|
||||
explicit bad_boxed_type_cast(const utility::Static_String &w) noexcept
|
||||
: bad_boxed_cast(w)
|
||||
{
|
||||
}
|
||||
@ -87,16 +88,16 @@ namespace chaiscript
|
||||
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
|
||||
const Type_Info &to() const noexcept
|
||||
{
|
||||
return m_to;
|
||||
}
|
||||
const Type_Info &from() const
|
||||
const Type_Info &from() const noexcept
|
||||
{
|
||||
return m_from;
|
||||
}
|
||||
|
||||
virtual bool bidir() const
|
||||
virtual bool bidir() const noexcept
|
||||
{
|
||||
return true;
|
||||
}
|
||||
@ -122,6 +123,7 @@ namespace chaiscript
|
||||
public:
|
||||
static Boxed_Value cast(const Boxed_Value &t_from)
|
||||
{
|
||||
|
||||
if (t_from.get_type_info().bare_equal(chaiscript::user_type<From>()))
|
||||
{
|
||||
if (t_from.is_pointer())
|
||||
@ -272,7 +274,7 @@ namespace chaiscript
|
||||
"Unable to cast down inheritance hierarchy with non-polymorphic types");
|
||||
}
|
||||
|
||||
bool bidir() const override
|
||||
bool bidir() const noexcept override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -306,7 +308,7 @@ namespace chaiscript
|
||||
return m_func(t_from);
|
||||
}
|
||||
|
||||
bool bidir() const override
|
||||
bool bidir() const noexcept override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@ -328,7 +330,7 @@ namespace chaiscript
|
||||
|
||||
struct Less_Than
|
||||
{
|
||||
bool operator()(const std::type_info *t_lhs, const std::type_info *t_rhs) const
|
||||
bool operator()(const std::type_info *t_lhs, const std::type_info *t_rhs) const noexcept
|
||||
{
|
||||
return *t_lhs != *t_rhs && t_lhs->before(*t_rhs);
|
||||
}
|
||||
@ -370,18 +372,19 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool convertable_type() const
|
||||
bool convertable_type() const noexcept
|
||||
{
|
||||
return thread_cache().count(user_type<T>().bare_type_info()) != 0;
|
||||
constexpr auto type = user_type<T>().bare_type_info();
|
||||
return thread_cache().count(type) != 0;
|
||||
}
|
||||
|
||||
template<typename To, typename From>
|
||||
bool converts() const
|
||||
bool converts() const noexcept
|
||||
{
|
||||
return converts(user_type<To>(), user_type<From>());
|
||||
}
|
||||
|
||||
bool converts(const Type_Info &to, const Type_Info &from) const
|
||||
bool converts(const Type_Info &to, const Type_Info &from) const noexcept
|
||||
{
|
||||
const auto &types = thread_cache();
|
||||
if (types.count(to.bare_type_info()) != 0 && types.count(from.bare_type_info()) != 0)
|
||||
@ -459,11 +462,11 @@ namespace chaiscript
|
||||
{
|
||||
return *itr;
|
||||
} else {
|
||||
throw std::out_of_range("No such conversion exists from " + from.bare_name() + " to " + to.bare_name());
|
||||
throw std::out_of_range(std::string("No such conversion exists from ") + from.bare_name() + " to " + to.bare_name());
|
||||
}
|
||||
}
|
||||
|
||||
Conversion_Saves &conversion_saves() const {
|
||||
Conversion_Saves &conversion_saves() const noexcept {
|
||||
return *m_conversion_saves;
|
||||
}
|
||||
|
||||
@ -518,15 +521,15 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
const Type_Conversions *operator->() const {
|
||||
const Type_Conversions *operator->() const noexcept {
|
||||
return &m_conversions.get();
|
||||
}
|
||||
|
||||
const Type_Conversions *get() const {
|
||||
const Type_Conversions *get() const noexcept {
|
||||
return &m_conversions.get();
|
||||
}
|
||||
|
||||
Type_Conversions::Conversion_Saves &saves() const {
|
||||
Type_Conversions::Conversion_Saves &saves() const noexcept {
|
||||
return m_saves;
|
||||
}
|
||||
|
||||
@ -535,7 +538,7 @@ namespace chaiscript
|
||||
std::reference_wrapper<Type_Conversions::Conversion_Saves> m_saves;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<chaiscript::detail::Type_Conversion_Base> Type_Conversion;
|
||||
using Type_Conversion = std::shared_ptr<chaiscript::detail::Type_Conversion_Base>;
|
||||
|
||||
/// \brief Used to register a to / parent class relationship with ChaiScript. Necessary if you
|
||||
/// want automatic conversions up your inheritance hierarchy.
|
||||
@ -559,23 +562,17 @@ namespace chaiscript
|
||||
/// \endcode
|
||||
///
|
||||
template<typename Base, typename Derived>
|
||||
Type_Conversion base_class(typename std::enable_if<std::is_polymorphic<Base>::value && std::is_polymorphic<Derived>::value>::type* = nullptr)
|
||||
Type_Conversion base_class()
|
||||
{
|
||||
//Can only be used with related polymorphic types
|
||||
//may be expanded some day to support conversions other than child -> parent
|
||||
static_assert(std::is_base_of<Base,Derived>::value, "Classes are not related by inheritance");
|
||||
|
||||
return chaiscript::make_shared<detail::Type_Conversion_Base, detail::Dynamic_Conversion_Impl<Base, Derived>>();
|
||||
}
|
||||
|
||||
template<typename Base, typename Derived>
|
||||
Type_Conversion base_class(typename std::enable_if<!std::is_polymorphic<Base>::value || !std::is_polymorphic<Derived>::value>::type* = nullptr)
|
||||
{
|
||||
//Can only be used with related polymorphic types
|
||||
//may be expanded some day to support conversions other than child -> parent
|
||||
static_assert(std::is_base_of<Base,Derived>::value, "Classes are not related by inheritance");
|
||||
|
||||
return chaiscript::make_shared<detail::Type_Conversion_Base, detail::Static_Conversion_Impl<Base, Derived>>();
|
||||
if constexpr(std::is_polymorphic<Base>::value && std::is_polymorphic<Derived>::value) {
|
||||
return chaiscript::make_shared<detail::Type_Conversion_Base, detail::Dynamic_Conversion_Impl<Base, Derived>>();
|
||||
} else {
|
||||
return chaiscript::make_shared<detail::Type_Conversion_Base, detail::Static_Conversion_Impl<Base, Derived>>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -24,7 +24,7 @@ namespace chaiscript
|
||||
template<typename T>
|
||||
struct Bare_Type
|
||||
{
|
||||
typedef typename std::remove_cv<typename std::remove_pointer<typename std::remove_reference<T>::type>::type>::type type;
|
||||
using type = typename std::remove_cv<typename std::remove_pointer<typename std::remove_reference<T>::type>::type>::type;
|
||||
};
|
||||
}
|
||||
|
||||
@ -34,7 +34,7 @@ namespace chaiscript
|
||||
{
|
||||
public:
|
||||
constexpr Type_Info(const bool t_is_const, const bool t_is_reference, const bool t_is_pointer, const bool t_is_void,
|
||||
const bool t_is_arithmetic, const std::type_info *t_ti, const std::type_info *t_bare_ti)
|
||||
const bool t_is_arithmetic, const std::type_info *t_ti, const std::type_info *t_bare_ti) noexcept
|
||||
: m_type_info(t_ti), m_bare_type_info(t_bare_ti),
|
||||
m_flags((static_cast<unsigned int>(t_is_const) << is_const_flag)
|
||||
+ (static_cast<unsigned int>(t_is_reference) << is_reference_flag)
|
||||
@ -44,7 +44,7 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
constexpr Type_Info() = default;
|
||||
constexpr Type_Info() noexcept = default;
|
||||
|
||||
bool operator<(const Type_Info &ti) const noexcept
|
||||
{
|
||||
@ -90,7 +90,7 @@ namespace chaiscript
|
||||
constexpr bool is_undef() const noexcept { return (m_flags & (1 << is_undef_flag)) != 0; }
|
||||
constexpr bool is_pointer() const noexcept { return (m_flags & (1 << is_pointer_flag)) != 0; }
|
||||
|
||||
std::string name() const
|
||||
const char * name() const noexcept
|
||||
{
|
||||
if (!is_undef())
|
||||
{
|
||||
@ -100,7 +100,7 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
std::string bare_name() const
|
||||
const char * bare_name() const noexcept
|
||||
{
|
||||
if (!is_undef())
|
||||
{
|
||||
@ -110,7 +110,7 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
constexpr const std::type_info *bare_type_info() const
|
||||
constexpr const std::type_info *bare_type_info() const noexcept
|
||||
{
|
||||
return m_bare_type_info;
|
||||
}
|
||||
@ -135,7 +135,7 @@ namespace chaiscript
|
||||
template<typename T>
|
||||
struct Get_Type_Info
|
||||
{
|
||||
static constexpr Type_Info get()
|
||||
constexpr static Type_Info get() noexcept
|
||||
{
|
||||
return Type_Info(std::is_const<typename std::remove_pointer<typename std::remove_reference<T>::type>::type>::value,
|
||||
std::is_reference<T>::value, std::is_pointer<T>::value,
|
||||
@ -152,7 +152,7 @@ namespace chaiscript
|
||||
{
|
||||
// typedef T type;
|
||||
|
||||
static constexpr Type_Info get()
|
||||
constexpr static Type_Info get() noexcept
|
||||
{
|
||||
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
|
||||
std::is_void<T>::value,
|
||||
@ -170,7 +170,7 @@ namespace chaiscript
|
||||
template<typename T>
|
||||
struct Get_Type_Info<const std::shared_ptr<T> &>
|
||||
{
|
||||
static constexpr Type_Info get()
|
||||
constexpr static Type_Info get() noexcept
|
||||
{
|
||||
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
|
||||
std::is_void<T>::value,
|
||||
@ -183,7 +183,7 @@ namespace chaiscript
|
||||
template<typename T>
|
||||
struct Get_Type_Info<std::reference_wrapper<T> >
|
||||
{
|
||||
static constexpr Type_Info get()
|
||||
constexpr static Type_Info get() noexcept
|
||||
{
|
||||
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
|
||||
std::is_void<T>::value,
|
||||
@ -196,7 +196,7 @@ namespace chaiscript
|
||||
template<typename T>
|
||||
struct Get_Type_Info<const std::reference_wrapper<T> &>
|
||||
{
|
||||
static constexpr Type_Info get()
|
||||
constexpr static Type_Info get() noexcept
|
||||
{
|
||||
return Type_Info(std::is_const<T>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
|
||||
std::is_void<T>::value,
|
||||
@ -218,7 +218,7 @@ namespace chaiscript
|
||||
/// chaiscript::Type_Info ti = chaiscript::user_type(i);
|
||||
/// \endcode
|
||||
template<typename T>
|
||||
constexpr Type_Info user_type(const T &/*t*/)
|
||||
constexpr Type_Info user_type(const T &/*t*/) noexcept
|
||||
{
|
||||
return detail::Get_Type_Info<T>::get();
|
||||
}
|
||||
@ -233,7 +233,7 @@ namespace chaiscript
|
||||
/// chaiscript::Type_Info ti = chaiscript::user_type<int>();
|
||||
/// \endcode
|
||||
template<typename T>
|
||||
constexpr Type_Info user_type()
|
||||
constexpr Type_Info user_type() noexcept
|
||||
{
|
||||
return detail::Get_Type_Info<T>::get();
|
||||
}
|
||||
|
||||
@ -11,7 +11,7 @@
|
||||
#ifndef CHAISCRIPT_ALGEBRAIC_HPP_
|
||||
#define CHAISCRIPT_ALGEBRAIC_HPP_
|
||||
|
||||
#include "../utility/fnv1a.hpp"
|
||||
#include "../utility/hash.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
@ -21,23 +21,18 @@ namespace chaiscript
|
||||
struct Operators {
|
||||
enum class Opers
|
||||
{
|
||||
boolean_flag,
|
||||
equals, less_than, greater_than, less_than_equal, greater_than_equal, not_equal,
|
||||
non_const_flag,
|
||||
assign, pre_increment, pre_decrement, assign_product, assign_sum,
|
||||
assign_quotient, assign_difference,
|
||||
non_const_int_flag,
|
||||
assign_bitwise_and, assign_bitwise_or, assign_shift_left, assign_shift_right,
|
||||
assign_remainder, assign_bitwise_xor,
|
||||
const_int_flag,
|
||||
shift_left, shift_right, remainder, bitwise_and, bitwise_or, bitwise_xor, bitwise_complement,
|
||||
const_flag,
|
||||
sum, quotient, product, difference, unary_plus, unary_minus,
|
||||
invalid
|
||||
};
|
||||
|
||||
static const char *to_string(Opers t_oper) {
|
||||
static const char *opers[] = {
|
||||
constexpr static const char *to_string(Opers t_oper) noexcept {
|
||||
constexpr const char *opers[] = {
|
||||
"",
|
||||
"==", "<", ">", "<=", ">=", "!=",
|
||||
"",
|
||||
@ -55,44 +50,44 @@ namespace chaiscript
|
||||
return opers[static_cast<int>(t_oper)];
|
||||
}
|
||||
|
||||
static Opers to_operator(const std::string &t_str, bool t_is_unary = false)
|
||||
constexpr static Opers to_operator(const std::string_view &t_str, bool t_is_unary = false) noexcept
|
||||
{
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4307)
|
||||
#endif
|
||||
|
||||
const auto op_hash = utility::fnv1a_32(t_str.c_str());
|
||||
const auto op_hash = utility::hash(t_str);
|
||||
switch (op_hash) {
|
||||
case utility::fnv1a_32("=="): { return Opers::equals; }
|
||||
case utility::fnv1a_32("<"): { return Opers::less_than; }
|
||||
case utility::fnv1a_32(">"): { return Opers::greater_than; }
|
||||
case utility::fnv1a_32("<="): { return Opers::less_than_equal; }
|
||||
case utility::fnv1a_32(">="): { return Opers::greater_than_equal; }
|
||||
case utility::fnv1a_32("!="): { return Opers::not_equal; }
|
||||
case utility::fnv1a_32("="): { return Opers::assign; }
|
||||
case utility::fnv1a_32("++"): { return Opers::pre_increment; }
|
||||
case utility::fnv1a_32("--"): { return Opers::pre_decrement; }
|
||||
case utility::fnv1a_32("*="): { return Opers::assign_product; }
|
||||
case utility::fnv1a_32("+="): { return Opers::assign_sum; }
|
||||
case utility::fnv1a_32("-="): { return Opers::assign_difference; }
|
||||
case utility::fnv1a_32("&="): { return Opers::assign_bitwise_and; }
|
||||
case utility::fnv1a_32("|="): { return Opers::assign_bitwise_or; }
|
||||
case utility::fnv1a_32("<<="): { return Opers::assign_shift_left; }
|
||||
case utility::fnv1a_32(">>="): { return Opers::assign_shift_right; }
|
||||
case utility::fnv1a_32("%="): { return Opers::assign_remainder; }
|
||||
case utility::fnv1a_32("^="): { return Opers::assign_bitwise_xor; }
|
||||
case utility::fnv1a_32("<<"): { return Opers::shift_left; }
|
||||
case utility::fnv1a_32(">>"): { return Opers::shift_right; }
|
||||
case utility::fnv1a_32("%"): { return Opers::remainder; }
|
||||
case utility::fnv1a_32("&"): { return Opers::bitwise_and; }
|
||||
case utility::fnv1a_32("|"): { return Opers::bitwise_or; }
|
||||
case utility::fnv1a_32("^"): { return Opers::bitwise_xor; }
|
||||
case utility::fnv1a_32("~"): { return Opers::bitwise_complement; }
|
||||
case utility::fnv1a_32("+"): { return t_is_unary ? Opers::unary_plus : Opers::sum; }
|
||||
case utility::fnv1a_32("-"): { return t_is_unary ? Opers::unary_minus : Opers::difference; }
|
||||
case utility::fnv1a_32("/"): { return Opers::quotient; }
|
||||
case utility::fnv1a_32("*"): { return Opers::product; }
|
||||
case utility::hash("=="): { return Opers::equals; }
|
||||
case utility::hash("<"): { return Opers::less_than; }
|
||||
case utility::hash(">"): { return Opers::greater_than; }
|
||||
case utility::hash("<="): { return Opers::less_than_equal; }
|
||||
case utility::hash(">="): { return Opers::greater_than_equal; }
|
||||
case utility::hash("!="): { return Opers::not_equal; }
|
||||
case utility::hash("="): { return Opers::assign; }
|
||||
case utility::hash("++"): { return Opers::pre_increment; }
|
||||
case utility::hash("--"): { return Opers::pre_decrement; }
|
||||
case utility::hash("*="): { return Opers::assign_product; }
|
||||
case utility::hash("+="): { return Opers::assign_sum; }
|
||||
case utility::hash("-="): { return Opers::assign_difference; }
|
||||
case utility::hash("&="): { return Opers::assign_bitwise_and; }
|
||||
case utility::hash("|="): { return Opers::assign_bitwise_or; }
|
||||
case utility::hash("<<="): { return Opers::assign_shift_left; }
|
||||
case utility::hash(">>="): { return Opers::assign_shift_right; }
|
||||
case utility::hash("%="): { return Opers::assign_remainder; }
|
||||
case utility::hash("^="): { return Opers::assign_bitwise_xor; }
|
||||
case utility::hash("<<"): { return Opers::shift_left; }
|
||||
case utility::hash(">>"): { return Opers::shift_right; }
|
||||
case utility::hash("%"): { return Opers::remainder; }
|
||||
case utility::hash("&"): { return Opers::bitwise_and; }
|
||||
case utility::hash("|"): { return Opers::bitwise_or; }
|
||||
case utility::hash("^"): { return Opers::bitwise_xor; }
|
||||
case utility::hash("~"): { return Opers::bitwise_complement; }
|
||||
case utility::hash("+"): { return t_is_unary ? Opers::unary_plus : Opers::sum; }
|
||||
case utility::hash("-"): { return t_is_unary ? Opers::unary_minus : Opers::difference; }
|
||||
case utility::hash("/"): { return Opers::quotient; }
|
||||
case utility::hash("*"): { return Opers::product; }
|
||||
default: { return Opers::invalid; }
|
||||
}
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
|
||||
@ -23,6 +23,7 @@
|
||||
#include "../dispatchkit/dispatchkit.hpp"
|
||||
#include "../dispatchkit/proxy_functions.hpp"
|
||||
#include "../dispatchkit/type_info.hpp"
|
||||
#include <unordered_set>
|
||||
|
||||
namespace chaiscript {
|
||||
struct AST_Node;
|
||||
@ -31,34 +32,59 @@ struct AST_Node;
|
||||
namespace chaiscript
|
||||
{
|
||||
struct Name_Validator {
|
||||
static bool is_reserved_word(const std::string &name)
|
||||
template<typename T>
|
||||
static bool is_reserved_word(const T &s) noexcept
|
||||
{
|
||||
static const std::set<std::string> m_reserved_words
|
||||
= {"def", "fun", "while", "for", "if", "else", "&&", "||", ",", "auto",
|
||||
"return", "break", "true", "false", "class", "attr", "var", "global", "GLOBAL", "_",
|
||||
"__LINE__", "__FILE__", "__FUNC__", "__CLASS__"};
|
||||
return m_reserved_words.count(name) > 0;
|
||||
const static std::unordered_set<std::uint32_t> words{
|
||||
utility::hash("def"),
|
||||
utility::hash("fun"),
|
||||
utility::hash("while"),
|
||||
utility::hash("for"),
|
||||
utility::hash("if"),
|
||||
utility::hash("else"),
|
||||
utility::hash("&&"),
|
||||
utility::hash("||"),
|
||||
utility::hash(","),
|
||||
utility::hash("auto"),
|
||||
utility::hash("return"),
|
||||
utility::hash("break"),
|
||||
utility::hash("true"),
|
||||
utility::hash("false"),
|
||||
utility::hash("class"),
|
||||
utility::hash("attr"),
|
||||
utility::hash("var"),
|
||||
utility::hash("global"),
|
||||
utility::hash("GLOBAL"),
|
||||
utility::hash("_"),
|
||||
utility::hash("__LINE__"),
|
||||
utility::hash("__FILE__"),
|
||||
utility::hash("__FUNC__"),
|
||||
utility::hash("__CLASS__")};
|
||||
|
||||
return words.count(utility::hash(s)) == 1;
|
||||
}
|
||||
|
||||
static bool valid_object_name(const std::string &name)
|
||||
template<typename T>
|
||||
static bool valid_object_name(const T &name) noexcept
|
||||
{
|
||||
return name.find("::") == std::string::npos && !is_reserved_word(name);
|
||||
}
|
||||
|
||||
static void validate_object_name(const std::string &name)
|
||||
template<typename T>
|
||||
static void validate_object_name(const T &name)
|
||||
{
|
||||
if (is_reserved_word(name)) {
|
||||
throw exception::reserved_word_error(name);
|
||||
throw exception::reserved_word_error(std::string(name));
|
||||
}
|
||||
|
||||
if (name.find("::") != std::string::npos) {
|
||||
throw exception::illegal_name_error(name);
|
||||
throw exception::illegal_name_error(std::string(name));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/// Signature of module entry point that all binary loadable modules must implement.
|
||||
typedef ModulePtr (*Create_Module_Func)();
|
||||
using Create_Module_Func = ModulePtr (*)();
|
||||
|
||||
|
||||
/// Types of AST nodes available to the parser and eval
|
||||
@ -76,8 +102,8 @@ namespace chaiscript
|
||||
namespace
|
||||
{
|
||||
/// Helper lookup to get the name of each node type
|
||||
inline const char *ast_node_type_to_string(AST_Node_Type ast_node_type) {
|
||||
static const char * const ast_node_types[] = { "Id", "Fun_Call", "Unused_Return_Fun_Call", "Arg_List", "Equation", "Var_Decl", "Assign_Decl",
|
||||
constexpr const char *ast_node_type_to_string(AST_Node_Type ast_node_type) noexcept {
|
||||
constexpr const char * const ast_node_types[] = { "Id", "Fun_Call", "Unused_Return_Fun_Call", "Arg_List", "Equation", "Var_Decl", "Assign_Decl",
|
||||
"Array_Call", "Dot_Access",
|
||||
"Lambda", "Block", "Scopeless_Block", "Def", "While", "If", "For", "Ranged_For", "Inline_Array", "Inline_Map", "Return", "File", "Prefix", "Break", "Continue", "Map_Pair", "Value_Range",
|
||||
"Inline_Range", "Try", "Catch", "Finally", "Method", "Attr_Decl",
|
||||
@ -89,13 +115,13 @@ namespace chaiscript
|
||||
|
||||
/// \brief Convenience type for file positions
|
||||
struct File_Position {
|
||||
int line;
|
||||
int column;
|
||||
int line = 0;
|
||||
int column = 0;
|
||||
|
||||
File_Position(int t_file_line, int t_file_column)
|
||||
constexpr File_Position(int t_file_line, int t_file_column) noexcept
|
||||
: line(t_file_line), column(t_file_column) { }
|
||||
|
||||
File_Position() : line(0), column(0) { }
|
||||
constexpr File_Position() noexcept = default;
|
||||
};
|
||||
|
||||
struct Parse_Location {
|
||||
@ -124,8 +150,8 @@ namespace chaiscript
|
||||
|
||||
|
||||
/// \brief Typedef for pointers to AST_Node objects. Used in building of the AST_Node tree
|
||||
typedef std::unique_ptr<AST_Node> AST_NodePtr;
|
||||
typedef std::unique_ptr<const AST_Node> AST_NodePtr_Const;
|
||||
using AST_NodePtr = std::unique_ptr<AST_Node>;
|
||||
using AST_NodePtr_Const = std::unique_ptr<const AST_Node>;
|
||||
|
||||
struct AST_Node_Trace;
|
||||
|
||||
@ -136,7 +162,7 @@ namespace chaiscript
|
||||
/// \brief Thrown if an error occurs while attempting to load a binary module
|
||||
struct load_module_error : std::runtime_error
|
||||
{
|
||||
explicit load_module_error(const std::string &t_reason) noexcept
|
||||
explicit load_module_error(const std::string &t_reason)
|
||||
: std::runtime_error(t_reason)
|
||||
{
|
||||
}
|
||||
@ -228,7 +254,7 @@ namespace chaiscript
|
||||
private:
|
||||
|
||||
template<typename T>
|
||||
static AST_Node_Type id(const T& t)
|
||||
static AST_Node_Type id(const T& t) noexcept
|
||||
{
|
||||
return t.identifier;
|
||||
}
|
||||
@ -240,7 +266,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static const std::string &fname(const T& t)
|
||||
static const std::string &fname(const T& t) noexcept
|
||||
{
|
||||
return t.filename();
|
||||
}
|
||||
@ -479,7 +505,7 @@ namespace chaiscript
|
||||
|
||||
/// Errors generated when loading a file
|
||||
struct file_not_found_error : std::runtime_error {
|
||||
explicit file_not_found_error(const std::string &t_filename) noexcept
|
||||
explicit file_not_found_error(const std::string &t_filename)
|
||||
: std::runtime_error("File Not Found: " + t_filename),
|
||||
filename(t_filename)
|
||||
{ }
|
||||
@ -500,15 +526,15 @@ namespace chaiscript
|
||||
const std::string text;
|
||||
Parse_Location location;
|
||||
|
||||
const std::string &filename() const {
|
||||
const std::string &filename() const noexcept {
|
||||
return *location.filename;
|
||||
}
|
||||
|
||||
const File_Position &start() const {
|
||||
const File_Position &start() const noexcept {
|
||||
return location.start;
|
||||
}
|
||||
|
||||
const File_Position &end() const {
|
||||
const File_Position &end() const noexcept {
|
||||
return location.end;
|
||||
}
|
||||
|
||||
@ -553,7 +579,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
|
||||
virtual ~AST_Node() = default;
|
||||
virtual ~AST_Node() noexcept = default;
|
||||
AST_Node(AST_Node &&) = default;
|
||||
AST_Node &operator=(AST_Node &&) = default;
|
||||
AST_Node(const AST_Node &) = delete;
|
||||
@ -576,15 +602,15 @@ namespace chaiscript
|
||||
const std::string text;
|
||||
Parse_Location location;
|
||||
|
||||
const std::string &filename() const {
|
||||
const std::string &filename() const noexcept {
|
||||
return *location.filename;
|
||||
}
|
||||
|
||||
const File_Position &start() const {
|
||||
const File_Position &start() const noexcept {
|
||||
return location.start;
|
||||
}
|
||||
|
||||
const File_Position &end() const {
|
||||
const File_Position &end() const noexcept {
|
||||
return location.end;
|
||||
}
|
||||
|
||||
@ -632,7 +658,7 @@ namespace chaiscript
|
||||
ChaiScript_Parser_Base &operator=(const ChaiScript_Parser_Base &&) = delete;
|
||||
|
||||
template<typename T>
|
||||
T &get_tracer()
|
||||
T &get_tracer() noexcept
|
||||
{
|
||||
// to do type check this somehow?
|
||||
return *static_cast<T*>(get_tracer_ptr());
|
||||
@ -655,13 +681,11 @@ namespace chaiscript
|
||||
|
||||
/// Special type indicating a call to 'break'
|
||||
struct Break_Loop {
|
||||
Break_Loop() = default;
|
||||
};
|
||||
|
||||
|
||||
/// Special type indicating a call to 'continue'
|
||||
struct Continue_Loop {
|
||||
Continue_Loop() = default;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -98,7 +98,7 @@ namespace chaiscript
|
||||
|
||||
|
||||
/// Evaluates the given file and looks in the 'use' paths
|
||||
const Boxed_Value internal_eval_file(const std::string &t_filename) {
|
||||
Boxed_Value internal_eval_file(const std::string &t_filename) {
|
||||
for (const auto &path : m_use_paths)
|
||||
{
|
||||
try {
|
||||
@ -119,7 +119,7 @@ namespace chaiscript
|
||||
|
||||
|
||||
/// Evaluates the given string, used during eval() inside of a script
|
||||
const Boxed_Value internal_eval(const std::string &t_e) {
|
||||
Boxed_Value internal_eval(const std::string &t_e) {
|
||||
try {
|
||||
return do_eval(t_e, "__EVAL__", true);
|
||||
} catch (const exception::eval_error &t_ee) {
|
||||
@ -128,7 +128,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
/// Returns the current evaluation m_engine
|
||||
chaiscript::detail::Dispatch_Engine &get_eval_engine() {
|
||||
chaiscript::detail::Dispatch_Engine &get_eval_engine() noexcept {
|
||||
return m_engine;
|
||||
}
|
||||
|
||||
@ -343,13 +343,13 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
#else // CHAISCRIPT_NO_DYNLOAD
|
||||
explicit ChaiScript_Basic(std::unique_ptr<parser::ChaiScript_Parser_Base> &&parser,
|
||||
std::vector<std::string> t_module_paths = {},
|
||||
std::vector<std::string> t_use_paths = {},
|
||||
const std::vector<chaiscript::Options> &t_opts = chaiscript::default_options()) = delete;
|
||||
explicit ChaiScript_Basic(std::unique_ptr<parser::ChaiScript_Parser_Base> &&parser,
|
||||
std::vector<std::string> t_module_paths = {},
|
||||
std::vector<std::string> t_use_paths = {},
|
||||
const std::vector<chaiscript::Options> &t_opts = chaiscript::default_options()) = delete;
|
||||
#endif
|
||||
|
||||
parser::ChaiScript_Parser_Base &get_parser()
|
||||
parser::ChaiScript_Parser_Base &get_parser() noexcept
|
||||
{
|
||||
return *m_parser;
|
||||
}
|
||||
@ -594,7 +594,6 @@ explicit ChaiScript_Basic(std::unique_ptr<parser::ChaiScript_Parser_Base> &&pars
|
||||
std::string load_module(const std::string &t_module_name)
|
||||
{
|
||||
#ifdef CHAISCRIPT_NO_DYNLOAD
|
||||
(void)t_module_name; // -Wunused-parameter
|
||||
throw chaiscript::exception::load_module_error("Loadable module support was disabled (CHAISCRIPT_NO_DYNLOAD)");
|
||||
#else
|
||||
std::vector<exception::load_module_error> errors;
|
||||
|
||||
@ -34,11 +34,9 @@
|
||||
#include "chaiscript_algebraic.hpp"
|
||||
#include "chaiscript_common.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
namespace exception {
|
||||
namespace chaiscript::exception {
|
||||
class bad_boxed_cast;
|
||||
} // namespace exception
|
||||
} // namespace chaiscript
|
||||
} // namespace chaiscript::exception
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
@ -57,8 +55,9 @@ namespace chaiscript
|
||||
chaiscript::detail::Dispatch_State state(t_ss);
|
||||
|
||||
const Boxed_Value *thisobj = [&]() -> const Boxed_Value *{
|
||||
auto &stack = t_ss.get_stack_data(state.stack_holder()).back();
|
||||
if (!stack.empty() && stack.back().first == "__this") {
|
||||
if (auto &stack = t_ss.get_stack_data(state.stack_holder()).back();
|
||||
!stack.empty() && stack.back().first == "__this")
|
||||
{
|
||||
return &stack.back().second;
|
||||
} else if (!t_vals.empty()) {
|
||||
return &t_vals[0];
|
||||
@ -71,8 +70,8 @@ namespace chaiscript
|
||||
if (thisobj && !has_this_capture) { state.add_object("this", *thisobj); }
|
||||
|
||||
if (t_locals) {
|
||||
for (const auto &local : *t_locals) {
|
||||
state.add_object(local.first, local.second);
|
||||
for (const auto &[name, value] : *t_locals) {
|
||||
state.add_object(name, value);
|
||||
}
|
||||
}
|
||||
|
||||
@ -126,7 +125,7 @@ namespace chaiscript
|
||||
std::vector<std::reference_wrapper<AST_Node>> get_children() const final {
|
||||
std::vector<std::reference_wrapper<AST_Node>> retval;
|
||||
retval.reserve(children.size());
|
||||
for (auto &&child : children) {
|
||||
for (auto &child : children) {
|
||||
retval.emplace_back(*child);
|
||||
}
|
||||
|
||||
@ -706,7 +705,7 @@ namespace chaiscript
|
||||
);
|
||||
}
|
||||
|
||||
static bool has_this_capture(const std::vector<AST_Node_Impl_Ptr<T>> &children) {
|
||||
static bool has_this_capture(const std::vector<AST_Node_Impl_Ptr<T>> &children) noexcept {
|
||||
return std::any_of(std::begin(children), std::end(children),
|
||||
[](const auto &child){
|
||||
return child->children[0]->text == "this";
|
||||
@ -782,7 +781,7 @@ namespace chaiscript
|
||||
return std::move(vec.back());
|
||||
}
|
||||
|
||||
static bool has_guard(const std::vector<AST_Node_Impl_Ptr<T>> &t_children, const std::size_t offset)
|
||||
static bool has_guard(const std::vector<AST_Node_Impl_Ptr<T>> &t_children, const std::size_t offset) noexcept
|
||||
{
|
||||
if ((t_children.size() > 2 + offset) && (t_children[1+offset]->identifier == AST_Node_Type::Arg_List)) {
|
||||
if (t_children.size() > 3 + offset) {
|
||||
@ -909,9 +908,9 @@ namespace chaiscript
|
||||
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{
|
||||
const auto get_function = [&t_ss](const std::string &t_name, auto &t_hint){
|
||||
uint_fast32_t hint = t_hint;
|
||||
auto funs = t_ss->get_function(t_name, hint);
|
||||
if (funs.first != hint) { t_hint = uint_fast32_t(funs.first); }
|
||||
return std::move(funs.second);
|
||||
auto [funs_loc, funs] = t_ss->get_function(t_name, hint);
|
||||
if (funs_loc != hint) { t_hint = uint_fast32_t(funs_loc); }
|
||||
return std::move(funs);
|
||||
};
|
||||
|
||||
const auto call_function = [&t_ss](const auto &t_funcs, const Boxed_Value &t_param) {
|
||||
|
||||
@ -24,13 +24,13 @@ namespace chaiscript {
|
||||
|
||||
template<typename Tracer>
|
||||
auto optimize(eval::AST_Node_Impl_Ptr<Tracer> p) {
|
||||
(void)std::initializer_list<int>{ (p = static_cast<T&>(*this).optimize(std::move(p)), 0)... };
|
||||
( (p = static_cast<T&>(*this).optimize(std::move(p))), ... );
|
||||
return p;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
eval::AST_Node_Impl<T> &child_at(eval::AST_Node_Impl<T> &node, const size_t offset) {
|
||||
eval::AST_Node_Impl<T> &child_at(eval::AST_Node_Impl<T> &node, const size_t offset) noexcept {
|
||||
if (node.children[offset]->identifier == AST_Node_Type::Compiled) {
|
||||
return *(dynamic_cast<eval::Compiled_AST_Node<T> &>(*node.children[offset]).m_original_node);
|
||||
} else {
|
||||
@ -39,7 +39,7 @@ namespace chaiscript {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
const eval::AST_Node_Impl<T> &child_at(const eval::AST_Node_Impl<T> &node, const size_t offset) {
|
||||
const eval::AST_Node_Impl<T> &child_at(const eval::AST_Node_Impl<T> &node, const size_t offset) noexcept {
|
||||
if (node.children[offset]->identifier == AST_Node_Type::Compiled) {
|
||||
return *(dynamic_cast<const eval::Compiled_AST_Node<T> &>(*node.children[offset]).m_original_node);
|
||||
} else {
|
||||
@ -57,7 +57,7 @@ namespace chaiscript {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
auto child_count(const eval::AST_Node_Impl<T> &node) {
|
||||
auto child_count(const eval::AST_Node_Impl<T> &node) noexcept {
|
||||
if (node.identifier == AST_Node_Type::Compiled) {
|
||||
return dynamic_cast<const eval::Compiled_AST_Node<T>&>(node).m_original_node->children.size();
|
||||
} else {
|
||||
@ -95,7 +95,7 @@ namespace chaiscript {
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
bool contains_var_decl_in_scope(const eval::AST_Node_Impl<T> &node)
|
||||
bool contains_var_decl_in_scope(const eval::AST_Node_Impl<T> &node) noexcept
|
||||
{
|
||||
if (node.identifier == AST_Node_Type::Var_Decl || node.identifier == AST_Node_Type::Assign_Decl || node.identifier == AST_Node_Type::Reference) {
|
||||
return true;
|
||||
@ -469,3 +469,4 @@ namespace chaiscript {
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
@ -27,7 +27,7 @@
|
||||
#include "chaiscript_common.hpp"
|
||||
#include "chaiscript_optimizer.hpp"
|
||||
#include "chaiscript_tracer.hpp"
|
||||
#include "../utility/fnv1a.hpp"
|
||||
#include "../utility/hash.hpp"
|
||||
#include "../utility/static_string.hpp"
|
||||
|
||||
#if defined(CHAISCRIPT_UTF16_UTF32)
|
||||
@ -76,7 +76,7 @@ namespace chaiscript
|
||||
// common for all implementations
|
||||
static std::string u8str_from_ll(long long val)
|
||||
{
|
||||
typedef std::string::value_type char_type;
|
||||
using char_type = std::string::value_type;
|
||||
|
||||
char_type c[2];
|
||||
c[1] = char_type(val);
|
||||
@ -92,7 +92,7 @@ namespace chaiscript
|
||||
|
||||
static string_type str_from_ll(long long val)
|
||||
{
|
||||
typedef typename string_type::value_type target_char_type;
|
||||
using target_char_type = typename string_type::value_type;
|
||||
#if defined (CHAISCRIPT_UTF16_UTF32)
|
||||
// prepare converter
|
||||
std::wstring_convert<std::codecvt_utf8<target_char_type>, target_char_type> converter;
|
||||
@ -120,7 +120,7 @@ namespace chaiscript
|
||||
|
||||
template<typename Tracer, typename Optimizer, std::size_t Parse_Depth=512>
|
||||
class ChaiScript_Parser final : public ChaiScript_Parser_Base {
|
||||
void *get_tracer_ptr() override {
|
||||
void *get_tracer_ptr() noexcept override {
|
||||
return &m_tracer;
|
||||
}
|
||||
|
||||
@ -146,97 +146,147 @@ namespace chaiscript
|
||||
ChaiScript_Parser *parser;
|
||||
};
|
||||
|
||||
static std::array<std::array<bool, detail::lengthof_alphabet>, detail::max_alphabet> build_alphabet()
|
||||
template<typename Array2D, typename First, typename Second>
|
||||
constexpr static void set_alphabet(Array2D &array, const First first, const Second second) noexcept
|
||||
{
|
||||
std::array<std::array<bool, detail::lengthof_alphabet>, detail::max_alphabet> alphabet;
|
||||
auto *first_ptr = &std::get<0>(array) + static_cast<std::size_t>(first);
|
||||
auto *second_ptr = &std::get<0>(*first_ptr) + static_cast<std::size_t>(second);
|
||||
*second_ptr = true;
|
||||
}
|
||||
|
||||
for (auto &alpha : alphabet) {
|
||||
alpha.fill(false);
|
||||
}
|
||||
constexpr static std::array<std::array<bool, detail::lengthof_alphabet>, detail::max_alphabet> build_alphabet() noexcept
|
||||
{
|
||||
std::array<std::array<bool, detail::lengthof_alphabet>, detail::max_alphabet> alphabet{};
|
||||
|
||||
alphabet[detail::symbol_alphabet][static_cast<size_t>('?')]=true;
|
||||
alphabet[detail::symbol_alphabet][static_cast<size_t>('+')]=true;
|
||||
alphabet[detail::symbol_alphabet][static_cast<size_t>('-')]=true;
|
||||
alphabet[detail::symbol_alphabet][static_cast<size_t>('*')]=true;
|
||||
alphabet[detail::symbol_alphabet][static_cast<size_t>('/')]=true;
|
||||
alphabet[detail::symbol_alphabet][static_cast<size_t>('|')]=true;
|
||||
alphabet[detail::symbol_alphabet][static_cast<size_t>('&')]=true;
|
||||
alphabet[detail::symbol_alphabet][static_cast<size_t>('^')]=true;
|
||||
alphabet[detail::symbol_alphabet][static_cast<size_t>('=')]=true;
|
||||
alphabet[detail::symbol_alphabet][static_cast<size_t>('.')]=true;
|
||||
alphabet[detail::symbol_alphabet][static_cast<size_t>('<')]=true;
|
||||
alphabet[detail::symbol_alphabet][static_cast<size_t>('>')]=true;
|
||||
set_alphabet(alphabet, detail::symbol_alphabet, '?');
|
||||
|
||||
for ( size_t c = 'a' ; c <= 'z' ; ++c ) { alphabet[detail::keyword_alphabet][c]=true; }
|
||||
for ( size_t c = 'A' ; c <= 'Z' ; ++c ) { alphabet[detail::keyword_alphabet][c]=true; }
|
||||
for ( size_t c = '0' ; c <= '9' ; ++c ) { alphabet[detail::keyword_alphabet][c]=true; }
|
||||
alphabet[detail::keyword_alphabet][static_cast<size_t>('_')]=true;
|
||||
set_alphabet(alphabet, detail::symbol_alphabet, '?');
|
||||
set_alphabet(alphabet, detail::symbol_alphabet, '+');
|
||||
set_alphabet(alphabet, detail::symbol_alphabet, '-');
|
||||
set_alphabet(alphabet, detail::symbol_alphabet, '*');
|
||||
set_alphabet(alphabet, detail::symbol_alphabet, '/');
|
||||
set_alphabet(alphabet, detail::symbol_alphabet, '|');
|
||||
set_alphabet(alphabet, detail::symbol_alphabet, '&');
|
||||
set_alphabet(alphabet, detail::symbol_alphabet, '^');
|
||||
set_alphabet(alphabet, detail::symbol_alphabet, '=');
|
||||
set_alphabet(alphabet, detail::symbol_alphabet, '.');
|
||||
set_alphabet(alphabet, detail::symbol_alphabet, '<');
|
||||
set_alphabet(alphabet, detail::symbol_alphabet, '>');
|
||||
|
||||
for ( size_t c = '0' ; c <= '9' ; ++c ) { alphabet[detail::int_alphabet][c]=true; }
|
||||
for ( size_t c = '0' ; c <= '9' ; ++c ) { alphabet[detail::float_alphabet][c]=true; }
|
||||
alphabet[detail::float_alphabet][static_cast<size_t>('.')]=true;
|
||||
for ( size_t c = 'a' ; c <= 'z' ; ++c ) { set_alphabet(alphabet, detail::keyword_alphabet, c); }
|
||||
for ( size_t c = 'A' ; c <= 'Z' ; ++c ) { set_alphabet(alphabet, detail::keyword_alphabet, c); }
|
||||
for ( size_t c = '0' ; c <= '9' ; ++c ) { set_alphabet(alphabet, detail::keyword_alphabet, c); }
|
||||
set_alphabet(alphabet, detail::keyword_alphabet, '_');
|
||||
|
||||
for ( size_t c = '0' ; c <= '9' ; ++c ) { alphabet[detail::hex_alphabet][c]=true; }
|
||||
for ( size_t c = 'a' ; c <= 'f' ; ++c ) { alphabet[detail::hex_alphabet][c]=true; }
|
||||
for ( size_t c = 'A' ; c <= 'F' ; ++c ) { alphabet[detail::hex_alphabet][c]=true; }
|
||||
for ( size_t c = '0' ; c <= '9' ; ++c ) { set_alphabet(alphabet, detail::int_alphabet, c); }
|
||||
for ( size_t c = '0' ; c <= '9' ; ++c ) { set_alphabet(alphabet, detail::float_alphabet, c); }
|
||||
set_alphabet(alphabet, detail::float_alphabet, '.');
|
||||
|
||||
alphabet[detail::x_alphabet][static_cast<size_t>('x')]=true;
|
||||
alphabet[detail::x_alphabet][static_cast<size_t>('X')]=true;
|
||||
for ( size_t c = '0' ; c <= '9' ; ++c ) { set_alphabet(alphabet, detail::hex_alphabet, c); }
|
||||
for ( size_t c = 'a' ; c <= 'f' ; ++c ) { set_alphabet(alphabet, detail::hex_alphabet, c); }
|
||||
for ( size_t c = 'A' ; c <= 'F' ; ++c ) { set_alphabet(alphabet, detail::hex_alphabet, c); }
|
||||
|
||||
for ( size_t c = '0' ; c <= '1' ; ++c ) { alphabet[detail::bin_alphabet][c]=true; }
|
||||
alphabet[detail::b_alphabet][static_cast<size_t>('b')]=true;
|
||||
alphabet[detail::b_alphabet][static_cast<size_t>('B')]=true;
|
||||
set_alphabet(alphabet, detail::x_alphabet, 'x');
|
||||
set_alphabet(alphabet, detail::x_alphabet, 'X');
|
||||
|
||||
for ( size_t c = 'a' ; c <= 'z' ; ++c ) { alphabet[detail::id_alphabet][c]=true; }
|
||||
for ( size_t c = 'A' ; c <= 'Z' ; ++c ) { alphabet[detail::id_alphabet][c]=true; }
|
||||
alphabet[detail::id_alphabet][static_cast<size_t>('_')] = true;
|
||||
for ( size_t c = '0' ; c <= '1' ; ++c ) { set_alphabet(alphabet, detail::bin_alphabet, c); }
|
||||
set_alphabet(alphabet, detail::b_alphabet, 'b');
|
||||
set_alphabet(alphabet, detail::b_alphabet, 'B');
|
||||
|
||||
alphabet[detail::white_alphabet][static_cast<size_t>(' ')]=true;
|
||||
alphabet[detail::white_alphabet][static_cast<size_t>('\t')]=true;
|
||||
for ( size_t c = 'a' ; c <= 'z' ; ++c ) { set_alphabet(alphabet, detail::id_alphabet, c); }
|
||||
for ( size_t c = 'A' ; c <= 'Z' ; ++c ) { set_alphabet(alphabet, detail::id_alphabet, c); }
|
||||
set_alphabet(alphabet, detail::id_alphabet, '_');
|
||||
|
||||
alphabet[detail::int_suffix_alphabet][static_cast<size_t>('l')] = true;
|
||||
alphabet[detail::int_suffix_alphabet][static_cast<size_t>('L')] = true;
|
||||
alphabet[detail::int_suffix_alphabet][static_cast<size_t>('u')] = true;
|
||||
alphabet[detail::int_suffix_alphabet][static_cast<size_t>('U')] = true;
|
||||
set_alphabet(alphabet, detail::white_alphabet, ' ');
|
||||
set_alphabet(alphabet, detail::white_alphabet, '\t');
|
||||
|
||||
alphabet[detail::float_suffix_alphabet][static_cast<size_t>('l')] = true;
|
||||
alphabet[detail::float_suffix_alphabet][static_cast<size_t>('L')] = true;
|
||||
alphabet[detail::float_suffix_alphabet][static_cast<size_t>('f')] = true;
|
||||
alphabet[detail::float_suffix_alphabet][static_cast<size_t>('F')] = true;
|
||||
set_alphabet(alphabet, detail::int_suffix_alphabet, 'l');
|
||||
set_alphabet(alphabet, detail::int_suffix_alphabet, 'L');
|
||||
set_alphabet(alphabet, detail::int_suffix_alphabet, 'u');
|
||||
set_alphabet(alphabet, detail::int_suffix_alphabet, 'U');
|
||||
|
||||
set_alphabet(alphabet, detail::float_suffix_alphabet, 'l');
|
||||
set_alphabet(alphabet, detail::float_suffix_alphabet, 'L');
|
||||
set_alphabet(alphabet, detail::float_suffix_alphabet, 'f');
|
||||
set_alphabet(alphabet, detail::float_suffix_alphabet, 'F');
|
||||
|
||||
return alphabet;
|
||||
}
|
||||
|
||||
static const std::array<std::array<bool, detail::lengthof_alphabet>, detail::max_alphabet> &create_alphabet()
|
||||
|
||||
struct Operator_Matches
|
||||
{
|
||||
static const auto alpha = build_alphabet();
|
||||
return alpha;
|
||||
}
|
||||
using SS = utility::Static_String;
|
||||
|
||||
|
||||
static const std::vector<std::vector<utility::Static_String>> &create_operator_matches() {
|
||||
static const std::vector<std::vector<utility::Static_String>> operator_matches {
|
||||
{"?"},
|
||||
{"||"},
|
||||
{"&&"},
|
||||
{"|"},
|
||||
{"^"},
|
||||
{"&"},
|
||||
{"==", "!="},
|
||||
{"<", "<=", ">", ">="},
|
||||
{"<<", ">>"},
|
||||
std::array<utility::Static_String, 1> m_0 {{SS("?")}};
|
||||
std::array<utility::Static_String, 1> m_1 {{SS("||")}};
|
||||
std::array<utility::Static_String, 1> m_2 {{SS("&&")}};
|
||||
std::array<utility::Static_String, 1> m_3 {{SS("|")}};
|
||||
std::array<utility::Static_String, 1> m_4 {{SS("^")}};
|
||||
std::array<utility::Static_String, 1> m_5 {{SS("&")}};
|
||||
std::array<utility::Static_String, 2> m_6 {{SS("=="), SS("!=")}};
|
||||
std::array<utility::Static_String, 4> m_7 {{SS("<"), SS("<="), SS(">"), SS(">=")}};
|
||||
std::array<utility::Static_String, 2> m_8 {{SS("<<"), SS(">>")}};
|
||||
//We share precedence here but then separate them later
|
||||
{"+", "-"},
|
||||
{"*", "/", "%"},
|
||||
{"++", "--", "-", "+", "!", "~"}
|
||||
};
|
||||
std::array<utility::Static_String, 2> m_9 {{SS("+"), SS("-")}};
|
||||
std::array<utility::Static_String, 3> m_10 {{SS("*"), SS("/"), SS("%")}};
|
||||
std::array<utility::Static_String, 6> m_11 {{SS("++"), SS("--"), SS("-"), SS("+"), SS("!"), SS("~")}};
|
||||
|
||||
return operator_matches;
|
||||
}
|
||||
bool is_match(const std::string_view &t_str) const noexcept {
|
||||
constexpr std::array<std::size_t, 12> groups{{0,1,2,3,4,5,6,7,8,9,10,11}};
|
||||
return std::any_of(groups.begin(), groups.end(), [&t_str, this](const std::size_t group){ return is_match(group, t_str); });
|
||||
}
|
||||
|
||||
template<typename Predicate>
|
||||
bool any_of(const std::size_t t_group, Predicate &&predicate) const
|
||||
{
|
||||
auto match = [&predicate](const auto &array) {
|
||||
return std::any_of(array.begin(), array.end(), predicate);
|
||||
};
|
||||
|
||||
static const std::array<Operator_Precidence, 12> &create_operators() {
|
||||
static const std::array<Operator_Precidence, 12> operators = { {
|
||||
switch (t_group) {
|
||||
case 0: return match(m_0);
|
||||
case 1: return match(m_1);
|
||||
case 2: return match(m_2);
|
||||
case 3: return match(m_3);
|
||||
case 4: return match(m_4);
|
||||
case 5: return match(m_5);
|
||||
case 6: return match(m_6);
|
||||
case 7: return match(m_7);
|
||||
case 8: return match(m_8);
|
||||
case 9: return match(m_9);
|
||||
case 10: return match(m_10);
|
||||
case 11: return match(m_11);
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr bool is_match(const std::size_t t_group, const std::string_view &t_str) const noexcept {
|
||||
auto match = [&t_str](const auto &array) {
|
||||
return std::any_of(array.begin(), array.end(), [&t_str](const auto &v){ return v == t_str; });
|
||||
};
|
||||
|
||||
switch (t_group) {
|
||||
case 0: return match(m_0);
|
||||
case 1: return match(m_1);
|
||||
case 2: return match(m_2);
|
||||
case 3: return match(m_3);
|
||||
case 4: return match(m_4);
|
||||
case 5: return match(m_5);
|
||||
case 6: return match(m_6);
|
||||
case 7: return match(m_7);
|
||||
case 8: return match(m_8);
|
||||
case 9: return match(m_9);
|
||||
case 10: return match(m_10);
|
||||
case 11: return match(m_11);
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
constexpr static std::array<Operator_Precidence, 12> create_operators() noexcept {
|
||||
std::array<Operator_Precidence, 12> operators = { {
|
||||
Operator_Precidence::Ternary_Cond,
|
||||
Operator_Precidence::Logical_Or,
|
||||
Operator_Precidence::Logical_And,
|
||||
@ -253,39 +303,12 @@ namespace chaiscript
|
||||
return operators;
|
||||
}
|
||||
|
||||
static const utility::Static_String &multiline_comment_end()
|
||||
{
|
||||
static const utility::Static_String s("*/");
|
||||
return s;
|
||||
}
|
||||
|
||||
static const utility::Static_String &multiline_comment_begin()
|
||||
{
|
||||
static const utility::Static_String s("/*");
|
||||
return s;
|
||||
}
|
||||
|
||||
static const utility::Static_String &singleline_comment()
|
||||
{
|
||||
static const utility::Static_String s("//");
|
||||
return s;
|
||||
}
|
||||
|
||||
static const utility::Static_String &annotation()
|
||||
{
|
||||
static const utility::Static_String s("#");
|
||||
return s;
|
||||
}
|
||||
|
||||
static const utility::Static_String &cr_lf()
|
||||
{
|
||||
static const utility::Static_String s("\r\n");
|
||||
return s;
|
||||
}
|
||||
|
||||
const std::array<std::array<bool, detail::lengthof_alphabet>, detail::max_alphabet> &m_alphabet = create_alphabet();
|
||||
const std::vector<std::vector<utility::Static_String>> &m_operator_matches = create_operator_matches();
|
||||
const std::array<Operator_Precidence, 12> &m_operators = create_operators();
|
||||
constexpr static utility::Static_String m_multiline_comment_end{"*/"};
|
||||
constexpr static utility::Static_String m_multiline_comment_begin{"/*"};
|
||||
constexpr static utility::Static_String m_singleline_comment{"//"};
|
||||
constexpr static utility::Static_String m_annotation{"#"};
|
||||
constexpr static utility::Static_String m_cr_lf{"\r\n"};
|
||||
constexpr static auto m_operators = create_operators();
|
||||
|
||||
std::shared_ptr<std::string> m_filename;
|
||||
std::vector<eval::AST_Node_Impl_Ptr<Tracer>> m_match_stack;
|
||||
@ -293,22 +316,27 @@ namespace chaiscript
|
||||
|
||||
struct Position
|
||||
{
|
||||
Position() = default;
|
||||
constexpr Position() = default;
|
||||
|
||||
Position(std::string::const_iterator t_pos, std::string::const_iterator t_end)
|
||||
constexpr Position(const char * t_pos, const char * t_end) noexcept
|
||||
: line(1), col(1), m_pos(t_pos), m_end(t_end), m_last_col(1)
|
||||
{
|
||||
}
|
||||
|
||||
static std::string str(const Position &t_begin, const Position &t_end) {
|
||||
return std::string(t_begin.m_pos, t_end.m_pos);
|
||||
static std::string_view str(const Position &t_begin, const Position &t_end) noexcept {
|
||||
if (t_begin.m_pos != nullptr && t_end.m_pos != nullptr) {
|
||||
return std::string_view(t_begin.m_pos, std::distance(t_begin.m_pos, t_end.m_pos));
|
||||
} else {
|
||||
return {};
|
||||
}
|
||||
}
|
||||
|
||||
Position &operator++() {
|
||||
constexpr Position &operator++() noexcept {
|
||||
if (m_pos != m_end) {
|
||||
if (*m_pos == '\n') {
|
||||
++line;
|
||||
m_last_col = std::exchange(col, 1);
|
||||
m_last_col = col;
|
||||
col = 1;
|
||||
} else {
|
||||
++col;
|
||||
}
|
||||
@ -318,7 +346,7 @@ namespace chaiscript
|
||||
return *this;
|
||||
}
|
||||
|
||||
Position &operator--() {
|
||||
constexpr Position &operator--() noexcept {
|
||||
--m_pos;
|
||||
if (*m_pos == '\n') {
|
||||
--line;
|
||||
@ -329,12 +357,12 @@ namespace chaiscript
|
||||
return *this;
|
||||
}
|
||||
|
||||
Position &operator+=(size_t t_distance) {
|
||||
constexpr Position &operator+=(size_t t_distance) noexcept {
|
||||
*this = (*this) + t_distance;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Position operator+(size_t t_distance) const {
|
||||
constexpr Position operator+(size_t t_distance) const noexcept {
|
||||
Position ret(*this);
|
||||
for (size_t i = 0; i < t_distance; ++i) {
|
||||
++ret;
|
||||
@ -342,12 +370,12 @@ namespace chaiscript
|
||||
return ret;
|
||||
}
|
||||
|
||||
Position &operator-=(size_t t_distance) {
|
||||
constexpr Position &operator-=(size_t t_distance) noexcept {
|
||||
*this = (*this) - t_distance;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Position operator-(size_t t_distance) const {
|
||||
constexpr Position operator-(size_t t_distance) const noexcept {
|
||||
Position ret(*this);
|
||||
for (size_t i = 0; i < t_distance; ++i) {
|
||||
--ret;
|
||||
@ -355,26 +383,25 @@ namespace chaiscript
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool operator==(const Position &t_rhs) const {
|
||||
constexpr bool operator==(const Position &t_rhs) const noexcept {
|
||||
return m_pos == t_rhs.m_pos;
|
||||
}
|
||||
|
||||
bool operator!=(const Position &t_rhs) const {
|
||||
constexpr bool operator!=(const Position &t_rhs) const noexcept {
|
||||
return m_pos != t_rhs.m_pos;
|
||||
}
|
||||
|
||||
bool has_more() const {
|
||||
constexpr bool has_more() const noexcept {
|
||||
return m_pos != m_end;
|
||||
}
|
||||
|
||||
size_t remaining() const {
|
||||
return static_cast<size_t>(std::distance(m_pos, m_end));
|
||||
constexpr size_t remaining() const noexcept {
|
||||
return static_cast<size_t>(m_end - m_pos);
|
||||
}
|
||||
|
||||
const char& operator*() const {
|
||||
constexpr const char& operator*() const noexcept {
|
||||
if (m_pos == m_end) {
|
||||
static const char ktmp ='\0';
|
||||
return ktmp;
|
||||
return ""[0];
|
||||
} else {
|
||||
return *m_pos;
|
||||
}
|
||||
@ -384,8 +411,8 @@ namespace chaiscript
|
||||
int col = -1;
|
||||
|
||||
private:
|
||||
std::string::const_iterator m_pos;
|
||||
std::string::const_iterator m_end;
|
||||
const char *m_pos = nullptr;
|
||||
const char *m_end = nullptr;
|
||||
int m_last_col = -1;
|
||||
};
|
||||
|
||||
@ -394,14 +421,14 @@ namespace chaiscript
|
||||
Tracer m_tracer;
|
||||
Optimizer m_optimizer;
|
||||
|
||||
void validate_object_name(const std::string &name) const
|
||||
void validate_object_name(const std::string_view &name) const
|
||||
{
|
||||
if (!Name_Validator::valid_object_name(name)) {
|
||||
throw exception::eval_error("Invalid Object Name: " + name, File_Position(m_position.line, m_position.col), *m_filename);
|
||||
throw exception::eval_error("Invalid Object Name: " + std::string(name), File_Position(m_position.line, m_position.col), *m_filename);
|
||||
}
|
||||
}
|
||||
|
||||
public:
|
||||
public:
|
||||
explicit ChaiScript_Parser(Tracer tracer = Tracer(), Optimizer optimizer=Optimizer())
|
||||
: m_tracer(std::move(tracer)),
|
||||
m_optimizer(std::move(optimizer))
|
||||
@ -409,12 +436,12 @@ namespace chaiscript
|
||||
m_match_stack.reserve(2);
|
||||
}
|
||||
|
||||
Tracer &get_tracer()
|
||||
Tracer &get_tracer() noexcept
|
||||
{
|
||||
return m_tracer;
|
||||
}
|
||||
|
||||
Optimizer &get_optimizer()
|
||||
Optimizer &get_optimizer() noexcept
|
||||
{
|
||||
return m_optimizer;
|
||||
}
|
||||
@ -424,8 +451,13 @@ namespace chaiscript
|
||||
ChaiScript_Parser(ChaiScript_Parser &&) = default;
|
||||
ChaiScript_Parser &operator=(ChaiScript_Parser &&) = delete;
|
||||
|
||||
constexpr static auto m_alphabet = build_alphabet();
|
||||
constexpr static Operator_Matches m_operator_matches{};
|
||||
|
||||
/// test a char in an m_alphabet
|
||||
bool char_in_alphabet(char c, detail::Alphabet a) const { return m_alphabet[a][static_cast<uint8_t>(c)]; }
|
||||
constexpr bool char_in_alphabet(char c, detail::Alphabet a) const noexcept {
|
||||
return m_alphabet[a][static_cast<uint8_t>(c)];
|
||||
}
|
||||
|
||||
/// Prints the parsed ast_nodes as a tree
|
||||
void debug_print(const AST_Node &t, std::string prepend = "") const override {
|
||||
@ -483,7 +515,7 @@ namespace chaiscript
|
||||
|
||||
|
||||
/// Reads a symbol group from input if it matches the parameter, without skipping initial whitespace
|
||||
inline auto Symbol_(const utility::Static_String &sym)
|
||||
inline auto Symbol_(const utility::Static_String &sym) noexcept
|
||||
{
|
||||
const auto len = sym.size();
|
||||
if (m_position.remaining() >= len) {
|
||||
@ -500,18 +532,18 @@ namespace chaiscript
|
||||
|
||||
/// Skips any multi-line or single-line comment
|
||||
bool SkipComment() {
|
||||
if (Symbol_(multiline_comment_begin())) {
|
||||
if (Symbol_(m_multiline_comment_begin)) {
|
||||
while (m_position.has_more()) {
|
||||
if (Symbol_(multiline_comment_end())) {
|
||||
if (Symbol_(m_multiline_comment_end)) {
|
||||
break;
|
||||
} else if (!Eol_()) {
|
||||
++m_position;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else if (Symbol_(singleline_comment())) {
|
||||
} else if (Symbol_(m_singleline_comment)) {
|
||||
while (m_position.has_more()) {
|
||||
if (Symbol_(cr_lf())) {
|
||||
if (Symbol_(m_cr_lf)) {
|
||||
m_position -= 2;
|
||||
break;
|
||||
} else if (Char_('\n')) {
|
||||
@ -522,9 +554,9 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
return true;
|
||||
} else if (Symbol_(annotation())) {
|
||||
} else if (Symbol_(m_annotation)) {
|
||||
while (m_position.has_more()) {
|
||||
if (Symbol_(cr_lf())) {
|
||||
if (Symbol_(m_cr_lf)) {
|
||||
m_position -= 2;
|
||||
break;
|
||||
} else if (Char_('\n')) {
|
||||
@ -575,7 +607,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
/// Reads the optional exponent (scientific notation) and suffix for a Float
|
||||
bool read_exponent_and_suffix() {
|
||||
bool read_exponent_and_suffix() noexcept {
|
||||
// Support a form of scientific notation: 1e-5, 35.5E+8, 0.01e19
|
||||
if (m_position.has_more() && (std::tolower(*m_position) == 'e')) {
|
||||
++m_position;
|
||||
@ -603,7 +635,7 @@ namespace chaiscript
|
||||
|
||||
|
||||
/// Reads a floating point value from input, without skipping initial whitespace
|
||||
bool Float_() {
|
||||
bool Float_() noexcept {
|
||||
if (m_position.has_more() && char_in_alphabet(*m_position,detail::float_alphabet) ) {
|
||||
while (m_position.has_more() && char_in_alphabet(*m_position,detail::int_alphabet) ) {
|
||||
++m_position;
|
||||
@ -631,7 +663,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
/// Reads a hex value from input, without skipping initial whitespace
|
||||
bool Hex_() {
|
||||
bool Hex_() noexcept {
|
||||
if (m_position.has_more() && (*m_position == '0')) {
|
||||
++m_position;
|
||||
|
||||
@ -692,7 +724,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
/// Parses a floating point value and returns a Boxed_Value representation of it
|
||||
static Boxed_Value buildFloat(const std::string &t_val)
|
||||
static Boxed_Value buildFloat(const std::string_view &t_val)
|
||||
{
|
||||
bool float_ = false;
|
||||
bool long_ = false;
|
||||
@ -725,7 +757,7 @@ namespace chaiscript
|
||||
|
||||
|
||||
|
||||
static Boxed_Value buildInt(const int base, const std::string &t_val, const bool prefixed)
|
||||
static Boxed_Value buildInt(const int base, std::string_view t_val, const bool prefixed)
|
||||
{
|
||||
bool unsigned_ = false;
|
||||
bool long_ = false;
|
||||
@ -752,7 +784,7 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
const auto val = prefixed?std::string(t_val.begin()+2,t_val.end()):t_val;
|
||||
if (prefixed) { t_val.remove_prefix(2); };
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
@ -766,7 +798,8 @@ namespace chaiscript
|
||||
#endif
|
||||
|
||||
try {
|
||||
auto u = std::stoll(val,nullptr,base);
|
||||
/// TODO fix this to use from_chars
|
||||
auto u = std::stoll(std::string(t_val),nullptr,base);
|
||||
|
||||
|
||||
if (!unsigned_ && !long_ && u >= std::numeric_limits<int>::min() && u <= std::numeric_limits<int>::max()) {
|
||||
@ -789,7 +822,8 @@ namespace chaiscript
|
||||
} catch (const std::out_of_range &) {
|
||||
// too big to be signed
|
||||
try {
|
||||
auto u = std::stoull(val,nullptr,base);
|
||||
/// TODO fix this to use from_chars
|
||||
auto u = std::stoull(std::string(t_val),nullptr,base);
|
||||
|
||||
if (!longlong_ && u >= std::numeric_limits<unsigned long>::min() && u <= std::numeric_limits<unsigned long>::max()) {
|
||||
return const_var(static_cast<unsigned long>(u));
|
||||
@ -809,9 +843,9 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
template<typename T, typename ... Param>
|
||||
std::unique_ptr<eval::AST_Node_Impl<Tracer>> make_node(std::string t_match, const int t_prev_line, const int t_prev_col, Param && ...param)
|
||||
std::unique_ptr<eval::AST_Node_Impl<Tracer>> make_node(std::string_view t_match, const int t_prev_line, const int t_prev_col, Param && ...param)
|
||||
{
|
||||
return chaiscript::make_unique<eval::AST_Node_Impl<Tracer>, T>(std::move(t_match), Parse_Location(m_filename, t_prev_line, t_prev_col, m_position.line, m_position.col), std::forward<Param>(param)...);
|
||||
return chaiscript::make_unique<eval::AST_Node_Impl<Tracer>, T>(std::string(t_match), Parse_Location(m_filename, t_prev_line, t_prev_col, m_position.line, m_position.col), std::forward<Param>(param)...);
|
||||
}
|
||||
|
||||
/// Reads a number from the input, detecting if it's an integer or floating point
|
||||
@ -824,20 +858,20 @@ namespace chaiscript
|
||||
if (Hex_()) {
|
||||
auto match = Position::str(start, m_position);
|
||||
auto bv = buildInt(16, match, true);
|
||||
m_match_stack.emplace_back(make_node<eval::Constant_AST_Node<Tracer>>(std::move(match), start.line, start.col, std::move(bv)));
|
||||
m_match_stack.emplace_back(make_node<eval::Constant_AST_Node<Tracer>>(match, start.line, start.col, std::move(bv)));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Binary_()) {
|
||||
auto match = Position::str(start, m_position);
|
||||
auto bv = buildInt(2, match, true);
|
||||
m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(std::move(match), start.line, start.col, std::move(bv)));
|
||||
m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(match, start.line, start.col, std::move(bv)));
|
||||
return true;
|
||||
}
|
||||
if (Float_()) {
|
||||
auto match = Position::str(start, m_position);
|
||||
auto bv = buildFloat(match);
|
||||
m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(std::move(match), start.line, start.col, std::move(bv)));
|
||||
m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(match, start.line, start.col, std::move(bv)));
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
@ -845,11 +879,11 @@ namespace chaiscript
|
||||
auto match = Position::str(start, m_position);
|
||||
if (!match.empty() && (match[0] == '0')) {
|
||||
auto bv = buildInt(8, match, false);
|
||||
m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(std::move(match), start.line, start.col, std::move(bv)));
|
||||
m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(match, start.line, start.col, std::move(bv)));
|
||||
}
|
||||
else if (!match.empty()) {
|
||||
auto bv = buildInt(10, match, false);
|
||||
m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(std::move(match), start.line, start.col, std::move(bv)));
|
||||
m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(match, start.line, start.col, std::move(bv)));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
@ -908,7 +942,7 @@ namespace chaiscript
|
||||
if (Id_()) {
|
||||
|
||||
auto text = Position::str(start, m_position);
|
||||
const auto text_hash = utility::fnv1a_32(text.c_str());
|
||||
const auto text_hash = utility::hash(text);
|
||||
|
||||
if (validate) {
|
||||
validate_object_name(text);
|
||||
@ -920,29 +954,29 @@ namespace chaiscript
|
||||
#endif
|
||||
|
||||
switch (text_hash) {
|
||||
case utility::fnv1a_32("true"): {
|
||||
m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(std::move(text), start.line, start.col, const_var(true)));
|
||||
case utility::hash("true"): {
|
||||
m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(text, start.line, start.col, const_var(true)));
|
||||
} break;
|
||||
case utility::fnv1a_32("false"): {
|
||||
m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(std::move(text), start.line, start.col, const_var(false)));
|
||||
case utility::hash("false"): {
|
||||
m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(text, start.line, start.col, const_var(false)));
|
||||
} break;
|
||||
case utility::fnv1a_32("Infinity"): {
|
||||
m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(std::move(text), start.line, start.col,
|
||||
case utility::hash("Infinity"): {
|
||||
m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(text, start.line, start.col,
|
||||
const_var(std::numeric_limits<double>::infinity())));
|
||||
} break;
|
||||
case utility::fnv1a_32("NaN"): {
|
||||
m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(std::move(text), start.line, start.col,
|
||||
case utility::hash("NaN"): {
|
||||
m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(text, start.line, start.col,
|
||||
const_var(std::numeric_limits<double>::quiet_NaN())));
|
||||
} break;
|
||||
case utility::fnv1a_32("__LINE__"): {
|
||||
m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(std::move(text), start.line, start.col,
|
||||
case utility::hash("__LINE__"): {
|
||||
m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(text, start.line, start.col,
|
||||
const_var(start.line)));
|
||||
} break;
|
||||
case utility::fnv1a_32("__FILE__"): {
|
||||
m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(std::move(text), start.line, start.col,
|
||||
case utility::hash("__FILE__"): {
|
||||
m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(text, start.line, start.col,
|
||||
const_var(m_filename)));
|
||||
} break;
|
||||
case utility::fnv1a_32("__FUNC__"): {
|
||||
case utility::hash("__FUNC__"): {
|
||||
std::string fun_name = "NOT_IN_FUNCTION";
|
||||
for (size_t idx = m_match_stack.empty() ? 0 : m_match_stack.size() - 1; idx > 0; --idx)
|
||||
{
|
||||
@ -952,10 +986,10 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(std::move(text), start.line, start.col,
|
||||
m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(text, start.line, start.col,
|
||||
const_var(fun_name)));
|
||||
} break;
|
||||
case utility::fnv1a_32("__CLASS__"): {
|
||||
case utility::hash("__CLASS__"): {
|
||||
std::string fun_name = "NOT_IN_CLASS";
|
||||
for (size_t idx = m_match_stack.empty() ? 0 : m_match_stack.size() - 1; idx > 1; --idx)
|
||||
{
|
||||
@ -969,15 +1003,16 @@ namespace chaiscript
|
||||
m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(std::move(text), start.line, start.col,
|
||||
const_var(fun_name)));
|
||||
} break;
|
||||
case utility::fnv1a_32("_"): {
|
||||
case utility::hash("_"): {
|
||||
m_match_stack.push_back(make_node<eval::Constant_AST_Node<Tracer>>(std::move(text), start.line, start.col,
|
||||
Boxed_Value(std::make_shared<dispatch::Placeholder_Object>())));
|
||||
} break;
|
||||
default: {
|
||||
std::string val = std::move(text);
|
||||
auto val = text;
|
||||
if (*start == '`') {
|
||||
// 'escaped' literal, like an operator name
|
||||
val = Position::str(start+1, m_position-1);
|
||||
// val.remove_prefix(1); val.remove_suffix(1);
|
||||
}
|
||||
m_match_stack.push_back(make_node<eval::Id_AST_Node<Tracer>>(val, start.line, start.col));
|
||||
} break;
|
||||
@ -1060,7 +1095,7 @@ namespace chaiscript
|
||||
struct Char_Parser
|
||||
{
|
||||
string_type &match;
|
||||
typedef typename string_type::value_type char_type;
|
||||
using char_type = typename string_type::value_type;
|
||||
bool is_escaped = false;
|
||||
bool is_interpolated = false;
|
||||
bool saw_interpolation_marker = false;
|
||||
@ -1456,14 +1491,8 @@ namespace chaiscript
|
||||
return retval;
|
||||
}
|
||||
|
||||
bool is_operator(const std::string &t_s) const {
|
||||
return std::any_of(m_operator_matches.begin(), m_operator_matches.end(),
|
||||
[t_s](const std::vector<utility::Static_String> &opers) {
|
||||
return std::any_of(opers.begin(), opers.end(),
|
||||
[t_s](const utility::Static_String &s) {
|
||||
return t_s == s.c_str();
|
||||
});
|
||||
});
|
||||
bool is_operator(const std::string_view &t_s) const noexcept {
|
||||
return m_operator_matches.is_match(t_s);
|
||||
}
|
||||
|
||||
/// Reads (and potentially captures) a symbol group from input if it matches the parameter
|
||||
@ -1490,7 +1519,7 @@ namespace chaiscript
|
||||
bool Eol_(const bool t_eos = false) {
|
||||
bool retval = false;
|
||||
|
||||
if (m_position.has_more() && (Symbol_(cr_lf()) || Char_('\n'))) {
|
||||
if (m_position.has_more() && (Symbol_(m_cr_lf) || Char_('\n'))) {
|
||||
retval = true;
|
||||
//++m_position.line;
|
||||
m_position.col = 1;
|
||||
@ -2381,7 +2410,7 @@ namespace chaiscript
|
||||
Depth_Counter dc{this};
|
||||
const auto prev_stack_top = m_match_stack.size();
|
||||
using SS = utility::Static_String;
|
||||
constexpr const std::array<utility::Static_String, 6> prefix_opers{{
|
||||
const std::array<utility::Static_String, 6> prefix_opers{{
|
||||
SS{"++"},
|
||||
SS{"--"},
|
||||
SS{"-"},
|
||||
@ -2414,16 +2443,19 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
bool Operator_Helper(const size_t t_precedence, std::string &oper) {
|
||||
Depth_Counter dc{this};
|
||||
for (auto & elem : m_operator_matches[t_precedence]) {
|
||||
if (Symbol(elem)) {
|
||||
oper = elem.c_str();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return m_operator_matches.any_of(t_precedence,
|
||||
[&oper, this](const auto &elem){
|
||||
if (Symbol(elem)) {
|
||||
oper = elem.c_str();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
bool Operator(const size_t t_precedence = 0) {
|
||||
Depth_Counter dc{this};
|
||||
bool retval = false;
|
||||
@ -2661,7 +2693,9 @@ 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) {
|
||||
m_position = Position(t_input.begin(), t_input.end());
|
||||
const auto begin = t_input.empty() ? nullptr : &t_input.front();
|
||||
const auto end = begin == nullptr ? nullptr : begin + t_input.size();
|
||||
m_position = Position(begin, end);
|
||||
m_filename = std::make_shared<std::string>(std::move(t_fname));
|
||||
|
||||
if ((t_input.size() > 1) && (t_input[0] == '#') && (t_input[1] == '!')) {
|
||||
|
||||
@ -49,6 +49,19 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
static T cast_symbol(void *p) noexcept
|
||||
{
|
||||
union cast_union
|
||||
{
|
||||
T func_ptr;
|
||||
void *in_ptr;
|
||||
};
|
||||
|
||||
cast_union c;
|
||||
c.in_ptr = p;
|
||||
return c.func_ptr;
|
||||
}
|
||||
|
||||
T m_symbol;
|
||||
};
|
||||
|
||||
|
||||
@ -14,7 +14,7 @@ namespace chaiscript {
|
||||
struct Noop_Tracer_Detail
|
||||
{
|
||||
template<typename T>
|
||||
void trace(const chaiscript::detail::Dispatch_State &, const AST_Node_Impl<T> *)
|
||||
constexpr void trace(const chaiscript::detail::Dispatch_State &, const AST_Node_Impl<T> *) noexcept
|
||||
{
|
||||
}
|
||||
};
|
||||
@ -23,13 +23,13 @@ namespace chaiscript {
|
||||
struct Tracer : T...
|
||||
{
|
||||
Tracer() = default;
|
||||
explicit Tracer(T ... t)
|
||||
constexpr explicit Tracer(T ... t)
|
||||
: T(std::move(t))...
|
||||
{
|
||||
}
|
||||
|
||||
void do_trace(const chaiscript::detail::Dispatch_State &ds, const AST_Node_Impl<Tracer<T...>> *node) {
|
||||
(void)std::initializer_list<int>{ (static_cast<T&>(*this).trace(ds, node), 0)... };
|
||||
(static_cast<T&>(*this).trace(ds, node), ... );
|
||||
}
|
||||
|
||||
static void trace(const chaiscript::detail::Dispatch_State &ds, const AST_Node_Impl<Tracer<T...>> *node) {
|
||||
|
||||
101
include/chaiscript/utility/hash.hpp
Normal file
101
include/chaiscript/utility/hash.hpp
Normal file
@ -0,0 +1,101 @@
|
||||
// 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
|
||||
|
||||
#ifndef CHAISCRIPT_UTILITY_FNV1A_HPP_
|
||||
#define CHAISCRIPT_UTILITY_FNV1A_HPP_
|
||||
|
||||
|
||||
#include <cstdint>
|
||||
#include "../chaiscript_defines.hpp"
|
||||
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace utility
|
||||
{
|
||||
namespace fnv1a {
|
||||
template<typename Itr>
|
||||
static constexpr std::uint32_t hash(Itr begin, Itr end) noexcept {
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wsign-conversion"
|
||||
#endif
|
||||
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4307)
|
||||
#endif
|
||||
std::uint32_t h = 0x811c9dc5;
|
||||
|
||||
while (begin != end) {
|
||||
h = (h ^ (*begin)) * 0x01000193;
|
||||
++begin;
|
||||
}
|
||||
return h;
|
||||
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
template<size_t N>
|
||||
static constexpr std::uint32_t hash(const char (&str)[N]) noexcept {
|
||||
return hash(std::begin(str), std::end(str)-1);
|
||||
}
|
||||
|
||||
static constexpr std::uint32_t hash(const std::string_view &sv) noexcept {
|
||||
return hash(sv.begin(), sv.end());
|
||||
}
|
||||
|
||||
static inline std::uint32_t hash(const std::string &s) noexcept {
|
||||
return hash(s.begin(), s.end());
|
||||
}
|
||||
}
|
||||
|
||||
namespace jenkins_one_at_a_time {
|
||||
template<typename Itr>
|
||||
static constexpr std::uint32_t hash(Itr begin, Itr end) noexcept {
|
||||
std::uint32_t hash = 0;
|
||||
|
||||
while (begin != end) {
|
||||
hash += *begin;
|
||||
hash += hash << 10;
|
||||
hash ^= hash >> 6;
|
||||
++begin;
|
||||
}
|
||||
|
||||
hash += hash << 3;
|
||||
hash ^= hash >> 11;
|
||||
hash += hash << 15;
|
||||
return hash;
|
||||
}
|
||||
|
||||
template<size_t N>
|
||||
static constexpr std::uint32_t hash(const char (&str)[N]) noexcept {
|
||||
return hash(std::begin(str), std::end(str)-1);
|
||||
}
|
||||
|
||||
static constexpr std::uint32_t hash(const std::string_view &sv) noexcept {
|
||||
return hash(sv.begin(), sv.end());
|
||||
}
|
||||
|
||||
static inline std::uint32_t hash(const std::string &s) noexcept {
|
||||
return hash(s.begin(), s.end());
|
||||
}
|
||||
}
|
||||
|
||||
using fnv1a::hash;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
@ -3,7 +3,6 @@
|
||||
//
|
||||
|
||||
|
||||
#pragma once
|
||||
|
||||
#ifndef SIMPLEJSON_HPP
|
||||
#define SIMPLEJSON_HPP
|
||||
@ -19,7 +18,9 @@
|
||||
#include <initializer_list>
|
||||
#include <ostream>
|
||||
#include <iostream>
|
||||
#include <variant>
|
||||
#include "../chaiscript_defines.hpp"
|
||||
#include "quick_flat_map.hpp"
|
||||
|
||||
namespace json {
|
||||
|
||||
@ -37,7 +38,7 @@ class JSON
|
||||
{
|
||||
public:
|
||||
enum class Class {
|
||||
Null,
|
||||
Null = 0,
|
||||
Object,
|
||||
Array,
|
||||
String,
|
||||
@ -48,155 +49,97 @@ class JSON
|
||||
|
||||
private:
|
||||
|
||||
struct QuickFlatMap
|
||||
|
||||
using Data = std::variant<std::nullptr_t, chaiscript::utility::QuickFlatMap<std::string, JSON>, std::vector<JSON>, std::string, double, std::int64_t, bool>;
|
||||
|
||||
struct Internal
|
||||
{
|
||||
auto find(const std::string &s) {
|
||||
return std::find_if(std::begin(data), std::end(data), [&s](const auto &d) { return d.first == s; });
|
||||
Internal(std::nullptr_t) : d(nullptr) { }
|
||||
Internal() : d(nullptr) { }
|
||||
Internal(Class c) : d(make_type(c)) { }
|
||||
template<typename T> Internal(T t) : d(std::move(t)) { }
|
||||
|
||||
static Data make_type(Class c) {
|
||||
switch (c) {
|
||||
case Class::Null: return nullptr;
|
||||
case Class::Object: return chaiscript::utility::QuickFlatMap<std::string, JSON>{};
|
||||
case Class::Array: return std::vector<JSON>{};
|
||||
case Class::String: return std::string{};
|
||||
case Class::Floating: return double{};
|
||||
case Class::Integral: return std::int64_t{};
|
||||
case Class::Boolean: return bool{};
|
||||
}
|
||||
throw std::runtime_error("unknown type");
|
||||
}
|
||||
|
||||
auto find(const std::string &s) const {
|
||||
return std::find_if(std::begin(data), std::end(data), [&s](const auto &d) { return d.first == s; });
|
||||
}
|
||||
|
||||
auto size() const {
|
||||
return data.size();
|
||||
}
|
||||
|
||||
auto begin() const {
|
||||
return data.begin();
|
||||
}
|
||||
|
||||
auto end() const {
|
||||
return data.end();
|
||||
}
|
||||
|
||||
|
||||
auto begin() {
|
||||
return data.begin();
|
||||
}
|
||||
|
||||
auto end() {
|
||||
return data.end();
|
||||
}
|
||||
|
||||
|
||||
JSON &operator[](const std::string &s) {
|
||||
const auto itr = find(s);
|
||||
if (itr != data.end()) {
|
||||
return itr->second;
|
||||
} else {
|
||||
data.emplace_back(s, JSON());
|
||||
return data.back().second;
|
||||
void set_type(Class c) {
|
||||
if (type() != c) {
|
||||
d = make_type(c);
|
||||
}
|
||||
}
|
||||
|
||||
JSON &at(const std::string &s) {
|
||||
const auto itr = find(s);
|
||||
if (itr != data.end()) {
|
||||
return itr->second;
|
||||
Class type() const noexcept {
|
||||
return Class(d.index());
|
||||
}
|
||||
|
||||
|
||||
template<auto ClassValue, typename Visitor, typename Or>
|
||||
decltype(auto) visit_or(Visitor &&visitor, Or &&other) const
|
||||
{
|
||||
if (type() == Class(ClassValue)) {
|
||||
return visitor(std::get<static_cast<std::size_t>(ClassValue)>(d));
|
||||
} else {
|
||||
throw std::out_of_range("Unknown key: " + s);
|
||||
return other();
|
||||
}
|
||||
}
|
||||
|
||||
const JSON &at(const std::string &s) const {
|
||||
const auto itr = find(s);
|
||||
if (itr != data.end()) {
|
||||
return itr->second;
|
||||
} else {
|
||||
throw std::out_of_range("Unknown key: " + s);
|
||||
}
|
||||
template<auto ClassValue>
|
||||
auto &get_set_type() {
|
||||
set_type(ClassValue);
|
||||
return std::get<static_cast<std::size_t>(ClassValue)>(d);
|
||||
}
|
||||
|
||||
size_t count(const std::string &s) const {
|
||||
return (find(s) != data.end())?1:0;
|
||||
auto &Map() {
|
||||
return get_set_type<Class::Object>();
|
||||
}
|
||||
auto &Vector() {
|
||||
return get_set_type<Class::Array>();
|
||||
}
|
||||
auto &String() {
|
||||
return get_set_type<Class::String>();
|
||||
}
|
||||
auto &Int() {
|
||||
return get_set_type<Class::Integral>();
|
||||
}
|
||||
auto &Float() {
|
||||
return get_set_type<Class::Floating>();
|
||||
}
|
||||
auto &Bool() {
|
||||
return get_set_type<Class::Boolean>();
|
||||
}
|
||||
|
||||
std::vector<std::pair<std::string, JSON>> data;
|
||||
|
||||
using iterator = decltype(data)::iterator;
|
||||
using const_iterator = decltype(data)::const_iterator;
|
||||
|
||||
auto Map() const noexcept {
|
||||
return std::get_if<static_cast<std::size_t>(Class::Object)>(&d);
|
||||
}
|
||||
auto Vector() const noexcept {
|
||||
return std::get_if<static_cast<std::size_t>(Class::Array)>(&d);
|
||||
}
|
||||
auto String() const noexcept {
|
||||
return std::get_if<static_cast<std::size_t>(Class::String)>(&d);
|
||||
}
|
||||
auto Int() const noexcept {
|
||||
return std::get_if<static_cast<std::size_t>(Class::Integral)>(&d);
|
||||
}
|
||||
auto Float() const noexcept {
|
||||
return std::get_if<static_cast<std::size_t>(Class::Floating)>(&d);
|
||||
}
|
||||
auto Bool() const noexcept {
|
||||
return std::get_if<static_cast<std::size_t>(Class::Boolean)>(&d);
|
||||
}
|
||||
|
||||
Data d;
|
||||
};
|
||||
|
||||
struct Internal {
|
||||
template<typename T>
|
||||
auto clone(const std::unique_ptr<T> &ptr) {
|
||||
if (ptr != nullptr) {
|
||||
return std::make_unique<T>(*ptr);
|
||||
} else {
|
||||
return std::unique_ptr<T>(nullptr);
|
||||
}
|
||||
}
|
||||
|
||||
Internal( double d ) : Float( d ), Type(Class::Floating) {}
|
||||
Internal( int64_t l ) : Int( l ), Type(Class::Integral) {}
|
||||
Internal( bool b ) : Bool( b ), Type(Class::Boolean) {}
|
||||
Internal( std::string s ) : String(std::make_unique<std::string>(std::move(s))), Type(Class::String) {}
|
||||
Internal() : Type(Class::Null) {}
|
||||
|
||||
Internal(Class t_type) {
|
||||
set_type(t_type);
|
||||
}
|
||||
|
||||
Internal(const Internal &other)
|
||||
: List(clone(other.List)),
|
||||
Map(clone(other.Map)),
|
||||
String(clone(other.String)),
|
||||
Float(other.Float),
|
||||
Int(other.Int),
|
||||
Bool(other.Bool),
|
||||
Type(other.Type)
|
||||
{
|
||||
}
|
||||
|
||||
Internal &operator=(const Internal &other)
|
||||
{
|
||||
List = clone(other.List);
|
||||
Map = clone(other.Map);
|
||||
String = clone(other.String);
|
||||
Float = other.Float;
|
||||
Int = other.Int;
|
||||
Bool = other.Bool;
|
||||
Type = other.Type;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void set_type( Class type ) {
|
||||
if( type == Type ) {
|
||||
return;
|
||||
}
|
||||
|
||||
Map.reset();
|
||||
List.reset();
|
||||
String.reset();
|
||||
|
||||
switch( type ) {
|
||||
case Class::Object: Map = std::make_unique<QuickFlatMap>(); break;
|
||||
case Class::Array: List = std::make_unique<std::vector<JSON>>(); break;
|
||||
case Class::String: String = std::make_unique<std::string>(); break;
|
||||
case Class::Floating: Float = 0.0; break;
|
||||
case Class::Integral: Int = 0; break;
|
||||
case Class::Boolean: Bool = false; break;
|
||||
case Class::Null: break;
|
||||
}
|
||||
|
||||
Type = type;
|
||||
}
|
||||
|
||||
Internal(Internal &&) = default;
|
||||
Internal &operator=(Internal &&) = default;
|
||||
|
||||
std::unique_ptr<std::vector<JSON>> List;
|
||||
std::unique_ptr<QuickFlatMap> Map;
|
||||
std::unique_ptr<std::string> String;
|
||||
double Float = 0;
|
||||
int64_t Int = 0;
|
||||
bool Bool = false;
|
||||
|
||||
Class Type = Class::Null;
|
||||
};
|
||||
|
||||
Internal internal;
|
||||
|
||||
@ -224,8 +167,8 @@ class JSON
|
||||
JSONConstWrapper( const Container *val ) : object( val ) {}
|
||||
JSONConstWrapper( std::nullptr_t ) {}
|
||||
|
||||
typename Container::const_iterator begin() const { return object ? object->begin() : typename Container::const_iterator(); }
|
||||
typename Container::const_iterator end() const { return object ? object->end() : typename Container::const_iterator(); }
|
||||
typename Container::const_iterator begin() const noexcept { return object ? object->begin() : typename Container::const_iterator(); }
|
||||
typename Container::const_iterator end() const noexcept { return object ? object->end() : typename Container::const_iterator(); }
|
||||
};
|
||||
|
||||
JSON() = default;
|
||||
@ -245,13 +188,13 @@ class JSON
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
explicit JSON( T b, typename enable_if<is_same<T,bool>::value>::type* = nullptr ) : internal( static_cast<bool>(b) ) {}
|
||||
explicit JSON( T b, typename enable_if<is_same<T,bool>::value>::type* = nullptr ) noexcept : internal( static_cast<bool>(b) ) {}
|
||||
|
||||
template <typename T>
|
||||
explicit JSON( T i, typename enable_if<is_integral<T>::value && !is_same<T,bool>::value>::type* = nullptr ) : internal( static_cast<int64_t>(i) ) {}
|
||||
explicit JSON( T i, typename enable_if<is_integral<T>::value && !is_same<T,bool>::value>::type* = nullptr ) noexcept : internal( static_cast<std::int64_t>(i) ) {}
|
||||
|
||||
template <typename T>
|
||||
explicit JSON( T f, typename enable_if<is_floating_point<T>::value>::type* = nullptr ) : internal( static_cast<double>(f) ) {}
|
||||
explicit JSON( T f, typename enable_if<is_floating_point<T>::value>::type* = nullptr ) noexcept : internal( static_cast<double>(f) ) {}
|
||||
|
||||
template <typename T>
|
||||
explicit JSON( T s, typename enable_if<is_convertible<T,std::string>::value>::type* = nullptr ) : internal( static_cast<std::string>(s) ) {}
|
||||
@ -261,17 +204,16 @@ class JSON
|
||||
static JSON Load( const std::string & );
|
||||
|
||||
JSON& operator[]( const std::string &key ) {
|
||||
internal.set_type( Class::Object );
|
||||
return internal.Map->operator[]( key );
|
||||
return internal.Map().operator[]( key );
|
||||
}
|
||||
|
||||
JSON& operator[]( const size_t index ) {
|
||||
internal.set_type( Class::Array );
|
||||
if( index >= internal.List->size() ) {
|
||||
internal.List->resize( index + 1 );
|
||||
auto &vec = internal.Vector();
|
||||
if( index >= vec.size() ) {
|
||||
vec.resize( index + 1 );
|
||||
}
|
||||
|
||||
return internal.List->operator[]( index );
|
||||
return vec.operator[]( index );
|
||||
}
|
||||
|
||||
|
||||
@ -280,7 +222,10 @@ class JSON
|
||||
}
|
||||
|
||||
const JSON &at( const std::string &key ) const {
|
||||
return internal.Map->at( key );
|
||||
return internal.visit_or<Class::Object>(
|
||||
[&](const auto &m)->const JSON &{ return m.at(key); },
|
||||
[]()->const JSON &{ throw std::range_error("Not an object, no keys"); }
|
||||
);
|
||||
}
|
||||
|
||||
JSON &at( size_t index ) {
|
||||
@ -288,100 +233,84 @@ class JSON
|
||||
}
|
||||
|
||||
const JSON &at( size_t index ) const {
|
||||
return internal.List->at( index );
|
||||
return internal.visit_or<Class::Array>(
|
||||
[&](const auto &m)->const JSON&{ return m.at(index); },
|
||||
[]()->const JSON &{ throw std::range_error("Not an array, no indexes"); }
|
||||
);
|
||||
}
|
||||
|
||||
auto length() const noexcept {
|
||||
return internal.visit_or<Class::Array>(
|
||||
[&](const auto &m){ return static_cast<int>(m.size()); },
|
||||
[](){ return -1; }
|
||||
);
|
||||
}
|
||||
|
||||
long length() const {
|
||||
if( internal.Type == Class::Array ) {
|
||||
return static_cast<long>(internal.List->size());
|
||||
bool has_key( const std::string &key ) const noexcept {
|
||||
return internal.visit_or<Class::Object>(
|
||||
[&](const auto &m){ return m.count(key) != 0; },
|
||||
[](){ return false; }
|
||||
);
|
||||
}
|
||||
|
||||
int size() const noexcept {
|
||||
if (auto m = internal.Map(); m != nullptr) {
|
||||
return static_cast<int>(m->size());
|
||||
} if (auto v = internal.Vector(); v != nullptr) {
|
||||
return static_cast<int>(v->size());
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
bool has_key( const std::string &key ) const {
|
||||
if( internal.Type == Class::Object ) {
|
||||
return internal.Map->count(key) != 0;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int size() const {
|
||||
if( internal.Type == Class::Object ) {
|
||||
return static_cast<int>(internal.Map->size());
|
||||
} else if( internal.Type == Class::Array ) {
|
||||
return static_cast<int>(internal.List->size());
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
Class JSONType() const { return internal.Type; }
|
||||
Class JSONType() const noexcept { return internal.type(); }
|
||||
|
||||
/// Functions for getting primitives from the JSON object.
|
||||
bool is_null() const { return internal.Type == Class::Null; }
|
||||
bool is_null() const noexcept { return internal.type() == Class::Null; }
|
||||
|
||||
std::string to_string() const { bool b; return to_string( b ); }
|
||||
std::string to_string( bool &ok ) const {
|
||||
ok = (internal.Type == Class::String);
|
||||
return ok ? *internal.String : std::string("");
|
||||
std::string to_string() const noexcept {
|
||||
return internal.visit_or<Class::String>(
|
||||
[](const auto &o){ return o; },
|
||||
[](){ return std::string{}; }
|
||||
);
|
||||
}
|
||||
double to_float() const noexcept {
|
||||
return internal.visit_or<Class::Floating>(
|
||||
[](const auto &o){ return o; },
|
||||
[](){ return double{}; }
|
||||
);
|
||||
}
|
||||
std::int64_t to_int() const noexcept {
|
||||
return internal.visit_or<Class::Integral>(
|
||||
[](const auto &o){ return o; },
|
||||
[](){ return std::int64_t{}; }
|
||||
);
|
||||
}
|
||||
bool to_bool() const noexcept {
|
||||
return internal.visit_or<Class::Boolean>(
|
||||
[](const auto &o){ return o; },
|
||||
[](){ return false; }
|
||||
);
|
||||
}
|
||||
|
||||
double to_float() const { bool b; return to_float( b ); }
|
||||
double to_float( bool &ok ) const {
|
||||
ok = (internal.Type == Class::Floating);
|
||||
return ok ? internal.Float : 0.0;
|
||||
}
|
||||
|
||||
int64_t to_int() const { bool b; return to_int( b ); }
|
||||
int64_t to_int( bool &ok ) const {
|
||||
ok = (internal.Type == Class::Integral);
|
||||
return ok ? internal.Int : 0;
|
||||
}
|
||||
|
||||
bool to_bool() const { bool b; return to_bool( b ); }
|
||||
bool to_bool( bool &ok ) const {
|
||||
ok = (internal.Type == Class::Boolean);
|
||||
return ok ? internal.Bool : false;
|
||||
}
|
||||
|
||||
JSONWrapper<QuickFlatMap> object_range() {
|
||||
if( internal.Type == Class::Object ) {
|
||||
return JSONWrapper<QuickFlatMap>( internal.Map.get() );
|
||||
} else {
|
||||
return JSONWrapper<QuickFlatMap>( nullptr );
|
||||
}
|
||||
JSONWrapper<chaiscript::utility::QuickFlatMap<std::string, JSON>> object_range() {
|
||||
return std::get_if<static_cast<std::size_t>(Class::Object)>(&internal.d);
|
||||
}
|
||||
|
||||
JSONWrapper<std::vector<JSON>> array_range() {
|
||||
if( internal.Type == Class::Array ) {
|
||||
return JSONWrapper<std::vector<JSON>>( internal.List.get() );
|
||||
} else {
|
||||
return JSONWrapper<std::vector<JSON>>( nullptr );
|
||||
}
|
||||
return std::get_if<static_cast<std::size_t>(Class::Array)>(&internal.d);
|
||||
}
|
||||
|
||||
JSONConstWrapper<QuickFlatMap> object_range() const {
|
||||
if( internal.Type == Class::Object ) {
|
||||
return JSONConstWrapper<QuickFlatMap>( internal.Map.get() );
|
||||
} else {
|
||||
return JSONConstWrapper<QuickFlatMap>( nullptr );
|
||||
}
|
||||
JSONConstWrapper<chaiscript::utility::QuickFlatMap<std::string, JSON>> object_range() const {
|
||||
return std::get_if<static_cast<std::size_t>(Class::Object)>(&internal.d);
|
||||
}
|
||||
|
||||
|
||||
JSONConstWrapper<std::vector<JSON>> array_range() const {
|
||||
if( internal.Type == Class::Array ) {
|
||||
return JSONConstWrapper<std::vector<JSON>>( internal.List.get() );
|
||||
} else {
|
||||
return JSONConstWrapper<std::vector<JSON>>( nullptr );
|
||||
}
|
||||
return std::get_if<static_cast<std::size_t>(Class::Array)>(&internal.d);
|
||||
}
|
||||
|
||||
std::string dump( long depth = 1, std::string tab = " ") const {
|
||||
switch( internal.Type ) {
|
||||
switch( internal.type() ) {
|
||||
case Class::Null:
|
||||
return "null";
|
||||
case Class::Object: {
|
||||
@ -390,7 +319,7 @@ class JSON
|
||||
|
||||
std::string s = "{\n";
|
||||
bool skip = true;
|
||||
for( auto &p : *internal.Map ) {
|
||||
for( auto &p : *internal.Map() ) {
|
||||
if( !skip ) { s += ",\n"; }
|
||||
s += ( pad + "\"" + json_escape(p.first) + "\" : " + p.second.dump( depth + 1, tab ) );
|
||||
skip = false;
|
||||
@ -401,7 +330,7 @@ class JSON
|
||||
case Class::Array: {
|
||||
std::string s = "[";
|
||||
bool skip = true;
|
||||
for( auto &p : *internal.List ) {
|
||||
for( auto &p : *internal.Vector() ) {
|
||||
if( !skip ) { s += ", "; }
|
||||
s += p.dump( depth + 1, tab );
|
||||
skip = false;
|
||||
@ -410,13 +339,13 @@ class JSON
|
||||
return s;
|
||||
}
|
||||
case Class::String:
|
||||
return "\"" + json_escape( *internal.String ) + "\"";
|
||||
return "\"" + json_escape( *internal.String() ) + "\"";
|
||||
case Class::Floating:
|
||||
return std::to_string( internal.Float );
|
||||
return std::to_string( *internal.Float() );
|
||||
case Class::Integral:
|
||||
return std::to_string( internal.Int );
|
||||
return std::to_string( *internal.Int() );
|
||||
case Class::Boolean:
|
||||
return internal.Bool ? "true" : "false";
|
||||
return *internal.Bool() ? "true" : "false";
|
||||
}
|
||||
|
||||
throw std::runtime_error("Unhandled JSON type");
|
||||
@ -447,7 +376,7 @@ class JSON
|
||||
|
||||
|
||||
struct JSONParser {
|
||||
static bool isspace(const char c)
|
||||
static bool isspace(const char c) noexcept
|
||||
{
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
// MSVC warns on these line in some circumstances
|
||||
@ -568,7 +497,7 @@ struct JSONParser {
|
||||
char c = '\0';
|
||||
bool isDouble = false;
|
||||
bool isNegative = false;
|
||||
int64_t exp = 0;
|
||||
std::int64_t exp = 0;
|
||||
bool isExpNegative = false;
|
||||
if( offset < str.size() && str.at(offset) == '-' ) {
|
||||
isNegative = true;
|
||||
@ -606,7 +535,7 @@ struct JSONParser {
|
||||
break;
|
||||
}
|
||||
}
|
||||
exp = chaiscript::parse_num<int64_t>( exp_str ) * (isExpNegative?-1:1);
|
||||
exp = chaiscript::parse_num<std::int64_t>( exp_str ) * (isExpNegative?-1:1);
|
||||
}
|
||||
else if( offset < str.size() && (!isspace( c ) && c != ',' && c != ']' && c != '}' )) {
|
||||
throw std::runtime_error(std::string("JSON ERROR: Number: unexpected character '") + c + "'");
|
||||
@ -617,9 +546,9 @@ struct JSONParser {
|
||||
return JSON((isNegative?-1:1) * chaiscript::parse_num<double>( val ) * std::pow( 10, exp ));
|
||||
} else {
|
||||
if( !exp_str.empty() ) {
|
||||
return JSON((isNegative?-1:1) * static_cast<double>(chaiscript::parse_num<int64_t>( val )) * std::pow( 10, exp ));
|
||||
return JSON((isNegative?-1:1) * static_cast<double>(chaiscript::parse_num<std::int64_t>( val )) * std::pow( 10, exp ));
|
||||
} else {
|
||||
return JSON((isNegative?-1:1) * chaiscript::parse_num<int64_t>( val ));
|
||||
return JSON((isNegative?-1:1) * chaiscript::parse_num<std::int64_t>( val ));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
81
include/chaiscript/utility/quick_flat_map.hpp
Normal file
81
include/chaiscript/utility/quick_flat_map.hpp
Normal file
@ -0,0 +1,81 @@
|
||||
#ifndef CHAISCRIPT_UTILITY_QUICK_FLAT_MAP_HPP
|
||||
#define CHAISCRIPT_UTILITY_QUICK_FLAT_MAP_HPP
|
||||
|
||||
namespace chaiscript::utility {
|
||||
|
||||
template<typename Key, typename Value>
|
||||
struct QuickFlatMap
|
||||
{
|
||||
auto find(const Key &s) noexcept {
|
||||
return std::find_if(std::begin(data), std::end(data), [&s](const auto &d) { return d.first == s; });
|
||||
}
|
||||
|
||||
auto find(const Key &s) const noexcept {
|
||||
return std::find_if(std::begin(data), std::end(data), [&s](const auto &d) { return d.first == s; });
|
||||
}
|
||||
|
||||
auto size() const noexcept {
|
||||
return data.size();
|
||||
}
|
||||
|
||||
auto begin() const noexcept {
|
||||
return data.begin();
|
||||
}
|
||||
|
||||
auto end() const noexcept {
|
||||
return data.end();
|
||||
}
|
||||
|
||||
|
||||
auto begin() noexcept {
|
||||
return data.begin();
|
||||
}
|
||||
|
||||
auto end() noexcept {
|
||||
return data.end();
|
||||
}
|
||||
|
||||
|
||||
Value &operator[](const Key &s) {
|
||||
const auto itr = find(s);
|
||||
if (itr != data.end()) {
|
||||
return itr->second;
|
||||
} else {
|
||||
return data.emplace_back(s, Value()).second;
|
||||
}
|
||||
}
|
||||
|
||||
Value &at(const Key &s) {
|
||||
const auto itr = find(s);
|
||||
if (itr != data.end()) {
|
||||
return itr->second;
|
||||
} else {
|
||||
throw std::out_of_range("Unknown key: " + s);
|
||||
}
|
||||
}
|
||||
|
||||
const Value &at(const Key &s) const {
|
||||
const auto itr = find(s);
|
||||
if (itr != data.end()) {
|
||||
return itr->second;
|
||||
} else {
|
||||
throw std::out_of_range("Unknown key: " + s);
|
||||
}
|
||||
}
|
||||
|
||||
size_t count(const Key &s) const noexcept {
|
||||
return (find(s) != data.end())?1:0;
|
||||
}
|
||||
|
||||
std::vector<std::pair<Key, Value>> data;
|
||||
|
||||
using iterator = typename decltype(data)::iterator;
|
||||
using const_iterator = typename decltype(data)::const_iterator;
|
||||
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@ -15,19 +15,47 @@ namespace chaiscript
|
||||
struct Static_String
|
||||
{
|
||||
template<size_t N>
|
||||
constexpr Static_String(const char (&str)[N])
|
||||
constexpr Static_String(const char (&str)[N]) noexcept
|
||||
: m_size(N-1), data(&str[0])
|
||||
{
|
||||
}
|
||||
|
||||
constexpr size_t size() const {
|
||||
constexpr size_t size() const noexcept {
|
||||
return m_size;
|
||||
}
|
||||
|
||||
constexpr const char *c_str() const {
|
||||
constexpr const char *c_str() const noexcept {
|
||||
return data;
|
||||
}
|
||||
|
||||
constexpr auto begin() const noexcept {
|
||||
return data;
|
||||
}
|
||||
|
||||
constexpr auto end() const noexcept {
|
||||
return data + m_size;
|
||||
}
|
||||
|
||||
constexpr bool operator==(const std::string_view &other) const noexcept {
|
||||
//return std::string_view(data, m_size) == other;
|
||||
auto b1 = begin();
|
||||
const auto e1 = end();
|
||||
auto b2 = other.begin();
|
||||
const auto e2 = other.end();
|
||||
|
||||
if (e1 - b1 != e2 - b2) { return false; }
|
||||
|
||||
while (b1 != e1) {
|
||||
if (*b1 != *b2) { return false; }
|
||||
++b1; ++b2;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool operator==(const std::string &t_str) const noexcept {
|
||||
return std::equal(begin(), end(), std::cbegin(t_str), std::cend(t_str));
|
||||
}
|
||||
|
||||
const size_t m_size;
|
||||
const char *data = nullptr;
|
||||
};
|
||||
|
||||
@ -7,7 +7,7 @@ double f(const std::string &, double, bool) noexcept {
|
||||
|
||||
int main()
|
||||
{
|
||||
chaiscript::ChaiScript chai(chaiscript::Std_Lib::library());
|
||||
chaiscript::ChaiScript chai;
|
||||
|
||||
chai.add(chaiscript::fun(&f), "f");
|
||||
|
||||
|
||||
@ -7,7 +7,7 @@ double f(const std::string &, double, bool) noexcept {
|
||||
|
||||
int main()
|
||||
{
|
||||
chaiscript::ChaiScript chai(chaiscript::Std_Lib::library());
|
||||
chaiscript::ChaiScript chai;
|
||||
|
||||
chai.add(chaiscript::fun(&f), "f");
|
||||
|
||||
|
||||
@ -12,8 +12,23 @@ class TestBaseType
|
||||
TestBaseType(int) : val(10), const_val(15), mdarray{} { }
|
||||
TestBaseType(int *) : val(10), const_val(15), mdarray{} { }
|
||||
|
||||
TestBaseType(const TestBaseType &) = default;
|
||||
virtual ~TestBaseType() {}
|
||||
TestBaseType(const TestBaseType &other)
|
||||
: val(other.val), const_val(other.const_val), const_val_ptr(&const_val),
|
||||
func_member(other.func_member)
|
||||
{
|
||||
}
|
||||
|
||||
TestBaseType(TestBaseType &&other)
|
||||
: val(other.val), const_val(other.const_val), const_val_ptr(&const_val),
|
||||
func_member(std::move(other.func_member))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
TestBaseType &operator=(TestBaseType &&) = delete;
|
||||
TestBaseType &operator=(const TestBaseType &) = delete;
|
||||
|
||||
virtual ~TestBaseType() = default;
|
||||
virtual int func() { return 0; }
|
||||
|
||||
int base_only_func() { return -9; }
|
||||
@ -36,8 +51,6 @@ class TestBaseType
|
||||
t_str = "42";
|
||||
}
|
||||
|
||||
private:
|
||||
TestBaseType &operator=(const TestBaseType &) = delete;
|
||||
};
|
||||
|
||||
class Type2
|
||||
@ -78,22 +91,14 @@ int to_int(TestEnum t)
|
||||
class TestDerivedType : public TestBaseType
|
||||
{
|
||||
public:
|
||||
~TestDerivedType() override {}
|
||||
TestDerivedType(const TestDerivedType &) = default;
|
||||
TestDerivedType() = default;
|
||||
virtual int func() override { return 1; }
|
||||
int derived_only_func() { return 19; }
|
||||
|
||||
private:
|
||||
TestDerivedType &operator=(const TestDerivedType &) = delete;
|
||||
};
|
||||
|
||||
class TestMoreDerivedType : public TestDerivedType
|
||||
{
|
||||
public:
|
||||
TestMoreDerivedType(const TestMoreDerivedType &) = default;
|
||||
TestMoreDerivedType() = default;
|
||||
virtual ~TestMoreDerivedType() {}
|
||||
};
|
||||
|
||||
std::shared_ptr<TestBaseType> derived_type_factory()
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user