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