eolian: preliminary support for new constructors section

This commit is contained in:
Daniel Kolesa 2014-09-01 15:35:50 +01:00
parent 0c9a1d8a99
commit 21530bd5d8
15 changed files with 325 additions and 59 deletions

View File

@ -27,6 +27,8 @@ lib_eolian_libeolian_la_SOURCES = \
lib/eolian/database_type_api.c \
lib/eolian/database_implement.c \
lib/eolian/database_implement_api.c \
lib/eolian/database_constructor.c \
lib/eolian/database_constructor_api.c \
lib/eolian/database_event.c \
lib/eolian/database_event_api.c \
lib/eolian/database_print.c \

View File

@ -68,6 +68,12 @@ typedef struct _Eolian_Function_Parameter Eolian_Function_Parameter;
*/
typedef struct _Eolian_Implement Eolian_Implement;
/* Class constructor information
*
* @ingroup Eolian
*/
typedef struct _Eolian_Constructor Eolian_Constructor;
/* Event information
*
* @ingroup Eolian
@ -975,6 +981,46 @@ EAPI Eina_Bool eolian_implement_is_prop_set(const Eolian_Implement *impl);
*/
EAPI Eina_Iterator *eolian_class_implements_get(const Eolian_Class *klass);
/*
* @brief Get full string of a constructing function.
*
* @param[in] ctor the handle of the constructor
* @return the full string.
*
* @ingroup Eolian
*/
EAPI Eina_Stringshare *eolian_constructor_full_name_get(const Eolian_Constructor *ctor);
/*
* @brief Get the class of a constructing function.
*
* @param[in] ctor the handle of the constructor
* @return the class handle or NULL.
*
* @ingroup Eolian
*/
EAPI const Eolian_Class *eolian_constructor_class_get(const Eolian_Constructor *ctor);
/*
* @brief Get the function of a constructing function.
*
* @param[in] ctor the handle of the constructor
* @return the function handle or NULL.
*
* @ingroup Eolian
*/
EAPI const Eolian_Function *eolian_constructor_function_get(const Eolian_Constructor *ctor);
/*
* @brief Get an iterator to the constructing functions defined in a class.
*
* @param[in] klass the class.
* @return the iterator
*
* @ingroup Eolian
*/
EAPI Eina_Iterator *eolian_class_constructors_get(const Eolian_Class *klass);
/*
* @brief Get an iterator to the events defined in a class.
*

View File

@ -23,6 +23,14 @@ database_class_del(Eolian_Class *cl)
free(impl);
}
Eolian_Constructor *ctor;
Eina_List *constructors = cl->constructors;
EINA_LIST_FREE(constructors, ctor)
{
eina_stringshare_del(ctor->full_name);
free(ctor);
}
EINA_LIST_FREE(cl->methods, fid) database_function_del(fid);
EINA_LIST_FREE(cl->properties, fid) database_function_del(fid);
EINA_LIST_FREE(cl->events, ev) database_event_del(ev);

View File

@ -94,13 +94,20 @@ eolian_class_inherits_get(const Eolian_Class *cl)
return (cl->inherits ? eina_list_iterator_new(cl->inherits) : NULL);
}
EAPI Eina_Iterator*
EAPI Eina_Iterator *
eolian_class_implements_get(const Eolian_Class *cl)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(cl, NULL);
return (cl->implements ? eina_list_iterator_new(cl->implements) : NULL);
}
EAPI Eina_Iterator *
eolian_class_constructors_get(const Eolian_Class *cl)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(cl, NULL);
return (cl->constructors ? eina_list_iterator_new(cl->constructors) : NULL);
}
EAPI const Eolian_Function *
eolian_class_function_get_by_name(const Eolian_Class *cl, const char *func_name, Eolian_Function_Type f_type)
{

View File

@ -0,0 +1,11 @@
#include <Eina.h>
#include "eolian_database.h"
void
database_constructor_del(Eolian_Constructor *ctor)
{
if (!ctor) return;
if (ctor->base.file) eina_stringshare_del(ctor->base.file);
if (ctor->full_name) eina_stringshare_del(ctor->full_name);
free(ctor);
}

View File

@ -0,0 +1,41 @@
#include <Eina.h>
#include "eolian_database.h"
EAPI Eina_Stringshare *
eolian_constructor_full_name_get(const Eolian_Constructor *ctor)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(ctor, NULL);
return ctor->full_name;
}
static Eina_Bool
_fill_class(Eolian_Constructor *ctor)
{
const Eolian_Class *class = NULL;
if (ctor->klass)
return EINA_TRUE;
if (!database_class_name_validate(ctor->full_name, &class) || !class)
return EINA_FALSE;
ctor->klass = class;
return EINA_TRUE;
}
EAPI const Eolian_Class *
eolian_constructor_class_get(const Eolian_Constructor *ctor)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(ctor, NULL);
if (!_fill_class((Eolian_Constructor*)ctor))
return NULL;
return ctor->klass;
}
EAPI const Eolian_Function *
eolian_constructor_function_get(const Eolian_Constructor *ctor)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(ctor, NULL);
const Eolian_Class *klass = eolian_constructor_class_get(ctor);
if (!klass)
return NULL;
return eolian_class_function_get_by_name(klass,
ctor->full_name + strlen(klass->full_name) + 1, EOLIAN_UNRESOLVED);
}

View File

@ -297,6 +297,35 @@ _db_fill_implements(Eolian_Class *cl, Eo_Class_Def *kls)
return EINA_TRUE;
}
static void
_db_fill_constructor(Eolian_Class *cl, Eolian_Constructor *ctor)
{
const char *ctor_name = ctor->full_name;
if (ctor_name[0] == '.')
{
ctor->full_name = eina_stringshare_printf("%s%s", cl->full_name,
ctor_name);
eina_stringshare_del(ctor_name);
}
cl->constructors = eina_list_append(cl->constructors, ctor);
}
static Eina_Bool
_db_fill_constructors(Eolian_Class *cl, Eo_Class_Def *kls)
{
Eolian_Constructor *ctor;
Eina_List *l;
EINA_LIST_FOREACH(kls->constructors, l, ctor)
{
_db_fill_constructor(cl, ctor);
eina_list_data_set(l, NULL); /* prevent double free */
}
return EINA_TRUE;
}
static Eina_Bool
_db_fill_events(Eolian_Class *cl, Eo_Class_Def *kls)
{
@ -334,10 +363,11 @@ _db_fill_class(Eo_Class_Def *kls)
if (kls->data_type)
cl->data_type = eina_stringshare_ref(kls->data_type);
if (!_db_fill_properties(cl, kls)) return EINA_FALSE;
if (!_db_fill_methods (cl, kls)) return EINA_FALSE;
if (!_db_fill_implements(cl, kls)) return EINA_FALSE;
if (!_db_fill_events (cl, kls)) return EINA_FALSE;
if (!_db_fill_properties (cl, kls)) return EINA_FALSE;
if (!_db_fill_methods (cl, kls)) return EINA_FALSE;
if (!_db_fill_implements (cl, kls)) return EINA_FALSE;
if (!_db_fill_constructors(cl, kls)) return EINA_FALSE;
if (!_db_fill_events (cl, kls)) return EINA_FALSE;
cl->base = kls->base;
kls->base.file = NULL;

View File

@ -8,51 +8,13 @@ eolian_implement_full_name_get(const Eolian_Implement *impl)
return impl->full_name;
}
/*
* ret false -> clash, class = NULL
* ret true && class -> only one class corresponding
* ret true && !class -> no class corresponding
*/
static Eina_Bool
_class_name_validate(const char *class_name, const Eolian_Class **cl)
{
char *name = strdup(class_name);
char *colon = name + 1;
const Eolian_Class *found_class = NULL;
const Eolian_Class *candidate;
if (cl) *cl = NULL;
do
{
colon = strchr(colon, '.');
if (colon) *colon = '\0';
candidate = eolian_class_get_by_name(name);
if (candidate)
{
if (found_class)
{
ERR("Name clash between class %s and class %s",
candidate->full_name,
found_class->full_name);
free(name);
return EINA_FALSE; // Names clash
}
found_class = candidate;
}
if (colon) *colon++ = '.';
}
while(colon);
if (cl) *cl = found_class;
free(name);
return EINA_TRUE;
}
static Eina_Bool
_fill_class(Eolian_Implement *impl)
{
const Eolian_Class *class = NULL;
if (impl->klass)
return EINA_TRUE;
if (!_class_name_validate(impl->full_name, &class) || !class)
if (!database_class_name_validate(impl->full_name, &class) || !class)
return EINA_FALSE;
impl->klass = class;
return EINA_TRUE;

View File

@ -4,26 +4,40 @@
static void
_implements_print(Eolian_Implement *impl, int nb_spaces)
{
Eolian_Function_Type ft;
const char *t;
Eolian_Function_Type ft = EOLIAN_UNRESOLVED;
eolian_implement_function_get(impl, &ft);
switch (ft)
{
case EOLIAN_PROP_SET: t = "SET"; break;
case EOLIAN_PROP_GET: t = "GET"; break;
case EOLIAN_METHOD: t = "METHOD"; break;
case EOLIAN_UNRESOLVED:
{
t = "Type is the same as function being overriden";
break;
}
case EOLIAN_UNRESOLVED: t = ""; break;
default:
return;
}
printf("%*s <%s> <%s>\n", nb_spaces + 5, "", eolian_implement_full_name_get(impl), t);
}
static void
_constructors_print(Eolian_Constructor *ctor, int nb_spaces)
{
const char *t;
const Eolian_Function *func = eolian_constructor_function_get(ctor);
Eolian_Function_Type ft = eolian_function_type_get(func);
switch (ft)
{
case EOLIAN_PROP_SET: t = "SET"; break;
case EOLIAN_PROP_GET: t = "GET"; break;
case EOLIAN_METHOD: t = "METHOD"; break;
case EOLIAN_UNRESOLVED: t = ""; break;
default:
return;
}
printf("%*s <%s> <%s>\n", nb_spaces + 5, "", eolian_constructor_full_name_get(ctor), t);
}
static void
_event_print(Eolian_Event *ev, int nb_spaces)
{
@ -200,6 +214,8 @@ _class_print(const Eolian_Class *cl)
{
_function_print(function, 4);
}
printf("\n");
// Implement
printf(" implements:\n");
Eolian_Implement *impl;
@ -208,6 +224,16 @@ _class_print(const Eolian_Class *cl)
_implements_print(impl, 4);
}
printf("\n");
// Constructor
printf(" constructors:\n");
Eolian_Constructor *ctor;
EINA_LIST_FOREACH(cl->constructors, itr, ctor)
{
_constructors_print(ctor, 4);
}
printf("\n");
// Implement
printf(" events:\n");
Eolian_Event *ev;
@ -216,6 +242,7 @@ _class_print(const Eolian_Class *cl)
_event_print(ev, 4);
}
printf("\n");
return EINA_TRUE;
}

