diff options
Diffstat (limited to 'src/analysis/scan/exprs/relop.c')
-rw-r--r-- | src/analysis/scan/exprs/relop.c | 156 |
1 files changed, 87 insertions, 69 deletions
diff --git a/src/analysis/scan/exprs/relop.c b/src/analysis/scan/exprs/relop.c index 94ce77d..7dc6864 100644 --- a/src/analysis/scan/exprs/relop.c +++ b/src/analysis/scan/exprs/relop.c @@ -52,11 +52,11 @@ static void g_relational_operation_finalize(GRelOperation *); /* Réalise une comparaison entre objets selon un critère précis. */ static bool g_relational_operation_compare_rich(const GRelOperation *, const GRelOperation *, RichCmpOperation, bool *); -/* Initialise une instance d'opération de relation. */ -static GScanExpression *g_relational_operation_duplicate(const GRelOperation *); +/* Reproduit une expression en place dans une nouvelle instance. */ +static void g_relational_operation_copy(GRelOperation *, const GRelOperation *); /* Réduit une expression à une forme plus simple. */ -GScanExpression *g_relational_operation_reduce(GRelOperation *, GScanContext *, bool); +static bool g_relational_operation_reduce(GRelOperation *, GScanContext *, GScanScope *, GScanExpression **); @@ -94,7 +94,7 @@ static void g_relational_operation_class_init(GRelOperationClass *klass) expr = G_SCAN_EXPRESSION_CLASS(klass); expr->cmp_rich = (compare_expr_rich_fc)g_relational_operation_compare_rich; - expr->dup = (dup_expr_fc)g_relational_operation_duplicate; + expr->copy = (copy_expr_fc)g_relational_operation_copy; expr->reduce = (reduce_expr_fc)g_relational_operation_reduce; } @@ -114,8 +114,8 @@ static void g_relational_operation_class_init(GRelOperationClass *klass) static void g_relational_operation_init(GRelOperation *op) { - op->first = NULL; - op->second = NULL; + op->left = NULL; + op->right = NULL; } @@ -134,8 +134,8 @@ static void g_relational_operation_init(GRelOperation *op) static void g_relational_operation_dispose(GRelOperation *op) { - g_clear_object(&op->first); - g_clear_object(&op->second); + g_clear_object(&op->left); + g_clear_object(&op->right); G_OBJECT_CLASS(g_relational_operation_parent_class)->dispose(G_OBJECT(op)); @@ -163,9 +163,9 @@ static void g_relational_operation_finalize(GRelOperation *op) /****************************************************************************** * * -* Paramètres : type = type d'opération booléenne à représenter. * -* first = premier opérande concerné. * -* second = éventuel second opérande impliqué ou NULL. * +* Paramètres : type = type d'opération booléenne à représenter. * +* left = premier opérande concerné. * +* right = éventuel second opérande impliqué ou NULL. * * * * Description : Organise une opération relationnelle entre expressions. * * * @@ -175,13 +175,13 @@ static void g_relational_operation_finalize(GRelOperation *op) * * ******************************************************************************/ -GScanExpression *g_relational_operation_new(RichCmpOperation type, GScanExpression *first, GScanExpression *second) +GScanExpression *g_relational_operation_new(RichCmpOperation type, GScanExpression *left, GScanExpression *right) { GScanExpression *result; /* Structure à retourner */ result = g_object_new(G_TYPE_RELATIONAL_OPERATION, NULL); - if (!g_relational_operation_create(G_RELATIONAL_OPERATION(result), type, first, second)) + if (!g_relational_operation_create(G_RELATIONAL_OPERATION(result), type, left, right)) g_clear_object(&result); return result; @@ -191,10 +191,10 @@ GScanExpression *g_relational_operation_new(RichCmpOperation type, GScanExpressi /****************************************************************************** * * -* Paramètres : op = instance à initialiser pleinement. * -* type = type d'opération booléenne à représenter. * -* first = premier opérande concerné. * -* second = éventuel second opérande impliqué ou NULL. * +* Paramètres : op = instance à initialiser pleinement. * +* type = type d'opération booléenne à représenter. * +* left = premier opérande concerné. * +* right = éventuel second opérande impliqué ou NULL. * * * * Description : Met en place une opération relationnelle entre expressions. * * * @@ -204,13 +204,13 @@ GScanExpression *g_relational_operation_new(RichCmpOperation type, GScanExpressi * * ******************************************************************************/ -bool g_relational_operation_create(GRelOperation *op, RichCmpOperation type, GScanExpression *first, GScanExpression *second) +bool g_relational_operation_create(GRelOperation *op, RichCmpOperation type, GScanExpression *left, GScanExpression *right) { bool result; /* Bilan à retourner */ result = false; - if (g_scan_expression_get_value_type(first) != g_scan_expression_get_value_type(first)) + if (g_scan_expression_get_value_type(left) != g_scan_expression_get_value_type(left)) goto exit; if (!g_scan_expression_create(G_SCAN_EXPRESSION(op), EVT_BOOLEAN)) @@ -218,11 +218,11 @@ bool g_relational_operation_create(GRelOperation *op, RichCmpOperation type, GSc op->rel_type = type; - op->first = first; - g_object_ref(G_OBJECT(op->first)); + op->left = left; + g_object_ref(G_OBJECT(op->left)); - op->second = second; - g_object_ref(G_OBJECT(op->second)); + op->right = right; + g_object_ref(G_OBJECT(op->right)); result = true; @@ -257,28 +257,26 @@ bool g_relational_operation_create(GRelOperation *op, RichCmpOperation type, GSc static bool g_relational_operation_compare_rich(const GRelOperation *item, const GRelOperation *other, RichCmpOperation op, bool *status) { bool result; /* Etat à retourner */ - bool equal; /* Bilan intermédiaire */ - result = true; // TODO : cmp parent()->type + result = g_type_is_a(G_TYPE_FROM_INSTANCE(other), G_TYPE_RELATIONAL_OPERATION); + if (!result) goto done; if (item->rel_type != other->rel_type) { - result = compare_rich_integer_values(item->rel_type, other->rel_type, op); + *status = compare_rich_integer_values(item->rel_type, other->rel_type, op); 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) - { - result = 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->left), + G_COMPARABLE_ITEM(other->left), + op, status); + if (!result || STATUS_NOT_EQUAL(*status, op)) goto done; - result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->second), - G_COMPARABLE_ITEM(other->second), + result = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(item->right), + G_COMPARABLE_ITEM(other->right), op, status); done: @@ -290,23 +288,29 @@ static bool g_relational_operation_compare_rich(const GRelOperation *item, const /****************************************************************************** * * -* 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_relational_operation_duplicate(const GRelOperation *expr) +static void g_relational_operation_copy(GRelOperation *dest, const GRelOperation *src) { - GScanExpression *result; /* Instance copiée à retourner */ + GScanExpressionClass *class; /* Classe parente à solliciter */ - result = g_relational_operation_new(expr->rel_type, expr->first, expr->second); + class = G_SCAN_EXPRESSION_CLASS(g_relational_operation_parent_class); - return result; + class->copy(G_SCAN_EXPRESSION(dest), G_SCAN_EXPRESSION(src)); + + dest->rel_type = src->rel_type; + + dest->left = g_scan_expression_duplicate(src->left); + dest->right = g_scan_expression_duplicate(src->right); } @@ -315,60 +319,74 @@ static GScanExpression *g_relational_operation_duplicate(const GRelOperation *ex * * * 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_relational_operation_reduce(GRelOperation *expr, GScanContext *ctx, bool final) +static bool g_relational_operation_reduce(GRelOperation *expr, GScanContext *ctx, GScanScope *scope, GScanExpression **out) { - GScanExpression *result; /* Instance à renvoyer */ - GScanExpression *new; /* Nouvelle expression obtenue */ + bool result; /* Bilan à retourner */ + GScanExpression *new_left; /* Expression réduite (gauche) */ + GScanExpression *new_right; /* Expression réduite (droite) */ bool status; /* Bilan d'une comparaison */ bool valid; /* Validité de ce bilan obtenu */ - result = NULL; - /* Réduction des éléments considérés */ - new = g_scan_expression_reduce(expr->first, ctx, final); + new_left = NULL; + new_right = NULL; - if (new != NULL) - { - g_object_unref(G_OBJECT(expr->first)); - expr->first = new; - } + result = g_scan_expression_reduce(expr->left, ctx, scope, &new_left); + if (!result) goto exit; + + result = g_scan_expression_reduce(expr->right, ctx, scope, &new_right); + if (!result) goto exit; + + /* Construction d'une réduction locale ? */ - if (expr->second != NULL) + if (G_IS_LITERAL_EXPRESSION(new_left) && G_IS_LITERAL_EXPRESSION(new_right)) { - new = g_scan_expression_reduce(expr->second, ctx, final); + valid = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(new_left), + G_COMPARABLE_ITEM(new_right), + expr->rel_type, &status); - if (new != NULL) - { - g_object_unref(G_OBJECT(expr->second)); - expr->second = new; - } + if (valid) + *out = g_literal_expression_new(EVT_BOOLEAN, (bool []) { status }); } - /* Construction d'une réduction locale ? */ + /* Mise à jour de la progression ? */ - if (G_IS_LITERAL_EXPRESSION(expr->first) && G_IS_LITERAL_EXPRESSION(expr->second)) + else if ((new_left != NULL && new_left != expr->left) || (new_right != NULL && new_right != expr->right)) { - valid = g_comparable_item_compare_rich(G_COMPARABLE_ITEM(expr->first), - G_COMPARABLE_ITEM(expr->second), - expr->rel_type, &status); + if (new_left == NULL) + { + new_left = expr->left; + g_object_ref(G_OBJECT(new_left)); + } - if (valid) - result = g_literal_expression_new(EVT_BOOLEAN, (bool []) { status }); + if (new_right == NULL) + { + new_right = expr->right; + g_object_ref(G_OBJECT(new_right)); + } + + *out = g_relational_operation_new(expr->rel_type, new_left, new_right); } + exit: + + g_clear_object(&new_left); + g_clear_object(&new_right); + return result; } |