eolian: initial API for expression evaluation

This commit also does several side (related) changes. Particularly, it updates
the Eolian C generator to use the new API, it adds missing expr types (null, char)
and masks, updates the API dealing with default return values to use expressions
instead of strings and does several fixes (mainly in lexer) around the place.
It also disallows single quoted strings as those are reserved for characters.
This commit is contained in:
Daniel Kolesa 2014-08-07 15:15:07 +01:00
parent 90e17acd15
commit 8c1b9ed3e2
19 changed files with 422 additions and 105 deletions

View File

@ -30,7 +30,8 @@ lib_eolian_libeolian_la_SOURCES = \
lib/eolian/database_event.c \
lib/eolian/database_event_api.c \
lib/eolian/database_print.c \
lib/eolian/database_expr.c
lib/eolian/database_expr.c \
lib/eolian/database_expr_api.c
lib_eolian_libeolian_la_CPPFLAGS = -I$(top_builddir)/src/lib/efl @EOLIAN_CFLAGS@ \
-DPACKAGE_DATA_DIR=\"$(datadir)/eolian\"

View File

@ -464,20 +464,20 @@ eo_bind_func_generate(const Eolian_Class *class, const Eolian_Function *funcid,
func_env.lower_eo_func);
if (!ret_is_void)
{
const char *default_ret_val =
const Eolian_Expression *default_ret_val =
eolian_function_return_default_value_get(funcid, ftype);
const char *val_str = NULL;
if (default_ret_val)
{
if (!strcmp(default_ret_val, "true"))
default_ret_val = "EINA_TRUE";
else if (!strcmp(default_ret_val, "false"))
default_ret_val = "EINA_FALSE";
else if (!strcmp(default_ret_val, "null"))
default_ret_val = "NULL";
Eina_Value *val = NULL;
Eolian_Expression_Type etp = eolian_expression_eval_type
(default_ret_val, rettypet, &val);
if (etp)
val_str = eolian_expression_value_to_literal(val, etp);
}
eina_strbuf_append_printf(eo_func_decl, ", %s%s, %s",
ret_const ? "const " : "", rettype,
default_ret_val?default_ret_val:"0");
val_str?val_str:"0");
}
if (has_params)

View File

@ -326,21 +326,21 @@ _eapi_func_generate(const Eolian_Class *class, const Eolian_Function *funcid, Eo
{
char tmp_ret_str[0xFF];
sprintf (tmp_ret_str, "%s%s", ret_const?"const ":"", rettype);
const char *default_ret_val =
const Eolian_Expression *default_ret_val =
eolian_function_return_default_value_get(funcid, ftype);
const char *val_str = NULL;
if (default_ret_val)
{
if (!strcmp(default_ret_val, "true"))
default_ret_val = "EINA_TRUE";
else if (!strcmp(default_ret_val, "false"))
default_ret_val = "EINA_FALSE";
else if (!strcmp(default_ret_val, "null"))
default_ret_val = "NULL";
Eina_Value *val = NULL;
Eolian_Expression_Type etp = eolian_expression_eval_type
(default_ret_val, rettypet, &val);
if (etp)
val_str = eolian_expression_value_to_literal(val, etp);
}
Eina_Bool had_star = !!strchr(rettype, '*');
sprintf (tmpstr, " %s%s%s%s = %s;\n",
ret_const?"const ":"", rettype, had_star?"":" ", retname,
default_ret_val?default_ret_val:"0");
val_str?val_str:"0");
eina_strbuf_replace_all(fbody, "@#ret_type", tmp_ret_str);
eina_strbuf_replace_all(fbody, "@#ret_init_val", tmpstr);

View File

@ -145,6 +145,8 @@ typedef enum
EOLIAN_EXPR_DOUBLE,
EOLIAN_EXPR_LDOUBLE,
EOLIAN_EXPR_STRING,
EOLIAN_EXPR_CHAR,
EOLIAN_EXPR_NULL,
EOLIAN_EXPR_BOOL,
EOLIAN_EXPR_NAME,
EOLIAN_EXPR_UNARY,
@ -159,9 +161,12 @@ typedef enum
EOLIAN_MASK_FLOAT = 1 << 2,
EOLIAN_MASK_BOOL = 1 << 3,
EOLIAN_MASK_STRING = 1 << 4,
EOLIAN_MASK_CHAR = 1 << 5,
EOLIAN_MASK_NULL = 1 << 6,
EOLIAN_MASK_NUMBER = EOLIAN_MASK_INT | EOLIAN_MASK_FLOAT,
EOLIAN_MASK_ALL = EOLIAN_MASK_NUMBER | EOLIAN_MASK_BOOL
| EOLIAN_MASK_STRING
| EOLIAN_MASK_STRING | EOLIAN_MASK_CHAR
| EOLIAN_MASK_NULL
} Eolian_Expression_Mask;
/*
@ -690,7 +695,7 @@ EAPI const Eolian_Type *eolian_function_return_type_get(const Eolian_Function *f
*
* @ingroup Eolian
*/
EAPI Eina_Stringshare *
EAPI const Eolian_Expression *
eolian_function_return_default_value_get(const Eolian_Function *foo_id, Eolian_Function_Type ftype);
/*
@ -1074,6 +1079,49 @@ EAPI Eina_Stringshare *eolian_type_full_name_get(const Eolian_Type *tp);
*/
EAPI Eina_Iterator *eolian_type_namespaces_get(const Eolian_Type *tp);
/*
* @brief Evaluate an Eolian expression.
*
* @param[in] expr the expression.
* @param[in] mask the mask of allowed values (can combine with bitwise OR).
* @param[out] val the resulting value of the expression.
* @return the type of the resulting value or EOLIAN_EXPR_UNKNOWN on error.
*
* Represents value types from Eolian_Expression_Type. Booleans
* are represented as unsigned char, strings as a stringshare.
* The Eina_Value pointer must be freed manually.
*
* @ingroup Eolian
*/
EAPI Eolian_Expression_Type eolian_expression_eval(const Eolian_Expression *expr, Eolian_Expression_Mask m, Eina_Value **val);
/*
* @brief Evaluate an Eolian expression given a type instead of a mask.
*
* @param[in] expr the expression.
* @param[in] type the type the expression is assigned to.
* @param[out] val the resulting value of the expression.
* @return the type of the resulting value or EOLIAN_EXPR_UNKNOWN on error.
*
* The mask is automatically decided from the given type, allowing only values
* that can be assigned to that type.
*
* @ingroup Eolian
*/
EAPI Eolian_Expression_Type eolian_expression_eval_type(const Eolian_Expression *expr, const Eolian_Type *type, Eina_Value **val);
/*
* @brief Convert the result of expression evaluation to string.
*
* @param[in] v the value.
* @param[in] etp the eolian type of the value.
* @return a stringshare containing the literal (quoted and escaped as needed)
* or NULL.
*
* @ingroup Eolian
*/
EAPI Eina_Stringshare *eolian_expression_value_to_literal(const Eina_Value *v, Eolian_Expression_Type etp);
#endif
#ifdef __cplusplus

