cedric pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=dc954d8dba4538ef6cc70cb28bd6c622031825b5

commit dc954d8dba4538ef6cc70cb28bd6c622031825b5
Author: Felipe Magno de Almeida <fel...@expertisesolutions.com.br>
Date:   Fri Apr 1 22:50:28 2016 -0300

    eolian: add Eolian support for Eina Promises
    
    Add a promise object to allows Eolian interface to include promises
    as a way to have asynchronous value return and composibility.
    
    The usage is like this in a .eo file:
    
    class Foo {
       methods {
          bar {
             params {
                @inout promise: Promise<int>;
             }
          }
       }
    }
    
    Which will create the following API interface:
    
    void foo_bar(Eo* obj, Eina_Promise** promise);
    
    and a Eina_Promise_Owner for the implementation, like this:
    
    void _foo_bar(Eo* obj, Private_Data* pdata, Eina_Promise_Owner* promise);
    
    Signed-off-by: Cedric Bail <ced...@osg.samsung.com>
---
 src/Makefile_Eolian.am                      | 13 +++++---
 src/bin/eolian/eo_generator.c               | 48 ++++++++++++++++++++++++++---
 src/lib/eina/eina_promise.h                 | 20 ++++++++++++
 src/lib/eolian/eo_lexer.c                   |  3 +-
 src/lib/eolian/eo_lexer.h                   |  9 ++++--
 src/lib/eolian/eo_parser.c                  |  2 +-
 src/tests/eolian/eolian_generated_promise.c | 46 +++++++++++++++++++++++++++
 src/tests/eolian/generated_promise.eo       | 42 +++++++++++++++++++++++++
 8 files changed, 170 insertions(+), 13 deletions(-)

diff --git a/src/Makefile_Eolian.am b/src/Makefile_Eolian.am
index 2f4554c..a542127 100644
--- a/src/Makefile_Eolian.am
+++ b/src/Makefile_Eolian.am
@@ -111,19 +111,24 @@ tests/eolian/eolian_suite
 tests_eolian_eolian_suite_SOURCES = \
 tests/eolian/eolian_parsing.c \
 tests/eolian/eolian_generation.c \
+tests/eolian/eolian_generated_promise.c \
 tests/eolian/eolian_suite.c \
 tests/eolian/eolian_suite.h
 
-tests_eolian_eolian_suite_CPPFLAGS = -I$(top_builddir)/src/lib/efl \
+tests/eolian/tests_eolian_eolian_suite-eolian_generated_promise.$(OBJEXT): 
tests/eolian/generated_promise.eo.h tests/eolian/generated_promise.eo.c
+
+CLEANFILES += tests/eolian/generated_promise.eo.h 
tests/eolian/generated_promise.eo.c
+
+tests_eolian_eolian_suite_CPPFLAGS = -I$(top_builddir)/src/lib/efl 
-I$(top_builddir)/src/tests/eolian \
 -DTESTS_BUILD_DIR=\"$(top_builddir)/src/tests/eolian\" \
 -DPACKAGE_DATA_DIR=\"$(top_srcdir)/src/tests/eolian\" \
 -DPACKAGE_BUILD_DIR=\"$(abs_top_builddir)\" \
 @CHECK_CFLAGS@ \
-@EOLIAN_CFLAGS@
+@EOLIAN_CFLAGS@ @EO_CFLAGS@
 TESTS += tests/eolian/eolian_suite
 
-tests_eolian_eolian_suite_LDADD = @CHECK_LIBS@ @USE_EOLIAN_LIBS@
-tests_eolian_eolian_suite_DEPENDENCIES = @USE_EOLIAN_INTERNAL_LIBS@
+tests_eolian_eolian_suite_LDADD = @CHECK_LIBS@ @USE_EOLIAN_LIBS@ @USE_EO_LIBS@
+tests_eolian_eolian_suite_DEPENDENCIES = @USE_EOLIAN_INTERNAL_LIBS@ 
@USE_EO_INTERNAL_LIBS@
 tests_eolian_eolian_suite.$(OBJEXT): $(EOLIAN_TESTS_EOS_GENERATED)
 
 endif
