[m2sci] kernel code reorganization: clarify dependencies & ease code browsing
[scilab.git] / scilab / modules / m2sci / macros / kernel / sci_m2scideclare.sci
1 // Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
2 // Copyright (C) ???? - INRIA - Scilab
3 // Copyright (C) 2002-2004 - INRIA - Vincent COUVERT
4 //
5 // Copyright (C) 2012 - 2016 - Scilab Enterprises
6 //
7 // This file is hereby licensed under the terms of the GNU GPL v2.0,
8 // pursuant to article 5.3.4 of the CeCILL v.2.1.
9 // This file was originally licensed under the terms of the CeCILL v2.1,
10 // and continues to be available under such terms.
11 // For more information, see the COPYING file which you should have received
12 // along with this program.
13
14 function sci_m2scideclare(def)
15     // INTERNAL function called only by expression2sci()
16     //
17     // This function translate calls to m2scideclare
18     // which can be used by the user to influence translation
19     // by adding a comment which begins by m2scideclare
20
21     // Global variable for M2SCI
22     global("varslist")
23
24     //variable_name|dimensions|datatype|property
25
26     //dimensions: variable dimensions separated by blanks (Unknown dimension is ?)
27
28     //datatype:
29     // - double: scalar/vector/matrix/hypermatrix containing double values
30     // - string: scalar/vector/matrix/hypermatrix containing character strings
31     // - boolean: scalar/vector/matrix/hypermatrix containing boolean values
32     // - int: scalar/vector/matrix/hypermatrix containing integer values
33     // - handle: matrix of graphics handles or graphics handle
34     // - sparse: sparse scalar/vector/matrix/hypermatrix
35     // - cell: cell array
36     // - struct: struct array
37     // - ? if unknown
38
39     //property:
40     // - real/complex/? for double and int datatype
41     // - real for string and boolean datatype (ignored if not)
42     // - NOT USED for struct/cell/handle datatype
43
44     // def is the comment added by the user
45     userdata=def.rhs(1).value
46     // Remove all multiple blanks
47     while strindex(userdata,"  ")<>[]
48         userdata=strsubst(userdat,"  "," ")
49     end
50
51     seppos=strindex(userdata,"|")
52
53     seppos=[seppos,length(userdata)+1]
54
55     nbsep=size(seppos,"*")
56
57     if nbsep<3 then
58         error(gettext("not enough data, you should give at least variable_name|dimensions|datatype."));
59     elseif nbsep>4 then
60         error(gettext("too much data."));
61     end
62
63     name=stripblanks(part(userdata,1:seppos(1)-1))
64
65     dimstxt=part(userdata,seppos(1)+1:seppos(2)-1)
66
67     datatypetxt=part(userdata,seppos(2)+1:seppos(3)-1)
68
69     if nbsep==4 then
70         proptxt=part(userdata,seppos(3)+1:seppos(4)-1)
71     else
72         proptxt="?"
73     end
74
75     // Dimensions
76     dimstxt=strsubst(dimstxt,"?","-1")
77     dimstxt=strsubst(dimstxt,"*","-2")
78     dimstxt=strsubst(dimstxt,"#","-3")
79     blpos=strindex(dimstxt," ")
80     nbblanks=size(blpos)
81     blpos=[1,blpos,length(dimstxt)+1]
82     fmt="%d"
83     dims=list()
84     for kbl=1:size(blpos,"*")-1
85         dims($+1)=evstr(part(dimstxt,blpos(kbl):blpos(kbl+1)))
86     end
87
88     // Datatype
89     datatypetxt=strsubst(datatypetxt,"?","Unknown")
90     datatype=convstr(datatypetxt,"l")
91     if or(datatype==["double","boolean","string","int","handle","sparse","cell","struct","unknown"]) then
92         datatype=convstr(part(datatype,1),"u")+convstr(part(datatype,2:length(datatype)),"l")
93         vtype=evstr(datatype)
94     else
95         error(msprintf(gettext("Unknown datatype %s."),datatypetxt));
96     end
97
98     // Property
99     proptxt=strsubst(proptxt,"?","Unknown")
100     prop=convstr(proptxt,"l")
101     if or(prop==["real","complex","homogen","unknown"]) then
102         prop=convstr(part(prop,1),"u")+part(prop,2:length(prop))
103         property=evstr(prop)
104     else
105         error(msprintf(gettext("Unknown property %s."),proptxt));
106     end
107     // Property correction
108     if or(vtype==[Boolean,String]) then
109         property=Real
110     end
111
112     if strindex(name,".")<>[] then // Cell or Struct m2scideclare
113         // Get varname
114         endofname=min([strindex(name,[".","("])])-1
115         varname=part(name,1:endofname)
116
117         // First field name (if is 'entries' then a cell else a struct)
118         firstpoint=min(strindex(name,"."))
119         secpoint=min(strindex(part(name,firstpoint+1:length(name)),"."))
120         par=min(strindex(part(name,firstpoint+1:length(name)),"("))
121         if isempty(secpoint) & isempty(par) then //x.fieldname
122             firstfield=part(name,firstpoint:length(name))
123         elseif isempty(secpoint) then //x.fieldname(p...)
124             firstfield=part(name,firstpoint:par-1)
125         elseif isempty(par) then //x.fieldname.fieldname2
126             firstfield=part(name,firstpoint:secpoint-1)
127         else //x.fieldname(p...).fieldname2
128             firstfield=part(name,firstpoint:min([secpoint par])-1)
129         end
130         if firstfield==".entries" then // Cell
131             vartype=Cell
132         else // Struct
133             vartype=Struct
134         end
135
136         // Indexes for varname ? myvar(1,2).field....
137         if or(strindex(name,"(")<strindex(name,".")) | (~isempty(strindex(name,"("))&isempty(strindex(name,"."))) then
138             ierr=execstr("vardims=list"+part(name,min(strindex(name,"(")):min(strindex(name,")"))),"errcatch")
139             if ierr then
140                 if ~isempty(strindex(part(name,min(strindex(name,"(")):min(strindex(name,")"))),"*")) then // Generic command *
141                     vardims="generic"
142                 else
143                     error(gettext("Wrong dimensions user data."));
144                 end
145             end
146         else
147             vardims=list(1,1)
148         end
149
150         [isvar,index]=isdefinedvar(Variable(varname,Infer()))
151
152         if ~isvar then // If variable does not exist it is added to varslist
153             if vardims=="generic" then
154                 vardims=list(Unknown,Unknown)
155             end
156             contents=Contents()
157             name=strsubst(name,"*","%genericm2sciindex")
158             deff("m2scitmp",name)
159             t=macr2tree(m2scitmp);
160             if isempty(firstpoint) then
161                 contents.index($+1)=t.statements(2).expression.rhs;
162             else
163                 contents.index($+1)=t.statements(2).expression.rhs(1);
164             end
165             clear m2scitmp
166             for k = 1:size(contents.index($))
167                 if typeof(contents.index($)(k))=="variable" & contents.index($)(k).name=="%genericm2sciindex" then
168                     contents.index($)(k)=Cste("*")
169                 elseif typeof(contents.index($)(k))=="cste" then
170                     contents.index($)(k)=Cste(contents.index($)(k).value)
171                 elseif typeof(contents.index($)(k))=="list" then
172                     for kk = 1:size(contents.index($)(k))
173                         if typeof(contents.index($)(k)(kk))=="variable" & contents.index($)(k)(kk).name=="%genericm2sciindex" then
174                             contents.index($)(k)(kk)=Cste("*")
175                         elseif typeof(contents.index($)(k)(kk))=="cste" then
176                             contents.index($)(k)(kk)=Cste(contents.index($)(k)(kk).value)
177                         end
178                     end
179                 end
180             end
181             contents.data($+1)=Infer(dims,Type(vtype,property))
182             varslist($+1)=M2scivar(varname,varname,Infer(vardims,Type(vartype,Unknown),contents))
183         else
184             if vardims=="generic" then
185                 vardims=varslist(index).dims
186             else
187                 vardims=dims
188             end
189
190             infereddims=varslist(index).dims
191
192             err=%F
193             for kd=1:min([size(vardims) size(infereddims)])
194                 if infereddims(kd)~=vardims(kd) & infereddims(kd)<>Unknown then
195                     err=%T
196                     break
197                 end
198             end
199
200             // Update dimensions
201             if err then
202                 set_infos(msprintf(gettext("Dimensions current value and m2scideclare statements conflict for: %s\n   m2scideclare given dimension: %s\n   Current dimension: %s\n   m2scideclare IGNORED"),varname,dims2str(vardims),dims2str(infereddims)),2)
203             else
204                 varslist(index)=M2scivar(varslist(index).matname,varslist(index).matname,Infer(vardims,Type(varslist(index).type.vtype,property)))
205             end
206
207             // Update vtype
208             if varslist(index).type.vtype==Unknown then
209                 varslist(index)=M2scivar(varslist(index).matname,varslist(index).matname,Infer(vardims,Type(vartype,varslist(index).property)))
210             elseif varslist(index).type.vtype~=vartype then
211                 set_infos(msprintf(gettext("Type current value and m2scideclare statements conflict for: %s\n   m2scideclare given type: %s\n   current type: %s\n   m2scideclare IGNORED"),varname,tp2str(vartype),tp2str(varslist(index).type.vtype)),2)
212             end
213
214             // Update property
215             if varslist(index).property==Unknown then
216                 varslist(index).infer.type.property=property
217             elseif property==Unknown then
218                 varslist(index).type.property=Unknown
219             elseif varslist(index).type.property~=property then
220                 set_infos(msprintf(gettext("Property current value and m2scideclare statements conflict for: %s\n   m2scideclare given type: %s\n   current type: %s\n   m2scideclare IGNORED"),name,prop2str(Unknown),prop2str(varslist(index).type.property)),2)
221             end
222
223             // Update contents (no verification made...too complex)
224             contents=varslist(index).contents
225             name=strsubst(name,"*","%genericm2sciindex")
226             deff("m2scitmp",name)
227             t=macr2tree(m2scitmp);
228             if isempty(firstpoint) then
229                 contents.index($+1)=t.statements(2).expression.rhs;
230             else
231                 contents.index($+1)=t.statements(2).expression.rhs(1);
232             end
233             clear m2scitmp
234             for k=1:size(contents.index($))
235                 if typeof(contents.index($)(k))=="variable" & contents.index($)(k).name=="%genericm2sciindex" then
236                     contents.index($)(k)=Cste("*")
237                 elseif typeof(contents.index($)(k))=="cste" then
238                     contents.index($)(k)=Cste(contents.index($)(k).value)
239                 elseif typeof(contents.index($)(k))=="list" then
240                     for kk=1:size(contents.index($)(k))
241                         if typeof(contents.index($)(k)(kk))=="variable" & contents.index($)(k)(kk).name=="%genericm2sciindex" then
242                             contents.index($)(k)(kk)=Cste("*")
243                         elseif typeof(contents.index($)(k)(kk))=="cste" then
244                             contents.index($)(k)(kk)=Cste(contents.index($)(k)(kk).value)
245                         end
246                     end
247                 end
248             end
249             contents.data($+1)=Infer(dims,Type(vtype,property))
250             varslist(index)=M2scivar(varname,varname,Infer(vardims,Type(vartype,Unknown),contents))
251
252         end
253     else // Variable m2scideclare
254
255         // Special part for %graphicswindow
256         if name=="%graphicswindow" then
257             global %graphicswindow
258             if and(vtype<>[Handle,Double]) then
259                 set_infos(gettext("%graphicswindow set to default value Handle."),2);
260             else
261                 %graphicswindow=vtype
262             end
263             return
264         end
265
266         [isvar,index]=isdefinedvar(Variable(name,Infer()))
267
268         if ~isvar then // If variable does not exist it is added to varslist
269             varslist($+1)=M2scivar(name,name,Infer(dims,Type(vtype,property)))
270         else // Try to compare with already infered data
271             // Update dims
272             infereddims=varslist(index).dims
273
274             err=%F
275             for kd=1:min([size(dims) size(infereddims)])
276                 if infereddims(kd)~=dims(kd) & infereddims(kd)<>Unknown then
277                     err=%T
278                     break
279                 end
280             end
281
282             if err then
283                 set_infos(msprintf(gettext("Dimensions current value and m2scideclare statements conflict for: %s\n   m2scideclare given dimension: %s\n   Current dimension: %s\n   m2scideclare IGNORED"),name,dims2str(dims),dims2str(infereddims)),2)
284             else
285                 varslist(index)=M2scivar(varslist(index).matname,varslist(index).sciname,Infer(dims,varslist(index).type))
286             end
287
288             // Update vtype
289             if varslist(index).type.vtype==Unknown then
290                 varslist(index)=M2scivar(varslist(index).matname,varslist(index).sciname,Infer(varslist(index).dims,Type(vtype,varslist(index).type.property)))
291             elseif varslist(index).type.vtype~=vtype then
292                 set_infos(msprintf(gettext("Type current value and m2scideclare statements conflict for: %s\n   m2scideclare given type: %s\n   current type: %s\n   m2scideclare IGNORED"),name,tp2str(vtype),tp2str(varslist(index).type.vtype)),2)
293             end
294
295             // Update property
296             if varslist(index).type.property==Unknown then
297                 varslist(index)=M2scivar(varslist(index).matname,varslist(index).sciname,Infer(varslist(index).dims,Type(varslist(index).type.vtype,property)))
298             elseif varslist(index).type.property~=property then
299                 set_infos(msprintf(gettext("Property current value and m2scideclare statements conflict for: %s\n   m2scideclare given type: %s\n   current type: %s\n   m2scideclare IGNORED"),name,prop2str(property),prop2str(varslist(index).type.property)),2)
300             end
301         end
302     end
303 endfunction
304
305
306 function str=tp2str(tp)
307     // Returns equivalent of typeof() from data coming from type()
308
309     if tp==1 then
310         str="Double"
311     elseif tp==4 then
312         str="Boolean"
313     elseif tp==6 then
314         str="Sparse"
315     elseif tp==8 then
316         str="Int"
317     elseif tp==9 then
318         str="Handle"
319     elseif tp==10 then
320         str="String"
321     elseif tp==16 then
322         str="Struct"
323     elseif tp==17 then
324         str="Cell"
325     elseif tp==-1 then
326         str="Unknown"
327     else
328         error(msprintf(gettext("type %d is not implemented."),tp))
329     end
330 endfunction
331
332 function str=prop2str(prop)
333     if type(prop)==10 then
334         str=prop
335     elseif prop==-1 then
336         str="Unknown"
337     else
338         error(msprintf(gettext("type %d is not implemented."),prop))
339     end
340 endfunction
341
342 function str=dims2str(dims)
343     str=""
344     for kd=1:size(dims)
345         str=str+string(dims(kd))+" "
346     end
347 endfunction