summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFelipe Magno de Almeida <felipe@expertisesolutions.com.br>2018-01-17 21:39:42 -0200
committerFelipe Magno de Almeida <felipe@expertisesolutions.com.br>2018-01-17 21:39:42 -0200
commit1440ff4c9be3a01f889b78cb0713e65252153f59 (patch)
treed09083d5602303b41f49fe9728d52df64e97fa5f
parent166c371e93505adfcc6217c706ec704c30b99450 (diff)
eolian-js: Add parameter passing code
-rw-r--r--src/bin/eolian_js/eolian/grammar/class_registration.hpp15
-rw-r--r--src/bin/eolian_js/eolian/grammar/out_parameter_definition.hpp112
-rw-r--r--src/bin/eolian_js/eolian/grammar/parameter.hpp102
-rw-r--r--src/bin/eolian_js/eolian/grammar/stub_function_definition.hpp32
-rw-r--r--src/bin/eolian_js/main.cc38
-rw-r--r--src/bindings/js/eina_js/eina_js_get_value.hh42
-rw-r--r--src/lib/eolian_cxx/grammar/empty_generator.hpp34
-rw-r--r--src/lib/eolian_cxx/grammar/if.hpp131
8 files changed, 488 insertions, 18 deletions
diff --git a/src/bin/eolian_js/eolian/grammar/class_registration.hpp b/src/bin/eolian_js/eolian/grammar/class_registration.hpp
index d6e5cac4b4..f9b072f077 100644
--- a/src/bin/eolian_js/eolian/grammar/class_registration.hpp
+++ b/src/bin/eolian_js/eolian/grammar/class_registration.hpp
@@ -7,6 +7,8 @@
7#include <grammar/attribute_reorder.hpp> 7#include <grammar/attribute_reorder.hpp>
8#include <grammar/attributed.hpp> 8#include <grammar/attributed.hpp>
9#include <grammar/attribute_replace.hpp> 9#include <grammar/attribute_replace.hpp>
10#include <grammar/if.hpp>
11#include <grammar/empty_generator.hpp>
10#include <eolian/grammar/stub_function_definition.hpp> 12#include <eolian/grammar/stub_function_definition.hpp>
11 13
12namespace eolian { namespace js { namespace grammar { 14namespace eolian { namespace js { namespace grammar {
@@ -49,12 +51,15 @@ struct class_registration_generator
49 ( 51 (
50 attribute_reorder<0, 1, 2, 3, 0, 1, 0, 1> 52 attribute_reorder<0, 1, 2, 3, 0, 1, 0, 1>
51 ( 53 (
52 "static void register_prototype_" 54 "static void register_prototype_"
53 << lower_case[*(string << "_")] 55 << lower_case[*(string << "_")]
54 << lower_case[string] 56 << lower_case[string]
55 << "(v8::Handle<v8::Object> global, v8::Local<v8::ObjectTemplate> prototype, v8::Isolate* isolate)\n" 57 << "(v8::Handle<v8::Object> global, v8::Local<v8::ObjectTemplate> prototype, v8::Isolate* isolate)\n"
56 << "{\n" 58 << "{\n"
57 << *attribute_reorder<1, 1, 1, 1> 59 << *
60 if_([] (attributes::function_def const& f) { return !f.is_beta && !f.is_protected; })
61 [
62 attribute_reorder<1, 1, 1, 1>
58 ( 63 (
59 scope_tab << "prototype->Set( ::efl::eina::js::compatibility_new<v8::String>(isolate, \"" 64 scope_tab << "prototype->Set( ::efl::eina::js::compatibility_new<v8::String>(isolate, \""
60 << attribute_replace(&eolian::js::format::format_method)[string] << "\")\n" 65 << attribute_replace(&eolian::js::format::format_method)[string] << "\")\n"
@@ -66,8 +71,9 @@ struct class_registration_generator
66 << lower_case[string] << "_" 71 << lower_case[string] << "_"
67 ] 72 ]
68 << lower_case[string] 73 << lower_case[string]
69 << "));\n" 74 << "));\n"
70 ) 75 )
76 ][empty_generator]
71 << 77 <<
72 *( 78 *(
73 scope_tab << "register_prototype_" 79 scope_tab << "register_prototype_"
@@ -88,7 +94,8 @@ struct class_registration_generator
88 << lower_case[string] 94 << lower_case[string]
89 << "(global, prototype, isolate);\n" 95 << "(global, prototype, isolate);\n"
90 << "}\n" 96 << "}\n"
91 )).generate(sink, std::make_tuple(cls.namespaces, cls.cxx_name, cls.functions, cls.immediate_inherits), context); 97 )).generate(sink, std::make_tuple(cls.namespaces, cls.cxx_name, cls.functions, cls.immediate_inherits
98 , cls.eolian_name), context);
92 99
93 as_generator 100 as_generator
94 ( 101 (
diff --git a/src/bin/eolian_js/eolian/grammar/out_parameter_definition.hpp b/src/bin/eolian_js/eolian/grammar/out_parameter_definition.hpp
new file mode 100644
index 0000000000..a90b1a5408
--- /dev/null
+++ b/src/bin/eolian_js/eolian/grammar/out_parameter_definition.hpp
@@ -0,0 +1,112 @@
1#ifndef EOLIAN_JS_OUT_PARAMETER_DEFINITION_HPP
2#define EOLIAN_JS_OUT_PARAMETER_DEFINITION_HPP
3
4#include <grammar/klass_def.hpp>
5#include <grammar/indentation.hpp>
6#include <grammar/string.hpp>
7#include <grammar/attribute_reorder.hpp>
8#include <grammar/attributed.hpp>
9#include <grammar/attribute_replace.hpp>
10#include <eolian/grammar/stub_function_definition.hpp>
11
12namespace eolian { namespace js { namespace grammar {
13
14namespace attributes = efl::eolian::grammar::attributes;
15
16template <typename ParameterContainer, typename Generator>
17struct out_parameter_definition_generator
18{
19 out_parameter_definition_generator(attributes::klass_def const& cls, ParameterContainer const& container
20 , Generator prefix_generator)
21 : klass(cls), container(container), prefix_generator(prefix_generator) {}
22
23 template <typename OutputIterator, typename Context>
24 bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
25 {
26 using namespace efl::eolian::grammar;
27 using efl::eolian::grammar::attributes::unused;
28 namespace attributes = efl::eolian::grammar::attributes;
29
30 std::size_t index;
31 {
32 auto iterator = std::find(container.begin(), container.end(), param);
33 assert(iterator != container.end());
34 index = std::distance(container.begin(), iterator);
35 }
36
37 switch(param.direction)
38 {
39 case attributes::parameter_direction::in:
40 break;
41 case attributes::parameter_direction::inout:
42 case attributes::parameter_direction::out:
43 attributes::generate(prefix_generator, sink, param, context);
44
45 as_generator(string
46 << " __out_"
47 << string
48 ).generate(sink, std::make_tuple(param.type.c_type, param.param_name), context);
49
50 if(param.direction == attributes::parameter_direction::inout)
51 as_generator(" = ::efl::eina::js::get_value_from_javascript(args["
52 << string
53 << "], isolate, \"\", ::efl::eina::js::value_tag< "
54 << string
55 << " >{})"
56 ).generate(sink, std::make_tuple(std::to_string(index), param.type.c_type), context);
57
58 *sink++ = ';';
59 *sink++ = '\n';
60 break;
61 };
62
63
64 return true;
65 }
66
67 attributes::klass_def klass;
68 ParameterContainer const& container;
69 Generator prefix_generator;
70};
71
72template <typename ParameterContainer>
73struct out_parameter_definition_directive
74{
75 template <typename Generator>
76 out_parameter_definition_generator<ParameterContainer, Generator>
77 operator[](Generator const& gen) const
78 {
79 return {klass, container, gen};
80 }
81
82 attributes::klass_def klass;
83 ParameterContainer const& container;
84};
85
86template <typename ParameterContainer>
87out_parameter_definition_directive<ParameterContainer>
88out_parameter_definition(attributes::klass_def const& cls, ParameterContainer const& container)
89{
90 return {cls, container};
91}
92
93} } }
94
95namespace efl { namespace eolian { namespace grammar {
96
97template <typename ParameterContainer, typename Generator>
98struct is_generator< ::eolian::js::grammar::out_parameter_definition_generator<ParameterContainer, Generator> > : std::true_type {};
99template <typename ParameterContainer, typename Generator>
100struct is_eager_generator< ::eolian::js::grammar::out_parameter_definition_generator<ParameterContainer, Generator>> : std::true_type {};
101
102namespace type_traits {
103
104template <typename ParameterContainer, typename Generator>
105struct attributes_needed< ::eolian::js::grammar::out_parameter_definition_generator<ParameterContainer, Generator>> : std::integral_constant<int, 1> {};
106template <typename ParameterContainer, typename Generator>
107struct accepts_specific_tuple< ::eolian::js::grammar::out_parameter_definition_generator<ParameterContainer, Generator>
108 , ::efl::eolian::grammar::attributes::parameter_def > : std::true_type {};
109
110} } } }
111
112#endif
diff --git a/src/bin/eolian_js/eolian/grammar/parameter.hpp b/src/bin/eolian_js/eolian/grammar/parameter.hpp
new file mode 100644
index 0000000000..5c22715874
--- /dev/null
+++ b/src/bin/eolian_js/eolian/grammar/parameter.hpp
@@ -0,0 +1,102 @@
1#ifndef EOLIAN_JS_PARAMETER_HPP
2#define EOLIAN_JS_PARAMETER_HPP
3
4#include <grammar/klass_def.hpp>
5#include <grammar/indentation.hpp>
6#include <grammar/string.hpp>
7#include <grammar/attribute_reorder.hpp>
8#include <grammar/attributed.hpp>
9#include <grammar/attribute_replace.hpp>
10#include <eolian/grammar/stub_function_definition.hpp>
11
12namespace eolian { namespace js { namespace grammar {
13
14namespace attributes = efl::eolian::grammar::attributes;
15
16template <typename ParameterContainer>
17struct parameter_generator
18{
19 parameter_generator(attributes::klass_def const& cls, ParameterContainer const& container)
20 : klass(cls), container(container) {}
21
22 template <typename OutputIterator, typename Context>
23 bool generate(OutputIterator sink, attributes::parameter_def const& param, Context const& context) const
24 {
25 using namespace efl::eolian::grammar;
26 using efl::eolian::grammar::attributes::unused;
27 namespace attributes = efl::eolian::grammar::attributes;
28
29 std::size_t index;
30 {
31 auto iterator = std::find(container.begin(), container.end(), param);
32 assert(iterator != container.end());
33 index = std::distance(container.begin(), iterator);
34 }
35
36 bool is_function_ptr = false;
37 if(attributes::regular_type_def const* def
38 = ::efl::eina::get<attributes::regular_type_def>(&param.type.original_type))
39 {
40 is_function_ptr = def->is_function_ptr();
41 }
42
43 if(is_function_ptr)
44 {
45 as_generator(" NULL, NULL, NULL").generate(sink, unused, context);
46 }
47 else
48 {
49 switch(param.direction)
50 {
51 case attributes::parameter_direction::in:
52 as_generator(" ::efl::eina::js::get_value_from_javascript(args["
53 << string
54 << "], isolate, \"\", ::efl::eina::js::value_tag< "
55 << string
56 << " >{})"
57 ).generate(sink, std::make_tuple(std::to_string(index), param.type.c_type), context);
58 break;
59 case attributes::parameter_direction::inout:
60 case attributes::parameter_direction::out:
61 as_generator("&__out_"
62 << string
63 ).generate(sink, param.param_name, context);
64 break;
65 };
66 }
67
68 return true;
69 }
70
71 attributes::klass_def klass;
72 ParameterContainer const& container;
73};
74
75
76template <typename ParameterContainer>
77parameter_generator<ParameterContainer>
78parameter(attributes::klass_def const& cls, ParameterContainer const& container)
79{
80 return {cls, container};
81}
82
83} } }
84
85namespace efl { namespace eolian { namespace grammar {
86
87template <typename ParameterContainer>
88struct is_generator< ::eolian::js::grammar::parameter_generator<ParameterContainer> > : std::true_type {};
89template <typename ParameterContainer>
90struct is_eager_generator< ::eolian::js::grammar::parameter_generator<ParameterContainer>> : std::true_type {};
91
92namespace type_traits {
93
94template <typename ParameterContainer>
95struct attributes_needed< ::eolian::js::grammar::parameter_generator<ParameterContainer>> : std::integral_constant<int, 1> {};
96template <typename ParameterContainer>
97struct accepts_specific_tuple< ::eolian::js::grammar::parameter_generator<ParameterContainer>
98 , ::efl::eolian::grammar::attributes::parameter_def > : std::true_type {};
99
100} } } }
101
102#endif
diff --git a/src/bin/eolian_js/eolian/grammar/stub_function_definition.hpp b/src/bin/eolian_js/eolian/grammar/stub_function_definition.hpp
index d5d7169431..f3ba9f084b 100644
--- a/src/bin/eolian_js/eolian/grammar/stub_function_definition.hpp
+++ b/src/bin/eolian_js/eolian/grammar/stub_function_definition.hpp
@@ -5,6 +5,8 @@
5#include <grammar/indentation.hpp> 5#include <grammar/indentation.hpp>
6#include <grammar/string.hpp> 6#include <grammar/string.hpp>
7#include <grammar/attribute_reorder.hpp> 7#include <grammar/attribute_reorder.hpp>
8#include <eolian/grammar/parameter.hpp>
9#include <eolian/grammar/out_parameter_definition.hpp>
8 10
9namespace eolian { namespace js { namespace grammar { 11namespace eolian { namespace js { namespace grammar {
10 12
@@ -21,6 +23,9 @@ struct stub_function_definition_generator
21 using namespace efl::eolian::grammar; 23 using namespace efl::eolian::grammar;
22 using efl::eolian::grammar::attributes::unused; 24 using efl::eolian::grammar::attributes::unused;
23 25
26 if(f.is_beta || f.is_protected)
27 return true;
28
24 // std::string suffix; 29 // std::string suffix;
25 // switch(cls.type) 30 // switch(cls.type)
26 // { 31 // {
@@ -45,7 +50,7 @@ struct stub_function_definition_generator
45 50
46 as_generator 51 as_generator
47 ( 52 (
48 //attribute_reorder<0, 1, 0, 1, 0, 1> 53 attribute_reorder<0, 1, 2, 3, 4, 3>
49 ( 54 (
50 "eina::js::compatibility_return_type stub_function_" 55 "eina::js::compatibility_return_type stub_function_"
51 << lower_case[*(string << "_")] 56 << lower_case[*(string << "_")]
@@ -54,14 +59,21 @@ struct stub_function_definition_generator
54 << lower_case[string] 59 << lower_case[string]
55 << "(eina::js::compatibility_callback_info_type args)\n" 60 << "(eina::js::compatibility_callback_info_type args)\n"
56 << "{\n" 61 << "{\n"
57 << scope_tab << "if(/*input_parameters*/" << std::to_string(ins) << " != args.Length())\n" 62 << scope_tab << "if(/*input_parameters*/" << std::to_string(ins) << " == args.Length())\n"
58 << scope_tab << "{\n" 63 << scope_tab << "{\n"
64 << scope_tab(2) << "v8::Isolate* isolate = args.GetIsolate(); static_cast<void>(isolate);\n"
59 << scope_tab(2) << "v8::Local<v8::Object> self = args.This();\n" 65 << scope_tab(2) << "v8::Local<v8::Object> self = args.This();\n"
60 << scope_tab(2) << "v8::Local<v8::Value> external = self->GetInternalField(0);\n" 66 << scope_tab(2) << "v8::Local<v8::Value> external = self->GetInternalField(0);\n"
61 << scope_tab(2) << "Eo* eo = static_cast<Eo*>(v8::External::Cast(*external)->Value());\n" 67 << scope_tab(2) << "Eo* eo = static_cast<Eo*>(v8::External::Cast(*external)->Value());\n"
62 << scope_tab(2) << "try\n" 68 << scope_tab(2) << "try\n"
63 << scope_tab(2) << "{\n" 69 << scope_tab(2) << "{\n"
64 << scope_tab(3) << ";" 70 << *(out_parameter_definition(klass, f.parameters)[scope_tab(3)])
71 << scope_tab(3) << "::" << lower_case[string]
72 << "("
73 << "eo"
74 << *(", " << parameter(klass, f.parameters))
75 << ")"
76 << ";\n"
65 << scope_tab(2) << "}\n" 77 << scope_tab(2) << "}\n"
66 << scope_tab(2) << "catch(std::logic_error const&)\n" 78 << scope_tab(2) << "catch(std::logic_error const&)\n"
67 << scope_tab(2) << "{\n" 79 << scope_tab(2) << "{\n"
@@ -75,7 +87,8 @@ struct stub_function_definition_generator
75 << scope_tab(4) << "(eina::js::compatibility_new<v8::String>(nullptr, \"Expected more arguments for this call\")));\n" 87 << scope_tab(4) << "(eina::js::compatibility_new<v8::String>(nullptr, \"Expected more arguments for this call\")));\n"
76 << scope_tab << "}\n" 88 << scope_tab << "}\n"
77 << "}\n" 89 << "}\n"
78 )).generate(sink, std::make_tuple(klass.namespaces, klass.cxx_name, f.name), context); 90 )).generate(sink, std::make_tuple(klass.namespaces, klass.cxx_name, f.name, f.parameters
91 , f.c_name), context);
79 92
80 // methods 93 // methods
81 94
@@ -104,7 +117,16 @@ template <>
104struct is_generator< ::eolian::js::grammar::stub_function_definition_generator> : std::true_type {}; 117struct is_generator< ::eolian::js::grammar::stub_function_definition_generator> : std::true_type {};
105template <> 118template <>
106struct is_eager_generator< ::eolian::js::grammar::stub_function_definition_generator> : std::true_type {}; 119struct is_eager_generator< ::eolian::js::grammar::stub_function_definition_generator> : std::true_type {};
120
121namespace type_traits {
122
123template <>
124struct attributes_needed< ::eolian::js::grammar::stub_function_definition_generator> : std::integral_constant<int, 1> {};
125template <>
126struct accepts_specific_tuple< ::eolian::js::grammar::stub_function_definition_generator
127 , ::efl::eolian::grammar::attributes::function_def> : std::true_type {};
128
107 129
108} } } 130} } } }
109 131
110#endif 132#endif
diff --git a/src/bin/eolian_js/main.cc b/src/bin/eolian_js/main.cc
index 6d755da249..7dced737d2 100644
--- a/src/bin/eolian_js/main.cc
+++ b/src/bin/eolian_js/main.cc
@@ -702,17 +702,21 @@ int main(int argc, char** argv)
702 } 702 }
703 }; 703 };
704 704
705 os << "extern \"C\" {\n\n"; 705 auto generate_includes =
706 706 [&]
707 auto includes_fun = [&os] (Eolian_Class const* klass)
708 { 707 {
708 os << "extern \"C\" {\n\n";
709
710 auto includes_fun = [&os] (Eolian_Class const* klass)
711 {
712 os << "#include <" << eolian_class_file_get(klass) << ".h>\n\n";
713 };
714 // generate include for all inheritance
715 recurse_inherits(klass, includes_fun);
709 os << "#include <" << eolian_class_file_get(klass) << ".h>\n\n"; 716 os << "#include <" << eolian_class_file_get(klass) << ".h>\n\n";
710 };
711 // generate include for all inheritance
712 recurse_inherits(klass, includes_fun);
713 os << "#include <" << eolian_class_file_get(klass) << ".h>\n\n";
714 717
715 os << "}\n\n"; 718 os << "}\n\n";
719 };
716 720
717 using efl::eolian::grammar::attributes::unused; 721 using efl::eolian::grammar::attributes::unused;
718 using efl::eolian::grammar::context_null; 722 using efl::eolian::grammar::context_null;
@@ -720,9 +724,26 @@ int main(int argc, char** argv)
720 using efl::eolian::grammar::lower_case; 724 using efl::eolian::grammar::lower_case;
721 using efl::eolian::grammar::string; 725 using efl::eolian::grammar::string;
722 using efl::eolian::grammar::as_generator; 726 using efl::eolian::grammar::as_generator;
727 using efl::eolian::grammar::attribute_reorder;
728 using efl::eolian::grammar::upper_case;
723 if(!dummy_generation) 729 if(!dummy_generation)
724 { 730 {
725 context_null context; 731 context_null context;
732
733 // as_generator
734 // (attribute_reorder<0, 1, 0, 1>
735 // (
736 // "#define "
737 // << *(upper_case[string] << "_")
738 // << upper_case[string]
739 // << "_BETA\n"
740 // "#define "
741 // << *(upper_case[string] << "_")
742 // << upper_case[string]
743 // << "_PROTECTED\n"
744 // )).generate(iterator, std::make_tuple(klass_def.namespaces, klass_def.eolian_name), context);
745
746 generate_includes();
726 747
727 as_generator("namespace efl { namespace js { namespace binding { namespace {\n") 748 as_generator("namespace efl { namespace js { namespace binding { namespace {\n")
728 .generate(iterator, unused, context); 749 .generate(iterator, unused, context);
@@ -753,6 +774,7 @@ int main(int argc, char** argv)
753 } 774 }
754 else 775 else
755 { 776 {
777 generate_includes();
756 as_generator 778 as_generator
757 ( 779 (
758 "namespace efl { namespace js { namespace binding { namespace {\n" 780 "namespace efl { namespace js { namespace binding { namespace {\n"
diff --git a/src/bindings/js/eina_js/eina_js_get_value.hh b/src/bindings/js/eina_js/eina_js_get_value.hh
index 450ba067fc..c7aa483bea 100644
--- a/src/bindings/js/eina_js/eina_js_get_value.hh
+++ b/src/bindings/js/eina_js/eina_js_get_value.hh
@@ -35,6 +35,18 @@ inline int get_value_from_javascript
35 return 0; 35 return 0;
36} 36}
37 37
38template <typename T>
39inline T get_value_from_javascript
40 (v8::Local<v8::Value> v
41 , v8::Isolate* isolate
42 , const char*
43 , value_tag<T>
44 , bool throw_js_exception = true
45 , typename std::enable_if<(std::is_pointer<T>::value && std::is_function<typename std::remove_pointer<T>::type>::value)>::type* = 0)
46{
47 return 0;
48}
49
38inline char* get_value_from_javascript 50inline char* get_value_from_javascript
39 (v8::Local<v8::Value> v 51 (v8::Local<v8::Value> v
40 , v8::Isolate* isolate 52 , v8::Isolate* isolate
@@ -262,7 +274,35 @@ inline T get_value_from_javascript
262 !std::is_same<T, const Eina_Array*>::value && 274 !std::is_same<T, const Eina_Array*>::value &&
263 !std::is_same<T, const Eina_Iterator*>::value && 275 !std::is_same<T, const Eina_Iterator*>::value &&
264 !std::is_same<T, const Eina_Hash*>::value && 276 !std::is_same<T, const Eina_Hash*>::value &&
265 !std::is_same<T, const Eina_List*>::value 277 !std::is_same<T, const Eina_List*>::value &&
278 !std::is_function<typename std::remove_pointer<T>::type>::value
279 >::type* = 0)
280{
281 if (throw_js_exception)
282 eina::js::compatibility_throw
283 (isolate, v8::Exception::TypeError
284 (eina::js::compatibility_new<v8::String>(isolate, "Not implemented yet")));
285 throw std::logic_error("");
286}
287
288// TODO:
289template <typename T>
290inline T get_value_from_javascript
291 (v8::Local<v8::Value>, v8::Isolate* isolate, const char*, value_tag<T>
292 , bool throw_js_exception = true
293 , typename std::enable_if<
294 std::is_same<T, Eina_Accessor*>::value ||
295 std::is_same<T, Eina_Array*>::value ||
296 std::is_same<T, Eina_Iterator*>::value ||
297 std::is_same<T, Eina_Hash*>::value ||
298 std::is_same<T, Eina_List*>::value ||
299 std::is_same<T, const Eina_Accessor*>::value ||
300 std::is_same<T, const Eina_Array*>::value ||
301 std::is_same<T, const Eina_Iterator*>::value ||
302 std::is_same<T, const Eina_Hash*>::value ||
303 std::is_same<T, const Eina_List*>::value ||
304 std::is_same<T, Eina_Iterator*>::value ||
305 std::is_same<T, const Eina_Iterator*>::value
266 >::type* = 0) 306 >::type* = 0)
267{ 307{
268 if (throw_js_exception) 308 if (throw_js_exception)
diff --git a/src/lib/eolian_cxx/grammar/empty_generator.hpp b/src/lib/eolian_cxx/grammar/empty_generator.hpp
new file mode 100644
index 0000000000..30077f54b9
--- /dev/null
+++ b/src/lib/eolian_cxx/grammar/empty_generator.hpp
@@ -0,0 +1,34 @@
1#ifndef EOLIAN_CXX_EMPTY_GENERATOR_HH
2#define EOLIAN_CXX_EMPTY_GENERATOR_HH
3
4#include "grammar/generator.hpp"
5
6namespace efl { namespace eolian { namespace grammar {
7
8struct empty_generator
9{
10 template <typename OutputIterator, typename Attribute, typename Context>
11 bool generate(OutputIterator const&, Attribute const&, Context const&) const
12 {
13 return true;
14 }
15};
16
17struct empty_generator const empty_generator = {};
18
19template <>
20struct is_eager_generator<struct ::efl::eolian::grammar::empty_generator> : std::true_type {};
21template <>
22struct is_generator<struct ::efl::eolian::grammar::empty_generator> : std::true_type {};
23
24namespace type_traits {
25
26template <>
27struct attributes_needed<struct ::efl::eolian::grammar::empty_generator>
28 : std::integral_constant<int, 0> {};
29
30}
31
32} } }
33
34#endif
diff --git a/src/lib/eolian_cxx/grammar/if.hpp b/src/lib/eolian_cxx/grammar/if.hpp
new file mode 100644
index 0000000000..401a81a0d7
--- /dev/null
+++ b/src/lib/eolian_cxx/grammar/if.hpp
@@ -0,0 +1,131 @@
1#ifndef EOLIAN_CXX_IF_HH
2#define EOLIAN_CXX_IF_HH
3
4#include "grammar/generator.hpp"
5
6namespace efl { namespace eolian { namespace grammar {
7
8template <typename F, typename TrueGenerator, typename FalseGenerator>
9struct if_true_false_generator
10{
11 template <typename OutputIterator, typename Attribute, typename Context>
12 bool generate(OutputIterator sink, Attribute const& attribute, Context const& ctx) const
13 {
14 if(f(attribute))
15 {
16 return true_generator.generate(sink, attribute, ctx);
17 }
18 else
19 {
20 return false_generator.generate(sink, attribute, ctx);
21 }
22 }
23
24 F f;
25 TrueGenerator true_generator;
26 FalseGenerator false_generator;
27};
28
29template <typename F, typename TrueGenerator>
30struct if_true_generator
31{
32 template <typename FalseGenerator>
33 if_true_false_generator<F, TrueGenerator, FalseGenerator> operator[](FalseGenerator false_g) const
34 {
35 return {f, true_generator, false_g};
36 }
37
38 template <typename OutputIterator, typename Attribute, typename Context>
39 bool generate(OutputIterator sink, Attribute const& attribute, Context const& context) const
40 {
41 if(f(attribute))
42 {
43 return true_generator.generate(sink, attribute, context);
44 }
45 else
46 {
47 return false;
48 }
49 }
50
51 F f;
52 TrueGenerator true_generator;
53};
54
55template <typename F>
56struct if_generator
57{
58 template <typename TrueGenerator>
59 if_true_generator<F, TrueGenerator> operator[](TrueGenerator true_g) const
60 {
61 return {f, true_g};
62 }
63
64 template <typename OutputIterator, typename Attribute, typename Context>
65 bool generate(OutputIterator, Attribute const& attribute, Context const&) const
66 {
67 return f(attribute);
68 }
69
70 F f;
71};
72
73struct if_terminal
74{
75 template <typename F>
76 if_generator<F> operator()(F f) const
77 {
78 return {f};
79 }
80} const if_ = {};
81
82template <typename F>
83struct is_eager_generator<if_generator<F>> : std::true_type {};
84template <typename F, typename TrueGenerator>
85struct is_eager_generator<if_true_generator<F, TrueGenerator>> : std::true_type {};
86template <typename F, typename TrueGenerator, typename FalseGenerator>
87struct is_eager_generator<if_true_false_generator<F, TrueGenerator, FalseGenerator>> : std::true_type {};
88
89template <typename F>
90struct is_generator<if_generator<F>> : std::true_type {};
91template <typename F, typename TrueGenerator>
92struct is_generator<if_true_generator<F, TrueGenerator>> : std::true_type {};
93template <typename F, typename TrueGenerator, typename FalseGenerator>
94struct is_generator<if_true_false_generator<F, TrueGenerator, FalseGenerator>> : std::true_type {};
95
96namespace type_traits {
97
98template <typename F>
99struct attributes_needed<if_generator<F>>
100 : std::integral_constant<int, 1> {};
101
102template <typename F, typename TrueGenerator>
103struct attributes_needed<if_true_generator<F, TrueGenerator>> : attributes_needed<TrueGenerator> {};
104template <typename F, typename TrueGenerator, typename FalseGenerator>
105struct attributes_needed<if_true_false_generator<F, TrueGenerator, FalseGenerator>>
106 : std::conditional<(attributes_needed<TrueGenerator>::value >= attributes_needed<FalseGenerator>::value)
107 , attributes_needed<TrueGenerator>, attributes_needed<FalseGenerator>>::type
108{};
109
110template <typename F, typename TrueGenerator, typename T>
111struct accepts_specific_tuple<if_true_generator<F, TrueGenerator>, T>
112 : accepts_specific_tuple<TrueGenerator, T> {};
113template <typename F, typename TrueGenerator, typename FalseGenerator, typename T>
114struct accepts_specific_tuple<if_true_false_generator<F, TrueGenerator, FalseGenerator>, T>
115 : std::integral_constant<bool, accepts_specific_tuple<TrueGenerator, T>::value
116 ||accepts_specific_tuple<FalseGenerator, T>::value>
117{};
118
119template <typename F, typename TrueGenerator>
120struct accepts_tuple<if_true_generator<F, TrueGenerator>>
121 : accepts_tuple<TrueGenerator> {};
122template <typename F, typename TrueGenerator, typename FalseGenerator>
123struct accepts_tuple<if_true_false_generator<F, TrueGenerator, FalseGenerator>>
124 : std::integral_constant<bool, accepts_tuple<TrueGenerator>::value || accepts_tuple<FalseGenerator>::value>
125{};
126
127}
128
129} } }
130
131#endif