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

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: 
1.52    ! bertrand   69:    // Ajout des fonctions
1.1       bertrand   70: 
1.52    ! bertrand   71:    l_liste = (*s_arbre).feuille;
1.50      bertrand   72: 
                     73:    free((*s_arbre).branches);
                     74:    free(s_arbre);
                     75: 
                     76:    // Chaînage des arguments
                     77: 
                     78:    while(l_pile_locale != NULL)
                     79:    {
                     80:        l_element_courant = (void *) (*l_pile_locale).donnee;
                     81: 
                     82:        if (l_element_courant == NULL)
1.1       bertrand   83:        {
1.50      bertrand   84:            (*s_etat_processus).erreur_systeme = d_es_pile_vide;
1.1       bertrand   85:            return(NULL);
                     86:        }
                     87: 
1.50      bertrand   88:        while((*l_element_courant).suivant != NULL)
1.1       bertrand   89:        {
                     90:            l_element_courant = (*l_element_courant).suivant;
                     91:        }
                     92: 
1.50      bertrand   93:        (*l_element_courant).suivant = l_liste;
                     94:        l_liste = (void *) (*l_pile_locale).donnee;
1.1       bertrand   95: 
1.50      bertrand   96:        l_nouvelle_pile_locale = (*l_pile_locale).suivant;
                     97:        liberation_maillon(s_etat_processus, l_pile_locale);
                     98:        l_pile_locale = l_nouvelle_pile_locale;
1.1       bertrand   99:    }
                    100: 
1.50      bertrand  101:    return(l_liste);
1.1       bertrand  102: }
                    103: 
                    104: 
                    105: /*
                    106: ================================================================================
1.51      bertrand  107:   Fonction de simplification d'un arbre
                    108: ================================================================================
                    109:   Entrées : pointeur sur une structure struct_processus
                    110: --------------------------------------------------------------------------------
                    111:   Sorties :
                    112: --------------------------------------------------------------------------------
                    113:   Effets de bord : néant
                    114: ================================================================================
                    115: */
                    116: 
                    117: static void
                    118: inversion_fonctions_arbre(struct_arbre *s_arbre)
                    119: {
                    120:    return;
                    121: }
                    122: 
                    123: 
                    124: static void
                    125: simplification_arbre(struct_processus *s_etat_processus,
1.52    ! bertrand  126:        struct_arbre *s_arbre)
1.51      bertrand  127: {
1.52    ! bertrand  128:    integer8                i;
        !           129: 
        !           130:    if ((*(*(*s_arbre).feuille).donnee).type != FCT)
        !           131:    {
        !           132:        // L'objet formant le noeud n'est pas une fonction. Il n'y a aucune
        !           133:        // simplification possible.
        !           134: 
        !           135:        return;
        !           136:    }
        !           137: 
        !           138:    if ((strcmp((*((struct_fonction *) (*(*(*s_arbre).feuille).donnee).objet))
        !           139:            .nom_fonction, "+") == 0) || (strcmp((*((struct_fonction *)
        !           140:            (*(*(*s_arbre).feuille).donnee).objet)).nom_fonction, "-") == 0))
        !           141:    {
        !           142:        for(i = 0; i < (*s_arbre).nombre_branches; i++)
        !           143:        {
        !           144:        }
        !           145:    }
        !           146:    else if ((strcmp((*((struct_fonction *) (*(*(*s_arbre).feuille).donnee)
        !           147:            .objet)).nom_fonction, "*") == 0) || (strcmp((*((struct_fonction *)
        !           148:            (*(*(*s_arbre).feuille).donnee).objet)).nom_fonction, "/") == 0))
        !           149:    {
        !           150:        for(i = 0; i < (*s_arbre).nombre_branches; i++)
        !           151:        {
        !           152:        }
        !           153:    }
        !           154: 
1.51      bertrand  155:    return;
                    156: }
                    157: 
                    158: 
                    159: /*
                    160: ================================================================================
1.50      bertrand  161:   Fonction 'simplification' (ne libère pas les paramètres)
1.1       bertrand  162: ================================================================================
1.50      bertrand  163:   Entrées : pointeur sur une structure struct_processus
1.1       bertrand  164: --------------------------------------------------------------------------------
                    165:   Sorties :
                    166: --------------------------------------------------------------------------------
                    167:   Effets de bord : néant
                    168: ================================================================================
                    169: */
                    170: 
1.50      bertrand  171: struct_objet *
                    172: simplification(struct_processus *s_etat_processus, struct_objet *s_objet)
