Merge branch 'develop' of github.com:ChaiScript/ChaiScript into multithreaded_performance

Conflicts:
	include/chaiscript/language/chaiscript_eval.hpp
This commit is contained in:
Jason Turner
2015-07-16 13:16:04 -06:00
14 changed files with 131 additions and 47 deletions

View File

@@ -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"); 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 ## Adding Objects
``` ```

View File

@@ -14,8 +14,10 @@
#include <thread> #include <thread>
#include <mutex> #include <mutex>
#else #else
#ifndef CHAISCRIPT_NO_THREADS_WARNING
#pragma message ("ChaiScript is compiling without thread safety.") #pragma message ("ChaiScript is compiling without thread safety.")
#endif #endif
#endif
#include "chaiscript_defines.hpp" #include "chaiscript_defines.hpp"
@@ -153,6 +155,7 @@ namespace chaiscript
private: private:
/// \todo this leaks thread instances. It needs to be culled from time to time
std::shared_ptr<T> get_tls() const std::shared_ptr<T> get_tls() const
{ {
unique_lock<mutex> lock(m_mutex); unique_lock<mutex> lock(m_mutex);

View File

@@ -36,7 +36,7 @@ namespace chaiscript
} }
bad_boxed_cast(Type_Info t_from, const std::type_info &t_to) 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())
{ {
} }

View File

@@ -319,7 +319,7 @@ namespace chaiscript
/// Add back insertion sequence concept to the given ContainerType /// Add back insertion sequence concept to the given ContainerType
/// http://www.sgi.com/tech/stl/BackInsertionSequence.html /// http://www.sgi.com/tech/stl/BackInsertionSequence.html
template<typename ContainerType> 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)(); typedef typename ContainerType::reference (ContainerType::*backptr)();
@@ -328,8 +328,16 @@ namespace chaiscript
typedef void (ContainerType::*push_back)(const typename ContainerType::value_type &); typedef void (ContainerType::*push_back)(const typename ContainerType::value_type &);
m->add(fun(static_cast<push_back>(&ContainerType::push_back)), m->add(fun(static_cast<push_back>(&ContainerType::push_back)),
[]()->std::string{ [&]()->std::string{
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) { 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"; return "push_back_ref";
} else { } else {
return "push_back"; return "push_back";
@@ -345,7 +353,7 @@ namespace chaiscript
/// Front insertion sequence /// Front insertion sequence
/// http://www.sgi.com/tech/stl/FrontInsertionSequence.html /// http://www.sgi.com/tech/stl/FrontInsertionSequence.html
template<typename ContainerType> 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::reference (ContainerType::*front_ptr)();
typedef typename ContainerType::const_reference (ContainerType::*const_front_ptr)() const; 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<const_front_ptr>(&ContainerType::front)), "front");
m->add(fun(static_cast<push_ptr>(&ContainerType::push_front)), m->add(fun(static_cast<push_ptr>(&ContainerType::push_front)),
[]()->std::string{ [&]()->std::string{
if (typeid(typename ContainerType::value_type) == typeid(Boxed_Value)) { 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"; return "push_front_ref";
} else { } else {
return "push_front"; return "push_front";

View File

@@ -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>()) if (t_conversions && t_conversions->convertable_type<Type>())
{ {
try { try {
@@ -108,10 +101,6 @@ namespace chaiscript
throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type)); throw exception::bad_boxed_cast(bv.get_type_info(), typeid(Type));
} }
#ifdef CHAISCRIPT_MSVC
#pragma warning(pop)
#endif
} }
} }

View File

@@ -31,9 +31,9 @@ namespace chaiscript
struct Function_Caller_Ret struct Function_Caller_Ret
{ {
static Ret call(const std::vector<Const_Proxy_Function> &t_funcs, static Ret call(const std::vector<Const_Proxy_Function> &t_funcs,
const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions) const std::vector<Boxed_Value> &params, 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> struct Function_Caller_Ret<Ret, true>
{ {
static Ret call(const std::vector<Const_Proxy_Function> &t_funcs, static Ret call(const std::vector<Const_Proxy_Function> &t_funcs,
const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions) const std::vector<Boxed_Value> &params, 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> struct Function_Caller_Ret<void, false>
{ {
static void call(const std::vector<Const_Proxy_Function> &t_funcs, static void call(const std::vector<Const_Proxy_Function> &t_funcs,
const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions) const std::vector<Boxed_Value> &params, 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> template<typename Ret, typename ... Param>
struct Build_Function_Caller_Helper 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_funcs(std::move(t_funcs)),
m_conversions(t_conversions) 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, { 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 }, 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; 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> 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) 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));
} }
} }
} }

View File

@@ -337,7 +337,7 @@ namespace chaiscript
Type_Conversions(const Type_Conversions &t_other) Type_Conversions(const Type_Conversions &t_other)
: m_mutex(), : m_mutex(),
m_conversions(t_other.get_conversions()), m_conversions(t_other.get_conversions()),
m_convertableTypes(), m_convertableTypes(t_other.m_convertableTypes),
m_num_types(m_conversions.size()), m_num_types(m_conversions.size()),
m_thread_cache(this), m_thread_cache(this),
m_conversion_saves(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); 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);
}
} }