diff --git a/src/bin/eolian/eo_generator.c b/src/bin/eolian/eo_generator.c
index 22efb10..78e8108 100644
--- a/src/bin/eolian/eo_generator.c
+++ b/src/bin/eolian/eo_generator.c
@@ -311,6 +311,9 @@ eo_bind_func_generate(const Eolian_Class *class, const 
Eolian_Function *funcid,
    if (ftype != EOLIAN_PROP_GET && ftype != EOLIAN_PROP_SET) ftype = 
eolian_function_type_get(funcid);
    Eina_Bool is_prop = (ftype == EOLIAN_PROP_GET || ftype == EOLIAN_PROP_SET);
 
+   Eina_Bool has_promise = EINA_FALSE;
+   const char* promise_param_name = NULL;
+   const char* promise_value_type = NULL;
    Eina_Bool need_implementation = EINA_TRUE;
    if (!impl_env && eolian_function_is_virtual_pure(funcid, ftype)) 
need_implementation = EINA_FALSE;
 
@@ -318,6 +321,7 @@ eo_bind_func_generate(const Eolian_Class *class, const 
Eolian_Function *funcid,
    Eina_Strbuf *va_args = eina_strbuf_new();
    Eina_Strbuf *params = eina_strbuf_new(); /* only variables names */
    Eina_Strbuf *full_params = eina_strbuf_new(); /* variables types + names */
+   Eina_Strbuf *impl_full_params = eina_strbuf_new(); /* variables types + 
names */
    Eina_Strbuf *params_init = eina_strbuf_new(); /* init of variables to 
default */
 
    rettypet = eolian_function_return_type_get(funcid, ftype);
@@ -360,6 +364,8 @@ eo_bind_func_generate(const Eolian_Class *class, const 
Eolian_Function *funcid,
         eina_strbuf_append_printf(params, "%s", pname);
         eina_strbuf_append_printf(full_params, ", %s %s%s",
               ptype, pname, is_empty || is_auto?" EINA_UNUSED":"");
+        eina_strbuf_append_printf(impl_full_params, ", %s %s%s",
+              ptype, pname, is_empty || is_auto?" EINA_UNUSED":"");
         eina_stringshare_del(ptype);
      }
    eina_iterator_free(itr);
@@ -375,9 +381,33 @@ eo_bind_func_generate(const Eolian_Class *class, const 
Eolian_Function *funcid,
              const char *ptype = eolian_type_c_type_get(ptypet);
              Eolian_Parameter_Dir pdir = eolian_parameter_direction_get(param);
              Eina_Bool had_star = !!strchr(ptype, '*');
+
              if (ftype == EOLIAN_UNRESOLVED || ftype == EOLIAN_METHOD) 
add_star = (pdir == EOLIAN_OUT_PARAM || pdir == EOLIAN_INOUT_PARAM);
+
+             if(!has_promise && !strcmp(ptype, "Eina_Promise *") &&
+                (ftype == EOLIAN_UNRESOLVED || ftype == EOLIAN_METHOD) && pdir 
== EOLIAN_INOUT_PARAM)
+               {
+                  Eina_Iterator* promise_values;
+                  has_promise = EINA_TRUE;
+                  promise_param_name = eina_stringshare_add(pname);
+                  promise_values = 
eolian_type_subtypes_get(eolian_type_base_type_get(ptypet));
+                  Eolian_Type* subtype;
+                  if(eina_iterator_next(promise_values, (void**)&subtype))
+                      promise_value_type = eolian_type_c_type_get(subtype);
+                  eina_strbuf_append_printf(impl_full_params, ", 
Eina_Promise_Owner *%s%s",
+                         pname, is_empty && !dflt_value ?" EINA_UNUSED":"");
+               }
+             else
+               {
+                  eina_strbuf_append_printf(impl_full_params, ", %s%s%s%s%s",
+                        ptype, had_star?"":" ", add_star?"*":"", pname, 
is_empty && !dflt_value ?" EINA_UNUSED":"");
+               }
+
              if (eina_strbuf_length_get(params)) eina_strbuf_append(params, ", 
");
-             eina_strbuf_append_printf(params, "%s", pname);
+             if(has_promise)
+               eina_strbuf_append_printf(params, "%s", "__eo_promise");
+             else
+               eina_strbuf_append_printf(params, "%s", pname);
              eina_strbuf_append_printf(full_params, ", %s%s%s%s%s",
                    ptype, had_star?"":" ", add_star?"*":"", pname, is_empty && 
!dflt_value ?" EINA_UNUSED":"");
              if (is_auto)
@@ -439,7 +469,7 @@ eo_bind_func_generate(const Eolian_Class *class, const 
Eolian_Function *funcid,
                    impl_env?impl_env->lower_classname:"",
                    eolian_function_name_get(funcid), suffix,
                    eolian_function_object_is_const(funcid)?"const ":"",
-                   eina_strbuf_string_get(full_params));
+                   eina_strbuf_string_get(impl_full_params));
           }
 
         if (is_empty || is_auto || eina_strbuf_length_get(params_init))
@@ -457,7 +487,7 @@ eo_bind_func_generate(const Eolian_Class *class, const 
Eolian_Function *funcid,
                    eolian_function_object_is_const(funcid)?"const ":"",
                    is_empty || is_auto?" EINA_UNUSED":"",
                    is_empty || (is_auto && 
!eina_strbuf_length_get(params_init))?" EINA_UNUSED":"",
-                   eina_strbuf_string_get(full_params));
+                   eina_strbuf_string_get(impl_full_params));
           }
         if (eina_strbuf_length_get(params_init))
           {
@@ -511,11 +541,21 @@ eo_bind_func_generate(const Eolian_Class *class, const 
Eolian_Function *funcid,
         Eina_Bool ret_is_void = (!rettype || !strcmp(rettype, "void"));
         _class_func_env_create(class, eolian_function_name_get(funcid), ftype, 
&func_env);
         eina_strbuf_append_printf(eo_func_decl,
-              "EOAPI EO_%sFUNC_BODY%s%s(%s, _EO_EMPTY_HOOK, _EO_EMPTY_HOOK",
+              "EOAPI EO_%sFUNC_BODY%s%s(%s",
               ret_is_void?"VOID_":"", has_params?"V":"",
               (ftype == EOLIAN_PROP_GET ||
                eolian_function_object_is_const(funcid) ||
                eolian_function_is_class(funcid))?"_CONST":"", 
func_env.lower_eo_func);
+        if(has_promise)
+          {
+             eina_strbuf_append_printf(eo_func_decl,
+                   ", _EINA_PROMISE_BEFORE_HOOK(%s, %s%s) _EO_EMPTY_HOOK, 
_EINA_PROMISE_AFTER_HOOK(%s) _EO_EMPTY_HOOK",
+                   promise_value_type, !rettype ? "void" : rettype,
+                   eina_strbuf_string_get(impl_full_params),
+                   promise_param_name);
+          }
+        else
+          eina_strbuf_append_printf(eo_func_decl, ", _EO_EMPTY_HOOK, 
_EO_EMPTY_HOOK");
         if (!ret_is_void)
           {
              const char *val_str = NULL;
diff --git a/src/lib/eina/eina_promise.h b/src/lib/eina/eina_promise.h
index fa9376f..70584e4 100644
--- a/src/lib/eina/eina_promise.h
+++ b/src/lib/eina/eina_promise.h
@@ -438,4 +438,24 @@ EAPI void 
eina_promise_owner_default_manual_then_set(Eina_Promise_Owner* promise
  */
 EAPI void eina_promise_owner_default_call_then(Eina_Promise_Owner* promise);
 
+
+/*
+ * @internal
+ */
+#define _EINA_PROMISE_BEFORE_HOOK(PromiseValue, Ret, ...)               \
+  Eina_Promise_Owner* __eo_promise = 
eina_promise_default_add(sizeof(PromiseValue)); \
+  typedef Ret (*_Eo__Promise_func_)(Eo*, void *obj_data, ##__VA_ARGS__);  \
+  _Eo__Promise_func_ const _promise_func = (_Eo__Promise_func_)_func_;  \
+  {                                                                     \
+    _Eo__Promise_func_ const _func_ = _promise_func;
+
+
+/*
+ * @internal
+ */
+#define _EINA_PROMISE_AFTER_HOOK(Promise)                               \
+  }                                                                     \
+     if(Promise)                                                        \
+       *Promise = eina_promise_owner_promise_get(__eo_promise);
+
 #endif
diff --git a/src/lib/eolian/eo_lexer.c b/src/lib/eolian/eo_lexer.c
index 0e98313..dff540c 100644
--- a/src/lib/eolian/eo_lexer.c
+++ b/src/lib/eolian/eo_lexer.c
@@ -73,9 +73,10 @@ static const char * const ctypes[] =
    "void",
 
    "Eina_Accessor", "Eina_Array", "Eina_Iterator", "Eina_Hash", "Eina_List",
+   "Eina_Promise",
    "Eina_Value",
 
-   "Eo_Event_Cb"
+   "Eo_Event_Cb",
 };
 
 #undef KW
diff --git a/src/lib/eolian/eo_lexer.h b/src/lib/eolian/eo_lexer.h
index b28a3fc..c43e3df 100644
--- a/src/lib/eolian/eo_lexer.h
+++ b/src/lib/eolian/eo_lexer.h
@@ -50,9 +50,12 @@ enum Tokens
     \
     KW(void), \
     \
-    KW(accessor), KW(array), KW(iterator), KW(hash), KW(list), 
KW(generic_value), \
+    KW(accessor), KW(array), KW(iterator), KW(hash), KW(list), \
+    KW(promise), \
+    KW(generic_value), \
     \
-    KW(__builtin_event_cb), KW(__undefined_type), \
+    KW(__builtin_event_cb), \
+    KW(__undefined_type), \
     \
     KW(true), KW(false), KW(null)
 
@@ -206,4 +209,4 @@ void eo_lexer_context_pop    (Eo_Lexer *ls);
 void eo_lexer_context_restore(Eo_Lexer *ls);
 void eo_lexer_context_clear  (Eo_Lexer *ls);
 
-#endif /* __EO_LEXER_H__ */
\ No newline at end of file
+#endif /* __EO_LEXER_H__ */
diff --git a/src/lib/eolian/eo_parser.c b/src/lib/eolian/eo_parser.c
index e02fd57..9b8ec2a 100644
--- a/src/lib/eolian/eo_parser.c
+++ b/src/lib/eolian/eo_parser.c
@@ -782,7 +782,7 @@ parse_type_void_base(Eo_Lexer *ls, Eina_Bool noptr)
              _fill_name(eina_stringshare_ref(ls->t.value.s), &def->full_name,
                         &def->name, &def->namespaces);
              eo_lexer_get(ls);
-             if (tpid >= KW_accessor && tpid <= KW_list)
+             if (tpid >= KW_accessor && tpid <= KW_promise)
                {
                   int bline = ls->line_number, bcol = ls->column;
                   def->type = EOLIAN_TYPE_COMPLEX;
diff --git a/src/tests/eolian/eolian_generated_promise.c 
b/src/tests/eolian/eolian_generated_promise.c
new file mode 100644
index 0000000..2d0e6f6
--- /dev/null
+++ b/src/tests/eolian/eolian_generated_promise.c
@@ -0,0 +1,46 @@
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <Eina.h>
+#include <Eo.h>
+
+#include <check.h>
+
+struct Generated_Promise_Data {};
+typedef struct Generated_Promise_Data Generated_Promise_Data;
+
+static Eina_Promise * _generated_promise_prop1_get(Eo *obj EINA_UNUSED, 
Generated_Promise_Data *pd EINA_UNUSED)
+{
+   return NULL;
+}
+
+static void _generated_promise_prop2_get(Eo *obj EINA_UNUSED, 
Generated_Promise_Data *pd EINA_UNUSED, int *i EINA_UNUSED,
+                                         Eina_Promise **promise1 EINA_UNUSED)
+{
+}
+
+static void _generated_promise_prop3_set(Eo *obj EINA_UNUSED, 
Generated_Promise_Data *pd EINA_UNUSED,
+                                         Eina_Promise *promise1 EINA_UNUSED)
+{
+}
+
+static void _generated_promise_method1(Eo *obj EINA_UNUSED, 
Generated_Promise_Data *pd EINA_UNUSED,
+                                       Eina_Promise_Owner *promise1 
EINA_UNUSED)
+{
+}
+
+static void _generated_promise_method2(Eo *obj EINA_UNUSED, 
Generated_Promise_Data *pd EINA_UNUSED,
+                                       Eina_Promise **promise1 EINA_UNUSED)
+{
+}
+
+static void _generated_promise_method3(Eo *obj EINA_UNUSED, 
Generated_Promise_Data *pd EINA_UNUSED,
+                                       Eina_Promise *promise1 EINA_UNUSED)
+{
+   ck_assert(promise1 != NULL);
+}
+
+#include "generated_promise.eo.h"
+#include "generated_promise.eo.c"
diff --git a/src/tests/eolian/generated_promise.eo 
b/src/tests/eolian/generated_promise.eo
new file mode 100644
index 0000000..66c1a68
--- /dev/null
+++ b/src/tests/eolian/generated_promise.eo
@@ -0,0 +1,42 @@
+class Generated_Promise (Eo.Base)
+{
+   legacy_prefix: null;
+   methods {
+      method1 {
+         params {
+            @inout promise1: promise<int>*;
+         }
+      }
+      method2 {
+         params {
+            @out promise1: promise<int>*;
+         }
+      }
+      method3 {
+         params {
+            @in promise1: promise<int>*;
+         }
+      }
+      @property prop1 {
+         get {}
+         values {
+            promise1: promise<int>*;
+         }
+      }
+      @property prop2 {
+         get {}
+         values {
+            i: int;
+            promise1: promise<int>*;
+         }
+      }
+      @property prop3 {
+         set {}
+         values {
+            promise1: promise<int>*;
+         }
+      }
+   }
+}
+
+

-- 


Reply via email to