diff options
author | Cyrille Bagard <nocbos@gmail.com> | 2023-07-07 06:32:43 (GMT) |
---|---|---|
committer | Cyrille Bagard <nocbos@gmail.com> | 2023-07-07 06:32:43 (GMT) |
commit | 4c10dfa2a95cea6fc704d68066d0c284cfd79342 (patch) | |
tree | 5827bbc411459800747e21929daecdf99fde7dfd /src/analysis/scan/exprs/arithmop.c | |
parent | 3f996be1e5858b54740bf92515795982a16b169a (diff) |
Rewrite core parts of the ROST API.
Diffstat (limited to 'src/analysis/scan/exprs/arithmop.c')
-rw-r--r-- | src/analysis/scan/exprs/arithmop.c | 210 |
1 files changed, 116 insertions, 94 deletions
diff --git a/src/analysis/scan/exprs/arithmop.c b/src/analysis/scan/exprs/arithmop.c index f57e260..5f9e3f1 100644 --- a/src/analysis/scan/exprs/arithmop.c +++ b/src/analysis/scan/exprs/arithmop.c @@ -52,11 +52,11 @@ static void g_arithmetic_operation_finalize(GArithmOperation *); /* Réalise une comparaison entre objets selon un critère précis. */ static bool g_arithmetic_operation_compare_rich(const GArithmOperation *, const GArithmOperation *, RichCmpOperation, bool *); -/* Initialise une instance d'opération de relation. */ -static GScanExpression *g_arithmetic_operation_duplicate(const GArithmOperation *); +/* Reproduit une expression en place dans une nouvelle instance. */ +static void g_arithmetic_operation_copy(GArithmOperation *, const GArithmOperation *); /* Réduit une expression à une forme plus simple. */ -GScanExpression *g_arithmetic_operation_reduce(GArithmOperation *, GScanContext *, bool); +static bool g_arithmetic_operation_reduce(GArithmOperation *, GScanContext *, GScanScope *, GScanExpression **); @@ -94,7 +94,7 @@ static void g_arithmetic_operation_class_init(GArithmOperationClass *klass) expr = G_SCAN_EXPRESSION_CLASS(klass); expr->cmp_rich = (compare_expr_rich_fc)g_arithmetic_operation_compare_rich; - expr->dup = (dup_expr_fc)g_arithmetic_operation_duplicate; + expr->copy = (copy_expr_fc)g_arithmetic_operation_copy; expr->reduce = (reduce_expr_fc)g_arithmetic_operation_reduce; } @@ -114,8 +114,8 @@ static void g_arithmetic_operation_class_init(GArithmOperationClass *klass) static void g_arithmetic_operation_init(GArithmOperation *op) { - op->first = NULL; - op->second = NULL; + op->left = NULL; + op->right = NULL; } @@ -134,8 +134,8 @@ static void g_arithmetic_operation_init(GArithmOperation *op) static void g_arithmetic_operation_dispose(GArithmOperation *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_arithmetic_operation_parent_class)->dispose(G_OBJECT(op)); @@ -164,8 +164,8 @@ static void g_arithmetic_operation_finalize(GArithmOperation *op) /****************************************************************************** * * * Paramètres : operator = type d'opération arithmétique à représenter. * -* first = premier opérande concerné. * -* second = éventuel second opérande impliqué ou NULL. * +* left = premier opérande concerné. * +* right = éventuel second opérande impliqué ou NULL. * * * * Description : Organise une opération arithmétique entre expressions. * * * @@ -175,13 +175,13 @@ static void g_arithmetic_operation_finalize(GArithmOperation *op) * * ******************************************************************************/ -GScanExpression *g_arithmetic_operation_new(ArithmeticExpressionOperator operator, GScanExpression *first, GScanExpression *second) +GScanExpression *g_arithmetic_operation_new(ArithmeticExpressionOperator operator, GScanExpression *left, GScanExpression *right) { GScanExpression *result; /* Structure à retourner */ result = g_object_new(G_TYPE_ARITHMETIC_OPERATION, NULL); - if (!g_arithmetic_operation_create(G_ARITHMETIC_OPERATION(result), operator, first, second)) + if (!g_arithmetic_operation_create(G_ARITHMETIC_OPERATION(result), operator, left, right)) g_clear_object(&result); return result; @@ -193,8 +193,8 @@ GScanExpression *g_arithmetic_operation_new(ArithmeticExpressionOperator operato * * * Paramètres : op = instance à initialiser pleinement. * * operator = type d'opération booléenne à représenter. * -* first = premier opérande concerné. * -* second = éventuel second opérande impliqué ou NULL. * +* left = premier opérande concerné. * +* right = éventuel second opérande impliqué ou NULL. * * * * Description : Met en place une opération arithmétique entre expressions. * * * @@ -204,19 +204,19 @@ GScanExpression *g_arithmetic_operation_new(ArithmeticExpressionOperator operato * * ******************************************************************************/ -bool g_arithmetic_operation_create(GArithmOperation *op, ArithmeticExpressionOperator operator, GScanExpression *first, GScanExpression *second) +bool g_arithmetic_operation_create(GArithmOperation *op, ArithmeticExpressionOperator operator, GScanExpression *left, GScanExpression *right) { bool result; /* Bilan à retourner */ ExprValueType vtype; /* Type de valeur portée */ result = false; - vtype = g_scan_expression_get_value_type(first); + vtype = g_scan_expression_get_value_type(left); if (vtype != EVT_INTEGER && vtype != EVT_PENDING) goto exit; - vtype = g_scan_expression_get_value_type(second); + vtype = g_scan_expression_get_value_type(right); if (vtype != EVT_INTEGER && vtype != EVT_PENDING) goto exit; @@ -226,11 +226,11 @@ bool g_arithmetic_operation_create(GArithmOperation *op, ArithmeticExpressionOpe op->operator = operator; - 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; @@ -265,9 +265,9 @@ bool g_arithmetic_operation_create(GArithmOperation *op, ArithmeticExpressionOpe static bool g_arithmetic_operation_compare_rich(const GArithmOperation *item, const GArithmOperation *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_ARITHMETIC_OPERATION); + if (!result) goto done; if (item->operator != other->operator) { @@ -275,18 +275,16 @@ static bool g_arithmetic_operation_compare_rich(const GArithmOperation *item, co 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: @@ -298,23 +296,29 @@ static bool g_arithmetic_operation_compare_rich(const GArithmOperation *item, co /****************************************************************************** * * -* 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_arithmetic_operation_duplicate(const GArithmOperation *expr) +static void g_arithmetic_operation_copy(GArithmOperation *dest, const GArithmOperation *src) { - GScanExpression *result; /* Instance copiée à retourner */ + GScanExpressionClass *class; /* Classe parente à solliciter */ - result = g_arithmetic_operation_new(expr->operator, expr->first, expr->second); + class = G_SCAN_EXPRESSION_CLASS(g_arithmetic_operation_parent_class); - return result; + class->copy(G_SCAN_EXPRESSION(dest), G_SCAN_EXPRESSION(src)); + + dest->operator = src->operator; + + dest->left = g_scan_expression_duplicate(src->left); + dest->right = g_scan_expression_duplicate(src->right); } @@ -323,92 +327,110 @@ static GScanExpression *g_arithmetic_operation_duplicate(const GArithmOperation * * * 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_arithmetic_operation_reduce(GArithmOperation *expr, GScanContext *ctx, bool final) +static bool g_arithmetic_operation_reduce(GArithmOperation *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) */ + GLiteralExpression *op_left; /* Opérande gauche final */ + GLiteralExpression *op_right; /* Opérande droite final */ unsigned long long val_1; /* Première valeur à traiter */ - unsigned long long val_2; /* Second valeur à traiter */ - bool valid; /* Validité de ce bilan obtenu */ + unsigned long long val_2; /* Seconde valeur à traiter */ unsigned long long reduced; /* Valeur réduite finale */ - result = NULL; - /* Réduction des éléments considérés */ - new = g_scan_expression_reduce(expr->first, ctx, final); - - if (new != NULL) - { - g_object_unref(G_OBJECT(expr->first)); - expr->first = new; - } + new_left = NULL; + new_right = NULL; - if (expr->second != NULL) - { - new = g_scan_expression_reduce(expr->second, ctx, final); + result = g_scan_expression_reduce(expr->left, ctx, scope, &new_left); + if (!result) goto exit; - if (new != NULL) - { - g_object_unref(G_OBJECT(expr->second)); - expr->second = new; - } - - } + result = g_scan_expression_reduce(expr->right, ctx, scope, &new_right); + if (!result) goto exit; /* Construction d'une réduction locale ? */ - if (G_IS_LITERAL_EXPRESSION(expr->first) && G_IS_LITERAL_EXPRESSION(expr->second)) + if (G_IS_LITERAL_EXPRESSION(new_left) && G_IS_LITERAL_EXPRESSION(new_right)) { - valid = g_literal_expression_get_integer_value(G_LITERAL_EXPRESSION(expr->first), &val_1); + op_left = G_LITERAL_EXPRESSION(new_left); + op_right = G_LITERAL_EXPRESSION(new_right); - if (valid) - valid = g_literal_expression_get_integer_value(G_LITERAL_EXPRESSION(expr->second), &val_2); + result = g_literal_expression_get_integer_value(op_left, &val_1); + if (!result) goto exit; - if (valid) - switch (expr->operator) - { - case AEO_PLUS: - reduced = val_1 + val_2; - break; + result = g_literal_expression_get_integer_value(op_right, &val_2); + if (!result) goto exit; - case AEO_MINUS: - reduced = val_1 - val_2; - break; + switch (expr->operator) + { + case AEO_PLUS: + reduced = val_1 + val_2; + break; + + case AEO_MINUS: + reduced = val_1 - val_2; + break; + + case AEO_MUL: + reduced = val_1 * val_2; + break; + + case AEO_DIV: + result = (val_2 != 0); + if (result) + reduced = val_1 / val_2; + break; + + case AEO_MOD: + result = (val_2 != 0); + if (result) + reduced = val_1 % val_2; + break; - case AEO_MUL: - reduced = val_1 * val_2; - break; + } - case AEO_DIV: - valid = (val_2 != 0); - if (valid) - reduced = val_1 / val_2; - break; + if (result) + *out = g_literal_expression_new(EVT_INTEGER, &reduced); - case AEO_MOD: - valid = (val_2 != 0); - if (valid) - reduced = val_1 % val_2; - break; + } - } + /* Mise à jour de la progression ? */ - if (valid) - result = g_literal_expression_new(EVT_INTEGER, &reduced); + else if ((new_left != NULL && new_left != expr->left) || (new_right != NULL && new_right != expr->right)) + { + if (new_left == NULL) + { + new_left = expr->left; + g_object_ref(G_OBJECT(new_left)); + } + + if (new_right == NULL) + { + new_right = expr->right; + g_object_ref(G_OBJECT(new_right)); + } + + *out = g_arithmetic_operation_new(expr->operator, new_left, new_right); } + exit: + + g_clear_object(&new_left); + g_clear_object(&new_right); + return result; } |