1.1       bertrand  173: {
1.50      bertrand  174:    struct_objet                *s_objet_simplifie;
                    175: 
                    176:    integer8                    i;
                    177:    integer8                    nombre_arguments;
                    178: 
                    179:    struct_arbre                *s_arbre;
                    180: 
                    181:    struct_liste_chainee        *l_element_courant;
                    182: 
                    183:    // Attention : l_liste_locale et l_ancienne_liste_locale ne contiennent pas
                    184:    // un pointeur sur une struct_objet, mais sur une struct_arbre.
1.1       bertrand  185: 
1.50      bertrand  186:    struct_liste_chainee        *l_liste_locale;
                    187:    struct_liste_chainee        *l_ancienne_liste_locale;
1.1       bertrand  188: 
1.50      bertrand  189:    if ((*s_objet).type == ALG)
1.1       bertrand  190:    {
1.50      bertrand  191:        /*
                    192:         * Transcription de l'expression algébrique en arbre q-aire
                    193:         */
1.1       bertrand  194: 
1.50      bertrand  195:        l_liste_locale = NULL;
                    196:        l_element_courant = (*s_objet).objet;
1.1       bertrand  197: 
1.50      bertrand  198:        while(l_element_courant != NULL)
1.1       bertrand  199:        {
1.50      bertrand  200:            switch((*(*l_element_courant).donnee).type)
                    201:            {
                    202:                // Toutes les fonctions (intrinsèques, extrinsèques et
                    203:                // utilisateurs).
                    204: 
                    205:                case FCT:
                    206:                {
                    207:                    // Il s'agit d'un objet de type ALG. Nous pouvons donc
                    208:                    // sauter les délimiteurs d'expression.
                    209: 
                    210:                    if ((l_element_courant != (*s_objet).objet) &&
                    211:                            ((*l_element_courant).suivant != NULL))
                    212:                    {
                    213:                        nombre_arguments = (*((struct_fonction *)
                    214:                                (*(*l_element_courant).donnee).objet))
                    215:                                .nombre_arguments;
                    216: 
                    217:                        // Si le nombre d'arguments vaut 0, la fonction
                    218:                        // apparaît en notation algébrique comme une fonction
                    219:                        // infixe.
                    220: 
                    221:                        if (nombre_arguments == 0)
                    222:                        {
                    223:                            nombre_arguments = 2;
                    224:                        }
                    225: 
                    226:                        if ((s_arbre = malloc(sizeof(struct_arbre))) == NULL)
                    227:                        {
                    228:                            (*s_etat_processus).erreur_systeme =
                    229:                                    d_es_allocation_memoire;
                    230:                            return(NULL);
                    231:                        }
                    232: 
                    233:                        (*s_arbre).nombre_branches = nombre_arguments;
1.52    ! bertrand  234: 
        !           235:                        if (((*s_arbre).feuille = allocation_maillon(
        !           236:                                s_etat_processus)) == NULL)
        !           237:                        {
        !           238:                            (*s_etat_processus).erreur_systeme =
        !           239:                                    d_es_allocation_memoire;
        !           240:                            return(NULL);
        !           241:                        }
        !           242: 
        !           243:                        (*(*s_arbre).feuille).donnee = copie_objet(
        !           244:                                s_etat_processus, (*l_element_courant).donnee,
        !           245:                                'P');
        !           246:                        (*(*s_arbre).feuille).suivant = NULL;
1.50      bertrand  247: 
                    248:                        if (((*s_arbre).branches = malloc(((size_t) (*s_arbre)
                    249:                                .nombre_branches) * sizeof(struct_arbre *)))
                    250:                                == NULL)
                    251:                        {
                    252:                            (*s_etat_processus).erreur_systeme =
                    253:                                    d_es_allocation_memoire;
                    254:                            return(NULL);
                    255:                        }
                    256: 
1.51      bertrand  257:                        for(i = nombre_arguments - 1; i >= 0; i--)
1.50      bertrand  258:                        {
                    259:                            if (l_liste_locale == NULL)
                    260:                            {
                    261:                                (*s_etat_processus).erreur_execution =
                    262:                                        d_ex_manque_argument;
                    263:                                return(NULL);
                    264:                            }
                    265: 
1.51      bertrand  266:                            (*s_arbre).branches[i] = (struct_arbre *)
1.50      bertrand  267:                                    (*l_liste_locale).donnee;
                    268: 
                    269:                            l_ancienne_liste_locale = l_liste_locale;
                    270:                            l_liste_locale = (*l_liste_locale).suivant;
                    271: 
                    272:                            liberation_maillon(s_etat_processus,
                    273:                                    l_ancienne_liste_locale);
                    274:                        }
                    275: 
                    276:                        // Introduction de l'arbre dans la pile locale
                    277: 
                    278:                        l_ancienne_liste_locale = l_liste_locale;
                    279: 
                    280:                        if ((l_liste_locale = allocation_maillon(
                    281:                                s_etat_processus)) == NULL)
                    282:                        {
                    283:                            (*s_etat_processus).erreur_systeme =
                    284:                                    d_es_allocation_memoire;
                    285:                            return(NULL);
                    286:                        }
                    287: 
                    288:                        (*l_liste_locale).suivant = l_ancienne_liste_locale;
                    289:                        (*l_liste_locale).donnee = (void *) s_arbre;
                    290:                    }
1.1       bertrand  291: 
1.50      bertrand  292:                    break;
                    293:                }
1.1       bertrand  294: 
1.50      bertrand  295:                default:
1.1       bertrand  296:                {
1.50      bertrand  297:                    l_ancienne_liste_locale = l_liste_locale;
                    298: 
                    299:                    if ((l_liste_locale = allocation_maillon(s_etat_processus))
                    300:                            == NULL)
                    301:                    {
                    302:                        (*s_etat_processus).erreur_systeme =
                    303:                                d_es_allocation_memoire;
                    304:                        return(NULL);
                    305:                    }
                    306: 
                    307:                    (*l_liste_locale).suivant = l_ancienne_liste_locale;
                    308: 
                    309:                    if ((s_arbre = malloc(sizeof(struct_arbre))) == NULL)
                    310:                    {
                    311:                        (*s_etat_processus).erreur_systeme =
                    312:                                d_es_allocation_memoire;
                    313:                        return(NULL);
                    314:                    }
                    315: 
1.52    ! bertrand  316:                    if (((*s_arbre).feuille = allocation_maillon(
        !           317:                            s_etat_processus)) == NULL)
        !           318:                    {
        !           319:                        (*s_etat_processus).erreur_systeme =
        !           320:                                d_es_allocation_memoire;
        !           321:                        return(NULL);
        !           322:                    }
        !           323: 
        !           324:                    (*(*s_arbre).feuille).donnee = copie_objet(
        !           325:                            s_etat_processus, (*l_element_courant).donnee, 'P');
        !           326:                    (*(*s_arbre).feuille).suivant = NULL;
1.50      bertrand  327:                    (*s_arbre).nombre_branches = 0;
                    328:                    (*s_arbre).branches = NULL;
                    329: 
                    330:                    (*l_liste_locale).donnee = (void *) s_arbre;
                    331:                    break;
1.1       bertrand  332:                }
                    333:            }
1.50      bertrand  334: 
                    335:            l_element_courant = (*l_element_courant).suivant;
1.1       bertrand  336:        }
                    337: 
1.50      bertrand  338:        // Toute l'expression a été balayée. On ne doit plus avoir qu'un
                    339:        // seul niveau dans la pile locale, ce niveau contenant l'arbre
                    340:        // à réduire.
                    341: 
                    342:        if (l_liste_locale == NULL)
                    343:        {
                    344:            (*s_etat_processus).erreur_execution = d_ex_erreur_evaluation;
                    345:            return(NULL);
                    346:        }
                    347:        else if ((*l_liste_locale).suivant != NULL)
                    348:        {
                    349:            (*s_etat_processus).erreur_execution = d_ex_erreur_evaluation;
                    350:            return(NULL);
                    351:        }
                    352: 
                    353:        s_arbre = (void *) (*l_liste_locale).donnee;
                    354: 
                    355:        liberation_maillon(s_etat_processus, l_liste_locale);
                    356:        l_liste_locale = NULL;
                    357: 
                    358:        /*
                    359:         * Simplification de l'arbre
                    360:         */
                    361: 
1.51      bertrand  362: #      ifdef   EXPERIMENTAL_CODE 
1.52    ! bertrand  363:        simplification_arbre(s_etat_processus, s_arbre);
1.51      bertrand  364: 
                    365:        if ((*s_etat_processus).erreur_systeme != d_es)
                    366:        {
                    367:            return(NULL);
                    368:        }
1.50      bertrand  369: #      endif
                    370: 
                    371:        /*
                    372:         * Transcription de l'arbre q-aire simplifié en expression algébrique.
                    373:         * Seule une fonction récursive permet de faire cette conversion
                    374:         * simplement.
                    375:         */
                    376: 
                    377:        l_liste_locale = transcription_arbre(s_etat_processus, s_arbre);
1.1       bertrand  378: 
1.50      bertrand  379:        if ((s_objet_simplifie = allocation(s_etat_processus, ALG))
                    380:                == NULL)
                    381:        {
                    382:            (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                    383:            return(NULL);
                    384:        }
1.1       bertrand  385: 
1.50      bertrand  386:        // Ajout des délimiteurs '<<' et '>>' à la liste d'instructions
1.1       bertrand  387: 
1.50      bertrand  388:        if (((*s_objet_simplifie).objet = allocation_maillon(s_etat_processus))
                    389:                == NULL)
1.1       bertrand  390:        {
1.50      bertrand  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 = (*s_objet_simplifie).objet;
1.1       bertrand  396: 
1.50      bertrand  397:        if (((*l_element_courant).donnee = allocation(s_etat_processus,
                    398:                FCT)) == NULL)
                    399:        {
                    400:            (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                    401:            return(NULL);
1.1       bertrand  402:        }
                    403: 
1.50      bertrand  404:        (*((struct_fonction *) (*(*l_element_courant).donnee).objet))
                    405:                .nombre_arguments = 0;
                    406:        (*((struct_fonction *) (*(*l_element_courant).donnee).objet))
                    407:                .fonction = instruction_vers_niveau_superieur;
1.1       bertrand  408: 
1.50      bertrand  409:        if (((*((struct_fonction *) (*(*l_element_courant).donnee).objet))
                    410:                .nom_fonction = malloc(3 * sizeof(unsigned char))) == NULL)
                    411:        {
                    412:            (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                    413:            return(NULL);
                    414:        }
1.1       bertrand  415: 
1.50      bertrand  416:        strcpy((*((struct_fonction *) (*(*l_element_courant).donnee).objet))
                    417:                .nom_fonction, "<<");
1.1       bertrand  418: 
1.50      bertrand  419:        (*l_element_courant).suivant = l_liste_locale;
1.1       bertrand  420: 
1.50      bertrand  421:        while((*l_element_courant).suivant != NULL)
1.1       bertrand  422:        {
1.50      bertrand  423:            l_element_courant = (*l_element_courant).suivant;
1.1       bertrand  424:        }
                    425: 
1.50      bertrand  426:        if (((*l_element_courant).suivant =
                    427:                allocation_maillon(s_etat_processus)) == NULL)
                    428:        {
                    429:            (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                    430:            return(NULL);
                    431:        }
1.1       bertrand  432: 
1.50      bertrand  433:        l_element_courant = (*l_element_courant).suivant;
                    434:        (*l_element_courant).suivant = NULL;
1.1       bertrand  435: 
1.50      bertrand  436:        if (((*l_element_courant).donnee = allocation(s_etat_processus,
                    437:                FCT)) == NULL)
                    438:        {
                    439:            (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                    440:            return(NULL);
                    441:        }
1.1       bertrand  442: 
1.50      bertrand  443:        (*((struct_fonction *) (*(*l_element_courant).donnee).objet))
                    444:                .nombre_arguments = 0;
                    445:        (*((struct_fonction *) (*(*l_element_courant).donnee).objet))
                    446:                .fonction = instruction_vers_niveau_inferieur;
1.1       bertrand  447: 
1.50      bertrand  448:        if (((*((struct_fonction *) (*(*l_element_courant).donnee).objet))
                    449:                .nom_fonction = malloc(3 * sizeof(unsigned char))) == NULL)
1.1       bertrand  450:        {
1.50      bertrand  451:            (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
                    452:            return(NULL);
1.1       bertrand  453:        }
1.50      bertrand  454: 
                    455:        strcpy((*((struct_fonction *) (*(*l_element_courant).donnee).objet))
                    456:                .nom_fonction, ">>");
                    457:    }
                    458:    else
                    459:    {
                    460:        s_objet_simplifie = copie_objet(s_etat_processus, s_objet, 'P');
1.1       bertrand  461:    }
                    462: 
1.50      bertrand  463:    return(s_objet_simplifie);
1.1       bertrand  464: }
                    465: 
                    466: // vim: ts=4

CVSweb interface <joel.bertrand@systella.fr>