Compare commits

..

48 Commits

Author SHA1 Message Date
Jason Turner
5c541c3d8e Implement valuetypes with small size optimizations
Reduces trivial types such as int down to 1 dynamic allocation instead
of 3.
2014-10-18 15:58:25 -06:00
Jason Turner
48c97bce9c Add faux-inheritance example 2014-10-12 22:13:40 -07:00
Jason Turner
021e2a7949 Fix returning of boolean values from functors 2014-10-12 22:12:54 -07:00
Jason Turner
78cd980067 Work around broken Apple clang implementation
This line of code does not cause an error on clang-3.4 or clang-3.5
on Linux. Apple's clang is somewhere between the two, no way to know
where.

For an unknown reason, specifying default move operations in 'Data'
causes the compiler to think that Boxed_Value is an incomplete type.

This is highly illogical since Data is only used via a shared_ptr, so
the size / type of Boxed_Value should be fully known (and is known on
every other compiler/platform combination).
2014-10-01 15:49:11 -06:00
Jason Turner
58d9e69479 Work around missing move operations in MSVC12 2014-10-05 21:53:44 -06:00
Jason Turner
935e9de19e GCC 4.6 fixes to cleanups 2014-10-05 14:58:27 -06:00
Jason Turner
f547b4bb10 Enable moving of data into Boxed_Values when possible 2014-10-05 12:11:46 -06:00
Jason Turner
87e40237d3 Enable moving of Any objects 2014-10-05 11:47:50 -06:00
Jason Turner
5619f2602d Eliminate extra dynamic allocation in the Stack 2014-10-05 08:58:29 -06:00
Jason Turner
5986531bba dispatchkit modernization 2014-10-04 22:59:52 -06:00
Jason Turner
8ecc11c275 First pass of modernization of chaiscript_eval.hpp done 2014-10-04 18:31:08 -06:00
Jason Turner
81dc4949d2 1/4 through modernization of chaiscript_eval.hpp 2014-10-04 15:34:32 -06:00
Jason Turner
9a7d03df05 Modernization of chaiscript_parser 2014-10-04 09:37:33 -06:00
Jason Turner
4f5a6da280 Move constructor and noexcept correctness 2014-09-21 14:19:41 -06:00
Jason Turner
e4b9be6e09 Merge remote-tracking branch 'origin/develop' into code_cleanups
Conflicts:
	.decent_ci-Linux.yaml
2014-09-20 14:27:37 -06:00
Jason Turner
0a7e7b3a0d Merge pull request #137 from ChaiScript/enable_decent_ci
Enable decent ci
2014-09-20 14:24:24 -06:00
Jason Turner
e1b80abac4 Update documenation to-dos regarding gcc 4.6 2014-09-20 14:20:37 -06:00
Jason Turner
b6e8605aee Attempt again to satisfy gcc 4.6 2014-09-20 14:17:41 -06:00
Jason Turner
0e381e333e Attempt to satisfy G++4.6 and decltype usage 2014-09-20 08:31:18 -06:00
Jason Turner
8c31255012 Windows and GCC 4.6 error cleanups 2014-09-20 07:21:30 -06:00
Jason Turner
01cf906e18 Clean up 32bit windows warnings 2014-09-19 21:58:28 -06:00
Jason Turner
e55700b86b Remove static in bind_first - VS12 warns on it 2014-09-19 21:52:18 -06:00
Jason Turner
81184cbbd7 Rollback template alias, not supported in gcc 4.6 2014-09-19 21:46:52 -06:00
Jason Turner
c00c38bc22 Fix spelling of "USE_LIBCXX" flag 2014-09-19 10:34:51 -06:00
Jason Turner
ae1897e2ea Update to force CI rebuild 2014-09-19 10:25:04 -06:00
Jason Turner
93c1cfde99 Try out some alias templates for cleanup 2014-09-18 20:48:34 -06:00
Jason Turner
2321f1d709 Enable clang linux builds 2014-09-18 20:07:15 -06:00
Jason Turner
cfd4a73a89 Add VS 2014 CI Support 2014-09-16 13:30:47 -06:00
Jason Turner
04782b6a33 Add gcc-4.6 to test configuration 2014-09-16 08:02:12 -06:00
Jason Turner
5861c45fc1 C++11 related cleanup and improvments 2014-09-15 21:16:44 -06:00
Jason Turner
d62a452a9d Correct -I path for cppcheck run 2014-09-15 07:12:19 -06:00
Jason Turner
3ccb155358 Fix up usage of cppcheck, enable samples build 2014-09-14 21:57:07 -06:00
Jason Turner
6c2ccf3869 Various cleanups prefering lambda to bind 2014-09-14 21:53:11 -06:00
Jason Turner
f02a9fa885 Merge remote-tracking branch 'origin/enable_decent_ci' into code_cleanups 2014-09-14 20:10:52 -06:00
Jason Turner
0036ebfe5d Update .decent_ci-Windows.yaml 2014-09-14 12:44:20 -06:00
Jason Turner
7b28f9ef57 Fix results location 2014-09-13 23:11:17 -06:00
Jason Turner
bd8a78eccc Initial decent_ci files 2014-09-13 21:53:12 -06:00
Jason Turner
9436533ddb Merge commit '243f400' into develop
Conflicts:
	include/chaiscript/dispatchkit/bind_first.hpp
