Merge branch 'develop' into typed_function_ordering

This commit is contained in:
Jason Turner 2016-03-15 12:46:47 -06:00
commit 82a69ca043
18 changed files with 196 additions and 150 deletions

View File

@ -213,7 +213,7 @@ endif()
include_directories(include) include_directories(include)
set(Chai_INCLUDES include/chaiscript/chaiscript.hpp include/chaiscript/chaiscript_threading.hpp include/chaiscript/dispatchkit/bad_boxed_cast.hpp include/chaiscript/dispatchkit/bind_first.hpp include/chaiscript/dispatchkit/bootstrap.hpp include/chaiscript/dispatchkit/bootstrap_stl.hpp include/chaiscript/dispatchkit/boxed_cast.hpp include/chaiscript/dispatchkit/boxed_cast_helper.hpp include/chaiscript/dispatchkit/boxed_number.hpp include/chaiscript/dispatchkit/boxed_value.hpp include/chaiscript/dispatchkit/dispatchkit.hpp include/chaiscript/dispatchkit/type_conversions.hpp include/chaiscript/dispatchkit/dynamic_object.hpp include/chaiscript/dispatchkit/exception_specification.hpp include/chaiscript/dispatchkit/function_call.hpp include/chaiscript/dispatchkit/function_call_detail.hpp include/chaiscript/dispatchkit/handle_return.hpp include/chaiscript/dispatchkit/operators.hpp include/chaiscript/dispatchkit/proxy_constructors.hpp include/chaiscript/dispatchkit/proxy_functions.hpp include/chaiscript/dispatchkit/proxy_functions_detail.hpp include/chaiscript/dispatchkit/register_function.hpp include/chaiscript/dispatchkit/type_info.hpp include/chaiscript/language/chaiscript_algebraic.hpp include/chaiscript/language/chaiscript_common.hpp include/chaiscript/language/chaiscript_engine.hpp include/chaiscript/language/chaiscript_eval.hpp include/chaiscript/language/chaiscript_parser.hpp include/chaiscript/language/chaiscript_prelude.chai include/chaiscript/language/chaiscript_prelude_docs.hpp include/chaiscript/utility/utility.hpp include/chaiscript/utility/json.hpp include/chaiscript/utility/json_wrap.hpp) set(Chai_INCLUDES include/chaiscript/chaiscript.hpp include/chaiscript/chaiscript_threading.hpp include/chaiscript/dispatchkit/bad_boxed_cast.hpp include/chaiscript/dispatchkit/bind_first.hpp include/chaiscript/dispatchkit/bootstrap.hpp include/chaiscript/dispatchkit/bootstrap_stl.hpp include/chaiscript/dispatchkit/boxed_cast.hpp include/chaiscript/dispatchkit/boxed_cast_helper.hpp include/chaiscript/dispatchkit/boxed_number.hpp include/chaiscript/dispatchkit/boxed_value.hpp include/chaiscript/dispatchkit/dispatchkit.hpp include/chaiscript/dispatchkit/type_conversions.hpp include/chaiscript/dispatchkit/dynamic_object.hpp include/chaiscript/dispatchkit/exception_specification.hpp include/chaiscript/dispatchkit/function_call.hpp include/chaiscript/dispatchkit/function_call_detail.hpp include/chaiscript/dispatchkit/handle_return.hpp include/chaiscript/dispatchkit/operators.hpp include/chaiscript/dispatchkit/proxy_constructors.hpp include/chaiscript/dispatchkit/proxy_functions.hpp include/chaiscript/dispatchkit/proxy_functions_detail.hpp include/chaiscript/dispatchkit/register_function.hpp include/chaiscript/dispatchkit/type_info.hpp include/chaiscript/language/chaiscript_algebraic.hpp include/chaiscript/language/chaiscript_common.hpp include/chaiscript/language/chaiscript_engine.hpp include/chaiscript/language/chaiscript_eval.hpp include/chaiscript/language/chaiscript_parser.hpp include/chaiscript/language/chaiscript_prelude.hpp include/chaiscript/language/chaiscript_prelude_docs.hpp include/chaiscript/utility/utility.hpp include/chaiscript/utility/json.hpp include/chaiscript/utility/json_wrap.hpp)
set_source_files_properties(${Chai_INCLUDES} PROPERTIES HEADER_FILE_ONLY TRUE) set_source_files_properties(${Chai_INCLUDES} PROPERTIES HEADER_FILE_ONLY TRUE)

View File

@ -18,7 +18,7 @@
#include "dispatchkit/bootstrap.hpp" #include "dispatchkit/bootstrap.hpp"
#include "dispatchkit/bootstrap_stl.hpp" #include "dispatchkit/bootstrap_stl.hpp"
#include "dispatchkit/boxed_value.hpp" #include "dispatchkit/boxed_value.hpp"
#include "language/chaiscript_prelude.chai" #include "language/chaiscript_prelude.hpp"
#include "utility/json_wrap.hpp" #include "utility/json_wrap.hpp"
#ifndef CHAISCRIPT_NO_THREADS #ifndef CHAISCRIPT_NO_THREADS