View File

@ -10,6 +10,8 @@ database_class_del(Eolian_Class *cl)
Eolian_Event *ev;
const char *sp;
if (cl->base.file) eina_stringshare_del(cl->base.file);
EINA_LIST_FREE(inherits, inherit_name)
eina_stringshare_del(inherit_name);

View File

@ -4,7 +4,7 @@
#include "eolian_database.h"
static Eina_Bool
node_error(Eolian_Object *obj, const char *msg)
node_error(const Eolian_Object *obj, const char *msg)
{
eina_log_print(_eolian_log_dom, EINA_LOG_LEVEL_ERR, obj->file, "",
obj->line, "%s at column %d", msg, obj->column);
@ -37,13 +37,17 @@ mask_to_str(int mask, char *buf)
APPEND_TP("boolean")
if (mask & EOLIAN_MASK_STRING)
APPEND_TP("string")
if (mask & EOLIAN_MASK_CHAR)
APPEND_TP("char")
if (mask & EOLIAN_MASK_NULL)
APPEND_TP("null")
*buf = '\0';
#undef APPEND_TP
}
static Eina_Bool
expr_type_error(Eolian_Expression *expr, int type, int mask)
expr_type_error(const Eolian_Expression *expr, int type, int mask)
{
char buf[512];
char ebuf[256];
@ -52,11 +56,11 @@ expr_type_error(Eolian_Expression *expr, int type, int mask)
mask_to_str(type, tbuf);
snprintf(buf, sizeof(buf), "invalid type (given %s, expected %s)",
tbuf, ebuf);
return node_error((Eolian_Object*)expr, buf);
return node_error((const Eolian_Object*)expr, buf);
}
static int
expr_type_to_mask(Eolian_Expression *expr)
expr_type_to_mask(const Eolian_Expression *expr)
{
assert(expr->type);
switch (expr->type)
@ -77,6 +81,10 @@ expr_type_to_mask(Eolian_Expression *expr)
return EOLIAN_MASK_BOOL;
case EOLIAN_EXPR_STRING:
return EOLIAN_MASK_STRING;
case EOLIAN_EXPR_NULL:
return EOLIAN_MASK_NULL;
case EOLIAN_EXPR_CHAR:
return EOLIAN_MASK_CHAR;
default:
return 0;
}
@ -84,7 +92,8 @@ expr_type_to_mask(Eolian_Expression *expr)
}
static Eina_Bool
expr_type_mismatch_error(Eolian_Expression *lhs, Eolian_Expression *rhs)
expr_type_mismatch_error(const Eolian_Expression *lhs,
const Eolian_Expression *rhs)
{
char buf[512];
char tbuf[256];
@ -92,7 +101,7 @@ expr_type_mismatch_error(Eolian_Expression *lhs, Eolian_Expression *rhs)
mask_to_str(expr_type_to_mask(lhs), tbuf);
mask_to_str(expr_type_to_mask(rhs), ebuf);
snprintf(buf, sizeof(buf), "mismatched types (%s vs %s)", tbuf, ebuf);
return node_error((Eolian_Object*)rhs, buf);
return node_error((const Eolian_Object*)rhs, buf);
}
static Eina_Bool
@ -163,10 +172,10 @@ promote(Eolian_Expression *a, Eolian_Expression *b)
#undef CONVERT_CASE
}
static Eina_Bool eval_exp(Eolian_Expression *expr, Eolian_Expression_Mask mask, Eolian_Expression *out);
static Eina_Bool eval_exp(const Eolian_Expression *expr, Eolian_Expression_Mask mask, Eolian_Expression *out);
static Eina_Bool
eval_unary(Eolian_Expression *expr, Eolian_Expression_Mask mask,
eval_unary(const Eolian_Expression *expr, Eolian_Expression_Mask mask,
Eolian_Expression *out)
{
switch (expr->unop)
@ -240,13 +249,17 @@ eval_unary(Eolian_Expression *expr, Eolian_Expression_Mask mask,
*out = exp;
return EINA_TRUE;
}
default:
assert(EINA_FALSE);
return EINA_FALSE;
}
return EINA_TRUE;
}
static Eina_Bool
eval_promote_num(Eolian_Expression *expr, Eolian_Expression *lhs,
eval_promote_num(const Eolian_Expression *expr, Eolian_Expression *lhs,
Eolian_Expression *rhs, int mask, int emask)
{
/* make sure the output can be a number */
@ -268,7 +281,7 @@ eval_promote_num(Eolian_Expression *expr, Eolian_Expression *lhs,
}
static Eina_Bool
eval_binary(Eolian_Expression *expr, Eolian_Expression_Mask mask,
eval_binary(const Eolian_Expression *expr, Eolian_Expression_Mask mask,
Eolian_Expression *out)
{
#define APPLY_CASE(id, expr, lhs, rhs, fnm, op) \
@ -348,7 +361,6 @@ eval_binary(Eolian_Expression *expr, Eolian_Expression_Mask mask,
else if (rhs.type >= EOLIAN_EXPR_STRING && rhs.type != lhs.type) \
return expr_type_mismatch_error(&lhs, &rhs); \
out->type = EOLIAN_EXPR_BOOL; \
printf("%d %lld %lld\n", lhs.value.ull == rhs.value.ull, lhs.value.ull, rhs.value.ull); \
out->value.b = lhs.value.ull op rhs.value.ull; \
return EINA_TRUE; \
}
@ -377,6 +389,10 @@ eval_binary(Eolian_Expression *expr, Eolian_Expression_Mask mask,
CASE_ARITH_INT(BXOR, ^)
CASE_ARITH_INT(LSH , <<)
CASE_ARITH_INT(RSH , >>)
default:
assert(EINA_FALSE);
return EINA_FALSE;
}
return EINA_TRUE;
@ -391,7 +407,8 @@ eval_binary(Eolian_Expression *expr, Eolian_Expression_Mask mask,
}
static Eina_Bool
eval_exp(Eolian_Expression *expr, Eolian_Expression_Mask mask, Eolian_Expression *out)
eval_exp(const Eolian_Expression *expr, Eolian_Expression_Mask mask,
Eolian_Expression *out)
{
switch (expr->type)
{
@ -429,6 +446,20 @@ eval_exp(Eolian_Expression *expr, Eolian_Expression_Mask mask, Eolian_Expression
*out = *expr;
return EINA_TRUE;
}
case EOLIAN_EXPR_NULL:
{
if (!(mask & EOLIAN_MASK_NULL))
return expr_type_error(expr, EOLIAN_MASK_NULL, mask);
*out = *expr;
return EINA_TRUE;
}
case EOLIAN_EXPR_CHAR:
{
if (!(mask & EOLIAN_MASK_CHAR))
return expr_type_error(expr, EOLIAN_MASK_CHAR, mask);
*out = *expr;
return EINA_TRUE;
}
case EOLIAN_EXPR_BOOL:
{
if (!(mask & EOLIAN_MASK_BOOL))
@ -448,61 +479,90 @@ eval_exp(Eolian_Expression *expr, Eolian_Expression_Mask mask, Eolian_Expression
return EINA_TRUE;
}
Eina_Value *
database_expr_eval(Eolian_Expression *expr, Eolian_Expression_Mask mask)
Eolian_Expression_Type
database_expr_eval(const Eolian_Expression *expr, Eolian_Expression_Mask mask,
Eina_Value **outval)
{
Eina_Value *ret = NULL;
Eolian_Expression out;
if (!mask)
return EOLIAN_EXPR_UNKNOWN;
if (!eval_exp(expr, mask, &out))
return NULL;
return EOLIAN_EXPR_UNKNOWN;
if (!outval)
return out.type;
switch (out.type)
{
case EOLIAN_EXPR_INT:
ret = eina_value_new(EINA_VALUE_TYPE_INT);
eina_value_set(ret, out.value.i);
*outval = eina_value_new(EINA_VALUE_TYPE_INT);
eina_value_set(*outval, out.value.i);
break;
case EOLIAN_EXPR_UINT:
ret = eina_value_new(EINA_VALUE_TYPE_UINT);
eina_value_set(ret, out.value.u);
*outval = eina_value_new(EINA_VALUE_TYPE_UINT);
eina_value_set(*outval, out.value.u);
break;
case EOLIAN_EXPR_LONG:
ret = eina_value_new(EINA_VALUE_TYPE_LONG);
eina_value_set(ret, out.value.l);
*outval = eina_value_new(EINA_VALUE_TYPE_LONG);
eina_value_set(*outval, out.value.l);
break;
case EOLIAN_EXPR_ULONG:
ret = eina_value_new(EINA_VALUE_TYPE_ULONG);
eina_value_set(ret, out.value.ul);
*outval = eina_value_new(EINA_VALUE_TYPE_ULONG);
eina_value_set(*outval, out.value.ul);
break;
case EOLIAN_EXPR_LLONG:
ret = eina_value_new(EINA_VALUE_TYPE_INT64);
eina_value_set(ret, out.value.ll);
*outval = eina_value_new(EINA_VALUE_TYPE_INT64);
eina_value_set(*outval, out.value.ll);
break;
case EOLIAN_EXPR_ULLONG:
ret = eina_value_new(EINA_VALUE_TYPE_UINT64);
eina_value_set(ret, out.value.ull);
*outval = eina_value_new(EINA_VALUE_TYPE_UINT64);
eina_value_set(*outval, out.value.ull);
break;
case EOLIAN_EXPR_FLOAT:
ret = eina_value_new(EINA_VALUE_TYPE_FLOAT);
eina_value_set(ret, out.value.f);
*outval = eina_value_new(EINA_VALUE_TYPE_FLOAT);
eina_value_set(*outval, out.value.f);
break;
case EOLIAN_EXPR_DOUBLE:
ret = eina_value_new(EINA_VALUE_TYPE_DOUBLE);
eina_value_set(ret, out.value.d);
*outval = eina_value_new(EINA_VALUE_TYPE_DOUBLE);
eina_value_set(*outval, out.value.d);
break;
case EOLIAN_EXPR_LDOUBLE:
ret = eina_value_new(EINA_VALUE_TYPE_DOUBLE);
eina_value_set(ret, (double)out.value.ld);
*outval = eina_value_new(EINA_VALUE_TYPE_DOUBLE);
eina_value_set(*outval, (double)out.value.ld);
break;
case EOLIAN_EXPR_STRING:
ret = eina_value_new(EINA_VALUE_TYPE_STRINGSHARE);
eina_value_set(ret, eina_stringshare_ref(out.value.s));
*outval = eina_value_new(EINA_VALUE_TYPE_STRINGSHARE);
eina_value_set(*outval, eina_stringshare_ref(out.value.s));
break;
case EOLIAN_EXPR_CHAR:
*outval = eina_value_new(EINA_VALUE_TYPE_CHAR);
eina_value_set(*outval, out.value.c);
break;
case EOLIAN_EXPR_BOOL:
ret = eina_value_new(EINA_VALUE_TYPE_UCHAR);
eina_value_set(ret, out.value.b);
*outval = eina_value_new(EINA_VALUE_TYPE_UCHAR);
eina_value_set(*outval, out.value.b);
break;
default:
return NULL;
return EOLIAN_EXPR_UNKNOWN;
}
return ret;
return out.type;
}
void
database_expr_del(Eolian_Expression *expr)
{
if (!expr) return;
if (expr->base.file) eina_stringshare_del(expr->base.file);
if (expr->type == EOLIAN_EXPR_BINARY)
{
database_expr_del(expr->lhs);
database_expr_del(expr->rhs);
}
else if (expr->type == EOLIAN_EXPR_UNARY)
{
database_expr_del(expr->expr);
}
else if (expr->type == EOLIAN_EXPR_STRING)
{
eina_stringshare_del(expr->value.s);
}
free(expr);
}

View File

@ -0,0 +1,140 @@
#include <Eina.h>
#include "eo_lexer.h"
EAPI Eolian_Expression_Type
eolian_expression_eval(const Eolian_Expression *expr, Eolian_Expression_Mask m,
Eina_Value **val)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(expr, EOLIAN_EXPR_UNKNOWN);
return database_expr_eval(expr, m, val);
}
static Eolian_Expression_Type
_eval_type(const Eolian_Expression *expr, const Eolian_Type *type,
Eina_Value **val)
{
if (!type)
return EOLIAN_EXPR_UNKNOWN;
switch (type->type)
{
case EOLIAN_TYPE_ALIAS:
return _eval_type(expr, eolian_type_base_type_get(type), val);
case EOLIAN_TYPE_POINTER:
{
int mask = EOLIAN_MASK_NULL;
const Eolian_Type *base = eolian_type_base_type_get(type);
int kw = base->name ? eo_lexer_keyword_str_to_id(base->name) : 0;
if (kw == KW_char)
mask |= EOLIAN_MASK_STRING;
return database_expr_eval(expr, mask, val);
}
case EOLIAN_TYPE_CLASS:
return database_expr_eval(expr, EOLIAN_MASK_NULL, val);
case EOLIAN_TYPE_REGULAR:
{
int kw = eo_lexer_keyword_str_to_id(type->name);
if (!kw || kw < KW_byte || kw >= KW_void)
return EOLIAN_EXPR_UNKNOWN;
switch (kw)
{
case KW_byte:
case KW_short:
case KW_int:
case KW_long:
case KW_llong:
case KW_int8:
case KW_int16:
case KW_int32:
case KW_int64:
case KW_int128:
case KW_ssize:
case KW_intptr:
case KW_ptrdiff:
return database_expr_eval(expr, EOLIAN_MASK_SINT, val);
case KW_ubyte:
case KW_ushort:
case KW_uint:
case KW_ulong:
case KW_ullong:
case KW_uint8:
case KW_uint16:
case KW_uint32:
case KW_uint64:
case KW_uint128:
case KW_size:
case KW_uintptr:
case KW_time:
return database_expr_eval(expr, EOLIAN_MASK_UINT, val);
case KW_float:
case KW_double:
case KW_ldouble:
return database_expr_eval(expr, EOLIAN_MASK_FLOAT, val);
case KW_bool:
return database_expr_eval(expr, EOLIAN_MASK_BOOL, val);
case KW_char:
return database_expr_eval(expr, EOLIAN_MASK_CHAR, val);
default:
return EOLIAN_EXPR_UNKNOWN;
}
}
default:
return EOLIAN_EXPR_UNKNOWN;
}
}
EAPI Eolian_Expression_Type
eolian_expression_eval_type(const Eolian_Expression *expr,
const Eolian_Type *type,
Eina_Value **val)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(expr, EOLIAN_EXPR_UNKNOWN);
return _eval_type(expr, type, val);
}
EAPI Eina_Stringshare *
eolian_expression_value_to_literal(const Eina_Value *v,
Eolian_Expression_Type etp)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(v, NULL);
switch (etp)
{
case EOLIAN_EXPR_BOOL:
{
unsigned char b;
eina_value_get(v, &b);
return eina_stringshare_add(b ? "EINA_TRUE" : "EINA_FALSE");
}
case EOLIAN_EXPR_NULL:
return eina_stringshare_add("NULL");
case EOLIAN_EXPR_CHAR:
{
char c;
eina_value_get(v, &c);
return eina_stringshare_printf("'%c'", c);
}
case EOLIAN_EXPR_STRING:
{
char *str = eina_value_to_string(v);
const char *ret = eina_stringshare_printf("\"%s\"", str);
free(str);
return ret;
}
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:
{
char *str = eina_value_to_string(v);
const char *ret = eina_stringshare_add(str);
free(str);
return ret;
}
default:
return NULL;
}
}

View File

@ -26,6 +26,7 @@ _db_fill_ctor(Eolian_Class *cl, Eo_Method_Def *meth)
}
foo_id->base = meth->base;
meth->base.file = NULL;
return EINA_TRUE;
}
@ -54,6 +55,7 @@ _db_fill_key(Eolian_Function *foo_id, Eo_Param_Def *param)
param->type = NULL;
p->base = param->base;
param->base.file = NULL;
return EINA_TRUE;
}
@ -81,6 +83,7 @@ _db_fill_value(Eolian_Function *foo_id, Eo_Param_Def *param)
param->type = NULL;
p->base = param->base;
param->base.file = NULL;
return EINA_TRUE;
}
@ -109,6 +112,7 @@ _db_fill_param(Eolian_Function *foo_id, Eo_Param_Def *param)
param->type = NULL;
p->base = param->base;
param->base.file = NULL;
return EINA_TRUE;
}
@ -148,6 +152,7 @@ _db_fill_accessor(Eolian_Function *foo_id, Eo_Class_Def *kls,
database_function_return_default_val_set(foo_id, ftype,
accessor->ret->default_ret_val);
accessor->ret->type = NULL;
accessor->ret->default_ret_val = NULL;
}
if (accessor->legacy)
@ -190,6 +195,8 @@ _db_fill_accessor(Eolian_Function *foo_id, Eo_Class_Def *kls,
else
foo_id->set_base = accessor->base;
accessor->base.file = NULL;
return EINA_TRUE;
}
@ -226,6 +233,7 @@ _db_fill_property(Eolian_Class *cl, Eo_Class_Def *kls, Eo_Property_Def *prop)
if (kls->type == EOLIAN_CLASS_INTERFACE)
database_function_set_as_virtual_pure(foo_id, EOLIAN_UNRESOLVED);
foo_id->base = prop->base;
prop->base.file = NULL;
}
database_class_function_add(cl, foo_id);
@ -269,6 +277,7 @@ _db_fill_method(Eolian_Class *cl, Eo_Class_Def *kls, Eo_Method_Def *meth)
database_function_return_default_val_set(foo_id, EOLIAN_METHOD,
meth->ret->default_ret_val);
meth->ret->type = NULL;
meth->ret->default_ret_val = NULL;
}
database_function_description_set(foo_id, EOLIAN_COMMENT, meth->comment);
@ -282,6 +291,7 @@ _db_fill_method(Eolian_Class *cl, Eo_Class_Def *kls, Eo_Method_Def *meth)
database_function_set_as_virtual_pure(foo_id, EOLIAN_METHOD);
foo_id->base = meth->base;
meth->base.file = NULL;
return EINA_TRUE;
}
@ -426,6 +436,7 @@ _db_fill_class(Eo_Class_Def *kls)
if (!_db_fill_events (cl, kls)) return EINA_FALSE;
cl->base = kls->base;
kls->base.file = NULL;
return EINA_TRUE;
}

