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