View File

@ -442,6 +442,7 @@ namespace chaiscript
m->add(fun(&dispatch::Dynamic_Object::get_attrs), "get_attrs"); m->add(fun(&dispatch::Dynamic_Object::get_attrs), "get_attrs");
m->add(fun(&dispatch::Dynamic_Object::set_explicit), "set_explicit"); m->add(fun(&dispatch::Dynamic_Object::set_explicit), "set_explicit");
m->add(fun(&dispatch::Dynamic_Object::is_explicit), "is_explicit"); m->add(fun(&dispatch::Dynamic_Object::is_explicit), "is_explicit");
m->add(fun(&dispatch::Dynamic_Object::has_attr), "has_attr");
m->add(fun(static_cast<Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &)>(&dispatch::Dynamic_Object::get_attr)), "get_attr"); m->add(fun(static_cast<Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &)>(&dispatch::Dynamic_Object::get_attr)), "get_attr");
m->add(fun(static_cast<const Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &) const>(&dispatch::Dynamic_Object::get_attr)), "get_attr"); m->add(fun(static_cast<const Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &) const>(&dispatch::Dynamic_Object::get_attr)), "get_attr");
@ -452,13 +453,42 @@ namespace chaiscript
m->add(fun(static_cast<Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &)>(&dispatch::Dynamic_Object::get_attr)), "[]"); m->add(fun(static_cast<Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &)>(&dispatch::Dynamic_Object::get_attr)), "[]");
m->add(fun(static_cast<const Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &) const>(&dispatch::Dynamic_Object::get_attr)), "[]"); m->add(fun(static_cast<const Boxed_Value & (dispatch::Dynamic_Object::*)(const std::string &) const>(&dispatch::Dynamic_Object::get_attr)), "[]");
m->eval(R""( m->eval(R"chaiscript(
def Dynamic_Object::clone() { def Dynamic_Object::clone() {
auto &new_o = Dynamic_Object(this.get_type_name()); auto &new_o = Dynamic_Object(this.get_type_name());
for_each(this.get_attrs(), fun[new_o](x) { new_o.get_attr(x.first) = x.second; } ); for_each(this.get_attrs(), fun[new_o](x) { new_o.get_attr(x.first) = x.second; } );
new_o; new_o;
} }
)"");
def `=`(Dynamic_Object lhs, Dynamic_Object rhs) : lhs.get_type_name() == rhs.get_type_name()
{
for_each(rhs.get_attrs(), fun[lhs](x) { lhs.get_attr(x.first) = clone(x.second); } );
}
def `!=`(Dynamic_Object lhs, Dynamic_Object rhs) : lhs.get_type_name() == rhs.get_type_name()
{
var rhs_attrs := rhs.get_attrs();
var lhs_attrs := lhs.get_attrs();
if (rhs_attrs.size() != lhs_attrs.size()) {
true;
} else {
return any_of(rhs_attrs, fun[lhs](x) { !lhs.has_attr(x.first) || lhs.get_attr(x.first) != x.second; } );
}
}
def `==`(Dynamic_Object lhs, Dynamic_Object rhs) : lhs.get_type_name() == rhs.get_type_name()
{
var rhs_attrs := rhs.get_attrs();
var lhs_attrs := lhs.get_attrs();
if (rhs_attrs.size() != lhs_attrs.size()) {
false;
} else {
return all_of(rhs_attrs, fun[lhs](x) { lhs.has_attr(x.first) && lhs.get_attr(x.first) == x.second; } );
}
}
)chaiscript");
m->add(fun(&has_guard), "has_guard"); m->add(fun(&has_guard), "has_guard");
m->add(fun(&get_guard), "get_guard"); m->add(fun(&get_guard), "get_guard");

View File

