q66 pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=9594f09156abe649c7015b452765100ed7e2f54b

commit 9594f09156abe649c7015b452765100ed7e2f54b
Author: Daniel Kolesa <d.kol...@osg.samsung.com>
Date:   Thu Mar 8 17:30:30 2018 +0100

    eolian: add API to query information about Objects
    
    As nearly every Eolian handle is backed by an Eolian_Object,
    this information is now publicly exposed and has an API. This
    opens up an array of new possibilities for tooling, as you
    can now externally query file names, line numbers etc.,
    as well as cast arbitrary handles to Eolian_Object pointers
    and back.
    
    This will be expanded later and it will replace the Declaration
    system, as it's cleaner, better integrated and more versatile.
    
    @feature
---
 src/lib/eolian/Eolian.h          | 86 ++++++++++++++++++++++++++++++++++++++++
 src/lib/eolian/eo_parser.c       | 73 +++++++++++++++++-----------------
 src/lib/eolian/eolian_database.c | 28 +++++++++++++
 src/lib/eolian/eolian_database.h |  5 ++-
 4 files changed, 154 insertions(+), 38 deletions(-)

diff --git a/src/lib/eolian/Eolian.h b/src/lib/eolian/Eolian.h
index 900c9f167b..e74832f70c 100644
--- a/src/lib/eolian/Eolian.h
+++ b/src/lib/eolian/Eolian.h
@@ -93,6 +93,14 @@ extern "C" {
  */
 typedef struct _Eolian_State Eolian_State;
 
+/* Any Eolian object
+ *
+ * @see Eolian_Object_Type
+ *
+ * @ingroup Eolian
+ */
+typedef struct _Eolian_Object Eolian_Object;
+
 /* Class type used to extract information on classes
  *
  * @ingroup Eolian
@@ -191,6 +199,26 @@ typedef struct _Eolian_Unit Eolian_Unit;
 
 typedef enum
 {
+   EOLIAN_OBJECT_UNKNOWN = 0,
+   EOLIAN_OBJECT_CLASS,
+   EOLIAN_OBJECT_TYPEDECL,
+   EOLIAN_OBJECT_STRUCT_FIELD,
+   EOLIAN_OBJECT_ENUM_FIELD,
+   EOLIAN_OBJECT_TYPE,
+   EOLIAN_OBJECT_VARIABLE,
+   EOLIAN_OBJECT_EXPRESSION,
+   EOLIAN_OBJECT_FUNCTION,
+   EOLIAN_OBJECT_FUNCTION_PARAMETER,
+   EOLIAN_OBJECT_EVENT,
+   EOLIAN_OBJECT_PART,
+   EOLIAN_OBJECT_IMPLEMENT,
+   EOLIAN_OBJECT_CONSTRUCTOR,
+   EOLIAN_OBJECT_DOCUMENTATION,
+   EOLIAN_OBJECT_DECLARATION
+} Eolian_Object_Type;
+
+typedef enum
+{
    EOLIAN_UNRESOLVED = 0,
    EOLIAN_PROPERTY,
    EOLIAN_PROP_SET,
@@ -500,6 +528,64 @@ EAPI Eolian_State *eolian_state_new(void);
 EAPI void eolian_state_free(Eolian_State *state);
 
 /*
+ * @brief Get the type of an Eolian object.
+ *
+ * Most handles returned by Eolian somewhere are Eolian_Objects. You can cast
+ * them to Eolian_Object, store or manipulate them and then use this function
+ * to check their type in order to for example cast it back.
+ *
+ * @see eolian_object_file_get
+ * @see eolian_object_line_get
+ * @see eolian_object_column_get
+ *
+ * @ingroup Eolian
+ */
+EAPI Eolian_Object_Type eolian_object_type_get(const Eolian_Object *obj);
+
+/*
+ * @brief Get the name of the file the object comes from.
+ *
+ * This returns the name of the file the object was declared in. It's not
+ * a full path, just the file name.
+ *
+ * @see eolian_object_type_get
+ * @see eolian_object_line_get
+ * @see eolian_object_column_get
+ *
+ * @ingroup Eolian
+ */
+EAPI const char *eolian_object_file_get(const Eolian_Object *obj);
+
+/*
+ * @brief Get the line the object was declared at.
+ *
+ * This returns the line number in the file the object was declared at.
+ *
+ * @see eolian_object_type_get
+ * @see eolian_object_file_get
+ * @see eolian_object_column_get
+ *
+ * @ingroup Eolian
+ */
+EAPI int eolian_object_line_get(const Eolian_Object *obj);
+
+/*
+ * @brief Get the column the object was declared at.
+ *
+ * This returns the column number in the file the object was declared at,
+ * that means which character on the line. It is Unicode-aware, Eolian
+ * assumes all input files are encoded in UTF-8, so this is really the
+ * code point number, not the byte number.
+ *
+ * @see eolian_object_type_get
+ * @see eolian_object_file_get
+ * @see eolian_object_line_get
+ *
+ * @ingroup Eolian
+ */
+EAPI int eolian_object_column_get(const Eolian_Object *obj);
+
+/*
  * @brief Scan the given directory for .eo and .eot files.
  *
  * You need to add every directory you plan to use .eo/.eot files from.
diff --git a/src/lib/eolian/eo_parser.c b/src/lib/eolian/eo_parser.c
index 6ed90395d3..7c8003d0f7 100644
--- a/src/lib/eolian/eo_parser.c
+++ b/src/lib/eolian/eo_parser.c
@@ -12,10 +12,11 @@
      eo_lexer_syntax_error(ls, "double " msg); \
    has_##var = EINA_TRUE;
 
-#define FILL_BASE(exp, ls, l, c) \
+#define FILL_BASE(exp, ls, l, c, tp) \
    (exp).file = eina_stringshare_ref(ls->filename); \
    (exp).line = l; \
-   (exp).column = c;
+   (exp).column = c; \
+   (exp).type = EOLIAN_OBJECT_##tp
 
 #define FILL_DOC(ls, def, docf) \
    if (ls->t.token == TOK_DOC) \
@@ -333,7 +334,7 @@ parse_expr_simple(Eo_Lexer *ls)
         Eolian_Expression *exp = parse_expr_bin(ls, UNARY_PRECEDENCE);
         pop_expr(ls);
         expr = push_expr(ls);
-        FILL_BASE(expr->base, ls, line, col);
+        FILL_BASE(expr->base, ls, line, col, EXPRESSION);
         expr->unop = unop;
         expr->type = EOLIAN_EXPR_UNARY;
         expr->expr = exp;
@@ -345,7 +346,7 @@ parse_expr_simple(Eo_Lexer *ls)
         {
            int line = ls->line_number, col = ls->column;
            expr = push_expr(ls);
-           FILL_BASE(expr->base, ls, line, col);
+           FILL_BASE(expr->base, ls, line, col, EXPRESSION);
            expr->type = ls->t.kw + 1; /* map Numbers from lexer to expr type */
            memcpy(&expr->value, &ls->t.value, sizeof(expr->value));
            eo_lexer_get(ls);
@@ -355,7 +356,7 @@ parse_expr_simple(Eo_Lexer *ls)
         {
            int line = ls->line_number, col = ls->column;
            expr = push_expr(ls);
-           FILL_BASE(expr->base, ls, line, col);
+           FILL_BASE(expr->base, ls, line, col, EXPRESSION);
            expr->type = EOLIAN_EXPR_STRING;
            expr->value.s = eina_stringshare_ref(ls->t.value.s);
            eo_lexer_get(ls);
@@ -365,7 +366,7 @@ parse_expr_simple(Eo_Lexer *ls)
         {
            int line = ls->line_number, col = ls->column;
            expr = push_expr(ls);
-           FILL_BASE(expr->base, ls, line, col);
+           FILL_BASE(expr->base, ls, line, col, EXPRESSION);
            expr->type = EOLIAN_EXPR_CHAR;
            expr->value.c = ls->t.value.c;
            eo_lexer_get(ls);
@@ -404,7 +405,7 @@ parse_expr_simple(Eo_Lexer *ls)
                    break;
                 }
              }
-           FILL_BASE(expr->base, ls, line, col);
+           FILL_BASE(expr->base, ls, line, col, EXPRESSION);
            break;
         }
       case '(':
