Salome HOME
51100165d7c079f0a968678c5125bc582ab4dea1
[tools/eficas.git] / Ihm / I_FORM_ETAPE.py
1 """
2 """
3 import string,traceback
4
5 from I_MACRO_ETAPE import MACRO_ETAPE
6 from Extensions import interpreteur_formule
7 from Editeur import analyse_catalogue
8
9 analyse_catalogue.l_noms_commandes.append('FORM') # déclare le nom FORM à l'analyseur de catalogue
10
11
12 class FORM_ETAPE(MACRO_ETAPE):
13
14     interpreteur = interpreteur_formule.Interpreteur_Formule
15
16     def McBuild(self):
17         self.mc_liste=self.build_mc()
18         # on crée la liste des types autorisés (liste des noms de mots-clés
19         # simples dans le catalogue de FORMULE)
20         self.l_types_autorises = self.definition.entites.keys()
21         # en plus de la construction traditionnelle des fils de self
22         # il faut pour les FORMULE décortiquer l'expression ...
23         self.type_retourne,self.arguments,self.corps = self.analyse_formule()
24
25     def analyse_formule(self):
26         """
27         Cette méthode décortique l'expression de la FORMULE.
28         Elle retourne 3 valeurs:
29             - le type retourné par la FORMULE
30             - les arguments de la FORMULE
31             - le corps de la FORMULE, cad son expression
32         """
33         if len(self.mc_liste) == 0:
34             # pas de fils pour self --> la FORMULE est incomplète
35             return None,None,None
36         child = self.mc_liste[0] # child est un MCSIMP
37         type_retourne = child.definition.nom
38         valeur = child.getval()
39         # c'est dans valeur que se trouvent la liste des arguments et le corps de la fonction
40         try:
41             l_args,corps = string.split(valeur,'=',1)
42         except:
43             # pas de signe = --> la formule est fausse
44             return type_retourne,None,None
45         l_args = string.strip(l_args)
46         corps = string.strip(corps)
47         return type_retourne,l_args,corps
48
49     def get_nom(self):
50         """
51         Retourne le nom de la FORMULE, cad le nom de la SD si elle existe,
52         la string vide sinon
53         """
54         if self.sd :
55             return self.sd.get_name()
56         else:
57             return ''
58
59     def verif_arguments(self,arguments = None):
60         """
61         Vérifie si les arguments passés en argument (si aucun prend les arguments courants)
62         sont des arguments valide pour une FORMULE.
63         Retourne :
64             - un booléen, qui vaut 1 si arguments licites, 0 sinon
65             - un message d'erreurs ('' si illicites)
66         """
67         if not arguments :
68             arguments = self.arguments
69         if not arguments :
70             return 0,"Une formule doit avoir au minimum un argument"
71         # il faut au préalable enlever les parenthèses ouvrantes et fermantes
72         # encadrant les arguments
73         arguments = string.strip(arguments)
74         if arguments[0] != '(':
75             return 0,"La liste des arguments d'une formule doit être entre parenthèses : parenthèse ouvrante manquante"
76         if arguments[-1] != ')':
77             return 0,"La liste des arguments d'une formule doit être entre parenthèses : parenthèse fermante manquante"
78         # on peut tester la syntaxe de chaque argument maintenant
79         erreur=''
80         test = 1
81         arguments = arguments[1:-1] # on enlève les parenthèses ouvrante et fermante
82         l_arguments = string.split(arguments,',')
83         for argument in l_arguments:
84             argument = string.strip(argument)
85             try:
86                 typ,nom = string.split(argument,':')
87                 # pas de vérification sur le nom de l'argument
88                 # vérification du type de l'argument
89                 typ = string.strip(typ)
90                 if typ not in self.l_types_autorises :
91                     test = 0
92                     erreur = erreur + "Le type "+typ+" n'est pas un type permis pour "+nom+'\n'
93             except:
94                 # l'argument ne respecte pas la syntaxe : typ_arg : nom_arg
95                 test = 0
96                 erreur = erreur+"Syntaxe argument non valide : "+argument+'\n'
97         return test,erreur
98
99     def verif_corps(self,corps=None,arguments=None):
100         """
101         Cette méthode a pour but de vérifier si le corps de la FORMULE
102         est syntaxiquement correct.
103         Retourne :
104             - un booléen, qui vaut 1 si corps de FORMULE licite, 0 sinon
105             - un message d'erreurs ('' si illicite)
106         """
107         if not corps :
108             corps = self.corps
109         if not arguments :
110             arguments = self.arguments
111         formule=(self.get_nom(),self.type_retourne,arguments,corps)
112         # on récupère la liste des constantes et des autres fonctions prédéfinies
113         # et qui peuvent être utilisées dans le corps de la formule courante
114         l_ctes,l_form = self.jdc.get_parametres_fonctions_avant_etape(self)
115         # on crée un objet vérificateur
116         try:
117             verificateur = self.interpreteur(formule=formule,
118                                              constantes = l_ctes,
119                                              fonctions = l_form)
120         except :
121             traceback.print_exc()
122             return 0,"Impossible de réaliser la vérification de la formule"
123         return verificateur.isvalid(),verificateur.report()
124
125     def verif_nom(self,nom=None):
126         """
127         Vérifie si le nom passé en argument (si aucun prend le nom courant)
128         est un nom valide pour une FORMULE.
129         Retourne :
130             - un booléen, qui vaut 1 si nom licite, 0 sinon
131             - un message d'erreurs ('' si illicite)
132         """
133         if not nom :
134             nom = self.get_nom()
135         if nom == "" :
136             return 0,"Pas de nom donné à la FORMULE"
137         if len(nom) > 8 :
138             return 0,"Un nom de FORMULE ne peut dépasser 8 caractères"
139         sd = self.parent.get_sd_autour_etape(nom,self)
140         if sd :
141             return 0,"Un concept de nom %s existe déjà !" %nom
142         return 1,''
143
144     def verif_type(self,type=None):
145         """
146         Vérifie si le type passé en argument (si aucun prend le type courant)
147         est un type valide pour une FORMULE.
148         Retourne :
149             - un booléen, qui vaut 1 si type licite, 0 sinon
150             - un message d'erreurs ('' si illicite)
151         """
152         if not type:
153             type = self.type_retourne
154         if not type :
155             return 0,"Le type de la valeur retournée n'est pas spécifié"
156         if type not in self.l_types_autorises:
157             return 0,"Une formule ne peut retourner une valeur de type : %s" %type
158         return 1,''
159
160     def verif_formule(self,formule=None):
161         """
162         Vérifie la validité de la formule passée en argument.
163         Cette nouvelle formule est passée sous la forme d'un tuple :
164                 (nom,type_retourne,arguments,corps)
165         Si aucune formule passée, prend les valeurs courantes de la formule
166         Retourne :
167             - un booléen, qui vaut 1 si formule licite, 0 sinon
168             - un message d'erreurs ('' si illicite)
169         """
170         if not formule :
171             formule = (None,None,None,None)
172         test_nom,erreur_nom = self.verif_nom(formule[0])
173         test_type,erreur_type = self.verif_type(formule[1])
174         if formule[2]:
175             args = '('+formule[2]+')'
176         else:
177             args = None
178         test_arguments,erreur_arguments = self.verif_arguments(args)
179         test_corps,erreur_corps = self.verif_corps(corps = formule[3], arguments = args)
180         # test global = produit des tests partiels
181         test = test_nom*test_type*test_arguments*test_corps
182         # message d'erreurs global = concaténation des messages partiels
183         erreur = ''
184         if not test :
185             for mess in (erreur_nom,erreur_type,erreur_arguments,erreur_corps):
186                 erreur = erreur+(len(mess) > 0)*'\n'+mess
187         return test,erreur
188
189     def update(self,formule):
190         """
191         Méthode externe.
192         Met à jour les champs nom, type_retourne,arguments et corps de la FORMULE
193         par les nouvelles valeurs passées dans le tuple formule.
194         On stocke les valeurs SANS vérifications.
195         """
196         self.init_modif()
197         self.type_retourne = formule[1]
198         self.arguments = '('+formule[2]+')'
199         self.corps = formule[3]
200         # il faut ajouter le mot-clé simple correspondant dans mc_liste
201         # pour cela on utilise la méthode générale build_mc
202         # du coup on est obligé de modifier le dictionnaire valeur de self ...
203         self.valeur = {}
204         self.valeur[self.type_retourne] = self.arguments+' = ' + self.corps
205         self.McBuild()
206         sd = self.get_sd_prod()
207         if sd:
208             sd.nom = formule[0]
209
210     def active(self):
211         """
212         Rend l'etape courante active.
213         Il faut ajouter la formule au contexte global du JDC
214         """
215         self.actif = 1
216         nom = self.get_nom()
217         if nom == '' : return
218         try:
219             self.jdc.append_fonction(self.sd)
220         except:
221             pass
222
223     def inactive(self):
224         """
225         Rend l'etape courante inactive
226         Il faut supprimer la formule du contexte global du JDC
227         """
228         self.actif = 0
229         if not self.sd : return
230         self.jdc.del_fonction(self.sd)
231
232     def delete_concept(self,sd):
233         """ 
234          Inputs :
235            sd=concept detruit
236          Fonction :
237            Mettre a jour les mos cles de l etape et eventuellement le concept produit si reuse
238            suite à la disparition du concept sd
239            Seuls les mots cles simples MCSIMP font un traitement autre que de transmettre aux fils,
240            sauf les objets FORM_ETAPE qui doivent vérifier que le concept détruit n'est pas 
241            utilisé dans le corps de la fonction
242         """
243         self.init_modif()
244