@ -312,7 +312,7 @@ namespace chaiscript
bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const override bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const override
{ {
return std::any_of(m_funcs.cbegin(), m_funcs.cend(), return std::any_of(std::begin(m_funcs), std::end(m_funcs),
[&vals, &t_conversions](const Proxy_Function &f){ return f->call_match(vals, t_conversions); }); [&vals, &t_conversions](const Proxy_Function &f){ return f->call_match(vals, t_conversions); });
} }
@ -620,7 +620,7 @@ namespace chaiscript
/// Searches the current stack for an object of the given name /// Searches the current stack for an object of the given name
/// includes a special overload for the _ place holder object to /// includes a special overload for the _ place holder object to
/// ensure that it is always in scope. /// ensure that it is always in scope.
Boxed_Value get_object(const std::string &name, std::atomic_uint_fast32_t &t_loc) const Boxed_Value get_object(const std::string &name, std::atomic_uint_fast32_t &t_loc, Stack_Holder &t_holder) const
{ {
enum class Loc : uint_fast32_t { enum class Loc : uint_fast32_t {
located = 0x80000000, located = 0x80000000,
@ -633,7 +633,7 @@ namespace chaiscript
if (loc == 0) if (loc == 0)
{ {
auto &stack = get_stack_data(); auto &stack = get_stack_data(t_holder);
// Is it in the stack? // Is it in the stack?
for (auto stack_elem = stack.rbegin(); stack_elem != stack.rend(); ++stack_elem) for (auto stack_elem = stack.rbegin(); stack_elem != stack.rend(); ++stack_elem)
@ -652,7 +652,7 @@ namespace chaiscript
t_loc = static_cast<uint_fast32_t>(Loc::located); t_loc = static_cast<uint_fast32_t>(Loc::located);
} else if (loc & static_cast<uint_fast32_t>(Loc::is_local)) { } else if (loc & static_cast<uint_fast32_t>(Loc::is_local)) {
auto &stack = get_stack_data(); auto &stack = get_stack_data(t_holder);
return stack[stack.size() - 1 - ((loc & static_cast<uint_fast32_t>(Loc::stack_mask)) >> 16)][loc & static_cast<uint_fast32_t>(Loc::loc_mask)].second; return stack[stack.size() - 1 - ((loc & static_cast<uint_fast32_t>(Loc::stack_mask)) >> 16)][loc & static_cast<uint_fast32_t>(Loc::loc_mask)].second;
} }
@ -911,13 +911,12 @@ namespace chaiscript
return false; return false;
} }
for (const auto &fun : t_funs) { return std::any_of(std::begin(t_funs), std::end(t_funs),
if (fun->is_attribute_function() [&](const auto &fun) {
&& fun->compare_first_type(t_params[0], t_conversions)) { return fun->is_attribute_function() && fun->compare_first_type(t_params[0], t_conversions);
} }
} );
return false;
} }
#ifdef CHAISCRIPT_MSVC #ifdef CHAISCRIPT_MSVC
@ -1605,6 +1604,10 @@ namespace chaiscript
m_engine.get().add_object(t_name, std::move(obj), m_stack_holder.get()); m_engine.get().add_object(t_name, std::move(obj), m_stack_holder.get());
} }
Boxed_Value get_object(const std::string &t_name, std::atomic_uint_fast32_t &t_loc) const {
return m_engine.get().get_object(t_name, t_loc, m_stack_holder.get());
}
private: private:
std::reference_wrapper<Dispatch_Engine> m_engine; std::reference_wrapper<Dispatch_Engine> m_engine;
std::reference_wrapper<Stack_Holder> m_stack_holder; std::reference_wrapper<Stack_Holder> m_stack_holder;

View File

@ -44,9 +44,7 @@ namespace chaiscript
{ {
} }
Dynamic_Object() : m_type_name(""), m_option_explicit(false) Dynamic_Object() = default;
{
}
bool is_explicit() const bool is_explicit() const
{ {
@ -84,6 +82,10 @@ namespace chaiscript
} }
} }
bool has_attr(const std::string &t_attr_name) const {
return m_attrs.find(t_attr_name) != m_attrs.end();
}
Boxed_Value &get_attr(const std::string &t_attr_name) Boxed_Value &get_attr(const std::string &t_attr_name)
{ {
return m_attrs[t_attr_name]; return m_attrs[t_attr_name];
@ -107,15 +109,14 @@ namespace chaiscript
return get_attr(t_method_name); return get_attr(t_method_name);
} }
std::map<std::string, Boxed_Value> get_attrs() const std::map<std::string, Boxed_Value> get_attrs() const
{ {
return m_attrs; return m_attrs;
} }
private: private:
std::string m_type_name; const std::string m_type_name = "";
bool m_option_explicit; bool m_option_explicit = false;
std::map<std::string, Boxed_Value> m_attrs; std::map<std::string, Boxed_Value> m_attrs;
}; };

View File

@ -235,7 +235,7 @@ namespace chaiscript
return dc && dc->m_type_name == m_type_name && (*dc->m_func) == (*m_func); return dc && dc->m_type_name == m_type_name && (*dc->m_func) == (*m_func);
} }
virtual bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const override bool call_match(const std::vector<Boxed_Value> &vals, const Type_Conversions_State &t_conversions) const override
{ {
std::vector<Boxed_Value> new_vals{Boxed_Value(Dynamic_Object(m_type_name))}; std::vector<Boxed_Value> new_vals{Boxed_Value(Dynamic_Object(m_type_name))};
new_vals.insert(new_vals.end(), vals.begin(), vals.end()); new_vals.insert(new_vals.end(), vals.begin(), vals.end());
@ -243,7 +243,7 @@ namespace chaiscript
return m_func->call_match(new_vals, t_conversions); return m_func->call_match(new_vals, t_conversions);
} }
virtual std::string annotation() const override std::string annotation() const override
{ {
return m_func->annotation(); return m_func->annotation();
} }
@ -261,8 +261,8 @@ namespace chaiscript
} }
private: private:
std::string m_type_name; const std::string m_type_name;
Proxy_Function m_func; const Proxy_Function m_func;
}; };
} }

