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