File:  [local] / rpl / src / simplification.c
Revision 1.50: download - view: text, annotated - select for diffs - revision graph
Mon Oct 13 07:12:54 2014 UTC (9 years, 6 months ago) by bertrand
Branches: MAIN
CVS tags: HEAD
Refonte des routines de simplification (non testées et marquées en
expérimental).

    1: /*
    2: ================================================================================
    3:   RPL/2 (R) version 4.1.19
    4:   Copyright (C) 1989-2014 Dr. BERTRAND Joël
    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: 
   23: #include "rpl-conv.h"
   24: 
   25: 
   26: /*
   27: ================================================================================
   28:   Fonction de transcription d'un arbre en liste chaînée
   29: ================================================================================
   30:   Entrées : pointeur sur une structure struct_processus
   31: --------------------------------------------------------------------------------
   32:   Sorties :
   33: --------------------------------------------------------------------------------
   34:   Effets de bord : néant
   35: ================================================================================
   36: */
   37: 
   38: static struct_liste_chainee *
   39: transcription_arbre(struct_processus *s_etat_processus, struct_arbre *s_arbre)
   40: {
   41:     integer8                i;
   42: 
   43:     struct_liste_chainee    *l_element_courant;
   44:     struct_liste_chainee    *l_liste;
   45:     struct_liste_chainee    *l_nouvelle_pile_locale;
   46:     struct_liste_chainee    *l_pile_locale;
   47: 
   48:     l_pile_locale = NULL;
   49: 
   50:     for(i = 0; i < (*s_arbre).nombre_branches; i++)
   51:     {
   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:         }
   58: 
   59:         (*l_nouvelle_pile_locale).suivant = l_pile_locale;
   60:         l_pile_locale = l_nouvelle_pile_locale;
   61: 
   62:         if (((*l_pile_locale).donnee = (void *) transcription_arbre(
   63:                 s_etat_processus, (*s_arbre).branches[i])) == NULL)
   64:         {
   65:             return(NULL);
   66:         }
   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:     }
   74: 
   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)
   90:         {
   91:             (*s_etat_processus).erreur_systeme = d_es_pile_vide;
   92:             return(NULL);
   93:         }
   94: 
   95:         while((*l_element_courant).suivant != NULL)
   96:         {
   97:             l_element_courant = (*l_element_courant).suivant;
   98:         }
   99: 
  100:         (*l_element_courant).suivant = l_liste;
  101:         l_liste = (void *) (*l_pile_locale).donnee;
  102: 
  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;
  106:     }
  107: 
  108:     return(l_liste);
  109: }
  110: 
  111: 
  112: /*
  113: ================================================================================
  114:   Fonction 'simplification' (ne libère pas les paramètres)
  115: ================================================================================
  116:   Entrées : pointeur sur une structure struct_processus
  117: --------------------------------------------------------------------------------
  118:   Sorties :
  119: --------------------------------------------------------------------------------
  120:   Effets de bord : néant
  121: ================================================================================
  122: */
  123: 
  124: struct_objet *
  125: simplification(struct_processus *s_etat_processus, struct_objet *s_objet)
  126: {
  127:     struct_objet                *s_objet_simplifie;
  128: 
  129: #   ifdef   EXPERIMENTAL_CODE 
  130: 
  131:     integer8                    i;
  132:     integer8                    nombre_arguments;
  133: 
  134:     struct_arbre                *s_arbre;
  135: 
  136:     struct_liste_chainee        *l_element_courant;
  137: 
  138:     // Attention : l_liste_locale et l_ancienne_liste_locale ne contiennent pas
  139:     // un pointeur sur une struct_objet, mais sur une struct_arbre.
  140: 
  141:     struct_liste_chainee        *l_liste_locale;
  142:     struct_liste_chainee        *l_ancienne_liste_locale;
  143: 
  144:     if ((*s_objet).type == ALG)
  145:     {
  146:         /*
  147:          * Transcription de l'expression algébrique en arbre q-aire
  148:          */
  149: 
  150:         l_liste_locale = NULL;
  151:         l_element_courant = (*s_objet).objet;
  152: 
  153:         while(l_element_courant != NULL)
  154:         {
  155:             switch((*(*l_element_courant).donnee).type)
  156:             {
  157:                 // Toutes les fonctions (intrinsèques, extrinsèques et
  158:                 // utilisateurs).
  159: 
  160:                 case FCT:
  161:                 {
  162:                     // Il s'agit d'un objet de type ALG. Nous pouvons donc
  163:                     // sauter les délimiteurs d'expression.
  164: 
  165:                     if ((l_element_courant != (*s_objet).objet) &&
  166:                             ((*l_element_courant).suivant != NULL))
  167:                     {
  168:                         nombre_arguments = (*((struct_fonction *)
  169:                                 (*(*l_element_courant).donnee).objet))
  170:                                 .nombre_arguments;
  171: 
  172:                         // Si le nombre d'arguments vaut 0, la fonction
  173:                         // apparaît en notation algébrique comme une fonction
  174:                         // infixe.
  175: 
  176:                         if (nombre_arguments == 0)
  177:                         {
  178:                             nombre_arguments = 2;
  179:                         }
  180: 
  181:                         if ((s_arbre = malloc(sizeof(struct_arbre))) == NULL)
  182:                         {
  183:                             (*s_etat_processus).erreur_systeme =
  184:                                     d_es_allocation_memoire;
  185:                             return(NULL);
  186:                         }
  187: 
  188:                         (*s_arbre).inversion = d_faux;
  189:                         (*s_arbre).nombre_branches = nombre_arguments;
  190: 
  191:                         if (((*s_arbre).branches = malloc(((size_t) (*s_arbre)
  192:                                 .nombre_branches) * sizeof(struct_arbre *)))
  193:                                 == NULL)
  194:                         {
  195:                             (*s_etat_processus).erreur_systeme =
  196:                                     d_es_allocation_memoire;
  197:                             return(NULL);
  198:                         }
  199: 
  200:                         for(i = 0; i < nombre_arguments; i++)
  201:                         {
  202:                             if (l_liste_locale == NULL)
  203:                             {
  204:                                 (*s_etat_processus).erreur_execution =
  205:                                         d_ex_manque_argument;
  206:                                 return(NULL);
  207:                             }
  208: 
  209:                             if (((*s_arbre).branches[i] = malloc(
  210:                                     sizeof(struct_arbre))) == NULL)
  211:                             {
  212:                                 (*s_etat_processus).erreur_systeme =
  213:                                         d_es_allocation_memoire;
  214:                                 return(NULL);
  215:                             }
  216: 
  217:                             (*(*s_arbre).branches[i]).feuille =
  218:                                     (*l_liste_locale).donnee;
  219:                             (*(*s_arbre).branches[i]).inversion = d_faux;
  220:                             (*(*s_arbre).branches[i]).nombre_branches = 0;
  221:                             (*(*s_arbre).branches[i]).branches = NULL;
  222: 
  223:                             l_ancienne_liste_locale = l_liste_locale;
  224:                             l_liste_locale = (*l_liste_locale).suivant;
  225: 
  226:                             liberation_maillon(s_etat_processus,
  227:                                     l_ancienne_liste_locale);
  228:                         }
  229: 
  230:                         // Introduction de l'arbre dans la pile locale
  231: 
  232:                         l_ancienne_liste_locale = l_liste_locale;
  233: 
  234:                         if ((l_liste_locale = allocation_maillon(
  235:                                 s_etat_processus)) == NULL)
  236:                         {
  237:                             (*s_etat_processus).erreur_systeme =
  238:                                     d_es_allocation_memoire;
  239:                             return(NULL);
  240:                         }
  241: 
  242:                         (*l_liste_locale).suivant = l_ancienne_liste_locale;
  243:                         (*l_liste_locale).donnee = (void *) s_arbre;
  244:                     }
  245: 
  246:                     break;
  247:                 }
  248: 
  249:                 default:
  250:                 {
  251:                     l_ancienne_liste_locale = l_liste_locale;
  252: 
  253:                     if ((l_liste_locale = allocation_maillon(s_etat_processus))
  254:                             == NULL)
  255:                     {
  256:                         (*s_etat_processus).erreur_systeme =
  257:                                 d_es_allocation_memoire;
  258:                         return(NULL);
  259:                     }
  260: 
  261:                     (*l_liste_locale).suivant = l_ancienne_liste_locale;
  262: 
  263:                     if ((s_arbre = malloc(sizeof(struct_arbre))) == NULL)
  264:                     {
  265:                         (*s_etat_processus).erreur_systeme =
  266:                                 d_es_allocation_memoire;
  267:                         return(NULL);
  268:                     }
  269: 
  270:                     (*s_arbre).feuille = copie_objet(s_etat_processus,
  271:                             (*l_element_courant).donnee, 'P');
  272:                     (*s_arbre).inversion = d_faux;
  273:                     (*s_arbre).nombre_branches = 0;
  274:                     (*s_arbre).branches = NULL;
  275: 
  276:                     (*l_liste_locale).donnee = (void *) s_arbre;
  277:                     break;
  278:                 }
  279:             }
  280: 
  281:             l_element_courant = (*l_element_courant).suivant;
  282:         }
  283: 
  284:         // Toute l'expression a été balayée. On ne doit plus avoir qu'un
  285:         // seul niveau dans la pile locale, ce niveau contenant l'arbre
  286:         // à réduire.
  287: 
  288:         if (l_liste_locale == NULL)
  289:         {
  290:             (*s_etat_processus).erreur_execution = d_ex_erreur_evaluation;
  291:             return(NULL);
  292:         }
  293:         else if ((*l_liste_locale).suivant != NULL)
  294:         {
  295:             (*s_etat_processus).erreur_execution = d_ex_erreur_evaluation;
  296:             return(NULL);
  297:         }
  298: 
  299:         s_arbre = (void *) (*l_liste_locale).donnee;
  300: 
  301:         liberation_maillon(s_etat_processus, l_liste_locale);
  302:         l_liste_locale = NULL;
  303: 
  304:         /*
  305:          * Simplification de l'arbre
  306:          */
  307: 
  308: #       if 0
  309:         simplification_arbre();
  310: #       endif
  311: 
  312:         /*
  313:          * Transcription de l'arbre q-aire simplifié en expression algébrique.
  314:          * Seule une fonction récursive permet de faire cette conversion
  315:          * simplement.
  316:          */
  317: 
  318:         l_liste_locale = transcription_arbre(s_etat_processus, s_arbre);
  319: 
  320:         if ((s_objet_simplifie = allocation(s_etat_processus, ALG))
  321:                 == NULL)
  322:         {
  323:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  324:             return(NULL);
  325:         }
  326: 
  327:         // Ajout des délimiteurs '<<' et '>>' à la liste d'instructions
  328: 
  329:         if (((*s_objet_simplifie).objet = allocation_maillon(s_etat_processus))
  330:                 == NULL)
  331:         {
  332:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  333:             return(NULL);
  334:         }
  335: 
  336:         l_element_courant = (*s_objet_simplifie).objet;
  337: 
  338:         if (((*l_element_courant).donnee = allocation(s_etat_processus,
  339:                 FCT)) == NULL)
  340:         {
  341:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  342:             return(NULL);
  343:         }
  344: 
  345:         (*((struct_fonction *) (*(*l_element_courant).donnee).objet))
  346:                 .nombre_arguments = 0;
  347:         (*((struct_fonction *) (*(*l_element_courant).donnee).objet))
  348:                 .fonction = instruction_vers_niveau_superieur;
  349: 
  350:         if (((*((struct_fonction *) (*(*l_element_courant).donnee).objet))
  351:                 .nom_fonction = malloc(3 * sizeof(unsigned char))) == NULL)
  352:         {
  353:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  354:             return(NULL);
  355:         }
  356: 
  357:         strcpy((*((struct_fonction *) (*(*l_element_courant).donnee).objet))
  358:                 .nom_fonction, "<<");
  359: 
  360:         (*l_element_courant).suivant = l_liste_locale;
  361: 
  362:         while((*l_element_courant).suivant != NULL)
  363:         {
  364:             l_element_courant = (*l_element_courant).suivant;
  365:         }
  366: 
  367:         if (((*l_element_courant).suivant =
  368:                 allocation_maillon(s_etat_processus)) == NULL)
  369:         {
  370:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  371:             return(NULL);
  372:         }
  373: 
  374:         l_element_courant = (*l_element_courant).suivant;
  375:         (*l_element_courant).suivant = NULL;
  376: 
  377:         if (((*l_element_courant).donnee = allocation(s_etat_processus,
  378:                 FCT)) == NULL)
  379:         {
  380:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  381:             return(NULL);
  382:         }
  383: 
  384:         (*((struct_fonction *) (*(*l_element_courant).donnee).objet))
  385:                 .nombre_arguments = 0;
  386:         (*((struct_fonction *) (*(*l_element_courant).donnee).objet))
  387:                 .fonction = instruction_vers_niveau_inferieur;
  388: 
  389:         if (((*((struct_fonction *) (*(*l_element_courant).donnee).objet))
  390:                 .nom_fonction = malloc(3 * sizeof(unsigned char))) == NULL)
  391:         {
  392:             (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
  393:             return(NULL);
  394:         }
  395: 
  396:         strcpy((*((struct_fonction *) (*(*l_element_courant).donnee).objet))
  397:                 .nom_fonction, ">>");
  398:     }
  399:     else
  400: #   endif
  401:     {
  402:         s_objet_simplifie = copie_objet(s_etat_processus, s_objet, 'P');
  403:     }
  404: 
  405:     return(s_objet_simplifie);
  406: }
  407: 
  408: // vim: ts=4

CVSweb interface <joel.bertrand@systella.fr>