Annotation of rpl/src/simplification.c, revision 1.51

1.1       bertrand    1: /*
                      2: ================================================================================
1.49      bertrand    3:   RPL/2 (R) version 4.1.19
1.47      bertrand    4:   Copyright (C) 1989-2014 Dr. BERTRAND Joël
1.1       bertrand    5: 
                      6:   This file is part of RPL/2.
                      7: 
                      8:   RPL/2 is free software; you can redistribute it and/or modify it
                      9:   under the terms of the CeCILL V2 License as published by the french
                     10:   CEA, CNRS and INRIA.
                     11:  
                     12:   RPL/2 is distributed in the hope that it will be useful, but WITHOUT
                     13:   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
                     14:   FITNESS FOR A PARTICULAR PURPOSE.  See the CeCILL V2 License
                     15:   for more details.
                     16:  
                     17:   You should have received a copy of the CeCILL License
                     18:   along with RPL/2. If not, write to info@cecill.info.
                     19: ================================================================================
                     20: */
                     21: 
                     22: 
1.11      bertrand   23: #include "rpl-conv.h"
1.1       bertrand   24: 
                     25: 
                     26: /*
                     27: ================================================================================
1.50      bertrand   28:   Fonction de transcription d'un arbre en liste chaînée
1.1       bertrand   29: ================================================================================
                     30:   Entrées : pointeur sur une structure struct_processus
                     31: --------------------------------------------------------------------------------
                     32:   Sorties :
                     33: --------------------------------------------------------------------------------
                     34:   Effets de bord : néant
                     35: ================================================================================
                     36: */
                     37: 
1.50      bertrand   38: static struct_liste_chainee *
                     39: transcription_arbre(struct_processus *s_etat_processus, struct_arbre *s_arbre)
