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