* Bug 16365 fixed: median(m,'r'|'c') was wrong after 5dc990
[scilab.git] / scilab / modules / ast / includes / ast / runvisitor.hxx
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2010-2010 - 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 #ifndef AST_RUNVISITOR_HXX
17 #define AST_RUNVISITOR_HXX
18
19 #include "context.hxx"
20 #include "all.hxx"
21 #include "types.hxx"
22 #include "double.hxx"
23 #include "bool.hxx"
24 #include "polynom.hxx"
25 #include "colon.hxx"
26 #include "string.hxx"
27 #include "void.hxx"
28 #include "configvariable.hxx"
29 #include "overload.hxx"
30 #include "scilabWrite.hxx"
31 #include "variables.hxx"
32
33 extern "C" {
34 #include "more.h"
35 #include "sci_malloc.h"
36 }
37
38 namespace ast
39 {
40 class EXTERN_AST RunVisitor : public ConstVisitor
41 {
42 public:
43     RunVisitor()
44     {
45         _expected_result = -1;
46         _resultVect.push_back(nullptr);
47         _result = nullptr;
48         m_bSingleResult = true;
49         m_pAns = symbol::Context::getInstance()->getOrCreate(symbol::Symbol(L"ans"));
50     }
51
52     ~RunVisitor()
53     {
54         clearResult();
55     }
56
57     void clearResultButFirst()
58     {
59         if (!isSingleResult() && _resultVect.size() > 1)
60         {
61             for (std::vector<types::InternalType*>::iterator rv = _resultVect.begin() + 1, end = _resultVect.end(); rv != end; ++rv)
62             {
63                 if (*rv != nullptr)
64                 {
65                     (*rv)->killMe();
66                     *rv = nullptr;
67                 }
68             }
69         }
70     }
71
72     void clearResult()
73     {
74         if (isSingleResult())
75         {
76             if (_result != nullptr)
77             {
78                 //                    std::cout << "before single delete : " << _result << std::endl;
79                 _result->killMe();
80                 //                    std::cout << "after single delete" << std::endl;
81             }
82         }
83         else
84         {
85             for (std::vector<types::InternalType*>::iterator rv = _resultVect.begin(); rv != _resultVect.end(); rv++)
86             {
87                 if (*rv != nullptr)
88                 {
89                     (*rv)->killMe();
90                 }
91             }
92         }
93         _resultVect.clear();
94         m_bSingleResult = true;
95         _result = nullptr;
96     }
97
98 public:
99     void getInputs(const CallExp& e, exps_t& args, types::typed_list& inTmp, std::vector<std::wstring>& vectOptName, std::vector<int>& vectNbResult);
100
101     int getExpectedSize(void)
102     {
103         return _expected_result;
104     }
105
106     void setExpectedSize(int _iSize)
107     {
108         _expected_result = _iSize;
109     }
110
111     int getResultSize(void)
112     {
113         if (isSingleResult())
114         {
115             if (_result == nullptr)
116             {
117                 return 0;
118             }
119             else
120             {
121                 return 1;
122             }
123         }
124         else
125         {
126             return static_cast<int>(_resultVect.size());
127         }
128     }
129
130     inline types::InternalType* getResult(void)
131     {
132         if (isSingleResult())
133         {
134             return _result;
135         }
136         else
137         {
138             return _resultVect[0];
139         }
140     }
141
142     types::InternalType* getResult(int _iPos)
143     {
144         if (isSingleResult() && _iPos == 0)
145         {
146             return _result;
147         }
148
149         if (_iPos >= static_cast<int>(_resultVect.size()))
150         {
151             return nullptr;
152         }
153         return _resultVect[_iPos];
154     }
155
156     std::vector<types::InternalType*>* getResultList()
157     {
158         // TODO: this function is not used but it could lead to a memleak
159         // (in the first case the vector is allocated and so must be freed)
160         if (getResultSize() == 1)
161         {
162             std::vector<types::InternalType*>* pList = new std::vector<types::InternalType*>;
163             pList->push_back(_result);
164             return pList;
165         }
166         else
167         {
168             return &_resultVect;
169         }
170     }
171
172     void setResult(int _iPos, const types::InternalType *gtVal)
173     {
174         m_bSingleResult = false;
175         if (_iPos >= static_cast<int>(_resultVect.size()))
176         {
177             _resultVect.resize(_iPos + 1, nullptr);
178         }
179
180         _resultVect[_iPos] = const_cast<types::InternalType *>(gtVal);
181     }
182
183     inline void setResult(const types::InternalType *gtVal)
184     {
185         m_bSingleResult = true;
186         _result = const_cast<types::InternalType *>(gtVal);
187     }
188
189     inline void setResult(const types::typed_list & out)
190     {
191         if (out.size() == 0)
192         {
193             setResult(nullptr);
194         }
195         else if (out.size() == 1)
196         {
197             setResult(out[0]);
198         }
199         else
200         {
201             m_bSingleResult = false;
202             _resultVect.clear();
203             for (types::typed_list::const_iterator it = out.begin(); it != out.end(); ++it)
204             {
205                 _resultVect.push_back(*it);
206             }
207         }
208     }
209
210     inline bool isSingleResult()
211     {
212         return m_bSingleResult;
213     }
214
215     void cleanIn(const types::typed_list & in, const types::typed_list & out)
216     {
217         // Check if in contains entries which are in out too.
218         // When an entry is in in and not in out, then in is killed.
219         if (!in.empty())
220         {
221             for (types::typed_list::const_iterator o = out.begin(); o != out.end(); ++o)
222             {
223                 if (*o)
224                 {
225                     (*o)->IncreaseRef();
226                 }
227             }
228
229             for (types::typed_list::const_iterator i = in.begin(); i != in.end(); ++i)
230             {
231                 if (*i)
232                 {
233                     (*i)->DecreaseRef();
234                     (*i)->killMe();
235                 }
236             }
237
238             for (types::typed_list::const_iterator o = out.begin(); o != out.end(); ++o)
239             {
240                 if (*o)
241                 {
242                     (*o)->DecreaseRef();
243                 }
244             }
245         }
246     }
247
248     inline void cleanInOut(const types::typed_list & in, const types::typed_list & out)
249     {
250         cleanIn(in, out);
251         cleanOut(out);
252     }
253
254     void cleanOut(const types::typed_list & out)
255     {
256         if (!out.empty())
257         {
258             for (types::typed_list::const_iterator o = out.begin(); o != out.end(); ++o)
259             {
260                 if (*o)
261                 {
262                     (*o)->killMe();
263                 }
264             }
265         }
266     }
267
268     void cleanOpt(const types::optional_list & opt, const types::typed_list & out)
269     {
270         if (!opt.empty())
271         {
272             for (types::typed_list::const_iterator o = out.begin(); o != out.end(); ++o)
273             {
274                 if (*o)
275                 {
276                     (*o)->IncreaseRef();
277                 }
278             }
279
280             for (types::optional_list::const_iterator o = opt.begin(); o != opt.end(); ++o)
281             {
282                 if (o->second)
283                 {
284                     //decreasef ref after increaseref in callexp
285                     o->second->DecreaseRef();
286                     o->second->killMe();
287                 }
288             }
289
290             for (types::typed_list::const_iterator o = out.begin(); o != out.end(); ++o)
291             {
292                 if (*o)
293                 {
294                     (*o)->DecreaseRef();
295                 }
296             }
297         }
298     }
299
300     /*-------------.
301     | Attributes.  |
302     `-------------*/
303 protected:
304     std::vector<types::InternalType*>    _resultVect;
305     types::InternalType*    _result;
306     bool m_bSingleResult;
307     int _expected_result;
308     symbol::Variable* m_pAns;
309 };
310
311 template <class T>
312 class EXTERN_AST RunVisitorT : public RunVisitor
313 {
314 public :
315     RunVisitorT() : RunVisitor()
316     {
317     }
318
319     types::typed_list* GetArgumentList(exps_t const & _plstArg)
320     {
321         types::typed_list* pArgs = new types::typed_list();
322         for (exps_t::const_iterator it = _plstArg.begin() ; it != _plstArg.end() ; ++it)
323         {
324             (*it)->accept(*this);
325             if (getResultSize() > 1)
326             {
327                 const int size = getResultSize();
328                 for (int i = 0 ; i < size; i++)
329                 {
330                     pArgs->push_back(getResult(i));
331                 }
332             }
333             else
334             {
335                 if (getResult())
336                 {
337                     pArgs->push_back(getResult());
338                 }
339                 //else optional argument skipped
340             }
341         }
342         //to be sure, delete operation does not delete result
343         setResult(nullptr);
344         return pArgs;
345     }
346
347 public :
348     //process in another node
349     void visitprivate(const MatrixLineExp &/*e*/) {}
350     void visitprivate(const CommentExp &/*e*/) {}
351     void visitprivate(const ArrayListVar &/*e*/) {}
352     void visitprivate(const CaseExp &/*e*/) {}
353     void visitprivate(const AssignListExp  &/*e*/) {}
354
355     void visitprivate(const CellExp &e);
356     void visitprivate(const FieldExp &e);
357     void visitprivate(const IfExp &e);
358     void visitprivate(const WhileExp &e);
359     void visitprivate(const ForExp  &e);
360     void visitprivate(const ReturnExp &e);
361     void visitprivate(const SelectExp &e);
362     void visitprivate(const SeqExp  &e);
363     void visitprivate(const NotExp &e);
364     void visitprivate(const TransposeExp &e);
365     void visitprivate(const FunctionDec &e);
366     void visitprivate(const ListExp &e);
367     void visitprivate(const AssignExp &e);
368     void visitprivate(const OpExp &e);
369     void visitprivate(const LogicalOpExp &e);
370     void visitprivate(const MatrixExp &e);
371     void visitprivate(const CallExp &e);
372     void visitprivate(const CellCallExp &e);
373     void visitprivate(const OptimizedExp &e);
374     void visitprivate(const MemfillExp &e);
375     void visitprivate(const DAXPYExp &e);
376     void visitprivate(const IntSelectExp &e);
377     void visitprivate(const StringSelectExp &e);
378     void visitprivate(const TryCatchExp &e);
379
380     void visitprivate(const StringExp & e);
381     void visitprivate(const DoubleExp & e);
382     void visitprivate(const BoolExp & e);
383     void visitprivate(const NilExp & e);
384     void visitprivate(const SimpleVar & e);
385     void visitprivate(const ColonVar & e);
386     void visitprivate(const DollarVar & e);
387     void visitprivate(const BreakExp & e);
388     void visitprivate(const ContinueExp & e);
389     void visitprivate(const ArrayListExp & e);
390     void visitprivate(const VarDec & e);
391
392     types::InternalType* callOverloadOpExp(OpExp::Oper _oper, types::InternalType* _paramL, types::InternalType* _paramR);
393     types::InternalType* callOverloadMatrixExp(const std::wstring& strType, types::InternalType* _paramL, types::InternalType* _paramR);
394 };
395 }
396
397 #endif // !AST_RUNVISITOR_HXX