Eolian/Generator: support params initialization.

This is needed when get properties or methods have to return a
value in case of failure or to initialize parameters.
The way used is to generate an intermediate function that will
initialize the parameters and then invoke the "user" function.
This commit is contained in:
Daniel Zaoui 2014-09-02 17:00:14 +03:00
parent 3f468537fd
commit ffa9ad7daf
5 changed files with 138 additions and 9 deletions

View File

@ -116,5 +116,6 @@ tests/eolian/data/class_funcs.eo \
tests/eolian/data/enum.eo \
tests/eolian/data/free_func.eo \
tests/eolian/data/typedef_ref.c \
tests/eolian/data/struct_ref.c
tests/eolian/data/struct_ref.c \
tests/eolian/data/class_simple_ref.c

View File

@ -6,6 +6,10 @@
#include "common_funcs.h"
static _eolian_class_vars class_env;
/* Used to store the function names that will have to be appended
* with __eolian during C generation. Needed when params have to
* be initialized and for future features. */
static Eina_Hash *_funcs_params_init = NULL;
static const char
tmpl_dtor[] = "\
@ -348,6 +352,7 @@ eo_bind_func_generate(const Eolian_Class *class, const Eolian_Function *funcid,
Eina_Bool add_star = EINA_FALSE;
Eina_Iterator *itr;
void *data, *data2;
const Eolian_Expression *default_ret_val = NULL;
Eina_Bool need_implementation = EINA_TRUE;
if (!impl_env && eolian_function_is_virtual_pure(funcid, ftype)) need_implementation = EINA_FALSE;
@ -356,8 +361,11 @@ 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 *params_init = eina_strbuf_new(); /* init of variables to default */
rettypet = eolian_function_return_type_get(funcid, ftype);
if (rettypet)
default_ret_val = eolian_function_return_default_value_get(funcid, ftype);
if (ftype == EOLIAN_PROP_GET)
{
suffix = "_get";
@ -372,6 +380,7 @@ eo_bind_func_generate(const Eolian_Class *class, const Eolian_Function *funcid,
rettypet = eolian_parameter_type_get(param);
var_as_ret = EINA_TRUE;
ret_const = eolian_parameter_const_attribute_get(data, EINA_TRUE);
default_ret_val = eolian_parameter_default_value_get(param);
}
eina_iterator_free(itr);
}
@ -415,6 +424,30 @@ eo_bind_func_generate(const Eolian_Class *class, const Eolian_Function *funcid,
eina_strbuf_append_printf(full_params, ", %s%s%s%s%s",
is_const?"const ":"",
ptype, had_star?"":" ", add_star?"*":"", pname);
if (ftype != EOLIAN_PROP_SET)
{
const Eolian_Expression *dflt_value = eolian_parameter_default_value_get(param);
if (dflt_value)
{
const char *val_str = NULL;
Eolian_Value val = eolian_expression_eval
(dflt_value, EOLIAN_MASK_ALL);
if (val.type)
{
val_str = eolian_expression_value_to_literal(&val);
eina_strbuf_append_printf(params_init,
" if (%s) *%s = %s;",
pname, pname, val_str);
if (eolian_expression_type_get(dflt_value) == EOLIAN_EXPR_ENUM)
{
Eina_Stringshare *string = eolian_expression_serialize(dflt_value);
eina_strbuf_append_printf(params_init, " /* %s */", string);
eina_stringshare_del(string);
}
eina_strbuf_append_printf(params_init, "\n");
}
}
}
eina_stringshare_del(ptype);
}
eina_iterator_free(itr);
@ -433,6 +466,25 @@ eo_bind_func_generate(const Eolian_Class *class, const Eolian_Function *funcid,
impl_env?impl_env->lower_classname:"",
eolian_function_name_get(funcid), suffix);
if (eina_strbuf_length_get(params_init))
{
eina_hash_add(_funcs_params_init,
eina_stringshare_add(eolian_function_name_get(funcid)), funcid);
eina_strbuf_append_printf(fbody, "static %s%s __eolian_%s%s%s_%s%s(Eo *obj, @#Datatype_Data *pd@#full_params)\n{\n%s\n",
ret_const?"const ":"", rettype?rettype:"void",
class_env.lower_classname,
impl_env?"_":"",
impl_env?impl_env->lower_classname:"",
eolian_function_name_get(funcid), suffix,
eina_strbuf_string_get(params_init));
eina_strbuf_append_printf(fbody, " %s_%s%s%s_%s%s(obj, pd, %s);\n}\n\n",
rettype?"return ":"",
class_env.lower_classname,
impl_env?"_":"",
impl_env?impl_env->lower_classname:"",
eolian_function_name_get(funcid), suffix,
eina_strbuf_string_get(params));
}
eina_strbuf_free(ret_param);
}
if (!impl_env)
@ -458,20 +510,23 @@ eo_bind_func_generate(const Eolian_Class *class, const Eolian_Function *funcid,
func_env.lower_eo_func);
if (!ret_is_void)
{
const Eolian_Expression *default_ret_val =
eolian_function_return_default_value_get(funcid, ftype);
const char *val_str = NULL;
if (default_ret_val)
{
Eolian_Value val = eolian_expression_eval_type
(default_ret_val, rettypet);
Eolian_Value val = eolian_expression_eval
(default_ret_val, EOLIAN_MASK_ALL);
if (val.type)
val_str = eolian_expression_value_to_literal(&val);
}
eina_strbuf_append_printf(eo_func_decl, ", %s%s, %s",
ret_const ? "const " : "", rettype,
val_str?val_str:"0");
if (val_str && eolian_expression_type_get(default_ret_val) == EOLIAN_EXPR_ENUM)
{
Eina_Stringshare *string = eolian_expression_serialize(default_ret_val);
eina_strbuf_append_printf(eo_func_decl, " /* %s */", string);
eina_stringshare_del(string);
}
}
if (has_params)
{
@ -508,6 +563,7 @@ eo_bind_func_generate(const Eolian_Class *class, const Eolian_Function *funcid,
eina_strbuf_free(va_args);
eina_strbuf_free(full_params);
eina_strbuf_free(params_init);
eina_strbuf_free(params);
eina_strbuf_free(fbody);
return EINA_TRUE;
@ -530,7 +586,12 @@ eo_op_desc_generate(const Eolian_Class *class, Eolian_Function *fid, Eolian_Func
if (eolian_function_is_class(fid)) class_str = "CLASS_";
eina_strbuf_append_printf(buf, "\n EO_OP_%sFUNC(%s, ", class_str, func_env.lower_eo_func);
if (!is_virtual_pure)
eina_strbuf_append_printf(buf, "_%s_%s%s, \"%s\"),", class_env.lower_classname, funcname, suffix, desc);
{
eina_strbuf_append_printf(buf, "%s_%s_%s%s, \"%s\"),",
eina_hash_find(_funcs_params_init, funcname)
&& ftype != EOLIAN_PROP_SET?"__eolian":"",
class_env.lower_classname, funcname, suffix, desc);
}
else
eina_strbuf_append_printf(buf, "NULL, \"%s\"),", desc);
@ -863,6 +924,7 @@ eo_source_generate(const Eolian_Class *class, Eina_Strbuf *buf)
Eina_Strbuf *str_bodyf = eina_strbuf_new();
_class_env_create(class, NULL, &class_env);
_funcs_params_init = eina_hash_stringshared_new(NULL);
if (!eo_source_beginning_generate(class, buf)) goto end;
@ -901,6 +963,8 @@ eo_source_generate(const Eolian_Class *class, Eina_Strbuf *buf)
ret = EINA_TRUE;
end:
eina_hash_free(_funcs_params_init);
_funcs_params_init = NULL;
eina_strbuf_free(str_bodyf);
return ret;
}

View File

@ -16,8 +16,8 @@ class Evas.Line (Evas.Object)
second end point. */
}
values {
Evas_Coord x1; /*@ The X coordinate of the first point. */
Evas_Coord y1; /*@ The Y coordinate of the first point. */
Evas_Coord x1(0); /*@ The X coordinate of the first point. */
Evas_Coord y1(3); /*@ The Y coordinate of the first point. */
Evas_Coord x2; /*@ The X coordinate of the second point. */
Evas_Coord y2; /*@ The Y coordinate of the second point. */
}

View File

@ -0,0 +1,47 @@
Eina_Bool _class_simple_a_set(Eo *obj, Evas_Simple_Data *pd, int value);
EOAPI EO_FUNC_BODYV(evas_obj_simple_a_set, Eina_Bool, EINA_TRUE, EO_FUNC_CALL(value), int value);
int _class_simple_a_get(Eo *obj, Evas_Simple_Data *pd);
EOAPI EO_FUNC_BODY(evas_obj_simple_a_get, int, 100);
void _class_simple_b_set(Eo *obj, Evas_Simple_Data *pd);
EOAPI EO_VOID_FUNC_BODY(evas_obj_simple_b_set);
char * _class_simple_foo(Eo *obj, Evas_Simple_Data *pd, int a, char *b, double *c);
static char * __eolian_class_simple_foo(Eo *obj, Evas_Simple_Data *pd, int a, char *b, double *c)
{
if (c) *c = 1337.600000;
return _class_simple_foo(obj, pd, a, b, c);
}
EOAPI EO_FUNC_BODYV(evas_obj_simple_foo, char *, NULL, EO_FUNC_CALL(a, b, c), int a, char *b, double *c);
int _class_simple_bar(Eo *obj, Evas_Simple_Data *pd, int x);
EOAPI EO_FUNC_BODYV(evas_obj_simple_bar, int, 0, EO_FUNC_CALL(x), int x);
static Eo_Op_Description _class_simple_op_desc[] = {
EO_OP_FUNC(evas_obj_simple_a_set, _class_simple_a_set, "comment a.set"),
EO_OP_FUNC(evas_obj_simple_a_get, _class_simple_a_get, ""),
EO_OP_FUNC(evas_obj_simple_foo, __eolian_class_simple_foo, "comment foo"),
EO_OP_SENTINEL
};
static const Eo_Class_Description _class_simple_class_desc = {
EO_VERSION,
"Class_Simple",
EO_CLASS_TYPE_REGULAR,
EO_CLASS_DESCRIPTION_OPS(_class_simple_op_desc),
NULL,
sizeof(Evas_Simple_Data),
NULL,
NULL
};
EO_DEFINE_CLASS(class_simple_class_get, &_class_simple_class_desc, NULL, NULL);

View File

@ -124,9 +124,26 @@ START_TEST(eolian_types_generation)
}
END_TEST
START_TEST(eolian_default_values_generation)
{
char output_filepath[PATH_MAX] = "";
snprintf(output_filepath, PATH_MAX, "%s/eolian_output.c",
#ifdef HAVE_EVIL
(char *)evil_tmpdir_get()
#else
"/tmp"
#endif
);
remove(output_filepath);
fail_if(0 != _eolian_gen_execute(PACKAGE_DATA_DIR"/data/class_simple.eo", "--eo --gc", output_filepath));
fail_if(!_files_compare(PACKAGE_DATA_DIR"/data/class_simple_ref.c", output_filepath));
}
END_TEST
void eolian_generation_test(TCase *tc)
{
tcase_add_test(tc, eolian_types_generation);
tcase_add_test(tc, eolian_default_values_generation);
tcase_add_test(tc, eolian_dev_impl_code);
}