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