License Header change: Removed the LICENSE_END before beta
[scilab.git] / scilab / modules / ast / src / cpp / analysis / VisitOpExp.cpp
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2015 - Scilab Enterprises - Calixte DENIZET
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  */
15
16 #include "AnalysisVisitor.hxx"
17 #include "analyzers/OperAnalyzer.hxx"
18 #include "tools.hxx"
19
20 namespace analysis
21 {
22
23 void AnalysisVisitor::visit(ast::OpExp & e)
24 {
25     logger.log(L"OpExp", e.getLocation());
26     TIType resT(getGVN());
27     int tempId = -1;
28     bool safe = false;
29     ast::Exp & Lexp = e.getLeft();
30     ast::Exp & Rexp = e.getRight();
31
32     Lexp.accept(*this);
33     Result LR = getResult();
34     Rexp.accept(*this);
35     Result & RR = getResult();
36     if (LR.getType().isknown() && RR.getType().isknown())
37     {
38         TIType & LT = LR.getType();
39         TIType & RT = RR.getType();
40
41         if (!operSymbolicRange(e) && !operGVNValues(e))
42         {
43             switch (e.getOper())
44             {
45                 case ast::OpExp::plus :
46                 {
47                     resT = checkEWBinOp<_check_plus>(LT, RT, LR, RR, safe, tempId, &Lexp, &Rexp);
48                     break;
49                 }
50                 case ast::OpExp::minus:
51                 {
52                     resT = checkEWBinOp<_check_minus>(LT, RT, LR, RR, safe, tempId, &Lexp, &Rexp);
53                     break;
54                 }
55                 case ast::OpExp::times:
56                 {
57                     resT = Checkers::check_____times____(getGVN(), LT, RT);
58                     if (resT.hasInvalidDims())
59                     {
60                         const bool ret = getCM().check(ConstraintManager::EQUAL, LT.cols.getValue(), RT.rows.getValue());
61                         if (ret)
62                         {
63                             resT = Checkers::check_____times____(getGVN(), LT, RT);
64                             safe = true;
65                         }
66                         else
67                         {
68                             resT = resT.asUnknownMatrix();
69                         }
70                     }
71                     else
72                     {
73                         safe = true;
74                     }
75
76                     tempId = dm.getTmpId(resT, false);
77                     dm.releaseTmp(LR.getTempId(), &e);
78                     dm.releaseTmp(RR.getTempId(), &e);
79
80                     break;
81                 }
82                 case ast::OpExp::rdivide:
83                 {
84                     resT = Checkers::check_____rdivide____(getGVN(), LT, RT);
85                     if (resT.hasInvalidDims())
86                     {
87                         const bool ret = getCM().check(ConstraintManager::EQUAL, LT.cols.getValue(), RT.cols.getValue());
88                         if (ret)
89                         {
90                             resT = Checkers::check_____rdivide____(getGVN(), LT, RT);
91                             safe = true;
92                         }
93                         else
94                         {
95                             resT = resT.asUnknownMatrix();
96                         }
97                     }
98                     else
99                     {
100                         safe = true;
101                     }
102
103                     tempId = dm.getTmpId(resT, false);
104                     dm.releaseTmp(LR.getTempId(), &e);
105                     dm.releaseTmp(RR.getTempId(), &e);
106                     break;
107                 }
108                 case ast::OpExp::ldivide:
109                 {
110                     resT = Checkers::check_____ldivide____(getGVN(), LT, RT);
111                     if (resT.hasInvalidDims())
112                     {
113                         const bool ret = getCM().check(ConstraintManager::EQUAL, LT.rows.getValue(), RT.rows.getValue());
114                         if (ret)
115                         {
116                             resT = Checkers::check_____ldivide____(getGVN(), LT, RT);
117                             safe = true;
118                         }
119                         else
120                         {
121                             resT = resT.asUnknownMatrix();
122                         }
123                     }
124                     else
125                     {
126                         safe = true;
127                     }
128
129                     tempId = dm.getTmpId(resT, false);
130                     dm.releaseTmp(LR.getTempId(), &e);
131                     dm.releaseTmp(RR.getTempId(), &e);
132                     break;
133                 }
134                 case ast::OpExp::power:
135                 {
136                     resT = Checkers::check_____power____(getGVN(), LT, RT);
137                     if (resT.hasInvalidDims())
138                     {
139                         const bool ret = getCM().check(ConstraintManager::EQUAL, LT.rows.getValue(), LT.cols.getValue());
140                         if (ret)
141                         {
142                             resT = Checkers::check_____power____(getGVN(), LT, RT);
143                             safe = true;
144                         }
145                         else
146                         {
147                             resT = resT.asUnknownMatrix();
148                         }
149                     }
150                     else
151                     {
152                         safe = true;
153                     }
154
155                     tempId = dm.getTmpId(resT, false);
156                     dm.releaseTmp(LR.getTempId(), &e);
157                     dm.releaseTmp(RR.getTempId(), &e);
158                     break;
159                 }
160                 case ast::OpExp::dottimes :
161                 {
162                     resT = checkEWBinOp<_check_dottimes>(LT, RT, LR, RR, safe, tempId, &Lexp, &Rexp);
163                     break;
164                 }
165                 case ast::OpExp::dotrdivide:
166                 {
167                     resT = checkEWBinOp<_check_dotrdiv>(LT, RT, LR, RR, safe, tempId, &Lexp, &Rexp);
168                     break;
169                 }
170                 case ast::OpExp::dotpower:
171                 {
172                     resT = checkEWBinOp<_check_dotpower>(LT, RT, LR, RR, safe, tempId, &Lexp, &Rexp);
173                     break;
174                 }
175                 case ast::OpExp::unaryMinus :
176                 {
177                     resT = Checkers::check_____unaryminus____(getGVN(), RT);
178                     if (!resT.hasInvalidDims())
179                     {
180                         safe = true;
181                     }
182                     tempId = RR.getTempId();
183                     break;
184                 }
185                 case ast::OpExp::krontimes :
186                 {
187                     resT = Checkers::check_____krontimes____(getGVN(), LT, RT);
188                     if (!resT.hasInvalidDims())
189                     {
190                         safe = true;
191                     }
192                     tempId = dm.getTmpId(resT, false);
193                     dm.releaseTmp(LR.getTempId(), &e);
194                     dm.releaseTmp(RR.getTempId(), &e);
195                     break;
196                 }
197                 case ast::OpExp::eq:
198                 {
199                     resT = checkEWBinOp<_check_eq>(LT, RT, LR, RR, safe, tempId, &Lexp, &Rexp);
200                     break;
201                 }
202                 case ast::OpExp::ne:
203                 {
204                     resT = checkEWBinOp<_check_neq>(LT, RT, LR, RR, safe, tempId, &Lexp, &Rexp);
205                     break;
206                 }
207                 case ast::OpExp::lt:
208                 {
209                     resT = checkEWBinOp<_check_lt>(LT, RT, LR, RR, safe, tempId, &Lexp, &Rexp);
210                     break;
211                 }
212                 case ast::OpExp::le:
213                 {
214                     resT = checkEWBinOp<_check_le>(LT, RT, LR, RR, safe, tempId, &Lexp, &Rexp);
215                     break;
216                 }
217                 case ast::OpExp::gt:
218                 {
219                     resT = checkEWBinOp<_check_gt>(LT, RT, LR, RR, safe, tempId, &Lexp, &Rexp);
220                     break;
221                 }
222                 case ast::OpExp::ge:
223                 {
224                     resT = checkEWBinOp<_check_ge>(LT, RT, LR, RR, safe, tempId, &Lexp, &Rexp);
225                     break;
226                 }
227                 case ast::OpExp::logicalAnd:
228                 {
229                     resT = checkEWBinOp<_check_and>(LT, RT, LR, RR, safe, tempId, &Lexp, &Rexp);
230                     break;
231                 }
232                 case ast::OpExp::logicalOr:
233                 {
234                     resT = checkEWBinOp<_check_or>(LT, RT, LR, RR, safe, tempId, &Lexp, &Rexp);
235                     break;
236                 }
237                 case ast::OpExp::logicalShortCutAnd:
238                 {
239                     resT = checkEWBinOp<_check_andand>(LT, RT, LR, RR, safe, tempId, &Lexp, &Rexp);
240                     break;
241                 }
242                 case ast::OpExp::logicalShortCutOr:
243                 {
244                     resT = checkEWBinOp<_check_oror>(LT, RT, LR, RR, safe, tempId, &Lexp, &Rexp);
245                     break;
246                 }
247             }
248         }
249         else
250         {
251             // SymbolicRange or GVNValue ops.
252             return;
253         }
254     }
255
256     e.getDecorator().safe = safe;
257     e.getDecorator().res = Result(resT, tempId);
258     setResult(e.getDecorator().res);
259
260     OperAnalyzer opAn;
261     opAn.analyze(*this, e);
262 }
263
264 void AnalysisVisitor::visit(ast::NotExp & e)
265 {
266     logger.log(L"NotExp", e.getLocation());
267     e.getExp().accept(*this);
268     Result & LR = getResult();
269     TIType & LT = LR.getType();
270     const int tempId = LR.getTempId();
271     if (LT.isknown())
272     {
273         TIType resT = Checkers::check_____not____(getGVN(), LT);
274         e.getDecorator().res = Result(resT, tempId);
275         e.getDecorator().safe = true;
276     }
277     else
278     {
279         e.getDecorator().res = Result(TIType(getGVN()), tempId);
280     }
281     setResult(e.getDecorator().res);
282 }
283
284 void AnalysisVisitor::visit(ast::TransposeExp & e)
285 {
286     logger.log(L"TransposeExp", e.getLocation());
287     e.getExp().accept(*this);
288     Result & res = getResult();
289     const TIType & type = res.getType();
290     TIType resType(dm.getGVN(), type.type, type.cols, type.rows);
291     e.getDecorator().res = Result(resType, dm.getTmpId(resType, false));
292     e.getDecorator().safe = true;
293     dm.releaseTmp(res.getTempId(), &e);
294
295     setResult(e.getDecorator().res);
296 }
297 }