Annotation of rpl/src/simplification.c, revision 1.50
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.50 ! bertrand 114: Fonction 'simplification' (ne libère pas les paramètres)
1.1 bertrand 115: ================================================================================
1.50 ! bertrand 116: Entrées : pointeur sur une structure struct_processus
1.1 bertrand 117: --------------------------------------------------------------------------------
118: Sorties :
119: --------------------------------------------------------------------------------
120: Effets de bord : néant
121: ================================================================================
122: */
123:
1.50 ! bertrand 124: struct_objet *
! 125: simplification(struct_processus *s_etat_processus, struct_objet *s_objet)
1.1 bertrand 126: {
1.50 ! bertrand 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.
1.1 bertrand 140:
1.50 ! bertrand 141: struct_liste_chainee *l_liste_locale;
! 142: struct_liste_chainee *l_ancienne_liste_locale;
1.1 bertrand 143:
1.50 ! bertrand 144: if ((*s_objet).type == ALG)
1.1 bertrand 145: {
1.50 ! bertrand 146: /*
! 147: * Transcription de l'expression algébrique en arbre q-aire
! 148: */
1.1 bertrand 149:
1.50 ! bertrand 150: l_liste_locale = NULL;
! 151: l_element_courant = (*s_objet).objet;
1.1 bertrand 152:
1.50 ! bertrand 153: while(l_element_courant != NULL)
1.1 bertrand 154: {
1.50 ! bertrand 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: }
1.1 bertrand 245:
1.50 ! bertrand 246: break;
! 247: }
1.1 bertrand 248:
1.50 ! bertrand 249: default:
1.1 bertrand 250: {
1.50 ! bertrand 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;
1.1 bertrand 278: }
279: }
1.50 ! bertrand 280:
! 281: l_element_courant = (*l_element_courant).suivant;
1.1 bertrand 282: }
283:
1.50 ! bertrand 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);
1.1 bertrand 319:
1.50 ! bertrand 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: }
1.1 bertrand 326:
1.50 ! bertrand 327: // Ajout des délimiteurs '<<' et '>>' à la liste d'instructions
1.1 bertrand 328:
1.50 ! bertrand 329: if (((*s_objet_simplifie).objet = allocation_maillon(s_etat_processus))
! 330: == NULL)
1.1 bertrand 331: {
1.50 ! bertrand 332: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
! 333: return(NULL);
! 334: }
1.1 bertrand 335:
1.50 ! bertrand 336: l_element_courant = (*s_objet_simplifie).objet;
1.1 bertrand 337:
1.50 ! bertrand 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);
1.1 bertrand 343: }
344:
1.50 ! bertrand 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;
1.1 bertrand 349:
1.50 ! bertrand 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: }
1.1 bertrand 356:
1.50 ! bertrand 357: strcpy((*((struct_fonction *) (*(*l_element_courant).donnee).objet))
! 358: .nom_fonction, "<<");
1.1 bertrand 359:
1.50 ! bertrand 360: (*l_element_courant).suivant = l_liste_locale;
1.1 bertrand 361:
1.50 ! bertrand 362: while((*l_element_courant).suivant != NULL)
1.1 bertrand 363: {
1.50 ! bertrand 364: l_element_courant = (*l_element_courant).suivant;
1.1 bertrand 365: }
366:
1.50 ! bertrand 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: }
1.1 bertrand 373:
1.50 ! bertrand 374: l_element_courant = (*l_element_courant).suivant;
! 375: (*l_element_courant).suivant = NULL;
1.1 bertrand 376:
1.50 ! bertrand 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: }
1.1 bertrand 383:
1.50 ! bertrand 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;
1.1 bertrand 388:
1.50 ! bertrand 389: if (((*((struct_fonction *) (*(*l_element_courant).donnee).objet))
! 390: .nom_fonction = malloc(3 * sizeof(unsigned char))) == NULL)
1.1 bertrand 391: {
1.50 ! bertrand 392: (*s_etat_processus).erreur_systeme = d_es_allocation_memoire;
! 393: return(NULL);
1.1 bertrand 394: }
1.50 ! bertrand 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');
1.1 bertrand 403: }
404:
1.50 ! bertrand 405: return(s_objet_simplifie);
1.1 bertrand 406: }
407:
408: // vim: ts=4
CVSweb interface <joel.bertrand@systella.fr>