std::wstring as parameter must be const & when is possible
[scilab.git] / scilab / modules / ast / src / cpp / ast / runvisitor.cpp
1 /*
2  *  Scilab ( http://www.scilab.org/ ) - This file is part of Scilab
3  *  Copyright (C) 2014 - Scilab Enterprises - 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 //for Visual Leak Detector in debug compilation mode
14 //#define DEBUG_VLD
15 #if defined(DEBUG_VLD) && defined(_DEBUG)
16 #include <vld.h>
17 #endif
18
19 #include <string>
20
21 #include "runvisitor.hxx"
22 #include "execvisitor.hxx"
23 #include "stepvisitor.hxx"
24 #include "timedvisitor.hxx"
25 #include "shortcutvisitor.hxx"
26 #include "printvisitor.hxx"
27 #include "mutevisitor.hxx"
28 //#include "AnalysisVisitor.hxx"
29
30 #include "visitor_common.hxx"
31
32 #include "context.hxx"
33 #include "generic_operations.hxx"
34 #include "types_or.hxx"
35 #include "types_and.hxx"
36 #include "localization.hxx"
37
38 #include "macrofile.hxx"
39 #include "macro.hxx"
40 #include "filemanager_interface.h"
41
42 #include "runner.hxx"
43 #include "threadmanagement.hxx"
44
45 extern "C"
46 {
47 #include "sciprint.h"
48 #include "os_string.h"
49 #include "elem_common.h"
50 }
51
52 namespace ast
53 {
54 template <class T>
55 void RunVisitorT<T>::visitprivate(const CellExp &e)
56 {
57     exps_t::const_iterator row;
58     exps_t::const_iterator col;
59     int iColMax = 0;
60
61     exps_t lines = e.getLines();
62     //check dimmension
63     for (row = lines.begin() ; row != lines.end() ; ++row )
64     {
65         exps_t cols = (*row)->getAs<MatrixLineExp>()->getColumns();
66         if (iColMax == 0)
67         {
68             iColMax = static_cast<int>(cols.size());
69         }
70
71         if (iColMax != static_cast<int>(cols.size()))
72         {
73             std::wostringstream os;
74             os << _W("inconsistent row/column dimensions\n");
75             //os << ((Location)(*row)->getLocation()).getLocationString() << std::endl;
76             throw InternalError(os.str(), 999, (*row)->getLocation());
77         }
78     }
79
80     //alloc result cell
81     types::Cell *pC = new types::Cell(static_cast<int>(lines.size()), iColMax);
82
83     int i = 0;
84     int j = 0;
85
86     //insert items in cell
87     for (i = 0, row = lines.begin() ; row != lines.end() ; ++row, ++i)
88     {
89         exps_t cols = (*row)->getAs<MatrixLineExp>()->getColumns();
90         for (j = 0, col = cols.begin() ; col != cols.end() ; ++col, ++j)
91         {
92             (*col)->accept(*this);
93             types::InternalType *pIT = getResult();
94             if (pIT->isImplicitList())
95             {
96                 types::InternalType * _pIT = pIT->getAs<types::ImplicitList>()->extractFullMatrix();
97                 pC->set(i, j, _pIT);
98                 _pIT->killMe();
99             }
100             else
101             {
102                 pC->set(i, j, pIT);
103             }
104             clearResult();
105         }
106     }
107
108     //return new cell
109     setResult(pC);
110 }
111
112 template <class T>
113 void RunVisitorT<T>::visitprivate(const FieldExp &e)
114 {
115     /*
116       a.b
117     */
118
119     if (!e.getTail()->isSimpleVar())
120     {
121         wchar_t szError[bsiz];
122         os_swprintf(szError, bsiz, _W("/!\\ Unmanaged FieldExp.\n").c_str());
123         throw InternalError(szError, 999, e.getLocation());
124     }
125
126     try
127     {
128         e.getHead()->accept(*this);
129     }
130     catch (const InternalError& error)
131     {
132         throw error;
133     }
134
135     if (getResult() == NULL)
136     {
137         wchar_t szError[bsiz];
138         os_swprintf(szError, bsiz, _W("Attempt to reference field of non-structure array.\n").c_str());
139         throw InternalError(szError, 999, e.getLocation());
140     }
141
142     // TODO: handle case where getSize() > 1
143     // l=list(struct("toto","coucou"),struct("toto","hello"),1,2);[a,b]=l(1:2).toto
144     //
145     if (getResultSize() > 1)
146     {
147         clearResult();
148         wchar_t szError[bsiz];
149         os_swprintf(szError, bsiz, _W("Not yet implemented in Scilab.\n").c_str());
150         throw InternalError(szError, 999, e.getLocation());
151     }
152
153     SimpleVar * psvRightMember = static_cast<SimpleVar *>(const_cast<Exp *>(e.getTail()));
154     std::wstring wstField = psvRightMember->getSymbol().getName();
155     types::InternalType * pValue = getResult();
156     types::InternalType * pReturn = NULL;
157     bool ok = false;
158
159     try
160     {
161         if (pValue->isGenericType() || pValue->isUserType())
162         {
163             ok = pValue->getAs<types::GenericType>()->extract(wstField, pReturn);
164         }
165     }
166     catch (std::wstring & err)
167     {
168         pValue->killMe();
169         throw InternalError(err.c_str(), 999, e.getTail()->getLocation());
170     }
171
172     if (ok)
173     {
174         if (pReturn == NULL)
175         {
176             std::wostringstream os;
177             os << _W("Invalid index.\n");
178             throw InternalError(os.str(), 999, e.getLocation());
179         }
180
181         setResult(pReturn);
182         if (pValue->isDeletable())
183         {
184             if (pValue->isContainer())
185             {
186                 // prevent delete of pReturn in case where
187                 // extract not return a clone
188                 pReturn->IncreaseRef();
189                 pValue->killMe();
190                 pReturn->DecreaseRef();
191             }
192             else
193             {
194                 pValue->killMe();
195             }
196         }
197     }
198     else if (pValue->isFieldExtractionOverloadable())
199     {
200         types::typed_list in;
201         types::typed_list out;
202
203         types::String* pS = new types::String(wstField.c_str());
204
205         //TODO: in the case where overload is a macro there is no need to incref in
206         // because args will be put in context, removed and killed if required.
207         // But if the overload is a function... it is another story...
208
209         pS->IncreaseRef();
210         pValue->IncreaseRef();
211
212         in.push_back(pS);
213         in.push_back(pValue);
214         types::Callable::ReturnValue Ret = types::Callable::Error;
215         std::wstring stType = pValue->getShortTypeStr();
216
217         try
218         {
219             Ret = Overload::call(L"%" + stType + L"_e", in, 1, out, this);
220         }
221         catch (const InternalError& ie)
222         {
223             try
224             {
225                 //to compatibility with scilab 5 code.
226                 //tlist/mlist name are truncated to 8 first character
227                 if (stType.size() > 8)
228                 {
229                     Ret = Overload::call(L"%" + stType.substr(0, 8) + L"_e", in, 1, out, this);
230                 }
231                 else
232                 {
233                     throw ie;
234                 }
235             }
236             catch (const InternalError& ie)
237             {
238                 // TList or Mlist
239                 if (pValue->isList())
240                 {
241                     Ret = Overload::call(L"%l_e", in, 1, out, this);
242                 }
243                 else
244                 {
245                     throw ie;
246                 }
247             }
248         }
249
250         if (Ret != types::Callable::OK)
251         {
252             cleanInOut(in, out);
253             setResult(NULL);
254             throw InternalError(ConfigVariable::getLastErrorMessage(), ConfigVariable::getLastErrorNumber(), e.getLocation());
255         }
256
257         setResult(out);
258         cleanIn(in, out);
259     }
260     else
261     {
262         pValue->killMe();
263         wchar_t szError[bsiz];
264         os_swprintf(szError, bsiz, _W("Attempt to reference field of non-structure array.\n").c_str());
265         throw InternalError(szError, 999, e.getLocation());
266     }
267 }
268
269 template <class T>
270 void RunVisitorT<T>::visitprivate(const IfExp  &e)
271 {
272     //Create local exec visitor
273     ShortCutVisitor SCTest;
274     bool bTestStatus = false;
275
276     //condition
277     e.getTest().accept(SCTest);
278     e.getTest().accept(*this);
279
280     bTestStatus = getResult()->isTrue();
281     clearResult();
282     if (bTestStatus == true)
283     {
284         e.getThen().accept(*this);
285     }
286     else if (e.hasElse())
287     {
288         e.getElse().accept(*this);
289     }
290
291     if (e.isBreakable()
292             && ( (&e.getElse())->isBreak()
293                  || (&e.getThen())->isBreak() ))
294     {
295         const_cast<IfExp*>(&e)->setBreak();
296         const_cast<Exp*>(&e.getElse())->resetBreak();
297         const_cast<Exp*>(&e.getThen())->resetBreak();
298     }
299
300     if (e.isContinuable()
301             && ( (&e.getElse())->isContinue()
302                  || (&e.getThen())->isContinue() ))
303     {
304         const_cast<IfExp*>(&e)->setContinue();
305         const_cast<Exp*>(&e.getElse())->resetContinue();
306         const_cast<Exp*>(&e.getThen())->resetContinue();
307     }
308
309     if (e.isReturnable()
310             && ( (&e.getElse())->isReturn()
311                  || (&e.getThen())->isReturn() ))
312     {
313         const_cast<IfExp*>(&e)->setReturn();
314         const_cast<Exp*>(&e.getElse())->resetReturn();
315         const_cast<Exp*>(&e.getThen())->resetReturn();
316     }
317 }
318
319 template <class T>
320 void RunVisitorT<T>::visitprivate(const WhileExp  &e)
321 {
322
323     //Create local exec visitor
324     ShortCutVisitor SCTest;
325
326     //manage & and | like && and ||
327     e.getTest().accept(SCTest);
328     //condition
329     e.getTest().accept(*this);
330
331     types::InternalType* pIT = getResult();
332
333     while (pIT->isTrue())
334     {
335         pIT->killMe();
336         e.getBody().accept(*this);
337
338         //clear old result value before evaluate new one
339         if (getResult() != NULL)
340         {
341             getResult()->killMe();
342         }
343
344         if (e.getBody().isBreak())
345         {
346             const_cast<Exp*>(&(e.getBody()))->resetBreak();
347             break;
348         }
349
350         if (e.getBody().isReturn())
351         {
352             const_cast<WhileExp*>(&e)->setReturn();
353             const_cast<Exp*>(&(e.getBody()))->resetReturn();
354             break;
355         }
356
357         if (e.getBody().isContinue())
358         {
359             const_cast<Exp*>(&(e.getBody()))->resetContinue();
360         }
361
362         e.getTest().accept(*this);
363         pIT = getResult();
364     }
365
366     //pIT->killMe();
367     //clear result of condition or result of body
368     clearResult();
369 }
370
371 template <class T>
372 void RunVisitorT<T>::visitprivate(const ForExp  &e)
373 {
374     symbol::Context* ctx = symbol::Context::getInstance();
375     //vardec visit increase its result reference
376     e.getVardec().accept(*this);
377     types::InternalType* pIT = getResult();
378
379     if (pIT->isImplicitList())
380     {
381         //get IL
382         types::ImplicitList* pVar = pIT->getAs<types::ImplicitList>();
383         //get IL initial Type
384         types::InternalType * pIL = pVar->getInitalType();
385         //std::cout << "for IL: " << pIL << std::endl;
386         //std::cout << "  for IV: " << pIT << std::endl;
387         //get index stack
388         symbol::Variable* var = e.getVardec().getAs<VarDec>()->getStack();
389
390         if (ctx->isprotected(var))
391         {
392             std::wostringstream os;
393             os << _W("Redefining permanent variable.\n");
394             throw ast::InternalError(os.str(), 999, e.getVardec().getLocation());
395         }
396
397         ctx->put(var, pIL);
398         //use ref count to lock var against clear and detect any changes
399         pIL->IncreaseRef();
400
401         int size = static_cast<int>(pVar->getSize());
402         for (int i = 0; i < size; ++i)
403         {
404             //check if loop index has changed, deleted, copy ...
405             if (pIL->getRef() != 2)
406             {
407                 switch (pIL->getRef())
408                 {
409                     case 1:
410                         //someone clear me
411                         ctx->put(var, pIL);
412                         break;
413                     default:
414                         //someone assign me to another var
415                         //a = i;
416                         //unlock me
417                         pIL->DecreaseRef();
418
419                         //no need to destroy, it already assign to another var
420                         //pIL->killMe();
421
422                         //create a new me
423                         pIL = pVar->getInitalType();
424                         //lock loop index
425                         pIL->IncreaseRef();
426                         //update me ( must decrease ref of a )
427                         if (ctx->isprotected(var))
428                         {
429                             std::wostringstream os;
430                             os << _W("Redefining permanent variable.\n");
431                             throw ast::InternalError(os.str(), 999, e.getVardec().getLocation());
432                         }
433
434                         ctx->put(var, pIL);
435                         break;
436                 }
437             }
438
439             pVar->extractValue(i, pIL);
440
441             try
442             {
443                 e.getBody().accept(*this);
444             }
445             catch (const InternalError& ie)
446             {
447                 //unlock loop index and implicit list
448                 pIL->DecreaseRef();
449                 pIL->killMe();
450                 pIT->DecreaseRef();
451                 pIT->killMe();
452
453                 setResult(NULL);
454                 throw ie;
455             }
456
457             if (e.getBody().isBreak())
458             {
459                 const_cast<Exp&>(e.getBody()).resetBreak();
460                 break;
461             }
462
463             if (e.getBody().isContinue())
464             {
465                 const_cast<Exp&>(e.getBody()).resetContinue();
466                 continue;
467             }
468
469             if (e.getBody().isReturn())
470             {
471                 const_cast<ForExp&>(e).setReturn();
472                 const_cast<Exp&>(e.getBody()).resetReturn();
473                 break;
474             }
475         }
476
477         //unlock loop index
478         pIL->DecreaseRef();
479         pIL->killMe();
480     }
481     else if (pIT->isList())
482     {
483         types::List* pL = pIT->getAs<types::List>();
484         const int size = pL->getSize();
485         symbol::Variable* var = e.getVardec().getAs<VarDec>()->getStack();
486         for (int i = 0; i < size; ++i)
487         {
488             types::InternalType* pNew = pL->get(i);
489
490             if (ctx->isprotected(var))
491             {
492                 std::wostringstream os;
493                 os << _W("Redefining permanent variable.\n");
494                 throw ast::InternalError(os.str(), 999, e.getVardec().getLocation());
495             }
496             ctx->put(var, pNew);
497
498             try
499             {
500                 e.getBody().accept(*this);
501             }
502             catch (const InternalError& ie)
503             {
504                 //implicit list
505                 pIT->DecreaseRef();
506                 pIT->killMe();
507                 setResult(NULL);
508                 throw ie;
509             }
510
511             if (e.getBody().isBreak())
512             {
513                 const_cast<Exp*>(&(e.getBody()))->resetBreak();
514                 break;
515             }
516
517             if (e.getBody().isContinue())
518             {
519                 const_cast<Exp*>(&(e.getBody()))->resetContinue();
520                 continue;
521             }
522
523             if (e.getBody().isReturn())
524             {
525                 const_cast<ForExp*>(&e)->setReturn();
526                 const_cast<Exp&>(e.getBody()).resetReturn();
527                 break;
528             }
529         }
530     }
531     else if (pIT->isGenericType())
532     {
533         //Matrix i = [1,3,2,6] or other type
534         types::GenericType* pVar = pIT->getAs<types::GenericType>();
535         if (pVar->getDims() > 2)
536         {
537             pIT->DecreaseRef();
538             pIT->killMe();
539             throw InternalError(_W("for expression can only manage 1 or 2 dimensions variables\n"), 999, e.getVardec().getLocation());
540         }
541
542         symbol::Variable* var = e.getVardec().getAs<VarDec>()->getStack();
543         for (int i = 0; i < pVar->getCols(); i++)
544         {
545             types::GenericType* pNew = pVar->getColumnValues(i);
546             if (pNew == NULL)
547             {
548                 pIT->DecreaseRef();
549                 pIT->killMe();
550                 throw InternalError(_W("for expression : Wrong type for loop iterator.\n"), 999, e.getVardec().getLocation());
551             }
552
553             if (ctx->isprotected(var))
554             {
555                 std::wostringstream os;
556                 os << _W("Redefining permanent variable.\n");
557                 throw InternalError(os.str(), 999, e.getVardec().getLocation());
558             }
559             ctx->put(var, pNew);
560
561             try
562             {
563                 e.getBody().accept(*this);
564             }
565             catch (const InternalError& ie)
566             {
567                 //implicit list
568                 pIT->DecreaseRef();
569                 pIT->killMe();
570                 setResult(NULL);
571                 throw ie;
572             }
573
574             if (e.getBody().isBreak())
575             {
576                 const_cast<Exp*>(&(e.getBody()))->resetBreak();
577                 break;
578             }
579
580             if (e.getBody().isContinue())
581             {
582                 const_cast<Exp*>(&(e.getBody()))->resetContinue();
583                 continue;
584             }
585
586             if (e.getBody().isReturn())
587             {
588                 const_cast<ForExp*>(&e)->setReturn();
589                 const_cast<Exp&>(e.getBody()).resetReturn();
590                 break;
591             }
592         }
593     }
594     else
595     {
596         pIT->DecreaseRef();
597         pIT->killMe();
598         throw InternalError(_W("for expression : Wrong type for loop iterator.\n"), 999, e.getVardec().getLocation());
599     }
600
601     pIT->DecreaseRef();
602     pIT->killMe();
603
604     setResult(NULL);
605 }
606
607 template <class T>
608 void RunVisitorT<T>::visitprivate(const ReturnExp &e)
609 {
610     if (e.isGlobal())
611     {
612         if (ConfigVariable::getPauseLevel() != 0 && symbol::Context::getInstance()->getScopeLevel() == ConfigVariable::getActivePauseLevel())
613         {
614             //return or resume
615             ConfigVariable::DecreasePauseLevel();
616             return;
617         }
618         else
619         {
620             const_cast<ReturnExp*>(&e)->setReturn();
621         }
622     }
623     else
624     {
625         //return(x)
626
627         //in case of CallExp, we can return only one values
628         int iSaveExpectedSize = getExpectedSize();
629         setExpectedSize(1);
630         e.getExp().accept(*this);
631         setExpectedSize(iSaveExpectedSize);
632         const_cast<ReturnExp*>(&e)->setReturn();
633     }
634 }
635
636 template <class T>
637 void RunVisitorT<T>::visitprivate(const IntSelectExp &e)
638 {
639     bool found = false;
640     //e.getSelect()->accept(*this);
641     //InternalType* pIT = getResult();
642     //setResult(nullptr);
643     //if (pIT && pIT->isDouble())
644     //{
645     //    Double * pDbl = static_cast<Double *>(pIT);
646     //    if (!pDbl->isComplex() && pDbl->getSize() == 1)
647     //    {
648     //        int64_t val;
649     //        if (analysis::tools::asInteger<int64_t>(pDbl->get(0), val))
650     //        {
651     //            Exp * exp = e.getExp(val);
652     //            found = true;
653     //            if (exp)
654     //            {
655     //                Exp * body = exp->isCaseExp() ? exp->getAs<CaseExp>()->getBody() : exp;
656     //                if (e.isBreakable())
657     //                {
658     //                    const_cast<IntSelectExp*>(&e)->resetBreak();
659     //                    body->setBreakable();
660     //                }
661
662     //                if (e.isContinuable())
663     //                {
664     //                    const_cast<IntSelectExp*>(&e)->resetContinue();
665     //                    body->setContinuable();
666     //                }
667
668     //                if (e.isReturnable())
669     //                {
670     //                    const_cast<IntSelectExp*>(&e)->resetReturn();
671     //                    body->setReturnable();
672     //                }
673
674     //                try
675     //                {
676     //                    //the good one
677     //                    body->accept(*this);
678     //                }
679     //                catch (const InternalError& ie)
680     //                {
681     //                    pIT->killMe();
682     //                    throw ie;
683     //                }
684
685     //                if (e.isBreakable() && body->isBreak())
686     //                {
687     //                    const_cast<IntSelectExp*>(&e)->setBreak();
688     //                    body->resetBreak();
689     //                }
690
691     //                if (e.isContinuable() && body->isContinue())
692     //                {
693     //                    const_cast<IntSelectExp*>(&e)->setContinue();
694     //                    body->resetContinue();
695     //                }
696
697     //                if (e.isReturnable() && body->isReturn())
698     //                {
699     //                    const_cast<IntSelectExp*>(&e)->setReturn();
700     //                    body->resetReturn();
701     //                }
702     //            }
703     //        }
704     //    }
705     //}
706
707     if (!found)
708     {
709         e.getOriginal()->accept(*this);
710     }
711 }
712
713 template <class T>
714 void RunVisitorT<T>::visitprivate(const StringSelectExp &e)
715 {
716     e.getSelect()->accept(*this);
717     types::InternalType* pIT = getResult();
718     setResult(nullptr);
719     bool found = false;
720     if (pIT && pIT->isString())
721     {
722         types::String * pStr = static_cast<types::String *>(pIT);
723         if (pStr->getSize() == 1)
724         {
725             if (wchar_t * s = pStr->get(0))
726             {
727                 const std::wstring ws(s);
728                 Exp * exp = e.getExp(ws);
729                 found = true;
730                 if (exp)
731                 {
732                     Exp * body = exp->isCaseExp() ? exp->getAs<CaseExp>()->getBody() : exp;
733                     if (e.isBreakable())
734                     {
735                         const_cast<StringSelectExp*>(&e)->resetBreak();
736                         body->setBreakable();
737                     }
738
739                     if (e.isContinuable())
740                     {
741                         const_cast<StringSelectExp*>(&e)->resetContinue();
742                         body->setContinuable();
743                     }
744
745                     if (e.isReturnable())
746                     {
747                         const_cast<StringSelectExp*>(&e)->resetReturn();
748                         body->setReturnable();
749                     }
750
751                     try
752                     {
753                         //the good one
754                         body->accept(*this);
755                     }
756                     catch (const InternalError& ie)
757                     {
758                         pIT->killMe();
759                         throw ie;
760                     }
761
762                     if (e.isBreakable() && body->isBreak())
763                     {
764                         const_cast<StringSelectExp*>(&e)->setBreak();
765                         body->resetBreak();
766                     }
767
768                     if (e.isContinuable() && body->isContinue())
769                     {
770                         const_cast<StringSelectExp*>(&e)->setContinue();
771                         body->resetContinue();
772                     }
773
774                     if (e.isReturnable() && body->isReturn())
775                     {
776                         const_cast<StringSelectExp*>(&e)->setReturn();
777                         body->resetReturn();
778                     }
779                 }
780             }
781         }
782     }
783
784     if (!found)
785     {
786         e.getOriginal()->accept(*this);
787     }
788 }
789
790 template <class T>
791 void RunVisitorT<T>::visitprivate(const SelectExp &e)
792 {
793     // FIXME : exec select ... case ... else ... end
794     e.getSelect()->accept(*this);
795     bool bCase = false;
796
797     types::InternalType* pIT = getResult();
798     setResult(NULL);
799     if (pIT)
800     {
801         // protect pIT to avoid double free when
802         // the variable in select is override in the case
803         pIT->IncreaseRef();
804
805         //find good case
806         exps_t cases = e.getCases();
807         for (auto exp : cases)
808         {
809             CaseExp* pCase = exp->getAs<CaseExp>();
810             pCase->getTest()->accept(*this);
811             types::InternalType *pITCase = getResult();
812             setResult(NULL);
813             if (pITCase)
814             {
815                 if (pITCase->isContainer()) //WARNING ONLY FOR CELL
816                 {
817                     //check each item
818                 }
819                 else if (*pITCase == *pIT)
820                 {
821                     try
822                     {
823                         //the good one
824                         pCase->getBody()->accept(*this);
825                     }
826                     catch (const InternalError& ie)
827                     {
828                         pIT->DecreaseRef();
829                         pIT->killMe();
830                         throw ie;
831                     }
832
833                     if (e.isBreakable() && pCase->getBody()->isBreak())
834                     {
835                         const_cast<SelectExp*>(&e)->setBreak();
836                         pCase->getBody()->resetBreak();
837                     }
838
839                     if (e.isContinuable() && pCase->getBody()->isContinue())
840                     {
841                         const_cast<SelectExp*>(&e)->setContinue();
842                         pCase->getBody()->resetContinue();
843                     }
844
845                     if (e.isReturnable() && pCase->getBody()->isReturn())
846                     {
847                         const_cast<SelectExp*>(&e)->setReturn();
848                         pCase->getBody()->resetReturn();
849                     }
850
851                     pITCase->killMe();
852                     bCase = true;
853                     break;
854                 }
855
856                 pITCase->killMe();
857             }
858         }
859     }
860
861     if (bCase == false && e.getDefaultCase() != NULL)
862     {
863         try
864         {
865             //default case
866             e.getDefaultCase()->accept(*this);
867         }
868         catch (const InternalError& ie)
869         {
870             if (pIT)
871             {
872                 pIT->DecreaseRef();
873                 pIT->killMe();
874             }
875             throw ie;
876         }
877
878         if (e.isBreakable() && e.getDefaultCase()->isBreak())
879         {
880             const_cast<SelectExp*>(&e)->setBreak();
881             e.getDefaultCase()->resetBreak();
882         }
883
884         if (e.isContinuable() && e.getDefaultCase()->isContinue())
885         {
886             const_cast<SelectExp*>(&e)->setContinue();
887             e.getDefaultCase()->resetContinue();
888         }
889
890         if (e.isReturnable() && e.getDefaultCase()->isReturn())
891         {
892             const_cast<SelectExp*>(&e)->setReturn();
893             e.getDefaultCase()->resetReturn();
894         }
895     }
896
897     clearResult();
898
899     if (pIT)
900     {
901         pIT->DecreaseRef();
902         pIT->killMe();
903     }
904 }
905
906 template <class T>
907 void RunVisitorT<T>::visitprivate(const SeqExp  &e)
908 {
909     for (auto exp : e.getExps())
910     {
911         if (exp->isCommentExp())
912         {
913             continue;
914         }
915
916         // interrupt me to execute a prioritary command
917         while (StaticRunner_isInterruptibleCommand() == 1 && StaticRunner_isRunnerAvailable() == 1)
918         {
919             StaticRunner_launch();
920             StaticRunner_setInterruptibleCommand(1);
921         }
922
923         try
924         {
925             //reset default values
926             setResult(NULL);
927             int iExpectedSize = getExpectedSize();
928             setExpectedSize(-1);
929             exp->accept(*this);
930             setExpectedSize(iExpectedSize);
931             types::InternalType * pIT = getResult();
932
933             // In case of exec file, set the file name in the Macro to store where it is defined.
934             int iFileID = ConfigVariable::getExecutedFileID();
935             if (iFileID && exp->isFunctionDec())
936             {
937                 types::InternalType* pITMacro = symbol::Context::getInstance()->get(exp->getAs<FunctionDec>()->getSymbol());
938                 if (pITMacro)
939                 {
940                     types::Macro* pMacro = pITMacro->getAs<types::Macro>();
941                     const wchar_t* filename = getfile_filename(iFileID);
942                     // scilab.quit is not open with mopen
943                     // in this case filename is NULL because FileManager have not been filled.
944                     if (filename)
945                     {
946                         pMacro->setFileName(filename);
947                     }
948                 }
949             }
950
951             if (pIT != NULL)
952             {
953                 bool bImplicitCall = false;
954                 if (pIT->isCallable()) //to manage call without ()
955                 {
956                     types::Callable *pCall = pIT->getAs<types::Callable>();
957                     types::typed_list out;
958                     types::typed_list in;
959                     types::optional_list opt;
960
961                     try
962                     {
963                         //in this case of calling, we can return only one values
964                         int iSaveExpectedSize = getExpectedSize();
965                         setExpectedSize(1);
966
967                         pCall->invoke(in, opt, getExpectedSize(), out, *this, e);
968                         setExpectedSize(iSaveExpectedSize);
969
970                         if (out.size() == 0)
971                         {
972                             setResult(NULL);
973                         }
974                         else
975                         {
976                             setResult(out[0]);
977                         }
978
979                         bImplicitCall = true;
980                     }
981                     catch (const InternalError& ie)
982                     {
983                         if (ConfigVariable::getLastErrorFunction() == L"")
984                         {
985                             ConfigVariable::setLastErrorFunction(pCall->getName());
986                             ConfigVariable::setLastErrorLine(e.getLocation().first_line);
987                         }
988
989                         throw ie;
990                     }
991                 }
992
993                 //don't output Simplevar and empty result
994                 if (getResult() != NULL && (!exp->isSimpleVar() || bImplicitCall))
995                 {
996                     //symbol::Context::getInstance()->put(symbol::Symbol(L"ans"), *execMe.getResult());
997                     types::InternalType* pITAns = getResult();
998                     symbol::Context::getInstance()->put(m_pAns, pITAns);
999                     if (exp->isVerbose() && ConfigVariable::isPromptShow())
1000                     {
1001                         //TODO manage multiple returns
1002                         scilabWriteW(L" ans  =\n\n");
1003                         std::wostringstream ostrName;
1004                         ostrName << L"ans";
1005                         VariableToString(pITAns, ostrName.str().c_str());
1006                     }
1007                 }
1008
1009                 pIT->killMe();
1010             }
1011
1012             if ((&e)->isBreakable() && exp->isBreak())
1013             {
1014                 const_cast<SeqExp *>(&e)->setBreak();
1015                 exp->resetBreak();
1016                 break;
1017             }
1018
1019             if ((&e)->isContinuable() && exp->isContinue())
1020             {
1021                 const_cast<SeqExp *>(&e)->setContinue();
1022                 exp->resetContinue();
1023                 break;
1024             }
1025
1026             if ((&e)->isReturnable() && exp->isReturn())
1027             {
1028                 const_cast<SeqExp *>(&e)->setReturn();
1029                 exp->resetReturn();
1030                 break;
1031             }
1032         }
1033         catch (const InternalError& ie)
1034         {
1035             ConfigVariable::fillWhereError(ie.GetErrorLocation().first_line);
1036             throw ie;
1037         }
1038
1039         // If something other than NULL is given to setResult, then that would imply
1040         // to make a cleanup in visit(ForExp) for example (e.getBody().accept(*this);)
1041         setResult(NULL);
1042     }
1043 }
1044
1045 template <class T>
1046 void RunVisitorT<T>::visitprivate(const NotExp &e)
1047 {
1048     /*
1049       @ or ~ !
1050     */
1051     e.getExp().accept(*this);
1052
1053     types::InternalType * pValue = getResult();
1054     types::InternalType * pReturn = NULL;
1055     if (pValue->neg(pReturn))
1056     {
1057         if (pValue != pReturn)
1058         {
1059             pValue->killMe();
1060         }
1061
1062         setResult(pReturn);
1063     }
1064     else
1065     {
1066         // neg returned false so the negation is not possible so we call the overload (%foo_5)
1067         types::typed_list in;
1068         types::typed_list out;
1069
1070         pValue->IncreaseRef();
1071         in.push_back(pValue);
1072
1073         types::Callable::ReturnValue Ret = Overload::call(L"%" + pValue->getShortTypeStr() + L"_5", in, 1, out, this);
1074
1075         if (Ret != types::Callable::OK)
1076         {
1077             cleanInOut(in, out);
1078             throw InternalError(ConfigVariable::getLastErrorMessage(), ConfigVariable::getLastErrorNumber(), e.getLocation());
1079         }
1080
1081         setResult(out);
1082         cleanIn(in, out);
1083     }
1084 }
1085
1086 template <class T>
1087 void RunVisitorT<T>::visitprivate(const TransposeExp &e)
1088 {
1089     e.getExp().accept(*this);
1090
1091     if (getResultSize() != 1)
1092     {
1093         clearResult();
1094         wchar_t szError[bsiz];
1095         os_swprintf(szError, bsiz, _W("%ls: Can not transpose multiple elements.\n").c_str(), L"Transpose");
1096         throw InternalError(szError, 999, e.getLocation());
1097     }
1098
1099     types::InternalType * pValue = getResult();
1100     types::InternalType * pReturn = NULL;
1101     const bool bConjug = e.getConjugate() == TransposeExp::_Conjugate_;
1102
1103     if ((bConjug && pValue->adjoint(pReturn)) || (!bConjug && pValue->transpose(pReturn)))
1104     {
1105         if (pValue != pReturn)
1106         {
1107             pValue->killMe();
1108         }
1109
1110         setResult(pReturn);
1111
1112         return;
1113     }
1114     else
1115     {
1116         // transpose returned false so the negation is not possible so we call the overload (%foo_t or %foo_0)
1117         types::typed_list in;
1118         types::typed_list out;
1119
1120         pValue->IncreaseRef();
1121         in.push_back(pValue);
1122
1123         types::Callable::ReturnValue Ret;
1124         if (bConjug)
1125         {
1126             Ret = Overload::call(L"%" + getResult()->getShortTypeStr() + L"_t", in, 1, out, this);
1127         }
1128         else
1129         {
1130             Ret = Overload::call(L"%" + getResult()->getShortTypeStr() + L"_0", in, 1, out, this);
1131         }
1132
1133         if (Ret != types::Callable::OK)
1134         {
1135             cleanInOut(in, out);
1136             throw InternalError(ConfigVariable::getLastErrorMessage(), ConfigVariable::getLastErrorNumber(), e.getLocation());
1137         }
1138
1139         setResult(out);
1140         cleanIn(in, out);
1141     }
1142 }
1143
1144 template <class T>
1145 void RunVisitorT<T>::visitprivate(const FunctionDec & e)
1146 {
1147     symbol::Context* ctx = symbol::Context::getInstance();
1148     /*
1149       function foo
1150       endfunction
1151     */
1152
1153     // funcprot(0) : do nothing
1154     // funcprot(1) && warning(on) : warning
1155     //get input parameters list
1156     std::list<symbol::Variable*> *pVarList = new std::list<symbol::Variable*>();
1157     const exps_t & vars = e.getArgs().getVars();
1158     for (const auto var : vars)
1159     {
1160         pVarList->push_back(var->getAs<SimpleVar>()->getStack());
1161     }
1162
1163     //get output parameters list
1164     std::list<symbol::Variable*> *pRetList = new std::list<symbol::Variable*>();
1165     const exps_t & rets = e.getReturns().getVars();
1166     for (const auto ret : rets)
1167     {
1168         pRetList->push_back(ret->getAs<SimpleVar>()->getStack());
1169     }
1170
1171     types::Macro *pMacro = new types::Macro(e.getSymbol().getName(), *pVarList, *pRetList,
1172                                             const_cast<SeqExp&>(static_cast<const SeqExp&>(e.getBody())), L"script");
1173     pMacro->setLines(e.getLocation().first_line, e.getLocation().last_line);
1174
1175     bool bEquals = false;
1176     int iFuncProt = ConfigVariable::getFuncprot();
1177     if (iFuncProt != 0)
1178     {
1179         types::InternalType* pITFunc = ctx->get(((FunctionDec&)e).getStack());
1180         if (pITFunc && pITFunc->isCallable())
1181         {
1182             if (pITFunc->isMacroFile())
1183             {
1184                 types::MacroFile* pMF = pITFunc->getAs<types::MacroFile>();
1185                 bEquals = *pMF->getMacro() == *pMacro;
1186             }
1187             else if (pITFunc->isMacro())
1188             {
1189                 types::Macro* pM = pITFunc->getAs<types::Macro>();
1190                 bEquals = *pM == *pMacro;
1191             }
1192         }
1193         else
1194         {
1195             bEquals = true; //avoid msg but keep assignation
1196         }
1197     }
1198
1199     if (bEquals == false && iFuncProt == 1 && ConfigVariable::getWarningMode())
1200     {
1201         wchar_t pwstFuncName[1024];
1202         os_swprintf(pwstFuncName, 1024, L"%-24ls", e.getSymbol().getName().c_str());
1203         char* pstFuncName = wide_string_to_UTF8(pwstFuncName);
1204
1205
1206         sciprint(_("Warning : redefining function: %s. Use funcprot(0) to avoid this message"), pstFuncName);
1207         sciprint("\n");
1208         FREE(pstFuncName);
1209     }
1210     else if (bEquals == false && iFuncProt == 2)
1211     {
1212         char pstError[1024];
1213         char* pstFuncName = wide_string_to_UTF8(e.getSymbol().getName().c_str());
1214         os_sprintf(pstError, _("It is not possible to redefine the %s primitive this way (see clearfun).\n"), pstFuncName);
1215         wchar_t* pwstError = to_wide_string(pstError);
1216         std::wstring wstError(pwstError);
1217         FREE(pstFuncName);
1218         FREE(pwstError);
1219         delete pMacro;
1220         throw InternalError(wstError, 999, e.getLocation());
1221     }
1222
1223
1224     if (ctx->isprotected(symbol::Symbol(pMacro->getName())))
1225     {
1226         delete pMacro;
1227         std::wostringstream os;
1228         os << _W("Redefining permanent variable.\n");
1229         throw InternalError(os.str(), 999, e.getLocation());
1230     }
1231
1232     ctx->addMacro(pMacro);
1233
1234 }
1235
1236 template <class T>
1237 void RunVisitorT<T>::visitprivate(const ListExp &e)
1238 {
1239     e.getStart().accept(*this);
1240     types::GenericType* pITStart = static_cast<types::GenericType*>(getResult());
1241     if ((pITStart->getSize() != 1 || (pITStart->isDouble() && pITStart->getAs<types::Double>()->isComplex())) &&
1242             pITStart->isList() == false) // list case => call overload
1243     {
1244         pITStart->killMe();
1245         wchar_t szError[bsiz];
1246         os_swprintf(szError, bsiz, _W("%ls: Wrong type for argument %d: Real scalar expected.\n").c_str(), L"':'", 1);
1247         throw InternalError(szError, 999, e.getLocation());
1248     }
1249     types::InternalType * piStart = pITStart;
1250
1251     e.getStep().accept(*this);
1252     types::GenericType* pITStep = static_cast<types::GenericType*>(getResult());
1253     if ((pITStep->getSize() != 1 || (pITStep->isDouble() && pITStep->getAs<types::Double>()->isComplex())) &&
1254             pITStep->isList() == false) // list case => call overload
1255     {
1256         pITStart->killMe();
1257         pITStep->killMe();
1258         wchar_t szError[bsiz];
1259         os_swprintf(szError, bsiz, _W("%ls: Wrong type for argument %d: Real scalar expected.\n").c_str(), L"':'", 2);
1260         throw InternalError(szError, 999, e.getLocation());
1261     }
1262     types::InternalType* piStep = pITStep;
1263
1264     e.getEnd().accept(*this);
1265     types::GenericType* pITEnd = static_cast<types::GenericType*>(getResult());
1266     if ((pITEnd->getSize() != 1 || (pITEnd->isDouble() && pITEnd->getAs<types::Double>()->isComplex())) &&
1267             pITEnd->isList() == false) // list case => call overload
1268     {
1269         pITStart->killMe();
1270         pITStep->killMe();
1271         pITEnd->killMe();
1272         wchar_t szError[bsiz];
1273         os_swprintf(szError, bsiz, _W("%ls: Wrong type for argument %d: Real scalar expected.\n").c_str(), L"':'", 3);
1274         throw InternalError(szError, 999, e.getLocation());
1275     }
1276     types::InternalType* piEnd = pITEnd;
1277
1278     ////check if implicitlist is 1:$ to replace by ':'
1279     //if (piStart->isDouble() && piStep->isDouble() && piEnd->isPoly())
1280     //{
1281     //    if (piStart->getAs<Double>()->get()[0] == 1 && piStep->getAs<Double>()->get()[0] == 1)
1282     //    {
1283     //        SinglePoly* end = piEnd->getAs<Polynom>()->get()[0];
1284     //        if (end->getRank() == 1 && end->get()[0] == 0 && end->get()[1] == 1)
1285     //        {
1286     //            setResult(new Colon());
1287     //            return;
1288     //        }
1289     //    }
1290     //}
1291
1292     //check compatibility
1293     // double : double : double or poly : poly : poly and mix like double : double : poly
1294     if ((piStart->isPoly() || piStart->isDouble()) &&
1295             (piStep->isPoly()  || piStep->isDouble())  &&
1296             (piEnd->isPoly()   || piEnd->isDouble()))
1297     {
1298         // No need to kill piStart, ... because Implicit list ctor will incref them
1299         setResult(new types::ImplicitList(piStart, piStep, piEnd));
1300         return;
1301     }
1302
1303     // int : double or int : int
1304     if ( piStart->isInt()   &&
1305             (piStep->isDouble() || piStep->isInt()) &&
1306             piEnd->isInt())
1307     {
1308         // check for same int type int8, int 16 ...
1309         if (piStart->getType() == piEnd->getType()  &&
1310                 (piStart->getType() == piStep->getType() ||
1311                  piStep->isDouble()))
1312         {
1313             // No need to kill piStart, ... because Implicit list ctor will incref them
1314             setResult(new types::ImplicitList(piStart, piStep, piEnd));
1315             return;
1316         }
1317     }
1318
1319     // Call Overload
1320     types::Callable::ReturnValue Ret;
1321     types::typed_list in;
1322     types::typed_list out;
1323
1324     piStart->IncreaseRef();
1325     in.push_back(piStart);
1326
1327     try
1328     {
1329         if (e.hasExplicitStep())
1330         {
1331             // 1:2:4
1332             //call overload %typeStart_b_typeStep
1333             piStep->IncreaseRef();
1334             in.push_back(piStep);
1335             piEnd->IncreaseRef();
1336             in.push_back(piEnd);
1337             Ret = Overload::call(L"%" + piStart->getShortTypeStr() + L"_b_" + piStep->getShortTypeStr(), in, 1, out, this, true);
1338         }
1339         else
1340         {
1341             // 1:2
1342             //call overload %typeStart_b_typeEnd
1343             piStep->killMe();
1344             piEnd->IncreaseRef();
1345             in.push_back(piEnd);
1346             Ret = Overload::call(L"%" + piStart->getShortTypeStr() + L"_b_" + piEnd->getShortTypeStr(), in, 1, out, this, true);
1347         }
1348     }
1349     catch (const InternalError& error)
1350     {
1351         cleanInOut(in, out);
1352         throw error;
1353     }
1354
1355     if (Ret != types::Callable::OK)
1356     {
1357         cleanInOut(in, out);
1358         throw InternalError(ConfigVariable::getLastErrorMessage(), ConfigVariable::getLastErrorNumber(), e.getLocation());
1359     }
1360
1361     setResult(out);
1362     cleanIn(in, out);
1363 }
1364
1365 template <class T>
1366 void RunVisitorT<T>::visitprivate(const OptimizedExp &e)
1367 {
1368 }
1369
1370 template <class T>
1371 void RunVisitorT<T>::visitprivate(const MemfillExp &e)
1372 {
1373     e.getOriginal()->accept(*this);
1374 }
1375
1376 template <class T>
1377 void RunVisitorT<T>::visitprivate(const DAXPYExp &e)
1378 {
1379     types::InternalType* pIT = NULL;
1380     types::Double* ad = NULL;
1381     int ar = 0;
1382     int ac = 0;
1383
1384     types::Double* xd = NULL;
1385     int xr = 0;
1386     int xc = 0;
1387
1388     types::Double* yd = NULL;
1389     int yr = 0;
1390     int yc = 0;
1391
1392     //check types and dimensions
1393
1394     //y must be double
1395     const Exp &ye = e.getY();
1396     ye.accept(*this);
1397     pIT = getResult();
1398     if (pIT->isDouble())
1399     {
1400         yd = pIT->getAs<types::Double>();
1401         if (yd->getDims() == 2 && yd->isComplex() == false)
1402         {
1403             yr = yd->getRows();
1404             yc = yd->getCols();
1405         }
1406         else
1407         {
1408             yd->killMe();
1409             e.getOriginal()->accept(*this);
1410             return;
1411         }
1412     }
1413     else
1414     {
1415         pIT->killMe();
1416         e.getOriginal()->accept(*this);
1417         return;
1418     }
1419
1420     //x
1421     const Exp &xe = e.getX();
1422     xe.accept(*this);
1423     pIT = getResult();
1424
1425     if (pIT->isDouble())
1426     {
1427         xd = pIT->getAs<types::Double>();
1428         if (xd->isScalar() && xd->isComplex() == false)
1429         {
1430             // x become a
1431             ad = xd;
1432             ar = 1;
1433             ac = 1;
1434         }
1435         else if (xd->getDims() == 2 && xd->isComplex() == false)
1436         {
1437             xr = xd->getRows();
1438             xc = xd->getCols();
1439         }
1440         else
1441         {
1442             yd->killMe();
1443             xd->killMe();
1444             e.getOriginal()->accept(*this);
1445             return;
1446         }
1447     }
1448     else
1449     {
1450         pIT->killMe();
1451         yd->killMe();
1452         e.getOriginal()->accept(*this);
1453         return;
1454     }
1455
1456     const Exp &ae = e.getA();
1457     ae.accept(*this);
1458     pIT = getResult();
1459
1460     if (pIT->isDouble())
1461     {
1462         if (ad)
1463         {
1464             xd = pIT->getAs<types::Double>();
1465             //X is scalar it become A
1466             //now use A as X
1467             if (xd->getDims() == 2 && xd->isComplex() == false)
1468             {
1469                 xr = xd->getRows();
1470                 xc = xd->getCols();
1471             }
1472             else
1473             {
1474                 yd->killMe();
1475                 xd->killMe();
1476                 ad->killMe();
1477                 e.getOriginal()->accept(*this);
1478                 return;
1479             }
1480         }
1481         else
1482         {
1483             //a is a and it must be scalar
1484             ad = pIT->getAs<types::Double>();
1485             if (/*ad->isScalar() && */ad->isComplex() == false)
1486             {
1487                 ar = ad->getRows(); //1;
1488                 ac = ad->getCols();//1;
1489             }
1490             else
1491             {
1492                 yd->killMe();
1493                 xd->killMe();
1494                 ad->killMe();
1495                 e.getOriginal()->accept(*this);
1496                 return;
1497             }
1498         }
1499     }
1500     else
1501     {
1502         pIT->killMe();
1503         yd->killMe();
1504         xd->killMe();
1505         e.getOriginal()->accept(*this);
1506         return;
1507     }
1508
1509     if (ad && xd && yd)
1510     {
1511         if ( ac == 1 &&
1512                 ar == 1 &&
1513                 xr == yr &&
1514                 xc == yc)
1515         {
1516             //go !
1517             int one = 1;
1518             int size = xc * xr;
1519             //Double* od = (Double*)yd->clone();
1520             C2F(daxpy)(&size, ad->get(), xd->get(), &one, yd->get(), &one);
1521             //setResult(od);
1522             //yd->killMe();
1523             xd->killMe();
1524             ad->killMe();
1525             return;
1526         }
1527         else if (ac == xr && ar == yr && xc == yc)
1528         {
1529             char n = 'n';
1530             double one = 1;
1531             C2F(dgemm)(&n, &n, &ar, &xc, &ac, &one, ad->get(), &ar, xd->get(), &ac, &one, yd->get(), &ar);
1532             xd->killMe();
1533             ad->killMe();
1534             return;
1535         }
1536     }
1537
1538     if (yd)
1539     {
1540         yd->killMe();
1541     }
1542
1543     if (xd)
1544     {
1545         xd->killMe();
1546     }
1547
1548     if (ad)
1549     {
1550         ad->killMe();
1551     }
1552
1553     e.getOriginal()->accept(*this);
1554     return;
1555 }
1556
1557 } /* namespace ast */
1558
1559 #include "run_CallExp.hpp"
1560 #include "run_MatrixExp.hpp"
1561 #include "run_OpExp.hpp"
1562 #include "run_AssignExp.hpp"
1563
1564 template EXTERN_AST class ast::RunVisitorT<ast::ExecVisitor>;
1565 template EXTERN_AST class ast::RunVisitorT<ast::StepVisitor>;
1566 template EXTERN_AST class ast::RunVisitorT<ast::TimedVisitor>;