18bf80f4bSopenharmony_ci/* 28bf80f4bSopenharmony_ci * Copyright (c) 2024 Huawei Device Co., Ltd. 38bf80f4bSopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 48bf80f4bSopenharmony_ci * you may not use this file except in compliance with the License. 58bf80f4bSopenharmony_ci * You may obtain a copy of the License at 68bf80f4bSopenharmony_ci * 78bf80f4bSopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 88bf80f4bSopenharmony_ci * 98bf80f4bSopenharmony_ci * Unless required by applicable law or agreed to in writing, software 108bf80f4bSopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 118bf80f4bSopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 128bf80f4bSopenharmony_ci * See the License for the specific language governing permissions and 138bf80f4bSopenharmony_ci * limitations under the License. 148bf80f4bSopenharmony_ci */ 158bf80f4bSopenharmony_ci 168bf80f4bSopenharmony_ci#ifndef META_API_FUNCTION_H 178bf80f4bSopenharmony_ci#define META_API_FUNCTION_H 188bf80f4bSopenharmony_ci 198bf80f4bSopenharmony_ci#include <meta/api/call_context.h> 208bf80f4bSopenharmony_ci#include <meta/interface/builtin_objects.h> 218bf80f4bSopenharmony_ci#include <meta/interface/interface_helpers.h> 228bf80f4bSopenharmony_ci#include <meta/interface/intf_cloneable.h> 238bf80f4bSopenharmony_ci#include <meta/interface/intf_function.h> 248bf80f4bSopenharmony_ci#include <meta/interface/object_macros.h> 258bf80f4bSopenharmony_ci 268bf80f4bSopenharmony_ciMETA_BEGIN_NAMESPACE() 278bf80f4bSopenharmony_ci 288bf80f4bSopenharmony_ci/** 298bf80f4bSopenharmony_ci * @brief Function implementation that is used for the meta function system. 308bf80f4bSopenharmony_ci */ 318bf80f4bSopenharmony_citemplate<typename Obj, typename Func> 328bf80f4bSopenharmony_ciclass DefaultFunction : public IntroduceInterfaces<IFunction, ICloneable> { 338bf80f4bSopenharmony_cipublic: 348bf80f4bSopenharmony_ci ~DefaultFunction() override = default; 358bf80f4bSopenharmony_ci DefaultFunction& operator=(const DefaultFunction&) noexcept = delete; 368bf80f4bSopenharmony_ci META_NO_MOVE(DefaultFunction) 378bf80f4bSopenharmony_ci 388bf80f4bSopenharmony_ci BASE_NS::string GetName() const override 398bf80f4bSopenharmony_ci { 408bf80f4bSopenharmony_ci return name_; 418bf80f4bSopenharmony_ci } 428bf80f4bSopenharmony_ci 438bf80f4bSopenharmony_ci IObject::ConstPtr GetDestination() const override 448bf80f4bSopenharmony_ci { 458bf80f4bSopenharmony_ci return interface_pointer_cast<IObject>(obj_); 468bf80f4bSopenharmony_ci } 478bf80f4bSopenharmony_ci 488bf80f4bSopenharmony_ci void Invoke(const ICallContext::Ptr& context) const override 498bf80f4bSopenharmony_ci { 508bf80f4bSopenharmony_ci func_(obj_, context); 518bf80f4bSopenharmony_ci } 528bf80f4bSopenharmony_ci 538bf80f4bSopenharmony_ci ICallContext::Ptr CreateCallContext() const override 548bf80f4bSopenharmony_ci { 558bf80f4bSopenharmony_ci if (context_) { 568bf80f4bSopenharmony_ci return context_(); 578bf80f4bSopenharmony_ci } 588bf80f4bSopenharmony_ci return nullptr; 598bf80f4bSopenharmony_ci } 608bf80f4bSopenharmony_ci 618bf80f4bSopenharmony_ci BASE_NS::shared_ptr<CORE_NS::IInterface> GetClone() const override 628bf80f4bSopenharmony_ci { 638bf80f4bSopenharmony_ci BASE_NS::shared_ptr<DefaultFunction> p(new DefaultFunction(*this)); 648bf80f4bSopenharmony_ci return interface_pointer_cast<CORE_NS::IInterface>(p); 658bf80f4bSopenharmony_ci } 668bf80f4bSopenharmony_ci 678bf80f4bSopenharmony_ci DefaultFunction( 688bf80f4bSopenharmony_ci BASE_NS::string n, BASE_NS::weak_ptr<BASE_NS::remove_const_t<Obj>> obj, Func f, Internal::FContext* context) 698bf80f4bSopenharmony_ci : name_(BASE_NS::move(n)), obj_(obj), func_(BASE_NS::move(f)), context_(context) 708bf80f4bSopenharmony_ci {} 718bf80f4bSopenharmony_ci 728bf80f4bSopenharmony_ciprotected: 738bf80f4bSopenharmony_ci DefaultFunction(const DefaultFunction& s) : name_(s.name_), obj_(s.obj_), func_(s.func_), context_(s.context_) {} 748bf80f4bSopenharmony_ci 758bf80f4bSopenharmony_ciprotected: 768bf80f4bSopenharmony_ci BASE_NS::string name_; 778bf80f4bSopenharmony_ci BASE_NS::weak_ptr<BASE_NS::remove_const_t<Obj>> obj_ {}; 788bf80f4bSopenharmony_ci Func func_; 798bf80f4bSopenharmony_ci Internal::FContext* const context_; 808bf80f4bSopenharmony_ci}; 818bf80f4bSopenharmony_ci 828bf80f4bSopenharmony_ci/** 838bf80f4bSopenharmony_ci * @brief Create DefaultFunction object for obj+memfun (used in metadata initialisation) 848bf80f4bSopenharmony_ci */ 858bf80f4bSopenharmony_citemplate<typename Obj, typename MemFun> 868bf80f4bSopenharmony_ciIFunction::Ptr CreateFunction(BASE_NS::string_view name, Obj* obj, MemFun func, Internal::FContext* context) 878bf80f4bSopenharmony_ci{ 888bf80f4bSopenharmony_ci using ObjType = BASE_NS::shared_ptr<BASE_NS::remove_const_t<Obj>>; 898bf80f4bSopenharmony_ci ObjType objPtr { obj->GetSelf(), obj }; 908bf80f4bSopenharmony_ci auto l = [func](auto obj, const ICallContext::Ptr& context) { 918bf80f4bSopenharmony_ci if (auto o = obj.lock()) { 928bf80f4bSopenharmony_ci (o.get()->*func)(context); 938bf80f4bSopenharmony_ci } 948bf80f4bSopenharmony_ci }; 958bf80f4bSopenharmony_ci return IFunction::Ptr( 968bf80f4bSopenharmony_ci new DefaultFunction<Obj, decltype(l)>(BASE_NS::string(name), objPtr, BASE_NS::move(l), context)); 978bf80f4bSopenharmony_ci} 988bf80f4bSopenharmony_ci 998bf80f4bSopenharmony_ci/** 1008bf80f4bSopenharmony_ci * @brief Create DefaultFunction object from lambda 1018bf80f4bSopenharmony_ci */ 1028bf80f4bSopenharmony_citemplate<typename Func, typename = EnableIfBindFunction<Func>> 1038bf80f4bSopenharmony_ciIFunction::Ptr CreateBindFunction(Func func) 1048bf80f4bSopenharmony_ci{ 1058bf80f4bSopenharmony_ci auto ccontext = []() { 1068bf80f4bSopenharmony_ci ::BASE_NS::string_view arr[] = { "" }; 1078bf80f4bSopenharmony_ci return CreateCallContextImpl<decltype(func())>(ParamNameToView(arr)); 1088bf80f4bSopenharmony_ci }; 1098bf80f4bSopenharmony_ci // wrap to make CallFunction to work with operator()(auto...) 1108bf80f4bSopenharmony_ci auto wrapper = [func]() mutable { return func(); }; 1118bf80f4bSopenharmony_ci auto l = [wrapper](auto, const ICallContext::Ptr& context) { ::META_NS::CallFunction(context, wrapper); }; 1128bf80f4bSopenharmony_ci return IFunction::Ptr(new DefaultFunction<IObject, decltype(l)>("Bind", nullptr, BASE_NS::move(l), ccontext)); 1138bf80f4bSopenharmony_ci} 1148bf80f4bSopenharmony_ci 1158bf80f4bSopenharmony_ci/** 1168bf80f4bSopenharmony_ci * @brief Create DefaultFunction object from lambda 1178bf80f4bSopenharmony_ci */ 1188bf80f4bSopenharmony_citemplate<typename Func, typename... Args> 1198bf80f4bSopenharmony_ciIFunction::Ptr CreateBindFunctionSafe(Func func, Args&&... args) 1208bf80f4bSopenharmony_ci{ 1218bf80f4bSopenharmony_ci return CreateBindFunction(CaptureSafe(BASE_NS::move(func), BASE_NS::forward<Args>(args)...)); 1228bf80f4bSopenharmony_ci} 1238bf80f4bSopenharmony_ci 1248bf80f4bSopenharmony_ci/** 1258bf80f4bSopenharmony_ci * @brief Create forwarding function object 1268bf80f4bSopenharmony_ci */ 1278bf80f4bSopenharmony_ciinline IFunction::Ptr CreateFunction(const IObject::Ptr& obj, BASE_NS::string_view name) 1288bf80f4bSopenharmony_ci{ 1298bf80f4bSopenharmony_ci if (auto f = META_NS::GetObjectRegistry().Create<ISettableFunction>(ClassId::SettableFunction)) { 1308bf80f4bSopenharmony_ci if (f->SetTarget(obj, name)) { 1318bf80f4bSopenharmony_ci return f; 1328bf80f4bSopenharmony_ci } 1338bf80f4bSopenharmony_ci } 1348bf80f4bSopenharmony_ci return nullptr; 1358bf80f4bSopenharmony_ci} 1368bf80f4bSopenharmony_ci 1378bf80f4bSopenharmony_ci/** 1388bf80f4bSopenharmony_ci * @brief Helper class for meta function call result. 1398bf80f4bSopenharmony_ci */ 1408bf80f4bSopenharmony_citemplate<typename Type> 1418bf80f4bSopenharmony_cistruct CallResult { 1428bf80f4bSopenharmony_ci explicit operator bool() const 1438bf80f4bSopenharmony_ci { 1448bf80f4bSopenharmony_ci return success; 1458bf80f4bSopenharmony_ci } 1468bf80f4bSopenharmony_ci 1478bf80f4bSopenharmony_ci /** 1488bf80f4bSopenharmony_ci * @brief Call context that was used for the call. 1498bf80f4bSopenharmony_ci */ 1508bf80f4bSopenharmony_ci ICallContext::Ptr context; 1518bf80f4bSopenharmony_ci /** 1528bf80f4bSopenharmony_ci * @brief True if it was possible to make the call (i.e. the argument types match the parameters). 1538bf80f4bSopenharmony_ci */ 1548bf80f4bSopenharmony_ci bool success {}; 1558bf80f4bSopenharmony_ci /** 1568bf80f4bSopenharmony_ci * @brief Return value of the function call. 1578bf80f4bSopenharmony_ci */ 1588bf80f4bSopenharmony_ci Type value {}; 1598bf80f4bSopenharmony_ci}; 1608bf80f4bSopenharmony_ci 1618bf80f4bSopenharmony_citemplate<> 1628bf80f4bSopenharmony_cistruct CallResult<void> { 1638bf80f4bSopenharmony_ci explicit operator bool() const 1648bf80f4bSopenharmony_ci { 1658bf80f4bSopenharmony_ci return success; 1668bf80f4bSopenharmony_ci } 1678bf80f4bSopenharmony_ci 1688bf80f4bSopenharmony_ci ICallContext::Ptr context; 1698bf80f4bSopenharmony_ci bool success {}; 1708bf80f4bSopenharmony_ci}; 1718bf80f4bSopenharmony_ci 1728bf80f4bSopenharmony_citemplate<typename Ret, typename... Args, size_t... Index> 1738bf80f4bSopenharmony_ciCallResult<Ret> CallMetaFunctionImpl(const IFunction::Ptr& func, IndexSequence<Index...>, Args&&... args) 1748bf80f4bSopenharmony_ci{ 1758bf80f4bSopenharmony_ci auto context = func->CreateCallContext(); 1768bf80f4bSopenharmony_ci if (!context) { 1778bf80f4bSopenharmony_ci return {}; 1788bf80f4bSopenharmony_ci } 1798bf80f4bSopenharmony_ci auto params = context->GetParameters(); 1808bf80f4bSopenharmony_ci // Allow to use defaults from call context 1818bf80f4bSopenharmony_ci if (params.size() < sizeof...(Args)) { 1828bf80f4bSopenharmony_ci context->ReportError("invalid meta call"); 1838bf80f4bSopenharmony_ci return { context }; 1848bf80f4bSopenharmony_ci } 1858bf80f4bSopenharmony_ci 1868bf80f4bSopenharmony_ci if (!(true && ... && Set<PlainType_t<Args>>(context, params[Index].name, args))) { 1878bf80f4bSopenharmony_ci context->ReportError("invalid meta call"); 1888bf80f4bSopenharmony_ci return { context }; 1898bf80f4bSopenharmony_ci } 1908bf80f4bSopenharmony_ci 1918bf80f4bSopenharmony_ci func->Invoke(context); 1928bf80f4bSopenharmony_ci if (context->Succeeded()) { 1938bf80f4bSopenharmony_ci if constexpr (BASE_NS::is_same_v<Ret, void>) { 1948bf80f4bSopenharmony_ci return CallResult<Ret> { context, true }; 1958bf80f4bSopenharmony_ci } 1968bf80f4bSopenharmony_ci if constexpr (!BASE_NS::is_same_v<Ret, void>) { 1978bf80f4bSopenharmony_ci if (auto p = GetResult<Ret>(context)) { 1988bf80f4bSopenharmony_ci return CallResult<Ret> { context, true, *p }; 1998bf80f4bSopenharmony_ci } 2008bf80f4bSopenharmony_ci } 2018bf80f4bSopenharmony_ci } 2028bf80f4bSopenharmony_ci return { context }; 2038bf80f4bSopenharmony_ci} 2048bf80f4bSopenharmony_ci 2058bf80f4bSopenharmony_ci/** 2068bf80f4bSopenharmony_ci * @brief Call function via interface with the given arguments. 2078bf80f4bSopenharmony_ci * @param func Function to call. 2088bf80f4bSopenharmony_ci * @param args Arguments for the function call. 2098bf80f4bSopenharmony_ci * @return Result of the call. 2108bf80f4bSopenharmony_ci * @see CallResult 2118bf80f4bSopenharmony_ci */ 2128bf80f4bSopenharmony_citemplate<typename Ret, typename... Args> 2138bf80f4bSopenharmony_ciCallResult<Ret> CallMetaFunction(const IFunction::Ptr& func, Args&&... args) 2148bf80f4bSopenharmony_ci{ 2158bf80f4bSopenharmony_ci return CallMetaFunctionImpl<Ret>(func, MakeIndexSequenceFor<Args...>(), BASE_NS::forward<Args>(args)...); 2168bf80f4bSopenharmony_ci} 2178bf80f4bSopenharmony_ci 2188bf80f4bSopenharmony_citemplate<typename Signature> 2198bf80f4bSopenharmony_cistruct IsFunctionCompatibleImpl; 2208bf80f4bSopenharmony_ci 2218bf80f4bSopenharmony_citemplate<typename Ret, typename... Args> 2228bf80f4bSopenharmony_cistruct IsFunctionCompatibleImpl<Ret(Args...)> { 2238bf80f4bSopenharmony_ci template<size_t... Index> 2248bf80f4bSopenharmony_ci static bool Call(const IFunction::Ptr& func, IndexSequence<Index...>) 2258bf80f4bSopenharmony_ci { 2268bf80f4bSopenharmony_ci auto context = func->CreateCallContext(); 2278bf80f4bSopenharmony_ci // e.g. wrong number of parameters when implementing meta function 2288bf80f4bSopenharmony_ci if (!context) { 2298bf80f4bSopenharmony_ci return false; 2308bf80f4bSopenharmony_ci } 2318bf80f4bSopenharmony_ci auto params = context->GetParameters(); 2328bf80f4bSopenharmony_ci // Allow to use defaults from call context 2338bf80f4bSopenharmony_ci if (params.size() < sizeof...(Args)) { 2348bf80f4bSopenharmony_ci return false; 2358bf80f4bSopenharmony_ci } 2368bf80f4bSopenharmony_ci 2378bf80f4bSopenharmony_ci // if we have void, allow any return type, it will just be ignored 2388bf80f4bSopenharmony_ci if constexpr (!BASE_NS::is_same_v<Ret, void>) { 2398bf80f4bSopenharmony_ci if (!IsCompatibleWith<Ret>(context->GetResult())) { 2408bf80f4bSopenharmony_ci return false; 2418bf80f4bSopenharmony_ci } 2428bf80f4bSopenharmony_ci } 2438bf80f4bSopenharmony_ci 2448bf80f4bSopenharmony_ci if (!(true && ... && IsCompatibleWith<Args>(*params[Index].value))) { 2458bf80f4bSopenharmony_ci return false; 2468bf80f4bSopenharmony_ci } 2478bf80f4bSopenharmony_ci return true; 2488bf80f4bSopenharmony_ci } 2498bf80f4bSopenharmony_ci static bool Call(const IFunction::Ptr& func) 2508bf80f4bSopenharmony_ci { 2518bf80f4bSopenharmony_ci if constexpr ((true && ... && HasUid_v<PlainType_t<Args>>)) { 2528bf80f4bSopenharmony_ci return Call(func, MakeIndexSequenceFor<Args...>()); 2538bf80f4bSopenharmony_ci } 2548bf80f4bSopenharmony_ci return false; 2558bf80f4bSopenharmony_ci } 2568bf80f4bSopenharmony_ci}; 2578bf80f4bSopenharmony_ci 2588bf80f4bSopenharmony_ci/** 2598bf80f4bSopenharmony_ci * @brief Check if function is compatible with given signature (The return type and parameter types match). 2608bf80f4bSopenharmony_ci */ 2618bf80f4bSopenharmony_citemplate<typename FuncSignature> 2628bf80f4bSopenharmony_cibool IsFunctionCompatible(const IFunction::Ptr& func) 2638bf80f4bSopenharmony_ci{ 2648bf80f4bSopenharmony_ci return IsFunctionCompatibleImpl<FuncSignature>::Call(func); 2658bf80f4bSopenharmony_ci} 2668bf80f4bSopenharmony_ci 2678bf80f4bSopenharmony_ciMETA_END_NAMESPACE() 2688bf80f4bSopenharmony_ci 2698bf80f4bSopenharmony_ci#endif 270