2014-09-12 15:18:38 -06:00
Jason Turner
243f4001d1 Code cleanups 2014-09-12 15:16:24 -06:00
Jason Turner
3bd2a9c00d Clean up bind_first implementation 2014-09-10 07:40:16 -06:00
Jason Turner
fde90ad980 Throw exception if user attempts to use null Boxed_Value 2014-09-09 13:43:05 -06:00
Jason Turner
308eb34d05 Correct test_module changes 2014-09-08 21:15:02 -06:00
Jason Turner
4a70ffe599 Add failing unit test for accessing member of null object 2014-09-08 18:23:53 -06:00
Jason Turner
52179d8333 Merge branch 'develop' of https://github.com/ChaiScript/ChaiScript into develop 2014-09-08 11:11:35 -06:00
Jason Turner
eed90b521d Spelling corrections and comment fixes 2014-09-08 11:10:53 -06:00
Jason Turner
166f3501c3 Ignore missing system include files 2014-09-05 08:41:58 -06:00
Jason Turner
29b1fca76c Use g++-4.8 for cppcheck building 2014-09-05 08:09:22 -06:00
Jason Turner
8d36b66c89 Fix call to cppcheck 2014-09-05 07:45:36 -06:00
35 changed files with 2562 additions and 2770 deletions

13
.decent_ci-Linux.yaml Normal file
View 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
View 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
View 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
View 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

View File

