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