1.1       bertrand   40: {
1.50      bertrand   41:    integer8                i;
1.1       bertrand   42: 
                     43:    struct_liste_chainee    *l_element_courant;
1.50      bertrand   44:    struct_liste_chainee    *l_liste;
                     45:    struct_liste_chainee    *l_nouvelle_pile_locale;
                     46:    struct_liste_chainee    *l_pile_locale;
1.1       bertrand   47: 
1.50      bertrand   48:    l_pile_locale = NULL;
1.1       bertrand   49: 
1.50      bertrand   50:    for(i = 0; i < (*s_arbre).nombre_branches; i++)
1.1       bertrand   51:    {
1.50      bertrand   52:        if ((l_nouvelle_pile_locale = allocation_maillon(s_etat_processus))
                     53:                == NULL)
                     54:        {
                     55:            (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                     56:            return(NULL);
                     57:        }
1.1       bertrand   58: 
1.50      bertrand   59:        (*l_nouvelle_pile_locale).suivant = l_pile_locale;
                     60:        l_pile_locale = l_nouvelle_pile_locale;
1.1       bertrand   61: 
1.50      bertrand   62:        if (((*l_pile_locale).donnee = (void *) transcription_arbre(
                     63:                s_etat_processus, (*s_arbre).branches[i])) == NULL)
1.1       bertrand   64:        {
1.50      bertrand   65:            return(NULL);
1.1       bertrand   66:        }
1.50      bertrand   67:    }
                     68: 
                     69:    if ((l_liste = allocation_maillon(s_etat_processus)) == NULL)
                     70:    {
                     71:        (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                     72:        return(NULL);
                     73:    }
1.1       bertrand   74: 
1.50      bertrand   75:    // Ajout de la fonction
                     76: 
                     77:    (*l_liste).suivant = NULL;
                     78:    (*l_liste).donnee = (*s_arbre).feuille;
                     79: 
                     80:    free((*s_arbre).branches);
                     81:    free(s_arbre);
                     82: 
                     83:    // Chaînage des arguments
                     84: 
                     85:    while(l_pile_locale != NULL)
                     86:    {
                     87:        l_element_courant = (void *) (*l_pile_locale).donnee;
                     88: 
                     89:        if (l_element_courant == NULL)
1.1       bertrand   90:        {
1.50      bertrand   91:            (*s_etat_processus).erreur_systeme = d_es_pile_vide;
1.1       bertrand   92:            return(NULL);
                     93:        }
                     94: 
1.50      bertrand   95:        while((*l_element_courant).suivant != NULL)
1.1       bertrand   96:        {
                     97:            l_element_courant = (*l_element_courant).suivant;
                     98:        }
                     99: 
1.50      bertrand  100:        (*l_element_courant).suivant = l_liste;
                    101:        l_liste = (void *) (*l_pile_locale).donnee;
1.1       bertrand  102: 
1.50      bertrand  103:        l_nouvelle_pile_locale = (*l_pile_locale).suivant;
                    104:        liberation_maillon(s_etat_processus, l_pile_locale);
                    105:        l_pile_locale = l_nouvelle_pile_locale;
1.1       bertrand  106:    }
                    107: 
1.50      bertrand  108:    return(l_liste);
1.1       bertrand  109: }
                    110: 
                    111: 
                    112: /*
                    113: ================================================================================
1.51    ! bertrand  114:   Fonction de simplification d'un arbre
        !           115: ================================================================================
        !           116:   Entrées : pointeur sur une structure struct_processus
        !           117: --------------------------------------------------------------------------------
        !           118:   Sorties :
        !           119: --------------------------------------------------------------------------------
        !           120:   Effets de bord : néant
        !           121: ================================================================================
        !           122: */
        !           123: 
        !           124: static void
        !           125: inversion_fonctions_arbre(struct_arbre *s_arbre)
        !           126: {
        !           127:    return;
        !           128: }
        !           129: 
        !           130: 
        !           131: static void
        !           132: simplification_arbre(struct_processus *s_etat_processus,
        !           133:        struct_arbre **s_arbre)
        !           134: {
        !           135:    return;
        !           136: }
        !           137: 
        !           138: 
        !           139: /*
        !           140: ================================================================================
1.50      bertrand  141:   Fonction 'simplification' (ne libère pas les paramètres)
1.1       bertrand  142: ================================================================================
1.50      bertrand  143:   Entrées : pointeur sur une structure struct_processus
1.1       bertrand  144: --------------------------------------------------------------------------------
                    145:   Sorties :
                    146: --------------------------------------------------------------------------------
                    147:   Effets de bord : néant
                    148: ================================================================================
                    149: */
                    150: 
1.50      bertrand  151: struct_objet *
                    152: simplification(struct_processus *s_etat_processus, struct_objet *s_objet)
1.1       bertrand  153: {
1.50      bertrand  154:    struct_objet                *s_objet_simplifie;
                    155: 
                    156:    integer8                    i;
                    157:    integer8                    nombre_arguments;
                    158: 
                    159:    struct_arbre                *s_arbre;
                    160: 
                    161:    struct_liste_chainee        *l_element_courant;
                    162: 
                    163:    // Attention : l_liste_locale et l_ancienne_liste_locale ne contiennent pas
                    164:    // un pointeur sur une struct_objet, mais sur une struct_arbre.
1.1       bertrand  165: 
1.50      bertrand  166:    struct_liste_chainee        *l_liste_locale;
                    167:    struct_liste_chainee        *l_ancienne_liste_locale;
1.1       bertrand  168: 
1.50      bertrand  169:    if ((*s_objet).type == ALG)
1.1       bertrand  170:    {
1.50      bertrand  171:        /*
                    172:         * Transcription de l'expression algébrique en arbre q-aire
                    173:         */
1.1       bertrand  174: 
1.50      bertrand  175:        l_liste_locale = NULL;
                    176:        l_element_courant = (*s_objet).objet;
1.1       bertrand  177: 
1.50      bertrand  178:        while(l_element_courant != NULL)
1.1       bertrand  179:        {
1.50      bertrand  180:            switch((*(*l_element_courant).donnee).type)
                    181:            {
                    182:                // Toutes les fonctions (intrinsèques, extrinsèques et
                    183:                // utilisateurs).
                    184: 
                    185:                case FCT:
                    186:                {
                    187:                    // Il s'agit d'un objet de type ALG. Nous pouvons donc
                    188:                    // sauter les délimiteurs d'expression.
                    189: 
                    190:                    if ((l_element_courant != (*s_objet).objet) &&
                    191:                            ((*l_element_courant).suivant != NULL))
                    192:                    {
                    193:                        nombre_arguments = (*((struct_fonction *)
                    194:                                (*(*l_element_courant).donnee).objet))
                    195:                                .nombre_arguments;
                    196: 
                    197:                        // Si le nombre d'arguments vaut 0, la fonction
                    198:                        // apparaît en notation algébrique comme une fonction
                    199:                        // infixe.
                    200: 
                    201:                        if (nombre_arguments == 0)
                    202:                        {
                    203:                            nombre_arguments = 2;
                    204:                        }
                    205: 
                    206:                        if ((s_arbre = malloc(sizeof(struct_arbre))) == NULL)
                    207:                        {
                    208:                            (*s_etat_processus).erreur_systeme =
                    209:                                    d_es_allocation_memoire;
                    210:                            return(NULL);
                    211:                        }
                    212: 
                    213:                        (*s_arbre).inversion = d_faux;
                    214:                        (*s_arbre).nombre_branches = nombre_arguments;
1.51    ! bertrand  215:                        (*s_arbre).feuille = copie_objet(s_etat_processus,
        !           216:                                (*l_element_courant).donnee, 'P');
1.50      bertrand  217: 
                    218:                        if (((*s_arbre).branches = malloc(((size_t) (*s_arbre)
                    219:                                .nombre_branches) * sizeof(struct_arbre *)))
                    220:                                == NULL)
                    221:                        {
                    222:                            (*s_etat_processus).erreur_systeme =
                    223:                                    d_es_allocation_memoire;
                    224:                            return(NULL);
                    225:                        }
                    226: 
1.51    ! bertrand  227:                        for(i = nombre_arguments - 1; i >= 0; i--)
1.50      bertrand  228:                        {
                    229:                            if (l_liste_locale == NULL)
                    230:                            {
                    231:                                (*s_etat_processus).erreur_execution =
                    232:                                        d_ex_manque_argument;
                    233:                                return(NULL);
                    234:                            }
                    235: 
1.51    ! bertrand  236:                            (*s_arbre).branches[i] = (struct_arbre *)
1.50      bertrand  237:                                    (*l_liste_locale).donnee;
                    238: 
                    239:                            l_ancienne_liste_locale = l_liste_locale;
                    240:                            l_liste_locale = (*l_liste_locale).suivant;
                    241: 
                    242:                            liberation_maillon(s_etat_processus,
                    243:                                    l_ancienne_liste_locale);
                    244:                        }
                    245: 
                    246:                        // Introduction de l'arbre dans la pile locale
                    247: 
                    248:                        l_ancienne_liste_locale = l_liste_locale;
                    249: 
                    250:                        if ((l_liste_locale = allocation_maillon(
                    251:                                s_etat_processus)) == NULL)
                    252:                        {
                    253:                            (*s_etat_processus).erreur_systeme =
                    254:                                    d_es_allocation_memoire;
                    255:                            return(NULL);
                    256:                        }
                    257: 
                    258:                        (*l_liste_locale).suivant = l_ancienne_liste_locale;
                    259:                        (*l_liste_locale).donnee = (void *) s_arbre;
                    260:                    }
1.1       bertrand  261: 
1.50      bertrand  262:                    break;
                    263:                }
1.1       bertrand  264: 
1.50      bertrand  265:                default:
1.1       bertrand  266:                {
1.50      bertrand  267:                    l_ancienne_liste_locale = l_liste_locale;
                    268: 
                    269:                    if ((l_liste_locale = allocation_maillon(s_etat_processus))
                    270:                            == NULL)
                    271:                    {
                    272:                        (*s_etat_processus).erreur_systeme =
                    273:                                d_es_allocation_memoire;
                    274:                        return(NULL);
                    275:                    }
                    276: 
                    277:                    (*l_liste_locale).suivant = l_ancienne_liste_locale;
                    278: 
                    279:                    if ((s_arbre = malloc(sizeof(struct_arbre))) == NULL)
                    280:                    {
                    281:                        (*s_etat_processus).erreur_systeme =
                    282:                                d_es_allocation_memoire;
                    283:                        return(NULL);
                    284:                    }
                    285: 
                    286:                    (*s_arbre).feuille = copie_objet(s_etat_processus,
                    287:                            (*l_element_courant).donnee, 'P');
                    288:                    (*s_arbre).inversion = d_faux;
                    289:                    (*s_arbre).nombre_branches = 0;
                    290:                    (*s_arbre).branches = NULL;
                    291: 
                    292:                    (*l_liste_locale).donnee = (void *) s_arbre;
                    293:                    break;
1.1       bertrand  294:                }
                    295:            }
1.50      bertrand  296: 
                    297:            l_element_courant = (*l_element_courant).suivant;
1.1       bertrand  298:        }
                    299: 
1.50      bertrand  300:        // Toute l'expression a été balayée. On ne doit plus avoir qu'un
                    301:        // seul niveau dans la pile locale, ce niveau contenant l'arbre
                    302:        // à réduire.
                    303: 
                    304:        if (l_liste_locale == NULL)
                    305:        {
                    306:            (*s_etat_processus).erreur_execution = d_ex_erreur_evaluation;
                    307:            return(NULL);
                    308:        }
                    309:        else if ((*l_liste_locale).suivant != NULL)
                    310:        {
                    311:            (*s_etat_processus).erreur_execution = d_ex_erreur_evaluation;
                    312:            return(NULL);
                    313:        }
                    314: 
                    315:        s_arbre = (void *) (*l_liste_locale).donnee;
                    316: 
                    317:        liberation_maillon(s_etat_processus, l_liste_locale);
                    318:        l_liste_locale = NULL;
                    319: 
                    320:        /*
                    321:         * Simplification de l'arbre
                    322:         */
                    323: 
1.51    ! bertrand  324: #      ifdef   EXPERIMENTAL_CODE 
        !           325:        simplification_arbre(s_etat_processus, &s_arbre);
        !           326: 
        !           327:        if ((*s_etat_processus).erreur_systeme != d_es)
        !           328:        {
        !           329:            return(NULL);
        !           330:        }
1.50      bertrand  331: #      endif
                    332: 
                    333:        /*
                    334:         * Transcription de l'arbre q-aire simplifié en expression algébrique.
                    335:         * Seule une fonction récursive permet de faire cette conversion
                    336:         * simplement.
                    337:         */
                    338: 
                    339:        l_liste_locale = transcription_arbre(s_etat_processus, s_arbre);
1.1       bertrand  340: 
1.50      bertrand  341:        if ((s_objet_simplifie = allocation(s_etat_processus, ALG))
                    342:                == NULL)
                    343:        {
                    344:            (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                    345:            return(NULL);
                    346:        }
1.1       bertrand  347: 
1.50      bertrand  348:        // Ajout des délimiteurs '<<' et '>>' à la liste d'instructions
1.1       bertrand  349: 
1.50      bertrand  350:        if (((*s_objet_simplifie).objet = allocation_maillon(s_etat_processus))
                    351:                == NULL)
1.1       bertrand  352:        {
1.50      bertrand  353:            (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                    354:            return(NULL);
                    355:        }
1.1       bertrand  356: 
1.50      bertrand  357:        l_element_courant = (*s_objet_simplifie).objet;
1.1       bertrand  358: 
1.50      bertrand  359:        if (((*l_element_courant).donnee = allocation(s_etat_processus,
                    360:                FCT)) == NULL)
                    361:        {
                    362:            (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                    363:            return(NULL);
1.1       bertrand  364:        }
                    365: 
1.50      bertrand  366:        (*((struct_fonction *) (*(*l_element_courant).donnee).objet))
                    367:                .nombre_arguments = 0;
                    368:        (*((struct_fonction *) (*(*l_element_courant).donnee).objet))
                    369:                .fonction = instruction_vers_niveau_superieur;
1.1       bertrand  370: 
1.50      bertrand  371:        if (((*((struct_fonction *) (*(*l_element_courant).donnee).objet))
                    372:                .nom_fonction = malloc(3 * sizeof(unsigned char))) == NULL)
                    373:        {
                    374:            (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                    375:            return(NULL);
                    376:        }
1.1       bertrand  377: 
1.50      bertrand  378:        strcpy((*((struct_fonction *) (*(*l_element_courant).donnee).objet))
                    379:                .nom_fonction, "<<");
1.1       bertrand  380: 
1.50      bertrand  381:        (*l_element_courant).suivant = l_liste_locale;
1.1       bertrand  382: 
1.50      bertrand  383:        while((*l_element_courant).suivant != NULL)
1.1       bertrand  384:        {
1.50      bertrand  385:            l_element_courant = (*l_element_courant).suivant;
1.1       bertrand  386:        }
                    387: 
1.50      bertrand  388:        if (((*l_element_courant).suivant =
                    389:                allocation_maillon(s_etat_processus)) == NULL)
                    390:        {
                    391:            (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                    392:            return(NULL);
                    393:        }
1.1       bertrand  394: 
1.50      bertrand  395:        l_element_courant = (*l_element_courant).suivant;
                    396:        (*l_element_courant).suivant = NULL;
1.1       bertrand  397: 
1.50      bertrand  398:        if (((*l_element_courant).donnee = allocation(s_etat_processus,
                    399:                FCT)) == NULL)
                    400:        {
                    401:            (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                    402:            return(NULL);
                    403:        }
1.1       bertrand  404: 
1.50      bertrand  405:        (*((struct_fonction *) (*(*l_element_courant).donnee).objet))
                    406:                .nombre_arguments = 0;
                    407:        (*((struct_fonction *) (*(*l_element_courant).donnee).objet))
                    408:                .fonction = instruction_vers_niveau_inferieur;
1.1       bertrand  409: 
1.50      bertrand  410:        if (((*((struct_fonction *) (*(*l_element_courant).donnee).objet))
                    411:                .nom_fonction = malloc(3 * sizeof(unsigned char))) == NULL)
1.1       bertrand  412:        {
1.50      bertrand  413:            (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                    414:            return(NULL);
1.1       bertrand  415:        }
1.50      bertrand  416: 
                    417:        strcpy((*((struct_fonction *) (*(*l_element_courant).donnee).objet))
                    418:                .nom_fonction, ">>");
                    419:    }
                    420:    else
                    421:    {
                    422:        s_objet_simplifie = copie_objet(s_etat_processus, s_objet, 'P');
1.1       bertrand  423:    }
                    424: 
1.50      bertrand  425:    return(s_objet_simplifie);
1.1       bertrand  426: }
                    427: 
                    428: // vim: ts=4

CVSweb interface <joel.bertrand@systella.fr>