View File

@ -6,12 +6,16 @@ database_function_del(Eolian_Function *fid)
{
Eolian_Function_Parameter *param;
if (!fid) return;
if (fid->base.file) eina_stringshare_del(fid->base.file);
eina_stringshare_del(fid->name);
eina_hash_free(fid->data);
EINA_LIST_FREE(fid->keys, param) database_parameter_del(param);
EINA_LIST_FREE(fid->params, param) database_parameter_del(param);
database_type_del(fid->get_ret_type);
database_type_del(fid->set_ret_type);
database_expr_del(fid->get_ret_val);
database_expr_del(fid->set_ret_val);
free(fid);
}
@ -124,17 +128,14 @@ void database_function_return_type_set(Eolian_Function *fid, Eolian_Function_Typ
}
}
void database_function_return_default_val_set(Eolian_Function *fid, Eolian_Function_Type ftype, const char *ret_default_value)
void database_function_return_default_val_set(Eolian_Function *fid, Eolian_Function_Type ftype, Eolian_Expression *ret_default_value)
{
const char *key = NULL;
switch (ftype)
{
case EOLIAN_PROP_SET: key = PROP_SET_RETURN_DEFAULT_VAL; break;
case EOLIAN_PROP_GET: key = PROP_GET_RETURN_DEFAULT_VAL; break;
case EOLIAN_METHOD: key = METHOD_RETURN_DEFAULT_VAL; break;
case EOLIAN_PROP_SET: fid->set_ret_val = ret_default_value; break;
case EOLIAN_UNRESOLVED: case EOLIAN_METHOD: case EOLIAN_PROP_GET: fid->get_ret_val = ret_default_value; break;
default: return;
}
database_function_data_set(fid, key, ret_default_value);
}
void database_function_return_comment_set(Eolian_Function *fid, Eolian_Function_Type ftype, const char *ret_comment)

