summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Kolesa <d.kolesa@samsung.com>2014-07-30 11:57:11 +0100
committerDaniel Kolesa <d.kolesa@samsung.com>2014-08-04 16:29:13 +0100
commit2f175156b8520e9dfcdc1b818f194ff5792a9a12 (patch)
tree7ea867e64201ed98d127628af80c8d2c85276daf
parent3a0e0df84aea8d7f1cfcc903b2abbb9116664dcb (diff)
downloadefl-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.h25
-rw-r--r--src/lib/eolian/database_class.c3
-rw-r--r--src/lib/eolian/database_class_api.c26
-rw-r--r--src/lib/eolian/database_print.c19
-rw-r--r--src/lib/eolian/database_type.c7
-rw-r--r--src/lib/eolian/database_type_api.c11
-rw-r--r--src/lib/eolian/eo_parser.c37
-rw-r--r--src/lib/eolian/eolian_database.c23
-rw-r--r--src/lib/eolian/eolian_database.h5
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);