Skip to content

Commit d2ed8fd

Browse files
committed
Get class members that are functions working
Automatic conversion of return values into Proxy_Function objects Issue: #155
1 parent 2f44454 commit d2ed8fd

File tree

7 files changed

+170
-9
lines changed

7 files changed

+170
-9
lines changed

include/chaiscript/dispatchkit/bootstrap.hpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -372,6 +372,7 @@ namespace chaiscript
372372
m->add(user_type<Boxed_Value>(), "Object");
373373
m->add(user_type<Boxed_Number>(), "Number");
374374
m->add(user_type<Proxy_Function>(), "Function");
375+
m->add(user_type<dispatch::Assignable_Proxy_Function>(), "Assignable_Function");
375376
m->add(user_type<std::exception>(), "exception");
376377

377378
m->add(fun(&dispatch::Proxy_Function_Base::get_arity), "get_arity");
@@ -468,6 +469,13 @@ namespace chaiscript
468469
m->add(fun(&shared_ptr_unconst_clone<dispatch::Proxy_Function_Base>), "clone");
469470
m->add(fun(&ptr_assign<std::remove_const<dispatch::Proxy_Function_Base>::type>), "=");
470471
m->add(fun(&ptr_assign<std::add_const<dispatch::Proxy_Function_Base>::type>), "=");
472+
m->add(chaiscript::base_class<dispatch::Proxy_Function_Base, dispatch::Assignable_Proxy_Function>());
473+
m->add(fun<void (dispatch::Assignable_Proxy_Function &, const std::shared_ptr<const dispatch::Proxy_Function_Base> &)>(
474+
[](dispatch::Assignable_Proxy_Function &t_lhs, const std::shared_ptr<const dispatch::Proxy_Function_Base> &t_rhs) {
475+
t_lhs.assign(t_rhs);
476+
}
477+
), "="
478+
);
471479

472480
m->add(fun(&Boxed_Value::type_match), "type_match");
473481

include/chaiscript/dispatchkit/function_call.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ namespace chaiscript
5757
std::function<FunctionType>
5858
functor(Const_Proxy_Function func, const Type_Conversions *t_conversions)
5959
{
60-
return functor<FunctionType>(std::vector<Const_Proxy_Function>({func}), t_conversions);
60+
return functor<FunctionType>(std::vector<Const_Proxy_Function>({std::move(func)}), t_conversions);
6161
}
6262

6363
/// Helper for automatically unboxing a Boxed_Value that contains a function object

