36a38213de8d2fc90a5c5012e91ee47bcd7489bc
[scilab.git] / scilab / modules / m2sci / macros / percent / %i_st2sci.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 [tree]=%i_st2sci(tree)
14     // M2SCI function
15     // Conversion function for Matlab insertion in structs
16     // Input: tree = Matlab operation tree
17     // Output: tree = Scilab equivalent for tree
18     // Emulation functions: mtlb_i() and mtlb_is()
19
20     // Global variable for M2SCI
21     global("varslist")
22
23     from=tree.operands($)
24     to=tree.operands(1)
25
26     // Insertion of a struct in a not-struct array
27     if typeof(to)=="variable" & to.vtype<>Struct then
28         // To be sure that variable will now be of type Struct
29         [bval,index]=isdefinedvar(to)
30         varslist(index).infer.type.vtype=Struct
31         varslist(index).infer.contents=Contents()
32         tree.out(1).infer=Infer(list(0,0),Type(Struct,Unknown),Contents())
33     elseif typeof(to)=="operation" & to.vtype<>Struct then
34         // To be sure that variable will now be of type Struct
35         [bval,index]=isdefinedvar(to.operands(1))
36         varslist(index).infer.type.vtype=Struct
37         varslist(index).infer.contents=Contents()
38         tree.out(1).infer=Infer(list(0,0),Type(Struct,Unknown),Contents())
39     end
40
41     // Just one index value
42     if rhs==1 then
43         ind=tree.operands(2)
44         // --- Insertion with just one index ---
45         if type(ind)<>15 then
46             // --- Insertion in a struct with just one index ---
47             if ind.vtype==String then // A.f
48                 tree.out(1).dims=list(1,1);
49                 tree.out(1).vtype=Struct
50                 tree.out(1).contents.index($+1)=list(list(Cste(1),Cste(1)),ind)
51                 tree.out(1).contents.data($+1)=from.infer
52             else
53                 if from.vtype<>Double then // X(p)=struct(...)
54                     tree.operands(2)=list(Cste(1),tree.operands(2))
55                     tree.out(1).vtype=Struct
56                     if typeof(ind)=="cste" then
57                         if ind.vtype<>String then // Not :
58                             tree.out(1).dims=list(1,ind.value)
59
60                             tree.out(1).contents.index($+1)=list(Cste(1),ind)
61
62                             // Update contents for an extraction of type: z = X(p)
63                             CONT=Contents()
64                             for k=1:lstsize(from.infer.contents.index)
65                                 if type(from.contents.index(k)(1))==15 then
66                                     CONT.index($+1)=list(from.contents.index(k)(2))
67                                 else
68                                     CONT.index($+1)=list(from.contents.index(k))
69                                 end
70                                 CONT.data($+1)=from.contents.data(k)
71                             end
72                             tree.out(1).contents.data($+1)=Infer(list(1,1),Type(Struct,Unknown),CONT)
73
74                             // Update contents for extraction of type: z = X(p).f
75                             for k=1:lstsize(from.infer.contents.index)
76                                 if type(from.contents.index(k)(1))==15 then
77                                     tree.out(1).contents.index($+1)=list(list(Cste(1),ind),from.contents.index(k)(2))
78                                 else
79                                     tree.out(1).contents.index($+1)=list(list(Cste(1),ind),from.contents.index(k))
80                                 end
81                                 tree.out(1).contents.data($+1)=from.contents.data(k)
82                             end
83                         else
84                             tree.out(1).dims=from.dims
85                             tree.out(1).contents=from.contents
86                         end
87                     end
88                 else
89                     if is_empty(from) then // Clear element: A(p)=[]
90                         // Nothing done
91                     else // Change type of variable
92                         error(gettext("Not yet implemented."))
93                     end
94                 end
95             end
96             // --- Insertion with more than one index value (index is a recursive index list) ---
97         else
98
99             // Change index value if just one double
100             for k=1:lstsize(ind)
101                 //ind(k+1) <-> tree.operands(2)(k+1)
102                 if typeof(ind(k))=="cste" | (typeof(ind(k))<>"list" & is_a_scalar(ind(k))) then
103                     if ind(k).vtype<>String then
104                         tree.operands(2)(k)=list(Cste(1),tree.operands(2)(k))
105                     end
106                 end
107             end
108             ind=tree.operands(2);
109
110             if typeof(ind($))=="list" | ind($).vtype~=String then // X.p(m,n)=y
111                 tmp=gettempvar()
112                 oplist=list()
113
114                 tmpind=ind
115                 tmpind($)=null()
116                 if or(get_contents_infer(tree.operands(1),tmpind)<>Infer()) then
117                     tmp.infer=get_contents_infer(tree.operands(1),tmpind)
118                 end
119                 oplist(1)=tmp
120
121                 for kind=1:size(ind($))
122                     oplist($+1)=ind($)(kind)
123                 end
124
125                 oplist($+1)=tree.operands($)
126
127                 newop=Operation("ins",oplist,list(tmp))
128                 newop=%i2sci(newop)
129                 tree.out(1).infer.contents.index($+1)=tmpind
130                 tree.out(1).infer.contents.data($+1)=newop.out(1).infer
131             end
132
133             infertree=tree.operands(2)
134
135             // A(x,y,...).f
136             if typeof(infertree(1))=="list" then
137                 possible_dims=infertree(1)
138                 infdims=tree.out(1).dims
139                 if lstsize(infdims)<lstsize(possible_dims) then
140                     for k=lstsize(infdims)+1:lstsize(possible_dims)
141                         infdims(k)=Unknown
142                     end
143                 end
144                 for k=1:lstsize(possible_dims)
145                     if typeof(possible_dims(k))<>"cste" then
146                         infdims(k)=Unknown
147                     elseif infdims(k)<>Unknown & infdims(k)<possible_dims(k).value then
148                         infdims(k)=possible_dims(k).value
149                     end
150                 end
151                 tree.out(1).infer.contents.index($+1)=ind
152                 tree.out(1).infer.contents.data($+1)=from.infer
153                 tree.out(1).dims=infdims
154                 tree.out(1).type=Type(Struct,Unknown)
155                 // A.b.f
156             else
157                 tree.out(1).dims=list(1,1)
158                 tree.out(1).type=Type(Struct,Unknown)
159                 tree.out(1).infer.contents.index($+1)=ind
160                 tree.out(1).infer.contents.data($+1)=from.infer
161             end
162
163         end
164         // Two indexes: to(ind1,ind2,...)=from or more
165     else
166         tree.out(1).dims=list()
167         for k=1:lstsize(tree.operands)-2
168             tree.out(1).dims(k)=Unknown
169         end
170
171         // dim can be infered when index is a constant and when index value is greater than older dim and this dim is not unknown
172         for kdim=1:size(tree.operands)-2
173             if typeof(tree.operands(kdim+1))=="cste" then
174                 if to.dims(kdim)<>Unknown then
175                     if to.dims(kdim)<=tree.operands(kdim+1).value then
176                         tree.out(1).dims(kdim)=tree.operands(kdim+1).value;
177                     else
178                         tree.out(1).dims(kdim)=to.dims(kdim)
179                     end
180                 end
181             end
182         end
183         tree.out(1).type=from.type
184
185         // Update contents
186         ind=tree.operands
187         ind(1)=null()
188         ind($)=null()
189         tree.out(1).infer.contents.index($+1)=ind
190         tree.out(1).infer.contents.data($+1)=from.infer
191
192     end
193 endfunction
194