summaryrefslogtreecommitdiff
path: root/src/lib/eolian_cxx
diff options
context:
space:
mode:
authorJean-Philippe Andre <jp.andre@samsung.com>2017-11-27 19:52:44 +0900
committerJean-Philippe Andre <jp.andre@samsung.com>2017-12-05 10:15:40 +0900
commit5901b4601e3a240f6286ab9396d1ea2967ca61bc (patch)
treedcb679ad428348da47fd2c08cab26e292419e197 /src/lib/eolian_cxx
parentf47bb54f4f0960b34050be4342f692f33feedf35 (diff)
cxx: Implement support for parts
This generates methods like this: Part_Class part_name() const; Which can then be used like: slider.indicator().format_string_set("%1.1f");
Diffstat (limited to 'src/lib/eolian_cxx')
-rw-r--r--src/lib/eolian_cxx/grammar/base_class_definition.hpp4
-rw-r--r--src/lib/eolian_cxx/grammar/class_definition.hpp9
-rw-r--r--src/lib/eolian_cxx/grammar/class_implementation.hpp11
-rw-r--r--src/lib/eolian_cxx/grammar/klass_def.hpp72
-rw-r--r--src/lib/eolian_cxx/grammar/part_declaration.hpp44
-rw-r--r--src/lib/eolian_cxx/grammar/part_implementation.hpp72
6 files changed, 196 insertions, 16 deletions
diff --git a/src/lib/eolian_cxx/grammar/base_class_definition.hpp b/src/lib/eolian_cxx/grammar/base_class_definition.hpp
index d5fa914b53..edc6afb86a 100644
--- a/src/lib/eolian_cxx/grammar/base_class_definition.hpp
+++ b/src/lib/eolian_cxx/grammar/base_class_definition.hpp
@@ -14,6 +14,7 @@
14#include "grammar/case.hpp" 14#include "grammar/case.hpp"
15#include "grammar/address_of.hpp" 15#include "grammar/address_of.hpp"
16#include "grammar/attribute_reorder.hpp" 16#include "grammar/attribute_reorder.hpp"
17#include "grammar/part_declaration.hpp"
17 18
18namespace efl { namespace eolian { namespace grammar { 19namespace efl { namespace eolian { namespace grammar {
19 20
@@ -36,6 +37,9 @@ struct base_class_definition_generator
36 if(!as_generator(*(scope_tab << function_declaration(get_klass_name(cls)))) 37 if(!as_generator(*(scope_tab << function_declaration(get_klass_name(cls))))
37 .generate(sink, cls.functions, context)) return false; 38 .generate(sink, cls.functions, context)) return false;
38 39
40 if(!as_generator(*(scope_tab << part_declaration << ";\n"))
41 .generate(sink, cls.parts, context)) return false;
42
39 // static Efl_Class const* _eo_class(); 43 // static Efl_Class const* _eo_class();
40 std::string suffix; 44 std::string suffix;
41 switch(cls.type) 45 switch(cls.type)
diff --git a/src/lib/eolian_cxx/grammar/class_definition.hpp b/src/lib/eolian_cxx/grammar/class_definition.hpp
index 30a9daf134..7367cf7ef0 100644
--- a/src/lib/eolian_cxx/grammar/class_definition.hpp
+++ b/src/lib/eolian_cxx/grammar/class_definition.hpp
@@ -15,6 +15,7 @@
15#include "grammar/attribute_reorder.hpp" 15#include "grammar/attribute_reorder.hpp"
16#include "grammar/attribute_conditional.hpp" 16#include "grammar/attribute_conditional.hpp"
17#include "grammar/attribute_replace.hpp" 17#include "grammar/attribute_replace.hpp"
18#include "grammar/part_declaration.hpp"
18 19
19namespace efl { namespace eolian { namespace grammar { 20namespace efl { namespace eolian { namespace grammar {
20 21
@@ -206,11 +207,17 @@ struct class_definition_generator
206 // /// @endcond 207 // /// @endcond
207 if(!as_generator(scope_tab << "/// @endcond\n").generate(sink, attributes::unused, context)) return false; 208 if(!as_generator(scope_tab << "/// @endcond\n").generate(sink, attributes::unused, context)) return false;
208 209
210 // EXPERIMENTAL: Parts
211 if(!as_generator("#ifdef EFL_CXXPERIMENTAL\n").generate(sink, attributes::unused, context)) return false;
212 if(!as_generator(*(scope_tab << part_declaration << ";\n"))
213 .generate(sink, cls.parts, context)) return false;
214 if(!as_generator("#endif \n").generate(sink, attributes::unused, context)) return false;
215
209 if(!as_generator( scope_tab << "::efl::eo::wref<" << string << "> _get_wref() const { " 216 if(!as_generator( scope_tab << "::efl::eo::wref<" << string << "> _get_wref() const { "
210 "return ::efl::eo::wref<" << string << ">(*this); }\n" 217 "return ::efl::eo::wref<" << string << ">(*this); }\n"
211 ).generate(sink, std::make_tuple(cls.cxx_name, cls.cxx_name), context)) return false; 218 ).generate(sink, std::make_tuple(cls.cxx_name, cls.cxx_name), context)) return false;
212 219
213 // EXPERIMENTAL 220 // EXPERIMENTAL: wref and implicit conversion to Eo*
214 if(!as_generator("#ifdef EFL_CXXPERIMENTAL\n").generate(sink, attributes::unused, context)) return false; 221 if(!as_generator("#ifdef EFL_CXXPERIMENTAL\n").generate(sink, attributes::unused, context)) return false;
215 // For easy wref, operator-> in wref needs to also return a pointer type 222 // For easy wref, operator-> in wref needs to also return a pointer type
216 if(!as_generator( scope_tab << "const " << string << "* operator->() const { return this; }\n" 223 if(!as_generator( scope_tab << "const " << string << "* operator->() const { return this; }\n"
diff --git a/src/lib/eolian_cxx/grammar/class_implementation.hpp b/src/lib/eolian_cxx/grammar/class_implementation.hpp
index 373f04efef..60eb075073 100644
--- a/src/lib/eolian_cxx/grammar/class_implementation.hpp
+++ b/src/lib/eolian_cxx/grammar/class_implementation.hpp
@@ -14,6 +14,7 @@
14#include "grammar/namespace.hpp" 14#include "grammar/namespace.hpp"
15#include "grammar/type_impl.hpp" 15#include "grammar/type_impl.hpp"
16#include "grammar/attribute_reorder.hpp" 16#include "grammar/attribute_reorder.hpp"
17#include "grammar/part_implementation.hpp"
17 18
18namespace efl { namespace eolian { namespace grammar { 19namespace efl { namespace eolian { namespace grammar {
19 20
@@ -40,19 +41,21 @@ struct class_implementation_generator
40#ifndef USE_EOCXX_INHERIT_ONLY 41#ifndef USE_EOCXX_INHERIT_ONLY
41 if(!as_generator( 42 if(!as_generator(
42 (namespaces 43 (namespaces
43 [*function_definition(get_klass_name(cls))] 44 [*function_definition(get_klass_name(cls))
45 << *part_implementation(cls.cxx_name)]
44 << "\n" 46 << "\n"
45 )).generate(sink, std::make_tuple(cls.namespaces, cls.functions), ctx)) 47 )).generate(sink, std::make_tuple(cls.namespaces, cls.functions, cls.parts), ctx))
46 return false; 48 return false;
47#endif 49#endif
48 50
49 if(!as_generator( 51 if(!as_generator(
50 attribute_reorder<0, 1, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3> 52 attribute_reorder<0, 1, 4, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3, 2, 3>
51 ( 53 (
52 "namespace eo_cxx {\n" 54 "namespace eo_cxx {\n"
53 << namespaces 55 << namespaces
54 [ 56 [
55 *function_definition(get_klass_name(cls)) 57 *function_definition(get_klass_name(cls))
58 << *part_implementation(cls.cxx_name)
56 << "inline " << base_class_name << "::operator " << class_name << "() const { return *static_cast< " 59 << "inline " << base_class_name << "::operator " << class_name << "() const { return *static_cast< "
57 << class_name << " const*>(static_cast<void const*>(this)); }\n" 60 << class_name << " const*>(static_cast<void const*>(this)); }\n"
58 << "inline " << base_class_name << "::operator " << class_name << "&() { return *static_cast< " 61 << "inline " << base_class_name << "::operator " << class_name << "&() { return *static_cast< "
@@ -61,7 +64,7 @@ struct class_implementation_generator
61 << class_name << " const*>(static_cast<void const*>(this)); }\n" 64 << class_name << " const*>(static_cast<void const*>(this)); }\n"
62 ] 65 ]
63 << "}\n" 66 << "}\n"
64 )).generate(sink, std::make_tuple(cls.namespaces, cls.functions, cpp_namespaces, cls.cxx_name), ctx)) 67 )).generate(sink, std::make_tuple(cls.namespaces, cls.functions, cpp_namespaces, cls.cxx_name, cls.parts), ctx))
65 return false; 68 return false;
66 69
67 if(!as_generator("#endif\n").generate(sink, std::make_tuple(), ctx)) 70 if(!as_generator("#endif\n").generate(sink, std::make_tuple(), ctx))
diff --git a/src/lib/eolian_cxx/grammar/klass_def.hpp b/src/lib/eolian_cxx/grammar/klass_def.hpp
index 739390ddc6..fc6d62d5b8 100644
--- a/src/lib/eolian_cxx/grammar/klass_def.hpp
+++ b/src/lib/eolian_cxx/grammar/klass_def.hpp
@@ -225,6 +225,11 @@ struct type_def
225 } 225 }
226 void set(Eolian_Type const* eolian_type, Eolian_Unit const* unit, Eolian_C_Type_Type ctype); 226 void set(Eolian_Type const* eolian_type, Eolian_Unit const* unit, Eolian_C_Type_Type ctype);
227 void set(Eolian_Expression_Type eolian_exp_type); 227 void set(Eolian_Expression_Type eolian_exp_type);
228
229 friend inline bool operator<(type_def const& lhs, type_def const& rhs)
230 {
231 return lhs.c_type < rhs.c_type;
232 }
228}; 233};
229 234
230struct get_qualifier_visitor 235struct get_qualifier_visitor
@@ -690,6 +695,32 @@ auto get(event_def& def) -> decltype(tuple_element<N, event_def>::get(def))
690 return tuple_element<N, event_def>::get(def); 695 return tuple_element<N, event_def>::get(def);
691} 696}
692 697
698struct part_def
699{
700 klass_name klass;
701 std::string name;
702 //bool beta, protect; // can it be applied??
703
704 friend inline bool operator==(part_def const& lhs, part_def const& rhs)
705 {
706 return lhs.klass == rhs.klass
707 && lhs.name == rhs.name;
708 }
709 friend inline bool operator!=(part_def const& lhs, part_def const& rhs)
710 {
711 return !(lhs == rhs);
712 }
713 friend inline bool operator<(part_def const& lhs, part_def const& rhs)
714 {
715 return lhs.name < rhs.name ||
716 lhs.klass < rhs.klass;
717 }
718
719 part_def(Eolian_Part const* part, Eolian_Unit const*)
720 : klass(klass_name(::eolian_part_class_get(part), {attributes::qualifier_info::is_none, std::string()}))
721 , name(::eolian_part_name_get(part)) {}
722};
723
693inline Eolian_Class const* get_klass(klass_name const& klass_name_, Eolian_Unit const* unit); 724inline Eolian_Class const* get_klass(klass_name const& klass_name_, Eolian_Unit const* unit);
694 725
695struct klass_def 726struct klass_def
@@ -703,6 +734,7 @@ struct klass_def
703 class_type type; 734 class_type type;
704 std::vector<event_def> events; 735 std::vector<event_def> events;
705 std::set<klass_name, compare_klass_name_by_name> immediate_inherits; 736 std::set<klass_name, compare_klass_name_by_name> immediate_inherits;
737 std::set<part_def> parts;
706 738
707 friend inline bool operator==(klass_def const& lhs, klass_def const& rhs) 739 friend inline bool operator==(klass_def const& lhs, klass_def const& rhs)
708 { 740 {
@@ -713,7 +745,8 @@ struct klass_def
713 && lhs.functions == rhs.functions 745 && lhs.functions == rhs.functions
714 && lhs.inherits == rhs.inherits 746 && lhs.inherits == rhs.inherits
715 && lhs.type == rhs.type 747 && lhs.type == rhs.type
716 && lhs.events == rhs.events; 748 && lhs.events == rhs.events
749 && lhs.parts == rhs.parts;
717 } 750 }
718 friend inline bool operator!=(klass_def const& lhs, klass_def const& rhs) 751 friend inline bool operator!=(klass_def const& lhs, klass_def const& rhs)
719 { 752 {
@@ -723,7 +756,8 @@ struct klass_def
723 { 756 {
724 return lhs.eolian_name < rhs.eolian_name 757 return lhs.eolian_name < rhs.eolian_name
725 || lhs.cxx_name < rhs.cxx_name 758 || lhs.cxx_name < rhs.cxx_name
726 || lhs.namespaces < rhs.namespaces; 759 || lhs.namespaces < rhs.namespaces
760 || lhs.parts < rhs.parts;
727 } 761 }
728 762
729 klass_def(std::string eolian_name, std::string cxx_name, std::string filename 763 klass_def(std::string eolian_name, std::string cxx_name, std::string filename
@@ -737,6 +771,15 @@ struct klass_def
737 , functions(functions), inherits(inherits), type(type) 771 , functions(functions), inherits(inherits), type(type)
738 , immediate_inherits(immediate_inherits) 772 , immediate_inherits(immediate_inherits)
739 {} 773 {}
774 klass_def(std::string _eolian_name, std::string _cxx_name
775 , std::vector<std::string> _namespaces
776 , std::vector<function_def> _functions
777 , std::set<klass_name, compare_klass_name_by_name> _inherits
778 , class_type _type)
779 : eolian_name(_eolian_name), cxx_name(_cxx_name)
780 , namespaces(_namespaces)
781 , functions(_functions), inherits(_inherits), type(_type)
782 {}
740 klass_def(Eolian_Class const* klass, Eolian_Unit const* unit) 783 klass_def(Eolian_Class const* klass, Eolian_Unit const* unit)
741 { 784 {
742 for(efl::eina::iterator<const char> namespace_iterator( ::eolian_class_namespaces_get(klass)) 785 for(efl::eina::iterator<const char> namespace_iterator( ::eolian_class_namespaces_get(klass))
@@ -750,8 +793,8 @@ struct klass_def
750 , functions_last; eolian_functions != functions_last; ++eolian_functions) 793 , functions_last; eolian_functions != functions_last; ++eolian_functions)
751 { 794 {
752 Eolian_Function const* function = &*eolian_functions; 795 Eolian_Function const* function = &*eolian_functions;
753 Eolian_Function_Type type = ::eolian_function_type_get(function); 796 Eolian_Function_Type func_type = ::eolian_function_type_get(function);
754 if(type == EOLIAN_PROPERTY) 797 if(func_type == EOLIAN_PROPERTY)
755 { 798 {
756 try { 799 try {
757 if(! ::eolian_function_is_legacy_only(function, EOLIAN_PROP_GET) 800 if(! ::eolian_function_is_legacy_only(function, EOLIAN_PROP_GET)
@@ -766,9 +809,9 @@ struct klass_def
766 } 809 }
767 else 810 else
768 try { 811 try {
769 if(! ::eolian_function_is_legacy_only(function, type) 812 if(! ::eolian_function_is_legacy_only(function, func_type)
770 && ::eolian_function_scope_get(function, type) != EOLIAN_SCOPE_PRIVATE) 813 && ::eolian_function_scope_get(function, func_type) != EOLIAN_SCOPE_PRIVATE)
771 functions.push_back({function, type, unit}); 814 functions.push_back({function, func_type, unit});
772 } catch(std::exception const&) {} 815 } catch(std::exception const&) {}
773 } 816 }
774 for(efl::eina::iterator<Eolian_Function const> eolian_functions ( ::eolian_class_functions_get(klass, EOLIAN_METHOD)) 817 for(efl::eina::iterator<Eolian_Function const> eolian_functions ( ::eolian_class_functions_get(klass, EOLIAN_METHOD))
@@ -776,9 +819,9 @@ struct klass_def
776 { 819 {
777 try { 820 try {
778 Eolian_Function const* function = &*eolian_functions; 821 Eolian_Function const* function = &*eolian_functions;
779 Eolian_Function_Type type = eolian_function_type_get(function); 822 Eolian_Function_Type func_type = eolian_function_type_get(function);
780 if(! ::eolian_function_is_legacy_only(function, EOLIAN_METHOD) 823 if(! ::eolian_function_is_legacy_only(function, EOLIAN_METHOD)
781 && ::eolian_function_scope_get(function, type) != EOLIAN_SCOPE_PRIVATE) 824 && ::eolian_function_scope_get(function, func_type) != EOLIAN_SCOPE_PRIVATE)
782 functions.push_back({function, EOLIAN_METHOD, unit}); 825 functions.push_back({function, EOLIAN_METHOD, unit});
783 } catch(std::exception const&) {} 826 } catch(std::exception const&) {}
784 } 827 }
@@ -789,9 +832,9 @@ struct klass_def
789 immediate_inherits.insert({inherit, {}}); 832 immediate_inherits.insert({inherit, {}});
790 } 833 }
791 std::function<void(Eolian_Class const*)> inherit_algo = 834 std::function<void(Eolian_Class const*)> inherit_algo =
792 [&] (Eolian_Class const* klass) 835 [&] (Eolian_Class const* inherit_klass)
793 { 836 {
794 for(efl::eina::iterator<Eolian_Class const> inherit_iterator ( ::eolian_class_inherits_get(klass)) 837 for(efl::eina::iterator<Eolian_Class const> inherit_iterator ( ::eolian_class_inherits_get(inherit_klass))
795 , inherit_last; inherit_iterator != inherit_last; ++inherit_iterator) 838 , inherit_last; inherit_iterator != inherit_last; ++inherit_iterator)
796 { 839 {
797 Eolian_Class const* inherit = &*inherit_iterator; 840 Eolian_Class const* inherit = &*inherit_iterator;
@@ -800,6 +843,13 @@ struct klass_def
800 } 843 }
801 }; 844 };
802 inherit_algo(klass); 845 inherit_algo(klass);
846
847 for(efl::eina::iterator<Eolian_Part const> parts_itr ( ::eolian_class_parts_get(klass))
848 , parts_last; parts_itr != parts_last; ++parts_itr)
849 {
850 parts.insert({&*parts_itr, unit});
851 }
852
803 switch(eolian_class_type_get(klass)) 853 switch(eolian_class_type_get(klass))
804 { 854 {
805 case EOLIAN_CLASS_REGULAR: 855 case EOLIAN_CLASS_REGULAR:
diff --git a/src/lib/eolian_cxx/grammar/part_declaration.hpp b/src/lib/eolian_cxx/grammar/part_declaration.hpp
new file mode 100644
index 0000000000..383403c6bd
--- /dev/null
+++ b/src/lib/eolian_cxx/grammar/part_declaration.hpp
@@ -0,0 +1,44 @@
1#ifndef EOLIAN_CXX_PART_DECLARATION_HH
2#define EOLIAN_CXX_PART_DECLARATION_HH
3
4#include "grammar/generator.hpp"
5
6#include "grammar/string.hpp"
7#include "grammar/indentation.hpp"
8#include "grammar/list.hpp"
9#include "grammar/alternative.hpp"
10#include "grammar/type.hpp"
11#include "grammar/parameter.hpp"
12#include "grammar/keyword.hpp"
13
14namespace efl { namespace eolian { namespace grammar {
15
16struct part_declaration_generator
17{
18 template <typename OutputIterator, typename Context>
19 bool generate(OutputIterator sink, attributes::part_def const& part, Context const& ctx) const
20 {
21 if(!as_generator("::efl::eolian::return_traits<::" << *(string << "::"))
22 .generate(sink, part.klass.namespaces, add_lower_case_context(ctx)))
23 return false;
24 if(!as_generator(string << ">::type " << string << "() const")
25 .generate(sink, std::make_tuple(part.klass.eolian_name, part.name), ctx))
26 return false;
27
28 return true;
29 }
30};
31
32template <>
33struct is_eager_generator<part_declaration_generator> : std::true_type {};
34
35namespace type_traits {
36template <>
37struct attributes_needed<part_declaration_generator> : std::integral_constant<int, 1> {};
38}
39
40part_declaration_generator const part_declaration = {};
41
42} } }
43
44#endif
diff --git a/src/lib/eolian_cxx/grammar/part_implementation.hpp b/src/lib/eolian_cxx/grammar/part_implementation.hpp
new file mode 100644
index 0000000000..cee2fc7fa8
--- /dev/null
+++ b/src/lib/eolian_cxx/grammar/part_implementation.hpp
@@ -0,0 +1,72 @@
1#ifndef EOLIAN_CXX_PART_IMPLEMENTATION_HH
2#define EOLIAN_CXX_PART_IMPLEMENTATION_HH
3
4#include "grammar/generator.hpp"
5
6#include "grammar/string.hpp"
7#include "grammar/indentation.hpp"
8#include "grammar/list.hpp"
9#include "grammar/alternative.hpp"
10#include "grammar/type.hpp"
11#include "grammar/parameter.hpp"
12#include "grammar/keyword.hpp"
13
14namespace efl { namespace eolian { namespace grammar {
15
16struct part_implementation_generator
17{
18 part_implementation_generator(std::string const& _klass_name)
19 : klass_name(_klass_name) {}
20
21 template <typename OutputIterator, typename Context>
22 bool generate(OutputIterator sink, attributes::part_def const& part, Context const& ctx) const
23 {
24 if(!as_generator("#ifdef EFL_CXXPERIMENTAL\n").generate(sink, attributes::unused, ctx))
25 return false;
26
27 if(!as_generator("::efl::eolian::return_traits<::" << *(string << "::"))
28 .generate(sink, part.klass.namespaces, add_lower_case_context(ctx)))
29 return false;
30 // FIXME: part_def can't depend on klass_def so C type is not known :(
31 if(!as_generator(string << ">::type "<< string << "::" << string << "() const\n{\n"
32 << scope_tab << "::Eo *__return_value = ::efl_part"
33 << "(this->_eo_ptr(), \"" << string << "\");\n"
34 << scope_tab << "::efl_auto_unref_set(__return_value, false);\n")
35 .generate(sink, std::make_tuple(part.klass.eolian_name, klass_name, part.name, part.name), ctx))
36 return false;
37 if(!as_generator(scope_tab << "return ::" << *(string << "::"))
38 .generate(sink, part.klass.namespaces, add_lower_case_context(ctx)))
39 return false;
40 if(!as_generator(string << "{__return_value};\n}\n")
41 .generate(sink, part.klass.eolian_name, ctx))
42 return false;
43
44 if(!as_generator("#endif\n").generate(sink, attributes::unused, ctx))
45 return false;
46
47 return true;
48 }
49
50private:
51 std::string klass_name;
52};
53
54template <>
55struct is_eager_generator<part_implementation_generator> : std::true_type {};
56
57namespace type_traits {
58template <>
59struct attributes_needed<part_implementation_generator> : std::integral_constant<int, 1> {};
60}
61
62struct part_implementation_terminal
63{
64 part_implementation_generator operator()(std::string klass_name) const
65 {
66 return part_implementation_generator{klass_name};
67 }
68} const part_implementation = {};
69
70} } }
71
72#endif