[m2sci] kernel code reorganization: clarify dependencies & ease code browsing
[scilab.git] / scilab / modules / m2sci / macros / kernel / instruction2sci.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 [converted_instr, nblines] = instruction2sci(mtlb_instr,nblines)
14
15     // Convertion of empty lines
16     if mtlb_instr==list("EOL") then
17         converted_instr=list("EOL")
18         nblines = nblines + 1;
19         return
20     end
21
22     if typeof(mtlb_instr)=="equal" then
23         [converted_instr] = equal2sci(mtlb_instr)
24
25     elseif or(typeof(mtlb_instr)==["ifthenelse","selectcase","for","while","trycatch"]) then
26         [converted_instr, nblines] = clause2sci(mtlb_instr, nblines)
27
28     elseif or(typeof(mtlb_instr)==["funcall","cste","operation","variable"]) then
29         converted_instr = expression2sci(mtlb_instr)
30
31     elseif typeof(mtlb_instr)=="comment" then
32         converted_instr = mtlb_instr
33
34     else
35         error(gettext("unknown instruction type %s."),typeof(mtlb_instr))
36     end
37
38 endfunction
39
40 // ---------------------------------------------------------------------------
41
42 function sci_instr = equal2sci(mtlb_instr)
43     // PRIVATE INTERNAL function called only by instruction2sci()
44     //
45     // Conversion of a Matlab instruction or expression to Scilab
46     // Input:
47     // - mtlb_instr: Matlab instr or expression to convert
48     // Output:
49     // - sci_instr: Scilab equivalent for mtlb_instr
50
51     // Trees to insert in converted function tree
52     global("m2sci_to_insert_b")
53     m2sci_to_insert_b=list()
54     global("m2sci_to_insert_a")
55     m2sci_to_insert_a=list()
56     global("varslist")
57
58     sci_instr=mtlb_instr
59
60     // Add inference data to lhs
61     lhslist=list()
62
63     // Inference field added to each lhs argument
64     // Get infos in varslist to init
65     for k=1:size(mtlb_instr.lhs)
66         if typeof(mtlb_instr.lhs(k))=="variable" then
67             [bval,index]=isdefinedvar(mtlb_instr.lhs(k))
68             if bval then
69                 INFER=varslist(index).infer
70             else
71                 INFER=Infer()
72             end
73             lhslist($+1)=Variable(mtlb_instr.lhs(k).name,INFER)
74         elseif typeof(mtlb_instr.lhs(k))=="operation" then
75             if mtlb_instr.lhs(k).operator<>"ins" then
76                 error(msprintf(gettext("lhs cannot be a %s operation."),mtlb_instr.lhs(k).operator))
77             end
78
79             [bval,index]=isdefinedvar(mtlb_instr.lhs(k).operands(1))
80             if bval then
81                 INFER=varslist(index).infer
82             else
83                 INFER=Infer()
84             end
85
86             lhslist($+1)=Operation(mtlb_instr.lhs(k).operator,..
87             mtlb_instr.lhs(k).operands,..
88             list(Variable(mtlb_instr.lhs(k).operands(1).name,INFER)))
89         else
90             error(msprintf(gettext("lhs cannot be a %s."),typeof(mtlb_instr.lhs(k))))
91         end
92     end
93
94     // Convert expression
95
96     [sci_expr]=expression2sci(mtlb_instr.expression,lhslist);
97
98     if sci_expr==list() then // Conversion made by inserted instructions or 'm2scideclare'
99         sci_instr=list()
100     else
101
102         sci_instr.expression=sci_expr;
103
104         // Update lhs of instruction
105         select typeof(sci_instr.expression)
106         case "operation" then
107             sci_instr.lhs=sci_expr.out;
108         case "funcall" then
109             sci_instr.lhs=sci_instr.expression.lhs
110             if typeof(mtlb_instr.expression)=="funcall" then
111                 sci_instr.lhs=sci_expr.lhs;
112             end
113         case "cste" then
114             sci_instr.lhs=lhslist;
115             sci_instr.lhs(1).dims=sci_expr.dims;
116             sci_instr.lhs(1).type=sci_expr.type;
117         case "variable" then
118             sci_instr.lhs=lhslist;
119             sci_instr.lhs(1).dims=sci_expr.dims;
120             sci_instr.lhs(1).type=sci_expr.type;
121         else
122             error(msprintf(gettext("%s is not yet implemented."),typeof(sci_instr.expression)));
123         end
124
125         // If lhs are insertion operation, they also have to be converted
126         for k=1:size(sci_instr.lhs)
127             if typeof(sci_instr.lhs(k))=="operation" then
128                 sci_instr.lhs(k).operands($+1)=sci_instr.expression
129                 // Keep just one inference field in sci_instr.expression (if is a funcall) so that inference can be made in operation2sci()
130                 if typeof(sci_instr.lhs(k).operands($))=="funcall" then
131                     for l=1:size(sci_instr.lhs(k).operands($).lhs)
132                         if l<>k then
133                             sci_instr.lhs(k).operands($).lhs(l)=list()
134                         end
135                     end
136                     l=1
137                     while l<=size(sci_instr.lhs(k).operands($).lhs)
138                         if sci_instr.lhs(k).operands($).lhs(l)==list() then
139                             sci_instr.lhs(k).operands($).lhs(l)=null()
140                         else
141                             l=l+1
142                         end
143                     end
144                     // Verify that there is just one lhs kept
145                     if size(sci_instr.lhs(k).operands($).lhs)<>1 then pause;end
146                 end
147                 // If insertion made in an unknown variable, I add it to varslist
148                 inservar=sci_instr.lhs(k).operands(1)
149                 [bval,index]=isdefinedvar(inservar)
150                 if ~bval then
151                     // Variable added to varslist before insertion
152                     if funptr(inservar.name)<>0 then
153                         matname="%"+inservar.name
154                     else
155                         matname=inservar.name
156                     end
157                     if sci_instr.expression.vtype==Struct then
158                         // Variable is initialized to struct() in converted script is does not already exist
159                         varslist($+1)=M2scivar(matname,inservar.name,Infer(list(0,0),Type(Struct,Unknown)))
160                         //m2sci_to_insert_b($+1)=Equal(list(inservar),Funcall("struct",1,list(),list()))
161                     elseif sci_instr.expression.vtype==Cell then
162                         // Variable is initialized to cell() in converted script is does not already exist
163                         varslist($+1)=M2scivar(matname,inservar.name,Infer(list(0,0),Type(Cell,Unknown)))
164                         //m2sci_to_insert_b($+1)=Equal(list(inservar),Funcall("cell",1,list(),list()))
165                     else
166                         // Variable is initialized to [] in converted script is does not already exist
167                         varslist($+1)=M2scivar(matname,inservar.name,Infer(list(0,0),Type(Double,Real)))
168                         //m2sci_to_insert_b($+1)=Equal(list(inservar),Cste([]))
169                     end
170                     sci_instr.lhs(k).out(1).infer=varslist($).infer
171                 else
172                     sci_instr.lhs(k).out(1).infer=varslist(index).infer
173                 end
174                 [sci_instr.lhs(k)]=operation2sci(sci_instr.lhs(k))
175                 if typeof(sci_instr.lhs(k))=="operation" then
176                     if or(sci_instr.lhs(k).operands($)<>sci_instr.expression) then // Update expression if has been modified while converting lhs
177                         sci_instr.expression=sci_instr.lhs(k).operands($)
178                     end
179
180                     sci_instr.lhs(k).operands($)=null()
181                     updatevarslist(sci_instr.lhs(k).out)
182                 else
183                     // Insertion done by inserted instruction
184                     sci_instr=list()
185                     return
186                 end
187             end
188         end
189         // Update varslist
190         updatevarslist(sci_instr.lhs);
191     end
192 endfunction
193
194 // ---------------------------------------------------------------------------
195
196 function [sci_clause, nblines] = clause2sci(mtlb_clause, nblines, leveltemp)
197     // M2SCI function
198
199     // Global variables for M2SCI
200     global("m2sci_to_insert_b")
201     global("varslist")
202
203     // Increment level of clause indentation
204     level
205
206     // Temp variable used to store instructions to insert before clause
207     to_insert=list()
208     select typeof(mtlb_clause)
209         // --- TRYCATCH ---
210     case "trycatch"
211         level=[level;0]
212
213         // Get instructions to insert if there are
214         if m2sci_to_insert_b<>list() then
215             to_insert=m2sci_to_insert_b
216             m2sci_to_insert_b=list()
217         end
218
219         // Convert try
220         sci_try=list()
221         level($)=level($)+1
222         for k=1:size(mtlb_clause.trystat)
223             if typeof(mtlb_clause.trystat(k))=="sup_equal" then
224                 sci_try_temp=list()
225                 for i=1:size(mtlb_clause.trystat(k).sup_instr)
226                     [instr,nblines]=instruction2sci(mtlb_clause.trystat(k).sup_instr(i),nblines)
227                     sci_try_temp=update_instr_list(sci_try_temp,instr)
228                 end
229                 sci_try($+1)=tlist(["sup_equal","sup_instr","nb_opr"],sci_try_temp,mtlb_clause.trystat(k).nb_opr)
230             else
231                 [instr,nblines]=instruction2sci(mtlb_clause.trystat(k),nblines)
232                 sci_try=update_instr_list(sci_try,instr)
233             end
234         end
235
236         // Convert catch
237         sci_catch=list()
238         level($)=level($)+1
239         for k=1:size(mtlb_clause.catchstat)
240             if typeof(mtlb_clause.catchstat(k))=="sup_equal" then
241                 sci_catch_temp=list()
242                 for i=1:size(mtlb_clause.catchstat(k).sup_instr)
243                     [instr,nblines]=instruction2sci(mtlb_clause.catchstat(k).sup_instr(i),nblines)
244                     sci_catch_temp=update_instr_list(sci_catch_temp,instr)
245                 end
246                 sci_catch($+1)=tlist(["sup_equal","sup_instr","nb_opr"],sci_catch_temp,mtlb_clause.catchstat(k).nb_opr)
247             else
248                 [instr,nblines]=instruction2sci(mtlb_clause.catchstat(k),nblines)
249                 sci_catch=update_instr_list(sci_catch,instr)
250             end
251         end
252
253         // Create Scilab trycatch
254         sci_clause=tlist(["trycatch","trystat","catchstat"],sci_try,sci_catch)
255         level($)=level($)+1
256         updatevarslist("END OF CLAUSE")
257
258         // --- IF ---
259     case "ifthenelse"
260         level=[level;0]
261
262         // Convert expression
263         [sci_expr]=expression2sci(mtlb_clause.expression)
264
265         // Get instructions to insert if there are
266         if m2sci_to_insert_b<>list() then
267             to_insert=m2sci_to_insert_b
268             m2sci_to_insert_b=list()
269         end
270
271         // Convert then statements
272         sci_then=list()
273         level($)=level($)+1
274         for k=1:size(mtlb_clause.then)
275             if typeof(mtlb_clause.then(k))=="sup_equal" then
276                 sci_then_temp=list()
277                 for i=1:size(mtlb_clause.then(k).sup_instr)
278                     [instr,nblines]=instruction2sci(mtlb_clause.then(k).sup_instr(i),nblines)
279                     sci_then_temp=update_instr_list(sci_then_temp,instr)
280                 end
281                 sci_then($+1)=tlist(["sup_equal","sup_instr","nb_opr"],sci_then_temp,mtlb_clause.then(k).nb_opr)
282             else
283                 [instr,nblines]=instruction2sci(mtlb_clause.then(k),nblines)
284                 sci_then=update_instr_list(sci_then,instr)
285             end
286         end
287
288         // Convert elseifs
289         sci_elseifs=list()
290         for k=1:size(mtlb_clause.elseifs)
291             level($)=level($)+1
292
293             // Convert expression
294             [sci_exprn]=expression2sci(mtlb_clause.elseifs(k).expression)
295
296             // Get instructions to insert if there are
297             if m2sci_to_insert_b<>list() then
298                 to_insert=m2sci_to_insert_b
299                 m2sci_to_insert_b=list()
300             end
301
302             // Convert statements
303             sci_stat=list()
304             for l=1:size(mtlb_clause.elseifs(k).then)
305                 if typeof(mtlb_clause.elseifs(k).then(l))=="sup_equal" then
306                     sci_stat_temp=list()
307                     for i=1:size(mtlb_clause.elseifs(k).then(l).sup_instr)
308                         [instr,nblines]=instruction2sci(mtlb_clause.elseifs(k).then(l).sup_instr(i),nblines)
309                         sci_stat_temp=update_instr_list(sci_stat_temp,instr)
310                     end
311                     sci_stat($+1)=tlist(["sup_equal","sup_instr","nb_opr"],sci_stat_temp,mtlb_clause.elseifs(k).then(l).nb_opr)
312                 else
313                     [instr,nblines]=instruction2sci(mtlb_clause.elseifs(k).then(l),nblines)
314                     sci_stat=update_instr_list(sci_stat,instr)
315                 end
316             end
317             sci_elseifs($+1)=tlist(["elseif","expression","then"],sci_exprn,sci_stat)
318         end
319
320         // Convert else
321         sci_else=list()
322         if size(mtlb_clause.else)<>0 then
323             level($)=level($)+1
324         end
325         for k=1:size(mtlb_clause.else)
326             if typeof(mtlb_clause.else(k))=="sup_equal" then
327                 sci_else_temp=list()
328                 for i=1:size(mtlb_clause.else(k).sup_instr)
329                 [instr,nblines]=instruction2sci(mtlb_clause.else(k).sup_instr(i),nblines)
330                     sci_else_temp=update_instr_list(sci_else_temp,instr)
331                 end
332             sci_else($+1)=tlist(["sup_equal","sup_instr","nb_opr"],sci_else_temp,mtlb_clause.else(k).nb_opr)
333             else
334             [instr,nblines]=instruction2sci(mtlb_clause.else(k),nblines)
335                 sci_else=update_instr_list(sci_else,instr)
336             end
337         end
338
339         // Create Scilab ifthenelse
340         sci_clause=tlist(["ifthenelse","expression","then","elseifs","else"],sci_expr,sci_then,sci_elseifs,sci_else)
341         level($)=level($)+1
342         updatevarslist("END OF CLAUSE")
343
344         // --- SELECT ---
345     case "selectcase"
346         level=[level;0]
347         // Convert expression
348         sci_expr=list()
349         [sci_expr(1)]=expression2sci(mtlb_clause.expression(1))
350         for i=2:size(mtlb_clause.expression)
351             sci_expr(i)=mtlb_clause.expression(i) // EOL or comment
352         end
353
354         // Get instructions to insert if there are
355         if m2sci_to_insert_b<>list() then
356             to_insert=m2sci_to_insert_b
357             m2sci_to_insert_b=list()
358         end
359
360         // Convert cases
361         sci_cases=list()
362         k=0
363         while k<size(mtlb_clause.cases)
364             k=k+1
365             level($)=level($)+1
366             // Convert expression
367             if typeof(mtlb_clause.cases(k).expression)=="funcall" then
368                 if mtlb_clause.cases(k).expression.name=="makecell" then
369                     // Insert new cases
370                     for nbcas=size(mtlb_clause.cases):-1:k+1
371                         mtlb_clause.cases(nbcas+size(mtlb_clause.cases(k).expression.rhs))=mtlb_clause.cases(nbcas)
372                     end
373                     for nbrhs=1:size(mtlb_clause.cases(k).expression.rhs)
374                         mtlb_clause.cases(nbrhs+k)=tlist(["case","expression","then"],mtlb_clause.cases(k).expression.rhs(nbrhs),mtlb_clause.cases(k).then)
375                     end
376                     mtlb_clause.cases(k)=null()
377                 end
378             end
379             [sci_exprn]=expression2sci(mtlb_clause.cases(k).expression)
380             // Get instructions to insert if there are
381             if m2sci_to_insert_b<>list() then
382                 to_insert=m2sci_to_insert_b
383                 m2sci_to_insert_b=list()
384             end
385
386             // Convert statements
387             sci_stat=list()
388             for l=1:size(mtlb_clause.cases(k).then)
389                 if typeof(mtlb_clause.cases(k).then(l))=="sup_equal" then
390                     sci_stat_temp=list()
391                     for i=1:size(mtlb_clause.cases(k).then(l).sup_instr)
392                         [instr,nblines]=instruction2sci(mtlb_clause.cases(k).then(l).sup_instr(i),nblines)
393                         sci_stat_temp=update_instr_list(sci_stat_temp,instr)
394                     end
395                     sci_stat($+1)=tlist(["sup_equal","sup_instr","nb_opr"],sci_stat_temp,mtlb_clause.cases(k).then(l).nb_opr)
396                 else
397                     [instr,nblines]=instruction2sci(mtlb_clause.cases(k).then(l),nblines)
398                     sci_stat=update_instr_list(sci_stat,instr)
399                 end
400             end
401             sci_cases($+1)=tlist(["case","expression","then"],sci_exprn,sci_stat)
402         end
403
404         // Convert else
405         sci_else=list()
406         if size(mtlb_clause.else)<>0 then
407             level($)=level($)+1
408         end
409         for k=1:size(mtlb_clause.else)
410             if typeof(mtlb_clause.else(k))=="sup_equal" then
411                 sci_else_temp=list();
412                 for i=1:size(mtlb_clause.else(k).sup_instr)
413                 [instr,nblines]=instruction2sci(mtlb_clause.else(k).sup_instr(i),nblines)
414                     sci_else_temp=update_instr_list(sci_else_temp,instr)
415                 end
416             sci_else($+1)=tlist(["sup_equal","sup_instr","nb_opr"],sci_else_temp,mtlb_clause.else(k).nb_opr)
417             else
418             [instr,nblines]=instruction2sci(mtlb_clause.else(k),nblines)
419                 sci_else=update_instr_list(sci_else,instr)
420             end
421         end
422         // Create Scilab selectcase
423         sci_clause=tlist(["selectcase","expression","cases","else"],sci_expr,sci_cases,sci_else)
424         level($)=level($)+1
425         updatevarslist("END OF CLAUSE")
426
427         // --- WHILE ---
428     case "while"
429         level=[level;0]
430         sci_do=list()
431         // Convert expression
432         [sci_expr]=expression2sci(mtlb_clause.expression)
433         // If there are instructions to insert, while is modified so that inserted instruction is evaluated in each loop
434         if m2sci_to_insert_b<>list() then
435             newif=tlist(["ifthenelse","expression","then","elseifs","else"],sci_expr,list(Funcall("break",1,list(),list())),list(),list())
436             m2sci_to_insert_b($+1)=newif
437             sci_expr=Cste(%T)
438             sci_do=m2sci_to_insert_b
439             m2sci_to_insert_b=list()
440         end
441
442         // Convert all do instructions
443         level($)=level($)+1
444         for k=1:size(mtlb_clause.statements)
445             if typeof(mtlb_clause.statements(k))=="sup_equal" then
446                 sci_do_temp=list()
447                 for i=1:size(mtlb_clause.statements(k).sup_instr)
448                     [instr,nblines]=instruction2sci(mtlb_clause.statements(k).sup_instr(i),nblines)
449                     // If inserted instruction is an initialisation, it has to be done just one time and before loop
450                     l=1;
451                     while l <= size(m2sci_to_insert_b)
452                         if typeof(m2sci_to_insert_b(l))=="equal" & ..
453                             (and(m2sci_to_insert_b(l).expression==Cste([])) | ..
454                             and(m2sci_to_insert_b(l).expression==Funcall("struct",1,list(),list())) | ..
455                             and(m2sci_to_insert_b(l).expression==Funcall("cell",1,list(),list())) ) then
456                             to_insert($+1)=m2sci_to_insert_b(l)
457                             m2sci_to_insert_b(l)=null()
458                             if size(m2sci_to_insert_b)>=l & m2sci_to_insert_b(l)==list("EOL") then
459                                 to_insert($+1)=m2sci_to_insert_b(l)
460                                 m2sci_to_insert_b(l)=null()
461                             end
462                         else
463                             l=l+1;
464                         end
465                     end
466                     sci_do_temp=update_instr_list(sci_do_temp,instr)
467                 end
468                 sci_do($+1)=tlist(["sup_equal","sup_instr","nb_opr"],sci_do_temp,mtlb_clause.statements(k).nb_opr)
469             else
470                 [instr,nblines]=instruction2sci(mtlb_clause.statements(k),nblines)
471                 // If inserted instruction is an initialisation, it has to be done just one time and before loop
472                 l=1;
473                 while l <= size(m2sci_to_insert_b)
474                     if typeof(m2sci_to_insert_b(l))=="equal" & ..
475                         (and(m2sci_to_insert_b(l).expression==Cste([])) | ..
476                         and(m2sci_to_insert_b(l).expression==Funcall("struct",1,list(),list())) | ..
477                         and(m2sci_to_insert_b(l).expression==Funcall("cell",1,list(),list())) ) then
478                         to_insert($+1)=m2sci_to_insert_b(l)
479                         m2sci_to_insert_b(l)=null()
480                         if size(m2sci_to_insert_b)>=l & m2sci_to_insert_b(l)==list("EOL") then
481                             to_insert($+1)=m2sci_to_insert_b(l)
482                             m2sci_to_insert_b(l)=null()
483                         end
484                     else
485                         l=l+1;
486                     end
487                 end
488                 sci_do=update_instr_list(sci_do,instr)
489             end
490         end
491
492         // Create Scilab while
493         sci_clause=tlist(["while","expression","statements"],sci_expr,sci_do)
494         level($)=level($)+1
495         updatevarslist("END OF CLAUSE")
496
497         // --- FOR ---
498     case "for"
499         //level=[level;1]
500         // Convert expression
501         [sci_expr,nblines]=instruction2sci(mtlb_clause.expression,nblines)
502         if typeof(sci_expr)=="equal" then
503             [bval,pos]=isdefinedvar(sci_expr.lhs(1))
504             if bval then
505                 varslist(pos).infer.dims=list(varslist(pos).infer.dims(1),1)
506             end
507         end
508         // Get instructions to insert if there are
509         if m2sci_to_insert_b<>list() then
510             to_insert=m2sci_to_insert_b
511             m2sci_to_insert_b=list()
512         end
513         sci_instr=list()
514         // Convert all do instructions
515         for k=1:size(mtlb_clause.statements)
516             if typeof(mtlb_clause.statements(k))=="sup_equal" then
517                 sci_instr_temp=list()
518                 for i=1:size(mtlb_clause.statements(k).sup_instr)
519                     [instr,nblines]=instruction2sci(mtlb_clause.statements(k).sup_instr(i),nblines)
520                     // If inserted instruction is an initialisation, it has to be done just one time and before loop
521                     l=1;
522                     while l <= size(m2sci_to_insert_b)
523                         if typeof(m2sci_to_insert_b(l))=="equal" & ..
524                             (and(m2sci_to_insert_b(l).expression==Cste([])) | ..
525                             and(m2sci_to_insert_b(l).expression==Funcall("struct",1,list(),list())) | ..
526                             and(m2sci_to_insert_b(l).expression==Funcall("cell",1,list(),list())) ) then
527                             to_insert($+1)=m2sci_to_insert_b(l)
528                             m2sci_to_insert_b(l)=null()
529                             if size(m2sci_to_insert_b)>=l & m2sci_to_insert_b(l)==list("EOL") then
530                                 to_insert($+1)=m2sci_to_insert_b(l)
531                                 m2sci_to_insert_b(l)=null()
532                             end
533                         else
534                             l=l+1;
535                         end
536                     end
537                     sci_instr_temp=update_instr_list(sci_instr_temp,instr)
538                 end
539                 sci_instr($+1)=tlist(["sup_equal","sup_instr","nb_opr"],sci_instr_temp,mtlb_clause.statements(k).nb_opr)
540             else
541                 [instr,nblines]=instruction2sci(mtlb_clause.statements(k),nblines)
542                 // If inserted instruction is an initialisation, it has to be done just one time and before loop
543                 l=1;
544                 while l <= size(m2sci_to_insert_b)
545                     if typeof(m2sci_to_insert_b(l))=="equal" & ..
546                         (and(m2sci_to_insert_b(l).expression==Cste([])) | ..
547                         and(m2sci_to_insert_b(l).expression==Funcall("struct",1,list(),list())) | ..
548                         and(m2sci_to_insert_b(l).expression==Funcall("cell",1,list(),list())) ) then
549                         to_insert($+1)=m2sci_to_insert_b(l)
550                         m2sci_to_insert_b(l)=null()
551                         if size(m2sci_to_insert_b)>=l & m2sci_to_insert_b(l)==list("EOL") then
552                             to_insert($+1)=m2sci_to_insert_b(l)
553                             m2sci_to_insert_b(l)=null()
554                         end
555                     else
556                         l=l+1;
557                     end
558                 end
559                 sci_instr=update_instr_list(sci_instr,instr)
560             end
561         end
562         // Create Scilab while
563         sci_clause=tlist(["for","expression","statements"],sci_expr,sci_instr)
564     else
565         error(msprintf(gettext("unknown clause type: %s."),typeof(mtlb_clause)))
566     end
567     m2sci_to_insert_b=to_insert
568     if m2sci_to_insert_b<>list() then
569         m2sci_to_insert_b($+1)=list("EOL");
570     end
571 endfunction
572
573 // ---------------------------------------------------------------------------
574
575 function updatevarslist(instr_lhs)
576     // PRIVATE INTERNAL function called only by equal2sci() and clause2sci()
577     //                  that are also private to instruction2sci()
578     //
579     // (2 functions in this file: merge_vars() at the end)
580     // Update list of M2SCI variables with converted instruction lhs
581     // Input:
582     // - instr_lhs: list of lhs of current instruction
583     // - in_a_clause: boolean value
584     //   Set to 1 if instruction is in a clause
585     //   In this case, type and dimensions are set to unknown if differ from those already stored in varslist
586     //   (Default value is %F)
587
588     // Global variable for M2SCI
589     global("varslist")
590     if isempty(varslist)
591         varslist = list()
592     end
593     // level is declared in m2sci.sci and modified in clause2sci.sci
594     level;
595
596     rhs=argn(2)
597     if rhs==2 then
598         in_a_clause=%F
599     end
600
601     // Merge infered data from the last two parts of clause which are above the current part
602     // if we are in the third part of clause (current), then : merge the first and second part of clause
603     // when end of conversion of a clause : merge infered data from the last two parts of clause
604     levelsize=size(level,1)
605     changepartclause=%F
606
607     for i=size(varslist):-1:1
608         if size(varslist(i).level,1)==levelsize then
609             varlevel=varslist(i).level
610             if varlevel($)<>level($)
611                 changepartclause=%T
612             else
613                 changepartclause=%F
614                 break
615             end
616         end
617     end
618     if changepartclause | instr_lhs=="END OF CLAUSE" then
619         index=[] // Search variables from two part above current part clause
620         for k=size(varslist):-1:1
621             if size(varslist(k).level,1)==levelsize then
622                 varlevel=varslist(k).level
623                 if and(varlevel(1:$-1)==level(1:$-1)) & varlevel($)==level($)-2 then
624                     index=[index;k]
625                 end
626             end
627         end
628         if index<>[] then  // Found variables from the second part above current part of a clause
629             for k=1:size(index,1)
630                 boolmerge =%F
631                 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
632                     varlevel=varslist(i).level
633                     if varslist(i).matname==varslist(index(k)).matname & and(varlevel(1:$-1)==level(1:$-1)) &  varlevel($)==level($)-1 then
634                         boolmerge =%T // Found the same variable name from the last two parts above the current part : Merge
635                         merge_vars(index(k),varslist(i))
636                         varslist(i)=null()
637                         break
638                     end
639                 end
640                 if ~boolmerge then
641                     varslist(index(k)).level=[level(1:$-1);level($)-1]
642                 end
643             end
644         end
645     end
646
647     // Special case when end of conversion of a clause
648     // Merge infered data from clause and those from level-1
649     if instr_lhs=="END OF CLAUSE" then // Search variables in the last part of a clause (above end of conversion of a clause)
650         index=[] //
651         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
652             varlevel=varslist(k).level
653             if varlevel==[level(1:$-1);level($)-1] then
654                 index=[index;k]
655             end
656         end
657         if index<>[] then
658             for j=1:size(index,1)
659                 boolmerge=%F
660                 for k=size(varslist):-1:1 //
661                     varlevel=varslist(k).level
662                     if varslist(k).matname==varslist(index(j)).matname  & and(varlevel==level(1:$-1)) then
663                         boolmerge=%T // Found variables from level-1 which have the same name than variables from the last part of current level : Merge
664                         index_lower_level=k
665                         merge_vars(index_lower_level,varslist(index(j)))
666                         varslist(k).level=level(1:$-1)
667                         varslist(index(j))=null()
668                         break
669                     end
670                 end
671                 if boolmerge==%F then
672                     varslist(index(j)).level=level(1:$-1)
673                 end
674             end
675         end
676         return
677     end
678
679     // Expression: lhs name is empty => nothing to do
680     if instr_lhs==list() then
681         return
682     end
683
684     // Remove lhs which are not variables
685     k=1
686     while k<=size(instr_lhs)
687         // Insertion operation
688         if typeof(instr_lhs(k))=="operation" then
689             instr_lhs(k)=null()
690         else
691             k=k+1
692         end
693     end
694
695     if size(instr_lhs)==0 then
696         return
697     end
698
699     // Update varslist
700     for k=1:size(instr_lhs)
701         [bval,index]=isdefinedvar(instr_lhs(k))
702         ierr=execstr("zz=instr_lhs(k).contents.index","errcatch")
703         if ierr<>0 then pause;end
704         // Remove multiple entries from contents
705         for kcont = size(instr_lhs(k).contents.index):-1:1
706             [infertlist,pos]=get_contents_infer(instr_lhs(k),instr_lhs(k).contents.index(kcont))
707             if pos<>0 & pos<>kcont then
708                 instr_lhs(k).contents.index(pos)=null()
709                 instr_lhs(k).contents.data(pos)=null()
710             end
711         end
712         // If variable exists for the current level in the same part of clause then update exixting variable
713         if bval
714             boolupdate=%F
715             for l=1:size(varslist)
716                 if varslist(l).matname==instr_lhs(k).name & varslist(l).level==level then
717                     varslist(l)=M2scivar(varslist(l).sciname,..
718                     varslist(l).matname,..
719                     Infer(instr_lhs(k).infer.dims,instr_lhs(k).infer.type,instr_lhs(k).infer.contents),..
720                     varslist(l).level)
721                     boolupdate=%T
722                     break
723                 end
724             end
725             // If variable exists, but not for the current level or not in the same part of clause then Update variable then create new variable
726             if ~boolupdate then
727                 varslist($+1)=M2scivar(varslist(index).sciname,..
728                 varslist(index).matname,..
729                 instr_lhs(k).infer,..
730                 level)
731             end
732         else
733             // Variable added to varslist if as a name (not done for expressions
734             if execstr("f=instr_lhs(k).name","errcatch")<>0 then pause;end;errclear();
735             if instr_lhs(k).name<>"ans" then
736                 varslist($+1)=M2scivar(instr_lhs(k).name,..
737                 instr_lhs(k).name,..
738                 instr_lhs(k).infer,..
739                 level)
740             end
741         end
742     end
743 endfunction
744
745 // ---------------------------------------------------------------------------
746
747 function merge_vars(oldvarindex, newvar)
748     // PRIVATE INTERNAL function called only by updatevarslist() hereabove.
749     // M2SCI function
750     // Merge two variables inference properties, if different then set to Unknown
751     // Input:
752     // - oldvarindex: index of old variable in varslist
753     // - newvar: new variable to take in account to update oldvar properties
754
755     // Global variable for M2SCI
756     global("varslist")
757     oldvar=varslist(oldvarindex)
758
759     olddims=oldvar.dims
760     oldvtype=oldvar.vtype
761     oldprop=oldvar.property
762
763     newdims=newvar.dims
764     newvtype=newvar.vtype
765     newprop=newvar.property
766
767     // Verify dims
768     for l=1:min(size(newdims),size(olddims))
769         if newdims(l)<>olddims(l) then
770             newdims(l)=Unknown
771         end
772     end
773     if size(newdims)>size(olddims) then
774         for l=size(olddims):size(newdims)
775             newdims(l)=null()
776         end
777     end
778
779     // Verify vtype
780     if newvtype<>oldvtype then
781         newvtype=Unknown
782     end
783
784     // Verify property
785     if newprop<>oldprop then
786         newprop=Unknown
787     end
788
789     // Verify contents
790     for k = 1:size(newvar.contents.index)
791         olddata=get_contents_infer(oldvar,newvar.contents.index(k))
792         newdata=newvar.contents.data(k)
793
794         if or(olddata<>newdata) then
795             newvar.infer.contents.data(k)=Infer()
796         end
797     end
798
799     // Write result in varslist
800     varslist(oldvarindex)=M2scivar(oldvar.sciname,..
801     oldvar.matname,..
802     Infer(newdims,Type(newvtype,newprop),newvar.contents),..
803     newvar.level)
804 endfunction