/* ================================================================================ RPL/2 (R) version 4.1.22 Copyright (C) 1989-2015 Dr. BERTRAND Joël This file is part of RPL/2. RPL/2 is free software; you can redistribute it and/or modify it under the terms of the CeCILL V2 License as published by the french CEA, CNRS and INRIA. RPL/2 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the CeCILL V2 License for more details. You should have received a copy of the CeCILL License along with RPL/2. If not, write to info@cecill.info. ================================================================================ */ #include "rpl-conv.h" /* ================================================================================ Fonction de transcription d'un arbre en liste chaînée ================================================================================ Entrées : pointeur sur une structure struct_processus -------------------------------------------------------------------------------- Sorties : -------------------------------------------------------------------------------- Effets de bord : néant ================================================================================ */ static struct_liste_chainee * transcription_arbre(struct_processus *s_etat_processus, struct_arbre *s_arbre) { integer8 i; struct_liste_chainee *l_element_courant; struct_liste_chainee *l_liste; struct_liste_chainee *l_nouvelle_pile_locale; struct_liste_chainee *l_pile_locale; l_pile_locale = NULL; for(i = 0; i < (*s_arbre).nombre_branches; i++) { if ((l_nouvelle_pile_locale = allocation_maillon(s_etat_processus)) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(NULL); } (*l_nouvelle_pile_locale).suivant = l_pile_locale; l_pile_locale = l_nouvelle_pile_locale; if (((*l_pile_locale).donnee = (void *) transcription_arbre( s_etat_processus, (*s_arbre).branches[i])) == NULL) { return(NULL); } } // Ajout des fonctions l_liste = (*s_arbre).feuille; free((*s_arbre).branches); free(s_arbre); // Chaînage des arguments while(l_pile_locale != NULL) { l_element_courant = (void *) (*l_pile_locale).donnee; if (l_element_courant == NULL) { (*s_etat_processus).erreur_systeme = d_es_pile_vide; return(NULL); } while((*l_element_courant).suivant != NULL) { l_element_courant = (*l_element_courant).suivant; } (*l_element_courant).suivant = l_liste; l_liste = (void *) (*l_pile_locale).donnee; l_nouvelle_pile_locale = (*l_pile_locale).suivant; liberation_maillon(s_etat_processus, l_pile_locale); l_pile_locale = l_nouvelle_pile_locale; } return(l_liste); } /* ================================================================================ Fonction de simplification d'un arbre ================================================================================ Entrées : pointeur sur une structure struct_processus -------------------------------------------------------------------------------- Sorties : -------------------------------------------------------------------------------- Effets de bord : néant ================================================================================ */ static void inversion_fonctions_arbre(struct_arbre *s_arbre) { return; } static void simplification_arbre(struct_processus *s_etat_processus, struct_arbre *s_arbre) { integer8 i; if ((*(*(*s_arbre).feuille).donnee).type != FCT) { // L'objet formant le noeud n'est pas une fonction. Il n'y a aucune // simplification possible. return; } if ((strcmp((*((struct_fonction *) (*(*(*s_arbre).feuille).donnee).objet)) .nom_fonction, "+") == 0) || (strcmp((*((struct_fonction *) (*(*(*s_arbre).feuille).donnee).objet)).nom_fonction, "-") == 0)) { for(i = 0; i < (*s_arbre).nombre_branches; i++) { } } else if ((strcmp((*((struct_fonction *) (*(*(*s_arbre).feuille).donnee) .objet)).nom_fonction, "*") == 0) || (strcmp((*((struct_fonction *) (*(*(*s_arbre).feuille).donnee).objet)).nom_fonction, "/") == 0)) { for(i = 0; i < (*s_arbre).nombre_branches; i++) { } } return; } /* ================================================================================ Fonction 'simplification' (ne libère pas les paramètres) ================================================================================ Entrées : pointeur sur une structure struct_processus -------------------------------------------------------------------------------- Sorties : -------------------------------------------------------------------------------- Effets de bord : néant ================================================================================ */ struct_objet * simplification(struct_processus *s_etat_processus, struct_objet *s_objet) { struct_objet *s_objet_simplifie; integer8 i; integer8 nombre_arguments; struct_arbre *s_arbre; struct_liste_chainee *l_element_courant; // Attention : l_liste_locale et l_ancienne_liste_locale ne contiennent pas // un pointeur sur une struct_objet, mais sur une struct_arbre. struct_liste_chainee *l_liste_locale; struct_liste_chainee *l_ancienne_liste_locale; if ((*s_objet).type == ALG) { /* * Transcription de l'expression algébrique en arbre q-aire */ l_liste_locale = NULL; l_element_courant = (*s_objet).objet; while(l_element_courant != NULL) { switch((*(*l_element_courant).donnee).type) { // Toutes les fonctions (intrinsèques, extrinsèques et // utilisateurs). case FCT: { // Il s'agit d'un objet de type ALG. Nous pouvons donc // sauter les délimiteurs d'expression. if ((l_element_courant != (*s_objet).objet) && ((*l_element_courant).suivant != NULL)) { nombre_arguments = (*((struct_fonction *) (*(*l_element_courant).donnee).objet)) .nombre_arguments; // Si le nombre d'arguments vaut 0, la fonction // apparaît en notation algébrique comme une fonction // infixe. if (nombre_arguments == 0) { nombre_arguments = 2; } if ((s_arbre = malloc(sizeof(struct_arbre))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(NULL); } (*s_arbre).nombre_branches = nombre_arguments; if (((*s_arbre).feuille = allocation_maillon( s_etat_processus)) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(NULL); } (*(*s_arbre).feuille).donnee = copie_objet( s_etat_processus, (*l_element_courant).donnee, 'P'); (*(*s_arbre).feuille).suivant = NULL; if (((*s_arbre).branches = malloc(((size_t) (*s_arbre) .nombre_branches) * sizeof(struct_arbre *))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(NULL); } for(i = nombre_arguments - 1; i >= 0; i--) { if (l_liste_locale == NULL) { (*s_etat_processus).erreur_execution = d_ex_manque_argument; return(NULL); } (*s_arbre).branches[i] = (struct_arbre *) (*l_liste_locale).donnee; l_ancienne_liste_locale = l_liste_locale; l_liste_locale = (*l_liste_locale).suivant; liberation_maillon(s_etat_processus, l_ancienne_liste_locale); } // Introduction de l'arbre dans la pile locale l_ancienne_liste_locale = l_liste_locale; if ((l_liste_locale = allocation_maillon( s_etat_processus)) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(NULL); } (*l_liste_locale).suivant = l_ancienne_liste_locale; (*l_liste_locale).donnee = (void *) s_arbre; } break; } default: { l_ancienne_liste_locale = l_liste_locale; if ((l_liste_locale = allocation_maillon(s_etat_processus)) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(NULL); } (*l_liste_locale).suivant = l_ancienne_liste_locale; if ((s_arbre = malloc(sizeof(struct_arbre))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(NULL); } if (((*s_arbre).feuille = allocation_maillon( s_etat_processus)) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(NULL); } (*(*s_arbre).feuille).donnee = copie_objet( s_etat_processus, (*l_element_courant).donnee, 'P'); (*(*s_arbre).feuille).suivant = NULL; (*s_arbre).nombre_branches = 0; (*s_arbre).branches = NULL; (*l_liste_locale).donnee = (void *) s_arbre; break; } } l_element_courant = (*l_element_courant).suivant; } // Toute l'expression a été balayée. On ne doit plus avoir qu'un // seul niveau dans la pile locale, ce niveau contenant l'arbre // à réduire. if (l_liste_locale == NULL) { (*s_etat_processus).erreur_execution = d_ex_erreur_evaluation; return(NULL); } else if ((*l_liste_locale).suivant != NULL) { (*s_etat_processus).erreur_execution = d_ex_erreur_evaluation; return(NULL); } s_arbre = (void *) (*l_liste_locale).donnee; liberation_maillon(s_etat_processus, l_liste_locale); l_liste_locale = NULL; /* * Simplification de l'arbre */ # ifdef EXPERIMENTAL_CODE simplification_arbre(s_etat_processus, s_arbre); if ((*s_etat_processus).erreur_systeme != d_es) { return(NULL); } # endif /* * Transcription de l'arbre q-aire simplifié en expression algébrique. * Seule une fonction récursive permet de faire cette conversion * simplement. */ l_liste_locale = transcription_arbre(s_etat_processus, s_arbre); if ((s_objet_simplifie = allocation(s_etat_processus, ALG)) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(NULL); } // Ajout des délimiteurs '<<' et '>>' à la liste d'instructions if (((*s_objet_simplifie).objet = allocation_maillon(s_etat_processus)) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(NULL); } l_element_courant = (*s_objet_simplifie).objet; if (((*l_element_courant).donnee = allocation(s_etat_processus, FCT)) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(NULL); } (*((struct_fonction *) (*(*l_element_courant).donnee).objet)) .nombre_arguments = 0; (*((struct_fonction *) (*(*l_element_courant).donnee).objet)) .fonction = instruction_vers_niveau_superieur; if (((*((struct_fonction *) (*(*l_element_courant).donnee).objet)) .nom_fonction = malloc(3 * sizeof(unsigned char))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(NULL); } strcpy((*((struct_fonction *) (*(*l_element_courant).donnee).objet)) .nom_fonction, "<<"); (*l_element_courant).suivant = l_liste_locale; while((*l_element_courant).suivant != NULL) { l_element_courant = (*l_element_courant).suivant; } if (((*l_element_courant).suivant = allocation_maillon(s_etat_processus)) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(NULL); } l_element_courant = (*l_element_courant).suivant; (*l_element_courant).suivant = NULL; if (((*l_element_courant).donnee = allocation(s_etat_processus, FCT)) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(NULL); } (*((struct_fonction *) (*(*l_element_courant).donnee).objet)) .nombre_arguments = 0; (*((struct_fonction *) (*(*l_element_courant).donnee).objet)) .fonction = instruction_vers_niveau_inferieur; if (((*((struct_fonction *) (*(*l_element_courant).donnee).objet)) .nom_fonction = malloc(3 * sizeof(unsigned char))) == NULL) { (*s_etat_processus).erreur_systeme = d_es_allocation_memoire; return(NULL); } strcpy((*((struct_fonction *) (*(*l_element_courant).donnee).objet)) .nom_fonction, ">>"); } else { s_objet_simplifie = copie_objet(s_etat_processus, s_objet, 'P'); } return(s_objet_simplifie); } // vim: ts=4