fix some gcc 4.9 valid warnings
[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 using namespace types;
36
37 namespace ast
38 {
39 class EXTERN_AST RunVisitor : public ConstVisitor
40 {
41 public:
42     RunVisitor()
43     {
44         _excepted_result = -1;
45         _resultVect.push_back(nullptr);
46         _result = nullptr;
47         m_bSingleResult = true;
48         m_pAns = symbol::Context::getInstance()->getOrCreate(symbol::Symbol(L"ans"));
49     }
50
51     ~RunVisitor()
52     {
53         clearResult();
54     }
55
56     void clearResultButFirst()
57     {
58         if (!isSingleResult() && _resultVect.size() > 1)
59         {
60             for (vector<types::InternalType*>::iterator rv = _resultVect.begin() + 1, end = _resultVect.end(); rv != end; ++rv)
61             {
62                 if (*rv != nullptr)
63                 {
64                     (*rv)->killMe();
65                     *rv = nullptr;
66                 }
67             }
68         }
69     }
70
71     void clearResult()
72     {
73         if (isSingleResult())
74         {
75             if (_result != nullptr)
76             {
77                 //                    std::cout << "before single delete : " << _result << std::endl;
78                 _result->killMe();
79                 //                    std::cout << "after single delete" << std::endl;
80             }
81         }
82         else
83         {
84             for (vector<types::InternalType*>::iterator rv = _resultVect.begin(); rv != _resultVect.end(); rv++)
85             {
86                 if (*rv != nullptr)
87                 {
88                     (*rv)->killMe();
89                 }
90             }
91         }
92         _resultVect.clear();
93         m_bSingleResult = true;
94         _result = nullptr;
95     }
96
97 public:
98     int getExpectedSize(void)
99     {
100         return _excepted_result;
101     }
102
103     void setExpectedSize(int _iSize)
104     {
105         _excepted_result = _iSize;
106     }
107
108     int getResultSize(void)
109     {
110         if (isSingleResult())
111         {
112             if (_result == nullptr)
113             {
114                 return 0;
115             }
116             else
117             {
118                 return 1;
119             }
120         }
121         else
122         {
123             return static_cast<int>(_resultVect.size());
124         }
125     }
126
127     inline types::InternalType* getResult(void)
128     {
129         if (isSingleResult())
130         {
131             return _result;
132         }
133         else
134         {
135             return _resultVect[0];
136         }
137     }
138
139     types::InternalType* getResult(int _iPos)
140     {
141         if (isSingleResult() && _iPos == 0)
142         {
143             return _result;
144         }
145
146         if (_iPos >= static_cast<int>(_resultVect.size()))
147         {
148             return nullptr;
149         }
150         return _resultVect[_iPos];
151     }
152
153     vector<types::InternalType*>* getResultList()
154     {
155         // TODO: this function is not used but it could lead to a memleak
156         // (in the first case the vector is allocated and so must be freed)
157         if (getResultSize() == 1)
158         {
159             vector<types::InternalType*>* pList = new vector<types::InternalType*>;
160             pList->push_back(_result);
161             return pList;
162         }
163         else
164         {
165             return &_resultVect;
166         }
167     }
168
169     void setResult(int _iPos, const types::InternalType *gtVal)
170     {
171         m_bSingleResult = false;
172         if (_iPos >= static_cast<int>(_resultVect.size()))
173         {
174             _resultVect.resize(_iPos + 1, nullptr);
175         }
176
177         _resultVect[_iPos] = const_cast<types::InternalType *>(gtVal);
178     }
179
180     inline void setResult(const types::InternalType *gtVal)
181     {
182         m_bSingleResult = true;
183         _result = const_cast<types::InternalType *>(gtVal);
184     }
185
186     inline void setResult(const types::typed_list & out)
187     {
188         if (out.size() == 0)
189         {
190             setResult(nullptr);
191         }
192         else if (out.size() == 1)
193         {
194             setResult(out[0]);
195         }
196         else
197         {
198             m_bSingleResult = false;
199             _resultVect.clear();
200             for (types::typed_list::const_iterator it = out.begin(); it != out.end(); ++it)
201             {
202                 _resultVect.push_back(*it);
203             }
204         }
205     }
206
207     inline bool isSingleResult()
208     {
209         return m_bSingleResult;
210     }
211
212     void cleanIn(const types::typed_list & in, const types::typed_list & out)
213     {
214         // Check if in contains entries which are in out too.
215         // When an entry is in in and not in out, then in is killed.
216         if (!in.empty())
217         {
218             for (types::typed_list::const_iterator o = out.begin(); o != out.end(); ++o)
219             {
220                 if (*o)
221                 {
222                     (*o)->IncreaseRef();
223                 }
224             }
225
226             for (types::typed_list::const_iterator i = in.begin(); i != in.end(); ++i)
227             {
228                 if (*i)
229                 {
230                     (*i)->DecreaseRef();
231                     (*i)->killMe();
232                 }
233             }
234
235             for (types::typed_list::const_iterator o = out.begin(); o != out.end(); ++o)
236             {
237                 if (*o)
238                 {
239                     (*o)->DecreaseRef();
240                 }
241             }
242         }
243     }
244
245     inline void cleanInOut(const types::typed_list & in, const types::typed_list & out)
246     {
247         cleanIn(in, out);
248         cleanOut(out);
249     }
250
251     void cleanOut(const types::typed_list & out)
252     {
253         if (!out.empty())
254         {
255             for (types::typed_list::const_iterator o = out.begin(); o != out.end(); ++o)
256             {
257                 if (*o)
258                 {
259                     (*o)->killMe();
260                 }
261             }
262         }
263     }
264
265     void cleanOpt(const types::optional_list & opt)
266     {
267         if (!opt.empty())
268         {
269             for (types::optional_list::const_iterator o = opt.begin(); o != opt.end(); ++o)
270             {
271                 if (o->second)
272                 {
273                     //decreasef ref after increaseref in callexp
274                     o->second->DecreaseRef();
275                     o->second->killMe();
276                 }
277             }
278         }
279     }
280
281     /*-------------.
282     | Attributes.  |
283     `-------------*/
284 protected:
285     vector<types::InternalType*>    _resultVect;
286     types::InternalType*    _result;
287     bool m_bSingleResult;
288     int _excepted_result;
289     symbol::Variable* m_pAns;
290 };
291
292 template <class T>
293 class EXTERN_AST RunVisitorT : public RunVisitor
294 {
295 public :
296     RunVisitorT() : RunVisitor()
297     {
298     }
299
300     types::typed_list* GetArgumentList(exps_t const & _plstArg)
301     {
302         types::typed_list* pArgs = new types::typed_list();
303         for (exps_t::const_iterator it = _plstArg.begin() ; it != _plstArg.end() ; ++it)
304         {
305             (*it)->accept(*this);
306             if (getResultSize() > 1)
307             {
308                 const int size = getResultSize();
309                 for (int i = 0 ; i < size; i++)
310                 {
311                     pArgs->push_back(getResult(i));
312                 }
313             }
314             else
315             {
316                 pArgs->push_back(getResult());
317             }
318         }
319         //to be sure, delete operation does not delete result
320         setResult(nullptr);
321         return pArgs;
322     }
323
324 public :
325     //process in another node
326     void visitprivate(const MatrixLineExp &/*e*/) {}
327     void visitprivate(const CommentExp &/*e*/) {}
328     void visitprivate(const ArrayListVar &/*e*/) {}
329     void visitprivate(const CaseExp &/*e*/) {}
330     void visitprivate(const AssignListExp  &/*e*/) {}
331
332     void visitprivate(const CellExp &e);
333     void visitprivate(const FieldExp &e);
334     void visitprivate(const IfExp  &e);
335     void visitprivate(const WhileExp  &e);
336     void visitprivate(const ForExp  &e);
337     void visitprivate(const ReturnExp &e);
338     void visitprivate(const SelectExp &e);
339     void visitprivate(const SeqExp  &e);
340     void visitprivate(const NotExp &e);
341     void visitprivate(const TransposeExp &e);
342     void visitprivate(const FunctionDec  &e);
343     void visitprivate(const ListExp &e);
344     void visitprivate(const AssignExp  &e);
345     void visitprivate(const OpExp &e);
346     void visitprivate(const LogicalOpExp &e);
347     void visitprivate(const MatrixExp &e);
348     void visitprivate(const CallExp &e);
349     void visitprivate(const CellCallExp &e);
350     void visitprivate(const OptimizedExp &e);
351     void visitprivate(const MemfillExp &e);
352     void visitprivate(const DAXPYExp &e);
353     void visitprivate(const IntSelectExp &e);
354     void visitprivate(const StringSelectExp &e);
355
356     void visitprivate(const StringExp &e)
357     {
358         if (e.getConstant() == nullptr)
359         {
360             types::String *psz = new types::String(e.getValue().c_str());
361             (const_cast<StringExp *>(&e))->setConstant(psz);
362
363         }
364         setResult(e.getConstant());
365     }
366
367
368     void visitprivate(const DoubleExp  &e)
369     {
370         if (e.getConstant() == nullptr)
371         {
372             Double *pdbl = new Double(e.getValue());
373             (const_cast<DoubleExp *>(&e))->setConstant(pdbl);
374
375         }
376         setResult(e.getConstant());
377     }
378
379
380     void visitprivate(const BoolExp  &e)
381     {
382         if (e.getConstant() == nullptr)
383         {
384             Bool *pB = new Bool(e.getValue());
385             (const_cast<BoolExp *>(&e))->setConstant(pB);
386
387         }
388         setResult(e.getConstant());
389     }
390
391
392     void visitprivate(const NilExp &/*e*/)
393     {
394         setResult(new types::Void());
395     }
396
397
398     void visitprivate(const SimpleVar &e)
399     {
400         symbol::Context* ctx = symbol::Context::getInstance();
401         symbol::Variable* var = ((SimpleVar&)e).getStack();
402         InternalType *pI = ctx->get(var);
403         setResult(pI);
404         if (pI != nullptr)
405         {
406             if (e.isVerbose() && pI->isCallable() == false && ConfigVariable::isPromptShow())
407             {
408                 std::wostringstream ostr;
409                 ostr << e.getSymbol().getName() << L"  = ";
410 #ifndef NDEBUG
411                 ostr << L"(" << pI->getRef() << L")";
412 #endif
413                 ostr << std::endl;
414                 ostr << std::endl;
415                 scilabWriteW(ostr.str().c_str());
416                 std::wostringstream ostrName;
417                 ostrName  << e.getSymbol().getName();
418                 VariableToString(pI, ostrName.str().c_str());
419             }
420
421             //check if var is recalled in current scope like
422             //function f()
423             //  a; //<=> a=a;
424             //  a(2) = 18;
425             //endfunction
426             if (e.getParent()->isSeqExp())
427             {
428                 if (ctx->getScopeLevel() > 1 && var->empty() == false && var->top()->m_iLevel != ctx->getScopeLevel())
429                 {
430                     //put var in current scope
431                     ctx->put(var, pI);
432                 }
433             }
434         }
435         else
436         {
437             char pstError[bsiz];
438             wchar_t* pwstError;
439
440             char* strErr =  wide_string_to_UTF8(e.getSymbol().getName().c_str());
441
442             os_sprintf(pstError, _("Undefined variable: %s\n"), strErr);
443             pwstError = to_wide_string(pstError);
444             FREE(strErr);
445             std::wstring wstError(pwstError);
446             FREE(pwstError);
447             throw InternalError(wstError, 999, e.getLocation());
448             //Err, SimpleVar doesn't exist in Scilab scopes.
449         }
450     }
451
452
453     void visitprivate(const ColonVar &/*e*/)
454     {
455         Colon *pC = new Colon();
456         setResult(pC);
457     }
458
459
460     void visitprivate(const DollarVar &/*e*/)
461     {
462         setResult(Polynom::Dollar());
463     }
464
465     void visitprivate(const TryCatchExp  &e)
466     {
467         //save current prompt mode
468         int oldVal = ConfigVariable::getSilentError();
469         //set mode silent for errors
470         ConfigVariable::setSilentError(1);
471         try
472         {
473             e.getTry().accept(*this);
474             //restore previous prompt mode
475             ConfigVariable::setSilentError(oldVal);
476         }
477         catch (const InternalError& /* ie */)
478         {
479             //restore previous prompt mode
480             ConfigVariable::setSilentError(oldVal);
481             //to lock lasterror
482             ConfigVariable::setLastErrorCall();
483             // reset call stack filled when error occured
484             ConfigVariable::resetWhereError();
485             e.getCatch().accept(*this);
486         }
487     }
488
489     void visitprivate(const BreakExp &e)
490     {
491         const_cast<BreakExp*>(&e)->setBreak();
492     }
493
494     void visitprivate(const ContinueExp &e)
495     {
496         const_cast<ContinueExp*>(&e)->setContinue();
497     }
498
499     void visitprivate(const ArrayListExp  &e)
500     {
501         exps_t::const_iterator it;
502         int iNbExpSize = this->getExpectedSize();
503         this->setExpectedSize(1);
504
505         typed_list lstIT;
506         for (it = e.getExps().begin() ; it != e.getExps().end() ; it++)
507         {
508             (*it)->accept(*this);
509             for (int j = 0; j < getResultSize(); j++)
510             {
511                 lstIT.push_back(getResult(j));
512             }
513         }
514
515         setResult(lstIT);
516
517         this->setExpectedSize(iNbExpSize);
518     }
519
520     void visitprivate(const VarDec  &e)
521     {
522         try
523         {
524             /*getting what to assign*/
525             e.getInit().accept(*this);
526             getResult()->IncreaseRef();
527         }
528         catch (const InternalError& error)
529         {
530             throw error;
531         }
532     }
533
534     types::InternalType* callOverloadOpExp(OpExp::Oper _oper, types::InternalType* _paramL, types::InternalType* _paramR);
535     types::InternalType* callOverloadMatrixExp(std::wstring strType, types::InternalType* _paramL, types::InternalType* _paramR);
536 };
537 }
538
539 #endif // !AST_RUNVISITOR_HXX