View File

@ -126,18 +126,15 @@ eolian_function_return_type_get(const Eolian_Function *fid, Eolian_Function_Type
}
}
EAPI Eina_Stringshare *
EAPI const Eolian_Expression *
eolian_function_return_default_value_get(const Eolian_Function *fid, Eolian_Function_Type ftype)
{
const char *key = NULL;
switch (ftype)
{
case EOLIAN_PROP_SET: key = PROP_SET_RETURN_DEFAULT_VAL; break;
case EOLIAN_PROP_GET: key = PROP_GET_RETURN_DEFAULT_VAL; break;
case EOLIAN_UNRESOLVED: case EOLIAN_METHOD: key = METHOD_RETURN_DEFAULT_VAL; break;
case EOLIAN_PROP_SET: return fid->set_ret_val;
case EOLIAN_UNRESOLVED: case EOLIAN_METHOD: case EOLIAN_PROP_GET: return fid->get_ret_val;
default: return NULL;
}
return eolian_function_data_get(fid, key);
}
EAPI Eina_Stringshare *

View File

@ -15,6 +15,7 @@ database_parameter_add(Eolian_Type *type, const char *name, const char *descript
void
database_parameter_del(Eolian_Function_Parameter *pdesc)
{
if (pdesc->base.file) eina_stringshare_del(pdesc->base.file);
eina_stringshare_del(pdesc->name);
database_type_del(pdesc->type);

View File

@ -5,6 +5,7 @@ void
database_implement_del(Eolian_Implement *impl)
{
if (!impl) return;
if (impl->base.file) eina_stringshare_del(impl->base.file);
if (impl->full_name) eina_stringshare_del(impl->full_name);
free(impl);
}

View File

@ -8,6 +8,7 @@ database_type_del(Eolian_Type *tp)
if (!tp) return;
const char *sp;
Eolian_Type *stp;
if (tp->base.file) eina_stringshare_del(tp->base.file);
if (tp->subtypes) EINA_LIST_FREE(tp->subtypes, stp)
database_type_del(stp);
if (tp->base_type)

View File

@ -8,13 +8,14 @@ eo_definitions_ret_free(Eo_Ret_Def *ret)
{
if (ret->type) database_type_del(ret->type);
if (ret->comment) eina_stringshare_del(ret->comment);
if (ret->default_ret_val) eina_stringshare_del(ret->default_ret_val);
database_expr_del(ret->default_ret_val);
free(ret);
}
static void
eo_definitions_param_free(Eo_Param_Def *param)
{
if (param->base.file) eina_stringshare_del(param->base.file);
if (param->type) database_type_del(param->type);
if (param->name) eina_stringshare_del(param->name);
if (param->comment) eina_stringshare_del(param->comment);
@ -31,6 +32,9 @@ eo_definitions_accessor_param_free(Eo_Accessor_Param *param)
static void
eo_definitions_accessor_free(Eo_Accessor_Def *accessor)
{
if (accessor->base.file)
eina_stringshare_del(accessor->base.file);
if (accessor->comment)
eina_stringshare_del(accessor->comment);
@ -53,6 +57,9 @@ eo_definitions_property_def_free(Eo_Property_Def *prop)
Eo_Param_Def *param;
Eo_Accessor_Def *accessor;
if (prop->base.file)
eina_stringshare_del(prop->base.file);
if (prop->name)
eina_stringshare_del(prop->name);
@ -73,6 +80,9 @@ eo_definitions_method_def_free(Eo_Method_Def *meth)
{
Eo_Param_Def *param;
if (meth->base.file)
eina_stringshare_del(meth->base.file);
if (meth->ret)
eo_definitions_ret_free(meth->ret);
@ -98,6 +108,9 @@ eo_definitions_class_def_free(Eo_Class_Def *kls)
Eolian_Event *sgn;
Eolian_Implement *impl;
if (kls->base.file)
eina_stringshare_del(kls->base.file);
if (kls->name)
eina_stringshare_del(kls->name);
if (kls->file)

View File

@ -12,7 +12,7 @@ typedef struct _Eo_Ret_Def
{
Eolian_Type *type;
Eina_Stringshare *comment;
Eina_Stringshare *default_ret_val;
Eolian_Expression *default_ret_val;
Eina_Bool warn_unused:1;
} Eo_Ret_Def;

View File

@ -46,7 +46,7 @@ static const char * const tokens[] =
{
"==", "!=", ">=", "<=", "&&", "||", "<<", ">>",
"<comment>", "<string>", "<number>", "<value>",
"<comment>", "<string>", "<char>", "<number>", "<value>",
KEYWORDS
};
@ -106,7 +106,7 @@ init_hash(void)
unsigned int i, u;
if (keyword_map) return;
keyword_map = eina_hash_string_superfast_new(NULL);
for (i = u = 12; i < (sizeof(tokens) / sizeof(const char*)); ++i)
for (i = u = 13; i < (sizeof(tokens) / sizeof(const char*)); ++i)
{
eina_hash_add(keyword_map, tokens[i], (void*)(size_t)(i - u + 1));
}
@ -252,10 +252,10 @@ read_dec_esc(Eo_Lexer *ls)
static void
read_string(Eo_Lexer *ls, Eo_Token *tok)
{
int del = ls->current;
eina_strbuf_reset(ls->buff);
eina_strbuf_append_char(ls->buff, del);
while (ls->current != del) switch (ls->current)
eina_strbuf_append_char(ls->buff, '"');
next_char(ls);
while (ls->current != '"') switch (ls->current)
{
case '\0':
eo_lexer_lex_error(ls, "unfinished string", -1);
@ -282,7 +282,7 @@ read_string(Eo_Lexer *ls, Eo_Token *tok)
next_line(ls);
eina_strbuf_append_char(ls->buff, '\n');
goto skip;
case '\\': case '"': case '\'':
case '\\': case '"':
eina_strbuf_append_char(ls->buff, ls->current);
goto skip;
case '\0':
@ -358,7 +358,7 @@ write_val(Eo_Lexer *ls, Eo_Token *tok, Eina_Bool is_float)
{
const char *str = eina_strbuf_string_get(ls->buff);
int type = get_type(ls, is_float);
char *end;
char *end = NULL;
if (is_float)
{
if (type == NUM_FLOAT)
@ -378,7 +378,7 @@ write_val(Eo_Lexer *ls, Eo_Token *tok, Eina_Bool is_float)
else if (type == NUM_LLONG || type == NUM_ULLONG)
tok->value.ull = strtoull(str, &end, 0);
}
if (end)
if (end && end[0])
eo_lexer_lex_error(ls, "malformed number", TOK_NUMBER);
tok->kw = type;
}
@ -439,7 +439,7 @@ read_number(Eo_Lexer *ls, Eo_Token *tok)
return;
}
}
while (isdigit(ls->current || ls->current == '.'))
while (isdigit(ls->current) || ls->current == '.')
{
eina_strbuf_append_char(ls->buff, ls->current);
if (ls->current == '.') is_float = EINA_TRUE;
@ -530,9 +530,17 @@ lex(Eo_Lexer *ls, Eo_Token *tok)
if (ls->current != '|') return '|';
next_char(ls);
return TOK_OR;
case '"': case '\'':
case '"':
read_string(ls, tok);
return TOK_STRING;
case '\'':
next_char(ls);
tok->value.c = ls->current;
next_char(ls);
if (ls->current != '\'')
eo_lexer_lex_error(ls, "unfinished character", TOK_CHAR);
next_char(ls);
return TOK_CHAR;
case '.':
next_char(ls);
if (!isdigit(ls->current)) return '.';
@ -762,7 +770,7 @@ eo_lexer_token_to_str(int token, char *buf)
const char *
eo_lexer_keyword_str_get(int kw)
{
return tokens[kw + 11];
return tokens[kw + 12];
}
Eina_Bool
@ -771,6 +779,12 @@ eo_lexer_is_type_keyword(int kw)
return (kw >= KW_byte && kw <= KW_void);
}
int
eo_lexer_keyword_str_to_id(const char *kw)
{
return (int)(uintptr_t)eina_hash_find(keyword_map, kw);
}
const char *
eo_lexer_get_c_type(int kw)
{

View File

@ -16,7 +16,7 @@ enum Tokens
TOK_EQ = START_CUSTOM, TOK_NQ, TOK_GE, TOK_LE,
TOK_AND, TOK_OR, TOK_LSH, TOK_RSH,
TOK_COMMENT, TOK_STRING, TOK_NUMBER, TOK_VALUE
TOK_COMMENT, TOK_STRING, TOK_CHAR, TOK_NUMBER, TOK_VALUE
};
/* all keywords in eolian, they can still be used as names (they're TOK_VALUE)
@ -179,6 +179,8 @@ void eo_lexer_token_to_str (int token, char *buf);
const char *eo_lexer_keyword_str_get(int kw);
/* checks if the given keyword is a builtin type */
Eina_Bool eo_lexer_is_type_keyword(int kw);
/* gets a keyword id from the keyword string */
int eo_lexer_keyword_str_to_id(const char *kw);
/* gets the C type name for a builtin type name - e.g. uchar -> unsigned char */
const char *eo_lexer_get_c_type (int kw);
/* save, restore and clear context (line, column, line string) */

View File

@ -364,6 +364,18 @@ parse_expr_simple(Eo_Lexer *ls)
eo_lexer_get(ls);
break;
}
case TOK_CHAR:
{
int line = ls->line_number, col = ls->column;
expr = push_expr(ls);
expr->base.file = get_filename(ls);
expr->base.line = line;
expr->base.column = col;
expr->type = EOLIAN_EXPR_CHAR;
expr->value.c = ls->t.value.c;
eo_lexer_get(ls);
break;
}
case TOK_VALUE:
{
int line = ls->line_number, col = ls->column;
@ -375,9 +387,16 @@ parse_expr_simple(Eo_Lexer *ls)
expr = push_expr(ls);
expr->type = EOLIAN_EXPR_BOOL;
expr->value.b = (ls->t.kw == KW_true);
eo_lexer_get(ls);
eo_lexer_get(ls);
break;
}
}
case KW_null:
{
expr = push_expr(ls);
expr->type = EOLIAN_EXPR_NULL;
eo_lexer_get(ls);
break;
}
default:
{
expr = push_expr(ls);
@ -390,17 +409,19 @@ parse_expr_simple(Eo_Lexer *ls)
expr->base.file = get_filename(ls);
expr->base.line = line;
expr->base.column = col;
break;
}
case '(':
{
int line = ls->line_number, col = ls->column;
eo_lexer_get(ls);
expr = parse_expr(ls);
check_match(ls, ')', '(', line, col);
}
default:
eo_lexer_syntax_error(ls, "unexpected symbol");
break;
case '(':
{
int line = ls->line_number, col = ls->column;
eo_lexer_get(ls);
expr = parse_expr(ls);
check_match(ls, ')', '(', line, col);
}
default:
expr = NULL; /* shut up compiler */
eo_lexer_syntax_error(ls, "unexpected symbol");
break;
}
return expr;
@ -508,6 +529,7 @@ parse_function_type(Eo_Lexer *ls)
static void
_struct_field_free(Eolian_Struct_Field *def)
{
if (def->base.file) eina_stringshare_del(def->base.file);
database_type_del(def->type);
if (def->comment) eina_stringshare_del(def->comment);
free(def);
@ -807,9 +829,8 @@ parse_return(Eo_Lexer *ls, Eina_Bool allow_void)
if (ls->t.token == '(')
{
int line = ls->line_number, col = ls->column;
eo_lexer_get_balanced(ls, '(', ')');
ret->default_ret_val = eina_stringshare_ref(ls->t.value.s);
eo_lexer_get(ls);
ret->default_ret_val = parse_expr(ls);
check_match(ls, ')', '(', line, col);
}
if (ls->t.kw == KW_at_warn_unused)

View File

@ -31,10 +31,6 @@ extern Eina_Prefix *_eolian_prefix;
#endif
#define DBG(...) EINA_LOG_DOM_DBG(_eolian_log_dom, __VA_ARGS__)
#define PROP_GET_RETURN_DEFAULT_VAL "property_get_return_default_val"
#define PROP_SET_RETURN_DEFAULT_VAL "property_set_return_default_val"
#define METHOD_RETURN_DEFAULT_VAL "method_return_default_val"
#define EOLIAN_METHOD_RETURN_COMMENT "method_return_comment"
#define EOLIAN_PROP_GET_RETURN_COMMENT "property_get_return_comment"
#define EOLIAN_PROP_SET_RETURN_COMMENT "property_set_return_comment"
@ -88,6 +84,8 @@ struct _Eolian_Function
Eolian_Function_Scope scope;
Eolian_Type *get_ret_type;
Eolian_Type *set_ret_type;
Eolian_Expression *get_ret_val;
Eolian_Expression *set_ret_val;
Eina_Hash *data;
Eina_Bool obj_is_const :1; /* True if the object has to be const. Useful for a few methods. */
Eina_Bool get_virtual_pure :1;
@ -159,6 +157,7 @@ typedef struct _Eolian_Struct_Field
typedef union
{
char c;
Eina_Bool b;
const char *s;
signed int i;
@ -174,6 +173,8 @@ typedef union
typedef enum
{
EOLIAN_BINOP_INVALID = -1,
EOLIAN_BINOP_ADD, /* + int, float */
EOLIAN_BINOP_SUB, /* - int, float */
EOLIAN_BINOP_MUL, /* * int, float */
@ -199,6 +200,8 @@ typedef enum
typedef enum
{
EOLIAN_UNOP_INVALID = -1,
EOLIAN_UNOP_UNM, /* - sint */
EOLIAN_UNOP_UNP, /* + sint */
@ -242,7 +245,8 @@ void database_type_to_str(const Eolian_Type *tp, Eina_Strbuf *buf, const char *n
/* expressions */
Eina_Value *database_expr_eval(Eolian_Expression *expr, Eolian_Expression_Mask mask);
Eolian_Expression_Type database_expr_eval(const Eolian_Expression *expr, Eolian_Expression_Mask mask, Eina_Value **out);
void database_expr_del(Eolian_Expression *expr);
/* classes */
@ -277,7 +281,7 @@ void database_function_data_set(Eolian_Function *function_id, const char *key, c
void database_function_return_type_set(Eolian_Function *foo_id, Eolian_Function_Type ftype, Eolian_Type *ret_type);
void database_function_return_comment_set(Eolian_Function *foo_id, Eolian_Function_Type ftype, const char *ret_comment);
void database_function_return_default_val_set(Eolian_Function *foo_id, Eolian_Function_Type ftype, const char *ret_default_value);
void database_function_return_default_val_set(Eolian_Function *foo_id, Eolian_Function_Type ftype, Eolian_Expression *ret_default_value);
void database_function_return_flag_set_as_warn_unused(Eolian_Function *foo_id, Eolian_Function_Type ftype, Eina_Bool warn_unused);
void database_function_object_set_as_const(Eolian_Function *foo_id, Eina_Bool is_const);