forked from enlightenment/efl
eolian: add capturing of variables/typedecls in expr eval
This will be used from validation to properly count actual dependencies of a unit.
This commit is contained in:
parent
591567a6ac
commit
dd90488b69
|
@ -184,11 +184,13 @@ promote(Eolian_Expression *a, Eolian_Expression *b)
|
|||
|
||||
static Eina_Bool eval_exp(const Eolian_Unit *unit,
|
||||
Eolian_Expression *expr,
|
||||
Eolian_Expression_Mask mask, Eolian_Expression *out);
|
||||
Eolian_Expression_Mask mask, Eolian_Expression *out,
|
||||
Expr_Obj_Cb cb, void *data);
|
||||
|
||||
static Eina_Bool
|
||||
eval_unary(const Eolian_Unit *unit, Eolian_Expression *expr,
|
||||
Eolian_Expression_Mask mask, Eolian_Expression *out)
|
||||
Eolian_Expression_Mask mask, Eolian_Expression *out,
|
||||
Expr_Obj_Cb cb, void *data)
|
||||
{
|
||||
switch (expr->unop)
|
||||
{
|
||||
|
@ -198,7 +200,7 @@ eval_unary(const Eolian_Unit *unit, Eolian_Expression *expr,
|
|||
if (!(mask & EOLIAN_MASK_SIGNED))
|
||||
return expr_type_error(expr, EOLIAN_MASK_SIGNED, mask);
|
||||
|
||||
return eval_exp(unit, expr->expr, EOLIAN_MASK_SIGNED, out);
|
||||
return eval_exp(unit, expr->expr, EOLIAN_MASK_SIGNED, out, cb, data);
|
||||
}
|
||||
case EOLIAN_UNOP_UNM:
|
||||
{
|
||||
|
@ -207,7 +209,7 @@ eval_unary(const Eolian_Unit *unit, Eolian_Expression *expr,
|
|||
if (!(mask & EOLIAN_MASK_SIGNED))
|
||||
return expr_type_error(expr, EOLIAN_MASK_SIGNED, mask);
|
||||
|
||||
if (!eval_exp(unit, expr->expr, EOLIAN_MASK_SIGNED, &exp))
|
||||
if (!eval_exp(unit, expr->expr, EOLIAN_MASK_SIGNED, &exp, cb, data))
|
||||
return EINA_FALSE;
|
||||
|
||||
switch (exp.type)
|
||||
|
@ -230,7 +232,7 @@ eval_unary(const Eolian_Unit *unit, Eolian_Expression *expr,
|
|||
if (!(mask & EOLIAN_MASK_BOOL))
|
||||
return expr_type_error(expr, EOLIAN_MASK_BOOL, mask);
|
||||
|
||||
if (!eval_exp(unit, expr->expr, EOLIAN_MASK_NUMBER | EOLIAN_MASK_BOOL, &exp))
|
||||
if (!eval_exp(unit, expr->expr, EOLIAN_MASK_NUMBER | EOLIAN_MASK_BOOL, &exp, cb, data))
|
||||
return EINA_FALSE;
|
||||
|
||||
exp.value.b = !(exp.value.ull);
|
||||
|
@ -246,7 +248,7 @@ eval_unary(const Eolian_Unit *unit, Eolian_Expression *expr,
|
|||
if (!(mask & EOLIAN_MASK_INT))
|
||||
return expr_type_error(expr, EOLIAN_MASK_INT, mask);
|
||||
|
||||
if (!eval_exp(unit, expr->expr, EOLIAN_MASK_INT, &exp))
|
||||
if (!eval_exp(unit, expr->expr, EOLIAN_MASK_INT, &exp, cb, data))
|
||||
return EINA_FALSE;
|
||||
|
||||
switch (exp.type)
|
||||
|
@ -275,17 +277,17 @@ eval_unary(const Eolian_Unit *unit, Eolian_Expression *expr,
|
|||
static Eina_Bool
|
||||
eval_promote_num(const Eolian_Unit *unit, Eolian_Expression *expr,
|
||||
Eolian_Expression *lhs, Eolian_Expression *rhs, int mask,
|
||||
int emask)
|
||||
int emask, Expr_Obj_Cb cb, void *data)
|
||||
{
|
||||
/* make sure the output can be a number */
|
||||
if (!(mask & EOLIAN_MASK_NUMBER))
|
||||
return expr_type_error(expr, EOLIAN_MASK_NUMBER, mask);
|
||||
|
||||
/* eval into primitive value */
|
||||
if (!eval_exp(unit, expr->lhs, emask, lhs))
|
||||
if (!eval_exp(unit, expr->lhs, emask, lhs, cb, data))
|
||||
return EINA_FALSE;
|
||||
|
||||
if (!eval_exp(unit, expr->rhs, emask, rhs))
|
||||
if (!eval_exp(unit, expr->rhs, emask, rhs, cb, data))
|
||||
return EINA_FALSE;
|
||||
|
||||
/* promote so both sides are of the same type */
|
||||
|
@ -297,7 +299,8 @@ eval_promote_num(const Eolian_Unit *unit, Eolian_Expression *expr,
|
|||
|
||||
static Eina_Bool
|
||||
eval_binary(const Eolian_Unit *unit, Eolian_Expression *expr,
|
||||
Eolian_Expression_Mask mask, Eolian_Expression *out)
|
||||
Eolian_Expression_Mask mask, Eolian_Expression *out,
|
||||
Expr_Obj_Cb cb, void *data)
|
||||
{
|
||||
#define APPLY_CASE(id, expr, lhs, rhs, fnm, op) \
|
||||
case EOLIAN_EXPR_##id: \
|
||||
|
@ -342,7 +345,7 @@ eval_binary(const Eolian_Unit *unit, Eolian_Expression *expr,
|
|||
int emask = (mask & EOLIAN_MASK_FLOAT) \
|
||||
? EOLIAN_MASK_NUMBER \
|
||||
: EOLIAN_MASK_INT; \
|
||||
if (!eval_promote_num(unit, expr, &lhs, &rhs, mask, emask)) \
|
||||
if (!eval_promote_num(unit, expr, &lhs, &rhs, mask, emask, cb, data)) \
|
||||
return EINA_FALSE; \
|
||||
APPLY_NUM(out, lhs, rhs, op) \
|
||||
return EINA_TRUE; \
|
||||
|
@ -353,7 +356,7 @@ eval_binary(const Eolian_Unit *unit, Eolian_Expression *expr,
|
|||
{ \
|
||||
Eolian_Expression lhs; \
|
||||
Eolian_Expression rhs; \
|
||||
if (!eval_promote_num(unit, expr, &lhs, &rhs, mask, EOLIAN_MASK_INT)) \
|
||||
if (!eval_promote_num(unit, expr, &lhs, &rhs, mask, EOLIAN_MASK_INT, cb, data)) \
|
||||
return EINA_FALSE; \
|
||||
APPLY_INT(out, lhs, rhs, op) \
|
||||
return EINA_TRUE; \
|
||||
|
@ -366,9 +369,9 @@ eval_binary(const Eolian_Unit *unit, Eolian_Expression *expr,
|
|||
Eolian_Expression rhs; \
|
||||
if (!(mask & EOLIAN_MASK_BOOL)) \
|
||||
return expr_type_error(expr, EOLIAN_MASK_BOOL, mask); \
|
||||
if (!eval_exp(unit, expr->lhs, allowed, &lhs)) \
|
||||
if (!eval_exp(unit, expr->lhs, allowed, &lhs, cb, data)) \
|
||||
return EINA_FALSE; \
|
||||
if (!eval_exp(unit, expr->rhs, allowed, &rhs)) \
|
||||
if (!eval_exp(unit, expr->rhs, allowed, &rhs, cb, data)) \
|
||||
return EINA_FALSE; \
|
||||
if (lhs.type >= EOLIAN_EXPR_STRING && rhs.type != lhs.type) \
|
||||
return expr_type_mismatch_error(&lhs, &rhs); \
|
||||
|
@ -438,7 +441,8 @@ split_enum_name(const char *str, char **ename, char **memb)
|
|||
|
||||
static Eina_Bool
|
||||
eval_exp(const Eolian_Unit *unit, Eolian_Expression *expr,
|
||||
Eolian_Expression_Mask mask, Eolian_Expression *out)
|
||||
Eolian_Expression_Mask mask, Eolian_Expression *out,
|
||||
Expr_Obj_Cb cb, void *data)
|
||||
{
|
||||
switch (expr->type)
|
||||
{
|
||||
|
@ -502,7 +506,7 @@ eval_exp(const Eolian_Unit *unit, Eolian_Expression *expr,
|
|||
{
|
||||
if (!expr->expr)
|
||||
return expr_error(expr, "undefined value");
|
||||
return eval_exp(NULL, expr->expr, mask, out);
|
||||
return eval_exp(NULL, expr->expr, mask, out, cb, data);
|
||||
}
|
||||
|
||||
const Eolian_Variable *var = eolian_unit_constant_by_name_get
|
||||
|
@ -525,6 +529,7 @@ eval_exp(const Eolian_Unit *unit, Eolian_Expression *expr,
|
|||
return expr_type_error(expr, EOLIAN_MASK_INT, mask);
|
||||
|
||||
etpd = eolian_unit_alias_by_name_get(unit, fulln);
|
||||
if (etpd && cb) cb((const Eolian_Object *)etpd, data);
|
||||
while (etpd && etpd->type == EOLIAN_TYPEDECL_ALIAS)
|
||||
{
|
||||
const Eolian_Type *etp = eolian_typedecl_base_type_get(etpd);
|
||||
|
@ -533,7 +538,11 @@ eval_exp(const Eolian_Unit *unit, Eolian_Expression *expr,
|
|||
etpd = database_type_decl_find(unit, etp);
|
||||
}
|
||||
|
||||
if (!etpd) etpd = eolian_unit_enum_by_name_get(unit, fulln);
|
||||
if (!etpd)
|
||||
{
|
||||
etpd = eolian_unit_enum_by_name_get(unit, fulln);
|
||||
if (etpd && cb) cb((const Eolian_Object *)etpd, data);
|
||||
}
|
||||
if (!etpd || etpd->type != EOLIAN_TYPEDECL_ENUM)
|
||||
{
|
||||
free(fulln);
|
||||
|
@ -548,18 +557,21 @@ eval_exp(const Eolian_Unit *unit, Eolian_Expression *expr,
|
|||
return expr_error(expr, "invalid enum field");
|
||||
}
|
||||
else
|
||||
exp = (Eolian_Expression *)var->value;
|
||||
{
|
||||
exp = (Eolian_Expression *)var->value;
|
||||
if (cb) cb((const Eolian_Object *)var, data);
|
||||
}
|
||||
|
||||
if (!exp)
|
||||
return expr_error(expr, "undefined variable");
|
||||
|
||||
expr->expr = exp;
|
||||
return eval_exp(unit, exp, mask, out);
|
||||
return eval_exp(unit, exp, mask, out, cb, data);
|
||||
}
|
||||
case EOLIAN_EXPR_UNARY:
|
||||
return eval_unary(unit, expr, mask, out);
|
||||
return eval_unary(unit, expr, mask, out, cb, data);
|
||||
case EOLIAN_EXPR_BINARY:
|
||||
return eval_binary(unit, expr, mask, out);
|
||||
return eval_binary(unit, expr, mask, out, cb, data);
|
||||
default:
|
||||
assert(EINA_FALSE);
|
||||
return EINA_FALSE;
|
||||
|
@ -570,14 +582,14 @@ eval_exp(const Eolian_Unit *unit, Eolian_Expression *expr,
|
|||
|
||||
Eolian_Value
|
||||
database_expr_eval(const Eolian_Unit *unit, Eolian_Expression *expr,
|
||||
Eolian_Expression_Mask mask)
|
||||
Eolian_Expression_Mask mask, Expr_Obj_Cb cb, void *data)
|
||||
{
|
||||
Eolian_Expression out;
|
||||
Eolian_Value ret;
|
||||
ret.type = EOLIAN_EXPR_UNKNOWN;
|
||||
if (!mask)
|
||||
return ret;
|
||||
if (!eval_exp(unit, expr, mask, &out))
|
||||
if (!eval_exp(unit, expr, mask, &out, cb, data))
|
||||
return ret;
|
||||
ret.type = out.type;
|
||||
ret.value = out.value;
|
||||
|
@ -586,7 +598,7 @@ database_expr_eval(const Eolian_Unit *unit, Eolian_Expression *expr,
|
|||
|
||||
Eolian_Value
|
||||
database_expr_eval_type(const Eolian_Unit *unit, Eolian_Expression *expr,
|
||||
const Eolian_Type *type)
|
||||
const Eolian_Type *type, Expr_Obj_Cb cb, void *data)
|
||||
{
|
||||
Eolian_Value err;
|
||||
err.type = EOLIAN_EXPR_UNKNOWN;
|
||||
|
@ -595,11 +607,11 @@ database_expr_eval_type(const Eolian_Unit *unit, Eolian_Expression *expr,
|
|||
switch (type->type)
|
||||
{
|
||||
case EOLIAN_TYPE_CLASS:
|
||||
return database_expr_eval(unit, expr, EOLIAN_MASK_NULL);
|
||||
return database_expr_eval(unit, expr, EOLIAN_MASK_NULL, cb, data);
|
||||
case EOLIAN_TYPE_REGULAR:
|
||||
{
|
||||
if (database_type_is_ownable(unit, type))
|
||||
return database_expr_eval(unit, expr, EOLIAN_MASK_NULL);
|
||||
return database_expr_eval(unit, expr, EOLIAN_MASK_NULL, cb, data);
|
||||
int kw = eo_lexer_keyword_str_to_id(type->base.name);
|
||||
if (!kw || kw < KW_byte || kw >= KW_void)
|
||||
{
|
||||
|
@ -607,9 +619,9 @@ database_expr_eval_type(const Eolian_Unit *unit, Eolian_Expression *expr,
|
|||
if (!base)
|
||||
return err;
|
||||
if (base->type == EOLIAN_TYPEDECL_ALIAS)
|
||||
return database_expr_eval_type(unit, expr, eolian_typedecl_base_type_get(base));
|
||||
return database_expr_eval_type(unit, expr, eolian_typedecl_base_type_get(base), cb, data);
|
||||
else if (base->type == EOLIAN_TYPEDECL_ENUM)
|
||||
return database_expr_eval(unit, expr, EOLIAN_MASK_INT);
|
||||
return database_expr_eval(unit, expr, EOLIAN_MASK_INT, cb, data);
|
||||
return err;
|
||||
}
|
||||
switch (kw)
|
||||
|
@ -627,7 +639,7 @@ database_expr_eval_type(const Eolian_Unit *unit, Eolian_Expression *expr,
|
|||
case KW_ssize:
|
||||
case KW_intptr:
|
||||
case KW_ptrdiff:
|
||||
return database_expr_eval(unit, expr, EOLIAN_MASK_SINT);
|
||||
return database_expr_eval(unit, expr, EOLIAN_MASK_SINT, cb, data);
|
||||
case KW_ubyte:
|
||||
case KW_ushort:
|
||||
case KW_uint:
|
||||
|
@ -641,14 +653,14 @@ database_expr_eval_type(const Eolian_Unit *unit, Eolian_Expression *expr,
|
|||
case KW_size:
|
||||
case KW_uintptr:
|
||||
case KW_time:
|
||||
return database_expr_eval(unit, expr, EOLIAN_MASK_UINT);
|
||||
return database_expr_eval(unit, expr, EOLIAN_MASK_UINT, cb, data);
|
||||
case KW_float:
|
||||
case KW_double:
|
||||
return database_expr_eval(unit, expr, EOLIAN_MASK_FLOAT);
|
||||
return database_expr_eval(unit, expr, EOLIAN_MASK_FLOAT, cb, data);
|
||||
case KW_bool:
|
||||
return database_expr_eval(unit, expr, EOLIAN_MASK_BOOL);
|
||||
return database_expr_eval(unit, expr, EOLIAN_MASK_BOOL, cb, data);
|
||||
case KW_char:
|
||||
return database_expr_eval(unit, expr, EOLIAN_MASK_CHAR);
|
||||
return database_expr_eval(unit, expr, EOLIAN_MASK_CHAR, cb, data);
|
||||
default:
|
||||
return err;
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@ eolian_expression_eval(const Eolian_Expression *expr, Eolian_Expression_Mask m)
|
|||
Eolian_Value err;
|
||||
err.type = EOLIAN_EXPR_UNKNOWN;
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(expr, err);
|
||||
return database_expr_eval(NULL, (Eolian_Expression *)expr, m);
|
||||
return database_expr_eval(NULL, (Eolian_Expression *)expr, m, NULL, NULL);
|
||||
}
|
||||
|
||||
EAPI Eolian_Value
|
||||
|
@ -22,7 +22,7 @@ eolian_expression_eval_type(const Eolian_Expression *expr,
|
|||
Eolian_Value err;
|
||||
err.type = EOLIAN_EXPR_UNKNOWN;
|
||||
EINA_SAFETY_ON_NULL_RETURN_VAL(expr, err);
|
||||
return database_expr_eval_type(NULL, (Eolian_Expression *)expr, type);
|
||||
return database_expr_eval_type(NULL, (Eolian_Expression *)expr, type, NULL, NULL);
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -317,9 +317,9 @@ _validate_expr(Eolian_Expression *expr, const Eolian_Type *tp,
|
|||
{
|
||||
Eolian_Value val;
|
||||
if (tp)
|
||||
val = database_expr_eval_type(expr->base.unit, expr, tp);
|
||||
val = database_expr_eval_type(expr->base.unit, expr, tp, NULL, NULL);
|
||||
else
|
||||
val = database_expr_eval(expr->base.unit, expr, msk);
|
||||
val = database_expr_eval(expr->base.unit, expr, msk, NULL, NULL);
|
||||
|
||||
if (val.type == EOLIAN_EXPR_UNKNOWN)
|
||||
return EINA_FALSE;
|
||||
|
|
|
@ -410,8 +410,10 @@ Eina_Bool database_type_is_ownable(const Eolian_Unit *unit, const Eolian_Type *t
|
|||
|
||||
/* expressions */
|
||||
|
||||
Eolian_Value database_expr_eval(const Eolian_Unit *unit, Eolian_Expression *expr, Eolian_Expression_Mask mask);
|
||||
Eolian_Value database_expr_eval_type(const Eolian_Unit *unit, Eolian_Expression *expr, const Eolian_Type *type);
|
||||
typedef void (*Expr_Obj_Cb)(const Eolian_Object *obj, void *data);
|
||||
|
||||
Eolian_Value database_expr_eval(const Eolian_Unit *unit, Eolian_Expression *expr, Eolian_Expression_Mask mask, Expr_Obj_Cb cb, void *data);
|
||||
Eolian_Value database_expr_eval_type(const Eolian_Unit *unit, Eolian_Expression *expr, const Eolian_Type *type, Expr_Obj_Cb cb, void *data);
|
||||
void database_expr_del(Eolian_Expression *expr);
|
||||
void database_expr_print(Eolian_Expression *expr);
|
||||
|
||||
|
|
Loading…
Reference in New Issue