Compare commits
1 Commits
v5.5.1
...
value_type
Author | SHA1 | Date | |
---|---|---|---|
![]() |
5c541c3d8e |
@@ -1,24 +1,12 @@
|
||||
compilers:
|
||||
- name: "clang"
|
||||
version: "3.5"
|
||||
skip_packaging: true
|
||||
cmake_extra_flags: -DUSE_LIBCXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON
|
||||
- name: "clang"
|
||||
build_tag: AddressSanitizer
|
||||
version: "3.5"
|
||||
skip_packaging: true
|
||||
cmake_extra_flags: -DUSE_LIBCXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DENABLE_ADDRESS_SANITIZER:BOOL=ON
|
||||
- name: "clang"
|
||||
build_tag: ThreadSanitizer
|
||||
version: "3.5"
|
||||
skip_packaging: true
|
||||
cmake_extra_flags: -DUSE_LIBCXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DENABLE_THREAD_SANITIZER:BOOL=ON
|
||||
- name: "gcc"
|
||||
version: "4.8"
|
||||
cmake_extra_flags: -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DBUILD_TESTING:BOOL=ON
|
||||
- name: "gcc"
|
||||
version: "4.6"
|
||||
skip_packaging: true
|
||||
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON
|
||||
- name: cppcheck
|
||||
compiler_extra_flags: --enable=all -I include --inline-suppr
|
||||
|
@@ -4,5 +4,4 @@ compilers:
|
||||
- name: clang
|
||||
build_type: Debug
|
||||
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=$COMMIT_SHA
|
||||
skip_packaging: true
|
||||
|
||||
|
@@ -3,13 +3,11 @@ compilers:
|
||||
version: 14
|
||||
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA%
|
||||
compiler_extra_flags: /ANALYZE
|
||||
skip_packaging: true
|
||||
- name: Visual Studio
|
||||
version: 14
|
||||
architecture: Win64
|
||||
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA%
|
||||
compiler_extra_flags: /ANALYZE
|
||||
skip_packaging: true
|
||||
- name: Visual Studio
|
||||
version: 12
|
||||
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA%
|
||||
|
@@ -36,38 +36,11 @@ if(CMAKE_COMPILER_IS_GNUCC OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
set(LINKER_FLAGS "${LINKER_FLAGS} -fsanitize=address")
|
||||
endif()
|
||||
|
||||
option(ENABLE_MEMORY_SANITIZER "Enable memory sanitizer testing in gcc/clang" FALSE)
|
||||
if(ENABLE_MEMORY_SANITIZER)
|
||||
add_definitions(-fsanitize=memory -g)
|
||||
set(LINKER_FLAGS "${LINKER_FLAGS} -fsanitize=memory")
|
||||
endif()
|
||||
|
||||
option(ENABLE_UNDEFINED_SANITIZER "Enable undefined behavior sanitizer testing in gcc/clang" FALSE)
|
||||
if(ENABLE_UNDEFINED_SANITIZER)
|
||||
add_definitions(-fsanitize=undefined -g)
|
||||
set(LINKER_FLAGS "${LINKER_FLAGS} -fsanitize=undefined")
|
||||
endif()
|
||||
|
||||
option(ENABLE_LTO "Enable Link Time Optimization" FALSE)
|
||||
|
||||
if (ENABLE_LTO)
|
||||
add_definitions(-flto)
|
||||
set(LINKER_FLAGS "${LINKER_FLAGS} -flto")
|
||||
endif()
|
||||
|
||||
option(PROFILE_GENERATE "Generate profile data" FALSE)
|
||||
if (PROFILE_GENERATE)
|
||||
add_definitions(-fprofile-generate)
|
||||
set(LINKER_FLAGS "${LINKER_FLAGS} -fprofile-generate")
|
||||
endif()
|
||||
|
||||
option(PROFILE_USE "Use profile data" FALSE)
|
||||
if (PROFILE_USE)
|
||||
add_definitions(-fprofile-use)
|
||||
set(LINKER_FLAGS "${LINKER_FLAGS} -fprofile-use")
|
||||
endif()
|
||||
|
||||
|
||||
endif()
|
||||
|
||||
list(APPEND CPACK_SOURCE_IGNORE_FILES "${CMAKE_CURRENT_BINARY_DIR}")
|
||||
@@ -81,8 +54,8 @@ set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/readme.md")
|
||||
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/description.txt")
|
||||
|
||||
set(CPACK_PACKAGE_VERSION_MAJOR 5)
|
||||
set(CPACK_PACKAGE_VERSION_MINOR 5)
|
||||
set(CPACK_PACKAGE_VERSION_PATCH 1)
|
||||
set(CPACK_PACKAGE_VERSION_MINOR 4)
|
||||
set(CPACK_PACKAGE_VERSION_PATCH 0)
|
||||
|
||||
set(CPACK_PACKAGE_EXECUTABLES "chai;ChaiScript Eval")
|
||||
set(CPACK_PACKAGE_VENDOR "ChaiScript.com")
|
||||
@@ -160,7 +133,7 @@ else()
|
||||
endif()
|
||||
|
||||
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
option(USE_LIBCXX "Use clang's libcxx" TRUE)
|
||||
option(USE_LIBCXX "Use clang's libcxx" FALSE)
|
||||
|
||||
if(USE_LIBCXX)
|
||||
add_definitions(-stdlib=libc++)
|
||||
@@ -181,7 +154,7 @@ endif()
|
||||
include_directories(include)
|
||||
|
||||
|
||||
set(Chai_INCLUDES include/chaiscript/chaiscript.hpp include/chaiscript/chaiscript_threading.hpp include/chaiscript/dispatchkit/bad_boxed_cast.hpp include/chaiscript/dispatchkit/bind_first.hpp include/chaiscript/dispatchkit/bootstrap.hpp include/chaiscript/dispatchkit/bootstrap_stl.hpp include/chaiscript/dispatchkit/boxed_cast.hpp include/chaiscript/dispatchkit/boxed_cast_helper.hpp include/chaiscript/dispatchkit/boxed_number.hpp include/chaiscript/dispatchkit/boxed_value.hpp include/chaiscript/dispatchkit/dispatchkit.hpp include/chaiscript/dispatchkit/type_conversions.hpp include/chaiscript/dispatchkit/dynamic_object.hpp include/chaiscript/dispatchkit/exception_specification.hpp include/chaiscript/dispatchkit/function_call.hpp include/chaiscript/dispatchkit/function_call_detail.hpp include/chaiscript/dispatchkit/handle_return.hpp include/chaiscript/dispatchkit/operators.hpp include/chaiscript/dispatchkit/proxy_constructors.hpp include/chaiscript/dispatchkit/proxy_functions.hpp include/chaiscript/dispatchkit/proxy_functions_detail.hpp include/chaiscript/dispatchkit/register_function.hpp include/chaiscript/dispatchkit/type_info.hpp include/chaiscript/language/chaiscript_algebraic.hpp include/chaiscript/language/chaiscript_common.hpp include/chaiscript/language/chaiscript_engine.hpp include/chaiscript/language/chaiscript_eval.hpp include/chaiscript/language/chaiscript_parser.hpp include/chaiscript/language/chaiscript_prelude.chai include/chaiscript/language/chaiscript_prelude_docs.hpp include/chaiscript/utility/utility.hpp)
|
||||
set(Chai_INCLUDES include/chaiscript/chaiscript.hpp include/chaiscript/chaiscript_threading.hpp include/chaiscript/dispatchkit/bad_boxed_cast.hpp include/chaiscript/dispatchkit/bind_first.hpp include/chaiscript/dispatchkit/bootstrap.hpp include/chaiscript/dispatchkit/bootstrap_stl.hpp include/chaiscript/dispatchkit/boxed_cast.hpp include/chaiscript/dispatchkit/boxed_cast_helper.hpp include/chaiscript/dispatchkit/boxed_number.hpp include/chaiscript/dispatchkit/boxed_value.hpp include/chaiscript/dispatchkit/dispatchkit.hpp include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp include/chaiscript/dispatchkit/dynamic_object.hpp include/chaiscript/dispatchkit/exception_specification.hpp include/chaiscript/dispatchkit/function_call.hpp include/chaiscript/dispatchkit/function_call_detail.hpp include/chaiscript/dispatchkit/handle_return.hpp include/chaiscript/dispatchkit/operators.hpp include/chaiscript/dispatchkit/proxy_constructors.hpp include/chaiscript/dispatchkit/proxy_functions.hpp include/chaiscript/dispatchkit/proxy_functions_detail.hpp include/chaiscript/dispatchkit/register_function.hpp include/chaiscript/dispatchkit/type_info.hpp include/chaiscript/language/chaiscript_algebraic.hpp include/chaiscript/language/chaiscript_common.hpp include/chaiscript/language/chaiscript_engine.hpp include/chaiscript/language/chaiscript_eval.hpp include/chaiscript/language/chaiscript_parser.hpp include/chaiscript/language/chaiscript_prelude.chai include/chaiscript/language/chaiscript_prelude_docs.hpp include/chaiscript/utility/utility.hpp)
|
||||
|
||||
set_source_files_properties(${Chai_INCLUDES} PROPERTIES HEADER_FILE_ONLY TRUE)
|
||||
|
||||
@@ -232,8 +205,6 @@ if(BUILD_SAMPLES)
|
||||
target_link_libraries(memory_leak_test ${LIBS})
|
||||
add_executable(inheritance samples/inheritance.cpp)
|
||||
target_link_libraries(inheritance ${LIBS})
|
||||
add_executable(fun_call_performance samples/fun_call_performance.cpp)
|
||||
target_link_libraries(fun_call_performance ${LIBS})
|
||||
endif()
|
||||
|
||||
|
||||
@@ -296,10 +267,6 @@ if(BUILD_TESTING)
|
||||
target_link_libraries(object_lifetime_test ${LIBS})
|
||||
add_test(NAME Object_Lifetime_Test COMMAND object_lifetime_test)
|
||||
|
||||
add_executable(object_lifetime_test2 unittests/object_lifetime_test2.cpp)
|
||||
target_link_libraries(object_lifetime_test2 ${LIBS})
|
||||
add_test(NAME Object_Lifetime_Test2 COMMAND object_lifetime_test2)
|
||||
|
||||
add_executable(function_ordering_test unittests/function_ordering_test.cpp)
|
||||
target_link_libraries(function_ordering_test ${LIBS})
|
||||
add_test(NAME Function_Ordering_Test COMMAND function_ordering_test)
|
||||
|
@@ -45,8 +45,8 @@
|
||||
|
||||
namespace chaiscript {
|
||||
static const int version_major = 5;
|
||||
static const int version_minor = 5;
|
||||
static const int version_patch = 1;
|
||||
static const int version_minor = 4;
|
||||
static const int version_patch = 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@@ -44,31 +44,20 @@ namespace chaiscript {
|
||||
private:
|
||||
struct Data
|
||||
{
|
||||
Data(const std::type_info &t_type)
|
||||
: m_type(t_type)
|
||||
{
|
||||
}
|
||||
|
||||
Data &operator=(const Data &) = delete;
|
||||
|
||||
virtual ~Data() {}
|
||||
|
||||
virtual void *data() = 0;
|
||||
const std::type_info &type() const
|
||||
{
|
||||
return m_type;
|
||||
}
|
||||
|
||||
virtual std::unique_ptr<Data> clone() const = 0;
|
||||
const std::type_info &m_type;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct Data_Impl : Data
|
||||
{
|
||||
explicit Data_Impl(T t_type)
|
||||
: Data(typeid(T)),
|
||||
m_data(std::move(t_type))
|
||||
: m_data(std::move(t_type))
|
||||
{
|
||||
}
|
||||
|
||||
@@ -90,19 +79,21 @@ namespace chaiscript {
|
||||
};
|
||||
|
||||
std::unique_ptr<Data> m_data;
|
||||
mutable std::array<uint8_t, 15> m_smallSize;
|
||||
bool m_isSmall = false;
|
||||
const std::type_info *m_type = &typeid(void);
|
||||
|
||||
public:
|
||||
// construct/copy/destruct
|
||||
Any() = default;
|
||||
|
||||
Any(const Any &t_any)
|
||||
{
|
||||
if (!t_any.empty())
|
||||
{
|
||||
m_data = t_any.m_data->clone();
|
||||
} else {
|
||||
m_data.reset();
|
||||
}
|
||||
: m_data(t_any.m_data?t_any.m_data->clone():nullptr),
|
||||
m_smallSize(t_any.m_smallSize),
|
||||
m_isSmall(t_any.m_isSmall),
|
||||
m_type(t_any.m_type)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#if _MSC_VER != 1800
|
||||
@@ -111,13 +102,31 @@ namespace chaiscript {
|
||||
#endif
|
||||
|
||||
template<typename ValueType,
|
||||
typename = typename std::enable_if<!std::is_same<Any, typename std::decay<ValueType>::type>::value>::type>
|
||||
typename = typename std::enable_if<!std::is_same<Any, typename std::decay<ValueType>::type>::value>::type,
|
||||
typename = typename std::enable_if< std::is_trivial<typename std::decay<ValueType>::type>::value>::type,
|
||||
typename = typename std::enable_if<sizeof(typename std::decay<ValueType>::type) <= sizeof(decltype(m_smallSize)) >::type>
|
||||
explicit Any(ValueType &&t_value)
|
||||
: m_data(std::unique_ptr<Data>(new Data_Impl<typename std::decay<ValueType>::type>(std::forward<ValueType>(t_value))))
|
||||
: m_isSmall(true), m_type(&typeid(typename std::decay<ValueType>::type))
|
||||
{
|
||||
m_smallSize.fill(0);
|
||||
*(static_cast<typename std::decay<ValueType>::type *>(static_cast<void *>(m_smallSize.data()))) = t_value;
|
||||
// std::cout << "Setting type: " << typeid(typename std::decay<ValueType>::type).name() << " " << t_value << " actual val: " << *(static_cast<typename std::decay<ValueType>::type *>(static_cast<void *>(m_smallSize.data()))) << " cast: " << cast<typename std::decay<ValueType>::type>() << "\n";
|
||||
}
|
||||
|
||||
template<typename ValueType,
|
||||
typename = typename std::enable_if<!std::is_same<Any, typename std::decay<ValueType>::type>::value>::type,
|
||||
typename = typename std::enable_if<
|
||||
!std::is_trivial<typename std::decay<ValueType>::type>::value
|
||||
|| !(sizeof(typename std::decay<ValueType>::type) <= sizeof(decltype(m_smallSize))) >::type>
|
||||
explicit Any(ValueType &&t_value)
|
||||
: m_data(std::unique_ptr<Data>(new Data_Impl<typename std::decay<ValueType>::type>(std::forward<ValueType>(t_value)))),
|
||||
m_isSmall(false),
|
||||
m_type(&typeid(typename std::decay<ValueType>::type))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
|
||||
Any & operator=(const Any &t_any)
|
||||
{
|
||||
Any copy(t_any);
|
||||
@@ -128,14 +137,20 @@ namespace chaiscript {
|
||||
template<typename ToType>
|
||||
ToType &cast() const
|
||||
{
|
||||
if (m_data && typeid(ToType) == m_data->type())
|
||||
if (m_isSmall && typeid(ToType) == *m_type)
|
||||
{
|
||||
return *static_cast<ToType *>(static_cast<void *>(m_smallSize.data()));
|
||||
} else if (!m_isSmall && m_data && typeid(ToType) == *m_type) {
|
||||
return *static_cast<ToType *>(m_data->data());
|
||||
} else {
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
}
|
||||
|
||||
const std::type_info &type() const
|
||||
{
|
||||
return *m_type;
|
||||
}
|
||||
|
||||
~Any()
|
||||
{
|
||||
@@ -144,25 +159,31 @@ namespace chaiscript {
|
||||
// modifiers
|
||||
Any & swap(Any &t_other)
|
||||
{
|
||||
std::swap(t_other.m_smallSize, m_smallSize);
|
||||
std::swap(t_other.m_isSmall, m_isSmall);
|
||||
std::swap(t_other.m_data, m_data);
|
||||
std::swap(t_other.m_type, m_type);
|
||||
return *this;
|
||||
}
|
||||
|
||||
// queries
|
||||
bool empty() const
|
||||
{
|
||||
return !bool(m_data);
|
||||
return !bool(m_data) && !m_isSmall;
|
||||
}
|
||||
|
||||
const std::type_info & type() const
|
||||
void *data() const
|
||||
{
|
||||
if (m_data)
|
||||
if (m_isSmall)
|
||||
{
|
||||
return m_data->type();
|
||||
return static_cast<void *>(m_smallSize.data());
|
||||
} else if (m_data) {
|
||||
return m_data->data();
|
||||
} else {
|
||||
return typeid(void);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
@@ -10,7 +10,6 @@
|
||||
#include <string>
|
||||
#include <typeinfo>
|
||||
|
||||
#include "../chaiscript_defines.hpp"
|
||||
#include "type_info.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
@@ -29,14 +28,14 @@ namespace chaiscript
|
||||
class bad_boxed_cast : public std::bad_cast
|
||||
{
|
||||
public:
|
||||
bad_boxed_cast(Type_Info t_from, const std::type_info &t_to,
|
||||
bad_boxed_cast(const Type_Info &t_from, const std::type_info &t_to,
|
||||
std::string t_what) CHAISCRIPT_NOEXCEPT
|
||||
: from(std::move(t_from)), to(&t_to), m_what(std::move(t_what))
|
||||
: from(t_from), to(&t_to), m_what(std::move(t_what))
|
||||
{
|
||||
}
|
||||
|
||||
bad_boxed_cast(Type_Info t_from, const std::type_info &t_to)
|
||||
: from(std::move(t_from)), to(&t_to), m_what("Cannot perform boxed_cast")
|
||||
bad_boxed_cast(const Type_Info &t_from, const std::type_info &t_to) CHAISCRIPT_NOEXCEPT
|
||||
: from(t_from), to(&t_to), m_what("Cannot perform boxed_cast")
|
||||
{
|
||||
}
|
||||
|
||||
|
@@ -18,16 +18,16 @@ namespace chaiscript
|
||||
{
|
||||
static std::tuple<decltype(std::placeholders::_1),decltype(std::placeholders::_2),decltype(std::placeholders::_3),decltype(std::placeholders::_4),decltype(std::placeholders::_5),decltype(std::placeholders::_6),decltype(std::placeholders::_7),decltype(std::placeholders::_8),decltype(std::placeholders::_9),decltype(std::placeholders::_10)> placeholder() {
|
||||
return std::tuple<decltype(std::placeholders::_1),decltype(std::placeholders::_2),decltype(std::placeholders::_3),decltype(std::placeholders::_4),decltype(std::placeholders::_5),decltype(std::placeholders::_6),decltype(std::placeholders::_7),decltype(std::placeholders::_8),decltype(std::placeholders::_9),decltype(std::placeholders::_10)>(std::placeholders::_1,std::placeholders::_2,std::placeholders::_3,std::placeholders::_4,std::placeholders::_5,std::placeholders::_6,std::placeholders::_7,std::placeholders::_8,std::placeholders::_9,std::placeholders::_10);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
template<int count, int maxcount, typename Sig>
|
||||
struct Bind_First
|
||||
{
|
||||
template<typename F, typename ... InnerParams>
|
||||
static std::function<Sig> bind(F&& f, InnerParams ... innerparams)
|
||||
static std::function<Sig> bind(F f, InnerParams ... innerparams)
|
||||
{
|
||||
return Bind_First<count - 1, maxcount, Sig>::bind(std::forward<F>(f), innerparams..., std::get<maxcount - count>(Placeholder::placeholder()));
|
||||
return Bind_First<count - 1, maxcount, Sig>::bind(f, innerparams..., std::get<maxcount - count>(Placeholder::placeholder()));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -35,42 +35,37 @@ namespace chaiscript
|
||||
struct Bind_First<0, maxcount, Sig>
|
||||
{
|
||||
template<typename F, typename ... InnerParams>
|
||||
static std::function<Sig> bind(F&& f, InnerParams ... innerparams)
|
||||
static std::function<Sig> bind(F f, InnerParams ... innerparams)
|
||||
{
|
||||
return std::bind(std::forward<F>(f), innerparams...);
|
||||
return std::bind(f, innerparams...);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename O, typename Ret, typename P1, typename ... Param>
|
||||
std::function<Ret (Param...)> bind_first(Ret (*f)(P1, Param...), O&& o)
|
||||
std::function<Ret (Param...)> bind_first(Ret (*f)(P1, Param...), O o)
|
||||
{
|
||||
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(f, std::forward<O>(o));
|
||||
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(f, o);
|
||||
}
|
||||
|
||||
template<typename O, typename Ret, typename Class, typename ... Param>
|
||||
std::function<Ret (Param...)> bind_first(Ret (Class::*f)(Param...), O&& o)
|
||||
std::function<Ret (Param...)> bind_first(Ret (Class::*f)(Param...), O o)
|
||||
{
|
||||
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(f, std::forward<O>(o));
|
||||
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(f, o);
|
||||
}
|
||||
|
||||
template<typename O, typename Ret, typename Class, typename ... Param>
|
||||
std::function<Ret (Param...)> bind_first(Ret (Class::*f)(Param...) const, O&& o)
|
||||
std::function<Ret (Param...)> bind_first(Ret (Class::*f)(Param...) const, O o)
|
||||
{
|
||||
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(f, std::forward<O>(o));
|
||||
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(f, o);
|
||||
}
|
||||
|
||||
template<typename O, typename Ret, typename P1, typename ... Param>
|
||||
std::function<Ret (Param...)> bind_first(const std::function<Ret (P1, Param...)> &f, O&& o)
|
||||
std::function<Ret (Param...)> bind_first(const std::function<Ret (P1, Param...)> &f, O o)
|
||||
{
|
||||
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(f, std::forward<O>(o));
|
||||
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(f, o);
|
||||
}
|
||||
|
||||
template<typename O, typename Ret, typename P1, typename ... Param>
|
||||
std::function<Ret (Param...)> bind_first(std::function<Ret (P1, Param...)> &&f, O&& o)
|
||||
{
|
||||
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(std::move(f), std::forward<O>(o));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@@ -24,7 +24,7 @@
|
||||
#include "boxed_number.hpp"
|
||||
#include "boxed_value.hpp"
|
||||
#include "dispatchkit.hpp"
|
||||
#include "type_conversions.hpp"
|
||||
#include "dynamic_cast_conversion.hpp"
|
||||
#include "dynamic_object.hpp"
|
||||
#include "operators.hpp"
|
||||
#include "proxy_constructors.hpp"
|
||||
@@ -156,7 +156,9 @@ namespace chaiscript
|
||||
return p;
|
||||
}
|
||||
|
||||
/// Specific version of shared_ptr_clone just for Proxy_Functions
|
||||
/**
|
||||
* 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)
|
||||
@@ -166,9 +168,11 @@ namespace chaiscript
|
||||
|
||||
|
||||
|
||||
/// Assignment function for shared_ptr objects, does not perform a copy of the
|
||||
/// object pointed to, instead maintains the shared_ptr concept.
|
||||
/// Similar to shared_ptr_clone. Used for Proxy_Function.
|
||||
/**
|
||||
* Assignment function for shared_ptr objects, does not perform a copy of the
|
||||
* object pointed to, instead maintains the shared_ptr concept.
|
||||
* Similar to shared_ptr_clone. Used for Proxy_Function.
|
||||
*/
|
||||
template<typename Type>
|
||||
Boxed_Value ptr_assign(Boxed_Value lhs, const std::shared_ptr<Type> &rhs)
|
||||
{
|
||||
@@ -182,8 +186,10 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
/// Class consisting of only static functions. All default bootstrapping occurs
|
||||
/// from this class.
|
||||
/**
|
||||
* Class consisting of only static functions. All default bootstrapping occurs
|
||||
* from this class.
|
||||
*/
|
||||
class Bootstrap
|
||||
{
|
||||
private:
|
||||
@@ -202,16 +208,18 @@ namespace chaiscript
|
||||
|
||||
static void print(const std::string &s)
|
||||
{
|
||||
fwrite(s.c_str(), 1, s.size(), stdout);
|
||||
std::cout << s;
|
||||
}
|
||||
|
||||
static void println(const std::string &s)
|
||||
{
|
||||
puts(s.c_str());
|
||||
std::cout << s << std::endl;
|
||||
}
|
||||
|
||||
|
||||
/// Add all arithmetic operators for PODs
|
||||
/**
|
||||
* Add all arithmetic operators for PODs
|
||||
*/
|
||||
static void opers_arithmetic_pod(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&Boxed_Number::equals), "==");
|
||||
@@ -251,8 +259,11 @@ 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
|
||||
/**
|
||||
* 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> ¶ms)
|
||||
{
|
||||
if (params.size() < 2)
|
||||
@@ -262,7 +273,7 @@ namespace chaiscript
|
||||
|
||||
Const_Proxy_Function f = boxed_cast<Const_Proxy_Function>(params[0]);
|
||||
|
||||
return Boxed_Value(Const_Proxy_Function(std::make_shared<dispatch::Bound_Function>(f,
|
||||
return Boxed_Value(Const_Proxy_Function(new dispatch::Bound_Function(f,
|
||||
std::vector<Boxed_Value>(params.begin() + 1, params.end()))));
|
||||
}
|
||||
|
||||
@@ -307,7 +318,9 @@ namespace chaiscript
|
||||
return e.what();
|
||||
}
|
||||
|
||||
/// Boolean specialization of internal to_string function
|
||||
/**
|
||||
* Boolean specialization of internal to_string function
|
||||
*/
|
||||
static std::string bool_to_string(bool b)
|
||||
{
|
||||
if (b)
|
||||
@@ -337,7 +350,9 @@ namespace chaiscript
|
||||
|
||||
static bool has_parse_tree(const chaiscript::Const_Proxy_Function &t_pf)
|
||||
{
|
||||
if (auto pf = std::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf))
|
||||
std::shared_ptr<const chaiscript::dispatch::Dynamic_Proxy_Function> pf
|
||||
= std::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf);
|
||||
if (pf)
|
||||
{
|
||||
if (pf->get_parse_tree())
|
||||
{
|
||||
@@ -352,7 +367,9 @@ namespace chaiscript
|
||||
|
||||
static chaiscript::AST_NodePtr get_parse_tree(const chaiscript::Const_Proxy_Function &t_pf)
|
||||
{
|
||||
if (auto pf = std::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf))
|
||||
std::shared_ptr<const chaiscript::dispatch::Dynamic_Proxy_Function> pf
|
||||
= std::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf);
|
||||
if (pf)
|
||||
{
|
||||
if (pf->get_parse_tree())
|
||||
{
|
||||
@@ -443,7 +460,7 @@ namespace chaiscript
|
||||
operators::assign<bool>(m);
|
||||
operators::equal<bool>(m);
|
||||
|
||||
m->add(fun<std::string (const std::string &t_ss)>([](const std::string &s) -> std::string { return s; }), "to_string");
|
||||
m->add(fun(&to_string<const std::string &>), "to_string");
|
||||
m->add(fun(&Bootstrap::bool_to_string), "to_string");
|
||||
m->add(fun(&unknown_assign), "=");
|
||||
m->add(fun(&throw_exception), "throw");
|
||||
|
@@ -278,9 +278,9 @@ namespace chaiscript
|
||||
template<typename ContainerType>
|
||||
ModulePtr container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun<size_t (const ContainerType *)>([](const ContainerType *a) { return a->size(); } ), "size");
|
||||
m->add(fun<bool (const ContainerType *)>([](const ContainerType *a) { return a->empty(); } ), "empty");
|
||||
m->add(fun<void (ContainerType *)>([](ContainerType *a) { a->clear(); } ), "clear");
|
||||
m->add(fun( std::function<size_t (const ContainerType *)>( [](const ContainerType *a) { return a->size(); } ) ), "size");
|
||||
m->add(fun( std::function<bool (const ContainerType *)>( [](const ContainerType *a) { return a->empty(); } ) ), "empty");
|
||||
m->add(fun( std::function<void (ContainerType *)>( [](ContainerType *a) { a->clear(); } ) ), "clear");
|
||||
return m;
|
||||
}
|
||||
|
||||
@@ -493,26 +493,24 @@ namespace chaiscript
|
||||
|
||||
if (typeid(VectorType) == typeid(std::vector<Boxed_Value>))
|
||||
{
|
||||
m->eval(R"(
|
||||
def Vector::`==`(rhs) : type_match(rhs, this) {
|
||||
if ( rhs.size() != this.size() ) {
|
||||
return false;
|
||||
} else {
|
||||
auto r1 = range(this);
|
||||
auto r2 = range(rhs);
|
||||
while (!r1.empty())
|
||||
{
|
||||
if (!eq(r1.front(), r2.front()))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
r1.pop_front();
|
||||
r2.pop_front();
|
||||
}
|
||||
true;
|
||||
}
|
||||
} )"
|
||||
);
|
||||
m->eval("def Vector::`==`(rhs) : type_match(rhs, this) { \
|
||||
if ( rhs.size() != this.size() ) { \
|
||||
return false; \
|
||||
} else { \
|
||||
auto r1 = range(this); \
|
||||
auto r2 = range(rhs); \
|
||||
while (!r1.empty()) \
|
||||
{ \
|
||||
if (!eq(r1.front(), r2.front())) \
|
||||
{ \
|
||||
return false; \
|
||||
} \
|
||||
r1.pop_front(); \
|
||||
r2.pop_front(); \
|
||||
} \
|
||||
return true; \
|
||||
} \
|
||||
}");
|
||||
}
|
||||
|
||||
return m;
|
||||
|
@@ -14,11 +14,11 @@
|
||||
#include "bad_boxed_cast.hpp"
|
||||
#include "boxed_cast_helper.hpp"
|
||||
#include "boxed_value.hpp"
|
||||
#include "type_conversions.hpp"
|
||||
#include "dynamic_cast_conversion.hpp"
|
||||
#include "type_info.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
class Type_Conversions;
|
||||
class Dynamic_Cast_Conversions;
|
||||
namespace detail {
|
||||
namespace exception {
|
||||
class bad_any_cast;
|
||||
@@ -72,7 +72,7 @@ namespace chaiscript
|
||||
/// assert(i == 5);
|
||||
/// \endcode
|
||||
template<typename Type>
|
||||
typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv, const Type_Conversions *t_conversions = nullptr)
|
||||
typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv, const Dynamic_Cast_Conversions *t_conversions = nullptr)
|
||||
{
|
||||
try {
|
||||
return detail::Cast_Helper<Type>::cast(bv, t_conversions);
|
||||
@@ -86,18 +86,18 @@ namespace chaiscript
|
||||
#pragma warning(disable : 4127)
|
||||
#endif
|
||||
|
||||
if (t_conversions && t_conversions->convertable_type<Type>())
|
||||
if (std::is_polymorphic<typename detail::Bare_Type<Type>::type>::value && t_conversions)
|
||||
{
|
||||
try {
|
||||
// std::cout << "trying an up conversion " << typeid(Type).name() << '\n';
|
||||
// std::cout << "trying an up conversion " << typeid(Type).name() << std::endl;
|
||||
// We will not catch any bad_boxed_dynamic_cast that is thrown, let the user get it
|
||||
// either way, we are not responsible if it doesn't work
|
||||
return detail::Cast_Helper<Type>::cast(t_conversions->boxed_type_conversion<Type>(bv), t_conversions);
|
||||
return detail::Cast_Helper<Type>::cast(t_conversions->boxed_dynamic_cast<Type>(bv), t_conversions);
|
||||
} catch (...) {
|
||||
try {
|
||||
// std::cout << "trying a down conversion " << typeid(Type).name() << '\n';
|
||||
// std::cout << "trying a down conversion " << typeid(Type).name() << std::endl;
|
||||
// try going the other way - down the inheritance graph
|
||||
return detail::Cast_Helper<Type>::cast(t_conversions->boxed_type_down_conversion<Type>(bv), t_conversions);
|
||||
return detail::Cast_Helper<Type>::cast(t_conversions->boxed_dynamic_down_cast<Type>(bv), t_conversions);
|
||||
} catch (const chaiscript::detail::exception::bad_any_cast &) {
|
||||
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
|
||||
}
|
||||
|
@@ -17,7 +17,7 @@
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
class Type_Conversions;
|
||||
class Dynamic_Cast_Conversions;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
@@ -36,7 +36,7 @@ namespace chaiscript
|
||||
{
|
||||
typedef typename std::reference_wrapper<typename std::add_const<Result>::type > Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
|
||||
{
|
||||
if (ob.get_type_info().bare_equal_type_info(typeid(Result)))
|
||||
{
|
||||
@@ -63,7 +63,7 @@ namespace chaiscript
|
||||
struct Cast_Helper_Inner<const Result *>
|
||||
{
|
||||
typedef const Result * Result_Type;
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
|
||||
{
|
||||
if (ob.is_ref())
|
||||
{
|
||||
@@ -89,7 +89,7 @@ namespace chaiscript
|
||||
struct Cast_Helper_Inner<Result *>
|
||||
{
|
||||
typedef Result * Result_Type;
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
|
||||
{
|
||||
if (ob.is_ref())
|
||||
{
|
||||
@@ -107,7 +107,7 @@ namespace chaiscript
|
||||
{
|
||||
typedef Result& Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
|
||||
{
|
||||
if (!ob.get_type_info().is_const() && ob.get_type_info().bare_equal_type_info(typeid(Result)))
|
||||
{
|
||||
@@ -124,7 +124,7 @@ namespace chaiscript
|
||||
{
|
||||
typedef typename std::shared_ptr<Result> Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
|
||||
{
|
||||
return ob.get().cast<std::shared_ptr<Result> >();
|
||||
}
|
||||
@@ -136,7 +136,7 @@ namespace chaiscript
|
||||
{
|
||||
typedef typename std::shared_ptr<const Result> Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
|
||||
{
|
||||
if (!ob.get_type_info().is_const())
|
||||
{
|
||||
@@ -178,7 +178,7 @@ namespace chaiscript
|
||||
{
|
||||
typedef const Boxed_Value & Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
|
||||
{
|
||||
return ob;
|
||||
}
|
||||
@@ -190,7 +190,7 @@ namespace chaiscript
|
||||
{
|
||||
typedef Boxed_Value& Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
|
||||
{
|
||||
return const_cast<Boxed_Value &>(ob);
|
||||
}
|
||||
@@ -246,7 +246,7 @@ namespace chaiscript
|
||||
{
|
||||
typedef typename Cast_Helper_Inner<T>::Result_Type Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *t_conversions)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *t_conversions)
|
||||
{
|
||||
return Cast_Helper_Inner<T>::cast(ob, t_conversions);
|
||||
}
|
||||
|
@@ -19,7 +19,7 @@
|
||||
#include "type_info.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
class Type_Conversions;
|
||||
class Dynamic_Cast_Conversions;
|
||||
} // namespace chaiscript
|
||||
|
||||
namespace chaiscript
|
||||
@@ -826,25 +826,31 @@ namespace chaiscript
|
||||
|
||||
namespace detail
|
||||
{
|
||||
/// Cast_Helper for converting from Boxed_Value to Boxed_Number
|
||||
/**
|
||||
* Cast_Helper for converting from Boxed_Value to Boxed_Number
|
||||
*/
|
||||
template<>
|
||||
struct Cast_Helper<Boxed_Number>
|
||||
{
|
||||
typedef Boxed_Number Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
|
||||
{
|
||||
return Boxed_Number(ob);
|
||||
}
|
||||
};
|
||||
|
||||
/// Cast_Helper for converting from Boxed_Value to Boxed_Number
|
||||
/**
|
||||
* Cast_Helper for converting from Boxed_Value to Boxed_Number
|
||||
*/
|
||||
template<>
|
||||
struct Cast_Helper<const Boxed_Number &> : Cast_Helper<Boxed_Number>
|
||||
{
|
||||
};
|
||||
|
||||
/// Cast_Helper for converting from Boxed_Value to Boxed_Number
|
||||
/**
|
||||
* Cast_Helper for converting from Boxed_Value to Boxed_Number
|
||||
*/
|
||||
template<>
|
||||
struct Cast_Helper<const Boxed_Number> : Cast_Helper<Boxed_Number>
|
||||
{
|
||||
|
@@ -13,7 +13,6 @@
|
||||
#include <type_traits>
|
||||
|
||||
#include "../chaiscript_threading.hpp"
|
||||
#include "../chaiscript_defines.hpp"
|
||||
#include "any.hpp"
|
||||
#include "type_info.hpp"
|
||||
|
||||
@@ -67,7 +66,6 @@ namespace chaiscript
|
||||
Data &operator=(Data &&rhs) = default;
|
||||
#endif
|
||||
|
||||
|
||||
Type_Info m_type_info;
|
||||
chaiscript::detail::Any m_obj;
|
||||
void *m_data_ptr;
|
||||
@@ -78,7 +76,7 @@ namespace chaiscript
|
||||
|
||||
struct Object_Data
|
||||
{
|
||||
static std::shared_ptr<Data> get(Boxed_Value::Void_Type)
|
||||
static std::shared_ptr<Data> get(Boxed_Value::Void_Type, bool, bool)
|
||||
{
|
||||
return std::make_shared<Data>(
|
||||
detail::Get_Type_Info<void>::get(),
|
||||
@@ -89,13 +87,13 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::shared_ptr<Data> get(const std::shared_ptr<T> *obj)
|
||||
static std::shared_ptr<Data> get(const std::shared_ptr<T> *obj, bool, bool)
|
||||
{
|
||||
return get(*obj);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::shared_ptr<Data> get(const std::shared_ptr<T> &obj)
|
||||
static std::shared_ptr<Data> get(const std::shared_ptr<T> &obj, bool, bool)
|
||||
{
|
||||
return std::make_shared<Data>(
|
||||
detail::Get_Type_Info<T>::get(),
|
||||
@@ -106,7 +104,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::shared_ptr<Data> get(std::shared_ptr<T> &&obj)
|
||||
static std::shared_ptr<Data> get(std::shared_ptr<T> &&obj, bool, bool)
|
||||
{
|
||||
auto ptr = obj.get();
|
||||
return std::make_shared<Data>(
|
||||
@@ -124,14 +122,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::shared_ptr<Data> get(const T *t)
|
||||
{
|
||||
return get(std::cref(*t));
|
||||
}
|
||||
|
||||
|
||||
template<typename T>
|
||||
static std::shared_ptr<Data> get(std::reference_wrapper<T> obj)
|
||||
static std::shared_ptr<Data> get(std::reference_wrapper<T> obj, bool, bool)
|
||||
{
|
||||
auto p = &obj.get();
|
||||
return std::make_shared<Data>(
|
||||
@@ -143,22 +134,57 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::shared_ptr<Data> get(T t)
|
||||
static std::shared_ptr<Data> get(T t, bool t_value_type, bool t_make_const)
|
||||
{
|
||||
auto p = std::make_shared<T>(std::move(t));
|
||||
auto ptr = p.get();
|
||||
return std::make_shared<Data>(
|
||||
detail::Get_Type_Info<T>::get(),
|
||||
chaiscript::detail::Any(std::move(p)),
|
||||
false,
|
||||
ptr
|
||||
);
|
||||
typedef typename std::add_const<T>::type const_type;
|
||||
if (t_make_const)
|
||||
{
|
||||
if (t_value_type)
|
||||
{
|
||||
chaiscript::detail::Any a(std::move(t));
|
||||
return std::make_shared<Data>(
|
||||
detail::Get_Type_Info<const_type>::get(),
|
||||
std::move(a),
|
||||
false,
|
||||
nullptr
|
||||
);
|
||||
} else {
|
||||
auto p = std::make_shared<const_type>(std::move(t));
|
||||
auto ptr = p.get();
|
||||
return std::make_shared<Data>(
|
||||
detail::Get_Type_Info<const_type>::get(),
|
||||
chaiscript::detail::Any(std::move(p)),
|
||||
false,
|
||||
ptr
|
||||
);
|
||||
}
|
||||
} else {
|
||||
if (t_value_type)
|
||||
{
|
||||
chaiscript::detail::Any a(std::move(t));
|
||||
return std::make_shared<Data>(
|
||||
detail::Get_Type_Info<T>::get(),
|
||||
std::move(a),
|
||||
false,
|
||||
nullptr
|
||||
);
|
||||
} else {
|
||||
auto p = std::make_shared<T>(std::move(t));
|
||||
auto ptr = p.get();
|
||||
return std::make_shared<Data>(
|
||||
detail::Get_Type_Info<T>::get(),
|
||||
chaiscript::detail::Any(std::move(p)),
|
||||
false,
|
||||
ptr
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static std::shared_ptr<Data> get()
|
||||
{
|
||||
return std::make_shared<Data>(
|
||||
Type_Info(),
|
||||
Type_Info(),
|
||||
chaiscript::detail::Any(),
|
||||
false,
|
||||
nullptr
|
||||
@@ -171,9 +197,10 @@ namespace chaiscript
|
||||
/// Basic Boxed_Value constructor
|
||||
template<typename T,
|
||||
typename = typename std::enable_if<!std::is_same<Boxed_Value, typename std::decay<T>::type>::value>::type>
|
||||
explicit Boxed_Value(T &&t)
|
||||
: m_data(Object_Data::get(std::forward<T>(t)))
|
||||
explicit Boxed_Value(T &&t, bool t_make_const=false, bool t_value_type = std::is_trivial<typename std::decay<T>::type>::value)
|
||||
: m_data(Object_Data::get(std::forward<T>(t), t_make_const, t_value_type))
|
||||
{
|
||||
//std::cout << "typeid: " << typeid(T).name() << " is trivial " << std::is_trivial<typename std::decay<T>::type>::value << "\n";
|
||||
}
|
||||
|
||||
/// Unknown-type constructor
|
||||
@@ -246,12 +273,22 @@ namespace chaiscript
|
||||
|
||||
void *get_ptr() const CHAISCRIPT_NOEXCEPT
|
||||
{
|
||||
return m_data->m_data_ptr;
|
||||
if (m_data->m_data_ptr)
|
||||
{
|
||||
return m_data->m_data_ptr;
|
||||
} else {
|
||||
return m_data->m_obj.data();
|
||||
}
|
||||
}
|
||||
|
||||
const void *get_const_ptr() const CHAISCRIPT_NOEXCEPT
|
||||
{
|
||||
return m_data->m_const_data_ptr;
|
||||
if (m_data->m_const_data_ptr)
|
||||
{
|
||||
return m_data->m_const_data_ptr;
|
||||
} else {
|
||||
return m_data->m_obj.data();
|
||||
}
|
||||
}
|
||||
|
||||
Boxed_Value get_attr(const std::string &t_name)
|
||||
@@ -312,7 +349,7 @@ namespace chaiscript
|
||||
template<typename T>
|
||||
Boxed_Value const_var_impl(const T &t)
|
||||
{
|
||||
return Boxed_Value(std::make_shared<typename std::add_const<T>::type >(t));
|
||||
return Boxed_Value(std::make_shared<typename std::add_const<T>::type >(t), true);
|
||||
}
|
||||
|
||||
/// \brief Takes a pointer to a value, adds const to the pointed to type and returns an immutable Boxed_Value.
|
||||
|
@@ -27,7 +27,7 @@
|
||||
#include "boxed_cast.hpp"
|
||||
#include "boxed_cast_helper.hpp"
|
||||
#include "boxed_value.hpp"
|
||||
#include "type_conversions.hpp"
|
||||
#include "dynamic_cast_conversion.hpp"
|
||||
#include "dynamic_object.hpp"
|
||||
#include "proxy_constructors.hpp"
|
||||
#include "proxy_functions.hpp"
|
||||
@@ -141,7 +141,7 @@ namespace chaiscript
|
||||
return *this;
|
||||
}
|
||||
|
||||
Module &add(Type_Conversion d)
|
||||
Module &add(Dynamic_Cast_Conversion d)
|
||||
{
|
||||
m_conversions.push_back(std::move(d));
|
||||
return *this;
|
||||
@@ -157,7 +157,7 @@ namespace chaiscript
|
||||
{
|
||||
if (!t_bv.is_const())
|
||||
{
|
||||
throw chaiscript::exception::global_non_const();
|
||||
// throw chaiscript::exception::global_non_const();
|
||||
}
|
||||
|
||||
m_globals.emplace_back(std::move(t_bv), std::move(t_name));
|
||||
@@ -166,9 +166,9 @@ namespace chaiscript
|
||||
|
||||
|
||||
//Add a bit of ChaiScript to eval during module implementation
|
||||
Module &eval(const std::string &str)
|
||||
Module &eval(std::string str)
|
||||
{
|
||||
m_evals.push_back(str);
|
||||
m_evals.push_back(std::move(str));
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -197,7 +197,7 @@ namespace chaiscript
|
||||
std::vector<std::pair<Proxy_Function, std::string> > m_funcs;
|
||||
std::vector<std::pair<Boxed_Value, std::string> > m_globals;
|
||||
std::vector<std::string> m_evals;
|
||||
std::vector<Type_Conversion> m_conversions;
|
||||
std::vector<Dynamic_Cast_Conversion> m_conversions;
|
||||
|
||||
template<typename T, typename InItr>
|
||||
static void apply(InItr begin, const InItr end, T &t)
|
||||
@@ -257,7 +257,7 @@ namespace chaiscript
|
||||
{
|
||||
public:
|
||||
Dispatch_Function(std::vector<Proxy_Function> t_funcs)
|
||||
: Proxy_Function_Base(build_type_infos(t_funcs), calculate_arity(t_funcs)),
|
||||
: Proxy_Function_Base(build_type_infos(t_funcs)),
|
||||
m_funcs(std::move(t_funcs))
|
||||
{
|
||||
}
|
||||
@@ -265,7 +265,7 @@ namespace chaiscript
|
||||
virtual bool operator==(const dispatch::Proxy_Function_Base &rhs) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
try {
|
||||
const auto &dispatchfun = dynamic_cast<const Dispatch_Function &>(rhs);
|
||||
const Dispatch_Function &dispatchfun = dynamic_cast<const Dispatch_Function &>(rhs);
|
||||
return m_funcs == dispatchfun.m_funcs;
|
||||
} catch (const std::bad_cast &) {
|
||||
return false;
|
||||
@@ -280,15 +280,15 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
|
||||
static int calculate_arity(const std::vector<Proxy_Function> &t_funcs)
|
||||
virtual int get_arity() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
if (t_funcs.empty()) {
|
||||
if (m_funcs.empty()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
const auto arity = t_funcs.front()->get_arity();
|
||||
const int arity = m_funcs.front()->get_arity();
|
||||
|
||||
for (const auto &func : t_funcs)
|
||||
for (const auto &func : m_funcs)
|
||||
{
|
||||
if (arity != func->get_arity())
|
||||
{
|
||||
@@ -300,10 +300,17 @@ namespace chaiscript
|
||||
return arity;
|
||||
}
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return std::any_of(m_funcs.cbegin(), m_funcs.cend(),
|
||||
[&vals, &t_conversions](const Proxy_Function &f){ return f->call_match(vals, t_conversions); });
|
||||
for (const auto &func : m_funcs)
|
||||
{
|
||||
if (func->call_match(vals, t_conversions))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
|
||||
@@ -312,9 +319,9 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return dispatch::dispatch(m_funcs, params, t_conversions);
|
||||
return dispatch::dispatch(m_funcs.begin(), m_funcs.end(), params, t_conversions);
|
||||
}
|
||||
|
||||
private:
|
||||
@@ -322,8 +329,10 @@ namespace chaiscript
|
||||
|
||||
static std::vector<Type_Info> build_type_infos(const std::vector<Proxy_Function> &t_funcs)
|
||||
{
|
||||
auto begin = t_funcs.cbegin();
|
||||
const auto &end = t_funcs.cend();
|
||||
typedef std::vector<Proxy_Function> function_vec;
|
||||
|
||||
auto begin = t_funcs.begin();
|
||||
const function_vec::const_iterator end = t_funcs.end();
|
||||
|
||||
if (begin != end)
|
||||
{
|
||||
@@ -371,8 +380,10 @@ namespace chaiscript
|
||||
|
||||
namespace detail
|
||||
{
|
||||
/// Main class for the dispatchkit. Handles management
|
||||
/// of the object stack, functions and registered types.
|
||||
/**
|
||||
* Main class for the dispatchkit. Handles management
|
||||
* of the object stack, functions and registered types.
|
||||
*/
|
||||
class Dispatch_Engine
|
||||
{
|
||||
public:
|
||||
@@ -409,7 +420,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
/// Add a new conversion for upcasting to a base class
|
||||
void add(const Type_Conversion &d)
|
||||
void add(const Dynamic_Cast_Conversion &d)
|
||||
{
|
||||
m_conversions.add_conversion(d);
|
||||
}
|
||||
@@ -426,12 +437,12 @@ namespace chaiscript
|
||||
void add(const Boxed_Value &obj, const std::string &name)
|
||||
{
|
||||
validate_object_name(name);
|
||||
auto &stack = get_stack_data();
|
||||
StackData &stack = get_stack_data();
|
||||
|
||||
for (auto stack_elem = stack.rbegin(); stack_elem != stack.rend(); ++stack_elem)
|
||||
for (int i = static_cast<int>(stack.size())-1; i >= 0; --i)
|
||||
{
|
||||
auto itr = stack_elem->find(name);
|
||||
if (itr != stack_elem->end())
|
||||
const auto itr = stack[i].find(name);
|
||||
if (itr != stack[i].end())
|
||||
{
|
||||
itr->second = std::move(obj);
|
||||
return;
|
||||
@@ -443,13 +454,17 @@ 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
|
||||
void add_object(const std::string &name, const Boxed_Value &obj) const
|
||||
{
|
||||
if (!get_stack_data().back().insert(std::make_pair(name, obj)).second)
|
||||
StackData &stack = get_stack_data();
|
||||
validate_object_name(name);
|
||||
|
||||
const Scope &scope = stack.back();
|
||||
if (scope.find(name) != scope.end())
|
||||
{
|
||||
throw chaiscript::exception::name_conflict_error(name);
|
||||
} else {
|
||||
stack.back().insert(std::make_pair(name, std::move(obj)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -459,7 +474,7 @@ namespace chaiscript
|
||||
validate_object_name(name);
|
||||
if (!obj.is_const())
|
||||
{
|
||||
throw chaiscript::exception::global_non_const();
|
||||
// throw chaiscript::exception::global_non_const();
|
||||
}
|
||||
|
||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_global_object_mutex);
|
||||
@@ -493,13 +508,11 @@ namespace chaiscript
|
||||
void new_scope()
|
||||
{
|
||||
get_stack_data().emplace_back();
|
||||
m_stack_holder->call_params.emplace_back();
|
||||
}
|
||||
|
||||
/// Pops the current scope from the stack
|
||||
void pop_scope()
|
||||
{
|
||||
m_stack_holder->call_params.pop_back();
|
||||
StackData &stack = get_stack_data();
|
||||
if (stack.size() > 1)
|
||||
{
|
||||
@@ -533,13 +546,13 @@ namespace chaiscript
|
||||
return m_place_holder;
|
||||
}
|
||||
|
||||
auto &stack = get_stack_data();
|
||||
StackData &stack = get_stack_data();
|
||||
|
||||
// Is it in the stack?
|
||||
for (auto stack_elem = stack.rbegin(); stack_elem != stack.rend(); ++stack_elem)
|
||||
for (int i = static_cast<int>(stack.size())-1; i >= 0; --i)
|
||||
{
|
||||
const auto stackitr = stack_elem->find(name);
|
||||
if (stackitr != stack_elem->end())
|
||||
const auto stackitr = stack[i].find(name);
|
||||
if (stackitr != stack[i].end())
|
||||
{
|
||||
return stackitr->second;
|
||||
}
|
||||
@@ -659,7 +672,7 @@ namespace chaiscript
|
||||
/// the current scope.
|
||||
std::map<std::string, Boxed_Value> get_parent_locals() const
|
||||
{
|
||||
auto &stack = get_stack_data();
|
||||
StackData &stack = get_stack_data();
|
||||
if (stack.size() > 1)
|
||||
{
|
||||
return stack[1];
|
||||
@@ -671,8 +684,8 @@ namespace chaiscript
|
||||
/// \returns All values in the local thread state, added through the add() function
|
||||
std::map<std::string, Boxed_Value> get_locals() const
|
||||
{
|
||||
auto &stack = get_stack_data();
|
||||
auto &scope = stack.front();
|
||||
StackData &stack = get_stack_data();
|
||||
Scope &scope = stack.front();
|
||||
return scope;
|
||||
}
|
||||
|
||||
@@ -683,8 +696,8 @@ namespace chaiscript
|
||||
/// Any existing locals are removed and the given set of variables is added
|
||||
void set_locals(const std::map<std::string, Boxed_Value> &t_locals)
|
||||
{
|
||||
auto &stack = get_stack_data();
|
||||
auto &scope = stack.front();
|
||||
StackData &stack = get_stack_data();
|
||||
Scope &scope = stack.front();
|
||||
scope = t_locals;
|
||||
}
|
||||
|
||||
@@ -766,14 +779,16 @@ namespace chaiscript
|
||||
m_state.m_reserved_words.insert(name);
|
||||
}
|
||||
|
||||
const Type_Conversions &conversions() const
|
||||
const Dynamic_Cast_Conversions &conversions() const
|
||||
{
|
||||
return m_conversions;
|
||||
}
|
||||
|
||||
Boxed_Value call_function(const std::string &t_name, const std::vector<Boxed_Value> ¶ms) const
|
||||
{
|
||||
return dispatch::dispatch(get_function(t_name), params, m_conversions);
|
||||
std::vector<Proxy_Function> functions = get_function(t_name);
|
||||
|
||||
return dispatch::dispatch(functions.begin(), functions.end(), params, m_conversions);
|
||||
}
|
||||
|
||||
Boxed_Value call_function(const std::string &t_name) const
|
||||
@@ -794,7 +809,7 @@ namespace chaiscript
|
||||
/// Dump object info to stdout
|
||||
void dump_object(const Boxed_Value &o) const
|
||||
{
|
||||
std::cout << (o.is_const()?"const ":"") << type_name(o) << '\n';
|
||||
std::cout << (o.is_const()?"const ":"") << type_name(o) << std::endl;
|
||||
}
|
||||
|
||||
/// Dump type info to stdout
|
||||
@@ -828,14 +843,14 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << ") \n";
|
||||
std::cout << ") " << std::endl;
|
||||
}
|
||||
|
||||
/// 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> ¶ms)
|
||||
{
|
||||
if (params.empty())
|
||||
if (params.size() < 1)
|
||||
{
|
||||
throw chaiscript::exception::arity_error(static_cast<int>(params.size()), 1);
|
||||
}
|
||||
@@ -848,7 +863,7 @@ namespace chaiscript
|
||||
/// Dump all system info to stdout
|
||||
void dump_system() const
|
||||
{
|
||||
std::cout << "Registered Types: \n";
|
||||
std::cout << "Registered Types: " << std::endl;
|
||||
std::vector<std::pair<std::string, Type_Info> > types = get_types();
|
||||
for (std::vector<std::pair<std::string, Type_Info> >::const_iterator itr = types.begin();
|
||||
itr != types.end();
|
||||
@@ -856,20 +871,20 @@ namespace chaiscript
|
||||
{
|
||||
std::cout << itr->first << ": ";
|
||||
std::cout << itr->second.bare_name();
|
||||
std::cout << '\n';
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
std::cout << '\n';
|
||||
std::cout << std::endl;
|
||||
std::vector<std::pair<std::string, Proxy_Function > > funcs = get_functions();
|
||||
|
||||
std::cout << "Functions: \n";
|
||||
std::cout << "Functions: " << std::endl;
|
||||
for (std::vector<std::pair<std::string, Proxy_Function > >::const_iterator itr = funcs.begin();
|
||||
itr != funcs.end();
|
||||
++itr)
|
||||
{
|
||||
dump_function(*itr);
|
||||
}
|
||||
std::cout << '\n';
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
/// return true if the Boxed_Value matches the registered type by name
|
||||
@@ -913,39 +928,15 @@ namespace chaiscript
|
||||
m_state = t_state;
|
||||
}
|
||||
|
||||
void save_function_params(std::initializer_list<Boxed_Value> t_params)
|
||||
{
|
||||
Stack_Holder &s = *m_stack_holder;
|
||||
s.call_params.back().insert(s.call_params.back().begin(), std::move(t_params));
|
||||
}
|
||||
|
||||
void save_function_params(std::vector<Boxed_Value> &&t_params)
|
||||
{
|
||||
Stack_Holder &s = *m_stack_holder;
|
||||
|
||||
for (auto &¶m : t_params)
|
||||
{
|
||||
s.call_params.back().insert(s.call_params.back().begin(), std::move(param));
|
||||
}
|
||||
}
|
||||
|
||||
void save_function_params(const std::vector<Boxed_Value> &t_params)
|
||||
{
|
||||
Stack_Holder &s = *m_stack_holder;
|
||||
s.call_params.back().insert(s.call_params.back().begin(), t_params.begin(), t_params.end());
|
||||
s.call_params.insert(s.call_params.begin(), t_params.begin(), t_params.end());
|
||||
}
|
||||
|
||||
void new_function_call()
|
||||
{
|
||||
Stack_Holder &s = *m_stack_holder;
|
||||
if (s.call_depth == 0)
|
||||
{
|
||||
m_conversions.enable_conversion_saves(true);
|
||||
}
|
||||
|
||||
++s.call_depth;
|
||||
|
||||
save_function_params(m_conversions.take_saves());
|
||||
++m_stack_holder->call_depth;
|
||||
}
|
||||
|
||||
void pop_function_call()
|
||||
@@ -957,8 +948,9 @@ namespace chaiscript
|
||||
|
||||
if (s.call_depth == 0)
|
||||
{
|
||||
s.call_params.back().clear();
|
||||
m_conversions.enable_conversion_saves(false);
|
||||
/// \todo Critical: this needs to be smarter, memory can expand quickly
|
||||
/// in tight loops involving function calls
|
||||
s.call_params.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -992,17 +984,17 @@ namespace chaiscript
|
||||
|
||||
static bool function_less_than(const Proxy_Function &lhs, const Proxy_Function &rhs)
|
||||
{
|
||||
const auto &lhsparamtypes = lhs->get_param_types();
|
||||
const auto &rhsparamtypes = rhs->get_param_types();
|
||||
const std::vector<Type_Info> &lhsparamtypes = lhs->get_param_types();
|
||||
const std::vector<Type_Info> &rhsparamtypes = rhs->get_param_types();
|
||||
|
||||
const auto lhssize = lhsparamtypes.size();
|
||||
const auto rhssize = rhsparamtypes.size();
|
||||
const size_t lhssize = lhsparamtypes.size();
|
||||
const size_t rhssize = rhsparamtypes.size();
|
||||
|
||||
CHAISCRIPT_CONSTEXPR auto boxed_type = user_type<Boxed_Value>();
|
||||
CHAISCRIPT_CONSTEXPR auto boxed_pod_type = user_type<Boxed_Number>();
|
||||
const Type_Info boxed_type = user_type<Boxed_Value>();
|
||||
const Type_Info boxed_pod_type = user_type<Boxed_Number>();
|
||||
|
||||
auto dynamic_lhs(std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(lhs));
|
||||
auto dynamic_rhs(std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(rhs));
|
||||
std::shared_ptr<const dispatch::Dynamic_Proxy_Function> dynamic_lhs(std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(lhs));
|
||||
std::shared_ptr<const dispatch::Dynamic_Proxy_Function> dynamic_rhs(std::dynamic_pointer_cast<const dispatch::Dynamic_Proxy_Function>(rhs));
|
||||
|
||||
if (dynamic_lhs && dynamic_rhs)
|
||||
{
|
||||
@@ -1149,16 +1141,15 @@ namespace chaiscript
|
||||
: call_depth(0)
|
||||
{
|
||||
stacks.emplace_back(1);
|
||||
call_params.emplace_back();
|
||||
}
|
||||
|
||||
std::deque<StackData> stacks;
|
||||
|
||||
std::deque<std::list<Boxed_Value>> call_params;
|
||||
std::list<Boxed_Value> call_params;
|
||||
int call_depth;
|
||||
};
|
||||
|
||||
Type_Conversions m_conversions;
|
||||
Dynamic_Cast_Conversions m_conversions;
|
||||
chaiscript::detail::threading::Thread_Storage<Stack_Holder> m_stack_holder;
|
||||
|
||||
|
||||
|
294
include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp
Normal file
294
include/chaiscript/dispatchkit/dynamic_cast_conversion.hpp
Normal file
@@ -0,0 +1,294 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_
|
||||
#define CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_
|
||||
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <typeinfo>
|
||||
|
||||
#include "../chaiscript_threading.hpp"
|
||||
#include "bad_boxed_cast.hpp"
|
||||
#include "boxed_cast_helper.hpp"
|
||||
#include "boxed_value.hpp"
|
||||
#include "type_info.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace exception
|
||||
{
|
||||
class bad_boxed_dynamic_cast : public bad_boxed_cast
|
||||
{
|
||||
public:
|
||||
bad_boxed_dynamic_cast(const Type_Info &t_from, const std::type_info &t_to,
|
||||
const std::string &t_what) CHAISCRIPT_NOEXCEPT
|
||||
: bad_boxed_cast(t_from, t_to, t_what)
|
||||
{
|
||||
}
|
||||
|
||||
bad_boxed_dynamic_cast(const Type_Info &t_from, const std::type_info &t_to) CHAISCRIPT_NOEXCEPT
|
||||
: bad_boxed_cast(t_from, t_to)
|
||||
{
|
||||
}
|
||||
|
||||
bad_boxed_dynamic_cast(const std::string &w) CHAISCRIPT_NOEXCEPT
|
||||
: bad_boxed_cast(w)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~bad_boxed_dynamic_cast() CHAISCRIPT_NOEXCEPT {}
|
||||
};
|
||||
}
|
||||
|
||||
namespace detail
|
||||
{
|
||||
class Dynamic_Conversion
|
||||
{
|
||||
public:
|
||||
virtual Boxed_Value convert(const Boxed_Value &derived) const = 0;
|
||||
virtual Boxed_Value convert_down(const Boxed_Value &base) const = 0;
|
||||
|
||||
const Type_Info &base() const
|
||||
{
|
||||
return m_base;
|
||||
}
|
||||
const Type_Info &derived() const
|
||||
{
|
||||
return m_derived;
|
||||
}
|
||||
|
||||
protected:
|
||||
Dynamic_Conversion(const Type_Info &t_base, const Type_Info &t_derived)
|
||||
: m_base(t_base), m_derived(t_derived)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~Dynamic_Conversion() {}
|
||||
|
||||
private:
|
||||
Type_Info m_base;
|
||||
Type_Info m_derived;
|
||||
|
||||
};
|
||||
|
||||
template<typename From, typename To>
|
||||
class Dynamic_Caster
|
||||
{
|
||||
public:
|
||||
static Boxed_Value cast(const Boxed_Value &t_from)
|
||||
{
|
||||
if (t_from.get_type_info().bare_equal(user_type<From>()))
|
||||
{
|
||||
if (t_from.is_pointer())
|
||||
{
|
||||
// Dynamic cast out the contained boxed value, which we know is the type we want
|
||||
if (t_from.is_const())
|
||||
{
|
||||
std::shared_ptr<const To> data
|
||||
= std::dynamic_pointer_cast<const To>(detail::Cast_Helper<std::shared_ptr<const From> >::cast(t_from, nullptr));
|
||||
if (!data)
|
||||
{
|
||||
throw std::bad_cast();
|
||||
}
|
||||
|
||||
return Boxed_Value(data);
|
||||
} else {
|
||||
std::shared_ptr<To> data
|
||||
= std::dynamic_pointer_cast<To>(detail::Cast_Helper<std::shared_ptr<From> >::cast(t_from, nullptr));
|
||||
|
||||
if (!data)
|
||||
{
|
||||
throw std::bad_cast();
|
||||
}
|
||||
|
||||
return Boxed_Value(data);
|
||||
}
|
||||
} else {
|
||||
// Pull the reference out of the contained boxed value, which we know is the type we want
|
||||
if (t_from.is_const())
|
||||
{
|
||||
const From &d = detail::Cast_Helper<const From &>::cast(t_from, nullptr);
|
||||
const To &data = dynamic_cast<const To &>(d);
|
||||
return Boxed_Value(std::cref(data));
|
||||
} else {
|
||||
From &d = detail::Cast_Helper<From &>::cast(t_from, nullptr);
|
||||
To &data = dynamic_cast<To &>(d);
|
||||
return Boxed_Value(std::ref(data));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw chaiscript::exception::bad_boxed_dynamic_cast(t_from.get_type_info(), typeid(To), "Unknown dynamic_cast_conversion");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Base, typename Derived>
|
||||
class Dynamic_Conversion_Impl : public Dynamic_Conversion
|
||||
{
|
||||
public:
|
||||
Dynamic_Conversion_Impl()
|
||||
: Dynamic_Conversion(user_type<Base>(), user_type<Derived>())
|
||||
{
|
||||
}
|
||||
|
||||
virtual Boxed_Value convert_down(const Boxed_Value &t_base) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return Dynamic_Caster<Base, Derived>::cast(t_base);
|
||||
}
|
||||
|
||||
virtual Boxed_Value convert(const Boxed_Value &t_derived) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return Dynamic_Caster<Derived, Base>::cast(t_derived);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
class Dynamic_Cast_Conversions
|
||||
{
|
||||
public:
|
||||
Dynamic_Cast_Conversions()
|
||||
{
|
||||
}
|
||||
|
||||
Dynamic_Cast_Conversions(const Dynamic_Cast_Conversions &t_other)
|
||||
: m_conversions(t_other.get_conversions())
|
||||
{
|
||||
}
|
||||
|
||||
void add_conversion(const std::shared_ptr<detail::Dynamic_Conversion> &conversion)
|
||||
{
|
||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
m_conversions.insert(conversion);
|
||||
}
|
||||
|
||||
template<typename Base, typename Derived>
|
||||
bool dynamic_cast_converts() const
|
||||
{
|
||||
return dynamic_cast_converts(user_type<Base>(), user_type<Derived>());
|
||||
}
|
||||
|
||||
bool dynamic_cast_converts(const Type_Info &base, const Type_Info &derived) const
|
||||
{
|
||||
return has_conversion(base, derived) || has_conversion(derived, base);
|
||||
}
|
||||
|
||||
template<typename Base>
|
||||
Boxed_Value boxed_dynamic_cast(const Boxed_Value &derived) const
|
||||
{
|
||||
try {
|
||||
return get_conversion(user_type<Base>(), derived.get_type_info())->convert(derived);
|
||||
} catch (const std::out_of_range &) {
|
||||
throw exception::bad_boxed_dynamic_cast(derived.get_type_info(), typeid(Base), "No known conversion");
|
||||
} catch (const std::bad_cast &) {
|
||||
throw exception::bad_boxed_dynamic_cast(derived.get_type_info(), typeid(Base), "Unable to perform dynamic_cast operation");
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Derived>
|
||||
Boxed_Value boxed_dynamic_down_cast(const Boxed_Value &base) const
|
||||
{
|
||||
try {
|
||||
return get_conversion(base.get_type_info(), user_type<Derived>())->convert_down(base);
|
||||
} catch (const std::out_of_range &) {
|
||||
throw exception::bad_boxed_dynamic_cast(base.get_type_info(), typeid(Derived), "No known conversion");
|
||||
} catch (const std::bad_cast &) {
|
||||
throw exception::bad_boxed_dynamic_cast(base.get_type_info(), typeid(Derived), "Unable to perform dynamic_cast operation");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool has_conversion(const Type_Info &base, const Type_Info &derived) const
|
||||
{
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
return find(base, derived) != m_conversions.end();
|
||||
}
|
||||
|
||||
std::shared_ptr<detail::Dynamic_Conversion> get_conversion(const Type_Info &base, const Type_Info &derived) const
|
||||
{
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
auto itr =
|
||||
find(base, derived);
|
||||
|
||||
if (itr != m_conversions.end())
|
||||
{
|
||||
return *itr;
|
||||
} else {
|
||||
throw std::out_of_range("No such conversion exists from " + derived.bare_name() + " to " + base.bare_name());
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::set<std::shared_ptr<detail::Dynamic_Conversion> >::const_iterator find(
|
||||
const Type_Info &base, const Type_Info &derived) const
|
||||
{
|
||||
for (auto itr = m_conversions.begin();
|
||||
itr != m_conversions.end();
|
||||
++itr)
|
||||
{
|
||||
if ((*itr)->base().bare_equal(base) && (*itr)->derived().bare_equal(derived))
|
||||
{
|
||||
return itr;
|
||||
}
|
||||
}
|
||||
|
||||
return m_conversions.end();
|
||||
}
|
||||
|
||||
std::set<std::shared_ptr<detail::Dynamic_Conversion> > get_conversions() const
|
||||
{
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
return m_conversions;
|
||||
}
|
||||
|
||||
mutable chaiscript::detail::threading::shared_mutex m_mutex;
|
||||
std::set<std::shared_ptr<detail::Dynamic_Conversion> > m_conversions;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<chaiscript::detail::Dynamic_Conversion> Dynamic_Cast_Conversion;
|
||||
|
||||
/// \brief Used to register a base / parent class relationship with ChaiScript. Necessary if you
|
||||
/// want automatic conversions up your inheritance hierarchy.
|
||||
///
|
||||
/// Create a new base class registration for applying to a module or to the ChaiScript engine
|
||||
/// Currently, due to limitations in module loading on Windows, and for the sake of portability,
|
||||
/// if you have a type that is introduced in a loadable module and is used by multiple modules
|
||||
/// (through a tertiary dll that is shared between the modules, static linking the new type
|
||||
/// into both loadable modules would not be portable), you need to register the base type
|
||||
/// relationship in all modules that use the newly added type in a polymorphic way.
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// class Base
|
||||
/// {};
|
||||
/// class Derived : public Base
|
||||
/// {};
|
||||
///
|
||||
/// chaiscript::ChaiScript chai;
|
||||
/// chai.add(chaiscript::base_class<Base, Derived>());
|
||||
/// \endcode
|
||||
///
|
||||
template<typename Base, typename Derived>
|
||||
Dynamic_Cast_Conversion base_class()
|
||||
{
|
||||
//Can only be used with related polymorphic types
|
||||
//may be expanded some day to support conversions other than child -> parent
|
||||
static_assert(std::is_base_of<Base,Derived>::value, "Classes are not related by inheritance");
|
||||
static_assert(std::is_polymorphic<Base>::value, "Base class must be polymorphic");
|
||||
static_assert(std::is_polymorphic<Derived>::value, "Derived class must be polymorphic");
|
||||
|
||||
return std::shared_ptr<detail::Dynamic_Conversion>(new detail::Dynamic_Conversion_Impl<Base, Derived>());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
@@ -23,7 +23,7 @@
|
||||
#include "type_info.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
class Type_Conversions;
|
||||
class Dynamic_Cast_Conversions;
|
||||
namespace dispatch {
|
||||
class Proxy_Function_Base;
|
||||
} // namespace dispatch
|
||||
@@ -64,16 +64,18 @@ namespace chaiscript
|
||||
|
||||
namespace detail
|
||||
{
|
||||
/// A Proxy_Function implementation designed for calling a function
|
||||
/// that is automatically guarded based on the first param based on the
|
||||
/// param's type name
|
||||
/**
|
||||
* A Proxy_Function implementation designed for calling a function
|
||||
* that is automatically guarded based on the first param based on the
|
||||
* param's type name
|
||||
*/
|
||||
class Dynamic_Object_Function : public Proxy_Function_Base
|
||||
{
|
||||
public:
|
||||
Dynamic_Object_Function(
|
||||
std::string t_type_name,
|
||||
const Proxy_Function &t_func)
|
||||
: Proxy_Function_Base(t_func->get_param_types(), t_func->get_arity()),
|
||||
: Proxy_Function_Base(t_func->get_param_types()),
|
||||
m_type_name(std::move(t_type_name)), m_func(t_func), m_doti(user_type<Dynamic_Object>())
|
||||
{
|
||||
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
|
||||
@@ -84,7 +86,7 @@ namespace chaiscript
|
||||
std::string t_type_name,
|
||||
const Proxy_Function &t_func,
|
||||
const Type_Info &t_ti)
|
||||
: Proxy_Function_Base(build_param_types(t_func->get_param_types(), t_ti), t_func->get_arity()),
|
||||
: Proxy_Function_Base(build_param_types(t_func->get_param_types(), t_ti)),
|
||||
m_type_name(std::move(t_type_name)), m_func(t_func), m_ti(new Type_Info(t_ti)), m_doti(user_type<Dynamic_Object>())
|
||||
{
|
||||
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
|
||||
@@ -94,11 +96,11 @@ namespace chaiscript
|
||||
virtual ~Dynamic_Object_Function() {}
|
||||
|
||||
Dynamic_Object_Function &operator=(const Dynamic_Object_Function) = delete;
|
||||
Dynamic_Object_Function(Dynamic_Object_Function &) = delete;
|
||||
|
||||
virtual bool operator==(const Proxy_Function_Base &f) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
if (const auto *df = dynamic_cast<const Dynamic_Object_Function *>(&f))
|
||||
const Dynamic_Object_Function *df = dynamic_cast<const Dynamic_Object_Function *>(&f);
|
||||
if (df)
|
||||
{
|
||||
return df->m_type_name == m_type_name && (*df->m_func) == (*m_func);
|
||||
} else {
|
||||
@@ -106,7 +108,7 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
if (dynamic_object_typename_match(vals, m_type_name, m_ti, t_conversions))
|
||||
{
|
||||
@@ -121,6 +123,12 @@ namespace chaiscript
|
||||
return {m_func};
|
||||
}
|
||||
|
||||
|
||||
virtual int get_arity() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return m_func->get_arity();
|
||||
}
|
||||
|
||||
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return m_func->annotation();
|
||||
@@ -128,7 +136,7 @@ namespace chaiscript
|
||||
|
||||
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
if (dynamic_object_typename_match(params, m_type_name, m_ti, t_conversions))
|
||||
{
|
||||
@@ -138,7 +146,7 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool compare_first_type(const Boxed_Value &bv, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual bool compare_first_type(const Boxed_Value &bv, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return dynamic_object_typename_match(bv, m_type_name, m_ti, t_conversions);
|
||||
}
|
||||
@@ -156,7 +164,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
bool dynamic_object_typename_match(const Boxed_Value &bv, const std::string &name,
|
||||
const std::unique_ptr<Type_Info> &ti, const Type_Conversions &t_conversions) const
|
||||
const std::shared_ptr<Type_Info> &ti, const Dynamic_Cast_Conversions &t_conversions) const
|
||||
{
|
||||
if (bv.get_type_info().bare_equal(m_doti))
|
||||
{
|
||||
@@ -178,7 +186,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
bool dynamic_object_typename_match(const std::vector<Boxed_Value> &bvs, const std::string &name,
|
||||
const std::unique_ptr<Type_Info> &ti, const Type_Conversions &t_conversions) const
|
||||
const std::shared_ptr<Type_Info> &ti, const Dynamic_Cast_Conversions &t_conversions) const
|
||||
{
|
||||
if (bvs.size() > 0)
|
||||
{
|
||||
@@ -190,7 +198,7 @@ namespace chaiscript
|
||||
|
||||
std::string m_type_name;
|
||||
Proxy_Function m_func;
|
||||
std::unique_ptr<Type_Info> m_ti;
|
||||
std::shared_ptr<Type_Info> m_ti;
|
||||
const Type_Info m_doti;
|
||||
|
||||
|
||||
@@ -209,7 +217,7 @@ namespace chaiscript
|
||||
Dynamic_Object_Constructor(
|
||||
std::string t_type_name,
|
||||
const Proxy_Function &t_func)
|
||||
: Proxy_Function_Base(build_type_list(t_func->get_param_types()), t_func->get_arity() - 1),
|
||||
: Proxy_Function_Base(build_type_list(t_func->get_param_types())),
|
||||
m_type_name(std::move(t_type_name)), m_func(t_func)
|
||||
{
|
||||
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
|
||||
@@ -242,24 +250,33 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
std::vector<Boxed_Value> new_vals{Boxed_Value(Dynamic_Object(m_type_name))};
|
||||
std::vector<Boxed_Value> new_vals;
|
||||
new_vals.push_back(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);
|
||||
}
|
||||
|
||||
|
||||
virtual int get_arity() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
// "this" is not considered part of the arity
|
||||
return m_func->get_arity() - 1;
|
||||
}
|
||||
|
||||
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return m_func->annotation();
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
auto bv = var(Dynamic_Object(m_type_name));
|
||||
std::vector<Boxed_Value> new_params{bv};
|
||||
std::vector<Boxed_Value> new_params;
|
||||
chaiscript::Boxed_Value bv = var(Dynamic_Object(m_type_name));
|
||||
new_params.push_back(bv);
|
||||
new_params.insert(new_params.end(), params.begin(), params.end());
|
||||
|
||||
(*m_func)(new_params, t_conversions);
|
||||
|
@@ -18,7 +18,7 @@
|
||||
|
||||
namespace chaiscript {
|
||||
class Boxed_Value;
|
||||
class Type_Conversions;
|
||||
class Dynamic_Cast_Conversions;
|
||||
namespace detail {
|
||||
template <typename T> struct Cast_Helper;
|
||||
} // namespace detail
|
||||
@@ -28,56 +28,66 @@ namespace chaiscript
|
||||
{
|
||||
namespace dispatch
|
||||
{
|
||||
/// Build a function caller that knows how to dispatch on a set of functions
|
||||
/// example:
|
||||
/// std::function<void (int)> f =
|
||||
/// build_function_caller(dispatchkit.get_function("print"));
|
||||
/// \returns A std::function object for dispatching
|
||||
/// \param[in] funcs the set of functions to dispatch on.
|
||||
/**
|
||||
* Build a function caller that knows how to dispatch on a set of functions
|
||||
* example:
|
||||
* std::function<void (int)> f =
|
||||
* build_function_caller(dispatchkit.get_function("print"));
|
||||
* \returns A std::function object for dispatching
|
||||
* \param[in] funcs the set of functions to dispatch on.
|
||||
*/
|
||||
template<typename FunctionType>
|
||||
std::function<FunctionType>
|
||||
functor(const std::vector<Const_Proxy_Function> &funcs, const Type_Conversions *t_conversions)
|
||||
functor(const std::vector<Const_Proxy_Function> &funcs, const Dynamic_Cast_Conversions *t_conversions)
|
||||
{
|
||||
FunctionType *p=nullptr;
|
||||
return detail::build_function_caller_helper(p, funcs, t_conversions);
|
||||
}
|
||||
|
||||
/// Build a function caller for a particular Proxy_Function object
|
||||
/// useful in the case that a function is being pass out from scripting back
|
||||
/// into code
|
||||
/// example:
|
||||
/// void my_function(Proxy_Function f)
|
||||
/// {
|
||||
/// std::function<void (int)> local_f =
|
||||
/// build_function_caller(f);
|
||||
/// }
|
||||
/// \returns A std::function object for dispatching
|
||||
/// \param[in] func A function to execute.
|
||||
/**
|
||||
* Build a function caller for a particular Proxy_Function object
|
||||
* useful in the case that a function is being pass out from scripting back
|
||||
* into code
|
||||
* example:
|
||||
* void my_function(Proxy_Function f)
|
||||
* {
|
||||
* std::function<void (int)> local_f =
|
||||
* build_function_caller(f);
|
||||
* }
|
||||
* \returns A std::function object for dispatching
|
||||
* \param[in] func A function to execute.
|
||||
*/
|
||||
template<typename FunctionType>
|
||||
std::function<FunctionType>
|
||||
functor(Const_Proxy_Function func, const Type_Conversions *t_conversions)
|
||||
functor(Const_Proxy_Function func, const Dynamic_Cast_Conversions *t_conversions)
|
||||
{
|
||||
return functor<FunctionType>(std::vector<Const_Proxy_Function>({func}), t_conversions);
|
||||
std::vector<Const_Proxy_Function> funcs;
|
||||
funcs.push_back(func);
|
||||
return functor<FunctionType>(funcs, t_conversions);
|
||||
}
|
||||
|
||||
/// Helper for automatically unboxing a Boxed_Value that contains a function object
|
||||
/// and creating a typesafe C++ function caller from it.
|
||||
/**
|
||||
* Helper for automatically unboxing a Boxed_Value that contains a function object
|
||||
* and creating a typesafe C++ function caller from it.
|
||||
*/
|
||||
template<typename FunctionType>
|
||||
std::function<FunctionType>
|
||||
functor(const Boxed_Value &bv, const Type_Conversions *t_conversions)
|
||||
functor(const Boxed_Value &bv, const Dynamic_Cast_Conversions *t_conversions)
|
||||
{
|
||||
return functor<FunctionType>(boxed_cast<Const_Proxy_Function >(bv, t_conversions), t_conversions);
|
||||
}
|
||||
}
|
||||
|
||||
namespace detail{
|
||||
/// Cast helper to handle automatic casting to const std::function &
|
||||
/**
|
||||
* Cast helper to handle automatic casting to const std::function &
|
||||
*/
|
||||
template<typename Signature>
|
||||
struct Cast_Helper<const std::function<Signature> &>
|
||||
{
|
||||
typedef std::function<Signature> Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *t_conversions)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *t_conversions)
|
||||
{
|
||||
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
|
||||
{
|
||||
@@ -88,13 +98,15 @@ namespace chaiscript
|
||||
}
|
||||
};
|
||||
|
||||
/// Cast helper to handle automatic casting to std::function
|
||||
/**
|
||||
* Cast helper to handle automatic casting to std::function
|
||||
*/
|
||||
template<typename Signature>
|
||||
struct Cast_Helper<std::function<Signature> >
|
||||
{
|
||||
typedef std::function<Signature> Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *t_conversions)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *t_conversions)
|
||||
{
|
||||
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
|
||||
{
|
||||
@@ -105,13 +117,15 @@ namespace chaiscript
|
||||
}
|
||||
};
|
||||
|
||||
/// Cast helper to handle automatic casting to const std::function
|
||||
/**
|
||||
* Cast helper to handle automatic casting to const std::function
|
||||
*/
|
||||
template<typename Signature>
|
||||
struct Cast_Helper<const std::function<Signature> >
|
||||
{
|
||||
typedef std::function<Signature> Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *t_conversions)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *t_conversions)
|
||||
{
|
||||
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
|
||||
{
|
||||
|
@@ -17,7 +17,7 @@
|
||||
#include "boxed_cast.hpp"
|
||||
#include "boxed_number.hpp"
|
||||
#include "boxed_value.hpp"
|
||||
#include "type_conversions.hpp"
|
||||
#include "dynamic_cast_conversion.hpp"
|
||||
#include "proxy_functions.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
@@ -26,13 +26,15 @@ namespace chaiscript
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
/// Internal helper class for handling the return
|
||||
/// value of a build_function_caller
|
||||
/**
|
||||
* 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> ¶ms, const Type_Conversions &t_conversions)
|
||||
const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions)
|
||||
{
|
||||
return boxed_cast<Ret>(dispatch::dispatch(t_funcs, params, t_conversions));
|
||||
}
|
||||
@@ -45,7 +47,7 @@ namespace chaiscript
|
||||
struct Function_Caller_Ret<Ret, true>
|
||||
{
|
||||
static Ret call(const std::vector<Const_Proxy_Function> &t_funcs,
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions)
|
||||
const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions)
|
||||
{
|
||||
return Boxed_Number(dispatch::dispatch(t_funcs, params, t_conversions)).get_as<Ret>();
|
||||
}
|
||||
@@ -59,7 +61,7 @@ namespace chaiscript
|
||||
struct Function_Caller_Ret<void, false>
|
||||
{
|
||||
static void call(const std::vector<Const_Proxy_Function> &t_funcs,
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions)
|
||||
const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions)
|
||||
{
|
||||
dispatch::dispatch(t_funcs, params, t_conversions);
|
||||
}
|
||||
@@ -71,7 +73,7 @@ namespace chaiscript
|
||||
template<typename Ret, typename ... Param>
|
||||
struct Build_Function_Caller_Helper
|
||||
{
|
||||
Build_Function_Caller_Helper(std::vector<Const_Proxy_Function> t_funcs, const Type_Conversions &t_conversions)
|
||||
Build_Function_Caller_Helper(std::vector<Const_Proxy_Function> t_funcs, const Dynamic_Cast_Conversions &t_conversions)
|
||||
: m_funcs(std::move(t_funcs)),
|
||||
m_conversions(t_conversions)
|
||||
{
|
||||
@@ -88,13 +90,13 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
std::vector<Const_Proxy_Function> m_funcs;
|
||||
Type_Conversions m_conversions;
|
||||
Dynamic_Cast_Conversions m_conversions;
|
||||
};
|
||||
|
||||
|
||||
|
||||
template<typename Ret, typename ... Params>
|
||||
std::function<Ret (Params...)> build_function_caller_helper(Ret (Params...), const std::vector<Const_Proxy_Function> &funcs, const Type_Conversions *t_conversions)
|
||||
std::function<Ret (Params...)> build_function_caller_helper(Ret (Params...), const std::vector<Const_Proxy_Function> &funcs, const Dynamic_Cast_Conversions *t_conversions)
|
||||
{
|
||||
if (funcs.size() == 1)
|
||||
{
|
||||
@@ -110,7 +112,7 @@ namespace chaiscript
|
||||
// we cannot make any other guesses or assumptions really, so continuing
|
||||
}
|
||||
|
||||
return std::function<Ret (Params...)>(Build_Function_Caller_Helper<Ret, Params...>(funcs, t_conversions?*t_conversions:Type_Conversions()));
|
||||
return std::function<Ret (Params...)>(Build_Function_Caller_Helper<Ret, Params...>(funcs, t_conversions?*t_conversions:Dynamic_Cast_Conversions()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -48,15 +48,6 @@ namespace chaiscript
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<const Ret *>
|
||||
{
|
||||
static Boxed_Value handle(const Ret *p)
|
||||
{
|
||||
return Boxed_Value(p);
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Ret>
|
||||
struct Handle_Return<std::shared_ptr<Ret> &>
|
||||
{
|
||||
|
@@ -26,7 +26,7 @@
|
||||
#include "type_info.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
class Type_Conversions;
|
||||
class Dynamic_Cast_Conversions;
|
||||
namespace exception {
|
||||
class bad_boxed_cast;
|
||||
struct arity_error;
|
||||
@@ -55,7 +55,7 @@ namespace chaiscript
|
||||
public:
|
||||
virtual ~Proxy_Function_Base() {}
|
||||
|
||||
Boxed_Value operator()(const std::vector<Boxed_Value> ¶ms, const chaiscript::Type_Conversions &t_conversions) const
|
||||
Boxed_Value operator()(const std::vector<Boxed_Value> ¶ms, const chaiscript::Dynamic_Cast_Conversions &t_conversions) const
|
||||
{
|
||||
Boxed_Value bv = do_call(params, t_conversions);
|
||||
return bv;
|
||||
@@ -68,7 +68,7 @@ namespace chaiscript
|
||||
const std::vector<Type_Info> &get_param_types() const { return m_types; }
|
||||
|
||||
virtual bool operator==(const Proxy_Function_Base &) const = 0;
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const = 0;
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const = 0;
|
||||
|
||||
bool has_arithmetic_param() const
|
||||
{
|
||||
@@ -82,13 +82,15 @@ 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 &t_conversions) const
|
||||
bool filter(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const
|
||||
{
|
||||
if (m_arity < 0)
|
||||
int arity = get_arity();
|
||||
|
||||
if (arity < 0)
|
||||
{
|
||||
return true;
|
||||
} else if (size_t(m_arity) == vals.size()) {
|
||||
if (m_arity == 0)
|
||||
} else if (size_t(arity) == vals.size()) {
|
||||
if (arity == 0)
|
||||
{
|
||||
return true;
|
||||
} else {
|
||||
@@ -100,14 +102,11 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
/// \returns the number of arguments the function takes or -1 if it is variadic
|
||||
int get_arity() const
|
||||
{
|
||||
return m_arity;
|
||||
}
|
||||
virtual int get_arity() const = 0;
|
||||
|
||||
virtual std::string annotation() const = 0;
|
||||
|
||||
static bool compare_type_to_param(const Type_Info &ti, const Boxed_Value &bv, const Type_Conversions &t_conversions)
|
||||
static bool compare_type_to_param(const Type_Info &ti, const Boxed_Value &bv, const Dynamic_Cast_Conversions &t_conversions)
|
||||
{
|
||||
if (ti.is_undef()
|
||||
|| ti.bare_equal(user_type<Boxed_Value>())
|
||||
@@ -115,7 +114,7 @@ namespace chaiscript
|
||||
&& (ti.bare_equal(user_type<Boxed_Number>())
|
||||
|| ti.bare_equal(bv.get_type_info())
|
||||
|| bv.get_type_info().bare_equal(user_type<std::shared_ptr<const Proxy_Function_Base> >())
|
||||
|| t_conversions.converts(ti, bv.get_type_info())
|
||||
|| t_conversions.dynamic_cast_converts(ti, bv.get_type_info())
|
||||
)
|
||||
)
|
||||
)
|
||||
@@ -126,10 +125,10 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const = 0;
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions) const = 0;
|
||||
|
||||
Proxy_Function_Base(std::vector<Type_Info> t_types, int t_arity)
|
||||
: m_types(std::move(t_types)), m_has_arithmetic_param(false), m_arity(t_arity)
|
||||
Proxy_Function_Base(std::vector<Type_Info> t_types)
|
||||
: m_types(std::move(t_types)), m_has_arithmetic_param(false)
|
||||
{
|
||||
for (size_t i = 1; i < m_types.size(); ++i)
|
||||
{
|
||||
@@ -142,7 +141,7 @@ namespace chaiscript
|
||||
|
||||
}
|
||||
|
||||
virtual bool compare_first_type(const Boxed_Value &bv, const Type_Conversions &t_conversions) const
|
||||
virtual bool compare_first_type(const Boxed_Value &bv, const Dynamic_Cast_Conversions &t_conversions) const
|
||||
{
|
||||
const std::vector<Type_Info> &types = get_param_types();
|
||||
|
||||
@@ -176,7 +175,7 @@ namespace chaiscript
|
||||
|
||||
std::vector<Type_Info> m_types;
|
||||
bool m_has_arithmetic_param;
|
||||
int m_arity;
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
@@ -217,7 +216,7 @@ namespace chaiscript
|
||||
AST_NodePtr t_parsenode = AST_NodePtr(),
|
||||
std::string t_description = "",
|
||||
Proxy_Function t_guard = Proxy_Function())
|
||||
: Proxy_Function_Base(build_param_type_list(t_arity), t_arity),
|
||||
: Proxy_Function_Base(build_param_type_list(t_arity)),
|
||||
m_f(std::move(t_f)), m_arity(t_arity), m_description(std::move(t_description)), m_guard(std::move(t_guard)), m_parsenode(std::move(t_parsenode))
|
||||
{
|
||||
}
|
||||
@@ -234,12 +233,16 @@ namespace chaiscript
|
||||
&& !this->m_guard && !prhs->m_guard);
|
||||
}
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return (m_arity < 0 || vals.size() == size_t(m_arity))
|
||||
&& test_guard(vals, t_conversions);
|
||||
}
|
||||
|
||||
virtual int get_arity() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return m_arity;
|
||||
}
|
||||
|
||||
Proxy_Function get_guard() const
|
||||
{
|
||||
@@ -257,7 +260,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
if (m_arity < 0 || params.size() == size_t(m_arity))
|
||||
{
|
||||
@@ -275,7 +278,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
private:
|
||||
bool test_guard(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const
|
||||
bool test_guard(const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions) const
|
||||
{
|
||||
if (m_guard)
|
||||
{
|
||||
@@ -335,8 +338,8 @@ namespace chaiscript
|
||||
public:
|
||||
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)
|
||||
: Proxy_Function_Base(build_param_type_info(t_f, t_args)),
|
||||
m_f(t_f), m_args(t_args), m_arity(t_f->get_arity()<0?-1:static_cast<int>(get_param_types().size())-1)
|
||||
{
|
||||
assert(m_f->get_arity() < 0 || m_f->get_arity() == static_cast<int>(m_args.size()));
|
||||
}
|
||||
@@ -348,7 +351,7 @@ namespace chaiscript
|
||||
|
||||
virtual ~Bound_Function() {}
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return m_f->call_match(build_param_list(vals), t_conversions);
|
||||
}
|
||||
@@ -392,6 +395,11 @@ namespace chaiscript
|
||||
return args;
|
||||
}
|
||||
|
||||
virtual int get_arity() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return m_arity;
|
||||
}
|
||||
|
||||
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return "Bound: " + m_f->annotation();
|
||||
@@ -421,7 +429,7 @@ namespace chaiscript
|
||||
return retval;
|
||||
}
|
||||
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return (*m_f)(build_param_list(params), t_conversions);
|
||||
}
|
||||
@@ -429,24 +437,30 @@ namespace chaiscript
|
||||
private:
|
||||
Const_Proxy_Function m_f;
|
||||
std::vector<Boxed_Value> m_args;
|
||||
int m_arity;
|
||||
};
|
||||
|
||||
class Proxy_Function_Impl_Base : public Proxy_Function_Base
|
||||
{
|
||||
public:
|
||||
Proxy_Function_Impl_Base(const std::vector<Type_Info> &t_types)
|
||||
: Proxy_Function_Base(t_types, static_cast<int>(t_types.size()) - 1)
|
||||
Proxy_Function_Impl_Base(std::vector<Type_Info> t_types)
|
||||
: Proxy_Function_Base(std::move(t_types))
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~Proxy_Function_Impl_Base() {}
|
||||
|
||||
virtual int get_arity() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return static_cast<int>(m_types.size()) - 1;
|
||||
}
|
||||
|
||||
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
if (int(vals.size()) != get_arity())
|
||||
{
|
||||
@@ -456,7 +470,7 @@ namespace chaiscript
|
||||
return compare_types(m_types, vals) || compare_types_with_cast(vals, t_conversions);
|
||||
}
|
||||
|
||||
virtual bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const = 0;
|
||||
virtual bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -476,7 +490,7 @@ namespace chaiscript
|
||||
|
||||
virtual ~Proxy_Function_Impl() {}
|
||||
|
||||
virtual bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return detail::compare_types_cast(m_dummy_func, vals, t_conversions);
|
||||
}
|
||||
@@ -492,7 +506,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions) const
|
||||
{
|
||||
return detail::Do_Call<typename std::function<Func>::result_type>::go(m_f, params, t_conversions);
|
||||
}
|
||||
@@ -510,8 +524,8 @@ namespace chaiscript
|
||||
{
|
||||
public:
|
||||
Attribute_Access(T Class::* t_attr)
|
||||
: Proxy_Function_Base(param_types(), 1),
|
||||
m_attr(t_attr)
|
||||
: Proxy_Function_Base(param_types()),
|
||||
m_attr(t_attr)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -529,7 +543,13 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &) const CHAISCRIPT_OVERRIDE
|
||||
|
||||
virtual int get_arity() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
if (vals.size() != 1)
|
||||
{
|
||||
@@ -545,7 +565,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
if (params.size() == 1)
|
||||
{
|
||||
@@ -602,7 +622,7 @@ namespace chaiscript
|
||||
{
|
||||
template<typename FuncType>
|
||||
bool types_match_except_for_arithmetic(const FuncType &t_func, const std::vector<Boxed_Value> &plist,
|
||||
const Type_Conversions &t_conversions)
|
||||
const Dynamic_Cast_Conversions &t_conversions)
|
||||
{
|
||||
if (t_func->get_arity() != static_cast<int>(plist.size()))
|
||||
{
|
||||
@@ -630,7 +650,7 @@ namespace chaiscript
|
||||
|
||||
template<typename InItr>
|
||||
Boxed_Value dispatch_with_conversions(InItr begin, const InItr &end, const std::vector<Boxed_Value> &plist,
|
||||
const Type_Conversions &t_conversions)
|
||||
const Dynamic_Cast_Conversions &t_conversions)
|
||||
{
|
||||
InItr orig(begin);
|
||||
|
||||
@@ -692,42 +712,17 @@ namespace chaiscript
|
||||
* each function against the set of parameters, in order, until a matching
|
||||
* 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 &t_conversions)
|
||||
template<typename InItr>
|
||||
Boxed_Value dispatch(InItr begin, const InItr &end,
|
||||
const std::vector<Boxed_Value> &plist, const Dynamic_Cast_Conversions &t_conversions)
|
||||
{
|
||||
|
||||
std::multimap<size_t, const Proxy_Function_Base *> ordered_funcs;
|
||||
|
||||
for (const auto &func : funcs)
|
||||
{
|
||||
size_t numdiffs = 0;
|
||||
const auto arity = func->get_arity();
|
||||
|
||||
if (arity == -1)
|
||||
{
|
||||
numdiffs = plist.size();
|
||||
} else if (arity == static_cast<int>(plist.size())) {
|
||||
for (size_t i = 0; i < plist.size(); ++i)
|
||||
{
|
||||
if (!func->get_param_types()[i+1].bare_equal(plist[i].get_type_info()))
|
||||
{
|
||||
++numdiffs;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
ordered_funcs.insert(std::make_pair(numdiffs, func.get()));
|
||||
}
|
||||
|
||||
for (const auto &func : ordered_funcs )
|
||||
InItr orig(begin);
|
||||
while (begin != end)
|
||||
{
|
||||
try {
|
||||
if (func.second->filter(plist, t_conversions))
|
||||
if ((*begin)->filter(plist, t_conversions))
|
||||
{
|
||||
return (*(func.second))(plist, t_conversions);
|
||||
return (*(*begin))(plist, t_conversions);
|
||||
}
|
||||
} catch (const exception::bad_boxed_cast &) {
|
||||
//parameter failed to cast, try again
|
||||
@@ -737,9 +732,22 @@ namespace chaiscript
|
||||
//guard failed to allow the function to execute,
|
||||
//try again
|
||||
}
|
||||
++begin;
|
||||
}
|
||||
|
||||
return detail::dispatch_with_conversions(funcs.cbegin(), funcs.cend(), plist, t_conversions);
|
||||
return detail::dispatch_with_conversions(orig, end, plist, t_conversions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Take a vector of functions and a vector of parameters. Attempt to execute
|
||||
* each function against the set of parameters, in order, until a matching
|
||||
* 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 Dynamic_Cast_Conversions &t_conversions)
|
||||
{
|
||||
return dispatch::dispatch(funcs.begin(), funcs.end(), plist, t_conversions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -20,7 +20,7 @@
|
||||
#include "type_info.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
class Type_Conversions;
|
||||
class Dynamic_Cast_Conversions;
|
||||
namespace exception {
|
||||
class bad_boxed_cast;
|
||||
} // namespace exception
|
||||
@@ -72,7 +72,7 @@ namespace chaiscript
|
||||
template<typename Param, typename ... Rest>
|
||||
struct Try_Cast<Param, Rest...>
|
||||
{
|
||||
static void do_try(const std::vector<Boxed_Value> ¶ms, int generation, const Type_Conversions &t_conversions)
|
||||
static void do_try(const std::vector<Boxed_Value> ¶ms, int generation, const Dynamic_Cast_Conversions &t_conversions)
|
||||
{
|
||||
boxed_cast<Param>(params[generation], &t_conversions);
|
||||
Try_Cast<Rest...>::do_try(params, generation+1, t_conversions);
|
||||
@@ -83,7 +83,7 @@ namespace chaiscript
|
||||
template<>
|
||||
struct Try_Cast<>
|
||||
{
|
||||
static void do_try(const std::vector<Boxed_Value> &, int, const Type_Conversions &)
|
||||
static void do_try(const std::vector<Boxed_Value> &, int, const Dynamic_Cast_Conversions &)
|
||||
{
|
||||
}
|
||||
};
|
||||
@@ -96,7 +96,7 @@ namespace chaiscript
|
||||
*/
|
||||
template<typename Ret, typename ... Params>
|
||||
bool compare_types_cast(Ret (*)(Params...),
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions)
|
||||
const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions)
|
||||
{
|
||||
try {
|
||||
Try_Cast<Params...>::do_try(params, 0, t_conversions);
|
||||
@@ -113,7 +113,7 @@ namespace chaiscript
|
||||
|
||||
template<typename ... InnerParams>
|
||||
static Ret do_call(const std::function<Ret (Params...)> &f,
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions, InnerParams &&... innerparams)
|
||||
const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions, InnerParams &&... innerparams)
|
||||
{
|
||||
return Call_Func<Ret, count - 1, Params...>::do_call(f, params, t_conversions, std::forward<InnerParams>(innerparams)..., params[sizeof...(Params) - count]);
|
||||
}
|
||||
@@ -128,7 +128,7 @@ namespace chaiscript
|
||||
#endif
|
||||
template<typename ... InnerParams>
|
||||
static Ret do_call(const std::function<Ret (Params...)> &f,
|
||||
const std::vector<Boxed_Value> &, const Type_Conversions &t_conversions, InnerParams &&... innerparams)
|
||||
const std::vector<Boxed_Value> &, const Dynamic_Cast_Conversions &t_conversions, InnerParams &&... innerparams)
|
||||
{
|
||||
return f(boxed_cast<Params>(std::forward<InnerParams>(innerparams), &t_conversions)...);
|
||||
}
|
||||
@@ -145,7 +145,7 @@ namespace chaiscript
|
||||
*/
|
||||
template<typename Ret, typename ... Params>
|
||||
Ret call_func(const std::function<Ret (Params...)> &f,
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions)
|
||||
const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions)
|
||||
{
|
||||
if (params.size() == sizeof...(Params))
|
||||
{
|
||||
@@ -171,7 +171,7 @@ namespace chaiscript
|
||||
struct Do_Call
|
||||
{
|
||||
template<typename Fun>
|
||||
static Boxed_Value go(const std::function<Fun> &fun, const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions)
|
||||
static Boxed_Value go(const std::function<Fun> &fun, const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions)
|
||||
{
|
||||
return Handle_Return<Ret>::handle(call_func(fun, params, t_conversions));
|
||||
}
|
||||
@@ -181,7 +181,7 @@ namespace chaiscript
|
||||
struct Do_Call<void>
|
||||
{
|
||||
template<typename Fun>
|
||||
static Boxed_Value go(const std::function<Fun> &fun, const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions)
|
||||
static Boxed_Value go(const std::function<Fun> &fun, const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions)
|
||||
{
|
||||
call_func(fun, params, t_conversions);
|
||||
return Handle_Return<void>::handle();
|
||||
|
@@ -1,443 +0,0 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#ifndef CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_
|
||||
#define CHAISCRIPT_DYNAMIC_CAST_CONVERSION_HPP_
|
||||
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <set>
|
||||
#include <stdexcept>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <typeinfo>
|
||||
|
||||
#include "../chaiscript_threading.hpp"
|
||||
#include "bad_boxed_cast.hpp"
|
||||
#include "boxed_cast_helper.hpp"
|
||||
#include "boxed_value.hpp"
|
||||
#include "type_info.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
namespace exception
|
||||
{
|
||||
class bad_boxed_dynamic_cast : public bad_boxed_cast
|
||||
{
|
||||
public:
|
||||
bad_boxed_dynamic_cast(const Type_Info &t_from, const std::type_info &t_to,
|
||||
const std::string &t_what) CHAISCRIPT_NOEXCEPT
|
||||
: bad_boxed_cast(t_from, t_to, t_what)
|
||||
{
|
||||
}
|
||||
|
||||
bad_boxed_dynamic_cast(const Type_Info &t_from, const std::type_info &t_to) CHAISCRIPT_NOEXCEPT
|
||||
: bad_boxed_cast(t_from, t_to)
|
||||
{
|
||||
}
|
||||
|
||||
bad_boxed_dynamic_cast(const std::string &w) CHAISCRIPT_NOEXCEPT
|
||||
: bad_boxed_cast(w)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~bad_boxed_dynamic_cast() CHAISCRIPT_NOEXCEPT {}
|
||||
};
|
||||
|
||||
class bad_boxed_type_cast : public bad_boxed_cast
|
||||
{
|
||||
public:
|
||||
bad_boxed_type_cast(const Type_Info &t_from, const std::type_info &t_to,
|
||||
const std::string &t_what) CHAISCRIPT_NOEXCEPT
|
||||
: bad_boxed_cast(t_from, t_to, t_what)
|
||||
{
|
||||
}
|
||||
|
||||
bad_boxed_type_cast(const Type_Info &t_from, const std::type_info &t_to) CHAISCRIPT_NOEXCEPT
|
||||
: bad_boxed_cast(t_from, t_to)
|
||||
{
|
||||
}
|
||||
|
||||
bad_boxed_type_cast(const std::string &w) CHAISCRIPT_NOEXCEPT
|
||||
: bad_boxed_cast(w)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~bad_boxed_type_cast() CHAISCRIPT_NOEXCEPT {}
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
namespace detail
|
||||
{
|
||||
class Type_Conversion_Base
|
||||
{
|
||||
public:
|
||||
virtual Boxed_Value convert(const Boxed_Value &from) const = 0;
|
||||
virtual Boxed_Value convert_down(const Boxed_Value &to) const = 0;
|
||||
|
||||
const Type_Info &to() const
|
||||
{
|
||||
return m_to;
|
||||
}
|
||||
const Type_Info &from() const
|
||||
{
|
||||
return m_from;
|
||||
}
|
||||
|
||||
protected:
|
||||
Type_Conversion_Base(const Type_Info &t_to, const Type_Info &t_from)
|
||||
: m_to(t_to), m_from(t_from)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~Type_Conversion_Base() {}
|
||||
|
||||
private:
|
||||
Type_Info m_to;
|
||||
Type_Info m_from;
|
||||
|
||||
};
|
||||
|
||||
template<typename From, typename To>
|
||||
class Dynamic_Caster
|
||||
{
|
||||
public:
|
||||
static Boxed_Value cast(const Boxed_Value &t_from)
|
||||
{
|
||||
if (t_from.get_type_info().bare_equal(chaiscript::user_type<From>()))
|
||||
{
|
||||
if (t_from.is_pointer())
|
||||
{
|
||||
// Dynamic cast out the contained boxed value, which we know is the type we want
|
||||
if (t_from.is_const())
|
||||
{
|
||||
std::shared_ptr<const To> data
|
||||
= std::dynamic_pointer_cast<const To>(detail::Cast_Helper<std::shared_ptr<const From> >::cast(t_from, nullptr));
|
||||
if (!data)
|
||||
{
|
||||
throw std::bad_cast();
|
||||
}
|
||||
|
||||
return Boxed_Value(data);
|
||||
} else {
|
||||
std::shared_ptr<To> data
|
||||
= std::dynamic_pointer_cast<To>(detail::Cast_Helper<std::shared_ptr<From> >::cast(t_from, nullptr));
|
||||
|
||||
if (!data)
|
||||
{
|
||||
throw std::bad_cast();
|
||||
}
|
||||
|
||||
return Boxed_Value(data);
|
||||
}
|
||||
} else {
|
||||
// Pull the reference out of the contained boxed value, which we know is the type we want
|
||||
if (t_from.is_const())
|
||||
{
|
||||
const From &d = detail::Cast_Helper<const From &>::cast(t_from, nullptr);
|
||||
const To &data = dynamic_cast<const To &>(d);
|
||||
return Boxed_Value(std::cref(data));
|
||||
} else {
|
||||
From &d = detail::Cast_Helper<From &>::cast(t_from, nullptr);
|
||||
To &data = dynamic_cast<To &>(d);
|
||||
return Boxed_Value(std::ref(data));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
throw chaiscript::exception::bad_boxed_dynamic_cast(t_from.get_type_info(), typeid(To), "Unknown dynamic_cast_conversion");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template<typename Base, typename Derived>
|
||||
class Dynamic_Conversion_Impl : public Type_Conversion_Base
|
||||
{
|
||||
public:
|
||||
Dynamic_Conversion_Impl()
|
||||
: Type_Conversion_Base(chaiscript::user_type<Base>(), chaiscript::user_type<Derived>())
|
||||
{
|
||||
}
|
||||
|
||||
virtual Boxed_Value convert_down(const Boxed_Value &t_base) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return Dynamic_Caster<Base, Derived>::cast(t_base);
|
||||
}
|
||||
|
||||
virtual Boxed_Value convert(const Boxed_Value &t_derived) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return Dynamic_Caster<Derived, Base>::cast(t_derived);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
template<typename Callable>
|
||||
class Type_Conversion_Impl : public Type_Conversion_Base
|
||||
{
|
||||
public:
|
||||
Type_Conversion_Impl(Type_Info t_from, Type_Info t_to, Callable t_func)
|
||||
: Type_Conversion_Base(std::move(t_to), std::move(t_from)),
|
||||
m_func(std::move(t_func))
|
||||
{
|
||||
}
|
||||
|
||||
virtual Boxed_Value convert_down(const Boxed_Value &) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
throw chaiscript::exception::bad_boxed_type_cast("No conversion exists");
|
||||
}
|
||||
|
||||
virtual Boxed_Value convert(const Boxed_Value &t_from) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
/// \todo better handling of errors from the conversion function
|
||||
return m_func(t_from);
|
||||
}
|
||||
|
||||
private:
|
||||
Callable m_func;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
class Type_Conversions
|
||||
{
|
||||
public:
|
||||
struct Less_Than
|
||||
{
|
||||
bool operator()(const std::type_info *t_lhs, const std::type_info *t_rhs) const
|
||||
{
|
||||
return *t_lhs != *t_rhs && t_lhs->before(*t_rhs);
|
||||
}
|
||||
};
|
||||
|
||||
Type_Conversions()
|
||||
: m_num_types(0),
|
||||
m_thread_cache(this),
|
||||
m_conversion_saves(this)
|
||||
{
|
||||
}
|
||||
|
||||
Type_Conversions(const Type_Conversions &t_other)
|
||||
: m_conversions(t_other.get_conversions()), m_num_types(m_conversions.size()),
|
||||
m_thread_cache(this),
|
||||
m_conversion_saves(this)
|
||||
|
||||
{
|
||||
}
|
||||
|
||||
const std::set<const std::type_info *, Less_Than> &thread_cache() const
|
||||
{
|
||||
auto &cache = *m_thread_cache;
|
||||
if (cache.size() != m_num_types)
|
||||
{
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
cache = m_convertableTypes;
|
||||
}
|
||||
|
||||
return cache;
|
||||
}
|
||||
|
||||
void add_conversion(const std::shared_ptr<detail::Type_Conversion_Base> &conversion)
|
||||
{
|
||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
/// \todo error if a conversion already exists
|
||||
m_conversions.insert(conversion);
|
||||
m_convertableTypes.insert({conversion->to().bare_type_info(), conversion->from().bare_type_info()});
|
||||
m_num_types = m_convertableTypes.size();
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool convertable_type() const
|
||||
{
|
||||
return thread_cache().count(user_type<T>().bare_type_info()) != 0;
|
||||
}
|
||||
|
||||
template<typename To, typename From>
|
||||
bool converts() const
|
||||
{
|
||||
return converts(user_type<To>(), user_type<From>());
|
||||
}
|
||||
|
||||
bool converts(const Type_Info &to, const Type_Info &from) const
|
||||
{
|
||||
const auto &types = thread_cache();
|
||||
if (types.count(to.bare_type_info()) != 0 && types.count(from.bare_type_info()) != 0)
|
||||
{
|
||||
return has_conversion(to, from) || has_conversion(from, to);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
template<typename To>
|
||||
Boxed_Value boxed_type_conversion(const Boxed_Value &from) const
|
||||
{
|
||||
try {
|
||||
Boxed_Value ret = get_conversion(user_type<To>(), from.get_type_info())->convert(from);
|
||||
if (m_conversion_saves->enabled) m_conversion_saves->saves.push_back(ret);
|
||||
return ret;
|
||||
} catch (const std::out_of_range &) {
|
||||
throw exception::bad_boxed_dynamic_cast(from.get_type_info(), typeid(To), "No known conversion");
|
||||
} catch (const std::bad_cast &) {
|
||||
throw exception::bad_boxed_dynamic_cast(from.get_type_info(), typeid(To), "Unable to perform dynamic_cast operation");
|
||||
}
|
||||
}
|
||||
|
||||
template<typename From>
|
||||
Boxed_Value boxed_type_down_conversion(const Boxed_Value &to) const
|
||||
{
|
||||
try {
|
||||
Boxed_Value ret = get_conversion(to.get_type_info(), user_type<From>())->convert_down(to);
|
||||
if (m_conversion_saves->enabled) m_conversion_saves->saves.push_back(ret);
|
||||
return ret;
|
||||
} catch (const std::out_of_range &) {
|
||||
throw exception::bad_boxed_dynamic_cast(to.get_type_info(), typeid(From), "No known conversion");
|
||||
} catch (const std::bad_cast &) {
|
||||
throw exception::bad_boxed_dynamic_cast(to.get_type_info(), typeid(From), "Unable to perform dynamic_cast operation");
|
||||
}
|
||||
}
|
||||
|
||||
void enable_conversion_saves(bool t_val)
|
||||
{
|
||||
m_conversion_saves->enabled = t_val;
|
||||
}
|
||||
|
||||
std::vector<Boxed_Value> take_saves()
|
||||
{
|
||||
std::vector<Boxed_Value> ret;
|
||||
std::swap(ret, m_conversion_saves->saves);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool has_conversion(const Type_Info &to, const Type_Info &from) const
|
||||
{
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
return find(to, from) != m_conversions.end();
|
||||
}
|
||||
|
||||
std::shared_ptr<detail::Type_Conversion_Base> get_conversion(const Type_Info &to, const Type_Info &from) const
|
||||
{
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
auto itr = find(to, from);
|
||||
|
||||
if (itr != m_conversions.end())
|
||||
{
|
||||
return *itr;
|
||||
} else {
|
||||
throw std::out_of_range("No such conversion exists from " + from.bare_name() + " to " + to.bare_name());
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::set<std::shared_ptr<detail::Type_Conversion_Base> >::const_iterator find(
|
||||
const Type_Info &to, const Type_Info &from) const
|
||||
{
|
||||
return std::find_if(m_conversions.begin(), m_conversions.end(),
|
||||
[&to, &from](const std::shared_ptr<detail::Type_Conversion_Base> &conversion)
|
||||
{
|
||||
return conversion->to().bare_equal(to) && conversion->from().bare_equal(from);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
std::set<std::shared_ptr<detail::Type_Conversion_Base>> get_conversions() const
|
||||
{
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
return m_conversions;
|
||||
}
|
||||
|
||||
|
||||
struct Conversion_Saves
|
||||
{
|
||||
Conversion_Saves()
|
||||
: enabled(false)
|
||||
{}
|
||||
|
||||
bool enabled;
|
||||
std::vector<Boxed_Value> saves;
|
||||
};
|
||||
|
||||
mutable chaiscript::detail::threading::shared_mutex m_mutex;
|
||||
std::set<std::shared_ptr<detail::Type_Conversion_Base>> m_conversions;
|
||||
std::set<const std::type_info *, Less_Than> m_convertableTypes;
|
||||
std::atomic_size_t m_num_types;
|
||||
chaiscript::detail::threading::Thread_Storage<std::set<const std::type_info *, Less_Than>> m_thread_cache;
|
||||
chaiscript::detail::threading::Thread_Storage<Conversion_Saves> m_conversion_saves;
|
||||
};
|
||||
|
||||
typedef std::shared_ptr<chaiscript::detail::Type_Conversion_Base> Type_Conversion;
|
||||
|
||||
/// \brief Used to register a to / parent class relationship with ChaiScript. Necessary if you
|
||||
/// want automatic conversions up your inheritance hierarchy.
|
||||
///
|
||||
/// Create a new to class registration for applying to a module or to the ChaiScript engine
|
||||
/// Currently, due to limitations in module loading on Windows, and for the sake of portability,
|
||||
/// if you have a type that is introduced in a loadable module and is used by multiple modules
|
||||
/// (through a tertiary dll that is shared between the modules, static linking the new type
|
||||
/// into both loadable modules would not be portable), you need to register the type
|
||||
/// relationship in all modules that use the newly added type in a polymorphic way.
|
||||
///
|
||||
/// Example:
|
||||
/// \code
|
||||
/// class Base
|
||||
/// {};
|
||||
/// class Derived : public Base
|
||||
/// {};
|
||||
///
|
||||
/// chaiscript::ChaiScript chai;
|
||||
/// chai.add(chaiscript::to_class<Base, Derived>());
|
||||
/// \endcode
|
||||
///
|
||||
template<typename Base, typename Derived>
|
||||
Type_Conversion base_class()
|
||||
{
|
||||
//Can only be used with related polymorphic types
|
||||
//may be expanded some day to support conversions other than child -> parent
|
||||
static_assert(std::is_base_of<Base,Derived>::value, "Classes are not related by inheritance");
|
||||
static_assert(std::is_polymorphic<Base>::value, "Base class must be polymorphic");
|
||||
static_assert(std::is_polymorphic<Derived>::value, "Derived class must be polymorphic");
|
||||
|
||||
return std::make_shared<detail::Dynamic_Conversion_Impl<Base, Derived>>();
|
||||
}
|
||||
|
||||
template<typename Callable>
|
||||
Type_Conversion type_conversion(const Type_Info &t_from, const Type_Info &t_to,
|
||||
const Callable &t_func)
|
||||
{
|
||||
return std::make_shared<detail::Type_Conversion_Impl<Callable>>(t_from, t_to, t_func);
|
||||
}
|
||||
|
||||
template<typename From, typename To, typename Callable>
|
||||
Type_Conversion type_conversion(const Callable &t_function)
|
||||
{
|
||||
auto func = [t_function](const Boxed_Value &t_bv) -> Boxed_Value {
|
||||
// not even attempting to call boxed_cast so that we don't get caught in some call recursion
|
||||
return chaiscript::Boxed_Value(t_function(detail::Cast_Helper<const From &>::cast(t_bv, nullptr)));
|
||||
};
|
||||
|
||||
return std::make_shared<detail::Type_Conversion_Impl<decltype(func)>>(user_type<From>(), user_type<To>(), func);
|
||||
}
|
||||
|
||||
template<typename From, typename To>
|
||||
Type_Conversion type_conversion()
|
||||
{
|
||||
static_assert(std::is_convertible<From, To>::value, "Types are not automatically convertible");
|
||||
auto func = [](const Boxed_Value &t_bv) -> Boxed_Value {
|
||||
// not even attempting to call boxed_cast so that we don't get caught in some call recursion
|
||||
auto &&from = detail::Cast_Helper<From>::cast(t_bv, nullptr);
|
||||
To to(from);
|
||||
return chaiscript::Boxed_Value(to);
|
||||
};
|
||||
|
||||
return std::make_shared<detail::Type_Conversion_Impl<decltype(func)>>(user_type<From>(), user_type<To>(), func);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif
|
@@ -111,11 +111,6 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
CHAISCRIPT_CONSTEXPR const std::type_info *bare_type_info() const
|
||||
{
|
||||
return m_bare_type_info;
|
||||
}
|
||||
|
||||
private:
|
||||
const std::type_info *m_type_info;
|
||||
const std::type_info *m_bare_type_info;
|
||||
|
@@ -37,7 +37,7 @@ namespace chaiscript
|
||||
Comparison, Addition, Subtraction, Multiplication, Division, Modulus, Array_Call, Dot_Access, Quoted_String, Single_Quoted_String,
|
||||
Lambda, Block, Def, While, If, For, Inline_Array, Inline_Map, Return, File, Prefix, Break, Continue, Map_Pair, Value_Range,
|
||||
Inline_Range, Annotation, Try, Catch, Finally, Method, Attr_Decl, Shift, Equality, Bitwise_And, Bitwise_Xor, Bitwise_Or,
|
||||
Logical_And, Logical_Or, Reference, Switch, Case, Default, Ternary_Cond, Noop, Class, Binary
|
||||
Logical_And, Logical_Or, Reference, Switch, Case, Default, Ternary_Cond, Noop, Class
|
||||
};
|
||||
};
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace chaiscript
|
||||
"Comparison", "Addition", "Subtraction", "Multiplication", "Division", "Modulus", "Array_Call", "Dot_Access", "Quoted_String", "Single_Quoted_String",
|
||||
"Lambda", "Block", "Def", "While", "If", "For", "Inline_Array", "Inline_Map", "Return", "File", "Prefix", "Break", "Continue", "Map_Pair", "Value_Range",
|
||||
"Inline_Range", "Annotation", "Try", "Catch", "Finally", "Method", "Attr_Decl", "Shift", "Equality", "Bitwise_And", "Bitwise_Xor", "Bitwise_Or",
|
||||
"Logical_And", "Logical_Or", "Reference", "Switch", "Case", "Default", "Ternary Condition", "Noop", "Class", "Binary"};
|
||||
"Logical_And", "Logical_Or", "Reference", "Switch", "Case", "Default", "Ternary Condition", "Noop"};
|
||||
|
||||
return ast_node_types[ast_node_type];
|
||||
}
|
||||
@@ -118,19 +118,19 @@ namespace chaiscript
|
||||
|
||||
ss << what();
|
||||
if (call_stack.size() > 0) {
|
||||
ss << "during evaluation at (" << fname(call_stack[0]) << " " << startpos(call_stack[0]) << ")\n";
|
||||
ss << '\n' << detail << '\n';
|
||||
ss << "during evaluation at (" << fname(call_stack[0]) << " " << startpos(call_stack[0]) << ")" << std::endl;
|
||||
ss << std::endl << detail << std::endl;
|
||||
ss << " " << fname(call_stack[0]) << " (" << startpos(call_stack[0]) << ") '" << pretty(call_stack[0]) << "'";
|
||||
for (size_t j = 1; j < call_stack.size(); ++j) {
|
||||
if (id(call_stack[j]) != chaiscript::AST_Node_Type::Block
|
||||
&& id(call_stack[j]) != chaiscript::AST_Node_Type::File)
|
||||
{
|
||||
ss << '\n';
|
||||
ss << std::endl;
|
||||
ss << " from " << fname(call_stack[j]) << " (" << startpos(call_stack[j]) << ") '" << pretty(call_stack[j]) << "'";
|
||||
}
|
||||
}
|
||||
}
|
||||
ss << '\n';
|
||||
ss << std::endl;
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
@@ -264,13 +264,13 @@ namespace chaiscript
|
||||
std::stringstream ss;
|
||||
if (t_functions.size() == 1)
|
||||
{
|
||||
ss << " Expected: " << format_types(t_functions[0], t_dot_notation, t_ss) << '\n';
|
||||
ss << " Expected: " << format_types(t_functions[0], t_dot_notation, t_ss) << std::endl;
|
||||
} else {
|
||||
ss << " " << t_functions.size() << " overloads available:\n";
|
||||
ss << " " << t_functions.size() << " overloads available:" << std::endl;
|
||||
|
||||
for (const auto & t_function : t_functions)
|
||||
{
|
||||
ss << " " << format_types((t_function), t_dot_notation, t_ss) << '\n';
|
||||
ss << " " << format_types((t_function), t_dot_notation, t_ss) << std::endl;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -430,7 +430,7 @@ namespace chaiscript
|
||||
std::ostringstream oss;
|
||||
|
||||
oss << t_prepend << "(" << ast_node_type_to_string(this->identifier) << ") "
|
||||
<< this->text << " : " << this->start.line << ", " << this->start.column << '\n';
|
||||
<< this->text << " : " << this->start.line << ", " << this->start.column << std::endl;
|
||||
|
||||
for (size_t j = 0; j < this->children.size(); ++j) {
|
||||
oss << this->children[j]->to_string(t_prepend + " ");
|
||||
@@ -549,11 +549,6 @@ namespace chaiscript
|
||||
m_de.save_function_params(t_params);
|
||||
}
|
||||
|
||||
void save_params(std::initializer_list<Boxed_Value> t_params)
|
||||
{
|
||||
m_de.save_function_params(std::move(t_params));
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
|
@@ -26,7 +26,7 @@
|
||||
#include "../dispatchkit/boxed_cast_helper.hpp"
|
||||
#include "../dispatchkit/boxed_value.hpp"
|
||||
#include "../dispatchkit/dispatchkit.hpp"
|
||||
#include "../dispatchkit/type_conversions.hpp"
|
||||
#include "../dispatchkit/dynamic_cast_conversion.hpp"
|
||||
#include "../dispatchkit/proxy_functions.hpp"
|
||||
#include "chaiscript_common.hpp"
|
||||
|
||||
@@ -353,13 +353,6 @@ namespace chaiscript
|
||||
|
||||
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_type_name, std::ref(m_engine)), "name");
|
||||
|
||||
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_type, std::ref(m_engine)), "type");
|
||||
m_engine.add(fun<void (const Type_Info &, const Type_Info &, const std::function<Boxed_Value (const Boxed_Value &)> &)> (
|
||||
[=](const Type_Info &t_from, const Type_Info &t_to, const std::function<Boxed_Value (const Boxed_Value &)> &t_func) {
|
||||
m_engine.add(chaiscript::type_conversion(t_from, t_to, t_func));
|
||||
}
|
||||
), "add_type_conversion");
|
||||
|
||||
|
||||
typedef std::string (ChaiScript::*load_mod_1)(const std::string&);
|
||||
typedef void (ChaiScript::*load_mod_2)(const std::string&, const std::string&);
|
||||
@@ -686,7 +679,7 @@ namespace chaiscript
|
||||
/// chaiscript::ChaiScript chai;
|
||||
/// chai.add(chaiscript::base_class<std::runtime_error, chaiscript::dispatch_error>());
|
||||
/// \endcode
|
||||
ChaiScript &add(const Type_Conversion &d)
|
||||
ChaiScript &add(const Dynamic_Cast_Conversion &d)
|
||||
{
|
||||
m_engine.add(d);
|
||||
return *this;
|
||||
@@ -735,11 +728,11 @@ namespace chaiscript
|
||||
{
|
||||
try {
|
||||
const auto name = elem + prefix + t_module_name + postfix;
|
||||
// std::cerr << "trying location: " << name << '\n';
|
||||
// std::cerr << "trying location: " << name << std::endl;
|
||||
load_module(version_stripped_name, name);
|
||||
return name;
|
||||
} catch (const chaiscript::exception::load_module_error &e) {
|
||||
// std::cerr << "error: " << e.what() << '\n';
|
||||
// std::cerr << "error: " << e.what() << std::endl;
|
||||
errors.push_back(e);
|
||||
// Try next set
|
||||
}
|
||||
|
@@ -63,21 +63,25 @@ namespace chaiscript
|
||||
|
||||
struct Binary_Operator_AST_Node : public AST_Node {
|
||||
public:
|
||||
Binary_Operator_AST_Node(const std::string &t_oper) :
|
||||
AST_Node(t_oper, AST_Node_Type::Binary, std::make_shared<std::string>(""), 0, 0, 0, 0),
|
||||
m_oper(Operators::to_operator(t_oper))
|
||||
Binary_Operator_AST_Node(std::string t_ast_node_text, int t_id, const std::shared_ptr<std::string> &t_fname, int t_start_line, int t_start_col, int t_end_line, int t_end_col) :
|
||||
AST_Node(std::move(t_ast_node_text), t_id, t_fname, t_start_line, t_start_col, t_end_line, t_end_col)
|
||||
{ }
|
||||
|
||||
virtual ~Binary_Operator_AST_Node() {}
|
||||
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE {
|
||||
return do_oper(t_ss, m_oper, text,
|
||||
return do_oper(t_ss, Operators::to_operator(children[1]->text), children[1]->text,
|
||||
this->children[0]->eval(t_ss),
|
||||
this->children[1]->eval(t_ss));
|
||||
this->children[2]->eval(t_ss));
|
||||
}
|
||||
|
||||
virtual std::string pretty_print() const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return "(" + this->children[0]->pretty_print() + " " + text + " " + this->children[1]->pretty_print() + ")";
|
||||
if (children.size() == 3)
|
||||
{
|
||||
return "(" + this->children[0]->pretty_print() + " " + this->children[1]->text + " " + this->children[2]->pretty_print() + ")";
|
||||
} else {
|
||||
return "(" + this->children[0]->pretty_print() + " " + text + " " + this->children[1]->pretty_print() + ")";
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
@@ -106,9 +110,6 @@ namespace chaiscript
|
||||
throw exception::eval_error("Can not find appropriate '" + t_oper_string + "' operator.", e.parameters, e.functions, false, t_ss);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Operators::Opers m_oper;
|
||||
};
|
||||
|
||||
struct Int_AST_Node : public AST_Node {
|
||||
@@ -291,7 +292,6 @@ namespace chaiscript
|
||||
virtual ~Inplace_Fun_Call_AST_Node() {}
|
||||
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{
|
||||
std::vector<Boxed_Value> params;
|
||||
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
|
||||
|
||||
if ((this->children.size() > 1) && (this->children[1]->identifier == AST_Node_Type::Arg_List)) {
|
||||
for (const auto &child : this->children[1]->children) {
|
||||
@@ -315,6 +315,8 @@ namespace chaiscript
|
||||
}
|
||||
catch(const exception::bad_boxed_cast &){
|
||||
// handle the case where there is only 1 function to try to call and dispatch fails on it
|
||||
std::vector<Const_Proxy_Function> funcs;
|
||||
funcs.push_back(fn);
|
||||
throw exception::eval_error("Error calling function '" + this->children[0]->text + "'", params, {fn}, false, t_ss);
|
||||
}
|
||||
catch(const exception::arity_error &e){
|
||||
@@ -379,7 +381,6 @@ namespace chaiscript
|
||||
|
||||
virtual ~Equation_AST_Node() {}
|
||||
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE {
|
||||
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
|
||||
Boxed_Value retval = this->children.back()->eval(t_ss);
|
||||
|
||||
|
||||
@@ -452,7 +453,7 @@ namespace chaiscript
|
||||
{
|
||||
return this->children[0]->eval(t_ss);
|
||||
} else {
|
||||
const std::string &idname = this->children[0]->text;
|
||||
std::string idname = this->children[0]->text;
|
||||
|
||||
Boxed_Value bv;
|
||||
try {
|
||||
@@ -475,6 +476,72 @@ namespace chaiscript
|
||||
|
||||
};
|
||||
|
||||
struct Comparison_AST_Node : public Binary_Operator_AST_Node {
|
||||
public:
|
||||
Comparison_AST_Node(std::string t_ast_node_text = "", const std::shared_ptr<std::string> &t_fname=std::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
||||
Binary_Operator_AST_Node(std::move(t_ast_node_text), AST_Node_Type::Comparison, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
|
||||
virtual ~Comparison_AST_Node() {}
|
||||
};
|
||||
|
||||
struct Addition_AST_Node : public Binary_Operator_AST_Node {
|
||||
public:
|
||||
Addition_AST_Node(std::string t_ast_node_text = "+",
|
||||
const std::shared_ptr<std::string> &t_fname=std::shared_ptr<std::string>(),
|
||||
int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
||||
Binary_Operator_AST_Node(std::move(t_ast_node_text), AST_Node_Type::Addition, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
|
||||
virtual ~Addition_AST_Node() {}
|
||||
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE {
|
||||
return do_oper(t_ss, Operators::sum, "+", this->children[0]->eval(t_ss), this->children[1]->eval(t_ss));
|
||||
}
|
||||
};
|
||||
|
||||
struct Subtraction_AST_Node : public Binary_Operator_AST_Node {
|
||||
public:
|
||||
Subtraction_AST_Node(std::string t_ast_node_text = "-",
|
||||
const std::shared_ptr<std::string> &t_fname=std::shared_ptr<std::string>(), int t_start_line = 0,
|
||||
int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
||||
Binary_Operator_AST_Node(std::move(t_ast_node_text), AST_Node_Type::Subtraction, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
|
||||
virtual ~Subtraction_AST_Node() {}
|
||||
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE {
|
||||
return do_oper(t_ss, Operators::difference, "-", this->children[0]->eval(t_ss), this->children[1]->eval(t_ss));
|
||||
}
|
||||
};
|
||||
|
||||
struct Multiplication_AST_Node : public Binary_Operator_AST_Node {
|
||||
public:
|
||||
Multiplication_AST_Node(std::string t_ast_node_text = "*",
|
||||
const std::shared_ptr<std::string> &t_fname=std::shared_ptr<std::string>(), int t_start_line = 0,
|
||||
int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
||||
Binary_Operator_AST_Node(std::move(t_ast_node_text), AST_Node_Type::Multiplication, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
|
||||
virtual ~Multiplication_AST_Node() {}
|
||||
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE {
|
||||
return do_oper(t_ss, Operators::product, "*", this->children[0]->eval(t_ss), this->children[1]->eval(t_ss));
|
||||
}
|
||||
};
|
||||
|
||||
struct Division_AST_Node : public Binary_Operator_AST_Node {
|
||||
public:
|
||||
Division_AST_Node(std::string t_ast_node_text = "/",
|
||||
const std::shared_ptr<std::string> &t_fname=std::shared_ptr<std::string>(), int t_start_line = 0,
|
||||
int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
||||
Binary_Operator_AST_Node(std::move(t_ast_node_text), AST_Node_Type::Division, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
|
||||
virtual ~Division_AST_Node() {}
|
||||
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE {
|
||||
return do_oper(t_ss, Operators::quotient, "/", this->children[0]->eval(t_ss), this->children[1]->eval(t_ss));
|
||||
}
|
||||
};
|
||||
|
||||
struct Modulus_AST_Node : public Binary_Operator_AST_Node {
|
||||
public:
|
||||
Modulus_AST_Node(std::string t_ast_node_text = "%",
|
||||
const std::shared_ptr<std::string> &t_fname=std::shared_ptr<std::string>(), int t_start_line = 0,
|
||||
int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
||||
Binary_Operator_AST_Node(std::move(t_ast_node_text), AST_Node_Type::Modulus, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
|
||||
virtual ~Modulus_AST_Node() {}
|
||||
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE {
|
||||
return do_oper(t_ss, Operators::remainder, "%", this->children[0]->eval(t_ss), this->children[1]->eval(t_ss));
|
||||
}
|
||||
};
|
||||
|
||||
struct Array_Call_AST_Node : public AST_Node {
|
||||
public:
|
||||
@@ -527,11 +594,11 @@ namespace chaiscript
|
||||
AST_Node(t_ast_node_text, AST_Node_Type::Dot_Access, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
|
||||
virtual ~Dot_Access_AST_Node() {}
|
||||
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &t_ss) const CHAISCRIPT_OVERRIDE{
|
||||
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
|
||||
Boxed_Value retval = this->children[0]->eval(t_ss);
|
||||
|
||||
if (this->children.size() > 1) {
|
||||
for (size_t i = 2; i < this->children.size(); i+=2) {
|
||||
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
|
||||
std::vector<Boxed_Value> params{retval};
|
||||
|
||||
if (this->children[i]->children.size() > 1) {
|
||||
@@ -1076,9 +1143,8 @@ namespace chaiscript
|
||||
|
||||
struct Prefix_AST_Node : public AST_Node {
|
||||
public:
|
||||
Prefix_AST_Node(Operators::Opers t_oper) :
|
||||
AST_Node("", AST_Node_Type::Prefix, std::make_shared<std::string>(""), 0, 0, 0, 0),
|
||||
m_oper(t_oper)
|
||||
Prefix_AST_Node(std::string t_ast_node_text = "", const std::shared_ptr<std::string> &t_fname=std::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
||||
AST_Node(std::move(t_ast_node_text), AST_Node_Type::Prefix, t_fname, t_start_line, t_start_col, t_end_line, t_end_col)
|
||||
{ }
|
||||
|
||||
virtual ~Prefix_AST_Node() {}
|
||||
@@ -1086,11 +1152,12 @@ namespace chaiscript
|
||||
chaiscript::eval::detail::Function_Push_Pop fpp(t_ss);
|
||||
Boxed_Value bv(this->children[1]->eval(t_ss));
|
||||
|
||||
Operators::Opers oper = Operators::to_operator(children[0]->text, true);
|
||||
try {
|
||||
// short circuit arithmetic operations
|
||||
if (m_oper != Operators::invalid && bv.get_type_info().is_arithmetic())
|
||||
if (bv.get_type_info().is_arithmetic() && oper != Operators::invalid)
|
||||
{
|
||||
return Boxed_Number::do_oper(m_oper, std::move(bv));
|
||||
return Boxed_Number::do_oper(oper, std::move(bv));
|
||||
} else {
|
||||
chaiscript::eval::detail::Stack_Push_Pop spp(t_ss);
|
||||
fpp.save_params({bv});
|
||||
@@ -1101,8 +1168,6 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
Operators::Opers m_oper;
|
||||
};
|
||||
|
||||
struct Break_AST_Node : public AST_Node {
|
||||
@@ -1446,6 +1511,40 @@ namespace chaiscript
|
||||
|
||||
};
|
||||
|
||||
struct Shift_AST_Node : public Binary_Operator_AST_Node {
|
||||
public:
|
||||
Shift_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr<std::string> &t_fname=std::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
||||
Binary_Operator_AST_Node(t_ast_node_text, AST_Node_Type::Shift, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
|
||||
virtual ~Shift_AST_Node() {}
|
||||
};
|
||||
|
||||
struct Equality_AST_Node : public Binary_Operator_AST_Node {
|
||||
public:
|
||||
Equality_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr<std::string> &t_fname=std::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
||||
Binary_Operator_AST_Node(t_ast_node_text, AST_Node_Type::Equality, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
|
||||
virtual ~Equality_AST_Node() {}
|
||||
};
|
||||
|
||||
struct Bitwise_And_AST_Node : public Binary_Operator_AST_Node {
|
||||
public:
|
||||
Bitwise_And_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr<std::string> &t_fname=std::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
||||
Binary_Operator_AST_Node(t_ast_node_text, AST_Node_Type::Bitwise_And, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
|
||||
virtual ~Bitwise_And_AST_Node() {}
|
||||
};
|
||||
|
||||
struct Bitwise_Xor_AST_Node : public Binary_Operator_AST_Node {
|
||||
public:
|
||||
Bitwise_Xor_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr<std::string> &t_fname=std::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
||||
Binary_Operator_AST_Node(t_ast_node_text, AST_Node_Type::Bitwise_Xor, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
|
||||
virtual ~Bitwise_Xor_AST_Node() {}
|
||||
};
|
||||
|
||||
struct Bitwise_Or_AST_Node : public Binary_Operator_AST_Node {
|
||||
public:
|
||||
Bitwise_Or_AST_Node(const std::string &t_ast_node_text = "", const std::shared_ptr<std::string> &t_fname=std::shared_ptr<std::string>(), int t_start_line = 0, int t_start_col = 0, int t_end_line = 0, int t_end_col = 0) :
|
||||
Binary_Operator_AST_Node(t_ast_node_text, AST_Node_Type::Bitwise_Or, t_fname, t_start_line, t_start_col, t_end_line, t_end_col) { }
|
||||
virtual ~Bitwise_Or_AST_Node() {}
|
||||
};
|
||||
|
||||
struct Logical_And_AST_Node : public AST_Node {
|
||||
public:
|
||||
|
@@ -171,7 +171,7 @@ namespace chaiscript
|
||||
/// Prints the parsed ast_nodes as a tree
|
||||
/*
|
||||
void debug_print(AST_NodePtr t, std::string prepend = "") {
|
||||
std::cout << prepend << "(" << ast_node_type_to_string(t->identifier) << ") " << t->text << " : " << t->start.line << ", " << t->start.column << '\n';
|
||||
std::cout << prepend << "(" << ast_node_type_to_string(t->identifier) << ") " << t->text << " : " << t->start.line << ", " << t->start.column << std::endl;
|
||||
for (unsigned int j = 0; j < t->children.size(); ++j) {
|
||||
debug_print(t->children[j], prepend + " ");
|
||||
}
|
||||
@@ -266,27 +266,16 @@ namespace chaiscript
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/// Skips ChaiScript whitespace, which means space and tab, but not cr/lf
|
||||
/// jespada: Modified SkipWS to skip optionally CR ('\n') and/or LF+CR ("\r\n")
|
||||
bool SkipWS(bool skip_cr=false) {
|
||||
/// jespada: Modified SkipWS to skip optionally CR ('\n')
|
||||
bool SkipWS(const bool skip_cr=false) {
|
||||
bool retval = false;
|
||||
|
||||
while (has_more_input()) {
|
||||
auto end_line = (*m_input_pos != 0) && ((*m_input_pos == '\n') || (*m_input_pos == '\r' && *(m_input_pos+1) == '\n'));
|
||||
|
||||
if ( char_in_alphabet(*m_input_pos,detail::white_alphabet) || (skip_cr && end_line)) {
|
||||
|
||||
if(end_line) {
|
||||
if ( char_in_alphabet(*m_input_pos,detail::white_alphabet) || (skip_cr && (*m_input_pos == '\n'))) {
|
||||
if(*m_input_pos == '\n') {
|
||||
m_col = 1;
|
||||
++m_line;
|
||||
|
||||
if(*(m_input_pos) == '\r') {
|
||||
// discards lf
|
||||
++m_input_pos;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
++m_col;
|
||||
}
|
||||
++m_input_pos;
|
||||
@@ -295,14 +284,14 @@ namespace chaiscript
|
||||
}
|
||||
else if (SkipComment()) {
|
||||
retval = true;
|
||||
} else {
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
/// Reads a floating point value from input, without skipping initial whitespace
|
||||
bool Float_() {
|
||||
if (has_more_input() && char_in_alphabet(*m_input_pos,detail::float_alphabet) ) {
|
||||
@@ -787,7 +776,7 @@ namespace chaiscript
|
||||
//If we've seen previous interpolation, add on instead of making a new one
|
||||
m_match_stack.push_back(std::make_shared<eval::Quoted_String_AST_Node>(match, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
|
||||
build_match(std::make_shared<eval::Binary_Operator_AST_Node>("+"), prev_stack_top);
|
||||
build_match(std::make_shared<eval::Addition_AST_Node>(), prev_stack_top);
|
||||
} else {
|
||||
m_match_stack.push_back(std::make_shared<eval::Quoted_String_AST_Node>(match, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
}
|
||||
@@ -824,7 +813,7 @@ namespace chaiscript
|
||||
build_match(std::make_shared<eval::Inplace_Fun_Call_AST_Node>(), ev_stack_top);
|
||||
build_match(std::make_shared<eval::Arg_List_AST_Node>(), ev_stack_top);
|
||||
build_match(std::make_shared<eval::Fun_Call_AST_Node>(), tostr_stack_top);
|
||||
build_match(std::make_shared<eval::Binary_Operator_AST_Node>("+"), prev_stack_top);
|
||||
build_match(std::make_shared<eval::Addition_AST_Node>(), prev_stack_top);
|
||||
} else {
|
||||
throw exception::eval_error("Unclosed in-string eval", File_Position(prev_line, prev_col), *m_filename);
|
||||
}
|
||||
@@ -867,7 +856,7 @@ namespace chaiscript
|
||||
if (is_interpolated) {
|
||||
m_match_stack.push_back(std::make_shared<eval::Quoted_String_AST_Node>(match, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
|
||||
build_match(std::make_shared<eval::Binary_Operator_AST_Node>("+"), prev_stack_top);
|
||||
build_match(std::make_shared<eval::Addition_AST_Node>(), prev_stack_top);
|
||||
} else {
|
||||
m_match_stack.push_back(std::make_shared<eval::Quoted_String_AST_Node>(match, m_filename, prev_line, prev_col, m_line, m_col));
|
||||
}
|
||||
@@ -1835,24 +1824,72 @@ namespace chaiscript
|
||||
|
||||
/// Reads a unary prefixed expression from input
|
||||
bool Prefix() {
|
||||
bool retval = false;
|
||||
|
||||
const auto prev_stack_top = m_match_stack.size();
|
||||
const std::vector<std::string> prefix_opers{"++", "--", "-", "+", "!", "~", "&"};
|
||||
|
||||
for (const auto &oper : prefix_opers)
|
||||
{
|
||||
bool is_char = oper.size() == 1;
|
||||
if ((is_char && Char(oper[0], true)) || (!is_char && Symbol(oper.c_str(), true)))
|
||||
{
|
||||
if (!Operator(m_operators.size()-1)) {
|
||||
throw exception::eval_error("Incomplete prefix '" + oper + "' expression", File_Position(m_line, m_col), *m_filename);
|
||||
}
|
||||
if (Symbol("++", true)) {
|
||||
retval = true;
|
||||
|
||||
build_match(std::make_shared<eval::Prefix_AST_Node>(Operators::to_operator(oper, true)), prev_stack_top);
|
||||
return true;
|
||||
if (!Operator(m_operators.size()-1)) {
|
||||
throw exception::eval_error("Incomplete '++' expression", File_Position(m_line, m_col), *m_filename);
|
||||
}
|
||||
|
||||
build_match(std::make_shared<eval::Prefix_AST_Node>(), prev_stack_top);
|
||||
} else if (Symbol("--", true)) {
|
||||
retval = true;
|
||||
|
||||
if (!Operator(m_operators.size()-1)) {
|
||||
throw exception::eval_error("Incomplete '--' expression", File_Position(m_line, m_col), *m_filename);
|
||||
}
|
||||
|
||||
build_match(std::make_shared<eval::Prefix_AST_Node>(), prev_stack_top);
|
||||
} else if (Char('-', true)) {
|
||||
retval = true;
|
||||
|
||||
if (!Operator(m_operators.size()-1)) {
|
||||
throw exception::eval_error("Incomplete unary '-' expression", File_Position(m_line, m_col), *m_filename);
|
||||
}
|
||||
|
||||
build_match(std::make_shared<eval::Prefix_AST_Node>(), prev_stack_top);
|
||||
} else if (Char('+', true)) {
|
||||
retval = true;
|
||||
|
||||
if (!Operator(m_operators.size()-1)) {
|
||||
throw exception::eval_error("Incomplete unary '+' expression", File_Position(m_line, m_col), *m_filename);
|
||||
}
|
||||
|
||||
build_match(std::make_shared<eval::Prefix_AST_Node>(), prev_stack_top);
|
||||
}
|
||||
else if (Char('!', true)) {
|
||||
retval = true;
|
||||
|
||||
if (!Operator(m_operators.size()-1)) {
|
||||
throw exception::eval_error("Incomplete '!' expression", File_Position(m_line, m_col), *m_filename);
|
||||
}
|
||||
|
||||
build_match(std::make_shared<eval::Prefix_AST_Node>(), prev_stack_top);
|
||||
}
|
||||
else if (Char('~', true)) {
|
||||
retval = true;
|
||||
|
||||
if (!Operator(m_operators.size()-1)) {
|
||||
throw exception::eval_error("Incomplete '~' expression", File_Position(m_line, m_col), *m_filename);
|
||||
}
|
||||
|
||||
build_match(std::make_shared<eval::Prefix_AST_Node>(), prev_stack_top);
|
||||
}
|
||||
else if (Char('&', true)) {
|
||||
retval = true;
|
||||
|
||||
if (!Operator(m_operators.size()-1)) {
|
||||
throw exception::eval_error("Incomplete '~' expression", File_Position(m_line, m_col), *m_filename);
|
||||
}
|
||||
|
||||
build_match(std::make_shared<eval::Prefix_AST_Node>(), prev_stack_top);
|
||||
}
|
||||
|
||||
return false;
|
||||
return retval;
|
||||
}
|
||||
|
||||
/// Parses any of a group of 'value' style ast_node groups from input
|
||||
@@ -1875,6 +1912,7 @@ namespace chaiscript
|
||||
|
||||
bool Operator(const size_t t_precedence = 0) {
|
||||
bool retval = false;
|
||||
AST_NodePtr oper;
|
||||
const auto prev_stack_top = m_match_stack.size();
|
||||
|
||||
if (t_precedence < m_operators.size()) {
|
||||
@@ -1889,9 +1927,10 @@ namespace chaiscript
|
||||
File_Position(m_line, m_col), *m_filename);
|
||||
}
|
||||
|
||||
AST_NodePtr oper = m_match_stack.at(m_match_stack.size()-2);
|
||||
|
||||
switch (m_operators[t_precedence]) {
|
||||
case(AST_Node_Type::Comparison) :
|
||||
build_match(std::make_shared<eval::Comparison_AST_Node>(), prev_stack_top);
|
||||
break;
|
||||
case(AST_Node_Type::Ternary_Cond) :
|
||||
m_match_stack.erase(m_match_stack.begin() + m_match_stack.size() - 2,
|
||||
m_match_stack.begin() + m_match_stack.size() - 1);
|
||||
@@ -1909,26 +1948,52 @@ namespace chaiscript
|
||||
File_Position(m_line, m_col), *m_filename);
|
||||
}
|
||||
break;
|
||||
|
||||
case(AST_Node_Type::Addition) :
|
||||
case(AST_Node_Type::Multiplication) :
|
||||
case(AST_Node_Type::Shift) :
|
||||
case(AST_Node_Type::Equality) :
|
||||
case(AST_Node_Type::Bitwise_And) :
|
||||
case(AST_Node_Type::Bitwise_Xor) :
|
||||
case(AST_Node_Type::Bitwise_Or) :
|
||||
case(AST_Node_Type::Comparison) :
|
||||
m_match_stack.erase(m_match_stack.begin() + m_match_stack.size() - 2, m_match_stack.begin() + m_match_stack.size() - 1);
|
||||
build_match(std::make_shared<eval::Binary_Operator_AST_Node>(oper->text), prev_stack_top);
|
||||
oper = m_match_stack.at(m_match_stack.size()-2);
|
||||
m_match_stack.erase(m_match_stack.begin() + m_match_stack.size() - 2,
|
||||
m_match_stack.begin() + m_match_stack.size() - 1);
|
||||
if (oper->text == "+") {
|
||||
build_match(std::make_shared<eval::Addition_AST_Node>(), prev_stack_top);
|
||||
}
|
||||
else if (oper->text == "-") {
|
||||
build_match(std::make_shared<eval::Subtraction_AST_Node>(), prev_stack_top);
|
||||
}
|
||||
break;
|
||||
case(AST_Node_Type::Multiplication) :
|
||||
oper = m_match_stack.at(m_match_stack.size()-2);
|
||||
m_match_stack.erase(m_match_stack.begin() + m_match_stack.size() - 2,
|
||||
m_match_stack.begin() + m_match_stack.size() - 1);
|
||||
if (oper->text == "*") {
|
||||
build_match(std::make_shared<eval::Multiplication_AST_Node>(), prev_stack_top);
|
||||
}
|
||||
else if (oper->text == "/") {
|
||||
build_match(std::make_shared<eval::Division_AST_Node>(), prev_stack_top);
|
||||
}
|
||||
else if (oper->text == "%") {
|
||||
build_match(std::make_shared<eval::Modulus_AST_Node>(), prev_stack_top);
|
||||
}
|
||||
break;
|
||||
case(AST_Node_Type::Shift) :
|
||||
build_match(std::make_shared<eval::Shift_AST_Node>(), prev_stack_top);
|
||||
break;
|
||||
case(AST_Node_Type::Equality) :
|
||||
build_match(std::make_shared<eval::Equality_AST_Node>(), prev_stack_top);
|
||||
break;
|
||||
case(AST_Node_Type::Bitwise_And) :
|
||||
build_match(std::make_shared<eval::Bitwise_And_AST_Node>(), prev_stack_top);
|
||||
break;
|
||||
case(AST_Node_Type::Bitwise_Xor) :
|
||||
build_match(std::make_shared<eval::Bitwise_Xor_AST_Node>(), prev_stack_top);
|
||||
break;
|
||||
case(AST_Node_Type::Bitwise_Or) :
|
||||
build_match(std::make_shared<eval::Bitwise_Or_AST_Node>(), prev_stack_top);
|
||||
break;
|
||||
|
||||
case(AST_Node_Type::Logical_And) :
|
||||
build_match(std::make_shared<eval::Logical_And_AST_Node>(), prev_stack_top);
|
||||
break;
|
||||
case(AST_Node_Type::Logical_Or) :
|
||||
build_match(std::make_shared<eval::Logical_Or_AST_Node>(), prev_stack_top);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw exception::eval_error("Internal error: unhandled ast_node", File_Position(m_line, m_col), *m_filename);
|
||||
}
|
||||
@@ -2035,7 +2100,14 @@ namespace chaiscript
|
||||
while (has_more) {
|
||||
const auto prev_line = m_line;
|
||||
const auto prev_col = m_col;
|
||||
if (Def(true) || Var_Decl(true)) {
|
||||
if (Def(true)) {
|
||||
if (!saw_eol) {
|
||||
throw exception::eval_error("Two function definitions missing line separator", File_Position(prev_line, prev_col), *m_filename);
|
||||
}
|
||||
has_more = true;
|
||||
retval = true;
|
||||
saw_eol = true;
|
||||
} else if (Var_Decl(true)) {
|
||||
if (!saw_eol) {
|
||||
throw exception::eval_error("Two function definitions missing line separator", File_Position(prev_line, prev_col), *m_filename);
|
||||
}
|
||||
@@ -2064,7 +2136,7 @@ namespace chaiscript
|
||||
while (has_more) {
|
||||
int prev_line = m_line;
|
||||
int prev_col = m_col;
|
||||
if (Def() || Try() || If() || While() || Class() || For() || Switch()) {
|
||||
if (Def()) {
|
||||
if (!saw_eol) {
|
||||
throw exception::eval_error("Two function definitions missing line separator", File_Position(prev_line, prev_col), *m_filename);
|
||||
}
|
||||
@@ -2072,7 +2144,55 @@ namespace chaiscript
|
||||
retval = true;
|
||||
saw_eol = true;
|
||||
}
|
||||
else if (Return() || Break() || Continue() || Equation()) {
|
||||
else if (Try()) {
|
||||
if (!saw_eol) {
|
||||
throw exception::eval_error("Two function definitions missing line separator", File_Position(prev_line, prev_col), *m_filename);
|
||||
}
|
||||
has_more = true;
|
||||
retval = true;
|
||||
saw_eol = true;
|
||||
}
|
||||
else if (If()) {
|
||||
if (!saw_eol) {
|
||||
throw exception::eval_error("Two function definitions missing line separator", File_Position(prev_line, prev_col), *m_filename);
|
||||
}
|
||||
has_more = true;
|
||||
retval = true;
|
||||
saw_eol = true;
|
||||
}
|
||||
else if (While()) {
|
||||
if (!saw_eol) {
|
||||
throw exception::eval_error("Two function definitions missing line separator", File_Position(prev_line, prev_col), *m_filename);
|
||||
}
|
||||
has_more = true;
|
||||
retval = true;
|
||||
saw_eol = true;
|
||||
}
|
||||
else if (Class()) {
|
||||
if (!saw_eol) {
|
||||
throw exception::eval_error("Two function definitions missing line separator", File_Position(prev_line, prev_col), *m_filename);
|
||||
}
|
||||
has_more = true;
|
||||
retval = true;
|
||||
saw_eol = true;
|
||||
}
|
||||
else if (For()) {
|
||||
if (!saw_eol) {
|
||||
throw exception::eval_error("Two function definitions missing line separator", File_Position(prev_line, prev_col), *m_filename);
|
||||
}
|
||||
has_more = true;
|
||||
retval = true;
|
||||
saw_eol = true;
|
||||
}
|
||||
else if (Switch()) {
|
||||
if (!saw_eol) {
|
||||
throw exception::eval_error("Two function definitions missing line separator", File_Position(prev_line, prev_col), *m_filename);
|
||||
}
|
||||
has_more = true;
|
||||
retval = true;
|
||||
saw_eol = true;
|
||||
}
|
||||
else if (Return()) {
|
||||
if (!saw_eol) {
|
||||
throw exception::eval_error("Two expressions missing line separator", File_Position(prev_line, prev_col), *m_filename);
|
||||
}
|
||||
@@ -2080,7 +2200,36 @@ namespace chaiscript
|
||||
retval = true;
|
||||
saw_eol = false;
|
||||
}
|
||||
else if (Block() || Eol()) {
|
||||
else if (Break()) {
|
||||
if (!saw_eol) {
|
||||
throw exception::eval_error("Two expressions missing line separator", File_Position(prev_line, prev_col), *m_filename);
|
||||
}
|
||||
has_more = true;
|
||||
retval = true;
|
||||
saw_eol = false;
|
||||
}
|
||||
else if (Continue()) {
|
||||
if (!saw_eol) {
|
||||
throw exception::eval_error("Two expressions missing line separator", File_Position(prev_line, prev_col), *m_filename);
|
||||
}
|
||||
has_more = true;
|
||||
retval = true;
|
||||
saw_eol = false;
|
||||
}
|
||||
else if (Block()) {
|
||||
has_more = true;
|
||||
retval = true;
|
||||
saw_eol = true;
|
||||
}
|
||||
else if (Equation()) {
|
||||
if (!saw_eol) {
|
||||
throw exception::eval_error("Two expressions missing line separator", File_Position(prev_line, prev_col), *m_filename);
|
||||
}
|
||||
has_more = true;
|
||||
retval = true;
|
||||
saw_eol = false;
|
||||
}
|
||||
else if (Eol()) {
|
||||
has_more = true;
|
||||
retval = true;
|
||||
saw_eol = true;
|
||||
|
@@ -16,8 +16,6 @@ Release under the BSD license, see "license.txt" for details.
|
||||
Introduction
|
||||
============
|
||||
|
||||
[](https://gitter.im/ChaiScript/ChaiScript?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
||||
|
||||
ChaiScript is one of the only embedded scripting language designed from the
|
||||
ground up to directly target C++ and take advantage of modern C++ development
|
||||
techniques, working with the developer like he expects it to work. Being a
|
||||
|
@@ -1,20 +1,6 @@
|
||||
Notes:
|
||||
=======
|
||||
Current Version: 5.5.1
|
||||
|
||||
### Changes since 5.5.0
|
||||
* 30% performance increase
|
||||
* Fix handling of object stack, resulting in greatly reduced memory usage
|
||||
* Code cleanups
|
||||
|
||||
### Changes since 5.4.0
|
||||
* 2x performance increase
|
||||
* Significant code cleanups
|
||||
* Throw exception if user attempts to call function on null object
|
||||
* Allow user defined type conversions
|
||||
* Fix object lifetime for nested function calls made at the global scope
|
||||
* Fix returning of boolean values from function calls
|
||||
|
||||
Current Version: 5.4.0
|
||||
|
||||
### Changes since 5.3.1
|
||||
* Decreased compile time and build size
|
||||
|
@@ -13,12 +13,12 @@
|
||||
|
||||
void log(const std::string &msg)
|
||||
{
|
||||
std::cout << "[" << time(nullptr) << "] " << msg << '\n';
|
||||
std::cout << "[" << time(nullptr) << "] " << msg << std::endl;
|
||||
}
|
||||
|
||||
void log(const std::string &module, const std::string &msg)
|
||||
{
|
||||
std::cout << "[" << time(nullptr) << "] <" << module << "> " << msg << '\n';
|
||||
std::cout << "[" << time(nullptr) << "] <" << module << "> " << msg << std::endl;
|
||||
}
|
||||
|
||||
void bound_log(const std::string &msg)
|
||||
@@ -28,12 +28,12 @@ void bound_log(const std::string &msg)
|
||||
|
||||
void hello_world(const chaiscript::Boxed_Value & /*o*/)
|
||||
{
|
||||
std::cout << "Hello World\n";
|
||||
std::cout << "Hello World" << std::endl;
|
||||
}
|
||||
|
||||
void hello_constructor(const chaiscript::Boxed_Value & /*o*/)
|
||||
{
|
||||
std::cout << "Hello Constructor\n";
|
||||
std::cout << "Hello Constructor" << std::endl;
|
||||
}
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ struct System
|
||||
|
||||
void take_shared_ptr(const std::shared_ptr<const std::string> &p)
|
||||
{
|
||||
std::cout << *p << '\n';
|
||||
std::cout << *p << std::endl;
|
||||
}
|
||||
|
||||
int main(int /*argc*/, char * /*argv*/[]) {
|
||||
@@ -122,7 +122,7 @@ int main(int /*argc*/, char * /*argv*/[]) {
|
||||
//the templated version of eval:
|
||||
int i = chai.eval<int>("5+5");
|
||||
|
||||
std::cout << "5+5: " << i << '\n';
|
||||
std::cout << "5+5: " << i << std::endl;
|
||||
|
||||
//Add a new variable
|
||||
chai("var scripti = 15");
|
||||
@@ -130,9 +130,9 @@ int main(int /*argc*/, char * /*argv*/[]) {
|
||||
//We can even get a handle to the variables in the system
|
||||
int &scripti = chai.eval<int &>("scripti");
|
||||
|
||||
std::cout << "scripti: " << scripti << '\n';
|
||||
std::cout << "scripti: " << scripti << std::endl;
|
||||
scripti *= 2;
|
||||
std::cout << "scripti (updated): " << scripti << '\n';
|
||||
std::cout << "scripti (updated): " << scripti << std::endl;
|
||||
chai("print(\"Scripti from chai: \" + to_string(scripti))");
|
||||
|
||||
//To do: Add examples of handling Boxed_Values directly when needed
|
||||
|
@@ -1,4 +0,0 @@
|
||||
for (var i = 0; i < 1000; ++i) {
|
||||
puts(helloWorld("Bob12345"))
|
||||
}
|
||||
|
@@ -1,407 +0,0 @@
|
||||
// This file is distributed under the BSD License.
|
||||
// See "license.txt" for details.
|
||||
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
|
||||
// Copyright 2009-2014, Jason Turner (jason@emptycrate.com)
|
||||
// http://www.chaiscript.com
|
||||
|
||||
#include <iostream>
|
||||
#include <list>
|
||||
#include <regex>
|
||||
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
#include <chaiscript/chaiscript_stdlib.hpp>
|
||||
|
||||
#ifdef READLINE_AVAILABLE
|
||||
#include <readline/readline.h>
|
||||
#include <readline/history.h>
|
||||
#else
|
||||
|
||||
char *mystrdup(const char *s) {
|
||||
size_t len = strlen(s); // Space for length plus nul
|
||||
char *d = static_cast<char*>(malloc(len + 1));
|
||||
if (d == nullptr) return nullptr; // No memory
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
strcpy_s(d, len + 1, s); // Copy the characters
|
||||
#else
|
||||
strncpy(d, s, len); // Copy the characters
|
||||
#endif
|
||||
d[len] = '\0';
|
||||
return d; // Return the new string
|
||||
}
|
||||
|
||||
char* readline(const char* p)
|
||||
{
|
||||
std::string retval;
|
||||
std::cout << p;
|
||||
std::getline(std::cin, retval);
|
||||
return std::cin.eof() ? nullptr : mystrdup(retval.c_str());
|
||||
}
|
||||
|
||||
|
||||
void add_history(const char*){}
|
||||
void using_history(){}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
void *cast_module_symbol(std::vector<std::string>(*t_path)())
|
||||
{
|
||||
union cast_union
|
||||
{
|
||||
std::vector<std::string>(*in_ptr)();
|
||||
void *out_ptr;
|
||||
};
|
||||
|
||||
cast_union c;
|
||||
c.in_ptr = t_path;
|
||||
return c.out_ptr;
|
||||
}
|
||||
|
||||
std::vector<std::string> default_search_paths()
|
||||
{
|
||||
std::vector<std::string> paths;
|
||||
|
||||
#ifdef CHAISCRIPT_WINDOWS // force no unicode
|
||||
CHAR path[4096];
|
||||
int size = GetModuleFileNameA(0, path, sizeof(path) - 1);
|
||||
|
||||
std::string exepath(path, size);
|
||||
|
||||
size_t lastslash = exepath.rfind('\\');
|
||||
size_t secondtolastslash = exepath.rfind('\\', lastslash - 1);
|
||||
if (lastslash != std::string::npos)
|
||||
{
|
||||
paths.push_back(exepath.substr(0, lastslash));
|
||||
}
|
||||
|
||||
if (secondtolastslash != std::string::npos)
|
||||
{
|
||||
return{ exepath.substr(0, secondtolastslash) + "\\lib\\chaiscript\\" };
|
||||
}
|
||||
#else
|
||||
|
||||
std::string exepath;
|
||||
|
||||
std::vector<char> buf(2048);
|
||||
ssize_t size = -1;
|
||||
|
||||
if ((size = readlink("/proc/self/exe", &buf.front(), buf.size())) != -1)
|
||||
{
|
||||
exepath = std::string(&buf.front(), size);
|
||||
}
|
||||
|
||||
if (exepath.empty())
|
||||
{
|
||||
if ((size = readlink("/proc/curproc/file", &buf.front(), buf.size())) != -1)
|
||||
{
|
||||
exepath = std::string(&buf.front(), size);
|
||||
}
|
||||
}
|
||||
|
||||
if (exepath.empty())
|
||||
{
|
||||
if ((size = readlink("/proc/self/path/a.out", &buf.front(), buf.size())) != -1)
|
||||
{
|
||||
exepath = std::string(&buf.front(), size);
|
||||
}
|
||||
}
|
||||
|
||||
if (exepath.empty())
|
||||
{
|
||||
Dl_info rInfo;
|
||||
memset(&rInfo, 0, sizeof(rInfo));
|
||||
if (!dladdr(cast_module_symbol(&default_search_paths), &rInfo) || !rInfo.dli_fname) {
|
||||
return paths;
|
||||
}
|
||||
|
||||
exepath = std::string(rInfo.dli_fname);
|
||||
}
|
||||
|
||||
size_t lastslash = exepath.rfind('/');
|
||||
|
||||
size_t secondtolastslash = exepath.rfind('/', lastslash - 1);
|
||||
if (lastslash != std::string::npos)
|
||||
{
|
||||
paths.push_back(exepath.substr(0, lastslash));
|
||||
}
|
||||
|
||||
if (secondtolastslash != std::string::npos)
|
||||
{
|
||||
paths.push_back(exepath.substr(0, secondtolastslash) + "/lib/chaiscript/");
|
||||
}
|
||||
#endif
|
||||
|
||||
return 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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
void version(int){
|
||||
std::cout << "chai: compiled " << __TIME__ << " " << __DATE__ << std::endl;
|
||||
}
|
||||
|
||||
std::string helloWorld(const std::string &t_name)
|
||||
{
|
||||
return "Hello " + t_name + "!";
|
||||
}
|
||||
|
||||
bool throws_exception(const std::function<void()> &f)
|
||||
{
|
||||
try {
|
||||
f();
|
||||
}
|
||||
catch (...) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
chaiscript::exception::eval_error get_eval_error(const std::function<void()> &f)
|
||||
{
|
||||
try {
|
||||
f();
|
||||
}
|
||||
catch (const chaiscript::exception::eval_error &e) {
|
||||
return e;
|
||||
}
|
||||
|
||||
throw std::runtime_error("no exception throw");
|
||||
}
|
||||
|
||||
std::string get_next_command() {
|
||||
std::string retval("quit");
|
||||
if (!std::cin.eof()) {
|
||||
char *input_raw = readline("eval> ");
|
||||
if (input_raw) {
|
||||
add_history(input_raw);
|
||||
|
||||
std::string val(input_raw);
|
||||
size_t pos = val.find_first_not_of("\t \n");
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
val.erase(0, pos);
|
||||
}
|
||||
pos = val.find_last_not_of("\t \n");
|
||||
if (pos != std::string::npos)
|
||||
{
|
||||
val.erase(pos + 1, std::string::npos);
|
||||
}
|
||||
|
||||
retval = val;
|
||||
|
||||
::free(input_raw);
|
||||
}
|
||||
}
|
||||
if (retval == "quit"
|
||||
|| retval == "exit"
|
||||
|| retval == "help"
|
||||
|| retval == "version")
|
||||
{
|
||||
retval += "(0)";
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
// We have to wrap exit with our own because Clang has a hard time with
|
||||
// function pointers to functions with special attributes (system exit being marked NORETURN)
|
||||
void myexit(int return_val) {
|
||||
exit(return_val);
|
||||
}
|
||||
|
||||
void interactive(chaiscript::ChaiScript& chai)
|
||||
{
|
||||
using_history();
|
||||
|
||||
for (;;) {
|
||||
std::string input = get_next_command();
|
||||
try {
|
||||
// evaluate input
|
||||
chaiscript::Boxed_Value val = chai.eval(input);
|
||||
|
||||
//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;
|
||||
}
|
||||
catch (...) {} //If we can't, do nothing
|
||||
}
|
||||
}
|
||||
catch (const chaiscript::exception::eval_error &ee) {
|
||||
std::cout << ee.what();
|
||||
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;
|
||||
}
|
||||
catch (const std::exception &e) {
|
||||
std::cout << e.what();
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
|
||||
// Disable deprecation warning for getenv call.
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4996)
|
||||
#endif
|
||||
|
||||
const char *usepath = getenv("CHAI_USE_PATH");
|
||||
const char *modulepath = getenv("CHAI_MODULE_PATH");
|
||||
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
std::vector<std::string> usepaths;
|
||||
usepaths.push_back("");
|
||||
if (usepath)
|
||||
{
|
||||
usepaths.push_back(usepath);
|
||||
}
|
||||
|
||||
std::vector<std::string> modulepaths;
|
||||
std::vector<std::string> searchpaths = default_search_paths();
|
||||
modulepaths.insert(modulepaths.end(), searchpaths.begin(), searchpaths.end());
|
||||
modulepaths.push_back("");
|
||||
if (modulepath)
|
||||
{
|
||||
modulepaths.push_back(modulepath);
|
||||
}
|
||||
|
||||
//chaiscript::ChaiScript chai(modulepaths, usepaths);
|
||||
chaiscript::ChaiScript chai(chaiscript::Std_Lib::library(), usepaths);
|
||||
|
||||
chai.add(chaiscript::fun(&myexit), "exit");
|
||||
chai.add(chaiscript::fun(&myexit), "quit");
|
||||
chai.add(chaiscript::fun(&help), "help");
|
||||
chai.add(chaiscript::fun(&version), "version");
|
||||
chai.add(chaiscript::fun(&throws_exception), "throws_exception");
|
||||
chai.add(chaiscript::fun(&get_eval_error), "get_eval_error");
|
||||
|
||||
chai.add(chaiscript::fun(&helloWorld), "helloWorld");
|
||||
|
||||
clock_t begin = clock();
|
||||
|
||||
for (int i = 0; i < 1000; i++)
|
||||
{
|
||||
std::string str = helloWorld("Bob12345");
|
||||
fwrite(str.c_str(), 1, str.size(), stdout);
|
||||
}
|
||||
|
||||
clock_t end = clock();
|
||||
double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
|
||||
|
||||
//begin = clock();
|
||||
|
||||
////for (int i = 0; i < 1000; i++)
|
||||
////{
|
||||
//// chai.eval("puts(helloWorld(\"Bob12345\"));");
|
||||
////}
|
||||
//chai.eval_file("E:\\C++\\ChaiScript - 5.4.0\\samples\forx.chai");
|
||||
|
||||
//end = clock();
|
||||
//elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
|
||||
//printf("**MyProgram::time= %lf\n", elapsed_secs);
|
||||
|
||||
for (int i = 0; i < argc; ++i) {
|
||||
if (i == 0 && argc > 1) {
|
||||
++i;
|
||||
}
|
||||
|
||||
std::string arg(i ? argv[i] : "--interactive");
|
||||
|
||||
enum {
|
||||
eInteractive
|
||||
, eCommand
|
||||
, eFile
|
||||
} mode = eCommand;
|
||||
|
||||
if (arg == "-c" || arg == "--command") {
|
||||
if ((i + 1) >= argc) {
|
||||
std::cout << "insufficient input following " << arg << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
else {
|
||||
arg = argv[++i];
|
||||
}
|
||||
}
|
||||
else if (arg == "-" || arg == "--stdin") {
|
||||
arg = "";
|
||||
std::string line;
|
||||
while (std::getline(std::cin, line)) {
|
||||
arg += line + '\n';
|
||||
}
|
||||
}
|
||||
else if (arg == "-v" || arg == "--version") {
|
||||
arg = "version(0)";
|
||||
}
|
||||
else if (arg == "-h" || arg == "--help") {
|
||||
arg = "help(-1)";
|
||||
}
|
||||
else if (arg == "-i" || arg == "--interactive") {
|
||||
mode = eInteractive;
|
||||
}
|
||||
else if (arg.find('-') == 0) {
|
||||
std::cout << "unrecognised argument " << arg << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
else {
|
||||
mode = eFile;
|
||||
}
|
||||
|
||||
chaiscript::Boxed_Value val;
|
||||
try {
|
||||
switch (mode) {
|
||||
case eInteractive: interactive(chai); break;
|
||||
case eCommand: val = chai.eval(arg); break;
|
||||
case eFile: {
|
||||
begin = clock();
|
||||
|
||||
val = chai.eval_file(arg);
|
||||
|
||||
end = clock();
|
||||
double elapsed_secs1 = double(end - begin) / CLOCKS_PER_SEC;
|
||||
printf("**C++::time= %.10f\n", elapsed_secs);
|
||||
printf("**ChaiScript::time= %.10f\n", elapsed_secs1);
|
||||
break;
|
||||
}
|
||||
default: std::cout << "Unrecognized execution mode" << std::endl; return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
catch (const chaiscript::exception::eval_error &ee) {
|
||||
std::cout << ee.pretty_print();
|
||||
std::cout << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
std::cout << e.what() << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@@ -8,7 +8,7 @@ class BaseClass
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~BaseClass() {}
|
||||
virtual ~BaseClass() = default;
|
||||
|
||||
virtual std::string doSomething(float, double) const = 0;
|
||||
|
||||
@@ -42,14 +42,14 @@ class ChaiScriptDerived : public BaseClass
|
||||
tie(t_funcs.at(1), m_validateValueImpl);
|
||||
}
|
||||
|
||||
std::string doSomething(float f, double d) const CHAISCRIPT_OVERRIDE
|
||||
std::string doSomething(float f, double d) const override
|
||||
{
|
||||
assert(m_doSomethingImpl);
|
||||
return m_doSomethingImpl(*this, f, d);
|
||||
}
|
||||
|
||||
protected:
|
||||
bool validateValue(const std::string &t_val) CHAISCRIPT_OVERRIDE
|
||||
bool validateValue(const std::string &t_val) override
|
||||
{
|
||||
assert(m_validateValueImpl);
|
||||
return m_validateValueImpl(*this, t_val);
|
||||
|
@@ -54,7 +54,7 @@ class test
|
||||
chaiscript::Boxed_Value val = chai.eval_file(sFile);
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
std::cout << e.what() << '\n';
|
||||
std::cout << e.what() << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
42
src/main.cpp
42
src/main.cpp
@@ -136,24 +136,24 @@ 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>.\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";
|
||||
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;
|
||||
} else {
|
||||
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';
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
void version(int){
|
||||
std::cout << "chai: compiled " << __TIME__ << " " << __DATE__ << '\n';
|
||||
std::cout << "chai: compiled " << __TIME__ << " " << __DATE__ << std::endl;
|
||||
}
|
||||
|
||||
bool throws_exception(const std::function<void ()> &f)
|
||||
@@ -231,7 +231,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) << '\n';
|
||||
std::cout << chai.eval<std::function<std::string (const chaiscript::Boxed_Value &bv)> >("to_string")(val) << std::endl;
|
||||
}
|
||||
catch (...) {} //If we can't, do nothing
|
||||
}
|
||||
@@ -241,11 +241,11 @@ 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 << '\n';
|
||||
std::cout << std::endl;
|
||||
}
|
||||
catch (const std::exception &e) {
|
||||
std::cout << e.what();
|
||||
std::cout << '\n';
|
||||
std::cout << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -305,7 +305,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
if ( arg == "-c" || arg == "--command" ) {
|
||||
if ( (i+1) >= argc ) {
|
||||
std::cout << "insufficient input following " << arg << '\n';
|
||||
std::cout << "insufficient input following " << arg << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
arg = argv[++i];
|
||||
@@ -323,7 +323,7 @@ int main(int argc, char *argv[])
|
||||
} else if ( arg == "-i" || arg == "--interactive" ) {
|
||||
mode = eInteractive ;
|
||||
} else if ( arg.find('-') == 0 ) {
|
||||
std::cout << "unrecognised argument " << arg << '\n';
|
||||
std::cout << "unrecognised argument " << arg << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
} else {
|
||||
mode = eFile;
|
||||
@@ -335,16 +335,16 @@ int main(int argc, char *argv[])
|
||||
case eInteractive : interactive(chai); break;
|
||||
case eCommand : val = chai.eval(arg); break;
|
||||
case eFile : val = chai.eval_file(arg); break;
|
||||
default : std::cout << "Unrecognized execution mode\n"; return EXIT_FAILURE;
|
||||
default : std::cout << "Unrecognized execution mode" << std::endl; return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
catch (const chaiscript::exception::eval_error &ee) {
|
||||
std::cout << ee.pretty_print();
|
||||
std::cout << '\n';
|
||||
std::cout << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
catch (std::exception &e) {
|
||||
std::cout << e.what() << '\n';
|
||||
std::cout << e.what() << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
@@ -2,8 +2,6 @@
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
#include <string>
|
||||
|
||||
|
||||
|
||||
class TestBaseType
|
||||
{
|
||||
public:
|
||||
@@ -24,30 +22,6 @@ class TestBaseType
|
||||
TestBaseType &operator=(const TestBaseType &);
|
||||
};
|
||||
|
||||
class Type2
|
||||
{
|
||||
public:
|
||||
Type2(TestBaseType t_bt)
|
||||
: m_bt(std::move(t_bt)),
|
||||
m_str("Hello World")
|
||||
{
|
||||
}
|
||||
|
||||
int get_val() const
|
||||
{
|
||||
return m_bt.val;
|
||||
}
|
||||
|
||||
const char *get_str() const
|
||||
{
|
||||
return m_str.c_str();
|
||||
}
|
||||
|
||||
private:
|
||||
TestBaseType m_bt;
|
||||
std::string m_str;
|
||||
};
|
||||
|
||||
enum TestEnum
|
||||
{
|
||||
TestValue1 = 1
|
||||
@@ -121,7 +95,6 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo
|
||||
m->add(chaiscript::user_type<TestBaseType>(), "TestBaseType");
|
||||
m->add(chaiscript::user_type<TestDerivedType>(), "TestDerivedType");
|
||||
m->add(chaiscript::user_type<TestMoreDerivedType>(), "TestMoreDerivedType");
|
||||
m->add(chaiscript::user_type<Type2>(), "Type2");
|
||||
|
||||
m->add(chaiscript::constructor<TestBaseType ()>(), "TestBaseType");
|
||||
// m->add(chaiscript::constructor<TestBaseType (int)>(), "TestBaseType");
|
||||
@@ -162,12 +135,6 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo
|
||||
m->add(chaiscript::fun(&to_int), "to_int");
|
||||
m->add(chaiscript::fun(&TestBaseType::constMe), "constMe");
|
||||
|
||||
m->add(chaiscript::type_conversion<TestBaseType, Type2>([](const TestBaseType &t_bt) { return Type2(t_bt); }));
|
||||
|
||||
m->add(chaiscript::fun(&Type2::get_val), "get_val");
|
||||
m->add(chaiscript::fun(&Type2::get_str), "get_str");
|
||||
m->add(chaiscript::type_conversion<const char *, std::string>());
|
||||
m->add(chaiscript::constructor<Type2 (const TestBaseType &)>(), "Type2");
|
||||
|
||||
return m;
|
||||
}
|
||||
|
@@ -15,16 +15,16 @@ bool run_test_type_conversion(const Boxed_Value &bv, bool expectedpass)
|
||||
use(ret);
|
||||
} catch (const chaiscript::exception::bad_boxed_cast &/*e*/) {
|
||||
if (expectedpass) {
|
||||
// std::cerr << "Failure in run_test_type_conversion: " << e.what() << '\n';
|
||||
// std::cerr << "Failure in run_test_type_conversion: " << e.what() << std::endl;
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} catch (const std::exception &e) {
|
||||
std::cerr << "Unexpected standard exception when attempting cast_conversion: " << e.what() << '\n';
|
||||
std::cerr << "Unexpected standard exception when attempting cast_conversion: " << e.what() << std::endl;
|
||||
return false;
|
||||
} catch (...) {
|
||||
std::cerr << "Unexpected unknown exception when attempting cast_conversion.\n";
|
||||
std::cerr << "Unexpected unknown exception when attempting cast_conversion." << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ bool test_type_conversion(const Boxed_Value &bv, bool expectedpass)
|
||||
<< (bv.is_const()?(std::string("const ")):(std::string())) << bv.get_type_info().name()
|
||||
<< " To: "
|
||||
<< (std::is_const<To>::value?(std::string("const ")):(std::string())) << typeid(To).name()
|
||||
<< " test was expected to " << ((expectedpass)?(std::string("succeed")):(std::string("fail"))) << " but did not\n";
|
||||
<< " test was expected to " << ((expectedpass)?(std::string("succeed")):(std::string("fail"))) << " but did not" << std::endl;
|
||||
}
|
||||
|
||||
return ret;
|
||||
@@ -264,21 +264,21 @@ bool pointer_test(const T& default_value, const T& new_value)
|
||||
|
||||
|
||||
if (p != (*result) ) {
|
||||
std::cerr << "Pointer passed in different than one returned\n";
|
||||
std::cerr << "Pointer passed in different than one returned" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (*p != *(*result) ) {
|
||||
std::cerr << "Somehow dereferenced pointer values are not the same?\n";
|
||||
std::cerr << "Somehow dereferenced pointer values are not the same?" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (const exception::bad_boxed_cast &) {
|
||||
std::cerr << "Bad boxed cast performing ** to ** test\n";
|
||||
std::cerr << "Bad boxed cast performing ** to ** test" << std::endl;
|
||||
return false;
|
||||
} catch (...) {
|
||||
std::cerr << "Unknown exception performing ** to ** test\n";
|
||||
std::cerr << "Unknown exception performing ** to ** test" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@@ -8,7 +8,7 @@ void assert_equal(const LHS &lhs, const RHS &rhs)
|
||||
{
|
||||
return;
|
||||
} else {
|
||||
std::cout << "Got: " << lhs << " expected " << rhs << '\n';
|
||||
std::cout << "Got: " << lhs << " expected " << rhs << std::endl;
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
|
@@ -16,7 +16,7 @@ int test_generic()
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "test_generic failed\n";
|
||||
std::cout << "test_generic failed" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ int test_1()
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "test_1 failed\n";
|
||||
std::cout << "test_1 failed" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ int test_2()
|
||||
}
|
||||
}
|
||||
|
||||
std::cout << "test_2 failed\n";
|
||||
std::cout << "test_2 failed" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
@@ -61,22 +61,22 @@ int test_5()
|
||||
try {
|
||||
chai.eval("throw(runtime_error(\"error\"))", chaiscript::exception_specification<int, double, float, const std::string &, const std::exception &>());
|
||||
} catch (const double) {
|
||||
std::cout << "test_5 failed with double\n";
|
||||
std::cout << "test_5 failed with double" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
} catch (int) {
|
||||
std::cout << "test_5 failed with int\n";
|
||||
std::cout << "test_5 failed with int" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
} catch (float) {
|
||||
std::cout << "test_5 failed with float\n";
|
||||
std::cout << "test_5 failed with float" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
} catch (const std::string &) {
|
||||
std::cout << "test_5 failed with string\n";
|
||||
std::cout << "test_5 failed with string" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
} catch (const std::exception &) {
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
std::cout << "test_5 failed\n";
|
||||
std::cout << "test_5 failed" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
@@ -87,22 +87,22 @@ int test_unhandled()
|
||||
try {
|
||||
chai.eval("throw(\"error\")", chaiscript::exception_specification<int, double, float, const std::exception &>());
|
||||
} catch (double) {
|
||||
std::cout << "test_unhandled failed with double\n";
|
||||
std::cout << "test_unhandled failed with double" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
} catch (int) {
|
||||
std::cout << "test_unhandled failed with int\n";
|
||||
std::cout << "test_unhandled failed with int" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
} catch (float) {
|
||||
std::cout << "test_unhandled failed with float\n";
|
||||
std::cout << "test_unhandled failed with float" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
} catch (const std::exception &) {
|
||||
std::cout << "test_unhandled failed with std::exception\n";
|
||||
std::cout << "test_unhandled failed with std::exception" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
} catch (const chaiscript::Boxed_Value &) {
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
std::cout << "test_unhandled failed\n";
|
||||
std::cout << "test_unhandled failed" << std::endl;
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
|
@@ -7,7 +7,7 @@ bool test_literal(T val, const std::string &str)
|
||||
{
|
||||
chaiscript::ChaiScript chai;
|
||||
T val2 = chai.eval<T>(str);
|
||||
std::cout << "Comparing : " << val << " " << val2 << '\n';
|
||||
std::cout << "Comparing : " << val << " " << val2 << std::endl;
|
||||
return val == val2;
|
||||
}
|
||||
|
||||
|
@@ -1,69 +0,0 @@
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
#include <chaiscript/chaiscript_stdlib.hpp>
|
||||
|
||||
template<typename T>
|
||||
struct Vector2
|
||||
{
|
||||
Vector2() : x(0), y(0) {};
|
||||
Vector2(T px, T py) : x(px), y(py) {};
|
||||
Vector2(const Vector2& cp) : x(cp.x), y(cp.y) {};
|
||||
|
||||
Vector2& operator+=(const Vector2& vec_r)
|
||||
{
|
||||
x += vec_r.x;
|
||||
y += vec_r.y;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Vector2 operator+(const Vector2& vec_r)
|
||||
{
|
||||
return Vector2(*this += vec_r);
|
||||
}
|
||||
|
||||
void operator=(const Vector2& ver_r)
|
||||
{
|
||||
x = ver_r.x;
|
||||
y = ver_r.y;
|
||||
}
|
||||
|
||||
|
||||
T x;
|
||||
T y;
|
||||
};
|
||||
|
||||
Vector2<float> GetValue()
|
||||
{
|
||||
return Vector2<float>(10,15);
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
chaiscript::ChaiScript _script(chaiscript::Std_Lib::library());
|
||||
|
||||
//Registering stuff
|
||||
_script.add(chaiscript::user_type<Vector2<float>>(), "Vector2f");
|
||||
_script.add(chaiscript::constructor<Vector2<float> ()>(), "Vector2f");
|
||||
_script.add(chaiscript::constructor<Vector2<float> (float, float)>(), "Vector2f");
|
||||
_script.add(chaiscript::constructor<Vector2<float> (const Vector2<float>&)>(), "Vector2f");
|
||||
_script.add(chaiscript::fun(&Vector2<float>::x), "x");
|
||||
_script.add(chaiscript::fun(&Vector2<float>::y), "y");
|
||||
_script.add(chaiscript::fun(&Vector2<float>::operator +), "+");
|
||||
_script.add(chaiscript::fun(&Vector2<float>::operator +=), "+=");
|
||||
_script.add(chaiscript::fun(&Vector2<float>::operator =), "=");
|
||||
_script.add(chaiscript::fun(&GetValue), "getValue");
|
||||
|
||||
_script.eval(R"(
|
||||
var test = 0.0
|
||||
var test2 = Vector2f(10,10)
|
||||
|
||||
test = getValue().x
|
||||
print(test)
|
||||
print(test2.x)
|
||||
)");
|
||||
|
||||
if (_script.eval<std::string>("to_string(test)") != "10") { return EXIT_FAILURE; }
|
||||
if (_script.eval<std::string>("to_string(test2.x)") != "10") { return EXIT_FAILURE; }
|
||||
|
||||
|
||||
//_script.eval_file("object_lifetime_test2.inc");
|
||||
}
|
@@ -31,7 +31,7 @@ int main()
|
||||
test_type(chaiscript::user_type<const int *>(), true, true, false, false, false);
|
||||
test_type(chaiscript::Type_Info(), false, false, false, false, true);
|
||||
|
||||
std::cout << "Size of Type_Info " << sizeof(chaiscript::Type_Info) << '\n';
|
||||
std::cout << "Size of Type_Info " << sizeof(chaiscript::Type_Info) << std::endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
@@ -1,11 +0,0 @@
|
||||
|
||||
add_type_conversion(type("string"), type("Type_Info"), fun(s) { return type(s); });
|
||||
|
||||
// This looks simple, but it takes the string "string" and using the registered
|
||||
// conversion above, automatically converts that into a Type_Info object, which then
|
||||
// allows the Type_Info.name() function to be called
|
||||
|
||||
assert_equal("string".name(), "string");
|
||||
|
||||
|
||||
|
@@ -1,27 +0,0 @@
|
||||
load_module("test_module")
|
||||
|
||||
auto t := TestBaseType();
|
||||
|
||||
// This uses the TestBaseType to Type2 user type
|
||||
// conversion which was added in the module and then calls
|
||||
// "get_val()" which exists on the Type2 type
|
||||
//assert_equal(t.get_val(), 10);
|
||||
//print("Made it past test 1");
|
||||
|
||||
var t2 := Type2(t);
|
||||
var str = string(get_str(t2));
|
||||
|
||||
assert_equal("Hello World", str);
|
||||
print("Made it past test 2");
|
||||
|
||||
assert_equal(11, size(get_str(t2)));
|
||||
print("Made it past test 3");
|
||||
|
||||
|
||||
assert_equal(11, t2.get_str().size());
|
||||
print("Made it past test 4");
|
||||
|
||||
assert_equal(11, t.get_str().size());
|
||||
print("Made it past test 5");
|
||||
|
||||
|
Reference in New Issue
Block a user