eolian: fine-grained is_auto/is_empty for implements

This commit is contained in:
Daniel Kolesa 2017-01-11 19:25:54 +01:00
parent 289287f497
commit baaa482ebf
8 changed files with 109 additions and 80 deletions

View 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);

View 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)

View 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.

View 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)
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_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)
{
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;
}

View 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

View 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)
{

View 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

View 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);