Merge 8af9cc5f113e90640e4f6f81fd9813eb191ae311 into 6491b804966bd69b44c7d902cbc5240142585af1

This commit is contained in:
Glen Fraser 2021-05-24 03:30:20 +02:00 committed by GitHub
commit 19051d3369
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 61 additions and 0 deletions

View File

@ -681,6 +681,13 @@ namespace chaiscript
} }
virtual void assign(const std::shared_ptr<const Proxy_Function_Base> &t_rhs) = 0; virtual void assign(const std::shared_ptr<const Proxy_Function_Base> &t_rhs) = 0;
// Check whether the function is callable (not empty)
// Note: this conversion *should* be marked "explicit", but virtual together
// with explicit isn't allowed with MSVC (bug)
virtual operator bool() const = 0;
virtual void clear() = 0;
}; };
template<typename Func> template<typename Func>
@ -713,6 +720,16 @@ namespace chaiscript
m_f.get() = dispatch::functor<Func>(t_rhs, nullptr); m_f.get() = dispatch::functor<Func>(t_rhs, nullptr);
} }
operator bool() const override
{
return static_cast<bool>(m_f.get());
}
void clear() override
{
m_f.get() = nullptr;
}
protected: protected:
Boxed_Value do_call(const Function_Params &params, const Type_Conversions_State &t_conversions) const override Boxed_Value do_call(const Function_Params &params, const Type_Conversions_State &t_conversions) const override
{ {

View File

@ -113,6 +113,50 @@ TEST_CASE("Function objects can be created from chaiscript functions")
CHECK(chai.eval<std::function<std::string (const chaiscript::Boxed_Value &)> >("to_string")(chaiscript::var(6)) == "6"); CHECK(chai.eval<std::function<std::string (const chaiscript::Boxed_Value &)> >("to_string")(chaiscript::var(6)) == "6");
} }
TEST_CASE("Function callbacks can be set, tested and cleared")
{
struct MyObject {
std::function<int(int)> callback;
};
using namespace chaiscript;
ModulePtr m = chaiscript::ModulePtr(new chaiscript::Module());
ChaiScript_Basic chai(create_chaiscript_stdlib(),create_chaiscript_parser());
utility::add_class<MyObject>(*m,
"MyObject",
{ constructor<MyObject ()>(),
constructor<MyObject (const MyObject &)>() },
{ {fun(&MyObject::callback), "callback"},
{fun(static_cast<MyObject & (MyObject::*)(const MyObject &)>(&MyObject::operator=)), "=" }
}
);
m->add(fun([](dispatch::Assignable_Proxy_Function const& func) { return !func; }), "empty");
m->add(fun([](dispatch::Assignable_Proxy_Function& func) { func.clear(); }), "clear");
chai.add(m);
// Function object set from C++
MyObject test;
test.callback = [](int i) { return i + 10; };
chai.add(var(std::ref(test)), "test");
CHECK(chai.eval<int>("!test.callback.empty ? test.callback(13) : -1") == 23);
CHECK(chai.eval<int>("test.callback(9)") == 19);
CHECK(chai.eval<bool>("test.callback.empty") == false);
chai.eval("test.callback.clear");
CHECK(chai.eval<bool>("test.callback.empty") == true);
CHECK_THROWS(chai.eval<int>("test.callback(1)") == 11);
// Function object set from ChaiScript
chai.eval("auto o = MyObject()");
CHECK(chai.eval<bool>("o.callback.empty") == true);
chai.eval("o.callback = fun(int i) { return i + 10 }");
CHECK(chai.eval<bool>("o.callback.empty") == false);
CHECK(chai.eval<int>("!o.callback.empty ? o.callback(13) : -1") == 23);
CHECK(chai.eval<int>("o.callback(9)") == 19);
chai.eval("o.callback.clear");
CHECK(chai.eval<bool>("o.callback.empty") == true);
CHECK_THROWS(chai.eval<int>("o.callback(1)") == 11);
}
TEST_CASE("ChaiScript can be created and destroyed on heap") TEST_CASE("ChaiScript can be created and destroyed on heap")
{ {