bug 14671: || misworks when LHS is %f or zeros. ...
[scilab.git] / scilab / modules / ast / src / cpp / ast / run_OpExp.hpp
1 /*
2 *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3 *  Copyright (C) 2008-2008 - DIGITEO - Antoine ELIAS
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 //file included in runvisitor.cpp
17 namespace ast {
18
19 template<class T>
20 void RunVisitorT<T>::visitprivate(const OpExp &e)
21 {
22     CoverageInstance::invokeAndStartChrono((void*)&e);
23     types::InternalType * pITL = NULL, *pITR = NULL, *pResult = NULL;
24     try
25     {
26         /*getting what to assign*/
27         e.getLeft().accept(*this);
28         if (isSingleResult() == false)
29         {
30             clearResult();
31             std::wostringstream os;
32             os << _W("Incompatible output argument.\n");
33             //os << ((Location)e.right_get().getLocation()).getLocationString() << std::endl;
34             throw ast::InternalError(os.str(), 999, e.getRight().getLocation());
35         }
36         pITL = getResult();
37
38         /*getting what to assign*/
39         e.getRight().accept(*this);
40         if (isSingleResult() == false)
41         {
42             clearResult();
43             std::wostringstream os;
44             os << _W("Incompatible output argument.\n");
45             //os << ((Location)e.right_get().getLocation()).getLocationString() << std::endl;
46             throw ast::InternalError(os.str(), 999, e.getRight().getLocation());
47         }
48         pITR = getResult();
49
50         if (pITL->getType() == types::InternalType::ScilabImplicitList)
51         {
52             types::ImplicitList* pIL = pITL->getAs<types::ImplicitList>();
53             if (pIL->isComputable())
54             {
55                 pITL = pIL->extractFullMatrix();
56                 pIL->killMe();
57             }
58         }
59
60         if (pITR->getType() == types::InternalType::ScilabImplicitList)
61         {
62             types::ImplicitList* pIR = pITR->getAs<types::ImplicitList>();
63             if (pIR->isComputable())
64             {
65                 pITR = pIR->extractFullMatrix();
66                 pIR->killMe();
67             }
68         }
69
70         switch (e.getOper())
71         {
72             case OpExp::plus:
73             {
74                 pResult = GenericPlus(pITL, pITR);
75                 break;
76             }
77             case OpExp::unaryMinus:
78             {
79                 pResult = GenericUnaryMinus(pITR);
80                 break;
81             }
82             case OpExp::minus:
83             {
84                 pResult = GenericMinus(pITL, pITR);
85                 break;
86             }
87             case OpExp::times:
88             {
89                 pResult = GenericTimes(pITL, pITR);
90                 break;
91             }
92             case OpExp::ldivide:
93             {
94                 pResult = GenericLDivide(pITL, pITR);
95                 break;
96             }
97             case OpExp::dotldivide:
98             {
99                 pResult = GenericDotLDivide(pITL, pITR);
100                 break;
101             }
102             case OpExp::rdivide:
103             {
104                 pResult = GenericRDivide(pITL, pITR);
105                 break;
106             }
107             case OpExp::dotrdivide:
108             {
109                 pResult = GenericDotRDivide(pITL, pITR);
110                 break;
111             }
112             case OpExp::dottimes:
113             {
114                 pResult = GenericDotTimes(pITL, pITR);
115                 break;
116             }
117             case OpExp::dotpower:
118             {
119                 pResult = GenericDotPower(pITL, pITR);
120                 break;
121             }
122             case OpExp::eq:
123             {
124                 pResult = GenericComparisonEqual(pITL, pITR);
125                 break;
126             }
127             case OpExp::ne:
128             {
129                 pResult = GenericComparisonNonEqual(pITL, pITR);
130                 break;
131             }
132             case OpExp::lt:
133             {
134                 pResult = GenericLess(pITL, pITR);
135                 break;
136             }
137             case OpExp::le:
138             {
139                 pResult = GenericLessEqual(pITL, pITR);
140                 break;
141             }
142             case OpExp::gt:
143             {
144                 pResult = GenericGreater(pITL, pITR);
145                 break;
146             }
147             case OpExp::ge:
148             {
149                 pResult = GenericGreaterEqual(pITL, pITR);
150                 break;
151             }
152             case OpExp::power:
153             {
154                 pResult = GenericPower(pITL, pITR);
155                 break;
156             }
157             case OpExp::krontimes:
158             {
159                 pResult = GenericKrontimes(pITL, pITR);
160                 break;
161             }
162             case OpExp::kronrdivide:
163             {
164                 pResult = GenericKronrdivide(pITL, pITR);
165                 break;
166             }
167             case OpExp::kronldivide:
168             {
169                 pResult = GenericKronldivide(pITL, pITR);
170                 break;
171             }
172             default:
173                 break;
174         }
175
176         //overloading
177         if (pResult == NULL)
178         {
179             // We did not have any algorithm matching, so we try to call OverLoad
180             pResult = callOverloadOpExp(e.getOper(), pITL, pITR);
181         }
182
183         setResult(pResult);
184
185         //clear left and/or right operands
186         if (pResult != pITL)
187         {
188             pITL->killMe();
189         }
190
191         if (pResult != pITR)
192         {
193             pITR->killMe();
194         }
195     }
196     catch (ast::InternalError& error)
197     {
198         setResult(NULL);
199         if (pResult)
200         {
201             pResult->killMe();
202         }
203         if (pITL && (pITL != pResult))
204         {
205             pITL->killMe();
206         }
207         if (pITR && (pITR != pResult))
208         {
209             pITR->killMe();
210         }
211
212         error.SetErrorLocation(e.getLocation());
213         CoverageInstance::stopChrono((void*)&e);
214         throw error;
215     }
216
217     CoverageInstance::stopChrono((void*)&e);
218     /*if (e.getDecorator().res.isConstant())
219     {
220
221     }*/
222 }
223
224 template<class T>
225 void RunVisitorT<T>::visitprivate(const LogicalOpExp &e)
226 {
227     CoverageInstance::invokeAndStartChrono((void*)&e);
228     types::InternalType *pITR = NULL; //assign only in non shortcut operations.
229     types::InternalType *pITL = NULL;
230     types::InternalType *pResult = NULL;
231
232     try
233     {
234
235         /*getting what to assign*/
236         e.getLeft().accept(*this);
237         pITL = getResult();
238         if (isSingleResult() == false)
239         {
240             std::wostringstream os;
241             os << _W("Incompatible output argument.\n");
242             //os << ((Location)e.right_get().getLocation()).getLocationString() << std::endl;
243             throw ast::InternalError(os.str(), 999, e.getRight().getLocation());
244         }
245
246         setResult(NULL);
247
248         if (pITL->getType() == types::InternalType::ScilabImplicitList)
249         {
250             types::ImplicitList* pIL = pITL->getAs<types::ImplicitList>();
251             if (pIL->isComputable())
252             {
253                 pITL = pIL->extractFullMatrix();
254                 pIL->killMe();
255             }
256         }
257
258         switch (e.getOper())
259         {
260             case LogicalOpExp::logicalShortCutAnd:
261             {
262                 pResult = GenericShortcutAnd(pITL);
263                 if (pResult)
264                 {
265                     break;
266                 }
267
268                 //Continue to logicalAnd
269             }
270             case LogicalOpExp::logicalAnd:
271             {
272                 /*getting what to assign*/
273                 e.getRight().accept(*this);
274                 pITR = getResult();
275                 if (isSingleResult() == false)
276                 {
277                     std::wostringstream os;
278                     os << _W("Incompatible output argument.\n");
279                     //os << ((Location)e.right_get().getLocation()).getLocationString() << std::endl;
280                     throw ast::InternalError(os.str(), 999, e.getRight().getLocation());
281                 }
282
283                 if (pITR->getType() == types::InternalType::ScilabImplicitList)
284                 {
285                     types::ImplicitList* pIR = pITR->getAs<types::ImplicitList>();
286                     if (pIR->isComputable())
287                     {
288                         pITR = pIR->extractFullMatrix();
289                         pIR->killMe();
290                     }
291                 }
292                 pResult = GenericLogicalAnd(pITL, pITR);
293                 
294                 if (e.getOper() == LogicalOpExp::logicalShortCutAnd)
295                 {
296                     types::InternalType* pResult2 = GenericShortcutAnd(pResult);
297                     pResult->killMe();
298                     if (pResult2)
299                     {
300                         pResult = pResult2;
301                     }
302                     else
303                     {
304                         pResult = new types::Bool(1);
305                     }
306                 }
307                 break;
308             }
309             case LogicalOpExp::logicalShortCutOr:
310             {
311                 pResult = GenericShortcutOr(pITL);
312                 if (pResult)
313                 {
314                     break;
315                 }
316
317                 //Continue to logicalAnd
318             }
319             case LogicalOpExp::logicalOr:
320             {
321                 /*getting what to assign*/
322                 e.getRight().accept(*this);
323                 pITR = getResult();
324                 if (isSingleResult() == false)
325                 {
326                     std::wostringstream os;
327                     os << _W("Incompatible output argument.\n");
328                     //os << ((Location)e.right_get().getLocation()).getLocationString() << std::endl;
329                     throw ast::InternalError(os.str(), 999, e.getRight().getLocation());
330                 }
331
332                 if (pITR->getType() == types::InternalType::ScilabImplicitList)
333                 {
334                     types::ImplicitList* pIR = pITR->getAs<types::ImplicitList>();
335                     if (pIR->isComputable())
336                     {
337                         pITR = pIR->extractFullMatrix();
338                     }
339                 }
340                 pResult = GenericLogicalOr(pITL, pITR);
341                 if (e.getOper() == LogicalOpExp::logicalShortCutOr)
342                 {
343                     types::InternalType* pResult2 = GenericShortcutOr(pResult);
344                     pResult->killMe();
345                     if (pResult2)
346                     {
347                         pResult = pResult2;
348                     }
349                     else
350                     {
351                         pResult = new types::Bool(0);
352                     }
353                 }
354                 break;
355             }
356
357             default:
358                 break;
359         }
360         //overloading
361         if (pResult == NULL)
362         {
363             // We did not have any algorithm matching, so we try to call OverLoad
364             e.getRight().accept(*this);
365             pITR = getResult();
366             if (isSingleResult() == false)
367             {
368                 clearResult();
369                 std::wostringstream os;
370                 os << _W("Incompatible output argument.\n");
371                 //os << ((Location)e.right_get().getLocation()).getLocationString() << std::endl;
372                 throw ast::InternalError(os.str(), 999, e.getRight().getLocation());
373             }
374
375             if (pITR->getType() == types::InternalType::ScilabImplicitList)
376             {
377                 types::ImplicitList* pIR = pITR->getAs<types::ImplicitList>();
378                 if (pIR->isComputable())
379                 {
380                     pITR = pIR->extractFullMatrix();
381                 }
382             }
383             pResult = callOverloadOpExp(e.getOper(), pITL, pITR);
384         }
385
386         setResult(pResult);
387
388         // protect pResult in case where pITL or pITR equal pResult
389         pResult->IncreaseRef();
390
391         //clear left and/or right operands
392         pITL->killMe();
393         if (pITR)
394         {
395             pITR->killMe();
396         }
397
398         // unprotect pResult
399         pResult->DecreaseRef();
400     }
401     catch (ast::InternalError& error)
402     {
403         setResult(NULL);
404         if (pResult)
405         {
406             pResult->killMe();
407         }
408         if (pITL && (pITL != pResult))
409         {
410             pITL->killMe();
411         }
412         if (pITR && (pITR != pResult))
413         {
414             pITR->killMe();
415         }
416         error.SetErrorLocation(e.getLocation());
417         CoverageInstance::stopChrono((void*)&e);
418         throw error;
419     }
420
421     CoverageInstance::stopChrono((void*)&e);
422 }
423
424 template<class T>
425 types::InternalType* RunVisitorT<T>::callOverloadOpExp(OpExp::Oper _oper, types::InternalType* _paramL, types::InternalType* _paramR)
426 {
427     types::typed_list in;
428     types::typed_list out;
429
430     /*
431     ** Special case for unary minus => will call %{type_s}
432     */
433     if (_oper == OpExp::unaryMinus)
434     {
435         _paramR->IncreaseRef();
436         in.push_back(_paramR);
437         try
438         {
439             Overload::generateNameAndCall(Overload::getNameFromOper(_oper), in, 1, out, true);
440         }
441         catch (const ast::InternalError& e)
442         {
443             _paramR->DecreaseRef();
444             throw e;
445         }
446
447         _paramR->DecreaseRef();
448         return out[0];
449     }
450
451     _paramL->IncreaseRef();
452     _paramR->IncreaseRef();
453     in.push_back(_paramL);
454     in.push_back(_paramR);
455
456     try
457     {
458         Overload::generateNameAndCall(Overload::getNameFromOper(_oper), in, 1, out, true);
459     }
460     catch (const ast::InternalError& e)
461     {
462         _paramL->DecreaseRef();
463         _paramR->DecreaseRef();
464         throw e;
465     }
466
467     _paramL->DecreaseRef();
468     _paramR->DecreaseRef();
469     return out[0];
470 }
471
472 } /* namespace ast */