@@ -441,7 +442,7 @@ parse_expr_bin(Eo_Lexer *ls, int min_prec)
         pop_expr(ls);
         pop_expr(ls);
         bin = push_expr(ls);
-        FILL_BASE(bin->base, ls, line, col);
+        FILL_BASE(bin->base, ls, line, col, EXPRESSION);
         bin->binop = op;
         bin->type = EOLIAN_EXPR_BINARY;
         bin->lhs = lhs;
@@ -515,7 +516,7 @@ parse_struct(Eo_Lexer *ls, const char *name, Eina_Bool 
is_extern,
         eo_lexer_get(ls);
         check_next(ls, ':');
         tp = parse_type(ls);
-        FILL_BASE(fdef->base, ls, fline, fcol);
+        FILL_BASE(fdef->base, ls, fline, fcol, STRUCT_FIELD);
         fdef->type = tp;
         fdef->name = eina_stringshare_ref(fname);
         pop_type(ls);
@@ -525,7 +526,7 @@ parse_struct(Eo_Lexer *ls, const char *name, Eina_Bool 
is_extern,
         FILL_DOC(ls, fdef, doc);
      }
    check_match(ls, '}', '{', bline, bcolumn);
-   FILL_BASE(def->base, ls, line, column);
+   FILL_BASE(def->base, ls, line, column, TYPEDECL);
    if (name) database_struct_add(ls->unit, def);
    return def;
 }
