insertion in output of function call
[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)
264     {
265         if (!opt.empty())
266         {
267             for (types::optional_list::const_iterator o = opt.begin(); o != opt.end(); ++o)
268             {
269                 if (o->second)
270                 {
271                     //decreasef ref after increaseref in callexp
272                     o->second->DecreaseRef();
273                     o->second->killMe();
274                 }
275             }
276         }
277     }
278
279     /*-------------.
280     | Attributes.  |
281     `-------------*/
282 protected:
283     std::vector<types::InternalType*>    _resultVect;
284     types::InternalType*    _result;
285     bool m_bSingleResult;
286     int _excepted_result;
287     symbol::Variable* m_pAns;
288 };
289
290 template <class T>
291 class EXTERN_AST RunVisitorT : public RunVisitor
292 {
293 public :
294     RunVisitorT() : RunVisitor()
295     {
296     }
297
298     types::typed_list* GetArgumentList(exps_t const & _plstArg)
299     {
300         types::typed_list* pArgs = new types::typed_list();
301         for (exps_t::const_iterator it = _plstArg.begin() ; it != _plstArg.end() ; ++it)
302         {
303             (*it)->accept(*this);
304             if (getResultSize() > 1)
305             {
306                 const int size = getResultSize();
307                 for (int i = 0 ; i < size; i++)
308                 {
309                     pArgs->push_back(getResult(i));
310                 }
311             }
312             else
313             {
314                 if (getResult())
315                 {
316                     pArgs->push_back(getResult());
317                 }
318                 //else optional argument skipped
319             }
320         }
321         //to be sure, delete operation does not delete result
322         setResult(nullptr);
323         return pArgs;
324     }
325
326 public :
327     //process in another node
328     void visitprivate(const MatrixLineExp &/*e*/) {}
329     void visitprivate(const CommentExp &/*e*/) {}
330     void visitprivate(const ArrayListVar &/*e*/) {}
331     void visitprivate(const CaseExp &/*e*/) {}
332     void visitprivate(const AssignListExp  &/*e*/) {}
333
334     void visitprivate(const CellExp &e);
335     void visitprivate(const FieldExp &e);
336     void visitprivate(const IfExp  &e);
337     void visitprivate(const WhileExp  &e);
338     void visitprivate(const ForExp  &e);
339     void visitprivate(const ReturnExp &e);
340     void visitprivate(const SelectExp &e);
341     void visitprivate(const SeqExp  &e);
342     void visitprivate(const NotExp &e);
343     void visitprivate(const TransposeExp &e);
344     void visitprivate(const FunctionDec  &e);
345     void visitprivate(const ListExp &e);
346     void visitprivate(const AssignExp  &e);
347     void visitprivate(const OpExp &e);
348     void visitprivate(const LogicalOpExp &e);
349     void visitprivate(const MatrixExp &e);
350     void visitprivate(const CallExp &e);
351     void visitprivate(const CellCallExp &e);
352     void visitprivate(const OptimizedExp &e);
353     void visitprivate(const MemfillExp &e);
354     void visitprivate(const DAXPYExp &e);
355     void visitprivate(const IntSelectExp &e);
356     void visitprivate(const StringSelectExp &e);
357     void visitprivate(const TryCatchExp  &e);
358
359     void visitprivate(const StringExp &e)
360     {
361         if (e.getConstant() == nullptr)
362         {
363             types::String *psz = new types::String(e.getValue().c_str());
364             (const_cast<StringExp *>(&e))->setConstant(psz);
365
366         }
367         setResult(e.getConstant());
368     }
369
370
371     void visitprivate(const DoubleExp  &e)
372     {
373         if (e.getConstant() == nullptr)
374         {
375             types::Double *pdbl = new types::Double(e.getValue());
376             (const_cast<DoubleExp *>(&e))->setConstant(pdbl);
377
378         }
379         setResult(e.getConstant());
380     }
381
382
383     void visitprivate(const BoolExp  &e)
384     {
385         if (e.getConstant() == nullptr)
386         {
387             types::Bool *pB = new types::Bool(e.getValue());
388             (const_cast<BoolExp *>(&e))->setConstant(pB);
389
390         }
391         setResult(e.getConstant());
392     }
393
394
395     void visitprivate(const NilExp &/*e*/)
396     {
397         setResult(new types::Void());
398     }
399
400
401     void visitprivate(const SimpleVar &e)
402     {
403         symbol::Context* ctx = symbol::Context::getInstance();
404         symbol::Variable* var = ((SimpleVar&)e).getStack();
405         types::InternalType *pI = ctx->get(var);
406         setResult(pI);
407         if (pI != nullptr)
408         {
409             if (e.isVerbose() && pI->isCallable() == false && ConfigVariable::isPromptShow())
410             {
411                 std::wostringstream ostr;
412                 ostr << e.getSymbol().getName() << L"  = ";
413 #ifndef NDEBUG
414                 ostr << L"(" << pI->getRef() << L")";
415 #endif
416                 ostr << std::endl;
417                 ostr << std::endl;
418                 scilabWriteW(ostr.str().c_str());
419                 std::wostringstream ostrName;
420                 ostrName  << e.getSymbol().getName();
421                 VariableToString(pI, ostrName.str().c_str());
422             }
423
424             //check if var is recalled in current scope like
425             //function f()
426             //  a; //<=> a=a;
427             //  a(2) = 18;
428             //endfunction
429             if (e.getParent()->isSeqExp())
430             {
431                 if (ctx->getScopeLevel() > 1 && var->empty() == false && var->top()->m_iLevel != ctx->getScopeLevel())
432                 {
433                     //put var in current scope
434                     ctx->put(var, pI);
435                 }
436             }
437         }
438         else
439         {
440             char pstError[bsiz];
441             wchar_t* pwstError;
442
443             char* strErr =  wide_string_to_UTF8(e.getSymbol().getName().c_str());
444
445             os_sprintf(pstError, _("Undefined variable: %s\n"), strErr);
446             pwstError = to_wide_string(pstError);
447             FREE(strErr);
448             std::wstring wstError(pwstError);
449             FREE(pwstError);
450             throw InternalError(wstError, 999, e.getLocation());
451             //Err, SimpleVar doesn't exist in Scilab scopes.
452         }
453     }
454
455
456     void visitprivate(const ColonVar &/*e*/)
457     {
458         types::Colon *pC = new types::Colon();
459         setResult(pC);
460     }
461
462
463     void visitprivate(const DollarVar &/*e*/)
464     {
465         setResult(types::Polynom::Dollar());
466     }
467
468     void visitprivate(const BreakExp &e)
469     {
470         const_cast<BreakExp*>(&e)->setBreak();
471     }
472
473     void visitprivate(const ContinueExp &e)
474     {
475         const_cast<ContinueExp*>(&e)->setContinue();
476     }
477
478     void visitprivate(const ArrayListExp  &e)
479     {
480         exps_t::const_iterator it;
481         int iNbExpSize = this->getExpectedSize();
482         this->setExpectedSize(1);
483
484         types::typed_list lstIT;
485         for (it = e.getExps().begin() ; it != e.getExps().end() ; it++)
486         {
487             (*it)->accept(*this);
488             for (int j = 0; j < getResultSize(); j++)
489             {
490                 lstIT.push_back(getResult(j));
491             }
492         }
493
494         setResult(lstIT);
495
496         this->setExpectedSize(iNbExpSize);
497     }
498
499     void visitprivate(const VarDec  &e)
500     {
501         try
502         {
503             /*getting what to assign*/
504             e.getInit().accept(*this);
505             getResult()->IncreaseRef();
506         }
507         catch (const InternalError& error)
508         {
509             throw error;
510         }
511     }
512
513     types::InternalType* callOverloadOpExp(OpExp::Oper _oper, types::InternalType* _paramL, types::InternalType* _paramR);
514     types::InternalType* callOverloadMatrixExp(const std::wstring& strType, types::InternalType* _paramL, types::InternalType* _paramR);
515 };
516 }
517
518 #endif // !AST_RUNVISITOR_HXX