Annotation of rpl/src/simplification.c, revision 1.62
1.1 bertrand 1: /*
2: ================================================================================
1.62 ! bertrand 3: RPL/2 (R) version 4.1.27
1.61 bertrand 4: Copyright (C) 1989-2017 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>