eolian: prepare for proper unit API by merging unit hashes

Eolian now properly merges all unit hashes (e.g. unit A has
children B and C, hashes of B and C are merged into A's hashes
in order to be able to look up B and C's contents via A) and
maintains a (potentially cyclic) children graph.

Not everything is yet added into all hashes, but at least the
building blocks are there.
This commit is contained in:
Daniel Kolesa 2018-02-21 16:36:08 +01:00
parent 885ea03230
commit 76b9f4c224
5 changed files with 65 additions and 5 deletions

View File

@ -15,7 +15,7 @@ database_class_del(Eolian_Class *cl)
Eolian_Constructor *ctor;
const char *s;
if (!cl) return;
if (!cl || eolian_object_unref(&cl->base)) return;
if (cl->base.file) eina_stringshare_del(cl->base.file);

View File

@ -8,7 +8,7 @@
void
database_type_del(Eolian_Type *tp)
{
if (!tp) return;
if (!tp || eolian_object_unref(&tp->base)) return;
const char *sp;
if (tp->base.file) eina_stringshare_del(tp->base.file);
database_type_del(tp->base_type);
@ -24,7 +24,7 @@ database_type_del(Eolian_Type *tp)
void
database_typedecl_del(Eolian_Typedecl *tp)
{
if (!tp) return;
if (!tp || eolian_object_unref(&tp->base)) return;
const char *sp;
if (tp->base.file) eina_stringshare_del(tp->base.file);
database_type_del(tp->base_type);

View File

@ -8,7 +8,7 @@
void
database_var_del(Eolian_Variable *var)
{
if (!var) return;
if (!var || eolian_object_unref(&var->base)) return;
const char *sp;
if (var->base.file) eina_stringshare_del(var->base.file);
if (var->base_type)

View File

@ -2257,7 +2257,11 @@ eo_parser_database_fill(Eolian_Unit *parent, const char *filename, Eina_Bool eot
eina_stringshare_del(fname);
if (ret)
return ret;
{
if (parent != ret)
eina_hash_add(parent->children, filename, ret);
return ret;
}
Eo_Lexer *ls = eo_lexer_new(parent->state, filename);
if (!ls)
@ -2284,7 +2288,10 @@ eo_parser_database_fill(Eolian_Unit *parent, const char *filename, Eina_Bool eot
ls->tmp.kls = NULL;
eina_hash_set(ls->state->unit.classes, cl->full_name, cl);
eina_hash_set(ls->unit->classes, cl->full_name, cl);
eina_hash_set(ls->state->classes_f, cl->base.file, cl);
/* once for unit, once for state */
eolian_object_ref(&cl->base);
eolian_object_ref(&cl->base);
done:

View File

@ -702,6 +702,56 @@ _parse_deferred(Eolian_Unit *parent)
return EINA_TRUE;
}
static Eina_Bool
_merge_unit_cb(const Eina_Hash *hash EINA_UNUSED,
const void *key, void *data, void *fdata)
{
if (eina_hash_add((Eina_Hash *)fdata, key, data))
eolian_object_ref((Eolian_Object *)data);
return EINA_TRUE;
}
static void
_merge_unit(Eolian_Unit *dest, Eolian_Unit *src)
{
eina_hash_foreach(src->classes, _merge_unit_cb, dest->classes);
eina_hash_foreach(src->globals, _merge_unit_cb, dest->globals);
eina_hash_foreach(src->constants, _merge_unit_cb, dest->constants);
eina_hash_foreach(src->aliases, _merge_unit_cb, dest->aliases);
eina_hash_foreach(src->structs, _merge_unit_cb, dest->structs);
eina_hash_foreach(src->enums, _merge_unit_cb, dest->enums);
eina_hash_foreach(src->decls, _merge_unit_cb, dest->decls);
}
typedef struct _Merge_Data
{
Eina_Hash *cycles;
Eolian_Unit *unit;
} Merge_Data;
static Eina_Bool
_merge_units_cb(const Eina_Hash *hash EINA_UNUSED,
const void *key EINA_UNUSED, void *data, void *fdata)
{
Merge_Data *mdata = fdata;
Merge_Data imdata = { mdata->cycles, data };
if (!eina_hash_find(imdata.cycles, &imdata.unit))
{
eina_hash_add(imdata.cycles, &imdata.unit, imdata.unit);
eina_hash_foreach(imdata.unit->children, _merge_units_cb, &imdata);
}
_merge_unit(mdata->unit, imdata.unit);
return EINA_TRUE;
}
static void
_merge_units(Eolian_Unit *unit)
{
Merge_Data mdata = { eina_hash_pointer_new(NULL), unit };
eina_hash_foreach(unit->children, _merge_units_cb, &mdata);
eina_hash_free(mdata.cycles);
}
EAPI const Eolian_Unit *
eolian_file_parse(Eolian *state, const char *filepath)
{
@ -713,6 +763,7 @@ eolian_file_parse(Eolian *state, const char *filepath)
return NULL;
if (!_parse_deferred(ret))
return NULL;
_merge_units(ret);
/* FIXME: pass unit properly */
if (!database_validate(state, &state->unit))
return NULL;
@ -733,6 +784,7 @@ static Eina_Bool _tfile_parse(const Eina_Hash *hash EINA_UNUSED, const void *key
unit = eo_parser_database_fill((Eolian_Unit *)pd->state, data, EINA_TRUE);
pd->ret = !!unit;
if (pd->ret) pd->ret = _parse_deferred(unit);
_merge_units(unit);
return pd->ret;
}
@ -761,6 +813,7 @@ static Eina_Bool _file_parse(const Eina_Hash *hash EINA_UNUSED, const void *key
unit = eo_parser_database_fill((Eolian_Unit *)pd->state, data, EINA_FALSE);
pd->ret = !!unit;
if (pd->ret) pd->ret = _parse_deferred(unit);
_merge_units(unit);
return pd->ret;
}