File Coverage

/usr/local/lib/perl5/site_perl/5.26.1/x86_64-linux/XS/libpanda.x/i/panda/function_utils.h
Criterion Covered Total %
statement 12 19 63.1
branch 4 18 22.2
condition n/a
subroutine n/a
pod n/a
total 16 37 43.2


line stmt bran cond sub pod time code
1             #pragma once
2             #include "refcnt.h"
3             #include "traits.h"
4             #include
5              
6             namespace panda {
7              
8             template
9             class function;
10              
11             namespace function_details {
12 3           struct AnyFunction {
13 0 0         virtual ~AnyFunction() {}
14              
15 0           virtual const AnyFunction* get_base() const {
16 0           return this;
17             }
18             };
19             }
20              
21              
22             template
23 6           struct Ifunction : function_details::AnyFunction, virtual Refcnt {
24 0 0         virtual ~Ifunction() {}
    0          
25             virtual Ret operator()(Args...) = 0;
26             virtual bool equals(const function_details::AnyFunction* oth) const = 0;
27             };
28              
29             namespace function_details {
30              
31             template
32             class abstract_function {};
33              
34             template
35             class storage {
36             public:
37             template
38 6           explicit storage(F&& f) : func(std::forward(f)) {}
39              
40             std::remove_reference_t func;
41             };
42              
43             template
44             class callable {};
45              
46             template
47             class callable : public storage
48             {
49             public:
50             template
51 6           explicit callable(F&& f) : storage(std::forward(f)) {}
52              
53 3           Ret operator()(Self&, Args... args) {
54 3           return this->func(args...);
55             }
56             };
57              
58              
59             template
60             class callable : public storage
61             {
62             public:
63             template
64             explicit callable(F&& f) : storage(std::forward(f)) {}
65              
66             Ret operator()(Self& self, Args... args) {
67             return this->func(self, args...);
68             }
69             };
70              
71             template
72             class abstract_function : public Ifunction, public storage {
73             public:
74             template
75             explicit abstract_function(F&& f) : storage(std::forward(f)) {}
76              
77             Ret operator()(Args... args) override {
78             static_assert(std::is_convertiblefunc(args...)), Ret>::value, "return type mismatch");
79             return this->func(args...);
80             }
81              
82             bool equals(const AnyFunction* oth) const override {
83             auto foth = dynamic_cast*>(oth->get_base());
84             if (foth == nullptr) {
85             return false;
86             }
87              
88             return this->func == foth->func;
89             }
90             };
91              
92             template
93 0 0         class abstract_function : public Ifunction
    0          
94             , public callable::value, Ifunction, Args...>
95             {
96             public:
97             using Derfed = std::remove_reference_t;
98             using Caller = callable::value, Ifunction, Args...>;
99              
100             template
101 3 50         explicit abstract_function(F&& f) : Caller(std::forward(f)) {}
    50          
102              
103 3           Ret operator()(Args... args) override {
104 3           return Caller::operator()(*this, args...);
105             }
106              
107 0           bool equals(const AnyFunction* oth) const override {
108 0           return this->get_base() == oth->get_base();
109             }
110              
111             private:
112             template
113             Ret call(Args... args) {
114             return (this->template func.*meth)(args...);
115             }
116             };
117              
118              
119             template
120             class abstract_function : public Ifunction, public storage {
121             public:
122             using Func = FRet (*)(FArgs...);
123             explicit abstract_function(const Func& f) : storage(f) {}
124              
125             Ret operator()(Args... args) override {
126             return this->func(args...);
127             }
128              
129             bool equals(const AnyFunction* oth) const override {
130             auto foth = dynamic_cast*>(oth->get_base());
131             if (foth == nullptr) return false;
132              
133             return this->func == foth->func;
134             }
135             };
136              
137             template
138             struct function_caster : public Ifunction {
139             From src;
140             using Check = std::is_base_of;
141              
142             function_caster(From src) : src(src) {}
143              
144             Ret operator()(Args... args) override {
145             return src->operator()(args...);
146             }
147              
148             bool equals(const function_details::AnyFunction* oth) const override {
149             return src->equals(oth);
150             }
151              
152             const AnyFunction* get_base() const override {
153             return src->get_base();
154             }
155              
156              
157             };
158              
159             template
160             struct is_panda_function_t {
161             static constexpr bool value = false;
162             };
163              
164             template
165             struct is_panda_function_t> {
166             static constexpr bool value = true;
167             };
168              
169             template
170             auto make_abstract_function(Ret (*f)(Args...)) -> iptr> {
171             if (!f) return nullptr;
172             return new abstract_function(f);
173             }
174              
175             template
176             auto tmp_abstract_function(Ret (*f)(Args...)) -> abstract_function {
177             assert(f);
178             return abstract_function(f);
179             }
180              
181             template
182             bool IsComp = is_comparable>::value,
183             typename DeFunctor = std::remove_reference_t,
184             typename = std::enable_if_t&, Args...>::value ||
185             has_call_operator::value>,
186             typename = std::enable_if_t::value>,
187             typename = std::enable_if_t::value>>
188 3           iptr> make_abstract_function(Functor&& f) {
189 3 50         if (!bool_or(f, true)) return nullptr;
190 3 50         return new abstract_function(std::forward(f));
191             }
192              
193             template
194             bool IsComp = is_comparable>::value,
195             typename DeFunctor = std::remove_reference_t,
196             typename = std::enable_if_t&, Args...>::value ||
197             has_call_operator::value>,
198             typename = std::enable_if_t::value>,
199             typename = std::enable_if_t::value>>
200             abstract_function tmp_abstract_function (Functor&& f) {
201             assert(bool_or(f, true));
202             return abstract_function(std::forward(f));
203             }
204              
205             template
206             typename = std::enable_if_t, Args...>::value>>
207             auto make_abstract_function(const function& func) -> iptr> {
208             if (!func) return nullptr;
209             return new function_caster(func.func);
210             }
211              
212              
213             template
214             struct method : public Ifunction{
215             using Method = Ret (Class::*)(Args...);
216             using ifunction = Ifunction;
217              
218             method(Method method, iptr thiz = nullptr) : thiz(thiz), meth(method) {}
219             iptr bind(iptr thiz) {
220             this->thiz = thiz;
221             return iptr(this);
222             }
223              
224             Ret operator()(Args... args) override {
225             return (thiz.get()->*meth)(std::forward(args)...);
226             }
227              
228             bool equals(const AnyFunction* oth) const override {
229             auto moth = dynamic_cast*>(oth->get_base());
230             if (moth == nullptr) return false;
231              
232             return operator ==(*moth);
233             }
234              
235             bool operator==(const method& oth) const {
236             return thiz == oth.thiz && meth == oth.meth;
237             }
238              
239             bool operator !=(const method& oth) const {
240             return !operator ==(oth);
241             }
242              
243             explicit operator bool() const {
244             return thiz && meth;
245             }
246              
247             private:
248             iptr thiz;
249             Method meth;
250             };
251              
252             template
253             inline iptr> make_method(Ret (Class::*meth)(Args...), iptr thiz = nullptr) {
254             if (!meth) return nullptr;
255             return new method(meth, thiz);
256             }
257              
258             template
259             inline iptr> make_abstract_function(Ret (Class::*meth)(Args...), iptr thiz = nullptr) {
260             if (!meth) return nullptr;
261             return new method(meth, thiz);
262             }
263              
264             template
265             inline method tmp_abstract_function(Ret (Class::*meth)(Args...), iptr thiz = nullptr) {
266             assert(meth);
267             return method(meth, thiz);
268             }
269             }
270              
271             }