From ffa9ad7daf0bdc6c8de9cb8e3994cc5b6e53858a Mon Sep 17 00:00:00 2001 From: Daniel Zaoui Date: Tue, 2 Sep 2014 17:00:14 +0300 Subject: [PATCH] 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. --- src/Makefile_Eolian.am | 3 +- src/bin/eolian/eo_generator.c | 76 ++++++++++++++++++++++-- src/lib/evas/canvas/evas_line.eo | 4 +- src/tests/eolian/data/class_simple_ref.c | 47 +++++++++++++++ src/tests/eolian/eolian_generation.c | 17 ++++++ 5 files changed, 138 insertions(+), 9 deletions(-) create mode 100644 src/tests/eolian/data/class_simple_ref.c diff --git a/src/Makefile_Eolian.am b/src/Makefile_Eolian.am index be2eb260c7..5df0ebfca6 100644 --- a/src/Makefile_Eolian.am +++ b/src/Makefile_Eolian.am @@ -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 diff --git a/src/bin/eolian/eo_generator.c b/src/bin/eolian/eo_generator.c index c4cc89c54c..ce1d0ad52c 100644 --- a/src/bin/eolian/eo_generator.c +++ b/src/bin/eolian/eo_generator.c @@ -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; } diff --git a/src/lib/evas/canvas/evas_line.eo b/src/lib/evas/canvas/evas_line.eo index e9283cf6fa..308defaa32 100644 --- a/src/lib/evas/canvas/evas_line.eo +++ b/src/lib/evas/canvas/evas_line.eo @@ -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. */ } diff --git a/src/tests/eolian/data/class_simple_ref.c b/src/tests/eolian/data/class_simple_ref.c new file mode 100644 index 0000000000..51a4f4ad63 --- /dev/null +++ b/src/tests/eolian/data/class_simple_ref.c @@ -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); \ No newline at end of file diff --git a/src/tests/eolian/eolian_generation.c b/src/tests/eolian/eolian_generation.c index 1beb29a0f9..25246c1baf 100644 --- a/src/tests/eolian/eolian_generation.c +++ b/src/tests/eolian/eolian_generation.c @@ -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); }