* Bug 16679 fixed: get_function_path('acosh') yielded an error
[scilab.git] / scilab / modules / functions / macros / expression2code.sci
1 // Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
2 // Copyright (C) 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
14 function C=expression2code(e)
15     // Translate an expression tree to macro code (called by tree2code)
16     // Input:
17     // - e: expression 'tree'
18     // Output:
19     // - C: Scilab code corresponding to e
20     // V.C.
21
22     // Change format for constants
23     fmtsav=format();
24     format(16);
25
26     // Tables of symbols arranged by priority in computations
27     sumops=["+","-","&","|"] //1
28     prodops=["*","/",".*","./","\",".\","^",".^"] //2
29     othops=["==",">=","<=","~=",">","<","~",".''",".''",":"] //3
30
31     C=""
32     select typeof(e)
33         // ---------
34         // OPERATION
35         // ---------
36     case "operation" then
37         operator=e.operator
38         bracket = ["[", "]"];
39         // if Cell Exp {}
40         if or(operator == ["ccc", "crc"]) then
41             operator = part(operator, 2:$);
42             bracket = ["{", "}"];
43         end
44
45         operands=[]
46         nb_op=size(e.operands)
47         if and(operator<>["cc","cceol"]) then
48             for i=1:nb_op
49                 if e.operands(i)==list("EOL") then
50                     continue
51                 end
52                 expression = expression2code(e.operands(i));
53                 if expression == "eye()" then
54                     expression = ":";
55                 end
56                 operands=[operands;expression]
57             end
58         end
59
60         // Row concatenation
61         if operator=="rc" then
62             for i=1:nb_op
63                 if typeof(e.operands(i))=="operation" then
64                     if e.operands(i).operator=="rc" then
65                         operands(i)=part(operands(i),2:length(operands(i))-1)
66                     elseif or(e.operands(i).operator==["cceol"]) then
67                         operands(1)=part(operands(1),2:length(operands(1)))
68                         operands($)=part(operands($),1:length(operands($))-1)
69                     end
70                 end
71             end
72             C=bracket(1)+strcat(operands,",")+bracket(2);
73             // Multi-line column concatenation
74         elseif operator=="cceol" then
75             for i=1:nb_op
76                 opi=expression2code(e.operands(i))
77                 if typeof(e.operands(i))=="operation" then
78                     if e.operands(i).operator=="rc" then
79                         opi=part(opi,2:length(opi)-1)
80                     elseif or(e.operands(i).operator==["cc","cceol"]) then
81                         opi(1)=part(opi(1),2:length(opi(1)))
82                         opi($)=part(opi($),1:length(opi($))-1)
83                     end
84                 end
85
86                 if i==1 then
87                     C=bracket(1)
88                     if size(opi,"*")>1 then
89                         C = [C+opi(1);opi(2:$)]
90                     else
91                         C = C+opi
92                     end
93                     C($)=C($)+";"
94                     C=[C;""]
95                 else
96                     if size(opi,"*")>1 then
97                         C = [C(1:$-1);C($)+opi(1);opi(2:$)]
98                     else
99                         C = [C(1:$-1);C($)+opi]
100                     end
101                     C($)=C($)+bracket(2)
102                 end
103             end
104             // Column concatenation
105         elseif operator=="cc" then
106             C=bracket(1)
107             for i=1:nb_op
108                 opi=expression2code(e.operands(i))
109                 // Delete [ and ] if there are...
110                 if typeof(e.operands(i))=="operation" then
111                     if e.operands(i).operator=="rc" then
112                         opi=part(opi,2:length(opi)-1)
113                     elseif or(e.operands(i).operator==["cc","cceol"]) then
114                         opi(1)=part(opi(1),2:length(opi(1)))
115                         opi($)=part(opi($),1:length(opi($))-1)
116                     end
117                 end
118                 if i==1 then
119                     if size(opi,"*")>1 then
120                         C = [C+opi(1);opi(2:$)]
121                     elseif opi=="(EOL)" then
122                         C = [C;""];
123                     else
124                         C = C+opi
125                     end
126                     C($)=C($)+";"
127                 else
128                     if size(opi,"*")>1 then
129                         C = [C(1:$-1);C($)+opi(1);opi(2:$)]
130                     elseif opi=="(EOL)" then
131                         C = [C;""]
132                     else
133                         C = [C(1:$-1);C($)+opi]
134                     end
135                 end
136             end
137             C($)=C($)+bracket(2)
138             // Extraction
139         elseif operator=="ext" then
140             if size(e.operands)==1 then
141                 C=e.operands(1).name
142                 return
143             end
144             if type(e.operands(2))==15 then // Recursive extraction
145                 C=operands(1)+operands(2)
146             else
147                 // Deal with :
148                 for k=2:size(operands,"*")
149                     if operands(k)==""":""" then
150                         operands(k)=":"
151                     elseif operands(k)=="""$""" then
152                         operands(k)="$"
153                     elseif operands(k)=="""*""" then // Only used for M2SCI
154                         operands(k)="*"
155                     end
156                 end
157                 val = part(operands(2),1)=="""" & part(operands(2),length(operands(2)))==""""
158                 if val then // struct field
159                     C=operands(1)+"."+evstr(operands(2))
160                     if size(operands,"*")>=3 then
161                         C=C+"("
162                     end
163                     for k=3:size(operands,"*")
164                         C=C+","+operands(k)
165                     end
166                     if size(operands,"*")>=3 then
167                         C=C+")"
168                     end
169                 else
170                     C=operands(1)+"("+operands(2)
171                     for k=3:size(operands,"*")
172                         C=C+","+operands(k)
173                     end
174                     C=C+")"
175                 end
176             end
177             // Insertion
178         elseif operator=="ins" then
179             if type(e.operands(2))==15 then // Recursive insertion
180                 C=operands(1)+operands(2)
181             else
182                 // Deal with :
183                 for k=2:size(operands,"*")
184                     if operands(k)==""":""" then
185                         operands(k)=":"
186                     elseif operands(k)=="""$""" then
187                         operands(k)="$"
188                     elseif operands(k)=="""*""" then // Only used in M2SCI
189                         operands(k)="*"
190                     end
191                 end
192                 val = part(operands(2),1)=="""" & part(operands(2),length(operands(2)))==""""
193                 if val then // struct field
194                     C=operands(1)+"."+evstr(operands(2))
195                     if size(operands,"*")>=3 then
196                         C=C+"("
197                     end
198                     for k=3:size(operands,"*")
199                         C=C+","+operands(k)
200                     end
201                     if size(operands,"*")>=3 then
202                         C=C+")"
203                     end
204                 else
205                     C=operands(1)+"("+operands(2)
206                     for k=3:size(operands,"*")
207                         C=C+","+operands(k)
208                     end
209                     C=C+")"
210                 end
211             end
212             // Unary Operators
213         elseif size(operands,"*")==1 then
214             if or(operator==["''",".''"]) then
215                 if typeof(e.operands(1))=="operation" then
216                     if and(e.operands(1).operator<>["rc","cc","-","+"]) then
217                         operands="("+operands+")"
218                     end
219                 end
220                 C=operands+operator
221             elseif or(operator==["+","-"]) then
222                 if typeof(e.operands(1))=="operation" then
223                     if or(e.operands(1).operator==["-","+"]) then
224                         operands="("+operands+")"
225                     end
226                 end
227                 C=operator+operands
228             else
229                 C=operator+operands
230             end
231             // Other operators
232         else
233             // Parenthesize
234             if or(operator==["+","-"]) then
235                 for i=1:nb_op
236                     if typeof(e.operands(i))=="operation" then
237                         if or(e.operands(i).operator==othops) then
238                             operands=[operands(1:i-1) "("+operands(i)+")" operands(i+1:$)]
239                         end
240                     end
241                 end
242                 for i=2:nb_op
243                     if typeof(e.operands(i))=="operation" then
244                         if or(e.operands(i).operator==sumops) then
245                             operands=[operands(1:i-1) "("+operands(i)+")" operands(i+1:$)]
246                         end
247                     end
248                 end
249             end
250             if or(operator==[prodops,othops]) & (operator<>":") then
251                 if typeof(e.operands(1))=="operation" then
252                     if or(e.operands(1).operator==[sumops,prodops,othops]) then
253                         operands(1)="("+operands(1)+")"
254                     end
255                 end
256                 if typeof(e.operands(2))=="operation" then
257                     if or(e.operands(2).operator==[sumops,prodops,othops]) then
258                         operands(2)="("+operands(2)+")"
259                     end
260                 end
261             end
262             if part(operator,1)=="." & part(operator,length(operator))=="." | or(operator==["&","|"]) then
263                 C=strcat(operands," "+operator+" ")
264             elseif part(operator,1)=="." then
265                 C=strcat(operands," "+operator)
266             elseif part(operator,length(operator))=="." then
267                 C=strcat(operands,operator+" ")
268             else
269                 C=strcat(operands,operator)
270             end
271         end
272         // --------
273         // CONSTANT
274         // --------
275     case "cste" then
276         C=sci2exp(e.value)
277         if C==""":""" then
278             //C=":"
279         elseif C=="""$""" then
280             C="$"
281         elseif C=="""*""" then // Only used in M2SCI
282             C="""*"""
283             //  C="*"
284         end
285         // --------
286         // VARIABLE
287         // --------
288     case "variable" then
289         C=e.name
290         // ----------------
291         // CHARACTER STRING
292         // ----------------
293     case "string" then
294         C=e
295         // -------
296         // FUNCALL
297         // -------
298     case "funcall" then
299         if size(e.rhs)==0 then
300             I=I; // I is defined in instruction2code
301             C=e.name
302             [l,mac]=where()
303             if size(grep(mac,"expression2code"),"*")>1 then
304                 C=C+"()"
305             elseif typeof(I)=="equal" & ( (typeof(I.lhs(1))=="variable" & I.lhs(1).name<>"ans") | typeof(I.lhs(1))=="operation") then
306                 C=C+"()"
307             end
308         else
309             rhscode = rhs2code(e.rhs);
310             if size(rhscode,"*")==1 then
311                 C=[e.name+"("+rhscode+")"]
312             else
313                 C=[e.name+"("+rhscode(1);rhscode(2:($-1));rhscode($)+")"]
314             end
315         end
316         // ----
317         // LIST
318         // ----
319     case "list"
320         // Recursive extraction
321         C=""
322         for k=1:size(e)
323             ind=expression2code(e(k))
324             if type(e(k))==15 then // Recursive extraction in recursive extraction
325                 ind=strsubst(ind,")(",",")
326                 if part(ind, 1)=="(" then
327                     ind = part(ind, 2:length(ind))
328                 end
329                 if part(ind, length(ind))==")" then
330                     ind = part(ind, 1:(length(ind)-1))
331                 end
332             end
333             if ind==""":""" then
334                 ind=":"
335             elseif ind=="""$""" then
336                 ind="$"
337             elseif ind=="""*""" then // Only used in M2SCI
338                 ind="*"
339             end
340             val = part(ind,1)=="""" & part(ind,length(ind))==""""
341             if val then
342                 C=C+"."+evstr(ind)
343             else
344                 C=C+"("+ind+")"
345             end
346         end
347         C=strsubst(C,")(",",")
348         // -----
349         // EQUAL (can occur fir disp(a=1) for example)
350         // -----
351     case "equal"
352         C=instruction2code(e)
353         // ------
354         // INLINE
355         // ------
356     case "inline"
357         C=["function " + e.prototype;"  " + e.definition;"endfunction"];
358         // -------
359         // COMMENT (inside a matrix declaration for example)
360         // -------
361     case "comment"
362         C=instruction2code(e)
363     else
364         error(msprintf(gettext("%s: This feature has not been implemented: %s.\n"),"expression2code",typeof(e)));
365     end
366
367     // Restore format
368     if fmtsav(1)==1 then
369         format("v",fmtsav(2));
370     else
371         format("e",fmtsav(2));
372     end
373 endfunction
374
375