From fe7ea44c5114400f2842aa5dd686dfd977e37e86 Mon Sep 17 00:00:00 2001 From: Vitor Sousa Date: Thu, 28 Feb 2019 11:09:38 -0300 Subject: [PATCH] efl_csharp: add constant variable generation to C# binding (constants) Reviewers: lauromoura, q66, bu5hm4n, zmike, cedric, felipealmeida, segfaultxavi Reviewed By: segfaultxavi Subscribers: segfaultxavi, cedric, #reviewers, #committers Tags: #efl_language_bindings Differential Revision: https://phab.enlightenment.org/D8048 --- src/Makefile_Efl_Mono.am | 1 + .../eolian_mono/eolian/mono/generation_contexts.hh | 1 + .../eolian_mono/eolian/mono/variable_definition.hh | 93 ++++++++++++++++++++++ src/bin/eolian_mono/eolian_mono.cc | 15 ++++ src/lib/eolian_cxx/grammar/klass_def.hpp | 64 +++++++++++++++ src/tests/efl_mono/Eo.cs | 18 +++++ src/tests/efl_mono/dummy_test_object.eo | 12 +++ 7 files changed, 204 insertions(+) create mode 100644 src/bin/eolian_mono/eolian/mono/variable_definition.hh diff --git a/src/Makefile_Efl_Mono.am b/src/Makefile_Efl_Mono.am index 1619411..fe8c66e 100644 --- a/src/Makefile_Efl_Mono.am +++ b/src/Makefile_Efl_Mono.am @@ -82,6 +82,7 @@ bin_eolian_mono_eolian_mono_SOURCES = \ bin/eolian_mono/eolian/mono/part_definition.hh \ bin/eolian_mono/eolian/mono/struct_fields.hh \ bin/eolian_mono/eolian/mono/parameter.hh \ + bin/eolian_mono/eolian/mono/variable_definition.hh \ bin/eolian_mono/eolian/mono/utils.hh \ bin/eolian_mono/eolian/mono/using_decl.hh \ bin/eolian_mono/eolian/mono/marshall_type.hh \ diff --git a/src/bin/eolian_mono/eolian/mono/generation_contexts.hh b/src/bin/eolian_mono/eolian/mono/generation_contexts.hh index 9a1493a..5cc57ef 100644 --- a/src/bin/eolian_mono/eolian/mono/generation_contexts.hh +++ b/src/bin/eolian_mono/eolian/mono/generation_contexts.hh @@ -14,6 +14,7 @@ struct class_context enums, function_ptr, alias, + variables, }; wrapper_kind current_wrapper_kind; }; diff --git a/src/bin/eolian_mono/eolian/mono/variable_definition.hh b/src/bin/eolian_mono/eolian/mono/variable_definition.hh new file mode 100644 index 0000000..2a0eac3 --- /dev/null +++ b/src/bin/eolian_mono/eolian/mono/variable_definition.hh @@ -0,0 +1,93 @@ +#ifndef EOLIAN_MONO_VARIABLE_DEFINITION_HH +#define EOLIAN_MONO_VARIABLE_DEFINITION_HH + +#include + +#include "grammar/generator.hpp" +#include "grammar/klass_def.hpp" + +#include "grammar/indentation.hpp" +#include "grammar/list.hpp" +#include "grammar/alternative.hpp" +#include "grammar/attribute_reorder.hpp" +#include "logging.hh" +#include "type.hh" +#include "name_helpers.hh" +#include "helpers.hh" +#include "function_helpers.hh" +#include "marshall_type.hh" +#include "parameter.hh" +#include "documentation.hh" +#include "using_decl.hh" +#include "generation_contexts.hh" +#include "blacklist.hh" + +namespace eolian_mono { + + +struct constant_definition_generator +{ + template + bool generate(OutputIterator sink, attributes::variable_def constant, Context context) const + { + // Open partial class + if (!name_helpers::open_namespaces(sink, constant.namespaces, context)) + return false; + + if (!as_generator("public partial class Constants {\n").generate(sink, attributes::unused, context)) + return false; + + std::string literal; + if (constant.expression_value.type == EOLIAN_EXPR_NULL) + literal = "null"; + else if (constant.expression_value.type == EOLIAN_EXPR_BOOL) + literal = (constant.expression_value.value.b ? "true" : "false"); + else + { + auto lit = ::eolian_expression_value_to_literal(&constant.expression_value); + if (!lit) + return false; + literal = lit; + ::eina_stringshare_del(lit); + } + + // declare variable + if (!as_generator(scope_tab(1) + << "public static readonly " << type + << " " << utils::remove_all(constant.name, '_') + << " = " << literal << ";\n") + .generate(sink, constant.base_type, context)) + return false; + + // FIXME missing documentation generator + + // Close partial class + if (!as_generator("}\n").generate(sink, attributes::unused, context)) + return false; + + if (!name_helpers::close_namespaces(sink, constant.namespaces, context)) + return false; + + return true; + + + } +} const constant_definition; + +} + +namespace efl { namespace eolian { namespace grammar { + +template <> +struct is_eager_generator< ::eolian_mono::constant_definition_generator> : std::true_type {}; +template <> +struct is_generator< ::eolian_mono::constant_definition_generator> : std::true_type {}; + +namespace type_traits { +template <> +struct attributes_needed< ::eolian_mono::constant_definition_generator> : std::integral_constant {}; +} + +} } } + +#endif diff --git a/src/bin/eolian_mono/eolian_mono.cc b/src/bin/eolian_mono/eolian_mono.cc index 235f250..58c725c 100644 --- a/src/bin/eolian_mono/eolian_mono.cc +++ b/src/bin/eolian_mono/eolian_mono.cc @@ -33,6 +33,7 @@ #include #include #include +#include namespace eolian_mono { @@ -168,6 +169,20 @@ run(options_type const& opts) } } + // Constants + { + auto var_cxt = context_add_tag(class_context{class_context::variables}, context); + for (efl::eina::iterator var_iterator( ::eolian_state_constants_by_file_get(opts.state, basename_input.c_str())) + , var_last; var_iterator != var_last; ++var_iterator) + { + efl::eolian::grammar::attributes::variable_def var(&*var_iterator, opts.unit); + if (!eolian_mono::constant_definition.generate(iterator, var, var_cxt)) + { + throw std::runtime_error("Failed to generate enum"); + } + } + } + if (klass) { efl::eolian::grammar::attributes::klass_def klass_def(klass, opts.unit); diff --git a/src/lib/eolian_cxx/grammar/klass_def.hpp b/src/lib/eolian_cxx/grammar/klass_def.hpp index 5fb0dbb..cba2fb1 100644 --- a/src/lib/eolian_cxx/grammar/klass_def.hpp +++ b/src/lib/eolian_cxx/grammar/klass_def.hpp @@ -91,6 +91,14 @@ inline typedecl_type typedecl_type_get(Eolian_Typedecl const* decl) } } +enum class variable_type +{ + unknown, + constant, + global +}; + + struct type_def; bool operator==(type_def const& rhs, type_def const& lhs); bool operator!=(type_def const& rhs, type_def const& lhs); @@ -857,6 +865,62 @@ struct property_def } }; +struct variable_def +{ + std::string name; + std::string full_name; + type_def base_type; + documentation_def documentation; + variable_type type; + std::vector namespaces; + Eolian_Value expression_value; + bool is_extern : 1; + + friend inline bool operator==(variable_def const& lhs, variable_def const& rhs) + { + return lhs.name == rhs.name + && lhs.full_name == rhs.full_name + && lhs.base_type == rhs.base_type + && lhs.documentation == rhs.documentation + && lhs.type == rhs.type + && lhs.namespaces == rhs.namespaces + && lhs.expression_value.type == rhs.expression_value.type + && lhs.expression_value.value.ll == rhs.expression_value.value.ll + && lhs.is_extern == rhs.is_extern; + } + + friend inline bool operator!=(variable_def const& lhs, variable_def const& rhs) + { + return !(lhs == rhs); + } + + variable_def() = default; + variable_def(Eolian_Variable const* variable, Eolian_Unit const* unit) + : name(::eolian_variable_short_name_get(variable)) + , full_name(::eolian_variable_name_get(variable)) + , base_type(::eolian_variable_base_type_get(variable), unit, ::EOLIAN_C_TYPE_DEFAULT) + , documentation(::eolian_variable_documentation_get(variable)) + , type(static_cast(::eolian_variable_type_get(variable))) + , expression_value() + , is_extern(::eolian_variable_is_extern(variable)) + { + for(efl::eina::iterator namespace_iterator( ::eolian_variable_namespaces_get(variable)) + , namespace_last; namespace_iterator != namespace_last; ++namespace_iterator) + { + this->namespaces.push_back((&*namespace_iterator)); + } + + if (this->type == variable_type::constant) + { + auto expr = ::eolian_variable_value_get(variable); + if (!expr) + throw std::runtime_error("Could not get constant variable value expression"); + + this->expression_value = ::eolian_expression_eval_type(expr, ::eolian_variable_base_type_get(variable)); + } + } +}; + // template // struct tuple_element : tuple_element {}; diff --git a/src/tests/efl_mono/Eo.cs b/src/tests/efl_mono/Eo.cs index ed1d65a..3e7f662 100644 --- a/src/tests/efl_mono/Eo.cs +++ b/src/tests/efl_mono/Eo.cs @@ -190,6 +190,24 @@ class TestTypedefs } } +class TestVariables +{ + public static void test_constant_variables() + { + Test.AssertEquals(Dummy.Constants.ConstvarBool, true); + Test.AssertEquals(Dummy.Constants.ConstvarInt, -32766); + Test.AssertEquals(Dummy.Constants.ConstvarUInt, 65533U); + Test.AssertEquals(Dummy.Constants.ConstvarLong, -2147483644L); + Test.AssertEquals(Dummy.Constants.ConstvarULong, 4294967288UL); + //Test.AssertEquals(Dummy.Constants.ConstvarLLong, -9223372036854775800); // TODO + //Test.AssertEquals(Dummy.Constants.ConstvarULLong, 18446744073709551615); + Test.AssertEquals(Dummy.Constants.ConstvarFloat, 16777211.0f); + Test.AssertEquals(Dummy.Constants.ConstvarDouble, 9007199254740988.0); + Test.AssertEquals(Dummy.Constants.ConstvarChar, '!'); + Test.AssertEquals(Dummy.Constants.ConstvarString, "test_str"); + } +} + class TestEoAccessors { public static void basic_eo_accessors() diff --git a/src/tests/efl_mono/dummy_test_object.eo b/src/tests/efl_mono/dummy_test_object.eo index 99e8d02..f405cd4 100644 --- a/src/tests/efl_mono/dummy_test_object.eo +++ b/src/tests/efl_mono/dummy_test_object.eo @@ -2,6 +2,18 @@ import eina_types; type Dummy.MyInt: int; +const Dummy.Constvar_Bool : bool = true; +const Dummy.Constvar_Int : int = -32766; +const Dummy.Constvar_UInt : uint = 65533U; +const Dummy.Constvar_Long : long = -2147483644L; +const Dummy.Constvar_ULong : ulong = 4294967288UL; +const Dummy.Constvar_LLong : llong = -9223372036854775800LL; +const Dummy.Constvar_ULLong : ullong = 18446744073709551615ULL; +const Dummy.Constvar_Float : float = 16777211.0f; +const Dummy.Constvar_Double : double = 9007199254740988.0; +const Dummy.Constvar_Char : char = '!'; +const Dummy.Constvar_String : string = "test_str"; + enum Dummy.SampleEnum { v0, v1, -- 2.7.4