View File

@ -35,8 +35,7 @@ namespace chaiscript
/// \returns A std::function object for dispatching /// \returns A std::function object for dispatching
/// \param[in] funcs the set of functions to dispatch on. /// \param[in] funcs the set of functions to dispatch on.
template<typename FunctionType> template<typename FunctionType>
std::function<FunctionType> std::function<FunctionType> functor(const std::vector<Const_Proxy_Function> &funcs, const Type_Conversions_State *t_conversions)
functor(const std::vector<Const_Proxy_Function> &funcs, const Type_Conversions_State *t_conversions)
{ {
const bool has_arity_match = std::any_of(funcs.begin(), funcs.end(), const bool has_arity_match = std::any_of(funcs.begin(), funcs.end(),
[](const Const_Proxy_Function &f) { [](const Const_Proxy_Function &f) {
@ -63,8 +62,7 @@ namespace chaiscript
/// \returns A std::function object for dispatching /// \returns A std::function object for dispatching
/// \param[in] func A function to execute. /// \param[in] func A function to execute.
template<typename FunctionType> template<typename FunctionType>
std::function<FunctionType> std::function<FunctionType> functor(Const_Proxy_Function func, const Type_Conversions_State *t_conversions)
functor(Const_Proxy_Function func, const Type_Conversions_State *t_conversions)
{ {
return functor<FunctionType>(std::vector<Const_Proxy_Function>({std::move(func)}), t_conversions); return functor<FunctionType>(std::vector<Const_Proxy_Function>({std::move(func)}), t_conversions);
} }
@ -72,8 +70,7 @@ namespace chaiscript
/// Helper for automatically unboxing a Boxed_Value that contains a function object /// Helper for automatically unboxing a Boxed_Value that contains a function object
/// and creating a typesafe C++ function caller from it. /// and creating a typesafe C++ function caller from it.
template<typename FunctionType> template<typename FunctionType>
std::function<FunctionType> std::function<FunctionType> functor(const Boxed_Value &bv, const Type_Conversions_State *t_conversions)
functor(const Boxed_Value &bv, const Type_Conversions_State *t_conversions)
{ {
return functor<FunctionType>(boxed_cast<Const_Proxy_Function >(bv, t_conversions), t_conversions); return functor<FunctionType>(boxed_cast<Const_Proxy_Function >(bv, t_conversions), t_conversions);
} }

View File

@ -59,13 +59,8 @@ namespace chaiscript
}; };
template<typename Ret> template<typename Ret>
struct Handle_Return<std::function<Ret>> struct Handle_Return<std::function<Ret>> : Handle_Return<const std::function<Ret> &>
{ {
static Boxed_Value handle(const std::function<Ret> &f) {
return Boxed_Value(
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Proxy_Function_Callable_Impl<Ret, std::function<Ret>>>(f)
);
}
}; };
template<typename Ret> template<typename Ret>
@ -79,23 +74,13 @@ namespace chaiscript
}; };
template<typename Ret> template<typename Ret>
struct Handle_Return<const std::shared_ptr<std::function<Ret>> &> struct Handle_Return<const std::shared_ptr<std::function<Ret>> &> : Handle_Return<const std::shared_ptr<std::function<Ret>>>
{ {
static Boxed_Value handle(const std::shared_ptr<std::function<Ret>> &f) {
return Boxed_Value(
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Assignable_Proxy_Function_Impl<Ret>>(std::ref(*f),f)
);
}
}; };
template<typename Ret> template<typename Ret>
struct Handle_Return<std::shared_ptr<std::function<Ret>>> struct Handle_Return<std::shared_ptr<std::function<Ret>>> : Handle_Return<const std::shared_ptr<std::function<Ret>>>
{ {
static Boxed_Value handle(const std::shared_ptr<std::function<Ret>> &f) {
return Boxed_Value(
chaiscript::make_shared<dispatch::Proxy_Function_Base, dispatch::Assignable_Proxy_Function_Impl<Ret>>(std::ref(*f),f)
);
}
}; };
template<typename Ret> template<typename Ret>
@ -143,21 +128,13 @@ namespace chaiscript
}; };
template<typename Ret> template<typename Ret>
struct Handle_Return<std::shared_ptr<Ret> > struct Handle_Return<std::shared_ptr<Ret>> : Handle_Return<std::shared_ptr<Ret> &>
{ {
static Boxed_Value handle(const std::shared_ptr<Ret> &r)
{
return Boxed_Value(r, true);
}
}; };
template<typename Ret> template<typename Ret>
struct Handle_Return<const std::shared_ptr<Ret> &> struct Handle_Return<const std::shared_ptr<Ret> &> : Handle_Return<std::shared_ptr<Ret> &>
{ {
static Boxed_Value handle(const std::shared_ptr<Ret> &r)
{
return Boxed_Value(r, true);
}
}; };
template<typename Ret> template<typename Ret>
@ -170,9 +147,6 @@ namespace chaiscript
}; };
/**
* Used internally for handling a return value from a Proxy_Function call
*/
template<typename Ret> template<typename Ret>
struct Handle_Return<Ret &> struct Handle_Return<Ret &>
{ {
@ -187,9 +161,6 @@ namespace chaiscript
} }
}; };
/**
* Used internally for handling a return value from a Proxy_Function call
*/
template<> template<>
struct Handle_Return<Boxed_Value> struct Handle_Return<Boxed_Value>
{ {
@ -199,40 +170,19 @@ namespace chaiscript
} }
}; };
/**
* Used internally for handling a return value from a Proxy_Function call
*/
template<> template<>
struct Handle_Return<const Boxed_Value> struct Handle_Return<const Boxed_Value> : Handle_Return<Boxed_Value>
{ {
static Boxed_Value handle(const Boxed_Value &r)
{
return r;
}
}; };
/**
* Used internally for handling a return value from a Proxy_Function call
*/
template<> template<>
struct Handle_Return<Boxed_Value &> struct Handle_Return<Boxed_Value &> : Handle_Return<Boxed_Value>
{ {
static Boxed_Value handle(const Boxed_Value &r)
{
return r;
}
}; };
/**
* Used internally for handling a return value from a Proxy_Function call
*/
template<> template<>
struct Handle_Return<const Boxed_Value &> struct Handle_Return<const Boxed_Value &> : Handle_Return<Boxed_Value>
{ {
static Boxed_Value handle(const Boxed_Value &r)
{
return r;
}
}; };
/** /**
@ -247,16 +197,9 @@ namespace chaiscript
} }
}; };
/**
* Used internally for handling a return value from a Proxy_Function call
*/
template<> template<>
struct Handle_Return<const Boxed_Number> struct Handle_Return<const Boxed_Number> : Handle_Return<Boxed_Number>
{ {
static Boxed_Value handle(const Boxed_Number &r)
{
return r.bv;
}
}; };

