Merge branch 'best_practices' into develop

This commit is contained in:
Jason Turner 2018-06-03 16:40:29 -06:00
commit d0d08d2ed9
28 changed files with 633 additions and 761 deletions

View File

@ -145,13 +145,7 @@ endif()
if(CMAKE_COMPILER_IS_GNUCC)
execute_process(COMMAND ${CMAKE_C_COMPILER} -dumpversion OUTPUT_VARIABLE GCC_VERSION)
if(GCC_VERSION VERSION_LESS 4.9)
set(CPP14_FLAG "-std=c++1y")
else()
set(CPP14_FLAG "-std=c++1z")
endif()
else()
set(CPP14_FLAG "-std=c++1z")
set(CPP17_FLAG "-std=c++1z")
endif()
if(MSVC)
@ -178,7 +172,7 @@ 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 -Wno-noexcept-type -Wpedantic ${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 ${CPP17_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 -Wno-undef )
@ -196,12 +190,12 @@ if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
if(USE_LIBCXX)
add_definitions(-stdlib=libc++)
set(LINKER_FLAGS "${LINKER_FLAGS} ${CPP14_FLAG} -stdlib=libc++")
set(LINKER_FLAGS "${LINKER_FLAGS} ${CPP17_FLAG} -stdlib=libc++")
else()
set(LINKER_FLAGS "${LINKER_FLAGS} ${CPP14_FLAG}")
set(LINKER_FLAGS "${LINKER_FLAGS} ${CPP17_FLAG}")
endif()
elseif(CMAKE_COMPILER_IS_GNUCC)
set(LINKER_FLAGS "${LINKER_FLAGS} ${CPP14_FLAG}")
set(LINKER_FLAGS "${LINKER_FLAGS} ${CPP17_FLAG}")
endif()
# limitations in MinGW require us to make an optimized build
@ -267,8 +261,8 @@ add_executable(chai src/main.cpp ${Chai_INCLUDES})
target_link_libraries(chai ${LIBS} ${CHAISCRIPT_LIBS})
if(BUILD_SAMPLES)
add_executable(example samples/example.cpp)
target_link_libraries(example ${LIBS})
add_executable(sanity_checks src/sanity_checks.cpp)
target_link_libraries(sanity_checks ${LIBS})
add_executable(test_num_exceptions samples/test_num_exceptions.cpp)
target_link_libraries(test_num_exceptions ${LIBS} ${CHAISCRIPT_LIBS})
add_executable(memory_leak_test samples/memory_leak_test.cpp)
@ -329,37 +323,6 @@ endif()
if(BUILD_TESTING)
# Add catch tests macro
macro(ADD_CATCH_TESTS executable)
if (MSVC)
file(TO_NATIVE_PATH "${QT_LIBRARY_DIR}" QT_LIB_PATH)
set(NEWPATH "${QT_LIB_PATH};$ENV{PATH}")
else()
set(NEWPATH $ENV{PATH})
endif()
get_target_property(target_files ${executable} SOURCES)
foreach(source ${target_files})
if(NOT "${source}" MATCHES "/moc_.*cxx")
string(REGEX MATCH .*cpp source "${source}")
if(source)
file(READ "${source}" contents)
string(REGEX MATCHALL "TEST_CASE\\([ ]*\"[^\"]+\"" found_tests ${contents})
foreach(hit ${found_tests})
string(REGEX REPLACE "TEST_CASE\\([ ]*(\"[^\"]+\").*" "\\1" test_name ${hit})
add_test(compiled.${test_name} "${executable}" ${test_name})
set_tests_properties(compiled.${test_name} PROPERTIES TIMEOUT 660 ENVIRONMENT "PATH=${NEWPATH}")
endforeach()
endif()
endif()
endforeach()
endmacro()
option(UNIT_TEST_LIGHT "Unit tests light (expect module loading failures)" FALSE)
add_test(version_check chai -c "if(\"\\\${ version() };\\\${version_major()};\\\${version_minor()};\\\${version_patch()}\" != \"${CHAI_VERSION};${CPACK_PACKAGE_VERSION_MAJOR};${CPACK_PACKAGE_VERSION_MINOR};${CPACK_PACKAGE_VERSION_PATCH}\") { exit(-1) }")

View File

@ -105,47 +105,47 @@ namespace chaiscript {
}
struct Build_Info {
constexpr static int version_major() noexcept
[[nodiscard]] constexpr static int version_major() noexcept
{
return chaiscript::version_major;
}
constexpr static int version_minor() noexcept
[[nodiscard]] constexpr static int version_minor() noexcept
{
return chaiscript::version_minor;
}
constexpr static int version_patch() noexcept
[[nodiscard]] constexpr static int version_patch() noexcept
{
return chaiscript::version_patch;
}
static std::string version()
[[nodiscard]] static std::string version()
{
return std::to_string(version_major()) + '.' + std::to_string(version_minor()) + '.' + std::to_string(version_patch());
}
static std::string compiler_id()
[[nodiscard]] static std::string compiler_id()
{
return compiler_name() + '-' + compiler_version();
}
static std::string build_id()
[[nodiscard]] static std::string build_id()
{
return compiler_id() + (debug_build()?"-Debug":"-Release");
}
static std::string compiler_version()
[[nodiscard]] static std::string compiler_version()
{
return chaiscript::compiler_version;
}
static std::string compiler_name()
[[nodiscard]] static std::string compiler_name()
{
return chaiscript::compiler_name;
}
constexpr static bool debug_build() noexcept
[[nodiscard]] constexpr static bool debug_build() noexcept
{
return chaiscript::debug_build;
}
@ -153,7 +153,7 @@ namespace chaiscript {
template<typename T>
constexpr auto parse_num(const std::string_view t_str) noexcept -> typename std::enable_if<std::is_integral<T>::value, T>::type
[[nodiscard]] 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 (const auto c : t_str) {
@ -168,7 +168,7 @@ namespace chaiscript {
template<typename T>
auto parse_num(const std::string_view t_str) -> typename std::enable_if<!std::is_integral<T>::value, T>::type
[[nodiscard]] 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{};
@ -217,16 +217,26 @@ namespace chaiscript {
}
}
return exponent ? base * std::pow(T(10), t * static_cast<T>(exponent)) : t;
}
struct str_equal {
[[nodiscard]] bool operator()(const std::string &t_lhs, const std::string &t_rhs) const noexcept {
return t_lhs == t_rhs;
}
template<typename LHS, typename RHS>
[[nodiscard]] constexpr bool operator()(const LHS &t_lhs, const RHS &t_rhs) const noexcept {
return std::equal(t_lhs.begin(), t_lhs.end(), t_rhs.begin(), t_rhs.end());
}
struct is_transparent{};
};
struct str_less {
bool operator()(const std::string &t_lhs, const std::string &t_rhs) const noexcept {
[[nodiscard]] bool operator()(const std::string &t_lhs, const std::string &t_rhs) const noexcept {
return t_lhs < t_rhs;
}
template<typename LHS, typename RHS>
constexpr bool operator()(const LHS &t_lhs, const RHS &t_rhs) const noexcept {
[[nodiscard]] constexpr bool operator()(const LHS &t_lhs, const RHS &t_rhs) const noexcept {
return std::lexicographical_compare(t_lhs.begin(), t_lhs.end(), t_rhs.begin(), t_rhs.end());
}
struct is_transparent{};
@ -240,6 +250,37 @@ namespace chaiscript {
External_Scripts
};
template<typename From, typename To>
struct is_nothrow_forward_constructible
: std::bool_constant<noexcept(To{std::declval<From>()})>
{
};
template< class From, class To >
inline constexpr bool is_nothrow_forward_constructible_v
= is_nothrow_forward_constructible<From, To>::value;
template<typename Container, typename ... T>
[[nodiscard]] constexpr auto make_container(T && ... t)
{
Container c;
c.reserve(sizeof...(t));
(c.push_back(std::forward<T>(t)), ...);
return c;
}
template<typename ... T>
[[nodiscard]] auto make_vector(T && ... t)
{
using container_type =
std::vector<std::common_type_t<std::decay_t<T>...>>;
return make_container<container_type>(std::forward<T>(t)...);
}
static inline std::vector<Options> default_options()
{
#ifdef CHAISCRIPT_NO_DYNLOAD

View File

@ -42,7 +42,7 @@ namespace chaiscript
{
public:
static ModulePtr library()
[[nodiscard]] static ModulePtr library()
{
auto lib = std::make_shared<Module>();
bootstrap::Bootstrap::bootstrap(*lib);

View File

@ -83,7 +83,7 @@ namespace chaiscript {
public:
// construct/copy/destruct
constexpr Any() noexcept = default;
Any(Any &&) = default;
Any(Any &&) noexcept = default;
Any &operator=(Any &&t_any) = default;
Any(const Any &t_any)
@ -128,7 +128,7 @@ namespace chaiscript {
// queries
bool empty() const noexcept
{
return !bool(m_data);
return !static_cast<bool>(m_data);
}
const std::type_info & type() const noexcept

View File

@ -152,7 +152,7 @@ namespace chaiscript
/// Specific version of shared_ptr_clone just for Proxy_Functions
template<typename Type>
std::shared_ptr<typename std::remove_const<Type>::type> shared_ptr_unconst_clone(const std::shared_ptr<typename std::add_const<Type>::type> &p)
std::shared_ptr<std::remove_const_t<Type>> shared_ptr_unconst_clone(const std::shared_ptr<std::add_const_t<Type>> &p)
{
return std::const_pointer_cast<typename std::remove_const<Type>::type>(p);
}
@ -242,7 +242,7 @@ namespace chaiscript
/// Create a bound function object. The first param is the function to bind
/// the remaining parameters are the args to bind into the result
static Boxed_Value bind_function(const std::vector<Boxed_Value> &params)
static Boxed_Value bind_function(const Function_Params &params)
{
if (params.empty()) {
throw exception::arity_error(0, 1);

View File

@ -178,13 +178,6 @@ namespace chaiscript
detail::input_range_type_impl<Bidir_Range<ContainerType, typename ContainerType::iterator> >(type,m);
detail::input_range_type_impl<Bidir_Range<const ContainerType, typename ContainerType::const_iterator> >("Const_" + type,m);
}
template<typename ContainerType>
ModulePtr input_range_type(const std::string &type)
{
auto m = std::make_shared<Module>();
input_range_type<ContainerType>(type, *m);
return m;
}
/// Add random_access_container concept to the given ContainerType
@ -197,7 +190,7 @@ namespace chaiscript
m.add(
fun(
[](ContainerType &c, int index) -> typename ContainerType::reference {
/// \todo we are prefering to keep the key as 'int' to avoid runtime conversions
/// \todo we are preferring to keep the key as 'int' to avoid runtime conversions
/// during dispatch. reevaluate
return c.at(static_cast<typename ContainerType::size_type>(index));
}), "[]");
@ -205,19 +198,11 @@ namespace chaiscript
m.add(
fun(
[](const ContainerType &c, int index) -> typename ContainerType::const_reference {
/// \todo we are prefering to keep the key as 'int' to avoid runtime conversions
/// \todo we are preferring to keep the key as 'int' to avoid runtime conversions
/// during dispatch. reevaluate
return c.at(static_cast<typename ContainerType::size_type>(index));
}), "[]");
}
template<typename ContainerType>
ModulePtr random_access_container_type(const std::string &type)
{
auto m = std::make_shared<Module>();
random_access_container_type<ContainerType>(type, *m);
return m;
}
/// Add assignable concept to the given ContainerType
@ -228,14 +213,6 @@ namespace chaiscript
copy_constructor<ContainerType>(type, m);
operators::assign<ContainerType>(m);
}
template<typename ContainerType>
ModulePtr assignable_type(const std::string &type)
{
auto m = std::make_shared<Module>();
assignable_type<ContainerType>(type, *m);
return m;
}
/// Add container resize concept to the given ContainerType
/// http://www.cplusplus.com/reference/stl/
@ -245,14 +222,6 @@ namespace chaiscript
m.add(fun([](ContainerType *a, typename ContainerType::size_type n, const typename ContainerType::value_type& val) { return a->resize(n, val); } ), "resize");
m.add(fun([](ContainerType *a, typename ContainerType::size_type n) { return a->resize(n); } ), "resize");
}
template<typename ContainerType>
ModulePtr resizable_type(const std::string &type)
{
auto m = std::make_shared<Module>();
resizable_type<ContainerType>(type, *m);
return m;
}
/// Add container reserve concept to the given ContainerType
/// http://www.cplusplus.com/reference/stl/
@ -262,14 +231,6 @@ namespace chaiscript
m.add(fun([](ContainerType *a, typename ContainerType::size_type n) { return a->reserve(n); } ), "reserve");
m.add(fun([](const ContainerType *a) { return a->capacity(); } ), "capacity");
}
template<typename ContainerType>
ModulePtr reservable_type(const std::string &type)
{
auto m = std::make_shared<Module>();
reservable_type<ContainerType>(type, *m);
return m;
}
/// Add container concept to the given ContainerType
/// http://www.sgi.com/tech/stl/Container.html
@ -280,14 +241,6 @@ namespace chaiscript
m.add(fun([](const ContainerType *a) { return a->empty(); } ), "empty");
m.add(fun([](ContainerType *a) { a->clear(); } ), "clear");
}
template <typename ContainerType>
ModulePtr container_type(const std::string& type)
{
auto m = std::make_shared<Module>();
container_type<ContainerType>(type, *m);
return m;
}
/// Add default constructable concept to the given Type
/// http://www.sgi.com/tech/stl/DefaultConstructible.html
@ -296,15 +249,6 @@ namespace chaiscript
{
m.add(constructor<Type ()>(), type);
}
template <typename Type>
ModulePtr default_constructible_type(const std::string& type)
{
auto m = std::make_shared<Module>();
default_constructible_type<Type>(type, *m);
return m;
}
/// Add sequence concept to the given ContainerType
/// http://www.sgi.com/tech/stl/Sequence.html
@ -322,13 +266,6 @@ namespace chaiscript
m.add(fun(&detail::erase_at<ContainerType>), "erase_at");
}
template <typename ContainerType>
ModulePtr sequence_type(const std::string &type)
{
auto m = std::make_shared<Module>();
sequence_type<ContainerType>(type, *m);
return m;
}
/// Add back insertion sequence concept to the given ContainerType
/// http://www.sgi.com/tech/stl/BackInsertionSequence.html
@ -380,14 +317,6 @@ namespace chaiscript
m.add(fun(&ContainerType::pop_back), "pop_back");
}
template<typename ContainerType>
ModulePtr back_insertion_sequence_type(const std::string &type)
{
auto m = std::make_shared<Module>();
back_insertion_sequence_type<ContainerType>(type, *m);
return m;
}
/// Front insertion sequence
@ -442,14 +371,6 @@ namespace chaiscript
m.add(fun(static_cast<pop_ptr>(&ContainerType::pop_front)), "pop_front");
}
template<typename ContainerType>
ModulePtr front_insertion_sequence_type(const std::string &type)
{
auto m = std::make_shared<Module>();
front_insertion_sequence_type<ContainerType>(type, *m);
return m;
}
/// bootstrap a given PairType
/// http://www.sgi.com/tech/stl/pair.html
@ -464,14 +385,6 @@ namespace chaiscript
basic_constructors<PairType>(type, m);
m.add(constructor<PairType (const typename PairType::first_type &, const typename PairType::second_type &)>(), type);
}
template<typename PairType>
ModulePtr pair_type(const std::string &type)
{
auto m = std::make_shared<Module>();
pair_type<PairType>(type, *m);
return m;
}
/// Add pair associative container concept to the given ContainerType
@ -482,14 +395,6 @@ namespace chaiscript
{
pair_type<typename ContainerType::value_type>(type + "_Pair", m);
}
template<typename ContainerType>
ModulePtr pair_associative_container_type(const std::string &type)
{
auto m = std::make_shared<Module>();
pair_associative_container_type<ContainerType>(type, *m);
return m;
}
/// Add unique associative container concept to the given ContainerType
/// http://www.sgi.com/tech/stl/UniqueAssociativeContainer.html
@ -513,14 +418,6 @@ namespace chaiscript
}
}());
}
template<typename ContainerType>
ModulePtr unique_associative_container_type(const std::string &type)
{
auto m = std::make_shared<Module>();
unique_associative_container_type<ContainerType>(type, *m);
return m;
}
/// Add a MapType container
/// http://www.sgi.com/tech/stl/Map.html
@ -568,14 +465,6 @@ namespace chaiscript
pair_associative_container_type<MapType>(type, m);
input_range_type<MapType>(type, m);
}
template<typename MapType>
ModulePtr map_type(const std::string &type)
{
auto m = std::make_shared<Module>();
map_type<MapType>(type, *m);
return m;
}
/// http://www.sgi.com/tech/stl/List.html
template<typename ListType>
@ -592,14 +481,6 @@ namespace chaiscript
assignable_type<ListType>(type, m);
input_range_type<ListType>(type, m);
}
template<typename ListType>
ModulePtr list_type(const std::string &type)
{
auto m = std::make_shared<Module>();
list_type<ListType>(type, m);
return m;
}
/// Create a vector type with associated concepts
/// http://www.sgi.com/tech/stl/Vector.html
@ -665,13 +546,6 @@ namespace chaiscript
);
}
}
template<typename VectorType>
ModulePtr vector_type(const std::string &type)
{
auto m = std::make_shared<Module>();
vector_type<VectorType>(type, *m);
return m;
}
/// Add a String container
/// http://www.sgi.com/tech/stl/basic_string.html
@ -717,14 +591,6 @@ namespace chaiscript
m.add(fun([](const String *s) { return s->data(); } ), "data");
m.add(fun([](const String *s, size_t pos, size_t len) { return s->substr(pos, len); } ), "substr");
}
template<typename String>
ModulePtr string_type(const std::string &type)
{
auto m = std::make_shared<Module>();
string_type<String>(type, *m);
return m;
}
/// Add a MapType container
@ -738,13 +604,6 @@ namespace chaiscript
m.add(fun([](FutureType &t) { return t.get(); }), "get");
m.add(fun(&FutureType::wait), "wait");
}
template<typename FutureType>
ModulePtr future_type(const std::string &type)
{
auto m = std::make_shared<Module>();
future_type<FutureType>(type, *m);
return m;
}
}
}
}

