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