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