View File

@ -194,7 +194,7 @@ namespace chaiscript
public:
/// Basic Boxed_Value constructor
template<typename T,
typename = typename std::enable_if<!std::is_same<Boxed_Value, typename std::decay<T>::type>::value>::type>
typename = std::enable_if_t<!std::is_same_v<Boxed_Value, std::decay_t<T>>>>
explicit Boxed_Value(T &&t, bool t_return_value = false)
: m_data(Object_Data::get(std::forward<T>(t), t_return_value))
{

View File

@ -36,6 +36,7 @@
#include "proxy_functions.hpp"
#include "type_info.hpp"
#include "short_alloc.hpp"
#include "../utility/quick_flat_map.hpp"
namespace chaiscript {
class Boxed_Number;
@ -313,14 +314,14 @@ namespace chaiscript
return arity;
}
bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const noexcept override
bool call_match(const Function_Params &vals, const Type_Conversions_State &t_conversions) const noexcept override
{
return std::any_of(std::begin(m_funcs), std::end(m_funcs),
[&vals, &t_conversions](const Proxy_Function &f){ return f->call_match(vals, t_conversions); });
}
protected:
Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
Boxed_Value do_call(const Function_Params &params, const Type_Conversions_State &t_conversions) const override
{
return dispatch::dispatch(m_funcs, params, t_conversions);
}
@ -388,7 +389,7 @@ namespace chaiscript
using SmallVector = std::vector<T>;
using Scope = SmallVector<std::pair<std::string, Boxed_Value>>;
using Scope = utility::QuickFlatMap<std::string, Boxed_Value, str_equal>;
using StackData = SmallVector<Scope>;
using Stacks = SmallVector<StackData>;
using Call_Param_List = SmallVector<Boxed_Value>;
@ -409,24 +410,13 @@ namespace chaiscript
void push_stack()
{
stacks.emplace_back(1);
// stacks.emplace_back(StackData(1, Scope(scope_allocator), stack_data_allocator));
}
void push_call_params()
{
call_params.emplace_back();
// call_params.emplace_back(Call_Param_List(call_param_list_allocator));
}
//Scope::allocator_type::arena_type scope_allocator;
//StackData::allocator_type::arena_type stack_data_allocator;
//Stacks::allocator_type::arena_type stacks_allocator;
//Call_Param_List::allocator_type::arena_type call_param_list_allocator;
//Call_Params::allocator_type::arena_type call_params_allocator;
// Stacks stacks = Stacks(stacks_allocator);
// Call_Params call_params = Call_Params(call_params_allocator);
Stacks stacks;
Call_Params call_params;
@ -440,14 +430,14 @@ namespace chaiscript
public:
using Type_Name_Map = std::map<std::string, chaiscript::Type_Info, str_less>;
using Scope = std::vector<std::pair<std::string, Boxed_Value>>;
using Scope = utility::QuickFlatMap<std::string, Boxed_Value, str_equal>;
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;
utility::QuickFlatMap<std::string, std::shared_ptr<std::vector<Proxy_Function>>, str_equal> m_functions;
utility::QuickFlatMap<std::string, Proxy_Function, str_equal> m_function_objects;
utility::QuickFlatMap<std::string, Boxed_Value, str_equal> m_boxed_functions;
std::map<std::string, Boxed_Value, str_less> m_global_objects;
Type_Name_Map m_types;
};
@ -486,12 +476,7 @@ namespace chaiscript
for (auto stack_elem = stack.rbegin(); stack_elem != stack.rend(); ++stack_elem)
{
auto itr = std::find_if(stack_elem->begin(), stack_elem->end(),
[&](const std::pair<std::string, Boxed_Value> &o) {
return o.first == name;
});
if (itr != stack_elem->end())
if (auto itr = stack_elem->find(name); itr != stack_elem->end())
{
itr->second = std::move(obj);
return;
@ -504,38 +489,32 @@ namespace chaiscript
/// Adds a named object to the current scope
/// \warning This version does not check the validity of the name
/// it is meant for internal use only
Boxed_Value &add_get_object(const std::string &t_name, Boxed_Value obj, Stack_Holder &t_holder)
Boxed_Value &add_get_object(std::string t_name, Boxed_Value obj, Stack_Holder &t_holder)
{
auto &stack_elem = get_stack_data(t_holder).back();
if (std::any_of(stack_elem.begin(), stack_elem.end(),
[&](const std::pair<std::string, Boxed_Value> &o) {
return o.first == t_name;
}))
if (auto result = stack_elem.insert(std::pair{std::move(t_name), std::move(obj)}); result.second)
{
throw chaiscript::exception::name_conflict_error(t_name);
return result.first->second;
} else {
//insert failed
throw chaiscript::exception::name_conflict_error(result.first->first);
}
return stack_elem.emplace_back(t_name, std::move(obj)).second;
}
/// Adds a named object to the current scope
/// \warning This version does not check the validity of the name
/// it is meant for internal use only
void add_object(const std::string &t_name, Boxed_Value obj, Stack_Holder &t_holder)
void add_object(std::string t_name, Boxed_Value obj, Stack_Holder &t_holder)
{
auto &stack_elem = get_stack_data(t_holder).back();
if (std::any_of(stack_elem.begin(), stack_elem.end(),
[&](const std::pair<std::string, Boxed_Value> &o) {
return o.first == t_name;
}))
if (auto result = stack_elem.insert(std::pair{std::move(t_name), std::move(obj)}); !result.second)
{
throw chaiscript::exception::name_conflict_error(t_name);
//insert failed
throw chaiscript::exception::name_conflict_error(result.first->first);
}
stack_elem.emplace_back(t_name, std::move(obj));
}
@ -566,46 +545,30 @@ namespace chaiscript
}
/// Adds a new global (non-const) shared object, between all the threads
Boxed_Value add_global_no_throw(const Boxed_Value &obj, const std::string &name)
Boxed_Value add_global_no_throw(Boxed_Value obj, std::string name)
{
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
const auto itr = m_state.m_global_objects.find(name);
if (itr == m_state.m_global_objects.end())
{
m_state.m_global_objects.insert(std::make_pair(name, obj));
return obj;
} else {
return itr->second;
}
return m_state.m_global_objects.insert(std::pair{std::move(name), std::move(obj)}).first->second;
}
/// Adds a new global (non-const) shared object, between all the threads
void add_global(const Boxed_Value &obj, const std::string &name)
void add_global(Boxed_Value obj, std::string name)
{
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
if (m_state.m_global_objects.find(name) != m_state.m_global_objects.end())
{
throw chaiscript::exception::name_conflict_error(name);
} else {
m_state.m_global_objects.insert(std::make_pair(name, obj));
if (auto result = m_state.m_global_objects.insert(std::pair{std::move(name), std::move(obj)}); !result.second) {
// insert failed
throw chaiscript::exception::name_conflict_error(result.first->first);
}
}
/// Updates an existing global shared object or adds a new global shared object if not found
void set_global(const Boxed_Value &obj, const std::string &name)
void set_global(Boxed_Value obj, std::string name)
{
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
const auto itr = m_state.m_global_objects.find(name);
if (itr != m_state.m_global_objects.end())
{
itr->second.assign(obj);
} else {
m_state.m_global_objects.insert(std::make_pair(name, obj));
}
m_state.m_global_objects.insert_or_assign(std::move(name), std::move(obj));
}
/// Adds a new scope to the stack
@ -688,7 +651,7 @@ namespace chaiscript
} else if ((loc & static_cast<uint_fast32_t>(Loc::is_local)) != 0u) {
auto &stack = get_stack_data(t_holder);
return stack[stack.size() - 1 - ((loc & static_cast<uint_fast32_t>(Loc::stack_mask)) >> 16)][loc & static_cast<uint_fast32_t>(Loc::loc_mask)].second;
return stack[stack.size() - 1 - ((loc & static_cast<uint_fast32_t>(Loc::stack_mask)) >> 16)].at_index(loc & static_cast<uint_fast32_t>(Loc::loc_mask));
}
// Is the value we are looking for a global or function?
@ -782,9 +745,7 @@ namespace chaiscript
const auto &funs = get_functions_int();
auto itr = find_keyed_value(funs, t_name, t_hint);
if (itr != funs.end())
if (const auto itr = funs.find(t_name, t_hint); itr != funs.end())
{
return std::make_pair(std::distance(funs.begin(), itr), itr->second);
} else {
@ -808,9 +769,7 @@ namespace chaiscript
{
const auto &funs = get_boxed_functions_int();
auto itr = find_keyed_value(funs, t_name, t_hint);
if (itr != funs.end())
if (const auto itr = funs.find(t_name, t_hint); itr != funs.end())
{
return std::make_pair(std::distance(funs.begin(), itr), itr->second);
} else {
@ -824,8 +783,7 @@ namespace chaiscript
{
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
const auto &functions = get_functions_int();
return find_keyed_value(functions, name) != functions.end();
return get_functions_int().count(name) > 0;
}
/// \returns All values in the local thread state in the parent scope, or if it doesn't exist,
@ -935,7 +893,7 @@ namespace chaiscript
return m_conversions;
}
static bool is_attribute_call(const std::vector<Proxy_Function> &t_funs, const std::vector<Boxed_Value> &t_params,
static bool is_attribute_call(const std::vector<Proxy_Function> &t_funs, const Function_Params &t_params,
bool t_has_params, const Type_Conversions_State &t_conversions) noexcept
{
if (!t_has_params || t_params.empty()) {
@ -956,17 +914,17 @@ namespace chaiscript
#pragma warning(push)
#pragma warning(disable : 4715)
#endif
Boxed_Value call_member(const std::string &t_name, std::atomic_uint_fast32_t &t_loc, const std::vector<Boxed_Value> &params, bool t_has_params,
Boxed_Value call_member(const std::string &t_name, std::atomic_uint_fast32_t &t_loc, const Function_Params &params, bool t_has_params,
const Type_Conversions_State &t_conversions)
{
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); }
const auto do_attribute_call =
[this](int l_num_params, const std::vector<Boxed_Value> &l_params, const std::vector<Proxy_Function> &l_funs, const Type_Conversions_State &l_conversions)->Boxed_Value
const auto do_attribute_call =
[this](int l_num_params, Function_Params l_params, const std::vector<Proxy_Function> &l_funs, const Type_Conversions_State &l_conversions)->Boxed_Value
{
std::vector<Boxed_Value> attr_params{l_params.begin(), l_params.begin() + l_num_params};
Function_Params attr_params(l_params.begin(), l_params.begin() + l_num_params);
Boxed_Value bv = dispatch::dispatch(l_funs, attr_params, l_conversions);
if (l_num_params < int(l_params.size()) || bv.get_type_info().bare_equal(user_type<dispatch::Proxy_Function_Base>())) {
struct This_Foist {
@ -1049,11 +1007,12 @@ namespace chaiscript
if (!functions.empty()) {
try {
if (is_no_param) {
auto tmp_params(params);
auto tmp_params = params.to_vector();
tmp_params.insert(tmp_params.begin() + 1, var(t_name));
return do_attribute_call(2, tmp_params, functions, t_conversions);
return do_attribute_call(2, Function_Params(tmp_params), functions, t_conversions);
} else {
return dispatch::dispatch(functions, {params[0], var(t_name), var(std::vector<Boxed_Value>(params.begin()+1, params.end()))}, t_conversions);
std::array<Boxed_Value, 3> p{params[0], var(t_name), var(std::vector<Boxed_Value>(params.begin()+1, params.end()))};
return dispatch::dispatch(functions, Function_Params{p}, t_conversions);
}
} catch (const dispatch::option_explicit_set &e) {
throw chaiscript::exception::dispatch_error(params, std::vector<Const_Proxy_Function>(funs.second->begin(), funs.second->end()),
@ -1076,7 +1035,7 @@ namespace chaiscript
Boxed_Value call_function(const std::string_view &t_name, std::atomic_uint_fast32_t &t_loc, const std::vector<Boxed_Value> &params,
Boxed_Value call_function(const std::string_view &t_name, std::atomic_uint_fast32_t &t_loc, const Function_Params &params,
const Type_Conversions_State &t_conversions) const
{
uint_fast32_t loc = t_loc;
@ -1124,7 +1083,7 @@ namespace chaiscript
/// Returns true if a call can be made that consists of the first parameter
/// (the function) with the remaining parameters as its arguments.
Boxed_Value call_exists(const std::vector<Boxed_Value> &params) const
Boxed_Value call_exists(const Function_Params &params) const
{
if (params.empty())
{
@ -1134,7 +1093,7 @@ namespace chaiscript
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));
return const_var(f->call_match(Function_Params(params.begin() + 1, params.end()), convs));
}
/// Dump all system info to stdout
@ -1195,11 +1154,6 @@ namespace chaiscript
m_state = t_state;
}
static void save_function_params(Stack_Holder &t_s, std::initializer_list<Boxed_Value> t_params)
{
t_s.call_params.back().insert(t_s.call_params.back().begin(), t_params);
}
static void save_function_params(Stack_Holder &t_s, std::vector<Boxed_Value> &&t_params)
{
for (auto &&param : t_params)
@ -1208,22 +1162,17 @@ namespace chaiscript
}
}
static void save_function_params(Stack_Holder &t_s, const std::vector<Boxed_Value> &t_params)
static void save_function_params(Stack_Holder &t_s, const Function_Params &t_params)
{
t_s.call_params.back().insert(t_s.call_params.back().begin(), t_params.begin(), t_params.end());
}
void save_function_params(std::initializer_list<Boxed_Value> t_params)
{
save_function_params(*m_stack_holder, t_params);
}
void save_function_params(std::vector<Boxed_Value> &&t_params)
{
save_function_params(*m_stack_holder, std::move(t_params));
}
void save_function_params(const std::vector<Boxed_Value> &t_params)
void save_function_params(const Function_Params &t_params)
{
save_function_params(*m_stack_holder, t_params);
}
@ -1292,32 +1241,32 @@ namespace chaiscript
private:
const std::vector<std::pair<std::string, Boxed_Value>> &get_boxed_functions_int() const noexcept
const decltype(State::m_boxed_functions) &get_boxed_functions_int() const noexcept
{
return m_state.m_boxed_functions;
}
std::vector<std::pair<std::string, Boxed_Value>> &get_boxed_functions_int() noexcept
decltype(State::m_boxed_functions) &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 noexcept
const decltype(State::m_function_objects) &get_function_objects_int() const noexcept
{
return m_state.m_function_objects;
}
std::vector<std::pair<std::string, Proxy_Function>> &get_function_objects_int() noexcept
decltype(State::m_function_objects) &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 noexcept
const decltype(State::m_functions) &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() noexcept
decltype(State::m_functions) &get_functions_int() noexcept
{
return m_state.m_functions;
}
@ -1406,63 +1355,17 @@ namespace chaiscript
return false;
}
template<typename Container, typename Key, typename Value>
static void add_keyed_value(Container &t_c, const Key &t_key, Value &&t_value)
{
auto itr = find_keyed_value(t_c, t_key);
if (itr == t_c.end()) {
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 {
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) noexcept
{
return std::find_if(t_c.begin(), t_c.end(),
[&t_key](const typename Container::value_type &o) {
return o.first == t_key;
});
}
template<typename Container, typename 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 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) 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));
} else {
return find_keyed_value(t_c, t_key);
}
}
/// Implementation detail for adding a function.
/// \throws exception::name_conflict_error if there's a function matching the given one being added
void add_function(const Proxy_Function &t_f, const std::string &t_name)
{
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
auto &funcs = get_functions_int();
auto itr = find_keyed_value(funcs, t_name);
Proxy_Function new_func =
[&]() -> Proxy_Function {
auto &funcs = get_functions_int();
auto itr = funcs.find(t_name);
if (itr != funcs.end())
{
auto vec = *itr->second;
@ -1483,17 +1386,21 @@ namespace chaiscript
// if the function is the only function but it also contains
// arithmetic operators, we must wrap it in a dispatch function
// to allow for automatic arithmetic type conversions
std::vector<Proxy_Function> vec({t_f});
funcs.emplace_back(t_name, std::make_shared<std::vector<Proxy_Function>>(vec));
std::vector<Proxy_Function> vec;
vec.push_back(t_f);
funcs.insert(std::pair{t_name, std::make_shared<std::vector<Proxy_Function>>(vec)});
return std::make_shared<Dispatch_Function>(std::move(vec));
} else {
funcs.emplace_back(t_name, std::make_shared<std::vector<Proxy_Function>>(std::initializer_list<Proxy_Function>({t_f})));
auto vec = std::make_shared<std::vector<Proxy_Function>>();
vec->push_back(t_f);
funcs.insert(std::pair{t_name, vec});
return t_f;
}
}();
add_keyed_value(get_boxed_functions_int(), t_name, const_var(new_func));
add_keyed_value(get_function_objects_int(), t_name, std::move(new_func));
get_boxed_functions_int().insert_or_assign(t_name, const_var(new_func));
get_function_objects_int().insert_or_assign(t_name, std::move(new_func));
}
mutable chaiscript::detail::threading::shared_mutex m_mutex;

View File

@ -83,7 +83,7 @@ namespace chaiscript
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 noexcept override
bool call_match(const Function_Params &vals, const Type_Conversions_State &t_conversions) const noexcept override
{
if (dynamic_object_typename_match(vals, m_type_name, m_ti, t_conversions))
{
@ -99,7 +99,7 @@ namespace chaiscript
}
protected:
Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
Boxed_Value do_call(const Function_Params &params, const Type_Conversions_State &t_conversions) const override
{
if (dynamic_object_typename_match(params, m_type_name, m_ti, t_conversions))
{
@ -148,7 +148,7 @@ namespace chaiscript
}
bool dynamic_object_typename_match(const std::vector<Boxed_Value> &bvs, const std::string &name,
bool dynamic_object_typename_match(const Function_Params &bvs, const std::string &name,
const std::unique_ptr<Type_Info> &ti, const Type_Conversions_State &t_conversions) const noexcept
{
if (!bvs.empty())
@ -205,22 +205,22 @@ namespace chaiscript
return (dc != nullptr) && dc->m_type_name == m_type_name && (*dc->m_func) == (*m_func);
}
bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const override
bool call_match(const Function_Params &vals, const Type_Conversions_State &t_conversions) const override
{
std::vector<Boxed_Value> new_vals{Boxed_Value(Dynamic_Object(m_type_name))};
new_vals.insert(new_vals.end(), vals.begin(), vals.end());
return m_func->call_match(new_vals, t_conversions);
return m_func->call_match(Function_Params{new_vals}, t_conversions);
}
protected:
Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
Boxed_Value do_call(const Function_Params &params, const Type_Conversions_State &t_conversions) const override
{
auto bv = Boxed_Value(Dynamic_Object(m_type_name), true);
std::vector<Boxed_Value> new_params{bv};
new_params.insert(new_params.end(), params.begin(), params.end());
(*m_func)(new_params, t_conversions);
(*m_func)(Function_Params{new_params}, t_conversions);
return bv;
}

View File

@ -29,66 +29,7 @@ namespace chaiscript
{
namespace detail
{
/// Internal helper class for handling the return
/// value of a build_function_caller
template<typename Ret, bool is_arithmetic>
struct Function_Caller_Ret
{
static Ret call(const std::vector<Const_Proxy_Function> &t_funcs,
const std::vector<Boxed_Value> &params, const Type_Conversions_State *t_conversions)
{
if (t_conversions != nullptr) {
return boxed_cast<Ret>(dispatch::dispatch(t_funcs, params, *t_conversions), t_conversions);
} else {
Type_Conversions conv;
Type_Conversions_State state(conv, conv.conversion_saves());
return boxed_cast<Ret>(dispatch::dispatch(t_funcs, params, state), t_conversions);
}
}
};
/**
* Specialization for arithmetic return types
*/
template<typename Ret>
struct Function_Caller_Ret<Ret, true>
{
static Ret call(const std::vector<Const_Proxy_Function> &t_funcs,
const std::vector<Boxed_Value> &params, const Type_Conversions_State *t_conversions)
{
if (t_conversions != nullptr) {
return Boxed_Number(dispatch::dispatch(t_funcs, params, *t_conversions)).get_as<Ret>();
} else {
Type_Conversions conv;
Type_Conversions_State state(conv, conv.conversion_saves());
return Boxed_Number(dispatch::dispatch(t_funcs, params, state)).get_as<Ret>();
}
}
};
/**
* Specialization for void return types
*/
template<>
struct Function_Caller_Ret<void, false>
{
static void call(const std::vector<Const_Proxy_Function> &t_funcs,
const std::vector<Boxed_Value> &params, const Type_Conversions_State *t_conversions)
{
if (t_conversions != nullptr) {
dispatch::dispatch(t_funcs, params, *t_conversions);
} else {
Type_Conversions conv;
Type_Conversions_State state(conv, conv.conversion_saves());
dispatch::dispatch(t_funcs, params, state);
}
}
};
/**
* used internally for unwrapping a function call's types
*/
/// used internally for unwrapping a function call's types
template<typename Ret, typename ... Param>
struct Build_Function_Caller_Helper
{
@ -98,41 +39,44 @@ namespace chaiscript
{
}
Ret call(const Function_Params &params, const Type_Conversions_State &t_state)
{
if constexpr (std::is_arithmetic_v<Ret>) {
return Boxed_Number(dispatch::dispatch(m_funcs, params, t_state)).get_as<Ret>();
} else if constexpr (std::is_same_v<void, Ret>) {
dispatch::dispatch(m_funcs, params, t_state);
} else {
return boxed_cast<Ret>(dispatch::dispatch(m_funcs, params, t_state), &t_state);
}
}
template<typename ... P>
Ret operator()(P&& ... param)
{
std::array<Boxed_Value, sizeof...(P)> params{box<P>(std::forward<P>(param))...};
if (m_conversions) {
Type_Conversions_State state(*m_conversions, m_conversions->conversion_saves());
return Function_Caller_Ret<Ret, std::is_arithmetic<Ret>::value && !std::is_same<Ret, bool>::value>::call(m_funcs, {
box<P>(std::forward<P>(param))...
}, &state
);
return call(Function_Params{params}, state);
} else {
return Function_Caller_Ret<Ret, std::is_arithmetic<Ret>::value && !std::is_same<Ret, bool>::value>::call(m_funcs, {
box<P>(std::forward<P>(param))...
}, nullptr
);
Type_Conversions conv;
Type_Conversions_State state(conv, conv.conversion_saves());
return call(Function_Params{params}, state);
}
}
template<typename P, typename Q>
static auto box(Q&& q) -> typename std::enable_if<std::is_reference<P>::value&&!std::is_same<chaiscript::Boxed_Value, typename std::remove_const<typename std::remove_reference<P>::type>::type>::value, Boxed_Value>::type
{
return Boxed_Value(std::ref(std::forward<Q>(q)));
}
template<typename P, typename Q>
static auto box(Q&& q) -> typename std::enable_if<!std::is_reference<P>::value&&!std::is_same<chaiscript::Boxed_Value, typename std::remove_const<typename std::remove_reference<P>::type>::type>::value, Boxed_Value>::type
{
return Boxed_Value(std::forward<Q>(q));
}
template<typename P>
static Boxed_Value box(Boxed_Value bv) noexcept
{
return bv;
}
static Boxed_Value box(Q &&q) {
if constexpr (std::is_same_v<chaiscript::Boxed_Value, std::decay_t<Q>>) {
return std::forward<Q>(q);
} else if constexpr (std::is_reference_v<P>) {
return Boxed_Value(std::ref(std::forward<Q>(q)));
} else {
return Boxed_Value(std::forward<Q>(q));
}
}
std::vector<Const_Proxy_Function> m_funcs;

View File

@ -0,0 +1,81 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#ifndef CHAISCRIPT_FUNCTION_PARAMS_HPP
#define CHAISCRIPT_FUNCTION_PARAMS_HPP
#include "boxed_value.hpp"
namespace chaiscript {
class Function_Params
{
public:
constexpr Function_Params(const Boxed_Value * const t_begin, const Boxed_Value * const t_end)
: m_begin(t_begin), m_end(t_end)
{
}
explicit Function_Params(const Boxed_Value &bv)
: m_begin(&bv), m_end(m_begin + 1)
{
}
explicit Function_Params(const std::vector<Boxed_Value> &vec)
: m_begin(&vec.front()), m_end(&vec.front() + vec.size())
{
}
template<size_t Size>
constexpr explicit Function_Params(const std::array<Boxed_Value, Size> &a)
: m_begin(std::begin(a)), m_end(std::end(a))
{
}
[[nodiscard]] constexpr const Boxed_Value &operator[](const std::size_t t_i) const noexcept {
return m_begin[t_i];
}
[[nodiscard]] constexpr const Boxed_Value *begin() const noexcept {
return m_begin;
}
[[nodiscard]] constexpr const Boxed_Value &front() const noexcept {
return *m_begin;
}
[[nodiscard]] constexpr const Boxed_Value *end() const noexcept {
return m_end;
}
[[nodiscard]] constexpr std::size_t size() const noexcept {
return m_end - m_begin;
}
std::vector<Boxed_Value> to_vector() const {
return std::vector<Boxed_Value>{m_begin, m_end};
}
[[nodiscard]] constexpr bool empty() const noexcept {
return m_begin == m_end;
}
private:
const Boxed_Value *m_begin = nullptr;
const Boxed_Value *m_end = nullptr;
};
}
#endif

View File

@ -36,14 +36,14 @@ namespace chaiscript
struct Handle_Return
{
template<typename T,
typename = typename std::enable_if<std::is_pod<typename std::decay<T>::type>::value>::type>
typename = std::enable_if_t<std::is_pod_v<std::decay_t<T>>>>
static Boxed_Value handle(T r)
{
return Boxed_Value(std::move(r), true);
}
template<typename T,
typename = typename std::enable_if<!std::is_pod<typename std::decay<T>::type>::value>::type>
typename = std::enable_if_t<!std::is_pod_v<std::decay_t<T>>>>
static Boxed_Value handle(T &&r)
{
return Boxed_Value(std::make_shared<T>(std::forward<T>(r)), true);

View File

@ -27,6 +27,7 @@
#include "proxy_functions_detail.hpp"
#include "type_info.hpp"
#include "dynamic_object.hpp"
#include "function_params.hpp"
namespace chaiscript {
class Type_Conversions;
@ -73,8 +74,9 @@ namespace chaiscript
return m_types == t_rhs.m_types;
}
std::vector<Boxed_Value> convert(std::vector<Boxed_Value> vals, const Type_Conversions_State &t_conversions) const
std::vector<Boxed_Value> convert(Function_Params t_params, const Type_Conversions_State &t_conversions) const
{
auto vals = t_params.to_vector();
constexpr auto dynamic_object_type_info = user_type<Dynamic_Object>();
for (size_t i = 0; i < vals.size(); ++i)
{
@ -113,7 +115,7 @@ 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 noexcept
std::pair<bool, bool> match(const Function_Params &vals, const Type_Conversions_State &t_conversions) const noexcept
{
constexpr auto dynamic_object_type_info = user_type<Dynamic_Object>();
bool needs_conversion = false;
@ -136,7 +138,7 @@ namespace chaiscript
}
} catch (const std::bad_cast &) {
return std::make_pair(false, false);
}
}
} else {
const auto &ti = m_types[i].second;
if (!ti.is_undef())
@ -196,7 +198,7 @@ namespace chaiscript
public:
virtual ~Proxy_Function_Base() = default;
Boxed_Value operator()(const std::vector<Boxed_Value> &params, const chaiscript::Type_Conversions_State &t_conversions) const
Boxed_Value operator()(const Function_Params &params, const chaiscript::Type_Conversions_State &t_conversions) const
{
if (m_arity < 0 || size_t(m_arity) == params.size()) {
return do_call(params, t_conversions);
@ -208,11 +210,11 @@ namespace chaiscript
/// Returns a vector containing all of the types of the parameters the function returns/takes
/// if the function is variadic or takes no arguments (arity of 0 or -1), the returned
/// value contains exactly 1 Type_Info object: the return type
/// \returns the types of all parameters.
/// \returns the types of all parameters.
const std::vector<Type_Info> &get_param_types() const noexcept { return m_types; }
virtual bool operator==(const Proxy_Function_Base &) const noexcept = 0;
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const = 0;
virtual bool call_match(const Function_Params &vals, const Type_Conversions_State &t_conversions) const = 0;
virtual bool is_attribute_function() const noexcept { return false; }
@ -228,7 +230,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 noexcept
bool filter(const Function_Params &vals, const Type_Conversions_State &t_conversions) const noexcept
{
assert(m_arity == -1 || (m_arity > 0 && static_cast<int>(vals.size()) == m_arity));
@ -254,13 +256,13 @@ namespace chaiscript
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()
if (ti.is_undef()
|| ti.bare_equal(boxed_value_ti)
|| (!bv.get_type_info().is_undef()
&& ( (ti.bare_equal(boxed_number_ti) && bv.get_type_info().is_arithmetic())
|| ti.bare_equal(bv.get_type_info())
|| bv.get_type_info().bare_equal(function_ti)
|| t_conversions->converts(ti, bv.get_type_info())
|| t_conversions->converts(ti, bv.get_type_info())
)
)
)
@ -278,7 +280,7 @@ namespace chaiscript
}
protected:
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const = 0;
virtual Boxed_Value do_call(const Function_Params &params, const Type_Conversions_State &t_conversions) const = 0;
Proxy_Function_Base(std::vector<Type_Info> t_types, int t_arity)
: m_types(std::move(t_types)), m_arity(t_arity), m_has_arithmetic_param(false)
@ -295,7 +297,7 @@ namespace chaiscript
}
static bool compare_types(const std::vector<Type_Info> &tis, const std::vector<Boxed_Value> &bvs,
static bool compare_types(const std::vector<Type_Info> &tis, const Function_Params &bvs,
const Type_Conversions_State &t_conversions) noexcept
{
if (tis.size() - 1 != bvs.size())
@ -342,10 +344,8 @@ namespace chaiscript
namespace dispatch
{
/**
* A Proxy_Function implementation that is not type safe, the called function
* is expecting a vector<Boxed_Value> that it works with how it chooses.
*/
/// A Proxy_Function implementation that is not type safe, the called function
/// is expecting a vector<Boxed_Value> that it works with how it chooses.
class Dynamic_Proxy_Function : public Proxy_Function_Base
{
public:
@ -373,7 +373,7 @@ namespace chaiscript
&& this->m_param_types == prhs->m_param_types);
}
bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const override
bool call_match(const Function_Params &vals, const Type_Conversions_State &t_conversions) const override
{
return call_match_internal(vals, t_conversions).first;
}
@ -403,7 +403,7 @@ namespace chaiscript
protected:
bool test_guard(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const
bool test_guard(const Function_Params &params, const Type_Conversions_State &t_conversions) const
{
if (m_guard)
{
@ -421,7 +421,7 @@ namespace chaiscript
// first result: is a match
// second result: needs conversions
std::pair<bool, bool> call_match_internal(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const
std::pair<bool, bool> call_match_internal(const Function_Params &vals, const Type_Conversions_State &t_conversions) const
{
const auto comparison_result = [&](){
if (m_arity < 0) {
@ -434,7 +434,7 @@ namespace chaiscript
}();
return std::make_pair(
comparison_result.first && test_guard(vals, t_conversions),
comparison_result.first && test_guard(vals, t_conversions),
comparison_result.second
);
}
@ -472,7 +472,7 @@ namespace chaiscript
{
public:
Dynamic_Proxy_Function_Impl(
Callable t_f,
Callable t_f,
int t_arity=-1,
std::shared_ptr<AST_Node> t_parsenode = AST_NodePtr(),
Param_Types t_param_types = Param_Types(),
@ -489,13 +489,13 @@ namespace chaiscript
protected:
Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
Boxed_Value do_call(const Function_Params &params, const Type_Conversions_State &t_conversions) const override
{
const auto match_results = call_match_internal(params, t_conversions);
if (match_results.first)
const auto [is_a_match, needs_conversions] = call_match_internal(params, t_conversions);
if (is_a_match)
{
if (match_results.second) {
return m_f(m_param_types.convert(params, t_conversions));
if (needs_conversions) {
return m_f(Function_Params{m_param_types.convert(params, t_conversions)});
} else {
return m_f(params);
}
@ -528,7 +528,7 @@ namespace chaiscript
class Bound_Function final : public Proxy_Function_Base
{
public:
Bound_Function(const Const_Proxy_Function &t_f,
Bound_Function(const Const_Proxy_Function &t_f,
const std::vector<Boxed_Value> &t_args)
: Proxy_Function_Base(build_param_type_info(t_f, t_args), (t_f->get_arity()<0?-1:static_cast<int>(build_param_type_info(t_f, t_args).size())-1)),
m_f(t_f), m_args(t_args)
@ -542,9 +542,9 @@ namespace chaiscript
}
bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const override
bool call_match(const Function_Params &vals, const Type_Conversions_State &t_conversions) const override
{
return m_f->call_match(build_param_list(vals), t_conversions);
return m_f->call_match(Function_Params(build_param_list(vals)), t_conversions);
}
std::vector<Const_Proxy_Function> get_contained_functions() const override
@ -553,7 +553,7 @@ namespace chaiscript
}
std::vector<Boxed_Value> build_param_list(const std::vector<Boxed_Value> &params) const
std::vector<Boxed_Value> build_param_list(const Function_Params &params) const
{
auto parg = params.begin();
auto barg = m_args.begin();
@ -562,7 +562,7 @@ namespace chaiscript
while (!(parg == params.end() && barg == m_args.end()))
{
while (barg != m_args.end()
while (barg != m_args.end()
&& !(barg->get_type_info() == chaiscript::detail::Get_Type_Info<Placeholder_Object>::get()))
{
args.push_back(*barg);
@ -575,18 +575,18 @@ namespace chaiscript
++parg;
}
if (barg != m_args.end()
if (barg != m_args.end()
&& barg->get_type_info() == chaiscript::detail::Get_Type_Info<Placeholder_Object>::get())
{
++barg;
}
}
}
return args;
}
protected:
static std::vector<Type_Info> build_param_type_info(const Const_Proxy_Function &t_f,
static std::vector<Type_Info> build_param_type_info(const Const_Proxy_Function &t_f,
const std::vector<Boxed_Value> &t_args)
{
assert(t_f->get_arity() < 0 || t_f->get_arity() == static_cast<int>(t_args.size()));
@ -610,9 +610,9 @@ namespace chaiscript
return retval;
}
Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
Boxed_Value do_call(const Function_Params &params, const Type_Conversions_State &t_conversions) const override
{
return (*m_f)(build_param_list(params), t_conversions);
return (*m_f)(Function_Params{build_param_list(params)}, t_conversions);
}
private:
@ -628,13 +628,13 @@ namespace chaiscript
{
}
bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const noexcept override
bool call_match(const Function_Params &vals, const Type_Conversions_State &t_conversions) const noexcept override
{
return static_cast<int>(vals.size()) == get_arity()
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 noexcept = 0;
virtual bool compare_types_with_cast(const Function_Params &vals, const Type_Conversions_State &t_conversions) const noexcept = 0;
};
@ -650,7 +650,7 @@ namespace chaiscript
{
}
bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const noexcept override
bool compare_types_with_cast(const Function_Params &vals, const Type_Conversions_State &t_conversions) const noexcept override
{
return detail::compare_types_cast(static_cast<Func *>(nullptr), vals, t_conversions);
}
@ -662,7 +662,7 @@ namespace chaiscript
protected:
Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
Boxed_Value do_call(const Function_Params &params, const Type_Conversions_State &t_conversions) const override
{
return detail::call_func(static_cast<Func *>(nullptr), m_f, params, t_conversions);
}
@ -694,7 +694,7 @@ 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 noexcept override
bool compare_types_with_cast(const Function_Params &vals, const Type_Conversions_State &t_conversions) const noexcept override
{
return detail::compare_types_cast(static_cast<Func *>(nullptr), vals, t_conversions);
}
@ -714,7 +714,7 @@ namespace chaiscript
}
protected:
Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
Boxed_Value do_call(const Function_Params &params, const Type_Conversions_State &t_conversions) const override
{
return detail::call_func(static_cast<Func *>(nullptr), m_f.get(), params, t_conversions);
}
@ -737,11 +737,11 @@ namespace chaiscript
{
}
bool is_attribute_function() const noexcept override { return true; }
bool is_attribute_function() const noexcept override { return true; }
bool operator==(const Proxy_Function_Base &t_func) const noexcept override
{
const Attribute_Access<T, Class> * aa
const Attribute_Access<T, Class> * aa
= dynamic_cast<const Attribute_Access<T, Class> *>(&t_func);
if (aa) {
@ -751,7 +751,7 @@ namespace chaiscript
}
}
bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &) const noexcept override
bool call_match(const Function_Params &vals, const Type_Conversions_State &) const noexcept override
{
if (vals.size() != 1)
{
@ -762,7 +762,7 @@ namespace chaiscript
}
protected:
Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) const override
Boxed_Value do_call(const Function_Params &params, const Type_Conversions_State &t_conversions) const override
{
const Boxed_Value &bv = params[0];
if (bv.is_const())
@ -811,22 +811,22 @@ namespace chaiscript
{
/// \brief Exception thrown in the case that a method dispatch fails
/// because no matching function was found
///
///
/// May be thrown due to an arity_error, a guard_error or a bad_boxed_cast
/// exception
class dispatch_error : public std::runtime_error
{
public:
dispatch_error(std::vector<Boxed_Value> t_parameters,
dispatch_error(const Function_Params &t_parameters,
std::vector<Const_Proxy_Function> t_functions)
: std::runtime_error("Error with function dispatch"), parameters(std::move(t_parameters)), functions(std::move(t_functions))
: std::runtime_error("Error with function dispatch"), parameters(t_parameters.to_vector()), functions(std::move(t_functions))
{
}
dispatch_error(std::vector<Boxed_Value> t_parameters,
dispatch_error(const Function_Params &t_parameters,
std::vector<Const_Proxy_Function> t_functions,
const std::string &t_desc)
: std::runtime_error(t_desc), parameters(std::move(t_parameters)), functions(std::move(t_functions))
: std::runtime_error(t_desc), parameters(t_parameters.to_vector()), functions(std::move(t_functions))
{
}
@ -837,14 +837,14 @@ namespace chaiscript
std::vector<Boxed_Value> parameters;
std::vector<Const_Proxy_Function> functions;
};
}
}
namespace dispatch
{
namespace detail
namespace detail
{
template<typename FuncType>
bool types_match_except_for_arithmetic(const FuncType &t_func, const std::vector<Boxed_Value> &plist,
bool types_match_except_for_arithmetic(const FuncType &t_func, const Function_Params &plist,
const Type_Conversions_State &t_conversions) noexcept
{
const std::vector<Type_Info> &types = t_func->get_param_types();
@ -863,7 +863,7 @@ namespace chaiscript
}
template<typename InItr, typename Funcs>
Boxed_Value dispatch_with_conversions(InItr begin, const InItr &end, const std::vector<Boxed_Value> &plist,
Boxed_Value dispatch_with_conversions(InItr begin, const InItr &end, const Function_Params &plist,
const Type_Conversions_State &t_conversions, const Funcs &t_funcs)
{
InItr matching_func(end);
@ -919,7 +919,7 @@ namespace chaiscript
);
try {
return (*(matching_func->second))(newplist, t_conversions);
return (*(matching_func->second))(Function_Params{newplist}, t_conversions);
} catch (const exception::bad_boxed_cast &) {
//parameter failed to cast
} catch (const exception::arity_error &) {
@ -938,7 +938,7 @@ namespace chaiscript
/// function is found or throw dispatch_error if no matching function is found
template<typename Funcs>
Boxed_Value dispatch(const Funcs &funcs,
const std::vector<Boxed_Value> &plist, const Type_Conversions_State &t_conversions)
const Function_Params &plist, const Type_Conversions_State &t_conversions)
{
std::vector<std::pair<size_t, const Proxy_Function_Base *>> ordered_funcs;
ordered_funcs.reserve(funcs.size());

View File

@ -21,6 +21,7 @@
#include "boxed_value.hpp"
#include "handle_return.hpp"
#include "type_info.hpp"
#include "function_params.hpp"
namespace chaiscript {
class Type_Conversions_State;
@ -77,7 +78,7 @@ namespace chaiscript
*/
template<typename Ret, typename ... Params>
bool compare_types_cast(Ret (*)(Params...),
const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions) noexcept
const Function_Params &params, const Type_Conversions_State &t_conversions) noexcept
{
try {
std::vector<Boxed_Value>::size_type i = 0;
@ -92,7 +93,7 @@ namespace chaiscript
template<typename Callable, typename Ret, typename ... Params, size_t ... I>
Ret call_func(Ret (*)(Params...),
std::index_sequence<I...>, const Callable &f,
[[maybe_unused]] const std::vector<Boxed_Value> &params,
[[maybe_unused]] const Function_Params &params,
[[maybe_unused]] const Type_Conversions_State &t_conversions)
{
return f(boxed_cast<Params>(params[I], &t_conversions)...);
@ -105,7 +106,7 @@ namespace chaiscript
/// the bad_boxed_cast is passed up to the caller.
template<typename Callable, typename Ret, typename ... Params>
Boxed_Value call_func(Ret (*sig)(Params...), const Callable &f,
const std::vector<Boxed_Value> &params, const Type_Conversions_State &t_conversions)
const Function_Params &params, const Type_Conversions_State &t_conversions)
{
if constexpr (std::is_same_v<Ret, void>) {
call_func(sig, std::index_sequence_for<Params...>{}, f, params, t_conversions);

View File

@ -95,7 +95,7 @@ namespace chaiscript
Logical_And, Logical_Or, Reference, Switch, Case, Default, Noop, Class, Binary, Arg, Global_Decl, Constant, Compiled
};
enum class Operator_Precidence { Ternary_Cond, Logical_Or,
enum class Operator_Precedence { Ternary_Cond, Logical_Or,
Logical_And, Bitwise_Or, Bitwise_Xor, Bitwise_And,
Equality, Comparison, Shift, Addition, Multiplication, Prefix };
@ -732,12 +732,7 @@ namespace chaiscript
m_ds->pop_function_call(m_ds.stack_holder(), m_ds.conversion_saves());
}
void save_params(const std::vector<Boxed_Value> &t_params)
{
m_ds->save_function_params(t_params);
}
void save_params(std::initializer_list<Boxed_Value> t_params)
void save_params(const Function_Params &t_params)
{
m_ds->save_function_params(t_params);
}

View File

@ -149,7 +149,7 @@ namespace chaiscript
m_engine.add(
dispatch::make_dynamic_proxy_function(
[this](const std::vector<Boxed_Value> &t_params) {
[this](const Function_Params &t_params) {
return m_engine.call_exists(t_params);
})
, "call_exists");
@ -158,7 +158,7 @@ namespace chaiscript
m_engine.add(fun(
[=](const dispatch::Proxy_Function_Base &t_fun, const std::vector<Boxed_Value> &t_params) -> Boxed_Value {
Type_Conversions_State s(this->m_engine.conversions(), this->m_engine.conversions().conversion_saves());
return t_fun(t_params, s);
return t_fun(Function_Params{t_params}, s);
}), "call");
@ -200,6 +200,7 @@ namespace chaiscript
m_engine.add(fun([this](const Boxed_Value &t_bv, const std::string &t_name){ add_global(t_bv, t_name); }), "add_global");
m_engine.add(fun([this](const Boxed_Value &t_bv, const std::string &t_name){ set_global(t_bv, t_name); }), "set_global");
// why this unused parameter to Namespace?
m_engine.add(fun([this](const std::string& t_namespace_name) { register_namespace([](Namespace& /*space*/) {}, t_namespace_name); import(t_namespace_name); }), "namespace");
m_engine.add(fun([this](const std::string& t_namespace_name) { import(t_namespace_name); }), "import");
}

View File

@ -51,7 +51,7 @@ namespace chaiscript
{
/// Helper function that will set up the scope around a function call, including handling the named function parameters
template<typename T>
static Boxed_Value eval_function(chaiscript::detail::Dispatch_Engine &t_ss, const AST_Node_Impl<T> &t_node, const std::vector<std::string> &t_param_names, const std::vector<Boxed_Value> &t_vals, const std::map<std::string, Boxed_Value> *t_locals=nullptr, bool has_this_capture = false) {
static Boxed_Value eval_function(chaiscript::detail::Dispatch_Engine &t_ss, const AST_Node_Impl<T> &t_node, const std::vector<std::string> &t_param_names, const Function_Params &t_vals, const std::map<std::string, Boxed_Value> *t_locals=nullptr, bool has_this_capture = false) {
chaiscript::detail::Dispatch_State state(t_ss);
const Boxed_Value *thisobj = [&]() -> const Boxed_Value *{
@ -96,8 +96,11 @@ namespace chaiscript
return Boxed_Number::clone(incoming);
} else if (incoming.get_type_info().bare_equal_type_info(typeid(bool))) {
return Boxed_Value(*static_cast<const bool*>(incoming.get_const_ptr()));
} else if (incoming.get_type_info().bare_equal_type_info(typeid(std::string))) {
return Boxed_Value(*static_cast<const std::string *>(incoming.get_const_ptr()));
} else {
return t_ss->call_function("clone", t_loc, {incoming}, t_ss.conversions());
std::array<Boxed_Value, 1> params{std::move(incoming)};
return t_ss->call_function("clone", t_loc, Function_Params{params}, t_ss.conversions());
}
} else {
incoming.reset_return_value();
@ -200,8 +203,9 @@ namespace chaiscript
}
} else {
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
fpp.save_params({t_lhs, m_rhs});
return t_ss->call_function(t_oper_string, m_loc, {t_lhs, m_rhs}, t_ss.conversions());
std::array<Boxed_Value, 2> params{t_lhs, m_rhs};
fpp.save_params(Function_Params{params});
return t_ss->call_function(t_oper_string, m_loc, Function_Params{params}, t_ss.conversions());
}
}
catch(const exception::dispatch_error &e){
@ -246,8 +250,9 @@ namespace chaiscript
}
} else {
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
fpp.save_params({t_lhs, t_rhs});
return t_ss->call_function(t_oper_string, m_loc, {t_lhs, t_rhs}, t_ss.conversions());
std::array<Boxed_Value, 2> params{t_lhs, t_rhs};
fpp.save_params(Function_Params(params));
return t_ss->call_function(t_oper_string, m_loc, Function_Params(params), t_ss.conversions());
}
}
catch(const exception::dispatch_error &e){
@ -321,14 +326,14 @@ namespace chaiscript
}
if (Save_Params) {
fpp.save_params(params);
fpp.save_params(Function_Params{params});
}
Boxed_Value fn(this->children[0]->eval(t_ss));
using ConstFunctionTypePtr = const dispatch::Proxy_Function_Base *;
try {
return (*t_ss->boxed_cast<ConstFunctionTypePtr>(fn))(params, t_ss.conversions());
return (*t_ss->boxed_cast<const dispatch::Proxy_Function_Base *>(fn))(Function_Params{params}, t_ss.conversions());
}
catch(const exception::dispatch_error &e){
throw exception::eval_error(std::string(e.what()) + " with function '" + this->children[0]->text + "'", e.parameters, e.functions, false, *t_ss);
@ -338,7 +343,7 @@ namespace chaiscript
using ConstFunctionTypeRef = const Const_Proxy_Function &;
Const_Proxy_Function f = t_ss->boxed_cast<ConstFunctionTypeRef>(fn);
// handle the case where there is only 1 function to try to call and dispatch fails on it
throw exception::eval_error("Error calling function '" + this->children[0]->text + "'", params, {f}, false, *t_ss);
throw exception::eval_error("Error calling function '" + this->children[0]->text + "'", params, make_vector(f), false, *t_ss);
} catch (const exception::bad_boxed_cast &) {
throw exception::eval_error("'" + this->children[0]->pretty_print() + "' does not evaluate to a function.");
}
@ -444,28 +449,37 @@ namespace chaiscript
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override {
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
Boxed_Value rhs = this->children[1]->eval(t_ss);
Boxed_Value lhs = this->children[0]->eval(t_ss);
if (lhs.is_return_value()) {
auto params = [&](){
// The RHS *must* be evaluated before the LHS
// consider `var range = range(x)`
// if we declare the variable in scope first, then the name lookup fails
// for the RHS
auto rhs = this->children[1]->eval(t_ss);
auto lhs = this->children[0]->eval(t_ss);
std::array<Boxed_Value, 2> p{std::move(lhs), std::move(rhs)};
return p;
}();
if (params[0].is_return_value()) {
throw exception::eval_error("Error, cannot assign to temporary value.");
} else if (lhs.is_const()) {
} else if (params[0].is_const()) {
throw exception::eval_error("Error, cannot assign to constant value.");
}
if (m_oper != Operators::Opers::invalid && lhs.get_type_info().is_arithmetic() &&
rhs.get_type_info().is_arithmetic())
if (m_oper != Operators::Opers::invalid && params[0].get_type_info().is_arithmetic() &&
params[1].get_type_info().is_arithmetic())
{
try {
return Boxed_Number::do_oper(m_oper, lhs, rhs);
return Boxed_Number::do_oper(m_oper, params[0], params[1]);
} catch (const std::exception &) {
throw exception::eval_error("Error with unsupported arithmetic assignment operation.");
}
} else if (m_oper == Operators::Opers::assign) {
try {
if (lhs.is_undef()) {
if (params[0].is_undef()) {
if (!this->children.empty()
&& ((this->children[0]->identifier == AST_Node_Type::Reference)
|| (!this->children[0]->children.empty()
@ -476,16 +490,16 @@ namespace chaiscript
{
/// \todo This does not handle the case of an unassigned reference variable
/// being assigned outside of its declaration
lhs.assign(rhs);
lhs.reset_return_value();
return rhs;
params[0].assign(params[1]);
params[0].reset_return_value();
return params[1];
} else {
rhs = detail::clone_if_necessary(std::move(rhs), m_clone_loc, t_ss);
params[1] = detail::clone_if_necessary(std::move(params[1]), m_clone_loc, t_ss);
}
}
try {
return t_ss->call_function(this->text, m_loc, {std::move(lhs), rhs}, t_ss.conversions());
return t_ss->call_function(this->text, m_loc, Function_Params{params}, t_ss.conversions());
}
catch(const exception::dispatch_error &e){
throw exception::eval_error("Unable to find appropriate'" + this->text + "' operator.", e.parameters, e.functions, false, *t_ss);
@ -496,22 +510,22 @@ namespace chaiscript
}
}
else if (this->text == ":=") {
if (lhs.is_undef() || Boxed_Value::type_match(lhs, rhs)) {
lhs.assign(rhs);
lhs.reset_return_value();
if (params[0].is_undef() || Boxed_Value::type_match(params[0], params[1])) {
params[0].assign(params[1]);
params[0].reset_return_value();
} else {
throw exception::eval_error("Mismatched types in equation");
}
}
else {
try {
return t_ss->call_function(this->text, m_loc, {std::move(lhs), rhs}, t_ss.conversions());
return t_ss->call_function(this->text, m_loc, Function_Params{params}, t_ss.conversions());
} catch(const exception::dispatch_error &e){
throw exception::eval_error("Unable to find appropriate'" + this->text + "' operator.", e.parameters, e.functions, false, *t_ss);
}
}
return rhs;
return params[1];
}
private:
@ -589,11 +603,11 @@ namespace chaiscript
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override {
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
const std::vector<Boxed_Value> params{this->children[0]->eval(t_ss), this->children[1]->eval(t_ss)};
std::array<Boxed_Value, 2> params{this->children[0]->eval(t_ss), this->children[1]->eval(t_ss)};
try {
fpp.save_params(params);
return t_ss->call_function("[]", m_loc, params, t_ss.conversions());
fpp.save_params(Function_Params{params});
return t_ss->call_function("[]", m_loc, Function_Params{params}, t_ss.conversions());
}
catch(const exception::dispatch_error &e){
throw exception::eval_error("Can not find appropriate array lookup operator '[]'.", e.parameters, e.functions, false, *t_ss );
@ -618,7 +632,7 @@ namespace chaiscript
Boxed_Value retval = this->children[0]->eval(t_ss);
std::vector<Boxed_Value> params{retval};
auto params = make_vector(retval);
bool has_function_params = false;
if (this->children[1]->children.size() > 1) {
@ -628,10 +642,10 @@ namespace chaiscript
}
}
fpp.save_params(params);
fpp.save_params(Function_Params{params});
try {
retval = t_ss->call_member(m_fun_name, m_loc, std::move(params), has_function_params, t_ss.conversions());
retval = t_ss->call_member(m_fun_name, m_loc, Function_Params{params}, has_function_params, t_ss.conversions());
}
catch(const exception::dispatch_error &e){
if (e.functions.empty())
@ -647,7 +661,8 @@ namespace chaiscript
if (this->children[1]->identifier == AST_Node_Type::Array_Call) {
try {
retval = t_ss->call_function("[]", m_array_loc, {retval, this->children[1]->children[1]->eval(t_ss)}, t_ss.conversions());
std::array<Boxed_Value, 2> p{retval, this->children[1]->children[1]->eval(t_ss)};
retval = t_ss->call_function("[]", m_array_loc, Function_Params{p}, t_ss.conversions());
}
catch(const exception::dispatch_error &e){
throw exception::eval_error("Can not find appropriate array lookup operator '[]'.", e.parameters, e.functions, true, *t_ss);
@ -696,7 +711,7 @@ namespace chaiscript
return Boxed_Value(
dispatch::make_dynamic_proxy_function(
[engine, lambda_node = this->m_lambda_node, param_names = this->m_param_names, captures,
this_capture = this->m_this_capture] (const std::vector<Boxed_Value> &t_params)
this_capture = this->m_this_capture] (const Function_Params &t_params)
{
return detail::eval_function(engine, *lambda_node, param_names, t_params, &captures, this_capture);
},
@ -812,7 +827,7 @@ namespace chaiscript
std::shared_ptr<dispatch::Proxy_Function_Base> guard;
if (m_guard_node) {
guard = dispatch::make_dynamic_proxy_function(
[engine, guardnode = m_guard_node, t_param_names](const std::vector<Boxed_Value> &t_params)
[engine, guardnode = m_guard_node, t_param_names](const Function_Params &t_params)
{
return detail::eval_function(engine, *guardnode, t_param_names, t_params);
},
@ -823,7 +838,7 @@ namespace chaiscript
const std::string & l_function_name = this->children[0]->text;
t_ss->add(
dispatch::make_dynamic_proxy_function(
[engine, func_node = m_body_node, t_param_names](const std::vector<Boxed_Value> &t_params)
[engine, func_node = m_body_node, t_param_names](const Function_Params &t_params)
{
return detail::eval_function(engine, *func_node, t_param_names, t_params);
},
@ -914,7 +929,7 @@ namespace chaiscript
};
const auto call_function = [&t_ss](const auto &t_funcs, const Boxed_Value &t_param) {
return dispatch::dispatch(*t_funcs, {t_param}, t_ss.conversions());
return dispatch::dispatch(*t_funcs, Function_Params{t_param}, t_ss.conversions());
};
@ -963,6 +978,7 @@ namespace chaiscript
try {
this->children[2]->eval(t_ss);
} catch (detail::Continue_Loop &) {
// continue statement hit
}
call_function(pop_front_funcs, range_obj);
}
@ -1034,7 +1050,8 @@ namespace chaiscript
if (this->children[currentCase]->identifier == AST_Node_Type::Case) {
//This is a little odd, but because want to see both the switch and the case simultaneously, I do a downcast here.
try {
if (hasMatched || boxed_cast<bool>(t_ss->call_function("==", m_loc, {match_value, this->children[currentCase]->children[0]->eval(t_ss)}, t_ss.conversions()))) {
std::array<Boxed_Value, 2> p{match_value, this->children[currentCase]->children[0]->eval(t_ss)};
if (hasMatched || boxed_cast<bool>(t_ss->call_function("==", m_loc, Function_Params{p}, t_ss.conversions()))) {
this->children[currentCase]->eval(t_ss);
hasMatched = true;
}
@ -1215,8 +1232,8 @@ namespace chaiscript
return Boxed_Number::do_oper(m_oper, bv);
} else {
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
fpp.save_params({bv});
return t_ss->call_function(this->text, m_loc, {std::move(bv)}, t_ss.conversions());
fpp.save_params(Function_Params{bv});
return t_ss->call_function(this->text, m_loc, Function_Params{bv}, t_ss.conversions());
}
} catch (const exception::dispatch_error &e) {
throw exception::eval_error("Error with prefix operator evaluation: '" + this->text + "'", e.parameters, e.functions, false, *t_ss);
@ -1281,9 +1298,12 @@ namespace chaiscript
Boxed_Value eval_internal(const chaiscript::detail::Dispatch_State &t_ss) const override{
try {
auto oper1 = this->children[0]->children[0]->children[0]->eval(t_ss);
auto oper2 = this->children[0]->children[0]->children[1]->eval(t_ss);
return t_ss->call_function("generate_range", m_loc, {oper1, oper2}, t_ss.conversions());
std::array<Boxed_Value, 2> params{
this->children[0]->children[0]->children[0]->eval(t_ss),
this->children[0]->children[0]->children[1]->eval(t_ss)
};
return t_ss->call_function("generate_range", m_loc, Function_Params{params}, t_ss.conversions());
}
catch (const exception::dispatch_error &e) {
throw exception::eval_error("Unable to generate range vector, while calling 'generate_range'", e.parameters, e.functions, false, *t_ss);
@ -1313,7 +1333,7 @@ namespace chaiscript
auto &catch_block = *this->children[i];
if (catch_block.children.size() == 1) {
//No variable capture, no guards
//No variable capture
retval = catch_block.children[0]->eval(t_ss);
break;
} else if (catch_block.children.size() == 2 || catch_block.children.size() == 3) {
@ -1321,32 +1341,15 @@ namespace chaiscript
if (dispatch::Param_Types(
std::vector<std::pair<std::string, Type_Info>>{Arg_List_AST_Node<T>::get_arg_type(*catch_block.children[0], t_ss)}
).match(std::vector<Boxed_Value>{t_except}, t_ss.conversions()).first)
).match(Function_Params{t_except}, t_ss.conversions()).first)
{
t_ss.add_object(name, t_except);
if (catch_block.children.size() == 2) {
//Variable capture, no guards
//Variable capture
retval = catch_block.children[1]->eval(t_ss);
break;
}
else if (catch_block.children.size() == 3) {
//Variable capture, guards
bool guard = false;
try {
guard = boxed_cast<bool>(catch_block.children[1]->eval(t_ss));
} catch (const exception::bad_boxed_cast &) {
if (this->children.back()->identifier == AST_Node_Type::Finally) {
this->children.back()->children[0]->eval(t_ss);
}
throw exception::eval_error("Guard condition not boolean");
}
if (guard) {
retval = catch_block.children[2]->eval(t_ss);
break;
}
}
}
}
else {
@ -1451,7 +1454,7 @@ namespace chaiscript
std::reference_wrapper<chaiscript::detail::Dispatch_Engine> engine(*t_ss);
if (m_guard_node) {
guard = dispatch::make_dynamic_proxy_function(
[engine, t_param_names, guardnode = m_guard_node](const std::vector<Boxed_Value> &t_params) {
[engine, t_param_names, guardnode = m_guard_node](const Function_Params &t_params) {
return chaiscript::eval::detail::eval_function(engine, *guardnode, t_param_names, t_params);
},
static_cast<int>(numparams), m_guard_node);
@ -1466,7 +1469,7 @@ namespace chaiscript
t_ss->add(
std::make_shared<dispatch::detail::Dynamic_Object_Constructor>(class_name,
dispatch::make_dynamic_proxy_function(
[engine, t_param_names, node = m_body_node](const std::vector<Boxed_Value> &t_params) {
[engine, t_param_names, node = m_body_node](const Function_Params &t_params) {
return chaiscript::eval::detail::eval_function(engine, *node, t_param_names, t_params);
},
static_cast<int>(numparams), m_body_node, param_types, guard
@ -1483,7 +1486,7 @@ namespace chaiscript
t_ss->add(
std::make_shared<dispatch::detail::Dynamic_Object_Function>(class_name,
dispatch::make_dynamic_proxy_function(
[engine, t_param_names, node = m_body_node](const std::vector<Boxed_Value> &t_params) {
[engine, t_param_names, node = m_body_node](const Function_Params &t_params) {
return chaiscript::eval::detail::eval_function(engine, *node, t_param_names, t_params);
},
static_cast<int>(numparams), m_body_node, param_types, guard), type),

View File

@ -285,20 +285,20 @@ namespace chaiscript
};
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,
Operator_Precidence::Bitwise_Or,
Operator_Precidence::Bitwise_Xor,
Operator_Precidence::Bitwise_And,
Operator_Precidence::Equality,
Operator_Precidence::Comparison,
Operator_Precidence::Shift,
Operator_Precidence::Addition,
Operator_Precidence::Multiplication,
Operator_Precidence::Prefix
constexpr static std::array<Operator_Precedence, 12> create_operators() noexcept {
std::array<Operator_Precedence, 12> operators = { {
Operator_Precedence::Ternary_Cond,
Operator_Precedence::Logical_Or,
Operator_Precedence::Logical_And,
Operator_Precedence::Bitwise_Or,
Operator_Precedence::Bitwise_Xor,
Operator_Precedence::Bitwise_And,
Operator_Precedence::Equality,
Operator_Precedence::Comparison,
Operator_Precedence::Shift,
Operator_Precedence::Addition,
Operator_Precedence::Multiplication,
Operator_Precedence::Prefix
} };
return operators;
}
@ -1791,11 +1791,6 @@ namespace chaiscript
if (!(Arg() && Char(')'))) {
throw exception::eval_error("Incomplete 'catch' expression", File_Position(m_position.line, m_position.col), *m_filename);
}
if (Char(':')) {
if (!Operator()) {
throw exception::eval_error("Missing guard expression for catch", File_Position(m_position.line, m_position.col), *m_filename);
}
}
}
while (Eol()) {}
@ -2471,7 +2466,7 @@ namespace chaiscript
bool retval = false;
const auto prev_stack_top = m_match_stack.size();
if (m_operators[t_precedence] != Operator_Precidence::Prefix) {
if (m_operators[t_precedence] != Operator_Precedence::Prefix) {
if (Operator(t_precedence+1)) {
retval = true;
std::string oper;
@ -2483,7 +2478,7 @@ namespace chaiscript
}
switch (m_operators[t_precedence]) {
case(Operator_Precidence::Ternary_Cond) :
case(Operator_Precedence::Ternary_Cond) :
if (Symbol(":")) {
if (!Operator(t_precedence+1)) {
throw exception::eval_error("Incomplete '" + oper + "' expression",
@ -2497,24 +2492,24 @@ namespace chaiscript
}
break;
case(Operator_Precidence::Addition) :
case(Operator_Precidence::Multiplication) :
case(Operator_Precidence::Shift) :
case(Operator_Precidence::Equality) :
case(Operator_Precidence::Bitwise_And) :
case(Operator_Precidence::Bitwise_Xor) :
case(Operator_Precidence::Bitwise_Or) :
case(Operator_Precidence::Comparison) :
case(Operator_Precedence::Addition) :
case(Operator_Precedence::Multiplication) :
case(Operator_Precedence::Shift) :
case(Operator_Precedence::Equality) :
case(Operator_Precedence::Bitwise_And) :
case(Operator_Precedence::Bitwise_Xor) :
case(Operator_Precedence::Bitwise_Or) :
case(Operator_Precedence::Comparison) :
build_match<eval::Binary_Operator_AST_Node<Tracer>>(prev_stack_top, oper);
break;
case(Operator_Precidence::Logical_And) :
case(Operator_Precedence::Logical_And) :
build_match<eval::Logical_And_AST_Node<Tracer>>(prev_stack_top, oper);
break;
case(Operator_Precidence::Logical_Or) :
case(Operator_Precedence::Logical_Or) :
build_match<eval::Logical_Or_AST_Node<Tracer>>(prev_stack_top, oper);
break;
case(Operator_Precidence::Prefix) :
case(Operator_Precedence::Prefix) :
assert(false); // cannot reach here because of if() statement at the top
break;

View File

@ -49,19 +49,6 @@ 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;
};

View File

@ -96,7 +96,7 @@ class JSON
template<auto ClassValue>
auto &get_set_type() {
set_type(ClassValue);
return std::get<static_cast<std::size_t>(ClassValue)>(d);
return (std::get<static_cast<std::size_t>(ClassValue)>(d));
}
auto &Map() {

View File

@ -3,15 +3,29 @@
namespace chaiscript::utility {
template<typename Key, typename Value>
template<typename Key, typename Value, typename Comparator=std::equal_to<>>
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; });
Comparator comparator;
template<typename Lookup>
auto find(const Lookup &s) noexcept {
return std::find_if(std::begin(data), std::end(data), [&s, this](const auto &d) { return comparator(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; });
template<typename Lookup>
auto find(const Lookup &s) const noexcept {
return std::find_if(std::cbegin(data), std::cend(data), [&s, this](const auto &d) { return comparator(d.first, s); });
}
template<typename Lookup>
auto find(const Lookup &s, const std::size_t t_hint) const noexcept {
if (data.size() > t_hint && comparator(data[t_hint].first, s)) {
const auto begin = std::cbegin(data);
return std::next(begin, static_cast<typename std::iterator_traits<std::decay_t<decltype(begin)>>::difference_type>(t_hint));
} else {
return find(s);
}
}
auto size() const noexcept {
@ -35,16 +49,46 @@ namespace chaiscript::utility {
return data.end();
}
auto &back() noexcept {
return data.back();
}
const auto &back() const noexcept {
return data.back();
}
Value &operator[](const Key &s) {
const auto itr = find(s);
if (itr != data.end()) {
return itr->second;
} else {
grow();
return data.emplace_back(s, Value()).second;
}
}
Value &at_index(const std::size_t idx) noexcept
{
return data[idx].second;
}
const Value &at_index(const std::size_t idx) const noexcept
{
return data[idx].second;
}
bool empty() const noexcept
{
return data.empty();
}
template<typename Itr>
void assign(Itr begin, Itr end)
{
data.assign(begin, end);
}
Value &at(const Key &s) {
const auto itr = find(s);
if (itr != data.end()) {
@ -54,6 +98,32 @@ namespace chaiscript::utility {
}
}
template<typename M>
auto insert_or_assign(Key &&key, M &&m)
{
if (auto itr = find(key); itr != data.end()) {
*itr = std::forward<M>(m);
return std::pair{itr, false};
} else {
grow();
return std::pair{data.emplace(data.end(), std::move(key), std::forward<M>(m)), true};
}
}
template<typename M>
auto insert_or_assign(const Key &key, M &&m)
{
if (auto itr = find(key); itr != data.end()) {
itr->second = std::forward<M>(m);
return std::pair{itr, false};
} else {
grow();
return std::pair{data.emplace(data.end(), key, std::forward<M>(m)), true};
}
}
const Value &at(const Key &s) const {
const auto itr = find(s);
if (itr != data.end()) {
@ -63,15 +133,33 @@ namespace chaiscript::utility {
}
}
size_t count(const Key &s) const noexcept {
template<typename Lookup>
size_t count(const Lookup &s) const noexcept {
return (find(s) != data.end())?1:0;
}
std::vector<std::pair<Key, Value>> data;
using value_type = std::pair<Key, Value>;
using iterator = typename decltype(data)::iterator;
using const_iterator = typename decltype(data)::const_iterator;
std::pair<iterator,bool> insert( value_type&& value )
{
if (const auto itr = find(value.first); itr != data.end()) {
return std::pair{itr, false};
} else {
grow();
return std::pair{data.insert(data.end(), std::move(value)), true};
}
}
void grow() {
if ((data.capacity() - data.size()) == 0) {
data.reserve(data.size() + 2);
}
}
};

View File

@ -0,0 +1,63 @@
// This file is distributed under the BSD License.
// See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// Copyright 2009-2017, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
// This is an open source non-commercial project. Dear PVS-Studio, please check it.
// PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
#ifndef CHAISCRIPT_STACK_VECTOR_HPP_
#define CHAISCRIPT_STACK_VECTOR_HPP_
#include <cstdint>
#include <type_traits>
#include <string>
template<typename T, std::size_t MaxSize>
struct Stack_Vector
{
constexpr static auto aligned_size = sizeof(T) + (sizeof(T) & std::alignment_of_v<T>) > 0 ? std::alignment_of_v<T> : 0;
alignas(std::alignment_of_v<T>) char data[aligned_size * MaxSize];
[[nodiscard]] T & operator[](const std::size_t idx) noexcept {
return *reinterpret_cast<T*>(&data + aligned_size * idx);
}
[[nodiscard]] const T & operator[](const std::size_t idx) const noexcept {
return *reinterpret_cast<const T*>(&data + aligned_size * idx);
}
template<typename ... Param>
T& emplace_back(Param && ... param) {
auto *p = new(&(*this)[m_size++]) T(std::forward<Param>(param)...);
return *p;
};
auto size() const noexcept {
return m_size;
};
void pop_back() noexcept(std::is_nothrow_destructible_v<T>) {
(*this)[m_size--].~T();
}
~Stack_Vector() noexcept(std::is_nothrow_destructible_v<T>)
{
auto loc = m_size - 1;
for (std::size_t pos = 0; pos < m_size; ++pos) {
(*this)[loc--].~T();
}
}
std::size_t m_size{0};
};
#endif CHAISCRIPT_STACK_VECTOR_HPP_

View File

@ -145,20 +145,20 @@ std::vector<std::string> default_search_paths()
void help(int n) {
if (n >= 0) {
std::cout << "ChaiScript evaluator. To evaluate an expression, type it and press <enter>." << std::endl;
std::cout << "Additionally, you can inspect the runtime system using:" << std::endl;
std::cout << " dump_system() - outputs all functions registered to the system" << std::endl;
std::cout << " dump_object(x) - dumps information about the given symbol" << std::endl;
std::cout << "ChaiScript evaluator. To evaluate an expression, type it and press <enter>.\n";
std::cout << "Additionally, you can inspect the runtime system using:\n";
std::cout << " dump_system() - outputs all functions registered to the system\n";
std::cout << " dump_object(x) - dumps information about the given symbol\n";
}
else {
std::cout << "usage : chai [option]+" << std::endl;
std::cout << "option:" << std::endl;
std::cout << " -h | --help" << std::endl;
std::cout << " -i | --interactive" << std::endl;
std::cout << " -c | --command cmd" << std::endl;
std::cout << " -v | --version" << std::endl;
std::cout << " - --stdin" << std::endl;
std::cout << " filepath" << std::endl;
std::cout << "usage : chai [option]+\n";
std::cout << "option:\n";
std::cout << " -h | --help\n";
std::cout << " -i | --interactive\n";
std::cout << " -c | --command cmd\n";
std::cout << " -v | --version\n";
std::cout << " - --stdin\n";
std::cout << " filepath\n";
}
}
@ -244,7 +244,7 @@ void interactive(chaiscript::ChaiScript& chai)
//Then, we try to print the result of the evaluation to the user
if (!val.get_type_info().bare_equal(chaiscript::user_type<void>())) {
try {
std::cout << chai.eval<std::function<std::string(const chaiscript::Boxed_Value &bv)> >("to_string")(val) << std::endl;
std::cout << chai.eval<std::function<std::string(const chaiscript::Boxed_Value &bv)> >("to_string")(val) << '\n';
}
catch (...) {} //If we can't, do nothing
}
@ -254,7 +254,7 @@ void interactive(chaiscript::ChaiScript& chai)
if (ee.call_stack.size() > 0) {
std::cout << "during evaluation at (" << ee.call_stack[0].start().line << ", " << ee.call_stack[0].start().column << ")";
}
std::cout << std::endl;
std::cout << '\n';
}
catch (const std::exception &e) {
std::cout << e.what();

View File

@ -4,6 +4,11 @@
// and Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com
// NOT TO BE USED AS A SOURCE OF BEST PRACTICES
// FOR CHAISCRIPT
#include <iostream>
#include <ctime>
@ -156,7 +161,7 @@ int main(int /*argc*/, char * /*argv*/[]) {
//Ability to create our own container types when needed. std::vector and std::map are
//mostly supported currently
chai.add(bootstrap::standard_library::vector_type<std::vector<int> >("IntVector"));
//chai.add(bootstrap::standard_library::vector_type<std::vector<int> >("IntVector"));
// Test ability to register a function that excepts a shared_ptr version of a type

View File

@ -1,34 +0,0 @@
var results = [];
for (var i = 2; i < 6; ++i) {
try {
throw(i)
}
catch(e) : e < 2 {
results.push_back("c1: " + e.to_string());
}
catch(e) : e < 4 {
results.push_back("c2: " + e.to_string());
}
catch(e) {
results.push_back("c3: " + e.to_string());
}
catch {
// Should never get called
assert_equal(false, true)
}
}
try {
throw(3)
}
catch(e) : e < 3
{
// Should never get called
assert_equal(false, true);
}
catch {
results.push_back("defaultcatch");
}
assert_equal(["c2: 2", "c2: 3", "c3: 4", "c3: 5", "defaultcatch"], results);

View File

@ -0,0 +1,41 @@
/*
global clone_count = 0;
class Cloneable
{
def Cloneable() {
}
}
def clone(Cloneable c)
{
print("Clone called");
++clone_count;
return c;
}
class MyObject
{
def MyObject() {
this.data = Cloneable();
}
var data;
}
assert_equal(0, clone_count);
var o = MyObject();
assert_equal(0, clone_count);
var p = o;
assert_equal(1, clone_count);
*/

View File

@ -1,34 +0,0 @@
auto results = [];
for (auto i = 2; i < 6; ++i) {
try {
throw(i)
}
catch(e) : e < 2 {
results.push_back("c1: " + e.to_string());
}
catch(e) : e < 4 {
results.push_back("c2: " + e.to_string());
}
catch(e) {
results.push_back("c3: " + e.to_string());
}
catch {
// Should never get called
assert_equal(false, true)
}
}
try {
throw(3)
}
catch(e) : e < 3
{
// Should never get called
assert_equal(false, true);
}
catch {
results.push_back("defaultcatch");
}
assert_equal(["c2: 2", "c2: 3", "c3: 4", "c3: 5", "defaultcatch"], results);

View File

@ -1,34 +0,0 @@
auto results = [];
for (auto i = 2; i < 6; ++i) {
try {
throw(i)
}
catch(int e) : e < 2 {
results.push_back("c1: " + e.to_string());
}
catch(int e) : e < 4 {
results.push_back("c2: " + e.to_string());
}
catch(e) {
results.push_back("c3: " + e.to_string());
}
catch {
// Should never get called
assert_equal(false, true)
}
}
try {
throw(3)
}
catch(int e) : e < 3
{
// Should never get called
assert_equal(false, true);
}
catch {
results.push_back("defaultcatch");
}
assert_equal(["c2: 2", "c2: 3", "c3: 4", "c3: 5", "defaultcatch"], results);