delete of opt arguments corrected.
[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 <set>
17
18 #include "all.hxx"
19 #include "types.hxx"
20 #include "alltypes.hxx"
21 #include "configvariable.hxx"
22 #include "overload.hxx"
23 #include "scilabWrite.hxx"
24 #include "context.hxx"
25 #include "variables.hxx"
26
27 extern "C" {
28 #include "more.h"
29 #include "sci_malloc.h"
30 }
31
32 using namespace types;
33
34 namespace ast
35 {
36 class EXTERN_AST RunVisitor : public ConstVisitor
37 {
38 public:
39     RunVisitor()
40     {
41         _excepted_result = -1;
42         _resultVect.push_back(NULL);
43         _result = NULL;
44         m_bSingleResult = true;
45         m_pAns = symbol::Context::getInstance()->getOrCreate(symbol::Symbol(L"ans"));
46     }
47
48     ~RunVisitor()
49     {
50         result_clear();
51     }
52
53     void result_clear_except_first()
54     {
55         if (!is_single_result() && _resultVect.size() > 1)
56         {
57             for (vector<types::InternalType*>::iterator rv = _resultVect.begin() + 1, end = _resultVect.end(); rv != end; ++rv)
58             {
59                 if (*rv != NULL)
60                 {
61                     (*rv)->killMe();
62                     *rv = NULL;
63                 }
64             }
65         }
66     }
67
68     void result_clear()
69     {
70         if (is_single_result())
71         {
72             if (_result != NULL)
73             {
74                 //                                      std::cout << "before single delete : " << _result << std::endl;
75                 _result->killMe();
76                 //                                      std::cout << "after single delete" << std::endl;
77             }
78         }
79         else
80         {
81             for (vector<types::InternalType*>::iterator rv = _resultVect.begin(), end = _resultVect.end(); rv != end; ++rv)
82             {
83                 if (*rv != NULL)
84                 {
85                     (*rv)->killMe();
86                 }
87             }
88         }
89         _resultVect.clear();
90         m_bSingleResult = true;
91         _result = NULL;
92     }
93
94 public:
95     int expected_getSize(void)
96     {
97         return _excepted_result;
98     }
99
100     int result_getSize(void)
101     {
102         if (is_single_result())
103         {
104             if (_result == NULL)
105             {
106                 return 0;
107             }
108             else
109             {
110                 return 1;
111             }
112         }
113         else
114         {
115             return static_cast<int>(_resultVect.size());
116         }
117     }
118
119     void expected_setSize(int _iSize)
120     {
121         _excepted_result = _iSize;
122     }
123
124     inline types::InternalType* result_get(void)
125     {
126         if (is_single_result())
127         {
128             return _result;
129         }
130         else
131         {
132             return _resultVect[0];
133         }
134     }
135
136     types::InternalType* result_get(int _iPos)
137     {
138         if (is_single_result() && _iPos == 0)
139         {
140             return _result;
141         }
142
143         if (_iPos >= static_cast<int>(_resultVect.size()))
144         {
145             return NULL;
146         }
147         return _resultVect[_iPos];
148     }
149
150     vector<types::InternalType*>* result_list_get()
151     {
152         // TODO: this function is not used but it could lead to a memleak
153         // (in the first case the vector is allocated and so must be freed)
154         if (result_getSize() == 1)
155         {
156             vector<types::InternalType*>* pList = new vector<types::InternalType*>;
157             pList->push_back(_result);
158             return pList;
159         }
160         else
161         {
162             return &_resultVect;
163         }
164     }
165
166     void result_set(int _iPos, const types::InternalType *gtVal)
167     {
168         m_bSingleResult = false;
169         if (_iPos < static_cast<int>(_resultVect.size()))
170         {
171             if (_resultVect[_iPos])
172             {
173                 _resultVect[_iPos]->killMe();
174             }
175         }
176         else
177         {
178             _resultVect.resize(_iPos + 1, NULL);
179         }
180
181         _resultVect[_iPos] = const_cast<types::InternalType *>(gtVal);
182     }
183
184     inline void result_set(const types::InternalType *gtVal)
185     {
186         m_bSingleResult = true;
187         _result = const_cast<types::InternalType *>(gtVal);
188     }
189
190     inline void result_set(const types::typed_list & out)
191     {
192         if (out.size() == 0)
193         {
194             result_set(NULL);
195         }
196         else if (out.size() == 1)
197         {
198             result_set(out[0]);
199         }
200         else
201         {
202             /*for (int i = 0 ; i < static_cast<int>(out.size()) ; i++)
203             {
204             result_set(i, out[i]);
205             }*/
206
207             m_bSingleResult = false;
208             for (vector<types::InternalType*>::const_iterator it = _resultVect.begin(); it != _resultVect.end(); ++it)
209             {
210                 if (*it)
211                 {
212                     (*it)->killMe();
213                 }
214             }
215             _resultVect.clear();
216
217             for (types::typed_list::const_iterator it = out.begin(); it != out.end(); ++it)
218             {
219                 _resultVect.push_back(*it);
220             }
221         }
222     }
223
224     inline bool is_single_result()
225     {
226         return m_bSingleResult;
227     }
228
229     void clean_in(const types::typed_list & in, const types::typed_list & out)
230     {
231         // Check if in contains entries which are in out too.
232         // When an entry is in in and not in out, then in is killed.
233         if (!in.empty())
234         {
235             if (out.empty())
236             {
237                 for (types::typed_list::const_iterator i = in.begin(); i != in.end(); ++i)
238                 {
239                     if (*i)
240                     {
241                         (*i)->DecreaseRef();
242                         (*i)->killMe();
243                     }
244                 }
245             }
246             else
247             {
248                 std::set<InternalType *> common;
249
250                 for (types::typed_list::const_iterator i = in.begin(); i != in.end(); ++i)
251                 {
252                     if (*i)
253                     {
254                         types::typed_list::const_iterator o = out.begin();
255                         for (; o != out.end(); ++o)
256                         {
257                             if (*i == *o)
258                             {
259                                 break;
260                             }
261                         }
262
263                         if (o == out.end())
264                         {
265                             (*i)->DecreaseRef();
266                             (*i)->killMe();
267                         }
268                         else
269                         {
270                             std::set<InternalType *>::const_iterator nc = common.find(*i);
271                             if (nc == common.end())
272                             {
273                                 common.insert(*i);
274                                 (*i)->DecreaseRef();
275                             }
276                         }
277                     }
278                 }
279             }
280         }
281     }
282
283     inline void clean_in_out(const types::typed_list & in, const types::typed_list & out)
284     {
285         clean_in(in, out);
286         clean_out(out);
287     }
288
289     void clean_out(const types::typed_list & out)
290     {
291         if (!out.empty())
292         {
293             for (types::typed_list::const_iterator o = out.begin(); o != out.end(); ++o)
294             {
295                 if (*o)
296                 {
297                     (*o)->killMe();
298                 }
299             }
300         }
301     }
302
303     void clean_opt(const types::optional_list & opt)
304     {
305         if (!opt.empty())
306         {
307             for (types::optional_list::const_iterator o = opt.begin(); o != opt.end(); ++o)
308             {
309                 if (o->second)
310                 {
311                     //decreasef ref after increaseref in callexp
312                     o->second->DecreaseRef();
313                     o->second->killMe();
314                 }
315             }
316         }
317     }
318
319     /*-------------.
320     | Attributes.  |
321     `-------------*/
322 protected:
323     vector<types::InternalType*>        _resultVect;
324     types::InternalType*        _result;
325     bool m_bSingleResult;
326     int _excepted_result;
327     symbol::Variable* m_pAns;
328 };
329
330 template <class T>
331 class EXTERN_AST RunVisitorT : public RunVisitor
332 {
333 public :
334     RunVisitorT() : RunVisitor()
335     {
336     }
337
338     types::typed_list* GetArgumentList(std::list<Exp *>const& _plstArg)
339     {
340         types::typed_list* pArgs = new types::typed_list();
341         for (std::list<Exp *>::const_iterator it = _plstArg.begin() ; it != _plstArg.end() ; ++it)
342         {
343             (*it)->accept(*this);
344             if (result_getSize() > 1)
345             {
346                 const int size = result_getSize();
347                 for (int i = 0 ; i < size; i++)
348                 {
349                     pArgs->push_back(result_get(i));
350                 }
351             }
352             else
353             {
354                 pArgs->push_back(result_get());
355             }
356         }
357         //to be sure, delete operation does not delete result
358         result_set(NULL);
359         return pArgs;
360     }
361
362 public :
363     //not use
364     void visitprivate(const IntExp  &/*e*/) {}
365     void visitprivate(const FloatExp  &/*e*/) {}
366
367     //process in another node
368     void visitprivate(const MatrixLineExp &/*e*/) {}
369     void visitprivate(const CommentExp &/*e*/) {}
370     void visitprivate(const ArrayListVar &/*e*/) {}
371     void visitprivate(const CaseExp &/*e*/) {}
372     void visitprivate(const AssignListExp  &/*e*/) {}
373
374     void visitprivate(const CellExp &e);
375     void visitprivate(const FieldExp &e);
376     void visitprivate(const IfExp  &e);
377     void visitprivate(const WhileExp  &e);
378     void visitprivate(const ForExp  &e);
379     void visitprivate(const ReturnExp &e);
380     void visitprivate(const SelectExp &e);
381     void visitprivate(const SeqExp  &e);
382     void visitprivate(const NotExp &e);
383     void visitprivate(const TransposeExp &e);
384     void visitprivate(const FunctionDec  &e);
385     void visitprivate(const ListExp &e);
386     void visitprivate(const AssignExp  &e);
387     void visitprivate(const OpExp &e);
388     void visitprivate(const LogicalOpExp &e);
389     void visitprivate(const MatrixExp &e);
390     void visitprivate(const CallExp &e);
391     void visitprivate(const CellCallExp &e);
392
393     void visitprivate(const StringExp &e)
394     {
395         if (e.getBigString() == NULL)
396         {
397             types::String *psz = new types::String(e.value_get().c_str());
398             (const_cast<StringExp *>(&e))->setBigString(psz);
399
400         }
401         result_set(e.getBigString());
402     }
403
404
405     void visitprivate(const DoubleExp  &e)
406     {
407         if (e.getBigDouble() == NULL)
408         {
409             Double *pdbl = new Double(e.value_get());
410             (const_cast<DoubleExp *>(&e))->setBigDouble(pdbl);
411
412         }
413         result_set(e.getBigDouble());
414     }
415
416
417     void visitprivate(const BoolExp  &e)
418     {
419         if (e.getBigBool() == NULL)
420         {
421             Bool *pB = new Bool(e.value_get());
422             (const_cast<BoolExp *>(&e))->setBigBool(pB);
423
424         }
425         result_set(e.getBigBool());
426     }
427
428
429     void visitprivate(const NilExp &e)
430     {
431         result_set(new types::Void());
432     }
433
434
435     void visitprivate(const SimpleVar &e)
436     {
437         InternalType *pI = symbol::Context::getInstance()->get(((SimpleVar&)e).stack_get());
438         result_set(pI);
439         if (pI != NULL)
440         {
441             if (e.is_verbose() && pI->isCallable() == false && ConfigVariable::isPromptShow())
442             {
443                 std::wostringstream ostr;
444                 ostr << e.name_get().name_get() << L"  = " << L"(" << pI->getRef() << L")" << std::endl;
445                 ostr << std::endl;
446                 scilabWriteW(ostr.str().c_str());
447                 VariableToString(pI, e.name_get().name_get().c_str());
448             }
449         }
450         else
451         {
452             char pstError[bsiz];
453             wchar_t* pwstError;
454
455             char* strErr =  wide_string_to_UTF8(e.name_get().name_get().c_str());
456
457             sprintf(pstError, _("Undefined variable: %s\n"), strErr);
458             pwstError = to_wide_string(pstError);
459             FREE(strErr);
460             std::wstring wstError(pwstError);
461             FREE(pwstError);
462             throw ScilabError(wstError, 999, e.location_get());
463             //Err, SimpleVar doesn't exist in Scilab scopes.
464         }
465     }
466
467
468     void visitprivate(const ColonVar &e)
469     {
470         Colon *pC = new Colon();
471         result_set(pC);
472     }
473
474
475     void visitprivate(const DollarVar &e)
476     {
477         Dollar* pVar = new Dollar();
478         result_set(pVar);
479     }
480
481     void visitprivate(const TryCatchExp  &e)
482     {
483         //save current prompt mode
484         int oldVal = ConfigVariable::getSilentError();
485         //set mode silent for errors
486         ConfigVariable::setSilentError(1);
487         try
488         {
489             e.try_get().accept(*this);
490             //restore previous prompt mode
491             ConfigVariable::setSilentError(oldVal);
492         }
493         catch (ScilabMessage sm)
494         {
495             //restore previous prompt mode
496             ConfigVariable::setSilentError(oldVal);
497             //to lock lasterror
498             ConfigVariable::setLastErrorCall();
499             e.catch_get().accept(*this);
500         }
501     }
502
503     void visitprivate(const BreakExp &e)
504     {
505         const_cast<BreakExp*>(&e)->break_set();
506     }
507
508     void visitprivate(const ContinueExp &e)
509     {
510         const_cast<ContinueExp*>(&e)->continue_set();
511     }
512
513     void visitprivate(const ArrayListExp  &e)
514     {
515         std::list<Exp *>::const_iterator it;
516         int i = 0;
517
518         std::list<InternalType*> lstIT;
519         for (it = e.exps_get().begin() ; it != e.exps_get().end() ; it++)
520         {
521             (*it)->accept(*this);
522             lstIT.push_back(result_get()->clone());
523         }
524
525         std::list<InternalType*>::iterator itIT = lstIT.begin();
526         for (; itIT != lstIT.end(); itIT++)
527         {
528             result_set(i++, *itIT);
529         }
530     }
531
532     void visitprivate(const VarDec  &e)
533     {
534         try
535         {
536             /*getting what to assign*/
537             e.init_get().accept(*this);
538             result_get()->IncreaseRef();
539         }
540         catch (ScilabError error)
541         {
542             throw error;
543         }
544     }
545
546     void VariableToString(types::InternalType* pIT, const wchar_t* wcsVarName)
547     {
548         std::wostringstream ostr;
549
550         if (pIT->isMList() || pIT->isTList() || pIT->hasToString() == false)
551         {
552             //call overload %type_p
553             types::typed_list in;
554             types::typed_list out;
555
556             pIT->IncreaseRef();
557             in.push_back(pIT);
558
559             try
560             {
561                 if (Overload::call(L"%" + pIT->getAs<TList>()->getShortTypeStr() + L"_p", in, 1, out, this) != Function::OK)
562                 {
563                     throw ScilabError();
564                 }
565             }
566             catch (ScilabError /*&e*/)
567             {
568                 ostr << wcsVarName;
569                 pIT->toString(ostr);
570                 scilabWriteW(ostr.str().c_str());
571             }
572
573             pIT->DecreaseRef();
574         }
575         else
576         {
577             //to manage lines information
578             int iLines = ConfigVariable::getConsoleLines();
579
580             bool bFinish = false;
581             do
582             {
583                 //block by block
584                 bFinish = pIT->toString(ostr);
585                 scilabWriteW(ostr.str().c_str());
586                 if (bFinish == false && iLines != 0)
587                 {
588                     //show message on prompt
589                     bFinish = linesmore() == 1;
590                 }
591                 ostr.str(L"");
592             }
593             while (bFinish == false);
594
595             pIT->clearPrintState();
596         }
597     }
598
599     types::InternalType* callOverloadOpExp(OpExp::Oper _oper, types::InternalType* _paramL, types::InternalType* _paramR);
600     types::InternalType* callOverloadMatrixExp(std::wstring strType, types::InternalType* _paramL, types::InternalType* _paramR);
601 };
602 }
603
604 #endif // !AST_RUNVISITOR_HXX