Merge pull request #144 from ChaiScript/develop
Merge release 5.5.0 to master
This commit is contained in:
commit
4a3315cfd1
13
.decent_ci-Linux.yaml
Normal file
13
.decent_ci-Linux.yaml
Normal file
@ -0,0 +1,13 @@
|
||||
compilers:
|
||||
- name: "clang"
|
||||
version: "3.5"
|
||||
cmake_extra_flags: -DUSE_LIBCXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING: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"
|
||||
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
|
||||
|
7
.decent_ci-MacOS.yaml
Normal file
7
.decent_ci-MacOS.yaml
Normal file
@ -0,0 +1,7 @@
|
||||
compilers:
|
||||
- name: clang
|
||||
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=$COMMIT_SHA
|
||||
- name: clang
|
||||
build_type: Debug
|
||||
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=$COMMIT_SHA
|
||||
|
20
.decent_ci-Windows.yaml
Normal file
20
.decent_ci-Windows.yaml
Normal file
@ -0,0 +1,20 @@
|
||||
compilers:
|
||||
- name: Visual Studio
|
||||
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
|
||||
- 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
|
||||
- name: Visual Studio
|
||||
version: 12
|
||||
cmake_extra_flags: -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DCOMMIT_SHA=%COMMIT_SHA%
|
||||
compiler_extra_flags: /ANALYZE
|
||||
- name: Visual Studio
|
||||
version: 12
|
||||
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
|
||||
|
4
.decent_ci.yaml
Normal file
4
.decent_ci.yaml
Normal file
@ -0,0 +1,4 @@
|
||||
results_repository : ChaiScript/ChaiScript-BuildResults
|
||||
results_path : _posts
|
||||
results_base_url : https://chaiscript.github.io/ChaiScript-BuildResults
|
||||
aging_pull_requests_notification: true
|
@ -36,11 +36,38 @@ 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}")
|
||||
@ -54,7 +81,7 @@ 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 4)
|
||||
set(CPACK_PACKAGE_VERSION_MINOR 5)
|
||||
set(CPACK_PACKAGE_VERSION_PATCH 0)
|
||||
|
||||
set(CPACK_PACKAGE_EXECUTABLES "chai;ChaiScript Eval")
|
||||
@ -154,7 +181,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/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(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_source_files_properties(${Chai_INCLUDES} PROPERTIES HEADER_FILE_ONLY TRUE)
|
||||
|
||||
@ -203,6 +230,8 @@ if(BUILD_SAMPLES)
|
||||
target_link_libraries(example ${LIBS})
|
||||
add_executable(memory_leak_test samples/memory_leak_test.cpp)
|
||||
target_link_libraries(memory_leak_test ${LIBS})
|
||||
add_executable(inheritance samples/inheritance.cpp)
|
||||
target_link_libraries(inheritance ${LIBS})
|
||||
endif()
|
||||
|
||||
|
||||
|
@ -4,9 +4,9 @@ pushd ..
|
||||
wget http://sourceforge.net/projects/cppcheck/files/cppcheck/1.66/cppcheck-1.66.tar.bz2
|
||||
tar -xvf cppcheck-1.66.tar.bz2
|
||||
cd cppcheck-1.66
|
||||
make -j2
|
||||
CXX=g++-4.8 make -j2
|
||||
popd
|
||||
../cppcheck-1.65/cppcheck --enable=all -I include --inline-suppr --std=c++11 --platform=unix64 src/main.cpp src/chai*.cpp --template ' - __{severity}__: [{file}:{line}](../blob/TRAVIS_COMMIT/{file}#L{line}) {message} ({id})' 2>output
|
||||
../cppcheck-1.66/cppcheck --enable=all -I include --inline-suppr --suppress=missingIncludeSystem --std=c++11 --platform=unix64 src/main.cpp src/chai*.cpp --template ' - __{severity}__: [{file}:{line}](../blob/TRAVIS_COMMIT/{file}#L{line}) {message} ({id})' 2>output
|
||||
sed -i "s/TRAVIS_COMMIT/${TRAVIS_COMMIT}/g" output
|
||||
echo -n '{ "body": " ' > output.json
|
||||
echo -n `awk '{printf "%s\\\\n", $0;}' output` >> output.json
|
||||
|
@ -75,7 +75,7 @@
|
||||
///
|
||||
/// @subsection compiling Compiling ChaiScript Applications
|
||||
///
|
||||
/// ChaiScript is a header only library with only one dependecy: The
|
||||
/// ChaiScript is a header only library with only one dependency: The
|
||||
/// operating system provided dynamic library loader, which has to be specified on some platforms.
|
||||
///
|
||||
/// @subsubsection compilinggcc Compiling with GCC
|
||||
@ -112,7 +112,7 @@
|
||||
///
|
||||
/// @subsubsection evalmethod Method 'eval'
|
||||
///
|
||||
/// The eval method is somewhat more verbose and can be used to get typesafely return values
|
||||
/// The eval method is somewhat more verbose and can be used to get type safely return values
|
||||
/// from the script.
|
||||
///
|
||||
/// ~~~~~~~~{.cpp}
|
||||
@ -311,7 +311,7 @@
|
||||
/// As much as possible, ChaiScript attempts to convert between &, *, const &, const *, std::shared_ptr<T>,
|
||||
/// std::shared_ptr<const T>, std::reference_wrapper<T>, std::reference_wrapper<const T> and value types automatically.
|
||||
///
|
||||
/// If a chaiscript::var object was created in C++ from a pointer, it cannot be convered to a shared_ptr (this would add invalid reference counting).
|
||||
/// If a chaiscript::var object was created in C++ from a pointer, it cannot be converted to a shared_ptr (this would add invalid reference counting).
|
||||
/// Const may be added, but never removed.
|
||||
///
|
||||
/// The take away is that you can pretty much expect function calls to Just Work when you need them to.
|
||||
|
@ -45,7 +45,7 @@
|
||||
|
||||
namespace chaiscript {
|
||||
static const int version_major = 5;
|
||||
static const int version_minor = 4;
|
||||
static const int version_minor = 5;
|
||||
static const int version_patch = 0;
|
||||
}
|
||||
|
||||
|
@ -28,7 +28,7 @@ namespace chaiscript {
|
||||
|
||||
virtual ~bad_any_cast() CHAISCRIPT_NOEXCEPT {}
|
||||
|
||||
/// \brief Description of what error occured
|
||||
/// \brief Description of what error occurred
|
||||
virtual const char * what() const CHAISCRIPT_NOEXCEPT CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return m_what.c_str();
|
||||
@ -52,6 +52,7 @@ namespace chaiscript {
|
||||
Data &operator=(const Data &) = delete;
|
||||
|
||||
virtual ~Data() {}
|
||||
|
||||
virtual void *data() = 0;
|
||||
const std::type_info &type() const
|
||||
{
|
||||
@ -65,7 +66,7 @@ namespace chaiscript {
|
||||
template<typename T>
|
||||
struct Data_Impl : Data
|
||||
{
|
||||
Data_Impl(T t_type)
|
||||
explicit Data_Impl(T t_type)
|
||||
: Data(typeid(T)),
|
||||
m_data(std::move(t_type))
|
||||
{
|
||||
@ -104,12 +105,19 @@ namespace chaiscript {
|
||||
}
|
||||
}
|
||||
|
||||
template<typename ValueType>
|
||||
Any(const ValueType &t_value)
|
||||
: m_data(std::unique_ptr<Data>(new Data_Impl<ValueType>(t_value)))
|
||||
#if _MSC_VER != 1800
|
||||
Any(Any &&) = default;
|
||||
Any &operator=(Any &&t_any) = default;
|
||||
#endif
|
||||
|
||||
template<typename ValueType,
|
||||
typename = typename std::enable_if<!std::is_same<Any, typename std::decay<ValueType>::type>::value>::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))))
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Any & operator=(const Any &t_any)
|
||||
{
|
||||
Any copy(t_any);
|
||||
@ -117,13 +125,6 @@ namespace chaiscript {
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename ValueType>
|
||||
Any & operator=(const ValueType &t_value)
|
||||
{
|
||||
m_data = std::unique_ptr<Data>(new Data_Impl<ValueType>(t_value));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename ToType>
|
||||
ToType &cast() const
|
||||
{
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <string>
|
||||
#include <typeinfo>
|
||||
|
||||
#include "../chaiscript_defines.hpp"
|
||||
#include "type_info.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
@ -28,14 +29,14 @@ namespace chaiscript
|
||||
class bad_boxed_cast : public std::bad_cast
|
||||
{
|
||||
public:
|
||||
bad_boxed_cast(const Type_Info &t_from, const std::type_info &t_to,
|
||||
bad_boxed_cast(Type_Info t_from, const std::type_info &t_to,
|
||||
std::string t_what) CHAISCRIPT_NOEXCEPT
|
||||
: from(t_from), to(&t_to), m_what(std::move(t_what))
|
||||
: from(std::move(t_from)), to(&t_to), m_what(std::move(t_what))
|
||||
{
|
||||
}
|
||||
|
||||
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")
|
||||
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")
|
||||
{
|
||||
}
|
||||
|
||||
@ -46,7 +47,7 @@ namespace chaiscript
|
||||
|
||||
virtual ~bad_boxed_cast() CHAISCRIPT_NOEXCEPT {}
|
||||
|
||||
/// \brief Description of what error occured
|
||||
/// \brief Description of what error occurred
|
||||
virtual const char * what() const CHAISCRIPT_NOEXCEPT CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return m_what.c_str();
|
||||
|
@ -14,79 +14,20 @@ namespace chaiscript
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template<int>
|
||||
struct Placeholder
|
||||
{
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Placeholder<1>
|
||||
{
|
||||
static decltype(std::placeholders::_1) value() { return std::placeholders::_1; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Placeholder<2>
|
||||
{
|
||||
static decltype(std::placeholders::_2) value() { return std::placeholders::_2; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Placeholder<3>
|
||||
{
|
||||
static decltype(std::placeholders::_3) value() { return std::placeholders::_3; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Placeholder<4>
|
||||
{
|
||||
static decltype(std::placeholders::_4) value() { return std::placeholders::_4; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Placeholder<5>
|
||||
{
|
||||
static decltype(std::placeholders::_5) value() { return std::placeholders::_5; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Placeholder<6>
|
||||
{
|
||||
static decltype(std::placeholders::_6) value() { return std::placeholders::_6; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Placeholder<7>
|
||||
{
|
||||
static decltype(std::placeholders::_7) value() { return std::placeholders::_7; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Placeholder<8>
|
||||
{
|
||||
static decltype(std::placeholders::_8) value() { return std::placeholders::_8; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Placeholder<9>
|
||||
{
|
||||
static decltype(std::placeholders::_9) value() { return std::placeholders::_9; }
|
||||
};
|
||||
|
||||
template<>
|
||||
struct Placeholder<10>
|
||||
{
|
||||
static decltype(std::placeholders::_10) value() { return std::placeholders::_10; }
|
||||
};
|
||||
|
||||
struct Placeholder
|
||||
{
|
||||
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(f, innerparams..., Placeholder<maxcount - count + 1>::value());
|
||||
return Bind_First<count - 1, maxcount, Sig>::bind(std::forward<F>(f), innerparams..., std::get<maxcount - count>(Placeholder::placeholder()));
|
||||
}
|
||||
};
|
||||
|
||||
@ -94,37 +35,42 @@ 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(f, innerparams...);
|
||||
return std::bind(std::forward<F>(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, o);
|
||||
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(f, std::forward<O>(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, o);
|
||||
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(f, std::forward<O>(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, o);
|
||||
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(f, std::forward<O>(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, o);
|
||||
return Bind_First<sizeof...(Param), sizeof...(Param), Ret (Param...)>::bind(f, std::forward<O>(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 "dynamic_cast_conversion.hpp"
|
||||
#include "type_conversions.hpp"
|
||||
#include "dynamic_object.hpp"
|
||||
#include "operators.hpp"
|
||||
#include "proxy_constructors.hpp"
|
||||
@ -46,13 +46,9 @@ namespace chaiscript
|
||||
/// \param[in] v Boxed_Number to copy into the new object
|
||||
/// \returns The newly created object.
|
||||
template<typename P1>
|
||||
std::shared_ptr<P1> construct_pod(Boxed_Number v)
|
||||
std::shared_ptr<P1> construct_pod(const Boxed_Number &v)
|
||||
{
|
||||
std::shared_ptr<P1> p(new P1());
|
||||
Boxed_Value bv(p);
|
||||
Boxed_Number nb(bv);
|
||||
nb = v;
|
||||
return p;
|
||||
return std::make_shared<P1>(v.get_as<P1>());
|
||||
}
|
||||
}
|
||||
|
||||
@ -113,9 +109,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* to_string function for internal use. Uses ostream operator<<
|
||||
*/
|
||||
/// to_string function for internal use. Uses ostream operator<<
|
||||
template<typename Input>
|
||||
std::string to_string(Input i)
|
||||
{
|
||||
@ -124,10 +118,8 @@ namespace chaiscript
|
||||
return ss.str();
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal function for converting from a string to a value
|
||||
* uses ostream operator >> to perform the conversion
|
||||
*/
|
||||
/// Internal function for converting from a string to a value
|
||||
/// uses ostream operator >> to perform the conversion
|
||||
template<typename Input>
|
||||
Input parse_string(const std::string &i)
|
||||
{
|
||||
@ -136,12 +128,10 @@ namespace chaiscript
|
||||
ss >> t;
|
||||
return t;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add all common functions for a POD type. All operators, and
|
||||
* common conversions
|
||||
*/
|
||||
|
||||
|
||||
/// Add all common functions for a POD type. All operators, and
|
||||
/// common conversions
|
||||
template<typename T>
|
||||
ModulePtr bootstrap_pod_type(const std::string &name, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
@ -155,22 +145,18 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* "clone" function for a shared_ptr type. This is used in the case
|
||||
* where you do not want to make a deep copy of an object during cloning
|
||||
* but want to instead maintain the shared_ptr. It is needed internally
|
||||
* for handling of Proxy_Function object (that is,
|
||||
* function variables.
|
||||
*/
|
||||
/// "clone" function for a shared_ptr type. This is used in the case
|
||||
/// where you do not want to make a deep copy of an object during cloning
|
||||
/// but want to instead maintain the shared_ptr. It is needed internally
|
||||
/// for handling of Proxy_Function object (that is,
|
||||
/// function variables.
|
||||
template<typename Type>
|
||||
std::shared_ptr<Type> shared_ptr_clone(const std::shared_ptr<Type> &p)
|
||||
{
|
||||
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)
|
||||
@ -180,11 +166,9 @@ 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)
|
||||
{
|
||||
@ -198,10 +182,8 @@ 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:
|
||||
@ -229,9 +211,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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), "==");
|
||||
@ -271,11 +251,8 @@ 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)
|
||||
@ -285,7 +262,7 @@ namespace chaiscript
|
||||
|
||||
Const_Proxy_Function f = boxed_cast<Const_Proxy_Function>(params[0]);
|
||||
|
||||
return Boxed_Value(Const_Proxy_Function(new dispatch::Bound_Function(f,
|
||||
return Boxed_Value(Const_Proxy_Function(std::make_shared<dispatch::Bound_Function>(f,
|
||||
std::vector<Boxed_Value>(params.begin() + 1, params.end()))));
|
||||
}
|
||||
|
||||
@ -330,9 +307,7 @@ 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)
|
||||
@ -362,9 +337,7 @@ namespace chaiscript
|
||||
|
||||
static bool has_parse_tree(const chaiscript::Const_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 (auto pf = std::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf))
|
||||
{
|
||||
if (pf->get_parse_tree())
|
||||
{
|
||||
@ -379,9 +352,7 @@ namespace chaiscript
|
||||
|
||||
static chaiscript::AST_NodePtr get_parse_tree(const chaiscript::Const_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 (auto pf = std::dynamic_pointer_cast<const chaiscript::dispatch::Dynamic_Proxy_Function>(t_pf))
|
||||
{
|
||||
if (pf->get_parse_tree())
|
||||
{
|
||||
@ -504,8 +475,7 @@ namespace chaiscript
|
||||
m->add(fun(&print), "print_string");
|
||||
m->add(fun(&println), "println_string");
|
||||
|
||||
m->add(Proxy_Function(new dispatch::Dynamic_Proxy_Function(std::bind(&bind_function, std::placeholders::_1))),
|
||||
"bind");
|
||||
m->add(Proxy_Function(new dispatch::Dynamic_Proxy_Function(&bind_function)), "bind");
|
||||
|
||||
m->add(fun(&shared_ptr_unconst_clone<dispatch::Proxy_Function_Base>), "clone");
|
||||
m->add(fun(&ptr_assign<std::remove_const<dispatch::Proxy_Function_Base>::type>), "=");
|
||||
@ -526,11 +496,11 @@ namespace chaiscript
|
||||
"eval_error",
|
||||
{ },
|
||||
{ {fun(&chaiscript::exception::eval_error::reason), "reason"},
|
||||
{fun(std::function<std::vector<Boxed_Value> (const chaiscript::exception::eval_error &t_eval_error)>([](const chaiscript::exception::eval_error &t_eval_error) {
|
||||
{fun(std::function<std::vector<Boxed_Value> (const chaiscript::exception::eval_error &t_eval_error)>([](const chaiscript::exception::eval_error &t_eval_error) -> std::vector<Boxed_Value> {
|
||||
std::vector<Boxed_Value> retval;
|
||||
std::transform(t_eval_error.call_stack.begin(), t_eval_error.call_stack.end(),
|
||||
std::back_inserter(retval),
|
||||
&chaiscript::var<std::shared_ptr<chaiscript::AST_Node>>);
|
||||
&chaiscript::var<std::shared_ptr<const chaiscript::AST_Node>>);
|
||||
return retval;
|
||||
})), "call_stack"} }
|
||||
);
|
||||
@ -554,7 +524,7 @@ namespace chaiscript
|
||||
{fun(&AST_Node::start), "start"},
|
||||
{fun(&AST_Node::end), "end"},
|
||||
{fun(&AST_Node::to_string), "to_string"},
|
||||
{fun(std::function<std::vector<Boxed_Value> (const chaiscript::AST_Node &t_node)>([](const chaiscript::AST_Node &t_node) {
|
||||
{fun(std::function<std::vector<Boxed_Value> (const chaiscript::AST_Node &t_node)>([](const chaiscript::AST_Node &t_node) -> std::vector<Boxed_Value> {
|
||||
std::vector<Boxed_Value> retval;
|
||||
std::transform(t_node.children.begin(), t_node.children.end(),
|
||||
std::back_inserter(retval),
|
||||
|
@ -278,9 +278,9 @@ namespace chaiscript
|
||||
template<typename ContainerType>
|
||||
ModulePtr container_type(const std::string &/*type*/, ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
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");
|
||||
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");
|
||||
return m;
|
||||
}
|
||||
|
||||
@ -493,24 +493,26 @@ namespace chaiscript
|
||||
|
||||
if (typeid(VectorType) == typeid(std::vector<Boxed_Value>))
|
||||
{
|
||||
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; \
|
||||
} \
|
||||
}");
|
||||
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;
|
||||
}
|
||||
} )"
|
||||
);
|
||||
}
|
||||
|
||||
return m;
|
||||
|
@ -14,11 +14,11 @@
|
||||
#include "bad_boxed_cast.hpp"
|
||||
#include "boxed_cast_helper.hpp"
|
||||
#include "boxed_value.hpp"
|
||||
#include "dynamic_cast_conversion.hpp"
|
||||
#include "type_conversions.hpp"
|
||||
#include "type_info.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
class Dynamic_Cast_Conversions;
|
||||
class Type_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 Dynamic_Cast_Conversions *t_conversions = nullptr)
|
||||
typename detail::Cast_Helper<Type>::Result_Type boxed_cast(const Boxed_Value &bv, const Type_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 (std::is_polymorphic<typename detail::Stripped_Type<Type>::type>::value && t_conversions)
|
||||
if (t_conversions && t_conversions->convertable_type<Type>())
|
||||
{
|
||||
try {
|
||||
// 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_dynamic_cast<Type>(bv), t_conversions);
|
||||
return detail::Cast_Helper<Type>::cast(t_conversions->boxed_type_conversion<Type>(bv), t_conversions);
|
||||
} catch (...) {
|
||||
try {
|
||||
// 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_dynamic_down_cast<Type>(bv), t_conversions);
|
||||
return detail::Cast_Helper<Type>::cast(t_conversions->boxed_type_down_conversion<Type>(bv), t_conversions);
|
||||
} catch (const chaiscript::detail::exception::bad_any_cast &) {
|
||||
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
|
||||
}
|
||||
|
@ -17,37 +17,32 @@
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
class Dynamic_Cast_Conversions;
|
||||
class Type_Conversions;
|
||||
|
||||
namespace detail
|
||||
{
|
||||
// Cast_Helper_Inner helper classes
|
||||
|
||||
/**
|
||||
* Generic Cast_Helper_Inner, for casting to any type
|
||||
*/
|
||||
template<typename T>
|
||||
T* throw_if_null(T *t)
|
||||
{
|
||||
if (t) return t;
|
||||
throw std::runtime_error("Attempted to dereference null Boxed_Value");
|
||||
}
|
||||
|
||||
/// Generic Cast_Helper_Inner, for casting to any type
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner
|
||||
{
|
||||
typedef typename std::reference_wrapper<typename std::add_const<Result>::type > Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
{
|
||||
if (ob.is_ref())
|
||||
if (ob.get_type_info().bare_equal_type_info(typeid(Result)))
|
||||
{
|
||||
if (!ob.get_type_info().is_const())
|
||||
{
|
||||
return std::cref((ob.get().cast<std::reference_wrapper<Result> >()).get());
|
||||
} else {
|
||||
return ob.get().cast<std::reference_wrapper<const Result> >();
|
||||
}
|
||||
return *(static_cast<const Result *>(throw_if_null(ob.get_const_ptr())));
|
||||
} else {
|
||||
if (!ob.get_type_info().is_const())
|
||||
{
|
||||
return std::cref(*(ob.get().cast<std::shared_ptr<Result> >()));
|
||||
} else {
|
||||
return std::cref(*(ob.get().cast<std::shared_ptr<const Result> >()));
|
||||
}
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
}
|
||||
};
|
||||
@ -57,23 +52,18 @@ namespace chaiscript
|
||||
{
|
||||
};
|
||||
|
||||
/**
|
||||
* Cast_Helper_Inner for casting to a const & type
|
||||
*/
|
||||
/// Cast_Helper_Inner for casting to a const & type
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<const Result &> : Cast_Helper_Inner<Result>
|
||||
{
|
||||
};
|
||||
|
||||
/**
|
||||
* Cast_Helper_Inner for casting to a const * type
|
||||
*/
|
||||
/// Cast_Helper_Inner for casting to a const * type
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<const Result *>
|
||||
{
|
||||
typedef const Result * Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
{
|
||||
if (ob.is_ref())
|
||||
{
|
||||
@ -94,15 +84,12 @@ namespace chaiscript
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Cast_Helper_Inner for casting to a * type
|
||||
*/
|
||||
/// Cast_Helper_Inner for casting to a * type
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<Result *>
|
||||
{
|
||||
typedef Result * Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
{
|
||||
if (ob.is_ref())
|
||||
{
|
||||
@ -113,49 +100,43 @@ namespace chaiscript
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Cast_Helper_Inner for casting to a & type
|
||||
*/
|
||||
|
||||
/// Cast_Helper_Inner for casting to a & type
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<Result &>
|
||||
{
|
||||
typedef Result& Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
{
|
||||
if (ob.is_ref())
|
||||
if (!ob.get_type_info().is_const() && ob.get_type_info().bare_equal_type_info(typeid(Result)))
|
||||
{
|
||||
return ob.get().cast<std::reference_wrapper<Result> >();
|
||||
return *(static_cast<Result *>(throw_if_null(ob.get_ptr())));
|
||||
} else {
|
||||
Result &r = *(ob.get().cast<std::shared_ptr<Result> >());
|
||||
return r;
|
||||
throw chaiscript::detail::exception::bad_any_cast();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Cast_Helper_Inner for casting to a std::shared_ptr<> type
|
||||
*/
|
||||
/// Cast_Helper_Inner for casting to a std::shared_ptr<> type
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<typename std::shared_ptr<Result> >
|
||||
{
|
||||
typedef typename std::shared_ptr<Result> Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
{
|
||||
return ob.get().cast<std::shared_ptr<Result> >();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Cast_Helper_Inner for casting to a std::shared_ptr<const> type
|
||||
*/
|
||||
/// Cast_Helper_Inner for casting to a std::shared_ptr<const> type
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<typename std::shared_ptr<const Result> >
|
||||
{
|
||||
typedef typename std::shared_ptr<const Result> Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
{
|
||||
if (!ob.get_type_info().is_const())
|
||||
{
|
||||
@ -166,9 +147,7 @@ namespace chaiscript
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Cast_Helper_Inner for casting to a const std::shared_ptr<> & type
|
||||
*/
|
||||
/// Cast_Helper_Inner for casting to a const std::shared_ptr<> & type
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<const std::shared_ptr<Result> > : Cast_Helper_Inner<std::shared_ptr<Result> >
|
||||
{
|
||||
@ -180,9 +159,7 @@ namespace chaiscript
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Cast_Helper_Inner for casting to a const std::shared_ptr<const> & type
|
||||
*/
|
||||
/// Cast_Helper_Inner for casting to a const std::shared_ptr<const> & type
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<const std::shared_ptr<const Result> > : Cast_Helper_Inner<std::shared_ptr<const Result> >
|
||||
{
|
||||
@ -195,38 +172,32 @@ namespace chaiscript
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Cast_Helper_Inner for casting to a Boxed_Value type
|
||||
*/
|
||||
/// Cast_Helper_Inner for casting to a Boxed_Value type
|
||||
template<>
|
||||
struct Cast_Helper_Inner<Boxed_Value>
|
||||
{
|
||||
typedef const Boxed_Value & Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
{
|
||||
return ob;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Cast_Helper_Inner for casting to a Boxed_Value & type
|
||||
*/
|
||||
/// Cast_Helper_Inner for casting to a Boxed_Value & type
|
||||
template<>
|
||||
struct Cast_Helper_Inner<Boxed_Value &>
|
||||
{
|
||||
typedef Boxed_Value& Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||
{
|
||||
return const_cast<Boxed_Value &>(ob);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Cast_Helper_Inner for casting to a const Boxed_Value & type
|
||||
*/
|
||||
/// Cast_Helper_Inner for casting to a const Boxed_Value & type
|
||||
template<>
|
||||
struct Cast_Helper_Inner<const Boxed_Value> : Cast_Helper_Inner<Boxed_Value>
|
||||
{
|
||||
@ -238,9 +209,7 @@ namespace chaiscript
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Cast_Helper_Inner for casting to a std::reference_wrapper type
|
||||
*/
|
||||
/// Cast_Helper_Inner for casting to a std::reference_wrapper type
|
||||
template<typename Result>
|
||||
struct Cast_Helper_Inner<std::reference_wrapper<Result> > : Cast_Helper_Inner<Result &>
|
||||
{
|
||||
@ -271,15 +240,13 @@ namespace chaiscript
|
||||
{
|
||||
};
|
||||
|
||||
/**
|
||||
* The exposed Cast_Helper object that by default just calls the Cast_Helper_Inner
|
||||
*/
|
||||
/// The exposed Cast_Helper object that by default just calls the Cast_Helper_Inner
|
||||
template<typename T>
|
||||
struct Cast_Helper
|
||||
{
|
||||
typedef typename Cast_Helper_Inner<T>::Result_Type Result_Type;
|
||||
|
||||
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_Conversions *t_conversions)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *t_conversions)
|
||||
{
|
||||
return Cast_Helper_Inner<T>::cast(ob, t_conversions);
|
||||
}
|
||||
|
@ -19,7 +19,7 @@
|
||||
#include "type_info.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
class Dynamic_Cast_Conversions;
|
||||
class Type_Conversions;
|
||||
} // namespace chaiscript
|
||||
|
||||
namespace chaiscript
|
||||
@ -233,7 +233,7 @@ namespace chaiscript
|
||||
template<typename LHS, bool Float>
|
||||
static Boxed_Value oper_rhs(Operators::Opers t_oper, const Boxed_Value &t_lhs, const Boxed_Value &t_rhs)
|
||||
{
|
||||
const Type_Info &inp_ = t_rhs.get_type_info();
|
||||
const auto &inp_ = t_rhs.get_type_info();
|
||||
|
||||
if (inp_ == typeid(int)) {
|
||||
return Go<LHS, int, Float>::go(t_oper, t_lhs, t_rhs);
|
||||
@ -334,10 +334,10 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
Boxed_Number(const Boxed_Value &v)
|
||||
: bv(v)
|
||||
Boxed_Number(Boxed_Value v)
|
||||
: bv(std::move(v))
|
||||
{
|
||||
validate_boxed_number(v);
|
||||
validate_boxed_number(bv);
|
||||
}
|
||||
|
||||
template<typename T> explicit Boxed_Number(T t)
|
||||
@ -826,31 +826,25 @@ 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 Dynamic_Cast_Conversions *)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_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,6 +13,7 @@
|
||||
#include <type_traits>
|
||||
|
||||
#include "../chaiscript_threading.hpp"
|
||||
#include "../chaiscript_defines.hpp"
|
||||
#include "any.hpp"
|
||||
#include "type_info.hpp"
|
||||
|
||||
@ -35,10 +36,10 @@ namespace chaiscript
|
||||
struct Data
|
||||
{
|
||||
Data(const Type_Info &ti,
|
||||
const chaiscript::detail::Any &to,
|
||||
chaiscript::detail::Any to,
|
||||
bool tr,
|
||||
const void *t_void_ptr)
|
||||
: m_type_info(ti), m_obj(to), m_data_ptr(ti.is_const()?nullptr:const_cast<void *>(t_void_ptr)), m_const_data_ptr(t_void_ptr),
|
||||
: m_type_info(ti), m_obj(std::move(to)), m_data_ptr(ti.is_const()?nullptr:const_cast<void *>(t_void_ptr)), m_const_data_ptr(t_void_ptr),
|
||||
m_is_ref(tr)
|
||||
{
|
||||
}
|
||||
@ -61,9 +62,11 @@ namespace chaiscript
|
||||
|
||||
Data(const Data &) = delete;
|
||||
|
||||
~Data()
|
||||
{
|
||||
}
|
||||
#if !defined(__APPLE__) && (!defined(_MSC_VER) || _MSC_VER != 1800)
|
||||
Data(Data &&) = default;
|
||||
Data &operator=(Data &&rhs) = default;
|
||||
#endif
|
||||
|
||||
|
||||
Type_Info m_type_info;
|
||||
chaiscript::detail::Any m_obj;
|
||||
@ -102,32 +105,53 @@ namespace chaiscript
|
||||
);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::shared_ptr<Data> get(std::shared_ptr<T> &&obj)
|
||||
{
|
||||
auto ptr = obj.get();
|
||||
return std::make_shared<Data>(
|
||||
detail::Get_Type_Info<T>::get(),
|
||||
chaiscript::detail::Any(std::move(obj)),
|
||||
false,
|
||||
ptr
|
||||
);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::shared_ptr<Data> get(T *t)
|
||||
{
|
||||
return get(std::ref(*t));
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
auto p = &obj.get();
|
||||
return std::make_shared<Data>(
|
||||
detail::Get_Type_Info<T>::get(),
|
||||
chaiscript::detail::Any(obj),
|
||||
chaiscript::detail::Any(std::move(obj)),
|
||||
true,
|
||||
&obj.get()
|
||||
p
|
||||
);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
static std::shared_ptr<Data> get(const T& t)
|
||||
static std::shared_ptr<Data> get(T t)
|
||||
{
|
||||
auto p = std::make_shared<T>(t);
|
||||
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(p),
|
||||
chaiscript::detail::Any(std::move(p)),
|
||||
false,
|
||||
p.get()
|
||||
ptr
|
||||
);
|
||||
}
|
||||
|
||||
@ -145,27 +169,26 @@ namespace chaiscript
|
||||
|
||||
public:
|
||||
/// Basic Boxed_Value constructor
|
||||
template<typename T>
|
||||
explicit Boxed_Value(T t)
|
||||
: m_data(Object_Data::get(t))
|
||||
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)))
|
||||
{
|
||||
}
|
||||
|
||||
/// Copy constructor - each copy shares the same data pointer
|
||||
Boxed_Value(const Boxed_Value &t_so)
|
||||
: m_data(t_so.m_data)
|
||||
{
|
||||
}
|
||||
|
||||
/// Unknown-type constructor
|
||||
Boxed_Value()
|
||||
: m_data(Object_Data::get())
|
||||
{
|
||||
}
|
||||
|
||||
~Boxed_Value()
|
||||
{
|
||||
}
|
||||
#if !defined(_MSC_VER) || _MSC_VER != 1800
|
||||
Boxed_Value(Boxed_Value&&) = default;
|
||||
Boxed_Value& operator=(Boxed_Value&&) = default;
|
||||
#endif
|
||||
|
||||
Boxed_Value(const Boxed_Value&) = default;
|
||||
Boxed_Value& operator=(const Boxed_Value&) = default;
|
||||
|
||||
void swap(Boxed_Value &rhs)
|
||||
{
|
||||
@ -180,61 +203,53 @@ namespace chaiscript
|
||||
return *this;
|
||||
}
|
||||
|
||||
/// shared data assignment, same as copy construction
|
||||
Boxed_Value &operator=(const Boxed_Value &rhs)
|
||||
{
|
||||
Boxed_Value temp(rhs);
|
||||
swap(temp);
|
||||
return *this;
|
||||
}
|
||||
|
||||
const Type_Info &get_type_info() const
|
||||
const Type_Info &get_type_info() const CHAISCRIPT_NOEXCEPT
|
||||
{
|
||||
return m_data->m_type_info;
|
||||
}
|
||||
|
||||
/// return true if the object is uninitialized
|
||||
bool is_undef() const
|
||||
bool is_undef() const CHAISCRIPT_NOEXCEPT
|
||||
{
|
||||
return m_data->m_type_info.is_undef();
|
||||
}
|
||||
|
||||
bool is_const() const
|
||||
bool is_const() const CHAISCRIPT_NOEXCEPT
|
||||
{
|
||||
return m_data->m_type_info.is_const();
|
||||
}
|
||||
|
||||
bool is_type(const Type_Info &ti) const
|
||||
bool is_type(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT
|
||||
{
|
||||
return m_data->m_type_info.bare_equal(ti);
|
||||
}
|
||||
|
||||
bool is_null() const
|
||||
bool is_null() const CHAISCRIPT_NOEXCEPT
|
||||
{
|
||||
return (m_data->m_data_ptr == nullptr && m_data->m_const_data_ptr == nullptr);
|
||||
}
|
||||
|
||||
const chaiscript::detail::Any & get() const
|
||||
const chaiscript::detail::Any & get() const CHAISCRIPT_NOEXCEPT
|
||||
{
|
||||
return m_data->m_obj;
|
||||
}
|
||||
|
||||
bool is_ref() const
|
||||
bool is_ref() const CHAISCRIPT_NOEXCEPT
|
||||
{
|
||||
return m_data->m_is_ref;
|
||||
}
|
||||
|
||||
bool is_pointer() const
|
||||
bool is_pointer() const CHAISCRIPT_NOEXCEPT
|
||||
{
|
||||
return !is_ref();
|
||||
}
|
||||
|
||||
void *get_ptr() const
|
||||
void *get_ptr() const CHAISCRIPT_NOEXCEPT
|
||||
{
|
||||
return m_data->m_data_ptr;
|
||||
}
|
||||
|
||||
const void *get_const_ptr() const
|
||||
const void *get_const_ptr() const CHAISCRIPT_NOEXCEPT
|
||||
{
|
||||
return m_data->m_const_data_ptr;
|
||||
}
|
||||
@ -260,7 +275,7 @@ namespace chaiscript
|
||||
|
||||
|
||||
/// \returns true if the two Boxed_Values share the same internal type
|
||||
static bool type_match(Boxed_Value l, Boxed_Value r)
|
||||
static bool type_match(const Boxed_Value &l, const Boxed_Value &r) CHAISCRIPT_NOEXCEPT
|
||||
{
|
||||
return l.get_type_info() == r.get_type_info();
|
||||
}
|
||||
@ -297,7 +312,7 @@ namespace chaiscript
|
||||
template<typename T>
|
||||
Boxed_Value const_var_impl(const T &t)
|
||||
{
|
||||
return Boxed_Value(std::shared_ptr<typename std::add_const<T>::type >(new T(t)));
|
||||
return Boxed_Value(std::make_shared<typename std::add_const<T>::type >(t));
|
||||
}
|
||||
|
||||
/// \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 "dynamic_cast_conversion.hpp"
|
||||
#include "type_conversions.hpp"
|
||||
#include "dynamic_object.hpp"
|
||||
#include "proxy_constructors.hpp"
|
||||
#include "proxy_functions.hpp"
|
||||
@ -53,9 +53,7 @@ namespace chaiscript
|
||||
{
|
||||
namespace exception
|
||||
{
|
||||
/**
|
||||
* Exception thrown in the case that an object name is invalid because it is a reserved word
|
||||
*/
|
||||
/// Exception thrown in the case that an object name is invalid because it is a reserved word
|
||||
class reserved_word_error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
@ -75,18 +73,16 @@ namespace chaiscript
|
||||
std::string m_word;
|
||||
};
|
||||
|
||||
/**
|
||||
* Exception thrown in the case that an object name is invalid because it contains illegal characters
|
||||
*/
|
||||
/// Exception thrown in the case that an object name is invalid because it contains illegal characters
|
||||
class illegal_name_error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
illegal_name_error(const std::string &t_name) throw()
|
||||
illegal_name_error(const std::string &t_name) CHAISCRIPT_NOEXCEPT
|
||||
: std::runtime_error("Reserved name not allowed in object name: " + t_name), m_name(t_name)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~illegal_name_error() throw() {}
|
||||
virtual ~illegal_name_error() CHAISCRIPT_NOEXCEPT {}
|
||||
|
||||
std::string name() const
|
||||
{
|
||||
@ -98,18 +94,16 @@ namespace chaiscript
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Exception thrown in the case that an object name is invalid because it already exists in current context
|
||||
*/
|
||||
/// Exception thrown in the case that an object name is invalid because it already exists in current context
|
||||
class name_conflict_error : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
name_conflict_error(const std::string &t_name) throw()
|
||||
name_conflict_error(const std::string &t_name) CHAISCRIPT_NOEXCEPT
|
||||
: std::runtime_error("Name already exists in current context " + t_name), m_name(t_name)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~name_conflict_error() throw() {}
|
||||
virtual ~name_conflict_error() CHAISCRIPT_NOEXCEPT {}
|
||||
|
||||
std::string name() const
|
||||
{
|
||||
@ -122,9 +116,7 @@ namespace chaiscript
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Exception thrown in the case that a non-const object was added as a shared object
|
||||
*/
|
||||
/// Exception thrown in the case that a non-const object was added as a shared object
|
||||
class global_non_const : public std::runtime_error
|
||||
{
|
||||
public:
|
||||
@ -143,37 +135,37 @@ namespace chaiscript
|
||||
class Module
|
||||
{
|
||||
public:
|
||||
Module &add(const Type_Info &ti, const std::string &name)
|
||||
Module &add(Type_Info ti, std::string name)
|
||||
{
|
||||
m_typeinfos.push_back(std::make_pair(ti, name));
|
||||
m_typeinfos.emplace_back(std::move(ti), std::move(name));
|
||||
return *this;
|
||||
}
|
||||
|
||||
Module &add(const Dynamic_Cast_Conversion &d)
|
||||
Module &add(Type_Conversion d)
|
||||
{
|
||||
m_conversions.push_back(d);
|
||||
m_conversions.push_back(std::move(d));
|
||||
return *this;
|
||||
}
|
||||
|
||||
Module &add(const Proxy_Function &f, const std::string &name)
|
||||
Module &add(Proxy_Function f, std::string name)
|
||||
{
|
||||
m_funcs.push_back(std::make_pair(f, name));
|
||||
m_funcs.emplace_back(std::move(f), std::move(name));
|
||||
return *this;
|
||||
}
|
||||
|
||||
Module &add_global_const(const Boxed_Value &t_bv, const std::string &t_name)
|
||||
Module &add_global_const(Boxed_Value t_bv, std::string t_name)
|
||||
{
|
||||
if (!t_bv.is_const())
|
||||
{
|
||||
throw chaiscript::exception::global_non_const();
|
||||
}
|
||||
|
||||
m_globals.push_back(std::make_pair(t_bv, t_name));
|
||||
m_globals.emplace_back(std::move(t_bv), std::move(t_name));
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
//Add a bit of chaiscript to eval during module implementation
|
||||
//Add a bit of ChaiScript to eval during module implementation
|
||||
Module &eval(const std::string &str)
|
||||
{
|
||||
m_evals.push_back(str);
|
||||
@ -205,21 +197,21 @@ 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<Dynamic_Cast_Conversion> m_conversions;
|
||||
std::vector<Type_Conversion> m_conversions;
|
||||
|
||||
template<typename T, typename InItr>
|
||||
static void apply(InItr begin, InItr end, T &t)
|
||||
static void apply(InItr begin, const InItr end, T &t)
|
||||
{
|
||||
while (begin != end)
|
||||
{
|
||||
try {
|
||||
t.add(begin->first, begin->second);
|
||||
} catch (const chaiscript::exception::name_conflict_error &) {
|
||||
/// \todo Should we throw an error if there's a name conflict
|
||||
/// while applying a module?
|
||||
}
|
||||
++begin;
|
||||
}
|
||||
for_each(begin, end, [&t](typename std::iterator_traits<InItr>::reference obj)
|
||||
{
|
||||
try {
|
||||
t.add(obj.first, obj.second);
|
||||
} catch (const chaiscript::exception::name_conflict_error &) {
|
||||
/// \todo Should we throw an error if there's a name conflict
|
||||
/// while applying a module?
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
template<typename T, typename InItr>
|
||||
@ -258,24 +250,22 @@ namespace chaiscript
|
||||
|
||||
namespace detail
|
||||
{
|
||||
/**
|
||||
* A Proxy_Function implementation that is able to take
|
||||
* a vector of Proxy_Functions and perform a dispatch on them. It is
|
||||
* used specifically in the case of dealing with Function object variables
|
||||
*/
|
||||
/// A Proxy_Function implementation that is able to take
|
||||
/// a vector of Proxy_Functions and perform a dispatch on them. It is
|
||||
/// used specifically in the case of dealing with Function object variables
|
||||
class Dispatch_Function : public dispatch::Proxy_Function_Base
|
||||
{
|
||||
public:
|
||||
Dispatch_Function(const std::vector<Proxy_Function> &t_funcs)
|
||||
: Proxy_Function_Base(build_type_infos(t_funcs)),
|
||||
m_funcs(t_funcs)
|
||||
Dispatch_Function(std::vector<Proxy_Function> t_funcs)
|
||||
: Proxy_Function_Base(build_type_infos(t_funcs), calculate_arity(t_funcs)),
|
||||
m_funcs(std::move(t_funcs))
|
||||
{
|
||||
}
|
||||
|
||||
virtual bool operator==(const dispatch::Proxy_Function_Base &rhs) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
try {
|
||||
const Dispatch_Function &dispatchfun = dynamic_cast<const Dispatch_Function &>(rhs);
|
||||
const auto &dispatchfun = dynamic_cast<const Dispatch_Function &>(rhs);
|
||||
return m_funcs == dispatchfun.m_funcs;
|
||||
} catch (const std::bad_cast &) {
|
||||
return false;
|
||||
@ -290,52 +280,30 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
|
||||
virtual int get_arity() const CHAISCRIPT_OVERRIDE
|
||||
static int calculate_arity(const std::vector<Proxy_Function> &t_funcs)
|
||||
{
|
||||
typedef std::vector<Proxy_Function> function_vec;
|
||||
|
||||
auto begin = m_funcs.begin();
|
||||
const function_vec::const_iterator end = m_funcs.end();
|
||||
|
||||
if (begin != end)
|
||||
{
|
||||
int arity = (*begin)->get_arity();
|
||||
|
||||
++begin;
|
||||
|
||||
while (begin != end)
|
||||
{
|
||||
if (arity != (*begin)->get_arity())
|
||||
{
|
||||
// The arities in the list do not match, so it's unspecified
|
||||
return -1;
|
||||
}
|
||||
|
||||
++begin;
|
||||
}
|
||||
|
||||
return arity;
|
||||
if (t_funcs.empty()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return -1; // unknown arity
|
||||
const auto arity = t_funcs.front()->get_arity();
|
||||
|
||||
for (const auto &func : t_funcs)
|
||||
{
|
||||
if (arity != func->get_arity())
|
||||
{
|
||||
// The arities in the list do not match, so it's unspecified
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return arity;
|
||||
}
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
auto begin = m_funcs.begin();
|
||||
auto end = m_funcs.end();
|
||||
|
||||
while (begin != end)
|
||||
{
|
||||
if ((*begin)->call_match(vals, t_conversions))
|
||||
{
|
||||
return true;
|
||||
} else {
|
||||
++begin;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return std::any_of(m_funcs.cbegin(), m_funcs.cend(),
|
||||
[&vals, &t_conversions](const Proxy_Function &f){ return f->call_match(vals, t_conversions); });
|
||||
}
|
||||
|
||||
virtual std::string annotation() const CHAISCRIPT_OVERRIDE
|
||||
@ -344,9 +312,9 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return dispatch::dispatch(m_funcs.begin(), m_funcs.end(), params, t_conversions);
|
||||
return dispatch::dispatch(m_funcs, params, t_conversions);
|
||||
}
|
||||
|
||||
private:
|
||||
@ -354,10 +322,8 @@ namespace chaiscript
|
||||
|
||||
static std::vector<Type_Info> build_type_infos(const std::vector<Proxy_Function> &t_funcs)
|
||||
{
|
||||
typedef std::vector<Proxy_Function> function_vec;
|
||||
|
||||
auto begin = t_funcs.begin();
|
||||
const function_vec::const_iterator end = t_funcs.end();
|
||||
auto begin = t_funcs.cbegin();
|
||||
const auto &end = t_funcs.cend();
|
||||
|
||||
if (begin != end)
|
||||
{
|
||||
@ -399,23 +365,20 @@ namespace chaiscript
|
||||
|
||||
return std::vector<Type_Info>();
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
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:
|
||||
typedef std::map<std::string, chaiscript::Type_Info> Type_Name_Map;
|
||||
typedef std::map<std::string, Boxed_Value> Scope;
|
||||
typedef std::deque<Scope> StackData;
|
||||
typedef std::shared_ptr<StackData> Stack;
|
||||
typedef std::vector<Scope> StackData;
|
||||
|
||||
struct State
|
||||
{
|
||||
@ -430,8 +393,7 @@ namespace chaiscript
|
||||
|
||||
Dispatch_Engine()
|
||||
: m_stack_holder(this),
|
||||
m_place_holder(std::shared_ptr<dispatch::Placeholder_Object>(new dispatch::Placeholder_Object()))
|
||||
|
||||
m_place_holder(std::make_shared<dispatch::Placeholder_Object>())
|
||||
{
|
||||
}
|
||||
|
||||
@ -446,67 +408,56 @@ namespace chaiscript
|
||||
return chaiscript::boxed_cast<Type>(bv, &m_conversions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new conversion for upcasting to a base class
|
||||
*/
|
||||
void add(const Dynamic_Cast_Conversion &d)
|
||||
/// Add a new conversion for upcasting to a base class
|
||||
void add(const Type_Conversion &d)
|
||||
{
|
||||
m_conversions.add_conversion(d);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a new named Proxy_Function to the system
|
||||
*/
|
||||
/// Add a new named Proxy_Function to the system
|
||||
void add(const Proxy_Function &f, const std::string &name)
|
||||
{
|
||||
validate_object_name(name);
|
||||
add_function(f, name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the value of an object, by name. If the object
|
||||
* is not available in the current scope it is created
|
||||
*/
|
||||
/// Set the value of an object, by name. If the object
|
||||
/// is not available in the current scope it is created
|
||||
void add(const Boxed_Value &obj, const std::string &name)
|
||||
{
|
||||
validate_object_name(name);
|
||||
StackData &stack = get_stack_data();
|
||||
auto &stack = get_stack_data();
|
||||
|
||||
for (int i = static_cast<int>(stack.size())-1; i >= 0; --i)
|
||||
for (auto stack_elem = stack.rbegin(); stack_elem != stack.rend(); ++stack_elem)
|
||||
{
|
||||
std::map<std::string, Boxed_Value>::const_iterator itr = stack[i].find(name);
|
||||
if (itr != stack[i].end())
|
||||
auto itr = stack_elem->find(name);
|
||||
if (itr != stack_elem->end())
|
||||
{
|
||||
stack[i][name] = obj;
|
||||
itr->second = std::move(obj);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
add_object(name, obj);
|
||||
add_object(name, std::move(obj));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a named object to the current scope
|
||||
*/
|
||||
/// Adds a named object to the current scope
|
||||
void add_object(const std::string &name, const Boxed_Value &obj) const
|
||||
{
|
||||
StackData &stack = get_stack_data();
|
||||
auto &stack = get_stack_data();
|
||||
validate_object_name(name);
|
||||
|
||||
Scope &scope = stack.back();
|
||||
auto itr = scope.find(name);
|
||||
if (itr != stack.back().end())
|
||||
auto &scope = stack.back();
|
||||
if (scope.find(name) != scope.end())
|
||||
{
|
||||
throw chaiscript::exception::name_conflict_error(name);
|
||||
} else {
|
||||
stack.back().insert(std::make_pair(name, obj));
|
||||
scope.insert(std::make_pair(name, obj));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new global shared object, between all the threads
|
||||
*/
|
||||
/// Adds a new global shared object, between all the threads
|
||||
void add_global_const(const Boxed_Value &obj, const std::string &name)
|
||||
{
|
||||
validate_object_name(name);
|
||||
@ -526,9 +477,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a new global (non-const) shared object, between all the threads
|
||||
*/
|
||||
/// Adds a new global (non-const) shared object, between all the threads
|
||||
void add_global(const Boxed_Value &obj, const std::string &name)
|
||||
{
|
||||
validate_object_name(name);
|
||||
@ -544,18 +493,13 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a new scope to the stack
|
||||
*/
|
||||
/// Adds a new scope to the stack
|
||||
void new_scope()
|
||||
{
|
||||
StackData &stack = get_stack_data();
|
||||
stack.push_back(Scope());
|
||||
get_stack_data().emplace_back();
|
||||
}
|
||||
|
||||
/**
|
||||
* Pops the current scope from the stack
|
||||
*/
|
||||
/// Pops the current scope from the stack
|
||||
void pop_scope()
|
||||
{
|
||||
StackData &stack = get_stack_data();
|
||||
@ -571,9 +515,8 @@ namespace chaiscript
|
||||
/// Pushes a new stack on to the list of stacks
|
||||
void new_stack()
|
||||
{
|
||||
Stack s(new Stack::element_type());
|
||||
s->push_back(Scope());
|
||||
m_stack_holder->stacks.push_back(s);
|
||||
// add a new Stack with 1 element
|
||||
m_stack_holder->stacks.emplace_back(1);
|
||||
}
|
||||
|
||||
void pop_stack()
|
||||
@ -581,17 +524,9 @@ namespace chaiscript
|
||||
m_stack_holder->stacks.pop_back();
|
||||
}
|
||||
|
||||
/// \returns the current stack
|
||||
Stack get_stack() const
|
||||
{
|
||||
return m_stack_holder->stacks.back();
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches the current stack for an object of the given name
|
||||
* includes a special overload for the _ place holder object to
|
||||
* ensure that it is always in scope.
|
||||
*/
|
||||
/// Searches the current stack for an object of the given name
|
||||
/// includes a special overload for the _ place holder object to
|
||||
/// ensure that it is always in scope.
|
||||
Boxed_Value get_object(const std::string &name) const
|
||||
{
|
||||
// Is it a placeholder object?
|
||||
@ -600,13 +535,13 @@ namespace chaiscript
|
||||
return m_place_holder;
|
||||
}
|
||||
|
||||
StackData &stack = get_stack_data();
|
||||
auto &stack = get_stack_data();
|
||||
|
||||
// Is it in the stack?
|
||||
for (int i = static_cast<int>(stack.size())-1; i >= 0; --i)
|
||||
for (auto stack_elem = stack.rbegin(); stack_elem != stack.rend(); ++stack_elem)
|
||||
{
|
||||
std::map<std::string, Boxed_Value>::const_iterator stackitr = stack[i].find(name);
|
||||
if (stackitr != stack[i].end())
|
||||
const auto stackitr = stack_elem->find(name);
|
||||
if (stackitr != stack_elem->end())
|
||||
{
|
||||
return stackitr->second;
|
||||
}
|
||||
@ -616,7 +551,7 @@ namespace chaiscript
|
||||
{
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_global_object_mutex);
|
||||
|
||||
auto itr = m_state.m_global_objects.find(name);
|
||||
const auto itr = m_state.m_global_objects.find(name);
|
||||
if (itr != m_state.m_global_objects.end())
|
||||
{
|
||||
return itr->second;
|
||||
@ -627,9 +562,7 @@ namespace chaiscript
|
||||
return get_function_object(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a new named type
|
||||
*/
|
||||
/// Registers a new named type
|
||||
void add(const Type_Info &ti, const std::string &name)
|
||||
{
|
||||
add_global_const(const_var(ti), name + "_type");
|
||||
@ -639,14 +572,12 @@ namespace chaiscript
|
||||
m_state.m_types.insert(std::make_pair(name, ti));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type info for a named type
|
||||
*/
|
||||
/// Returns the type info for a named type
|
||||
Type_Info get_type(const std::string &name) const
|
||||
{
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
auto itr = m_state.m_types.find(name);
|
||||
const auto itr = m_state.m_types.find(name);
|
||||
|
||||
if (itr != m_state.m_types.end())
|
||||
{
|
||||
@ -656,11 +587,9 @@ namespace chaiscript
|
||||
throw std::range_error("Type Not Known");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the registered name of a known type_info object
|
||||
* compares the "bare_type_info" for the broadest possible
|
||||
* match
|
||||
*/
|
||||
/// Returns the registered name of a known type_info object
|
||||
/// compares the "bare_type_info" for the broadest possible
|
||||
/// match
|
||||
std::string get_type_name(const Type_Info &ti) const
|
||||
{
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
@ -676,9 +605,7 @@ namespace chaiscript
|
||||
return ti.bare_name();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return all registered types
|
||||
*/
|
||||
/// Return all registered types
|
||||
std::vector<std::pair<std::string, Type_Info> > get_types() const
|
||||
{
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
@ -686,26 +613,22 @@ namespace chaiscript
|
||||
return std::vector<std::pair<std::string, Type_Info> >(m_state.m_types.begin(), m_state.m_types.end());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a function by name
|
||||
*/
|
||||
std::vector< Proxy_Function >
|
||||
get_function(const std::string &t_name) const
|
||||
/// Return a function by name
|
||||
std::vector< Proxy_Function > get_function(const std::string &t_name) const
|
||||
{
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
const auto &funs = get_functions_int();
|
||||
|
||||
auto itr = funs.find(t_name);
|
||||
|
||||
if (itr != funs.end())
|
||||
{
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
const std::map<std::string, std::vector<Proxy_Function> > &funs = get_functions_int();
|
||||
|
||||
auto itr
|
||||
= funs.find(t_name);
|
||||
|
||||
if (itr != funs.end())
|
||||
{
|
||||
return itr->second;
|
||||
} else {
|
||||
return std::vector<Proxy_Function>();
|
||||
}
|
||||
return itr->second;
|
||||
} else {
|
||||
return std::vector<Proxy_Function>();
|
||||
}
|
||||
}
|
||||
|
||||
/// \returns a function object (Boxed_Value wrapper) if it exists
|
||||
/// \throws std::range_error if it does not
|
||||
@ -713,7 +636,7 @@ namespace chaiscript
|
||||
{
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
const std::map<std::string, Proxy_Function> &funs = get_function_objects_int();
|
||||
const auto &funs = get_function_objects_int();
|
||||
|
||||
auto itr = funs.find(t_name);
|
||||
|
||||
@ -725,14 +648,12 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if a function exists
|
||||
*/
|
||||
/// Return true if a function exists
|
||||
bool function_exists(const std::string &name) const
|
||||
{
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
const std::map<std::string, std::vector<Proxy_Function> > &functions = get_functions_int();
|
||||
const auto &functions = get_functions_int();
|
||||
return functions.find(name) != functions.end();
|
||||
}
|
||||
|
||||
@ -740,7 +661,7 @@ namespace chaiscript
|
||||
/// the current scope.
|
||||
std::map<std::string, Boxed_Value> get_parent_locals() const
|
||||
{
|
||||
StackData &stack = get_stack_data();
|
||||
auto &stack = get_stack_data();
|
||||
if (stack.size() > 1)
|
||||
{
|
||||
return stack[1];
|
||||
@ -752,8 +673,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
|
||||
{
|
||||
StackData &stack = get_stack_data();
|
||||
Scope &scope = stack.front();
|
||||
auto &stack = get_stack_data();
|
||||
auto &scope = stack.front();
|
||||
return scope;
|
||||
}
|
||||
|
||||
@ -764,8 +685,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)
|
||||
{
|
||||
StackData &stack = get_stack_data();
|
||||
Scope &scope = stack.front();
|
||||
auto &stack = get_stack_data();
|
||||
auto &scope = stack.front();
|
||||
scope = t_locals;
|
||||
}
|
||||
|
||||
@ -779,12 +700,11 @@ namespace chaiscript
|
||||
Stack_Holder &s = *m_stack_holder;
|
||||
|
||||
// We don't want the current context, but one up if it exists
|
||||
StackData &stack = (s.stacks.size()==1)?(*(s.stacks.back())):(*s.stacks[s.stacks.size()-2]);
|
||||
StackData &stack = (s.stacks.size()==1)?(s.stacks.back()):(s.stacks[s.stacks.size()-2]);
|
||||
|
||||
std::map<std::string, Boxed_Value> retval;
|
||||
|
||||
// note: map insert doesn't overwrite existing values, which is why this works
|
||||
|
||||
for (auto itr = stack.rbegin(); itr != stack.rend(); ++itr)
|
||||
{
|
||||
retval.insert(itr->begin(), itr->end());
|
||||
@ -808,7 +728,7 @@ namespace chaiscript
|
||||
{
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
const std::map<std::string, Proxy_Function> &funs = get_function_objects_int();
|
||||
const auto &funs = get_function_objects_int();
|
||||
|
||||
std::map<std::string, Boxed_Value> objs;
|
||||
|
||||
@ -821,22 +741,20 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get a vector of all registered functions
|
||||
*/
|
||||
/// Get a vector of all registered functions
|
||||
std::vector<std::pair<std::string, Proxy_Function > > get_functions() const
|
||||
{
|
||||
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
std::vector<std::pair<std::string, Proxy_Function> > rets;
|
||||
|
||||
const std::map<std::string, std::vector<Proxy_Function> > &functions = get_functions_int();
|
||||
const auto &functions = get_functions_int();
|
||||
|
||||
for (const auto & function : functions)
|
||||
{
|
||||
for (const auto & internal_func : function.second)
|
||||
{
|
||||
rets.push_back(std::make_pair(function.first, internal_func));
|
||||
rets.emplace_back(function.first, internal_func);
|
||||
}
|
||||
}
|
||||
|
||||
@ -850,16 +768,14 @@ namespace chaiscript
|
||||
m_state.m_reserved_words.insert(name);
|
||||
}
|
||||
|
||||
const Dynamic_Cast_Conversions &conversions() const
|
||||
const Type_Conversions &conversions() const
|
||||
{
|
||||
return m_conversions;
|
||||
}
|
||||
|
||||
Boxed_Value call_function(const std::string &t_name, const std::vector<Boxed_Value> ¶ms) const
|
||||
{
|
||||
std::vector<Proxy_Function> functions = get_function(t_name);
|
||||
|
||||
return dispatch::dispatch(functions.begin(), functions.end(), params, m_conversions);
|
||||
return dispatch::dispatch(get_function(t_name), params, m_conversions);
|
||||
}
|
||||
|
||||
Boxed_Value call_function(const std::string &t_name) const
|
||||
@ -867,40 +783,29 @@ namespace chaiscript
|
||||
return call_function(t_name, std::vector<Boxed_Value>());
|
||||
}
|
||||
|
||||
Boxed_Value call_function(const std::string &t_name, const Boxed_Value &p1) const
|
||||
Boxed_Value call_function(const std::string &t_name, Boxed_Value p1) const
|
||||
{
|
||||
std::vector<Boxed_Value> params;
|
||||
params.push_back(p1);
|
||||
return call_function(t_name, params);
|
||||
return call_function(t_name, std::vector<Boxed_Value>({std::move(p1)}));
|
||||
}
|
||||
|
||||
Boxed_Value call_function(const std::string &t_name, const Boxed_Value &p1, const Boxed_Value &p2) const
|
||||
Boxed_Value call_function(const std::string &t_name, Boxed_Value p1, Boxed_Value p2) const
|
||||
{
|
||||
std::vector<Boxed_Value> params;
|
||||
params.push_back(p1);
|
||||
params.push_back(p2);
|
||||
return call_function(t_name, params);
|
||||
return call_function(t_name, std::vector<Boxed_Value>({std::move(p1), std::move(p2)}));
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump object info to stdout
|
||||
*/
|
||||
/// Dump object info to stdout
|
||||
void dump_object(const Boxed_Value &o) const
|
||||
{
|
||||
std::cout << (o.is_const()?"const ":"") << type_name(o) << std::endl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump type info to stdout
|
||||
*/
|
||||
/// Dump type info to stdout
|
||||
void dump_type(const Type_Info &type) const
|
||||
{
|
||||
std::cout << (type.is_const()?"const ":"") << get_type_name(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump function to stdout
|
||||
*/
|
||||
/// Dump function to stdout
|
||||
void dump_function(const std::pair<const std::string, Proxy_Function > &f) const
|
||||
{
|
||||
std::vector<Type_Info> params = f.second->get_param_types();
|
||||
@ -928,25 +833,21 @@ namespace chaiscript
|
||||
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.
|
||||
*/
|
||||
/// 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.size() < 1)
|
||||
if (params.empty())
|
||||
{
|
||||
throw chaiscript::exception::arity_error(static_cast<int>(params.size()), 1);
|
||||
}
|
||||
|
||||
Const_Proxy_Function f = this->boxed_cast<Const_Proxy_Function>(params[0]);
|
||||
const Const_Proxy_Function &f = this->boxed_cast<Const_Proxy_Function>(params[0]);
|
||||
|
||||
return Boxed_Value(f->call_match(std::vector<Boxed_Value>(params.begin() + 1, params.end()), m_conversions));
|
||||
}
|
||||
|
||||
/**
|
||||
* Dump all system info to stdout
|
||||
*/
|
||||
/// Dump all system info to stdout
|
||||
void dump_system() const
|
||||
{
|
||||
std::cout << "Registered Types: " << std::endl;
|
||||
@ -973,9 +874,7 @@ namespace chaiscript
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
/**
|
||||
* return true if the Boxed_Value matches the registered type by name
|
||||
*/
|
||||
/// return true if the Boxed_Value matches the registered type by name
|
||||
bool is_type(const Boxed_Value &r, const std::string &user_typename) const
|
||||
{
|
||||
try {
|
||||
@ -1016,6 +915,22 @@ 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.insert(s.call_params.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.insert(s.call_params.begin(), std::move(param));
|
||||
}
|
||||
}
|
||||
|
||||
void save_function_params(const std::vector<Boxed_Value> &t_params)
|
||||
{
|
||||
Stack_Holder &s = *m_stack_holder;
|
||||
@ -1024,7 +939,15 @@ namespace chaiscript
|
||||
|
||||
void new_function_call()
|
||||
{
|
||||
Stack_Holder &s = *m_stack_holder;
|
||||
if (s.call_depth == 0)
|
||||
{
|
||||
m_conversions.enable_conversion_saves(true);
|
||||
}
|
||||
|
||||
++m_stack_holder->call_depth;
|
||||
|
||||
save_function_params(m_conversions.take_saves());
|
||||
}
|
||||
|
||||
void pop_function_call()
|
||||
@ -1039,17 +962,16 @@ namespace chaiscript
|
||||
/// \todo Critical: this needs to be smarter, memory can expand quickly
|
||||
/// in tight loops involving function calls
|
||||
s.call_params.clear();
|
||||
m_conversions.enable_conversion_saves(false);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* Returns the current stack
|
||||
* make const/non const versions
|
||||
*/
|
||||
/// Returns the current stack
|
||||
/// make const/non const versions
|
||||
StackData &get_stack_data() const
|
||||
{
|
||||
return *(m_stack_holder->stacks.back());
|
||||
return m_stack_holder->stacks.back();
|
||||
}
|
||||
|
||||
const std::map<std::string, Proxy_Function> &get_function_objects_int() const
|
||||
@ -1074,17 +996,17 @@ namespace chaiscript
|
||||
|
||||
static bool function_less_than(const Proxy_Function &lhs, const Proxy_Function &rhs)
|
||||
{
|
||||
const std::vector<Type_Info> lhsparamtypes = lhs->get_param_types();
|
||||
const std::vector<Type_Info> rhsparamtypes = rhs->get_param_types();
|
||||
const auto &lhsparamtypes = lhs->get_param_types();
|
||||
const auto &rhsparamtypes = rhs->get_param_types();
|
||||
|
||||
const size_t lhssize = lhsparamtypes.size();
|
||||
const size_t rhssize = rhsparamtypes.size();
|
||||
const auto lhssize = lhsparamtypes.size();
|
||||
const auto rhssize = rhsparamtypes.size();
|
||||
|
||||
const Type_Info boxed_type = user_type<Boxed_Value>();
|
||||
const Type_Info boxed_pod_type = user_type<Boxed_Number>();
|
||||
CHAISCRIPT_CONSTEXPR auto boxed_type = user_type<Boxed_Value>();
|
||||
CHAISCRIPT_CONSTEXPR auto boxed_pod_type = user_type<Boxed_Number>();
|
||||
|
||||
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));
|
||||
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));
|
||||
|
||||
if (dynamic_lhs && dynamic_rhs)
|
||||
{
|
||||
@ -1112,11 +1034,10 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
|
||||
|
||||
for (size_t i = 1; i < lhssize && i < rhssize; ++i)
|
||||
{
|
||||
const Type_Info lt = lhsparamtypes[i];
|
||||
const Type_Info rt = rhsparamtypes[i];
|
||||
const Type_Info < = lhsparamtypes[i];
|
||||
const Type_Info &rt = rhsparamtypes[i];
|
||||
|
||||
if (lt.bare_equal(rt) && lt.is_const() == rt.is_const())
|
||||
{
|
||||
@ -1167,9 +1088,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Throw a reserved_word exception if the name is not allowed
|
||||
*/
|
||||
/// Throw a reserved_word exception if the name is not allowed
|
||||
void validate_object_name(const std::string &name) const
|
||||
{
|
||||
if (name.find("::") != std::string::npos) {
|
||||
@ -1184,29 +1103,24 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation detail for adding a function.
|
||||
* \throws exception::name_conflict_error if there's a function matching the given one being added
|
||||
*/
|
||||
/// Implementation detail for adding a function.
|
||||
/// \throws exception::name_conflict_error if there's a function matching the given one being added
|
||||
void add_function(const Proxy_Function &t_f, const std::string &t_name)
|
||||
{
|
||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
|
||||
|
||||
std::map<std::string, std::vector<Proxy_Function> > &funcs = get_functions_int();
|
||||
auto &funcs = get_functions_int();
|
||||
|
||||
auto itr
|
||||
= funcs.find(t_name);
|
||||
auto itr = funcs.find(t_name);
|
||||
|
||||
std::map<std::string, Proxy_Function> &func_objs = get_function_objects_int();
|
||||
auto &func_objs = get_function_objects_int();
|
||||
|
||||
if (itr != funcs.end())
|
||||
{
|
||||
std::vector<Proxy_Function> &vec = itr->second;
|
||||
for (std::vector<Proxy_Function>::const_iterator itr2 = vec.begin();
|
||||
itr2 != vec.end();
|
||||
++itr2)
|
||||
auto &vec = itr->second;
|
||||
for (const auto &func : vec)
|
||||
{
|
||||
if ((*t_f) == *(*itr2))
|
||||
if ((*t_f) == *(func))
|
||||
{
|
||||
throw chaiscript::exception::name_conflict_error(t_name);
|
||||
}
|
||||
@ -1214,19 +1128,16 @@ namespace chaiscript
|
||||
|
||||
vec.push_back(t_f);
|
||||
std::stable_sort(vec.begin(), vec.end(), &function_less_than);
|
||||
func_objs[t_name] = Proxy_Function(new Dispatch_Function(vec));
|
||||
func_objs[t_name] = std::make_shared<Dispatch_Function>(vec);
|
||||
} else if (t_f->has_arithmetic_param()) {
|
||||
// if the function is the only function but it also contains
|
||||
// arithmetic operators, we must wrap it in a dispatch function
|
||||
// to allow for automatic arithmetic type conversions
|
||||
std::vector<Proxy_Function> vec;
|
||||
vec.push_back(t_f);
|
||||
std::vector<Proxy_Function> vec({t_f});
|
||||
funcs.insert(std::make_pair(t_name, vec));
|
||||
func_objs[t_name] = Proxy_Function(new Dispatch_Function(vec));
|
||||
func_objs[t_name] = std::make_shared<Dispatch_Function>(std::move(vec));
|
||||
} else {
|
||||
std::vector<Proxy_Function> vec;
|
||||
vec.push_back(t_f);
|
||||
funcs.insert(std::make_pair(t_name, vec));
|
||||
funcs.insert(std::make_pair(t_name, std::vector<Proxy_Function>{t_f}));
|
||||
func_objs[t_name] = t_f;
|
||||
}
|
||||
|
||||
@ -1241,18 +1152,16 @@ namespace chaiscript
|
||||
Stack_Holder()
|
||||
: call_depth(0)
|
||||
{
|
||||
Stack s(new StackData());
|
||||
s->push_back(Scope());
|
||||
stacks.push_back(s);
|
||||
stacks.emplace_back(1);
|
||||
}
|
||||
|
||||
std::deque<Stack> stacks;
|
||||
std::deque<StackData> stacks;
|
||||
|
||||
std::list<Boxed_Value> call_params;
|
||||
int call_depth;
|
||||
};
|
||||
};
|
||||
|
||||
Dynamic_Cast_Conversions m_conversions;
|
||||
Type_Conversions m_conversions;
|
||||
chaiscript::detail::threading::Thread_Storage<Stack_Holder> m_stack_holder;
|
||||
|
||||
|
||||
|
@ -1,294 +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 <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 Dynamic_Cast_Conversions;
|
||||
class Type_Conversions;
|
||||
namespace dispatch {
|
||||
class Proxy_Function_Base;
|
||||
} // namespace dispatch
|
||||
@ -64,18 +64,16 @@ 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()),
|
||||
: Proxy_Function_Base(t_func->get_param_types(), t_func->get_arity()),
|
||||
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)
|
||||
@ -86,7 +84,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)),
|
||||
: Proxy_Function_Base(build_param_types(t_func->get_param_types(), t_ti), t_func->get_arity()),
|
||||
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)
|
||||
@ -96,11 +94,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
|
||||
{
|
||||
const Dynamic_Object_Function *df = dynamic_cast<const Dynamic_Object_Function *>(&f);
|
||||
if (df)
|
||||
if (const auto *df = dynamic_cast<const Dynamic_Object_Function *>(&f))
|
||||
{
|
||||
return df->m_type_name == m_type_name && (*df->m_func) == (*m_func);
|
||||
} else {
|
||||
@ -108,7 +106,7 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
if (dynamic_object_typename_match(vals, m_type_name, m_ti, t_conversions))
|
||||
{
|
||||
@ -123,12 +121,6 @@ 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();
|
||||
@ -136,7 +128,7 @@ namespace chaiscript
|
||||
|
||||
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
if (dynamic_object_typename_match(params, m_type_name, m_ti, t_conversions))
|
||||
{
|
||||
@ -146,7 +138,7 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool compare_first_type(const Boxed_Value &bv, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual bool compare_first_type(const Boxed_Value &bv, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return dynamic_object_typename_match(bv, m_type_name, m_ti, t_conversions);
|
||||
}
|
||||
@ -164,7 +156,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
bool dynamic_object_typename_match(const Boxed_Value &bv, const std::string &name,
|
||||
const std::shared_ptr<Type_Info> &ti, const Dynamic_Cast_Conversions &t_conversions) const
|
||||
const std::unique_ptr<Type_Info> &ti, const Type_Conversions &t_conversions) const
|
||||
{
|
||||
if (bv.get_type_info().bare_equal(m_doti))
|
||||
{
|
||||
@ -186,7 +178,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
bool dynamic_object_typename_match(const std::vector<Boxed_Value> &bvs, const std::string &name,
|
||||
const std::shared_ptr<Type_Info> &ti, const Dynamic_Cast_Conversions &t_conversions) const
|
||||
const std::unique_ptr<Type_Info> &ti, const Type_Conversions &t_conversions) const
|
||||
{
|
||||
if (bvs.size() > 0)
|
||||
{
|
||||
@ -198,7 +190,7 @@ namespace chaiscript
|
||||
|
||||
std::string m_type_name;
|
||||
Proxy_Function m_func;
|
||||
std::shared_ptr<Type_Info> m_ti;
|
||||
std::unique_ptr<Type_Info> m_ti;
|
||||
const Type_Info m_doti;
|
||||
|
||||
|
||||
@ -217,7 +209,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())),
|
||||
: Proxy_Function_Base(build_type_list(t_func->get_param_types()), t_func->get_arity() - 1),
|
||||
m_type_name(std::move(t_type_name)), m_func(t_func)
|
||||
{
|
||||
assert( (t_func->get_arity() > 0 || t_func->get_arity() < 0)
|
||||
@ -250,33 +242,24 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
std::vector<Boxed_Value> new_vals;
|
||||
new_vals.push_back(Boxed_Value(Dynamic_Object(m_type_name)));
|
||||
std::vector<Boxed_Value> new_vals{Boxed_Value(Dynamic_Object(m_type_name))};
|
||||
new_vals.insert(new_vals.end(), vals.begin(), vals.end());
|
||||
|
||||
return m_func->call_match(new_vals, t_conversions);
|
||||
}
|
||||
|
||||
|
||||
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 Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
std::vector<Boxed_Value> new_params;
|
||||
chaiscript::Boxed_Value bv = var(Dynamic_Object(m_type_name));
|
||||
new_params.push_back(bv);
|
||||
auto bv = var(Dynamic_Object(m_type_name));
|
||||
std::vector<Boxed_Value> new_params{bv};
|
||||
new_params.insert(new_params.end(), params.begin(), params.end());
|
||||
|
||||
(*m_func)(new_params, t_conversions);
|
||||
|
@ -23,6 +23,7 @@ namespace chaiscript
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
/// \todo make this a variadic template
|
||||
struct Exception_Handler_Base
|
||||
{
|
||||
virtual void handle(const Boxed_Value &bv, const Dispatch_Engine &t_engine) = 0;
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
namespace chaiscript {
|
||||
class Boxed_Value;
|
||||
class Dynamic_Cast_Conversions;
|
||||
class Type_Conversions;
|
||||
namespace detail {
|
||||
template <typename T> struct Cast_Helper;
|
||||
} // namespace detail
|
||||
@ -28,66 +28,56 @@ 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 Dynamic_Cast_Conversions *t_conversions)
|
||||
functor(const std::vector<Const_Proxy_Function> &funcs, const Type_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 Dynamic_Cast_Conversions *t_conversions)
|
||||
functor(Const_Proxy_Function func, const Type_Conversions *t_conversions)
|
||||
{
|
||||
std::vector<Const_Proxy_Function> funcs;
|
||||
funcs.push_back(func);
|
||||
return functor<FunctionType>(funcs, t_conversions);
|
||||
return functor<FunctionType>(std::vector<Const_Proxy_Function>({func}), 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 Dynamic_Cast_Conversions *t_conversions)
|
||||
functor(const Boxed_Value &bv, const Type_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 Dynamic_Cast_Conversions *t_conversions)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *t_conversions)
|
||||
{
|
||||
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
|
||||
{
|
||||
@ -98,15 +88,13 @@ 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 Dynamic_Cast_Conversions *t_conversions)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *t_conversions)
|
||||
{
|
||||
if (ob.get_type_info().bare_equal(user_type<Const_Proxy_Function>()))
|
||||
{
|
||||
@ -117,15 +105,13 @@ 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 Dynamic_Cast_Conversions *t_conversions)
|
||||
static Result_Type cast(const Boxed_Value &ob, const Type_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 "dynamic_cast_conversion.hpp"
|
||||
#include "type_conversions.hpp"
|
||||
#include "proxy_functions.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
@ -26,15 +26,13 @@ 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 Dynamic_Cast_Conversions &t_conversions)
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions)
|
||||
{
|
||||
return boxed_cast<Ret>(dispatch::dispatch(t_funcs, params, t_conversions));
|
||||
}
|
||||
@ -47,7 +45,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 Dynamic_Cast_Conversions &t_conversions)
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions)
|
||||
{
|
||||
return Boxed_Number(dispatch::dispatch(t_funcs, params, t_conversions)).get_as<Ret>();
|
||||
}
|
||||
@ -61,7 +59,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 Dynamic_Cast_Conversions &t_conversions)
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions)
|
||||
{
|
||||
dispatch::dispatch(t_funcs, params, t_conversions);
|
||||
}
|
||||
@ -73,7 +71,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 Dynamic_Cast_Conversions &t_conversions)
|
||||
Build_Function_Caller_Helper(std::vector<Const_Proxy_Function> t_funcs, const Type_Conversions &t_conversions)
|
||||
: m_funcs(std::move(t_funcs)),
|
||||
m_conversions(t_conversions)
|
||||
{
|
||||
@ -81,7 +79,7 @@ namespace chaiscript
|
||||
|
||||
Ret operator()(Param...param)
|
||||
{
|
||||
return Function_Caller_Ret<Ret, std::is_arithmetic<Ret>::value>::call(m_funcs, {
|
||||
return Function_Caller_Ret<Ret, std::is_arithmetic<Ret>::value && !std::is_same<Ret, bool>::value>::call(m_funcs, {
|
||||
(std::is_reference<Param>::value&&!(std::is_same<chaiscript::Boxed_Value, typename std::remove_const<typename std::remove_reference<Param>::type>::type>::value))?Boxed_Value(std::ref(param)):Boxed_Value(param)...
|
||||
}, m_conversions
|
||||
|
||||
@ -90,13 +88,13 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
std::vector<Const_Proxy_Function> m_funcs;
|
||||
Dynamic_Cast_Conversions m_conversions;
|
||||
Type_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 Dynamic_Cast_Conversions *t_conversions)
|
||||
std::function<Ret (Params...)> build_function_caller_helper(Ret (Params...), const std::vector<Const_Proxy_Function> &funcs, const Type_Conversions *t_conversions)
|
||||
{
|
||||
if (funcs.size() == 1)
|
||||
{
|
||||
@ -112,7 +110,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:Dynamic_Cast_Conversions()));
|
||||
return std::function<Ret (Params...)>(Build_Function_Caller_Helper<Ret, Params...>(funcs, t_conversions?*t_conversions:Type_Conversions()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -48,6 +48,15 @@ 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> &>
|
||||
{
|
||||
|
@ -8,6 +8,7 @@
|
||||
#define CHAISCRIPT_OPERATORS_HPP_
|
||||
|
||||
#include "../chaiscript_defines.hpp"
|
||||
#include "register_function.hpp"
|
||||
|
||||
namespace chaiscript
|
||||
{
|
||||
@ -15,442 +16,446 @@ namespace chaiscript
|
||||
{
|
||||
namespace operators
|
||||
{
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret assign(L l, R r)
|
||||
{
|
||||
return (l = r);
|
||||
}
|
||||
namespace detail
|
||||
{
|
||||
/// \todo make this return a decltype once we drop gcc 4.6
|
||||
template<typename L, typename R>
|
||||
auto assign(L l, R r) -> L&
|
||||
{
|
||||
return (l = r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret assign_bitwise_and(L l, R r)
|
||||
{
|
||||
return (l &= r);
|
||||
}
|
||||
template<typename L, typename R>
|
||||
auto assign_bitwise_and(L l, R r) -> decltype((l &= r))
|
||||
{
|
||||
return (l &= r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret assign_xor(L l, R r)
|
||||
{
|
||||
return (l ^= r);
|
||||
}
|
||||
template<typename L, typename R>
|
||||
auto assign_xor(L l, R r) -> decltype((l^=r))
|
||||
{
|
||||
return (l ^= r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret assign_bitwise_or(L l, R r)
|
||||
{
|
||||
return (l |= r);
|
||||
}
|
||||
template<typename L, typename R>
|
||||
auto assign_bitwise_or(L l, R r) -> decltype((l |= r))
|
||||
{
|
||||
return (l |= r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret assign_difference(L l, R r)
|
||||
{
|
||||
return (l -= r);
|
||||
}
|
||||
template<typename L, typename R>
|
||||
auto assign_difference(L l, R r) -> decltype(( l -= r))
|
||||
{
|
||||
return (l -= r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret assign_left_shift(L l, R r)
|
||||
{
|
||||
return (l <<= r);
|
||||
}
|
||||
template<typename L, typename R>
|
||||
auto assign_left_shift(L l, R r) -> decltype(( l <<= r))
|
||||
{
|
||||
return (l <<= r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret assign_product(L l, R r)
|
||||
{
|
||||
return (l *= r);
|
||||
}
|
||||
template<typename L, typename R>
|
||||
auto assign_product(L l, R r) -> decltype(( l *= r ))
|
||||
{
|
||||
return (l *= r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret assign_quotient(L l, R r)
|
||||
{
|
||||
return (l /= r);
|
||||
}
|
||||
template<typename L, typename R>
|
||||
auto assign_quotient(L l, R r) -> decltype(( l /= r ))
|
||||
{
|
||||
return (l /= r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret assign_remainder(L l, R r)
|
||||
{
|
||||
return (l %= r);
|
||||
}
|
||||
template<typename L, typename R>
|
||||
auto assign_remainder(L l, R r) -> decltype(( l %= r ))
|
||||
{
|
||||
return (l %= r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret assign_right_shift(L l, R r)
|
||||
{
|
||||
return (l >>= r);
|
||||
}
|
||||
template<typename L, typename R>
|
||||
auto assign_right_shift(L l, R r) -> decltype(( l >>= r))
|
||||
{
|
||||
return (l >>= r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret assign_sum(L l, R r)
|
||||
{
|
||||
return (l += r);
|
||||
}
|
||||
/// \todo make this return a decltype once we drop gcc 4.6
|
||||
template<typename L, typename R>
|
||||
auto assign_sum(L l, R r) -> L&
|
||||
{
|
||||
return (l += r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L>
|
||||
Ret prefix_decrement(L l)
|
||||
{
|
||||
return (--l);
|
||||
}
|
||||
template<typename L>
|
||||
auto prefix_decrement(L l) -> decltype(( --l ))
|
||||
{
|
||||
return (--l);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L>
|
||||
Ret prefix_increment(L l)
|
||||
{
|
||||
return (++l);
|
||||
}
|
||||
template<typename L>
|
||||
auto prefix_increment(L l) -> decltype(( ++l ))
|
||||
{
|
||||
return (++l);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret equal(L l, R r)
|
||||
{
|
||||
return (l == r);
|
||||
}
|
||||
template<typename L, typename R>
|
||||
auto equal(L l, R r) -> decltype(( l == r ))
|
||||
{
|
||||
return (l == r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret greater_than(L l, R r)
|
||||
{
|
||||
return (l > r);
|
||||
}
|
||||
template<typename L, typename R>
|
||||
auto greater_than(L l, R r) -> decltype(( l > r ))
|
||||
{
|
||||
return (l > r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret greater_than_equal(L l, R r)
|
||||
{
|
||||
return (l >= r);
|
||||
}
|
||||
template<typename L, typename R>
|
||||
auto greater_than_equal(L l, R r) -> decltype(( l >= r ))
|
||||
{
|
||||
return (l >= r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret less_than(L l, R r)
|
||||
{
|
||||
return (l < r);
|
||||
}
|
||||
template<typename L, typename R>
|
||||
auto less_than(L l, R r) -> decltype(( l < r ))
|
||||
{
|
||||
return (l < r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret less_than_equal(L l, R r)
|
||||
{
|
||||
return (l <= r);
|
||||
}
|
||||
template<typename L, typename R>
|
||||
auto less_than_equal(L l, R r) -> decltype(( l <= r ))
|
||||
{
|
||||
return (l <= r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L>
|
||||
Ret logical_compliment(L l)
|
||||
{
|
||||
return (!l);
|
||||
}
|
||||
template<typename L>
|
||||
auto logical_compliment(L l) -> decltype(( !l ))
|
||||
{
|
||||
return (!l);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret not_equal(L l, R r)
|
||||
{
|
||||
return (l != r);
|
||||
}
|
||||
template<typename L, typename R>
|
||||
auto not_equal(L l, R r) -> decltype(( l != r ))
|
||||
{
|
||||
return (l != r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret addition(L l, R r)
|
||||
{
|
||||
return (l + r);
|
||||
}
|
||||
template<typename L, typename R>
|
||||
auto addition(L l, R r) -> decltype(( l + r ))
|
||||
{
|
||||
return (l + r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L>
|
||||
Ret unary_plus(L l)
|
||||
{
|
||||
return (+l);
|
||||
}
|
||||
template<typename L>
|
||||
auto unary_plus(L l) -> decltype(( +l ))
|
||||
{
|
||||
return (+l);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret subtraction(L l, R r)
|
||||
{
|
||||
return (l - r);
|
||||
}
|
||||
template<typename L, typename R>
|
||||
auto subtraction(L l, R r) -> decltype(( l - r ))
|
||||
{
|
||||
return (l - r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L>
|
||||
Ret unary_minus(L l)
|
||||
{
|
||||
template<typename L>
|
||||
auto unary_minus(L l) -> decltype(( -l ))
|
||||
{
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4146)
|
||||
return (-l);
|
||||
return (-l);
|
||||
#pragma warning(pop)
|
||||
#else
|
||||
return (-l);
|
||||
return (-l);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret bitwise_and(L l, R r)
|
||||
{
|
||||
return (l & r);
|
||||
}
|
||||
template<typename L, typename R>
|
||||
auto bitwise_and(L l, R r) -> decltype(( l & r ))
|
||||
{
|
||||
return (l & r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L>
|
||||
Ret bitwise_compliment(L l)
|
||||
{
|
||||
return (~l);
|
||||
}
|
||||
template<typename L>
|
||||
auto bitwise_compliment(L l) -> decltype(( ~l ))
|
||||
{
|
||||
return (~l);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret bitwise_xor(L l, R r)
|
||||
{
|
||||
return (l ^ r);
|
||||
}
|
||||
template<typename L, typename R>
|
||||
auto bitwise_xor(L l, R r) -> decltype(( l ^ r ))
|
||||
{
|
||||
return (l ^ r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret bitwise_or(L l, R r)
|
||||
{
|
||||
return (l | r);
|
||||
}
|
||||
template<typename L, typename R>
|
||||
auto bitwise_or(L l, R r) -> decltype(( l | r ))
|
||||
{
|
||||
return (l | r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret division(L l, R r)
|
||||
{
|
||||
return (l / r);
|
||||
}
|
||||
template<typename L, typename R>
|
||||
auto division(L l, R r) -> decltype(( l / r ))
|
||||
{
|
||||
return (l / r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret left_shift(L l, R r)
|
||||
{
|
||||
return l << r;
|
||||
}
|
||||
template<typename L, typename R>
|
||||
auto left_shift(L l, R r) -> decltype(( l << r ))
|
||||
{
|
||||
return l << r;
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret multiplication(L l, R r)
|
||||
{
|
||||
return l * r;
|
||||
}
|
||||
template<typename L, typename R>
|
||||
auto multiplication(L l, R r) -> decltype(( l * r ))
|
||||
{
|
||||
return l * r;
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret remainder(L l, R r)
|
||||
{
|
||||
return (l % r);
|
||||
}
|
||||
|
||||
template<typename Ret, typename L, typename R>
|
||||
Ret right_shift(L l, R r)
|
||||
{
|
||||
return (l >> r);
|
||||
}
|
||||
template<typename L, typename R>
|
||||
auto remainder(L l, R r) -> decltype(( l % r ))
|
||||
{
|
||||
return (l % r);
|
||||
}
|
||||
|
||||
template<typename L, typename R>
|
||||
auto right_shift(L l, R r) -> decltype(( l >> r ))
|
||||
{
|
||||
return (l >> r);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&assign<T &, T &, const T&>), "=");
|
||||
m->add(chaiscript::fun(&detail::assign<T &, const T&>), "=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_bitwise_and(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&assign_bitwise_and<T &, T &, const T&>), "&=");
|
||||
m->add(chaiscript::fun(&detail::assign_bitwise_and<T &, const T&>), "&=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_xor(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&assign_xor<T &, T &, const T&>), "^=");
|
||||
m->add(chaiscript::fun(&detail::assign_xor<T &, const T&>), "^=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_bitwise_or(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&assign_bitwise_or<T &, T &, const T&>), "|=");
|
||||
m->add(chaiscript::fun(&detail::assign_bitwise_or<T &, const T&>), "|=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_difference(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&assign_difference<T &, T &, const T&>), "-=");
|
||||
m->add(chaiscript::fun(&detail::assign_difference<T &, const T&>), "-=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_left_shift(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&assign_left_shift<T &, T &, const T&>), "<<=");
|
||||
m->add(chaiscript::fun(&detail::assign_left_shift<T &, const T&>), "<<=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_product(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&assign_product<T &, T &, const T&>), "*=");
|
||||
m->add(chaiscript::fun(&detail::assign_product<T &, const T&>), "*=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_quotient(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&assign_quotient<T &, T &, const T&>), "/=");
|
||||
m->add(chaiscript::fun(&detail::assign_quotient<T &, const T&>), "/=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_remainder(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&assign_remainder<T &, T &, const T&>), "%=");
|
||||
m->add(chaiscript::fun(&detail::assign_remainder<T &, const T&>), "%=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_right_shift(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&assign_right_shift<T &, T &, const T&>), ">>=");
|
||||
m->add(chaiscript::fun(&detail::assign_right_shift<T &, const T&>), ">>=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr assign_sum(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&assign_sum<T &, T &, const T&>), "+=");
|
||||
m->add(chaiscript::fun(&detail::assign_sum<T &, const T&>), "+=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr prefix_decrement(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&prefix_decrement<T &, T &>), "--");
|
||||
m->add(chaiscript::fun(&detail::prefix_decrement<T &>), "--");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr prefix_increment(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&prefix_increment<T &, T &>), "++");
|
||||
m->add(chaiscript::fun(&detail::prefix_increment<T &>), "++");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr equal(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&equal<bool, const T&, const T&>), "==");
|
||||
m->add(chaiscript::fun(&detail::equal<const T&, const T&>), "==");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr greater_than(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&greater_than<bool, const T&, const T&>), ">");
|
||||
m->add(chaiscript::fun(&detail::greater_than<const T&, const T&>), ">");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr greater_than_equal(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&greater_than_equal<bool, const T&, const T&>), ">=");
|
||||
m->add(chaiscript::fun(&detail::greater_than_equal<const T&, const T&>), ">=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr less_than(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&less_than<bool, const T&, const T&>), "<");
|
||||
m->add(chaiscript::fun(&detail::less_than<const T&, const T&>), "<");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr less_than_equal(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&less_than_equal<bool, const T&, const T&>), "<=");
|
||||
m->add(chaiscript::fun(&detail::less_than_equal<const T&, const T&>), "<=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr logical_compliment(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&logical_compliment<bool, const T &>), "!");
|
||||
m->add(chaiscript::fun(&detail::logical_compliment<const T &>), "!");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr not_equal(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(¬_equal<bool, const T &, const T &>), "!=");
|
||||
m->add(chaiscript::fun(&detail::not_equal<const T &, const T &>), "!=");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr addition(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&addition<T, const T &, const T &>), "+");
|
||||
m->add(chaiscript::fun(&detail::addition<const T &, const T &>), "+");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr unary_plus(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&unary_plus<T, const T &>), "+");
|
||||
m->add(chaiscript::fun(&detail::unary_plus<const T &>), "+");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr subtraction(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&subtraction<T, const T &, const T &>), "-");
|
||||
m->add(chaiscript::fun(&detail::subtraction<const T &, const T &>), "-");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr unary_minus(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&unary_minus<T, const T &>), "-");
|
||||
m->add(chaiscript::fun(&detail::unary_minus<const T &>), "-");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr bitwise_and(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&bitwise_and<T, const T &, const T &>), "&");
|
||||
m->add(chaiscript::fun(&detail::bitwise_and<const T &, const T &>), "&");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr bitwise_compliment(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&bitwise_compliment<T, const T &>), "~");
|
||||
m->add(chaiscript::fun(&detail::bitwise_compliment<const T &>), "~");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr bitwise_xor(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&bitwise_xor<T, const T &, const T &>), "^");
|
||||
m->add(chaiscript::fun(&detail::bitwise_xor<const T &, const T &>), "^");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr bitwise_or(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&bitwise_or<T, const T &, const T &>), "|");
|
||||
m->add(chaiscript::fun(&detail::bitwise_or<const T &, const T &>), "|");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr division(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&division<T, const T &, const T &>), "/");
|
||||
m->add(chaiscript::fun(&detail::division<const T &, const T &>), "/");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr left_shift(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&left_shift<T, const T &, const T &>), "<<");
|
||||
m->add(chaiscript::fun(&detail::left_shift<const T &, const T &>), "<<");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr multiplication(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&multiplication<T, const T &, const T &>), "*");
|
||||
m->add(chaiscript::fun(&detail::multiplication<const T &, const T &>), "*");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr remainder(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&remainder<T, const T &, const T &>), "%");
|
||||
m->add(chaiscript::fun(&detail::remainder<const T &, const T &>), "%");
|
||||
return m;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
ModulePtr right_shift(ModulePtr m = ModulePtr(new Module()))
|
||||
{
|
||||
m->add(fun(&right_shift<T, const T &, const T &>), ">>");
|
||||
m->add(chaiscript::fun(&detail::right_shift<const T &, const T &>), ">>");
|
||||
return m;
|
||||
}
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ namespace chaiscript
|
||||
template<typename Class, typename ... Params>
|
||||
std::shared_ptr<Class> constructor_(Params ... params)
|
||||
{
|
||||
return std::shared_ptr<Class>(new Class(params...));
|
||||
return std::make_shared<Class>(params...);
|
||||
}
|
||||
|
||||
template<typename Class, typename ... Params >
|
||||
|
@ -26,7 +26,7 @@
|
||||
#include "type_info.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
class Dynamic_Cast_Conversions;
|
||||
class Type_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::Dynamic_Cast_Conversions &t_conversions) const
|
||||
Boxed_Value operator()(const std::vector<Boxed_Value> ¶ms, const chaiscript::Type_Conversions &t_conversions) const
|
||||
{
|
||||
Boxed_Value bv = do_call(params, t_conversions);
|
||||
return bv;
|
||||
@ -63,12 +63,12 @@ namespace chaiscript
|
||||
|
||||
/// Returns a vector containing all of the types of the parameters the function returns/takes
|
||||
/// if the function is variadic or takes no arguments (arity of 0 or -1), the returned
|
||||
/// value containes exactly 1 Type_Info object: the return type
|
||||
/// value contains exactly 1 Type_Info object: the return type
|
||||
/// \returns the types of all parameters.
|
||||
const std::vector<Type_Info> &get_param_types() const { return m_types; }
|
||||
|
||||
virtual bool operator==(const Proxy_Function_Base &) const = 0;
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const = 0;
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const = 0;
|
||||
|
||||
bool has_arithmetic_param() const
|
||||
{
|
||||
@ -82,15 +82,13 @@ 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 Dynamic_Cast_Conversions &t_conversions) const
|
||||
bool filter(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const
|
||||
{
|
||||
int arity = get_arity();
|
||||
|
||||
if (arity < 0)
|
||||
if (m_arity < 0)
|
||||
{
|
||||
return true;
|
||||
} else if (size_t(arity) == vals.size()) {
|
||||
if (arity == 0)
|
||||
} else if (size_t(m_arity) == vals.size()) {
|
||||
if (m_arity == 0)
|
||||
{
|
||||
return true;
|
||||
} else {
|
||||
@ -102,11 +100,14 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
/// \returns the number of arguments the function takes or -1 if it is variadic
|
||||
virtual int get_arity() const = 0;
|
||||
int get_arity() const
|
||||
{
|
||||
return m_arity;
|
||||
}
|
||||
|
||||
virtual std::string annotation() const = 0;
|
||||
|
||||
static bool compare_type_to_param(const Type_Info &ti, const Boxed_Value &bv, const Dynamic_Cast_Conversions &t_conversions)
|
||||
static bool compare_type_to_param(const Type_Info &ti, const Boxed_Value &bv, const Type_Conversions &t_conversions)
|
||||
{
|
||||
if (ti.is_undef()
|
||||
|| ti.bare_equal(user_type<Boxed_Value>())
|
||||
@ -114,7 +115,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.dynamic_cast_converts(ti, bv.get_type_info())
|
||||
|| t_conversions.converts(ti, bv.get_type_info())
|
||||
)
|
||||
)
|
||||
)
|
||||
@ -125,10 +126,10 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions) const = 0;
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const = 0;
|
||||
|
||||
Proxy_Function_Base(std::vector<Type_Info> t_types)
|
||||
: m_types(std::move(t_types)), m_has_arithmetic_param(false)
|
||||
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)
|
||||
{
|
||||
for (size_t i = 1; i < m_types.size(); ++i)
|
||||
{
|
||||
@ -141,7 +142,7 @@ namespace chaiscript
|
||||
|
||||
}
|
||||
|
||||
virtual bool compare_first_type(const Boxed_Value &bv, const Dynamic_Cast_Conversions &t_conversions) const
|
||||
virtual bool compare_first_type(const Boxed_Value &bv, const Type_Conversions &t_conversions) const
|
||||
{
|
||||
const std::vector<Type_Info> &types = get_param_types();
|
||||
|
||||
@ -175,14 +176,14 @@ namespace chaiscript
|
||||
|
||||
std::vector<Type_Info> m_types;
|
||||
bool m_has_arithmetic_param;
|
||||
|
||||
int m_arity;
|
||||
};
|
||||
}
|
||||
|
||||
/// \brief Common typedef used for passing of any registered function in ChaiScript
|
||||
typedef std::shared_ptr<dispatch::Proxy_Function_Base> Proxy_Function;
|
||||
|
||||
/// \brief Const version of Proxy_Function chaiscript. Points to a const Proxy_Function. This is how most registered functions
|
||||
/// \brief Const version of Proxy_Function. Points to a const Proxy_Function. This is how most registered functions
|
||||
/// are handled internally.
|
||||
typedef std::shared_ptr<const dispatch::Proxy_Function_Base> Const_Proxy_Function;
|
||||
|
||||
@ -216,7 +217,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)),
|
||||
: Proxy_Function_Base(build_param_type_list(t_arity), 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))
|
||||
{
|
||||
}
|
||||
@ -233,16 +234,12 @@ namespace chaiscript
|
||||
&& !this->m_guard && !prhs->m_guard);
|
||||
}
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_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
|
||||
{
|
||||
@ -260,7 +257,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
if (m_arity < 0 || params.size() == size_t(m_arity))
|
||||
{
|
||||
@ -278,7 +275,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
private:
|
||||
bool test_guard(const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions) const
|
||||
bool test_guard(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const
|
||||
{
|
||||
if (m_guard)
|
||||
{
|
||||
@ -338,8 +335,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)),
|
||||
m_f(t_f), m_args(t_args), m_arity(t_f->get_arity()<0?-1:static_cast<int>(get_param_types().size())-1)
|
||||
: 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)
|
||||
{
|
||||
assert(m_f->get_arity() < 0 || m_f->get_arity() == static_cast<int>(m_args.size()));
|
||||
}
|
||||
@ -351,7 +348,7 @@ namespace chaiscript
|
||||
|
||||
virtual ~Bound_Function() {}
|
||||
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return m_f->call_match(build_param_list(vals), t_conversions);
|
||||
}
|
||||
@ -395,11 +392,6 @@ 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();
|
||||
@ -429,7 +421,7 @@ namespace chaiscript
|
||||
return retval;
|
||||
}
|
||||
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return (*m_f)(build_param_list(params), t_conversions);
|
||||
}
|
||||
@ -437,30 +429,24 @@ 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(std::vector<Type_Info> t_types)
|
||||
: Proxy_Function_Base(std::move(t_types))
|
||||
Proxy_Function_Impl_Base(const std::vector<Type_Info> &t_types)
|
||||
: Proxy_Function_Base(t_types, static_cast<int>(t_types.size()) - 1)
|
||||
{
|
||||
}
|
||||
|
||||
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 Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
if (int(vals.size()) != get_arity())
|
||||
{
|
||||
@ -470,7 +456,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 Dynamic_Cast_Conversions &t_conversions) const = 0;
|
||||
virtual bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -490,7 +476,7 @@ namespace chaiscript
|
||||
|
||||
virtual ~Proxy_Function_Impl() {}
|
||||
|
||||
virtual bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
return detail::compare_types_cast(m_dummy_func, vals, t_conversions);
|
||||
}
|
||||
@ -506,7 +492,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions) const
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const
|
||||
{
|
||||
return detail::Do_Call<typename std::function<Func>::result_type>::go(m_f, params, t_conversions);
|
||||
}
|
||||
@ -524,8 +510,8 @@ namespace chaiscript
|
||||
{
|
||||
public:
|
||||
Attribute_Access(T Class::* t_attr)
|
||||
: Proxy_Function_Base(param_types()),
|
||||
m_attr(t_attr)
|
||||
: Proxy_Function_Base(param_types(), 1),
|
||||
m_attr(t_attr)
|
||||
{
|
||||
}
|
||||
|
||||
@ -543,13 +529,7 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions &) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
if (vals.size() != 1)
|
||||
{
|
||||
@ -565,7 +545,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
virtual Boxed_Value do_call(const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
if (params.size() == 1)
|
||||
{
|
||||
@ -622,7 +602,7 @@ namespace chaiscript
|
||||
{
|
||||
template<typename FuncType>
|
||||
bool types_match_except_for_arithmetic(const FuncType &t_func, const std::vector<Boxed_Value> &plist,
|
||||
const Dynamic_Cast_Conversions &t_conversions)
|
||||
const Type_Conversions &t_conversions)
|
||||
{
|
||||
if (t_func->get_arity() != static_cast<int>(plist.size()))
|
||||
{
|
||||
@ -650,7 +630,7 @@ namespace chaiscript
|
||||
|
||||
template<typename InItr>
|
||||
Boxed_Value dispatch_with_conversions(InItr begin, const InItr &end, const std::vector<Boxed_Value> &plist,
|
||||
const Dynamic_Cast_Conversions &t_conversions)
|
||||
const Type_Conversions &t_conversions)
|
||||
{
|
||||
InItr orig(begin);
|
||||
|
||||
@ -712,17 +692,42 @@ 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 InItr>
|
||||
Boxed_Value dispatch(InItr begin, const InItr &end,
|
||||
const std::vector<Boxed_Value> &plist, const Dynamic_Cast_Conversions &t_conversions)
|
||||
template<typename Funcs>
|
||||
Boxed_Value dispatch(const Funcs &funcs,
|
||||
const std::vector<Boxed_Value> &plist, const Type_Conversions &t_conversions)
|
||||
{
|
||||
InItr orig(begin);
|
||||
while (begin != end)
|
||||
|
||||
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 )
|
||||
{
|
||||
try {
|
||||
if ((*begin)->filter(plist, t_conversions))
|
||||
if (func.second->filter(plist, t_conversions))
|
||||
{
|
||||
return (*(*begin))(plist, t_conversions);
|
||||
return (*(func.second))(plist, t_conversions);
|
||||
}
|
||||
} catch (const exception::bad_boxed_cast &) {
|
||||
//parameter failed to cast, try again
|
||||
@ -732,22 +737,9 @@ namespace chaiscript
|
||||
//guard failed to allow the function to execute,
|
||||
//try again
|
||||
}
|
||||
++begin;
|
||||
}
|
||||
|
||||
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);
|
||||
return detail::dispatch_with_conversions(funcs.cbegin(), funcs.cend(), plist, t_conversions);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -20,7 +20,7 @@
|
||||
#include "type_info.hpp"
|
||||
|
||||
namespace chaiscript {
|
||||
class Dynamic_Cast_Conversions;
|
||||
class Type_Conversions;
|
||||
namespace exception {
|
||||
class bad_boxed_cast;
|
||||
} // namespace exception
|
||||
@ -53,29 +53,6 @@ namespace chaiscript
|
||||
{
|
||||
namespace detail
|
||||
{
|
||||
template<typename ... Rest>
|
||||
struct Build_Param_Type_List;
|
||||
|
||||
template<typename Param, typename ... Rest>
|
||||
struct Build_Param_Type_List<Param, Rest...>
|
||||
{
|
||||
static void build(std::vector<Type_Info> &t_params)
|
||||
{
|
||||
t_params.push_back(chaiscript::detail::Get_Type_Info<Param>::get());
|
||||
Build_Param_Type_List<Rest...>::build(t_params);
|
||||
}
|
||||
};
|
||||
|
||||
// 0th case
|
||||
template<>
|
||||
struct Build_Param_Type_List<>
|
||||
{
|
||||
static void build(std::vector<Type_Info> &)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Used by Proxy_Function_Impl to return a list of all param types
|
||||
* it contains.
|
||||
@ -83,12 +60,8 @@ namespace chaiscript
|
||||
template<typename Ret, typename ... Params>
|
||||
std::vector<Type_Info> build_param_type_list(Ret (*)(Params...))
|
||||
{
|
||||
/// \todo this code was previously using { chaiscript::detail::Get_Type_Info<Ret>::get()... }
|
||||
/// but this seems to indicate another bug with MSVC's uniform initializer lists
|
||||
std::vector<Type_Info> params;
|
||||
params.push_back(chaiscript::detail::Get_Type_Info<Ret>::get());
|
||||
Build_Param_Type_List<Params...>::build(params);
|
||||
return params;
|
||||
/// \note somehow this is responsible for a large part of the code generation
|
||||
return { user_type<Ret>(), user_type<Params>()... };
|
||||
}
|
||||
|
||||
|
||||
@ -99,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 Dynamic_Cast_Conversions &t_conversions)
|
||||
static void do_try(const std::vector<Boxed_Value> ¶ms, int generation, const Type_Conversions &t_conversions)
|
||||
{
|
||||
boxed_cast<Param>(params[generation], &t_conversions);
|
||||
Try_Cast<Rest...>::do_try(params, generation+1, t_conversions);
|
||||
@ -110,7 +83,7 @@ namespace chaiscript
|
||||
template<>
|
||||
struct Try_Cast<>
|
||||
{
|
||||
static void do_try(const std::vector<Boxed_Value> &, int, const Dynamic_Cast_Conversions &)
|
||||
static void do_try(const std::vector<Boxed_Value> &, int, const Type_Conversions &)
|
||||
{
|
||||
}
|
||||
};
|
||||
@ -118,12 +91,12 @@ namespace chaiscript
|
||||
|
||||
/**
|
||||
* Used by Proxy_Function_Impl to determine if it is equivalent to another
|
||||
* Proxy_Function_Impl object. This function is primarly used to prevent
|
||||
* Proxy_Function_Impl object. This function is primarily used to prevent
|
||||
* registration of two functions with the exact same signatures
|
||||
*/
|
||||
template<typename Ret, typename ... Params>
|
||||
bool compare_types_cast(Ret (*)(Params...),
|
||||
const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions)
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions)
|
||||
{
|
||||
try {
|
||||
Try_Cast<Params...>::do_try(params, 0, t_conversions);
|
||||
@ -140,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 Dynamic_Cast_Conversions &t_conversions, InnerParams &&... innerparams)
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_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]);
|
||||
}
|
||||
@ -155,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 Dynamic_Cast_Conversions &t_conversions, InnerParams &&... innerparams)
|
||||
const std::vector<Boxed_Value> &, const Type_Conversions &t_conversions, InnerParams &&... innerparams)
|
||||
{
|
||||
return f(boxed_cast<Params>(std::forward<InnerParams>(innerparams), &t_conversions)...);
|
||||
}
|
||||
@ -166,13 +139,13 @@ namespace chaiscript
|
||||
|
||||
/**
|
||||
* Used by Proxy_Function_Impl to perform typesafe execution of a function.
|
||||
* The function attempts to unbox each paramter to the expected type.
|
||||
* The function attempts to unbox each parameter to the expected type.
|
||||
* if any unboxing fails the execution of the function fails and
|
||||
* the bad_boxed_cast is passed up to the caller.
|
||||
*/
|
||||
template<typename Ret, typename ... Params>
|
||||
Ret call_func(const std::function<Ret (Params...)> &f,
|
||||
const std::vector<Boxed_Value> ¶ms, const Dynamic_Cast_Conversions &t_conversions)
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions)
|
||||
{
|
||||
if (params.size() == sizeof...(Params))
|
||||
{
|
||||
@ -198,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 Dynamic_Cast_Conversions &t_conversions)
|
||||
static Boxed_Value go(const std::function<Fun> &fun, const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions)
|
||||
{
|
||||
return Handle_Return<Ret>::handle(call_func(fun, params, t_conversions));
|
||||
}
|
||||
@ -208,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 Dynamic_Cast_Conversions &t_conversions)
|
||||
static Boxed_Value go(const std::function<Fun> &fun, const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions)
|
||||
{
|
||||
call_func(fun, params, t_conversions);
|
||||
return Handle_Return<void>::handle();
|
||||
|
447
include/chaiscript/dispatchkit/type_conversions.hpp
Normal file
447
include/chaiscript/dispatchkit/type_conversions.hpp
Normal file
@ -0,0 +1,447 @@
|
||||
// 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
|
||||
std::cout << " Type conversion to : " << typeid(To).name() << " from " << typeid(From).name() << std::endl;
|
||||
auto &&from = detail::Cast_Helper<From>::cast(t_bv, nullptr);
|
||||
std::cout << "Ptr" << static_cast<const void *>(from) << std::endl;
|
||||
std::cout << "Ptr" << from << std::endl;
|
||||
|
||||
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
|
@ -25,6 +25,7 @@ namespace chaiscript
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/// \brief Compile time deduced information about a type
|
||||
class Type_Info
|
||||
{
|
||||
@ -38,7 +39,7 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
Type_Info()
|
||||
CHAISCRIPT_CONSTEXPR Type_Info()
|
||||
: m_type_info(nullptr), m_bare_type_info(nullptr),
|
||||
m_is_const(false), m_is_reference(false), m_is_pointer(false),
|
||||
m_is_void(false), m_is_arithmetic(false),
|
||||
@ -46,63 +47,49 @@ namespace chaiscript
|
||||
{
|
||||
}
|
||||
|
||||
Type_Info(const Type_Info &ti)
|
||||
: m_type_info(ti.m_type_info),
|
||||
m_bare_type_info(ti.m_bare_type_info),
|
||||
m_is_const(ti.m_is_const), m_is_reference(ti.m_is_reference),
|
||||
m_is_pointer(ti.m_is_pointer),
|
||||
m_is_void(ti.m_is_void), m_is_arithmetic(ti.m_is_arithmetic),
|
||||
m_is_undef(ti.m_is_undef)
|
||||
{
|
||||
}
|
||||
#if !defined(_MSC_VER) || _MSC_VER != 1800
|
||||
Type_Info(Type_Info&&) = default;
|
||||
Type_Info& operator=(Type_Info&&) = default;
|
||||
#endif
|
||||
|
||||
Type_Info &operator=(const Type_Info &ti)
|
||||
{
|
||||
m_type_info = ti.m_type_info;
|
||||
m_bare_type_info = ti.m_bare_type_info;
|
||||
m_is_const = ti.m_is_const;
|
||||
m_is_reference = ti.m_is_reference;
|
||||
m_is_pointer = ti.m_is_pointer;
|
||||
m_is_void = ti.m_is_void;
|
||||
m_is_arithmetic = ti.m_is_arithmetic;
|
||||
m_is_undef = ti.m_is_undef;
|
||||
return *this;
|
||||
}
|
||||
Type_Info(const Type_Info&) = default;
|
||||
Type_Info& operator=(const Type_Info&) = default;
|
||||
|
||||
bool operator<(const Type_Info &ti) const
|
||||
|
||||
CHAISCRIPT_CONSTEXPR bool operator<(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT
|
||||
{
|
||||
return m_type_info < ti.m_type_info;
|
||||
}
|
||||
|
||||
bool operator==(const Type_Info &ti) const
|
||||
CHAISCRIPT_CONSTEXPR bool operator==(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT
|
||||
{
|
||||
return ti.m_type_info == m_type_info
|
||||
|| (ti.m_type_info && m_type_info && *ti.m_type_info == *m_type_info);
|
||||
}
|
||||
|
||||
bool operator==(const std::type_info &ti) const
|
||||
CHAISCRIPT_CONSTEXPR bool operator==(const std::type_info &ti) const CHAISCRIPT_NOEXCEPT
|
||||
{
|
||||
return m_type_info != nullptr && (*m_type_info) == ti;
|
||||
}
|
||||
|
||||
bool bare_equal(const Type_Info &ti) const
|
||||
CHAISCRIPT_CONSTEXPR bool bare_equal(const Type_Info &ti) const CHAISCRIPT_NOEXCEPT
|
||||
{
|
||||
return ti.m_bare_type_info == m_bare_type_info
|
||||
|| (ti.m_bare_type_info && m_bare_type_info && *ti.m_bare_type_info == *m_bare_type_info);
|
||||
}
|
||||
|
||||
bool bare_equal_type_info(const std::type_info &ti) const
|
||||
CHAISCRIPT_CONSTEXPR bool bare_equal_type_info(const std::type_info &ti) const CHAISCRIPT_NOEXCEPT
|
||||
{
|
||||
return m_bare_type_info != nullptr
|
||||
&& (*m_bare_type_info) == ti;
|
||||
}
|
||||
|
||||
bool is_const() const { return m_is_const; }
|
||||
bool is_reference() const { return m_is_reference; }
|
||||
bool is_void() const { return m_is_void; }
|
||||
bool is_arithmetic() const { return m_is_arithmetic; }
|
||||
bool is_undef() const { return m_is_undef || m_bare_type_info == nullptr; }
|
||||
bool is_pointer() const { return m_is_pointer; }
|
||||
CHAISCRIPT_CONSTEXPR bool is_const() const CHAISCRIPT_NOEXCEPT { return m_is_const; }
|
||||
CHAISCRIPT_CONSTEXPR bool is_reference() const CHAISCRIPT_NOEXCEPT { return m_is_reference; }
|
||||
CHAISCRIPT_CONSTEXPR bool is_void() const CHAISCRIPT_NOEXCEPT { return m_is_void; }
|
||||
CHAISCRIPT_CONSTEXPR bool is_arithmetic() const CHAISCRIPT_NOEXCEPT { return m_is_arithmetic; }
|
||||
CHAISCRIPT_CONSTEXPR bool is_undef() const CHAISCRIPT_NOEXCEPT { return m_is_undef || m_bare_type_info == nullptr; }
|
||||
CHAISCRIPT_CONSTEXPR bool is_pointer() const CHAISCRIPT_NOEXCEPT { return m_is_pointer; }
|
||||
|
||||
std::string name() const
|
||||
{
|
||||
@ -114,7 +101,7 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
std::string bare_name() const
|
||||
std::string bare_name() const
|
||||
{
|
||||
if (m_bare_type_info)
|
||||
{
|
||||
@ -124,6 +111,11 @@ 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;
|
||||
@ -215,11 +207,6 @@ namespace chaiscript
|
||||
}
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct Stripped_Type
|
||||
{
|
||||
typedef typename Bare_Type<typename detail::Get_Type_Info<T>::type>::type type;
|
||||
};
|
||||
}
|
||||
|
||||
/// \brief Creates a Type_Info object representing the type passed in
|
||||
|
@ -69,6 +69,7 @@ namespace chaiscript
|
||||
|
||||
/// \brief Typedef for pointers to AST_Node objects. Used in building of the AST_Node tree
|
||||
typedef std::shared_ptr<AST_Node> AST_NodePtr;
|
||||
typedef std::shared_ptr<const AST_Node> AST_NodePtr_Const;
|
||||
|
||||
|
||||
/// \brief Classes which may be thrown during error cases when ChaiScript is executing.
|
||||
@ -82,7 +83,7 @@ namespace chaiscript
|
||||
File_Position end_position;
|
||||
std::string filename;
|
||||
std::string detail;
|
||||
std::vector<AST_NodePtr> call_stack;
|
||||
std::vector<AST_NodePtr_Const> call_stack;
|
||||
|
||||
eval_error(const std::string &t_why, const File_Position &t_where, const std::string &t_fname,
|
||||
const std::vector<Boxed_Value> &t_parameters, const std::vector<chaiscript::Const_Proxy_Function> &t_functions,
|
||||
@ -425,7 +426,7 @@ namespace chaiscript
|
||||
|
||||
|
||||
/// Prints the contents of an AST node, including its children, recursively
|
||||
std::string to_string(const std::string &t_prepend = "") {
|
||||
std::string to_string(const std::string &t_prepend = "") const {
|
||||
std::ostringstream oss;
|
||||
|
||||
oss << t_prepend << "(" << ast_node_type_to_string(this->identifier) << ") "
|
||||
@ -437,7 +438,7 @@ namespace chaiscript
|
||||
return oss.str();
|
||||
}
|
||||
|
||||
Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_e)
|
||||
Boxed_Value eval(chaiscript::detail::Dispatch_Engine &t_e) const
|
||||
{
|
||||
try {
|
||||
return eval_internal(t_e);
|
||||
@ -466,7 +467,7 @@ namespace chaiscript
|
||||
|
||||
virtual ~AST_Node() {}
|
||||
|
||||
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &)
|
||||
virtual Boxed_Value eval_internal(chaiscript::detail::Dispatch_Engine &) const
|
||||
{
|
||||
throw std::runtime_error("Undispatched ast_node (internal error)");
|
||||
}
|
||||
@ -548,6 +549,11 @@ 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/dynamic_cast_conversion.hpp"
|
||||
#include "../dispatchkit/type_conversions.hpp"
|
||||
#include "../dispatchkit/proxy_functions.hpp"
|
||||
#include "chaiscript_common.hpp"
|
||||
|
||||
@ -282,7 +282,7 @@ namespace chaiscript
|
||||
return Boxed_Value();
|
||||
}
|
||||
}
|
||||
catch (const chaiscript::eval::detail::Return_Value &rv) {
|
||||
catch (chaiscript::eval::detail::Return_Value &rv) {
|
||||
return rv.retval;
|
||||
}
|
||||
}
|
||||
@ -345,12 +345,21 @@ namespace chaiscript
|
||||
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::function_exists, std::ref(m_engine)), "function_exists");
|
||||
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_function_objects, std::ref(m_engine)), "get_functions");
|
||||
m_engine.add(fun(&chaiscript::detail::Dispatch_Engine::get_scripting_objects, std::ref(m_engine)), "get_objects");
|
||||
m_engine.add(Proxy_Function(new dispatch::Dynamic_Proxy_Function(std::bind(&chaiscript::detail::Dispatch_Engine::call_exists, std::ref(m_engine), std::placeholders::_1))),
|
||||
"call_exists");
|
||||
m_engine.add(Proxy_Function(new dispatch::Dynamic_Proxy_Function(
|
||||
[this](const std::vector<Boxed_Value> &t_params) {
|
||||
return m_engine.call_exists(t_params);
|
||||
})), "call_exists");
|
||||
m_engine.add(fun<Boxed_Value (const dispatch::Proxy_Function_Base *, const std::vector<Boxed_Value> &)>(std::bind(&chaiscript::dispatch::Proxy_Function_Base::operator(), std::placeholders::_1, std::placeholders::_2, std::ref(m_engine.conversions()))), "call");
|
||||
|
||||
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&);
|
||||
@ -382,7 +391,7 @@ namespace chaiscript
|
||||
throw chaiscript::exception::file_not_found_error(t_filename);
|
||||
}
|
||||
|
||||
std::streampos size = infile.tellg();
|
||||
const auto size = infile.tellg();
|
||||
infile.seekg(0, std::ios::beg);
|
||||
|
||||
assert(size >= 0);
|
||||
@ -391,7 +400,7 @@ namespace chaiscript
|
||||
{
|
||||
return std::string();
|
||||
} else {
|
||||
std::vector<char> v(static_cast<unsigned int>(size));
|
||||
std::vector<char> v(static_cast<size_t>(size));
|
||||
infile.read(&v[0], size);
|
||||
return std::string(v.begin(), v.end());
|
||||
}
|
||||
@ -457,7 +466,7 @@ namespace chaiscript
|
||||
u.in_ptr = &ChaiScript::use;
|
||||
if ( dladdr((void*)(u.out_ptr), &rInfo) && rInfo.dli_fname ) {
|
||||
std::string dllpath(rInfo.dli_fname);
|
||||
size_t lastslash = dllpath.rfind('/');
|
||||
const size_t lastslash = dllpath.rfind('/');
|
||||
if (lastslash != std::string::npos)
|
||||
{
|
||||
dllpath.erase(lastslash);
|
||||
@ -465,15 +474,15 @@ namespace chaiscript
|
||||
|
||||
// Let's see if this is a link that we should expand
|
||||
std::vector<char> buf(2048);
|
||||
size_t pathlen = readlink(dllpath.c_str(), &buf.front(), buf.size());
|
||||
const size_t pathlen = readlink(dllpath.c_str(), &buf.front(), buf.size());
|
||||
if (pathlen > 0 && pathlen < buf.size())
|
||||
{
|
||||
dllpath = std::string(&buf.front(), pathlen);
|
||||
}
|
||||
|
||||
m_modulepaths.insert(m_modulepaths.begin(), dllpath+"/");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
// attempt to load the stdlib
|
||||
@ -523,10 +532,10 @@ namespace chaiscript
|
||||
/// \param[in] t_filename Filename to load and evaluate
|
||||
void use(const std::string &t_filename)
|
||||
{
|
||||
for (size_t i = 0; i < m_usepaths.size(); ++i)
|
||||
for (const auto &path : m_usepaths)
|
||||
{
|
||||
try {
|
||||
const std::string appendedpath = m_usepaths[i] + t_filename;
|
||||
const auto appendedpath = path + t_filename;
|
||||
|
||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::recursive_mutex> l(m_use_mutex);
|
||||
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l2(m_mutex);
|
||||
@ -541,14 +550,12 @@ namespace chaiscript
|
||||
|
||||
return; // return, we loaded it, or it was already loaded
|
||||
} catch (const exception::file_not_found_error &) {
|
||||
if (i == m_usepaths.size() - 1)
|
||||
{
|
||||
throw exception::file_not_found_error(t_filename);
|
||||
}
|
||||
|
||||
// failed to load, try the next path
|
||||
}
|
||||
}
|
||||
|
||||
// failed to load by any name
|
||||
throw exception::file_not_found_error(t_filename);
|
||||
}
|
||||
|
||||
/// \brief Adds a constant object that is available in all contexts and to all threads
|
||||
@ -679,7 +686,7 @@ namespace chaiscript
|
||||
/// chaiscript::ChaiScript chai;
|
||||
/// chai.add(chaiscript::base_class<std::runtime_error, chaiscript::dispatch_error>());
|
||||
/// \endcode
|
||||
ChaiScript &add(const Dynamic_Cast_Conversion &d)
|
||||
ChaiScript &add(const Type_Conversion &d)
|
||||
{
|
||||
m_engine.add(d);
|
||||
return *this;
|
||||
@ -716,15 +723,9 @@ namespace chaiscript
|
||||
version_stripped_name.erase(version_pos);
|
||||
}
|
||||
|
||||
std::vector<std::string> prefixes;
|
||||
prefixes.push_back("lib");
|
||||
prefixes.push_back("cyg");
|
||||
prefixes.push_back("");
|
||||
std::vector<std::string> prefixes{"lib", "cyg", ""};
|
||||
|
||||
std::vector<std::string> postfixes;
|
||||
postfixes.push_back(".dll");
|
||||
postfixes.push_back(".so");
|
||||
postfixes.push_back("");
|
||||
std::vector<std::string> postfixes{".dll", ".so", ""};
|
||||
|
||||
for (auto & elem : m_modulepaths)
|
||||
{
|
||||
@ -733,7 +734,7 @@ namespace chaiscript
|
||||
for (auto & postfix : postfixes)
|
||||
{
|
||||
try {
|
||||
std::string name = elem + prefix + t_module_name + postfix;
|
||||
const auto name = elem + prefix + t_module_name + postfix;
|
||||
// std::cerr << "trying location: " << name << std::endl;
|
||||
load_module(version_stripped_name, name);
|
||||
return name;
|
||||
@ -845,7 +846,7 @@ namespace chaiscript
|
||||
///
|
||||
/// \param[in] t_input Script to execute
|
||||
/// \param[in] t_handler Optional Exception_Handler used for automatic unboxing of script thrown exceptions
|
||||
/// \param[in] t_filename Optional filename to report to the user for where the error occured. Useful
|
||||
/// \param[in] t_filename Optional filename to report to the user for where the error occurred. Useful
|
||||
/// in special cases where you are loading a file internally instead of using eval_file
|
||||
///
|
||||
/// \return result of the script execution
|
||||
@ -879,7 +880,7 @@ namespace chaiscript
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Loads the file specified by filename, evaluates it, and returns the typesafe result.
|
||||
/// \brief Loads the file specified by filename, evaluates it, and returns the type safe result.
|
||||
/// \tparam T Type to extract from the result value of the script execution
|
||||
/// \param[in] t_filename File to load and parse.
|
||||
/// \param[in] t_handler Optional Exception_Handler used for automatic unboxing of script thrown exceptions
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -112,7 +112,7 @@ class Map
|
||||
};
|
||||
|
||||
|
||||
/// \brief A concept implemented by string, Vector and Map. It is convertable to Range, default constructable and back_insertable
|
||||
/// \brief A concept implemented by string, Vector and Map. It is convertible to Range, default constructable and back_insertable
|
||||
class Container
|
||||
{
|
||||
public:
|
||||
@ -153,10 +153,10 @@ void print(Object o);
|
||||
|
||||
/// \brief ChaiScript representation of std::string. It is an std::string but only some member are exposed to ChaiScript.
|
||||
///
|
||||
/// Because the ChaiScript string object is an std::string, it is directly convertable to and from std::string
|
||||
/// Because the ChaiScript string object is an std::string, it is directly convertible to and from std::string
|
||||
/// using the chaiscript::boxed_cast and chaiscript::var functions.
|
||||
///
|
||||
/// With the exception of string::trim, string::rtrim, string::ltrim, all members are direct passthroughs to the
|
||||
/// With the exception of string::trim, string::rtrim, string::ltrim, all members are direct pass-throughs to the
|
||||
/// std::string of the same name.
|
||||
///
|
||||
/// \note Object and function notations are equivalent in ChaiScript. This means that
|
||||
@ -519,7 +519,7 @@ class Function
|
||||
/// \brief Returns a vector of Type_Info objects that represent the param types for this function.
|
||||
/// The first value in the list is the return type.
|
||||
///
|
||||
/// If this function is a conglomeration of several functions (get_contained_values().size() > 0)
|
||||
/// If this function is a conglomerate of several functions (get_contained_values().size() > 0)
|
||||
/// then the function returns as many Type_Info objects as it can. If the functions contained all have
|
||||
/// the same arity, then it represents the arity. If they have different arities, it returns only
|
||||
/// one value - the return type.
|
||||
@ -534,7 +534,7 @@ class Function
|
||||
/// \endcode
|
||||
Vector get_param_types() const;
|
||||
|
||||
/// \brief Returns true if the function has a guard to it. Always returns falls for a conglomerate function
|
||||
/// \brief Returns true if the function has a guard to it. Always returns false for a conglomerate function
|
||||
bool has_guard() const;
|
||||
|
||||
/// \brief Calls the function with the given set of parameters and returns the value;
|
||||
|
@ -21,8 +21,29 @@ namespace chaiscript
|
||||
namespace utility
|
||||
{
|
||||
|
||||
/// \todo Use of this utility, and uniform initializer lists, is causing memory errors in MSVC
|
||||
|
||||
/// Single step command for registering a class with ChaiScript
|
||||
///
|
||||
/// \param[in,out] t_module Model to add class to
|
||||
/// \param[in] t_class_name Name of the class being registered
|
||||
/// \param[in] t_constructors Vector of constructors to add
|
||||
/// \param[in] t_funcs Vector of methods to add
|
||||
///
|
||||
/// \example Adding a basic class to ChaiScript in one step
|
||||
///
|
||||
/// \code
|
||||
/// chaiscript::utility::add_class<test>(*m,
|
||||
/// "test",
|
||||
/// { constructor<test ()>(),
|
||||
/// constructor<test (const test &)>() },
|
||||
/// { {fun(&test::function), "function"},
|
||||
/// {fun(&test::function2), "function2"},
|
||||
/// {fun(&test::function3), "function3"},
|
||||
/// {fun(static_cast<std::string(test::*)(double)>(&test::functionoverload)), "functionoverload" },
|
||||
/// {fun(static_cast<std::string(test::*)(int)>(&test::functionoverload)), "functionoverload" },
|
||||
/// {fun(static_cast<test & (test::*)(const test &)>(&test::operator=)), "=" }
|
||||
/// }
|
||||
/// );
|
||||
///
|
||||
template<typename Class, typename ModuleType>
|
||||
void add_class(ModuleType &t_module,
|
||||
const std::string &t_class_name,
|
||||
@ -36,13 +57,11 @@ namespace chaiscript
|
||||
t_module.add(ctor, t_class_name);
|
||||
}
|
||||
|
||||
for(auto fun: t_funcs)
|
||||
for(const auto &fun: t_funcs)
|
||||
{
|
||||
t_module.add(fun.first, fun.second);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,15 @@
|
||||
Notes:
|
||||
=======
|
||||
Current Version: 5.4.0
|
||||
Current Version: 5.5.0
|
||||
|
||||
### 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
|
||||
|
||||
|
||||
### Changes since 5.3.1
|
||||
* Decreased compile time and build size
|
||||
|
134
samples/inheritance.cpp
Normal file
134
samples/inheritance.cpp
Normal file
@ -0,0 +1,134 @@
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
#include <chaiscript/chaiscript_stdlib.hpp>
|
||||
|
||||
class BaseClass
|
||||
{
|
||||
public:
|
||||
BaseClass()
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~BaseClass() {}
|
||||
|
||||
virtual std::string doSomething(float, double) const = 0;
|
||||
|
||||
|
||||
void setValue(const std::string &t_val) {
|
||||
if (validateValue(t_val))
|
||||
{
|
||||
m_value = t_val;
|
||||
}
|
||||
}
|
||||
|
||||
std::string getValue() const {
|
||||
return m_value;
|
||||
}
|
||||
|
||||
protected:
|
||||
virtual bool validateValue(const std::string &t_val) = 0;
|
||||
|
||||
private:
|
||||
std::string m_value;
|
||||
};
|
||||
|
||||
class ChaiScriptDerived : public BaseClass
|
||||
{
|
||||
public:
|
||||
ChaiScriptDerived(const std::vector<chaiscript::Boxed_Value> &t_funcs)
|
||||
{
|
||||
// using the range-checked .at() methods to give us an exception
|
||||
// instead of a crash if the user passed in too-few params
|
||||
tie(t_funcs.at(0), m_doSomethingImpl);
|
||||
tie(t_funcs.at(1), m_validateValueImpl);
|
||||
}
|
||||
|
||||
std::string doSomething(float f, double d) const CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
assert(m_doSomethingImpl);
|
||||
return m_doSomethingImpl(*this, f, d);
|
||||
}
|
||||
|
||||
protected:
|
||||
bool validateValue(const std::string &t_val) CHAISCRIPT_OVERRIDE
|
||||
{
|
||||
assert(m_validateValueImpl);
|
||||
return m_validateValueImpl(*this, t_val);
|
||||
}
|
||||
|
||||
private:
|
||||
template<typename Param>
|
||||
void tie(const chaiscript::Boxed_Value &t_func, Param &t_param)
|
||||
{
|
||||
t_param = chaiscript::boxed_cast<Param>(t_func);
|
||||
}
|
||||
|
||||
std::function<std::string (const ChaiScriptDerived&, float, double)> m_doSomethingImpl;
|
||||
std::function<bool (ChaiScriptDerived&, const std::string &t_val)> m_validateValueImpl;
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
chaiscript::ChaiScript chai(chaiscript::Std_Lib::library());
|
||||
chai.add(chaiscript::fun(&BaseClass::doSomething), "doSomething");
|
||||
chai.add(chaiscript::fun(&BaseClass::setValue), "setValue");
|
||||
chai.add(chaiscript::fun(&BaseClass::getValue), "getValue");
|
||||
chai.add(chaiscript::constructor<ChaiScriptDerived (const std::vector<chaiscript::Boxed_Value> &)>(), "ChaiScriptDerived");
|
||||
chai.add(chaiscript::base_class<BaseClass, ChaiScriptDerived>());
|
||||
chai.add(chaiscript::user_type<BaseClass>(), "BaseClass");
|
||||
chai.add(chaiscript::user_type<ChaiScriptDerived>(), "ChaiScriptDerived");
|
||||
|
||||
std::string script = R""(
|
||||
def MakeDerived() {
|
||||
return ChaiScriptDerived(
|
||||
// create a dynamically created array and pass it in to the constructor
|
||||
[
|
||||
fun(this, f, d) {
|
||||
// see here that we are calling back into the 'this' pointer
|
||||
return "${this.getValue()}${f * d}";
|
||||
},
|
||||
|
||||
fun(this, new_val) {
|
||||
if (new_val.size() < 5) {
|
||||
true;
|
||||
} else {
|
||||
print("String ${new_val} is too long");
|
||||
false;
|
||||
}
|
||||
}
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
var myderived := MakeDerived(); // avoid a copy by using reference assignment :=
|
||||
|
||||
)"";
|
||||
|
||||
chai.eval(script);
|
||||
|
||||
BaseClass &myderived = chai.eval<ChaiScriptDerived&>("myderived");
|
||||
|
||||
// at this point in the code myderived is both a ChaiScript variable and a C++ variable. In both cases
|
||||
// it is a derivation of BaseClass, and the implementation is provided via ChaiScript functors
|
||||
// assigned in the MakeDerived() factory function
|
||||
//
|
||||
// Notice that our validateValue() function has a requirement that the new string be < 5 characters long
|
||||
|
||||
myderived.setValue("1234");
|
||||
assert(myderived.getValue() == "1234");
|
||||
|
||||
// chaiscript defined function will print out an error message and refuse to allow the setting
|
||||
myderived.setValue("12345");
|
||||
assert(myderived.getValue() == "1234");
|
||||
|
||||
|
||||
chai.eval("myderived.setValue(\"new\")"); // set the value via chaiscript
|
||||
assert(myderived.getValue() == "new");
|
||||
|
||||
// call the other derived method via chaiscript and return the value to c++ land:
|
||||
std::string retval = chai.eval<std::string>("myderived.doSomething(2,4.3)");
|
||||
assert(retval == "new8.6");
|
||||
|
||||
// The whole process is fully orthogonal
|
||||
}
|
||||
|
||||
|
@ -70,12 +70,12 @@ int main(int /*argc*/, char * /*argv*/[]) {
|
||||
std::string command = "";
|
||||
|
||||
//
|
||||
// this loop increases memoryusage, if RunFile is not called (just hitting enter)
|
||||
// this loop increases memory usage, if RunFile is not called (just hitting enter)
|
||||
// as soon RunFile gets called, memory will be freed.
|
||||
//
|
||||
// scenario1 - RunFile gets called every Loop: memoryusage does not change
|
||||
// scenario2 - RunFile gets never called (just hitting enter): memoryusage increases every loop
|
||||
// scenario3 - RunFile gets in changing intervals: memoryusage goes up and down, but never as
|
||||
// scenario1 - RunFile gets called every Loop: memory usage does not change
|
||||
// scenario2 - RunFile gets never called (just hitting enter): memory usage increases every loop
|
||||
// scenario3 - RunFile gets in changing intervals: memory usage goes up and down, but never as
|
||||
// low as in case 1 scenario3 :
|
||||
|
||||
while(command != "quit")
|
||||
|
@ -2,6 +2,8 @@
|
||||
#include <chaiscript/chaiscript.hpp>
|
||||
#include <string>
|
||||
|
||||
|
||||
|
||||
class TestBaseType
|
||||
{
|
||||
public:
|
||||
@ -22,6 +24,30 @@ 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
|
||||
@ -51,12 +77,17 @@ class TestMoreDerivedType : public TestDerivedType
|
||||
|
||||
std::shared_ptr<TestBaseType> derived_type_factory()
|
||||
{
|
||||
return std::shared_ptr<TestBaseType>(new TestDerivedType());
|
||||
return std::make_shared<TestDerivedType>();
|
||||
}
|
||||
|
||||
std::shared_ptr<TestBaseType> more_derived_type_factory()
|
||||
{
|
||||
return std::shared_ptr<TestBaseType>(new TestMoreDerivedType());
|
||||
return std::make_shared<TestMoreDerivedType>();
|
||||
}
|
||||
|
||||
std::shared_ptr<TestBaseType> null_factory()
|
||||
{
|
||||
return std::shared_ptr<TestBaseType>();
|
||||
}
|
||||
|
||||
std::string hello_world()
|
||||
@ -90,6 +121,7 @@ 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");
|
||||
@ -111,6 +143,7 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo
|
||||
|
||||
m->add(chaiscript::fun(&derived_type_factory), "derived_type_factory");
|
||||
m->add(chaiscript::fun(&more_derived_type_factory), "more_derived_type_factory");
|
||||
m->add(chaiscript::fun(&null_factory), "null_factory");
|
||||
|
||||
m->add(chaiscript::fun(&TestDerivedType::func), "func");
|
||||
|
||||
@ -129,6 +162,12 @@ 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;
|
||||
}
|
||||
|
13
unittests/null_object_access.chai
Normal file
13
unittests/null_object_access.chai
Normal file
@ -0,0 +1,13 @@
|
||||
load_module("test_module")
|
||||
|
||||
auto o := null_factory();
|
||||
|
||||
try {
|
||||
o.func();
|
||||
} catch (e) {
|
||||
exit(0);
|
||||
}
|
||||
|
||||
assert_true(false);
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
|
||||
#include <chaiscript/chaiscript_defines.hpp>
|
||||
#include <chaiscript/dispatchkit/type_info.hpp>
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
|
||||
void test_type(const chaiscript::Type_Info &ti, bool t_is_const, bool t_is_pointer, bool t_is_reference, bool t_is_void,
|
||||
@ -30,5 +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) << std::endl;
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
11
unittests/user_defined_conversions.chai
Normal file
11
unittests/user_defined_conversions.chai
Normal file
@ -0,0 +1,11 @@
|
||||
|
||||
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");
|
||||
|
||||
|
||||
|
27
unittests/user_defined_conversions_2.chai
Normal file
27
unittests/user_defined_conversions_2.chai
Normal file
@ -0,0 +1,27 @@
|
||||
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");
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user