View File

@ -107,6 +107,7 @@ eo_definitions_class_def_free(Eo_Class_Def *kls)
Eo_Method_Def *meth;
Eolian_Event *sgn;
Eolian_Implement *impl;
Eolian_Constructor *ctor;
if (kls->base.file)
eina_stringshare_del(kls->base.file);
@ -128,6 +129,9 @@ eo_definitions_class_def_free(Eo_Class_Def *kls)
EINA_LIST_FREE(kls->implements, impl)
database_implement_del(impl);
EINA_LIST_FREE(kls->constructors, ctor)
database_constructor_del(ctor);
EINA_LIST_FREE(kls->properties, prop)
eo_definitions_property_def_free(prop);
@ -194,6 +198,9 @@ eo_definitions_temps_free(Eo_Lexer_Temps *tmp)
if (tmp->impl)
database_implement_del(tmp->impl);
if (tmp->ctor)
database_constructor_del(tmp->ctor);
EINA_LIST_FREE(tmp->strs, s)
if (s) eina_stringshare_del(s);
}

View File

@ -98,6 +98,7 @@ typedef struct _Eo_Class_Def
Eina_Stringshare *data_type;
Eina_List *inherits;
Eina_List *implements;
Eina_List *constructors;
Eina_List *events;
Eina_List *properties;
Eina_List *methods;
@ -122,6 +123,7 @@ typedef struct _Eo_Lexer_Temps
Eina_List *str_items;
Eolian_Event *event;
Eolian_Implement *impl;
Eolian_Constructor *ctor;
Eina_List *expr_defs;
Eina_List *strs;
} Eo_Lexer_Temps;

