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