76e0c7ee716e9f5df082fa06cc14f21bd3668490
[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                 break;
294             }
295             case LogicalOpExp::logicalShortCutOr:
296             {
297                 pResult = GenericShortcutOr(pITL);
298                 if (pResult)
299                 {
300                     break;
301                 }
302
303                 //Continue to logicalAnd
304             }
305             case LogicalOpExp::logicalOr:
306             {
307                 /*getting what to assign*/
308                 e.getRight().accept(*this);
309                 pITR = getResult();
310                 if (isSingleResult() == false)
311                 {
312                     std::wostringstream os;
313                     os << _W("Incompatible output argument.\n");
314                     //os << ((Location)e.right_get().getLocation()).getLocationString() << std::endl;
315                     throw ast::InternalError(os.str(), 999, e.getRight().getLocation());
316                 }
317
318                 if (pITR->getType() == types::InternalType::ScilabImplicitList)
319                 {
320                     types::ImplicitList* pIR = pITR->getAs<types::ImplicitList>();
321                     if (pIR->isComputable())
322                     {
323                         pITR = pIR->extractFullMatrix();
324                     }
325                 }
326                 pResult = GenericLogicalOr(pITL, pITR);
327                 break;
328             }
329
330             default:
331                 break;
332         }
333         //overloading
334         if (pResult == NULL)
335         {
336             // We did not have any algorithm matching, so we try to call OverLoad
337             e.getRight().accept(*this);
338             pITR = getResult();
339             if (isSingleResult() == false)
340             {
341                 clearResult();
342                 std::wostringstream os;
343                 os << _W("Incompatible output argument.\n");
344                 //os << ((Location)e.right_get().getLocation()).getLocationString() << std::endl;
345                 throw ast::InternalError(os.str(), 999, e.getRight().getLocation());
346             }
347
348             if (pITR->getType() == types::InternalType::ScilabImplicitList)
349             {
350                 types::ImplicitList* pIR = pITR->getAs<types::ImplicitList>();
351                 if (pIR->isComputable())
352                 {
353                     pITR = pIR->extractFullMatrix();
354                 }
355             }
356             pResult = callOverloadOpExp(e.getOper(), pITL, pITR);
357         }
358
359         setResult(pResult);
360
361         // protect pResult in case where pITL or pITR equal pResult
362         pResult->IncreaseRef();
363
364         //clear left and/or right operands
365         pITL->killMe();
366         if (pITR)
367         {
368             pITR->killMe();
369         }
370
371         // unprotect pResult
372         pResult->DecreaseRef();
373     }
374     catch (ast::InternalError& error)
375     {
376         setResult(NULL);
377         if (pResult)
378         {
379             pResult->killMe();
380         }
381         if (pITL && (pITL != pResult))
382         {
383             pITL->killMe();
384         }
385         if (pITR && (pITR != pResult))
386         {
387             pITR->killMe();
388         }
389         error.SetErrorLocation(e.getLocation());
390         CoverageInstance::stopChrono((void*)&e);
391         throw error;
392     }
393
394     CoverageInstance::stopChrono((void*)&e);
395 }
396
397 template<class T>
398 types::InternalType* RunVisitorT<T>::callOverloadOpExp(OpExp::Oper _oper, types::InternalType* _paramL, types::InternalType* _paramR)
399 {
400     types::typed_list in;
401     types::typed_list out;
402
403     /*
404     ** Special case for unary minus => will call %{type_s}
405     */
406     if (_oper == OpExp::unaryMinus)
407     {
408         _paramR->IncreaseRef();
409         in.push_back(_paramR);
410         try
411         {
412             Overload::generateNameAndCall(Overload::getNameFromOper(_oper), in, 1, out, true);
413         }
414         catch (const ast::InternalError& e)
415         {
416             _paramR->DecreaseRef();
417             throw e;
418         }
419
420         _paramR->DecreaseRef();
421         return out[0];
422     }
423
424     _paramL->IncreaseRef();
425     _paramR->IncreaseRef();
426     in.push_back(_paramL);
427     in.push_back(_paramR);
428
429     try
430     {
431         Overload::generateNameAndCall(Overload::getNameFromOper(_oper), in, 1, out, true);
432     }
433     catch (const ast::InternalError& e)
434     {
435         _paramL->DecreaseRef();
436         _paramR->DecreaseRef();
437         throw e;
438     }
439
440     _paramL->DecreaseRef();
441     _paramR->DecreaseRef();
442     return out[0];
443 }
444
445 } /* namespace ast */