View File

@ -23,14 +23,14 @@ enum Tokens
* they just fill in the "kw" field of the token */
#define KEYWORDS KW(class), KW(const), KW(enum), KW(return), KW(struct), \
\
KW(abstract), KW(constructor), KW(data), KW(destructor), KW(eo), \
KW(eo_prefix), KW(events), KW(free), KW(func), KW(get), KW(implements), \
KW(interface), KW(keys), KW(legacy), KW(legacy_prefix), KW(methods), \
KW(mixin), KW(own), KW(params), KW(properties), KW(set), KW(type), \
KW(values), KW(var), KWAT(auto), KWAT(class), KWAT(const), \
KWAT(constructor), KWAT(empty), KWAT(extern), KWAT(free), KWAT(in), \
KWAT(inout), KWAT(nonull), KWAT(out), KWAT(private), KWAT(protected), \
KWAT(virtual), KWAT(warn_unused), \
KW(abstract), KW(constructor), KW(constructors), KW(data), \
KW(destructor), KW(eo), KW(eo_prefix), KW(events), KW(free), KW(func), \
KW(get), KW(implements), KW(interface), KW(keys), KW(legacy), \
KW(legacy_prefix), KW(methods), KW(mixin), KW(own), KW(params), \
KW(properties), KW(set), KW(type), KW(values), KW(var), KWAT(auto), \
KWAT(class), KWAT(const), KWAT(constructor), KWAT(empty), KWAT(extern), \
KWAT(free), KWAT(in), KWAT(inout), KWAT(nonull), KWAT(out), \
KWAT(private), KWAT(protected), KWAT(virtual), KWAT(warn_unused), \
\
KW(byte), KW(ubyte), KW(char), KW(short), KW(ushort), KW(int), KW(uint), \
KW(long), KW(ulong), KW(llong), KW(ullong), \

