a19d331b3e241f50eafac62f87cd9c16b520a432
[scilab.git] / scilab / modules / m2sci / macros / kernel / updatevarslist.sci
1 // Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
2 // Copyright (C) 2002-2004 - INRIA - Vincent COUVERT
3 //
4 // This file must be used under the terms of the CeCILL.
5 // This source file is licensed as described in the file COPYING, which
6 // you should have received as part of this distribution.  The terms
7 // are also available at
8 // http://www.cecill.info/licences/Licence_CeCILL_V2.1-en.txt
9
10 function []=updatevarslist(instr_lhs)
11     // (2 functions in this file: merge_vars() at the end)
12     // Update list of M2SCI variables with converted instruction lhs
13     // Input:
14     // - instr_lhs: list of lhs of current instruction
15     // - in_a_clause: boolean value
16     //   Set to 1 if instruction is in a clause
17     //   In this case, type and dimensions are set to unknown if differ from those already stored in varslist
18     //   (Default value is %F)
19
20     // Global variable for M2SCI
21     global("varslist")
22     if isempty(varslist)
23         varslist = list()
24     end
25     // level is declared in m2sci.sci and modified in clause2sci.sci
26     level;
27
28     rhs=argn(2)
29     if rhs==2 then
30         in_a_clause=%F
31     end
32
33     // Merge infered data from the last two parts of clause which are above the current part
34     // if we are in the third part of clause (current), then : merge the first and second part of clause
35     // when end of conversion of a clause : merge infered data from the last two parts of clause
36     levelsize=size(level,1)
37     changepartclause=%F
38
39     for i=size(varslist):-1:1
40         if size(varslist(i).level,1)==levelsize then
41             varlevel=varslist(i).level
42             if varlevel($)<>level($)
43                 changepartclause=%T
44             else
45                 changepartclause=%F
46                 break
47             end
48         end
49     end
50     if changepartclause | instr_lhs=="END OF CLAUSE" then
51         index=[] // Search variables from two part above current part clause
52         for k=size(varslist):-1:1
53             if size(varslist(k).level,1)==levelsize then
54                 varlevel=varslist(k).level
55                 if and(varlevel(1:$-1)==level(1:$-1)) & varlevel($)==level($)-2 then
56                     index=[index;k]
57                 end
58             end
59         end
60         if index<>[] then  // Found variables from the second part above current part of a clause
61             for k=1:size(index,1)
62                 boolmerge =%F
63                 for i=size(varslist):-1:1 // Search variables from the first part above current part of a clause, and which have the same name than variables from the second part above current part of a clause
64                     varlevel=varslist(i).level
65                     if varslist(i).matname==varslist(index(k)).matname & and(varlevel(1:$-1)==level(1:$-1)) &  varlevel($)==level($)-1 then
66                         boolmerge =%T // Found the same variable name from the last two parts above the current part : Merge
67                         merge_vars(index(k),varslist(i))
68                         varslist(i)=null()
69                         break
70                     end
71                 end
72                 if ~boolmerge then
73                     varslist(index(k)).level=[level(1:$-1);level($)-1]
74                 end
75             end
76         end
77     end
78
79     // Special case when end of conversion of a clause
80     // Merge infered data from clause and those from level-1
81     if instr_lhs=="END OF CLAUSE" then // Search variables in the last part of a clause (above end of conversion of a clause)
82         index=[] //
83         for k=size(varslist):-1:1 // Search variables from level-1 which have the same name than variables from the last part of current level
84             varlevel=varslist(k).level
85             if varlevel==[level(1:$-1);level($)-1] then
86                 index=[index;k]
87             end
88         end
89         if index<>[] then
90             for j=1:size(index,1)
91                 boolmerge=%F
92                 for k=size(varslist):-1:1 //
93                     varlevel=varslist(k).level
94                     if varslist(k).matname==varslist(index(j)).matname  & and(varlevel==level(1:$-1)) then
95                         boolmerge=%T // Found variables from level-1 which have the same name than variables from the last part of current level : Merge
96                         index_lower_level=k
97                         merge_vars(index_lower_level,varslist(index(j)))
98                         varslist(k).level=level(1:$-1)
99                         varslist(index(j))=null()
100                         break
101                     end
102                 end
103                 if boolmerge==%F then
104                     varslist(index(j)).level=level(1:$-1)
105                 end
106             end
107         end
108         return
109     end
110
111     // Expression: lhs name is empty => nothing to do
112     if instr_lhs==list() then
113         return
114     end
115
116     // Remove lhs which are not variables
117     k=1
118     while k<=size(instr_lhs)
119         // Insertion operation
120         if typeof(instr_lhs(k))=="operation" then
121             instr_lhs(k)=null()
122         else
123             k=k+1
124         end
125     end
126
127     if size(instr_lhs)==0 then
128         return
129     end
130
131     // Update varslist
132     for k=1:size(instr_lhs)
133         [bval,index]=isdefinedvar(instr_lhs(k))
134         ierr=execstr("zz=instr_lhs(k).contents.index","errcatch")
135         if ierr<>0 then pause;end
136         // Remove multiple entries from contents
137         for kcont=lstsize(instr_lhs(k).contents.index):-1:1
138             [infertlist,pos]=get_contents_infer(instr_lhs(k),instr_lhs(k).contents.index(kcont))
139             if pos<>0 & pos<>kcont then
140                 instr_lhs(k).contents.index(pos)=null()
141                 instr_lhs(k).contents.data(pos)=null()
142             end
143         end
144         // If variable exists for the current level in the same part of clause then update exixting variable
145         if bval
146             boolupdate=%F
147             for l=1:size(varslist)
148                 if varslist(l).matname==instr_lhs(k).name & varslist(l).level==level then
149                     varslist(l)=M2scivar(varslist(l).sciname,..
150                     varslist(l).matname,..
151                     Infer(instr_lhs(k).infer.dims,instr_lhs(k).infer.type,instr_lhs(k).infer.contents),..
152                     varslist(l).level)
153                     boolupdate=%T
154                     break
155                 end
156             end
157             // If variable exists, but not for the current level or not in the same part of clause then Update variable then create new variable
158             if ~boolupdate then
159                 varslist($+1)=M2scivar(varslist(index).sciname,..
160                 varslist(index).matname,..
161                 instr_lhs(k).infer,..
162                 level)
163             end
164         else
165             // Variable added to varslist if as a name (not done for expressions
166             if execstr("f=instr_lhs(k).name","errcatch")<>0 then pause;end;errclear();
167             if instr_lhs(k).name<>"ans" then
168                 varslist($+1)=M2scivar(instr_lhs(k).name,..
169                 instr_lhs(k).name,..
170                 instr_lhs(k).infer,..
171                 level)
172             end
173         end
174     end
175 endfunction
176
177 function []=merge_vars(oldvarindex,newvar)
178     // M2SCI function
179     // Merge two variables inference properties, if different then set to Unknown
180     // Input:
181     // - oldvarindex: index of old variable in varslist
182     // - newvar: new variable to take in account to update oldvar properties
183
184     // Global variable for M2SCI
185     global("varslist")
186     oldvar=varslist(oldvarindex)
187
188     olddims=oldvar.dims
189     oldvtype=oldvar.vtype
190     oldprop=oldvar.property
191
192     newdims=newvar.dims
193     newvtype=newvar.vtype
194     newprop=newvar.property
195
196     // Verify dims
197     for l=1:min(size(newdims),size(olddims))
198         if newdims(l)<>olddims(l) then
199             newdims(l)=Unknown
200         end
201     end
202     if size(newdims)>size(olddims) then
203         for l=size(olddims):size(newdims)
204             newdims(l)=null()
205         end
206     end
207
208     // Verify vtype
209     if newvtype<>oldvtype then
210         newvtype=Unknown
211     end
212
213     // Verify property
214     if newprop<>oldprop then
215         newprop=Unknown
216     end
217
218     // Verify contents
219     for k=1:lstsize(newvar.contents.index)
220         olddata=get_contents_infer(oldvar,newvar.contents.index(k))
221         newdata=newvar.contents.data(k)
222
223         if or(olddata<>newdata) then
224             newvar.infer.contents.data(k)=Infer()
225         end
226     end
227
228     // Write result in varslist
229     varslist(oldvarindex)=M2scivar(oldvar.sciname,..
230     oldvar.matname,..
231     Infer(newdims,Type(newvtype,newprop),newvar.contents),..
232     newvar.level)
233 endfunction