Salome HOME
CCAR:amelioration de la fonctionnalité mots clés inconnus
[tools/eficas.git] / Noyau / nommage.py
1 """
2    Ce module sert à nommer les concepts produits par les commandes.
3    Le nom du concept est obtenu en appelant la fonction GetNomConceptResultat
4    du module avec le nom de la commande en argument.
5    
6    Cette fonction parcourt le source dans lequel la commande se trouve, parse le
7    fichier et retrouve le nom du concept qui se trouve à gauche du signe = précédant
8    le nom de la commande.
9
10    Cette fonction utilise la fonction cur_frame du module N_utils qui retourne la frame
11    d'exécution Python située 2 niveaux au-dessus. C'est à partir de cette frame que
12    l'on retrouve le fichier source et le numéro de ligne où se trouve l'appel à la commande.
13
14 """
15
16 # Modules Python
17 import re,string
18 import linecache
19
20 # Modules EFICAS
21 import N_utils
22
23 regex1='=\s*%s\s*\('
24
25 def GetNomConceptResultat(ope):
26   """
27      Cette fonction recherche dans la pile des appels, l'appel à la commande
28      qui doit etre situé à 2 niveaux au-dessus (cur_frame(2)).
29      On retrouve d'abord la frame d'exécution f. Puis le numéro de la ligne
30      dans le source f.f_lineno et le nom du fichier source (f.f_code.co_filename).
31      A partir de là, on récupère la ligne de source avec linecache.getline
32      et on vérifie que cette ligne correspond véritablement à l'appel.
33
34      En effet, lorsque les commandes tiennent sur plusieurs lignes, on retrouve
35      la dernière ligne. Il faut donc remonter dans le source jusqu'à la première 
36      ligne.
37
38      Enfin la fonction evalnom forme un nom acceptable lorsque le concept est un
39      élément d'une liste, par exemple.
40
41   """
42   f=N_utils.cur_frame(2)
43   lineno = f.f_lineno     # XXX Too bad if -O is used
44   #lineno = f_lineno(f)  # Ne marche pas toujours
45   co = f.f_code
46   filename = co.co_filename
47   name = co.co_name
48   #print "NOMOP,FICHIER, LIGNE ",ope,filename,lineno
49   line = linecache.getline(filename, lineno)
50   if not line: line = None
51
52   list=[]
53   list.append(line)
54   while lineno > 0:
55     #print "LIGNE ",line
56     if re.search(regex1 % ope,line):
57       l=re.split(regex1 % ope,line)
58       list.reverse()
59       #print "COMMANDE ",string.join(list)
60       #print "SPLIT ",l
61       # On suppose que le concept resultat a bien ete
62       # isole en tete de la ligne de source
63       m=evalnom(string.strip(l[0]),f.f_locals)
64       #print "NOMS ",m
65       return m[-1]
66     lineno=lineno-1
67     line = linecache.getline(filename, lineno)
68     list.append(line)
69   #print "appel inconnu"
70   return ""
71
72 def evalnom(text,d):
73   """
74    Retourne un nom pour le concept resultat identifie par text
75    Pour obtenir ce nom il y a plusieurs possibilites :
76     1-text est un identificateur python c est le nom du concept
77     2-text est un element d une liste on construit le nom en
78       evaluant la partie indice dans le contexte de l appelant d
79   """
80   l=re.split('([\[\]]+)',text)
81   #print l
82   if l[-1] == '' :l=l[:-1]
83   lll=[]
84   i=0
85   while i<len(l):
86     s=l[i]
87     ll=string.split(s,',')
88     ll=re.split('[ ,]+',s)
89     if ll[0] == '' :ll=ll[1:]
90     if len(ll) == 1:
91       id0=ll[0]
92     else:
93       lll=lll+ll[0:-1]
94       id0=ll[-1]
95     if i+1<len(l) and l[i+1] == '[': # le nom est suivi d un subscript
96       sub=l[i+2]
97       nom=id0+'_'+str(eval(sub,d))
98       i=i+4
99     else:
100       nom=id0
101       i=i+1
102     lll.append(nom)
103   return lll
104
105 def f_lineno(f):
106    """
107       Calcule le numero de ligne courant
108       Devrait marcher meme avec -O
109       Semble ne pas marcher en présence de tuples longs
110    """
111    c=f.f_code
112    if not hasattr(c, 'co_lnotab'):return f.f_lineno
113    tab=c.co_lnotab
114    line = c.co_firstlineno
115    stopat = f.f_lasti
116    addr = 0
117    for i in range(0, len(tab), 2):
118        addr = addr + ord(tab[i])
119        if addr > stopat:
120            break
121        line = line + ord(tab[i+1])
122    return line
123