summaryrefslogtreecommitdiff
path: root/src/bin/eolian_mono/eolian/mono/type_impl.hh
diff options
context:
space:
mode:
authorLauro Moura <lauromoura@expertisesolutions.com.br>2017-11-23 21:50:16 -0300
committerLauro Moura <lauromoura@expertisesolutions.com.br>2017-12-04 15:47:50 -0300
commitd93e9ff286ce1961f530d56b5536881f47104ebd (patch)
treed9fd8cd25a64b9ab6b23ae34b92c342dc8e6b543 /src/bin/eolian_mono/eolian/mono/type_impl.hh
parent9391407319424c503a78479b407737ccead945b7 (diff)
eolian_mono: Added code for eolian_mono generator
Based on the eolian_cxx library generators. Buildsystem files will come in a future commmit.
Diffstat (limited to 'src/bin/eolian_mono/eolian/mono/type_impl.hh')
-rw-r--r--src/bin/eolian_mono/eolian/mono/type_impl.hh373
1 files changed, 373 insertions, 0 deletions
diff --git a/src/bin/eolian_mono/eolian/mono/type_impl.hh b/src/bin/eolian_mono/eolian/mono/type_impl.hh
new file mode 100644
index 0000000000..d6d753b88d
--- /dev/null
+++ b/src/bin/eolian_mono/eolian/mono/type_impl.hh
@@ -0,0 +1,373 @@
1#ifndef EOLIAN_MONO_TYPE_IMPL_HH
2#define EOLIAN_MONO_TYPE_IMPL_HH
3
4#include "grammar/generator.hpp"
5#include "grammar/klass_def.hpp"
6#include "grammar/case.hpp"
7#include "namespace.hh"
8
9namespace eolian_mono {
10
11namespace eina = efl::eina;
12
13template <typename T>
14T const* as_const_pointer(T* p) { return p; }
15
16attributes::regular_type_def replace_base_type(attributes::regular_type_def v, std::string name)
17{
18 v.base_type = name;
19 return v;
20}
21
22attributes::complex_type_def replace_outer(attributes::complex_type_def v, attributes::regular_type_def const& regular)
23{
24 v.outer = regular;
25 return v;
26}
27
28template <typename Array, typename F, int N, typename A>
29eina::optional<bool> call_match(Array const (&array)[N], F f, A a)
30{
31 typedef Array const* iterator_type;
32 iterator_type match_iterator = &array[0], match_last = match_iterator + N;
33 match_iterator = std::find_if(match_iterator, match_last, f);
34 if(match_iterator != match_last)
35 {
36 return a(match_iterator->function());
37 }
38 return {nullptr};
39}
40
41template <typename OutputIterator, typename Context>
42struct visitor_generate
43{
44 mutable OutputIterator sink;
45 Context const* context;
46 std::string c_type;
47 bool is_out;
48 bool is_return;
49
50 typedef visitor_generate<OutputIterator, Context> visitor_type;
51 typedef bool result_type;
52
53 bool operator()(attributes::regular_type_def const& regular) const
54 {
55 using attributes::regular_type_def;
56 struct match
57 {
58 eina::optional<std::string> name;
59 eina::optional<bool> has_own;
60 std::function<attributes::type_def::variant_type()> function;
61 }
62 const match_table[] =
63 {
64 // signed primitives
65 {"byte", nullptr, [&] { return replace_base_type(regular, " byte"); }}
66 , {"llong", nullptr, [&] { return replace_base_type(regular, " long"); }}
67 , {"int8", nullptr, [&] { return replace_base_type(regular, " byte"); }}
68 , {"int16", nullptr, [&] { return replace_base_type(regular, " short"); }}
69 , {"int32", nullptr, [&] { return replace_base_type(regular, " int"); }}
70 , {"int64", nullptr, [&] { return replace_base_type(regular, " long"); }}
71 , {"ssize", nullptr, [&] { return replace_base_type(regular, " long"); }}
72 // unsigned primitives
73 , {"ubyte", nullptr, [&] { return replace_base_type(regular, " byte"); }}
74 , {"ushort", nullptr, [&] { return replace_base_type(regular, " ushort"); }}
75 , {"uint", nullptr, [&] { return replace_base_type(regular, " uint"); }}
76 , {"ulong", nullptr, [&] { return replace_base_type(regular, " ulong"); }}
77 , {"ullong", nullptr, [&] { return replace_base_type(regular, " ulong"); }}
78 , {"uint8", nullptr, [&] { return replace_base_type(regular, " byte"); }}
79 , {"uint16", nullptr, [&] { return replace_base_type(regular, " ushort"); }}
80 , {"uint32", nullptr, [&] { return replace_base_type(regular, " uint"); }}
81 , {"uint64", nullptr, [&] { return replace_base_type(regular, " ulong"); }}
82 , {"size", nullptr, [&] { return replace_base_type(regular, " ulong"); }}
83
84 , {"ptrdiff", nullptr, [&] { return replace_base_type(regular, " long"); }}
85 , {"intptr", nullptr, [&] { return replace_base_type(regular, " System.IntPtr"); }}
86 , {"void_ptr", nullptr, [&] { return replace_base_type(regular, " System.IntPtr"); }}
87 , {"void", nullptr, [&]
88 {
89 regular_type_def r = regular;
90 r.namespaces.clear();
91 if (is_out) // @inout too
92 r.base_type = " System.IntPtr";
93 else
94 r.base_type = " void";
95 return r;
96 }}
97 , {"Error", nullptr, [&] // Eina.Error
98 {
99 return regular_type_def{" eina.Error", regular.base_qualifier, {}};
100 }} // TODO
101 , {"string", nullptr, [&]
102 {
103 regular_type_def r = regular;
104 r.base_qualifier.qualifier ^= qualifier_info::is_ref;
105 return replace_base_type(r, " System.String");
106 }}
107 , {"mstring", nullptr, [&]
108 {
109 regular_type_def r = regular;
110 r.base_qualifier.qualifier ^= qualifier_info::is_ref;
111 return replace_base_type(r, " System.String");
112 }}
113 , {"stringshare", nullptr, [&]
114 {
115 regular_type_def r = regular;
116 r.base_qualifier.qualifier ^= qualifier_info::is_ref;
117 return replace_base_type(r, " System.String");
118 }}
119 , {"any_value", true, [&]
120 { return regular_type_def{" eina.Value", regular.base_qualifier, {}};
121 }}
122 , {"any_value", false, [&]
123 { return regular_type_def{" eina.Value", regular.base_qualifier, {}};
124 }}
125 , {"any_value_ptr", nullptr, [&]
126 { return regular_type_def{" eina.Value", regular.base_qualifier, {}};
127 }} // FIXME add proper support for any_value_ptr
128 };
129 // if(regular.base_type == "void_ptr")
130 // {
131 // if(regular.base_qualifier & qualifier_info::is_ref)
132 // throw std::runtime_error("ref of void_ptr is invalid");
133 // return as_generator
134 // (
135 // lit("void") << (regular.base_qualifier & qualifier_info::is_const ? " const" : "")
136 // << "*"
137 // << (is_out ? "&" : "")
138 // )
139 // .generate(sink, attributes::unused, *context);
140 // }
141 // else
142 if(eina::optional<bool> b = call_match
143 (match_table
144 , [&] (match const& m)
145 {
146 return (!m.name || *m.name == regular.base_type)
147 && (!m.has_own || *m.has_own == (bool)(regular.base_qualifier & qualifier_info::is_own))
148 ;
149 }
150 , [&] (attributes::type_def::variant_type const& v)
151 {
152 return v.visit(*this); // we want to keep is_out info
153 }))
154 {
155 return *b;
156 }
157 // in A @optional -> optional<A>
158 // in A& @optional -> optional<A&>
159 // in A& @optional -> optional<A&>
160 // in own(A&) @optional -> A*
161 //
162 // out A @optional -> optional<A&>
163 // out A& @optional -> optional<A&>
164 // out own(A&) @optional -> optional<A*&>
165 // else if(regular.base_qualifier & qualifier_info::is_optional)
166 // {
167 // attributes::regular_type_def no_optional_regular = regular;
168 // no_optional_regular.base_qualifier.qualifier ^= qualifier_info::is_optional;
169 // if(is_out)
170 // {
171 // if(no_optional_regular.base_qualifier & qualifier_info::is_own)
172 // {
173 // return as_generator(" ::efl::eina::optional<").generate(sink, attributes::unused, *context)
174 // && (*this)(no_optional_regular)
175 // && as_generator("&>").generate(sink, attributes::unused, *context);
176 // }
177 // else if(no_optional_regular.base_qualifier & qualifier_info::is_ref)
178 // {
179 // no_optional_regular.base_qualifier.qualifier ^= qualifier_info::is_ref;
180 // return (*this)(no_optional_regular)
181 // && as_generator("**").generate(sink, attributes::unused, *context);
182 // }
183 // else
184 // return (*this)(no_optional_regular)
185 // && as_generator("*").generate(sink, attributes::unused, *context);
186 // }
187 // else
188 // {
189 // // regular.base_qualifier & qualifier_info::is_ref
190 // return as_generator(" ::efl::eina::optional<").generate(sink, attributes::unused, *context)
191 // && (*this)(no_optional_regular)
192 // && as_generator(">").generate(sink, attributes::unused, *context);
193 // }
194 // }
195 // else if((is_return || is_out) && regular.base_qualifier & qualifier_info::is_ref
196 // && regular.base_qualifier & qualifier_info::is_own)
197 // {
198 // if(as_generator
199 // (
200 // " ::std::unique_ptr<"
201 // << *(string << "_")
202 // << string
203 // << (regular.base_qualifier & qualifier_info::is_const ? " const" : "")
204 // << ", ::efl::eina::malloc_deleter>"
205 // )
206 // .generate(sink, std::make_tuple(regular.namespaces, regular.base_type), *context))
207 // return true;
208 // else
209 // return false;
210 // }
211 // else if(Eolian_Typedecl const* typedecl = eolian_typedecl_struct_get_by_name(c_type.c_str()))
212 // {
213 // return as_generator
214 // (
215 // *(string << ".")
216 // << string
217 // )
218 // .generate(sink, std::make_tuple(regular.namespaces, regular.base_type), *context);
219 // }
220 else
221 {
222 // as_generator(" Generating: " << *(lower_case[string] << ".") << string << "\n")
223 // .generate(std::ostream_iterator<char>(std::cerr), std::make_tuple(eolian_mono::escape_namespace(regular.namespaces), regular.base_type), *context);
224 if(as_generator
225 (
226 *(lower_case[string] << ".")
227 << string
228 // << (regular.base_qualifier & qualifier_info::is_const
229 // || (regular.base_qualifier & qualifier_info::is_ref
230 // && !is_return && !is_out)
231 // ? /*" const"*/ "" : "")
232 /*<< (regular.base_qualifier & qualifier_info::is_ref? "&" : "")*/
233 )
234 .generate(sink, std::make_tuple(eolian_mono::escape_namespace(regular.namespaces), regular.base_type), *context))
235 return true;
236 else
237 return false;
238 }
239 }
240 bool operator()(attributes::klass_name klass) const
241 {
242 // as_generator(" Generating: " << *(lower_case[string] << ".") << string << "\n")
243 // .generate(std::ostream_iterator<char>(std::cerr), std::make_tuple(attributes::cpp_namespaces(klass.namespaces), klass.eolian_name), *context);
244 // if(klass.namespaces.size() == 1
245 // && klass.namespaces[0] == "Eina"
246 // && klass.eolian_name == "Error")
247 // return
248 // as_generator(" System.IntPtr")
249 // .generate(sink, attributes::unused, *context);
250 return
251 as_generator(*(lower_case[string] << ".") << string)
252 .generate(sink, std::make_tuple(eolian_mono::escape_namespace(klass.namespaces), klass.eolian_name), *context)
253 // && (!(klass.base_qualifier & qualifier_info::is_ref)
254 // || as_generator("&").generate(sink, attributes::unused, *context))
255 ;
256 }
257 bool operator()(attributes::complex_type_def const& complex) const
258 {
259 using attributes::regular_type_def;
260 using attributes::complex_type_def;
261 using attributes::qualifier_info;
262 struct match
263 {
264 eina::optional<std::string> name;
265 eina::optional<bool> has_own;
266 eina::optional<bool> is_const;
267 std::function<attributes::type_def::variant_type()> function;
268 } const matches[] =
269 {
270 {"list", nullptr, nullptr, [&]
271 {
272 complex_type_def c = complex;
273 c.outer.base_type = "eina.List";
274 return c;
275 }}
276 , {"inlist", nullptr, nullptr, [&]
277 {
278 complex_type_def c = complex;
279 c.outer.base_type = "eina.Inlist";
280 return c;
281 }}
282 , {"array", nullptr, nullptr, [&]
283 {
284 complex_type_def c = complex;
285 c.outer.base_type = "eina.Array";
286 return c;
287 }}
288 , {"inarray", nullptr, nullptr, [&]
289 {
290 complex_type_def c = complex;
291 c.outer.base_type = "eina.Inarray";
292 return c;
293 }}
294 , {"hash", nullptr, nullptr
295 , [&]
296 {
297 complex_type_def c = complex;
298 c.outer.base_type = "eina.Hash";
299 return c;
300 }}
301 , {"promise", nullptr, nullptr, [&]
302 {
303 return replace_outer
304 (complex, regular_type_def{" ::efl::promise", complex.outer.base_qualifier, {}});
305 }
306 }
307 , {"future", nullptr, nullptr, [&]
308 {
309 (*this)(regular_type_def{" int", complex.outer.base_qualifier, {}});
310 return attributes::type_def::variant_type();
311 // return replace_outer
312 // (complex, regular_type_def{" ::efl::shared_future", complex.outer.base_qualifier, {}});
313 }
314 }
315 , {"iterator", nullptr, nullptr, [&]
316 {
317 complex_type_def c = complex;
318 c.outer.base_type = "eina.Iterator";
319 return c;
320 }
321 }
322 , {"accessor", nullptr, nullptr, [&]
323 {
324 (*this)(regular_type_def{" int", complex.outer.base_qualifier, {}});
325 return attributes::type_def::variant_type();
326 // return replace_outer
327 // (complex, regular_type_def{" ::efl::eina::accessor", complex.outer.base_qualifier, {}});
328 }
329 }
330 };
331
332 auto default_match = [&] (attributes::complex_type_def const& complex)
333 {
334 regular_type_def no_pointer_regular = complex.outer;
335 // std::vector<attributes::pointer_indirection> pointers;
336 // pointers.swap(no_pointer_regular.pointers);
337 // if(is_out)
338 // pointers.push_back({{attributes::qualifier_info::is_none, {}}, true});
339 return visitor_type{sink, context, c_type, false}(no_pointer_regular)
340 && as_generator("<" << (type % ", ") << ">").generate(sink, complex.subtypes, *context)
341 ;
342 // && detail::generate_pointers(sink, pointers, *context, false);
343 };
344
345 if(eina::optional<bool> b = call_match
346 (matches
347 , [&] (match const& m)
348 {
349 return (!m.name || *m.name == complex.outer.base_type)
350 && (!m.has_own || *m.has_own == bool(complex.outer.base_qualifier & qualifier_info::is_own))
351 && (!m.is_const || *m.is_const == bool(complex.outer.base_qualifier & qualifier_info::is_const));
352 }
353 , [&] (attributes::type_def::variant_type const& v)
354 {
355 if(v.empty())
356 return true;
357 else if(attributes::complex_type_def const* complex
358 = eina::get<attributes::complex_type_def>(&v))
359 return default_match(*complex);
360 else
361 return v.visit(*this);
362 }))
363 return *b;
364 else
365 {
366 return default_match(complex);
367 }
368 }
369};
370
371}
372
373#endif