From 65f868786a59533a1cbf9d58b886cdc4f49ceb94 Mon Sep 17 00:00:00 2001 From: Lauro Moura Date: Tue, 10 Apr 2018 22:30:40 -0300 Subject: [PATCH] efl_mono: Proper support for @class methods. Previously, class methods were implemented as regular instance methods. This commits generates C# static methods for @class methods on the *Concrete classes (and their childs). --- src/Makefile_Efl_Mono.am | 6 +++-- .../eolian/mono/function_declaration.hh | 2 +- .../eolian/mono/function_definition.hh | 13 +++++----- .../eolian/mono/function_registration.hh | 2 +- src/bin/eolian_mono/eolian/mono/helpers.hh | 15 ++++++++++++ src/bin/eolian_mono/eolian/mono/klass.hh | 9 +++---- src/lib/eolian_cxx/grammar/klass_def.hpp | 21 +++++++++++----- src/tests/efl_mono/Eo.cs | 17 +++++++++++++ src/tests/efl_mono/libefl_mono_native_test.c | 24 +++++++++++++++++++ src/tests/efl_mono/test_child.eo | 9 +++++++ src/tests/efl_mono/test_testing.eo | 8 +++++++ 11 files changed, 106 insertions(+), 20 deletions(-) create mode 100644 src/tests/efl_mono/test_child.eo diff --git a/src/Makefile_Efl_Mono.am b/src/Makefile_Efl_Mono.am index 45928f977a..01f6a12dd3 100644 --- a/src/Makefile_Efl_Mono.am +++ b/src/Makefile_Efl_Mono.am @@ -48,6 +48,7 @@ lib_efl_mono_libefl_mono_dll_sources = \ efl_mono_test_files = \ tests/efl_mono/test_testing.eo \ + tests/efl_mono/test_child.eo \ tests/efl_mono/test_numberwrapper.eo \ tests/efl_mono/mono_test_driver.sh @@ -382,10 +383,11 @@ tests_efl_mono_libefl_mono_native_test_la_LDFLAGS = -rpath $(abs_top_builddir)/t tests_efl_mono_libefl_mono_native_test_la_DEPENDENCIES = @USE_EINA_INTERNAL_LIBS@ @USE_EO_INTERNAL_LIBS@ @USE_ECORE_INTERNAL_LIBS@ @USE_ELDBUS_INTERNAL_LIBS@ tests_efl_mono_libefl_mono_native_test_la_LIBTOOLFLAGS = --tag=disable-static -tests/efl_mono/libefl_mono_native_test.c: tests/efl_mono/test_testing.eo.h tests/efl_mono/test_testing.eo.c tests/efl_mono/test_numberwrapper.eo.h tests/efl_mono/test_numberwrapper.eo.c +tests/efl_mono/libefl_mono_native_test.c: tests/efl_mono/test_testing.eo.h tests/efl_mono/test_testing.eo.c tests/efl_mono/test_child.eo.h tests/efl_mono/test_child.eo.c tests/efl_mono/test_numberwrapper.eo.h tests/efl_mono/test_numberwrapper.eo.c # Intermediate C Sharp test DLL efl_mono_test_eolian_mono_files = tests/efl_mono/test_testing.eo.cs \ +tests/efl_mono/test_child.eo.cs \ tests/efl_mono/test_numberwrapper.eo.cs tests/efl_mono/libefl_mono_test.dll: $(efl_mono_test_eolian_mono_files) tests/efl_mono/$(am__dirstamp) lib/efl_mono/libefl_mono.dll tests/efl_mono/libefl_mono_native_test.la tests/efl_mono/libefl_mono_test.dll.config @@ -456,7 +458,7 @@ tests/efl_mono/%.eo.cs: tests/efl_mono/%.eo $(_EOLIAN_MONO_DEP) $(MKDIR_P) $(dir $@); \ $(EOLIAN_MONO) $(EOLIAN_FLAGS) $(EOLIAN_MONO_FLAGS) --dllimport "@DLIB_PREFIX_MONO@efl_mono_native_test@DLIB_SUFFIX_MONO@" -o $@ $(ALL_EO_REFS) $< -CLEANFILES += tests/efl_mono/libefl_mono_test.dll tests/efl_mono/test_testing.eo.cs tests/efl_mono/test_numberwrapper.eo.cs tests/efl_mono/test_testing.eo.c tests/efl_mono/test_numberwrapper.eo.c tests/efl_mono/test_testing.eo.h tests/efl_mono/test_numberwrapper.eo.h tests/efl_mono/efl_mono.config +CLEANFILES += tests/efl_mono/libefl_mono_test.dll tests/efl_mono/test_testing.eo.cs tests/efl_mono/test_child.eo.cs tests/efl_mono/test_numberwrapper.eo.cs tests/efl_mono/test_testing.eo.c tests/efl_mono/test_child.eo.c tests/efl_mono/test_numberwrapper.eo.c tests/efl_mono/test_testing.eo.h tests/efl_mono/test_child.eo.h tests/efl_mono/test_numberwrapper.eo.h tests/efl_mono/efl_mono.config endif diff --git a/src/bin/eolian_mono/eolian/mono/function_declaration.hh b/src/bin/eolian_mono/eolian/mono/function_declaration.hh index 76bbd6103b..fe35c5341d 100644 --- a/src/bin/eolian_mono/eolian/mono/function_declaration.hh +++ b/src/bin/eolian_mono/eolian/mono/function_declaration.hh @@ -19,7 +19,7 @@ struct function_declaration_generator template bool generate(OutputIterator sink, attributes::function_def const& f, Context const& context) const { - if(is_function_blacklisted(f.c_name)) + if(is_function_blacklisted(f.c_name) || f.is_static) return true; if(!as_generator(documentation).generate(sink, f, context)) diff --git a/src/bin/eolian_mono/eolian/mono/function_definition.hh b/src/bin/eolian_mono/eolian/mono/function_definition.hh index 04e8921fad..e030434687 100644 --- a/src/bin/eolian_mono/eolian/mono/function_definition.hh +++ b/src/bin/eolian_mono/eolian/mono/function_definition.hh @@ -11,6 +11,7 @@ #include "grammar/alternative.hpp" #include "grammar/attribute_reorder.hpp" #include "type.hh" +#include "helpers.hh" #include "function_helpers.hh" #include "marshall_type.hh" #include "parameter.hh" @@ -28,7 +29,7 @@ struct native_function_definition_generator template bool generate(OutputIterator sink, attributes::function_def const& f, Context const& context) const { - if(is_function_blacklisted(f.c_name)) + if(is_function_blacklisted(f.c_name) || f.is_static) // Only Concrete classes implement static methods. return true; else { @@ -131,10 +132,11 @@ struct function_definition_generator template bool generate(OutputIterator sink, attributes::function_def const& f, Context const& context) const { + if(do_super && f.is_static) // Static methods goes only on Concrete classes. + return true; if(is_function_blacklisted(f.c_name)) return true; - else - { + if(!as_generator ("\n\n" << scope_tab << "[System.Runtime.InteropServices.DllImport(" << context_find_tag(context).actual_library_name(f.filename) << ")]\n" << scope_tab << eolian_mono::marshall_annotation(true) @@ -159,11 +161,11 @@ struct function_definition_generator return false; if(!as_generator - (scope_tab << (do_super ? "virtual " : "") << "public " << return_type << " " << string << "(" << (parameter % ", ") + (scope_tab << (do_super ? "virtual " : "") << "public " << (f.is_static ? "static " : "") << return_type << " " << string << "(" << (parameter % ", ") << ") {\n " << eolian_mono::function_definition_preamble() << string << "(" << (do_super ? "efl.eo.Globals.efl_super(" : "") - << "this.raw_handle" + << (f.is_static ? klass_get_name(f.klass) + "()": "this.raw_handle") << (do_super ? ", this.raw_klass)" : "") << *(", " << argument_invocation ) << ");\n" << eolian_mono::function_definition_epilogue() @@ -172,7 +174,6 @@ struct function_definition_generator return false; return true; - } } bool do_super; diff --git a/src/bin/eolian_mono/eolian/mono/function_registration.hh b/src/bin/eolian_mono/eolian/mono/function_registration.hh index a88c938924..aaae5511af 100644 --- a/src/bin/eolian_mono/eolian/mono/function_registration.hh +++ b/src/bin/eolian_mono/eolian/mono/function_registration.hh @@ -28,7 +28,7 @@ struct function_registration_generator template bool generate(OutputIterator sink, attributes::function_def const& f, Context const& context) const { - if(is_function_blacklisted(f.c_name)) + if(is_function_blacklisted(f.c_name) || f.is_static) // Static methods aren't overrideable return true; else { diff --git a/src/bin/eolian_mono/eolian/mono/helpers.hh b/src/bin/eolian_mono/eolian/mono/helpers.hh index a281f524d5..420efc6984 100644 --- a/src/bin/eolian_mono/eolian/mono/helpers.hh +++ b/src/bin/eolian_mono/eolian/mono/helpers.hh @@ -125,6 +125,21 @@ inline std::string klass_name_to_csharp(attributes::klass_name const& clsname) return output.str(); } +inline std::string klass_get_name(attributes::klass_name const &clsname) +{ + std::ostringstream output; + + output << klass_name_to_csharp(clsname); + output << "Concrete."; + + for (auto namesp : clsname.namespaces) + output << utils::to_lowercase(namesp) << "_"; + output << utils::to_lowercase(clsname.eolian_name); + output << "_class_get"; + + return output.str(); +} + } #endif diff --git a/src/bin/eolian_mono/eolian/mono/klass.hh b/src/bin/eolian_mono/eolian/mono/klass.hh index 2bfdbea3d7..bf3f27cdd5 100644 --- a/src/bin/eolian_mono/eolian/mono/klass.hh +++ b/src/bin/eolian_mono/eolian/mono/klass.hh @@ -69,12 +69,12 @@ static bool generate_equals_method(OutputIterator sink, Context const &context) /* Get the actual number of functions of a class, checking for blacklisted ones */ static std::size_t -get_function_count(grammar::attributes::klass_def const& cls) +get_inheritable_function_count(grammar::attributes::klass_def const& cls) { auto methods = cls.get_all_methods(); return std::count_if(methods.cbegin(), methods.cend(), [](grammar::attributes::function_def const& func) { - return !is_function_blacklisted(func.c_name); + return !is_function_blacklisted(func.c_name) && !func.is_static; }); } @@ -268,8 +268,9 @@ struct klass << scope_tab << "}\n" << scope_tab << "///Delegate for function to be called from inside the native constructor.\n" << scope_tab << "public delegate void ConstructingMethod(" << string << " obj);\n" + << scope_tab << "///Returns the pointer the unerlying Eo class object. Used internally on class methods.\n" << scope_tab << "[System.Runtime.InteropServices.DllImport(" << context_find_tag(concrete_cxt).actual_library_name(cls.filename) - << ")] private static extern System.IntPtr\n" + << ")] public static extern System.IntPtr\n" << scope_tab << scope_tab << class_get_name << "();\n" << (class_type == "class" ? "" : "/*") << scope_tab << "///Creates a new instance.\n" @@ -451,7 +452,7 @@ struct klass if(!as_generator("}\n").generate(sink, attributes::unused, inherit_cxt)) return false; } - std::size_t function_count = get_function_count(cls); + std::size_t function_count = get_inheritable_function_count(cls); int function_registration_index = 0; auto index_generator = [&function_registration_index] diff --git a/src/lib/eolian_cxx/grammar/klass_def.hpp b/src/lib/eolian_cxx/grammar/klass_def.hpp index 1db8df9444..d5a5894cac 100644 --- a/src/lib/eolian_cxx/grammar/klass_def.hpp +++ b/src/lib/eolian_cxx/grammar/klass_def.hpp @@ -109,6 +109,9 @@ struct klass_name qualifier_def base_qualifier; class_type type; + klass_name() { + } + klass_name(std::vector namespaces , std::string eolian_name, qualifier_def base_qualifier , class_type type) @@ -527,6 +530,7 @@ enum class function_type struct function_def { + klass_name klass; type_def return_type; std::string name; std::vector parameters; @@ -543,7 +547,8 @@ struct function_def friend inline bool operator==(function_def const& lhs, function_def const& rhs) { - return lhs.return_type == rhs.return_type + return lhs.klass == rhs.klass + && lhs.return_type == rhs.return_type && lhs.name == rhs.name && lhs.parameters == rhs.parameters && lhs.c_name == rhs.c_name @@ -561,7 +566,8 @@ struct function_def return !(lhs == rhs); } function_def() = default; - function_def(type_def _return_type, std::string const& _name, + function_def(klass_name _klass, + type_def _return_type, std::string const& _name, std::vector const& _parameters, std::string const& _c_name, std::string _filename, @@ -572,8 +578,9 @@ struct function_def bool _is_beta = false, bool _is_protected = false, Eolian_Unit const* unit = nullptr) - : return_type(_return_type), name(_name), parameters(_parameters), - c_name(_c_name), filename(_filename), documentation(_documentation), + : klass(_klass), return_type(_return_type), name(_name), + parameters(_parameters), c_name(_c_name), filename(_filename), + documentation(_documentation), return_documentation(_return_documentation), property_documentation(_property_documentation), type(_type), @@ -633,8 +640,10 @@ struct function_def c_name = eolian_function_full_c_name_get(function, type, EINA_FALSE); if (type != EOLIAN_FUNCTION_POINTER) { - const Eolian_Class *klass = eolian_function_class_get(function); - filename = eolian_object_file_get((const Eolian_Object *)klass); + const Eolian_Class *eolian_klass = eolian_function_class_get(function); + filename = eolian_object_file_get((const Eolian_Object *)eolian_klass); + klass = klass_name(eolian_klass, + {attributes::qualifier_info::is_none, std::string()}); } else { diff --git a/src/tests/efl_mono/Eo.cs b/src/tests/efl_mono/Eo.cs index 60d66821c7..a0c7a9ea40 100644 --- a/src/tests/efl_mono/Eo.cs +++ b/src/tests/efl_mono/Eo.cs @@ -191,4 +191,21 @@ class TestEoParent } } +class TestKlassMethods +{ + public static void basic_class_method() + { + int reference = 0xbeef; + test.TestingConcrete.SetKlassProp(reference); + Test.AssertEquals(reference, test.TestingConcrete.GetKlassProp()); + } + + public static void inherited_class_method() + { + int reference = 0xdead; + test.ChildConcrete.SetKlassProp(reference); + Test.AssertEquals(reference, test.ChildConcrete.GetKlassProp()); + } +} + } diff --git a/src/tests/efl_mono/libefl_mono_native_test.c b/src/tests/efl_mono/libefl_mono_native_test.c index b16c1625f9..b14fab86c7 100644 --- a/src/tests/efl_mono/libefl_mono_native_test.c +++ b/src/tests/efl_mono/libefl_mono_native_test.c @@ -3763,6 +3763,30 @@ void _test_testing_call_format_cb(EINA_UNUSED Eo *obj, EINA_UNUSED Test_Testing_ func_free_cb(func_data); } +/* Class Properties */ +static int _test_testing_klass_prop = 0; + +int _test_testing_klass_prop_get(Eo *klass, EINA_UNUSED void *pd) +{ + EINA_LOG_ERR("FAIL on GET"); + if (klass != test_testing_class_get()) + { + eina_error_set(EINVAL); + return -1; + } + return _test_testing_klass_prop; +} + +void _test_testing_klass_prop_set(Eo *klass, EINA_UNUSED void *pd, int value) +{ + EINA_LOG_ERR("FAIL on SET"); + if (klass != test_testing_class_get()) + { + eina_error_set(EINVAL); + } + _test_testing_klass_prop = value; +} + #include "test_testing.eo.c" #include "test_numberwrapper.eo.c" diff --git a/src/tests/efl_mono/test_child.eo b/src/tests/efl_mono/test_child.eo new file mode 100644 index 0000000000..d12ba6d3c6 --- /dev/null +++ b/src/tests/efl_mono/test_child.eo @@ -0,0 +1,9 @@ +import eina_types; + +class Test.Child (Test.Testing) { + + implements { + class.constructor; + class.destructor; + } +} diff --git a/src/tests/efl_mono/test_testing.eo b/src/tests/efl_mono/test_testing.eo index 9a9aa0f2d1..966df8e8bc 100644 --- a/src/tests/efl_mono/test_testing.eo +++ b/src/tests/efl_mono/test_testing.eo @@ -1583,6 +1583,14 @@ class Test.Testing (Efl.Object, Efl.Part) { @in func: Test.FormatCb; } } + + @property klass_prop @class { + get {} + set {} + values { + prop: int; + } + } } implements { class.constructor;