Merge branch 'develop' of github.com:ChaiScript/ChaiScript into multithreaded_performance
Conflicts: include/chaiscript/language/chaiscript_eval.hpp
This commit is contained in:
@@ -80,6 +80,18 @@ It's not strictly necessary to add types, but it helps with many things. Cloning
|
||||
chai.add(chaiscript::user_type<MyClass>, "MyClass");
|
||||
```
|
||||
|
||||
## Adding Type Conversions
|
||||
|
||||
User defined type conversions are possible, defined in either script or in C++.
|
||||
|
||||
A helper function exists for strongly typed and ChaiScript `Vector` function conversion definition:
|
||||
|
||||
```
|
||||
chai.add(chaiscript::vector_conversion<std::vector<int>>());
|
||||
```
|
||||
|
||||
This allows you to pass a ChaiScript function to a function requiring `std::vector<int>`
|
||||
|
||||
## Adding Objects
|
||||
|
||||
```
|
||||
|
@@ -14,8 +14,10 @@
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#else
|
||||
#ifndef CHAISCRIPT_NO_THREADS_WARNING
|
||||
#pragma message ("ChaiScript is compiling without thread safety.")
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "chaiscript_defines.hpp"
|
||||
|
||||
@@ -153,6 +155,7 @@ namespace chaiscript
|
||||
|
||||
|
||||
private:
|
||||
/// \todo this leaks thread instances. It needs to be culled from time to time
|
||||
std::shared_ptr<T> get_tls() const
|
||||
{
|
||||
unique_lock<mutex> lock(m_mutex);
|
||||
|
@@ -36,7 +36,7 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
bad_boxed_cast(Type_Info t_from, const std::type_info &t_to)
|
||||
: from(std::move(t_from)), to(&t_to), m_what("Cannot perform boxed_cast")
|
||||
: from(std::move(t_from)), to(&t_to), m_what("Cannot perform boxed_cast: " + t_from.name() + " to: " + t_to.name())
|
||||
{
|
||||
}
|
||||
|
||||
|
@@ -319,7 +319,7 @@ namespace chaiscript
|
||||
/// Add back insertion sequence concept to the given ContainerType
|
||||
/// http://www.sgi.com/tech/stl/BackInsertionSequence.html
|
||||
template<typename ContainerType>
|
||||
ModulePtr back_insertion_sequence_type(const std::string &/*type*/, ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr back_insertion_sequence_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
typedef typename ContainerType::reference (ContainerType::*backptr)();
|
||||
|
||||
@@ -328,8 +328,16 @@ namespace chaiscript
|
||||
|
||||
typedef void (ContainerType::*push_back)(const typename ContainerType::value_type &);
|
||||
m->add(fun(static_cast<push_back>(&ContainerType::push_back)),
|
||||
[]()->std::string{
|
||||
[&]()->std::string{
|
||||
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) {
|
||||
m->eval(
|
||||
"# Pushes the second value onto the container while making a clone of the value\n"
|
||||
"def push_back(" + type + " container, x)\n"
|
||||
"{ \n"
|
||||
" container.push_back_ref(clone(x)) \n"
|
||||
"} \n"
|
||||
);
|
||||
|
||||
return "push_back_ref";
|
||||
} else {
|
||||
return "push_back";
|
||||
@@ -345,7 +353,7 @@ namespace chaiscript
|
||||
/// Front insertion sequence
|
||||
/// http://www.sgi.com/tech/stl/FrontInsertionSequence.html
|
||||
template<typename ContainerType>
|
||||
ModulePtr front_insertion_sequence_type(const std::string &, ModulePtr m = std::make_shared<Module>())
|
||||
ModulePtr front_insertion_sequence_type(const std::string &type, ModulePtr m = std::make_shared<Module>())
|
||||
{
|
||||
typedef typename ContainerType::reference (ContainerType::*front_ptr)();
|
||||
typedef typename ContainerType::const_reference (ContainerType::*const_front_ptr)() const;
|
||||
@@ -356,8 +364,15 @@ namespace chaiscript
|
||||
m->add(fun(static_cast<const_front_ptr>(&ContainerType::front)), "front");
|
||||
|
||||
m->add(fun(static_cast<push_ptr>(&ContainerType::push_front)),
|
||||
[]()->std::string{
|
||||
[&]()->std::string{
|
||||
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) {
|
||||
m->eval(
|
||||
"# Pushes the second value onto the front of container while making a clone of the value\n"
|
||||
"def push_front(" + type + " container, x)\n"
|
||||
"{ \n"
|
||||
" container.push_front_ref(clone(x)) \n"
|
||||
"} \n"
|
||||
);
|
||||
return "push_front_ref";
|
||||
} else {
|
||||
return "push_front";
|
||||
|
@@ -79,13 +79,6 @@ namespace chaiscript
|
||||
}
|
||||
|
||||
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
//Thank you MSVC, yes we know that a constant value is being used in the if
|
||||
// statment in THIS VERSION of the template instantiation
|
||||
#pragma warning(push)
|
||||
#pragma warning(disable : 4127)
|
||||
#endif
|
||||
|
||||
if (t_conversions && t_conversions->convertable_type<Type>())
|
||||
{
|
||||
try {
|
||||
@@ -108,10 +101,6 @@ namespace chaiscript
|
||||
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
|
||||
}
|
||||
|
||||
#ifdef CHAISCRIPT_MSVC
|
||||
#pragma warning(pop)
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -31,9 +31,9 @@ namespace chaiscript
|
||||
struct Function_Caller_Ret
|
||||
{
|
||||
static Ret call(const std::vector<Const_Proxy_Function> &t_funcs,
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions)
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions *t_conversions)
|
||||
{
|
||||
return boxed_cast<Ret>(dispatch::dispatch(t_funcs, params, t_conversions));
|
||||
return boxed_cast<Ret>(dispatch::dispatch(t_funcs, params, t_conversions?*t_conversions:Type_Conversions()), t_conversions);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -44,9 +44,9 @@ namespace chaiscript
|
||||
struct Function_Caller_Ret<Ret, true>
|
||||
{
|
||||
static Ret call(const std::vector<Const_Proxy_Function> &t_funcs,
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions)
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions *t_conversions)
|
||||
{
|
||||
return Boxed_Number(dispatch::dispatch(t_funcs, params, t_conversions)).get_as<Ret>();
|
||||
return Boxed_Number(dispatch::dispatch(t_funcs, params, t_conversions?*t_conversions:Type_Conversions())).get_as<Ret>();
|
||||
}
|
||||
};
|
||||
|
||||
@@ -58,9 +58,9 @@ namespace chaiscript
|
||||
struct Function_Caller_Ret<void, false>
|
||||
{
|
||||
static void call(const std::vector<Const_Proxy_Function> &t_funcs,
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions &t_conversions)
|
||||
const std::vector<Boxed_Value> ¶ms, const Type_Conversions *t_conversions)
|
||||
{
|
||||
dispatch::dispatch(t_funcs, params, t_conversions);
|
||||
dispatch::dispatch(t_funcs, params, t_conversions?*t_conversions:Type_Conversions());
|
||||
}
|
||||
};
|
||||
|
||||
@@ -70,28 +70,49 @@ namespace chaiscript
|
||||
template<typename Ret, typename ... Param>
|
||||
struct Build_Function_Caller_Helper
|
||||
{
|
||||
Build_Function_Caller_Helper(std::vector<Const_Proxy_Function> t_funcs, const Type_Conversions &t_conversions)
|
||||
Build_Function_Caller_Helper(std::vector<Const_Proxy_Function> t_funcs, const Type_Conversions *t_conversions)
|
||||
: m_funcs(std::move(t_funcs)),
|
||||
m_conversions(t_conversions)
|
||||
{
|
||||
}
|
||||
|
||||
Ret operator()(Param...param)
|
||||
template<typename ... P>
|
||||
Ret operator()(P&& ... param)
|
||||
{
|
||||
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)...
|
||||
box<P>(std::forward<P>(param))...
|
||||
}, m_conversions
|
||||
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
template<typename P, typename Q>
|
||||
static auto box(Q&& q) -> typename std::enable_if<std::is_reference<P>::value&&!std::is_same<chaiscript::Boxed_Value, typename std::remove_const<typename std::remove_reference<P>::type>::type>::value, Boxed_Value>::type
|
||||
{
|
||||
return Boxed_Value(std::ref(std::forward<Q>(q)));
|
||||
}
|
||||
|
||||
template<typename P, typename Q>
|
||||
static auto box(Q&& q) -> typename std::enable_if<!std::is_reference<P>::value&&!std::is_same<chaiscript::Boxed_Value, typename std::remove_const<typename std::remove_reference<P>::type>::type>::value, Boxed_Value>::type
|
||||
{
|
||||
return Boxed_Value(std::forward<Q>(q));
|
||||
}
|
||||
|
||||
template<typename P>
|
||||
static Boxed_Value box(Boxed_Value bv)
|
||||
{
|
||||
return bv;
|
||||
}
|
||||
|
||||
|
||||
std::vector<Const_Proxy_Function> m_funcs;
|
||||
Type_Conversions m_conversions;
|
||||
const Type_Conversions *m_conversions;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// \todo what happens if t_conversions is deleted out from under us?!
|
||||
template<typename Ret, typename ... Params>
|
||||
std::function<Ret (Params...)> build_function_caller_helper(Ret (Params...), const std::vector<Const_Proxy_Function> &funcs, const Type_Conversions *t_conversions)
|
||||
{
|
||||
@@ -111,7 +132,7 @@ namespace chaiscript
|
||||
}
|
||||
*/
|
||||
|
||||
return std::function<Ret (Params...)>(Build_Function_Caller_Helper<Ret, Params...>(funcs, t_conversions?*t_conversions:Type_Conversions()));
|
||||
return std::function<Ret (Params...)>(Build_Function_Caller_Helper<Ret, Params...>(funcs, t_conversions));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -337,7 +337,7 @@ namespace chaiscript
|
||||
Type_Conversions(const Type_Conversions &t_other)
|
||||
: m_mutex(),
|
||||
m_conversions(t_other.get_conversions()),
|
||||
m_convertableTypes(),
|
||||
m_convertableTypes(t_other.m_convertableTypes),
|
||||
m_num_types(m_conversions.size()),
|
||||
m_thread_cache(this),
|
||||
m_conversion_saves(this)
|
||||
@@ -575,6 +575,24 @@ namespace chaiscript
|
||||
return chaiscript::make_shared<detail::Type_Conversion_Base, detail::Type_Conversion_Impl<decltype(func)>>(user_type<From>(), user_type<To>(), func);
|
||||
}
|
||||
|
||||
template<typename To>
|
||||
Type_Conversion vector_conversion()
|
||||
{
|
||||
auto func = [](const Boxed_Value &t_bv) -> Boxed_Value {
|
||||
const std::vector<Boxed_Value> &from_vec = detail::Cast_Helper<const std::vector<Boxed_Value> &>::cast(t_bv, nullptr);
|
||||
|
||||
To vec;
|
||||
|
||||
for (const Boxed_Value &bv : from_vec) {
|
||||
vec.push_back(detail::Cast_Helper<typename To::value_type>::cast(bv, nullptr));
|
||||
}
|
||||
|
||||
return Boxed_Value(std::move(vec));
|
||||
};
|
||||
|
||||
return chaiscript::make_shared<detail::Type_Conversion_Base, detail::Type_Conversion_Impl<decltype(func)>>(user_type<std::vector<Boxed_Value>>(), user_type<To>(), func);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@@ -136,9 +136,11 @@ namespace chaiscript
|
||||
|
||||
static Type_Info get()
|
||||
{
|
||||
return Type_Info(std::is_const<typename std::remove_pointer<typename std::remove_reference<T>::type>::type>::value, std::is_reference<T>::value, std::is_pointer<T>::value,
|
||||
return Type_Info(std::is_const<typename std::remove_pointer<typename std::remove_reference<T>::type>::type>::value,
|
||||
std::is_reference<T>::value, std::is_pointer<T>::value,
|
||||
std::is_void<T>::value,
|
||||
std::is_arithmetic<T>::value && !std::is_same<typename std::remove_const<T>::type, bool>::value,
|
||||
(std::is_arithmetic<T>::value || std::is_arithmetic<typename std::remove_reference<T>::type>::value)
|
||||
&& !std::is_same<typename std::remove_const<T>::type, bool>::value,
|
||||
&typeid(T),
|
||||
&typeid(typename Bare_Type<T>::type));
|
||||
}
|
||||
|
@@ -1050,7 +1050,12 @@ namespace chaiscript
|
||||
std::vector<Boxed_Value> vec;
|
||||
if (!children.empty()) {
|
||||
for (const auto &child : children[0]->children) {
|
||||
vec.push_back(t_ss->call_function("clone", child->eval(t_ss)));
|
||||
auto obj = child->eval(t_ss);
|
||||
if (!obj.is_return_value()) {
|
||||
vec.push_back(t_ss->call_function("clone", obj));
|
||||
} else {
|
||||
vec.push_back(std::move(obj));
|
||||
}
|
||||
}
|
||||
}
|
||||
return const_var(std::move(vec));
|
||||
@@ -1076,8 +1081,12 @@ namespace chaiscript
|
||||
std::map<std::string, Boxed_Value> retval;
|
||||
|
||||
for (const auto &child : children[0]->children) {
|
||||
Boxed_Value bv = t_ss->call_function("clone", child->children[1]->eval(t_ss));
|
||||
retval[t_ss->boxed_cast<std::string>(child->children[0]->eval(t_ss))] = std::move(bv);
|
||||
auto obj = child->children[1]->eval(t_ss);
|
||||
if (!obj.is_return_value()) {
|
||||
obj = t_ss->call_function("clone", obj);
|
||||
}
|
||||
|
||||
retval[t_ss->boxed_cast<std::string>(child->children[0]->eval(t_ss))] = std::move(obj);
|
||||
}
|
||||
|
||||
return const_var(std::move(retval));
|
||||
|
@@ -127,18 +127,6 @@ def even(x)
|
||||
}
|
||||
|
||||
|
||||
# Pushes the second value onto the container first value while making a clone of the value
|
||||
def push_back(container, x) : call_exists(push_back_ref, container, x)
|
||||
{
|
||||
container.push_back_ref(clone(x))
|
||||
}
|
||||
|
||||
# Pushes the second value onto the front of the container first value while making a clone of the value
|
||||
def push_front(container, x) : call_exists(push_front_ref, container, x)
|
||||
{
|
||||
container.push_front_ref(clone(x))
|
||||
}
|
||||
|
||||
# Inserts the third value at the position of the second value into the container of the first
|
||||
# while making a clone.
|
||||
def insert_at(container, pos, x)
|
||||
|
@@ -23,7 +23,11 @@
|
||||
|
||||
CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_stl_extra()
|
||||
{
|
||||
return chaiscript::bootstrap::standard_library::list_type<std::list<chaiscript::Boxed_Value> >("List");
|
||||
|
||||
auto module = chaiscript::bootstrap::standard_library::list_type<std::list<chaiscript::Boxed_Value> >("List");
|
||||
module->add(chaiscript::bootstrap::standard_library::vector_type<std::vector<uint16_t> >("u16vector"));
|
||||
module->add(chaiscript::vector_conversion<std::vector<uint16_t>>());
|
||||
return module;
|
||||
}
|
||||
|
||||
#ifdef __llvm__
|
||||
|
@@ -34,6 +34,11 @@ class TestBaseType
|
||||
int mdarray[2][3][5];
|
||||
std::function<int (int)> func_member;
|
||||
|
||||
void set_string_val(std::string &t_str)
|
||||
{
|
||||
t_str = "42";
|
||||
}
|
||||
|
||||
private:
|
||||
TestBaseType &operator=(const TestBaseType &) = delete;
|
||||
};
|
||||
@@ -52,6 +57,7 @@ class Type2
|
||||
return m_bt.val;
|
||||
}
|
||||
|
||||
|
||||
const char *get_str() const
|
||||
{
|
||||
return m_str.c_str();
|
||||
@@ -171,6 +177,7 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo
|
||||
m->add(chaiscript::fun(&TestBaseType::val), "val");
|
||||
m->add(chaiscript::fun(&TestBaseType::const_val), "const_val");
|
||||
m->add(chaiscript::fun(&TestBaseType::base_only_func), "base_only_func");
|
||||
m->add(chaiscript::fun(&TestBaseType::set_string_val), "set_string_val");
|
||||
|
||||
#ifndef CHAISCRIPT_MSVC_12
|
||||
// we cannot support these in MSVC_12 because of a bug in the implementation of
|
||||
|
8
unittests/non_const_param.chai
Normal file
8
unittests/non_const_param.chai
Normal file
@@ -0,0 +1,8 @@
|
||||
load_module("test_module")
|
||||
|
||||
var t2 = TestBaseType();
|
||||
|
||||
var s = "5";
|
||||
t2.set_string_val(s);
|
||||
assert_equal(s, "42")
|
||||
|
@@ -3,3 +3,11 @@ x.push_back(3)
|
||||
assert_equal(3, x.size())
|
||||
assert_equal(3, x.back())
|
||||
assert_equal(1, x.front())
|
||||
|
||||
|
||||
load_module("stl_extra")
|
||||
|
||||
auto uint16v = u16vector();
|
||||
uint16v.push_back(1u);
|
||||
assert_equal(1, uint16v.front());
|
||||
|
||||
|
Reference in New Issue
Block a user