@@ -133,7 +133,7 @@ else()
endif()
if("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
option(USE_LIBCXX "Use clang's libcxx" TRUE)
option(USE_LIBCXX "Use clang's libcxx" FALSE)
if(USE_LIBCXX)
add_definitions(-stdlib=libc++)
@@ -203,6 +203,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()

View File

@@ -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

View File

@@ -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.

View File

@@ -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();
@@ -44,30 +44,20 @@ namespace chaiscript {
private:
struct Data
{
Data(const std::type_info &t_type)
: m_type(t_type)
{
}
Data &operator=(const Data &) = delete;
virtual ~Data() {}
virtual void *data() = 0;
const std::type_info &type() const
{
return m_type;
}
virtual void *data() = 0;
virtual std::unique_ptr<Data> clone() const = 0;
const std::type_info &m_type;
};
template<typename T>
struct Data_Impl : Data
{
Data_Impl(T t_type)
: Data(typeid(T)),
m_data(std::move(t_type))
explicit Data_Impl(T t_type)
: m_data(std::move(t_type))
{
}
@@ -89,27 +79,54 @@ namespace chaiscript {
};
std::unique_ptr<Data> m_data;
mutable std::array<uint8_t, 15> m_smallSize;
bool m_isSmall = false;
const std::type_info *m_type = &typeid(void);
public:
// construct/copy/destruct
Any() = default;
Any(const Any &t_any)
{
if (!t_any.empty())
{
m_data = t_any.m_data->clone();
} else {
m_data.reset();
}
: m_data(t_any.m_data?t_any.m_data->clone():nullptr),
m_smallSize(t_any.m_smallSize),
m_isSmall(t_any.m_isSmall),
m_type(t_any.m_type)
{
}
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,
typename = typename std::enable_if< std::is_trivial<typename std::decay<ValueType>::type>::value>::type,
typename = typename std::enable_if<sizeof(typename std::decay<ValueType>::type) <= sizeof(decltype(m_smallSize)) >::type>
explicit Any(ValueType &&t_value)
: m_isSmall(true), m_type(&typeid(typename std::decay<ValueType>::type))
{
m_smallSize.fill(0);
*(static_cast<typename std::decay<ValueType>::type *>(static_cast<void *>(m_smallSize.data()))) = t_value;
// std::cout << "Setting type: " << typeid(typename std::decay<ValueType>::type).name() << " " << t_value << " actual val: " << *(static_cast<typename std::decay<ValueType>::type *>(static_cast<void *>(m_smallSize.data()))) << " cast: " << cast<typename std::decay<ValueType>::type>() << "\n";
}
template<typename ValueType,
typename = typename std::enable_if<!std::is_same<Any, typename std::decay<ValueType>::type>::value>::type,
typename = typename std::enable_if<
!std::is_trivial<typename std::decay<ValueType>::type>::value
|| !(sizeof(typename std::decay<ValueType>::type) <= sizeof(decltype(m_smallSize))) >::type>
explicit Any(ValueType &&t_value)
: m_data(std::unique_ptr<Data>(new Data_Impl<typename std::decay<ValueType>::type>(std::forward<ValueType>(t_value)))),
m_isSmall(false),
m_type(&typeid(typename std::decay<ValueType>::type))
{
}
Any & operator=(const Any &t_any)
{
Any copy(t_any);
@@ -117,24 +134,23 @@ 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
{
if (m_data && typeid(ToType) == m_data->type())
if (m_isSmall && typeid(ToType) == *m_type)
{
return *static_cast<ToType *>(static_cast<void *>(m_smallSize.data()));
} else if (!m_isSmall && m_data && typeid(ToType) == *m_type) {
return *static_cast<ToType *>(m_data->data());
} else {
throw chaiscript::detail::exception::bad_any_cast();
}
}
const std::type_info &type() const
{
return *m_type;
}
~Any()
{
@@ -143,25 +159,31 @@ namespace chaiscript {
// modifiers
Any & swap(Any &t_other)
{
std::swap(t_other.m_smallSize, m_smallSize);
std::swap(t_other.m_isSmall, m_isSmall);
std::swap(t_other.m_data, m_data);
std::swap(t_other.m_type, m_type);
return *this;
}
// queries
bool empty() const
{
return !bool(m_data);
return !bool(m_data) && !m_isSmall;
}
const std::type_info & type() const
void *data() const
{
if (m_data)
if (m_isSmall)
{
return m_data->type();
return static_cast<void *>(m_smallSize.data());
} else if (m_data) {
return m_data->data();
} else {
return typeid(void);
return nullptr;
}
}
};
}

View File

@@ -46,7 +46,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();

View File

@@ -14,71 +14,12 @@ namespace chaiscript
namespace detail
{
template<int>
struct Placeholder
{
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<>
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; }
};
};
template<int count, int maxcount, typename Sig>
struct Bind_First
@@ -86,7 +27,7 @@ namespace chaiscript
template<typename F, typename ... 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(f, innerparams..., std::get<maxcount - count>(Placeholder::placeholder()));
}
};

View File

@@ -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,13 +145,11 @@ 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)
{
@@ -504,8 +492,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 +513,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 +541,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),

View File

@@ -86,7 +86,7 @@ namespace chaiscript
#pragma warning(disable : 4127)
#endif
if (std::is_polymorphic<typename detail::Stripped_Type<Type>::type>::value && t_conversions)
if (std::is_polymorphic<typename detail::Bare_Type<Type>::type>::value && t_conversions)
{
try {
// std::cout << "trying an up conversion " << typeid(Type).name() << std::endl;

View File

@@ -23,9 +23,14 @@ namespace chaiscript
{
// 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
{
@@ -33,21 +38,11 @@ namespace chaiscript
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_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,22 +52,17 @@ 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 *)
{
if (ob.is_ref())
@@ -94,14 +84,11 @@ 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 *)
{
if (ob.is_ref())
@@ -113,9 +100,8 @@ 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 &>
{
@@ -123,19 +109,16 @@ namespace chaiscript
static Result_Type cast(const Boxed_Value &ob, const Dynamic_Cast_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> >
{
@@ -147,9 +130,7 @@ namespace chaiscript
}
};
/**
* 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> >
{
@@ -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,9 +172,7 @@ 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>
{
@@ -209,9 +184,7 @@ 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 &>
{
@@ -224,9 +197,7 @@ namespace chaiscript
};
/**
* 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,9 +240,7 @@ 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
{

View File

@@ -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)

View File

@@ -35,10 +35,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 +61,10 @@ 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;
@@ -75,7 +76,7 @@ namespace chaiscript
struct Object_Data
{
static std::shared_ptr<Data> get(Boxed_Value::Void_Type)
static std::shared_ptr<Data> get(Boxed_Value::Void_Type, bool, bool)
{
return std::make_shared<Data>(
detail::Get_Type_Info<void>::get(),
@@ -86,13 +87,13 @@ namespace chaiscript
}
template<typename T>
static std::shared_ptr<Data> get(const std::shared_ptr<T> *obj)
static std::shared_ptr<Data> get(const std::shared_ptr<T> *obj, bool, bool)
{
return get(*obj);
}
template<typename T>
static std::shared_ptr<Data> get(const std::shared_ptr<T> &obj)
static std::shared_ptr<Data> get(const std::shared_ptr<T> &obj, bool, bool)
{
return std::make_shared<Data>(
detail::Get_Type_Info<T>::get(),
@@ -102,6 +103,18 @@ namespace chaiscript
);
}
template<typename T>
static std::shared_ptr<Data> get(std::shared_ptr<T> &&obj, bool, bool)
{
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)
{
@@ -109,32 +122,69 @@ namespace chaiscript
}
template<typename T>
static std::shared_ptr<Data> get(std::reference_wrapper<T> obj)
static std::shared_ptr<Data> get(std::reference_wrapper<T> obj, bool, bool)
{
auto p = &obj.get();
return std::make_shared<Data>(
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, bool t_value_type, bool t_make_const)
{
auto p = std::make_shared<T>(t);
return std::make_shared<Data>(
detail::Get_Type_Info<T>::get(),
chaiscript::detail::Any(p),
false,
p.get()
);
typedef typename std::add_const<T>::type const_type;
if (t_make_const)
{
if (t_value_type)
{
chaiscript::detail::Any a(std::move(t));
return std::make_shared<Data>(
detail::Get_Type_Info<const_type>::get(),
std::move(a),
false,
nullptr
);
} else {
auto p = std::make_shared<const_type>(std::move(t));
auto ptr = p.get();
return std::make_shared<Data>(
detail::Get_Type_Info<const_type>::get(),
chaiscript::detail::Any(std::move(p)),
false,
ptr
);
}
} else {
if (t_value_type)
{
chaiscript::detail::Any a(std::move(t));
return std::make_shared<Data>(
detail::Get_Type_Info<T>::get(),
std::move(a),
false,
nullptr
);
} else {
auto p = std::make_shared<T>(std::move(t));
auto ptr = p.get();
return std::make_shared<Data>(
detail::Get_Type_Info<T>::get(),
chaiscript::detail::Any(std::move(p)),
false,
ptr
);
}
}
}
static std::shared_ptr<Data> get()
{
return std::make_shared<Data>(
Type_Info(),
Type_Info(),
chaiscript::detail::Any(),
false,
nullptr
@@ -145,27 +195,27 @@ 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, bool t_make_const=false, bool t_value_type = std::is_trivial<typename std::decay<T>::type>::value)
: m_data(Object_Data::get(std::forward<T>(t), t_make_const, t_value_type))
{
//std::cout << "typeid: " << typeid(T).name() << " is trivial " << std::is_trivial<typename std::decay<T>::type>::value << "\n";
}
/// 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,63 +230,65 @@ 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;
if (m_data->m_data_ptr)
{
return m_data->m_data_ptr;
} else {
return m_data->m_obj.data();
}
}
const void *get_const_ptr() const
const void *get_const_ptr() const CHAISCRIPT_NOEXCEPT
{
return m_data->m_const_data_ptr;
if (m_data->m_const_data_ptr)
{
return m_data->m_const_data_ptr;
} else {
return m_data->m_obj.data();
}
}
Boxed_Value get_attr(const std::string &t_name)
@@ -260,7 +312,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 +349,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), true);
}
/// \brief Takes a pointer to a value, adds const to the pointed to type and returns an immutable Boxed_Value.

View File

@@ -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,40 +135,40 @@ 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(Dynamic_Cast_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();
// 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
Module &eval(const std::string &str)
//Add a bit of ChaiScript to eval during module implementation
Module &eval(std::string str)
{
m_evals.push_back(str);
m_evals.push_back(std::move(str));
return *this;
}
@@ -208,18 +200,18 @@ namespace chaiscript
std::vector<Dynamic_Cast_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,17 +250,15 @@ 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)
Dispatch_Function(std::vector<Proxy_Function> t_funcs)
: Proxy_Function_Base(build_type_infos(t_funcs)),
m_funcs(t_funcs)
m_funcs(std::move(t_funcs))
{
}
@@ -292,46 +282,31 @@ namespace chaiscript
virtual int get_arity() const CHAISCRIPT_OVERRIDE
{
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 (m_funcs.empty()) {
return -1;
}
return -1; // unknown arity
const int arity = m_funcs.front()->get_arity();
for (const auto &func : m_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
{
auto begin = m_funcs.begin();
auto end = m_funcs.end();
while (begin != end)
for (const auto &func : m_funcs)
{
if ((*begin)->call_match(vals, t_conversions))
if (func->call_match(vals, t_conversions))
{
return true;
} else {
++begin;
}
}
@@ -399,7 +374,7 @@ namespace chaiscript
return std::vector<Type_Info>();
}
};
};
}
@@ -414,8 +389,7 @@ namespace chaiscript
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 +404,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,27 +419,21 @@ namespace chaiscript
return chaiscript::boxed_cast<Type>(bv, &m_conversions);
}
/**
* Add a new conversion for upcasting to a base class
*/
/// Add a new conversion for upcasting to a base class
void add(const Dynamic_Cast_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);
@@ -474,45 +441,40 @@ namespace chaiscript
for (int i = static_cast<int>(stack.size())-1; i >= 0; --i)
{
std::map<std::string, Boxed_Value>::const_iterator itr = stack[i].find(name);
const auto itr = stack[i].find(name);
if (itr != stack[i].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();
validate_object_name(name);
Scope &scope = stack.back();
auto itr = scope.find(name);
if (itr != stack.back().end())
const Scope &scope = stack.back();
if (scope.find(name) != scope.end())
{
throw chaiscript::exception::name_conflict_error(name);
} else {
stack.back().insert(std::make_pair(name, obj));
stack.back().insert(std::make_pair(name, std::move(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);
if (!obj.is_const())
{
throw chaiscript::exception::global_non_const();
// throw chaiscript::exception::global_non_const();
}
chaiscript::detail::threading::unique_lock<chaiscript::detail::threading::shared_mutex> l(m_global_object_mutex);
@@ -526,9 +488,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 +504,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 +526,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 +535,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?
@@ -605,7 +551,7 @@ namespace chaiscript
// Is it in the stack?
for (int i = static_cast<int>(stack.size())-1; i >= 0; --i)
{
std::map<std::string, Boxed_Value>::const_iterator stackitr = stack[i].find(name);
const auto stackitr = stack[i].find(name);
if (stackitr != stack[i].end())
{
return stackitr->second;
@@ -616,7 +562,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 +573,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 +583,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 +598,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 +616,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 +624,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 +647,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 +659,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();
}
@@ -779,12 +711,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 +739,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 +752,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);
}
}
@@ -867,40 +796,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,10 +846,8 @@ 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> &params)
{
if (params.size() < 1)
@@ -939,14 +855,12 @@ namespace chaiscript
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 +887,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 {
@@ -1043,13 +955,11 @@ namespace chaiscript
}
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,8 +984,8 @@ 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 std::vector<Type_Info> &lhsparamtypes = lhs->get_param_types();
const std::vector<Type_Info> &rhsparamtypes = rhs->get_param_types();
const size_t lhssize = lhsparamtypes.size();
const size_t rhssize = rhsparamtypes.size();
@@ -1112,11 +1022,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 &lt = lhsparamtypes[i];
const Type_Info &rt = rhsparamtypes[i];
if (lt.bare_equal(rt) && lt.is_const() == rt.is_const())
{
@@ -1167,9 +1076,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 +1091,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 +1116,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,16 +1140,14 @@ 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;
chaiscript::detail::threading::Thread_Storage<Stack_Holder> m_stack_holder;

View File

@@ -258,7 +258,7 @@ namespace chaiscript
/// \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
/// 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

View File

@@ -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;

View File

@@ -81,7 +81,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

View File

@@ -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(&not_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;
}
}

View File

@@ -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 >

View File

@@ -63,7 +63,7 @@ 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; }
@@ -182,7 +182,7 @@ namespace chaiscript
/// \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;

View File

@@ -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>()... };
}
@@ -118,7 +91,7 @@ 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>
@@ -166,7 +139,7 @@ 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.
*/

View File

@@ -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)
{
@@ -215,11 +202,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

View File

@@ -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)");
}

View File

@@ -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,8 +345,10 @@ 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");
@@ -382,7 +384,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 +393,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 +459,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 +467,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 +525,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 +543,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
@@ -716,15 +716,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 +727,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 +839,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 +873,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

View File

@@ -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;

View File

@@ -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);
}
}
}
}

134
samples/inheritance.cpp Normal file
View File

@@ -0,0 +1,134 @@
#include <chaiscript/chaiscript.hpp>
#include <chaiscript/chaiscript_stdlib.hpp>
class BaseClass
{
public:
BaseClass()
{
}
virtual ~BaseClass() = default;
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 override
{
assert(m_doSomethingImpl);
return m_doSomethingImpl(*this, f, d);
}
protected:
bool validateValue(const std::string &t_val) 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
}

View File

@@ -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")

View File

@@ -51,12 +51,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()
@@ -111,6 +116,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");

View File

@@ -0,0 +1,13 @@
load_module("test_module")
auto o := null_factory();
try {
o.func();
} catch (e) {
exit(0);
}
assert_true(false);

View File

@@ -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;
}