diff options
author | Daniel Kolesa <d.kolesa@samsung.com> | 2014-07-30 11:57:11 +0100 |
---|---|---|
committer | Daniel Kolesa <d.kolesa@samsung.com> | 2014-08-04 16:29:13 +0100 |
commit | 2f175156b8520e9dfcdc1b818f194ff5792a9a12 (patch) | |
tree | 7ea867e64201ed98d127628af80c8d2c85276daf | |
parent | 3a0e0df84aea8d7f1cfcc903b2abbb9116664dcb (diff) | |
download | efl-2f175156b8520e9dfcdc1b818f194ff5792a9a12.tar.gz |
eolian: add support for referencing classes as types
For this purpose, several other changes were made. There can now only be 1 class per file
and the class name has to match the file name. Also, I replaced the list of classes with
a hash, allowing for fast indexing (crucial for parser performance - otherwise it was
very slow).
This also adds a new API, eolian_type_class_get.
-rw-r--r-- | src/lib/eolian/Eolian.h | 25 | ||||
-rw-r--r-- | src/lib/eolian/database_class.c | 3 | ||||
-rw-r--r-- | src/lib/eolian/database_class_api.c | 26 | ||||
-rw-r--r-- | src/lib/eolian/database_print.c | 19 | ||||
-rw-r--r-- | src/lib/eolian/database_type.c | 7 | ||||
-rw-r--r-- | src/lib/eolian/database_type_api.c | 11 | ||||
-rw-r--r-- | src/lib/eolian/eo_parser.c | 37 | ||||
-rw-r--r-- | src/lib/eolian/eolian_database.c | 23 | ||||
-rw-r--r-- | src/lib/eolian/eolian_database.h | 5 |
9 files changed, 99 insertions, 57 deletions
diff --git a/src/lib/eolian/Eolian.h b/src/lib/eolian/Eolian.h index b22b751e68..d147068312 100644 --- a/src/lib/eolian/Eolian.h +++ b/src/lib/eolian/Eolian.h @@ -122,7 +122,8 @@ typedef enum EOLIAN_TYPE_POINTER, EOLIAN_TYPE_FUNCTION, EOLIAN_TYPE_STRUCT, - EOLIAN_TYPE_ALIAS + EOLIAN_TYPE_ALIAS, + EOLIAN_TYPE_CLASS } Eolian_Type_Type; /* @@ -818,8 +819,7 @@ EAPI Eina_Iterator *eolian_type_structs_get_by_file(const char *fname); * @brief Get the type of a type (regular, function, pointer) * * @param[in] tp the type. - * @return EOLIAN_TYPE_UNKNOWN_TYPE when @c tp is NULL, otherwise - * EOLIAN_TYPE_REGULAR, EOLIAN_TYPE_POINTER or EOLIAN_TYPE_FUNCTION. + * @return an Eolian_Type_Type. * * @ingroup Eolian */ @@ -839,8 +839,8 @@ EAPI Eina_Iterator *eolian_type_arguments_get(const Eolian_Type *tp); * @brief Get an iterator to all subtypes of a type. * * @param[in] tp the type. - * @return the iterator when @c tp is an EOLIAN_TYPE_REGULAR or - * EOLIAN_TYPE_POINTER and has subtypes, NULL otherwise. + * @return the iterator when @c tp is a regular/regular struct/class/pointer + * type. * * @ingroup Eolian */ @@ -921,6 +921,16 @@ EAPI const Eolian_Type *eolian_type_return_type_get(const Eolian_Type *tp); EAPI const Eolian_Type *eolian_type_base_type_get(const Eolian_Type *tp); /* + * @brief Get the class associated with an EOLIAN_TYPE_CLASS type. + * + * @param[in] tp the type. + * @return the class or NULL. + * + * @ingroup Eolian + */ +EAPI const Eolian_Class *eolian_type_class_get(const Eolian_Type *tp); + +/* * @brief Get whether the given type is @own. * * @param[in] tp the type. @@ -993,8 +1003,9 @@ EAPI Eina_Stringshare *eolian_type_c_type_get(const Eolian_Type *tp); * @brief Get the name of the given type. You have to manually delete * the stringshare. For EOLIAN_TYPE_REGULAR and EOLIAN_TYPE_REGULAR_STRUCT, * this is for example "int". For EOLIAN_TYPE_STRUCT and EOLIAN_TYPE_ALIAS, - * this is the name of the alias or of the struct. Keep in mind that the name - * doesn't include namespaces for structs and aliases. + * this is the name of the alias or of the struct. For EOLIAN_TYPE_CLASS, + * this can be "Button". Keep in mind that the name doesn't include + * namespaces for structs and aliases. * * @param[in] tp the type. * @return the name. diff --git a/src/lib/eolian/database_class.c b/src/lib/eolian/database_class.c index e48cdf4274..7a35324c33 100644 --- a/src/lib/eolian/database_class.c +++ b/src/lib/eolian/database_class.c @@ -63,7 +63,7 @@ database_class_add(const char *class_name, Eolian_Class_Type type) } while(colon); cl->name = eina_stringshare_add(name); - _classes = eina_list_append(_classes, cl); + eina_hash_set(_classes, cl->full_name, cl); free(full_name); return cl; } @@ -73,6 +73,7 @@ database_class_file_set(Eolian_Class *cl, const char *file_name) { EINA_SAFETY_ON_NULL_RETURN(cl); cl->file = eina_stringshare_add(file_name); + eina_hash_set(_classesf, cl->file, cl); } /* diff --git a/src/lib/eolian/database_class_api.c b/src/lib/eolian/database_class_api.c index d3b96a311e..4d5efa58e5 100644 --- a/src/lib/eolian/database_class_api.c +++ b/src/lib/eolian/database_class_api.c @@ -29,28 +29,20 @@ eolian_class_namespaces_get(const Eolian_Class *cl) EAPI const Eolian_Class * eolian_class_get_by_name(const char *class_name) { - Eina_List *itr; - Eolian_Class *cl; - Eina_Stringshare *shr_name = eina_stringshare_add(class_name); - EINA_LIST_FOREACH(_classes, itr, cl) - if (cl->full_name == shr_name) goto end; - cl = NULL; -end: - eina_stringshare_del(shr_name); + if (!_classes) return NULL; + Eina_Stringshare *shr = eina_stringshare_add(class_name); + Eolian_Class *cl = eina_hash_find(_classes, shr); + eina_stringshare_del(shr); return cl; } EAPI const Eolian_Class * eolian_class_get_by_file(const char *file_name) { - Eina_List *itr; - Eolian_Class *cl; - Eina_Stringshare *shr_file = eina_stringshare_add(file_name); - EINA_LIST_FOREACH(_classes, itr, cl) - if (cl->file == shr_file) goto end; - cl = NULL; -end: - eina_stringshare_del(shr_file); + if (!_classesf) return NULL; + Eina_Stringshare *shr = eina_stringshare_add(file_name); + Eolian_Class *cl = eina_hash_find(_classesf, shr); + eina_stringshare_del(shr); return cl; } @@ -64,7 +56,7 @@ eolian_class_type_get(const Eolian_Class *cl) EAPI Eina_Iterator * eolian_all_classes_get(void) { - return (_classes ? eina_list_iterator_new(_classes) : NULL); + return (_classes ? eina_hash_iterator_data_new(_classes) : NULL); } EAPI Eina_Stringshare * diff --git a/src/lib/eolian/database_print.c b/src/lib/eolian/database_print.c index f96cdc22dd..f2773d3551 100644 --- a/src/lib/eolian/database_print.c +++ b/src/lib/eolian/database_print.c @@ -247,20 +247,21 @@ _class_print(const Eolian_Class *cl) return EINA_TRUE; } +static Eina_Bool +_cl_print_cb(const Eina_Hash *hash EINA_UNUSED, const void *key EINA_UNUSED, + void *data, void *fdata EINA_UNUSED) +{ + _class_print((Eolian_Class*)data); + return EINA_TRUE; +} + EAPI Eina_Bool eolian_show_class(const Eolian_Class *class) { if (!class) - { - Eina_List *itr; - Eolian_Class *cl; - EINA_LIST_FOREACH(_classes, itr, cl) - _class_print(cl); - } + eina_hash_foreach(_classes, _cl_print_cb, NULL); else - { - _class_print(class); - } + _class_print(class); return EINA_TRUE; } diff --git a/src/lib/eolian/database_type.c b/src/lib/eolian/database_type.c index a0ea20ea78..cfb8bc7355 100644 --- a/src/lib/eolian/database_type.c +++ b/src/lib/eolian/database_type.c @@ -149,12 +149,13 @@ database_type_to_str(const Eolian_Type *tp, Eina_Strbuf *buf, const char *name) } if ((tp->type == EOLIAN_TYPE_REGULAR || tp->type == EOLIAN_TYPE_REGULAR_STRUCT - || tp->type == EOLIAN_TYPE_VOID) + || tp->type == EOLIAN_TYPE_VOID + || tp->type == EOLIAN_TYPE_CLASS) && tp->is_const) { eina_strbuf_append(buf, "const "); } - if (tp->type == EOLIAN_TYPE_REGULAR) + if (tp->type == EOLIAN_TYPE_REGULAR || tp->type == EOLIAN_TYPE_CLASS) { Eina_List *l; const char *sp; @@ -219,7 +220,7 @@ database_type_print(Eolian_Type *tp) printf("own("); if (tp->is_const) printf("const("); - if (tp->type == EOLIAN_TYPE_REGULAR) + if (tp->type == EOLIAN_TYPE_REGULAR || tp->type == EOLIAN_TYPE_CLASS) printf("%s", tp->full_name); else if (tp->type == EOLIAN_TYPE_VOID) printf("void"); diff --git a/src/lib/eolian/database_type_api.c b/src/lib/eolian/database_type_api.c index bf2241a0db..46ff42d35d 100644 --- a/src/lib/eolian/database_type_api.c +++ b/src/lib/eolian/database_type_api.c @@ -68,7 +68,8 @@ eolian_type_subtypes_get(const Eolian_Type *tp) tpt = tp->type; EINA_SAFETY_ON_FALSE_RETURN_VAL(tpt == EOLIAN_TYPE_REGULAR || tpt == EOLIAN_TYPE_POINTER - || tpt == EOLIAN_TYPE_REGULAR_STRUCT, NULL); + || tpt == EOLIAN_TYPE_REGULAR_STRUCT + || tpt == EOLIAN_TYPE_CLASS, NULL); if (!tp->subtypes) return NULL; return eina_list_iterator_new(tp->subtypes); } @@ -147,6 +148,14 @@ eolian_type_base_type_get(const Eolian_Type *tp) return tp->base_type; } +EAPI const Eolian_Class * +eolian_type_class_get(const Eolian_Type *tp) +{ + EINA_SAFETY_ON_NULL_RETURN_VAL(tp, NULL); + EINA_SAFETY_ON_FALSE_RETURN_VAL(eolian_type_type_get(tp) == EOLIAN_TYPE_CLASS, NULL); + return eolian_class_get_by_name(tp->full_name); +} + EAPI Eina_Bool eolian_type_is_own(const Eolian_Type *tp) { diff --git a/src/lib/eolian/eo_parser.c b/src/lib/eolian/eo_parser.c index 6e478a78dc..a9d089cedb 100644 --- a/src/lib/eolian/eo_parser.c +++ b/src/lib/eolian/eo_parser.c @@ -442,10 +442,24 @@ parse_type_struct_void(Eo_Lexer *ls, Eina_Bool allow_struct) } else { + const char *nm, *fpath; + char *fname; buf = push_strbuf(ls); parse_name(ls, buf); - _fill_type_name(def, eina_stringshare_add(eina_strbuf_string_get - (buf))); + nm = eina_strbuf_string_get(buf); + fname = database_class_to_filename(nm); + fpath = eina_hash_find(_filenames, fname); + free(fname); + if (fpath) + { + def->type = EOLIAN_TYPE_CLASS; + if (strcmp(ls->source, fpath)) + { + if (!eolian_class_get_by_name(nm) && !eolian_eo_file_parse(fpath)) + eo_lexer_syntax_error(ls, "failed to parse dependency"); + } + } + _fill_type_name(def, eina_stringshare_add(nm)); pop_strbuf(ls); } } @@ -1148,12 +1162,22 @@ parse_class_body(Eo_Lexer *ls, Eina_Bool allow_ctors, Eolian_Class_Type type) static void parse_class(Eo_Lexer *ls, Eina_Bool allow_ctors, Eolian_Class_Type type) { + const char *bnm; + char *fnm; + Eina_Bool same; int line, col; Eina_Strbuf *buf = push_strbuf(ls); ls->tmp.kls = calloc(1, sizeof(Eo_Class_Def)); eo_lexer_get(ls); ls->tmp.kls->type = type; parse_name(ls, buf); + bnm = get_filename(ls); + fnm = database_class_to_filename(eina_strbuf_string_get(buf)); + same = !!strcmp(bnm, fnm); + eina_stringshare_del(bnm); + free(fnm); + if (!same) + eo_lexer_syntax_error(ls, "class and file names differ"); ls->tmp.kls->name = eina_stringshare_add(eina_strbuf_string_get(buf)); pop_strbuf(ls); ls->tmp.kls->file = get_filename(ls); @@ -1176,7 +1200,7 @@ parse_class(Eo_Lexer *ls, Eina_Bool allow_ctors, Eolian_Class_Type type) check_match(ls, '}', '{', line, col); } -static void +static Eina_Bool parse_unit(Eo_Lexer *ls, Eina_Bool eot) { switch (ls->t.kw) @@ -1240,17 +1264,20 @@ parse_unit(Eo_Lexer *ls, Eina_Bool eot) eo_lexer_syntax_error(ls, "invalid token"); break; } - return; + return EINA_FALSE; found_class: append_node(ls, NODE_CLASS, ls->tmp.kls); ls->tmp.kls = NULL; + return EINA_TRUE; } static void parse_chunk(Eo_Lexer *ls, Eina_Bool eot) { while (ls->t.token >= 0) - parse_unit(ls, eot); + /* set eot to EINA_TRUE so that we only allow parsing of one class */ + if (parse_unit(ls, eot)) + eot = EINA_TRUE; } Eina_Bool diff --git a/src/lib/eolian/eolian_database.c b/src/lib/eolian/eolian_database.c index 2e3aa1a57e..5b9ba974fd 100644 --- a/src/lib/eolian/eolian_database.c +++ b/src/lib/eolian/eolian_database.c @@ -3,9 +3,10 @@ #include "eo_parser.h" #include "eolian_database.h" -Eina_List *_classes = NULL; +Eina_Hash *_classes = NULL; Eina_Hash *_aliases = NULL; Eina_Hash *_structs = NULL; +Eina_Hash *_classesf = NULL; Eina_Hash *_aliasesf = NULL; Eina_Hash *_structsf = NULL; Eina_Hash *_filenames = NULL; @@ -24,8 +25,10 @@ database_init() { if (_database_init_count > 0) return ++_database_init_count; eina_init(); + _classes = eina_hash_stringshared_new(EINA_FREE_CB(database_class_del)); _aliases = eina_hash_stringshared_new(EINA_FREE_CB(database_typedef_del)); _structs = eina_hash_stringshared_new(EINA_FREE_CB(database_type_del)); + _classesf = eina_hash_stringshared_new(NULL); _aliasesf = eina_hash_stringshared_new(_hashlist_free); _structsf = eina_hash_stringshared_new(_hashlist_free); _filenames = eina_hash_string_small_new(free); @@ -45,11 +48,10 @@ database_shutdown() if (_database_init_count == 0) { - Eolian_Class *class; - EINA_LIST_FREE(_classes, class) - database_class_del(class); + eina_hash_free(_classes); eina_hash_free(_aliases); eina_hash_free(_structs); + eina_hash_free(_classesf); eina_hash_free(_aliasesf); eina_hash_free(_structsf); eina_hash_free(_filenames); @@ -108,12 +110,12 @@ eolian_system_directory_scan() return ret; } -static char * -_eolian_class_to_filename(const char *filename) +char * +database_class_to_filename(const char *cname) { char *ret; Eina_Strbuf *strbuf = eina_strbuf_new(); - eina_strbuf_append(strbuf, filename); + eina_strbuf_append(strbuf, cname); eina_strbuf_replace_all(strbuf, ".", "_"); ret = eina_strbuf_string_steal(strbuf); @@ -160,7 +162,7 @@ eolian_eo_file_parse(const char *filepath) { if (!eolian_class_get_by_name(inherit_name)) { - char *filename = _eolian_class_to_filename(inherit_name); + char *filename = database_class_to_filename(inherit_name); filepath = eina_hash_find(_filenames, filename); free(filename); if (!filepath) @@ -169,11 +171,6 @@ eolian_eo_file_parse(const char *filepath) return EINA_FALSE; } if (!eolian_eo_file_parse(filepath)) return EINA_FALSE; - if (!eolian_class_get_by_name(inherit_name)) - { - ERR("Unable to find class %s", inherit_name); - return EINA_FALSE; - } } } eina_iterator_free(itr); diff --git a/src/lib/eolian/eolian_database.h b/src/lib/eolian/eolian_database.h index 2b79bf2513..e851039617 100644 --- a/src/lib/eolian/eolian_database.h +++ b/src/lib/eolian/eolian_database.h @@ -39,9 +39,10 @@ extern Eina_Prefix *_eolian_prefix; #define EOLIAN_PROP_GET_RETURN_COMMENT "property_get_return_comment" #define EOLIAN_PROP_SET_RETURN_COMMENT "property_set_return_comment" -extern Eina_List *_classes; +extern Eina_Hash *_classes; extern Eina_Hash *_aliases; extern Eina_Hash *_structs; +extern Eina_Hash *_classesf; extern Eina_Hash *_aliasesf; extern Eina_Hash *_structsf; extern Eina_Hash *_filenames; /* Hash: filename without extension -> full path */ @@ -162,6 +163,8 @@ void database_type_to_str(const Eolian_Type *tp, Eina_Strbuf *buf, const char *n Eolian_Class *database_class_add(const char *class_name, Eolian_Class_Type type); void database_class_del(Eolian_Class *cl); +char *database_class_to_filename(const char *cname); + Eina_Bool database_class_inherit_add(Eolian_Class *cl, const char *inherit_class_name); Eina_Bool database_class_function_add(Eolian_Class *cl, Eolian_Function *foo_id); Eina_Bool database_class_implement_add(Eolian_Class *cl, Eolian_Implement *impl_id); |