From baaa482ebff9c006390cff6e8c3a4f4094545857 Mon Sep 17 00:00:00 2001 From: Daniel Kolesa Date: Wed, 11 Jan 2017 19:25:54 +0100 Subject: [PATCH] eolian: fine-grained is_auto/is_empty for implements --- src/bin/eolian/sources.c | 4 +-- src/bindings/luajit/eolian.lua | 18 +++++----- src/lib/eolian/Eolian.h | 9 +++-- src/lib/eolian/database_fill.c | 63 +++++++++++---------------------- src/lib/eolian/database_implement_api.c | 27 ++++++++++---- src/lib/eolian/eo_parser.c | 41 +++++++++++++++++---- src/lib/eolian/eolian_database.h | 9 +++-- src/tests/eolian/eolian_parsing.c | 18 +++++----- 8 files changed, 109 insertions(+), 80 deletions(-) diff --git a/src/bin/eolian/sources.c b/src/bin/eolian/sources.c index b602680..67eb2a9 100644 --- a/src/bin/eolian/sources.c +++ b/src/bin/eolian/sources.c @@ -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); diff --git a/src/bindings/luajit/eolian.lua b/src/bindings/luajit/eolian.lua index 2b2df9f..409c94e 100644 --- a/src/bindings/luajit/eolian.lua +++ b/src/bindings/luajit/eolian.lua @@ -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) diff --git a/src/lib/eolian/Eolian.h b/src/lib/eolian/Eolian.h index 820bcb5..783c5b9 100644 --- a/src/lib/eolian/Eolian.h +++ b/src/lib/eolian/Eolian.h @@ -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. diff --git a/src/lib/eolian/database_fill.c b/src/lib/eolian/database_fill.c index a841e26..b904a57 100644 --- a/src/lib/eolian/database_fill.c +++ b/src/lib/eolian/database_fill.c @@ -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; } diff --git a/src/lib/eolian/database_implement_api.c b/src/lib/eolian/database_implement_api.c index 9ab6a83..4cd31db 100644 --- a/src/lib/eolian/database_implement_api.c +++ b/src/lib/eolian/database_implement_api.c @@ -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 diff --git a/src/lib/eolian/eo_parser.c b/src/lib/eolian/eo_parser.c index 8764c06..e3d72c4 100644 --- a/src/lib/eolian/eo_parser.c +++ b/src/lib/eolian/eo_parser.c @@ -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) { diff --git a/src/lib/eolian/eolian_database.h b/src/lib/eolian/eolian_database.h index 783558e..0c8157a 100644 --- a/src/lib/eolian/eolian_database.h +++ b/src/lib/eolian/eolian_database.h @@ -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 diff --git a/src/tests/eolian/eolian_parsing.c b/src/tests/eolian/eolian_parsing.c index 7185ab2..3e8e4eb 100644 --- a/src/tests/eolian/eolian_parsing.c +++ b/src/tests/eolian/eolian_parsing.c @@ -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); -- 2.7.4