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