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