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>