eolian: disallow cyclic dependencies between .eo files

Eo files will now fail to compile if a cycle is detected.

This required some temporary changes in existing eo files
(we had 2 cycles) for which I added a FIXME (they do not
affect C generation).

@feature
This commit is contained in:
Daniel Kolesa 2015-05-22 15:03:38 +01:00
parent adf445e3bd
commit 9214fa3db9
5 changed files with 23 additions and 82 deletions

View File

@ -51,7 +51,8 @@ class Ecore.Con.Server (Ecore.Con.Base) {
get {
}
values {
clients: const(list<const(Ecore.Con.Client) *>) *; /*@ The list of clients on this server. */
// FIXME: Ecore.Con.Client is needed, but that introduces a cycle
clients: const(list<const(Ecore.Con.Base) *>) *; /*@ The list of clients on this server. */
}
}
@property connection_type {

View File

@ -667,30 +667,22 @@ parse_struct_attrs(Eo_Lexer *ls, Eina_Bool is_enum, Eina_Bool *is_extern,
}
static void
_append_dep(Eo_Lexer *ls, const char *fname, const char *name, int line, int col)
_parse_dep(Eo_Lexer *ls, const char *fname, const char *name)
{
Eina_Stringshare *cname = eina_stringshare_add(name);
Eolian_Dependency *dep;
Eina_List *deps = eina_hash_find(_depclasses, ls->filename);
Eina_List *l;
void *data;
/* check for possible duplicates while building the deplist */
EINA_LIST_FOREACH(deps, l, data)
if (data == cname)
{
eina_stringshare_del(cname);
return;
}
dep = calloc(1, sizeof(Eolian_Dependency));
FILL_BASE(dep->base, ls, line, col);
dep->filename = eina_stringshare_add(fname);
dep->name = cname;
deps = eina_list_append(deps, dep);
eina_hash_set(_depclasses, ls->filename, deps);
if (eina_hash_find(_parsingeos, fname))
{
char buf[PATH_MAX];
eo_lexer_context_restore(ls);
snprintf(buf, sizeof(buf), "cyclic dependency '%s'", name);
eo_lexer_syntax_error(ls, buf);
}
if (!eolian_eo_file_parse(fname))
{
char buf[PATH_MAX];
eo_lexer_context_restore(ls);
snprintf(buf, sizeof(buf), "error parsing dependency '%s'", name);
eo_lexer_syntax_error(ls, buf);
}
}
static Eolian_Type *
@ -799,10 +791,10 @@ parse_type_void(Eo_Lexer *ls)
}
else
{
int dline = ls->line_number, dcol = ls->column;
const char *bnm, *nm;
char *fnm;
buf = push_strbuf(ls);
eo_lexer_context_push(ls);
parse_name(ls, buf);
nm = eina_strbuf_string_get(buf);
bnm = eina_stringshare_ref(ls->filename);
@ -814,7 +806,7 @@ parse_type_void(Eo_Lexer *ls)
free(fnm);
if (fname)
{
_append_dep(ls, fname, nm, dline, dcol);
_parse_dep(ls, fname, nm);
def->type = EOLIAN_TYPE_CLASS;
}
}
@ -826,6 +818,7 @@ parse_type_void(Eo_Lexer *ls)
}
_fill_name(eina_stringshare_add(nm), &def->full_name, &def->name,
&def->namespaces);
eo_lexer_context_pop(ls);
pop_strbuf(ls);
}
}
@ -1721,7 +1714,6 @@ parse_class_body(Eo_Lexer *ls, Eolian_Class_Type type)
static void
_inherit_dep(Eo_Lexer *ls, Eina_Strbuf *buf)
{
int dline = ls->line_number, dcol = ls->column;
const char *fname, *iname;
char *fnm;
eina_strbuf_reset(buf);
@ -1748,7 +1740,7 @@ _inherit_dep(Eo_Lexer *ls, Eina_Strbuf *buf)
snprintf(ebuf, sizeof(ebuf), "unknown inherit '%s'", iname);
eo_lexer_syntax_error(ls, ebuf);
}
_append_dep(ls, fname, iname, dline, dcol);
_parse_dep(ls, fname, iname);
ls->tmp.kls->inherits = eina_list_append(ls->tmp.kls->inherits,
eina_stringshare_add(iname));
eo_lexer_context_pop(ls);

View File

