eolian: add comments containing original expressions to generated enum fields

This required a new API, eolian_expression_serialize.
This commit is contained in:
Daniel Kolesa 2014-08-13 11:25:04 +01:00
parent 18c2b5082e
commit a5964f0252
6 changed files with 118 additions and 4 deletions

View File

@ -469,11 +469,11 @@ eo_bind_func_generate(const Eolian_Class *class, const Eolian_Function *funcid,
const char *val_str = NULL;
if (default_ret_val)
{
Eina_Value *val = NULL;
Eina_Value val;
Eolian_Expression_Type etp = eolian_expression_eval_type
(default_ret_val, rettypet, &val);
if (etp)
val_str = eolian_expression_value_to_literal(val, etp);
val_str = eolian_expression_value_to_literal(&val, etp);
}
eina_strbuf_append_printf(eo_func_decl, ", %s%s, %s",
ret_const ? "const " : "", rettype,

View File

@ -331,11 +331,11 @@ _eapi_func_generate(const Eolian_Class *class, const Eolian_Function *funcid, Eo
const char *val_str = NULL;
if (default_ret_val)
{
Eina_Value *val = NULL;
Eina_Value val;
Eolian_Expression_Type etp = eolian_expression_eval_type
(default_ret_val, rettypet, &val);
if (etp)
val_str = eolian_expression_value_to_literal(val, etp);
val_str = eolian_expression_value_to_literal(&val, etp);
}
Eina_Bool had_star = !!strchr(rettype, '*');
sprintf (tmpstr, " %s%s%s%s = %s;\n",

View File

@ -138,6 +138,12 @@ _type_generate(const Eolian_Type *tp, Eina_Bool in_typedef)
Eolian_Expression_Type et = eolian_expression_eval(member, EOLIAN_MASK_INT, &v);
const char *lit = eolian_expression_value_to_literal(&v, et);
eina_strbuf_append_printf(buf, " %s = %s", eina_strbuf_string_get(membuf), lit);
const char *exp = eolian_expression_serialize(member);
if (exp && strcmp(lit, exp))
{
eina_strbuf_append_printf(buf, " /* %s */", exp);
eina_stringshare_del(exp);
}
eina_stringshare_del(lit);
eina_value_flush(&v);
}

View File

@ -1301,6 +1301,21 @@ EAPI Eolian_Expression_Type eolian_expression_eval_type(const Eolian_Expression
*/
EAPI Eina_Stringshare *eolian_expression_value_to_literal(const Eina_Value *v, Eolian_Expression_Type etp);
/*
* @brief Serialize an expression.
*
* @param[in] expr the expression.
* @return the serialized expression or NULL.
*
* This serializes the expression into the original form as written in the .eo
* file (but with parens on binary operators explicitly specifying precedence).
* Keep in mind that it cannot be used alone pasted into C code as it doesn't
* resolve namespaces and enum field names.
*
* @ingroup Eolian
*/
EAPI Eina_Stringshare *eolian_expression_serialize(const Eolian_Expression *expr);
/*
* @brief Get a global variable by name. Supports namespaces.
*

View File

@ -661,6 +661,10 @@ database_expr_eval(const Eolian_Expression *expr, Eolian_Expression_Mask mask,
eina_value_set(outval, out.value.b);
break;
case EOLIAN_EXPR_NULL:
/* we need to initialize to prevent crashes */
if (!eina_value_setup(outval, EINA_VALUE_TYPE_UCHAR))
return EOLIAN_EXPR_UNKNOWN;
eina_value_set(outval, 0);
break;
default:
return EOLIAN_EXPR_UNKNOWN;

View File

@ -206,3 +206,92 @@ eolian_expression_value_to_literal(const Eina_Value *v,
return NULL;
}
}
static const char *_binops[] = {
"+", "-", "*", "/", "%",
"==", "!=", ">", "<", ">=", "<=",
"&&", "||",
"&", "|", "^", "<<", ">>"
};
static const char *_unops[] = {
"+", "-", "!", "~"
};
static Eina_Bool
_expr_serialize(const Eolian_Expression *expr, Eina_Strbuf *buf, Eina_Bool outer)
{
switch (expr->type)
{
case EOLIAN_EXPR_UNKNOWN:
return EINA_FALSE;
case EOLIAN_EXPR_INT:
case EOLIAN_EXPR_UINT:
case EOLIAN_EXPR_LONG:
case EOLIAN_EXPR_ULONG:
case EOLIAN_EXPR_LLONG:
case EOLIAN_EXPR_ULLONG:
case EOLIAN_EXPR_FLOAT:
case EOLIAN_EXPR_DOUBLE:
case EOLIAN_EXPR_LDOUBLE:
case EOLIAN_EXPR_STRING:
case EOLIAN_EXPR_CHAR:
case EOLIAN_EXPR_NULL:
case EOLIAN_EXPR_BOOL:
{
Eina_Value v;
Eolian_Expression_Type etp;
if (!(etp = eolian_expression_eval(expr, EOLIAN_MASK_ALL, &v)))
return EINA_FALSE;
const char *x = eolian_expression_value_to_literal(&v, etp);
if (!x)
{
eina_value_flush(&v);
return EINA_FALSE;
}
eina_strbuf_append(buf, x);
eina_stringshare_del(x);
eina_value_flush(&v);
break;
}
case EOLIAN_EXPR_NAME:
case EOLIAN_EXPR_ENUM:
{
if (expr->type == EOLIAN_EXPR_ENUM)
eina_strbuf_append(buf, "enum ");
eina_strbuf_append(buf, expr->value.s);
break;
}
case EOLIAN_EXPR_UNARY:
eina_strbuf_append(buf, _unops[expr->unop]);
_expr_serialize(expr->expr, buf, EINA_FALSE);
break;
case EOLIAN_EXPR_BINARY:
if (!outer)
eina_strbuf_append_char(buf, '(');
_expr_serialize(expr->lhs, buf, EINA_FALSE);
eina_strbuf_append_printf(buf, " %s ", _binops[expr->binop]);
_expr_serialize(expr->rhs, buf, EINA_FALSE);
if (!outer)
eina_strbuf_append_char(buf, ')');
break;
default:
return EINA_FALSE;
}
return EINA_TRUE;
}
EAPI Eina_Stringshare *
eolian_expression_serialize(const Eolian_Expression *expr)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(expr, NULL);
Eina_Strbuf *buf = eina_strbuf_new();
if (!_expr_serialize(expr, buf, EINA_TRUE))
{
eina_strbuf_free(buf);
return NULL;
}
const char *ret = eina_stringshare_add(eina_strbuf_string_get(buf));
eina_strbuf_free(buf);
return ret;
}