diff options
Diffstat (limited to 'src/analysis/scan/exprs/boolop.c')
-rw-r--r-- | src/analysis/scan/exprs/boolop.c | 161 |
1 files changed, 95 insertions, 66 deletions
diff --git a/src/analysis/scan/exprs/boolop.c b/src/analysis/scan/exprs/boolop.c index 2902fdd..f6a80dd 100644 --- a/src/analysis/scan/exprs/boolop.c +++ b/src/analysis/scan/exprs/boolop.c @@ -56,10 +56,10 @@ static void g_boolean_operation_finalize(GBoolOperation *); static bool g_boolean_operation_compare_rich(const GBoolOperation *, const GBoolOperation *, RichCmpOperation, bool *); /* Reproduit une expression en place dans une nouvelle instance. */ -static GScanExpression *g_boolean_operation_duplicate(const GBoolOperation *); +static void g_boolean_operation_copy(GBoolOperation *, const GBoolOperation *); /* Réduit une expression à une forme plus simple. */ -GScanExpression *g_boolean_operation_reduce(GBoolOperation *, GScanContext *, bool); +static bool g_boolean_operation_reduce(GBoolOperation *, GScanContext *, GScanScope *, GScanExpression **); @@ -97,7 +97,7 @@ static void g_boolean_operation_class_init(GBoolOperationClass *klass) expr = G_SCAN_EXPRESSION_CLASS(klass); expr->cmp_rich = (compare_expr_rich_fc)g_boolean_operation_compare_rich; - expr->dup = (dup_expr_fc)g_boolean_operation_duplicate; + expr->copy = (copy_expr_fc)g_boolean_operation_copy; expr->reduce = (reduce_expr_fc)g_boolean_operation_reduce; } @@ -278,9 +278,9 @@ bool g_boolean_operation_create(GBoolOperation *op, BooleanOperationType type, G static bool g_boolean_operation_compare_rich(const GBoolOperation *item, const GBoolOperation *other, RichCmpOperation op, bool *status) { bool result; /* Etat à retourner */ - bool equal; /* Bilan intermédiaire */ - result = true; + result = g_type_is_a(G_TYPE_FROM_INSTANCE(other), G_TYPE_BOOLEAN_OPERATION); + if (!result) goto done; if (item->type != other->type) { @@ -288,15 +288,13 @@ static bool g_boolean_operation_compare_rich(const GBoolOperation *item, const G goto done; } - equal = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item), G_COMPARABLE_ITEM(other), RCO_EQ, status); + result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item), G_COMPARABLE_ITEM(other), RCO_EQ, status); + if (!result || STATUS_NOT_EQUAL(*status, op)) goto done; - if (!equal) - { - *status = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->first), - G_COMPARABLE_ITEM(other->first), - op, status); - goto done; - } + result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->first), + G_COMPARABLE_ITEM(other->first), + op, status); + if (!result || STATUS_NOT_EQUAL(*status, op)) goto done; if (item->second == NULL) { @@ -321,9 +319,9 @@ static bool g_boolean_operation_compare_rich(const GBoolOperation *item, const G } else - *status = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->second), - G_COMPARABLE_ITEM(other->second), - op, status); + result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->second), + G_COMPARABLE_ITEM(other->second), + op, status); done: @@ -334,23 +332,31 @@ static bool g_boolean_operation_compare_rich(const GBoolOperation *item, const G /****************************************************************************** * * -* Paramètres : expr = expression à copier. * +* Paramètres : dest = emplacement d'enregistrement à constituer. [OUT] * +* src = expression source à copier. * * * * Description : Reproduit une expression en place dans une nouvelle instance.* * * -* Retour : Nouvelle instance d'expression. * +* Retour : - * * * * Remarques : - * * * ******************************************************************************/ -static GScanExpression *g_boolean_operation_duplicate(const GBoolOperation *expr) +static void g_boolean_operation_copy(GBoolOperation *dest, const GBoolOperation *src) { - GScanExpression *result; /* Instance copiée à retourner */ + GScanExpressionClass *class; /* Classe parente à solliciter */ - result = g_boolean_operation_new(expr->type, expr->first, expr->second); + class = G_SCAN_EXPRESSION_CLASS(g_boolean_operation_parent_class); - return result; + class->copy(G_SCAN_EXPRESSION(dest), G_SCAN_EXPRESSION(src)); + + dest->type = src->type; + + dest->first = g_scan_expression_duplicate(src->first); + + if (src->second != NULL) + dest->second = g_scan_expression_duplicate(src->second); } @@ -359,92 +365,115 @@ static GScanExpression *g_boolean_operation_duplicate(const GBoolOperation *expr * * * Paramètres : expr = expression à consulter. * * ctx = contexte de suivi de l'analyse courante. * -* final = impose une conversion finale de dernier tour. * +* scope = portée courante des variables locales. * +* out = zone d'enregistrement de la réduction opérée. [OUT] * * * * Description : Réduit une expression à une forme plus simple. * * * -* Retour : Réduction correspondante, expression déjà réduite, ou NULL. * +* Retour : Bilan de l'opération : false en cas d'erreur irrécupérable. * * * * Remarques : - * * * ******************************************************************************/ -GScanExpression *g_boolean_operation_reduce(GBoolOperation *expr, GScanContext *ctx, bool final) +static bool g_boolean_operation_reduce(GBoolOperation *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out) { - GScanExpression *result; /* Instance à renvoyer */ - GScanExpression *new; /* Nouvelle expression obtenue */ + bool result; /* Bilan à retourner */ + GScanExpression *new_first; /* Expression réduite (gauche) */ + GScanExpression *new_second; /* Expression réduite (droite) */ bool values[2]; /* Valeurs des éléments portés */ bool valid[2]; /* Validité de ces valeurs */ - result = NULL; - /* Réduction des éléments considérés */ - new = g_scan_expression_reduce(expr->first, ctx, final); + new_first = NULL; + new_second = NULL; + + result = g_scan_expression_reduce(expr->first, ctx, scope, &new_first); + if (!result) goto exit; - if (new != NULL) + if (expr->second == NULL) + new_second = NULL; + else { - g_object_unref(G_OBJECT(expr->first)); - expr->first = new; + result = g_scan_expression_reduce(expr->second, ctx, scope, &new_second); + if (!result) goto exit; } - if (expr->second != NULL) - { - new = g_scan_expression_reduce(expr->second, ctx, final); + /* Construction d'une réduction locale ? */ - if (new != NULL) - { - g_object_unref(G_OBJECT(expr->second)); - expr->second = new; - } + valid[0] = G_IS_LITERAL_EXPRESSION(new_first); - } + if (valid[0]) + valid[0] = g_literal_expression_get_boolean_value(G_LITERAL_EXPRESSION(new_first), &values[0]); - /* Construction d'une réduction locale ? */ + valid[1] = G_IS_LITERAL_EXPRESSION(new_second); + + if (valid[1]) + valid[1] = g_literal_expression_get_boolean_value(G_LITERAL_EXPRESSION(new_second), &values[1]); switch (expr->type) { case BOT_AND: - if (G_IS_LITERAL_EXPRESSION(expr->first) && G_IS_LITERAL_EXPRESSION(expr->second)) - { - valid[0] = g_literal_expression_get_boolean_value(G_LITERAL_EXPRESSION(expr->first), &values[0]); - valid[1] = g_literal_expression_get_boolean_value(G_LITERAL_EXPRESSION(expr->second), &values[1]); + if (valid[0] && valid[1]) + *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { values[0] && values[1] }); - if (valid[0] && valid[1]) - result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { values[0] && values[1] }); + else if (valid[0] && !values[0]) + *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { false }); - else - /* Etre malin si 0 && x => bilan (si ctx->quick) */ - ; + else if (valid[1] && !values[1]) + *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { false }); - } break; case BOT_OR: - if (G_IS_LITERAL_EXPRESSION(expr->first) && G_IS_LITERAL_EXPRESSION(expr->second)) - { - valid[0] = g_literal_expression_get_boolean_value(G_LITERAL_EXPRESSION(expr->first), &values[0]); - valid[1] = g_literal_expression_get_boolean_value(G_LITERAL_EXPRESSION(expr->second), &values[1]); + if (valid[0] && valid[1]) + *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { values[0] || values[1] }); - if (valid[0] && valid[1]) - result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { values[0] || values[1] }); + else if (valid[0] && values[0]) + *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { true }); + + else if (valid[1] && values[1]) + *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { true }); - } break; case BOT_NOT: - if (G_IS_LITERAL_EXPRESSION(expr->first)) - { - valid[0] = g_literal_expression_get_boolean_value(G_LITERAL_EXPRESSION(expr->first), &values[0]); + if (valid[0]) + *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { !values[0] }); + break; - if (valid[0]) - result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { !values[1] }); + } + + /* Mise à jour de la progression ? */ + + if (*out == NULL) + { + if ((new_first != NULL && new_first != expr->first) || (new_second != NULL && new_second != expr->second)) + { + if (new_first == NULL) + { + new_first = expr->first; + g_object_ref(G_OBJECT(new_first)); + } + if (new_second == NULL) + { + new_second = expr->second; + g_object_ref(G_OBJECT(new_second)); } - break; + + *out = g_boolean_operation_new(expr->type, new_first, new_second); + + } } + exit: + + g_clear_object(&new_first); + g_clear_object(&new_second); + return result; } |