@ -21,7 +21,6 @@ Eina_Hash *_globalsf = NULL;
Eina_Hash *_constantsf = NULL;
Eina_Hash *_filenames = NULL;
Eina_Hash *_tfilenames = NULL;
Eina_Hash *_depclasses = NULL;
Eina_Hash *_decls = NULL;
Eina_Hash *_parsedeots = NULL;
@ -35,19 +34,6 @@ _hashlist_free(void *data)
eina_list_free((Eina_List*)data);
}
static void
_deplist_free(Eina_List *data)
{
Eolian_Dependency *dep;
EINA_LIST_FREE(data, dep)
{
eina_stringshare_del(dep->base.file);
eina_stringshare_del(dep->filename);
eina_stringshare_del(dep->name);
free(dep);
}
}
int
database_init()
{
@ -67,7 +53,6 @@ database_init()
_constantsf = eina_hash_stringshared_new(_hashlist_free);
_filenames = eina_hash_string_small_new(free);
_tfilenames = eina_hash_string_small_new(free);
_depclasses = eina_hash_stringshared_new(EINA_FREE_CB(_deplist_free));
_decls = eina_hash_stringshared_new(free);
_parsedeots = eina_hash_string_small_new(NULL);
_parsingeos = eina_hash_string_small_new(NULL);
@ -100,7 +85,6 @@ database_shutdown()
eina_hash_free(_constantsf); _constantsf = NULL;
eina_hash_free(_filenames ); _filenames = NULL;
eina_hash_free(_tfilenames); _tfilenames = NULL;
eina_hash_free(_depclasses); _depclasses = NULL;
eina_hash_free(_decls ); _decls = NULL;
eina_hash_free(_parsedeots); _parsedeots = NULL;
eina_hash_free(_parsingeos); _parsingeos = NULL;
@ -233,8 +217,6 @@ EAPI Eina_Bool
eolian_eo_file_parse(const char *filepath)
{
Eina_Iterator *itr;
Eina_List *depl;
Eolian_Dependency *dep;
if (_database_init_count <= 0)
return EINA_FALSE;
@ -244,7 +226,6 @@ eolian_eo_file_parse(const char *filepath)
const Eolian_Class *class = eolian_class_get_by_file(bfilename);
Eolian_Implement *impl;
Eolian_Constructor *ctor;
Eina_Bool failed_dep = EINA_FALSE;
if (!class)
{
const char *full_filepath = eina_hash_find(_filenames, bfilename);
@ -263,30 +244,6 @@ eolian_eo_file_parse(const char *filepath)
}
}
free(bfiledup);
/* parse dependencies first (that includes inherits) */
depl = eina_hash_find(_depclasses, eolian_class_file_get(class));
if (!depl)
goto impls;
eina_hash_set(_depclasses, eolian_class_file_get(class), NULL);
EINA_LIST_FREE(depl, dep)
{
if (failed_dep) goto free;
if (!eolian_class_get_by_name(dep->name) &&
!eolian_eo_file_parse(dep->filename))
{
fprintf(stderr, "eolian:%s:%d:%d: failed to parse dependency '%s'\n",
dep->base.file, dep->base.line, dep->base.column, dep->name);
failed_dep = EINA_TRUE; /* do not parse anymore stuff */
}
free:
eina_stringshare_del(dep->base.file);
eina_stringshare_del(dep->filename);
eina_stringshare_del(dep->name);
free(dep);
}
if (failed_dep)
goto error;
impls:
itr = eolian_class_implements_get(class);
EINA_ITERATOR_FOREACH(itr, impl)
{

View File

@ -46,9 +46,6 @@ extern Eina_Hash *_constantsf;
extern Eina_Hash *_filenames; /* Hash: filename without extension -> full path */
extern Eina_Hash *_tfilenames;
/* a hash holding lists of deps */
extern Eina_Hash *_depclasses;
/* a hash holding all declarations, for redef checking etc */
extern Eina_Hash *_decls;
@ -63,13 +60,6 @@ typedef struct _Eolian_Object
int column;
} Eolian_Object;
typedef struct _Eolian_Dependency
{
Eolian_Object base;
Eina_Stringshare *filename;
Eina_Stringshare *name;
} Eolian_Dependency;
typedef enum {
EOLIAN_DECL_CLASS,
EOLIAN_DECL_ALIAS,

View File

@ -493,7 +493,8 @@ class Evas_3D_Node (Evas_3D_Object, Evas.Common_Interface)
*/
}
values {
camera: Evas_3D_Camera *; /*@ The camera */
// FIXME: Evas_3D_Camera is necessary, but that introduces a cycle
camera: Evas_3D_Object *; /*@ The camera */
}
}