8000 Merge branch 'develop' into Workaround_Thread_Local_MinGW · ChaiScript/ChaiScript@5852412 · GitHub
[go: up one dir, main page]

Skip to content

Commit 5852412

Browse files
committed
Merge branch 'develop' into Workaround_Thread_Local_MinGW
2 parents 21c3853 + 452f71b commit 5852412

File tree

9 files changed

+219
-44
lines changed

9 files changed

+219
-44
lines changed

cheatsheet.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ chai.add(chaiscript::constructor<MyType (const MyType &)>(), "MyType");
7777
It's not strictly necessary to add types, but it helps with many things. Cloning, better errors, etc.
7878

7979
```
80-
chai.add(chaiscript::user_type<MyClass>, "MyClass");
80+
chai.add(chaiscript::user_type<MyClass>(), "MyClass");
8181
```
8282

8383
## Adding Type Conversions
@@ -365,6 +365,7 @@ class My_Class {
365365
this.x = 2; // this would fail with explicit set to true
366366
}
367367
};
368+
```
368369

369370
## method_missing
370371

include/chaiscript/dispatchkit/boxed_cast_helper.hpp

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -33,14 +33,14 @@ namespace chaiscript
3333
template<typename Result>
3434
struct Cast_Helper_Inner
3535
{
36-
typedef std::reference_wrapper<typename std::add_const<Result>::type > Result_Type;
36+
typedef typename std::add_const<Result>::type Result_Type;
3737

3838
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
3939
{
4040
if (ob.get_type_info().bare_equal_type_info(typeid(Result)))
4141
{
4242
auto p = throw_if_null(ob.get_const_ptr());
43-
return std::cref(*static_cast<const Result *>(p));
43+
return *static_cast<const Result *>(p);
4444
} else {
4545
throw chaiscript::detail::exception::bad_any_cast();
4646
}
@@ -52,12 +52,6 @@ namespace chaiscript
5252
{
5353
};
5454

55-
/// Cast_Helper_Inner for casting to a const & type
56-
template<typename Result>
57-
struct Cast_Helper_Inner<const Result &> : Cast_Helper_Inner<Result>
58-
{
59-
};
60-
6155

6256
/// Cast_Helper_Inner for casting to a const * type
6357
template<typename Result>
@@ -68,7 +62,7 @@ namespace chaiscript
6862
{
6963
if (ob.get_type_info().bare_equal_type_info(typeid(Result)))
7064
{
71-
return static_cast<const Result *>(throw_if_null(ob.get_const_ptr()));
65+
return static_cast<const Result *>(ob.get_const_ptr());
7266
} else {
7367
throw chaiscript::detail::exception::bad_any_cast();
7468
}
@@ -84,7 +78,36 @@ namespace chaiscript
8478
{
8579
if (!ob.get_type_info().is_const() && ob.get_type_info() == typeid(Result))
8680
{
87-
return static_cast<Result *>(throw_if_null(ob.get_ptr()));
81+
return static_cast<Result *>(ob.get_ptr());
82+
} else {
83+
throw chaiscript::detail::exception::bad_any_cast();
84+
}
85+
}
86+
};
87+
88+
template<typename Result>
89+
struct Cast_Helper_Inner<Result * const &> : public Cast_Helper_Inner<Result *>
90+
{
91+
};
92+
93+
template<typename Result>
94+
struct Cast_Helper_Inner<const Result * const &> : public Cast_Helper_Inner<const Result *>
95+
{
96+
};
97+
98+
99+
/// Cast_Helper_Inner for casting to a & type
100+
template<typename Result>
101+
struct Cast_Helper_Inner<const Result &>
102+
{
103+
typedef const Result& Result_Type;
104+
105+
static Result_Type cast(const Boxed_Value &ob, const Type_Conversions *)
106+
{
107+
if (ob.get_type_info().bare_equal_type_info(typeid(Result)))
108+
{
109+
auto p = throw_if_null(ob.get_const_ptr());
110+
return *static_cast<const Result *>(p);
88111
} else {
89112
throw chaiscript::detail::exception::bad_any_cast();
90113
}

include/chaiscript/language/chaiscript_parser.hpp

Lines changed: 35 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -961,6 +961,40 @@ namespace chaiscript
961961
}
962962

963963
void parse(const char_type t_char, const int line, const int col, const std::string &filename) {
964+
const bool is_octal_char = t_char >= '0' && t_char <= '7';
965+
966+
if (is_octal) {
967+
if (is_octal_char) {
968+
octal_matches.push_back(t_char);
969+
970+
if (octal_matches.size() == 3) {
971+
process_octal();
972+
}
973+
return;
974+
} else {
975+
process_octal();
976+
}
977+
} else if (is_hex) {
978+
const bool is_hex_char = (t_char >= '0' && t_char <= '9')
979+
|| (t_char >= 'a' && t_char <= 'f')
980+
|| (t_char >= 'A' && t_char <= 'F');
981+
982+
if (is_hex_char) {
983+
hex_matches.push_back(t_char);
984+
985+
if (hex_matches.size() == 2*sizeof(char_type)) {
986+
// This rule differs from the C/C++ standard, but ChaiScript
987+
// does not offer the same workaround options, and having
988+
// hexadecimal sequences longer than can fit into the char
989+
// type is undefined behavior anyway.
990+
process_hex();
991+
}
992+
return;
993+
} else {
994+
process_hex();
995+
}
996+
}
997+
964998
if (t_char == '\\') {
965999
if (is_escaped) {
9661000
match.push_back('\\');
@@ -970,31 +1004,7 @@ namespace chaiscript
9701004
}
9711005
} else {
9721006
if (is_escaped) {
973-
const bool is_octal_char = t_char >= '0' && t_char <= '7';
974-
975-
if (is_octal) {
976-
if (is_octal_char) {
977-
octal_matches.push_back(t_char);
978-
979-
if (octal_matches.size() == 3) {
980-
process_octal();
981-
}
982-
} else {
983-
process_octal();
984-
match.push_back(t_char);
985-
}
986-
} else if (is_hex) {
987-
const bool is_hex_char = (t_char >= '0' && t_char <= '9')
988-
|| (t_char >= 'a' && t_char <= 'f')
989-
|| (t_char >= 'A' && t_char <= 'F');
990-
991-
if (is_hex_char) {
992-
hex_matches.push_back(t_char);
993-
} else {
994-
process_hex();
995-
match.push_back(t_char);
996-
}
997-
} else if (is_octal_char) {
1007+
if (is_octal_char) {
9981008
is_octal = true;
9991009
octal_matches.push_back(t_char);
10001010
} else if (t_char == 'x') {

include/chaiscript/utility/json.hpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -421,22 +421,22 @@ class JSON
421421
Class Type;
422422
};
423423

424-
JSON Array() {
424+
inline JSON Array() {
425425
return JSON::Make( JSON::Class::Array );
426426
}
427427

428428
template <typename... T>
429-
JSON Array( T... args ) {
429+
inline JSON Array( T... args ) {
430430
JSON arr = JSON::Make( JSON::Class::Array );
431431
arr.append( args... );
432432
return arr;
433433
}
434434

435-
JSON Object() {
435+
inline JSON Object() {
436436
return JSON::Make( JSON::Class::Object );
437437
}
438438

439-
std::ostream& operator<<( std::ostream &os, const JSON &json ) {
439+
inline std::ostream& operator<<( std::ostream &os, const JSON &json ) {
440440
os << json.dump();
441441
return os;
442442
}
@@ -636,7 +636,7 @@ namespace {
636636
}
637637
}
638638

639-
JSON JSON::Load( const string &str ) {
639+
inline JSON JSON::Load( const string &str ) {
640640
size_t offset = 0;
641641
return parse_next( str, offset );
642642
}

include/chaiscript/utility/utility.hpp

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,14 @@
88
#define CHAISCRIPT_UTILITY_UTILITY_HPP_
99

1010
#include <string>
11+
#include <type_traits>
1112
#include <utility>
1213
#include <vector>
1314

1415
#include "../chaiscript.hpp"
1516
#include "../dispatchkit/proxy_functions.hpp"
1617
#include "../dispatchkit/type_info.hpp"
18+
#include "../dispatchkit/operators.hpp"
1719

1820

1921
namespace chaiscript
@@ -62,6 +64,32 @@ namespace chaiscript
6264
t_module.add(fun.first, fun.second);
6365
}
6466
}
67+
68+
template<typename Enum, typename ModuleType>
69+
typename std::enable_if<std::is_enum<Enum>::value, void>::type
70+
add_class(ModuleType &t_module,
71+
const std::string &t_class_name,
72+
const std::vector<std::pair<typename std::underlying_type<Enum>::type, std::string>> &t_constants)
73+
{
74+
t_module.add(chaiscript::user_type<Enum>(), t_class_name);
75+
76+
t_module.add(chaiscript::constructor<Enum ()>(), t_class_name);
77+
t_module.add(chaiscript::constructor<Enum (const Enum &)>(), t_class_name);
78+
79+
t_module.add([](){
80+
// add some comparison and assignment operators
81+
using namespace chaiscript::bootstrap::operators;
82+
return assign<Enum>(not_equal<Enum>(equal<Enum>()));
83+
}());
84+
85+
t_module.add(chaiscript::fun([](const Enum &e, const typename std::underlying_type<Enum>::type &i) { return e == i; }), "==");
86+
t_module.add(chaiscript::fun([](const typename std::underlying_type<Enum>::type &i, const Enum &e) { return i == e; }), "==");
87+
88+
for (const auto &constant : t_constants)
89+
{
90+
t_module.add_global_const(chaiscript::const_var(Enum(constant.first)), constant.second);
91+
}
92+
}
6593
}
6694
}
6795

unittests/boxed_cast_test.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@ bool run_test_type_conversion(const Boxed_Value &bv, bool expectedpass)
1313
try {
1414
To ret = chaiscript::boxed_cast<To>(bv);
1515
use(ret);
16-
} catch (const chaiscript::exception::bad_boxed_cast &/*e*/) {
16+
} catch (const chaiscript::exception::bad_boxed_cast &e) {
1717
if (expectedpass) {
18-
// std::cerr << "Failure in run_test_type_conversion: " << e.what() << '\n';
18+
std::cerr << "Failure in run_test_type_conversion: " << e.what() << '\n';
1919
return false;
2020
} else {
2121
return true;

unittests/compiled_tests.cpp

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// caught in other cpp files if chaiscript causes them
33

44
#include <chaiscript/utility/utility.hpp>
5+
#include <chaiscript/dispatchkit/bootstrap_stl.hpp>
56

67
#ifdef CHAISCRIPT_MSVC
78
#pragma warning(push)
@@ -518,6 +519,65 @@ TEST_CASE("Utility_Test utility class wrapper")
518519
}
519520

520521

522+
enum Utility_Test_Numbers
523+
{
524+
ONE,
525+
TWO,
526+
THREE
527+
};
528+
529+
void do_something_with_enum_vector(const std::vector<Utility_Test_Numbers> &v)
530+
{
531+
CHECK(v.size() == 3);
532+
CHECK(v[0] == ONE);
533+
CHECK(v[1] == THREE);
534+
CHECK(v[2] == TWO);
535+
}
536+
537+
TEST_CASE("Utility_Test utility class wrapper for enum")
538+
{
539+
540+
chaiscript::ModulePtr m = chaiscript::ModulePtr(new chaiscript::Module());
541+
542+
using namespace chaiscript;
543+
544+
chaiscript::utility::add_class<Utility_Test_Numbers>(*m,
545+
"Utility_Test_Numbers",
546+
{ { ONE, "ONE" },
547+
{ TWO, "TWO" },
548+
{ THREE, "THREE" }
549+
550+
}
551+
);
552+
553+
554+
chaiscript::ChaiScript chai;
555+
chai.add(m);
556+
557+
CHECK(chai.eval<Utility_Test_Numbers>("ONE ") == 0);
558+
CHECK(chai.eval<Utility_Test_Numbers>("TWO ") == 1);
559+
CHECK(chai.eval<Utility_Test_Numbers>("THREE ") == 2);
560+
561+
CHECK(chai.eval<bool>("ONE == 0"));
562+
563+
chai.add(chaiscript::fun(&do_something_with_enum_vector), "do_something_with_enum_vector");
564+
chai.add(chaiscript::vector_conversion<std::vector<Utility_Test_Numbers>>());
565+
CHECK_NOTHROW(chai.eval("var a = [ONE, TWO, THREE]"));
566+
CHECK_NOTHROW(chai.eval("do_something_with_enum_vector([ONE, THREE, TWO])"));
567+
CHECK_NOTHROW(chai.eval("[ONE]"));
568+
569+
const auto v = chai.eval<std::vector<Utility_Test_Numbers>>("a");
570+
CHECK(v.size() == 3);
571+
CHECK(v.at(1) == TWO);
572+
573+
CHECK(chai.eval<bool>("ONE == ONE"));
574+
CHECK(chai.eval<bool>("ONE != TWO"));
575+
CHECK_NOTHROW(chai.eval("var o = ONE; o = TWO"));
576+
577+
578+
}
579+
580+
521581
////// Object copy count test
522582

523583
class Object_Copy_Count_Test
@@ -802,3 +862,54 @@ TEST_CASE("Test long long dispatch")
802862
chai.eval("ulonglong(15)");
803863
}
804864

865+
866+
struct Returned_Converted_Config
867+
{
868+
int num_iterations;
869+
int something_else;
870+
std::string a_string;
871+
std::function<int (const std::string &)> a_function;
872+
};
873+
874+
875+
TEST_CASE("Return of converted type from script")
876+
{
877+
chaiscript::ChaiScript chai;
878+
879+
chai.add(chaiscript::constructor<Returned_Converted_Config ()>(), "Returned_Converted_Config");
880+
chai.add(chaiscript::fun(&Returned_Converted_Config::num_iterations), "num_iterations");
881+
chai.add(chaiscript::fun(&Returned_Converted_Config::something_else), "something_else");
882+
chai.add(chaiscript::fun(&Returned_Converted_Config::a_string), "a_string");
883+
chai.add(chaiscript::fun(&Returned_Converted_Config::a_function), "a_function");
884+
chai.add(chaiscript::vector_conversion<std::vector<Returned_Converted_Config>>());
885+
886+
auto c = chai.eval<std::vector<Returned_Converted_Config>>(R"(
887+
var c = Returned_Converted_Config();
888+
889+
c.num_iterations = 5;
890+
c.something_else = c.num_iterations * 2;
891+
c.a_string = "string";
892+
c.a_function = fun(s) { s.size(); }
893+
894+
print("making vector");
895+
var v = [];
896+
print("adding config item");
897+
v.push_back_ref(c);
898+
print("returning vector");
899+
v;
900+
901+
)");
902+
903+
904+
std::cout << typeid(decltype(c)).name() << std::endl;
905+
906+
std::cout << "Info: " << c.size() << " " << &c[0] << std::endl;
907+
908+
std::cout << "num_iterations " << c[0].num_iterations << '\n'
909+
<< "something_else " << c[0].something_else << '\n'
910+
<< "a_string " << c[0].a_string << '\n'
911+
<< "a_function " << c[0].a_function("bob") << '\n';
912+
913+
chai.add(chaiscript::user_type<Returned_Converted_Config>(), "Returned_Converted_Config");
914+
}
915+

0 commit comments

Comments
 (0)
0