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