eolian: much better and stricter redefinition checking

We can now check redefinitions between different types of declarations,
such as redefinition of struct as variable etc.

@feature
This commit is contained in:
Daniel Kolesa 2015-05-15 15:10:58 +01:00
parent 56ffe74896
commit 8ec7d1cc48
6 changed files with 87 additions and 27 deletions

View File

@ -51,6 +51,7 @@ database_type_add(Eolian_Type *def)
eina_hash_set(_aliases, def->full_name, def);
eina_hash_set(_aliasesf, def->base.file, eina_list_append
((Eina_List*)eina_hash_find(_aliasesf, def->base.file), def));
database_decl_add(def->full_name, EOLIAN_DECL_ALIAS, def);
}
void
@ -59,6 +60,7 @@ database_struct_add(Eolian_Type *tp)
eina_hash_set(_structs, tp->full_name, tp);
eina_hash_set(_structsf, tp->base.file, eina_list_append
((Eina_List*)eina_hash_find(_structsf, tp->base.file), tp));
database_decl_add(tp->full_name, EOLIAN_DECL_STRUCT, tp);
}
void
@ -67,6 +69,7 @@ database_enum_add(Eolian_Type *tp)
eina_hash_set(_enums, tp->full_name, tp);
eina_hash_set(_enumsf, tp->base.file, eina_list_append
((Eina_List*)eina_hash_find(_enumsf, tp->base.file), tp));
database_decl_add(tp->full_name, EOLIAN_DECL_ENUM, tp);
}
static void

View File

@ -28,6 +28,7 @@ database_var_global_add(Eolian_Variable *var)
eina_hash_set(_globals, var->full_name, var);
eina_hash_set(_globalsf, var->base.file, eina_list_append
((Eina_List*)eina_hash_find(_globalsf, var->base.file), var));
database_decl_add(var->full_name, EOLIAN_DECL_VAR, var);
}
static void
@ -36,6 +37,7 @@ database_var_constant_add(Eolian_Variable *var)
eina_hash_set(_constants, var->full_name, var);
eina_hash_set(_constantsf, var->base.file, eina_list_append
((Eina_List*)eina_hash_find(_constantsf, var->base.file), var));
database_decl_add(var->full_name, EOLIAN_DECL_VAR, var);
}
void

View File

@ -92,15 +92,15 @@ throw(Eo_Lexer *ls, const char *fmt, ...)
va_start(ap, fmt);
eina_strbuf_append_vprintf(buf, fmt, ap);
va_end(ap);
eina_strbuf_append_char(buf, ' ');
eina_strbuf_append(buf, "\n ");
while (ln != end && !is_newline(*ln))
eina_strbuf_append_char(buf,*(ln++));
eina_strbuf_append_char(buf, '\n');
for (i = 0; i < ls->column; ++i)
eina_strbuf_append_char(buf, ' ');
eina_strbuf_append(buf, "^\n");
fprintf(stderr, "eolian:%s:%d: %s\n", ls->source, ls->line_number,
eina_strbuf_string_get(buf));
fprintf(stderr, "eolian:%s:%d:%d: %s\n", ls->source, ls->line_number,
ls->column, eina_strbuf_string_get(buf));
eina_strbuf_free(buf);
longjmp(ls->err_jmp, EINA_TRUE);
}
@ -767,10 +767,10 @@ eo_lexer_lex_error(Eo_Lexer *ls, const char *msg, int token)
{
char buf[256];
txt_token(ls, token, buf);
throw(ls, "%s at column %d near '%s'\n", msg, ls->column, buf);
throw(ls, "%s near '%s'", msg, buf);
}
else
throw(ls, "%s at column %d\n", msg, ls->column);
throw(ls, "%s", msg);
}
void

View File

