summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVitor Sousa <vitorsousasilva@gmail.com>2014-12-19 14:34:15 -0200
committerVitor Sousa <vitorsousasilva@gmail.com>2015-01-05 15:52:27 -0200
commit6519ae6ed98789857722cd1d6e3c1c254ad229e7 (patch)
treed31f19962327a4baf92c0694da724aa32b3c2c2d
parented75aa32d6ccdea66a952ed5c82203b0cd1961b2 (diff)
downloadefl-6519ae6ed98789857722cd1d6e3c1c254ad229e7.tar.gz
eolian_cxx: Fix "dreaded diamond" inheritance problem for C++ wrappers
Solved diamond inheritance problem by completely removing inheritance in the abstract class. All ancestors are inherited directly in the concrete class. The algorithm that list the ancestors also avoid repetition. Now concrete classes define methods too. This helps referring the correct method directly by the object type (when there are methods with the same name). Moved the declaration and definition of constructor methods to the concrete class, since they should not be used in derived classes. Updated example that call "color_set". With this model, if two ancestor classes have a method with the same name, to call one of them from a derived class you must write the scoped name of the member function in the wrapper. In this case, either Evas.Object and Evas.SmartObject have a property named "color". Added "from_global" option to the full_name grammar too.
-rw-r--r--src/bin/eolian_cxx/convert.cc34
-rw-r--r--src/examples/eolian_cxx/eolian_cxx_complex_types_01.cc2
-rw-r--r--src/lib/eolian_cxx/grammar/eo_class_constructors_generator.hh7
-rw-r--r--src/lib/eolian_cxx/grammar/eo_class_functions_generator.hh21
-rw-r--r--src/lib/eolian_cxx/grammar/eo_class_generator.hh16
-rw-r--r--src/lib/eolian_cxx/grammar/type_generator.hh10
6 files changed, 48 insertions, 42 deletions
diff --git a/src/bin/eolian_cxx/convert.cc b/src/bin/eolian_cxx/convert.cc
index 8f5cec8927..2fa45b569b 100644
--- a/src/bin/eolian_cxx/convert.cc
+++ b/src/bin/eolian_cxx/convert.cc
@@ -1,5 +1,6 @@
#include <vector>
+#include <set>
#include <algorithm>
#include <cassert>
#include <cstddef>
@@ -23,8 +24,11 @@ namespace eolian_cxx {
extern efl::eina::log_domain domain;
void
-remove_repeated_base(const char* klass_name, efl::eolian::parents_container_type& cont)
+add_parent_recursive(const char* klass_name, std::set<std::string>& parents)
{
+ if (!klass_name)
+ return;
+
Eolian_Class const* klass = ::eolian_class_get_by_name(klass_name);
if (!klass)
{
@@ -32,20 +36,14 @@ remove_repeated_base(const char* klass_name, efl::eolian::parents_container_type
return;
}
+ parents.insert(class_format_cxx(safe_lower(klass_name)));
+
Eina_Iterator* inheritances = ::eolian_class_inherits_get(klass);
void* curr = 0;
EINA_ITERATOR_FOREACH(inheritances, curr)
{
- if (!curr)
- continue;
-
- const char* parent = static_cast<const char*>(curr);
- cont.erase(
- std::remove(cont.begin(), cont.end(), safe_lower(class_format_cxx(parent)))
- , cont.end());
-
- remove_repeated_base(parent, cont);
+ add_parent_recursive(static_cast<const char*>(curr), parents);
}
eina_iterator_free(inheritances);
}
@@ -184,23 +182,15 @@ convert_eolian_inheritances(efl::eolian::eo_class& cls, Eolian_Class const& klas
::eolian_class_inherits_get(&klass);
void *curr;
- EINA_ITERATOR_FOREACH(inheritances, curr)
- {
- std::string parent = safe_lower(static_cast<const char*>(curr));
- cls.parents.push_back(class_format_cxx(parent));
- }
- eina_iterator_free(inheritances);
+ std::set<std::string> parents;
- if (cls.parents.empty())
- return;
-
- inheritances = ::eolian_class_inherits_get(&klass);
EINA_ITERATOR_FOREACH(inheritances, curr)
{
- if (curr)
- remove_repeated_base(static_cast<const char*>(curr), cls.parents);
+ add_parent_recursive(static_cast<const char*>(curr), parents);
}
eina_iterator_free(inheritances);
+
+ cls.parents.assign(parents.begin(), parents.end());
}
void
diff --git a/src/examples/eolian_cxx/eolian_cxx_complex_types_01.cc b/src/examples/eolian_cxx/eolian_cxx_complex_types_01.cc
index 264ece2640..8dd5d29d87 100644
--- a/src/examples/eolian_cxx/eolian_cxx_complex_types_01.cc
+++ b/src/examples/eolian_cxx/eolian_cxx_complex_types_01.cc
@@ -74,7 +74,7 @@ example_complex_types()
efl::evas::grid grid(efl::eo::parent = canvas);
grid.position_set(0, 0);
- grid.color_set(0, 0, 0, 255);
+ grid.object_smart::color_set(0, 0, 0, 255);
grid.size_set(5, 5);
grid.visibility_set(true);
diff --git a/src/lib/eolian_cxx/grammar/eo_class_constructors_generator.hh b/src/lib/eolian_cxx/grammar/eo_class_constructors_generator.hh
index 9e1ab5877d..9ffed7543e 100644
--- a/src/lib/eolian_cxx/grammar/eo_class_constructors_generator.hh
+++ b/src/lib/eolian_cxx/grammar/eo_class_constructors_generator.hh
@@ -46,8 +46,7 @@ operator<<(std::ostream& out, class_inheritance const& x)
last = cls.parents.cend();
for (it = first; it != last; ++it)
{
- out << tab(2) << (it == first ? ": " : ", ")
- << "::" << abstract_namespace << "::" << *it << endl;
+ out << tab(2) << ", ::" << abstract_namespace << "::" << *it << endl;
}
return out;
}
@@ -241,9 +240,9 @@ operator<<(std::ostream& out, constructor_method_function_definitions const& x)
}
out << template_parameters_declaration(c.params, 0)
- << "inline " << abstract_full_name(x._cls)
+ << "inline " << full_name(x._cls)
<< "::" << constructor_functor_type_decl(c) << " "
- << abstract_full_name(x._cls, false) << "::" << c.name << "("
+ << full_name(x._cls, false) << "::" << c.name << "("
<< parameters_declaration(c.params) << ") const" << endl
<< "{" << endl
<< tab(1) << "return " << constructor_functor_type_decl(c) << "("
diff --git a/src/lib/eolian_cxx/grammar/eo_class_functions_generator.hh b/src/lib/eolian_cxx/grammar/eo_class_functions_generator.hh
index f375fd7ca1..56b450bada 100644
--- a/src/lib/eolian_cxx/grammar/eo_class_functions_generator.hh
+++ b/src/lib/eolian_cxx/grammar/eo_class_functions_generator.hh
@@ -61,8 +61,9 @@ struct function_definition
{
eo_class const& _cls;
eo_function const& _func;
- function_definition(eo_class const& cls, eo_function const& func)
- : _cls(cls), _func(func)
+ bool _concrete;
+ function_definition(eo_class const& cls, eo_function const& func, bool concrete)
+ : _cls(cls), _func(func), _concrete(concrete)
{}
};
@@ -74,8 +75,14 @@ operator<<(std::ostream& out, function_definition const& x)
bool is_static = function_is_static(func);
out << template_parameters_declaration(func.params, 0)
- << "inline " << reinterpret_type(func.ret) << " "
- << abstract_full_name(x._cls, false) << "::" << func.name << "("
+ << "inline " << reinterpret_type(func.ret) << " ";
+
+ if (x._concrete)
+ out << full_name(x._cls, false);
+ else
+ out << abstract_full_name(x._cls, false);
+
+ out << "::" << func.name << "("
<< parameters_declaration(func.params)
<< (is_static ? ")" : ") const") << endl
<< "{" << endl;
@@ -121,8 +128,10 @@ operator<<(std::ostream& out, function_declarations const& x)
struct function_definitions
{
eo_class const& _cls;
- function_definitions(eo_class const& cls)
+ bool _concrete;
+ function_definitions(eo_class const& cls, bool concrete)
: _cls(cls)
+ , _concrete(concrete)
{}
};
@@ -131,7 +140,7 @@ operator<<(std::ostream& out, function_definitions const& x)
{
for (eo_function const& f : x._cls.functions)
{
- out << function_definition(x._cls, f) << endl;
+ out << function_definition(x._cls, f, x._concrete) << endl;
}
return out;
}
diff --git a/src/lib/eolian_cxx/grammar/eo_class_generator.hh b/src/lib/eolian_cxx/grammar/eo_class_generator.hh
index f54485cfa6..18d2e716c2 100644
--- a/src/lib/eolian_cxx/grammar/eo_class_generator.hh
+++ b/src/lib/eolian_cxx/grammar/eo_class_generator.hh
@@ -105,10 +105,7 @@ eo_class_generator(std::ostream& out, eo_class const& cls)
<< namespace_head(cls)
<< comment(cls.comment)
<< "struct " << cls.name << endl
- << class_inheritance(cls)
<< '{' << endl
- << functors_constructor_methods(cls)
- << constructor_method_function_declarations(cls)
<< function_declarations(cls)
<< events(cls)
<< eo_class_getter(cls)
@@ -120,22 +117,29 @@ eo_class_generator(std::ostream& out, eo_class const& cls)
<< "}" << endl << endl
<< namespace_head(cls)
<< "struct " << cls.name << endl
- << tab(2) << ": " << abstract_full_name(cls) << endl
- << tab(2) << ", ::efl::eo::concrete" << endl
+ << tab(2) << ": ::efl::eo::concrete" << endl
+ << class_inheritance(cls)
<< '{' << endl
+ << functors_constructor_methods(cls)
<< constructor_with_constructor_methods(cls)
<< constructor_eo(cls)
<< copy_constructor(cls)
<< destructor(cls)
+ << constructor_method_function_declarations(cls)
+ << function_declarations(cls)
+ << events(cls)
+ << eo_class_getter(cls)
<< "private:" << endl
<< function_call_constructor_methods(cls)
+ << tab(2) << "Eo* _concrete_eo_ptr() const { return _eo_ptr(); }" << endl
<< "};" << endl << endl
<< "static_assert(sizeof(" << full_name(cls) << ") == sizeof(Eo*), \"\");" << endl
<< "static_assert(std::is_standard_layout<" << full_name(cls) << ">::value, \"\");" << endl
<< endl
<< namespace_tail(cls)
<< constructor_method_function_definitions(cls)
- << function_definitions(cls)
+ << function_definitions(cls, true)
+ << function_definitions(cls, false)
<< class_implicit_conversion_definition(cls);
}
diff --git a/src/lib/eolian_cxx/grammar/type_generator.hh b/src/lib/eolian_cxx/grammar/type_generator.hh
index a476205271..2dc6681f48 100644
--- a/src/lib/eolian_cxx/grammar/type_generator.hh
+++ b/src/lib/eolian_cxx/grammar/type_generator.hh
@@ -15,15 +15,19 @@ using std::endl;
struct full_name
{
eo_class const& _cls;
- full_name(eo_class const& cls) : _cls(cls) {}
+ bool _from_global;
+ full_name(eo_class const& cls, bool from_global = true)
+ : _cls(cls), _from_global(from_global) {}
};
inline std::ostream&
operator<<(std::ostream& out, full_name const& x)
{
+ if (x._from_global)
+ out << "::";
if(!x._cls.name_space.empty())
- out << "::" << x._cls.name_space;
- return out << "::" << x._cls.name;
+ out << x._cls.name_space << "::";
+ return out << x._cls.name;
}
struct abstract_full_name