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