View File

@ -1598,6 +1598,46 @@ end:
pop_strbuf(ls);
}
static void
parse_constructor(Eo_Lexer *ls)
{
Eina_Strbuf *buf = NULL;
Eolian_Constructor *ctor = NULL;
ctor = calloc(1, sizeof(Eolian_Implement));
ctor->base.file = eina_stringshare_ref(ls->filename);
ctor->base.line = ls->line_number;
ctor->base.column = ls->column;
ls->tmp.ctor = ctor;
if (ls->t.token == '.')
{
check_next(ls, '.');
if (ls->t.token != TOK_VALUE)
eo_lexer_syntax_error(ls, "name expected");
ctor->full_name = eina_stringshare_add(ls->t.value.s);
eo_lexer_get(ls);
check_next(ls, ';');
return;
}
check(ls, TOK_VALUE);
buf = push_strbuf(ls);
eina_strbuf_append(buf, ls->t.value.s);
eo_lexer_get(ls);
check_next(ls, '.');
check(ls, TOK_VALUE);
for (;;)
{
eina_strbuf_append_char(buf, '.');
check(ls, TOK_VALUE);
eina_strbuf_append(buf, ls->t.value.s);
eo_lexer_get(ls);
if (ls->t.token != '.') break;
eo_lexer_get(ls);
}
check_next(ls, ';');
ctor->full_name = eina_stringshare_add(eina_strbuf_string_get(buf));
pop_strbuf(ls);
}
static void
parse_event(Eo_Lexer *ls)
{
@ -1684,6 +1724,19 @@ parse_implements(Eo_Lexer *ls, Eina_Bool iface)
check_match(ls, '}', '{', line, col);
}
static void
parse_constructors(Eo_Lexer *ls)
{
PARSE_SECTION
{
parse_constructor(ls);
ls->tmp.kls->constructors = eina_list_append(ls->tmp.kls->constructors,
ls->tmp.ctor);
ls->tmp.ctor = NULL;
}
check_match(ls, '}', '{', line, col);
}
static void
parse_events(Eo_Lexer *ls)
{
@ -1712,6 +1765,7 @@ parse_class_body(Eo_Lexer *ls, Eolian_Class_Type type)
has_properties = EINA_FALSE,
has_methods = EINA_FALSE,
has_implements = EINA_FALSE,
has_constructors = EINA_FALSE,
has_events = EINA_FALSE;
if (ls->t.token == TOK_COMMENT)
{
@ -1764,6 +1818,12 @@ parse_class_body(Eo_Lexer *ls, Eolian_Class_Type type)
CASE_LOCK(ls, implements, "implements definition")
parse_implements(ls, type == EOLIAN_CLASS_INTERFACE);
break;
case KW_constructors:
if (type == EOLIAN_CLASS_INTERFACE || type == EOLIAN_CLASS_MIXIN)
return;
CASE_LOCK(ls, constructors, "constructors definition")
parse_constructors(ls);
break;
case KW_events:
CASE_LOCK(ls, events, "events definition")
parse_events(ls);

View File

@ -160,6 +160,44 @@ database_class_to_filename(const char *cname)
return ret;
}
/*
* ret false -> clash, class = NULL
* ret true && class -> only one class corresponding
* ret true && !class -> no class corresponding
*/
Eina_Bool
database_class_name_validate(const char *class_name, const Eolian_Class **cl)
{
char *name = strdup(class_name);
char *colon = name + 1;
const Eolian_Class *found_class = NULL;
const Eolian_Class *candidate;
if (cl) *cl = NULL;
do
{
colon = strchr(colon, '.');
if (colon) *colon = '\0';
candidate = eolian_class_get_by_name(name);
if (candidate)
{
if (found_class)
{
ERR("Name clash between class %s and class %s",
candidate->full_name,
found_class->full_name);
free(name);
return EINA_FALSE; // Names clash
}
found_class = candidate;
}
if (colon) *colon++ = '.';
}
while(colon);
if (cl) *cl = found_class;
free(name);
return EINA_TRUE;
}
EAPI Eina_Bool
eolian_eot_file_parse(const char *filepath)
{
@ -177,6 +215,7 @@ eolian_eo_file_parse(const char *filepath)
const Eolian_Class *class = eolian_class_get_by_file(bfilename);
const char *inherit_name;
Eolian_Implement *impl;
Eolian_Constructor *ctor;
Eina_Bool failed_dep = EINA_FALSE;
if (!class)
{
@ -249,6 +288,17 @@ inherits:
}
}
eina_iterator_free(itr);
itr = eolian_class_constructors_get(class);
EINA_ITERATOR_FOREACH(itr, ctor)
{
const Eolian_Function *ctor_func = eolian_constructor_function_get(ctor);
if (!ctor_func)
{
ERR("Unable to find function %s", eolian_constructor_full_name_get(ctor));
goto error;
}
}
eina_iterator_free(itr);
return EINA_TRUE;

View File

@ -78,6 +78,7 @@ struct _Eolian_Class
Eina_List *properties; /* List prop_name -> Eolian_Function */
Eina_List *methods; /* List meth_name -> Eolian_Function */
Eina_List *implements; /* List implements name -> Eolian_Implement */
Eina_List *constructors; /* List constructors name -> Eolian_Constructor */
Eina_List *events; /* List event_name -> Eolian_Event */
Eina_Bool class_ctor_enable:1;
Eina_Bool class_dtor_enable:1;
@ -168,6 +169,13 @@ struct _Eolian_Implement
Eina_Bool is_empty: 1;
};
struct _Eolian_Constructor
{
Eolian_Object base;
const Eolian_Class *klass;
Eina_Stringshare *full_name;
};
struct _Eolian_Event
{
Eolian_Object base;
@ -270,6 +278,7 @@ int database_shutdown();
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);
/* types */
@ -312,6 +321,10 @@ void database_parameter_del(Eolian_Function_Parameter *pdesc);
void database_implement_del(Eolian_Implement *impl);
/* constructors */
void database_constructor_del(Eolian_Constructor *ctor);
/* events */
Eolian_Event *database_event_new(const char *event_name, const char *event_type, const char *event_desc);