From d2365e6267c8bcd22c96176e4356328e6b6bfaef Mon Sep 17 00:00:00 2001 From: Daniel Kolesa Date: Wed, 13 May 2015 17:56:18 +0100 Subject: [PATCH] eolian: allow forced retrieval of enum field values --- src/bin/eolian/types_generator.c | 4 +-- src/bindings/luajit/eolian.lua | 10 +++---- src/lib/eolian/Eolian.h | 13 ++++++--- src/lib/eolian/database_expr.c | 54 ++++---------------------------------- src/lib/eolian/database_type_api.c | 50 +++++++++++++++++++++++++++++++++-- src/lib/eolian/eo_parser.c | 2 ++ src/lib/eolian/eolian_database.h | 3 +++ src/tests/eolian/eolian_parsing.c | 14 +++++----- 8 files changed, 82 insertions(+), 68 deletions(-) diff --git a/src/bin/eolian/types_generator.c b/src/bin/eolian/types_generator.c index e323950..90b62bd 100644 --- a/src/bin/eolian/types_generator.c +++ b/src/bin/eolian/types_generator.c @@ -94,7 +94,7 @@ _type_generate(const Eolian_Type *tp, Eina_Bool full) } case EOLIAN_TYPE_ENUM: { - const Eolian_Enum_Type_Field *member; + Eolian_Enum_Type_Field *member; char *name; if (!full) break; @@ -112,7 +112,7 @@ _type_generate(const Eolian_Type *tp, Eina_Bool full) while (next) { const char *desc = eolian_type_enum_field_description_get(member); - const Eolian_Expression *value = eolian_type_enum_field_value_get(member); + const Eolian_Expression *value = eolian_type_enum_field_value_get(member, EINA_FALSE); char *memb_u = strdup(eolian_type_enum_field_name_get(member)); eina_str_toupper(&memb_u); eina_strbuf_reset(membuf); diff --git a/src/bindings/luajit/eolian.lua b/src/bindings/luajit/eolian.lua index 21c73d7..334d141 100644 --- a/src/bindings/luajit/eolian.lua +++ b/src/bindings/luajit/eolian.lua @@ -270,10 +270,10 @@ ffi.cdef [[ const char *eolian_type_struct_field_description_get(const Eolian_Struct_Type_Field *fl); const Eolian_Type *eolian_type_struct_field_type_get(const Eolian_Struct_Type_Field *fl); Eina_Iterator *eolian_type_enum_fields_get(const Eolian_Type *tp); - const Eolian_Enum_Type_Field *eolian_type_enum_field_get(const Eolian_Type *tp, const char *field); + Eolian_Enum_Type_Field *eolian_type_enum_field_get(const Eolian_Type *tp, const char *field); const char *eolian_type_enum_field_name_get(const Eolian_Enum_Type_Field *fl); const char *eolian_type_enum_field_description_get(const Eolian_Enum_Type_Field *fl); - const Eolian_Expression *eolian_type_enum_field_value_get(const Eolian_Enum_Type_Field *fl); + const Eolian_Expression *eolian_type_enum_field_value_get(Eolian_Enum_Type_Field *fl, Eina_Bool force); const char *eolian_type_enum_legacy_prefix_get(const Eolian_Type *tp); const char *eolian_type_description_get(const Eolian_Type *tp); const char *eolian_type_file_get(const Eolian_Type *tp); @@ -474,8 +474,8 @@ ffi.metatype("Eolian_Enum_Type_Field", { return ffi.string(v) end, - value_get = function(self) - local v = eolian.eolian_type_enum_field_value_get(self) + value_get = function(self, force) + local v = eolian.eolian_type_enum_field_value_get(self, force and 1 or 0) if v == nil then return nil end return v end @@ -510,7 +510,7 @@ M.Type = ffi.metatype("Eolian_Type", { end, enum_fields_get = function(self) - return Ptr_Iterator("const Eolian_Enum_Type_Field*", + return Ptr_Iterator("Eolian_Enum_Type_Field*", eolian.eolian_type_enum_fields_get(self)) end, diff --git a/src/lib/eolian/Eolian.h b/src/lib/eolian/Eolian.h index 795eed6..317d657 100644 --- a/src/lib/eolian/Eolian.h +++ b/src/lib/eolian/Eolian.h @@ -1551,7 +1551,7 @@ EAPI Eina_Iterator *eolian_type_enum_fields_get(const Eolian_Type *tp); * * @ingroup Eolian */ -EAPI const Eolian_Enum_Type_Field *eolian_type_enum_field_get(const Eolian_Type *tp, const char *field); +EAPI Eolian_Enum_Type_Field *eolian_type_enum_field_get(const Eolian_Type *tp, const char *field); /* * @brief Get the name of a field of an enum type. @@ -1588,12 +1588,19 @@ EAPI Eina_Stringshare *eolian_type_enum_field_description_get(const Eolian_Enum_ /* * @brief Get the value of a field of an enum type. * + * When the @c force parameter is EINA_FALSE, this will only return values for + * fields which are explicitly specified in the eo file. Otherwise, it will + * create the field (if not already there) and return it. Keep in mind that + * no matter if the field is already cached or not, you always have to force + * retrieval if you want to be sure that a valid expr is returned. + * * @param[in] fl the field. - * @return the description. + * @param[in] force force the value retrieval. + * @return the expression. * * @ingroup Eolian */ -EAPI const Eolian_Expression *eolian_type_enum_field_value_get(const Eolian_Enum_Type_Field *fl); +EAPI const Eolian_Expression *eolian_type_enum_field_value_get(Eolian_Enum_Type_Field *fl, Eina_Bool force); /* * @brief Get the legacy prefix of enum field names. When not specified, diff --git a/src/lib/eolian/database_expr.c b/src/lib/eolian/database_expr.c index cfd5b0b..7fe8108 100644 --- a/src/lib/eolian/database_expr.c +++ b/src/lib/eolian/database_expr.c @@ -495,12 +495,11 @@ eval_exp(const Eolian_Expression *expr, Eolian_Expression_Mask mask, const Eolian_Variable *var = eolian_variable_constant_get_by_name (expr->value.s); const Eolian_Expression *exp = NULL; - int fl_nadd = 0; if (!var) { const Eolian_Type *etp; - const Eolian_Enum_Type_Field *fl; + Eolian_Enum_Type_Field *fl; /* try aliases, hoping it'll be enum */ char *fulln = NULL, *memb = NULL; @@ -525,31 +524,7 @@ eval_exp(const Eolian_Expression *expr, Eolian_Expression_Mask mask, } fl = eolian_type_enum_field_get(etp, memb); - if (fl) - { - /* we have the field, but the value might not exist - * we should search for last valid enum field, use that */ - exp = fl->value; - if (!exp) - { - Eina_List *flist = fl->base_enum->field_list; - Eolian_Enum_Type_Field *lfl = eina_list_data_get(flist); - while (lfl && lfl->name != fl->name) - { - flist = eina_list_next(flist); - lfl = eina_list_data_get(flist); - } - /* we've found our list item, now let's go backwards */ - while (!lfl->value) - { - ++fl_nadd; - flist = eina_list_prev(flist); - lfl = eina_list_data_get(flist); - } - /* we've found our first reachable value */ - exp = lfl->value; - } - } + if (fl) exp = eolian_type_enum_field_value_get(fl, EINA_TRUE); free(fulln); if (!exp) @@ -561,25 +536,6 @@ eval_exp(const Eolian_Expression *expr, Eolian_Expression_Mask mask, if (!exp) return expr_error(expr, "undefined variable"); - if (fl_nadd) - { - Eolian_Expression eexp, vexp; - eexp.base.file = exp->base.file; - eexp.base.line = eexp.base.column = -1; - vexp.base.file = exp->base.file; - vexp.base.line = vexp.base.column = -1; - - vexp.type = EOLIAN_EXPR_INT; - vexp.value.i = fl_nadd; - - eexp.type = EOLIAN_EXPR_BINARY; - eexp.binop = EOLIAN_BINOP_ADD; - eexp.lhs = (Eolian_Expression *)exp; - eexp.rhs = &vexp; - - return eval_exp(&eexp, mask, out); - } - return eval_exp(exp, mask, out); } case EOLIAN_EXPR_UNARY: @@ -616,12 +572,12 @@ database_expr_del(Eolian_Expression *expr) if (expr->base.file) eina_stringshare_del(expr->base.file); if (expr->type == EOLIAN_EXPR_BINARY) { - database_expr_del(expr->lhs); - database_expr_del(expr->rhs); + if (!expr->weak_lhs) database_expr_del(expr->lhs); + if (!expr->weak_rhs) database_expr_del(expr->rhs); } else if (expr->type == EOLIAN_EXPR_UNARY) { - database_expr_del(expr->expr); + if (!expr->weak_lhs) database_expr_del(expr->expr); } else if (expr->type == EOLIAN_EXPR_STRING) { diff --git a/src/lib/eolian/database_type_api.c b/src/lib/eolian/database_type_api.c index 5c301f2..709f541 100644 --- a/src/lib/eolian/database_type_api.c +++ b/src/lib/eolian/database_type_api.c @@ -136,7 +136,7 @@ eolian_type_enum_fields_get(const Eolian_Type *tp) return eina_list_iterator_new(tp->field_list); } -EAPI const Eolian_Enum_Type_Field * +EAPI Eolian_Enum_Type_Field * eolian_type_enum_field_get(const Eolian_Type *tp, const char *field) { Eolian_Enum_Type_Field *ef = NULL; @@ -185,9 +185,55 @@ eolian_type_enum_field_description_get(const Eolian_Enum_Type_Field *fl) } EAPI const Eolian_Expression * -eolian_type_enum_field_value_get(const Eolian_Enum_Type_Field *fl) +eolian_type_enum_field_value_get(Eolian_Enum_Type_Field *fl, Eina_Bool force) { EINA_SAFETY_ON_NULL_RETURN_VAL(fl, NULL); + if (!force && !fl->is_public_value) return NULL; + if (force && !fl->value) + { + Eolian_Expression *exp = NULL; + Eolian_Expression *rhs = calloc(1, sizeof(Eolian_Expression)), + *bin = calloc(1, sizeof(Eolian_Expression)); + + int fl_nadd = 0; + + Eina_List *flist = fl->base_enum->field_list; + Eolian_Enum_Type_Field *lfl = eina_list_data_get(flist); + + /* first find our own node */ + while (lfl && lfl->name != fl->name) + { + flist = eina_list_next(flist); + lfl = eina_list_data_get(flist); + } + + /* we've found our list item, now let's go backwards */ + while (!lfl->value) + { + ++fl_nadd; + flist = eina_list_prev(flist); + lfl = eina_list_data_get(flist); + } + + /* we've found our first reachable value */ + exp = lfl->value; + + rhs->base.file = eina_stringshare_ref(exp->base.file); + bin->base.file = eina_stringshare_ref(exp->base.file); + rhs->base.line = rhs->base.column = -1; + bin->base.line = bin->base.column = -1; + + rhs->type = EOLIAN_EXPR_INT; + rhs->value.i = fl_nadd; + + bin->type = EOLIAN_EXPR_BINARY; + bin->binop = EOLIAN_BINOP_ADD; + bin->lhs = exp; + bin->rhs = rhs; + bin->weak_lhs = EINA_TRUE; + + fl->value = bin; + } return fl->value; } diff --git a/src/lib/eolian/eo_parser.c b/src/lib/eolian/eo_parser.c index a646526..7509196 100644 --- a/src/lib/eolian/eo_parser.c +++ b/src/lib/eolian/eo_parser.c @@ -589,6 +589,7 @@ parse_enum(Eo_Lexer *ls, const char *name, Eina_Bool is_extern, prev_exp->type = EOLIAN_EXPR_INT; prev_exp->value.i = 0; fdef->value = prev_exp; + fdef->is_public_value = EINA_TRUE; pop_expr(ls); } } @@ -597,6 +598,7 @@ parse_enum(Eo_Lexer *ls, const char *name, Eina_Bool is_extern, ls->expr_mode = EINA_TRUE; eo_lexer_get(ls); fdef->value = parse_expr(ls); + fdef->is_public_value = EINA_TRUE; ls->expr_mode = EINA_FALSE; if (!prev_exp) prev_exp = fdef->value; diff --git a/src/lib/eolian/eolian_database.h b/src/lib/eolian/eolian_database.h index 0bd9ac8..2f4b82e 100644 --- a/src/lib/eolian/eolian_database.h +++ b/src/lib/eolian/eolian_database.h @@ -205,6 +205,7 @@ struct _Eolian_Enum_Type_Field Eolian_Object base; Eolian_Expression *value; Eina_Stringshare *comment; + Eina_Bool is_public_value :1; }; struct _Eolian_Expression @@ -226,6 +227,8 @@ struct _Eolian_Expression }; Eolian_Value_Union value; }; + Eina_Bool weak_lhs :1; + Eina_Bool weak_rhs :1; }; struct _Eolian_Variable diff --git a/src/tests/eolian/eolian_parsing.c b/src/tests/eolian/eolian_parsing.c index 4591732..f7c827b 100644 --- a/src/tests/eolian/eolian_parsing.c +++ b/src/tests/eolian/eolian_parsing.c @@ -854,16 +854,16 @@ START_TEST(eolian_enum) fail_if(!(type = eolian_type_enum_get_by_name("Foo"))); fail_if(!(field = eolian_type_enum_field_get(type, "first"))); - fail_if(!(exp = eolian_type_enum_field_value_get(field))); + fail_if(!(exp = eolian_type_enum_field_value_get(field, EINA_FALSE))); v = eolian_expression_eval(exp, EOLIAN_MASK_ALL); fail_if(v.type != EOLIAN_EXPR_INT); fail_if(v.value.i != 0); fail_if(!(field = eolian_type_enum_field_get(type, "bar"))); - fail_if(eolian_type_enum_field_value_get(field)); + fail_if(eolian_type_enum_field_value_get(field, EINA_FALSE)); fail_if(!(field = eolian_type_enum_field_get(type, "baz"))); - fail_if(!(exp = eolian_type_enum_field_value_get(field))); + fail_if(!(exp = eolian_type_enum_field_value_get(field, EINA_FALSE))); v = eolian_expression_eval(exp, EOLIAN_MASK_ALL); fail_if(v.type != EOLIAN_EXPR_INT); fail_if(v.value.i != 15); @@ -872,7 +872,7 @@ START_TEST(eolian_enum) fail_if(strcmp(eolian_type_enum_legacy_prefix_get(type), "test")); fail_if(!(field = eolian_type_enum_field_get(type, "foo"))); - fail_if(!(exp = eolian_type_enum_field_value_get(field))); + fail_if(!(exp = eolian_type_enum_field_value_get(field, EINA_FALSE))); v = eolian_expression_eval(exp, EOLIAN_MASK_ALL); fail_if(v.type != EOLIAN_EXPR_INT); fail_if(v.value.i != 15); @@ -884,13 +884,13 @@ START_TEST(eolian_enum) fail_if(!(type = eolian_type_enum_get_by_name("Baz"))); fail_if(!(field = eolian_type_enum_field_get(type, "flag1"))); - fail_if(!(exp = eolian_type_enum_field_value_get(field))); + fail_if(!(exp = eolian_type_enum_field_value_get(field, EINA_FALSE))); v = eolian_expression_eval(exp, EOLIAN_MASK_ALL); fail_if(v.type != EOLIAN_EXPR_INT); fail_if(v.value.i != (1 << 0)); fail_if(!(field = eolian_type_enum_field_get(type, "flag2"))); - fail_if(!(exp = eolian_type_enum_field_value_get(field))); + fail_if(!(exp = eolian_type_enum_field_value_get(field, EINA_FALSE))); v = eolian_expression_eval(exp, EOLIAN_MASK_ALL); fail_if(v.type != EOLIAN_EXPR_INT); fail_if(v.value.i != (1 << 1)); @@ -900,7 +900,7 @@ START_TEST(eolian_enum) eina_stringshare_del(cname); fail_if(!(field = eolian_type_enum_field_get(type, "flag3"))); - fail_if(!(exp = eolian_type_enum_field_value_get(field))); + fail_if(!(exp = eolian_type_enum_field_value_get(field, EINA_FALSE))); v = eolian_expression_eval(exp, EOLIAN_MASK_ALL); fail_if(v.type != EOLIAN_EXPR_INT); fail_if(v.value.i != (1 << 2)); -- 2.7.4