eolian: fine-grained is_auto/is_empty for implements
authorDaniel Kolesa <d.kolesa@osg.samsung.com>
Wed, 11 Jan 2017 18:25:54 +0000 (19:25 +0100)
committerDaniel Kolesa <d.kolesa@osg.samsung.com>
Wed, 11 Jan 2017 18:26:21 +0000 (19:26 +0100)
src/bin/eolian/sources.c
src/bindings/luajit/eolian.lua
src/lib/eolian/Eolian.h
src/lib/eolian/database_fill.c
src/lib/eolian/database_implement_api.c
src/lib/eolian/eo_parser.c
src/lib/eolian/eolian_database.h
src/tests/eolian/eolian_parsing.c

index b602680..67eb2a9 100644 (file)
@@ -119,8 +119,8 @@ _gen_func(const Eolian_Class *cl, const Eolian_Function *fid,
           Eolian_Function_Type ftype, Eina_Strbuf *buf,
           const Eolian_Implement *impl, Eina_Strbuf *lbuf)
 {
-   Eina_Bool is_empty = eolian_implement_is_empty(impl);
-   Eina_Bool is_auto = eolian_implement_is_auto(impl);
+   Eina_Bool is_empty = eolian_implement_is_empty(impl, ftype);
+   Eina_Bool is_auto = eolian_implement_is_auto(impl, ftype);
 
    if ((ftype != EOLIAN_PROP_GET) && (ftype != EOLIAN_PROP_SET))
      ftype = eolian_function_type_get(fid);
index 2b2df9f..409c94e 100644 (file)
@@ -273,9 +273,9 @@ ffi.cdef [[
     const char *eolian_implement_full_name_get(const Eolian_Implement *impl);
     const Eolian_Class *eolian_implement_class_get(const Eolian_Implement *impl);
     const Eolian_Function *eolian_implement_function_get(const Eolian_Implement *impl, Eolian_Function_Type *func_type);
-    Eina_Bool eolian_implement_is_auto(const Eolian_Implement *impl);
-    Eina_Bool eolian_implement_is_empty(const Eolian_Implement *impl);
-    Eina_Bool eolian_implement_is_virtual(const Eolian_Implement *impl);
+    Eina_Bool eolian_implement_is_auto(const Eolian_Implement *impl, Eolian_Function_Type ftype);
+    Eina_Bool eolian_implement_is_empty(const Eolian_Implement *impl, Eolian_Function_Type ftype);
+    Eina_Bool eolian_implement_is_virtual(const Eolian_Implement *impl, Eolian_Function_Type ftype);
     Eina_Bool eolian_implement_is_prop_get(const Eolian_Implement *impl);
     Eina_Bool eolian_implement_is_prop_set(const Eolian_Implement *impl);
     Eina_Iterator *eolian_class_implements_get(const Eolian_Class *klass);
@@ -919,16 +919,16 @@ ffi.metatype("Eolian_Implement", {
             return v, tp[0]
         end,
 
-        is_auto = function(self)
-            return eolian.eolian_implement_is_auto(self) ~= 0
+        is_auto = function(self, ftype)
+            return eolian.eolian_implement_is_auto(self, ftype) ~= 0
         end,
 
-        is_empty = function(self)
-            return eolian.eolian_implement_is_empty(self) ~= 0
+        is_empty = function(self, ftype)
+            return eolian.eolian_implement_is_empty(self, ftype) ~= 0
         end,
 
-        is_virtual = function(self)
-            return eolian.eolian_implement_is_virtual(self) ~= 0
+        is_virtual = function(self, ftype)
+            return eolian.eolian_implement_is_virtual(self, ftype) ~= 0
         end,
 
         is_prop_get = function(self)
index 820bcb5..783c5b9 100644 (file)
@@ -1056,31 +1056,34 @@ EAPI const Eolian_Function *eolian_implement_function_get(const Eolian_Implement
  * @brief Get whether an implement is tagged with @auto.
  *
  * @param[in] impl the handle of the implement
+ * @param[in] f_type The function type, for property get/set distinction.
  * @return EINA_TRUE when it is, EINA_FALSE when it's not.
  *
  * @ingroup Eolian
  */
-EAPI Eina_Bool eolian_implement_is_auto(const Eolian_Implement *impl);
+EAPI Eina_Bool eolian_implement_is_auto(const Eolian_Implement *impl, Eolian_Function_Type f_type);
 
 /*
  * @brief Get whether an implement is tagged with @empty.
  *
  * @param[in] impl the handle of the implement
+ * @param[in] f_type The function type, for property get/set distinction.
  * @return EINA_TRUE when it is, EINA_FALSE when it's not.
  *
  * @ingroup Eolian
  */
-EAPI Eina_Bool eolian_implement_is_empty(const Eolian_Implement *impl);
+EAPI Eina_Bool eolian_implement_is_empty(const Eolian_Implement *impl, Eolian_Function_Type f_type);
 
 /*
  * @brief Get whether an implement is tagged with @virtual.
  *
  * @param[in] impl the handle of the implement
+ * @param[in] f_type The function type, for property get/set distinction.
  * @return EINA_TRUE when it is, EINA_FALSE when it's not.
  *
  * @ingroup Eolian
  */
-EAPI Eina_Bool eolian_implement_is_virtual(const Eolian_Implement *impl);
+EAPI Eina_Bool eolian_implement_is_virtual(const Eolian_Implement *impl, Eolian_Function_Type f_type);
 
 /*
  * @brief Get whether an implement references a property getter.
index a841e26..b904a57 100644 (file)
@@ -66,6 +66,8 @@ _get_impl_func(Eolian_Class *cl, Eolian_Implement *impl,
 
    Eolian_Function_Type aftype = eolian_function_type_get(fid);
 
+   Eina_Bool auto_empty = (impl->get_auto || impl->get_empty);
+
    /* match implement type against function type */
    if (ftype == EOLIAN_PROPERTY)
      {
@@ -76,6 +78,7 @@ _get_impl_func(Eolian_Class *cl, Eolian_Implement *impl,
              fprintf(stderr, "function '%s' is not a complete property", fnname);
              return EINA_FALSE;
           }
+        auto_empty = auto_empty && (impl->set_auto || impl->set_empty);
      }
    else if (ftype == EOLIAN_PROP_SET)
      {
@@ -86,6 +89,7 @@ _get_impl_func(Eolian_Class *cl, Eolian_Implement *impl,
              fprintf(stderr, "function '%s' doesn't have a setter\n", fnname);
              return EINA_FALSE;
           }
+        auto_empty = (impl->set_auto || impl->set_empty);
      }
    else if (ftype == EOLIAN_PROP_GET)
      {
@@ -104,7 +108,7 @@ _get_impl_func(Eolian_Class *cl, Eolian_Implement *impl,
         return EINA_FALSE;
      }
 
-   if ((fid->klass == cl) && !impl->is_auto && !impl->is_empty)
+   if ((fid->klass == cl) && !auto_empty)
      {
         /* only allow explicit implements from other classes, besides auto and
          * empty... also prevents pure virtuals from being implemented
@@ -137,42 +141,18 @@ _db_fill_implement(Eolian_Class *cl, Eolian_Implement *impl)
    if (!_get_impl_func(cl, impl, ftype, &foo_id))
      return EINA_FALSE;
 
-   if (impl->is_auto)
-     {
-        if (ftype == EOLIAN_PROP_GET)
-          {
-             foo_id->get_impl = impl;
-             foo_id->get_auto = EINA_TRUE;
-          }
-        else if (ftype == EOLIAN_PROP_SET)
-          {
-             foo_id->set_impl = impl;
-             foo_id->set_auto = EINA_TRUE;
-          }
-        else
-          {
-             foo_id->get_impl = foo_id->set_impl = impl;
-             foo_id->get_auto = foo_id->set_auto = EINA_TRUE;
-          }
-     }
-   else if (impl->is_empty)
+   foo_id->get_auto = impl->get_auto;
+   foo_id->set_auto = impl->set_auto;
+   foo_id->get_empty = impl->get_empty;
+   foo_id->set_empty = impl->set_empty;
+   if (foo_id->get_auto || foo_id->get_empty)
      {
-        if (ftype == EOLIAN_PROP_GET)
-          {
-             foo_id->get_impl = impl;
-             foo_id->get_empty = EINA_TRUE;
-          }
-        else if (ftype == EOLIAN_PROP_SET)
-          {
-             foo_id->set_impl = impl;
-             foo_id->set_empty = EINA_TRUE;
-          }
-        else
-          {
-             foo_id->get_impl = foo_id->set_impl = impl;
-             foo_id->get_empty = foo_id->set_empty = EINA_TRUE;
-          }
+        if (ftype == EOLIAN_UNRESOLVED)
+          foo_id->set_impl = impl;
+        foo_id->get_impl = impl;
      }
+   if (foo_id->set_auto || foo_id->set_empty)
+     foo_id->set_impl = impl;
 
    return EINA_TRUE;
 }
@@ -205,10 +185,9 @@ _db_build_implement(Eolian_Class *cl, Eolian_Function *foo_id)
 
    if (foo_id->type == EOLIAN_PROPERTY)
      {
-        /* FIXME fugly hack, ideally rework the whole implements api altogether */
         if (foo_id->get_virtual_pure && !foo_id->get_impl)
           {
-             impl->is_virtual = EINA_TRUE;
+             impl->get_virtual = EINA_TRUE;
              impl->is_prop_get = EINA_TRUE;
              foo_id->get_impl = impl;
              cl->implements = eina_list_append(cl->implements, impl);
@@ -218,7 +197,7 @@ _db_build_implement(Eolian_Class *cl, Eolian_Function *foo_id)
           }
         else if (foo_id->set_virtual_pure && !foo_id->set_impl)
           {
-             impl->is_virtual = EINA_TRUE;
+             impl->set_virtual = EINA_TRUE;
              impl->is_prop_set = EINA_TRUE;
              foo_id->set_impl = impl;
              cl->implements = eina_list_append(cl->implements, impl);
@@ -229,7 +208,7 @@ _db_build_implement(Eolian_Class *cl, Eolian_Function *foo_id)
         if (foo_id->get_impl)
           {
              impl->is_prop_set = EINA_TRUE;
-             impl->is_virtual = foo_id->set_virtual_pure;
+             impl->set_virtual = foo_id->set_virtual_pure;
              foo_id->set_impl = impl;
           }
         else if (foo_id->set_impl)
@@ -243,18 +222,18 @@ _db_build_implement(Eolian_Class *cl, Eolian_Function *foo_id)
    else if (foo_id->type == EOLIAN_PROP_SET)
      {
         impl->is_prop_set = EINA_TRUE;
-        impl->is_virtual = foo_id->get_virtual_pure;
+        impl->get_virtual = foo_id->get_virtual_pure;
         foo_id->set_impl = impl;
      }
    else if (foo_id->type == EOLIAN_PROP_GET)
      {
         impl->is_prop_get = EINA_TRUE;
-        impl->is_virtual = foo_id->set_virtual_pure;
+        impl->get_virtual = foo_id->set_virtual_pure;
         foo_id->get_impl = impl;
      }
    else
      {
-        impl->is_virtual = foo_id->get_virtual_pure;
+        impl->get_virtual = foo_id->get_virtual_pure;
         foo_id->get_impl = foo_id->set_impl = impl;
      }
 
index 9ab6a83..4cd31db 100644 (file)
@@ -44,24 +44,39 @@ eolian_implement_function_get(const Eolian_Implement *impl,
 }
 
 EAPI Eina_Bool
-eolian_implement_is_auto(const Eolian_Implement *impl)
+eolian_implement_is_auto(const Eolian_Implement *impl, Eolian_Function_Type ftype)
 {
    EINA_SAFETY_ON_NULL_RETURN_VAL(impl, EINA_FALSE);
-   return impl->is_auto;
+   switch (ftype)
+     {
+      case EOLIAN_UNRESOLVED: case EOLIAN_METHOD: case EOLIAN_PROPERTY: case EOLIAN_PROP_GET: return impl->get_auto; break;
+      case EOLIAN_PROP_SET: return impl->set_auto; break;
+      default: return EINA_FALSE;
+     }
 }
 
 EAPI Eina_Bool
-eolian_implement_is_empty(const Eolian_Implement *impl)
+eolian_implement_is_empty(const Eolian_Implement *impl, Eolian_Function_Type ftype)
 {
    EINA_SAFETY_ON_NULL_RETURN_VAL(impl, EINA_FALSE);
-   return impl->is_empty;
+   switch (ftype)
+     {
+      case EOLIAN_UNRESOLVED: case EOLIAN_METHOD: case EOLIAN_PROPERTY: case EOLIAN_PROP_GET: return impl->get_empty; break;
+      case EOLIAN_PROP_SET: return impl->set_empty; break;
+      default: return EINA_FALSE;
+     }
 }
 
 EAPI Eina_Bool
-eolian_implement_is_virtual(const Eolian_Implement *impl)
+eolian_implement_is_virtual(const Eolian_Implement *impl, Eolian_Function_Type ftype)
 {
    EINA_SAFETY_ON_NULL_RETURN_VAL(impl, EINA_FALSE);
-   return impl->is_virtual;
+   switch (ftype)
+     {
+      case EOLIAN_UNRESOLVED: case EOLIAN_METHOD: case EOLIAN_PROPERTY: case EOLIAN_PROP_GET: return impl->get_virtual; break;
+      case EOLIAN_PROP_SET: return impl->set_virtual; break;
+      default: return EINA_FALSE;
+     }
 }
 
 EAPI Eina_Bool
index 8764c06..e3d72c4 100644 (file)
@@ -1520,14 +1520,15 @@ parse_implement(Eo_Lexer *ls, Eina_Bool iface)
    impl = calloc(1, sizeof(Eolian_Implement));
    FILL_BASE(impl->base, ls, iline, icol);
    ls->tmp.kls->implements = eina_list_append(ls->tmp.kls->implements, impl);
+   Eina_Bool glob_auto = EINA_FALSE, glob_empty = EINA_FALSE;
    switch (ls->t.kw)
      {
         case KW_at_auto:
-          impl->is_auto = EINA_TRUE;
+          glob_auto = EINA_TRUE;
           eo_lexer_get(ls);
           break;
         case KW_at_empty:
-          impl->is_empty = EINA_TRUE;
+          glob_empty = EINA_TRUE;
           eo_lexer_get(ls);
           break;
         default:
@@ -1535,9 +1536,7 @@ parse_implement(Eo_Lexer *ls, Eina_Bool iface)
      }
    if (ls->t.token == '.')
      {
-        if (!impl->is_auto && !impl->is_empty)
-          eo_lexer_syntax_error(ls, "class name expected");
-        check_next(ls, '.');
+        eo_lexer_get(ls);
         if (ls->t.token != TOK_VALUE)
           eo_lexer_syntax_error(ls, "name expected");
         impl->full_name = eina_stringshare_printf("%s.%s",
@@ -1582,12 +1581,36 @@ propbeg:
              CASE_LOCK(ls, get, "get specifier");
              eo_lexer_get(ls);
              impl->is_prop_get = EINA_TRUE;
+             impl->get_auto = glob_auto;
+             impl->get_empty = glob_empty;
+             if (ls->t.kw == KW_at_auto)
+               {
+                  impl->get_auto = EINA_TRUE;
+                  eo_lexer_get(ls);
+               }
+             else if (ls->t.kw == KW_at_empty)
+               {
+                  impl->get_empty = EINA_TRUE;
+                  eo_lexer_get(ls);
+               }
              check_next(ls, ';');
              break;
            case KW_set:
              CASE_LOCK(ls, set, "set specifier");
              eo_lexer_get(ls);
              impl->is_prop_set = EINA_TRUE;
+             impl->set_auto = glob_auto;
+             impl->set_empty = glob_empty;
+             if (ls->t.kw == KW_at_auto)
+               {
+                  impl->set_auto = EINA_TRUE;
+                  eo_lexer_get(ls);
+               }
+             else if (ls->t.kw == KW_at_empty)
+               {
+                  impl->set_empty = EINA_TRUE;
+                  eo_lexer_get(ls);
+               }
              check_next(ls, ';');
              break;
            default:
@@ -1599,7 +1622,13 @@ propend:
         check_next(ls, '}');
      }
    else
-     check_next(ls, ';');
+     {
+        if (glob_auto)
+          impl->get_auto = impl->set_auto = EINA_TRUE;
+        if (glob_empty)
+          impl->get_empty = impl->set_empty = EINA_TRUE;
+        check_next(ls, ';');
+     }
 end:
    if (buf)
      {
index 783558e..0c8157a 100644 (file)
@@ -201,11 +201,14 @@ struct _Eolian_Implement
    const Eolian_Class *klass;
    const Eolian_Function *foo_id;
    Eina_Stringshare *full_name;
-   Eina_Bool is_virtual :1;
    Eina_Bool is_prop_get :1;
    Eina_Bool is_prop_set :1;
-   Eina_Bool is_auto: 1;
-   Eina_Bool is_empty: 1;
+   Eina_Bool get_virtual :1;
+   Eina_Bool set_virtual :1;
+   Eina_Bool get_auto: 1;
+   Eina_Bool set_auto: 1;
+   Eina_Bool get_empty: 1;
+   Eina_Bool set_empty: 1;
 };
 
 struct _Eolian_Constructor
index 7185ab2..3e8e4eb 100644 (file)
@@ -202,18 +202,18 @@ START_TEST(eolian_override)
    fail_if(!(iter = eolian_class_implements_get(class)));
 
    fail_if(!(eina_iterator_next(iter, (void**)&impl)));
-   fail_if(eolian_implement_is_auto(impl));
-   fail_if(eolian_implement_is_empty(impl));
-   fail_if(eolian_implement_is_virtual(impl));
+   fail_if(eolian_implement_is_auto(impl, EOLIAN_METHOD));
+   fail_if(eolian_implement_is_empty(impl, EOLIAN_METHOD));
+   fail_if(eolian_implement_is_virtual(impl, EOLIAN_METHOD));
    fail_if(!(impl_class = eolian_implement_class_get(impl)));
    fail_if(!(impl_func = eolian_implement_function_get(impl, NULL)));
    fail_if(impl_class != base);
    fail_if(strcmp(eolian_function_name_get(impl_func), "constructor"));
 
    fail_if(!(eina_iterator_next(iter, (void**)&impl)));
-   fail_if(!eolian_implement_is_auto(impl));
-   fail_if(eolian_implement_is_empty(impl));
-   fail_if(eolian_implement_is_virtual(impl));
+   fail_if(!eolian_implement_is_auto(impl, EOLIAN_PROP_SET));
+   fail_if(eolian_implement_is_empty(impl, EOLIAN_PROP_SET));
+   fail_if(eolian_implement_is_virtual(impl, EOLIAN_PROP_SET));
    fail_if(!(impl_class = eolian_implement_class_get(impl)));
    fail_if(!(impl_func = eolian_implement_function_get(impl, NULL)));
    fail_if(impl_class != class);
@@ -226,9 +226,9 @@ START_TEST(eolian_override)
    fail_if(eolian_function_is_virtual_pure(impl_func, EOLIAN_PROP_GET));
 
    fail_if(!(eina_iterator_next(iter, (void**)&impl)));
-   fail_if(eolian_implement_is_auto(impl));
-   fail_if(!eolian_implement_is_empty(impl));
-   fail_if(eolian_implement_is_virtual(impl));
+   fail_if(eolian_implement_is_auto(impl, EOLIAN_METHOD));
+   fail_if(!eolian_implement_is_empty(impl, EOLIAN_METHOD));
+   fail_if(eolian_implement_is_virtual(impl, EOLIAN_METHOD));
    fail_if(!(impl_class = eolian_implement_class_get(impl)));
    fail_if(!(impl_func = eolian_implement_function_get(impl, NULL)));
    fail_if(impl_class != class);