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