Compare commits
39 Commits
Test_Relea
...
Workaround
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5852412d2c | ||
|
|
452f71b51f | ||
|
|
a97cb1530d | ||
|
|
21048b9e65 | ||
|
|
d73e715997 | ||
|
|
353a077c6b | ||
|
|
373a3688c9 | ||
|
|
208107fd7e | ||
|
|
e19a8e31ea | ||
|
|
b55eff95cf | ||
|
|
b6287a194c | ||
|
|
888d897a3e | ||
|
|
e32714c456 | ||
|
|
e1c40f3e8f | ||
|
|
d7489358f3 | ||
|
|
316ba45e3c | ||
|
|
f0796b51c8 | ||
|
|
e638d450ed | ||
|
|
e60eabbeb2 | ||
|
|
c249bef27d | ||
|
|
4e69e5a3d2 | ||
|
|
49c89a3b88 | ||
|
|
7507223c8b | ||
|
|
681b7db727 | ||
|
|
4826bddb5b | ||
|
|
21c3853537 | ||
|
|
49436e5740 | ||
|
|
202204a82a | ||
|
|
34c6b17215 | ||
|
|
6fe7f5ce98 | ||
|
|
d9f86a96f0 | ||
|
|
40b1549b3b | ||
|
|
c9a5bf6f83 | ||
|
|
8496a86043 | ||
|
|
bc388e59da | ||
|
|
09748275db | ||
|
|
eec0299cbc | ||
|
|
19ecfdfec5 | ||
|
|
3e62a99f82 |
@@ -12,7 +12,7 @@ compilers:
|
|||||||
build_tag: AddressSanitizer
|
build_tag: AddressSanitizer
|
||||||
version: "3.6"
|
version: "3.6"
|
||||||
skip_packaging: true
|
skip_packaging: true
|
||||||
cmake_extra_flags: -DUSE_LIBCXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DENABLE_ADDRESS_SANITIZER:BOOL=ON
|
cmake_extra_flags: -DRUN_FUZZY_TESTS:BOOL=TRUE -DUSE_LIBCXX:BOOL=OFF -DBUILD_SAMPLES:BOOL=ON -DBUILD_PACKAGE:BOOL=ON -DBUILD_TESTING:BOOL=ON -DENABLE_ADDRESS_SANITIZER:BOOL=ON
|
||||||
- name: "clang"
|
- name: "clang"
|
||||||
build_tag: ThreadSanitizer
|
build_tag: ThreadSanitizer
|
||||||
version: "3.6"
|
version: "3.6"
|
||||||
|
|||||||
@@ -266,6 +266,8 @@ if(BUILD_SAMPLES)
|
|||||||
target_link_libraries(memory_leak_test ${LIBS})
|
target_link_libraries(memory_leak_test ${LIBS})
|
||||||
add_executable(inheritance samples/inheritance.cpp)
|
add_executable(inheritance samples/inheritance.cpp)
|
||||||
target_link_libraries(inheritance ${LIBS})
|
target_link_libraries(inheritance ${LIBS})
|
||||||
|
add_executable(factory samples/factory.cpp)
|
||||||
|
target_link_libraries(factory ${LIBS})
|
||||||
add_executable(fun_call_performance samples/fun_call_performance.cpp)
|
add_executable(fun_call_performance samples/fun_call_performance.cpp)
|
||||||
target_link_libraries(fun_call_performance ${LIBS})
|
target_link_libraries(fun_call_performance ${LIBS})
|
||||||
endif()
|
endif()
|
||||||
|
|||||||
@@ -77,7 +77,7 @@ chai.add(chaiscript::constructor<MyType (const MyType &)>(), "MyType");
|
|||||||
It's not strictly necessary to add types, but it helps with many things. Cloning, better errors, etc.
|
It's not strictly necessary to add types, but it helps with many things. Cloning, better errors, etc.
|
||||||
|
|
||||||
```
|
```
|
||||||
chai.add(chaiscript::user_type<MyClass>, "MyClass");
|
chai.add(chaiscript::user_type<MyClass>(), "MyClass");
|
||||||
```
|
```
|
||||||
|
|
||||||
## Adding Type Conversions
|
## Adding Type Conversions
|
||||||
@@ -365,6 +365,7 @@ class My_Class {
|
|||||||
this.x = 2; // this would fail with explicit set to true
|
this.x = 2; // this would fail with explicit set to true
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
```
|
||||||
|
|
||||||
## method_missing
|
## method_missing
|
||||||
|
|
||||||
|
|||||||
@@ -29,8 +29,9 @@
|
|||||||
#define CHAISCRIPT_WINDOWS
|
#define CHAISCRIPT_WINDOWS
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (defined(__GNUC__) && __GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) || (defined(__llvm__) && !defined(CHAISCRIPT_LIBCPP))
|
#if ( ( (defined(__GNUC__) && __GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8) ) && !defined(WIN32)) || (defined(__llvm__) && !defined(CHAISCRIPT_LIBCPP))
|
||||||
/// Currently only g++>=4.8 supports this natively
|
/// Currently only g++>=4.8 supports this natively
|
||||||
|
/// MinGW pretends to, but causes a crash on exit when thread_local objects are destructed
|
||||||
/// \todo Make this support other compilers when possible
|
/// \todo Make this support other compilers when possible
|
||||||
#define CHAISCRIPT_HAS_THREAD_LOCAL
|
#define CHAISCRIPT_HAS_THREAD_LOCAL
|
||||||
#endif
|
#endif
|
||||||
@@ -39,7 +40,11 @@
|
|||||||
#define CHAISCRIPT_GCC_4_6
|
#define CHAISCRIPT_GCC_4_6
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if (defined(__GNUC__) && __GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7) || defined(CHAISCRIPT_MSVC) || defined(__llvm__)
|
#if defined(__llvm__)
|
||||||
|
#define CHAISCRIPT_CLANG
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if (defined(__GNUC__) && __GNUC__ > 4) || (__GNUC__ == 4 && __GNUC_MINOR__ >= 7) || defined(CHAISCRIPT_MSVC) || defined(CHAISCRIPT_CLANG)
|
||||||
#define CHAISCRIPT_OVERRIDE override
|
#define CHAISCRIPT_OVERRIDE override
|
||||||
#else
|
#else
|
||||||
#define CHAISCRIPT_OVERRIDE
|
#define CHAISCRIPT_OVERRIDE
|
||||||
|
|||||||
@@ -33,14 +33,14 @@ namespace chaiscript
|
|||||||
template<typename Result>
|
template<typename Result>
|
||||||
struct Cast_Helper_Inner
|
struct Cast_Helper_Inner
|
||||||
{
|
{
|
||||||
typedef std::reference_wrapper<typename std::add_const<Result>::type > Result_Type;
|
typedef typename std::add_const<Result>::type Result_Type;
|
||||||
|
|
||||||
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||||
{
|
{
|
||||||
if (ob.get_type_info().bare_equal_type_info(typeid(Result)))
|
if (ob.get_type_info().bare_equal_type_info(typeid(Result)))
|
||||||
{
|
{
|
||||||
auto p = throw_if_null(ob.get_const_ptr());
|
auto p = throw_if_null(ob.get_const_ptr());
|
||||||
return std::cref(*static_cast<const Result *>(p));
|
return *static_cast<const Result *>(p);
|
||||||
} else {
|
} else {
|
||||||
throw chaiscript::detail::exception::bad_any_cast();
|
throw chaiscript::detail::exception::bad_any_cast();
|
||||||
}
|
}
|
||||||
@@ -52,12 +52,6 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
};
|
};
|
||||||
|
|
||||||
/// 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>
|
template<typename Result>
|
||||||
@@ -68,7 +62,7 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
if (ob.get_type_info().bare_equal_type_info(typeid(Result)))
|
if (ob.get_type_info().bare_equal_type_info(typeid(Result)))
|
||||||
{
|
{
|
||||||
return static_cast<const Result *>(throw_if_null(ob.get_const_ptr()));
|
return static_cast<const Result *>(ob.get_const_ptr());
|
||||||
} else {
|
} else {
|
||||||
throw chaiscript::detail::exception::bad_any_cast();
|
throw chaiscript::detail::exception::bad_any_cast();
|
||||||
}
|
}
|
||||||
@@ -84,7 +78,36 @@ namespace chaiscript
|
|||||||
{
|
{
|
||||||
if (!ob.get_type_info().is_const() && ob.get_type_info() == typeid(Result))
|
if (!ob.get_type_info().is_const() && ob.get_type_info() == typeid(Result))
|
||||||
{
|
{
|
||||||
return static_cast<Result *>(throw_if_null(ob.get_ptr()));
|
return static_cast<Result *>(ob.get_ptr());
|
||||||
|
} else {
|
||||||
|
throw chaiscript::detail::exception::bad_any_cast();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Result>
|
||||||
|
struct Cast_Helper_Inner<Result * const &> : public Cast_Helper_Inner<Result *>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
template<typename Result>
|
||||||
|
struct Cast_Helper_Inner<const Result * const &> : public Cast_Helper_Inner<const Result *>
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/// Cast_Helper_Inner for casting to a & type
|
||||||
|
template<typename Result>
|
||||||
|
struct Cast_Helper_Inner<const Result &>
|
||||||
|
{
|
||||||
|
typedef const Result& Result_Type;
|
||||||
|
|
||||||
|
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
|
||||||
|
{
|
||||||
|
if (ob.get_type_info().bare_equal_type_info(typeid(Result)))
|
||||||
|
{
|
||||||
|
auto p = throw_if_null(ob.get_const_ptr());
|
||||||
|
return *static_cast<const Result *>(p);
|
||||||
} else {
|
} else {
|
||||||
throw chaiscript::detail::exception::bad_any_cast();
|
throw chaiscript::detail::exception::bad_any_cast();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -31,6 +31,8 @@ namespace chaiscript
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
option_explicit_set(const option_explicit_set &) = default;
|
||||||
|
|
||||||
virtual ~option_explicit_set() CHAISCRIPT_NOEXCEPT {}
|
virtual ~option_explicit_set() CHAISCRIPT_NOEXCEPT {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -32,17 +32,17 @@ namespace chaiscript
|
|||||||
CHAISCRIPT_CONSTEXPR Type_Info(bool t_is_const, bool t_is_reference, bool t_is_pointer, bool t_is_void,
|
CHAISCRIPT_CONSTEXPR Type_Info(bool t_is_const, bool t_is_reference, bool t_is_pointer, bool t_is_void,
|
||||||
bool t_is_arithmetic, const std::type_info *t_ti, const std::type_info *t_bare_ti)
|
bool t_is_arithmetic, const std::type_info *t_ti, const std::type_info *t_bare_ti)
|
||||||
: m_type_info(t_ti), m_bare_type_info(t_bare_ti),
|
: m_type_info(t_ti), m_bare_type_info(t_bare_ti),
|
||||||
m_is_const(t_is_const), m_is_reference(t_is_reference), m_is_pointer(t_is_pointer),
|
m_flags((t_is_const << is_const_flag)
|
||||||
m_is_void(t_is_void), m_is_arithmetic(t_is_arithmetic),
|
+ (t_is_reference << is_reference_flag)
|
||||||
m_is_undef(false)
|
+ (t_is_pointer << is_pointer_flag)
|
||||||
|
+ (t_is_void << is_void_flag)
|
||||||
|
+ (t_is_arithmetic << is_arithmetic_flag))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
CHAISCRIPT_CONSTEXPR Type_Info()
|
CHAISCRIPT_CONSTEXPR Type_Info()
|
||||||
: m_type_info(nullptr), m_bare_type_info(nullptr),
|
: m_type_info(nullptr), m_bare_type_info(nullptr),
|
||||||
m_is_const(false), m_is_reference(false), m_is_pointer(false),
|
m_flags(1 << is_undef_flag)
|
||||||
m_is_void(false), m_is_arithmetic(false),
|
|
||||||
m_is_undef(true)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,12 +83,12 @@ namespace chaiscript
|
|||||||
&& (*m_bare_type_info) == ti;
|
&& (*m_bare_type_info) == ti;
|
||||||
}
|
}
|
||||||
|
|
||||||
CHAISCRIPT_CONSTEXPR bool is_const() const CHAISCRIPT_NOEXCEPT { return m_is_const; }
|
CHAISCRIPT_CONSTEXPR bool is_const() const CHAISCRIPT_NOEXCEPT { return m_flags & (1 << is_const_flag); }
|
||||||
CHAISCRIPT_CONSTEXPR bool is_reference() const CHAISCRIPT_NOEXCEPT { return m_is_reference; }
|
CHAISCRIPT_CONSTEXPR bool is_reference() const CHAISCRIPT_NOEXCEPT { return m_flags & (1 << is_reference_flag); }
|
||||||
CHAISCRIPT_CONSTEXPR bool is_void() const CHAISCRIPT_NOEXCEPT { return m_is_void; }
|
CHAISCRIPT_CONSTEXPR bool is_void() const CHAISCRIPT_NOEXCEPT { return m_flags & (1 << is_void_flag); }
|
||||||
CHAISCRIPT_CONSTEXPR bool is_arithmetic() const CHAISCRIPT_NOEXCEPT { return m_is_arithmetic; }
|
CHAISCRIPT_CONSTEXPR bool is_arithmetic() const CHAISCRIPT_NOEXCEPT { return m_flags & (1 << is_arithmetic_flag); }
|
||||||
CHAISCRIPT_CONSTEXPR bool is_undef() const CHAISCRIPT_NOEXCEPT { return m_is_undef; }
|
CHAISCRIPT_CONSTEXPR bool is_undef() const CHAISCRIPT_NOEXCEPT { return m_flags & (1 << is_undef_flag); }
|
||||||
CHAISCRIPT_CONSTEXPR bool is_pointer() const CHAISCRIPT_NOEXCEPT { return m_is_pointer; }
|
CHAISCRIPT_CONSTEXPR bool is_pointer() const CHAISCRIPT_NOEXCEPT { return m_flags & (1 << is_pointer_flag); }
|
||||||
|
|
||||||
std::string name() const
|
std::string name() const
|
||||||
{
|
{
|
||||||
@@ -118,12 +118,13 @@ namespace chaiscript
|
|||||||
private:
|
private:
|
||||||
const std::type_info *m_type_info;
|
const std::type_info *m_type_info;
|
||||||
const std::type_info *m_bare_type_info;
|
const std::type_info *m_bare_type_info;
|
||||||
bool m_is_const;
|
unsigned int m_flags;
|
||||||
bool m_is_reference;
|
static const int is_const_flag = 0;
|
||||||
bool m_is_pointer;
|
static const int is_reference_flag = 1;
|
||||||
bool m_is_void;
|
static const int is_pointer_flag = 2;
|
||||||
bool m_is_arithmetic;
|
static const int is_void_flag = 3;
|
||||||
bool m_is_undef;
|
static const int is_arithmetic_flag = 4;
|
||||||
|
static const int is_undef_flag = 5;
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace detail
|
namespace detail
|
||||||
|
|||||||
@@ -660,14 +660,20 @@ namespace chaiscript
|
|||||||
|
|
||||||
const auto val = prefixed?std::string(t_val.begin()+2,t_val.end()):t_val;
|
const auto val = prefixed?std::string(t_val.begin()+2,t_val.end()):t_val;
|
||||||
|
|
||||||
try {
|
|
||||||
auto u = std::stoll(val,nullptr,base);
|
|
||||||
|
|
||||||
#ifdef __GNUC__
|
#ifdef __GNUC__
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma GCC diagnostic ignored "-Wsign-compare"
|
#pragma GCC diagnostic ignored "-Wsign-compare"
|
||||||
|
|
||||||
|
#ifdef CHAISCRIPT_CLANG
|
||||||
|
#pragma GCC diagnostic ignored "-Wtautological-compare"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
try {
|
||||||
|
auto u = std::stoll(val,nullptr,base);
|
||||||
|
|
||||||
|
|
||||||
if (!unsigned_ && !long_ && u >= std::numeric_limits<int>::min() && u <= std::numeric_limits<int>::max()) {
|
if (!unsigned_ && !long_ && u >= std::numeric_limits<int>::min() && u <= std::numeric_limits<int>::max()) {
|
||||||
return const_var(static_cast<int>(u));
|
return const_var(static_cast<int>(u));
|
||||||
} else if ((unsigned_ || base != 10) && !long_ && u >= std::numeric_limits<unsigned int>::min() && u <= std::numeric_limits<unsigned int>::max()) {
|
} else if ((unsigned_ || base != 10) && !long_ && u >= std::numeric_limits<unsigned int>::min() && u <= std::numeric_limits<unsigned int>::max()) {
|
||||||
@@ -682,10 +688,6 @@ namespace chaiscript
|
|||||||
return const_var(static_cast<unsigned long long>(u));
|
return const_var(static_cast<unsigned long long>(u));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __GNUC__
|
|
||||||
#pragma GCC diagnostic pop
|
|
||||||
#endif
|
|
||||||
|
|
||||||
} catch (const std::out_of_range &) {
|
} catch (const std::out_of_range &) {
|
||||||
// too big to be signed
|
// too big to be signed
|
||||||
try {
|
try {
|
||||||
@@ -701,6 +703,11 @@ namespace chaiscript
|
|||||||
return const_var(std::numeric_limits<long long>::max());
|
return const_var(std::numeric_limits<long long>::max());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef __GNUC__
|
||||||
|
#pragma GCC diagnostic pop
|
||||||
|
#endif
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T, typename ... Param>
|
template<typename T, typename ... Param>
|
||||||
@@ -954,6 +961,40 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
|
|
||||||
void parse(const char_type t_char, const int line, const int col, const std::string &filename) {
|
void parse(const char_type t_char, const int line, const int col, const std::string &filename) {
|
||||||
|
const bool is_octal_char = t_char >= '0' && t_char <= '7';
|
||||||
|
|
||||||
|
if (is_octal) {
|
||||||
|
if (is_octal_char) {
|
||||||
|
octal_matches.push_back(t_char);
|
||||||
|
|
||||||
|
if (octal_matches.size() == 3) {
|
||||||
|
process_octal();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
process_octal();
|
||||||
|
}
|
||||||
|
} else if (is_hex) {
|
||||||
|
const bool is_hex_char = (t_char >= '0' && t_char <= '9')
|
||||||
|
|| (t_char >= 'a' && t_char <= 'f')
|
||||||
|
|| (t_char >= 'A' && t_char <= 'F');
|
||||||
|
|
||||||
|
if (is_hex_char) {
|
||||||
|
hex_matches.push_back(t_char);
|
||||||
|
|
||||||
|
if (hex_matches.size() == 2*sizeof(char_type)) {
|
||||||
|
// This rule differs from the C/C++ standard, but ChaiScript
|
||||||
|
// does not offer the same workaround options, and having
|
||||||
|
// hexadecimal sequences longer than can fit into the char
|
||||||
|
// type is undefined behavior anyway.
|
||||||
|
process_hex();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
process_hex();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (t_char == '\\') {
|
if (t_char == '\\') {
|
||||||
if (is_escaped) {
|
if (is_escaped) {
|
||||||
match.push_back('\\');
|
match.push_back('\\');
|
||||||
@@ -963,31 +1004,7 @@ namespace chaiscript
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (is_escaped) {
|
if (is_escaped) {
|
||||||
const bool is_octal_char = t_char >= '0' && t_char <= '7';
|
if (is_octal_char) {
|
||||||
|
|
||||||
if (is_octal) {
|
|
||||||
if (is_octal_char) {
|
|
||||||
octal_matches.push_back(t_char);
|
|
||||||
|
|
||||||
if (octal_matches.size() == 3) {
|
|
||||||
process_octal();
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
process_octal();
|
|
||||||
match.push_back(t_char);
|
|
||||||
}
|
|
||||||
} else if (is_hex) {
|
|
||||||
const bool is_hex_char = (t_char >= '0' && t_char <= '9')
|
|
||||||
|| (t_char >= 'a' && t_char <= 'f')
|
|
||||||
|| (t_char >= 'A' && t_char <= 'F');
|
|
||||||
|
|
||||||
if (is_hex_char) {
|
|
||||||
hex_matches.push_back(t_char);
|
|
||||||
} else {
|
|
||||||
process_hex();
|
|
||||||
match.push_back(t_char);
|
|
||||||
}
|
|
||||||
} else if (is_octal_char) {
|
|
||||||
is_octal = true;
|
is_octal = true;
|
||||||
octal_matches.push_back(t_char);
|
octal_matches.push_back(t_char);
|
||||||
} else if (t_char == 'x') {
|
} else if (t_char == 'x') {
|
||||||
|
|||||||
@@ -421,22 +421,22 @@ class JSON
|
|||||||
Class Type;
|
Class Type;
|
||||||
};
|
};
|
||||||
|
|
||||||
JSON Array() {
|
inline JSON Array() {
|
||||||
return JSON::Make( JSON::Class::Array );
|
return JSON::Make( JSON::Class::Array );
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename... T>
|
template <typename... T>
|
||||||
JSON Array( T... args ) {
|
inline JSON Array( T... args ) {
|
||||||
JSON arr = JSON::Make( JSON::Class::Array );
|
JSON arr = JSON::Make( JSON::Class::Array );
|
||||||
arr.append( args... );
|
arr.append( args... );
|
||||||
return arr;
|
return arr;
|
||||||
}
|
}
|
||||||
|
|
||||||
JSON Object() {
|
inline JSON Object() {
|
||||||
return JSON::Make( JSON::Class::Object );
|
return JSON::Make( JSON::Class::Object );
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream& operator<<( std::ostream &os, const JSON &json ) {
|
inline std::ostream& operator<<( std::ostream &os, const JSON &json ) {
|
||||||
os << json.dump();
|
os << json.dump();
|
||||||
return os;
|
return os;
|
||||||
}
|
}
|
||||||
@@ -636,7 +636,7 @@ namespace {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
JSON JSON::Load( const string &str ) {
|
inline JSON JSON::Load( const string &str ) {
|
||||||
size_t offset = 0;
|
size_t offset = 0;
|
||||||
return parse_next( str, offset );
|
return parse_next( str, offset );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,12 +8,14 @@
|
|||||||
#define CHAISCRIPT_UTILITY_UTILITY_HPP_
|
#define CHAISCRIPT_UTILITY_UTILITY_HPP_
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "../chaiscript.hpp"
|
#include "../chaiscript.hpp"
|
||||||
#include "../dispatchkit/proxy_functions.hpp"
|
#include "../dispatchkit/proxy_functions.hpp"
|
||||||
#include "../dispatchkit/type_info.hpp"
|
#include "../dispatchkit/type_info.hpp"
|
||||||
|
#include "../dispatchkit/operators.hpp"
|
||||||
|
|
||||||
|
|
||||||
namespace chaiscript
|
namespace chaiscript
|
||||||
@@ -62,6 +64,32 @@ namespace chaiscript
|
|||||||
t_module.add(fun.first, fun.second);
|
t_module.add(fun.first, fun.second);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Enum, typename ModuleType>
|
||||||
|
typename std::enable_if<std::is_enum<Enum>::value, void>::type
|
||||||
|
add_class(ModuleType &t_module,
|
||||||
|
const std::string &t_class_name,
|
||||||
|
const std::vector<std::pair<typename std::underlying_type<Enum>::type, std::string>> &t_constants)
|
||||||
|
{
|
||||||
|
t_module.add(chaiscript::user_type<Enum>(), t_class_name);
|
||||||
|
|
||||||
|
t_module.add(chaiscript::constructor<Enum ()>(), t_class_name);
|
||||||
|
t_module.add(chaiscript::constructor<Enum (const Enum &)>(), t_class_name);
|
||||||
|
|
||||||
|
t_module.add([](){
|
||||||
|
// add some comparison and assignment operators
|
||||||
|
using namespace chaiscript::bootstrap::operators;
|
||||||
|
return assign<Enum>(not_equal<Enum>(equal<Enum>()));
|
||||||
|
}());
|
||||||
|
|
||||||
|
t_module.add(chaiscript::fun([](const Enum &e, const typename std::underlying_type<Enum>::type &i) { return e == i; }), "==");
|
||||||
|
t_module.add(chaiscript::fun([](const typename std::underlying_type<Enum>::type &i, const Enum &e) { return i == e; }), "==");
|
||||||
|
|
||||||
|
for (const auto &constant : t_constants)
|
||||||
|
{
|
||||||
|
t_module.add_global_const(chaiscript::const_var(Enum(constant.first)), constant.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
103
samples/factory.cpp
Normal file
103
samples/factory.cpp
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
#include <chaiscript/chaiscript.hpp>
|
||||||
|
#include <chaiscript/chaiscript_stdlib.hpp>
|
||||||
|
|
||||||
|
class Entity
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
int x;
|
||||||
|
int y;
|
||||||
|
std::string name;
|
||||||
|
|
||||||
|
std::function<void (Entity &)> updater;
|
||||||
|
|
||||||
|
Entity(const int t_width, const int t_height, const int t_x, const int t_y, std::string t_name)
|
||||||
|
: width(t_width), height(t_height), x(t_x), y(t_y), name(std::move(t_name))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class Factory
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// we may as well pass the parameters for the entity to the factory method, this does the initialization
|
||||||
|
// in one step.
|
||||||
|
Entity *make_entity(const int width, const int height, const int x, const int y, const std::string &name)
|
||||||
|
{
|
||||||
|
auto entity = entities.insert({name, Entity{width, height, x, y, name}});
|
||||||
|
return &(entity.first->second);
|
||||||
|
}
|
||||||
|
|
||||||
|
Entity *get_entity(const std::string &name)
|
||||||
|
{
|
||||||
|
return &entities.at(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// loop over all entities and all their updater function (if it exists)
|
||||||
|
void update_entities()
|
||||||
|
{
|
||||||
|
for (auto &entity : entities)
|
||||||
|
{
|
||||||
|
if (entity.second.updater) {
|
||||||
|
entity.second.updater(entity.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
// we cannot store the entities in a std::vector if we want to return a pointer to them,
|
||||||
|
// because a vector automatically resizing itself can invalidate the pointer that was returned.
|
||||||
|
// using a map guarantees that the memory assigned to the entity will never change, plus
|
||||||
|
// lets us easily look up an entity by name
|
||||||
|
std::map<std::string, Entity> entities;
|
||||||
|
};
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
chaiscript::ChaiScript chai(chaiscript::Std_Lib::library());
|
||||||
|
|
||||||
|
chai.add(chaiscript::fun(&Entity::width), "width");
|
||||||
|
chai.add(chaiscript::fun(&Entity::height), "height");
|
||||||
|
chai.add(chaiscript::fun(&Entity::x), "x");
|
||||||
|
chai.add(chaiscript::fun(&Entity::y), "y");
|
||||||
|
chai.add(chaiscript::fun(&Entity::name), "name");
|
||||||
|
chai.add(chaiscript::fun(&Entity::updater), "updater");
|
||||||
|
chai.add(chaiscript::user_type<Entity>(), "Entity"); // this isn't strictly necessary but makes error messages nicer
|
||||||
|
|
||||||
|
chai.add(chaiscript::fun(&Factory::make_entity), "make_entity");
|
||||||
|
chai.add(chaiscript::fun(&Factory::get_entity), "get_entity");
|
||||||
|
chai.add(chaiscript::fun(&Factory::update_entities), "update_entities");
|
||||||
|
chai.add(chaiscript::user_type<Factory>(), "Factory"); // this isn't strictly necessary but makes error messages nicer
|
||||||
|
|
||||||
|
|
||||||
|
Factory f;
|
||||||
|
chai.add(chaiscript::var(&f), "f");
|
||||||
|
|
||||||
|
std::string script = R""(
|
||||||
|
f.make_entity(10,10,1,1,"entity1").updater = fun(e){ e.x += 1; e.y += 1 };
|
||||||
|
f.make_entity(10,10,10,10,"entity2").updater = fun(e){ e.x += 2; e.y += 2 };
|
||||||
|
f.make_entity(10,10,20,20,"entity3");
|
||||||
|
|
||||||
|
print(f.get_entity("entity1").x == 1)
|
||||||
|
print(f.get_entity("entity2").x == 10)
|
||||||
|
print(f.get_entity("entity3").x == 20)
|
||||||
|
|
||||||
|
f.update_entities(); // this runs the function objects we set in the previous lines
|
||||||
|
// we should now see the updated values
|
||||||
|
|
||||||
|
print(f.get_entity("entity1").x == 2)
|
||||||
|
print(f.get_entity("entity2").x == 12)
|
||||||
|
print(f.get_entity("entity3").x == 20) // this one has no updater, so it stays the same
|
||||||
|
)"";
|
||||||
|
|
||||||
|
|
||||||
|
chai.eval(script);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -23,7 +23,7 @@ int main( int /*argc*/ , char * /*argv*/[] )
|
|||||||
{
|
{
|
||||||
ch.eval( script );
|
ch.eval( script );
|
||||||
}
|
}
|
||||||
catch ( std::exception e )
|
catch ( const std::exception &e )
|
||||||
{
|
{
|
||||||
printf( " >>> Exception thrown: %s \n" , e.what( ) );
|
printf( " >>> Exception thrown: %s \n" , e.what( ) );
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,9 +13,9 @@ bool run_test_type_conversion(const Boxed_Value &bv, bool expectedpass)
|
|||||||
try {
|
try {
|
||||||
To ret = chaiscript::boxed_cast<To>(bv);
|
To ret = chaiscript::boxed_cast<To>(bv);
|
||||||
use(ret);
|
use(ret);
|
||||||
} catch (const chaiscript::exception::bad_boxed_cast &/*e*/) {
|
} catch (const chaiscript::exception::bad_boxed_cast &e) {
|
||||||
if (expectedpass) {
|
if (expectedpass) {
|
||||||
// std::cerr << "Failure in run_test_type_conversion: " << e.what() << '\n';
|
std::cerr << "Failure in run_test_type_conversion: " << e.what() << '\n';
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
// caught in other cpp files if chaiscript causes them
|
// caught in other cpp files if chaiscript causes them
|
||||||
|
|
||||||
#include <chaiscript/utility/utility.hpp>
|
#include <chaiscript/utility/utility.hpp>
|
||||||
|
#include <chaiscript/dispatchkit/bootstrap_stl.hpp>
|
||||||
|
|
||||||
#ifdef CHAISCRIPT_MSVC
|
#ifdef CHAISCRIPT_MSVC
|
||||||
#pragma warning(push)
|
#pragma warning(push)
|
||||||
@@ -518,6 +519,65 @@ TEST_CASE("Utility_Test utility class wrapper")
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
enum Utility_Test_Numbers
|
||||||
|
{
|
||||||
|
ONE,
|
||||||
|
TWO,
|
||||||
|
THREE
|
||||||
|
};
|
||||||
|
|
||||||
|
void do_something_with_enum_vector(const std::vector<Utility_Test_Numbers> &v)
|
||||||
|
{
|
||||||
|
CHECK(v.size() == 3);
|
||||||
|
CHECK(v[0] == ONE);
|
||||||
|
CHECK(v[1] == THREE);
|
||||||
|
CHECK(v[2] == TWO);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST_CASE("Utility_Test utility class wrapper for enum")
|
||||||
|
{
|
||||||
|
|
||||||
|
chaiscript::ModulePtr m = chaiscript::ModulePtr(new chaiscript::Module());
|
||||||
|
|
||||||
|
using namespace chaiscript;
|
||||||
|
|
||||||
|
chaiscript::utility::add_class<Utility_Test_Numbers>(*m,
|
||||||
|
"Utility_Test_Numbers",
|
||||||
|
{ { ONE, "ONE" },
|
||||||
|
{ TWO, "TWO" },
|
||||||
|
{ THREE, "THREE" }
|
||||||
|
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
chaiscript::ChaiScript chai;
|
||||||
|
chai.add(m);
|
||||||
|
|
||||||
|
CHECK(chai.eval<Utility_Test_Numbers>("ONE ") == 0);
|
||||||
|
CHECK(chai.eval<Utility_Test_Numbers>("TWO ") == 1);
|
||||||
|
CHECK(chai.eval<Utility_Test_Numbers>("THREE ") == 2);
|
||||||
|
|
||||||
|
CHECK(chai.eval<bool>("ONE == 0"));
|
||||||
|
|
||||||
|
chai.add(chaiscript::fun(&do_something_with_enum_vector), "do_something_with_enum_vector");
|
||||||
|
chai.add(chaiscript::vector_conversion<std::vector<Utility_Test_Numbers>>());
|
||||||
|
CHECK_NOTHROW(chai.eval("var a = [ONE, TWO, THREE]"));
|
||||||
|
CHECK_NOTHROW(chai.eval("do_something_with_enum_vector([ONE, THREE, TWO])"));
|
||||||
|
CHECK_NOTHROW(chai.eval("[ONE]"));
|
||||||
|
|
||||||
|
const auto v = chai.eval<std::vector<Utility_Test_Numbers>>("a");
|
||||||
|
CHECK(v.size() == 3);
|
||||||
|
CHECK(v.at(1) == TWO);
|
||||||
|
|
||||||
|
CHECK(chai.eval<bool>("ONE == ONE"));
|
||||||
|
CHECK(chai.eval<bool>("ONE != TWO"));
|
||||||
|
CHECK_NOTHROW(chai.eval("var o = ONE; o = TWO"));
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////// Object copy count test
|
////// Object copy count test
|
||||||
|
|
||||||
class Object_Copy_Count_Test
|
class Object_Copy_Count_Test
|
||||||
@@ -802,3 +862,54 @@ TEST_CASE("Test long long dispatch")
|
|||||||
chai.eval("ulonglong(15)");
|
chai.eval("ulonglong(15)");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
struct Returned_Converted_Config
|
||||||
|
{
|
||||||
|
int num_iterations;
|
||||||
|
int something_else;
|
||||||
|
std::string a_string;
|
||||||
|
std::function<int (const std::string &)> a_function;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
TEST_CASE("Return of converted type from script")
|
||||||
|
{
|
||||||
|
chaiscript::ChaiScript chai;
|
||||||
|
|
||||||
|
chai.add(chaiscript::constructor<Returned_Converted_Config ()>(), "Returned_Converted_Config");
|
||||||
|
chai.add(chaiscript::fun(&Returned_Converted_Config::num_iterations), "num_iterations");
|
||||||
|
chai.add(chaiscript::fun(&Returned_Converted_Config::something_else), "something_else");
|
||||||
|
chai.add(chaiscript::fun(&Returned_Converted_Config::a_string), "a_string");
|
||||||
|
chai.add(chaiscript::fun(&Returned_Converted_Config::a_function), "a_function");
|
||||||
|
chai.add(chaiscript::vector_conversion<std::vector<Returned_Converted_Config>>());
|
||||||
|
|
||||||
|
auto c = chai.eval<std::vector<Returned_Converted_Config>>(R"(
|
||||||
|
var c = Returned_Converted_Config();
|
||||||
|
|
||||||
|
c.num_iterations = 5;
|
||||||
|
c.something_else = c.num_iterations * 2;
|
||||||
|
c.a_string = "string";
|
||||||
|
c.a_function = fun(s) { s.size(); }
|
||||||
|
|
||||||
|
print("making vector");
|
||||||
|
var v = [];
|
||||||
|
print("adding config item");
|
||||||
|
v.push_back_ref(c);
|
||||||
|
print("returning vector");
|
||||||
|
v;
|
||||||
|
|
||||||
|
)");
|
||||||
|
|
||||||
|
|
||||||
|
std::cout << typeid(decltype(c)).name() << std::endl;
|
||||||
|
|
||||||
|
std::cout << "Info: " << c.size() << " " << &c[0] << std::endl;
|
||||||
|
|
||||||
|
std::cout << "num_iterations " << c[0].num_iterations << '\n'
|
||||||
|
<< "something_else " << c[0].something_else << '\n'
|
||||||
|
<< "a_string " << c[0].a_string << '\n'
|
||||||
|
<< "a_function " << c[0].a_function("bob") << '\n';
|
||||||
|
|
||||||
|
chai.add(chaiscript::user_type<Returned_Converted_Config>(), "Returned_Converted_Config");
|
||||||
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
|
|
||||||
assert_equal("\x39", "9")
|
assert_equal("\x39", "9")
|
||||||
assert_equal("\x039", "9")
|
assert_equal("\x39ec", "9ec")
|
||||||
assert_equal("\x39g", "9g")
|
assert_equal("\x39g", "9g")
|
||||||
assert_equal("b\x39g", "b9g")
|
assert_equal("b\x39g", "b9g")
|
||||||
|
assert_equal("\x39\x38g", "98g")
|
||||||
|
|
||||||
|
|||||||
@@ -3,4 +3,5 @@ assert_equal("\71", "9")
|
|||||||
assert_equal("\071", "9")
|
assert_equal("\071", "9")
|
||||||
assert_equal("\71a", "9a")
|
assert_equal("\71a", "9a")
|
||||||
assert_equal("b\71a", "b9a")
|
assert_equal("b\71a", "b9a")
|
||||||
|
assert_equal("\71\70a", "98a")
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user