View File

@@ -136,9 +136,11 @@ namespace chaiscript
static Type_Info get() 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_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(T),
&typeid(typename Bare_Type<T>::type)); &typeid(typename Bare_Type<T>::type));
} }

View File

@@ -1050,7 +1050,12 @@ namespace chaiscript
std::vector<Boxed_Value> vec; std::vector<Boxed_Value> vec;
if (!children.empty()) { if (!children.empty()) {
for (const auto &child : children[0]->children) { 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)); return const_var(std::move(vec));
@@ -1076,8 +1081,12 @@ namespace chaiscript
std::map<std::string, Boxed_Value> retval; std::map<std::string, Boxed_Value> retval;
for (const auto &child : children[0]->children) { for (const auto &child : children[0]->children) {
Boxed_Value bv = t_ss->call_function("clone", child->children[1]->eval(t_ss)); auto obj = child->children[1]->eval(t_ss);
retval[t_ss->boxed_cast<std::string>(child->children[0]->eval(t_ss))] = std::move(bv); 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)); return const_var(std::move(retval));

View File

@@ -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 # Inserts the third value at the position of the second value into the container of the first
# while making a clone. # while making a clone.
def insert_at(container, pos, x) def insert_at(container, pos, x)

View File

@@ -23,7 +23,11 @@
CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_stl_extra() 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__ #ifdef __llvm__

View File

@@ -34,6 +34,11 @@ class TestBaseType
int mdarray[2][3][5]; int mdarray[2][3][5];
std::function<int (int)> func_member; std::function<int (int)> func_member;
void set_string_val(std::string &t_str)
{
t_str = "42";
}
private: private:
TestBaseType &operator=(const TestBaseType &) = delete; TestBaseType &operator=(const TestBaseType &) = delete;
}; };
@@ -52,6 +57,7 @@ class Type2
return m_bt.val; return m_bt.val;
} }
const char *get_str() const const char *get_str() const
{ {
return m_str.c_str(); 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::val), "val");
m->add(chaiscript::fun(&TestBaseType::const_val), "const_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::base_only_func), "base_only_func");
m->add(chaiscript::fun(&TestBaseType::set_string_val), "set_string_val");
#ifndef CHAISCRIPT_MSVC_12 #ifndef CHAISCRIPT_MSVC_12
// we cannot support these in MSVC_12 because of a bug in the implementation of // we cannot support these in MSVC_12 because of a bug in the implementation of

View File

@@ -0,0 +1,8 @@
load_module("test_module")
var t2 = TestBaseType();
var s = "5";
t2.set_string_val(s);
assert_equal(s, "42")

View File

@@ -3,3 +3,11 @@ x.push_back(3)
assert_equal(3, x.size()) assert_equal(3, x.size())
assert_equal(3, x.back()) assert_equal(3, x.back())
assert_equal(1, x.front()) assert_equal(1, x.front())
load_module("stl_extra")
auto uint16v = u16vector();
uint16v.push_back(1u);
assert_equal(1, uint16v.front());