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