-
Notifications
You must be signed in to change notification settings - Fork 1
/
mrubyfunctional.hpp
134 lines (115 loc) · 3.33 KB
/
mrubyfunctional.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
#ifndef __MRUBYFUNCTIONAL_HPP__
#define __MRUBYFUNCTIONAL_HPP__
template<typename TFunc>
struct currier;
template<typename TRet, typename TArg>
struct currier< std::function<TRet(TArg)> >
{
using type = std::function<TRet(TArg)>;
const type result;
currier(const type fun) : result(fun) {}
};
template<typename TRet, typename TArgHead, typename ...TArgs>
struct currier< std::function<TRet(TArgHead, TArgs...)> >
{
using remaining_type = typename currier< std::function<TRet(TArgs...)> >::type;
using type = std::function<remaining_type(TArgHead)>;
const type result;
currier(const std::function<TRet(TArgHead, TArgs...)> fun) : result(
[=](const TArgHead& t)
{
return currier< std::function<TRet(TArgs...)> >(
[=](const TArgs&... ts)
{
return fun(t, ts...);
}
).result;
}
) {} // : result(
};
template <typename TRet, typename ...TArgs>
static auto curry(const std::function<TRet(TArgs...)> fun)
-> typename currier< std::function< TRet(TArgs...) > >::type
{
return currier< std::function< TRet(TArgs...) > >(fun).result;
}
template <typename TRet, typename ...TArgs>
static auto curry(TRet(*const fun)(TArgs...))
-> typename currier< std::function< TRet(TArgs...) > >::type
{
return currier< std::function< TRet(TArgs...) > >(fun).result;
}
template <int idx, typename TRet>
static TRet func_caller(mrb_state* mrb, TRet t, mrb_value* args)
{
return t;
}
template <int idx, typename TRet, typename TArgHead, typename ...TArgs>
static TRet func_caller(
mrb_state* mrb,
typename currier< std::function< TRet(TArgHead, TArgs...) > >::type fn,
mrb_value* args)
{
return func_caller<idx + 1, TRet, TArgs...>(
mrb,
fn(TypeBinder<TArgHead>::from_mrb_value(mrb, args[idx])),
args);
}
template <int idx, typename TArgHead>
static void void_func_caller(
mrb_state* mrb,
typename currier< std::function< void(TArgHead) > >::type fn,
mrb_value* args)
{
fn(TypeBinder<TArgHead>::from_mrb_value(mrb, args[idx]));
}
template <int idx, typename TArgHead, typename TArgHead2, typename ...TArgs>
static void void_func_caller(
mrb_state* mrb,
typename currier< std::function< void(TArgHead, TArgHead2, TArgs...) > >::type fn,
mrb_value* args)
{
void_func_caller<idx + 1, TArgHead2, TArgs...>(
mrb,
fn(TypeBinder<TArgHead>::from_mrb_value(mrb, args[idx])),
args);
}
template<typename TRet, typename ... TArgs>
struct mruby_func_called_returner
{
static mrb_value call(mrb_state* mrb, std::function<TRet(TArgs...)> func, mrb_value* args)
{
auto curried = curry(func);
TRet result = func_caller<0, TRet, TArgs...>(mrb, curried, args);
return TypeBinder<TRet>::to_mrb_value(mrb, result);
}
};
template<typename ... TArgs>
struct mruby_func_called_returner<void, TArgs...>
{
static mrb_value call(mrb_state* mrb, std::function<void(TArgs...)> func, mrb_value* args)
{
auto curried = curry(func);
void_func_caller<0, TArgs...>(mrb, curried, args);
return mrb_nil_value();
}
};
template<typename TRet>
struct mruby_func_called_returner<TRet>
{
static mrb_value call(mrb_state* mrb, std::function<TRet()> func, mrb_value* args)
{
TRet result = func();
return TypeBinder<TRet>::to_mrb_value(mrb, result);
}
};
template<>
struct mruby_func_called_returner<void>
{
static mrb_value call(mrb_state* mrb, std::function<void()> func, mrb_value* args)
{
func();
return mrb_nil_value();
}
};
#endif // __MRUBYFUNCTIONAL_HPP__