View File

@ -736,14 +736,40 @@ namespace chaiscript
if (bv.is_const()) if (bv.is_const())
{ {
const Class *o = boxed_cast<const Class *>(bv, &t_conversions); const Class *o = boxed_cast<const Class *>(bv, &t_conversions);
return detail::Handle_Return<const typename std::add_lvalue_reference<T>::type>::handle(o->*m_attr); return do_call_impl<T>(o);
} else { } else {
Class *o = boxed_cast<Class *>(bv, &t_conversions); Class *o = boxed_cast<Class *>(bv, &t_conversions);
return detail::Handle_Return<typename std::add_lvalue_reference<T>::type>::handle(o->*m_attr); return do_call_impl<T>(o);
} }
} }
private: private:
template<typename Type>
auto do_call_impl(Class *o) const -> std::enable_if_t<std::is_pointer<Type>::value, Boxed_Value>
{
return detail::Handle_Return<Type>::handle(o->*m_attr);
}
template<typename Type>
auto do_call_impl(const Class *o) const -> std::enable_if_t<std::is_pointer<Type>::value, Boxed_Value>
{
return detail::Handle_Return<const Type>::handle(o->*m_attr);
}
template<typename Type>
auto do_call_impl(Class *o) const -> std::enable_if_t<!std::is_pointer<Type>::value, Boxed_Value>
{
return detail::Handle_Return<const typename std::add_lvalue_reference<Type>::type>::handle(o->*m_attr);
}
template<typename Type>
auto do_call_impl(const Class *o) const -> std::enable_if_t<!std::is_pointer<Type>::value, Boxed_Value>
{
return detail::Handle_Return<const typename std::add_lvalue_reference<Type>::type>::handle(o->*m_attr);
}
static std::vector<Type_Info> param_types() static std::vector<Type_Info> param_types()
{ {
return {user_type<T>(), user_type<Class>()}; return {user_type<T>(), user_type<Class>()};

View File

@ -78,6 +78,7 @@ namespace chaiscript
{ {
try { try {
std::vector<Boxed_Value>::size_type i = 0; std::vector<Boxed_Value>::size_type i = 0;
(void)i;
(void)params; (void)t_conversions; (void)params; (void)t_conversions;
// this is ok because the order of evaluation of initializer lists is well defined // this is ok because the order of evaluation of initializer lists is well defined
(void)std::initializer_list<int>{(boxed_cast<Params>(params[i++], &t_conversions), 0)...}; (void)std::initializer_list<int>{(boxed_cast<Params>(params[i++], &t_conversions), 0)...};

View File

@ -46,7 +46,7 @@ namespace chaiscript
bad_boxed_dynamic_cast(const bad_boxed_dynamic_cast &) = default; bad_boxed_dynamic_cast(const bad_boxed_dynamic_cast &) = default;
virtual ~bad_boxed_dynamic_cast() noexcept {} virtual ~bad_boxed_dynamic_cast() noexcept = default;
}; };
class bad_boxed_type_cast : public bad_boxed_cast class bad_boxed_type_cast : public bad_boxed_cast
@ -70,7 +70,7 @@ namespace chaiscript
bad_boxed_type_cast(const bad_boxed_type_cast &) = default; bad_boxed_type_cast(const bad_boxed_type_cast &) = default;
virtual ~bad_boxed_type_cast() noexcept {} virtual ~bad_boxed_type_cast() noexcept = default;
}; };
} }
@ -97,7 +97,7 @@ namespace chaiscript
return true; return true;
} }
virtual ~Type_Conversion_Base() {} virtual ~Type_Conversion_Base() = default;
protected: protected:
Type_Conversion_Base(const Type_Info &t_to, const Type_Info &t_from) Type_Conversion_Base(const Type_Info &t_to, const Type_Info &t_from)
@ -107,8 +107,8 @@ namespace chaiscript
private: private:
Type_Info m_to; const Type_Info m_to;
Type_Info m_from; const Type_Info m_from;
}; };
@ -126,7 +126,7 @@ namespace chaiscript
if (t_from.is_const()) if (t_from.is_const())
{ {
return Boxed_Value( return Boxed_Value(
[&]()->std::shared_ptr<const To>{ [&](){
if (auto data = std::static_pointer_cast<const To>(detail::Cast_Helper<std::shared_ptr<const From> >::cast(t_from, nullptr))) if (auto data = std::static_pointer_cast<const To>(detail::Cast_Helper<std::shared_ptr<const From> >::cast(t_from, nullptr)))
{ {
return data; return data;
@ -137,7 +137,7 @@ namespace chaiscript
); );
} else { } else {
return Boxed_Value( return Boxed_Value(
[&]()->std::shared_ptr<To>{ [&](){
if (auto data = std::static_pointer_cast<To>(detail::Cast_Helper<std::shared_ptr<From> >::cast(t_from, nullptr))) if (auto data = std::static_pointer_cast<To>(detail::Cast_Helper<std::shared_ptr<From> >::cast(t_from, nullptr)))
{ {
return data; return data;
@ -182,7 +182,7 @@ namespace chaiscript
if (t_from.is_const()) if (t_from.is_const())
{ {
return Boxed_Value( return Boxed_Value(
[&]()->std::shared_ptr<const To>{ [&](){
if (auto data = std::dynamic_pointer_cast<const To>(detail::Cast_Helper<std::shared_ptr<const From> >::cast(t_from, nullptr))) if (auto data = std::dynamic_pointer_cast<const To>(detail::Cast_Helper<std::shared_ptr<const From> >::cast(t_from, nullptr)))
{ {
return data; return data;
@ -193,7 +193,7 @@ namespace chaiscript
); );
} else { } else {
return Boxed_Value( return Boxed_Value(
[&]()->std::shared_ptr<To>{ [&](){
if (auto data = std::dynamic_pointer_cast<To>(detail::Cast_Helper<std::shared_ptr<From> >::cast(t_from, nullptr))) if (auto data = std::dynamic_pointer_cast<To>(detail::Cast_Helper<std::shared_ptr<From> >::cast(t_from, nullptr)))
{ {
return data; return data;
@ -242,12 +242,12 @@ namespace chaiscript
{ {
} }
virtual Boxed_Value convert_down(const Boxed_Value &t_base) const override Boxed_Value convert_down(const Boxed_Value &t_base) const override
{ {
return Dynamic_Caster<Base, Derived>::cast(t_base); return Dynamic_Caster<Base, Derived>::cast(t_base);
} }
virtual Boxed_Value convert(const Boxed_Value &t_derived) const override Boxed_Value convert(const Boxed_Value &t_derived) const override
{ {
return Static_Caster<Derived, Base>::cast(t_derived); return Static_Caster<Derived, Base>::cast(t_derived);
} }
@ -262,17 +262,18 @@ namespace chaiscript
{ {
} }
virtual Boxed_Value convert_down(const Boxed_Value &t_base) const override Boxed_Value convert_down(const Boxed_Value &t_base) const override
{ {
throw chaiscript::exception::bad_boxed_dynamic_cast(t_base.get_type_info(), typeid(Derived), "Unable to cast down inheritance hierarchy with non-polymorphic types"); throw chaiscript::exception::bad_boxed_dynamic_cast(t_base.get_type_info(), typeid(Derived),
"Unable to cast down inheritance hierarchy with non-polymorphic types");
} }
virtual bool bidir() const override bool bidir() const override
{ {
return false; return false;
} }
virtual Boxed_Value convert(const Boxed_Value &t_derived) const override Boxed_Value convert(const Boxed_Value &t_derived) const override
{ {
return Static_Caster<Derived, Base>::cast(t_derived); return Static_Caster<Derived, Base>::cast(t_derived);
} }
@ -290,12 +291,12 @@ namespace chaiscript
{ {
} }
virtual Boxed_Value convert_down(const Boxed_Value &) const override Boxed_Value convert_down(const Boxed_Value &) const override
{ {
throw chaiscript::exception::bad_boxed_type_cast("No conversion exists"); throw chaiscript::exception::bad_boxed_type_cast("No conversion exists");
} }
virtual Boxed_Value convert(const Boxed_Value &t_from) const override Boxed_Value convert(const Boxed_Value &t_from) const override
{ {
/// \todo better handling of errors from the conversion function /// \todo better handling of errors from the conversion function
return m_func(t_from); return m_func(t_from);
@ -317,11 +318,7 @@ namespace chaiscript
public: public:
struct Conversion_Saves struct Conversion_Saves
{ {
Conversion_Saves() bool enabled = false;
: enabled(false)
{}
bool enabled;
std::vector<Boxed_Value> saves; std::vector<Boxed_Value> saves;
}; };
@ -350,7 +347,6 @@ namespace chaiscript
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)
{ {
} }
@ -448,7 +444,7 @@ namespace chaiscript
{ {
chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex); chaiscript::detail::threading::shared_lock<chaiscript::detail::threading::shared_mutex> l(m_mutex);
auto itr = find(to, from); const auto itr = find(to, from);
if (itr != m_conversions.end()) if (itr != m_conversions.end())
{ {

View File

@ -40,17 +40,7 @@ namespace chaiscript
{ {
} }
constexpr Type_Info() constexpr Type_Info() = default;
: m_type_info(nullptr), m_bare_type_info(nullptr),
m_flags(1 << is_undef_flag)
{
}
Type_Info(Type_Info&&) = default;
Type_Info& operator=(Type_Info&&) = default;
Type_Info(const Type_Info&) = default;
Type_Info& operator=(const Type_Info&) = default;
constexpr bool operator<(const Type_Info &ti) const noexcept constexpr bool operator<(const Type_Info &ti) const noexcept
{ {
@ -60,24 +50,23 @@ namespace chaiscript
constexpr bool operator==(const Type_Info &ti) const noexcept constexpr bool operator==(const Type_Info &ti) const noexcept
{ {
return ti.m_type_info == m_type_info return ti.m_type_info == m_type_info
|| (ti.m_type_info && m_type_info && *ti.m_type_info == *m_type_info); || *ti.m_type_info == *m_type_info;
} }
constexpr bool operator==(const std::type_info &ti) const noexcept constexpr bool operator==(const std::type_info &ti) const noexcept
{ {
return m_type_info != nullptr && (*m_type_info) == ti; return !is_undef() && (*m_type_info) == ti;
} }
constexpr bool bare_equal(const Type_Info &ti) const noexcept constexpr bool bare_equal(const Type_Info &ti) const noexcept
{ {
return ti.m_bare_type_info == m_bare_type_info 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); || *ti.m_bare_type_info == *m_bare_type_info;
} }
constexpr bool bare_equal_type_info(const std::type_info &ti) const noexcept constexpr bool bare_equal_type_info(const std::type_info &ti) const noexcept
{ {
return m_bare_type_info != nullptr return !is_undef() && (*m_bare_type_info) == ti;
&& (*m_bare_type_info) == ti;
} }
constexpr bool is_const() const noexcept { return (m_flags & (1 << is_const_flag)) != 0; } constexpr bool is_const() const noexcept { return (m_flags & (1 << is_const_flag)) != 0; }
@ -89,7 +78,7 @@ namespace chaiscript
std::string name() const std::string name() const
{ {
if (m_type_info) if (!is_undef())
{ {
return m_type_info->name(); return m_type_info->name();
} else { } else {
@ -99,7 +88,7 @@ namespace chaiscript
std::string bare_name() const std::string bare_name() const
{ {
if (m_bare_type_info) if (!is_undef())
{ {
return m_bare_type_info->name(); return m_bare_type_info->name();
} else { } else {
@ -113,15 +102,17 @@ namespace chaiscript
} }
private: private:
const std::type_info *m_type_info; struct Unknown_Type {};
const std::type_info *m_bare_type_info;
unsigned int m_flags; const std::type_info *m_type_info = &typeid(Unknown_Type);
const std::type_info *m_bare_type_info = &typeid(Unknown_Type);
static const int is_const_flag = 0; static const int is_const_flag = 0;
static const int is_reference_flag = 1; static const int is_reference_flag = 1;
static const int is_pointer_flag = 2; static const int is_pointer_flag = 2;
static const int is_void_flag = 3; static const int is_void_flag = 3;
static const int is_arithmetic_flag = 4; static const int is_arithmetic_flag = 4;
static const int is_undef_flag = 5; static const int is_undef_flag = 5;
unsigned int m_flags = (1 << is_undef_flag);
}; };
namespace detail namespace detail

View File

@ -168,7 +168,7 @@ namespace chaiscript
return m_value; return m_value;
} else { } else {
try { try {
return t_ss->get_object(this->text, m_loc); return t_ss.get_object(this->text, m_loc);
} }
catch (std::exception &) { catch (std::exception &) {
throw exception::eval_error("Can not find object: " + this->text); throw exception::eval_error("Can not find object: " + this->text);

View File

@ -60,7 +60,7 @@ namespace chaiscript
static std::array<std::array<bool, detail::lengthof_alphabet>, detail::max_alphabet> build_alphabet() static std::array<std::array<bool, detail::lengthof_alphabet>, detail::max_alphabet> build_alphabet()
{ {
std::array<std::array<bool, detail::lengthof_alphabet>, detail::max_alphabet> alphabet = {}; std::array<std::array<bool, detail::lengthof_alphabet>, detail::max_alphabet> alphabet;
for (auto &alpha : alphabet) { for (auto &alpha : alphabet) {
alpha.fill(false); alpha.fill(false);

View File

@ -1,7 +1,7 @@
// This file is distributed under the BSD License. // This file is distributed under the BSD License.
// See "license.txt" for details. // See "license.txt" for details.
// Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com) // Copyright 2009-2012, Jonathan Turner (jonathan@emptycrate.com)
// and Jason Turner (jason@emptycrate.com) // and 2009-2016, Jason Turner (jason@emptycrate.com)
// http://www.chaiscript.com // http://www.chaiscript.com
#ifndef CHAISCRIPT_PRELUDE_HPP_ #ifndef CHAISCRIPT_PRELUDE_HPP_
@ -9,7 +9,7 @@
namespace chaiscript { namespace chaiscript {
struct ChaiScript_Prelude { struct ChaiScript_Prelude {
static std::string chaiscript_prelude() { return R""( static std::string chaiscript_prelude() { return R"chaiscript(
def lt(l, r) { def lt(l, r) {
if (call_exists(`<`, l, r)) { if (call_exists(`<`, l, r)) {
@ -215,6 +215,29 @@ def for_each(container, func) : call_exists(range, container) {
} }
} }
def any_of(container, func) : call_exists(range, container) {
var t_range := range(container);
while (!t_range.empty()) {
if (func(t_range.front())) {
return true;
}
t_range.pop_front();
}
false;
}
def all_of(container, func) : call_exists(range, container) {
var t_range := range(container);
while (!t_range.empty()) {
if (!func(t_range.front())) {
return false;
}
t_range.pop_front();
}
true;
}
def back_inserter(container) { def back_inserter(container) {
bind(push_back, container, _); bind(push_back, container, _);
} }
@ -530,7 +553,7 @@ def find(container, value) {
} }
)""; )chaiscript";
} }
}; };

View File

@ -11,7 +11,7 @@ class TestBaseType
TestBaseType() : val(10), const_val(15), mdarray{} { } TestBaseType() : val(10), const_val(15), mdarray{} { }
TestBaseType(int) : val(10), const_val(15), mdarray{} { } TestBaseType(int) : val(10), const_val(15), mdarray{} { }
TestBaseType(int *) : val(10), const_val(15), mdarray{} { } TestBaseType(int *) : val(10), const_val(15), mdarray{} { }
TestBaseType(const TestBaseType &) = default; TestBaseType(const TestBaseType &) = default;
virtual ~TestBaseType() {} virtual ~TestBaseType() {}
virtual int func() { return 0; } virtual int func() { return 0; }
@ -22,6 +22,11 @@ class TestBaseType
int val; int val;
const int const_val; const int const_val;
const int *const_val_ptr = &const_val;
const int *get_const_val_ptr() {
return const_val_ptr;
}
int mdarray[2][3][5]; int mdarray[2][3][5];
std::function<int (int)> func_member; std::function<int (int)> func_member;
@ -168,6 +173,8 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo
m->add(chaiscript::fun(&TestBaseType::func), "func"); m->add(chaiscript::fun(&TestBaseType::func), "func");
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::const_val_ptr), "const_val_ptr");
m->add(chaiscript::fun(&TestBaseType::get_const_val_ptr), "get_const_val_ptr");
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"); m->add(chaiscript::fun(&TestBaseType::set_string_val), "set_string_val");

View File

@ -0,0 +1,26 @@
class MyClass
{
def MyClass()
{
this.x = 2;
}
var x;
}
var o = MyClass();
var o2 = MyClass();
o2.x = 5;
o = o2;
assert_true(o.x == 5)
assert_true(o == o2)
o2.x = 3;
print(o2.x);
print(o.x);
assert_true(o != o2)

View File

@ -8,4 +8,6 @@ assert_equal(13, t0.val)
assert_equal(15, t0.constMe().const_val) assert_equal(15, t0.constMe().const_val)
assert_equal(13, t0.constMe().val) assert_equal(13, t0.constMe().val)
assert_equal(15, t0.get_const_val_ptr())
assert_equal(15, t0.const_val_ptr)