@ -135,20 +135,27 @@ compare_class_file(const char *fn1, const char *fn2)
return !strcmp(fn1, fn2);
}
static const char *declnames[] = {
"class", "type alias", "struct", "enum", "variable"
};
static void
redef_error(Eo_Lexer *ls, Eolian_Type_Type type, Eolian_Type *old)
redef_error(Eo_Lexer *ls, Eolian_Declaration *decl, Eolian_Declaration_Type newt)
{
char buf[256];
char fbuf[256] = { '\0' };
const char *file = eina_stringshare_ref(ls->filename);
if (file != old->base.file)
snprintf(fbuf, sizeof(fbuf), " in file '%s'", old->base.file);
eina_stringshare_del(file);
snprintf(buf, sizeof(buf),
"%s '%s' redefined (originally at line %d, column %d%s)",
(type == EOLIAN_TYPE_ENUM) ? "enum" : ((type == EOLIAN_TYPE_STRUCT)
? "struct" : "type alias"),
old->full_name, old->base.line, old->base.column, fbuf);
Eolian_Object *obj = (Eolian_Object *)decl->data;
char buf[256], fbuf[256] = { '\0' };
if (ls->filename != obj->file)
snprintf(fbuf, sizeof(fbuf), "%s:%d:%d", obj->file, obj->line, obj->column);
else
snprintf(fbuf, sizeof(fbuf), "%d:%d", obj->line, obj->column);
if (newt != decl->type)
snprintf(buf, sizeof(buf), "%s '%s' redefined as %s (originally at %s)",
declnames[decl->type], decl->name, declnames[newt], fbuf);
else
snprintf(buf, sizeof(buf), "%s '%s' redefined (originally at %s)",
declnames[decl->type], decl->name, fbuf);
eo_lexer_syntax_error(ls, buf);
}
@ -841,6 +848,7 @@ parse_ptr:
static Eolian_Type *
parse_typedef(Eo_Lexer *ls)
{
Eolian_Declaration *decl;
Eolian_Type *def = push_type(ls);
Eina_Bool has_extern;
const char *freefunc;
@ -857,11 +865,11 @@ parse_typedef(Eo_Lexer *ls)
parse_name(ls, buf);
_fill_name(eina_stringshare_add(eina_strbuf_string_get(buf)),
&def->full_name, &def->name, &def->namespaces);
Eolian_Type *tp = (Eolian_Type*)eina_hash_find(_aliases, def->full_name);
if (tp)
decl = (Eolian_Declaration *)eina_hash_find(_decls, def->full_name);
if (decl)
{
eo_lexer_context_restore(ls);
redef_error(ls, EOLIAN_TYPE_ALIAS, tp);
redef_error(ls, decl, EOLIAN_DECL_ALIAS);
}
eo_lexer_context_pop(ls);
check_next(ls, ':');
@ -879,6 +887,7 @@ parse_typedef(Eo_Lexer *ls)
static Eolian_Variable *
parse_variable(Eo_Lexer *ls, Eina_Bool global)
{
Eolian_Declaration *decl;
Eolian_Variable *def = calloc(1, sizeof(Eolian_Variable));
Eina_Bool has_extern = EINA_FALSE;
Eina_Strbuf *buf;
@ -899,6 +908,13 @@ parse_variable(Eo_Lexer *ls, Eina_Bool global)
parse_name(ls, buf);
_fill_name(eina_stringshare_add(eina_strbuf_string_get(buf)),
&def->full_name, &def->name, &def->namespaces);
decl = (Eolian_Declaration *)eina_hash_find(_decls, def->full_name);
if (decl)
{
eo_lexer_context_restore(ls);
redef_error(ls, decl, EOLIAN_DECL_VAR);
}
eo_lexer_context_pop(ls);
check_next(ls, ':');
def->base_type = parse_type(ls);
pop_type(ls);
@ -1702,6 +1718,7 @@ parse_class_body(Eo_Lexer *ls, Eolian_Class_Type type)
static void
parse_class(Eo_Lexer *ls, Eolian_Class_Type type)
{
Eolian_Declaration *decl;
const char *bnm;
char *fnm;
Eina_Bool same;
@ -1723,10 +1740,16 @@ parse_class(Eo_Lexer *ls, Eolian_Class_Type type)
eo_lexer_context_restore(ls);
eo_lexer_syntax_error(ls, "class and file names differ");
}
eo_lexer_context_pop(ls);
_fill_name(eina_stringshare_add(eina_strbuf_string_get(buf)),
&ls->tmp.kls->full_name, &ls->tmp.kls->name,
&ls->tmp.kls->namespaces);
decl = (Eolian_Declaration *)eina_hash_find(_decls, ls->tmp.kls->full_name);
if (decl)
{
eo_lexer_context_restore(ls);
redef_error(ls, decl, EOLIAN_DECL_CLASS);
}
eo_lexer_context_pop(ls);
pop_strbuf(ls);
if (ls->t.token != '{')
{
@ -1784,7 +1807,7 @@ parse_unit(Eo_Lexer *ls, Eina_Bool eot)
Eina_Bool is_enum = (ls->t.kw == KW_enum);
const char *name;
int line, col;
Eolian_Type *tp;
Eolian_Declaration *decl;
Eina_Bool has_extern;
const char *freefunc;
Eina_Strbuf *buf;
@ -1796,14 +1819,12 @@ parse_unit(Eo_Lexer *ls, Eina_Bool eot)
col = ls->column;
parse_name(ls, buf);
name = eina_stringshare_add(eina_strbuf_string_get(buf));
tp = (Eolian_Type*)eina_hash_find(is_enum ? _enums
: _structs, name);
if (tp)
decl = (Eolian_Declaration *)eina_hash_find(_decls, name);
if (decl)
{
eina_stringshare_del(name);
eo_lexer_context_restore(ls);
redef_error(ls, is_enum ? EOLIAN_TYPE_ENUM
: EOLIAN_TYPE_STRUCT, tp);
redef_error(ls, decl, is_enum ? EOLIAN_DECL_ENUM : EOLIAN_DECL_STRUCT);
}
eo_lexer_context_pop(ls);
pop_strbuf(ls);
@ -1840,6 +1861,7 @@ parse_unit(Eo_Lexer *ls, Eina_Bool eot)
}
return EINA_FALSE;
found_class:
database_decl_add(ls->tmp.kls->full_name, EOLIAN_DECL_CLASS, ls->tmp.kls);
ls->tmp.classes = eina_list_append(ls->tmp.classes, ls->tmp.kls);
ls->tmp.kls = NULL;
return EINA_TRUE;

View File

@ -22,6 +22,7 @@ Eina_Hash *_constantsf = NULL;
Eina_Hash *_filenames = NULL;
Eina_Hash *_tfilenames = NULL;
Eina_Hash *_depclasses = NULL;
Eina_Hash *_decls = NULL;
static int _database_init_count = 0;
@ -64,6 +65,7 @@ database_init()
_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);
return ++_database_init_count;
}
@ -94,11 +96,22 @@ database_shutdown()
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_shutdown();
}
return _database_init_count;
}
void
database_decl_add(Eina_Stringshare *name, Eolian_Declaration_Type type, void *ptr)
{
Eolian_Declaration *decl = calloc(1, sizeof(Eolian_Declaration));
decl->type = type;
decl->name = name;
decl->data = ptr;
eina_hash_set(_decls, name, decl);
}
#define EO_SUFFIX ".eo"
#define EOT_SUFFIX ".eot"

View File

@ -49,6 +49,9 @@ 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;
typedef struct _Eolian_Object
{
const char *file;
@ -63,6 +66,21 @@ typedef struct _Eolian_Dependency
Eina_Stringshare *name;
} Eolian_Dependency;
typedef enum {
EOLIAN_DECL_CLASS,
EOLIAN_DECL_ALIAS,
EOLIAN_DECL_STRUCT,
EOLIAN_DECL_ENUM,
EOLIAN_DECL_VAR
} Eolian_Declaration_Type;
typedef struct _Eolian_Declaration
{
Eolian_Declaration_Type type;
Eina_Stringshare *name;
void *data;
} Eolian_Declaration;
struct _Eolian_Class
{
Eolian_Object base;
@ -251,6 +269,8 @@ char *database_class_to_filename(const char *cname);
Eina_Bool database_validate(void);
Eina_Bool database_class_name_validate(const char *class_name, const Eolian_Class **cl);
void database_decl_add(Eina_Stringshare *name, Eolian_Declaration_Type type, void *ptr);
/* types */
void database_type_add(Eolian_Type *def);