@@ -582,7 +583,7 @@ parse_enum(Eo_Lexer *ls, const char *name, Eina_Bool 
is_extern,
         def->field_list = eina_list_append(def->field_list, fdef);
         eolian_object_ref(&fdef->base);
         eo_lexer_get(ls);
-        FILL_BASE(fdef->base, ls, fline, fcol);
+        FILL_BASE(fdef->base, ls, fline, fcol, ENUM_FIELD);
         fdef->base_enum = def;
         fdef->name = eina_stringshare_ref(fname);
         if (ls->t.token != '=')
@@ -590,7 +591,7 @@ parse_enum(Eo_Lexer *ls, const char *name, Eina_Bool 
is_extern,
              if (!prev_fl)
                {
                   Eolian_Expression *eexp = push_expr(ls);
-                  FILL_BASE(eexp->base, ls, -1, -1);
+                  FILL_BASE(eexp->base, ls, -1, -1, EXPRESSION);
                   eexp->type = EOLIAN_EXPR_INT;
                   eexp->value.i = 0;
                   fdef->value = eexp;
@@ -603,8 +604,8 @@ parse_enum(Eo_Lexer *ls, const char *name, Eina_Bool 
is_extern,
                {
                   Eolian_Expression *rhs = push_expr(ls),
                                     *bin = push_expr(ls);
-                  FILL_BASE(rhs->base, ls, -1, -1);
-                  FILL_BASE(bin->base, ls, -1, -1);
+                  FILL_BASE(rhs->base, ls, -1, -1, EXPRESSION);
+                  FILL_BASE(bin->base, ls, -1, -1, EXPRESSION);
 
                   rhs->type = EOLIAN_EXPR_INT;
                   rhs->value.i = ++fl_nadd;
@@ -637,7 +638,7 @@ parse_enum(Eo_Lexer *ls, const char *name, Eina_Bool 
is_extern,
           break;
      }
    check_match(ls, '}', '{', bline, bcolumn);
-   FILL_BASE(def->base, ls, line, column);
+   FILL_BASE(def->base, ls, line, column, TYPEDECL);
    if (name) database_enum_add(ls->unit, def);
    return def;
 }
@@ -691,7 +692,7 @@ parse_type_void(Eo_Lexer *ls)
            pcol = ls->column;
            check_next(ls, '(');
            def = parse_type_void(ls);
-           FILL_BASE(def->base, ls, line, col);
+           FILL_BASE(def->base, ls, line, col, TYPE);
            def->is_const = EINA_TRUE;
            check_match(ls, ')', '(', pline, pcol);
            return def;
@@ -704,7 +705,7 @@ parse_type_void(Eo_Lexer *ls)
            pcol = ls->column;
            check_next(ls, '(');
            def = parse_type_void(ls);
-           FILL_BASE(def->base, ls, line, col);
+           FILL_BASE(def->base, ls, line, col, TYPE);
            def->is_ptr = EINA_TRUE;
            check_match(ls, ')', '(', pline, pcol);
            return def;
@@ -717,7 +718,7 @@ parse_type_void(Eo_Lexer *ls)
            pcol = ls->column;
            check_next(ls, '(');
            def = parse_type_void(ls);
-           FILL_BASE(def->base, ls, line, col);
+           FILL_BASE(def->base, ls, line, col, TYPE);
            def->legacy = EINA_TRUE;
            check_match(ls, ')', '(', pline, pcol);
            return def;
@@ -734,7 +735,7 @@ parse_type_void(Eo_Lexer *ls)
            check(ls, TOK_VALUE);
            def->freefunc = eina_stringshare_ref(ls->t.value.s);
            eo_lexer_get(ls);
-           FILL_BASE(def->base, ls, line, col);
+           FILL_BASE(def->base, ls, line, col, TYPE);
            check_match(ls, ')', '(', pline, pcolumn);
            return def;
         }
@@ -742,7 +743,7 @@ parse_type_void(Eo_Lexer *ls)
         break;
      }
    def = push_type(ls);
-   FILL_BASE(def->base, ls, line, col);
+   FILL_BASE(def->base, ls, line, col, TYPE);
    if (ls->t.kw == KW_void)
      {
         def->type = EOLIAN_TYPE_VOID;
@@ -844,7 +845,7 @@ parse_typedef(Eo_Lexer *ls)
    def->is_extern = has_extern;
    buf = push_strbuf(ls);
    eo_lexer_context_push(ls);
-   FILL_BASE(def->base, ls, ls->line_number, ls->column);
+   FILL_BASE(def->base, ls, ls->line_number, ls->column, TYPEDECL);
    parse_name(ls, buf);
    _fill_name(eina_stringshare_add(eina_strbuf_string_get(buf)),
               &def->full_name, &def->name, &def->namespaces);
@@ -880,7 +881,7 @@ parse_variable(Eo_Lexer *ls, Eina_Bool global)
    def->type = global ? EOLIAN_VAR_GLOBAL : EOLIAN_VAR_CONSTANT;
    buf = push_strbuf(ls);
    eo_lexer_context_push(ls);
-   FILL_BASE(def->base, ls, ls->line_number, ls->column);
+   FILL_BASE(def->base, ls, ls->line_number, ls->column, VARIABLE);
    parse_name(ls, buf);
    _fill_name(eina_stringshare_add(eina_strbuf_string_get(buf)),
               &def->full_name, &def->name, &def->namespaces);
@@ -974,7 +975,7 @@ parse_param(Eo_Lexer *ls, Eina_List **params, Eina_Bool 
allow_inout,
    Eina_Bool cref = (ls->t.kw == KW_at_cref);
    Eolian_Function_Parameter *par = calloc(1, 
sizeof(Eolian_Function_Parameter));
    par->param_dir = EOLIAN_IN_PARAM;
-   FILL_BASE(par->base, ls, ls->line_number, ls->column);
+   FILL_BASE(par->base, ls, ls->line_number, ls->column, FUNCTION_PARAMETER);
    *params = eina_list_append(*params, par);
    eolian_object_ref(&par->base);
    if (cref || (allow_inout && (ls->t.kw == KW_at_in)))
@@ -1088,7 +1089,7 @@ parse_accessor(Eo_Lexer *ls, Eolian_Function *prop)
      {
         if (prop->base.file)
           eina_stringshare_del(prop->base.file);
-        FILL_BASE(prop->base, ls, ls->line_number, ls->column);
+        FILL_BASE(prop->base, ls, ls->line_number, ls->column, FUNCTION);
         if (prop->type == EOLIAN_PROP_SET)
           prop->type = EOLIAN_PROPERTY;
         else
@@ -1096,7 +1097,7 @@ parse_accessor(Eo_Lexer *ls, Eolian_Function *prop)
      }
    else
      {
-        FILL_BASE(prop->set_base, ls, ls->line_number, ls->column);
+        FILL_BASE(prop->set_base, ls, ls->line_number, ls->column, FUNCTION);
         if (prop->type == EOLIAN_PROP_GET)
           prop->type = EOLIAN_PROPERTY;
         else
@@ -1236,11 +1237,11 @@ parse_property(Eo_Lexer *ls)
    prop->klass = ls->tmp.kls;
    prop->type = EOLIAN_UNRESOLVED;
    prop->get_scope = prop->set_scope = EOLIAN_SCOPE_PUBLIC;
-   FILL_BASE(prop->base, ls, ls->line_number, ls->column);
+   FILL_BASE(prop->base, ls, ls->line_number, ls->column, FUNCTION);
    impl = calloc(1, sizeof(Eolian_Implement));
    impl->klass = ls->tmp.kls;
    impl->foo_id = prop;
-   FILL_BASE(impl->base, ls, ls->line_number, ls->column);
+   FILL_BASE(impl->base, ls, ls->line_number, ls->column, IMPLEMENT);
    prop->impl = impl;
    ls->tmp.kls->properties = eina_list_append(ls->tmp.kls->properties, prop);
    ls->tmp.kls->implements = eina_list_append(ls->tmp.kls->implements, impl);
@@ -1382,8 +1383,8 @@ parse_function_pointer(Eo_Lexer *ls)
 end:
    check_match(ls, '}', '{', bline, bcol);
    check_next(ls, ';');
-   FILL_BASE(def->base, ls, line, col);
-   FILL_BASE(meth->base, ls, line, col);
+   FILL_BASE(def->base, ls, line, col, TYPEDECL);
+   FILL_BASE(meth->base, ls, line, col, FUNCTION);
    return def;
 }
 
@@ -1402,11 +1403,11 @@ parse_method(Eo_Lexer *ls)
    meth->klass = ls->tmp.kls;
    meth->type = EOLIAN_METHOD;
    meth->get_scope = meth->set_scope = EOLIAN_SCOPE_PUBLIC;
-   FILL_BASE(meth->base, ls, ls->line_number, ls->column);
+   FILL_BASE(meth->base, ls, ls->line_number, ls->column, FUNCTION);
    impl = calloc(1, sizeof(Eolian_Implement));
    impl->klass = ls->tmp.kls;
    impl->foo_id = meth;
-   FILL_BASE(impl->base, ls, ls->line_number, ls->column);
+   FILL_BASE(impl->base, ls, ls->line_number, ls->column, IMPLEMENT);
    meth->impl = impl;
    ls->tmp.kls->methods = eina_list_append(ls->tmp.kls->methods, meth);
    ls->tmp.kls->implements = eina_list_append(ls->tmp.kls->implements, impl);
@@ -1593,7 +1594,7 @@ parse_implement(Eo_Lexer *ls, Eina_Bool iface)
    else
      {
         impl = calloc(1, sizeof(Eolian_Implement));
-        FILL_BASE(impl->base, ls, iline, icol);
+        FILL_BASE(impl->base, ls, iline, icol, IMPLEMENT);
         ls->tmp.kls->implements = eina_list_append(ls->tmp.kls->implements, 
impl);
         eolian_object_ref(&impl->base);
      }
@@ -1698,7 +1699,7 @@ parse_constructor(Eo_Lexer *ls)
    Eina_Strbuf *buf = NULL;
    Eolian_Constructor *ctor = NULL;
    ctor = calloc(1, sizeof(Eolian_Constructor));
-   FILL_BASE(ctor->base, ls, ls->line_number, ls->column);
+   FILL_BASE(ctor->base, ls, ls->line_number, ls->column, CONSTRUCTOR);
    ls->tmp.kls->constructors = eina_list_append(ls->tmp.kls->constructors, 
ctor);
    eolian_object_ref(&ctor->base);
    if (ls->t.token == '.')
@@ -1747,7 +1748,7 @@ static void
 parse_event(Eo_Lexer *ls)
 {
    Eolian_Event *ev = calloc(1, sizeof(Eolian_Event));
-   FILL_BASE(ev->base, ls, ls->line_number, ls->column);
+   FILL_BASE(ev->base, ls, ls->line_number, ls->column, EVENT);
    ev->scope = EOLIAN_SCOPE_PUBLIC;
    Eina_Strbuf *buf = push_strbuf(ls);
    ls->tmp.kls->events = eina_list_append(ls->tmp.kls->events, ev);
@@ -2054,7 +2055,7 @@ parse_class(Eo_Lexer *ls, Eolian_Class_Type type)
    int line, col;
    Eina_Strbuf *buf = push_strbuf(ls);
    ls->tmp.kls = calloc(1, sizeof(Eolian_Class));
-   FILL_BASE(ls->tmp.kls->base, ls, ls->line_number, ls->column);
+   FILL_BASE(ls->tmp.kls->base, ls, ls->line_number, ls->column, DECLARATION);
    eo_lexer_get(ls);
    ls->tmp.kls->type = type;
    eo_lexer_context_push(ls);
@@ -2207,7 +2208,7 @@ parse_unit(Eo_Lexer *ls, Eina_Bool eot)
                 _fill_name(name, &def->full_name, &def->name, 
&def->namespaces);
                 eo_lexer_get(ls);
                 FILL_DOC(ls, def, doc);
-                FILL_BASE(def->base, ls, line, col);
+                FILL_BASE(def->base, ls, line, col, TYPEDECL);
                 database_struct_add(ls->unit, def);
                 pop_typedecl(ls);
                 break;
diff --git a/src/lib/eolian/eolian_database.c b/src/lib/eolian/eolian_database.c
index 4d206dc182..8e3d77fbaa 100644
--- a/src/lib/eolian/eolian_database.c
+++ b/src/lib/eolian/eolian_database.c
@@ -602,6 +602,34 @@ eolian_state_free(Eolian_State *state)
    free(state);
 }
 
+EAPI Eolian_Object_Type
+eolian_object_type_get(const Eolian_Object *obj)
+{
+   if (!obj) return EOLIAN_OBJECT_UNKNOWN;
+   return obj->type;
+}
+
+EAPI const char *
+eolian_object_file_get(const Eolian_Object *obj)
+{
+   if (!obj) return NULL;
+   return obj->file;
+}
+
+EAPI int
+eolian_object_line_get(const Eolian_Object *obj)
+{
+   if (!obj) return 0;
+   return obj->line;
+}
+
+EAPI int
+eolian_object_column_get(const Eolian_Object *obj)
+{
+   if (!obj) return 0;
+   return obj->column;
+}
+
 #define EO_SUFFIX ".eo"
 #define EOT_SUFFIX ".eot"
 
diff --git a/src/lib/eolian/eolian_database.h b/src/lib/eolian/eolian_database.h
index 675373c690..556cfce1ba 100644
--- a/src/lib/eolian/eolian_database.h
+++ b/src/lib/eolian/eolian_database.h
@@ -64,14 +64,15 @@ struct _Eolian_State
    Eina_Hash *decls_f;
 };
 
-typedef struct _Eolian_Object
+struct _Eolian_Object
 {
    const char *file;
    int line;
    int column;
    int refcount;
+   Eolian_Object_Type type;
    Eina_Bool validated;
-} Eolian_Object;
+};
 
 static inline void
 eolian_object_ref(Eolian_Object *obj)

-- 


Reply via email to