-
Notifications
You must be signed in to change notification settings - Fork 0
/
function.cc
177 lines (149 loc) · 6.42 KB
/
function.cc
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
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
#include <functional>
#include <iostream>
#include <emacs-module.h>
using namespace std;
using namespace std::placeholders;
template<typename... Args>
using env_first_parameter_function_type = std::function<emacs_value(emacs_env*, Args...)>;
template<typename... Args>
using string_first_parameter_function_type = std::function<emacs_value(const std::string&, Args...)>;
using emacs_function_type = emacs_value(emacs_env*, ptrdiff_t, emacs_value*, void*);
// Strategy here is heavily derived (as in, 1 iota more complicated than Command-C, Command-V) from:
// https://stackoverflow.com/questions/21192659/variadic-templates-and-stdbind#21193316
// We create a custom placeholder so we can generate a sequence of
// them using integer_sequence. Additionally, we need to specialize
// is_placeholder for the new custom placeholder type so that
// std::bind recognizers our placeholders (which it does by testing if
// it's integral_constant<int, N> for N >= 1).
template<int>
struct bind_placeholder
{};
namespace std {
template<int N>
struct is_placeholder< bind_placeholder<N> >
: integral_constant<int, N> {};
}
template<int N, int... Sequence> struct make_int_sequence
: make_int_sequence<N-1, N, Sequence...> {}; // Move N to the beginning of the sequence and recurse with N - 1
template<int... Sequence> struct make_int_sequence<0, Sequence...> // Now Sequence represents all integers from 1 to N
: integer_sequence<int, Sequence...> {};
emacs_value func1(emacs_env* env, emacs_env* env1, emacs_env* env2, emacs_env* env3) {
cout << "Func1" << endl;
if (!env) {
cout << "emacs env is null" << endl;
return nullptr;
} else {
return env->intern(env, "nil");
}
}
// template<typename... Args>
// std::function<emacs_function_type>
// createFunctionWrapperForEmacs(env_first_parameter_function_type<Args...> func) {
// return [func] (emacs_env *env, ptrdiff_t nargs, emacs_value* args, void* data) -> emacs_value {
// if (env == nullptr) {
// cout << "Did not receive emacs_env from emacs" << endl;
// }
// std::function<emacs_value(Args...)> nextParamFunc = std::bind(func, env, _1);
// return createFunctionWrapperForEmacs(nextParamFunc)(env, nargs, args, data);
// };
// }
// template<typename... Args>
// std::function<emacs_function_type>
// createFunctionWrapperForEmacs(string_first_parameter_function_type<Args...> func) {
// return [func] (emacs_env *env, ptrdiff_t nargs, emacs_value* args, void* data) -> emacs_value {
// cout << "hello, emacs 1st param string!" << endl;
// auto nextParamFunc = std::bind(func, "hello");
// return env->intern(env, "nil");
// };
// }
// template<typename... Args>
// std::function<emacs_value(emacs_env*, ptrdiff_t, emacs_value*, void*)>
// createFunctionWrapperForEmacs(std::function<emacs_value(Args...)> func) {
// return createFunctionWrapperForEmacs(func, 0);
// }
template<typename Callable, int... Is>
auto varargs_bind(Callable c, emacs_env* env, integer_sequence<int, Is...>) {
return std::bind(c, env, bind_placeholder<Is>{}...);
}
template<typename... Args>
std::function<emacs_value(emacs_env*, ptrdiff_t, emacs_value*, void*)>
createFunctionWrapperForEmacs(std::function<emacs_value(emacs_env*, Args...)> func) {
cout << "Currying emacs_env" << endl;
std::function<emacs_value(emacs_env*, ptrdiff_t, emacs_value*, void*)> l = [func] (emacs_env* env, ptrdiff_t nargs, emacs_value* args, void* data) {
if (env == nullptr) {
cout << "Emacs_env was invalid" << endl;
}
std::function<emacs_value(Args...)> f = varargs_bind(func, env, make_int_sequence<sizeof...(Args)>{});
return createFunctionWrapperForEmacs(f)(env, nargs, args, data);
};
return l;
}
std::function<emacs_value(emacs_env*, ptrdiff_t, emacs_value*, void*)>
createFunctionWrapperForEmacs(std::function<emacs_value()> func) {
cout << "Final function generation" << endl;
auto l = [func] (emacs_env* env, ptrdiff_t nargs, emacs_value* args, void*) {
return func();
};
return l;
}
// template<typename... Args>
// std::function<emacs_value(emacs_env*, ptrdiff_t, emacs_value*, void*)>
// createFunctionWrapperForEmacs(std::function<emacs_value(const std::string&)> func,
// int argNumber) {
// cout << "Currying string" << endl;
// auto l = [argNumber, func] (emacs_env* env, ptrdiff_t nargs, emacs_value* args, void*) {
// };
// return l;
// }
template<typename Fn>
void register_emacs_function(emacs_env* env, Fn fn) {
cout << "hello, register!" << endl;
}
// debugging aid
template<int... ints>
void print_sequence(std::integer_sequence<int, ints...> int_seq) {
std::cout << "The sequence of size " << int_seq.size() << ": ";
((std::cout << ints << ' '),...);
std::cout << '\n';
return;
}
int main(int argc, char* argv[]) {
createFunctionWrapperForEmacs(std::function<emacs_value(emacs_env*, emacs_env*, emacs_env*, emacs_env*)>(func1))(nullptr, 3, nullptr, nullptr);
auto n = make_int_sequence<5>{};
print_sequence(n);
cout << "hello, world!" << endl;
}
// template<typename... Args>
// std::function<emacs_value(emacs_env*, ptrdiff_t, emacs_value*, void*)>
// createFunctionWrapperForEmacs(std::function<emacs_value(const std::string&, Args...)> func,
// int argNumber) {
// cout << "hello, emacs 1st param string!" << endl;
// std::function<emacs_value(emacs_env*, ptrdiff_t, emacs_value*, void*)> f = [argNumber, func] (emacs_env* env, ptrdiff_t nargs, emacs_value* args, void*) {
// ptrdiff_t string_length;
// char* argument = NULL;
// bool ret = env->copy_string_contents(env, args[argNumber], NULL, &string_length);
// if (!ret) {
// abort();
// }
// argument = (char *)malloc(string_length);
// if (!argument) {
// abort();
// }
// ret = env->copy_string_contents(env, args[argNumber], argument, &string_length);
// if (!ret) {
// free(argument);
// abort();
// }
// std::function<emacs_value(Args...)> curried = std::bind(func, argument, _1);
// createFunctionWrapperForEmacs(env, curried, argNumber + 1);
// };
// return testFunc;
// }
// template<typename R, typename... Args>
// std::function<emacs_value(emacs_env*, ptrdiff_t, emacs_value*, void*)>
// createFunctionWrapperForEmacs(emacs_env * env,
// R (*func)(emacs_env* env, int a, Args...),
// int argNumber) {
// cout << "hello, emacs 1st param int!" << endl;
// return testFunc;
// }