diff options
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;  } | 
