clear result before throw exception if overload of fieldExp failed
[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();
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                         //create a new me
419                         pIL = pVar->getInitalType();
420                         //lock loop index
421                         pIL->IncreaseRef();
422                         //update me ( must decrease ref of a )
423                         if (ctx->isprotected(var))
424                         {
425                             std::wostringstream os;
426                             os << _W("Redefining permanent variable.\n");
427                             throw ast::ScilabError(os.str(), 999, e.getVardec().getLocation());
428                         }
429
430                         ctx->put(var, pIL);
431                         break;
432                 }
433             }
434
435             pVar->extractValue(i, pIL);
436
437             bool clearAndExit = false;
438             try
439             {
440                 e.getBody().accept(*this);
441             }
442             catch (ScilabMessage& sm)
443             {
444                 //unlock loop index and implicit list
445                 pIL->DecreaseRef();
446                 pIL->killMe();
447                 pIT->DecreaseRef();
448                 pIT->killMe();
449
450                 setResult(NULL);
451                 throw sm;
452             }
453
454             if (e.getBody().isBreak())
455             {
456                 const_cast<Exp&>(e.getBody()).resetBreak();
457                 break;
458             }
459
460             if (e.getBody().isContinue())
461             {
462                 const_cast<Exp&>(e.getBody()).resetContinue();
463                 continue;
464             }
465
466             if (e.getBody().isReturn())
467             {
468                 const_cast<ForExp&>(e).setReturn();
469                 const_cast<Exp&>(e.getBody()).resetReturn();
470                 break;
471             }
472         }
473
474         //unlock loop index
475         pIL->DecreaseRef();
476         pIL->killMe();
477     }
478     else if (pIT->isList())
479     {
480         List* pL = pIT->getAs<List>();
481         const int size = pL->getSize();
482         symbol::Variable* var = e.getVardec().getAs<VarDec>()->getStack();
483         for (int i = 0; i < size; ++i)
484         {
485             InternalType* pNew = pL->get(i);
486
487             if (ctx->isprotected(var))
488             {
489                 std::wostringstream os;
490                 os << _W("Redefining permanent variable.\n");
491                 throw ast::ScilabError(os.str(), 999, e.getVardec().getLocation());
492             }
493             ctx->put(var, pNew);
494
495             try
496             {
497                 e.getBody().accept(*this);
498             }
499             catch (ScilabMessage& sm)
500             {
501                 //implicit list
502                 pIT->DecreaseRef();
503                 pIT->killMe();
504                 setResult(NULL);
505                 throw sm;
506             }
507
508             if (e.getBody().isBreak())
509             {
510                 const_cast<Exp*>(&(e.getBody()))->resetBreak();
511                 break;
512             }
513
514             if (e.getBody().isContinue())
515             {
516                 const_cast<Exp*>(&(e.getBody()))->resetContinue();
517                 continue;
518             }
519
520             if (e.getBody().isReturn())
521             {
522                 const_cast<ForExp*>(&e)->setReturn();
523                 const_cast<Exp&>(e.getBody()).resetReturn();
524                 break;
525             }
526         }
527     }
528     else if (pIT->isGenericType())
529     {
530         //Matrix i = [1,3,2,6] or other type
531         GenericType* pVar = pIT->getAs<GenericType>();
532         if (pVar->getDims() > 2)
533         {
534             pIT->DecreaseRef();
535             pIT->killMe();
536             throw ScilabError(_W("for expression can only manage 1 or 2 dimensions variables\n"), 999, e.getVardec().getLocation());
537         }
538
539         symbol::Variable* var = e.getVardec().getAs<VarDec>()->getStack();
540         for (int i = 0; i < pVar->getCols(); i++)
541         {
542             GenericType* pNew = pVar->getColumnValues(i);
543             if (pNew == NULL)
544             {
545                 pIT->DecreaseRef();
546                 pIT->killMe();
547                 throw ScilabError(_W("for expression : Wrong type for loop iterator.\n"), 999, e.getVardec().getLocation());
548             }
549
550             if (ctx->isprotected(var))
551             {
552                 std::wostringstream os;
553                 os << _W("Redefining permanent variable.\n");
554                 throw ast::ScilabError(os.str(), 999, e.getVardec().getLocation());
555             }
556             ctx->put(var, pNew);
557
558             try
559             {
560                 e.getBody().accept(*this);
561             }
562             catch (ScilabMessage& sm)
563             {
564                 //implicit list
565                 pIT->DecreaseRef();
566                 pIT->killMe();
567                 setResult(NULL);
568                 throw sm;
569             }
570
571             if (e.getBody().isBreak())
572             {
573                 const_cast<Exp*>(&(e.getBody()))->resetBreak();
574                 break;
575             }
576
577             if (e.getBody().isContinue())
578             {
579                 const_cast<Exp*>(&(e.getBody()))->resetContinue();
580                 continue;
581             }
582
583             if (e.getBody().isReturn())
584             {
585                 const_cast<ForExp*>(&e)->setReturn();
586                 const_cast<Exp&>(e.getBody()).resetReturn();
587                 break;
588             }
589         }
590     }
591     else
592     {
593         pIT->DecreaseRef();
594         pIT->killMe();
595         throw ScilabError(_W("for expression : Wrong type for loop iterator.\n"), 999, e.getVardec().getLocation());
596     }
597
598     pIT->DecreaseRef();
599     pIT->killMe();
600
601     setResult(NULL);
602 }
603
604 template <class T>
605 void RunVisitorT<T>::visitprivate(const ReturnExp &e)
606 {
607     if (e.isGlobal())
608     {
609         if (ConfigVariable::getPauseLevel() != 0 && symbol::Context::getInstance()->getScopeLevel() == ConfigVariable::getActivePauseLevel())
610         {
611             //return or resume
612             ThreadId* pThreadId = ConfigVariable::getLastPausedThread();
613             if (pThreadId == NULL)
614             {
615                 //no paused thread, so just go leave
616                 return;
617             }
618
619             //force exit without prompt of current thread ( via Aborted status )
620             ThreadId* pMe = ConfigVariable::getThread(__GetCurrentThreadKey());
621             pMe->setStatus(ThreadId::Aborted);
622
623             //resume previous execution thread
624             pThreadId->resume();
625
626             return;
627         }
628         else
629         {
630             const_cast<ReturnExp*>(&e)->setReturn();
631         }
632     }
633     else
634     {
635         //return(x)
636
637         //in case of CallExp, we can return only one values
638         int iSaveExpectedSize = getExpectedSize();
639         setExpectedSize(1);
640         e.getExp().accept(*this);
641         setExpectedSize(iSaveExpectedSize);
642         const_cast<ReturnExp*>(&e)->setReturn();
643     }
644 }
645
646 template <class T>
647 void RunVisitorT<T>::visitprivate(const IntSelectExp &e)
648 {
649     bool found = false;
650     //e.getSelect()->accept(*this);
651     //InternalType* pIT = getResult();
652     //setResult(nullptr);
653     //if (pIT && pIT->isDouble())
654     //{
655     //    Double * pDbl = static_cast<Double *>(pIT);
656     //    if (!pDbl->isComplex() && pDbl->getSize() == 1)
657     //    {
658     //        int64_t val;
659     //        if (analysis::tools::asInteger<int64_t>(pDbl->get(0), val))
660     //        {
661     //            Exp * exp = e.getExp(val);
662     //            found = true;
663     //            if (exp)
664     //            {
665     //                Exp * body = exp->isCaseExp() ? exp->getAs<CaseExp>()->getBody() : exp;
666     //                if (e.isBreakable())
667     //                {
668     //                    const_cast<IntSelectExp*>(&e)->resetBreak();
669     //                    body->setBreakable();
670     //                }
671
672     //                if (e.isContinuable())
673     //                {
674     //                    const_cast<IntSelectExp*>(&e)->resetContinue();
675     //                    body->setContinuable();
676     //                }
677
678     //                if (e.isReturnable())
679     //                {
680     //                    const_cast<IntSelectExp*>(&e)->resetReturn();
681     //                    body->setReturnable();
682     //                }
683
684     //                try
685     //                {
686     //                    //the good one
687     //                    body->accept(*this);
688     //                }
689     //                catch (ScilabMessage& sm)
690     //                {
691     //                    pIT->killMe();
692     //                    throw sm;
693     //                }
694
695     //                if (e.isBreakable() && body->isBreak())
696     //                {
697     //                    const_cast<IntSelectExp*>(&e)->setBreak();
698     //                    body->resetBreak();
699     //                }
700
701     //                if (e.isContinuable() && body->isContinue())
702     //                {
703     //                    const_cast<IntSelectExp*>(&e)->setContinue();
704     //                    body->resetContinue();
705     //                }
706
707     //                if (e.isReturnable() && body->isReturn())
708     //                {
709     //                    const_cast<IntSelectExp*>(&e)->setReturn();
710     //                    body->resetReturn();
711     //                }
712     //            }
713     //        }
714     //    }
715     //}
716
717     if (!found)
718     {
719         e.getOriginal()->accept(*this);
720     }
721 }
722
723 template <class T>
724 void RunVisitorT<T>::visitprivate(const StringSelectExp &e)
725 {
726     e.getSelect()->accept(*this);
727     InternalType* pIT = getResult();
728     setResult(nullptr);
729     bool found = false;
730     if (pIT && pIT->isString())
731     {
732         String * pStr = static_cast<String *>(pIT);
733         if (pStr->getSize() == 1)
734         {
735             if (wchar_t * s = pStr->get(0))
736             {
737                 const std::wstring ws(s);
738                 Exp * exp = e.getExp(ws);
739                 found = true;
740                 if (exp)
741                 {
742                     Exp * body = exp->isCaseExp() ? exp->getAs<CaseExp>()->getBody() : exp;
743                     if (e.isBreakable())
744                     {
745                         const_cast<StringSelectExp*>(&e)->resetBreak();
746                         body->setBreakable();
747                     }
748
749                     if (e.isContinuable())
750                     {
751                         const_cast<StringSelectExp*>(&e)->resetContinue();
752                         body->setContinuable();
753                     }
754
755                     if (e.isReturnable())
756                     {
757                         const_cast<StringSelectExp*>(&e)->resetReturn();
758                         body->setReturnable();
759                     }
760
761                     try
762                     {
763                         //the good one
764                         body->accept(*this);
765                     }
766                     catch (ScilabMessage& sm)
767                     {
768                         pIT->killMe();
769                         throw sm;
770                     }
771
772                     if (e.isBreakable() && body->isBreak())
773                     {
774                         const_cast<StringSelectExp*>(&e)->setBreak();
775                         body->resetBreak();
776                     }
777
778                     if (e.isContinuable() && body->isContinue())
779                     {
780                         const_cast<StringSelectExp*>(&e)->setContinue();
781                         body->resetContinue();
782                     }
783
784                     if (e.isReturnable() && body->isReturn())
785                     {
786                         const_cast<StringSelectExp*>(&e)->setReturn();
787                         body->resetReturn();
788                     }
789                 }
790             }
791         }
792     }
793
794     if (!found)
795     {
796         e.getOriginal()->accept(*this);
797     }
798 }
799
800 template <class T>
801 void RunVisitorT<T>::visitprivate(const SelectExp &e)
802 {
803     // FIXME : exec select ... case ... else ... end
804     e.getSelect()->accept(*this);
805     bool bCase = false;
806
807     InternalType* pIT = getResult();
808     setResult(NULL);
809     if (pIT)
810     {
811         //find good case
812         exps_t cases = e.getCases();
813         for (auto exp : cases)
814         {
815             CaseExp* pCase = exp->getAs<CaseExp>();
816             pCase->getTest()->accept(*this);
817             InternalType *pITCase = getResult();
818             setResult(NULL);
819             if (pITCase)
820             {
821                 if (pITCase->isContainer()) //WARNING ONLY FOR CELL
822                 {
823                     //check each item
824                 }
825                 else if (*pITCase == *pIT)
826                 {
827                     try
828                     {
829                         //the good one
830                         pCase->getBody()->accept(*this);
831                     }
832                     catch (ScilabMessage& sm)
833                     {
834                         pIT->killMe();
835                         throw sm;
836                     }
837
838                     if (e.isBreakable() && pCase->getBody()->isBreak())
839                     {
840                         const_cast<SelectExp*>(&e)->setBreak();
841                         pCase->getBody()->resetBreak();
842                     }
843
844                     if (e.isContinuable() && pCase->getBody()->isContinue())
845                     {
846                         const_cast<SelectExp*>(&e)->setContinue();
847                         pCase->getBody()->resetContinue();
848                     }
849
850                     if (e.isReturnable() && pCase->getBody()->isReturn())
851                     {
852                         const_cast<SelectExp*>(&e)->setReturn();
853                         pCase->getBody()->resetReturn();
854                     }
855
856                     pITCase->killMe();
857                     bCase = true;
858                     break;
859                 }
860
861                 pITCase->killMe();
862             }
863         }
864     }
865
866     if (bCase == false && e.getDefaultCase() != NULL)
867     {
868         try
869         {
870             //default case
871             e.getDefaultCase()->accept(*this);
872         }
873         catch (ScilabMessage& sm)
874         {
875             pIT->killMe();
876             throw sm;
877         }
878
879         if (e.isBreakable() && e.getDefaultCase()->isBreak())
880         {
881             const_cast<SelectExp*>(&e)->setBreak();
882             e.getDefaultCase()->resetBreak();
883         }
884
885         if (e.isContinuable() && e.getDefaultCase()->isContinue())
886         {
887             const_cast<SelectExp*>(&e)->setContinue();
888             e.getDefaultCase()->resetContinue();
889         }
890
891         if (e.isReturnable() && e.getDefaultCase()->isReturn())
892         {
893             const_cast<SelectExp*>(&e)->setReturn();
894             e.getDefaultCase()->resetReturn();
895         }
896     }
897
898     clearResult();
899
900     pIT->killMe();
901 }
902
903 template <class T>
904 void RunVisitorT<T>::visitprivate(const SeqExp  &e)
905 {
906     types::ThreadId* pThreadMe = ConfigVariable::getThread(__GetCurrentThreadKey());
907
908     for (auto exp : e.getExps())
909     {
910         if (exp->isCommentExp())
911         {
912             continue;
913         }
914
915         if (pThreadMe && pThreadMe->getInterrupt())
916         {
917             ThreadManagement::SendAstPendingSignal();
918             pThreadMe->suspend();
919         }
920
921         try
922         {
923             //reset default values
924             setResult(NULL);
925             int iExpectedSize = getExpectedSize();
926             setExpectedSize(-1);
927             exp->accept(*this);
928             setExpectedSize(iExpectedSize);
929             InternalType * pIT = getResult();
930
931             // In case of exec file, set the file name in the Macro to store where it is defined.
932             int iFileID = ConfigVariable::getExecutedFileID();
933             if (iFileID && exp->isFunctionDec())
934             {
935                 InternalType* pITMacro = symbol::Context::getInstance()->get(exp->getAs<FunctionDec>()->getSymbol());
936                 if (pITMacro)
937                 {
938                     types::Macro* pMacro = pITMacro->getAs<types::Macro>();
939                     const wchar_t* filename = getfile_filename(iFileID);
940                     // scilab.quit is not open with mopen
941                     // in this case filename is NULL because FileManager have not been filled.
942                     if (filename)
943                     {
944                         pMacro->setFileName(filename);
945                     }
946                 }
947             }
948
949             if (pIT != NULL)
950             {
951                 bool bImplicitCall = false;
952                 if (pIT->isCallable()) //to manage call without ()
953                 {
954                     Callable *pCall = pIT->getAs<Callable>();
955                     typed_list out;
956                     typed_list in;
957                     optional_list opt;
958
959                     try
960                     {
961                         //in this case of calling, we can return only one values
962                         int iSaveExpectedSize = getExpectedSize();
963                         setExpectedSize(1);
964
965                         pCall->invoke(in, opt, getExpectedSize(), out, *this, e);
966                         setExpectedSize(iSaveExpectedSize);
967
968                         if (out.size() == 0)
969                         {
970                             setResult(NULL);
971                         }
972                         else
973                         {
974                             setResult(out[0]);
975                         }
976
977                         bImplicitCall = true;
978                     }
979                     catch (ScilabMessage& sm)
980                     {
981                         if (ConfigVariable::getLastErrorFunction() == L"")
982                         {
983                             ConfigVariable::setLastErrorFunction(pCall->getName());
984                         }
985
986                         throw sm;
987                     }
988                     catch (ast::ScilabError & se)
989                     {
990                         if (ConfigVariable::getLastErrorFunction() == L"")
991                         {
992                             ConfigVariable::setLastErrorFunction(pCall->getName());
993                             ConfigVariable::setLastErrorLine(e.getLocation().first_line);
994                         }
995
996                         throw se;
997                     }
998                 }
999
1000                 //don't output Simplevar and empty result
1001                 if (getResult() != NULL && (!exp->isSimpleVar() || bImplicitCall))
1002                 {
1003                     //symbol::Context::getInstance()->put(symbol::Symbol(L"ans"), *execMe.getResult());
1004                     InternalType* pITAns = getResult();
1005                     symbol::Context::getInstance()->put(m_pAns, pITAns);
1006                     if (exp->isVerbose() && ConfigVariable::isPromptShow())
1007                     {
1008                         //TODO manage multiple returns
1009                         scilabWriteW(L" ans  =\n\n");
1010                         std::wostringstream ostrName;
1011                         ostrName << L"ans";
1012                         VariableToString(pITAns, ostrName.str().c_str());
1013                     }
1014                 }
1015
1016                 pIT->killMe();
1017             }
1018
1019             if ((&e)->isBreakable() && exp->isBreak())
1020             {
1021                 const_cast<SeqExp *>(&e)->setBreak();
1022                 exp->resetBreak();
1023                 break;
1024             }
1025
1026             if ((&e)->isContinuable() && exp->isContinue())
1027             {
1028                 const_cast<SeqExp *>(&e)->setContinue();
1029                 exp->resetContinue();
1030                 break;
1031             }
1032
1033             if ((&e)->isReturnable() && exp->isReturn())
1034             {
1035                 const_cast<SeqExp *>(&e)->setReturn();
1036                 exp->resetReturn();
1037                 break;
1038             }
1039         }
1040         catch (ScilabMessage& sm)
1041         {
1042             ConfigVariable::fillWhereError(sm.GetErrorLocation().first_line);
1043             throw sm;
1044         }
1045         catch (const ScilabError& se)
1046         {
1047             // check on error number because error message can be empty.
1048             if (ConfigVariable::getLastErrorNumber() == 0)
1049             {
1050                 ConfigVariable::setLastErrorMessage(se.GetErrorMessage());
1051                 ConfigVariable::setLastErrorNumber(se.GetErrorNumber());
1052                 ConfigVariable::setLastErrorLine(se.GetErrorLocation().first_line);
1053                 ConfigVariable::setLastErrorFunction(wstring(L""));
1054             }
1055
1056             ConfigVariable::fillWhereError(se.GetErrorLocation().first_line);
1057             throw ScilabMessage(se.GetErrorMessage(), se.GetErrorNumber(), se.GetErrorLocation());
1058         }
1059
1060         // If something other than NULL is given to setResult, then that would imply
1061         // to make a cleanup in visit(ForExp) for example (e.getBody().accept(*this);)
1062         setResult(NULL);
1063     }
1064 }
1065
1066 template <class T>
1067 void RunVisitorT<T>::visitprivate(const NotExp &e)
1068 {
1069     /*
1070       @ or ~ !
1071     */
1072     e.getExp().accept(*this);
1073
1074     InternalType * pValue = getResult();
1075     InternalType * pReturn = NULL;
1076     if (pValue->neg(pReturn))
1077     {
1078         if (pValue != pReturn)
1079         {
1080             pValue->killMe();
1081         }
1082
1083         setResult(pReturn);
1084     }
1085     else
1086     {
1087         // neg returned false so the negation is not possible so we call the overload (%foo_5)
1088         types::typed_list in;
1089         types::typed_list out;
1090
1091         pValue->IncreaseRef();
1092         in.push_back(pValue);
1093
1094         Callable::ReturnValue Ret = Overload::call(L"%" + pValue->getShortTypeStr() + L"_5", in, 1, out, this);
1095
1096         if (Ret != Callable::OK)
1097         {
1098             cleanInOut(in, out);
1099             throw ScilabError();
1100         }
1101
1102         setResult(out);
1103         cleanIn(in, out);
1104     }
1105 }
1106
1107 template <class T>
1108 void RunVisitorT<T>::visitprivate(const TransposeExp &e)
1109 {
1110     e.getExp().accept(*this);
1111
1112     if (getResultSize() != 1)
1113     {
1114         clearResult();
1115         wchar_t szError[bsiz];
1116         os_swprintf(szError, bsiz, _W("%ls: Can not transpose multiple elements.\n").c_str(), L"Transpose");
1117         throw ScilabError(szError, 999, e.getLocation());
1118     }
1119
1120     InternalType * pValue = getResult();
1121     InternalType * pReturn = NULL;
1122     const bool bConjug = e.getConjugate() == TransposeExp::_Conjugate_;
1123
1124     if ((bConjug && pValue->adjoint(pReturn)) || (!bConjug && pValue->transpose(pReturn)))
1125     {
1126         if (pValue != pReturn)
1127         {
1128             pValue->killMe();
1129         }
1130
1131         setResult(pReturn);
1132
1133         return;
1134     }
1135     else
1136     {
1137         // transpose returned false so the negation is not possible so we call the overload (%foo_t or %foo_0)
1138         types::typed_list in;
1139         types::typed_list out;
1140
1141         pValue->IncreaseRef();
1142         in.push_back(pValue);
1143
1144         Callable::ReturnValue Ret;
1145         if (bConjug)
1146         {
1147             Ret = Overload::call(L"%" + getResult()->getShortTypeStr() + L"_t", in, 1, out, this);
1148         }
1149         else
1150         {
1151             Ret = Overload::call(L"%" + getResult()->getShortTypeStr() + L"_0", in, 1, out, this);
1152         }
1153
1154         if (Ret != Callable::OK)
1155         {
1156             cleanInOut(in, out);
1157             throw ScilabError();
1158         }
1159
1160         setResult(out);
1161         cleanIn(in, out);
1162     }
1163 }
1164
1165 template <class T>
1166 void RunVisitorT<T>::visitprivate(const FunctionDec & e)
1167 {
1168     symbol::Context* ctx = symbol::Context::getInstance();
1169     /*
1170       function foo
1171       endfunction
1172     */
1173
1174     // funcprot(0) : do nothing
1175     // funcprot(1) && warning(on) : warning
1176     //get input parameters list
1177     std::list<symbol::Variable*> *pVarList = new std::list<symbol::Variable*>();
1178     const exps_t & vars = e.getArgs().getVars();
1179     for (const auto var : vars)
1180     {
1181         pVarList->push_back(var->getAs<SimpleVar>()->getStack());
1182     }
1183
1184     //get output parameters list
1185     std::list<symbol::Variable*> *pRetList = new std::list<symbol::Variable*>();
1186     const exps_t & rets = e.getReturns().getVars();
1187     for (const auto ret : rets)
1188     {
1189         pRetList->push_back(ret->getAs<SimpleVar>()->getStack());
1190     }
1191
1192     types::Macro *pMacro = new types::Macro(e.getSymbol().getName(), *pVarList, *pRetList,
1193                                             const_cast<SeqExp&>(static_cast<const SeqExp&>(e.getBody())), L"script");
1194     pMacro->setLines(e.getLocation().first_line, e.getLocation().last_line);
1195
1196     bool bEquals = false;
1197     int iFuncProt = ConfigVariable::getFuncprot();
1198     if (iFuncProt != 0)
1199     {
1200         types::InternalType* pITFunc = ctx->get(((FunctionDec&)e).getStack());
1201         if (pITFunc && pITFunc->isCallable())
1202         {
1203             if (pITFunc->isMacroFile())
1204             {
1205                 types::MacroFile* pMF = pITFunc->getAs<types::MacroFile>();
1206                 bEquals = *pMF->getMacro() == *pMacro;
1207             }
1208             else if (pITFunc->isMacro())
1209             {
1210                 types::Macro* pM = pITFunc->getAs<types::Macro>();
1211                 bEquals = *pM == *pMacro;
1212             }
1213         }
1214         else
1215         {
1216             bEquals = true; //avoid msg but keep assignation
1217         }
1218     }
1219
1220     if (bEquals == false && iFuncProt == 1 && ConfigVariable::getWarningMode())
1221     {
1222         wchar_t pwstFuncName[1024];
1223         os_swprintf(pwstFuncName, 1024, L"%-24ls", e.getSymbol().getName().c_str());
1224         char* pstFuncName = wide_string_to_UTF8(pwstFuncName);
1225
1226
1227         sciprint(_("Warning : redefining function: %s. Use funcprot(0) to avoid this message"), pstFuncName);
1228         sciprint("\n");
1229         FREE(pstFuncName);
1230     }
1231     else if (bEquals == false && iFuncProt == 2)
1232     {
1233         char pstError[1024];
1234         char* pstFuncName = wide_string_to_UTF8(e.getSymbol().getName().c_str());
1235         os_sprintf(pstError, _("It is not possible to redefine the %s primitive this way (see clearfun).\n"), pstFuncName);
1236         wchar_t* pwstError = to_wide_string(pstError);
1237         std::wstring wstError(pwstError);
1238         FREE(pstFuncName);
1239         FREE(pwstError);
1240         delete pMacro;
1241         throw ScilabError(wstError, 999, e.getLocation());
1242     }
1243
1244
1245     if (ctx->isprotected(symbol::Symbol(pMacro->getName())))
1246     {
1247         delete pMacro;
1248         std::wostringstream os;
1249         os << _W("Redefining permanent variable.\n");
1250         throw ScilabError(os.str(), 999, e.getLocation());
1251     }
1252
1253     ctx->addMacro(pMacro);
1254
1255 }
1256
1257 template <class T>
1258 void RunVisitorT<T>::visitprivate(const ListExp &e)
1259 {
1260     e.getStart().accept(*this);
1261     GenericType* pITStart = static_cast<GenericType*>(getResult());
1262     if ((pITStart->getSize() != 1 || (pITStart->isDouble() && pITStart->getAs<Double>()->isComplex())) &&
1263             pITStart->isList() == false) // list case => call overload
1264     {
1265         pITStart->killMe();
1266         wchar_t szError[bsiz];
1267         os_swprintf(szError, bsiz, _W("%ls: Wrong type for argument %d: Real scalar expected.\n").c_str(), L"':'", 1);
1268         throw ScilabError(szError, 999, e.getLocation());
1269     }
1270     InternalType * piStart = pITStart;
1271
1272     e.getStep().accept(*this);
1273     GenericType* pITStep = static_cast<GenericType*>(getResult());
1274     if ((pITStep->getSize() != 1 || (pITStep->isDouble() && pITStep->getAs<Double>()->isComplex())) &&
1275             pITStep->isList() == false) // list case => call overload
1276     {
1277         pITStart->killMe();
1278         pITStep->killMe();
1279         wchar_t szError[bsiz];
1280         os_swprintf(szError, bsiz, _W("%ls: Wrong type for argument %d: Real scalar expected.\n").c_str(), L"':'", 2);
1281         throw ScilabError(szError, 999, e.getLocation());
1282     }
1283     InternalType* piStep = pITStep;
1284
1285     e.getEnd().accept(*this);
1286     GenericType* pITEnd = static_cast<GenericType*>(getResult());
1287     if ((pITEnd->getSize() != 1 || (pITEnd->isDouble() && pITEnd->getAs<Double>()->isComplex())) &&
1288             pITEnd->isList() == false) // list case => call overload
1289     {
1290         pITStart->killMe();
1291         pITStep->killMe();
1292         pITEnd->killMe();
1293         wchar_t szError[bsiz];
1294         os_swprintf(szError, bsiz, _W("%ls: Wrong type for argument %d: Real scalar expected.\n").c_str(), L"':'", 3);
1295         throw ScilabError(szError, 999, e.getLocation());
1296     }
1297     InternalType* piEnd = pITEnd;
1298
1299     ////check if implicitlist is 1:$ to replace by ':'
1300     //if (piStart->isDouble() && piStep->isDouble() && piEnd->isPoly())
1301     //{
1302     //    if (piStart->getAs<Double>()->get()[0] == 1 && piStep->getAs<Double>()->get()[0] == 1)
1303     //    {
1304     //        SinglePoly* end = piEnd->getAs<Polynom>()->get()[0];
1305     //        if (end->getRank() == 1 && end->get()[0] == 0 && end->get()[1] == 1)
1306     //        {
1307     //            setResult(new Colon());
1308     //            return;
1309     //        }
1310     //    }
1311     //}
1312
1313     //check compatibility
1314     // double : double : double or poly : poly : poly and mix like double : double : poly
1315     if ((piStart->isPoly() || piStart->isDouble()) &&
1316             (piStep->isPoly()  || piStep->isDouble())  &&
1317             (piEnd->isPoly()   || piEnd->isDouble()))
1318     {
1319         // No need to kill piStart, ... because Implicit list ctor will incref them
1320         setResult(new ImplicitList(piStart, piStep, piEnd));
1321         return;
1322     }
1323
1324     // int : double or int : int
1325     if ( piStart->isInt()   &&
1326             (piStep->isDouble() || piStep->isInt()) &&
1327             piEnd->isInt())
1328     {
1329         // check for same int type int8, int 16 ...
1330         if (piStart->getType() == piEnd->getType()  &&
1331                 (piStart->getType() == piStep->getType() ||
1332                  piStep->isDouble()))
1333         {
1334             // No need to kill piStart, ... because Implicit list ctor will incref them
1335             setResult(new ImplicitList(piStart, piStep, piEnd));
1336             return;
1337         }
1338     }
1339
1340     // Call Overload
1341     Callable::ReturnValue Ret;
1342     types::typed_list in;
1343     types::typed_list out;
1344
1345     piStart->IncreaseRef();
1346     in.push_back(piStart);
1347
1348     try
1349     {
1350         if (e.hasExplicitStep())
1351         {
1352             // 1:2:4
1353             //call overload %typeStart_b_typeStep
1354             piStep->IncreaseRef();
1355             in.push_back(piStep);
1356             piEnd->IncreaseRef();
1357             in.push_back(piEnd);
1358             Ret = Overload::call(L"%" + piStart->getShortTypeStr() + L"_b_" + piStep->getShortTypeStr(), in, 1, out, this, true);
1359         }
1360         else
1361         {
1362             // 1:2
1363             //call overload %typeStart_b_typeEnd
1364             piStep->killMe();
1365             piEnd->IncreaseRef();
1366             in.push_back(piEnd);
1367             Ret = Overload::call(L"%" + piStart->getShortTypeStr() + L"_b_" + piEnd->getShortTypeStr(), in, 1, out, this, true);
1368         }
1369     }
1370     catch (ScilabError& error)
1371     {
1372         cleanInOut(in, out);
1373         throw error;
1374     }
1375     catch (ast::ScilabMessage msg)
1376     {
1377         cleanInOut(in, out);
1378         throw msg;
1379     }
1380
1381     if (Ret != Callable::OK)
1382     {
1383         cleanInOut(in, out);
1384         throw ScilabError();
1385     }
1386
1387     setResult(out);
1388     cleanIn(in, out);
1389 }
1390
1391 template <class T>
1392 void RunVisitorT<T>::visitprivate(const OptimizedExp &e)
1393 {
1394 }
1395
1396 template <class T>
1397 void RunVisitorT<T>::visitprivate(const MemfillExp &e)
1398 {
1399     e.getOriginal()->accept(*this);
1400 }
1401
1402 template <class T>
1403 void RunVisitorT<T>::visitprivate(const DAXPYExp &e)
1404 {
1405     InternalType* pIT = NULL;
1406     Double* ad = NULL;
1407     int ar = 0;
1408     int ac = 0;
1409
1410     Double* xd = NULL;
1411     int xr = 0;
1412     int xc = 0;
1413
1414     Double* yd = NULL;
1415     int yr = 0;
1416     int yc = 0;
1417
1418     //check types and dimensions
1419
1420     //y must be double
1421     const Exp &ye = e.getY();
1422     ye.accept(*this);
1423     pIT = getResult();
1424     if (pIT->isDouble())
1425     {
1426         yd = pIT->getAs<Double>();
1427         if (yd->getDims() == 2 && yd->isComplex() == false)
1428         {
1429             yr = yd->getRows();
1430             yc = yd->getCols();
1431         }
1432         else
1433         {
1434             yd->killMe();
1435             e.getOriginal()->accept(*this);
1436             return;
1437         }
1438     }
1439     else
1440     {
1441         pIT->killMe();
1442         e.getOriginal()->accept(*this);
1443         return;
1444     }
1445
1446     //x
1447     const Exp &xe = e.getX();
1448     xe.accept(*this);
1449     pIT = getResult();
1450
1451     if (pIT->isDouble())
1452     {
1453         xd = pIT->getAs<Double>();
1454         if (xd->isScalar() && xd->isComplex() == false)
1455         {
1456             // x become a
1457             ad = xd;
1458             ar = 1;
1459             ac = 1;
1460         }
1461         else if (xd->getDims() == 2 && xd->isComplex() == false)
1462         {
1463             xr = xd->getRows();
1464             xc = xd->getCols();
1465         }
1466         else
1467         {
1468             yd->killMe();
1469             xd->killMe();
1470             e.getOriginal()->accept(*this);
1471             return;
1472         }
1473     }
1474     else
1475     {
1476         pIT->killMe();
1477         yd->killMe();
1478         e.getOriginal()->accept(*this);
1479         return;
1480     }
1481
1482     const Exp &ae = e.getA();
1483     ae.accept(*this);
1484     pIT = getResult();
1485
1486     if (pIT->isDouble())
1487     {
1488         if (ad)
1489         {
1490             xd = pIT->getAs<Double>();
1491             //X is scalar it become A
1492             //now use A as X
1493             if (xd->getDims() == 2 && xd->isComplex() == false)
1494             {
1495                 xr = xd->getRows();
1496                 xc = xd->getCols();
1497             }
1498             else
1499             {
1500                 yd->killMe();
1501                 xd->killMe();
1502                 ad->killMe();
1503                 e.getOriginal()->accept(*this);
1504                 return;
1505             }
1506         }
1507         else
1508         {
1509             //a is a and it must be scalar
1510             ad = pIT->getAs<Double>();
1511             if (/*ad->isScalar() && */ad->isComplex() == false)
1512             {
1513                 ar = ad->getRows(); //1;
1514                 ac = ad->getCols();//1;
1515             }
1516             else
1517             {
1518                 yd->killMe();
1519                 xd->killMe();
1520                 ad->killMe();
1521                 e.getOriginal()->accept(*this);
1522                 return;
1523             }
1524         }
1525     }
1526     else
1527     {
1528         pIT->killMe();
1529         yd->killMe();
1530         xd->killMe();
1531         e.getOriginal()->accept(*this);
1532         return;
1533     }
1534
1535     if (ad && xd && yd)
1536     {
1537         if ( ac == 1 &&
1538                 ar == 1 &&
1539                 xr == yr &&
1540                 xc == yc)
1541         {
1542             //go !
1543             int one = 1;
1544             int size = xc * xr;
1545             //Double* od = (Double*)yd->clone();
1546             C2F(daxpy)(&size, ad->get(), xd->get(), &one, yd->get(), &one);
1547             //setResult(od);
1548             //yd->killMe();
1549             xd->killMe();
1550             ad->killMe();
1551             return;
1552         }
1553         else if (ac == xr && ar == yr && xc == yc)
1554         {
1555             char n = 'n';
1556             double one = 1;
1557             C2F(dgemm)(&n, &n, &ar, &xc, &ac, &one, ad->get(), &ar, xd->get(), &ac, &one, yd->get(), &ar);
1558             xd->killMe();
1559             ad->killMe();
1560             return;
1561         }
1562     }
1563
1564     if (yd)
1565     {
1566         yd->killMe();
1567     }
1568
1569     if (xd)
1570     {
1571         xd->killMe();
1572     }
1573
1574     if (ad)
1575     {
1576         ad->killMe();
1577     }
1578
1579     e.getOriginal()->accept(*this);
1580     return;
1581 }
1582
1583 } /* namespace ast */
1584
1585 #include "run_CallExp.hpp"
1586 #include "run_MatrixExp.hpp"
1587 #include "run_OpExp.hpp"
1588 #include "run_AssignExp.hpp"
1589
1590 template EXTERN_AST class ast::RunVisitorT<ast::ExecVisitor>;
1591 template EXTERN_AST class ast::RunVisitorT<ast::StepVisitor>;
1592 template EXTERN_AST class ast::RunVisitorT<ast::TimedVisitor>;