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