efl_csharp: add constant variable generation to C# binding (constants)
authorVitor Sousa <vitorsousa@expertisesolutions.com.br>
Thu, 28 Feb 2019 14:09:38 +0000 (11:09 -0300)
committerWonki Kim <wonki_.kim@samsung.com>
Fri, 8 Mar 2019 11:49:37 +0000 (20:49 +0900)
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
src/bin/eolian_mono/eolian/mono/generation_contexts.hh
src/bin/eolian_mono/eolian/mono/variable_definition.hh [new file with mode: 0644]
src/bin/eolian_mono/eolian_mono.cc
src/lib/eolian_cxx/grammar/klass_def.hpp
src/tests/efl_mono/Eo.cs
src/tests/efl_mono/dummy_test_object.eo

index 1619411..fe8c66e 100644 (file)
@@ -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 \
index 9a1493a..5cc57ef 100644 (file)
@@ -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 (file)
index 0000000..2a0eac3
--- /dev/null
@@ -0,0 +1,93 @@
+#ifndef EOLIAN_MONO_VARIABLE_DEFINITION_HH
+#define EOLIAN_MONO_VARIABLE_DEFINITION_HH
+
+#include <Eina.hh>
+
+#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<typename OutputIterator, typename Context>
+  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<int, 1> {};
+}
+
+} } }
+
+#endif
index 235f250..58c725c 100644 (file)
@@ -33,6 +33,7 @@
 #include <eolian/mono/marshall_annotation.hh>
 #include <eolian/mono/function_pointer.hh>
 #include <eolian/mono/alias_definition.hh>
+#include <eolian/mono/variable_definition.hh>
 
 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<const Eolian_Variable> 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);
index 5fb0dbb..cba2fb1 100644 (file)
@@ -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<std::string> 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<variable_type>(::eolian_variable_type_get(variable)))
+        , expression_value()
+        , is_extern(::eolian_variable_is_extern(variable))
+  {
+     for(efl::eina::iterator<const char> 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 <int N>
 // struct tuple_element<N, function_def const> : tuple_element<N, function_def> {};
index ed1d65a..3e7f662 100644 (file)
@@ -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()
index 99e8d02..f405cd4 100644 (file)
@@ -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,