include/chaiscript/dispatchkit/handle_return.hpp

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,9 @@ namespace chaiscript
2626
{
2727
namespace dispatch
2828
{
29+
template<class T> class Proxy_Function_Impl;
30+
template<class T> class Assignable_Proxy_Function_Impl;
31+
2932
namespace detail
3033
{
3134
/**
@@ -49,6 +52,98 @@ namespace chaiscript
4952
}
5053
};
5154

55+
template<typename Ret>
56+
struct Handle_Return<const std::function<Ret> &>
57+
{
58+
static Boxed_Value handle(const std::function<Ret> &f) {
59+
return Boxed_Value(
60+
std::shared_ptr<dispatch::Proxy_Function_Base>(
61+
new dispatch::Proxy_Function_Impl<Ret>(f)
62+
)
63+
);
64+
}
65+
};
66+
67+
template<typename Ret>
68+
struct Handle_Return<std::function<Ret>>
69+
{
70+
static Boxed_Value handle(const std::function<Ret> &f) {
71+
return Boxed_Value(
72+
std::shared_ptr<dispatch::Proxy_Function_Base>(
73+
new Proxy_Function_Impl<Ret>(f)
74+
)
75+
);
76+
}
77+
};
78+
79+
template<typename Ret>
80+
struct Handle_Return<const std::shared_ptr<std::function<Ret>>>
81+
{
82+
static Boxed_Value handle(const std::shared_ptr<std::function<Ret>> &f) {
83+
return Boxed_Value(
84+
std::shared_ptr<Proxy_Function_Base>(
85+
new Assignable_Proxy_Function_Impl<Ret>(
86+
std::ref(*f),
87+
f
88+
)
89+
)
90+
);
91+
}
92+
};
93+
94+
template<typename Ret>
95+
struct Handle_Return<const std::shared_ptr<std::function<Ret>> &>
96+
{
97+
static Boxed_Value handle(const std::shared_ptr<std::function<Ret>> &f) {
98+
return Boxed_Value(
99+
std::shared_ptr<Proxy_Function_Base>(
100+
new Assignable_Proxy_Function_Impl<Ret>(
101+
std::ref(*f),
102+
f
103+
)
104+
)
105+
);
106+
}
107+
};
108+
109+
template<typename Ret>
110+
struct Handle_Return<std::shared_ptr<std::function<Ret>>>
111+
{
112+
static Boxed_Value handle(const std::shared_ptr<std::function<Ret>> &f) {
113+
return Boxed_Value(
114+
std::shared_ptr<Proxy_Function_Base>(
115+
new Assignable_Proxy_Function_Impl<Ret>(
116+
std::ref(*f),
117+
f
118+
)
119+
)
120+
);
121+
}
122+
};
123+
124+
template<typename Ret>
125+
struct Handle_Return<std::function<Ret> &>
126+
{
127+
static Boxed_Value handle(std::function<Ret> &f) {
128+
return Boxed_Value(
129+
std::shared_ptr<Proxy_Function_Base>(
130+
new Assignable_Proxy_Function_Impl<Ret>(
131+
std::ref(f),
132+
std::shared_ptr<std::function<Ret>>()
133+
)
134+
)
135+
);
136+
}
137+
138+
static Boxed_Value handle(const std::function<Ret> &f) {
139+
return Boxed_Value(
140+
std::shared_ptr<dispatch::Proxy_Function_Base>(
141+
new dispatch::Proxy_Function_Impl<Ret>(f)
142+
)
143+
);
144+
}
145+
};
146+
52147
template<typename Ret>
53148
struct Handle_Return<Ret *>
54149
{

include/chaiscript/dispatchkit/proxy_functions.hpp

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,9 @@ namespace chaiscript
4343

4444
namespace dispatch
4545
{
46+
template<typename FunctionType>
47+
std::function<FunctionType> functor(std::shared_ptr<const Proxy_Function_Base> func, const Type_Conversions *t_conversions);
48+
4649
class Param_Types
4750
{
4851
public:
@@ -571,11 +574,73 @@ namespace chaiscript
571574
return detail::Do_Call<typename std::function<Func>::result_type>::go(m_f, params, t_conversions);
572575
}
573576

577+
574578
private:
575579
std::function<Func> m_f;
576580
Func *m_dummy_func;
577581
};
578582

583+
class Assignable_Proxy_Function : public Proxy_Function_Impl_Base
584+
{
585+
public:
586+
Assignable_Proxy_Function(const std::vector<Type_Info> &t_types)
587+
: Proxy_Function_Impl_Base(t_types)
588+
{
589+
}
590+
591+
virtual ~Assignable_Proxy_Function() {}
592+
593+
594+
virtual void assign(const std::shared_ptr<const Proxy_Function_Base> &t_rhs) = 0;
595+
596+
597+
};
598+
599+
template<typename Func>
600+
class Assignable_Proxy_Function_Impl : public Assignable_Proxy_Function
601+
{
602+
public:
603+
Assignable_Proxy_Function_Impl(std::reference_wrapper<std::function<Func>> t_f, std::shared_ptr<std::function<Func>> t_ptr)
604+
: Assignable_Proxy_Function(detail::build_param_type_list(static_cast<Func *>(nullptr))),
605+
m_f(std::move(t_f)), m_shared_ptr_holder(std::move(t_ptr)), m_dummy_func(nullptr)
606+
{
607+
assert(!m_shared_ptr_holder || m_shared_ptr_holder.get() == &m_f.get());
608+
609+
}
610+
611+
virtual ~Assignable_Proxy_Function_Impl() {}
612+
613+
virtual bool compare_types_with_cast(const std::vector<Boxed_Value> &vals, const Type_Conversions &t_conversions) const CHAISCRIPT_OVERRIDE
614+
{
615+
return detail::compare_types_cast(m_dummy_func, vals, t_conversions);
616+
}
617+
618+
virtual bool operator==(const Proxy_Function_Base &t_func) const CHAISCRIPT_OVERRIDE
619+
{
620+
return dynamic_cast<const Assignable_Proxy_Function_Impl<Func> *>(&t_func) != nullptr;
621+
}
622+
623+
std::function<Func> internal_function() const
624+
{
625+
return m_f.get();
626+
}
627+
628+
virtual void assign(const std::shared_ptr<const Proxy_Function_Base> &t_rhs) {
629+
m_f.get() = dispatch::functor<Func>(t_rhs, nullptr);
630+
}
631+
632+
protected:
633+
virtual Boxed_Value do_call(const std::vector<Boxed_Value> &params, const Type_Conversions &t_conversions) const
634+
{
635+
return detail::Do_Call<typename std::function<Func>::result_type>::go(m_f.get(), params, t_conversions);
636+
}
637+
638+
639+
private:
640+
std::reference_wrapper<std::function<Func>> m_f;
641+
std::shared_ptr<std::function<Func>> m_shared_ptr_holder;
642+
Func *m_dummy_func;
643+
};
579644
/// Attribute getter Proxy_Function implementation
580645
template<typename T, typename Class>
581646
class Attribute_Access : public Proxy_Function_Base
@@ -625,7 +690,7 @@ namespace chaiscript
625690
if (bv.is_const())
626691
{
627692
const Class *o = boxed_cast<const Class *>(bv, &t_conversions);
628-
return detail::Handle_Return<typename std::add_lvalue_reference<T>::type>::handle(o->*m_attr);
693+
return detail::Handle_Return<const typename std::add_lvalue_reference<T>::type>::handle(o->*m_attr);
629694
} else {
630695
Class *o = boxed_cast<Class *>(bv, &t_conversions);
631696
return detail::Handle_Return<typename std::add_lvalue_reference<T>::type>::handle(o->*m_attr);

src/test_module.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -163,11 +163,6 @@ CHAISCRIPT_MODULE_EXPORT chaiscript::ModulePtr create_chaiscript_module_test_mo
163163

164164
// member that is a function
165165
m->add(chaiscript::fun(&TestBaseType::func_member), "func_member");
166-
m->add(chaiscript::fun<std::function<int(int)> &(std::function<int(int)> &, const std::function<int(int)> &)>(
167-
[](std::function<int (int)> &t_lhs, const std::function<int (int)> &t_rhs)-> std::function<int (int)> &{
168-
return t_lhs = t_rhs;
169-
}), "=");
170-
171166
m->add(chaiscript::fun(&get_new_int), "get_new_int");
172167

173168

unittests/function_attributes.chai

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,5 @@ t0.func_member = fun(int i){ i * 3; };
1616

1717
assert_true(func_member(t0)(2) == 6)
1818
assert_true((func_member(t0))(2) == 6)
19-
assert_true((t0.func_member)(2) == 6)
2019
assert_true(t0.func_member(2) == 6)
2120

unittests/function_members.chai

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,5 @@ t0.func_member = fun(int i){ i * 3; };
88

99
assert_true(func_member(t0)(2) == 6)
1010
assert_true((func_member(t0))(2) == 6)
11-
assert_true((t0.func_member)(2) == 6)
1211
assert_true(t0.func_member(2) == 6)
1312

0 commit comments

Comments
 (0)